[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [40452] branches/bmesh/blender/source/ blender/bmesh/intern: Normal math improvements and vector math cleanup

Andrew Wiggin ender79bl at gmail.com
Thu Sep 22 14:31:01 CEST 2011


Revision: 40452
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=40452
Author:   ender79
Date:     2011-09-22 12:31:01 +0000 (Thu, 22 Sep 2011)
Log Message:
-----------
Normal math improvements and vector math cleanup

Modified Paths:
--------------
    branches/bmesh/blender/source/blender/bmesh/intern/bmesh_mesh.c
    branches/bmesh/blender/source/blender/bmesh/intern/bmesh_polygon.c

Modified: branches/bmesh/blender/source/blender/bmesh/intern/bmesh_mesh.c
===================================================================
--- branches/bmesh/blender/source/blender/bmesh/intern/bmesh_mesh.c	2011-09-22 12:07:02 UTC (rev 40451)
+++ branches/bmesh/blender/source/blender/bmesh/intern/bmesh_mesh.c	2011-09-22 12:31:01 UTC (rev 40452)
@@ -172,12 +172,16 @@
 	BMVert *v;
 	BMFace *f;
 	BMLoop *l;
+	BMEdge *e;
 	BMIter verts;
 	BMIter faces;
 	BMIter loops;
+	BMIter edges;
 	unsigned int maxlength = 0;
+	int index;
 	float (*projectverts)[3];
-	
+	float (*edgevec)[3];
+
 	/*first, find out the largest face in mesh*/
 	BM_ITER(f, &faces, bm, BM_FACES_OF_MESH, NULL) {
 		if (BM_TestHFlag(f, BM_HIDDEN))
@@ -188,7 +192,7 @@
 	
 	/*make sure we actually have something to do*/
 	if(maxlength < 3) return; 
-	
+
 	/*allocate projectverts array*/
 	projectverts = MEM_callocN(sizeof(float) * maxlength * 3, "BM normal computation array");
 	
@@ -207,20 +211,57 @@
 		if (BM_TestHFlag(v, BM_HIDDEN))
 			continue;
 
-		v->no[0] = v->no[1] = v->no[2] = 0.0;
+		zero_v3(v->no);
 	}
 
-	/*add face normals to vertices*/
+	/* compute normalized direction vectors for each edge. directions will be
+	   used below for calculating the weights of the face normals on the vertex
+	   normals */
+	index = 0;
+	edgevec = MEM_callocN(sizeof(float) * 3 * bm->totedge, "BM normal computation array");
+	BM_ITER(e, &edges, bm, BM_EDGES_OF_MESH, NULL) {
+		if (!e->l) {
+			/* the edge vector will not be needed when the edge has no radial */
+			continue;
+		}
+		BM_SetIndex(e, index);
+		sub_v3_v3v3(edgevec[index], e->v2->co, e->v1->co);
+		normalize_v3(edgevec[index]);
+		index++;
+	}
+
+	/*add weighted face normals to vertices*/
 	BM_ITER(f, &faces, bm, BM_FACES_OF_MESH, NULL) {
 
 		if (BM_TestHFlag(f, BM_HIDDEN))
 			continue;
 
-		for(l = BMIter_New(&loops, bm, BM_LOOPS_OF_FACE, f ); l; l = BMIter_Step(&loops)) 
-			add_v3_v3v3(l->v->no, l->v->no, f->no);
+		BM_ITER(l, &loops, bm, BM_LOOPS_OF_FACE, f) {
+			float *e1diff, *e2diff;
+			float dotprod;
+			float fac;
+
+			/* calculate the dot product of the two edges that
+			   meet at the loop's vertex */
+			e1diff = edgevec[BM_GetIndex(l->prev->e)];
+			e2diff = edgevec[BM_GetIndex(l->e)];
+			dotprod = dot_v3v3(e1diff, e2diff);
+
+			/* edge vectors are calculated from e->v1 to e->v2, so
+			   adjust the dot product if one but not both loops 
+			   actually runs from from e->v2 to e->v1 */
+			if ((l->prev->e->v1 == l->prev->v) ^ (l->e->v1 == l->v)) {
+				dotprod *= -1.0f;
+			}
+
+			fac = saacos(-dotprod);
+
+			/* accumulate weighted face normal into the vertex's normal */
+			madd_v3_v3fl(l->v->no, f->no, fac);
+		}
 	}
 	
-	/*average the vertex normals*/
+	/* normalize the accumulated vertex normals */
 	BM_ITER(v, &verts, bm, BM_VERTS_OF_MESH, NULL) {
 		if (BM_TestHFlag(v, BM_HIDDEN))
 			continue;
@@ -231,6 +272,7 @@
 		}
 	}
 	
+	MEM_freeN(edgevec);
 	MEM_freeN(projectverts);
 }
 

Modified: branches/bmesh/blender/source/blender/bmesh/intern/bmesh_polygon.c
===================================================================
--- branches/bmesh/blender/source/blender/bmesh/intern/bmesh_polygon.c	2011-09-22 12:07:02 UTC (rev 40451)
+++ branches/bmesh/blender/source/blender/bmesh/intern/bmesh_polygon.c	2011-09-22 12:31:01 UTC (rev 40452)
@@ -90,15 +90,15 @@
 static void compute_poly_normal(float normal[3], float (*verts)[3], int nverts)
 {
 
-	float u[3],  v[3], w[3];/*, *w, v1[3], v2[3];*/
-	float n[3] = {0.0, 0.0, 0.0} /*, l, v1[3], v2[3] */;
+	float u[3], v[3], w[3];/*, *w, v1[3], v2[3];*/
+	float n[3]/*, l, v1[3], v2[3] */;
 	/* double l2; */
 	int i /*, s=0 */;
 
+	zero_v3(n);
+
 	/*this fixes some weird numerical error*/
-	verts[0][0] += 0.0001f;
-	verts[0][1] += 0.0001f;
-	verts[0][2] += 0.0001f;
+	add_v3_fl(verts[0], 0.0001f);
 
 	for(i = 0; i < nverts; i++){
 		copy_v3_v3(u, verts[i]);
@@ -137,8 +137,7 @@
 	}
 
 #if 0
-	l = n[0]*n[0]+n[1]*n[1]+n[2]*n[2];
-	l = sqrt(l);
+	l = len_v3(n);
 	/*fast square root, newton/babylonian method:
 	l2 = l*0.1;
 
@@ -155,13 +154,9 @@
 		return;
 	} else l = 1.0f / l;
 
-	n[0] *= l;
-	n[1] *= l;
-	n[2] *= l;
-	
-	normal[0] = (float) n[0];
-	normal[1] = (float) n[1];
-	normal[2] = (float) n[2];
+	mul_v3_fl(n, l);
+
+	copy_v3_v3(normal, n);
 #endif
 }
 
@@ -178,9 +173,9 @@
 {
 	int i, j;
 	float atmp = 0.0, xtmp = 0.0, ytmp = 0.0, ai;
-	
-	center[0] = center[1] = center[2] = 0.0;	
 
+	zero_v3(center);
+
 	if(nverts < 3) 
 		return 0;
 
@@ -266,15 +261,15 @@
 void compute_poly_plane(float (*verts)[3], int nverts)
 {
 	
-	float avgc[3], norm[3], temp[3], mag, avgn[3];
+	float avgc[3], norm[3], mag, avgn[3];
 	float *v1, *v2, *v3;
 	int i;
 	
 	if(nverts < 3) 
 		return;
 
-	avgn[0] = avgn[1] = avgn[2] = 0.0;
-	avgc[0] = avgc[1] = avgc[2] = 0.0;
+	zero_v3(avgn);
+	zero_v3(avgc);
 
 	for(i = 0; i < nverts; i++){
 		v1 = verts[i];
@@ -286,7 +281,7 @@
 	}
 
 	/*what was this bit for?*/
-	if(avgn[0] == 0.0f && avgn[1] == 0.0f && avgn[2] == 0.0f) {
+	if (is_zero_v3(avgn)) {
 		avgn[0] = 0.0f;
 		avgn[1] = 0.0f;
 		avgn[2] = 1.0f;
@@ -301,17 +296,8 @@
 	
 	for(i = 0; i < nverts; i++){
 		v1 = verts[i];
-		copy_v3_v3(temp, v1);
-		mag = 0.0;
-		mag += (temp[0] * avgn[0]);
-		mag += (temp[1] * avgn[1]);
-		mag += (temp[2] * avgn[2]);
-		
-		temp[0] = (avgn[0] * mag);
-		temp[1] = (avgn[1] * mag);
-		temp[2] = (avgn[2] * mag);
-
-		sub_v3_v3v3(v1, v1, temp);
+		mag = dot_v3v3(v1, avgn);
+		madd_v3_v3fl(v1, avgn, -mag);
 	}	
 }
 
@@ -433,20 +419,33 @@
 
 void BM_Vert_UpdateNormal(BMesh *bm, BMVert *v)
 {
-	BMIter iter;
-	BMFace *f;
+	BMIter eiter, liter;
+	BMEdge *e;
+	BMLoop *l;
+	float vec1[3], vec2[3], fac;
 	int len=0;
 
-	v->no[0] = v->no[1] = v->no[2] = 0.0f;
+	zero_v3(v->no);
 
-	f = BMIter_New(&iter, bm, BM_FACES_OF_VERT, v);
-	for (; f; f=BMIter_Step(&iter), len++) {
-		add_v3_v3v3(v->no, f->no, v->no);
+	BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, v) {
+		BM_ITER(l, &liter, bm, BM_LOOPS_OF_EDGE, e) {
+			if (l->v == v) {
+				/* Same calculation used in BM_Compute_Normals */
+				sub_v3_v3v3(vec1, l->v->co, l->prev->v->co);
+				sub_v3_v3v3(vec2, l->next->v->co, l->v->co);
+				normalize_v3(vec1);
+				normalize_v3(vec2);
+
+				fac = saacos(-dot_v3v3(vec1, vec2));
+				
+				madd_v3_v3fl(v->no, l->f->no, fac);
+			}
+		}
 	}
 
-	if (!len) return;
-
-	mul_v3_fl(v->no, 1.0f/(float)len);
+	if (len) {
+		normalize_v3(v->no);
+	}
 }
 
 void BM_Vert_UpdateAllNormals(BMesh *bm, BMVert *v)
@@ -455,7 +454,7 @@
 	BMFace *f;
 	int len=0;
 
-	v->no[0] = v->no[1] = v->no[2] = 0.0f;
+	zero_v3(v->no);
 
 	f = BMIter_New(&iter, bm, BM_FACES_OF_VERT, v);
 	for (; f; f=BMIter_Step(&iter), len++) {
@@ -500,9 +499,7 @@
 		normal_quad_v3( f->no,v1->co, v2->co, v3->co, v4->co);
 	}
 	else{ /*horrible, two sided face!*/
-		f->no[0] = 0.0;
-		f->no[1] = 0.0;
-		f->no[2] = 1.0;
+		zero_v3(f->no);
 	}
 
 }
@@ -518,7 +515,7 @@
 void BM_flip_normal(BMesh *bm, BMFace *f)
 {	
 	bmesh_loop_reverse(bm, f);
-	BM_Face_UpdateNormal(bm, f);
+	mul_v3_fl(f->no, -1.0f);
 }
 
 /* detects if two line segments cross each other (intersects).




More information about the Bf-blender-cvs mailing list