[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [56649] trunk/blender/source/blender: Optimize BKE_mesh_calc_normals(), gives approx 25% speedup.

Campbell Barton ideasman42 at gmail.com
Fri May 10 12:07:02 CEST 2013


Revision: 56649
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=56649
Author:   campbellbarton
Date:     2013-05-10 10:07:01 +0000 (Fri, 10 May 2013)
Log Message:
-----------
Optimize BKE_mesh_calc_normals(), gives approx 25% speedup.
- no need to allocate polygon normal array.
- no need to use BLI_array_ functions (realloc's).
- reduce some of the looping.

Modified Paths:
--------------
    trunk/blender/source/blender/blenkernel/intern/mesh.c
    trunk/blender/source/blender/blenlib/BLI_math_geom.h
    trunk/blender/source/blender/blenlib/intern/math_geom.c

Modified: trunk/blender/source/blender/blenkernel/intern/mesh.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/mesh.c	2013-05-10 09:54:25 UTC (rev 56648)
+++ trunk/blender/source/blender/blenkernel/intern/mesh.c	2013-05-10 10:07:01 UTC (rev 56649)
@@ -1941,52 +1941,75 @@
 	
 }
 
-void BKE_mesh_calc_normals(MVert *mverts, int numVerts, MLoop *mloop, MPoly *mpolys,
-                           int UNUSED(numLoops), int numPolys, float (*polyNors_r)[3])
+static void mesh_calc_normals_poly_accum(MPoly *mp, MLoop *ml,
+                                         MVert *mvert, float polyno[3], float (*tnorms)[3])
 {
-	float (*pnors)[3] = polyNors_r;
+	const int nverts = mp->totloop;
+	float (*edgevecbuf)[3] = BLI_array_alloca(edgevecbuf, nverts);
+	int i;
 
-	float (*tnorms)[3], (*edgevecbuf)[3] = NULL;
-	float **vertcos = NULL, **vertnos = NULL;
-	BLI_array_declare(vertcos);
-	BLI_array_declare(vertnos);
-	BLI_array_declare(edgevecbuf);
+	/* Polygon Normal and edge-vector */
+	/* inline version of #BKE_mesh_calc_poly_normal, also does edge-vectors */
+	{
+		float const *v_prev = mvert[ml[nverts - 1].v].co;
+		float const *v_curr;
+		int i_prev = nverts - 1;
 
-	int i, j;
-	MPoly *mp;
-	MLoop *ml;
+		zero_v3(polyno);
+		/* Newell's Method */
+		for (i = 0; i < nverts; i++) {
+			v_curr = mvert[ml[i].v].co;
+			add_newell_cross_v3_v3v3(polyno, v_prev, v_curr);
 
-	if (!pnors) pnors = MEM_callocN(sizeof(float) * 3 * numPolys, "poly_nors mesh.c");
+			/* Unrelated to normalize, calcualte edge-vector */
+			sub_v3_v3v3(edgevecbuf[i_prev], v_prev, v_curr);
+			i_prev = i;
 
-	/* first go through and calculate normals for all the polys */
-	tnorms = MEM_callocN(sizeof(float) * 3 * numVerts, "tnorms mesh.c");
+			v_prev = v_curr;
+		}
+		if (UNLIKELY(normalize_v3(polyno) == 0.0f)) {
+			polyno[2] = 1.0f; /* other axis set to 0.0 */
+		}
+	}
 
-	mp = mpolys;
-	for (i = 0; i < numPolys; i++, mp++) {
-		BKE_mesh_calc_poly_normal(mp, mloop + mp->loopstart, mverts, pnors[i]);
-		ml = mloop + mp->loopstart;
+	/* accumulate angle weighted face normal */
+	/* inline version of #accumulate_vertex_normals_poly */
+	{
+		const float *prev_edge = edgevecbuf[nverts - 1];
 
-		BLI_array_empty(vertcos);
-		BLI_array_empty(vertnos);
-		BLI_array_grow_items(vertcos, mp->totloop);
-		BLI_array_grow_items(vertnos, mp->totloop);
+		for (i = 0; i < nverts; i++) {
+			const float *cur_edge = edgevecbuf[i];
+			unsigned int vindex = ml[i].v;
 
-		for (j = 0; j < mp->totloop; j++) {
-			int vindex = ml[j].v;
-			vertcos[j] = mverts[vindex].co;
-			vertnos[j] = tnorms[vindex];
+			/* calculate angle between the two poly edges incident on
+			 * this vertex */
+			const float fac = saacos(-dot_v3v3(cur_edge, prev_edge));
+
+			/* accumulate */
+			madd_v3_v3fl(tnorms[vindex], polyno, fac);
+			prev_edge = cur_edge;
 		}
+	}
 
-		BLI_array_empty(edgevecbuf);
-		BLI_array_grow_items(edgevecbuf, mp->totloop);
+}
 
-		accumulate_vertex_normals_poly(vertnos, pnors[i], vertcos, edgevecbuf, mp->totloop);
+void BKE_mesh_calc_normals(MVert *mverts, int numVerts, MLoop *mloop, MPoly *mpolys,
+                           int UNUSED(numLoops), int numPolys, float (*polyNors_r)[3])
+{
+	float (*pnors)[3] = polyNors_r;
+	float (*tnorms)[3];
+	float tpnor[3];  /* temp poly normal */
+	int i;
+	MPoly *mp;
+
+	/* first go through and calculate normals for all the polys */
+	tnorms = MEM_callocN(sizeof(*tnorms) * numVerts, __func__);
+
+	mp = mpolys;
+	for (i = 0; i < numPolys; i++, mp++) {
+		mesh_calc_normals_poly_accum(mp, mloop + mp->loopstart, mverts, pnors ? pnors[i] : tpnor, tnorms);
 	}
 
-	BLI_array_free(vertcos);
-	BLI_array_free(vertnos);
-	BLI_array_free(edgevecbuf);
-
 	/* following Mesh convention; we use vertex coordinate itself for normal in this case */
 	for (i = 0; i < numVerts; i++) {
 		MVert *mv = &mverts[i];
@@ -2000,8 +2023,6 @@
 	}
 
 	MEM_freeN(tnorms);
-
-	if (pnors != polyNors_r) MEM_freeN(pnors);
 }
 
 void BKE_mesh_calc_normals_tessface(MVert *mverts, int numVerts, MFace *mfaces, int numFaces, float (*faceNors_r)[3])

Modified: trunk/blender/source/blender/blenlib/BLI_math_geom.h
===================================================================
--- trunk/blender/source/blender/blenlib/BLI_math_geom.h	2013-05-10 09:54:25 UTC (rev 56648)
+++ trunk/blender/source/blender/blenlib/BLI_math_geom.h	2013-05-10 10:07:01 UTC (rev 56649)
@@ -237,8 +237,8 @@
                                float n4[3], const float f_no[3], const float co1[3], const float co2[3],
                                const float co3[3], const float co4[3]);
 
-void accumulate_vertex_normals_poly(float **vertnos, float polyno[3],
-                                    float **vertcos, float vdiffs[][3], int nverts);
+void accumulate_vertex_normals_poly(float **vertnos, const float polyno[3],
+                                    const float **vertcos, float vdiffs[][3], const int nverts);
 
 /********************************* Tangents **********************************/
 

Modified: trunk/blender/source/blender/blenlib/intern/math_geom.c
===================================================================
--- trunk/blender/source/blender/blenlib/intern/math_geom.c	2013-05-10 09:54:25 UTC (rev 56648)
+++ trunk/blender/source/blender/blenlib/intern/math_geom.c	2013-05-10 10:07:01 UTC (rev 56649)
@@ -3107,8 +3107,8 @@
 
 /* Add weighted face normal component into normals of the face vertices.
  * Caller must pass pre-allocated vdiffs of nverts length. */
-void accumulate_vertex_normals_poly(float **vertnos, float polyno[3],
-                                    float **vertcos, float vdiffs[][3], int nverts)
+void accumulate_vertex_normals_poly(float **vertnos, const float polyno[3],
+                                    const float **vertcos, float vdiffs[][3], int nverts)
 {
 	int i;
 




More information about the Bf-blender-cvs mailing list