[Bf-blender-cvs] [c691551] master: Optimize tessellation code (min 20% better, up to 300% with some CD layers to tessellate).

Bastien Montagne noreply at git.blender.org
Tue Jan 21 16:36:19 CET 2014


Commit: c691551249f3fe3982c43e4c75be40a19503dd26
Author: Bastien Montagne
Date:   Tue Jan 21 16:32:36 2014 +0100
https://developer.blender.org/rBc691551249f3fe3982c43e4c75be40a19503dd26

Optimize tessellation code (min 20% better, up to 300% with some CD layers to tessellate).

The main idea is to store (during tessellation) or recreate (during tessdata update) a tessfaceverts-to-loops mapping, and then update all tessdata
in one pass, instead of calling `BKE_mesh_loops_to_mface_corners` repeatedly for all tfaces!

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

Reviewed by Campbell, thanks a lot!

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

M	source/blender/blenkernel/BKE_mesh.h
M	source/blender/blenkernel/BKE_mesh_mapping.h
M	source/blender/blenkernel/intern/DerivedMesh.c
M	source/blender/blenkernel/intern/mesh_evaluate.c
M	source/blender/editors/sculpt_paint/paint_vertex.c

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

diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index e82689e..302f71e 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -215,6 +215,9 @@ void BKE_mesh_loops_to_mface_corners(
         const int polyindex, const int mf_len,
         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,
+        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/BKE_mesh_mapping.h b/source/blender/blenkernel/BKE_mesh_mapping.h
index ee9e63e..f3f6b55 100644
--- a/source/blender/blenkernel/BKE_mesh_mapping.h
+++ b/source/blender/blenkernel/BKE_mesh_mapping.h
@@ -129,4 +129,13 @@ int *BKE_mesh_calc_smoothgroups(
         const struct MLoop *mloop, const int totloop,
         int *r_totgroup, const bool use_bitflags);
 
+/* No good (portable) way to have exported inlined functions... */
+#define BKE_MESH_TESSFACE_VINDEX_ORDER(_mf, _v)  (                          \
+    (CHECK_TYPE_INLINE(_mf, MFace *), CHECK_TYPE_INLINE(_v, unsigned int)), \
+    ((_mf->v1 == _v) ? 0 :                                                  \
+     (_mf->v2 == _v) ? 1 :                                                  \
+     (_mf->v3 == _v) ? 2 :                                                  \
+     (_mf->v4 && _mf->v4 == _v) ? 3 : -1)                                   \
+    )
+
 #endif  /* __BKE_MESH_MAPPING_H__ */
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index ee7d890..c142438 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -56,6 +56,7 @@
 #include "BKE_key.h"
 #include "BKE_modifier.h"
 #include "BKE_mesh.h"
+#include "BKE_mesh_mapping.h"
 #include "BKE_object.h"
 #include "BKE_object_deform.h"
 #include "BKE_paint.h"
@@ -431,16 +432,11 @@ void DM_update_tessface_data(DerivedMesh *dm)
 	CustomData *pdata = dm->getPolyDataLayout(dm);
 	CustomData *ldata = dm->getLoopDataLayout(dm);
 
-	const int numTex = CustomData_number_of_layers(pdata, CD_MTEXPOLY);
-	const int numCol = CustomData_number_of_layers(ldata, CD_MLOOPCOL);
-	const int hasPCol = CustomData_has_layer(ldata, CD_PREVIEW_MLOOPCOL);
-	const int hasOrigSpace = CustomData_has_layer(ldata, CD_ORIGSPACE_MLOOP);
-
-	int *polyindex = CustomData_get_layer(fdata, CD_ORIGINDEX);
-
 	const int totface = dm->getNumTessFaces(dm);
 	int mf_idx;
-	int ml_idx[4];
+
+	int *polyindex = CustomData_get_layer(fdata, CD_ORIGINDEX);
+	unsigned int (*loopindex)[4];
 
 	/* Should never occure, but better abort than segfault! */
 	if (!polyindex)
@@ -448,36 +444,35 @@ void DM_update_tessface_data(DerivedMesh *dm)
 
 	CustomData_from_bmeshpoly(fdata, pdata, ldata, totface);
 
-	for (mf_idx = 0; mf_idx < totface; mf_idx++, mf++) {
-		const int mf_len = mf->v4 ? 4 : 3;
-		int i, not_done;
-
-		/* Find out loop indices. */
-		/* XXX Is there a better way to do this? */
-		/* 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++) {
-			MLoop *tml = &ml[i];
-			if (tml->v == mf->v1) {
-				ml_idx[0] = i;
-				not_done--;
-			}
-			else if (tml->v == mf->v2) {
-				ml_idx[1] = i;
-				not_done--;
-			}
-			else if (tml->v == mf->v3) {
-				ml_idx[2] = i;
-				not_done--;
+	if (CustomData_has_layer(fdata, CD_MTFACE) ||
+	    CustomData_has_layer(fdata, CD_MCOL) ||
+	    CustomData_has_layer(fdata, CD_PREVIEW_MCOL) ||
+	    CustomData_has_layer(fdata, CD_ORIGSPACE))
+	{
+		loopindex = MEM_mallocN(sizeof(*loopindex) * totface, __func__);
+
+		for (mf_idx = 0; 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--;
+				}
 			}
-			else if (mf_len == 4 && tml->v == mf->v4) {
-				ml_idx[3] = i;
-				not_done--;
+			if (mf_len == 3) {
+				ml_idx[3] = 0;
 			}
 		}
-		BKE_mesh_loops_to_mface_corners(fdata, ldata, pdata,
-		                                ml_idx, mf_idx, polyindex[mf_idx],
-		                                mf_len,
-		                                numTex, numCol, hasPCol, hasOrigSpace);
+
+		BKE_mesh_loops_to_tessdata(fdata, ldata, pdata, polyindex, loopindex, totface);
+
+		MEM_freeN(loopindex);
 	}
 
 	if (G.debug & G_DEBUG)
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index 7759e53..d1b1c5c 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -1155,6 +1155,72 @@ 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.
+ */
+void BKE_mesh_loops_to_tessdata(CustomData *fdata, CustomData *ldata, CustomData *pdata,
+                                int *polyindices, unsigned int (*loopindices)[4], const int num_faces)
+{
+	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);
+	const bool hasOrigSpace = CustomData_has_layer(ldata, CD_ORIGSPACE_MLOOP);
+	int findex, i, j;
+	int *pidx;
+	unsigned int (*lidx)[4];
+
+	for (i = 0; i < numTex; i++) {
+		MTFace *texface = CustomData_get_layer_n(fdata, CD_MTFACE, i);
+		MTexPoly *texpoly = CustomData_get_layer_n(pdata, CD_MTEXPOLY, i);
+		MLoopUV *mloopuv = CustomData_get_layer_n(ldata, CD_MLOOPUV, i);
+
+		for (findex = 0, pidx = polyindices, lidx = loopindices;
+		     findex < num_faces;
+		     pidx++, lidx++, findex++, texface++)
+		{
+			ME_MTEXFACE_CPY(texface, &texpoly[*pidx]);
+
+			for (j = (*lidx)[3] ? 4 : 3; j--;) {
+				copy_v2_v2(texface->uv[j], mloopuv[(*lidx)[j]].uv);
+			}
+		}
+	}
+
+	for (i = 0; i < numCol; i++) {
+		MCol (*mcol)[4] = CustomData_get_layer_n(fdata, CD_MCOL, i);
+		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--;) {
+				MESH_MLOOPCOL_TO_MCOL(&mloopcol[(*lidx)[j]], &(*mcol)[j]);
+			}
+		}
+	}
+
+	if (hasPCol) {
+		MCol (*mcol)[4] = CustomData_get_layer(fdata, CD_PREVIEW_MCOL);
+		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--;) {
+				MESH_MLOOPCOL_TO_MCOL(&mloopcol[(*lidx)[j]], &(*mcol)[j]);
+			}
+		}
+	}
+
+	if (hasOrigSpace) {
+		OrigSpaceFace *of = CustomData_get_layer(fdata, CD_ORIGSPACE);
+		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--;) {
+				copy_v2_v2(of->uv[j], lof[(*lidx)[j]].uv);
+			}
+		}
+	}
+}
+
+/**
  * Recreate tessellation.
  *
  * use_poly_origindex sets whether or not the tessellation faces' origindex
@@ -1168,10 +1234,8 @@ void BKE_mesh_loops_to_mface_corners(
  *
  * \return number of tessellation faces.
  */
-int BKE_mesh_recalc_tessellation(CustomData *fdata,
-                                 CustomData *ldata, CustomData *pdata,
-                                 MVert *mvert, int totface, int totloop,
-                                 int totpoly,
+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)
@@ -1182,9 +1246,6 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata,
 #define USE_TESSFACE_SPEEDUP
 #define USE_TESSFACE_QUADS // NEEDS FURTHER TESTING
 
-#define TESSFACE_SCANFILL (1 << 0)
-#define TESSFACE_IS_QUAD  (1 << 1)
-
 	const int looptris_tot = poly_to_tri_count(totpoly, totloop);
 
 	MPoly *mp, *mpoly;
@@ -1192,13 +1253,9 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata,
 	MFace *mface, *mf;
 	MemArena *arena = NULL;
 	int *mface_to_poly_map;
-	int lindex[4]; /* only ever use 3 in this case */
-	int poly_index, j, mface_index;
-
-	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);
-	const bool hasOrigSpace = CustomData_has_layer(ldata, CD_ORIGSPACE_MLOOP);
+	unsigned int (*lindices)[4];
+	int poly_index, mface_index;
+	unsigned int j;
 
 	mpoly = CustomData_get_layer(pdata, CD_MPOLY);
 	mloop = CustomData_get_layer(ldata, CD_MLOOP);
@@ -1208,12 +1265,16 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata,
 	/* take care. we are _not_ calloc'ing so be sure to initialize each field */
 	mface_to_poly_map = MEM_mallocN(sizeof(*mface_to_poly_map) * (size_t)looptris_tot, __func__);
 	mface             = MEM_mallocN(sizeof(*mface) *             (size_t)looptris_tot, __func__);
+	lindices          = MEM_mallocN(sizeof(*lindices) *          (size_t)looptris_tot, __func__);
 
 	mface_index = 0;
 	mp = mpoly;
 	for (poly_index = 0; poly_index < totpoly; poly_index++, mp++) {
 		const unsigned int mp_loopstart = (unsigned int)mp->loopstart

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list