From 28a829893c702918afc5ac1945a06eaefa611594 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 16 Apr 2014 00:27:35 +1000 Subject: [PATCH] Math Lib: avoid having to pass a pre-calculated normal tot area_poly_v3 add normal_poly_v3 --- source/blender/blenkernel/BKE_mesh.h | 2 +- .../blender/blenkernel/intern/mesh_evaluate.c | 12 ++---- .../blender/blenkernel/intern/object_dupli.c | 2 +- source/blender/blenlib/BLI_math_geom.h | 3 +- source/blender/blenlib/intern/math_geom.c | 42 +++++++++++-------- source/blender/bmesh/intern/bmesh_polygon.c | 42 ++++--------------- source/blender/makesrna/intern/rna_mesh.c | 2 +- 7 files changed, 40 insertions(+), 65 deletions(-) diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index d6c3734fa2d..4b346b201ba 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -192,7 +192,7 @@ void BKE_mesh_calc_poly_center( struct MVert *mvarray, float cent[3]); float BKE_mesh_calc_poly_area( struct MPoly *mpoly, struct MLoop *loopstart, - struct MVert *mvarray, const float polynormal[3]); + struct MVert *mvarray); void BKE_mesh_calc_poly_angles( struct MPoly *mpoly, struct MLoop *loopstart, struct MVert *mvarray, float angles[]); diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c index edd0a8540e3..fe37b9222b6 100644 --- a/source/blender/blenkernel/intern/mesh_evaluate.c +++ b/source/blender/blenkernel/intern/mesh_evaluate.c @@ -872,7 +872,7 @@ void BKE_mesh_calc_poly_center(MPoly *mpoly, MLoop *loopstart, /* note, passing polynormal is only a speedup so we can skip calculating it */ float BKE_mesh_calc_poly_area(MPoly *mpoly, MLoop *loopstart, - MVert *mvarray, const float polynormal[3]) + MVert *mvarray) { if (mpoly->totloop == 3) { return area_tri_v3(mvarray[loopstart[0].v].co, @@ -890,22 +890,16 @@ float BKE_mesh_calc_poly_area(MPoly *mpoly, MLoop *loopstart, else { int i; MLoop *l_iter = loopstart; - float area, polynorm_local[3]; + float area; float (*vertexcos)[3] = BLI_array_alloca(vertexcos, (size_t)mpoly->totloop); - const float *no = polynormal ? polynormal : polynorm_local; /* pack vertex cos into an array for area_poly_v3 */ for (i = 0; i < mpoly->totloop; i++, l_iter++) { copy_v3_v3(vertexcos[i], mvarray[l_iter->v].co); } - /* need normal for area_poly_v3 as well */ - if (polynormal == NULL) { - BKE_mesh_calc_poly_normal(mpoly, loopstart, mvarray, polynorm_local); - } - /* finally calculate the area */ - area = area_poly_v3((const float (*)[3])vertexcos, (unsigned int)mpoly->totloop, no); + area = area_poly_v3((const float (*)[3])vertexcos, (unsigned int)mpoly->totloop); return area; } diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c index b3726ebc8da..786c283cd09 100644 --- a/source/blender/blenkernel/intern/object_dupli.c +++ b/source/blender/blenkernel/intern/object_dupli.c @@ -693,7 +693,7 @@ static void get_dupliface_transform(MPoly *mpoly, MLoop *mloop, MVert *mvert, } /* scale */ if (use_scale) { - float area = BKE_mesh_calc_poly_area(mpoly, mloop, mvert, f_no); + float area = BKE_mesh_calc_poly_area(mpoly, mloop, mvert); scale = sqrtf(area) * scale_fac; } else diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h index 7dcee518287..3c1b89fbd44 100644 --- a/source/blender/blenlib/BLI_math_geom.h +++ b/source/blender/blenlib/BLI_math_geom.h @@ -49,13 +49,14 @@ void cent_quad_v3(float r[3], const float a[3], const float b[3], const float c[ float normal_tri_v3(float r[3], const float a[3], const float b[3], const float c[3]); float normal_quad_v3(float r[3], const float a[3], const float b[3], const float c[3], const float d[3]); +float normal_poly_v3(float r[3], const float verts[][3], unsigned int nr); MINLINE float area_tri_v2(const float a[2], const float b[2], const float c[2]); MINLINE float area_tri_signed_v2(const float v1[2], const float v2[2], const float v3[2]); float area_tri_v3(const float a[3], const float b[3], const float c[3]); float area_tri_signed_v3(const float v1[3], const float v2[3], const float v3[3], const float normal[3]); float area_quad_v3(const float a[3], const float b[3], const float c[3], const float d[3]); -float area_poly_v3(const float verts[][3], unsigned int nr, const float normal[3]); +float area_poly_v3(const float verts[][3], unsigned int nr); float area_poly_v2(const float verts[][2], unsigned int nr); float cotangent_tri_weight_v3(const float v1[3], const float v2[3], const float v3[3]); diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index 01dbe01d152..45e8c425f64 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -88,6 +88,27 @@ float normal_quad_v3(float n[3], const float v1[3], const float v2[3], const flo return normalize_v3(n); } +/** + * Computes the normal of a planar + * polygon See Graphics Gems for + * computing newell normal. + */ +float normal_poly_v3(float n[3], const float verts[][3], unsigned int nr) +{ + float const *v_prev = verts[nr - 1]; + float const *v_curr = verts[0]; + unsigned int i; + + zero_v3(n); + + /* Newell's Method */ + for (i = 0; i < nr; v_prev = v_curr, v_curr = verts[++i]) { + add_newell_cross_v3_v3v3(n, v_prev, v_curr); + } + + return normalize_v3(n); +} + /* only convex Quadrilaterals */ float area_quad_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3]) { @@ -134,25 +155,10 @@ float area_tri_signed_v3(const float v1[3], const float v2[3], const float v3[3] return area; } -float area_poly_v3(const float verts[][3], unsigned int nr, const float normal[3]) +float area_poly_v3(const float verts[][3], unsigned int nr) { - unsigned int a; - int px, py; - const float max = axis_dominant_v3_max(&px, &py, normal); - float area; - const float *co_curr, *co_prev; - - /* The Trapezium Area Rule */ - co_prev = verts[nr - 1]; - co_curr = verts[0]; - area = 0.0f; - for (a = 0; a < nr; a++) { - area += (co_curr[px] - co_prev[px]) * (co_curr[py] + co_prev[py]); - co_prev = co_curr; - co_curr += 3; - } - - return fabsf(0.5f * area / max); + float n[3]; + return normal_poly_v3(n, verts, nr) * 0.5f; } float cross_poly_v2(const float verts[][2], unsigned int nr) diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index aff7d37abe9..17996176555 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -69,34 +69,10 @@ static bool testedgesidef(const float v1[2], const float v2[2], const float v3[2 return true; } -/** - * \brief COMPUTE POLY NORMAL - * - * Computes the normal of a planar - * polygon See Graphics Gems for - * computing newell normal. - */ -static void calc_poly_normal(float normal[3], float verts[][3], int nverts) -{ - float const *v_prev = verts[nverts - 1]; - float const *v_curr = verts[0]; - float n[3] = {0.0f}; - int i; - - /* Newell's Method */ - for (i = 0; i < nverts; v_prev = v_curr, v_curr = verts[++i]) { - add_newell_cross_v3_v3v3(n, v_prev, v_curr); - } - - if (UNLIKELY(normalize_v3_v3(normal, n) == 0.0f)) { - normal[2] = 1.0f; /* other axis set to 0.0 */ - } -} - /** * \brief COMPUTE POLY NORMAL (BMFace) * - * Same as #calc_poly_normal but operates directly on a bmesh face. + * Same as #normal_poly_v3 but operates directly on a bmesh face. */ static void bm_face_calc_poly_normal(const BMFace *f, float n[3]) { @@ -229,15 +205,15 @@ void BM_face_calc_tessellation(const BMFace *f, BMLoop **r_loops, unsigned int ( */ float BM_face_calc_area(BMFace *f) { - BMLoop *l; - BMIter iter; + BMLoop *l_iter, *l_first; float (*verts)[3] = BLI_array_alloca(verts, f->len); float area; - int i; + unsigned int i = 0; - BM_ITER_ELEM_INDEX (l, &iter, f, BM_LOOPS_OF_FACE, i) { - copy_v3_v3(verts[i], l->v->co); - } + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + copy_v3_v3(verts[i++], l_iter->v->co); + } while ((l_iter = l_iter->next) != l_first); if (f->len == 3) { area = area_tri_v3(verts[0], verts[1], verts[2]); @@ -246,9 +222,7 @@ float BM_face_calc_area(BMFace *f) area = area_quad_v3(verts[0], verts[1], verts[2], verts[3]); } else { - float normal[3]; - calc_poly_normal(normal, verts, f->len); - area = area_poly_v3((const float (*)[3])verts, f->len, normal); + area = area_poly_v3((const float (*)[3])verts, f->len); } return area; diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index 4190ce466ea..8c0f9980108 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -398,7 +398,7 @@ static float rna_MeshPolygon_area_get(PointerRNA *ptr) Mesh *me = (Mesh *)ptr->id.data; MPoly *mp = (MPoly *)ptr->data; - return BKE_mesh_calc_poly_area(mp, me->mloop + mp->loopstart, me->mvert, NULL); + return BKE_mesh_calc_poly_area(mp, me->mloop + mp->loopstart, me->mvert); } static void rna_MeshTessFace_normal_get(PointerRNA *ptr, float *values)