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_construct.c')
-rw-r--r--source/blender/bmesh/intern/bmesh_construct.c288
1 files changed, 144 insertions, 144 deletions
diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c
index e0348fea636..7664108f348 100644
--- a/source/blender/bmesh/intern/bmesh_construct.c
+++ b/source/blender/bmesh/intern/bmesh_construct.c
@@ -46,9 +46,41 @@
#define SELECT 1
+/**
+ * Fill in an edge array from a vertex array (connected polygon loop).
+ *
+ * \returns false if any edges aren't found .
+ */
+bool BM_edges_from_verts(BMEdge **edge_arr, BMVert **vert_arr, const int len)
+{
+ int i, i_prev = len - 1;
+ for (i = 0; i < len; i++) {
+ edge_arr[i_prev] = BM_edge_exists(vert_arr[i_prev], vert_arr[i]);
+ if (edge_arr[i_prev] == NULL) {
+ return false;
+ }
+ i_prev = i;
+ }
+ return true;
+}
+
+/**
+ * Fill in an edge array from a vertex array (connected polygon loop).
+ * Creating edges as-needed.
+ */
+void BM_edges_from_verts_ensure(BMesh *bm, BMEdge **edge_arr, BMVert **vert_arr, const int len)
+{
+ int i, i_prev = len - 1;
+ for (i = 0; i < len; i++) {
+ edge_arr[i_prev] = BM_edge_create(bm, vert_arr[i_prev], vert_arr[i], NULL, BM_CREATE_NO_DOUBLE);
+ i_prev = i;
+ }
+}
+
/* prototypes */
-static void bm_loop_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
- const BMLoop *source_loop, BMLoop *target_loop);
+static void bm_loop_attrs_copy(
+ BMesh *source_mesh, BMesh *target_mesh,
+ const BMLoop *source_loop, BMLoop *target_loop);
/**
* \brief Make Quad/Triangle
@@ -64,9 +96,10 @@ static void bm_loop_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
* of the vertices in the vertex array.
*/
-BMFace *BM_face_create_quad_tri(BMesh *bm,
- BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
- const BMFace *f_example, const eBMCreateFlag create_flag)
+BMFace *BM_face_create_quad_tri(
+ BMesh *bm,
+ BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
+ const BMFace *f_example, const eBMCreateFlag create_flag)
{
BMVert *vtar[4] = {v1, v2, v3, v4};
return BM_face_create_verts(bm, vtar, v4 ? 4 : 3, f_example, create_flag, true);
@@ -81,8 +114,9 @@ BMFace *BM_face_create_quad_tri(BMesh *bm,
* this is done since the face may not be completely surrounded by faces,
* this way: a quad with 2 connected quads on either side will still get all 4 loops updated
*/
-void BM_face_copy_shared(BMesh *bm, BMFace *f,
- BMElemFilterFunc filter_fn, void *user_data)
+void BM_face_copy_shared(
+ BMesh *bm, BMFace *f,
+ BMElemFilterFunc filter_fn, void *user_data)
{
BMLoop *l_first;
BMLoop *l_iter;
@@ -132,155 +166,113 @@ void BM_face_copy_shared(BMesh *bm, BMFace *f,
}
/**
- * \brief Make NGon
+ * Given an array of edges,
+ * order them using the winding defined by \a v1 & \a v2
+ * into \a edges_sort & \a verts_sort.
*
- * Makes an ngon from an unordered list of edges. \a v1 and \a v2
- * must be the verts defining edges[0],
- * and define the winding of the new face.
- *
- * \a edges are not required to be ordered, simply to to form
- * a single closed loop as a whole.
- *
- * \note While this function will work fine when the edges
- * are already sorted, if the edges are always going to be sorted,
- * #BM_face_create should be considered over this function as it
- * avoids some unnecessary work.
+ * All arrays must be \a len long.
*/
-BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, const int len,
- const BMFace *f_example, const eBMCreateFlag create_flag)
+static bool bm_edges_sort_winding(
+ BMVert *v1, BMVert *v2,
+ BMEdge **edges, const int len,
+ BMEdge **edges_sort, BMVert **verts_sort)
{
- BMEdge **edges_sort = BLI_array_alloca(edges_sort, len);
- BMVert **verts_sort = BLI_array_alloca(verts_sort, len + 1);
- int esort_index = 0;
- int vsort_index = 0;
-
- BMFace *f = NULL;
- BMEdge *e;
- BMVert *v, *ev1, *ev2;
+ BMEdge *e_iter, *e_first;
+ BMVert *v_iter;
int i;
- bool is_v1_found, is_reverse;
-
- /* this code is hideous, yeek. I'll have to think about ways of
- * cleaning it up. basically, it now combines the old BM_face_create_ngon
- * _and_ the old bmesh_mf functions, so its kindof smashed together
- * - joeedh */
-
- BLI_assert(len && v1 && v2 && edges && bm);
-
- /* put edges in correct order */
+ /* all flags _must_ be cleared on exit! */
for (i = 0; i < len; i++) {
BM_ELEM_API_FLAG_ENABLE(edges[i], _FLAG_MF);
+ BM_ELEM_API_FLAG_ENABLE(edges[i]->v1, _FLAG_MV);
+ BM_ELEM_API_FLAG_ENABLE(edges[i]->v2, _FLAG_MV);
}
- ev1 = edges[0]->v1;
- ev2 = edges[0]->v2;
-
- BLI_assert(ELEM(v1, ev1, ev2) && ELEM(v2, ev1, ev2));
-
- if (v1 == ev2) {
- /* Swapping here improves performance and consistency of face
- * structure in the special case that the edges are already in
- * the correct order and winding */
- SWAP(BMVert *, ev1, ev2);
- }
-
- verts_sort[vsort_index++] = ev1;
- v = ev2;
- e = edges[0];
+ /* find first edge */
+ i = 0;
+ v_iter = v1;
+ e_iter = e_first = v1->e;
do {
- BMEdge *e2 = e;
-
- /* vertex array is (len + 1) */
- if (UNLIKELY(vsort_index > len)) {
- goto err; /* vertex in loop twice */
+ if (BM_ELEM_API_FLAG_TEST(e_iter, _FLAG_MF) &&
+ (BM_edge_other_vert(e_iter, v_iter) == v2))
+ {
+ i = 1;
+ break;
}
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v_iter)) != e_first);
+ if (i == 0) {
+ goto error;
+ }
- verts_sort[vsort_index++] = v;
- edges_sort[esort_index++] = e;
-
- /* we only flag the verts to check if they are in the face more than once */
- BM_ELEM_API_FLAG_ENABLE(v, _FLAG_MV);
-
- do {
- e2 = bmesh_disk_edge_next(e2, v);
- if (e2 != e && BM_ELEM_API_FLAG_TEST(e2, _FLAG_MF)) {
- v = BM_edge_other_vert(e2, v);
- break;
+ i = 0;
+ do {
+ /* entering loop will always succeed */
+ if (BM_ELEM_API_FLAG_TEST(e_iter, _FLAG_MF)) {
+ if (UNLIKELY(BM_ELEM_API_FLAG_TEST(v_iter, _FLAG_MV) == false)) {
+ /* vert is in loop multiple times */
+ goto error;
}
- } while (e2 != e);
- if (UNLIKELY(e2 == e)) {
- goto err; /* the edges do not form a closed loop */
- }
+ BM_ELEM_API_FLAG_DISABLE(e_iter, _FLAG_MF);
+ edges_sort[i] = e_iter;
- e = e2;
- } while (e != edges[0]);
+ BM_ELEM_API_FLAG_DISABLE(v_iter, _FLAG_MV);
+ verts_sort[i] = v_iter;
- if (UNLIKELY(esort_index != len)) {
- goto err; /* we didn't use all edges in forming the boundary loop */
- }
+ i += 1;
- /* ok, edges are in correct order, now ensure they are going
- * in the correct direction */
- is_v1_found = is_reverse = false;
- for (i = 0; i < len; i++) {
- if (BM_vert_in_edge(edges_sort[i], v1)) {
- /* see if v1 and v2 are in the same edge */
- if (BM_vert_in_edge(edges_sort[i], v2)) {
- /* if v1 is shared by the *next* edge, then the winding
- * is incorrect */
- if (BM_vert_in_edge(edges_sort[(i + 1) % len], v1)) {
- is_reverse = true;
- break;
+ /* walk onto the next vertex */
+ v_iter = BM_edge_other_vert(e_iter, v_iter);
+ if (i == len) {
+ if (UNLIKELY(v_iter != verts_sort[0])) {
+ goto error;
}
+ break;
}
- is_v1_found = true;
- }
-
- if ((is_v1_found == false) && BM_vert_in_edge(edges_sort[i], v2)) {
- is_reverse = true;
- break;
+ e_first = e_iter;
}
- }
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v_iter)) != e_first);
- if (is_reverse) {
- for (i = 0; i < len / 2; i++) {
- v = verts_sort[i];
- verts_sort[i] = verts_sort[len - i - 1];
- verts_sort[len - i - 1] = v;
- }
+ if (i == len) {
+ return true;
}
+error:
for (i = 0; i < len; i++) {
- edges_sort[i] = BM_edge_exists(verts_sort[i], verts_sort[(i + 1) % len]);
- if (UNLIKELY(edges_sort[i] == NULL)) {
- goto err;
- }
-
- /* check if vert is in face more than once. if the flag is disabled. we've already visited */
- if (UNLIKELY(!BM_ELEM_API_FLAG_TEST(verts_sort[i], _FLAG_MV))) {
- goto err;
- }
- BM_ELEM_API_FLAG_DISABLE(verts_sort[i], _FLAG_MV);
+ BM_ELEM_API_FLAG_DISABLE(edges[i], _FLAG_MF);
+ BM_ELEM_API_FLAG_DISABLE(edges[i]->v1, _FLAG_MV);
+ BM_ELEM_API_FLAG_DISABLE(edges[i]->v2, _FLAG_MV);
}
- f = BM_face_create(bm, verts_sort, edges_sort, len, f_example, create_flag);
+ return false;
+}
- /* clean up flags */
- for (i = 0; i < len; i++) {
- BM_ELEM_API_FLAG_DISABLE(edges_sort[i], _FLAG_MF);
- }
+/**
+ * \brief Make NGon
+ *
+ * Makes an ngon from an unordered list of edges.
+ * Verts \a v1 and \a v2 define the winding of the new face.
+ *
+ * \a edges are not required to be ordered, simply to to form
+ * a single closed loop as a whole.
+ *
+ * \note While this function will work fine when the edges
+ * are already sorted, if the edges are always going to be sorted,
+ * #BM_face_create should be considered over this function as it
+ * avoids some unnecessary work.
+ */
+BMFace *BM_face_create_ngon(
+ BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, const int len,
+ const BMFace *f_example, const eBMCreateFlag create_flag)
+{
+ BMEdge **edges_sort = BLI_array_alloca(edges_sort, len);
+ BMVert **verts_sort = BLI_array_alloca(verts_sort, len);
- return f;
+ BLI_assert(len && v1 && v2 && edges && bm);
-err:
- for (i = 0; i < len; i++) {
- BM_ELEM_API_FLAG_DISABLE(edges[i], _FLAG_MF);
- }
- for (i = 0; i < vsort_index; i++) {
- BM_ELEM_API_FLAG_DISABLE(verts_sort[i], _FLAG_MV);
+ if (bm_edges_sort_winding(v1, v2, edges, len, edges_sort, verts_sort)) {
+ return BM_face_create(bm, verts_sort, edges_sort, len, f_example, create_flag);
}
return NULL;
@@ -294,9 +286,10 @@ err:
* - Optionally create edges between vertices.
* - Uses verts so no need to find edges (handy when you only have verts)
*/
-BMFace *BM_face_create_ngon_verts(BMesh *bm, BMVert **vert_arr, const int len,
- const BMFace *f_example, const eBMCreateFlag create_flag,
- const bool calc_winding, const bool create_edges)
+BMFace *BM_face_create_ngon_verts(
+ BMesh *bm, BMVert **vert_arr, const int len,
+ const BMFace *f_example, const eBMCreateFlag create_flag,
+ const bool calc_winding, const bool create_edges)
{
BMEdge **edge_arr = BLI_array_alloca(edge_arr, len);
unsigned int winding[2] = {0, 0};
@@ -375,8 +368,9 @@ BMFace *BM_face_create_ngon_verts(BMesh *bm, BMVert **vert_arr, const int len,
*
* \note Since this is a vcloud there is no direction.
*/
-BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len,
- const BMFace *f_example, const eBMCreateFlag create_flag)
+BMFace *BM_face_create_ngon_vcloud(
+ BMesh *bm, BMVert **vert_arr, int len,
+ const BMFace *f_example, const eBMCreateFlag create_flag)
{
struct SortIntByFloat *vang = BLI_array_alloca(vang, len);
BMVert **vert_arr_map = BLI_array_alloca(vert_arr_map, len);
@@ -497,8 +491,9 @@ BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len,
/*************************************************************/
-static void bm_vert_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
- const BMVert *source_vertex, BMVert *target_vertex)
+static void bm_vert_attrs_copy(
+ BMesh *source_mesh, BMesh *target_mesh,
+ const BMVert *source_vertex, BMVert *target_vertex)
{
if ((source_mesh == target_mesh) && (source_vertex == target_vertex)) {
BLI_assert(!"BMVert: source and targer match");
@@ -510,8 +505,9 @@ static void bm_vert_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
source_vertex->head.data, &target_vertex->head.data);
}
-static void bm_edge_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
- const BMEdge *source_edge, BMEdge *target_edge)
+static void bm_edge_attrs_copy(
+ BMesh *source_mesh, BMesh *target_mesh,
+ const BMEdge *source_edge, BMEdge *target_edge)
{
if ((source_mesh == target_mesh) && (source_edge == target_edge)) {
BLI_assert(!"BMEdge: source and targer match");
@@ -522,8 +518,9 @@ static void bm_edge_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
source_edge->head.data, &target_edge->head.data);
}
-static void bm_loop_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
- const BMLoop *source_loop, BMLoop *target_loop)
+static void bm_loop_attrs_copy(
+ BMesh *source_mesh, BMesh *target_mesh,
+ const BMLoop *source_loop, BMLoop *target_loop)
{
if ((source_mesh == target_mesh) && (source_loop == target_loop)) {
BLI_assert(!"BMLoop: source and targer match");
@@ -534,8 +531,9 @@ static void bm_loop_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
source_loop->head.data, &target_loop->head.data);
}
-static void bm_face_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
- const BMFace *source_face, BMFace *target_face)
+static void bm_face_attrs_copy(
+ BMesh *source_mesh, BMesh *target_mesh,
+ const BMFace *source_face, BMFace *target_face)
{
if ((source_mesh == target_mesh) && (source_face == target_face)) {
BLI_assert(!"BMFace: source and targer match");
@@ -555,8 +553,9 @@ static void bm_face_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
* Copies attributes, e.g. customdata, header flags, etc, from one element
* to another of the same type.
*/
-void BM_elem_attrs_copy_ex(BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v, void *ele_dst_v,
- const char hflag_mask)
+void BM_elem_attrs_copy_ex(
+ BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v, void *ele_dst_v,
+ const char hflag_mask)
{
const BMHeader *ele_src = ele_src_v;
BMHeader *ele_dst = ele_dst_v;
@@ -621,9 +620,10 @@ void BM_elem_select_copy(BMesh *bm_dst, BMesh *UNUSED(bm_src), void *ele_dst_v,
}
/* helper function for 'BM_mesh_copy' */
-static BMFace *bm_mesh_copy_new_face(BMesh *bm_new, BMesh *bm_old,
- BMVert **vtable, BMEdge **etable,
- BMFace *f)
+static BMFace *bm_mesh_copy_new_face(
+ BMesh *bm_new, BMesh *bm_old,
+ BMVert **vtable, BMEdge **etable,
+ BMFace *f)
{
BMLoop **loops = BLI_array_alloca(loops, f->len);
BMVert **verts = BLI_array_alloca(verts, f->len);