Commit: 8952f58375385a6e8a636aa1e86763e88fc68fc0
Author: Bastien Montagne
Date:   Sat Jan 11 11:31:44 2014 +0100
https://developer.blender.org/rB8952f58375385a6e8a636aa1e86763e88fc68fc0

Add tangent space computation/access from RNA (i.e. python).

This simply mimics code used for loopnormals, to enable py scripts to generate 
and access (temporary)
a tangent 3D vector and bitangent sign for each loop. Together with the split 
normals, this allow
to recreate a complete tangent space for normal mapping (bitangent = 
bitangent_sign * cross(normal, tangent)).

Expects all faces to be tri or quads.

Reviewed By: Brecht, campbellbarton

Differential Revision: https://developer.blender.org/D185

===================================================================

M       source/blender/blenkernel/BKE_mesh.h
M       source/blender/blenkernel/intern/DerivedMesh.c
M       source/blender/blenkernel/intern/customdata.c
M       source/blender/blenkernel/intern/mesh_evaluate.c
M       source/blender/makesdna/DNA_customdata_types.h
M       source/blender/makesrna/intern/rna_mesh.c
M       source/blender/makesrna/intern/rna_mesh_api.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_mesh.h 
b/source/blender/blenkernel/BKE_mesh.h
index 500b3d8..e82689e 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -58,6 +58,7 @@ struct UvVertMap;
 struct UvMapVert;
 struct UvElementMap;
 struct UvElement;
+struct ReportList;
 
 #ifdef __cplusplus
 extern "C" {
@@ -172,6 +173,12 @@ void BKE_mesh_normals_loop_split(
         struct MVert *mverts, const int numVerts, struct MEdge *medges, const 
int numEdges,
         struct MLoop *mloops, float (*r_loopnors)[3], const int numLoops,
         struct MPoly *mpolys, float (*polynors)[3], const int numPolys, float 
split_angle);
+void BKE_mesh_loop_tangents_ex(
+        struct MVert *mverts, const int numVerts, struct MLoop *mloops, float 
(*r_looptangent)[4], float (*loopnors)[3],
+        struct MLoopUV *loopuv, const int numLoops, struct MPoly *mpolys, 
const int numPolys,
+        struct ReportList *reports);
+void BKE_mesh_loop_tangents(
+        struct Mesh *mesh, const char *uvmap, float (*r_looptangents)[4], 
struct ReportList *reports);
 
 void BKE_mesh_calc_poly_normal(
         struct MPoly *mpoly, struct MLoop *loopstart,
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c 
b/source/blender/blenkernel/intern/DerivedMesh.c
index 341e8e6..8796bd5 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -2612,6 +2612,7 @@ static void GetNormal(const SMikkTSpaceContext *pContext, 
float r_no[3], const i
                normal_short_to_float_v3(r_no, no);
        }
 }
+
 static void SetTSpace(const SMikkTSpaceContext *pContext, const float 
fvTangent[3], const float fSign, const int face_num, const int iVert)
 {
        //assert(vert_index >= 0 && vert_index < 4);
@@ -2621,7 +2622,6 @@ static void SetTSpace(const SMikkTSpaceContext *pContext, 
const float fvTangent[
        pRes[3] = fSign;
 }
 
-
 void DM_add_tangent_layer(DerivedMesh *dm)
 {
        /* mesh vars */
diff --git a/source/blender/blenkernel/intern/customdata.c 
b/source/blender/blenkernel/intern/customdata.c
index 441a2b4..39b1a94 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -1168,7 +1168,9 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
        /* 37: CD_FREESTYLE_EDGE */
        {sizeof(FreestyleEdge), "FreestyleEdge", 1, NULL, NULL, NULL, NULL, 
NULL, NULL},
        /* 38: CD_FREESTYLE_FACE */
-       {sizeof(FreestyleFace), "FreestyleFace", 1, NULL, NULL, NULL, NULL, 
NULL, NULL}
+       {sizeof(FreestyleFace), "FreestyleFace", 1, NULL, NULL, NULL, NULL, 
NULL, NULL},
+       /* 39: CD_MLOOPTANGENT */
+       {sizeof(float[4]), "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
 };
 
 /* note, numbers are from trunk and need updating for bmesh */
@@ -1184,7 +1186,7 @@ static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
        /* 25-29 */ "CDMPoly", "CDMLoop", "CDShapeKeyIndex", "CDShapeKey", 
"CDBevelWeight",
        /* 30-34 */ "CDSubSurfCrease", "CDOrigSpaceLoop", "CDPreviewLoopCol", 
"CDBMElemPyPtr", "CDPaintMask",
        /* 35-36 */ "CDGridPaintMask", "CDMVertSkin",
-       /* 37-38 */ "CDFreestyleEdge", "CDFreestyleFace"
+       /* 37-38 */ "CDFreestyleEdge", "CDFreestyleFace", "CDMLoopTangent",
 };
 
 
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c 
b/source/blender/blenkernel/intern/mesh_evaluate.c
index 24362c1..9bafc9c 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -50,9 +50,11 @@
 #include "BKE_customdata.h"
 #include "BKE_mesh.h"
 #include "BKE_multires.h"
+#include "BKE_report.h"
 
 #include "BLI_strict_flags.h"
 
+#include "mikktspace.h"
 
 // #define DEBUG_TIME
 
@@ -577,6 +579,149 @@ void BKE_mesh_normals_loop_split(MVert *mverts, const int 
UNUSED(numVerts), MEdg
 
 /* -------------------------------------------------------------------- */
 
+/** \name Mesh Tangent Calculations
+ * \{ */
+
+/* Tangent space utils. */
+
+/* User data. */
+typedef struct {
+       MPoly *mpolys;         /* faces */
+       MLoop *mloops;         /* faces's vertices */
+       MVert *mverts;         /* vertices */
+       MLoopUV *luvs;         /* texture coordinates */
+       float (*lnors)[3];     /* loops' normals */
+       float (*tangents)[4];  /* output tangents */
+       int num_polys;         /* number of polygons */
+} BKEMeshToTangent;
+
+/* Mikktspace's API */
+static int get_num_faces(const SMikkTSpaceContext *pContext)
+{
+       BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData;
+       return p_mesh->num_polys;
+}
+
+static int get_num_verts_of_face(const SMikkTSpaceContext *pContext, const int 
face_idx)
+{
+       BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData;
+       return p_mesh->mpolys[face_idx].totloop;
+}
+
+static void get_position(const SMikkTSpaceContext *pContext, float r_co[3], 
const int face_idx, const int vert_idx)
+{
+       BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData;
+       const int loop_idx = p_mesh->mpolys[face_idx].loopstart + vert_idx;
+       copy_v3_v3(r_co, p_mesh->mverts[p_mesh->mloops[loop_idx].v].co);
+}
+
+static void get_texture_coordinate(const SMikkTSpaceContext *pContext, float 
r_uv[2], const int face_idx,
+                                   const int vert_idx)
+{
+       BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData;
+       copy_v2_v2(r_uv, p_mesh->luvs[p_mesh->mpolys[face_idx].loopstart + 
vert_idx].uv);
+}
+
+static void get_normal(const SMikkTSpaceContext *pContext, float r_no[3], 
const int face_idx, const int vert_idx)
+{
+       BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData;
+       copy_v3_v3(r_no, p_mesh->lnors[p_mesh->mpolys[face_idx].loopstart + 
vert_idx]);
+}
+
+static void set_tspace(const SMikkTSpaceContext *pContext, const float 
fv_tangent[3], const float face_sign,
+                       const int face_idx, const int vert_idx)
+{
+       BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData;
+       float *p_res = p_mesh->tangents[p_mesh->mpolys[face_idx].loopstart + 
vert_idx];
+       copy_v3_v3(p_res, fv_tangent);
+       p_res[3] = face_sign;
+}
+
+/**
+ * Compute simplified tangent space normals, i.e. tangent vector + sign of 
bi-tangent one, which combined with
+ * split normals can be used to recreate the full tangent space.
+ * Note: * The mesh should be made of only tris and quads!
+ */
+void BKE_mesh_loop_tangents_ex(MVert *mverts, const int UNUSED(numVerts), 
MLoop *mloops,
+                               float (*r_looptangent)[4], float 
(*loopnors)[3], MLoopUV *loopuvs,
+                               const int UNUSED(numLoops), MPoly *mpolys, 
const int numPolys, ReportList *reports)
+{
+       BKEMeshToTangent mesh_to_tangent = {NULL};
+       SMikkTSpaceContext s_context = {NULL};
+       SMikkTSpaceInterface s_interface = {NULL};
+
+       MPoly *mp;
+       int mp_index;
+
+       /* First check we do have a tris/quads only mesh. */
+       for (mp = mpolys, mp_index = 0; mp_index < numPolys; mp++, mp_index++) {
+               if (mp->totloop > 4) {
+                       BKE_report(reports, RPT_ERROR, "Tangent space can only 
be computed for tris/quads, aborting...\n");
+                       return;
+               }
+       }
+
+       /* Compute Mikktspace's tangent normals. */
+       mesh_to_tangent.mpolys = mpolys;
+       mesh_to_tangent.mloops = mloops;
+       mesh_to_tangent.mverts = mverts;
+       mesh_to_tangent.luvs = loopuvs;
+       mesh_to_tangent.lnors = loopnors;
+       mesh_to_tangent.tangents = r_looptangent;
+       mesh_to_tangent.num_polys = numPolys;
+
+       s_context.m_pUserData = &mesh_to_tangent;
+       s_context.m_pInterface = &s_interface;
+       s_interface.m_getNumFaces = get_num_faces;
+       s_interface.m_getNumVerticesOfFace = get_num_verts_of_face;
+       s_interface.m_getPosition = get_position;
+       s_interface.m_getTexCoord = get_texture_coordinate;
+       s_interface.m_getNormal = get_normal;
+       s_interface.m_setTSpaceBasic = set_tspace;
+
+       /* 0 if failed */
+       if (genTangSpaceDefault(&s_context) == false) {
+               BKE_report(reports, RPT_ERROR, "Mikktspace failed to generate 
tangents for this mesh!\n");
+       }
+}
+
+/**
+ * Wrapper around BKE_mesh_loop_tangents_ex, which takes care of most boiling 
code.
+ * Note: * There must be a valid loop's CD_NORMALS available.
+ *       * The mesh should be made of only tris and quads!
+ */
+void BKE_mesh_loop_tangents(Mesh *mesh, const char *uvmap, float 
(*r_looptangents)[4], ReportList *reports)
+{
+       MLoopUV *loopuvs;
+       float (*loopnors)[3];
+
+       /* Check we have valid texture coordinates first! */
+       if (uvmap) {
+               loopuvs = CustomData_get_layer_named(&mesh->ldata, CD_MLOOPUV, 
uvmap);
+       }
+       else {
+               loopuvs = CustomData_get_layer(&mesh->ldata, CD_MLOOPUV);
+       }
+       if (!loopuvs) {
+               BKE_reportf(reports, RPT_ERROR, "Tangent space computation 
needs an UVMap, \"%s\" not found, aborting.\n", uvmap);
+               return;
+       }
+
+       loopnors = CustomData_get_layer(&mesh->ldata, CD_NORMAL);
+       if (!loopnors) {
+               BKE_report(reports, RPT_ERROR, "Tangent space computation needs 
loop normals, none found, aborting.\n");
+               return;
+       }
+
+       BKE_mesh_loop_tangents_ex(mesh->mvert, mesh->totvert, mesh->mloop, 
r_looptangents,
+                              loopnors, loopuvs, mesh->totloop, mesh->mpoly, 
mesh->totpoly, reports);
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
 /** \name Polygon Calculations
  * \{ */
 
diff --git a/source/blender/makesdna/DNA_customdata_types.h 
b/source/blender/makesdna/DNA_customdata_types.h
index f651649..325c2a8 100644
--- a/source/blender/makesdna/DNA_customdata_types.h
+++ b/source/blender/makesdna/DNA_customdata_types.h
@@ -63,9 +63,10 @@ typedef struct CustomDataExternal {
  * layers, each with a data type (e.g. MTFace, MDeformVert, etc.). */
 typedef struct CustomData {
        CustomDataLayer *layers;      /* CustomDataLayers, ordered by type */
-       int typemap[39];              /* runtime only! - maps types to indices 
of first layer of that type,
+       int typemap[40];              /* runtime only! - maps types to indices 
of first layer of that type,
                                       * MUST be >= CD_NUMTYPES, but we cant 
use a define here.
                                       * Correct size is ensured in 
CustomData_update_typemap assert() */
+       int pad[1];
        int totlayer, maxlayer;       /* number of layers, size of layers array 
*/
        int totsize;                  /* in editmode, total size of all data 
layers */
        void *pool;     

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to