[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [60590] branches/vgroup_modifiers/source/ blender: Add loop tangent spaces computation, in a similar way as loop normals.
Bastien Montagne
montagne29 at wanadoo.fr
Mon Oct 7 15:29:24 CEST 2013
Revision: 60590
http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=60590
Author: mont29
Date: 2013-10-07 13:29:24 +0000 (Mon, 07 Oct 2013)
Log Message:
-----------
Add loop tangent spaces computation, in a similar way as loop normals. Note that you must feature a valid UVMap, and the mesh must be tessellated (i.e. have only tris/quads) for this to work.
Modified Paths:
--------------
branches/vgroup_modifiers/source/blender/blenkernel/BKE_mesh.h
branches/vgroup_modifiers/source/blender/blenkernel/intern/customdata.c
branches/vgroup_modifiers/source/blender/blenkernel/intern/mesh_evaluate.c
branches/vgroup_modifiers/source/blender/makesdna/DNA_customdata_types.h
branches/vgroup_modifiers/source/blender/makesrna/intern/rna_mesh.c
branches/vgroup_modifiers/source/blender/makesrna/intern/rna_mesh_api.c
Modified: branches/vgroup_modifiers/source/blender/blenkernel/BKE_mesh.h
===================================================================
--- branches/vgroup_modifiers/source/blender/blenkernel/BKE_mesh.h 2013-10-07 13:19:48 UTC (rev 60589)
+++ branches/vgroup_modifiers/source/blender/blenkernel/BKE_mesh.h 2013-10-07 13:29:24 UTC (rev 60590)
@@ -169,9 +169,13 @@
struct MFace *mfaces, int numFaces,
float (*faceNors_r)[3]);
void BKE_mesh_normals_loop_split(
- struct MVert *mverts, int numVerts, struct MEdge *medges, int numEdges,
- struct MLoop *mloops, float (*r_loopnors)[3], int numLoops,
- struct MPoly *mpolys, float (*polynors)[3], int numPolys, float split_angle);
+ 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_normals_loop_tangent(
+ struct MVert *mverts, const int numVerts,
+ struct MLoop *mloops, float (*r_looptangent)[4], float (*loopnors)[3], float (*loopuv)[2], const int numLoops,
+ struct MPoly *mpolys, const int numPolys);
void BKE_mesh_calc_poly_normal(
struct MPoly *mpoly, struct MLoop *loopstart,
Modified: branches/vgroup_modifiers/source/blender/blenkernel/intern/customdata.c
===================================================================
--- branches/vgroup_modifiers/source/blender/blenkernel/intern/customdata.c 2013-10-07 13:19:48 UTC (rev 60589)
+++ branches/vgroup_modifiers/source/blender/blenkernel/intern/customdata.c 2013-10-07 13:29:24 UTC (rev 60590)
@@ -1169,7 +1169,9 @@
/* 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_LOOPTANGENT */
+ {sizeof(float) * 4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
};
/* note, numbers are from trunk and need updating for bmesh */
@@ -1185,7 +1187,7 @@
/* 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", "CDLoopTangent",
};
Modified: branches/vgroup_modifiers/source/blender/blenkernel/intern/mesh_evaluate.c
===================================================================
--- branches/vgroup_modifiers/source/blender/blenkernel/intern/mesh_evaluate.c 2013-10-07 13:19:48 UTC (rev 60589)
+++ branches/vgroup_modifiers/source/blender/blenkernel/intern/mesh_evaluate.c 2013-10-07 13:29:24 UTC (rev 60590)
@@ -53,6 +53,7 @@
#include "BLI_strict_flags.h"
+#include "mikktspace.h"
// #define DEBUG_TIME
@@ -318,9 +319,9 @@
* Compute split normals, i.e. vertex normals associated with each poly (hence 'loop normals').
* Useful to materialize sharp edges (or non-smooth faces) without actually modifying the geometry (splitting edges).
*/
-void BKE_mesh_normals_loop_split(MVert *mverts, int UNUSED(numVerts), MEdge *medges, int numEdges,
- MLoop *mloops, float (*r_loopnors)[3], int numLoops,
- MPoly *mpolys, float (*polynors)[3], int numPolys, float split_angle)
+void BKE_mesh_normals_loop_split(MVert *mverts, const int UNUSED(numVerts), MEdge *medges, const int numEdges,
+ MLoop *mloops, float (*r_loopnors)[3], const int numLoops,
+ MPoly *mpolys, float (*polynors)[3], const int numPolys, float split_angle)
{
#define INDEX_UNSET INT_MIN
#define INDEX_INVALID -1
@@ -572,6 +573,111 @@
#undef IS_EDGE_SHARP
}
+
+/* Tangent space normals utils. */
+
+/* User data. */
+typedef struct {
+ MPoly *mpolys; /* faces */
+ MLoop *mloops; /* faces's vertices */
+ MVert *mverts; /* vertices */
+ float (*uvcos)[2]; /* 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->uvcos[p_mesh->mpolys[face_idx].loopstart + vert_idx]);
+}
+
+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: * There must be a valid loop's CD_NORMALS available.
+ * * The mesh should be made of only tris and quads!
+ */
+void BKE_mesh_normals_loop_tangent(MVert *mverts, const int UNUSED(numVerts), MLoop *mloops, float (*r_looptangent)[4],
+ float (*loopnors)[3], float (*loopuv)[2], const int UNUSED(numLoops),
+ MPoly *mpolys, const int numPolys)
+{
+ 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) {
+ printf("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.uvcos = loopuv;
+ 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) {
+ printf("Mikktspace failed to generate tangents for this mesh!\n");
+ }
+}
+
/** \} */
Modified: branches/vgroup_modifiers/source/blender/makesdna/DNA_customdata_types.h
===================================================================
--- branches/vgroup_modifiers/source/blender/makesdna/DNA_customdata_types.h 2013-10-07 13:19:48 UTC (rev 60589)
+++ branches/vgroup_modifiers/source/blender/makesdna/DNA_customdata_types.h 2013-10-07 13:29:24 UTC (rev 60590)
@@ -63,9 +63,10 @@
* 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_i0;
int totlayer, maxlayer; /* number of layers, size of layers array */
int totsize; /* in editmode, total size of all data layers */
void *pool; /* Bmesh: Memory pool for allocation of blocks */
@@ -117,7 +118,8 @@
CD_MVERT_SKIN = 36,
CD_FREESTYLE_EDGE = 37,
CD_FREESTYLE_FACE = 38,
- CD_NUMTYPES = 39,
+ CD_LOOPTANGENT = 39,
+ CD_NUMTYPES = 40,
};
/* Bits for CustomDataMask */
Modified: branches/vgroup_modifiers/source/blender/makesrna/intern/rna_mesh.c
===================================================================
--- branches/vgroup_modifiers/source/blender/makesrna/intern/rna_mesh.c 2013-10-07 13:19:48 UTC (rev 60589)
+++ branches/vgroup_modifiers/source/blender/makesrna/intern/rna_mesh.c 2013-10-07 13:29:24 UTC (rev 60590)
@@ -338,6 +338,20 @@
}
}
+static void rna_MeshLoop_tangent_get(PointerRNA *ptr, float *values)
+{
+ Mesh *me = rna_mesh(ptr);
+ MLoop *ml = (MLoop *)ptr->data;
+ const float (*vec)[4] = CustomData_get(&me->ldata, (int)(ml - me->mloop), CD_LOOPTANGENT);
+
+ if (!vec) {
+ zero_v4(values);
+ }
+ else {
+ copy_v4_v4(values, (const float *)vec);
+ }
+}
+
static void rna_MeshPolygon_normal_get(PointerRNA *ptr, float *values)
{
Mesh *me = rna_mesh(ptr);
@@ -1874,6 +1888,14 @@
"Local space unit length split normal vector of this vertex for this polygon "
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list