[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