Blender V2.61 - r43446

object_bake.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2004 by Blender Foundation
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): Morten Mikkelsen,
00024  *                 Sergey Sharybin
00025  *
00026  * ***** END GPL LICENSE BLOCK *****
00027  */
00028 
00034 /*
00035     meshtools.c: no editmode (violated already :), tools operating on meshes
00036 */
00037 
00038 #include <string.h>
00039 
00040 #include "MEM_guardedalloc.h"
00041 
00042 #include "DNA_scene_types.h"
00043 #include "DNA_screen_types.h"
00044 #include "DNA_space_types.h"
00045 #include "DNA_world_types.h"
00046 #include "DNA_object_types.h"
00047 #include "DNA_mesh_types.h"
00048 #include "DNA_meshdata_types.h"
00049 
00050 #include "BLI_blenlib.h"
00051 #include "BLI_threads.h"
00052 #include "BLI_utildefines.h"
00053 #include "BLI_math.h"
00054 #include "BLI_math_geom.h"
00055 
00056 #include "BKE_blender.h"
00057 #include "BKE_screen.h"
00058 #include "BKE_context.h"
00059 #include "BKE_global.h"
00060 #include "BKE_image.h"
00061 #include "BKE_main.h"
00062 #include "BKE_multires.h"
00063 #include "BKE_report.h"
00064 #include "BKE_cdderivedmesh.h"
00065 #include "BKE_modifier.h"
00066 #include "BKE_DerivedMesh.h"
00067 #include "BKE_subsurf.h"
00068 
00069 #include "RE_pipeline.h"
00070 #include "RE_shader_ext.h"
00071 
00072 #include "PIL_time.h"
00073 
00074 #include "IMB_imbuf_types.h"
00075 #include "IMB_imbuf.h"
00076 
00077 #include "GPU_draw.h" /* GPU_free_image */
00078 
00079 #include "WM_api.h"
00080 #include "WM_types.h"
00081 
00082 #include "ED_object.h"
00083 
00084 #include "object_intern.h"
00085 
00086 /* ****************** multires BAKING ********************** */
00087 
00088 /* holder of per-object data needed for bake job
00089    needed to make job totally thread-safe */
00090 typedef struct MultiresBakerJobData {
00091     struct MultiresBakerJobData *next, *prev;
00092     DerivedMesh *lores_dm, *hires_dm;
00093     int simple, lvl, tot_lvl;
00094 } MultiresBakerJobData;
00095 
00096 /* data passing to multires-baker job */
00097 typedef struct {
00098     ListBase data;
00099     int bake_clear, bake_filter;
00100     short mode, use_lores_mesh;
00101 } MultiresBakeJob;
00102 
00103 /* data passing to multires baker */
00104 typedef struct {
00105     DerivedMesh *lores_dm, *hires_dm;
00106     int simple, lvl, tot_lvl, bake_filter;
00107     short mode, use_lores_mesh;
00108 
00109     int tot_obj, tot_image;
00110     ListBase image;
00111 
00112     int baked_objects, baked_faces;
00113 
00114     short *stop;
00115     short *do_update;
00116     float *progress;
00117 } MultiresBakeRender;
00118 
00119 typedef void (*MPassKnownData)(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *bake_data,
00120                                const int face_index, const int lvl, const float st[2],
00121                                float tangmat[3][3], const int x, const int y);
00122 
00123 typedef void* (*MInitBakeData)(MultiresBakeRender *bkr, Image* ima);
00124 typedef void (*MApplyBakeData)(void *bake_data);
00125 typedef void (*MFreeBakeData)(void *bake_data);
00126 
00127 typedef struct {
00128     MVert *mvert;
00129     MFace *mface;
00130     MTFace *mtface;
00131     float *pvtangent;
00132     float *precomputed_normals;
00133     int w, h;
00134     int face_index;
00135     int i0, i1, i2;
00136     DerivedMesh *lores_dm, *hires_dm;
00137     int lvl;
00138     void *bake_data;
00139     MPassKnownData pass_data;
00140 } MResolvePixelData;
00141 
00142 typedef void (*MFlushPixel)(const MResolvePixelData *data, const int x, const int y);
00143 
00144 typedef struct {
00145     int w, h;
00146     char *texels;
00147     const MResolvePixelData *data;
00148     MFlushPixel flush_pixel;
00149 } MBakeRast;
00150 
00151 typedef struct {
00152     float *heights;
00153     float height_min, height_max;
00154     Image *ima;
00155     DerivedMesh *ssdm;
00156     const int *origindex;
00157 } MHeightBakeData;
00158 
00159 typedef struct {
00160     const int *origindex;
00161 } MNormalBakeData;
00162 
00163 static void multiresbake_get_normal(const MResolvePixelData *data, float norm[], const int face_num, const int vert_index)
00164 {
00165     unsigned int indices[]= {data->mface[face_num].v1, data->mface[face_num].v2,
00166                              data->mface[face_num].v3, data->mface[face_num].v4};
00167     const int smoothnormal= (data->mface[face_num].flag & ME_SMOOTH);
00168 
00169     if(!smoothnormal)  { /* flat */
00170         if(data->precomputed_normals) {
00171             copy_v3_v3(norm, &data->precomputed_normals[3*face_num]);
00172         } else {
00173             float nor[3];
00174             float *p0, *p1, *p2;
00175             const int iGetNrVerts= data->mface[face_num].v4!=0 ? 4 : 3;
00176 
00177             p0= data->mvert[indices[0]].co;
00178             p1= data->mvert[indices[1]].co;
00179             p2= data->mvert[indices[2]].co;
00180 
00181             if(iGetNrVerts==4) {
00182                 float *p3= data->mvert[indices[3]].co;
00183                 normal_quad_v3(nor, p0, p1, p2, p3);
00184             } else {
00185                 normal_tri_v3(nor, p0, p1, p2);
00186             }
00187 
00188             copy_v3_v3(norm, nor);
00189         }
00190     } else {
00191         short *no= data->mvert[indices[vert_index]].no;
00192 
00193         normal_short_to_float_v3(norm, no);
00194         normalize_v3(norm);
00195     }
00196 }
00197 
00198 static void init_bake_rast(MBakeRast *bake_rast, const ImBuf *ibuf, const MResolvePixelData *data, MFlushPixel flush_pixel)
00199 {
00200     memset(bake_rast, 0, sizeof(MBakeRast));
00201 
00202     bake_rast->texels = ibuf->userdata;
00203     bake_rast->w= ibuf->x;
00204     bake_rast->h= ibuf->y;
00205     bake_rast->data= data;
00206     bake_rast->flush_pixel= flush_pixel;
00207 }
00208 
00209 static void flush_pixel(const MResolvePixelData *data, const int x, const int y)
00210 {
00211     float st[2]= {(x+0.5f)/data->w, (y+0.5f)/data->h};
00212     float *st0, *st1, *st2;
00213     float *tang0, *tang1, *tang2;
00214     float no0[3], no1[3], no2[3];
00215     float fUV[2], from_tang[3][3], to_tang[3][3];
00216     float u, v, w, sign;
00217     int r;
00218 
00219     const int i0= data->i0;
00220     const int i1= data->i1;
00221     const int i2= data->i2;
00222 
00223     st0= data->mtface[data->face_index].uv[i0];
00224     st1= data->mtface[data->face_index].uv[i1];
00225     st2= data->mtface[data->face_index].uv[i2];
00226 
00227     tang0= data->pvtangent + data->face_index*16 + i0*4;
00228     tang1= data->pvtangent + data->face_index*16 + i1*4;
00229     tang2= data->pvtangent + data->face_index*16 + i2*4;
00230 
00231     multiresbake_get_normal(data, no0, data->face_index, i0);   /* can optimize these 3 into one call */
00232     multiresbake_get_normal(data, no1, data->face_index, i1);
00233     multiresbake_get_normal(data, no2, data->face_index, i2);
00234 
00235     resolve_tri_uv(fUV, st, st0, st1, st2);
00236 
00237     u= fUV[0];
00238     v= fUV[1];
00239     w= 1-u-v;
00240 
00241     /* the sign is the same at all face vertices for any non degenerate face.
00242        Just in case we clamp the interpolated value though. */
00243     sign= (tang0[3]*u + tang1[3]*v + tang2[3]*w)<0 ? (-1.0f) : 1.0f;
00244 
00245     /* this sequence of math is designed specifically as is with great care
00246        to be compatible with our shader. Please don't change without good reason. */
00247     for(r= 0; r<3; r++) {
00248         from_tang[0][r]= tang0[r]*u + tang1[r]*v + tang2[r]*w;
00249         from_tang[2][r]= no0[r]*u + no1[r]*v + no2[r]*w;
00250     }
00251 
00252     cross_v3_v3v3(from_tang[1], from_tang[2], from_tang[0]);  /* B = sign * cross(N, T)  */
00253     mul_v3_fl(from_tang[1], sign);
00254     invert_m3_m3(to_tang, from_tang);
00255     /* sequence end */
00256 
00257     data->pass_data(data->lores_dm, data->hires_dm, data->bake_data,
00258                     data->face_index, data->lvl, st, to_tang, x, y);
00259 }
00260 
00261 static void set_rast_triangle(const MBakeRast *bake_rast, const int x, const int y)
00262 {
00263     const int w= bake_rast->w;
00264     const int h= bake_rast->h;
00265 
00266     if(x>=0 && x<w && y>=0 && y<h) {
00267         if((bake_rast->texels[y*w+x])==0) {
00268             flush_pixel(bake_rast->data, x, y);
00269             bake_rast->texels[y*w+x]= FILTER_MASK_USED;
00270         }
00271     }
00272 }
00273 
00274 static void rasterize_half(const MBakeRast *bake_rast,
00275                            const float s0_s, const float t0_s, const float s1_s, const float t1_s,
00276                            const float s0_l, const float t0_l, const float s1_l, const float t1_l,
00277                            const int y0_in, const int y1_in, const int is_mid_right)
00278 {
00279     const int s_stable= fabsf(t1_s-t0_s)>FLT_EPSILON ? 1 : 0;
00280     const int l_stable= fabsf(t1_l-t0_l)>FLT_EPSILON ? 1 : 0;
00281     const int w= bake_rast->w;
00282     const int h= bake_rast->h;
00283     int y, y0, y1;
00284 
00285     if(y1_in<=0 || y0_in>=h)
00286         return;
00287 
00288     y0= y0_in<0 ? 0 : y0_in;
00289     y1= y1_in>=h ? h : y1_in;
00290 
00291     for(y= y0; y<y1; y++) {
00292         /*-b(x-x0) + a(y-y0) = 0 */
00293         int iXl, iXr, x;
00294         float x_l= s_stable!=0 ? (s0_s + (((s1_s-s0_s)*(y-t0_s))/(t1_s-t0_s))) : s0_s;
00295         float x_r= l_stable!=0 ? (s0_l + (((s1_l-s0_l)*(y-t0_l))/(t1_l-t0_l))) : s0_l;
00296 
00297         if(is_mid_right!=0)
00298             SWAP(float, x_l, x_r);
00299 
00300         iXl= (int)ceilf(x_l);
00301         iXr= (int)ceilf(x_r);
00302 
00303         if(iXr>0 && iXl<w) {
00304             iXl= iXl<0?0:iXl;
00305             iXr= iXr>=w?w:iXr;
00306 
00307             for(x= iXl; x<iXr; x++)
00308                 set_rast_triangle(bake_rast, x, y);
00309         }
00310     }
00311 }
00312 
00313 static void bake_rasterize(const MBakeRast *bake_rast, const float st0_in[2], const float st1_in[2], const float st2_in[2])
00314 {
00315     const int w= bake_rast->w;
00316     const int h= bake_rast->h;
00317     float slo= st0_in[0]*w - 0.5f;
00318     float tlo= st0_in[1]*h - 0.5f;
00319     float smi= st1_in[0]*w - 0.5f;
00320     float tmi= st1_in[1]*h - 0.5f;
00321     float shi= st2_in[0]*w - 0.5f;
00322     float thi= st2_in[1]*h - 0.5f;
00323     int is_mid_right= 0, ylo, yhi, yhi_beg;
00324 
00325     /* skip degenerates */
00326     if((slo==smi && tlo==tmi) || (slo==shi && tlo==thi) || (smi==shi && tmi==thi))
00327         return;
00328 
00329     /* sort by T */
00330     if(tlo>tmi && tlo>thi) {
00331         SWAP(float, shi, slo);
00332         SWAP(float, thi, tlo);
00333     } else if(tmi>thi) {
00334         SWAP(float, shi, smi);
00335         SWAP(float, thi, tmi);
00336     }
00337 
00338     if(tlo>tmi) {
00339         SWAP(float, slo, smi);
00340         SWAP(float, tlo, tmi);
00341     }
00342 
00343     /* check if mid point is to the left or to the right of the lo-hi edge */
00344     is_mid_right= (-(shi-slo)*(tmi-thi) + (thi-tlo)*(smi-shi))>0 ? 1 : 0;
00345     ylo= (int) ceilf(tlo);
00346     yhi_beg= (int) ceilf(tmi);
00347     yhi= (int) ceilf(thi);
00348 
00349     /*if(fTmi>ceilf(fTlo))*/
00350     rasterize_half(bake_rast, slo, tlo, smi, tmi, slo, tlo, shi, thi, ylo, yhi_beg, is_mid_right);
00351     rasterize_half(bake_rast, smi, tmi, shi, thi, slo, tlo, shi, thi, yhi_beg, yhi, is_mid_right);
00352 }
00353 
00354 static int multiresbake_test_break(MultiresBakeRender *bkr)
00355 {
00356     if(!bkr->stop) {
00357         /* this means baker is executed outside from job system */
00358         return 0;
00359     }
00360 
00361     return G.afbreek;
00362 }
00363 
00364 static void do_multires_bake(MultiresBakeRender *bkr, Image* ima, MPassKnownData passKnownData,
00365                              MInitBakeData initBakeData, MApplyBakeData applyBakeData, MFreeBakeData freeBakeData)
00366 {
00367     DerivedMesh *dm= bkr->lores_dm;
00368     ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
00369     const int lvl= bkr->lvl;
00370     const int tot_face= dm->getNumFaces(dm);
00371     MVert *mvert= dm->getVertArray(dm);
00372     MFace *mface= dm->getFaceArray(dm);
00373     MTFace *mtface= dm->getFaceDataArray(dm, CD_MTFACE);
00374     float *pvtangent= NULL;
00375 
00376     if(CustomData_get_layer_index(&dm->faceData, CD_TANGENT) == -1)
00377         DM_add_tangent_layer(dm);
00378 
00379     pvtangent= DM_get_face_data_layer(dm, CD_TANGENT);
00380 
00381     if(tot_face > 0) {  /* sanity check */
00382         int f= 0;
00383         MBakeRast bake_rast;
00384         MResolvePixelData data={NULL};
00385 
00386         data.mface= mface;
00387         data.mvert= mvert;
00388         data.mtface= mtface;
00389         data.pvtangent= pvtangent;
00390         data.precomputed_normals= dm->getFaceDataArray(dm, CD_NORMAL);  /* don't strictly need this */
00391         data.w= ibuf->x;
00392         data.h= ibuf->y;
00393         data.lores_dm= dm;
00394         data.hires_dm= bkr->hires_dm;
00395         data.lvl= lvl;
00396         data.pass_data= passKnownData;
00397 
00398         if(initBakeData)
00399             data.bake_data= initBakeData(bkr, ima);
00400 
00401         init_bake_rast(&bake_rast, ibuf, &data, flush_pixel);
00402 
00403         for(f= 0; f<tot_face; f++) {
00404             MTFace *mtfate= &mtface[f];
00405             int verts[3][2], nr_tris, t;
00406 
00407             if(multiresbake_test_break(bkr))
00408                 break;
00409 
00410             if(mtfate->tpage!=ima)
00411                 continue;
00412 
00413             data.face_index= f;
00414 
00415             /* might support other forms of diagonal splits later on such as
00416                split by shortest diagonal.*/
00417             verts[0][0]=0;
00418             verts[1][0]=1;
00419             verts[2][0]=2;
00420 
00421             verts[0][1]=0;
00422             verts[1][1]=2;
00423             verts[2][1]=3;
00424 
00425             nr_tris= mface[f].v4!=0 ? 2 : 1;
00426             for(t= 0; t<nr_tris; t++) {
00427                 data.i0= verts[0][t];
00428                 data.i1= verts[1][t];
00429                 data.i2 =verts[2][t];
00430 
00431                 bake_rasterize(&bake_rast, mtfate->uv[data.i0], mtfate->uv[data.i1], mtfate->uv[data.i2]);
00432             }
00433 
00434             bkr->baked_faces++;
00435 
00436             if(bkr->do_update)
00437                 *bkr->do_update= 1;
00438 
00439             if(bkr->progress)
00440                 *bkr->progress= ((float)bkr->baked_objects + (float)bkr->baked_faces / tot_face) / bkr->tot_obj;
00441         }
00442 
00443         if(applyBakeData)
00444             applyBakeData(data.bake_data);
00445 
00446         if(freeBakeData)
00447             freeBakeData(data.bake_data);
00448     }
00449 }
00450 
00451 static void interp_bilinear_quad_data(float data[4][3], float u, float v, float res[3])
00452 {
00453     float vec[3];
00454 
00455     copy_v3_v3(res, data[0]);
00456     mul_v3_fl(res, (1-u)*(1-v));
00457     copy_v3_v3(vec, data[1]);
00458     mul_v3_fl(vec, u*(1-v)); add_v3_v3(res, vec);
00459     copy_v3_v3(vec, data[2]);
00460     mul_v3_fl(vec, u*v); add_v3_v3(res, vec);
00461     copy_v3_v3(vec, data[3]);
00462     mul_v3_fl(vec, (1-u)*v); add_v3_v3(res, vec);
00463 }
00464 
00465 static void interp_barycentric_tri_data(float data[3][3], float u, float v, float res[3])
00466 {
00467     float vec[3];
00468 
00469     copy_v3_v3(res, data[0]);
00470     mul_v3_fl(res, u);
00471     copy_v3_v3(vec, data[1]);
00472     mul_v3_fl(vec, v); add_v3_v3(res, vec);
00473     copy_v3_v3(vec, data[2]);
00474     mul_v3_fl(vec, 1.0f-u-v); add_v3_v3(res, vec);
00475 }
00476 
00477 /* mode = 0: interpolate normals,
00478    mode = 1: interpolate coord */
00479 static void interp_bilinear_grid(DMGridData *grid, int grid_size, float crn_x, float crn_y, int mode, float res[3])
00480 {
00481     int x0, x1, y0, y1;
00482     float u, v;
00483     float data[4][3];
00484 
00485     x0= (int) crn_x;
00486     x1= x0>=(grid_size-1) ? (grid_size-1) : (x0+1);
00487 
00488     y0= (int) crn_y;
00489     y1= y0>=(grid_size-1) ? (grid_size-1) : (y0+1);
00490 
00491     u= crn_x-x0;
00492     v= crn_y-y0;
00493 
00494     if(mode == 0) {
00495         copy_v3_v3(data[0], grid[y0 * grid_size + x0].no);
00496         copy_v3_v3(data[1], grid[y0 * grid_size + x1].no);
00497         copy_v3_v3(data[2], grid[y1 * grid_size + x1].no);
00498         copy_v3_v3(data[3], grid[y1 * grid_size + x0].no);
00499     } else {
00500         copy_v3_v3(data[0], grid[y0 * grid_size + x0].co);
00501         copy_v3_v3(data[1], grid[y0 * grid_size + x1].co);
00502         copy_v3_v3(data[2], grid[y1 * grid_size + x1].co);
00503         copy_v3_v3(data[3], grid[y1 * grid_size + x0].co);
00504     }
00505 
00506     interp_bilinear_quad_data(data, u, v, res);
00507 }
00508 
00509 static void get_ccgdm_data(DerivedMesh *lodm, DerivedMesh *hidm, const int *origindex,  const int lvl, const int face_index, const float u, const float v, float co[3], float n[3])
00510 {
00511     MFace mface;
00512     DMGridData **grid_data;
00513     float crn_x, crn_y;
00514     int grid_size, S, face_side;
00515     int *grid_offset, g_index;
00516 
00517     lodm->getFace(lodm, face_index, &mface);
00518 
00519     grid_size= hidm->getGridSize(hidm);
00520     grid_data= hidm->getGridData(hidm);
00521     grid_offset= hidm->getGridOffset(hidm);
00522 
00523     face_side= (grid_size<<1)-1;
00524 
00525     if(lvl==0) {
00526         g_index= grid_offset[face_index];
00527         S= mdisp_rot_face_to_crn(mface.v4 ? 4 : 3, face_side, u*(face_side-1), v*(face_side-1), &crn_x, &crn_y);
00528     } else {
00529         int side= (1 << (lvl-1)) + 1;
00530         int grid_index= origindex[face_index];
00531         int loc_offs= face_index % (1<<(2*lvl));
00532         int cell_index= loc_offs % ((side-1)*(side-1));
00533         int cell_side= grid_size / (side-1);
00534         int row= cell_index / (side-1);
00535         int col= cell_index % (side-1);
00536 
00537         S= face_index / (1<<(2*(lvl-1))) - grid_offset[grid_index];
00538         g_index= grid_offset[grid_index];
00539 
00540         crn_y= (row * cell_side) + u * cell_side;
00541         crn_x= (col * cell_side) + v * cell_side;
00542     }
00543 
00544     CLAMP(crn_x, 0.0f, grid_size);
00545     CLAMP(crn_y, 0.0f, grid_size);
00546 
00547     if(n != NULL)
00548         interp_bilinear_grid(grid_data[g_index + S], grid_size, crn_x, crn_y, 0, n);
00549 
00550     if(co != NULL)
00551         interp_bilinear_grid(grid_data[g_index + S], grid_size, crn_x, crn_y, 1, co);
00552 }
00553 
00554 /* mode = 0: interpolate normals,
00555    mode = 1: interpolate coord */
00556 static void interp_bilinear_mface(DerivedMesh *dm, MFace *mface, const float u, const float v, const int mode, float res[3])
00557 {
00558     float data[4][3];
00559 
00560     if(mode == 0) {
00561         dm->getVertNo(dm, mface->v1, data[0]);
00562         dm->getVertNo(dm, mface->v2, data[1]);
00563         dm->getVertNo(dm, mface->v3, data[2]);
00564         dm->getVertNo(dm, mface->v4, data[3]);
00565     } else {
00566         dm->getVertCo(dm, mface->v1, data[0]);
00567         dm->getVertCo(dm, mface->v2, data[1]);
00568         dm->getVertCo(dm, mface->v3, data[2]);
00569         dm->getVertCo(dm, mface->v4, data[3]);
00570     }
00571 
00572     interp_bilinear_quad_data(data, u, v, res);
00573 }
00574 
00575 /* mode = 0: interpolate normals,
00576    mode = 1: interpolate coord */
00577 static void interp_barycentric_mface(DerivedMesh *dm, MFace *mface, const float u, const float v, const int mode, float res[3])
00578 {
00579     float data[3][3];
00580 
00581     if(mode == 0) {
00582         dm->getVertNo(dm, mface->v1, data[0]);
00583         dm->getVertNo(dm, mface->v2, data[1]);
00584         dm->getVertNo(dm, mface->v3, data[2]);
00585     } else {
00586         dm->getVertCo(dm, mface->v1, data[0]);
00587         dm->getVertCo(dm, mface->v2, data[1]);
00588         dm->getVertCo(dm, mface->v3, data[2]);
00589     }
00590 
00591     interp_barycentric_tri_data(data, u, v, res);
00592 }
00593 
00594 static void *init_heights_data(MultiresBakeRender *bkr, Image *ima)
00595 {
00596     MHeightBakeData *height_data;
00597     ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
00598     DerivedMesh *lodm= bkr->lores_dm;
00599 
00600     height_data= MEM_callocN(sizeof(MHeightBakeData), "MultiresBake heightData");
00601 
00602     height_data->ima= ima;
00603     height_data->heights= MEM_callocN(sizeof(float)*ibuf->x*ibuf->y, "MultiresBake heights");
00604     height_data->height_max= -FLT_MAX;
00605     height_data->height_min= FLT_MAX;
00606 
00607     if(!bkr->use_lores_mesh) {
00608         SubsurfModifierData smd= {{NULL}};
00609         int ss_lvl= bkr->tot_lvl - bkr->lvl;
00610 
00611         CLAMP(ss_lvl, 0, 6);
00612 
00613         smd.levels= smd.renderLevels= ss_lvl;
00614         smd.flags|= eSubsurfModifierFlag_SubsurfUv;
00615 
00616         if(bkr->simple)
00617             smd.subdivType= ME_SIMPLE_SUBSURF;
00618 
00619         height_data->ssdm= subsurf_make_derived_from_derived(bkr->lores_dm, &smd, 0, NULL, 0, 0, 0);
00620     }
00621 
00622     height_data->origindex= lodm->getFaceDataArray(lodm, CD_ORIGINDEX);
00623 
00624     return (void*)height_data;
00625 }
00626 
00627 static void *init_normal_data(MultiresBakeRender *bkr, Image *UNUSED(ima))
00628 {
00629     MNormalBakeData *normal_data;
00630     DerivedMesh *lodm= bkr->lores_dm;
00631 
00632     normal_data= MEM_callocN(sizeof(MNormalBakeData), "MultiresBake normalData");
00633 
00634     normal_data->origindex= lodm->getFaceDataArray(lodm, CD_ORIGINDEX);
00635 
00636     return (void*)normal_data;
00637 }
00638 
00639 static void free_normal_data(void *bake_data)
00640 {
00641     MNormalBakeData *normal_data= (MNormalBakeData*)bake_data;
00642 
00643     MEM_freeN(normal_data);
00644 }
00645 
00646 static void apply_heights_data(void *bake_data)
00647 {
00648     MHeightBakeData *height_data= (MHeightBakeData*)bake_data;
00649     ImBuf *ibuf= BKE_image_get_ibuf(height_data->ima, NULL);
00650     int x, y, i;
00651     float height, *heights= height_data->heights;
00652     float min= height_data->height_min, max= height_data->height_max;
00653 
00654     for(x= 0; x<ibuf->x; x++) {
00655         for(y =0; y<ibuf->y; y++) {
00656             i= ibuf->x*y + x;
00657 
00658             if(((char*)ibuf->userdata)[i] != FILTER_MASK_USED)
00659                 continue;
00660 
00661             if(ibuf->rect_float) {
00662                 float *rrgbf= ibuf->rect_float + i*4;
00663 
00664                 if(max-min > 1e-5f) height= (heights[i]-min)/(max-min);
00665                 else height= 0;
00666 
00667                 rrgbf[0]=rrgbf[1]=rrgbf[2]= height;
00668             } else {
00669                 char *rrgb= (char*)ibuf->rect + i*4;
00670 
00671                 if(max-min > 1e-5f) height= (heights[i]-min)/(max-min);
00672                 else height= 0;
00673 
00674                 rrgb[0]=rrgb[1]=rrgb[2]= FTOCHAR(height);
00675             }
00676         }
00677     }
00678 
00679     ibuf->userflags= IB_RECT_INVALID;
00680 }
00681 
00682 static void free_heights_data(void *bake_data)
00683 {
00684     MHeightBakeData *height_data= (MHeightBakeData*)bake_data;
00685 
00686     if(height_data->ssdm)
00687         height_data->ssdm->release(height_data->ssdm);
00688 
00689     MEM_freeN(height_data->heights);
00690     MEM_freeN(height_data);
00691 }
00692 
00693 /* MultiresBake callback for heights baking
00694    general idea:
00695      - find coord of point with specified UV in hi-res mesh (let's call it p1)
00696      - find coord of point and normal with specified UV in lo-res mesh (or subdivided lo-res
00697        mesh to make texture smoother) let's call this point p0 and n.
00698      - height wound be dot(n, p1-p0) */
00699 static void apply_heights_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *bake_data,
00700                                    const int face_index, const int lvl, const float st[2],
00701                                    float UNUSED(tangmat[3][3]), const int x, const int y)
00702 {
00703     MTFace *mtface= CustomData_get_layer(&lores_dm->faceData, CD_MTFACE);
00704     MFace mface;
00705     Image *ima= mtface[face_index].tpage;
00706     ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
00707     MHeightBakeData *height_data= (MHeightBakeData*)bake_data;
00708     float uv[2], *st0, *st1, *st2, *st3;
00709     int pixel= ibuf->x*y + x;
00710     float vec[3], p0[3], p1[3], n[3], len;
00711 
00712     lores_dm->getFace(lores_dm, face_index, &mface);
00713 
00714     st0= mtface[face_index].uv[0];
00715     st1= mtface[face_index].uv[1];
00716     st2= mtface[face_index].uv[2];
00717 
00718     if(mface.v4) {
00719         st3= mtface[face_index].uv[3];
00720         resolve_quad_uv(uv, st, st0, st1, st2, st3);
00721     } else
00722         resolve_tri_uv(uv, st, st0, st1, st2);
00723 
00724     CLAMP(uv[0], 0.0f, 1.0f);
00725     CLAMP(uv[1], 0.0f, 1.0f);
00726 
00727     get_ccgdm_data(lores_dm, hires_dm, height_data->origindex, lvl, face_index, uv[0], uv[1], p1, 0);
00728 
00729     if(height_data->ssdm) {
00730         get_ccgdm_data(lores_dm, height_data->ssdm, height_data->origindex, 0, face_index, uv[0], uv[1], p0, n);
00731     } else {
00732         lores_dm->getFace(lores_dm, face_index, &mface);
00733 
00734         if(mface.v4) {
00735             interp_bilinear_mface(lores_dm, &mface, uv[0], uv[1], 1, p0);
00736             interp_bilinear_mface(lores_dm, &mface, uv[0], uv[1], 0, n);
00737         } else {
00738             interp_barycentric_mface(lores_dm, &mface, uv[0], uv[1], 1, p0);
00739             interp_barycentric_mface(lores_dm, &mface, uv[0], uv[1], 0, n);
00740         }
00741     }
00742 
00743     sub_v3_v3v3(vec, p1, p0);
00744     len= dot_v3v3(n, vec);
00745 
00746     height_data->heights[pixel]= len;
00747     if(len<height_data->height_min) height_data->height_min= len;
00748     if(len>height_data->height_max) height_data->height_max= len;
00749 
00750     if(ibuf->rect_float) {
00751         float *rrgbf= ibuf->rect_float + pixel*4;
00752         rrgbf[3]= 1.0f;
00753 
00754         ibuf->userflags= IB_RECT_INVALID;
00755     } else {
00756         char *rrgb= (char*)ibuf->rect + pixel*4;
00757         rrgb[3]= 255;
00758     }
00759 }
00760 
00761 /* MultiresBake callback for normals' baking
00762    general idea:
00763      - find coord and normal of point with specified UV in hi-res mesh
00764      - multiply it by tangmat
00765      - vector in color space would be norm(vec) /2 + (0.5, 0.5, 0.5) */
00766 static void apply_tangmat_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *bake_data,
00767                                    const int face_index, const int lvl, const float st[2],
00768                                    float tangmat[3][3], const int x, const int y)
00769 {
00770     MTFace *mtface= CustomData_get_layer(&lores_dm->faceData, CD_MTFACE);
00771     MFace mface;
00772     Image *ima= mtface[face_index].tpage;
00773     ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
00774     MNormalBakeData *normal_data= (MNormalBakeData*)bake_data;
00775     float uv[2], *st0, *st1, *st2, *st3;
00776     int pixel= ibuf->x*y + x;
00777     float n[3], vec[3], tmp[3]= {0.5, 0.5, 0.5};
00778 
00779     lores_dm->getFace(lores_dm, face_index, &mface);
00780 
00781     st0= mtface[face_index].uv[0];
00782     st1= mtface[face_index].uv[1];
00783     st2= mtface[face_index].uv[2];
00784 
00785     if(mface.v4) {
00786         st3= mtface[face_index].uv[3];
00787         resolve_quad_uv(uv, st, st0, st1, st2, st3);
00788     } else
00789         resolve_tri_uv(uv, st, st0, st1, st2);
00790 
00791     CLAMP(uv[0], 0.0f, 1.0f);
00792     CLAMP(uv[1], 0.0f, 1.0f);
00793 
00794     get_ccgdm_data(lores_dm, hires_dm, normal_data->origindex, lvl, face_index, uv[0], uv[1], NULL, n);
00795 
00796     mul_v3_m3v3(vec, tangmat, n);
00797     normalize_v3(vec);
00798     mul_v3_fl(vec, 0.5);
00799     add_v3_v3(vec, tmp);
00800 
00801     if(ibuf->rect_float) {
00802         float *rrgbf= ibuf->rect_float + pixel*4;
00803         rrgbf[0]= vec[0];
00804         rrgbf[1]= vec[1];
00805         rrgbf[2]= vec[2];
00806         rrgbf[3]= 1.0f;
00807 
00808         ibuf->userflags= IB_RECT_INVALID;
00809     } else {
00810         char *rrgb= (char*)ibuf->rect + pixel*4;
00811         rrgb[0]= FTOCHAR(vec[0]);
00812         rrgb[1]= FTOCHAR(vec[1]);
00813         rrgb[2]= FTOCHAR(vec[2]);
00814         rrgb[3]= 255;
00815     }
00816 }
00817 
00818 static void count_images(MultiresBakeRender *bkr)
00819 {
00820     int a, totface;
00821     DerivedMesh *dm= bkr->lores_dm;
00822     MTFace *mtface= CustomData_get_layer(&dm->faceData, CD_MTFACE);
00823 
00824     bkr->image.first= bkr->image.last= NULL;
00825     bkr->tot_image= 0;
00826 
00827     totface= dm->getNumFaces(dm);
00828 
00829     for(a= 0; a<totface; a++)
00830         mtface[a].tpage->id.flag&= ~LIB_DOIT;
00831 
00832     for(a= 0; a<totface; a++) {
00833         Image *ima= mtface[a].tpage;
00834         if((ima->id.flag&LIB_DOIT)==0) {
00835             LinkData *data= BLI_genericNodeN(ima);
00836             BLI_addtail(&bkr->image, data);
00837             bkr->tot_image++;
00838             ima->id.flag|= LIB_DOIT;
00839         }
00840     }
00841 
00842     for(a= 0; a<totface; a++)
00843         mtface[a].tpage->id.flag&= ~LIB_DOIT;
00844 }
00845 
00846 static void bake_images(MultiresBakeRender *bkr)
00847 {
00848     LinkData *link;
00849 
00850     for(link= bkr->image.first; link; link= link->next) {
00851         Image *ima= (Image*)link->data;
00852         ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
00853 
00854         if(ibuf->x>0 && ibuf->y>0) {
00855             ibuf->userdata= MEM_callocN(ibuf->y*ibuf->x, "MultiresBake imbuf mask");
00856 
00857             switch(bkr->mode) {
00858                 case RE_BAKE_NORMALS:
00859                     do_multires_bake(bkr, ima, apply_tangmat_callback, init_normal_data, NULL, free_normal_data);
00860                     break;
00861                 case RE_BAKE_DISPLACEMENT:
00862                     do_multires_bake(bkr, ima, apply_heights_callback, init_heights_data,
00863                                      apply_heights_data, free_heights_data);
00864                     break;
00865             }
00866         }
00867 
00868         ima->id.flag|= LIB_DOIT;
00869     }
00870 }
00871 
00872 static void finish_images(MultiresBakeRender *bkr)
00873 {
00874     LinkData *link;
00875 
00876     for(link= bkr->image.first; link; link= link->next) {
00877         Image *ima= (Image*)link->data;
00878         ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
00879 
00880         if(ibuf->x<=0 || ibuf->y<=0)
00881             continue;
00882 
00883         RE_bake_ibuf_filter(ibuf, (char *)ibuf->userdata, bkr->bake_filter);
00884 
00885         ibuf->userflags|= IB_BITMAPDIRTY;
00886 
00887         if(ibuf->rect_float)
00888             ibuf->userflags|= IB_RECT_INVALID;
00889 
00890         if(ibuf->mipmap[0]) {
00891             ibuf->userflags|= IB_MIPMAP_INVALID;
00892             imb_freemipmapImBuf(ibuf);
00893         }
00894 
00895         if(ibuf->userdata) {
00896             MEM_freeN(ibuf->userdata);
00897             ibuf->userdata= NULL;
00898         }
00899     }
00900 }
00901 
00902 static void multiresbake_start(MultiresBakeRender *bkr)
00903 {
00904     count_images(bkr);
00905     bake_images(bkr);
00906     finish_images(bkr);
00907 }
00908 
00909 static int multiresbake_check(bContext *C, wmOperator *op)
00910 {
00911     Scene *scene= CTX_data_scene(C);
00912     Object *ob;
00913     Mesh *me;
00914     MultiresModifierData *mmd;
00915     int ok= 1, a;
00916 
00917     CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
00918         ob= base->object;
00919 
00920         if(ob->type != OB_MESH) {
00921             BKE_report(op->reports, RPT_ERROR, "Basking of multires data only works with active object which is a mesh");
00922 
00923             ok= 0;
00924             break;
00925         }
00926 
00927         me= (Mesh*)ob->data;
00928         mmd= get_multires_modifier(scene, ob, 0);
00929 
00930         /* Multi-resolution should be and be last in the stack */
00931         if(ok && mmd) {
00932             ModifierData *md;
00933 
00934             ok= mmd->totlvl>0;
00935 
00936             for(md = (ModifierData*)mmd->modifier.next; md && ok; md = md->next) {
00937                 if (modifier_isEnabled(scene, md, eModifierMode_Realtime)) {
00938                     ok= 0;
00939                 }
00940             }
00941         } else ok= 0;
00942 
00943         if(!ok) {
00944             BKE_report(op->reports, RPT_ERROR, "Multires data baking requires multi-resolution object");
00945 
00946             break;
00947         }
00948 
00949         if(!me->mtface) {
00950             BKE_report(op->reports, RPT_ERROR, "Mesh should be unwrapped before multires data baking");
00951 
00952             ok= 0;
00953         } else {
00954             a= me->totface;
00955             while (ok && a--) {
00956                 Image *ima= me->mtface[a].tpage;
00957 
00958                 if(!ima) {
00959                     BKE_report(op->reports, RPT_ERROR, "You should have active texture to use multires baker");
00960 
00961                     ok= 0;
00962                 } else {
00963                     ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
00964 
00965                     if(!ibuf) {
00966                         BKE_report(op->reports, RPT_ERROR, "Baking should happend to image with image buffer");
00967 
00968                         ok= 0;
00969                     } else {
00970                         if(ibuf->rect==NULL && ibuf->rect_float==NULL)
00971                             ok= 0;
00972 
00973                         if(ibuf->rect_float && !(ibuf->channels==0 || ibuf->channels==4))
00974                             ok= 0;
00975 
00976                         if(!ok)
00977                             BKE_report(op->reports, RPT_ERROR, "Baking to unsupported image type");
00978                     }
00979                 }
00980             }
00981         }
00982 
00983         if(!ok)
00984             break;
00985     }
00986     CTX_DATA_END;
00987 
00988     return ok;
00989 }
00990 
00991 static DerivedMesh *multiresbake_create_loresdm(Scene *scene, Object *ob, int *lvl)
00992 {
00993     DerivedMesh *dm;
00994     MultiresModifierData *mmd= get_multires_modifier(scene, ob, 0);
00995     Mesh *me= (Mesh*)ob->data;
00996 
00997     *lvl= mmd->lvl;
00998 
00999     if(*lvl==0) {
01000         return NULL;
01001     } else {
01002         MultiresModifierData tmp_mmd= *mmd;
01003         DerivedMesh *cddm= CDDM_from_mesh(me, ob);
01004 
01005         tmp_mmd.lvl= *lvl;
01006         dm= multires_dm_create_from_derived(&tmp_mmd, 1, cddm, ob, 0, 0);
01007         cddm->release(cddm);
01008     }
01009 
01010     return dm;
01011 }
01012 
01013 static DerivedMesh *multiresbake_create_hiresdm(Scene *scene, Object *ob, int *lvl, int *simple)
01014 {
01015     Mesh *me= (Mesh*)ob->data;
01016     MultiresModifierData *mmd= get_multires_modifier(scene, ob, 0);
01017     MultiresModifierData tmp_mmd= *mmd;
01018     DerivedMesh *cddm= CDDM_from_mesh(me, ob);
01019     DerivedMesh *dm;
01020 
01021     *lvl= mmd->totlvl;
01022     *simple= mmd->simple;
01023 
01024     tmp_mmd.lvl= mmd->totlvl;
01025     tmp_mmd.sculptlvl= mmd->totlvl;
01026     dm= multires_dm_create_from_derived(&tmp_mmd, 1, cddm, ob, 0, 0);
01027     cddm->release(cddm);
01028 
01029     return dm;
01030 }
01031 
01032 static void clear_images(MTFace *mtface, int totface)
01033 {
01034     int a;
01035     const float vec_alpha[4]= {0.0f, 0.0f, 0.0f, 0.0f};
01036     const float vec_solid[4]= {0.0f, 0.0f, 0.0f, 1.0f};
01037 
01038     for(a= 0; a<totface; a++)
01039         mtface[a].tpage->id.flag&= ~LIB_DOIT;
01040 
01041     for(a= 0; a<totface; a++) {
01042         Image *ima= mtface[a].tpage;
01043 
01044         if((ima->id.flag&LIB_DOIT)==0) {
01045             ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
01046 
01047             IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid);
01048             ima->id.flag|= LIB_DOIT;
01049         }
01050     }
01051 
01052     for(a= 0; a<totface; a++)
01053         mtface[a].tpage->id.flag&= ~LIB_DOIT;
01054 }
01055 
01056 static int multiresbake_image_exec_locked(bContext *C, wmOperator *op)
01057 {
01058     Object *ob;
01059     Scene *scene= CTX_data_scene(C);
01060     int objects_baked= 0;
01061 
01062     if(!multiresbake_check(C, op))
01063         return OPERATOR_CANCELLED;
01064 
01065     if(scene->r.bake_flag&R_BAKE_CLEAR) {  /* clear images */
01066         CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
01067             Mesh *me;
01068 
01069             ob= base->object;
01070             me= (Mesh*)ob->data;
01071 
01072             clear_images(me->mtface, me->totface);
01073         }
01074         CTX_DATA_END;
01075     }
01076 
01077     CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
01078         MultiresBakeRender bkr= {0};
01079 
01080         ob= base->object;
01081 
01082         multires_force_update(ob);
01083 
01084         /* copy data stored in job descriptor */
01085         bkr.bake_filter= scene->r.bake_filter;
01086         bkr.mode= scene->r.bake_mode;
01087         bkr.use_lores_mesh= scene->r.bake_flag&R_BAKE_LORES_MESH;
01088 
01089         /* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */
01090         bkr.lores_dm= multiresbake_create_loresdm(scene, ob, &bkr.lvl);
01091 
01092         if(!bkr.lores_dm)
01093             continue;
01094 
01095         bkr.hires_dm= multiresbake_create_hiresdm(scene, ob, &bkr.tot_lvl, &bkr.simple);
01096 
01097         multiresbake_start(&bkr);
01098 
01099         BLI_freelistN(&bkr.image);
01100 
01101         bkr.lores_dm->release(bkr.lores_dm);
01102         bkr.hires_dm->release(bkr.hires_dm);
01103 
01104         objects_baked++;
01105     }
01106     CTX_DATA_END;
01107 
01108     if(!objects_baked)
01109         BKE_report(op->reports, RPT_ERROR, "No objects found to bake from");
01110 
01111     return OPERATOR_FINISHED;
01112 }
01113 
01114 /* Multiresbake adopted for job-system executing */
01115 static void init_multiresbake_job(bContext *C, MultiresBakeJob *bkj)
01116 {
01117     Scene *scene= CTX_data_scene(C);
01118     Object *ob;
01119 
01120     /* backup scene settings, so their changing in UI would take no effect on baker */
01121     bkj->bake_filter= scene->r.bake_filter;
01122     bkj->mode= scene->r.bake_mode;
01123     bkj->use_lores_mesh= scene->r.bake_flag&R_BAKE_LORES_MESH;
01124     bkj->bake_clear= scene->r.bake_flag&R_BAKE_CLEAR;
01125 
01126     CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
01127         MultiresBakerJobData *data;
01128         DerivedMesh *lores_dm;
01129         int lvl;
01130         ob= base->object;
01131 
01132         multires_force_update(ob);
01133 
01134         lores_dm = multiresbake_create_loresdm(scene, ob, &lvl);
01135         if(!lores_dm)
01136             continue;
01137 
01138         data= MEM_callocN(sizeof(MultiresBakerJobData), "multiresBaker derivedMesh_data");
01139         data->lores_dm = lores_dm;
01140         data->lvl = lvl;
01141         data->hires_dm = multiresbake_create_hiresdm(scene, ob, &data->tot_lvl, &data->simple);
01142 
01143         BLI_addtail(&bkj->data, data);
01144     }
01145     CTX_DATA_END;
01146 }
01147 
01148 static void multiresbake_startjob(void *bkv, short *stop, short *do_update, float *progress)
01149 {
01150     MultiresBakerJobData *data;
01151     MultiresBakeJob *bkj= bkv;
01152     int baked_objects= 0, tot_obj;
01153 
01154     tot_obj= BLI_countlist(&bkj->data);
01155 
01156     if(bkj->bake_clear) {  /* clear images */
01157         for(data= bkj->data.first; data; data= data->next) {
01158             DerivedMesh *dm= data->lores_dm;
01159             MTFace *mtface= CustomData_get_layer(&dm->faceData, CD_MTFACE);
01160 
01161             clear_images(mtface, dm->getNumFaces(dm));
01162         }
01163     }
01164 
01165     for(data= bkj->data.first; data; data= data->next) {
01166         MultiresBakeRender bkr= {0};
01167 
01168         /* copy data stored in job descriptor */
01169         bkr.bake_filter= bkj->bake_filter;
01170         bkr.mode= bkj->mode;
01171         bkr.use_lores_mesh= bkj->use_lores_mesh;
01172 
01173         /* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */
01174         bkr.lores_dm= data->lores_dm;
01175         bkr.hires_dm= data->hires_dm;
01176         bkr.tot_lvl= data->tot_lvl;
01177         bkr.lvl= data->lvl;
01178         bkr.simple= data->simple;
01179 
01180         /* needed for proper progress bar */
01181         bkr.tot_obj= tot_obj;
01182         bkr.baked_objects= baked_objects;
01183 
01184         bkr.stop= stop;
01185         bkr.do_update= do_update;
01186         bkr.progress= progress;
01187 
01188         multiresbake_start(&bkr);
01189 
01190         BLI_freelistN(&bkr.image);
01191 
01192         baked_objects++;
01193     }
01194 }
01195 
01196 static void multiresbake_freejob(void *bkv)
01197 {
01198     MultiresBakeJob *bkj= bkv;
01199     MultiresBakerJobData *data, *next;
01200 
01201     data= bkj->data.first;
01202     while (data) {
01203         next= data->next;
01204         data->lores_dm->release(data->lores_dm);
01205         data->hires_dm->release(data->hires_dm);
01206         MEM_freeN(data);
01207         data= next;
01208     }
01209 
01210     MEM_freeN(bkj);
01211 }
01212 
01213 static int multiresbake_image_exec(bContext *C, wmOperator *op)
01214 {
01215     Scene *scene= CTX_data_scene(C);
01216     MultiresBakeJob *bkr;
01217     wmJob *steve;
01218 
01219     if(!multiresbake_check(C, op))
01220         return OPERATOR_CANCELLED;
01221 
01222     bkr= MEM_callocN(sizeof(MultiresBakeJob), "MultiresBakeJob data");
01223     init_multiresbake_job(C, bkr);
01224 
01225     if(!bkr->data.first) {
01226         BKE_report(op->reports, RPT_ERROR, "No objects found to bake from");
01227         return OPERATOR_CANCELLED;
01228     }
01229 
01230     /* setup job */
01231     steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Multires Bake", WM_JOB_EXCL_RENDER|WM_JOB_PRIORITY|WM_JOB_PROGRESS);
01232     WM_jobs_customdata(steve, bkr, multiresbake_freejob);
01233     WM_jobs_timer(steve, 0.2, NC_IMAGE, 0); /* TODO - only draw bake image, can we enforce this */
01234     WM_jobs_callbacks(steve, multiresbake_startjob, NULL, NULL, NULL);
01235 
01236     G.afbreek= 0;
01237 
01238     WM_jobs_start(CTX_wm_manager(C), steve);
01239     WM_cursor_wait(0);
01240 
01241     /* add modal handler for ESC */
01242     WM_event_add_modal_handler(C, op);
01243 
01244     return OPERATOR_RUNNING_MODAL;
01245 }
01246 
01247 /* ****************** render BAKING ********************** */
01248 
01249 /* threaded break test */
01250 static int thread_break(void *UNUSED(arg))
01251 {
01252     return G.afbreek;
01253 }
01254 
01255 typedef struct BakeRender {
01256     Render *re;
01257     Main *main;
01258     Scene *scene;
01259     struct Object *actob;
01260     int tot, ready;
01261 
01262     ReportList *reports;
01263 
01264     short *stop;
01265     short *do_update;
01266     float *progress;
01267     
01268     ListBase threads;
01269 
01270     /* backup */
01271     short prev_wo_amb_occ;
01272     short prev_r_raytrace;
01273 
01274     /* for redrawing */
01275     ScrArea *sa;
01276 } BakeRender;
01277 
01278 /* use by exec and invoke */
01279 static int test_bake_internal(bContext *C, ReportList *reports)
01280 {
01281     Scene *scene= CTX_data_scene(C);
01282 
01283     if((scene->r.bake_flag & R_BAKE_TO_ACTIVE) && CTX_data_active_object(C)==NULL) {
01284         BKE_report(reports, RPT_ERROR, "No active object");
01285     }
01286     else if(scene->r.bake_mode==RE_BAKE_AO && scene->world==NULL) {
01287         BKE_report(reports, RPT_ERROR, "No world set up");
01288     }
01289     else {
01290         return 1;
01291     }
01292 
01293     return 0;
01294 }
01295 
01296 static void init_bake_internal(BakeRender *bkr, bContext *C)
01297 {
01298     Scene *scene= CTX_data_scene(C);
01299 
01300     /* get editmode results */
01301     ED_object_exit_editmode(C, 0);  /* 0 = does not exit editmode */
01302 
01303     bkr->sa= BKE_screen_find_big_area(CTX_wm_screen(C), SPACE_IMAGE, 10); /* can be NULL */
01304     bkr->main= CTX_data_main(C);
01305     bkr->scene= scene;
01306     bkr->actob= (scene->r.bake_flag & R_BAKE_TO_ACTIVE) ? OBACT : NULL;
01307     bkr->re= RE_NewRender("_Bake View_");
01308 
01309     if(scene->r.bake_mode==RE_BAKE_AO) {
01310         /* If raytracing or AO is disabled, switch it on temporarily for baking. */
01311         bkr->prev_wo_amb_occ = (scene->world->mode & WO_AMB_OCC) != 0;
01312         scene->world->mode |= WO_AMB_OCC;
01313     }
01314     if(scene->r.bake_mode==RE_BAKE_AO || bkr->actob) {
01315         bkr->prev_r_raytrace = (scene->r.mode & R_RAYTRACE) != 0;
01316         scene->r.mode |= R_RAYTRACE;
01317     }
01318 }
01319 
01320 static void finish_bake_internal(BakeRender *bkr)
01321 {
01322     RE_Database_Free(bkr->re);
01323 
01324     /* restore raytrace and AO */
01325     if(bkr->scene->r.bake_mode==RE_BAKE_AO)
01326         if(bkr->prev_wo_amb_occ == 0)
01327             bkr->scene->world->mode &= ~WO_AMB_OCC;
01328 
01329     if(bkr->scene->r.bake_mode==RE_BAKE_AO || bkr->actob)
01330         if(bkr->prev_r_raytrace == 0)
01331             bkr->scene->r.mode &= ~R_RAYTRACE;
01332 
01333     if(bkr->tot) {
01334         Image *ima;
01335         /* force OpenGL reload and mipmap recalc */
01336         for(ima= G.main->image.first; ima; ima= ima->id.next) {
01337             if(ima->ok==IMA_OK_LOADED) {
01338                 ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
01339                 if(ibuf) {
01340                     if(ibuf->userflags & IB_BITMAPDIRTY) {
01341                         GPU_free_image(ima);
01342                         imb_freemipmapImBuf(ibuf);
01343                     }
01344 
01345                     /* freed when baking is done, but if its canceled we need to free here */
01346                     if (ibuf->userdata) {
01347                         MEM_freeN(ibuf->userdata);
01348                         ibuf->userdata= NULL;
01349                     }
01350                 }
01351             }
01352         }
01353     }
01354 }
01355 
01356 static void *do_bake_render(void *bake_v)
01357 {
01358     BakeRender *bkr= bake_v;
01359 
01360     bkr->tot= RE_bake_shade_all_selected(bkr->re, bkr->scene->r.bake_mode, bkr->actob, NULL, bkr->progress);
01361     bkr->ready= 1;
01362 
01363     return NULL;
01364 }
01365 
01366 static void bake_startjob(void *bkv, short *stop, short *do_update, float *progress)
01367 {
01368     BakeRender *bkr= bkv;
01369     Scene *scene= bkr->scene;
01370     Main *bmain= bkr->main;
01371 
01372     bkr->stop= stop;
01373     bkr->do_update= do_update;
01374     bkr->progress= progress;
01375 
01376     RE_test_break_cb(bkr->re, NULL, thread_break);
01377     G.afbreek= 0;   /* blender_test_break uses this global */
01378 
01379     RE_Database_Baking(bkr->re, bmain, scene, scene->lay, scene->r.bake_mode, bkr->actob);
01380 
01381     /* baking itself is threaded, cannot use test_break in threads. we also update optional imagewindow */
01382     bkr->tot= RE_bake_shade_all_selected(bkr->re, scene->r.bake_mode, bkr->actob, bkr->do_update, bkr->progress);
01383 }
01384 
01385 static void bake_update(void *bkv)
01386 {
01387     BakeRender *bkr= bkv;
01388 
01389     if(bkr->sa && bkr->sa->spacetype==SPACE_IMAGE) { /* incase the user changed while baking */
01390         SpaceImage *sima= bkr->sa->spacedata.first;
01391         if(sima)
01392             sima->image= RE_bake_shade_get_image();
01393     }
01394 }
01395 
01396 static void bake_freejob(void *bkv)
01397 {
01398     BakeRender *bkr= bkv;
01399     finish_bake_internal(bkr);
01400 
01401     if(bkr->tot==0) BKE_report(bkr->reports, RPT_ERROR, "No objects or images found to bake to");
01402     MEM_freeN(bkr);
01403     G.rendering = 0;
01404 }
01405 
01406 /* catch esc */
01407 static int objects_bake_render_modal(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
01408 {
01409     /* no running blender, remove handler and pass through */
01410     if(0==WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C)))
01411         return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH;
01412 
01413     /* running render */
01414     switch (event->type) {
01415         case ESCKEY:
01416             return OPERATOR_RUNNING_MODAL;
01417             break;
01418     }
01419     return OPERATOR_PASS_THROUGH;
01420 }
01421 
01422 static int is_multires_bake(Scene *scene)
01423 {
01424     if ( ELEM(scene->r.bake_mode, RE_BAKE_NORMALS, RE_BAKE_DISPLACEMENT))
01425         return scene->r.bake_flag & R_BAKE_MULTIRES;
01426 
01427     return 0;
01428 }
01429 
01430 static int objects_bake_render_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(_event))
01431 {
01432     Scene *scene= CTX_data_scene(C);
01433     int result= OPERATOR_CANCELLED;
01434 
01435     if(is_multires_bake(scene)) {
01436         result= multiresbake_image_exec(C, op);
01437     } else {
01438         /* only one render job at a time */
01439         if(WM_jobs_test(CTX_wm_manager(C), scene))
01440             return OPERATOR_CANCELLED;
01441 
01442         if(test_bake_internal(C, op->reports)==0) {
01443             return OPERATOR_CANCELLED;
01444         }
01445         else {
01446             BakeRender *bkr= MEM_callocN(sizeof(BakeRender), "render bake");
01447             wmJob *steve;
01448 
01449             init_bake_internal(bkr, C);
01450             bkr->reports= op->reports;
01451 
01452             /* setup job */
01453             steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Texture Bake", WM_JOB_EXCL_RENDER|WM_JOB_PRIORITY|WM_JOB_PROGRESS);
01454             WM_jobs_customdata(steve, bkr, bake_freejob);
01455             WM_jobs_timer(steve, 0.2, NC_IMAGE, 0); /* TODO - only draw bake image, can we enforce this */
01456             WM_jobs_callbacks(steve, bake_startjob, NULL, bake_update, NULL);
01457 
01458             G.afbreek= 0;
01459             G.rendering = 1;
01460 
01461             WM_jobs_start(CTX_wm_manager(C), steve);
01462 
01463             WM_cursor_wait(0);
01464 
01465             /* add modal handler for ESC */
01466             WM_event_add_modal_handler(C, op);
01467         }
01468 
01469         result= OPERATOR_RUNNING_MODAL;
01470     }
01471 
01472     WM_event_add_notifier(C, NC_SCENE|ND_RENDER_RESULT, scene);
01473 
01474     return result;
01475 }
01476 
01477 
01478 static int bake_image_exec(bContext *C, wmOperator *op)
01479 {
01480     Main *bmain= CTX_data_main(C);
01481     Scene *scene= CTX_data_scene(C);
01482     int result= OPERATOR_CANCELLED;
01483 
01484     if(is_multires_bake(scene)) {
01485         result= multiresbake_image_exec_locked(C, op);
01486     } else  {
01487         if(test_bake_internal(C, op->reports)==0) {
01488             return OPERATOR_CANCELLED;
01489         }
01490         else {
01491             ListBase threads;
01492             BakeRender bkr= {NULL};
01493 
01494             init_bake_internal(&bkr, C);
01495             bkr.reports= op->reports;
01496 
01497             RE_test_break_cb(bkr.re, NULL, thread_break);
01498             G.afbreek= 0;   /* blender_test_break uses this global */
01499 
01500             RE_Database_Baking(bkr.re, bmain, scene, scene->lay, scene->r.bake_mode, (scene->r.bake_flag & R_BAKE_TO_ACTIVE)? OBACT: NULL);
01501 
01502             /* baking itself is threaded, cannot use test_break in threads  */
01503             BLI_init_threads(&threads, do_bake_render, 1);
01504             bkr.ready= 0;
01505             BLI_insert_thread(&threads, &bkr);
01506 
01507             while(bkr.ready==0) {
01508                 PIL_sleep_ms(50);
01509                 if(bkr.ready)
01510                     break;
01511 
01512                 /* used to redraw in 2.4x but this is just for exec in 2.5 */
01513                 if (!G.background)
01514                     blender_test_break();
01515             }
01516             BLI_end_threads(&threads);
01517 
01518             if(bkr.tot==0) BKE_report(op->reports, RPT_ERROR, "No valid images found to bake to");
01519 
01520             finish_bake_internal(&bkr);
01521 
01522             result= OPERATOR_FINISHED;
01523         }
01524     }
01525 
01526     WM_event_add_notifier(C, NC_SCENE|ND_RENDER_RESULT, scene);
01527 
01528     return result;
01529 }
01530 
01531 void OBJECT_OT_bake_image(wmOperatorType *ot)
01532 {
01533     /* identifiers */
01534     ot->name= "Bake";
01535     ot->description= "Bake image textures of selected objects";
01536     ot->idname= "OBJECT_OT_bake_image";
01537 
01538     /* api callbacks */
01539     ot->exec= bake_image_exec;
01540     ot->invoke= objects_bake_render_invoke;
01541     ot->modal= objects_bake_render_modal;
01542 }