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