diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2007-11-29 01:21:12 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2007-11-29 01:21:12 +0300 |
commit | 561319989e6a80fda82bd70f7f9a3c0651536d98 (patch) | |
tree | 5b28dd152615e699277c69df36ba0aae7f394eb0 /source/blender/render | |
parent | 91dc459bccaa0ea89cf8a65cbb46729763ff6156 (diff) |
Render Baking
=============
A new "Selected to Active" option in the Bake panel, to (typically) bake
a high poly object onto a low poly object. Code based on patch #7339 by
Frank Richter (Crystal Space developer), thanks!.
Normal Mapping
==============
Camera, World, Object and Tangent space is now supported for baking, and
for material textures. The "NMap TS" setting is replaced with a dropdown
of the four choices in the image texture buttons.
http://www.blender.org/development/current-projects/changes-since-244/render-baking/
Diffstat (limited to 'source/blender/render')
-rw-r--r-- | source/blender/render/extern/include/RE_pipeline.h | 3 | ||||
-rw-r--r-- | source/blender/render/extern/include/RE_raytrace.h | 4 | ||||
-rw-r--r-- | source/blender/render/extern/include/RE_shader_ext.h | 3 | ||||
-rw-r--r-- | source/blender/render/intern/include/render_types.h | 3 | ||||
-rw-r--r-- | source/blender/render/intern/source/convertblender.c | 99 | ||||
-rw-r--r-- | source/blender/render/intern/source/rayshade.c | 26 | ||||
-rw-r--r-- | source/blender/render/intern/source/raytrace.c | 21 | ||||
-rw-r--r-- | source/blender/render/intern/source/rendercore.c | 228 | ||||
-rw-r--r-- | source/blender/render/intern/source/renderdatabase.c | 5 | ||||
-rw-r--r-- | source/blender/render/intern/source/shadeinput.c | 7 | ||||
-rw-r--r-- | source/blender/render/intern/source/texture.c | 25 |
11 files changed, 303 insertions, 121 deletions
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 { |