[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [54188] trunk/blender/source/blender: skip calculating the normal for each face when triangulating, all callers make sure its valid.

Campbell Barton ideasman42 at gmail.com
Tue Jan 29 16:05:23 CET 2013


Revision: 54188
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=54188
Author:   campbellbarton
Date:     2013-01-29 15:05:23 +0000 (Tue, 29 Jan 2013)
Log Message:
-----------
skip calculating the normal for each face when triangulating, all callers make sure its valid. also remove some commented code (more then one generation of bmesh old).

Modified Paths:
--------------
    trunk/blender/source/blender/blenlib/BLI_math_matrix.h
    trunk/blender/source/blender/blenlib/intern/math_matrix.c
    trunk/blender/source/blender/blenlib/intern/math_rotation.c
    trunk/blender/source/blender/bmesh/intern/bmesh_polygon.c
    trunk/blender/source/blender/bmesh/intern/bmesh_polygon.h
    trunk/blender/source/blender/bmesh/tools/bmesh_triangulate.c

Modified: trunk/blender/source/blender/blenlib/BLI_math_matrix.h
===================================================================
--- trunk/blender/source/blender/blenlib/BLI_math_matrix.h	2013-01-29 14:52:26 UTC (rev 54187)
+++ trunk/blender/source/blender/blenlib/BLI_math_matrix.h	2013-01-29 15:05:23 UTC (rev 54188)
@@ -95,6 +95,7 @@
 
 void mul_m3_v3(float M[3][3], float r[3]);
 void mul_v3_m3v3(float r[3], float M[3][3], float a[3]);
+void mul_v2_m3v3(float r[2], float M[3][3], float a[3]);
 void mul_transposed_m3_v3(float M[3][3], float r[3]);
 void mul_m3_v3_double(float M[3][3], double r[3]);
 

Modified: trunk/blender/source/blender/blenlib/intern/math_matrix.c
===================================================================
--- trunk/blender/source/blender/blenlib/intern/math_matrix.c	2013-01-29 14:52:26 UTC (rev 54187)
+++ trunk/blender/source/blender/blenlib/intern/math_matrix.c	2013-01-29 15:05:23 UTC (rev 54188)
@@ -411,6 +411,13 @@
 	r[2] = M[0][2] * a[0] + M[1][2] * a[1] + M[2][2] * a[2];
 }
 
+void mul_v2_m3v3(float r[2], float M[3][3], float a[3])
+{
+	r[0] = M[0][0] * a[0] + M[1][0] * a[1] + M[2][0] * a[2];
+	r[1] = M[0][1] * a[0] + M[1][1] * a[1] + M[2][1] * a[2];
+	r[2] = M[0][2] * a[0] + M[1][2] * a[1] + M[2][2] * a[2];
+}
+
 void mul_m3_v3(float M[3][3], float r[3])
 {
 	float tmp[3];

Modified: trunk/blender/source/blender/blenlib/intern/math_rotation.c
===================================================================
--- trunk/blender/source/blender/blenlib/intern/math_rotation.c	2013-01-29 14:52:26 UTC (rev 54187)
+++ trunk/blender/source/blender/blenlib/intern/math_rotation.c	2013-01-29 15:05:23 UTC (rev 54188)
@@ -84,6 +84,8 @@
  * \note:
  * Assumes a unit quaternion?
  *
+ * \note: multiplying by 3x3 matrix is ~25% faster.
+ *
  * in fact not, but you may want to use a unit quat, read on...
  *
  * Shortcut for 'q v q*' when \a v is actually a quaternion.

Modified: trunk/blender/source/blender/bmesh/intern/bmesh_polygon.c
===================================================================
--- trunk/blender/source/blender/bmesh/intern/bmesh_polygon.c	2013-01-29 14:52:26 UTC (rev 54187)
+++ trunk/blender/source/blender/bmesh/intern/bmesh_polygon.c	2013-01-29 15:05:23 UTC (rev 54188)
@@ -297,39 +297,51 @@
 	add_v3_v3v3(v2, v2, mid);
 }
 
-
 /**
- * \brief POLY ROTATE PLANE
+ * \brief POLY NORMAL TO MATRIX
  *
- * Rotates a polygon so that it's
- * normal is pointing towards the mesh Z axis
+ * Creates a 3x3 matrix from a normal.
  */
-void poly_rotate_plane(const float normal[3], float (*verts)[3], const int nverts)
+static bool poly_normal_to_xy_mat3(float r_mat[3][3], const float normal[3])
 {
-
-	float up[3] = {0.0f, 0.0f, 1.0f}, axis[3], q[4];
-	float mat[3][3];
+	float up[3] = {0.0f, 0.0f, 1.0f}, axis[3];
 	float angle;
-	int i;
 
 	cross_v3_v3v3(axis, normal, up);
-
 	angle = saacos(dot_v3v3(normal, up));
 
-	if (angle < FLT_EPSILON)
-		return;
+	if (angle >= FLT_EPSILON) {
+		if (len_squared_v3(axis) < FLT_EPSILON) {
+			axis[0] = 0.0f;
+			axis[1] = 1.0f;
+			axis[2] = 0.0f;
+		}
 
-	if (len_squared_v3(axis) < FLT_EPSILON) {
-		axis[0] = 0.0f;
-		axis[1] = 1.0f;
-		axis[2] = 0.0f;
+		axis_angle_to_mat3(r_mat, axis, angle);
+		return true;
 	}
+	else {
+		unit_m3(r_mat);
+		return false;
+	}
+}
 
-	axis_angle_to_quat(q, axis, angle);
-	quat_to_mat3(mat, q);
+/**
+ * \brief POLY ROTATE PLANE
+ *
+ * Rotates a polygon so that it's
+ * normal is pointing towards the mesh Z axis
+ */
+void poly_rotate_plane(const float normal[3], float (*verts)[3], const int nverts)
+{
+	float mat[3][3];
 
-	for (i = 0; i < nverts; i++)
-		mul_m3_v3(mat, verts[i]);
+	if (poly_normal_to_xy_mat3(mat, normal)) {
+		int i;
+		for (i = 0; i < nverts; i++) {
+			mul_m3_v3(mat, verts[i]);
+		}
+	}
 }
 
 /**
@@ -614,17 +626,17 @@
 	return crosses % 2 != 0;
 }
 
-static bool bm_face_goodline(float const (*projectverts)[3], BMFace *f, int v1i, int v2i, int v3i)
+static bool bm_face_goodline(float const (*projectverts)[2], BMFace *f, int v1i, int v2i, int v3i)
 {
 	BMLoop *l_iter;
 	BMLoop *l_first;
-	float v1[3], v2[3], v3[3], pv1[3];
+
+	float pv1[2];
+	const float *v1 = projectverts[v1i];
+	const float *v2 = projectverts[v2i];
+	const float *v3 = projectverts[v3i];
 	int i;
 
-	copy_v3_v3(v1, projectverts[v1i]);
-	copy_v3_v3(v2, projectverts[v2i]);
-	copy_v3_v3(v3, projectverts[v3i]);
-
 	/* v3 must be on the left side of [v1, v2] line, else we know [v1, v3] is outside of f! */
 	if (testedgesidef(v1, v2, v3)) {
 		return false;
@@ -633,7 +645,7 @@
 	l_iter = l_first = BM_FACE_FIRST_LOOP(f);
 	do {
 		i = BM_elem_index_get(l_iter->v);
-		copy_v3_v3(pv1, projectverts[i]);
+		copy_v2_v2(pv1, projectverts[i]);
 
 		if (ELEM3(i, v1i, v2i, v3i)) {
 #if 0
@@ -665,7 +677,7 @@
  * \param abscoss Must be allocated by caller, and at least f->len length
  *        (allow to avoid allocating a new one for each tri!).
  */
-static BMLoop *find_ear(BMFace *f, float (*verts)[3], const bool use_beauty, float *abscoss)
+static BMLoop *find_ear(BMFace *f, float (*projectverts)[2], const bool use_beauty, float *abscoss)
 {
 	BMLoop *bestear = NULL;
 
@@ -711,7 +723,7 @@
 		/* Last check we do not get overlapping triangles
 		 * (as much as possible, there are some cases with no good solution!) */
 		i4 = (i + 3) % 4;
-		if (!bm_face_goodline((float const (*)[3])verts, f, BM_elem_index_get(larr[i4]->v),
+		if (!bm_face_goodline((float const (*)[2])projectverts, f, BM_elem_index_get(larr[i4]->v),
 		                      BM_elem_index_get(larr[i]->v), BM_elem_index_get(larr[i + 1]->v)))
 		{
 			i = !i;
@@ -756,7 +768,7 @@
 			if (BM_edge_exists(v1, v3)) {
 				is_ear = false;
 			}
-			else if (!bm_face_goodline((float const (*)[3])verts, f, BM_elem_index_get(v1),
+			else if (!bm_face_goodline((float const (*)[2])projectverts, f, BM_elem_index_get(v1),
 			                           BM_elem_index_get(v2), BM_elem_index_get(v3)))
 			{
 #if 0
@@ -767,19 +779,6 @@
 			}
 
 			if (is_ear) {
-#if 0 /* Old, already commented code */
-				/* if this code comes back, it needs to be converted to radians */
-				angle = angle_v3v3v3(verts[v1->head.eflag2], verts[v2->head.eflag2], verts[v3->head.eflag2]);
-				if (!bestear || ABS(angle - 45.0f) < bestangle) {
-					bestear = l;
-					bestangle = ABS(45.0f - angle);
-				}
-
-				if (angle > 20 && angle < 90) break;
-				if (angle < 100 && i > 5) break;
-				i += 1;
-#endif
-
 				/* Compute highest cos (i.e. narrowest angle) of this tri. */
 				cos = *tcoss;
 				tcos = fabsf(cos_v3v3v3(v2->co, v3->co, v1->co));
@@ -839,50 +838,39 @@
  * produces a "remaining" face with too much wide/narrow angles
  * (using cos (i.e. dot product of normalized vectors) of angles).
  *
- * newfaces, if non-null, must be an array of BMFace pointers,
- * with a length equal to f->len. It will be filled with the new
- * triangles, and will be NULL-terminated.
+ * \param r_faces_new if non-null, must be an array of BMFace pointers,
+ * with a length equal to (f->len - 2). It will be filled with the new
+ * triangles.
  *
  * \note newedgeflag sets a flag layer flag, obviously not the header flag.
  */
 void BM_face_triangulate(BMesh *bm, BMFace *f,
-                         float (*projectverts)[3], BMFace **newfaces,
+                         BMFace **r_faces_new,
                          const bool use_beauty, const bool use_tag)
 {
-	int i, nvert, nf_i = 0;
-	bool done;
-	BMLoop *newl;
+	const float f_len_orig = f->len;
+	int i, nf_i = 0;
+	BMLoop *l_new;
 	BMLoop *l_iter;
 	BMLoop *l_first;
 	/* BM_face_triangulate: temp absolute cosines of face corners */
-	float *abscoss = BLI_array_alloca(abscoss, f->len);
+	float (*projectverts)[2] = BLI_array_alloca(projectverts, f_len_orig);
+	float *abscoss = BLI_array_alloca(abscoss, f_len_orig);
+	float mat[3][3];
 
+	poly_normal_to_xy_mat3(mat, f->no);
+
 	/* copy vertex coordinates to vertspace area */
 	i = 0;
 	l_iter = l_first = BM_FACE_FIRST_LOOP(f);
 	do {
-		copy_v3_v3(projectverts[i], l_iter->v->co);
-		BM_elem_index_set(l_iter->v, i); /* set dirty! */
-		i++;
+		mul_v2_m3v3(projectverts[i], mat, l_iter->v->co);
+		BM_elem_index_set(l_iter->v, i++); /* set dirty! */
 	} while ((l_iter = l_iter->next) != l_first);
 
 	bm->elem_index_dirty |= BM_VERT; /* see above */
 
-	/* bmesh_face_normal_update(bm, f, f->no, projectverts); */
-
-	calc_poly_normal(f->no, projectverts, f->len);
-	poly_rotate_plane(f->no, projectverts, i);
-
-	nvert = f->len;
-
-	/* calc_poly_plane(projectverts, i); */
-	for (i = 0; i < nvert; i++) {
-		projectverts[i][2] = 0.0f;
-	}
-
-	done = false;
-	while (!done && f->len > 3) {
-		done = true;
+	while (f->len > 3) {
 		l_iter = find_ear(f, projectverts, use_beauty, abscoss);
 
 		/* force triangulation - if we can't find an ear the face is degenerate */
@@ -890,70 +878,27 @@
 			l_iter = BM_FACE_FIRST_LOOP(f);
 		}
 
-		{
-			done = false;
-/*			printf("Subdividing face...\n");*/
-			f = BM_face_split(bm, l_iter->f, l_iter->prev->v, l_iter->next->v, &newl, NULL, true);
+/*		printf("Subdividing face...\n");*/
+		f = BM_face_split(bm, l_iter->f, l_iter->prev->v, l_iter->next->v, &l_new, NULL, true);
 
-			if (UNLIKELY(!f)) {
-				fprintf(stderr, "%s: triangulator failed to split face! (bmesh internal error)\n", __func__);
-				break;
-			}
+		if (UNLIKELY(!f)) {
+			fprintf(stderr, "%s: triangulator failed to split face! (bmesh internal error)\n", __func__);
+			break;
+		}
 
-			copy_v3_v3(f->no, l_iter->f->no);
+		copy_v3_v3(f->no, l_iter->f->no);
 
-			if (use_tag) {
-				BM_elem_flag_enable(newl->e, BM_ELEM_TAG);
-				BM_elem_flag_enable(f, BM_ELEM_TAG);
-			}
-			
-			if (newfaces)
-				newfaces[nf_i++] = f;
-
-#if 0
-			l = f->loopbase;
-			do {
-				if (l->v == v) {
-					f->loopbase = l;
-					break;
-				}
-				l = l->next;
-			} while (l != f->loopbase);
-#endif
-
+		if (use_tag) {
+			BM_elem_flag_enable(l_new->e, BM_ELEM_TAG);
+			BM_elem_flag_enable(f, BM_ELEM_TAG);
 		}
-	}
 
-	BLI_assert(f->len == 3);
-
-#if 0 /* XXX find_ear should now always return a corner, so no more need for this piece of code... */
-	if (f->len > 3) {
-		l_iter = BM_FACE_FIRST_LOOP(f);
-		while (l_iter->f->len > 3) {
-			nextloop = l_iter->next->next;
-			f = BM_face_split(bm, l_iter->f, l_iter->v, nextloop->v,
-			                  &newl, NULL, true);
-			if (!f) {
-				printf("triangle fan step of triangulator failed.\n");
-
-				/* NULL-terminate */
-				if (newfaces) newfaces[nf_i] = NULL;
-				return;
-			}
-
-			if (newfaces) newfaces[nf_i++] = f;
-			

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list