diff options
23 files changed, 393 insertions, 152 deletions
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 5cd905d07ac..075405b1097 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -44,7 +44,7 @@ struct ListBase; struct MemFile; #define BLENDER_VERSION 245 -#define BLENDER_SUBVERSION 8 +#define BLENDER_SUBVERSION 9 #define BLENDER_MINVERSION 240 #define BLENDER_MINSUBVERSION 0 diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index f410167c2ac..6248e01432e 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -296,7 +296,7 @@ static Render *fastshade_get_render(void) if(re==NULL) { re= RE_NewRender("_Shade View_"); - RE_Database_Baking(re, G.scene, 0); /* 0= no faces */ + RE_Database_Baking(re, G.scene, 0, 0); /* 0= no faces */ } return re; } diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index ed5fe58d06f..0699e3b8655 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -629,7 +629,7 @@ void new_material_to_objectdata(Object *ob) static void do_init_render_material(Material *ma, int r_mode, float *amb) { MTex *mtex; - int a, needuv=0; + int a, needuv=0, needtang=0; if(ma->flarec==0) ma->flarec= 1; @@ -653,8 +653,14 @@ static void do_init_render_material(Material *ma, int r_mode, float *amb) if(ma->texco & (TEXCO_ORCO|TEXCO_REFL|TEXCO_NORM|TEXCO_STRAND|TEXCO_STRESS)) needuv= 1; else if(ma->texco & (TEXCO_GLOB|TEXCO_UV|TEXCO_OBJECT|TEXCO_SPEED)) needuv= 1; else if(ma->texco & (TEXCO_LAVECTOR|TEXCO_VIEW|TEXCO_STICKY)) needuv= 1; + + if((ma->mapto & MAP_NORM) && (mtex->normapspace == MTEX_NSPACE_TANGENT)) + needtang= 1; } } + + if(needtang) ma->mode |= MA_NORMAP_TANG; + else ma->mode &= ~MA_NORMAP_TANG; if(r_mode & R_RADIO) if(ma->mode & MA_RADIO) needuv= 1; diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index aa9c489044a..ff7b429845d 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -206,6 +206,7 @@ Scene *add_scene(char *name) sce->r.bake_filter= 2; sce->r.bake_osa= 5; sce->r.bake_flag= R_BAKE_CLEAR; + sce->r.bake_normal_space= R_BAKE_SPACE_TANGENT; sce->r.xplay= 640; sce->r.yplay= 480; diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index baa6fae6fc8..d4a085ff8bd 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -517,6 +517,7 @@ void default_mtex(MTex *mtex) mtex->norfac= 0.5; mtex->varfac= 1.0; mtex->dispfac=0.2; + mtex->normapspace= MTEX_NSPACE_TANGENT; } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index ae6a2749269..ff2a4edab9d 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -7170,6 +7170,16 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } } + if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 9)) { + Material *ma; + int a; + + for(ma=main->mat.first; ma; ma= ma->id.next) + if(ma->mode & MA_NORMAP_TANG) + for(a=0; a<MAX_MTEX; a++) + if(ma->mtex[a] && ma->mtex[a]->tex) + ma->mtex[a]->normapspace = MTEX_NSPACE_TANGENT; + } /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ /* WATCH IT 2!: Userdef struct init has to be in src/usiblender.c! */ diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 1a1cb1c0f2b..f9418d1fc85 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -265,6 +265,8 @@ typedef struct RenderData { /* Bake Render options */ short bake_osa, bake_filter, bake_mode, bake_flag; + short bake_normal_space, bpad; + float bake_maxdist; /* yafray: global panel params. TODO: move elsewhere */ short GIquality, GIcache, GImethod, GIphotons, GIdirect; @@ -605,8 +607,15 @@ typedef struct Scene { /* bake_mode: same as RE_BAKE_xxx defines */ /* bake_flag: */ -#define R_BAKE_CLEAR 1 -#define R_BAKE_OSA 2 +#define R_BAKE_CLEAR 1 +#define R_BAKE_OSA 2 +#define R_BAKE_TO_ACTIVE 4 + +/* bake_normal_space */ +#define R_BAKE_SPACE_CAMERA 0 +#define R_BAKE_SPACE_WORLD 1 +#define R_BAKE_SPACE_OBJECT 2 +#define R_BAKE_SPACE_TANGENT 3 /* **************** SCENE ********************* */ #define RAD_PHASE_PATCHES 1 diff --git a/source/blender/makesdna/DNA_texture_types.h b/source/blender/makesdna/DNA_texture_types.h index 2de6aba6b6f..14ece2b31b2 100644 --- a/source/blender/makesdna/DNA_texture_types.h +++ b/source/blender/makesdna/DNA_texture_types.h @@ -58,6 +58,7 @@ typedef struct MTex { float ofs[3], size[3]; short texflag, colormodel, pmapto, pmaptoneg; + short normapspace, pad[3]; float r, g, b, k; float def_var, rt; @@ -157,7 +158,7 @@ typedef struct Tex { float cropxmin, cropymin, cropxmax, cropymax; short xrepeat, yrepeat; short extend; - + /* variables disabled, moved to struct iuser */ short fie_ima; int len; @@ -319,6 +320,12 @@ typedef struct TexMapping { #define TEX_COL2 2 #define TEX_COL3 3 +/* mtex->normapspace */ +#define MTEX_NSPACE_CAMERA 0 +#define MTEX_NSPACE_WORLD 1 +#define MTEX_NSPACE_OBJECT 2 +#define MTEX_NSPACE_TANGENT 3 + /* wrap */ #define MTEX_FLAT 0 #define MTEX_CUBE 1 diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index 9abc873172f..a8abf85a285 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -37,6 +37,7 @@ struct Scene; struct RenderData; struct NodeBlurData; +struct Object; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* this include is what is exposed of render to outside world */ @@ -209,7 +210,7 @@ void RE_zbuf_accumulate_vecblur(struct NodeBlurData *nbd, int xsize, int ysize, #define RE_BAKE_AO 2 #define RE_BAKE_NORMALS 3 #define RE_BAKE_TEXTURE 4 -void RE_Database_Baking(struct Render *re, struct Scene *scene, int type); +void RE_Database_Baking(struct Render *re, struct Scene *scene, int type, struct Object *actob); void RE_DataBase_GetView(struct Render *re, float mat[][4]); diff --git a/source/blender/render/extern/include/RE_raytrace.h b/source/blender/render/extern/include/RE_raytrace.h index 095ffcf0c18..d20e3130fa4 100644 --- a/source/blender/render/extern/include/RE_raytrace.h +++ b/source/blender/render/extern/include/RE_raytrace.h @@ -64,6 +64,9 @@ typedef struct Isect { RayFace *facecontr; float ddalabda; short faceisect; /* flag if facecontr was done or not */ + + /* custom pointer to be used in the RayCheckFunc */ + void *userdata; } Isect; /* function callbacks for face type abstraction */ @@ -80,6 +83,7 @@ void RE_ray_tree_free(RayTree *tree); /* intersection with full tree and single face */ int RE_ray_tree_intersect(RayTree *tree, Isect *is); +int RE_ray_tree_intersect_check(RayTree *tree, Isect *is, RayCheckFunc check); int RE_ray_face_intersection(Isect *is, RayCoordsFunc coordsfunc); /* retrieve the diameter of the tree structure, for setting intersection diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h index 052e104ee62..7717d6fdc48 100644 --- a/source/blender/render/extern/include/RE_shader_ext.h +++ b/source/blender/render/extern/include/RE_shader_ext.h @@ -173,9 +173,10 @@ int multitex_ext(struct Tex *tex, float *texvec, float *dxt, float *dyt, int osa /* shaded view and bake */ struct Render; struct Image; +struct Object; void RE_shade_external(struct Render *re, struct ShadeInput *shi, struct ShadeResult *shr); -int RE_bake_shade_all_selected(struct Render *re, int type); +int RE_bake_shade_all_selected(struct Render *re, int type, struct Object *actob); struct Image *RE_bake_shade_get_image(void); #endif /* RE_SHADER_EXT_H */ diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index abcdf417b62..c20d27bfcdc 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -181,6 +181,8 @@ struct Render ListBase customdata_names; + struct Object *excludeob; + /* arena for allocating data for use during render, for * example dynamic TFaces to go in the VlakRen structure. */ @@ -394,6 +396,7 @@ typedef struct LampRen { #define R_SEC_FIELD 4 #define R_LAMPHALO 8 #define R_GLOB_NOPUNOFLIP 16 +#define R_NEED_TANGENT 32 /* vlakren->flag (vlak = face in dutch) char!!! */ #define R_SMOOTH 1 diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index dd593d9edcc..f64ff1501cb 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -447,14 +447,39 @@ static void calc_edge_stress(Render *re, Mesh *me, int startvert, int startvlak) MEM_freeN(accum); } +void tangent_from_uv(float *uv1, float *uv2, float *uv3, float *co1, float *co2, float *co3, float *n, float *tang) +{ + float tangv[3], ct[3], e1[3], e2[3], s1, t1, s2, t2, det; + + s1= uv2[0] - uv1[0]; + s2= uv3[0] - uv1[0]; + t1= uv2[1] - uv1[1]; + t2= uv3[1] - uv1[1]; + det= 1.0f / (s1 * t2 - s2 * t1); + + /* normals in render are inversed... */ + VecSubf(e1, co1, co2); + VecSubf(e2, co1, co3); + tang[0] = (t2*e1[0] - t1*e2[0])*det; + tang[1] = (t2*e1[1] - t1*e2[1])*det; + tang[2] = (t2*e1[2] - t1*e2[2])*det; + tangv[0] = (s1*e2[0] - s2*e1[0])*det; + tangv[1] = (s1*e2[1] - s2*e1[1])*det; + tangv[2] = (s1*e2[2] - s2*e1[2])*det; + Crossf(ct, tang, tangv); + + /* check flip */ + if ((ct[0]*n[0] + ct[1]*n[1] + ct[2]*n[2]) < 0.0f) + VecMulf(tang, -1.0f); +} + /* gets tangent from tface or orco */ static void calc_tangent_vector(Render *re, VlakRen *vlr) { MTFace *tface= RE_vlakren_get_tface(re, vlr, 0, NULL, 0); VertRen *v1=vlr->v1, *v2=vlr->v2, *v3=vlr->v3, *v4=vlr->v4; - float tang[3], tangv[3], ct[3], e1[3], e2[3], *tav; + float tang[3], *tav; float *uv1, *uv2, *uv3, *uv4; - float s1, s2, t1, t2, det; float uv[4][2]; if(tface) { @@ -472,26 +497,8 @@ static void calc_tangent_vector(Render *re, VlakRen *vlr) spheremap(v4->orco[0], v4->orco[1], v4->orco[2], &uv[3][0], &uv[3][1]); } else return; - - s1= uv2[0] - uv1[0]; - s2= uv3[0] - uv1[0]; - t1= uv2[1] - uv1[1]; - t2= uv3[1] - uv1[1]; - det= 1.0f / (s1 * t2 - s2 * t1); - - /* normals in render are inversed... */ - VecSubf(e1, v1->co, v2->co); - VecSubf(e2, v1->co, v3->co); - tang[0] = (t2*e1[0] - t1*e2[0])*det; - tang[1] = (t2*e1[1] - t1*e2[1])*det; - tang[2] = (t2*e1[2] - t1*e2[2])*det; - tangv[0] = (s1*e2[0] - s2*e1[0])*det; - tangv[1] = (s1*e2[1] - s2*e1[1])*det; - tangv[2] = (s1*e2[2] - s2*e1[2])*det; - Crossf(ct, tang, tangv); - /* check flip */ - if ((ct[0]*vlr->n[0] + ct[1]*vlr->n[1] + ct[2]*vlr->n[2]) < 0.f) - VecMulf(tang, -1.f); + + tangent_from_uv(uv1, uv2, uv3, v1->co, v2->co, v3->co, vlr->n, tang); tav= RE_vertren_get_tangent(re, v1, 1); VECADD(tav, tav, tang); @@ -501,24 +508,7 @@ static void calc_tangent_vector(Render *re, VlakRen *vlr) VECADD(tav, tav, tang); if(v4) { - s1= uv3[0] - uv1[0]; - s2= uv4[0] - uv1[0]; - t1= uv3[1] - uv1[1]; - t2= uv4[1] - uv1[1]; - det= 1.0f / (s1 * t2 - s2 * t1); - - /* normals in render are inversed... */ - VecSubf(e1, v1->co, v3->co); - VecSubf(e2, v1->co, v4->co); - tang[0] = (t2*e1[0] - t1*e2[0])*det; - tang[1] = (t2*e1[1] - t1*e2[1])*det; - tang[2] = (t2*e1[2] - t1*e2[2])*det; - tangv[0] = (s1*e2[0] - s2*e1[0])*det; - tangv[1] = (s1*e2[1] - s2*e1[1])*det; - tangv[2] = (s1*e2[2] - s2*e1[2])*det; - Crossf(ct, tang, tangv); - if ((ct[0]*vlr->n[0] + ct[1]*vlr->n[1] + ct[2]*vlr->n[2]) < 0.f) - VecMulf(tang, -1.f); + tangent_from_uv(uv1, uv3, uv4, v1->co, v3->co, v4->co, vlr->n, tang); tav= RE_vertren_get_tangent(re, v1, 1); VECADD(tav, tav, tang); @@ -2627,6 +2617,13 @@ static void init_render_mesh(Render *re, Object *ob, Object *par, int only_verts do_autosmooth= 1; } } + + if(re->flag & R_NEED_TANGENT) { + /* exception for tangent space baking */ + need_tangent= 1; + if(me->mtface==NULL) + need_orco= 1; + } /* check autosmooth and displacement, we then have to skip only-verts optimize */ do_autosmooth |= (me->flag & ME_AUTOSMOOTH); @@ -4781,7 +4778,7 @@ void RE_DataBase_ApplyWindow(Render *re) RE_BAKE_AO: for baking, no lamps, but all objects RE_BAKE_TEXTURE:for baking, no lamps, only selected objects */ -void RE_Database_Baking(Render *re, Scene *scene, int type) +void RE_Database_Baking(Render *re, Scene *scene, int type, Object *actob) { Base *base; Object *ob; @@ -4795,8 +4792,12 @@ void RE_Database_Baking(Render *re, Scene *scene, int type) re->r= scene->r; re->r.mode &= ~R_OSA; re->flag |= R_GLOB_NOPUNOFLIP; + re->excludeob= actob; + + if(type==RE_BAKE_NORMALS && re->r.bake_normal_space==R_BAKE_SPACE_TANGENT) + re->flag |= R_NEED_TANGENT; - if( ELEM3(type, RE_BAKE_LIGHT, RE_BAKE_NORMALS, RE_BAKE_TEXTURE) ) { + if(!actob && ELEM3(type, RE_BAKE_LIGHT, RE_BAKE_NORMALS, RE_BAKE_TEXTURE)) { re->r.mode &= ~R_SHADOW; re->r.mode &= ~R_RAYTRACE; } @@ -4887,7 +4888,7 @@ void RE_Database_Baking(Render *re, Scene *scene, int type) init_render_object(re, ob, NULL, 0, 0); } else if(type!=RE_BAKE_LIGHT) { - if( !ELEM(type, RE_BAKE_NORMALS, RE_BAKE_TEXTURE) || (ob->flag & SELECT)) + if( !ELEM(type, RE_BAKE_NORMALS, RE_BAKE_TEXTURE) || (ob->flag & SELECT) || (ob == actob) ) init_render_object(re, ob, NULL, 0, 0); } } @@ -4915,14 +4916,10 @@ void RE_Database_Baking(Render *re, Scene *scene, int type) } } - if(type!=RE_BAKE_LIGHT) { - /* raytree */ - if(!re->test_break()) { - if(re->r.mode & R_RAYTRACE) { - makeraytree(re); - } - } - } + /* raytree */ + if(!re->test_break()) + if(re->r.mode & R_RAYTRACE) + makeraytree(re); } void RE_DataBase_GetView(Render *re, float mat[][4]) diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index e7345c106a6..5141841e157 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -111,15 +111,16 @@ void makeraytree(Render *re) else vlr++; if(vlr->mat->mode & MA_TRACEBLE) { if((vlr->mat->mode & MA_WIRE)==0) { - - DO_MINMAX(vlr->v1->co, min, max); - DO_MINMAX(vlr->v2->co, min, max); - DO_MINMAX(vlr->v3->co, min, max); - if(vlr->v4) { - DO_MINMAX(vlr->v4->co, min, max); - } + if(!re->excludeob || vlr->ob != re->excludeob) { + DO_MINMAX(vlr->v1->co, min, max); + DO_MINMAX(vlr->v2->co, min, max); + DO_MINMAX(vlr->v3->co, min, max); + if(vlr->v4) { + DO_MINMAX(vlr->v4->co, min, max); + } - totface++; + totface++; + } } } } @@ -149,11 +150,10 @@ void makeraytree(Render *re) } else vlr++; - if(vlr->mat->mode & MA_TRACEBLE) { - if((vlr->mat->mode & MA_WIRE)==0) { - RE_ray_tree_add_face(re->raytree, (RayFace*)vlr); - } - } + if(vlr->mat->mode & MA_TRACEBLE) + if((vlr->mat->mode & MA_WIRE)==0) + if(!re->excludeob || vlr->ob != re->excludeob) + RE_ray_tree_add_face(re->raytree, (RayFace*)vlr); } RE_ray_tree_done(re->raytree); diff --git a/source/blender/render/intern/source/raytrace.c b/source/blender/render/intern/source/raytrace.c index f86032b5d68..002148ed97c 100644 --- a/source/blender/render/intern/source/raytrace.c +++ b/source/blender/render/intern/source/raytrace.c @@ -902,7 +902,7 @@ int RE_ray_face_intersection(Isect *is, RayCoordsFunc coordsfunc) } /* check all faces in this node */ -static int testnode(Octree *oc, Isect *is, Node *no, OcVal ocval) +static int testnode(Octree *oc, Isect *is, Node *no, OcVal ocval, RayCheckFunc checkfunc) { RayFace *face; short nr=0; @@ -916,7 +916,7 @@ static int testnode(Octree *oc, Isect *is, Node *no, OcVal ocval) if(is->faceorig != face) { - if(oc->checkfunc(is, face)) { + if(checkfunc(is, face)) { ov= no->ov+nr; if( (ov->ocx & ocval.ocx) && (ov->ocy & ocval.ocy) && (ov->ocz & ocval.ocz) ) { @@ -952,7 +952,7 @@ static int testnode(Octree *oc, Isect *is, Node *no, OcVal ocval) while(face) { if(is->faceorig != face) { - if(oc->checkfunc(is, face)) { + if(checkfunc(is, face)) { ov= no->ov+nr; if( (ov->ocx & ocval.ocx) && (ov->ocy & ocval.ocy) && (ov->ocz & ocval.ocz) ) { //accepted++; @@ -1097,9 +1097,16 @@ static int do_coherence_test(int ocx1, int ocx2, int ocy1, int ocy2, int ocz1, i */ +int RE_ray_tree_intersect(RayTree *tree, Isect *is) +{ + Octree *oc= (Octree*)tree; + + return RE_ray_tree_intersect_check(tree, is, oc->checkfunc); +} + /* return 1: found valid intersection */ /* starts with is->faceorig */ -int RE_ray_tree_intersect(RayTree *tree, Isect *is) +int RE_ray_tree_intersect_check(RayTree *tree, Isect *is, RayCheckFunc checkfunc) { Octree *oc= (Octree*)tree; Node *no; @@ -1123,7 +1130,7 @@ int RE_ray_tree_intersect(RayTree *tree, Isect *is) /* check with last intersected shadow face */ if(is->face_last!=NULL && is->face_last!=is->faceorig) { - if(oc->checkfunc(is, is->face_last)) { + if(checkfunc(is, is->face_last)) { is->face= is->face_last; VECSUB(is->vec, is->end, is->start); if(RE_ray_face_intersection(is, oc->coordsfunc)) return 1; @@ -1193,7 +1200,7 @@ int RE_ray_tree_intersect(RayTree *tree, Isect *is) vec2[0]= ox2; vec2[1]= oy2; vec2[2]= oz2; calc_ocval_ray(&ocval, (float)ocx1, (float)ocy1, (float)ocz1, vec1, vec2); is->ddalabda= 1.0f; - if( testnode(oc, is, no, ocval) ) return 1; + if( testnode(oc, is, no, ocval, checkfunc) ) return 1; } } else { @@ -1272,7 +1279,7 @@ int RE_ray_tree_intersect(RayTree *tree, Isect *is) calc_ocval_ray(&ocval, (float)xo, (float)yo, (float)zo, vec1, vec2); is->ddalabda= ddalabda; - if( testnode(oc, is, no, ocval) ) return 1; + if( testnode(oc, is, no, ocval, checkfunc) ) return 1; } labdao= ddalabda; diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index 0f91a92fe9c..636bee32e05 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -66,6 +66,7 @@ #include "shading.h" #include "sss.h" #include "zbuf.h" +#include "RE_raytrace.h" #include "PIL_time.h" @@ -1657,43 +1658,35 @@ typedef struct BakeShade { ImBuf *ibuf; int rectx, recty, quad, type, vdone, ready; + + float dir[3]; + Object *actob; unsigned int *rect; float *rect_float; } BakeShade; -static void do_bake_shade(void *handle, int x, int y, float u, float v) +static void bake_set_shade_input(VlakRen *vlr, ShadeInput *shi, int quad, int isect, int x, int y, float u, float v) { - BakeShade *bs= handle; - ShadeSample *ssamp= &bs->ssamp; - ShadeInput *shi= ssamp->shi; - ShadeResult shr; - VlakRen *vlr= bs->vlr; - float l, *v1, *v2, *v3; - - /* fast threadsafe break test */ - if(R.test_break()) - return; - - /* setup render coordinates */ - if(bs->quad) { - v1= vlr->v1->co; - v2= vlr->v3->co; - v3= vlr->v4->co; + if(isect) { + /* raytrace intersection with different u,v than scanconvert */ + if(vlr->v4) { + if(quad) + shade_input_set_triangle_i(shi, vlr, 2, 1, 3); + else + shade_input_set_triangle_i(shi, vlr, 0, 1, 3); + } + else + shade_input_set_triangle_i(shi, vlr, 0, 1, 2); } else { - v1= vlr->v1->co; - v2= vlr->v2->co; - v3= vlr->v3->co; + /* regular scanconvert */ + if(quad) + shade_input_set_triangle_i(shi, vlr, 0, 2, 3); + else + shade_input_set_triangle_i(shi, vlr, 0, 1, 2); } - - /* renderco */ - l= 1.0f-u-v; - - shi->co[0]= l*v3[0]+u*v1[0]+v*v2[0]; - shi->co[1]= l*v3[1]+u*v1[1]+v*v2[1]; - shi->co[2]= l*v3[2]+u*v1[2]+v*v2[2]; - + /* set up view vector */ VECCOPY(shi->view, shi->co); Normalize(shi->view); @@ -1704,18 +1697,20 @@ static void do_bake_shade(void *handle, int x, int y, float u, float v) /* cache for shadow */ shi->samplenr++; - if(bs->quad) - shade_input_set_triangle_i(shi, vlr, 0, 2, 3); - else - shade_input_set_triangle_i(shi, vlr, 0, 1, 2); - shi->u= -u; shi->v= -v; shi->xs= x; shi->ys= y; shade_input_set_normals(shi); +} +static void bake_shade(void *handle, Object *ob, VlakRen *vlr, ShadeInput *shi, int quad, int x, int y, float u, float v, float *tvn, float *ttang) +{ + BakeShade *bs= handle; + ShadeSample *ssamp= &bs->ssamp; + ShadeResult shr; + /* init material vars */ memcpy(&shi->r, &shi->mat->r, 23*sizeof(float)); // note, keep this synced with render_types.h shi->har= shi->mat->har; @@ -1725,7 +1720,6 @@ static void do_bake_shade(void *handle, int x, int y, float u, float v) ambient_occlusion_to_diffuse(shi, shr.combined); } else { - shade_input_set_shade_texco(shi); shade_samples_do_AO(ssamp); @@ -1738,9 +1732,39 @@ static void do_bake_shade(void *handle, int x, int y, float u, float v) shade_material_loop(shi, &shr); if(bs->type==RE_BAKE_NORMALS) { - shr.combined[0]= shi->vn[0]/2.0f + 0.5f; - shr.combined[1]= 0.5f - shi->vn[1]/2.0f; - shr.combined[2]= shi->vn[2]/2.0f + 0.5f; + float nor[3]; + + VECCOPY(nor, shi->vn); + + if(R.r.bake_normal_space == R_BAKE_SPACE_CAMERA); + else if(R.r.bake_normal_space == R_BAKE_SPACE_TANGENT) { + float mat[3][3], imat[3][3]; + + /* bitangent */ + if(tvn && ttang) { + VECCOPY(mat[0], ttang); + Crossf(mat[1], tvn, ttang); + VECCOPY(mat[2], tvn); + } + else { + VECCOPY(mat[0], shi->tang); + Crossf(mat[1], shi->vn, shi->tang); + VECCOPY(mat[2], shi->vn); + } + + Mat3Inv(imat, mat); + Mat3MulVecfl(imat, nor); + } + else if(R.r.bake_normal_space == R_BAKE_SPACE_OBJECT) + Mat4Mul3Vecfl(ob->imat, nor); /* ob->imat includes viewinv! */ + else if(R.r.bake_normal_space == R_BAKE_SPACE_WORLD) + Mat4Mul3Vecfl(R.viewinv, nor); + + Normalize(nor); /* in case object has scaling */ + + shr.combined[0]= nor[0]/2.0f + 0.5f; + shr.combined[1]= 0.5f - nor[1]/2.0f; + shr.combined[2]= nor[2]/2.0f + 0.5f; } else if(bs->type==RE_BAKE_TEXTURE) { shr.combined[0]= shi->r; @@ -1763,6 +1787,131 @@ static void do_bake_shade(void *handle, int x, int y, float u, float v) } } +static int bake_check_intersect(Isect *is, RayFace *face) +{ + VlakRen *vlr = (VlakRen*)face; + BakeShade *bs = (BakeShade*)is->userdata; + + /* no direction checking for now, doesn't always improve the result + * (INPR(vlr->n, bs->dir) > 0.0f); */ + + return (vlr->ob != bs->actob); +} + +static int bake_intersect_tree(RayTree* raytree, Isect* isect, float *dir, float sign, float *hitco) +{ + float maxdist; + int hit; + + /* might be useful to make a user setting for maxsize*/ + if(R.r.bake_maxdist > 0.0f) + maxdist= R.r.bake_maxdist; + else + maxdist= RE_ray_tree_max_size(R.raytree); + + isect->end[0] = isect->start[0] + dir[0]*maxdist*sign; + isect->end[1] = isect->start[1] + dir[1]*maxdist*sign; + isect->end[2] = isect->start[2] + dir[2]*maxdist*sign; + + hit = RE_ray_tree_intersect_check(R.raytree, isect, bake_check_intersect); + if(hit) { + hitco[0] = isect->start[0] + isect->labda*isect->vec[0]; + hitco[1] = isect->start[1] + isect->labda*isect->vec[1]; + hitco[2] = isect->start[2] + isect->labda*isect->vec[2]; + } + + return hit; +} + +static void do_bake_shade(void *handle, int x, int y, float u, float v) +{ + BakeShade *bs= handle; + VlakRen *vlr= bs->vlr; + Object *ob= vlr->ob; + float l, *v1, *v2, *v3, tvn[3], ttang[3]; + int quad; + ShadeSample *ssamp= &bs->ssamp; + ShadeInput *shi= ssamp->shi; + + /* fast threadsafe break test */ + if(R.test_break()) + return; + + /* setup render coordinates */ + if(bs->quad) { + v1= vlr->v1->co; + v2= vlr->v3->co; + v3= vlr->v4->co; + } + else { + v1= vlr->v1->co; + v2= vlr->v2->co; + v3= vlr->v3->co; + } + + /* renderco */ + l= 1.0f-u-v; + + shi->co[0]= l*v3[0]+u*v1[0]+v*v2[0]; + shi->co[1]= l*v3[1]+u*v1[1]+v*v2[1]; + shi->co[2]= l*v3[2]+u*v1[2]+v*v2[2]; + + quad= bs->quad; + bake_set_shade_input(vlr, shi, quad, 0, x, y, u, v); + + if(bs->type==RE_BAKE_NORMALS && R.r.bake_normal_space==R_BAKE_SPACE_TANGENT) { + shade_input_set_shade_texco(shi); + VECCOPY(tvn, shi->vn); + VECCOPY(ttang, shi->tang); + } + + /* if we are doing selected to active baking, find point on other face */ + if(bs->actob) { + Isect isec, minisec; + float co[3], minco[3]; + int hit, sign; + + /* intersect with ray going forward and backward*/ + hit= 0; + memset(&minisec, 0, sizeof(minisec)); + minco[0]= minco[1]= minco[2]= 0.0f; + + VECCOPY(bs->dir, shi->vn); + + for(sign=-1; sign<=1; sign+=2) { + memset(&isec, 0, sizeof(isec)); + VECCOPY(isec.start, shi->co); + isec.mode= RE_RAY_MIRROR; + isec.faceorig= (RayFace*)vlr; + isec.userdata= bs; + + if(bake_intersect_tree(R.raytree, &isec, shi->vn, sign, co)) { + if(!hit || VecLenf(shi->co, co) < VecLenf(shi->co, minco)) { + minisec= isec; + VECCOPY(minco, co); + hit= 1; + } + } + } + + /* if hit, we shade from the new point, otherwise from point one starting face */ + if(hit) { + vlr= (VlakRen*)minisec.face; + quad= (minisec.isect == 2); + VECCOPY(shi->co, minco); + + u= -minisec.u; + v= -minisec.v; + bake_set_shade_input(vlr, shi, quad, 1, x, y, u, v); + } + } + + if(bs->type==RE_BAKE_NORMALS && R.r.bake_normal_space==R_BAKE_SPACE_TANGENT) + bake_shade(handle, ob, vlr, shi, quad, x, y, u, v, tvn, ttang); + else + bake_shade(handle, ob, vlr, shi, quad, x, y, u, v, 0, 0); +} + static int get_next_bake_face(BakeShade *bs) { VlakRen *vlr; @@ -1780,7 +1929,7 @@ static int get_next_bake_face(BakeShade *bs) for(; v<R.totvlak; v++) { vlr= RE_findOrAddVlak(&R, v); - if(vlr->ob->flag & SELECT) { + if((bs->actob && bs->actob == vlr->ob) || (!bs->actob && (vlr->ob->flag & SELECT))) { tface= RE_vlakren_get_tface(&R, vlr, 0, NULL, 0); if(tface && tface->tpage) { @@ -1887,7 +2036,7 @@ static void *do_bake_thread(void *bs_v) /* using object selection tags, the faces with UV maps get baked */ /* render should have been setup */ /* returns 0 if nothing was handled */ -int RE_bake_shade_all_selected(Render *re, int type) +int RE_bake_shade_all_selected(Render *re, int type, Object *actob) { BakeShade handles[BLENDER_MAX_THREADS]; ListBase threads; @@ -1919,6 +2068,7 @@ int RE_bake_shade_all_selected(Render *re, int type) handles[a].ssamp.tot= 1; handles[a].type= type; + handles[a].actob= actob; handles[a].zspan= MEM_callocN(sizeof(ZSpan), "zspan for bake"); BLI_insert_thread(&threads, &handles[a]); diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c index 9dc337c1dc4..6939e70a71b 100644 --- a/source/blender/render/intern/source/renderdatabase.c +++ b/source/blender/render/intern/source/renderdatabase.c @@ -1018,13 +1018,16 @@ void project_renderdata(Render *re, void (*projectfunc)(float *, float mat[][4], if((a & 255)==0) vlr= re->vlaknodes[a>>8].vlak; else vlr++; + if(!re->excludeob || vlr->ob != re->excludeob) { vlr->flag |= R_VISIBLE; if(vlr->v4) { if(vlr->v1->clip & vlr->v2->clip & vlr->v3->clip & vlr->v4->clip) vlr->flag &= ~R_VISIBLE; } else if(vlr->v1->clip & vlr->v2->clip & vlr->v3->clip) vlr->flag &= ~R_VISIBLE; - } + else + vlr->flag &= ~R_VISIBLE; + } } diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c index 71b59f7b8be..52a65b19824 100644 --- a/source/blender/render/intern/source/shadeinput.c +++ b/source/blender/render/intern/source/shadeinput.c @@ -538,9 +538,9 @@ void shade_input_set_shade_texco(ShadeInput *shi) } /* qdn: normalmap tangent space */ - if (mode & (MA_TANGENT_V|MA_NORMAP_TANG)) { + if (mode & (MA_TANGENT_V|MA_NORMAP_TANG) || R.flag & R_NEED_TANGENT) { float *s1, *s2, *s3; - + s1= RE_vertren_get_tangent(&R, v1, 0); s2= RE_vertren_get_tangent(&R, v2, 0); s3= RE_vertren_get_tangent(&R, v3, 0); @@ -556,7 +556,7 @@ void shade_input_set_shade_texco(ShadeInput *shi) } else { /* qdn: normalmap tangent space */ - if (mode & (MA_TANGENT_V|MA_NORMAP_TANG)) { + if (mode & (MA_TANGENT_V|MA_NORMAP_TANG) || R.flag & R_NEED_TANGENT) { /* qdn: flat faces have tangents too, could pick either one, using average here */ float *s1 = RE_vertren_get_tangent(&R, v1, 0); @@ -568,6 +568,7 @@ void shade_input_set_shade_texco(ShadeInput *shi) shi->tang[2] = (s1[2] + s2[2] + s3[2]); Normalize(shi->tang); } + else shi->tang[0]= shi->tang[1]= shi->tang[2]= 0.0f; } } diff --git a/source/blender/render/intern/source/texture.c b/source/blender/render/intern/source/texture.c index 7930fc97f2d..accd39170e4 100644 --- a/source/blender/render/intern/source/texture.c +++ b/source/blender/render/intern/source/texture.c @@ -1706,7 +1706,6 @@ void do_material_tex(ShadeInput *shi) } if( (mtex->mapto & MAP_NORM) ) { if(texres.nor) { - if(mtex->maptoneg & MAP_NORM) tex->norfac= -mtex->norfac; else tex->norfac= mtex->norfac; @@ -1723,7 +1722,7 @@ void do_material_tex(ShadeInput *shi) fact = Tnor*tex->norfac; if (fact>1.f) fact = 1.f; facm = 1.f-fact; - if (shi->mat->mode & MA_NORMAP_TANG) { + if(mtex->normapspace == MTEX_NSPACE_TANGENT) { /* qdn: tangent space */ float B[3], tv[3]; Crossf(B, shi->vn, shi->tang); /* bitangent */ @@ -1736,10 +1735,26 @@ void do_material_tex(ShadeInput *shi) shi->vn[2]= facm*shi->vn[2] + fact*tv[2]; } else { + float nor[3]; + + VECCOPY(nor, texres.nor); + + if(mtex->normapspace == MTEX_NSPACE_CAMERA); + else if(mtex->normapspace == MTEX_NSPACE_WORLD) { + Mat4Mul3Vecfl(R.viewmat, nor); + } + else if(mtex->normapspace == MTEX_NSPACE_OBJECT) { + if(shi->vlr && shi->vlr->ob) + Mat4Mul3Vecfl(shi->vlr->ob->obmat, nor); + Mat4Mul3Vecfl(R.viewmat, nor); + } + + Normalize(nor); + /* qdn: worldspace */ - shi->vn[0]= facm*shi->vn[0] + fact*texres.nor[0]; - shi->vn[1]= facm*shi->vn[1] + fact*texres.nor[1]; - shi->vn[2]= facm*shi->vn[2] + fact*texres.nor[2]; + shi->vn[0]= facm*shi->vn[0] + fact*nor[0]; + shi->vn[1]= facm*shi->vn[1] + fact*nor[1]; + shi->vn[2]= facm*shi->vn[2] + fact*nor[2]; } } else { diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 7dfd6a956cd..3855ae7de7d 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -1928,7 +1928,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco "Material value that gives no displacement"); uiDefButF(block, NUM, B_MODIFIER_RECALC, "Strength:", lx, (cy -= 19), buttonWidth, 19, &dmd->strength, - -1000, 1000, 10, 10, + -1000, 1000, 10, 0.1, "Strength of displacement"); sprintf(str, "Direction%%t|Normal%%x%d|RGB -> XYZ%%x%d|" "Z%%x%d|Y%%x%d|X%%x%d", diff --git a/source/blender/src/buttons_scene.c b/source/blender/src/buttons_scene.c index 2cc24c643cb..9da6cff1387 100644 --- a/source/blender/src/buttons_scene.c +++ b/source/blender/src/buttons_scene.c @@ -1246,6 +1246,16 @@ static void render_panel_bake(void) but= uiDefBut(block, BUT, B_NOP, "BAKE", 10, 150, 190,40, 0, 0, 0, 0, 0, "Start the bake render for selected Objects"); uiButSetFunc(but, do_bake_func, NULL, NULL); + + uiBlockBeginAlign(block); + uiDefButBitS(block, TOG, R_BAKE_TO_ACTIVE, B_DIFF, "Selected to Active", 10,120,190,20,&G.scene->r.bake_flag, 0.0, 0, 0, 0, "Bake shading on the surface of selected objects to the active object"); + uiDefButF(block, NUM, B_DIFF, "Dist:", 10,100,(G.scene->r.bake_mode == RE_BAKE_NORMALS)? 95: 190,20,&G.scene->r.bake_maxdist, 0.0, 10.0, 1, 0, "Maximum distance from active object to other object"); + + if(G.scene->r.bake_mode == RE_BAKE_NORMALS) + uiDefButS(block, MENU, B_DIFF, "Normal Space %t|Camera %x0|World %x1|Object %x2|Tangent %x3", + 105,100,95,20, &G.scene->r.bake_normal_space, 0, 0, 0, 0, "Choose normal space for baking"); + uiBlockEndAlign(block); + #if 0 uiBlockBeginAlign(block); uiDefButBitS(block, TOG, R_BAKE_OSA, B_DIFF, "OSA", 10,120,190,20, &G.scene->r.bake_flag, 0, 0, 0, 0, "Enables Oversampling (Anti-aliasing)"); @@ -1255,10 +1265,10 @@ static void render_panel_bake(void) uiDefButS(block, ROW,B_DIFF,"16", 150,100,50,20,&G.scene->r.bake_osa,2.0,16.0, 0, 0, "Sets oversample level to 16"); #endif uiBlockBeginAlign(block); - uiDefButS(block, ROW,B_DIFF,"Full Render", 210,170,120,20,&G.scene->r.bake_mode, 1.0, RE_BAKE_ALL, 0, 0, ""); - uiDefButS(block, ROW,B_DIFF,"Ambient Occlusion",210,150,120,20,&G.scene->r.bake_mode, 1.0, RE_BAKE_AO, 0, 0, ""); - uiDefButS(block, ROW,B_DIFF,"Normals", 210,130,120,20,&G.scene->r.bake_mode, 1.0, RE_BAKE_NORMALS, 0, 0, ""); - uiDefButS(block, ROW,B_DIFF,"Textures", 210,110,120,20,&G.scene->r.bake_mode, 1.0, RE_BAKE_TEXTURE, 0, 0, ""); + uiDefButS(block, ROW,B_REDR,"Full Render", 210,170,120,20,&G.scene->r.bake_mode, 1.0, RE_BAKE_ALL, 0, 0, ""); + uiDefButS(block, ROW,B_REDR,"Ambient Occlusion",210,150,120,20,&G.scene->r.bake_mode, 1.0, RE_BAKE_AO, 0, 0, ""); + uiDefButS(block, ROW,B_REDR,"Normals", 210,130,120,20,&G.scene->r.bake_mode, 1.0, RE_BAKE_NORMALS, 0, 0, ""); + uiDefButS(block, ROW,B_REDR,"Textures", 210,110,120,20,&G.scene->r.bake_mode, 1.0, RE_BAKE_TEXTURE, 0, 0, ""); uiBlockEndAlign(block); uiDefButBitS(block, TOG, R_BAKE_CLEAR, B_DIFF, "Clear", 210,80,120,20,&G.scene->r.bake_flag, 0.0, 0, 0, 0, "Clear Images before baking"); diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c index 03fce824f7f..f21272f53da 100644 --- a/source/blender/src/buttons_shading.c +++ b/source/blender/src/buttons_shading.c @@ -1227,7 +1227,7 @@ static void texture_panel_image(Image **ima, ImageUser *iuser) uiblock_image_panel(block, ima, iuser, B_REDR, B_IMAGECHANGED); } -static void texture_panel_image_map(Tex *tex) +static void texture_panel_image_map(Tex *tex, MTex *mtex) { uiBlock *block; @@ -1249,8 +1249,13 @@ static void texture_panel_image_map(Tex *tex) uiDefButF(block, NUM, B_TEXPRV, "Filter :", 10,120,150,20, &tex->filtersize, 0.1, 25.0, 10, 3, "Sets the filter size used by mipmap and interpol"); - uiDefButBitS(block, TOG, TEX_NORMALMAP, B_NOP, "Normal Map", 160,120,150,20, &tex->imaflag, + uiBlockBeginAlign(block); + uiDefButBitS(block, TOG, TEX_NORMALMAP, B_NOP, "Normal Map", 160,120,(mtex)? 75: 150,20, &tex->imaflag, 0, 0, 0, 0, "Use image RGB values for normal mapping"); + if(mtex) + uiDefButS(block, MENU, B_DIFF, "Normal Space %t|Camera %x0|World %x1|Object %x2|Tangent %x3", + 235,120,75,20, &mtex->normapspace, 0, 0, 0, 0, "Sets space of normal map image"); + uiBlockEndAlign(block); /* crop extend clip */ @@ -3783,9 +3788,6 @@ static void material_panel_shading(Material *ma) uiBlockSetCol(block, TH_BUT_SETTING1); uiDefButBitI(block, TOG, MA_TANGENT_V, B_MATPRV, "Tangent V", 245,180,65,19, &(ma->mode), 0, 0, 0, 0, "Use the tangent vector in V direction for shading"); - /* qdn: normalmap tangents separated from shading */ - uiDefButBitI(block, TOG, MA_NORMAP_TANG, B_MATPRV, "NMap TS", 245,160,65,19, &(ma->mode), 0, 0, 0, 0, "Enable Tangent Space normal mapping"); - uiBlockBeginAlign(block); uiDefButBitI(block, TOG, MA_SHADOW, B_MATPRV, "Shadow", 245,140,65,19, &(ma->mode), 0, 0, 0, 0, "Makes material receive shadows"); uiDefButBitI(block, TOG, MA_SHADOW_TRA, B_MATPRV, "TraShadow", 245,120,65,19, &(ma->mode), 0, 0, 0, 0, "Receives transparent shadows based at material color and alpha"); @@ -4293,7 +4295,7 @@ void texture_panels() switch(tex->type) { case TEX_IMAGE: texture_panel_image(&tex->ima, &tex->iuser); - texture_panel_image_map(tex); + texture_panel_image_map(tex, mtex); break; case TEX_ENVMAP: texture_panel_envmap(tex); diff --git a/source/blender/src/meshtools.c b/source/blender/src/meshtools.c index d901644c19f..d06208ea503 100644 --- a/source/blender/src/meshtools.c +++ b/source/blender/src/meshtools.c @@ -108,6 +108,7 @@ void sort_faces(void); #include "PIL_time.h" #include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" /* from rendercode.c */ #define VECMUL(dest, f) dest[0]*= f; dest[1]*= f; dest[2]*= f @@ -945,6 +946,7 @@ static ScrArea *biggest_image_area(void) typedef struct BakeRender { Render *re; + struct Object *actob; int event, tot, ready; } BakeRender; @@ -952,7 +954,7 @@ static void *do_bake_render(void *bake_v) { BakeRender *bkr= bake_v; - bkr->tot= RE_bake_shade_all_selected(bkr->re, bkr->event); + bkr->tot= RE_bake_shade_all_selected(bkr->re, bkr->event, bkr->actob); bkr->ready= 1; return NULL; @@ -971,6 +973,8 @@ void objects_bake_render_menu(void) /* all selected meshes with UV maps are rendered for current scene visibility */ void objects_bake_render(short event) { + Object *actob= OBACT; + int active= G.scene->r.bake_flag & R_BAKE_TO_ACTIVE; short prev_r_raytrace= 0, prev_wo_amb_occ= 0; if(event==0) event= G.scene->r.bake_mode; @@ -980,13 +984,16 @@ void objects_bake_render(short event) return; } + if(active && !actob) + return; + if(event>0) { Render *re= RE_NewRender("_Bake View_"); ScrArea *area= biggest_image_area(); ListBase threads; BakeRender bkr; int timer=0, tot, sculptmode= G.f & G_SCULPTMODE; - + if(sculptmode) set_sculptmode(); if(event==1) event= RE_BAKE_ALL; @@ -1001,19 +1008,20 @@ void objects_bake_render(short event) } /* If raytracing or AO is disabled, switch it on temporarily for baking. */ - prev_r_raytrace = (G.scene->r.mode & R_RAYTRACE) != 0; prev_wo_amb_occ = (G.scene->world->mode & WO_AMB_OCC) != 0; - - G.scene->r.mode |= R_RAYTRACE; G.scene->world->mode |= WO_AMB_OCC; } + if(event==RE_BAKE_AO || actob) { + prev_r_raytrace = (G.scene->r.mode & R_RAYTRACE) != 0; + G.scene->r.mode |= R_RAYTRACE; + } waitcursor(1); RE_test_break_cb(re, thread_break); g_break= 0; G.afbreek= 0; /* blender_test_break uses this global */ - RE_Database_Baking(re, G.scene, event); + RE_Database_Baking(re, G.scene, event, actob); /* baking itself is threaded, cannot use test_break in threads. we also update optional imagewindow */ @@ -1021,6 +1029,7 @@ void objects_bake_render(short event) bkr.re= re; bkr.event= event; bkr.ready= 0; + bkr.actob= actob; BLI_insert_thread(&threads, &bkr); while(bkr.ready==0) { @@ -1048,21 +1057,26 @@ void objects_bake_render(short event) if(tot==0) error("No Images found to bake to"); else { Image *ima; - /* force OpenGL reload */ + /* force OpenGL reload and mipmap recalc */ for(ima= G.main->image.first; ima; ima= ima->id.next) { if(ima->ok==IMA_OK_LOADED) { ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); - if(ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) + if(ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) { free_realtime_image(ima); + imb_freemipmapImBuf(ibuf); + } } } } - /* restore raytrace and AO */ - if(event==RE_BAKE_AO) { - if( prev_wo_amb_occ == 0) G.scene->world->mode &= ~WO_AMB_OCC; - if( prev_r_raytrace == 0) G.scene->r.mode &= ~R_RAYTRACE; - } + /* restore raytrace and AO */ + if(event==RE_BAKE_AO) + if(prev_wo_amb_occ == 0) + G.scene->world->mode &= ~WO_AMB_OCC; + + if(event==RE_BAKE_AO || actob) + if(prev_r_raytrace == 0) + G.scene->r.mode &= ~R_RAYTRACE; allqueue(REDRAWIMAGE, 0); allqueue(REDRAWVIEW3D, 0); @@ -1072,4 +1086,3 @@ void objects_bake_render(short event) } } - |