Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2007-11-29 01:21:12 +0300
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2007-11-29 01:21:12 +0300
commit561319989e6a80fda82bd70f7f9a3c0651536d98 (patch)
tree5b28dd152615e699277c69df36ba0aae7f394eb0 /source/blender/render
parent91dc459bccaa0ea89cf8a65cbb46729763ff6156 (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.h3
-rw-r--r--source/blender/render/extern/include/RE_raytrace.h4
-rw-r--r--source/blender/render/extern/include/RE_shader_ext.h3
-rw-r--r--source/blender/render/intern/include/render_types.h3
-rw-r--r--source/blender/render/intern/source/convertblender.c99
-rw-r--r--source/blender/render/intern/source/rayshade.c26
-rw-r--r--source/blender/render/intern/source/raytrace.c21
-rw-r--r--source/blender/render/intern/source/rendercore.c228
-rw-r--r--source/blender/render/intern/source/renderdatabase.c5
-rw-r--r--source/blender/render/intern/source/shadeinput.c7
-rw-r--r--source/blender/render/intern/source/texture.c25
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 {