[Bf-blender-cvs] [28ca299] master: Fix T38316: Half of a Face is Missing on Newly Created Cubes or Cylinders.

Bastien Montagne noreply at git.blender.org
Wed Jan 22 20:21:17 CET 2014


Commit: 28ca299d4dfc392462efd598f14b825ba8bd21ea
Author: Bastien Montagne
Date:   Wed Jan 22 19:49:14 2014 +0100
https://developer.blender.org/rB28ca299d4dfc392462efd598f14b825ba8bd21ea

Fix T38316: Half of a Face is Missing on Newly Created Cubes or Cylinders.

Own bug from rBc691551249f3. Now at least I understand why `test_index_face()` is needed for tessellated quads!

Added a bunch of comments to explain the issue, as it's far from an obvious one...

We loose some performances, but it's still much quicker than org code.

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

M	source/blender/blenkernel/BKE_mesh.h
M	source/blender/blenkernel/intern/DerivedMesh.c
M	source/blender/blenkernel/intern/mesh_evaluate.c

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

diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index 47fd7da..7b1f39a 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -216,7 +216,7 @@ void BKE_mesh_loops_to_mface_corners(
         const int numTex, const int numCol,
         const bool hasPCol, const bool hasOrigSpace);
 void BKE_mesh_loops_to_tessdata(
-        struct CustomData *fdata, struct CustomData *ldata, struct CustomData *pdata,
+        struct CustomData *fdata, struct CustomData *ldata, struct CustomData *pdata, 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,
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index c142438..49147db 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -424,7 +424,7 @@ void DM_ensure_tessface(DerivedMesh *dm)
 /* NOTE: Assumes dm has valid tessellated data! */
 void DM_update_tessface_data(DerivedMesh *dm)
 {
-	MFace *mf = dm->getTessFaceArray(dm);
+	MFace *mf, *mface = dm->getTessFaceArray(dm);
 	MPoly *mp = dm->getPolyArray(dm);
 	MLoop *ml = dm->getLoopArray(dm);
 
@@ -451,7 +451,7 @@ void DM_update_tessface_data(DerivedMesh *dm)
 	{
 		loopindex = MEM_mallocN(sizeof(*loopindex) * totface, __func__);
 
-		for (mf_idx = 0; mf_idx < totface; mf_idx++, mf++) {
+		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;
@@ -465,12 +465,14 @@ void DM_update_tessface_data(DerivedMesh *dm)
 					not_done--;
 				}
 			}
-			if (mf_len == 3) {
-				ml_idx[3] = 0;
-			}
 		}
 
-		BKE_mesh_loops_to_tessdata(fdata, ldata, pdata, polyindex, loopindex, totface);
+		/* 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_loops_to_tessdata(fdata, ldata, pdata, mface, polyindex, loopindex, totface);
 
 		MEM_freeN(loopindex);
 	}
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index 320714b..797d4b4 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -1156,11 +1156,18 @@ void BKE_mesh_loops_to_mface_corners(
 
 /**
  * Convert all CD layers from loop/poly to tessface data.
+ *
  * @loopindices is an array of an int[4] per tessface, mapping tessface's verts to loops indices.
+ *
+ * Note when mface is not NULL, mface[face_index].v4 is used to test quads, else, loopindices[face_index][3] is used.
  */
-void BKE_mesh_loops_to_tessdata(CustomData *fdata, CustomData *ldata, CustomData *pdata,
+void BKE_mesh_loops_to_tessdata(CustomData *fdata, CustomData *ldata, CustomData *pdata, 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 int numTex = CustomData_number_of_layers(pdata, CD_MTEXPOLY);
 	const int numCol = CustomData_number_of_layers(ldata, CD_MLOOPCOL);
 	const bool hasPCol = CustomData_has_layer(ldata, CD_PREVIEW_MLOOPCOL);
@@ -1180,7 +1187,7 @@ void BKE_mesh_loops_to_tessdata(CustomData *fdata, CustomData *ldata, CustomData
 		{
 			ME_MTEXFACE_CPY(texface, &texpoly[*pidx]);
 
-			for (j = (*lidx)[3] ? 4 : 3; j--;) {
+			for (j = (mface ? mface[findex].v4 : (*lidx[3])) ? 4 : 3; j--;) {
 				copy_v2_v2(texface->uv[j], mloopuv[(*lidx)[j]].uv);
 			}
 		}
@@ -1191,7 +1198,7 @@ void BKE_mesh_loops_to_tessdata(CustomData *fdata, CustomData *ldata, CustomData
 		MLoopCol *mloopcol = CustomData_get_layer_n(ldata, CD_MLOOPCOL, i);
 
 		for (findex = 0, lidx = loopindices; findex < num_faces; lidx++, findex++, mcol++) {
-			for (j = (*lidx)[3] ? 4 : 3; j--;) {
+			for (j = (mface ? mface[findex].v4 : (*lidx[3])) ? 4 : 3; j--;) {
 				MESH_MLOOPCOL_TO_MCOL(&mloopcol[(*lidx)[j]], &(*mcol)[j]);
 			}
 		}
@@ -1202,7 +1209,7 @@ void BKE_mesh_loops_to_tessdata(CustomData *fdata, CustomData *ldata, CustomData
 		MLoopCol *mloopcol = CustomData_get_layer(ldata, CD_PREVIEW_MLOOPCOL);
 
 		for (findex = 0, lidx = loopindices; findex < num_faces; lidx++, findex++, mcol++) {
-			for (j = (*lidx)[3] ? 4 : 3; j--;) {
+			for (j = (mface ? mface[findex].v4 : (*lidx[3])) ? 4 : 3; j--;) {
 				MESH_MLOOPCOL_TO_MCOL(&mloopcol[(*lidx)[j]], &(*mcol)[j]);
 			}
 		}
@@ -1213,7 +1220,7 @@ void BKE_mesh_loops_to_tessdata(CustomData *fdata, CustomData *ldata, CustomData
 		OrigSpaceLoop *lof = CustomData_get_layer(ldata, CD_ORIGSPACE_MLOOP);
 
 		for (findex = 0, lidx = loopindices; findex < num_faces; lidx++, findex++, of++) {
-			for (j = (*lidx)[3] ? 4 : 3; j--;) {
+			for (j = (mface ? mface[findex].v4 : (*lidx[3])) ? 4 : 3; j--;) {
 				copy_v2_v2(of->uv[j], lof[(*lidx)[j]].uv);
 			}
 		}
@@ -1223,28 +1230,21 @@ void BKE_mesh_loops_to_tessdata(CustomData *fdata, CustomData *ldata, CustomData
 /**
  * Recreate tessellation.
  *
- * use_poly_origindex sets whether or not the tessellation faces' origindex
- * layer should point to original poly indices or real poly indices.
- *
- * use_face_origindex sets the tessellation faces' origindex layer
- * to point to the tessellation faces themselves, not the polys.
- *
- * if both of the above are 0, it'll use the indices of the mpolys of the MPoly
- * data in pdata, and ignore the origindex layer altogether.
+ * @do_face_nor_copy controls whether the normals from the poly are copied to the tessellated faces.
  *
  * \return number of tessellation faces.
  */
 int BKE_mesh_recalc_tessellation(CustomData *fdata, CustomData *ldata, CustomData *pdata,
-                                 MVert *mvert, int totface, int totloop, int totpoly,
-                                 /* when tessellating to recalculate normals after
-                                  * we can skip copying here */
-                                 const bool do_face_nor_cpy)
+                                 MVert *mvert, int totface, int totloop, int totpoly, const bool do_face_nor_cpy)
 {
 	/* use this to avoid locking pthread for _every_ polygon
 	 * and calling the fill function */
 
 #define USE_TESSFACE_SPEEDUP
-#define USE_TESSFACE_QUADS // NEEDS FURTHER TESTING
+#define USE_TESSFACE_QUADS  /* NEEDS FURTHER TESTING */
+
+/* We abuse MFace->edcode to tag quad faces. See below for details. */
+#define TESSFACE_IS_QUAD 1
 
 	const int looptris_tot = poly_to_tri_count(totpoly, totloop);
 
@@ -1298,6 +1298,7 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata, CustomData *ldata, CustomDat
 		lidx[3] = 0;                                                          \
 		mf->mat_nr = mp->mat_nr;                                              \
 		mf->flag = mp->flag;                                                  \
+		mf->edcode = 0;                                                       \
 		(void)0
 
 /* ALMOST IDENTICAL TO DEFINE ABOVE (see EXCEPTION) */
@@ -1320,6 +1321,7 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata, CustomData *ldata, CustomDat
 		lidx[3] = l4;                                                         \
 		mf->mat_nr = mp->mat_nr;                                              \
 		mf->flag = mp->flag;                                                  \
+		mf->edcode = TESSFACE_IS_QUAD;                                        \
 		(void)0
 
 
@@ -1411,6 +1413,7 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata, CustomData *ldata, CustomDat
 
 				mf->mat_nr = mp->mat_nr;
 				mf->flag = mp->flag;
+				mf->edcode = 0;
 
 				mface_index++;
 			}
@@ -1454,22 +1457,28 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata, CustomData *ldata, CustomDat
 		}
 	}
 
-	BKE_mesh_loops_to_tessdata(fdata, ldata, pdata, mface_to_poly_map, lindices, totface);
+	/* NOTE: quad detection issue - forth vertidx vs forth loopidx:
+	 * Polygons take care of their loops ordering, hence not of their vertices ordering.
+	 * Currently, our tfaces' forth vertex index might be 0 even for a quad. However, we know our forth loop index is
+	 * never 0 for quads (because they are sorted for polygons, and our quads are still mere copies of their polygons).
+	 * So we pass NULL as MFace pointer, and BKE_mesh_loops_to_tessdata will use the forth loop index as quad test.
+	 * ...
+	 */
+	BKE_mesh_loops_to_tessdata(fdata, ldata, pdata, NULL, mface_to_poly_map, lindices, totface);
 
-	/* XXX Is it really needed to call test_index_face here??? Since we reuse tris/quads as-is, and sort tris generated
-	 *     by scanfill, our indices should always be OK?
+	/* NOTE: quad detection issue - forth vertidx vs forth loopidx:
+	 * ...However, most TFace code uses 'MFace->v4 == 0' test to check whether it is a tri or quad.
+	 * test_index_face() will check this and rotate the tessellated face if needed.
 	 */
-#if 0
 #ifdef USE_TESSFACE_QUADS
 	mf = mface;
 	for (mface_index = 0; mface_index < totface; mface_index++, mf++) {
-		const int mf_len = mf->v4 ? 4 : 3;
-
-		if (test_index_face(mf, fdata, mface_index, mf_len) != mf_len)
-			printf("%s: test_index_face had to make changes!!!\n", __func__);
+		if (mf->edcode == TESSFACE_IS_QUAD) {
+			test_index_face(mf, fdata, mface_index, 4);
+			mf->edcode = 0;
+		}
 	}
 #endif
-#endif
 
 	MEM_freeN(lindices);




More information about the Bf-blender-cvs mailing list