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:
Diffstat (limited to 'source/blender/bmesh/intern/bmesh_queries.c')
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.c474
1 files changed, 345 insertions, 129 deletions
diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c
index 633c715f257..26b0e42a1c1 100644
--- a/source/blender/bmesh/intern/bmesh_queries.c
+++ b/source/blender/bmesh/intern/bmesh_queries.c
@@ -43,7 +43,7 @@
* Returns whether or not a given vertex is
* is part of a given edge.
*/
-int BM_vert_in_edge(BMEdge *e, BMVert *v)
+bool BM_vert_in_edge(BMEdge *e, BMVert *v)
{
return bmesh_vert_in_edge(e, v);
}
@@ -208,9 +208,9 @@ BMLoop *BM_vert_find_first_loop(BMVert *v)
}
/**
- * Returns TRUE if the vertex is used in a given face.
+ * Returns true if the vertex is used in a given face.
*/
-int BM_vert_in_face(BMFace *f, BMVert *v)
+bool BM_vert_in_face(BMFace *f, BMVert *v)
{
BMLoop *l_iter, *l_first;
@@ -226,19 +226,19 @@ int BM_vert_in_face(BMFace *f, BMVert *v)
#endif
do {
if (l_iter->v == v) {
- return TRUE;
+ return true;
}
} while ((l_iter = l_iter->next) != l_first);
}
- return FALSE;
+ return false;
}
/**
* Compares the number of vertices in an array
* that appear in a given face
*/
-int BM_verts_in_face(BMFace *f, BMVert **varr, int len)
+int BM_verts_in_face_count(BMFace *f, BMVert **varr, int len)
{
BMLoop *l_iter, *l_first;
@@ -278,10 +278,64 @@ int BM_verts_in_face(BMFace *f, BMVert **varr, int len)
return count;
}
+
+/**
+ * Return true if all verts are in the face.
+ */
+bool BM_verts_in_face(BMFace *f, BMVert **varr, int len)
+{
+ BMLoop *l_iter, *l_first;
+
+#ifdef USE_BMESH_HOLES
+ BMLoopList *lst;
+#endif
+
+ int i;
+ bool ok = true;
+
+ /* simple check, we know can't succeed */
+ if (f->len < len) {
+ return false;
+ }
+
+ for (i = 0; i < len; i++) {
+ BM_ELEM_API_FLAG_ENABLE(varr[i], _FLAG_OVERLAP);
+ }
+
+#ifdef USE_BMESH_HOLES
+ for (lst = f->loops.first; lst; lst = lst->next)
+#endif
+ {
+
+#ifdef USE_BMESH_HOLES
+ l_iter = l_first = lst->first;
+#else
+ l_iter = l_first = f->l_first;
+#endif
+
+ do {
+ if (BM_ELEM_API_FLAG_TEST(l_iter->v, _FLAG_OVERLAP)) {
+ /* pass */
+ }
+ else {
+ ok = false;
+ break;
+ }
+
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+
+ for (i = 0; i < len; i++) {
+ BM_ELEM_API_FLAG_DISABLE(varr[i], _FLAG_OVERLAP);
+ }
+
+ return ok;
+}
+
/**
* Returns whether or not a given edge is is part of a given face.
*/
-int BM_edge_in_face(BMFace *f, BMEdge *e)
+bool BM_edge_in_face(BMFace *f, BMEdge *e)
{
BMLoop *l_iter;
BMLoop *l_first;
@@ -290,17 +344,17 @@ int BM_edge_in_face(BMFace *f, BMEdge *e)
do {
if (l_iter->e == e) {
- return TRUE;
+ return true;
}
} while ((l_iter = l_iter->next) != l_first);
- return FALSE;
+ return false;
}
/**
* Returns whether or not a given edge is is part of a given loop.
*/
-int BM_edge_in_loop(BMEdge *e, BMLoop *l)
+bool BM_edge_in_loop(BMEdge *e, BMLoop *l)
{
return (l->e == e || l->prev->e == e);
}
@@ -309,7 +363,7 @@ int BM_edge_in_loop(BMEdge *e, BMLoop *l)
* Returns whether or not two vertices are in
* a given edge
*/
-int BM_verts_in_edge(BMVert *v1, BMVert *v2, BMEdge *e)
+bool BM_verts_in_edge(BMVert *v1, BMVert *v2, BMEdge *e)
{
return bmesh_verts_in_edge(v1, v2, e);
}
@@ -418,7 +472,7 @@ BMLoop *BM_vert_step_fan_loop(BMLoop *l, BMEdge **e_step)
* The function takes a vertex at the center of a fan and returns the opposite edge in the fan.
* All edges in the fan must be manifold, otherwise return NULL.
*
- * \note This could (probably) be done more effieiently.
+ * \note This could (probably) be done more efficiently.
*/
BMEdge *BM_vert_other_disk_edge(BMVert *v, BMEdge *e_first)
{
@@ -468,7 +522,7 @@ BMEdge *BM_vert_other_disk_edge(BMVert *v, BMEdge *e_first)
}
/**
- * Returms edge length
+ * Returns edge length
*/
float BM_edge_calc_length(BMEdge *e)
{
@@ -476,12 +530,20 @@ float BM_edge_calc_length(BMEdge *e)
}
/**
+ * Returns edge length squared (for comparisons)
+ */
+float BM_edge_calc_length_squared(BMEdge *e)
+{
+ return len_squared_v3v3(e->v1->co, e->v2->co);
+}
+
+/**
* Utility function, since enough times we have an edge
* and want to access 2 connected faces.
*
- * \return TRUE when only 2 faces are found.
+ * \return true when only 2 faces are found.
*/
-int BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb)
+bool BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb)
{
BMLoop *la, *lb;
@@ -492,12 +554,12 @@ int BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb)
{
*r_fa = la->f;
*r_fb = lb->f;
- return TRUE;
+ return true;
}
else {
*r_fa = NULL;
*r_fb = NULL;
- return FALSE;
+ return false;
}
}
@@ -505,9 +567,9 @@ int BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb)
* Utility function, since enough times we have an edge
* and want to access 2 connected loops.
*
- * \return TRUE when only 2 faces are found.
+ * \return true when only 2 faces are found.
*/
-int BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb)
+bool BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb)
{
BMLoop *la, *lb;
@@ -518,12 +580,12 @@ int BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb)
{
*r_la = la;
*r_lb = lb;
- return TRUE;
+ return true;
}
else {
*r_la = NULL;
*r_lb = NULL;
- return FALSE;
+ return false;
}
}
@@ -581,7 +643,7 @@ int BM_vert_face_count(BMVert *v)
* Tests whether or not the vertex is part of a wire edge.
* (ie: has no faces attached to it)
*/
-int BM_vert_is_wire(BMVert *v)
+bool BM_vert_is_wire(BMVert *v)
{
if (v->e) {
BMEdge *e_first, *e_iter;
@@ -589,14 +651,14 @@ int BM_vert_is_wire(BMVert *v)
e_first = e_iter = v->e;
do {
if (e_iter->l) {
- return FALSE;
+ return false;
}
} while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
- return TRUE;
+ return true;
}
else {
- return FALSE;
+ return false;
}
}
@@ -604,9 +666,9 @@ int BM_vert_is_wire(BMVert *v)
* Tests whether or not the edge is part of a wire.
* (ie: has no faces attached to it)
*/
-int BM_edge_is_wire(BMEdge *e)
+bool BM_edge_is_wire(BMEdge *e)
{
- return (e->l) ? FALSE : TRUE;
+ return (e->l == NULL);
}
/**
@@ -616,36 +678,36 @@ int BM_edge_is_wire(BMEdge *e)
* 3: Is part of a an edge with more than 2 faces.
* 4: Is part of a wire edge.
*/
-int BM_vert_is_manifold(BMVert *v)
+bool BM_vert_is_manifold(BMVert *v)
{
- BMEdge *e, *oe;
+ BMEdge *e, *e_old;
BMLoop *l;
int len, count, flag;
if (v->e == NULL) {
/* loose vert */
- return FALSE;
+ return false;
}
/* count edges while looking for non-manifold edges */
len = 0;
- oe = e = v->e;
+ e_old = e = v->e;
do {
/* loose edge or edge shared by more than two faces,
* edges with 1 face user are OK, otherwise we could
* use BM_edge_is_manifold() here */
if (e->l == NULL || bmesh_radial_length(e->l) > 2) {
- return FALSE;
+ return false;
}
len++;
- } while ((e = bmesh_disk_edge_next(e, v)) != oe);
+ } while ((e = bmesh_disk_edge_next(e, v)) != e_old);
count = 1;
flag = 1;
e = NULL;
- oe = v->e;
- l = oe->l;
- while (e != oe) {
+ e_old = v->e;
+ l = e_old->l;
+ while (e != e_old) {
l = (l->v == v) ? l->prev : l->next;
e = l->e;
count++; /* count the edges */
@@ -654,13 +716,13 @@ int BM_vert_is_manifold(BMVert *v)
/* we've hit the edge of an open mesh, reset once */
flag = 0;
count = 1;
- oe = e;
+ e_old = e;
e = NULL;
- l = oe->l;
+ l = e_old->l;
}
else if (l->radial_next == l) {
/* break the loop */
- e = oe;
+ e = e_old;
}
else {
l = l->radial_next;
@@ -669,10 +731,10 @@ int BM_vert_is_manifold(BMVert *v)
if (count < len) {
/* vert shared by multiple regions */
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
/**
@@ -681,7 +743,7 @@ int BM_vert_is_manifold(BMVert *v)
*/
#if 1 /* fast path for checking manifold */
-int BM_edge_is_manifold(BMEdge *e)
+bool BM_edge_is_manifold(BMEdge *e)
{
const BMLoop *l = e->l;
return (l && (l->radial_next != l) && /* not 0 or 1 face users */
@@ -692,21 +754,34 @@ int BM_edge_is_manifold(BMEdge *e)
{
int count = BM_edge_face_count(e);
if (count == 2) {
- return TRUE;
+ return true;
}
else {
- return FALSE;
+ return false;
}
}
#endif
/**
+ * Tests that the edge is manifold and
+ * that both its faces point the same way.
+ */
+bool BM_edge_is_contiguous(BMEdge *e)
+{
+ const BMLoop *l = e->l;
+ const BMLoop *l_other;
+ return (l && ((l_other = l->radial_next) != l) && /* not 0 or 1 face users */
+ (l_other->radial_next == l) && /* 2 face users */
+ (l_other->v != l->v));
+}
+
+/**
* Tests whether or not an edge is on the boundary
* of a shell (has one face associated with it)
*/
#if 1 /* fast path for checking boundary */
-int BM_edge_is_boundary(BMEdge *e)
+bool BM_edge_is_boundary(BMEdge *e)
{
const BMLoop *l = e->l;
return (l && (l->radial_next == l));
@@ -716,10 +791,10 @@ int BM_edge_is_boundary(BMEdge *e)
{
int count = BM_edge_face_count(e);
if (count == 1) {
- return TRUE;
+ return true;
}
else {
- return FALSE;
+ return false;
}
}
#endif
@@ -749,7 +824,7 @@ int BM_face_share_face_count(BMFace *f1, BMFace *f2)
/**
* same as #BM_face_share_face_count but returns a bool
*/
-int BM_face_share_face_check(BMFace *f1, BMFace *f2)
+bool BM_face_share_face_check(BMFace *f1, BMFace *f2)
{
BMIter iter1, iter2;
BMEdge *e;
@@ -758,11 +833,11 @@ int BM_face_share_face_check(BMFace *f1, BMFace *f2)
BM_ITER_ELEM (e, &iter1, f1, BM_EDGES_OF_FACE) {
BM_ITER_ELEM (f, &iter2, e, BM_FACES_OF_EDGE) {
if (f != f1 && f != f2 && BM_face_share_edge_check(f, f2))
- return TRUE;
+ return true;
}
}
- return FALSE;
+ return false;
}
/**
@@ -785,9 +860,9 @@ int BM_face_share_edge_count(BMFace *f1, BMFace *f2)
}
/**
- * Returns TRUE if the faces share an edge
+ * Returns true if the faces share an edge
*/
-int BM_face_share_edge_check(BMFace *f1, BMFace *f2)
+bool BM_face_share_edge_check(BMFace *f1, BMFace *f2)
{
BMLoop *l_iter;
BMLoop *l_first;
@@ -795,17 +870,17 @@ int BM_face_share_edge_check(BMFace *f1, BMFace *f2)
l_iter = l_first = BM_FACE_FIRST_LOOP(f1);
do {
if (bmesh_radial_face_find(l_iter->e, f2)) {
- return TRUE;
+ return true;
}
} while ((l_iter = l_iter->next) != l_first);
- return FALSE;
+ return false;
}
/**
- * Test if e1 shares any faces with e2
+ * Test if e1 shares any faces with e2
*/
-int BM_edge_share_face_check(BMEdge *e1, BMEdge *e2)
+bool BM_edge_share_face_check(BMEdge *e1, BMEdge *e2)
{
BMLoop *l;
BMFace *f;
@@ -815,18 +890,18 @@ int BM_edge_share_face_check(BMEdge *e1, BMEdge *e2)
do {
f = l->f;
if (bmesh_radial_face_find(e2, f)) {
- return TRUE;
+ return true;
}
l = l->radial_next;
} while (l != e1->l);
}
- return FALSE;
+ return false;
}
/**
* Test if e1 shares any quad faces with e2
*/
-int BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2)
+bool BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2)
{
BMLoop *l;
BMFace *f;
@@ -837,19 +912,19 @@ int BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2)
f = l->f;
if (f->len == 4) {
if (bmesh_radial_face_find(e2, f)) {
- return TRUE;
+ return true;
}
}
l = l->radial_next;
} while (l != e1->l);
}
- return FALSE;
+ return false;
}
/**
* Tests to see if e1 shares a vertex with e2
*/
-int BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2)
+bool BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2)
{
return (e1->v1 == e2->v1 ||
e1->v1 == e2->v2 ||
@@ -945,6 +1020,22 @@ void BM_edge_ordered_verts(BMEdge *edge, BMVert **r_v1, BMVert **r_v2)
}
/**
+ * Check if the loop is convex or concave
+ * (depends on face normal)
+ */
+bool BM_loop_is_convex(BMLoop *l)
+{
+ float e_dir_prev[3];
+ float e_dir_next[3];
+ float l_no[3];
+
+ sub_v3_v3v3(e_dir_prev, l->prev->v->co, l->v->co);
+ sub_v3_v3v3(e_dir_next, l->next->v->co, l->v->co);
+ cross_v3_v3v3(l_no, e_dir_next, e_dir_prev);
+ return dot_v3v3(l_no, l->f->no) > 0.0f;
+}
+
+/**
* Calculates the angle between the previous and next loops
* (angle at this loops face corner).
*
@@ -972,7 +1063,7 @@ void BM_loop_calc_face_normal(BMLoop *l, float r_normal[3])
l->v->co,
l->next->v->co) != 0.0f)
{
- return;
+ /* pass */
}
else {
copy_v3_v3(r_normal, l->f->no);
@@ -980,6 +1071,29 @@ void BM_loop_calc_face_normal(BMLoop *l, float r_normal[3])
}
/**
+ * \brief BM_loop_calc_face_direction
+ *
+ * Calculate the direction a loop is pointing.
+ *
+ * \param l The loop to calculate the direction at
+ * \param r_dir Resulting direction
+ */
+void BM_loop_calc_face_direction(BMLoop *l, float r_dir[3])
+{
+ float v_prev[3];
+ float v_next[3];
+
+ sub_v3_v3v3(v_prev, l->v->co, l->prev->v->co);
+ sub_v3_v3v3(v_next, l->next->v->co, l->v->co);
+
+ normalize_v3(v_prev);
+ normalize_v3(v_next);
+
+ add_v3_v3v3(r_dir, v_prev, v_next);
+ normalize_v3(r_dir);
+}
+
+/**
* \brief BM_loop_calc_face_tangent
*
* Calculate the tangent at this loop corner or fallback to the face normal on straight lines.
@@ -992,23 +1106,27 @@ void BM_loop_calc_face_tangent(BMLoop *l, float r_tangent[3])
{
float v_prev[3];
float v_next[3];
+ float dir[3];
sub_v3_v3v3(v_prev, l->prev->v->co, l->v->co);
sub_v3_v3v3(v_next, l->v->co, l->next->v->co);
normalize_v3(v_prev);
normalize_v3(v_next);
+ add_v3_v3v3(dir, v_prev, v_next);
- if (compare_v3v3(v_prev, v_next, FLT_EPSILON) == FALSE) {
- float dir[3];
+ if (compare_v3v3(v_prev, v_next, FLT_EPSILON * 10.0f) == false) {
float nor[3]; /* for this purpose doesn't need to be normalized */
- add_v3_v3v3(dir, v_prev, v_next);
cross_v3_v3v3(nor, v_prev, v_next);
+ /* concave face check */
+ if (UNLIKELY(dot_v3v3(nor, l->f->no) < 0.0f)) {
+ negate_v3(nor);
+ }
cross_v3_v3v3(r_tangent, dir, nor);
}
else {
/* prev/next are the same - compare with face normal since we don't have one */
- cross_v3_v3v3(r_tangent, v_next, l->f->no);
+ cross_v3_v3v3(r_tangent, dir, l->f->no);
}
normalize_v3(r_tangent);
@@ -1113,6 +1231,40 @@ float BM_vert_calc_shell_factor(BMVert *v)
return 1.0f;
}
}
+/* alternate version of #BM_vert_calc_shell_factor which only
+ * uses 'hflag' faces, but falls back to all if none found. */
+float BM_vert_calc_shell_factor_ex(BMVert *v, const char hflag)
+{
+ BMIter iter;
+ BMLoop *l;
+ float accum_shell = 0.0f;
+ float accum_angle = 0.0f;
+ int tot_sel = 0, tot = 0;
+
+ BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
+ if (BM_elem_flag_test(l->f, hflag)) { /* <-- main difference to BM_vert_calc_shell_factor! */
+ const float face_angle = BM_loop_calc_face_angle(l);
+ accum_shell += shell_angle_to_dist(angle_normalized_v3v3(v->no, l->f->no)) * face_angle;
+ accum_angle += face_angle;
+ tot_sel++;
+ }
+ tot++;
+ }
+
+ if (accum_angle != 0.0f) {
+ return accum_shell / accum_angle;
+ }
+ else {
+ /* other main difference from BM_vert_calc_shell_factor! */
+ if (tot != 0 && tot_sel == 0) {
+ /* none selected, so use all */
+ return BM_vert_calc_shell_factor(v);
+ }
+ else {
+ return 1.0f;
+ }
+ }
+}
/**
* \note quite an obscure function.
@@ -1200,6 +1352,8 @@ BMEdge *BM_edge_exists(BMVert *v1, BMVert *v2)
BMIter iter;
BMEdge *e;
+ BLI_assert(v1 != v2);
+
BM_ITER_ELEM (e, &iter, v1, BM_EDGES_OF_VERT) {
if (e->v1 == v2 || e->v2 == v2)
return e;
@@ -1231,67 +1385,94 @@ BMEdge *BM_edge_find_double(BMEdge *e)
}
/**
- * Given a set of vertices \a varr, find out if
- * all those vertices overlap an existing face.
- *
- * \note Making a face here is valid but in some cases you wont want to
- * make a face thats part of another.
- *
- * \returns TRUE for overlap
+ * Given a set of vertices (varr), find out if
+ * there is a face with exactly those vertices
+ * (and only those vertices).
*
+ * \note there used to be a BM_face_exists_overlap function that checked for partial overlap,
+ * however this is no longer used, simple to add back.
*/
-int BM_face_exists_overlap(BMVert **varr, int len, BMFace **r_overlapface)
+bool BM_face_exists(BMVert **varr, int len, BMFace **r_existface)
{
+ BMVert *v_search = varr[0]; /* we can search any of the verts in the array */
BMIter viter;
BMFace *f;
- int i, amount;
- for (i = 0; i < len; i++) {
- BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) {
- amount = BM_verts_in_face(f, varr, len);
- if (amount >= len) {
- if (r_overlapface) {
- *r_overlapface = f;
+
+#if 0
+ BM_ITER_ELEM (f, &viter, v_search, BM_FACES_OF_VERT) {
+ if (f->len == len) {
+ if (BM_verts_in_face(f, varr, len)) {
+ if (r_existface) {
+ *r_existface = f;
}
- return TRUE;
+ return true;
}
}
}
- if (r_overlapface) {
- *r_overlapface = NULL;
+ if (r_existface) {
+ *r_existface = NULL;
}
+ return false;
- return FALSE;
-}
+#else
-/**
- * Given a set of vertices (varr), find out if
- * there is a face with exactly those vertices
- * (and only those vertices).
- */
-int BM_face_exists(BMVert **varr, int len, BMFace **r_existface)
-{
- BMIter viter;
- BMFace *f;
- int i, amount;
+ /* faster to do the flagging once, and inline */
+ bool is_init = false;
+ bool is_found = false;
+ int i;
- for (i = 0; i < len; i++) {
- BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) {
- amount = BM_verts_in_face(f, varr, len);
- if (amount == len && amount == f->len) {
+
+ BM_ITER_ELEM (f, &viter, v_search, BM_FACES_OF_VERT) {
+ if (f->len == len) {
+ if (is_init == false) {
+ is_init = true;
+ for (i = 0; i < len; i++) {
+ BLI_assert(!BM_ELEM_API_FLAG_TEST(varr[i], _FLAG_OVERLAP));
+ BM_ELEM_API_FLAG_ENABLE(varr[i], _FLAG_OVERLAP);
+ }
+ }
+
+ is_found = true;
+
+ {
+ BMLoop *l_iter;
+ BMLoop *l_first;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+
+ do {
+ if (!BM_ELEM_API_FLAG_TEST(l_iter->v, _FLAG_OVERLAP)) {
+ is_found = false;
+ break;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+
+ if (is_found) {
if (r_existface) {
*r_existface = f;
}
- return TRUE;
+ break;
}
}
}
- if (r_existface) {
- *r_existface = NULL;
+ if (is_found == false) {
+ if (r_existface) {
+ *r_existface = NULL;
+ }
}
- return FALSE;
+
+ if (is_init == true) {
+ for (i = 0; i < len; i++) {
+ BM_ELEM_API_FLAG_DISABLE(varr[i], _FLAG_OVERLAP);
+ }
+ }
+
+ return is_found;
+#endif
}
@@ -1307,12 +1488,12 @@ int BM_face_exists(BMVert **varr, int len, BMFace **r_existface)
*
* \a earr and \a varr can be in any order, however they _must_ form a closed loop.
*/
-int BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len)
+bool BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len)
{
BMFace *f;
BMEdge *e;
BMVert *v;
- int ok;
+ bool ok;
int tot_tag;
BMIter fiter;
@@ -1352,10 +1533,10 @@ int BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len)
for (i = 0; i < len; i++) {
BM_ITER_ELEM (f, &fiter, earr[i], BM_FACES_OF_EDGE) {
if (!BM_elem_flag_test(f, BM_ELEM_INTERNAL_TAG)) {
- ok = TRUE;
+ ok = true;
BM_ITER_ELEM (v, &viter, f, BM_VERTS_OF_FACE) {
if (!BM_elem_flag_test(v, BM_ELEM_INTERNAL_TAG)) {
- ok = FALSE;
+ ok = false;
break;
}
}
@@ -1374,20 +1555,20 @@ int BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len)
if (tot_tag == 0) {
/* no faces use only boundary verts, quit early */
- return FALSE;
+ return false;
}
/* 2) loop over non-boundary edges that use boundary verts,
* check each have 2 tagges faces connected (faces that only use 'varr' verts) */
- ok = TRUE;
+ ok = true;
for (i = 0; i < len; i++) {
BM_ITER_ELEM (e, &fiter, varr[i], BM_EDGES_OF_VERT) {
if (/* non-boundary edge */
- BM_elem_flag_test(e, BM_ELEM_INTERNAL_TAG) == FALSE &&
+ BM_elem_flag_test(e, BM_ELEM_INTERNAL_TAG) == false &&
/* ...using boundary verts */
- BM_elem_flag_test(e->v1, BM_ELEM_INTERNAL_TAG) == TRUE &&
- BM_elem_flag_test(e->v2, BM_ELEM_INTERNAL_TAG) == TRUE)
+ BM_elem_flag_test(e->v1, BM_ELEM_INTERNAL_TAG) == true &&
+ BM_elem_flag_test(e->v2, BM_ELEM_INTERNAL_TAG) == true)
{
int tot_face_tag = 0;
BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) {
@@ -1397,14 +1578,14 @@ int BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len)
}
if (tot_face_tag != 2) {
- ok = FALSE;
+ ok = false;
break;
}
}
}
- if (ok == FALSE) {
+ if (ok == false) {
break;
}
}
@@ -1413,25 +1594,25 @@ int BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len)
}
/* same as 'BM_face_exists_multi' but built vert array from edges */
-int BM_face_exists_multi_edge(BMEdge **earr, int len)
+bool BM_face_exists_multi_edge(BMEdge **earr, int len)
{
BMVert **varr = BLI_array_alloca(varr, len);
- int ok;
+ bool ok;
int i, i_next;
/* first check if verts have edges, if not we can bail out early */
- ok = TRUE;
+ ok = true;
for (i = len - 1, i_next = 0; i_next < len; (i = i_next++)) {
if (!(varr[i] = BM_edge_share_vert(earr[i], earr[i_next]))) {
- ok = FALSE;
+ ok = false;
break;
}
}
- if (ok == FALSE) {
+ if (ok == false) {
BMESH_ASSERT(0);
- return FALSE;
+ return false;
}
ok = BM_face_exists_multi(varr, earr, len);
@@ -1440,13 +1621,13 @@ int BM_face_exists_multi_edge(BMEdge **earr, int len)
}
/* convenience functions for checking flags */
-int BM_edge_is_any_vert_flag_test(BMEdge *e, const char hflag)
+bool BM_edge_is_any_vert_flag_test(BMEdge *e, const char hflag)
{
return (BM_elem_flag_test(e->v1, hflag) ||
BM_elem_flag_test(e->v2, hflag));
}
-int BM_face_is_any_vert_flag_test(BMFace *f, const char hflag)
+bool BM_face_is_any_vert_flag_test(BMFace *f, const char hflag)
{
BMLoop *l_iter;
BMLoop *l_first;
@@ -1454,13 +1635,13 @@ int BM_face_is_any_vert_flag_test(BMFace *f, const char hflag)
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
if (BM_elem_flag_test(l_iter->v, hflag)) {
- return TRUE;
+ return true;
}
} while ((l_iter = l_iter->next) != l_first);
- return FALSE;
+ return false;
}
-int BM_face_is_any_edge_flag_test(BMFace *f, const char hflag)
+bool BM_face_is_any_edge_flag_test(BMFace *f, const char hflag)
{
BMLoop *l_iter;
BMLoop *l_first;
@@ -1468,8 +1649,43 @@ int BM_face_is_any_edge_flag_test(BMFace *f, const char hflag)
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
if (BM_elem_flag_test(l_iter->e, hflag)) {
- return TRUE;
+ return true;
}
} while ((l_iter = l_iter->next) != l_first);
- return FALSE;
+ return false;
+}
+
+static void bm_mesh_calc_volume_face(BMFace *f, float *r_vol)
+{
+ int tottri = f->len - 2;
+ BMLoop **loops = BLI_array_alloca(loops, f->len);
+ int (*index)[3] = BLI_array_alloca(index, tottri);
+ int j;
+
+ tottri = BM_face_calc_tessellation(f, loops, index);
+ BLI_assert(tottri <= f->len - 2);
+
+ for (j = 0; j < tottri; j++) {
+ const float *p1 = loops[index[j][0]]->v->co;
+ const float *p2 = loops[index[j][1]]->v->co;
+ const float *p3 = loops[index[j][2]]->v->co;
+
+ /* co1.dot(co2.cross(co3)) / 6.0 */
+ float cross[3];
+ cross_v3_v3v3(cross, p2, p3);
+ *r_vol += (1.0f / 6.0f) * dot_v3v3(p1, cross);
+ }
+}
+float BM_mesh_calc_volume(BMesh *bm)
+{
+ /* warning, calls own tessellation function, may be slow */
+ float vol = 0.0f;
+ BMFace *f;
+ BMIter fiter;
+
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ bm_mesh_calc_volume_face(f, &vol);
+ }
+
+ return fabsf(vol);
}