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:
authorM.G. Kishalmi <lmg@kishalmi.net>2011-02-14 21:18:46 +0300
committerM.G. Kishalmi <lmg@kishalmi.net>2011-02-14 21:18:46 +0300
commit20553d4064e790f42fe707b8b6c5e6451e983eb7 (patch)
tree8453025eb4106b26ed323a16da222153f117ab81 /source/blender/render
parent8b7482892b2ecb456be60b42fe1625156d19e954 (diff)
This commit will switch blender to use tangent space generated within
the two files mikktspace.h and mikktspace.c. These are standalone files which can be redistributed into any other application and regenerate the same tangent spaces. The implementation is independent of the ordering of faces and the vertex ordering of faces.
Diffstat (limited to 'source/blender/render')
-rw-r--r--source/blender/render/extern/include/RE_shader_ext.h2
-rw-r--r--source/blender/render/intern/source/convertblender.c112
-rw-r--r--source/blender/render/intern/source/render_texture.c18
-rw-r--r--source/blender/render/intern/source/rendercore.c12
-rw-r--r--source/blender/render/intern/source/renderdatabase.c2
-rw-r--r--source/blender/render/intern/source/shadeinput.c47
6 files changed, 159 insertions, 34 deletions
diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h
index 2b451810e37..7825d2e4647 100644
--- a/source/blender/render/extern/include/RE_shader_ext.h
+++ b/source/blender/render/extern/include/RE_shader_ext.h
@@ -136,7 +136,7 @@ typedef struct ShadeInput
/* texture coordinates */
float lo[3], gl[3], ref[3], orn[3], winco[3], sticky[3], vcol[4];
float refcol[4], displace[3];
- float strandco, tang[3], nmaptang[3], stress, winspeed[4];
+ float strandco, tang[3], nmapnorm[3], nmaptang[4], stress, winspeed[4];
float duplilo[3], dupliuv[3];
ShadeInputUV uv[8]; /* 8 = MAX_MTFACE */
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index 72bec0cb596..b4e6d4a04c2 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -494,11 +494,82 @@ static void calc_tangent_vector(ObjectRen *obr, VertexTangent **vtangents, MemAr
}
+typedef struct
+{
+ ObjectRen *obr;
+
+} SRenderMeshToTangent;
+
+// interface
+#include "mikktspace.h"
+
+static int GetNumFaces(const SMikkTSpaceContext * pContext)
+{
+ SRenderMeshToTangent * pMesh = (SRenderMeshToTangent *) pContext->m_pUserData;
+ return pMesh->obr->totvlak;
+}
+
+static int GetNumVertsOfFace(const SMikkTSpaceContext * pContext, const int face_num)
+{
+ SRenderMeshToTangent * pMesh = (SRenderMeshToTangent *) pContext->m_pUserData;
+ VlakRen *vlr= RE_findOrAddVlak(pMesh->obr, face_num);
+ return vlr->v4!=NULL ? 4 : 3;
+}
+
+static void GetPosition(const SMikkTSpaceContext * pContext, float fPos[], const int face_num, const int vert_index)
+{
+ //assert(vert_index>=0 && vert_index<4);
+ SRenderMeshToTangent * pMesh = (SRenderMeshToTangent *) pContext->m_pUserData;
+ VlakRen *vlr= RE_findOrAddVlak(pMesh->obr, face_num);
+ VertRen * pVerts[] = {vlr->v1, vlr->v2, vlr->v3, vlr->v4};
+ VECCOPY(fPos, pVerts[vert_index]->co);
+}
+
+static void GetTextureCoordinate(const SMikkTSpaceContext * pContext, float fUV[], const int face_num, const int vert_index)
+{
+ //assert(vert_index>=0 && vert_index<4);
+ SRenderMeshToTangent * pMesh = (SRenderMeshToTangent *) pContext->m_pUserData;
+ VlakRen *vlr= RE_findOrAddVlak(pMesh->obr, face_num);
+ MTFace *tface= RE_vlakren_get_tface(pMesh->obr, vlr, pMesh->obr->actmtface, NULL, 0);
+
+ if(tface!=NULL)
+ {
+ float * pTexCo = tface->uv[vert_index];
+ fUV[0]=pTexCo[0]; fUV[1]=pTexCo[1];
+ }
+ else
+ {
+ VertRen * pVerts[] = {vlr->v1, vlr->v2, vlr->v3, vlr->v4};
+ map_to_sphere(&fUV[0], &fUV[1], pVerts[vert_index]->orco[0], pVerts[vert_index]->orco[1], pVerts[vert_index]->orco[2]);
+ }
+}
+
+static void GetNormal(const SMikkTSpaceContext * pContext, float fNorm[], const int face_num, const int vert_index)
+{
+ //assert(vert_index>=0 && vert_index<4);
+ SRenderMeshToTangent * pMesh = (SRenderMeshToTangent *) pContext->m_pUserData;
+ VlakRen *vlr= RE_findOrAddVlak(pMesh->obr, face_num);
+ VertRen * pVerts[] = {vlr->v1, vlr->v2, vlr->v3, vlr->v4};
+ VECCOPY(fNorm, pVerts[vert_index]->n);
+}
+static void SetTSpace(const SMikkTSpaceContext * pContext, const float fvTangent[], const float fSign, const int face_num, const int iVert)
+{
+ //assert(vert_index>=0 && vert_index<4);
+ SRenderMeshToTangent * pMesh = (SRenderMeshToTangent *) pContext->m_pUserData;
+ VlakRen *vlr= RE_findOrAddVlak(pMesh->obr, face_num);
+ float * ftang= RE_vlakren_get_nmap_tangent(pMesh->obr, vlr, 1);
+ if(ftang!=NULL)
+ {
+ VECCOPY(&ftang[iVert*4+0], fvTangent);
+ ftang[iVert*4+3]=fSign;
+ }
+}
+
static void calc_vertexnormals(Render *re, ObjectRen *obr, int do_tangent, int do_nmap_tangent)
{
MemArena *arena= NULL;
VertexTangent **vtangents= NULL;
- int a;
+ int a, iCalcNewMethod;
if(do_nmap_tangent) {
arena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "nmap tangent arena");
@@ -594,22 +665,24 @@ static void calc_vertexnormals(Render *re, ObjectRen *obr, int do_tangent, int d
MTFace *tface= RE_vlakren_get_tface(obr, vlr, obr->actmtface, NULL, 0);
if(tface) {
+ int k=0;
float *vtang, *ftang= RE_vlakren_get_nmap_tangent(obr, vlr, 1);
vtang= find_vertex_tangent(vtangents[v1->index], tface->uv[0]);
VECCOPY(ftang, vtang);
normalize_v3(ftang);
vtang= find_vertex_tangent(vtangents[v2->index], tface->uv[1]);
- VECCOPY(ftang+3, vtang);
- normalize_v3(ftang+3);
+ VECCOPY(ftang+4, vtang);
+ normalize_v3(ftang+4);
vtang= find_vertex_tangent(vtangents[v3->index], tface->uv[2]);
- VECCOPY(ftang+6, vtang);
- normalize_v3(ftang+6);
+ VECCOPY(ftang+8, vtang);
+ normalize_v3(ftang+8);
if(v4) {
vtang= find_vertex_tangent(vtangents[v4->index], tface->uv[3]);
- VECCOPY(ftang+9, vtang);
- normalize_v3(ftang+9);
+ VECCOPY(ftang+12, vtang);
+ normalize_v3(ftang+12);
}
+ for(k=0; k<4; k++) ftang[4*k+3]=1;
}
}
}
@@ -631,6 +704,31 @@ static void calc_vertexnormals(Render *re, ObjectRen *obr, int do_tangent, int d
}
}
+ iCalcNewMethod = 1;
+ if(iCalcNewMethod!=0 && do_nmap_tangent!=0)
+ {
+ SRenderMeshToTangent mesh2tangent;
+ SMikkTSpaceContext sContext;
+ SMikkTSpaceInterface sInterface;
+ memset(&mesh2tangent, 0, sizeof(SRenderMeshToTangent));
+ memset(&sContext, 0, sizeof(SMikkTSpaceContext));
+ memset(&sInterface, 0, sizeof(SMikkTSpaceInterface));
+
+ mesh2tangent.obr = obr;
+
+ sContext.m_pUserData = &mesh2tangent;
+ sContext.m_pInterface = &sInterface;
+ sInterface.m_getNumFaces = GetNumFaces;
+ sInterface.m_getNumVerticesOfFace = GetNumVertsOfFace;
+ sInterface.m_getPosition = GetPosition;
+ sInterface.m_getTexCoord = GetTextureCoordinate;
+ sInterface.m_getNormal = GetNormal;
+ sInterface.m_setTSpaceBasic = SetTSpace;
+
+ // 0 if failed
+ iCalcNewMethod = genTangSpaceDefault(&sContext);
+ }
+
if(arena)
BLI_memarena_free(arena);
diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c
index 62e684e79e2..0da1070679e 100644
--- a/source/blender/render/intern/source/render_texture.c
+++ b/source/blender/render/intern/source/render_texture.c
@@ -2114,6 +2114,7 @@ void do_material_tex(ShadeInput *shi)
float texvec[3], dxt[3], dyt[3], tempvec[3], norvec[3], warpvec[3]={0.0f, 0.0f, 0.0f}, Tnor=1.0;
int tex_nr, rgbnor= 0, warpdone=0;
int use_compat_bump, use_ntap_bump;
+ int iFirstTimeNMap=1;
compatible_bump_init(&compat_bump);
ntap_bump_init(&ntap_bump);
@@ -2427,14 +2428,17 @@ void do_material_tex(ShadeInput *shi)
if(mtex->normapspace == MTEX_NSPACE_TANGENT) {
/* qdn: tangent space */
float B[3], tv[3];
- cross_v3_v3v3(B, shi->vn, shi->nmaptang); /* bitangent */
+ const float * no = iFirstTimeNMap!=0 ? shi->nmapnorm : shi->vn;
+ iFirstTimeNMap=0;
+ cross_v3_v3v3(B, no, shi->nmaptang); /* bitangent */
+ mul_v3_fl(B, shi->nmaptang[3]);
/* transform norvec from tangent space to object surface in camera space */
- tv[0] = texres.nor[0]*shi->nmaptang[0] + texres.nor[1]*B[0] + texres.nor[2]*shi->vn[0];
- tv[1] = texres.nor[0]*shi->nmaptang[1] + texres.nor[1]*B[1] + texres.nor[2]*shi->vn[1];
- tv[2] = texres.nor[0]*shi->nmaptang[2] + texres.nor[1]*B[2] + texres.nor[2]*shi->vn[2];
- shi->vn[0]= facm*shi->vn[0] + fact*tv[0];
- shi->vn[1]= facm*shi->vn[1] + fact*tv[1];
- shi->vn[2]= facm*shi->vn[2] + fact*tv[2];
+ tv[0] = texres.nor[0]*shi->nmaptang[0] + texres.nor[1]*B[0] + texres.nor[2]*no[0];
+ tv[1] = texres.nor[0]*shi->nmaptang[1] + texres.nor[1]*B[1] + texres.nor[2]*no[1];
+ tv[2] = texres.nor[0]*shi->nmaptang[2] + texres.nor[1]*B[2] + texres.nor[2]*no[2];
+ shi->vn[0]= facm*no[0] + fact*tv[0];
+ shi->vn[1]= facm*no[1] + fact*tv[1];
+ shi->vn[2]= facm*no[2] + fact*tv[2];
}
else {
float nor[3];
diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c
index fac2e39c89a..5d2002e1213 100644
--- a/source/blender/render/intern/source/rendercore.c
+++ b/source/blender/render/intern/source/rendercore.c
@@ -2160,12 +2160,14 @@ static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int quad, int
if(tvn && ttang) {
VECCOPY(mat[0], ttang);
cross_v3_v3v3(mat[1], tvn, ttang);
+ mul_v3_fl(mat[1], ttang[3]);
VECCOPY(mat[2], tvn);
}
else {
VECCOPY(mat[0], shi->nmaptang);
- cross_v3_v3v3(mat[1], shi->vn, shi->nmaptang);
- VECCOPY(mat[2], shi->vn);
+ cross_v3_v3v3(mat[1], shi->nmapnorm, shi->nmaptang);
+ mul_v3_fl(mat[1], shi->nmaptang[3]);
+ VECCOPY(mat[2], shi->nmapnorm);
}
invert_m3_m3(imat, mat);
@@ -2347,7 +2349,7 @@ static void do_bake_shade(void *handle, int x, int y, float u, float v)
VlakRen *vlr= bs->vlr;
ObjectInstanceRen *obi= bs->obi;
Object *ob= obi->obr->ob;
- float l, *v1, *v2, *v3, tvn[3], ttang[3];
+ float l, *v1, *v2, *v3, tvn[3], ttang[4];
int quad;
ShadeSample *ssamp= &bs->ssamp;
ShadeInput *shi= ssamp->shi;
@@ -2386,8 +2388,8 @@ static void do_bake_shade(void *handle, int x, int y, float u, float 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->nmaptang);
+ VECCOPY(tvn, shi->nmapnorm);
+ QUATCOPY(ttang, shi->nmaptang);
}
/* if we are doing selected to active baking, find point on other face */
diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c
index c1a3b989c1f..036fb85e728 100644
--- a/source/blender/render/intern/source/renderdatabase.c
+++ b/source/blender/render/intern/source/renderdatabase.c
@@ -109,7 +109,7 @@
#define RE_RADFACE_ELEMS 1
#define RE_SIMPLIFY_ELEMS 2
#define RE_FACE_ELEMS 1
-#define RE_NMAP_TANGENT_ELEMS 12
+#define RE_NMAP_TANGENT_ELEMS 16
float *RE_vertren_get_sticky(ObjectRen *obr, VertRen *ver, int verify)
{
diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c
index 88dc13d38d1..38ed5a0a42c 100644
--- a/source/blender/render/intern/source/shadeinput.c
+++ b/source/blender/render/intern/source/shadeinput.c
@@ -286,9 +286,9 @@ void shade_input_set_triangle_i(ShadeInput *shi, ObjectInstanceRen *obi, VlakRen
VECCOPY(shi->n3, shi->v3->n);
if(obi->flag & R_TRANSFORMED) {
- mul_m3_v3(obi->nmat, shi->n1);
- mul_m3_v3(obi->nmat, shi->n2);
- mul_m3_v3(obi->nmat, shi->n3);
+ mul_m3_v3(obi->nmat, shi->n1); normalize_v3(shi->n1);
+ mul_m3_v3(obi->nmat, shi->n2); normalize_v3(shi->n2);
+ mul_m3_v3(obi->nmat, shi->n3); normalize_v3(shi->n3);
}
}
}
@@ -819,11 +819,17 @@ void shade_input_set_normals(ShadeInput *shi)
shi->vn[0]= l*n3[0]-u*n1[0]-v*n2[0];
shi->vn[1]= l*n3[1]-u*n1[1]-v*n2[1];
shi->vn[2]= l*n3[2]-u*n1[2]-v*n2[2];
+
+ // use unnormalized normal (closer to games)
+ VECCOPY(shi->nmapnorm, shi->vn);
normalize_v3(shi->vn);
}
else
+ {
VECCOPY(shi->vn, shi->facenor);
+ VECCOPY(shi->nmapnorm, shi->vn);
+ }
/* used in nodes */
VECCOPY(shi->vno, shi->vn);
@@ -849,6 +855,10 @@ void shade_input_flip_normals(ShadeInput *shi)
shi->vno[1]= -shi->vno[1];
shi->vno[2]= -shi->vno[2];
+ shi->nmapnorm[0] = -shi->nmapnorm[0];
+ shi->nmapnorm[1] = -shi->nmapnorm[1];
+ shi->nmapnorm[2] = -shi->nmapnorm[2];
+
shi->flippednor= !shi->flippednor;
}
@@ -924,21 +934,32 @@ void shade_input_set_shade_texco(ShadeInput *shi)
if(tangent) {
int j1= shi->i1, j2= shi->i2, j3= shi->i3;
+ float c0[3], c1[3], c2[3];
vlr_set_uv_indices(shi->vlr, &j1, &j2, &j3);
- s1= &tangent[j1*3];
- s2= &tangent[j2*3];
- s3= &tangent[j3*3];
-
- shi->nmaptang[0]= (tl*s3[0] - tu*s1[0] - tv*s2[0]);
- shi->nmaptang[1]= (tl*s3[1] - tu*s1[1] - tv*s2[1]);
- shi->nmaptang[2]= (tl*s3[2] - tu*s1[2] - tv*s2[2]);
+ VECCOPY(c0, &tangent[j1*4]);
+ VECCOPY(c1, &tangent[j2*4]);
+ VECCOPY(c2, &tangent[j3*4]);
+ // keeping tangents normalized at vertex level
+ // corresponds better to how it's done in game engines
if(obi->flag & R_TRANSFORMED)
- mul_m3_v3(obi->nmat, shi->nmaptang);
-
- normalize_v3(shi->nmaptang);
+ {
+ mul_mat3_m4_v3(obi->mat, c0); normalize_v3(c0);
+ mul_mat3_m4_v3(obi->mat, c1); normalize_v3(c1);
+ mul_mat3_m4_v3(obi->mat, c2); normalize_v3(c2);
+ }
+
+ // we don't normalize the interpolated TBN tangent
+ // corresponds better to how it's done in game engines
+ shi->nmaptang[0]= (tl*c2[0] - tu*c0[0] - tv*c1[0]);
+ shi->nmaptang[1]= (tl*c2[1] - tu*c0[1] - tv*c1[1]);
+ shi->nmaptang[2]= (tl*c2[2] - tu*c0[2] - tv*c1[2]);
+
+ // the sign is the same for all 3 vertices of any
+ // non degenerate triangle.
+ shi->nmaptang[3]= tangent[j1*4+3];
}
}
}