Index: source/blender/render/intern/source/convertblender.c =================================================================== --- source/blender/render/intern/source/convertblender.c (revision 12010) +++ source/blender/render/intern/source/convertblender.c (working copy) @@ -3942,7 +3942,7 @@ 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, int other) { Base *base; Object *ob; @@ -3957,7 +3957,7 @@ re->r.mode &= ~R_OSA; re->flag |= R_GLOB_NOPUNOFLIP; - if( ELEM3(type, RE_BAKE_LIGHT, RE_BAKE_NORMALS, RE_BAKE_TEXTURE) ) { + if( !other && ELEM3(type, RE_BAKE_LIGHT, RE_BAKE_NORMALS, RE_BAKE_TEXTURE) ) { re->r.mode &= ~R_SHADOW; re->r.mode &= ~R_RAYTRACE; } @@ -4044,11 +4044,11 @@ } else { if(ob->type==OB_LAMP) { if( ELEM(type, RE_BAKE_LIGHT, RE_BAKE_ALL) ) 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) || other) init_render_object(re, ob, NULL, 0, 0); } } @@ -4076,7 +4076,7 @@ } } - if(type!=RE_BAKE_LIGHT) { + if(other || type!=RE_BAKE_LIGHT) { /* raytree */ if(!re->test_break()) { if(re->r.mode & R_RAYTRACE) { Index: source/blender/render/intern/source/rendercore.c =================================================================== --- source/blender/render/intern/source/rendercore.c (revision 12010) +++ source/blender/render/intern/source/rendercore.c (working copy) @@ -66,6 +66,7 @@ #include "shading.h" #include "sss.h" #include "zbuf.h" +#include "RE_raytrace.h" #include "PIL_time.h" @@ -1654,43 +1655,19 @@ ImBuf *ibuf; int rectx, recty, quad, type, vdone, ready; + int fromOtherMesh; unsigned int *rect; float *rect_float; } BakeShade; -static void do_bake_shade(void *handle, int x, int y, float u, float v) +static void prepare_shade_input (VlakRen *vlr, ShadeInput *shi, int quad, 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; - } - 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]; - + if(quad) + shade_input_set_triangle_i(shi, vlr, 0, 2, 3); + else + shade_input_set_triangle_i(shi, vlr, 0, 1, 2); + /* set up view vector */ VECCOPY(shi->view, shi->co); Normalize(shi->view); @@ -1701,28 +1678,29 @@ /* 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 do_bake_shade_real(void *handle, VlakRen *vlr, ShadeInput *shi, int quad, int x, int y, float u, float v) +{ + 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; if(bs->type==RE_BAKE_AO) { ambient_occlusion(shi); ambient_occlusion_to_diffuse(shi, shr.combined); } else { - shade_input_set_shade_texco(shi); shade_samples_do_AO(ssamp); @@ -1760,6 +1754,138 @@ } } +static int intersect_face_with_direction (RayTree* raytree, Isect* isect, float* dir, + float* hit, float* outDist, float maxDist, float sgn, + Object* skipObject) +{ + int hasIntersect; + float distSum = 0; + + isect->end[0] = isect->start[0]+dir[0]*maxDist*sgn; + isect->end[1] = isect->start[1]+dir[1]*maxDist*sgn; + isect->end[2] = isect->start[2]+dir[2]*maxDist*sgn; + + hasIntersect = RE_ray_tree_intersect(R.raytree, isect); + while(hasIntersect) { + VlakRen *vlr= (VlakRen*)isect->face; + float hitpoint[3]; + float labdaSq, dist; + + hitpoint[0] = isect->start[0]+isect->labda*isect->vec[0]; + hitpoint[1] = isect->start[1]+isect->labda*isect->vec[1]; + hitpoint[2] = isect->start[2]+isect->labda*isect->vec[2]; + + labdaSq = isect->labda*isect->labda; + dist = isect->vec[0]*isect->vec[0]*labdaSq; + dist += isect->vec[1]*isect->vec[1]*labdaSq; + dist += isect->vec[2]*isect->vec[2]*labdaSq; + dist = sqrt (dist); + + if ((vlr->ob == skipObject) + || (((vlr->n[0] * dir[0]) + (vlr->n[1] * dir[1]) + (vlr->n[2] * dir[2])) <= 0)) + { + maxDist -= dist; + distSum += dist; + VECCOPY(isect->start, hitpoint); + /*isect->end[0] = isect->start[0]+dir[0]*maxDist*sgn; + isect->end[1] = isect->start[1]+dir[1]*maxDist*sgn; + isect->end[2] = isect->start[2]+dir[2]*maxDist*sgn;*/ + isect->faceorig = isect->face; + hasIntersect = RE_ray_tree_intersect(R.raytree, isect); + continue; + } + VECCOPY(hit, hitpoint); + *outDist = dist + distSum; + return 1; + } + return 0; +} + +static void do_bake_shade(void *handle, int x, int y, float u, float v) +{ + BakeShade *bs= handle; + VlakRen *vlr= bs->vlr; + float l, *v1, *v2, *v3; + 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]; + + prepare_shade_input (vlr, shi, bs->quad, x, y, u, v); + + if (bs->fromOtherMesh) + { + Isect isec, isec2; + float dir[3]; + float maxDist = 0.2f; + float hit[3], hit2[3]; + float dist, dist2; + int hitflags; + + VECCOPY(dir, shi->vn); + hitflags = 0; + + VECCOPY(isec.start, shi->co); + isec.mode= RE_RAY_MIRROR; + isec.faceorig= (RayFace*)vlr; + if (intersect_face_with_direction(R.raytree, &isec, dir, hit, &dist, maxDist, 1, vlr->ob)) + hitflags |= 1; + + VECCOPY(isec2.start, shi->co); + isec2.mode= RE_RAY_MIRROR; + isec2.faceorig= (RayFace*)vlr; + if (intersect_face_with_direction(R.raytree, &isec2, dir, hit2, &dist2, maxDist, -1, vlr->ob)) + hitflags |= 2; + + if (hitflags != 0) + { + if (hitflags == 3) + { + hitflags = (dist > dist2) ? 2 : 1; + } + + if (hitflags == 1) + { + vlr= (VlakRen*)isec.face; + VECCOPY(shi->co, hit); + prepare_shade_input (vlr, shi, isec.isect-1, x, y, -isec.u, -isec.v); + do_bake_shade_real (handle, vlr, shi, isec.isect-1, x, y, -isec.u, -isec.v); + } + else + { + vlr= (VlakRen*)isec2.face; + VECCOPY(shi->co, hit2); + prepare_shade_input (vlr, shi, isec2.isect-1, x, y, -isec2.u, -isec2.v); + do_bake_shade_real (handle, vlr, shi, isec2.isect-1, x, y, -isec2.u, -isec2.v); + } + return; + } + } + + do_bake_shade_real (handle, vlr, shi, bs->quad, x, y, u, v); +} + static int get_next_bake_face(BakeShade *bs) { VlakRen *vlr; @@ -1884,7 +2010,7 @@ /* 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, int other) { BakeShade handles[BLENDER_MAX_THREADS]; ListBase threads; @@ -1916,6 +2042,7 @@ handles[a].ssamp.tot= 1; handles[a].type= type; + handles[a].fromOtherMesh= other; handles[a].zspan= MEM_callocN(sizeof(ZSpan), "zspan for bake"); BLI_insert_thread(&threads, &handles[a]); Index: source/blender/render/extern/include/RE_pipeline.h =================================================================== --- source/blender/render/extern/include/RE_pipeline.h (revision 12010) +++ source/blender/render/extern/include/RE_pipeline.h (working copy) @@ -209,7 +209,7 @@ #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, int other); void RE_DataBase_GetView(struct Render *re, float mat[][4]); Index: source/blender/render/extern/include/RE_shader_ext.h =================================================================== --- source/blender/render/extern/include/RE_shader_ext.h (revision 12010) +++ source/blender/render/extern/include/RE_shader_ext.h (working copy) @@ -175,7 +175,7 @@ struct Image; 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, int other); struct Image *RE_bake_shade_get_image(void); #endif /* RE_SHADER_EXT_H */ Index: source/blender/blenkernel/intern/displist.c =================================================================== --- source/blender/blenkernel/intern/displist.c (revision 12010) +++ source/blender/blenkernel/intern/displist.c (working copy) @@ -296,7 +296,7 @@ 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; } Index: source/blender/include/BIF_meshtools.h =================================================================== --- source/blender/include/BIF_meshtools.h (revision 12010) +++ source/blender/include/BIF_meshtools.h (working copy) @@ -41,6 +41,7 @@ extern void sort_faces(void); extern void objects_bake_render_menu(void); extern void objects_bake_render(short event); +extern void objects_bake_other_render(short event); extern long mesh_octree_table(struct Object *ob, float *co, char mode); extern int mesh_get_x_mirror_vert(struct Object *ob, int index); Index: source/blender/src/meshtools.c =================================================================== --- source/blender/src/meshtools.c (revision 12010) +++ source/blender/src/meshtools.c (working copy) @@ -850,42 +850,41 @@ typedef struct BakeRender { Render *re; - int event, tot, ready; + int event, tot, ready, other; } BakeRender; 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->other); bkr->ready= 1; return NULL; } - void objects_bake_render_menu(void) { short event; event= pupmenu("Bake Selected Meshes %t|Full Render %x1|Ambient Occlusion %x2|Normals %x3|Texture Only %x4"); objects_bake_render(event); } /* all selected meshes with UV maps are rendered for current scene visibility */ -void objects_bake_render(short event) +static void objects_bake_render_common(short event, int other) { short prev_r_raytrace= 0, prev_wo_amb_occ= 0; if(event==0) event= G.scene->r.bake_mode; if(G.scene->r.renderer!=R_INTERN) { error("Bake only supported for Internal Renderer"); return; } if(event>0) { Render *re= RE_NewRender("_Bake View_"); ScrArea *area= biggest_image_area(); ListBase threads; @@ -918,14 +923,15 @@ 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, bakemode, other); /* baking itself is threaded, cannot use test_break in threads. we also update optional imagewindow */ BLI_init_threads(&threads, do_bake_render, 1); bkr.re= re; bkr.event= event; bkr.ready= 0; + bkr.other= other; BLI_insert_thread(&threads, &bkr); while(bkr.ready==0) { @@ -977,4 +983,12 @@ } } +void objects_bake_render(short event) +{ + objects_bake_render_common(event, 0); +} +void objects_bake_other_render(short event) +{ + objects_bake_render_common(event, 1); +} Index: source/blender/src/buttons_scene.c =================================================================== --- source/blender/src/buttons_scene.c (revision 12010) +++ source/blender/src/buttons_scene.c (working copy) @@ -1253,16 +1253,44 @@ #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, ""); 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"); uiDefButS(block, NUM, B_DIFF,"Margin:", 210,50,120,20,&G.scene->r.bake_filter, 0.0, 32.0, 0, 0, "Amount of pixels to extend the baked result with, as post process filter"); } +static void do_bake_other_func(void *unused_v, void *unused_p) +{ + objects_bake_other_render(0); +} + +static void render_panel_bake_othermesh(void) +{ + uiBlock *block; + uiBut *but; + + block= uiNewBlock(&curarea->uiblocks, "render_panel_bake_othermesh", UI_EMBOSS, UI_HELV, curarea->win); + uiNewPanelTabbed("Bake", "Render"); + if(uiNewPanel(curarea, block, "Bake(Other)", "Render", 320, 0, 318, 204)==0) return; + + 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_other_func, NULL, NULL); + uiBlockBeginAlign(block); + uiDefButS(block, ROW,B_DIFF,"Normals", 210, 90,120,20,&G.scene->r.bake_mode, 1.0, RE_BAKE_NORMALS, 0, 0, ""); + uiDefButS(block, ROW,B_DIFF,"Textures", 210, 70,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,40,120,20,&G.scene->r.bake_flag, 0.0, 0, 0, 0, "Clear Images before baking"); + + uiDefButS(block, NUM, B_DIFF,"Margin:", 210,10,120,20,&G.scene->r.bake_filter, 0.0, 32.0, 0, 0, "Amount of pixels to extend the baked result with, as post process filter"); + uiDefButF(block, NUMSLI, B_DIFF,"Light:", 10,10,190,20,&G.scene->r.bake_lightscale,0.0, 1.0, 0, 0, "Baked lighting scaling factor");*/ + +} + static void render_panel_render(void) { uiBlock *block; @@ -1925,6 +1957,7 @@ render_panel_render(); render_panel_anim(); render_panel_bake(); + render_panel_bake_othermesh(); render_panel_format(); #ifdef WITH_FFMPEG