[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [58506] trunk/blender/source/blender: optimization: lazy initialize EditDerivedBMesh members vertexNos, polyNos.

Campbell Barton ideasman42 at gmail.com
Mon Jul 22 18:49:38 CEST 2013


Revision: 58506
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=58506
Author:   campbellbarton
Date:     2013-07-22 16:49:37 +0000 (Mon, 22 Jul 2013)
Log Message:
-----------
optimization: lazy initialize EditDerivedBMesh members vertexNos, polyNos.

also add polyCos array which cache's face centers, gives overall ~20% speedup to drawing on a high-poly mesh in face-editmode.

Modified Paths:
--------------
    trunk/blender/source/blender/blenkernel/intern/editderivedmesh.c
    trunk/blender/source/blender/bmesh/intern/bmesh_polygon.c
    trunk/blender/source/blender/bmesh/intern/bmesh_polygon.h

Modified: trunk/blender/source/blender/blenkernel/intern/editderivedmesh.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/editderivedmesh.c	2013-07-22 16:41:36 UTC (rev 58505)
+++ trunk/blender/source/blender/blenkernel/intern/editderivedmesh.c	2013-07-22 16:49:37 UTC (rev 58506)
@@ -69,11 +69,121 @@
 
 	BMEditMesh *em;
 
-	float (*vertexCos)[3];
-	float (*vertexNos)[3];
-	float (*polyNos)[3];
+	/** when set, \a vertexNos, polyNos are lazy initialized */
+	const float (*vertexCos)[3];
+
+	/** lazy initialize (when \a vertexCos is set) */
+	float const (*vertexNos)[3];
+	float const (*polyNos)[3];
+	/** also lazy init but dont depend on \a vertexCos */
+	const float (*polyCos)[3];
 } EditDerivedBMesh;
 
+/* -------------------------------------------------------------------- */
+/* Lazy initialize datastructures */
+
+static void emDM_ensurePolyNormals(EditDerivedBMesh *bmdm);
+
+static void emDM_ensureVertNormals(EditDerivedBMesh *bmdm)
+{
+
+	if (bmdm->vertexCos && (bmdm->vertexNos == NULL)) {
+
+		BMesh *bm = bmdm->em->bm;
+		const float (*vertexCos)[3], (*polyNos)[3];
+		float (*vertexNos)[3];
+
+		BMFace *efa;
+		BMVert *eve;
+		BMIter fiter;
+		BMIter viter;
+		int i;
+
+		vertexCos = bmdm->vertexCos;
+		vertexNos = MEM_callocN(sizeof(*vertexNos) * bm->totvert, __func__);
+
+		/* calculate vertex normals from poly normals */
+		emDM_ensurePolyNormals(bmdm);
+
+		BM_mesh_elem_index_ensure(bm, BM_FACE);
+
+		vertexCos = bmdm->vertexCos;
+		polyNos = bmdm->polyNos;
+
+		BM_ITER_MESH_INDEX (eve, &viter, bm, BM_VERTS_OF_MESH, i) {
+			float *no = vertexNos[i];
+			BM_ITER_ELEM (efa, &fiter, eve, BM_FACES_OF_VERT) {
+				add_v3_v3(no, polyNos[BM_elem_index_get(efa)]);
+			}
+
+			/* following Mesh convention; we use vertex coordinate itself
+			 * for normal in this case */
+			if (UNLIKELY(normalize_v3(no) == 0.0f)) {
+				normalize_v3_v3(no, vertexCos[i]);
+			}
+		}
+
+		bmdm->vertexNos = (const float (*)[3])vertexNos;
+	}
+}
+
+static void emDM_ensurePolyNormals(EditDerivedBMesh *bmdm)
+{
+	if (bmdm->vertexCos && (bmdm->polyNos == NULL)) {
+		BMesh *bm = bmdm->em->bm;
+		const float (*vertexCos)[3];
+		float (*polyNos)[3];
+
+		BMFace *efa;
+		BMIter fiter;
+		int i;
+
+		BM_mesh_elem_index_ensure(bm, BM_VERT);
+
+		polyNos = MEM_mallocN(sizeof(*polyNos) * bm->totface, __func__);
+
+		vertexCos = bmdm->vertexCos;
+
+		BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) {
+			BM_elem_index_set(efa, i); /* set_inline */
+			BM_face_calc_normal_vcos(bm, efa, polyNos[i], vertexCos);
+		}
+		bm->elem_index_dirty &= ~BM_FACE;
+
+		bmdm->polyNos = (const float (*)[3])polyNos;
+	}
+}
+
+static void emDM_ensurePolyCenters(EditDerivedBMesh *bmdm)
+{
+	if (bmdm->polyCos == NULL) {
+		BMesh *bm = bmdm->em->bm;
+		float (*polyCos)[3];
+
+		BMFace *efa;
+		BMIter fiter;
+		int i;
+
+		polyCos = MEM_mallocN(sizeof(*polyCos) * bm->totface, __func__);
+
+		if (bmdm->vertexCos) {
+			const float (*vertexCos)[3];
+			vertexCos = bmdm->vertexCos;
+
+			BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) {
+				BM_face_calc_center_mean_vcos(bm, efa, polyCos[i], vertexCos);
+			}
+		}
+		else {
+			BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) {
+				BM_face_calc_center_mean(efa, polyCos[i]);
+			}
+		}
+
+		bmdm->polyCos = (const float (*)[3])polyCos;
+	}
+}
+
 static void emDM_calcNormals(DerivedMesh *dm)
 {
 	/* Nothing to do: normals are already calculated and stored on the
@@ -97,6 +207,7 @@
 	int i;
 
 	if (bmdm->vertexCos) {
+		emDM_ensureVertNormals(bmdm);
 		BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
 			func(userData, i, bmdm->vertexCos[i], bmdm->vertexNos[i], NULL);
 		}
@@ -248,56 +359,25 @@
 	glEnd();
 }
 
-static void emDM__calcFaceCent(BMFace *efa, float cent[3], float (*vertexCos)[3])
-{
-	BMIter liter;
-	BMLoop *l;
-	int tot = 0;
-
-	zero_v3(cent);
-
-	/*simple (and stupid) median (average) based method :/ */
-
-	if (vertexCos) {
-		BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
-			add_v3_v3(cent, vertexCos[BM_elem_index_get(l->v)]);
-			tot++;
-		}
-	}
-	else {
-		BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
-			add_v3_v3(cent, l->v->co);
-			tot++;
-		}
-	}
-
-	if (tot == 0) return;
-	mul_v3_fl(cent, 1.0f / (float)tot);
-}
-
 static void emDM_foreachMappedFaceCenter(DerivedMesh *dm,
                                          void (*func)(void *userData, int index, const float co[3], const float no[3]),
                                          void *userData)
 {
 	EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
 	BMesh *bm = bmdm->em->bm;
-	float (*polyNos)[3] = NULL;
+	const float (*polyNos)[3];
+	const float (*polyCos)[3];
 	BMFace *efa;
 	BMIter iter;
-	float cent[3];
 	int i;
 
-	/* ensure for face center calculation */
-	if (bmdm->vertexCos) {
-		BM_mesh_elem_index_ensure(bm, BM_VERT);
-		polyNos = bmdm->polyNos;
+	emDM_ensurePolyNormals(bmdm);
+	emDM_ensurePolyCenters(bmdm);
+	polyNos = bmdm->polyNos;  /* maybe NULL */
+	polyCos = bmdm->polyCos;  /* always set */
 
-		BLI_assert(polyNos != NULL);
-	}
-
 	BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) {
-		emDM__calcFaceCent(efa, cent, bmdm->vertexCos);
-		func(userData, i, cent, polyNos ? polyNos[i] : efa->no);
+		func(userData, i, polyCos[i], polyNos ? polyNos[i] : efa->no);
 	}
 }
 
@@ -349,11 +429,15 @@
 
 	if (bmdm->vertexCos) {
 		/* add direct access */
-		float (*vertexCos)[3] = bmdm->vertexCos;
-		float (*vertexNos)[3] = bmdm->vertexNos;
-		float (*polyNos)[3]   = bmdm->polyNos;
-		// int *triPolyMap = bmdm->triPolyMap;
+		const float (*vertexCos)[3] = bmdm->vertexCos;
+		const float (*vertexNos)[3];
+		const float (*polyNos)[3];
 
+		emDM_ensureVertNormals(bmdm);
+		emDM_ensurePolyNormals(bmdm);
+		vertexNos = bmdm->vertexNos;
+		polyNos = bmdm->polyNos;
+
 		BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
 
 		for (i = 0; i < tottri; i++) {
@@ -561,9 +645,6 @@
 	BMEditMesh *em = bmdm->em;
 	BMesh *bm = em->bm;
 	struct BMLoop *(*looptris)[3] = em->looptris;
-	float (*vertexCos)[3] = bmdm->vertexCos;
-	float (*vertexNos)[3] = bmdm->vertexNos;
-	float (*polyNos)[3]   = bmdm->polyNos;
 	BMFace *efa;
 	MLoopUV *luv[3], dummyluv = {{0}};
 	MLoopCol *lcol[3] = {NULL} /* , dummylcol = {0} */;
@@ -593,7 +674,17 @@
 		BM_mesh_elem_index_ensure(bm, BM_VERT);
 	}
 
-	if (vertexCos) {
+	if (bmdm->vertexCos) {
+		/* add direct access */
+		const float (*vertexCos)[3] = bmdm->vertexCos;
+		const float (*vertexNos)[3];
+		const float (*polyNos)[3];
+
+		emDM_ensureVertNormals(bmdm);
+		emDM_ensurePolyNormals(bmdm);
+		vertexNos = bmdm->vertexNos;
+		polyNos = bmdm->polyNos;
+
 		BM_mesh_elem_index_ensure(bm, BM_VERT);
 
 		for (i = 0; i < em->tottri; i++) {
@@ -791,9 +882,11 @@
 	BMEditMesh *em = bmdm->em;
 	BMesh *bm = em->bm;
 	struct BMLoop *(*looptris)[3] = em->looptris;
-	float (*vertexCos)[3] = bmdm->vertexCos;
-	float (*vertexNos)[3] = bmdm->vertexNos;
-	float (*polyNos)[3]   = bmdm->polyNos;
+	/* add direct access */
+	const float (*vertexCos)[3] = bmdm->vertexCos;
+	const float (*vertexNos)[3];
+	const float (*polyNos)[3];
+
 	BMFace *efa;
 	DMVertexAttribs attribs;
 	GPUVertexAttribs gattribs;
@@ -805,6 +898,11 @@
 
 	memset(&attribs, 0, sizeof(attribs));
 
+	emDM_ensureVertNormals(bmdm);
+	emDM_ensurePolyNormals(bmdm);
+	vertexNos = bmdm->vertexNos;
+	polyNos = bmdm->polyNos;
+
 	/* always use smooth shading even for flat faces, else vertex colors wont interpolate */
 	glShadeModel(GL_SMOOTH);
 	BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
@@ -926,9 +1024,9 @@
 	BMEditMesh *em = bmdm->em;
 	BMesh *bm = em->bm;
 	struct BMLoop *(*looptris)[3] = em->looptris;
-	float (*vertexCos)[3] = bmdm->vertexCos;
-	float (*vertexNos)[3] = bmdm->vertexNos;
-	float (*polyNos)[3]   = bmdm->polyNos;
+	const float (*vertexCos)[3] = bmdm->vertexCos;
+	const float (*vertexNos)[3];
+	const float (*polyNos)[3];
 	BMFace *efa;
 	DMVertexAttribs attribs = {{{0}}};
 	GPUVertexAttribs gattribs;
@@ -936,6 +1034,12 @@
 
 	matnr = -1;
 
+	emDM_ensureVertNormals(bmdm);
+	emDM_ensurePolyNormals(bmdm);
+
+	vertexNos = bmdm->vertexNos;
+	polyNos = bmdm->polyNos;
+
 	/* always use smooth shading even for flat faces, else vertex colors wont interpolate */
 	glShadeModel(GL_SMOOTH);
 
@@ -1139,7 +1243,9 @@
 		return;
 	}
 
-	if (bmdm->vertexNos) {
+
+	if (bmdm->vertexCos) {
+		emDM_ensureVertNormals(bmdm);
 		copy_v3_v3(r_no, bmdm->vertexNos[index]);
 	}
 	else {
@@ -1159,7 +1265,8 @@
 		return;
 	}
 
-	if (bmdm->polyNos) {
+	if (bmdm->vertexCos) {
+		emDM_ensurePolyNormals(bmdm);
 		copy_v3_v3(r_no, bmdm->polyNos[index]);
 	}
 	else {
@@ -1439,10 +1546,18 @@
 	if (DM_release(dm)) {
 		if (bmdm->vertexCos) {
 			MEM_freeN(bmdm->vertexCos);
-			MEM_freeN(bmdm->vertexNos);
-			MEM_freeN(bmdm->polyNos);
+			if (bmdm->vertexNos) {
+				MEM_freeN(bmdm->vertexNos);
+			}
+			if (bmdm->polyNos) {
+				MEM_freeN(bmdm->polyNos);
+			}
 		}
 
+		if (bmdm->polyCos) {
+			MEM_freeN(bmdm->polyCos);
+		}
+
 		MEM_freeN(bmdm);
 	}
 }
@@ -1549,7 +1664,7 @@
 
 	bmdm->dm.release = emDM_release;
 
-	bmdm->vertexCos = vertexCos;
+	bmdm->vertexCos = (const float (*)[3])vertexCos;
 	bmdm->dm.deformedOnly = (vertexCos != NULL);
 
 	if (cd_dvert_offset != -1) {
@@ -1578,38 +1693,6 @@
 		}
 	}
 
-	if (vertexCos) {
-		BMFace *efa;
-		BMVert *eve;
-		BMIter fiter;
-		BMIter viter;
-		int i;
-
-		BM_mesh_elem_index_ensure(bm, BM_VERT);
-
-		bmdm->vertexNos = MEM_callocN(sizeof(*bmdm->vertexNos) * bm->totvert, "bmdm_vno");
-		bmdm->polyNos = MEM_mallocN(sizeof(*bmdm->polyNos) * bm->totface, "bmdm_pno");
-
-		BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) {
-			BM_elem_index_set(efa, i); /* set_inline */
-			BM_face_normal_update_vcos(bm, efa, bmdm->polyNos[i], (float const (*)[3])vertexCos);
-		}
-		bm->elem_index_dirty &= ~BM_FACE;
-
-		BM_ITER_MESH_INDEX (eve, &viter, bm, BM_VERTS_OF_MESH, i) {
-			float *no = bmdm->vertexNos[i];
-			BM_ITER_ELEM (efa, &fiter, eve, BM_FACES_OF_VERT) {
-				add_v3_v3(no, bmdm->polyNos[BM_elem_index_get(efa)]);
-			}
-
-			/* following Mesh convention; we use vertex coordinate itself
-			 * for normal in this case */
-			if (UNLIKELY(normalize_v3(no) == 0.0f)) {
-				normalize_v3_v3(no, vertexCos[i]);
-			}
-		}
-	}
-
 	return (DerivedMesh *)bmdm;
 }
 
@@ -1877,7 +1960,7 @@
 
 static void statvis_calc_distort(
         BMEditMesh *em,
-        const float (*vertexCos)[3],
+        const float (*vertexCos)[3], const float (*polyNos)[3],
         /* values for calculating */
         const float min, const float max,
         /* result */
@@ -1886,7 +1969,7 @@

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list