Blender V2.61 - r43446
|
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 }