Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenlib/BLI_math_matrix.h1
-rw-r--r--source/blender/blenlib/intern/math_matrix.c7
-rw-r--r--source/blender/blenlib/intern/math_rotation.c2
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.c195
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.h2
-rw-r--r--source/blender/bmesh/tools/bmesh_triangulate.c15
6 files changed, 83 insertions, 139 deletions
diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h
index 415c503146c..c66536bc0e5 100644
--- a/source/blender/blenlib/BLI_math_matrix.h
+++ b/source/blender/blenlib/BLI_math_matrix.h
@@ -95,6 +95,7 @@ void mul_project_m4_v3(float M[4][4], float vec[3]);
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]);
diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c
index 8f9ea917b8c..b7e7fea897f 100644
--- a/source/blender/blenlib/intern/math_matrix.c
+++ b/source/blender/blenlib/intern/math_matrix.c
@@ -411,6 +411,13 @@ void mul_v3_m3v3(float r[3], float M[3][3], float a[3])
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];
diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c
index b38b5a2de10..e6399ed356e 100644
--- a/source/blender/blenlib/intern/math_rotation.c
+++ b/source/blender/blenlib/intern/math_rotation.c
@@ -84,6 +84,8 @@ void mul_qt_qtqt(float q[4], const float q1[4], const float q2[4])
* \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.
diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c
index b8b7abdbc76..af8ae5f9454 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.c
+++ b/source/blender/bmesh/intern/bmesh_polygon.c
@@ -297,39 +297,51 @@ static void scale_edge_v3f(float v1[3], float v2[3], const float fac)
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,16 +626,16 @@ bool BM_face_point_inside_test(BMFace *f, const float co[3])
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];
- int i;
- copy_v3_v3(v1, projectverts[v1i]);
- copy_v3_v3(v2, projectverts[v2i]);
- copy_v3_v3(v3, projectverts[v3i]);
+ float pv1[2];
+ const float *v1 = projectverts[v1i];
+ const float *v2 = projectverts[v2i];
+ const float *v3 = projectverts[v3i];
+ int i;
/* 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)) {
@@ -633,7 +645,7 @@ static bool bm_face_goodline(float const (*projectverts)[3], BMFace *f, int v1i,
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 @@ static bool bm_face_goodline(float const (*projectverts)[3], BMFace *f, int v1i,
* \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 @@ static BMLoop *find_ear(BMFace *f, float (*verts)[3], const bool use_beauty, flo
/* 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 @@ static BMLoop *find_ear(BMFace *f, float (*verts)[3], const bool use_beauty, flo
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 @@ static BMLoop *find_ear(BMFace *f, float (*verts)[3], const bool use_beauty, flo
}
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 @@ static BMLoop *find_ear(BMFace *f, float (*verts)[3], const bool use_beauty, flo
* 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 @@ void BM_face_triangulate(BMesh *bm, BMFace *f,
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);
-
- 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);
-
- 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
+/* 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;
}
- }
- BLI_assert(f->len == 3);
+ copy_v3_v3(f->no, l_iter->f->no);
-#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 (use_tag) {
+ BM_elem_flag_enable(l_new->e, BM_ELEM_TAG);
+ BM_elem_flag_enable(f, BM_ELEM_TAG);
+ }
- if (newfaces) newfaces[nf_i++] = f;
-
- BMO_elem_flag_enable(bm, newl->e, newedge_oflag);
- BMO_elem_flag_enable(bm, f, newface_oflag);
- l_iter = nextloop;
+ if (r_faces_new) {
+ r_faces_new[nf_i++] = f;
}
}
-#endif
- /* NULL-terminate */
- if (newfaces) {
- newfaces[nf_i] = NULL;
- }
+ BLI_assert(f->len == 3);
}
/**
diff --git a/source/blender/bmesh/intern/bmesh_polygon.h b/source/blender/bmesh/intern/bmesh_polygon.h
index 7c2b1782584..601caae2337 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.h
+++ b/source/blender/bmesh/intern/bmesh_polygon.h
@@ -44,7 +44,7 @@ void BM_vert_normal_update_all(BMVert *v);
void BM_face_normal_flip(BMesh *bm, BMFace *f);
bool BM_face_point_inside_test(BMFace *f, const float co[3]);
-void BM_face_triangulate(BMesh *bm, BMFace *f, float (*projectverts)[3], BMFace **newfaces,
+void BM_face_triangulate(BMesh *bm, BMFace *f, BMFace **newfaces,
const bool use_beauty, const bool use_tag);
void BM_face_legal_splits(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len);
diff --git a/source/blender/bmesh/tools/bmesh_triangulate.c b/source/blender/bmesh/tools/bmesh_triangulate.c
index 7e6e41a12e6..9948a15ea56 100644
--- a/source/blender/bmesh/tools/bmesh_triangulate.c
+++ b/source/blender/bmesh/tools/bmesh_triangulate.c
@@ -30,7 +30,6 @@
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
-#include "BLI_array.h"
#include "bmesh.h"
@@ -40,27 +39,17 @@ void BM_mesh_triangulate(BMesh *bm, const bool use_beauty, const bool tag_only)
{
BMIter iter;
BMFace *face;
- float (*projectverts)[3] = NULL;
- BLI_array_declare(projectverts);
if (tag_only == false) {
BM_ITER_MESH (face, &iter, bm, BM_FACES_OF_MESH) {
- BLI_array_empty(projectverts);
- BLI_array_reserve(projectverts, face->len * 3);
-
- BM_face_triangulate(bm, face, projectverts, NULL, use_beauty, false);
+ BM_face_triangulate(bm, face, NULL, use_beauty, false);
}
}
else {
BM_ITER_MESH (face, &iter, bm, BM_FACES_OF_MESH) {
if (BM_elem_flag_test(face, BM_ELEM_TAG)) {
- BLI_array_empty(projectverts);
- BLI_array_grow_items(projectverts, face->len * 3);
-
- BM_face_triangulate(bm, face, projectverts, NULL, use_beauty, true);
+ BM_face_triangulate(bm, face, NULL, use_beauty, true);
}
}
}
-
- BLI_array_free(projectverts);
}