[Bf-blender-cvs] [45fb145] temp-tangent-refactor: Tangents are now taken into account when generating tangents for rendering - Normal maps work again.

Antony Riakiotakis noreply at git.blender.org
Mon Jul 27 16:27:47 CEST 2015


Commit: 45fb14567831020bf85f32c8d1c44043e6cde5d0
Author: Antony Riakiotakis
Date:   Mon Jul 27 16:27:21 2015 +0200
Branches: temp-tangent-refactor
https://developer.blender.org/rB45fb14567831020bf85f32c8d1c44043e6cde5d0

Tangents are now taken into account when generating tangents for
rendering - Normal maps work again.

Added special code that only creates a tessface layer for tangents, also
added code that creates tangent mface data from loop data during mesh
conversion.

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

M	source/blender/blenkernel/BKE_DerivedMesh.h
M	source/blender/blenkernel/BKE_mesh.h
M	source/blender/blenkernel/intern/DerivedMesh.c
M	source/blender/blenkernel/intern/cdderivedmesh.c
M	source/blender/blenkernel/intern/customdata.c
M	source/blender/blenkernel/intern/mesh_evaluate.c
M	source/blender/render/intern/source/convertblender.c

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

diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index 32baa45..a39dc2e 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -614,6 +614,7 @@ void DM_ensure_looptri_data(DerivedMesh *dm);
 void DM_ensure_looptri(DerivedMesh *dm);
 
 void DM_update_tessface_data(DerivedMesh *dm);
+void DM_generate_tangent_tessface_data(DerivedMesh *dm, bool generate);
 
 void DM_update_materials(DerivedMesh *dm, struct Object *ob);
 struct MLoopUV *DM_paint_uvlayer_active_get(DerivedMesh *dm, int mat_nr);
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index b20bca7..1233069 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -287,6 +287,8 @@ void BKE_mesh_loops_to_mface_corners(
 void BKE_mesh_loops_to_tessdata(
         struct CustomData *fdata, struct CustomData *ldata, struct CustomData *pdata, struct MFace *mface,
         int *polyindices, unsigned int (*loopindices)[4], const int num_faces);
+void BKE_mesh_tangent_loops_to_tessdata(struct CustomData *fdata, struct CustomData *ldata, struct MFace *mface,
+                                        int *polyindices, unsigned int (*loopindices)[4], const int num_faces);
 int BKE_mesh_recalc_tessellation(
         struct CustomData *fdata, struct CustomData *ldata, struct CustomData *pdata,
         struct MVert *mvert,
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 935fc11..d654efd 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -521,7 +521,8 @@ void DM_update_tessface_data(DerivedMesh *dm)
 	    CustomData_has_layer(fdata, CD_MCOL) ||
 	    CustomData_has_layer(fdata, CD_PREVIEW_MCOL) ||
 	    CustomData_has_layer(fdata, CD_ORIGSPACE) ||
-	    CustomData_has_layer(fdata, CD_TESSLOOPNORMAL))
+	    CustomData_has_layer(fdata, CD_TESSLOOPNORMAL) ||
+	    CustomData_has_layer(fdata, CD_TANGENT))
 	{
 		loopindex = MEM_mallocN(sizeof(*loopindex) * totface, __func__);
 
@@ -557,6 +558,69 @@ void DM_update_tessface_data(DerivedMesh *dm)
 	dm->dirty &= ~DM_DIRTY_TESS_CDLAYERS;
 }
 
+void DM_generate_tangent_tessface_data(DerivedMesh *dm, bool generate)
+{
+	int i;
+	MFace *mf, *mface = dm->getTessFaceArray(dm);
+	MPoly *mp = dm->getPolyArray(dm);
+	MLoop *ml = dm->getLoopArray(dm);
+
+	CustomData *fdata = dm->getTessFaceDataLayout(dm);
+	CustomData *pdata = dm->getPolyDataLayout(dm);
+	CustomData *ldata = dm->getLoopDataLayout(dm);
+
+	const int totface = dm->getNumTessFaces(dm);
+	int mf_idx;
+
+	int *polyindex = CustomData_get_layer(fdata, CD_ORIGINDEX);
+	unsigned int (*loopindex)[4];
+
+	/* Should never occure, but better abort than segfault! */
+	if (!polyindex)
+		return;
+
+	CustomData_from_bmeshpoly(fdata, pdata, ldata, totface);
+
+	if (generate) {
+		for (i = 0; i < ldata->totlayer; i++) {
+			if (ldata->layers[i].type == CD_TANGENT)
+				CustomData_add_layer_named(fdata, CD_TANGENT, CD_CALLOC, NULL, totface, ldata->layers[i].name);
+		}
+		CustomData_bmesh_update_active_layers(fdata, pdata, ldata);
+	}
+
+	loopindex = MEM_mallocN(sizeof(*loopindex) * totface, __func__);
+
+	for (mf_idx = 0, mf = mface; mf_idx < totface; mf_idx++, mf++) {
+		const int mf_len = mf->v4 ? 4 : 3;
+		unsigned int *ml_idx = loopindex[mf_idx];
+		int i, not_done;
+
+		/* Find out loop indices. */
+		/* NOTE: This assumes tessface are valid and in sync with loop/poly... Else, most likely, segfault! */
+		for (i = mp[polyindex[mf_idx]].loopstart, not_done = mf_len; not_done; i++) {
+			const int tf_v = BKE_MESH_TESSFACE_VINDEX_ORDER(mf, ml[i].v);
+			if (tf_v != -1) {
+				ml_idx[tf_v] = i;
+				not_done--;
+			}
+		}
+	}
+
+	/* NOTE: quad detection issue - forth vertidx vs forth loopidx:
+	 * Here, our tfaces' forth vertex index is never 0 for a quad. However, we know our forth loop index may be
+	 * 0 for quads (because our quads may have been rotated compared to their org poly, see tessellation code).
+	 * So we pass the MFace's, and BKE_mesh_loops_to_tessdata will use MFace->v4 index as quad test.
+	 */
+	BKE_mesh_tangent_loops_to_tessdata(fdata, ldata, mface, polyindex, loopindex, totface);
+
+	MEM_freeN(loopindex);
+
+	if (G.debug & G_DEBUG)
+		printf("%s: Updated tessellated tangents of dm %p\n", __func__, dm);
+}
+
+
 void DM_update_materials(DerivedMesh *dm, Object *ob)
 {
 	int i, totmat = ob->totcol + 1; /* materials start from 1, default material is 0 */
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index 30adc76..8c50d52 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -1058,7 +1058,7 @@ static void cdDM_drawMappedFacesGLSL(
 					}
 					if (matconv[i].attribs.tottang && matconv[i].attribs.tang.array) {
 						if (matconv[i].attribs.tface[b].array) {
-							const float (*looptang)[4] = matconv[i].attribs.tang.array;
+							const float (*looptang)[4] = (const float (*)[4])matconv[i].attribs.tang.array;
 							for (j = 0; j < mpoly->totloop; j++)
 								copy_v4_v4((float *)&varray[offset + j * max_element_size], looptang[mpoly->loopstart + j]);
 							offset += sizeof(float) * 4;
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index dbc79d3..688a1dd 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -2489,6 +2489,9 @@ void CustomData_from_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData
 		else if (ldata->layers[i].type == CD_NORMAL) {
 			CustomData_add_layer_named(fdata, CD_TESSLOOPNORMAL, CD_CALLOC, NULL, total, ldata->layers[i].name);
 		}
+		else if (ldata->layers[i].type == CD_TANGENT) {
+			CustomData_add_layer_named(fdata, CD_TANGENT, CD_CALLOC, NULL, total, ldata->layers[i].name);
+		}
 	}
 
 	CustomData_bmesh_update_active_layers(fdata, pdata, ldata);
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index 74c5fb8..a334951 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -2243,6 +2243,7 @@ void BKE_mesh_loops_to_tessdata(CustomData *fdata, CustomData *ldata, CustomData
 	const bool hasPCol = CustomData_has_layer(ldata, CD_PREVIEW_MLOOPCOL);
 	const bool hasOrigSpace = CustomData_has_layer(ldata, CD_ORIGSPACE_MLOOP);
 	const bool hasLoopNormal = CustomData_has_layer(ldata, CD_NORMAL);
+	const bool hasLoopTangent = CustomData_has_layer(ldata, CD_TANGENT);
 	int findex, i, j;
 	const int *pidx;
 	unsigned int (*lidx)[4];
@@ -2307,6 +2308,51 @@ void BKE_mesh_loops_to_tessdata(CustomData *fdata, CustomData *ldata, CustomData
 			}
 		}
 	}
+
+	if (hasLoopTangent) {
+		/* need to do for all uv maps at some point */
+		float (*ftangents)[4] = CustomData_get_layer(fdata, CD_TANGENT);
+		float (*ltangents)[4] = CustomData_get_layer(ldata, CD_TANGENT);
+
+		for (findex = 0, pidx = polyindices, lidx = loopindices;
+		     findex < num_faces;
+		     pidx++, lidx++, findex++)
+		{
+			int nverts = (mface ? mface[findex].v4 : (*lidx)[3]) ? 4 : 3;
+			for (j = nverts; j--;) {
+				copy_v4_v4(ftangents[findex * 4 + j], ltangents[(*lidx)[j]]);
+			}
+		}
+	}
+}
+
+void BKE_mesh_tangent_loops_to_tessdata(CustomData *fdata, CustomData *ldata, MFace *mface,
+                                        int *polyindices, unsigned int (*loopindices)[4], const int num_faces)
+{
+	/* Note: performances are sub-optimal when we get a NULL mface, we could be ~25% quicker with dedicated code...
+	 *       Issue is, unless having two different functions with nearly the same code, there's not much ways to solve
+	 *       this. Better imho to live with it for now. :/ --mont29
+	 */
+	const bool hasLoopTangent = CustomData_has_layer(ldata, CD_TANGENT);
+	int findex, j;
+	const int *pidx;
+	unsigned int (*lidx)[4];
+
+	if (hasLoopTangent) {
+		/* need to do for all uv maps at some point */
+		float (*ftangents)[4] = CustomData_get_layer(fdata, CD_TANGENT);
+		float (*ltangents)[4] = CustomData_get_layer(ldata, CD_TANGENT);
+
+		for (findex = 0, pidx = polyindices, lidx = loopindices;
+		     findex < num_faces;
+		     pidx++, lidx++, findex++)
+		{
+			int nverts = (mface ? mface[findex].v4 : (*lidx)[3]) ? 4 : 3;
+			for (j = nverts; j--;) {
+				copy_v4_v4(ftangents[findex * 4 + j], ltangents[(*lidx)[j]]);
+			}
+		}
+	}
 }
 
 /**
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index 20387bc..49f7658 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -3272,8 +3272,14 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset)
 			RE_set_customdata_names(obr, &dm->faceData);
 
 			/* add tangent layer if we need one */
-			if (need_nmap_tangent!=0 && CustomData_get_layer_index(&dm->faceData, CD_TANGENT) == -1)
-				DM_add_tangent_layer(dm);
+			if (need_nmap_tangent!=0 && CustomData_get_layer_index(&dm->faceData, CD_TANGENT) == -1) {
+				bool generate_data = false;
+				if (CustomData_get_layer_index(&dm->loopData, CD_TANGENT) == -1) {
+					DM_add_tangent_layer(dm);
+					generate_data = true;
+				}
+				DM_generate_tangent_tessface_data(dm, generate_data);
+			}
 			
 			/* still to do for keys: the correct local texture coordinate */




More information about the Bf-blender-cvs mailing list