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:
authorCampbell Barton <ideasman42@gmail.com>2019-04-17 07:17:24 +0300
committerCampbell Barton <ideasman42@gmail.com>2019-04-17 07:21:24 +0300
commite12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch)
tree8cf3453d12edb177a218ef8009357518ec6cab6a /source/blender/bmesh/operators
parentb3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (diff)
ClangFormat: apply to source, most of intern
Apply clang format as proposed in T53211. For details on usage and instructions for migrating branches without conflicts, see: https://wiki.blender.org/wiki/Tools/ClangFormat
Diffstat (limited to 'source/blender/bmesh/operators')
-rw-r--r--source/blender/bmesh/operators/bmo_beautify.c71
-rw-r--r--source/blender/bmesh/operators/bmo_bevel.c100
-rw-r--r--source/blender/bmesh/operators/bmo_bisect_plane.c132
-rw-r--r--source/blender/bmesh/operators/bmo_bridge.c1117
-rw-r--r--source/blender/bmesh/operators/bmo_connect.c300
-rw-r--r--source/blender/bmesh/operators/bmo_connect_concave.c325
-rw-r--r--source/blender/bmesh/operators/bmo_connect_nonplanar.c257
-rw-r--r--source/blender/bmesh/operators/bmo_connect_pair.c1046
-rw-r--r--source/blender/bmesh/operators/bmo_create.c538
-rw-r--r--source/blender/bmesh/operators/bmo_dissolve.c1115
-rw-r--r--source/blender/bmesh/operators/bmo_dupe.c912
-rw-r--r--source/blender/bmesh/operators/bmo_edgenet.c454
-rw-r--r--source/blender/bmesh/operators/bmo_extrude.c1366
-rw-r--r--source/blender/bmesh/operators/bmo_fill_attribute.c215
-rw-r--r--source/blender/bmesh/operators/bmo_fill_edgeloop.c232
-rw-r--r--source/blender/bmesh/operators/bmo_fill_grid.c1158
-rw-r--r--source/blender/bmesh/operators/bmo_fill_holes.c93
-rw-r--r--source/blender/bmesh/operators/bmo_hull.c974
-rw-r--r--source/blender/bmesh/operators/bmo_inset.c2169
-rw-r--r--source/blender/bmesh/operators/bmo_join_triangles.c563
-rw-r--r--source/blender/bmesh/operators/bmo_mesh_conv.c48
-rw-r--r--source/blender/bmesh/operators/bmo_mirror.c160
-rw-r--r--source/blender/bmesh/operators/bmo_normals.c385
-rw-r--r--source/blender/bmesh/operators/bmo_offset_edgeloops.c406
-rw-r--r--source/blender/bmesh/operators/bmo_planar_faces.c196
-rw-r--r--source/blender/bmesh/operators/bmo_poke.c219
-rw-r--r--source/blender/bmesh/operators/bmo_primitive.c3146
-rw-r--r--source/blender/bmesh/operators/bmo_removedoubles.c1190
-rw-r--r--source/blender/bmesh/operators/bmo_rotate_edges.c403
-rw-r--r--source/blender/bmesh/operators/bmo_smooth_laplacian.c910
-rw-r--r--source/blender/bmesh/operators/bmo_split_edges.c21
-rw-r--r--source/blender/bmesh/operators/bmo_subdivide.c2159
-rw-r--r--source/blender/bmesh/operators/bmo_subdivide_edgering.c2044
-rw-r--r--source/blender/bmesh/operators/bmo_symmetrize.c103
-rw-r--r--source/blender/bmesh/operators/bmo_triangulate.c445
-rw-r--r--source/blender/bmesh/operators/bmo_unsubdivide.c40
-rw-r--r--source/blender/bmesh/operators/bmo_utils.c1005
-rw-r--r--source/blender/bmesh/operators/bmo_wireframe.c56
38 files changed, 13074 insertions, 12999 deletions
diff --git a/source/blender/bmesh/operators/bmo_beautify.c b/source/blender/bmesh/operators/bmo_beautify.c
index 4efa3d98262..36122e06e9b 100644
--- a/source/blender/bmesh/operators/bmo_beautify.c
+++ b/source/blender/bmesh/operators/bmo_beautify.c
@@ -29,50 +29,51 @@
#include "bmesh_tools.h"
#include "intern/bmesh_operators_private.h"
-#define ELE_NEW 1
-#define FACE_MARK 2
+#define ELE_NEW 1
+#define FACE_MARK 2
void bmo_beautify_fill_exec(BMesh *bm, BMOperator *op)
{
- BMIter iter;
- BMOIter siter;
- BMFace *f;
- BMEdge *e;
- const bool use_restrict_tag = BMO_slot_bool_get(op->slots_in, "use_restrict_tag");
- const short flag = (use_restrict_tag ? VERT_RESTRICT_TAG : 0);
- const short method = (short)BMO_slot_int_get(op->slots_in, "method");
+ BMIter iter;
+ BMOIter siter;
+ BMFace *f;
+ BMEdge *e;
+ const bool use_restrict_tag = BMO_slot_bool_get(op->slots_in, "use_restrict_tag");
+ const short flag = (use_restrict_tag ? VERT_RESTRICT_TAG : 0);
+ const short method = (short)BMO_slot_int_get(op->slots_in, "method");
- BMEdge **edge_array;
- int edge_array_len = 0;
- BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) {
- if (f->len == 3) {
- BMO_face_flag_enable(bm, f, FACE_MARK);
- }
- }
+ BMEdge **edge_array;
+ int edge_array_len = 0;
+ BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) {
+ if (f->len == 3) {
+ BMO_face_flag_enable(bm, f, FACE_MARK);
+ }
+ }
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- BM_elem_flag_disable(e, BM_ELEM_TAG);
- }
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ BM_elem_flag_disable(e, BM_ELEM_TAG);
+ }
- /* will over alloc if some edges can't be rotated */
- edge_array = MEM_mallocN(sizeof(*edge_array) * (size_t)BMO_slot_buffer_count(op->slots_in, "edges"), __func__);
+ /* will over alloc if some edges can't be rotated */
+ edge_array = MEM_mallocN(
+ sizeof(*edge_array) * (size_t)BMO_slot_buffer_count(op->slots_in, "edges"), __func__);
- BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
+ BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
- /* edge is manifold and can be rotated */
- if (BM_edge_rotate_check(e) &&
- /* faces are tagged */
- BMO_face_flag_test(bm, e->l->f, FACE_MARK) &&
- BMO_face_flag_test(bm, e->l->radial_next->f, FACE_MARK))
- {
- edge_array[edge_array_len] = e;
- edge_array_len++;
- }
- }
+ /* edge is manifold and can be rotated */
+ if (BM_edge_rotate_check(e) &&
+ /* faces are tagged */
+ BMO_face_flag_test(bm, e->l->f, FACE_MARK) &&
+ BMO_face_flag_test(bm, e->l->radial_next->f, FACE_MARK)) {
+ edge_array[edge_array_len] = e;
+ edge_array_len++;
+ }
+ }
- BM_mesh_beautify_fill(bm, edge_array, edge_array_len, flag, method, ELE_NEW, FACE_MARK | ELE_NEW);
+ BM_mesh_beautify_fill(
+ bm, edge_array, edge_array_len, flag, method, ELE_NEW, FACE_MARK | ELE_NEW);
- MEM_freeN(edge_array);
+ MEM_freeN(edge_array);
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_EDGE | BM_FACE, ELE_NEW);
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_EDGE | BM_FACE, ELE_NEW);
}
diff --git a/source/blender/bmesh/operators/bmo_bevel.c b/source/blender/bmesh/operators/bmo_bevel.c
index 19c377d18a9..33be9559db3 100644
--- a/source/blender/bmesh/operators/bmo_bevel.c
+++ b/source/blender/bmesh/operators/bmo_bevel.c
@@ -29,52 +29,68 @@
void bmo_bevel_exec(BMesh *bm, BMOperator *op)
{
- const float offset = BMO_slot_float_get(op->slots_in, "offset");
- const int offset_type = BMO_slot_int_get(op->slots_in, "offset_type");
- const int seg = BMO_slot_int_get(op->slots_in, "segments");
- const bool vonly = BMO_slot_bool_get(op->slots_in, "vertex_only");
- const float profile = BMO_slot_float_get(op->slots_in, "profile");
- const bool clamp_overlap = BMO_slot_bool_get(op->slots_in, "clamp_overlap");
- const int material = BMO_slot_int_get(op->slots_in, "material");
- const bool loop_slide = BMO_slot_bool_get(op->slots_in, "loop_slide");
- const bool mark_seam = BMO_slot_bool_get(op->slots_in, "mark_seam");
- const bool mark_sharp = BMO_slot_bool_get(op->slots_in, "mark_sharp");
- const bool harden_normals = BMO_slot_bool_get(op->slots_in, "harden_normals");
- const int face_strength_mode = BMO_slot_int_get(op->slots_in, "face_strength_mode");
- const int miter_outer = BMO_slot_int_get(op->slots_in, "miter_outer");
- const int miter_inner = BMO_slot_int_get(op->slots_in, "miter_inner");
- const float spread = BMO_slot_float_get(op->slots_in, "spread");
- const float smoothresh = BMO_slot_float_get(op->slots_in, "smoothresh");
+ const float offset = BMO_slot_float_get(op->slots_in, "offset");
+ const int offset_type = BMO_slot_int_get(op->slots_in, "offset_type");
+ const int seg = BMO_slot_int_get(op->slots_in, "segments");
+ const bool vonly = BMO_slot_bool_get(op->slots_in, "vertex_only");
+ const float profile = BMO_slot_float_get(op->slots_in, "profile");
+ const bool clamp_overlap = BMO_slot_bool_get(op->slots_in, "clamp_overlap");
+ const int material = BMO_slot_int_get(op->slots_in, "material");
+ const bool loop_slide = BMO_slot_bool_get(op->slots_in, "loop_slide");
+ const bool mark_seam = BMO_slot_bool_get(op->slots_in, "mark_seam");
+ const bool mark_sharp = BMO_slot_bool_get(op->slots_in, "mark_sharp");
+ const bool harden_normals = BMO_slot_bool_get(op->slots_in, "harden_normals");
+ const int face_strength_mode = BMO_slot_int_get(op->slots_in, "face_strength_mode");
+ const int miter_outer = BMO_slot_int_get(op->slots_in, "miter_outer");
+ const int miter_inner = BMO_slot_int_get(op->slots_in, "miter_inner");
+ const float spread = BMO_slot_float_get(op->slots_in, "spread");
+ const float smoothresh = BMO_slot_float_get(op->slots_in, "smoothresh");
- if (offset > 0) {
- BMOIter siter;
- BMEdge *e;
- BMVert *v;
+ if (offset > 0) {
+ BMOIter siter;
+ BMEdge *e;
+ BMVert *v;
- /* first flush 'geom' into flags, this makes it possible to check connected data,
- * BM_FACE is cleared so we can put newly created faces into a bmesh slot. */
- BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
+ /* first flush 'geom' into flags, this makes it possible to check connected data,
+ * BM_FACE is cleared so we can put newly created faces into a bmesh slot. */
+ BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
- BMO_ITER (v, &siter, op->slots_in, "geom", BM_VERT) {
- BM_elem_flag_enable(v, BM_ELEM_TAG);
- }
+ BMO_ITER (v, &siter, op->slots_in, "geom", BM_VERT) {
+ BM_elem_flag_enable(v, BM_ELEM_TAG);
+ }
- BMO_ITER (e, &siter, op->slots_in, "geom", BM_EDGE) {
- if (BM_edge_is_manifold(e)) {
- BM_elem_flag_enable(e, BM_ELEM_TAG);
- /* in case verts were not also included in the geom */
- BM_elem_flag_enable(e->v1, BM_ELEM_TAG);
- BM_elem_flag_enable(e->v2, BM_ELEM_TAG);
- }
- }
+ BMO_ITER (e, &siter, op->slots_in, "geom", BM_EDGE) {
+ if (BM_edge_is_manifold(e)) {
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
+ /* in case verts were not also included in the geom */
+ BM_elem_flag_enable(e->v1, BM_ELEM_TAG);
+ BM_elem_flag_enable(e->v2, BM_ELEM_TAG);
+ }
+ }
- BM_mesh_bevel(
- bm, offset, offset_type, seg, profile, vonly, false, clamp_overlap, NULL, -1, material,
- loop_slide, mark_seam, mark_sharp, harden_normals, face_strength_mode,
- miter_outer, miter_inner, spread, smoothresh);
+ BM_mesh_bevel(bm,
+ offset,
+ offset_type,
+ seg,
+ profile,
+ vonly,
+ false,
+ clamp_overlap,
+ NULL,
+ -1,
+ material,
+ loop_slide,
+ mark_seam,
+ mark_sharp,
+ harden_normals,
+ face_strength_mode,
+ miter_outer,
+ miter_inner,
+ spread,
+ smoothresh);
- BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG);
- BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "edges.out", BM_EDGE, BM_ELEM_TAG);
- BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "verts.out", BM_VERT, BM_ELEM_TAG);
- }
+ BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG);
+ BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "edges.out", BM_EDGE, BM_ELEM_TAG);
+ BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "verts.out", BM_VERT, BM_ELEM_TAG);
+ }
}
diff --git a/source/blender/bmesh/operators/bmo_bisect_plane.c b/source/blender/bmesh/operators/bmo_bisect_plane.c
index 800f5bac715..f3062cac85c 100644
--- a/source/blender/bmesh/operators/bmo_bisect_plane.c
+++ b/source/blender/bmesh/operators/bmo_bisect_plane.c
@@ -37,71 +37,69 @@
void bmo_bisect_plane_exec(BMesh *bm, BMOperator *op)
{
- const float dist = BMO_slot_float_get(op->slots_in, "dist");
- const bool use_snap_center = BMO_slot_bool_get(op->slots_in, "use_snap_center");
- const bool clear_outer = BMO_slot_bool_get(op->slots_in, "clear_outer");
- const bool clear_inner = BMO_slot_bool_get(op->slots_in, "clear_inner");
-
- float plane_co[3];
- float plane_no[3];
- float plane[4];
-
- BMO_slot_vec_get(op->slots_in, "plane_co", plane_co);
- BMO_slot_vec_get(op->slots_in, "plane_no", plane_no);
-
- if (is_zero_v3(plane_no)) {
- BMO_error_raise(bm, op, BMERR_MESH_ERROR, "Zero normal given");
- return;
- }
-
- plane_from_point_normal_v3(plane, plane_co, plane_no);
-
- /* tag geometry to bisect */
- BM_mesh_elem_hflag_disable_all(bm, BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
- BMO_slot_buffer_hflag_enable(bm, op->slots_in, "geom", BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
-
- BMO_slot_buffer_flag_enable(bm, op->slots_in, "geom", BM_ALL_NOLOOP, ELE_INPUT);
-
-
- BM_mesh_bisect_plane(bm, plane, use_snap_center, true,
- ELE_CUT, ELE_NEW, dist);
-
-
- if (clear_outer || clear_inner) {
- /* Use an array of vertices because 'geom' contains both vers and edges that may use them.
- * Removing a vert may remove and edge which is later checked by BMO_ITER.
- * over-alloc the total possible vert count */
- const int vert_arr_max = min_ii(bm->totvert, BMO_slot_buffer_count(op->slots_in, "geom"));
- BMVert **vert_arr = MEM_mallocN(sizeof(*vert_arr) * (size_t)vert_arr_max, __func__);
- BMOIter siter;
- BMVert *v;
- float plane_inner[4];
- float plane_outer[4];
-
- STACK_DECLARE(vert_arr);
-
- copy_v3_v3(plane_outer, plane);
- copy_v3_v3(plane_inner, plane);
- plane_outer[3] = plane[3] - dist;
- plane_inner[3] = plane[3] + dist;
-
- STACK_INIT(vert_arr, vert_arr_max);
-
- BMO_ITER (v, &siter, op->slots_in, "geom", BM_VERT) {
- if ((clear_outer && plane_point_side_v3(plane_outer, v->co) > 0.0f) ||
- (clear_inner && plane_point_side_v3(plane_inner, v->co) < 0.0f))
- {
- STACK_PUSH(vert_arr, v);
- }
- }
-
- while ((v = STACK_POP(vert_arr))) {
- BM_vert_kill(bm, v);
- }
-
- MEM_freeN(vert_arr);
- }
-
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_ALL_NOLOOP, ELE_NEW | ELE_INPUT);
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_cut.out", BM_VERT | BM_EDGE, ELE_CUT);
+ const float dist = BMO_slot_float_get(op->slots_in, "dist");
+ const bool use_snap_center = BMO_slot_bool_get(op->slots_in, "use_snap_center");
+ const bool clear_outer = BMO_slot_bool_get(op->slots_in, "clear_outer");
+ const bool clear_inner = BMO_slot_bool_get(op->slots_in, "clear_inner");
+
+ float plane_co[3];
+ float plane_no[3];
+ float plane[4];
+
+ BMO_slot_vec_get(op->slots_in, "plane_co", plane_co);
+ BMO_slot_vec_get(op->slots_in, "plane_no", plane_no);
+
+ if (is_zero_v3(plane_no)) {
+ BMO_error_raise(bm, op, BMERR_MESH_ERROR, "Zero normal given");
+ return;
+ }
+
+ plane_from_point_normal_v3(plane, plane_co, plane_no);
+
+ /* tag geometry to bisect */
+ BM_mesh_elem_hflag_disable_all(bm, BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
+ BMO_slot_buffer_hflag_enable(bm, op->slots_in, "geom", BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
+
+ BMO_slot_buffer_flag_enable(bm, op->slots_in, "geom", BM_ALL_NOLOOP, ELE_INPUT);
+
+ BM_mesh_bisect_plane(bm, plane, use_snap_center, true, ELE_CUT, ELE_NEW, dist);
+
+ if (clear_outer || clear_inner) {
+ /* Use an array of vertices because 'geom' contains both vers and edges that may use them.
+ * Removing a vert may remove and edge which is later checked by BMO_ITER.
+ * over-alloc the total possible vert count */
+ const int vert_arr_max = min_ii(bm->totvert, BMO_slot_buffer_count(op->slots_in, "geom"));
+ BMVert **vert_arr = MEM_mallocN(sizeof(*vert_arr) * (size_t)vert_arr_max, __func__);
+ BMOIter siter;
+ BMVert *v;
+ float plane_inner[4];
+ float plane_outer[4];
+
+ STACK_DECLARE(vert_arr);
+
+ copy_v3_v3(plane_outer, plane);
+ copy_v3_v3(plane_inner, plane);
+ plane_outer[3] = plane[3] - dist;
+ plane_inner[3] = plane[3] + dist;
+
+ STACK_INIT(vert_arr, vert_arr_max);
+
+ BMO_ITER (v, &siter, op->slots_in, "geom", BM_VERT) {
+ if ((clear_outer && plane_point_side_v3(plane_outer, v->co) > 0.0f) ||
+ (clear_inner && plane_point_side_v3(plane_inner, v->co) < 0.0f)) {
+ STACK_PUSH(vert_arr, v);
+ }
+ }
+
+ while ((v = STACK_POP(vert_arr))) {
+ BM_vert_kill(bm, v);
+ }
+
+ MEM_freeN(vert_arr);
+ }
+
+ BMO_slot_buffer_from_enabled_flag(
+ bm, op, op->slots_out, "geom.out", BM_ALL_NOLOOP, ELE_NEW | ELE_INPUT);
+ BMO_slot_buffer_from_enabled_flag(
+ bm, op, op->slots_out, "geom_cut.out", BM_VERT | BM_EDGE, ELE_CUT);
}
diff --git a/source/blender/bmesh/operators/bmo_bridge.c b/source/blender/bmesh/operators/bmo_bridge.c
index 84b5f44a43f..39ccc0c631e 100644
--- a/source/blender/bmesh/operators/bmo_bridge.c
+++ b/source/blender/bmesh/operators/bmo_bridge.c
@@ -28,32 +28,33 @@
#include "intern/bmesh_operators_private.h" /* own include */
-#define EDGE_MARK 4
-#define EDGE_OUT 8
-#define FACE_OUT 16
+#define EDGE_MARK 4
+#define EDGE_OUT 8
+#define FACE_OUT 16
/* el_a and el_b _must_ be same size */
-static void bm_bridge_splice_loops(BMesh *bm, LinkData *el_a, LinkData *el_b, const float merge_factor)
+static void bm_bridge_splice_loops(BMesh *bm,
+ LinkData *el_a,
+ LinkData *el_b,
+ const float merge_factor)
{
- BMOperator op_weld;
- BMOpSlot *slot_targetmap;
+ BMOperator op_weld;
+ BMOpSlot *slot_targetmap;
- BMO_op_init(bm, &op_weld, 0, "weld_verts");
+ BMO_op_init(bm, &op_weld, 0, "weld_verts");
- slot_targetmap = BMO_slot_get(op_weld.slots_in, "targetmap");
+ slot_targetmap = BMO_slot_get(op_weld.slots_in, "targetmap");
- do {
- BMVert *v_a = el_a->data, *v_b = el_b->data;
- BM_data_interp_from_verts(bm, v_a, v_b, v_b, merge_factor);
- interp_v3_v3v3(v_b->co, v_a->co, v_b->co, merge_factor);
- BLI_assert(v_a != v_b);
- BMO_slot_map_elem_insert(&op_weld, slot_targetmap, v_a, v_b);
- } while ((void)
- (el_b = el_b->next),
- (el_a = el_a->next));
+ do {
+ BMVert *v_a = el_a->data, *v_b = el_b->data;
+ BM_data_interp_from_verts(bm, v_a, v_b, v_b, merge_factor);
+ interp_v3_v3v3(v_b->co, v_a->co, v_b->co, merge_factor);
+ BLI_assert(v_a != v_b);
+ BMO_slot_map_elem_insert(&op_weld, slot_targetmap, v_a, v_b);
+ } while ((void)(el_b = el_b->next), (el_a = el_a->next));
- BMO_op_exec(bm, &op_weld);
- BMO_op_finish(bm, &op_weld);
+ BMO_op_exec(bm, &op_weld);
+ BMO_op_finish(bm, &op_weld);
}
/* get the 2 loops matching 2 verts.
@@ -61,557 +62,581 @@ static void bm_bridge_splice_loops(BMesh *bm, LinkData *el_a, LinkData *el_b, co
* if that fails just get any loop thats on the vert (the first one) */
static void bm_vert_loop_pair(BMesh *bm, BMVert *v1, BMVert *v2, BMLoop **l1, BMLoop **l2)
{
- BMEdge *e = BM_edge_exists(v1, v2);
- BMLoop *l = e->l;
-
- if (l) {
- if (l->v == v1) {
- *l1 = l;
- *l2 = l->next;
- }
- else {
- *l2 = l;
- *l1 = l->next;
- }
- }
- else {
- /* fallback to _any_ loop */
- *l1 = BM_iter_at_index(bm, BM_LOOPS_OF_VERT, v1, 0);
- *l2 = BM_iter_at_index(bm, BM_LOOPS_OF_VERT, v2, 0);
- }
+ BMEdge *e = BM_edge_exists(v1, v2);
+ BMLoop *l = e->l;
+
+ if (l) {
+ if (l->v == v1) {
+ *l1 = l;
+ *l2 = l->next;
+ }
+ else {
+ *l2 = l;
+ *l1 = l->next;
+ }
+ }
+ else {
+ /* fallback to _any_ loop */
+ *l1 = BM_iter_at_index(bm, BM_LOOPS_OF_VERT, v1, 0);
+ *l2 = BM_iter_at_index(bm, BM_LOOPS_OF_VERT, v2, 0);
+ }
}
/* el_b can have any offset */
-static float bm_edgeloop_offset_length(
- LinkData *el_a, LinkData *el_b,
- LinkData *el_b_first, const float len_max)
+static float bm_edgeloop_offset_length(LinkData *el_a,
+ LinkData *el_b,
+ LinkData *el_b_first,
+ const float len_max)
{
- float len = 0.0f;
- BLI_assert(el_a->prev == NULL); /* must be first */
- do {
- len += len_v3v3(((BMVert *)el_a->data)->co, ((BMVert *)el_b->data)->co);
- } while ((void)
- (el_b = el_b->next ? el_b->next : el_b_first),
- (el_a = el_a->next) && (len < len_max));
- return len;
+ float len = 0.0f;
+ BLI_assert(el_a->prev == NULL); /* must be first */
+ do {
+ len += len_v3v3(((BMVert *)el_a->data)->co, ((BMVert *)el_b->data)->co);
+ } while ((void)(el_b = el_b->next ? el_b->next : el_b_first),
+ (el_a = el_a->next) && (len < len_max));
+ return len;
}
-static void bm_bridge_best_rotation(struct BMEdgeLoopStore *el_store_a, struct BMEdgeLoopStore *el_store_b)
+static void bm_bridge_best_rotation(struct BMEdgeLoopStore *el_store_a,
+ struct BMEdgeLoopStore *el_store_b)
{
- ListBase *lb_a = BM_edgeloop_verts_get(el_store_a);
- ListBase *lb_b = BM_edgeloop_verts_get(el_store_b);
- LinkData *el_a = lb_a->first;
- LinkData *el_b = lb_b->first;
- LinkData *el_b_first = el_b;
- LinkData *el_b_best = NULL;
-
- float len_best = FLT_MAX;
-
- for (; el_b; el_b = el_b->next) {
- const float len = bm_edgeloop_offset_length(el_a, el_b, el_b_first, len_best);
- if (len < len_best) {
- el_b_best = el_b;
- len_best = len;
- }
- }
-
- if (el_b_best) {
- BLI_listbase_rotate_first(lb_b, el_b_best);
- }
+ ListBase *lb_a = BM_edgeloop_verts_get(el_store_a);
+ ListBase *lb_b = BM_edgeloop_verts_get(el_store_b);
+ LinkData *el_a = lb_a->first;
+ LinkData *el_b = lb_b->first;
+ LinkData *el_b_first = el_b;
+ LinkData *el_b_best = NULL;
+
+ float len_best = FLT_MAX;
+
+ for (; el_b; el_b = el_b->next) {
+ const float len = bm_edgeloop_offset_length(el_a, el_b, el_b_first, len_best);
+ if (len < len_best) {
+ el_b_best = el_b;
+ len_best = len;
+ }
+ }
+
+ if (el_b_best) {
+ BLI_listbase_rotate_first(lb_b, el_b_best);
+ }
}
static void bm_face_edges_tag_out(BMesh *bm, BMFace *f)
{
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- BMO_edge_flag_enable(bm, l_iter->e, EDGE_OUT);
- } while ((l_iter = l_iter->next) != l_first);
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BMO_edge_flag_enable(bm, l_iter->e, EDGE_OUT);
+ } while ((l_iter = l_iter->next) != l_first);
}
static bool bm_edge_test_cb(BMEdge *e, void *bm_v)
{
- return BMO_edge_flag_test((BMesh *)bm_v, e, EDGE_MARK);
+ return BMO_edge_flag_test((BMesh *)bm_v, e, EDGE_MARK);
}
-static void bridge_loop_pair(
- BMesh *bm,
- struct BMEdgeLoopStore *el_store_a,
- struct BMEdgeLoopStore *el_store_b,
- const bool use_merge, const float merge_factor, const int twist_offset)
+static void bridge_loop_pair(BMesh *bm,
+ struct BMEdgeLoopStore *el_store_a,
+ struct BMEdgeLoopStore *el_store_b,
+ const bool use_merge,
+ const float merge_factor,
+ const int twist_offset)
{
- const float eps = 0.00001f;
- LinkData *el_a_first, *el_b_first;
- const bool is_closed = BM_edgeloop_is_closed(el_store_a) && BM_edgeloop_is_closed(el_store_b);
- int el_store_a_len, el_store_b_len;
- bool el_store_b_free = false;
- float el_dir[3];
- float dot_a, dot_b;
- const bool use_edgeout = true;
-
- el_store_a_len = BM_edgeloop_length_get((struct BMEdgeLoopStore *)el_store_a);
- el_store_b_len = BM_edgeloop_length_get((struct BMEdgeLoopStore *)el_store_b);
-
- if (el_store_a_len < el_store_b_len) {
- SWAP(int, el_store_a_len, el_store_b_len);
- SWAP(struct BMEdgeLoopStore *, el_store_a, el_store_b);
- }
-
- if (use_merge) {
- BLI_assert((el_store_a_len == el_store_b_len));
- }
-
- if (el_store_a_len != el_store_b_len) {
- BM_mesh_elem_hflag_disable_all(bm, BM_FACE | BM_EDGE, BM_ELEM_TAG, false);
- }
-
- sub_v3_v3v3(el_dir, BM_edgeloop_center_get(el_store_a), BM_edgeloop_center_get(el_store_b));
-
- if (is_closed) {
- /* if all loops are closed this will calculate twice for all loops */
- BM_edgeloop_calc_normal(bm, el_store_a);
- BM_edgeloop_calc_normal(bm, el_store_b);
- }
- else {
- ListBase *lb_a = BM_edgeloop_verts_get(el_store_a);
- ListBase *lb_b = BM_edgeloop_verts_get(el_store_b);
-
- /* normalizing isn't strictly needed but without we may get very large values */
- float no[3];
- float dir_a_orig[3], dir_b_orig[3];
- float dir_a[3], dir_b[3];
- const float *test_a, *test_b;
-
- sub_v3_v3v3(dir_a_orig,
- ((BMVert *)(((LinkData *)lb_a->first)->data))->co,
- ((BMVert *)(((LinkData *)lb_a->last)->data))->co);
- sub_v3_v3v3(dir_b_orig,
- ((BMVert *)(((LinkData *)lb_b->first)->data))->co,
- ((BMVert *)(((LinkData *)lb_b->last)->data))->co);
-
- /* make the directions point out from the normals, 'no' is used as a temp var */
- cross_v3_v3v3(no, dir_a_orig, el_dir); cross_v3_v3v3(dir_a, no, el_dir);
- cross_v3_v3v3(no, dir_b_orig, el_dir); cross_v3_v3v3(dir_b, no, el_dir);
-
- if (LIKELY(!is_zero_v3(dir_a) && !is_zero_v3(dir_b))) {
- test_a = dir_a;
- test_b = dir_b;
- }
- else {
- /**
- * This is a corner case:
- *
- * <pre>
- * (loop a) (loop b)
- * +--------+ +--------+
- * </pre>
- *
- * When loops are aligned to the direction between the loops values of 'dir_a/b' is degenerate,
- * in this case compare the original directions (before they were corrected by 'el_dir'), see: T43013
- */
- test_a = dir_a_orig;
- test_b = dir_b_orig;
- }
-
- if (dot_v3v3(test_a, test_b) < 0.0f) {
- BM_edgeloop_flip(bm, el_store_b);
- }
-
- normalize_v3_v3(no, el_dir);
- BM_edgeloop_calc_normal_aligned(bm, el_store_a, no);
- BM_edgeloop_calc_normal_aligned(bm, el_store_b, no);
- }
-
- dot_a = dot_v3v3(BM_edgeloop_normal_get(el_store_a), el_dir);
- dot_b = dot_v3v3(BM_edgeloop_normal_get(el_store_b), el_dir);
-
- if (UNLIKELY((len_squared_v3(el_dir) < eps) ||
- ((fabsf(dot_a) < eps) && (fabsf(dot_b) < eps))))
- {
- /* in this case there is no depth between the two loops,
- * eg: 2x 2d circles, one scaled smaller,
- * in this case 'el_dir' cant be used, just ensure we have matching flipping. */
- if (dot_v3v3(BM_edgeloop_normal_get(el_store_a),
- BM_edgeloop_normal_get(el_store_b)) < 0.0f)
- {
- BM_edgeloop_flip(bm, el_store_b);
- }
- }
- else if ((dot_a < 0.0f) != (dot_b < 0.0f)) {
- BM_edgeloop_flip(bm, el_store_b);
- }
-
- /* we only care about flipping if we make faces */
- if (use_merge == false) {
- float no[3];
-
- add_v3_v3v3(no, BM_edgeloop_normal_get(el_store_a), BM_edgeloop_normal_get(el_store_b));
-
- if (dot_v3v3(no, el_dir) < 0.0f) {
- BM_edgeloop_flip(bm, el_store_a);
- BM_edgeloop_flip(bm, el_store_b);
- }
-
- /* vote on winding (so new face winding is based on existing connected faces) */
- if (bm->totface) {
- struct BMEdgeLoopStore *estore_pair[2] = {el_store_a, el_store_b};
- int i;
- int winding_votes[2] = {0, 0};
- int winding_dir = 1;
- for (i = 0; i < 2; i++, winding_dir = -winding_dir) {
- LinkData *el;
- for (el = BM_edgeloop_verts_get(estore_pair[i])->first; el; el = el->next) {
- LinkData *el_next = BM_EDGELINK_NEXT(estore_pair[i], el);
- if (el_next) {
- BMEdge *e = BM_edge_exists(el->data, el_next->data);
- if (e && BM_edge_is_boundary(e)) {
- winding_votes[i] += ((e->l->v == el->data) ? winding_dir : -winding_dir);
- }
- }
- }
- }
-
- if (winding_votes[0] || winding_votes[1]) {
- bool flip[2] = {false, false};
-
- /* for direction aligned loops we can't rely on the directly we have,
- * use the winding defined by the connected faces (see T48356). */
- if (fabsf(dot_a) < eps) {
- if (winding_votes[0] < 0) {
- flip[0] = !flip[0];
- winding_votes[0] *= -1;
-
- }
- }
- if (fabsf(dot_b) < eps) {
- if (winding_votes[1] < 0) {
- flip[1] = !flip[1];
- winding_votes[1] *= -1;
- }
- }
-
- /* when both loops contradict the winding, flip them so surrounding geometry matches */
- if ((winding_votes[0] + winding_votes[1]) < 0) {
- flip[0] = !flip[0];
- flip[1] = !flip[1];
-
- /* valid but unused */
+ const float eps = 0.00001f;
+ LinkData *el_a_first, *el_b_first;
+ const bool is_closed = BM_edgeloop_is_closed(el_store_a) && BM_edgeloop_is_closed(el_store_b);
+ int el_store_a_len, el_store_b_len;
+ bool el_store_b_free = false;
+ float el_dir[3];
+ float dot_a, dot_b;
+ const bool use_edgeout = true;
+
+ el_store_a_len = BM_edgeloop_length_get((struct BMEdgeLoopStore *)el_store_a);
+ el_store_b_len = BM_edgeloop_length_get((struct BMEdgeLoopStore *)el_store_b);
+
+ if (el_store_a_len < el_store_b_len) {
+ SWAP(int, el_store_a_len, el_store_b_len);
+ SWAP(struct BMEdgeLoopStore *, el_store_a, el_store_b);
+ }
+
+ if (use_merge) {
+ BLI_assert((el_store_a_len == el_store_b_len));
+ }
+
+ if (el_store_a_len != el_store_b_len) {
+ BM_mesh_elem_hflag_disable_all(bm, BM_FACE | BM_EDGE, BM_ELEM_TAG, false);
+ }
+
+ sub_v3_v3v3(el_dir, BM_edgeloop_center_get(el_store_a), BM_edgeloop_center_get(el_store_b));
+
+ if (is_closed) {
+ /* if all loops are closed this will calculate twice for all loops */
+ BM_edgeloop_calc_normal(bm, el_store_a);
+ BM_edgeloop_calc_normal(bm, el_store_b);
+ }
+ else {
+ ListBase *lb_a = BM_edgeloop_verts_get(el_store_a);
+ ListBase *lb_b = BM_edgeloop_verts_get(el_store_b);
+
+ /* normalizing isn't strictly needed but without we may get very large values */
+ float no[3];
+ float dir_a_orig[3], dir_b_orig[3];
+ float dir_a[3], dir_b[3];
+ const float *test_a, *test_b;
+
+ sub_v3_v3v3(dir_a_orig,
+ ((BMVert *)(((LinkData *)lb_a->first)->data))->co,
+ ((BMVert *)(((LinkData *)lb_a->last)->data))->co);
+ sub_v3_v3v3(dir_b_orig,
+ ((BMVert *)(((LinkData *)lb_b->first)->data))->co,
+ ((BMVert *)(((LinkData *)lb_b->last)->data))->co);
+
+ /* make the directions point out from the normals, 'no' is used as a temp var */
+ cross_v3_v3v3(no, dir_a_orig, el_dir);
+ cross_v3_v3v3(dir_a, no, el_dir);
+ cross_v3_v3v3(no, dir_b_orig, el_dir);
+ cross_v3_v3v3(dir_b, no, el_dir);
+
+ if (LIKELY(!is_zero_v3(dir_a) && !is_zero_v3(dir_b))) {
+ test_a = dir_a;
+ test_b = dir_b;
+ }
+ else {
+ /**
+ * This is a corner case:
+ *
+ * <pre>
+ * (loop a) (loop b)
+ * +--------+ +--------+
+ * </pre>
+ *
+ * When loops are aligned to the direction between the loops values of 'dir_a/b' is degenerate,
+ * in this case compare the original directions (before they were corrected by 'el_dir'), see: T43013
+ */
+ test_a = dir_a_orig;
+ test_b = dir_b_orig;
+ }
+
+ if (dot_v3v3(test_a, test_b) < 0.0f) {
+ BM_edgeloop_flip(bm, el_store_b);
+ }
+
+ normalize_v3_v3(no, el_dir);
+ BM_edgeloop_calc_normal_aligned(bm, el_store_a, no);
+ BM_edgeloop_calc_normal_aligned(bm, el_store_b, no);
+ }
+
+ dot_a = dot_v3v3(BM_edgeloop_normal_get(el_store_a), el_dir);
+ dot_b = dot_v3v3(BM_edgeloop_normal_get(el_store_b), el_dir);
+
+ if (UNLIKELY((len_squared_v3(el_dir) < eps) || ((fabsf(dot_a) < eps) && (fabsf(dot_b) < eps)))) {
+ /* in this case there is no depth between the two loops,
+ * eg: 2x 2d circles, one scaled smaller,
+ * in this case 'el_dir' cant be used, just ensure we have matching flipping. */
+ if (dot_v3v3(BM_edgeloop_normal_get(el_store_a), BM_edgeloop_normal_get(el_store_b)) < 0.0f) {
+ BM_edgeloop_flip(bm, el_store_b);
+ }
+ }
+ else if ((dot_a < 0.0f) != (dot_b < 0.0f)) {
+ BM_edgeloop_flip(bm, el_store_b);
+ }
+
+ /* we only care about flipping if we make faces */
+ if (use_merge == false) {
+ float no[3];
+
+ add_v3_v3v3(no, BM_edgeloop_normal_get(el_store_a), BM_edgeloop_normal_get(el_store_b));
+
+ if (dot_v3v3(no, el_dir) < 0.0f) {
+ BM_edgeloop_flip(bm, el_store_a);
+ BM_edgeloop_flip(bm, el_store_b);
+ }
+
+ /* vote on winding (so new face winding is based on existing connected faces) */
+ if (bm->totface) {
+ struct BMEdgeLoopStore *estore_pair[2] = {el_store_a, el_store_b};
+ int i;
+ int winding_votes[2] = {0, 0};
+ int winding_dir = 1;
+ for (i = 0; i < 2; i++, winding_dir = -winding_dir) {
+ LinkData *el;
+ for (el = BM_edgeloop_verts_get(estore_pair[i])->first; el; el = el->next) {
+ LinkData *el_next = BM_EDGELINK_NEXT(estore_pair[i], el);
+ if (el_next) {
+ BMEdge *e = BM_edge_exists(el->data, el_next->data);
+ if (e && BM_edge_is_boundary(e)) {
+ winding_votes[i] += ((e->l->v == el->data) ? winding_dir : -winding_dir);
+ }
+ }
+ }
+ }
+
+ if (winding_votes[0] || winding_votes[1]) {
+ bool flip[2] = {false, false};
+
+ /* for direction aligned loops we can't rely on the directly we have,
+ * use the winding defined by the connected faces (see T48356). */
+ if (fabsf(dot_a) < eps) {
+ if (winding_votes[0] < 0) {
+ flip[0] = !flip[0];
+ winding_votes[0] *= -1;
+ }
+ }
+ if (fabsf(dot_b) < eps) {
+ if (winding_votes[1] < 0) {
+ flip[1] = !flip[1];
+ winding_votes[1] *= -1;
+ }
+ }
+
+ /* when both loops contradict the winding, flip them so surrounding geometry matches */
+ if ((winding_votes[0] + winding_votes[1]) < 0) {
+ flip[0] = !flip[0];
+ flip[1] = !flip[1];
+
+ /* valid but unused */
#if 0
- winding_votes[0] *= -1;
- winding_votes[1] *= -1;
+ winding_votes[0] *= -1;
+ winding_votes[1] *= -1;
#endif
- }
-
- if (flip[0]) {
- BM_edgeloop_flip(bm, el_store_a);
- }
- if (flip[1]) {
- BM_edgeloop_flip(bm, el_store_b);
- }
- }
- }
- }
-
- if (el_store_a_len > el_store_b_len) {
- el_store_b = BM_edgeloop_copy(el_store_b);
- BM_edgeloop_expand(bm, el_store_b, el_store_a_len, false, NULL);
- el_store_b_free = true;
- }
-
- if (is_closed) {
- bm_bridge_best_rotation(el_store_a, el_store_b);
-
- /* add twist */
- if (twist_offset != 0) {
- const int len_b = BM_edgeloop_length_get(el_store_b);
- ListBase *lb_b = BM_edgeloop_verts_get(el_store_b);
- LinkData *el_b = BLI_rfindlink(lb_b, mod_i(twist_offset, len_b));
- BLI_listbase_rotate_first(lb_b, el_b);
- }
- }
-
- /* Assign after flipping is finalized */
- el_a_first = BM_edgeloop_verts_get(el_store_a)->first;
- el_b_first = BM_edgeloop_verts_get(el_store_b)->first;
-
-
- if (use_merge) {
- bm_bridge_splice_loops(bm, el_a_first, el_b_first, merge_factor);
- }
- else {
- LinkData *el_a = el_a_first;
- LinkData *el_b = el_b_first;
-
- LinkData *el_a_next;
- LinkData *el_b_next;
-
-
- while (true) {
- BMFace *f, *f_example;
- BMLoop *l_iter;
- BMVert *v_a, *v_b, *v_a_next, *v_b_next;
-
- BMLoop *l_a = NULL;
- BMLoop *l_b = NULL;
- BMLoop *l_a_next = NULL;
- BMLoop *l_b_next = NULL;
-
- if (is_closed) {
- el_a_next = BM_EDGELINK_NEXT(el_store_a, el_a);
- el_b_next = BM_EDGELINK_NEXT(el_store_b, el_b);
- }
- else {
- el_a_next = el_a->next;
- el_b_next = el_b->next;
- if (ELEM(NULL, el_a_next, el_b_next)) {
- break;
- }
- }
-
- v_a = el_a->data;
- v_b = el_b->data;
- v_a_next = el_a_next->data;
- v_b_next = el_b_next->data;
-
- /* get loop data - before making the face */
- if (v_b != v_b_next) {
- bm_vert_loop_pair(bm, v_a, v_a_next, &l_a, &l_a_next);
- bm_vert_loop_pair(bm, v_b, v_b_next, &l_b, &l_b_next);
- }
- else {
- /* lazy, could be more clever here */
- bm_vert_loop_pair(bm, v_a, v_a_next, &l_a, &l_a_next);
- l_b = l_b_next = BM_iter_at_index(bm, BM_LOOPS_OF_VERT, v_b, 0);
- }
-
- if (l_a && l_a_next == NULL) { l_a_next = l_a; }
- if (l_a_next && l_a == NULL) { l_a = l_a_next; }
- if (l_b && l_b_next == NULL) { l_b_next = l_b; }
- if (l_b_next && l_b == NULL) { l_b = l_b_next; }
- f_example = l_a ? l_a->f : (l_b ? l_b->f : NULL);
-
- if (v_b != v_b_next) {
- BMVert *v_arr[4] = {v_a, v_b, v_b_next, v_a_next};
- f = BM_face_exists(v_arr, 4);
- if (f == NULL) {
- /* copy if loop data if its is missing on one ring */
- f = BM_face_create_verts(bm, v_arr, 4, NULL, BM_CREATE_NOP, true);
-
- l_iter = BM_FACE_FIRST_LOOP(f);
- if (l_b) { BM_elem_attrs_copy(bm, bm, l_b, l_iter); } l_iter = l_iter->next;
- if (l_b_next) { BM_elem_attrs_copy(bm, bm, l_b_next, l_iter); } l_iter = l_iter->next;
- if (l_a_next) { BM_elem_attrs_copy(bm, bm, l_a_next, l_iter); } l_iter = l_iter->next;
- if (l_a) { BM_elem_attrs_copy(bm, bm, l_a, l_iter); }
- }
- }
- else {
- BMVert *v_arr[3] = {v_a, v_b, v_a_next};
- f = BM_face_exists(v_arr, 3);
- if (f == NULL) {
- /* fan-fill a triangle */
- f = BM_face_create_verts(bm, v_arr, 3, NULL, BM_CREATE_NOP, true);
-
- l_iter = BM_FACE_FIRST_LOOP(f);
- if (l_b) { BM_elem_attrs_copy(bm, bm, l_b, l_iter); } l_iter = l_iter->next;
- if (l_a_next) { BM_elem_attrs_copy(bm, bm, l_a_next, l_iter); } l_iter = l_iter->next;
- if (l_a) { BM_elem_attrs_copy(bm, bm, l_a, l_iter); }
- }
- }
-
- if (f_example && (f_example != f)) {
- BM_elem_attrs_copy(bm, bm, f_example, f);
- }
- BMO_face_flag_enable(bm, f, FACE_OUT);
- BM_elem_flag_enable(f, BM_ELEM_TAG);
-
- /* tag all edges of the face, untag the loop edges after */
- if (use_edgeout) {
- bm_face_edges_tag_out(bm, f);
- }
-
- if (el_a_next == el_a_first) {
- break;
- }
-
- el_a = el_a_next;
- el_b = el_b_next;
- }
- }
-
- if (el_store_a_len != el_store_b_len) {
- struct BMEdgeLoopStore *estore_pair[2] = {el_store_a, el_store_b};
- int i;
-
- BMOperator op_sub;
- /* when we have to bridge between different sized edge-loops,
- * be clever and post-process for best results */
-
-
- /* triangulate inline */
- BMO_op_initf(bm, &op_sub, 0,
- "triangulate faces=%hf",
- BM_ELEM_TAG, true);
- /* calc normals for input faces before executing */
- {
- BMOIter siter;
- BMFace *f;
- BMO_ITER (f, &siter, op_sub.slots_in, "faces", BM_FACE) {
- BM_face_normal_update(f);
- }
- }
- BMO_op_exec(bm, &op_sub);
- BMO_slot_buffer_flag_enable(bm, op_sub.slots_out, "faces.out", BM_FACE, FACE_OUT);
- BMO_slot_buffer_hflag_enable(bm, op_sub.slots_out, "faces.out", BM_FACE, BM_ELEM_TAG, false);
- BMO_op_finish(bm, &op_sub);
-
-
- /* tag verts on each side so we can restrict rotation of edges to verts on the same side */
- for (i = 0; i < 2; i++) {
- LinkData *el;
- for (el = BM_edgeloop_verts_get(estore_pair[i])->first; el; el = el->next) {
- BM_elem_flag_set((BMVert *)el->data, BM_ELEM_TAG, i);
- }
- }
-
-
- BMO_op_initf(bm, &op_sub, 0,
- "beautify_fill faces=%hf edges=ae use_restrict_tag=%b method=%i",
- BM_ELEM_TAG, true, 1);
-
- if (use_edgeout) {
- BMOIter siter;
- BMFace *f;
- BMO_ITER (f, &siter, op_sub.slots_in, "faces", BM_FACE) {
- BMO_face_flag_enable(bm, f, FACE_OUT);
- bm_face_edges_tag_out(bm, f);
- }
- }
-
- BMO_op_exec(bm, &op_sub);
- /* there may also be tagged faces that didnt rotate, mark input */
-
- if (use_edgeout) {
- BMOIter siter;
- BMFace *f;
- BMO_ITER (f, &siter, op_sub.slots_out, "geom.out", BM_FACE) {
- BMO_face_flag_enable(bm, f, FACE_OUT);
- bm_face_edges_tag_out(bm, f);
- }
- }
- else {
- BMO_slot_buffer_flag_enable(bm, op_sub.slots_out, "geom.out", BM_FACE, FACE_OUT);
- }
-
- BMO_op_finish(bm, &op_sub);
- }
-
- if (use_edgeout && use_merge == false) {
- /* we've enabled all face edges above, now disable all loop edges */
- struct BMEdgeLoopStore *estore_pair[2] = {el_store_a, el_store_b};
- int i;
- for (i = 0; i < 2; i++) {
- LinkData *el;
- for (el = BM_edgeloop_verts_get(estore_pair[i])->first; el; el = el->next) {
- LinkData *el_next = BM_EDGELINK_NEXT(estore_pair[i], el);
- if (el_next) {
- if (el->data != el_next->data) {
- BMEdge *e = BM_edge_exists(el->data, el_next->data);
- BMO_edge_flag_disable(bm, e, EDGE_OUT);
- }
- }
- }
- }
- }
-
- if (el_store_b_free) {
- BM_edgeloop_free(el_store_b);
- }
+ }
+
+ if (flip[0]) {
+ BM_edgeloop_flip(bm, el_store_a);
+ }
+ if (flip[1]) {
+ BM_edgeloop_flip(bm, el_store_b);
+ }
+ }
+ }
+ }
+
+ if (el_store_a_len > el_store_b_len) {
+ el_store_b = BM_edgeloop_copy(el_store_b);
+ BM_edgeloop_expand(bm, el_store_b, el_store_a_len, false, NULL);
+ el_store_b_free = true;
+ }
+
+ if (is_closed) {
+ bm_bridge_best_rotation(el_store_a, el_store_b);
+
+ /* add twist */
+ if (twist_offset != 0) {
+ const int len_b = BM_edgeloop_length_get(el_store_b);
+ ListBase *lb_b = BM_edgeloop_verts_get(el_store_b);
+ LinkData *el_b = BLI_rfindlink(lb_b, mod_i(twist_offset, len_b));
+ BLI_listbase_rotate_first(lb_b, el_b);
+ }
+ }
+
+ /* Assign after flipping is finalized */
+ el_a_first = BM_edgeloop_verts_get(el_store_a)->first;
+ el_b_first = BM_edgeloop_verts_get(el_store_b)->first;
+
+ if (use_merge) {
+ bm_bridge_splice_loops(bm, el_a_first, el_b_first, merge_factor);
+ }
+ else {
+ LinkData *el_a = el_a_first;
+ LinkData *el_b = el_b_first;
+
+ LinkData *el_a_next;
+ LinkData *el_b_next;
+
+ while (true) {
+ BMFace *f, *f_example;
+ BMLoop *l_iter;
+ BMVert *v_a, *v_b, *v_a_next, *v_b_next;
+
+ BMLoop *l_a = NULL;
+ BMLoop *l_b = NULL;
+ BMLoop *l_a_next = NULL;
+ BMLoop *l_b_next = NULL;
+
+ if (is_closed) {
+ el_a_next = BM_EDGELINK_NEXT(el_store_a, el_a);
+ el_b_next = BM_EDGELINK_NEXT(el_store_b, el_b);
+ }
+ else {
+ el_a_next = el_a->next;
+ el_b_next = el_b->next;
+ if (ELEM(NULL, el_a_next, el_b_next)) {
+ break;
+ }
+ }
+
+ v_a = el_a->data;
+ v_b = el_b->data;
+ v_a_next = el_a_next->data;
+ v_b_next = el_b_next->data;
+
+ /* get loop data - before making the face */
+ if (v_b != v_b_next) {
+ bm_vert_loop_pair(bm, v_a, v_a_next, &l_a, &l_a_next);
+ bm_vert_loop_pair(bm, v_b, v_b_next, &l_b, &l_b_next);
+ }
+ else {
+ /* lazy, could be more clever here */
+ bm_vert_loop_pair(bm, v_a, v_a_next, &l_a, &l_a_next);
+ l_b = l_b_next = BM_iter_at_index(bm, BM_LOOPS_OF_VERT, v_b, 0);
+ }
+
+ if (l_a && l_a_next == NULL) {
+ l_a_next = l_a;
+ }
+ if (l_a_next && l_a == NULL) {
+ l_a = l_a_next;
+ }
+ if (l_b && l_b_next == NULL) {
+ l_b_next = l_b;
+ }
+ if (l_b_next && l_b == NULL) {
+ l_b = l_b_next;
+ }
+ f_example = l_a ? l_a->f : (l_b ? l_b->f : NULL);
+
+ if (v_b != v_b_next) {
+ BMVert *v_arr[4] = {v_a, v_b, v_b_next, v_a_next};
+ f = BM_face_exists(v_arr, 4);
+ if (f == NULL) {
+ /* copy if loop data if its is missing on one ring */
+ f = BM_face_create_verts(bm, v_arr, 4, NULL, BM_CREATE_NOP, true);
+
+ l_iter = BM_FACE_FIRST_LOOP(f);
+ if (l_b) {
+ BM_elem_attrs_copy(bm, bm, l_b, l_iter);
+ }
+ l_iter = l_iter->next;
+ if (l_b_next) {
+ BM_elem_attrs_copy(bm, bm, l_b_next, l_iter);
+ }
+ l_iter = l_iter->next;
+ if (l_a_next) {
+ BM_elem_attrs_copy(bm, bm, l_a_next, l_iter);
+ }
+ l_iter = l_iter->next;
+ if (l_a) {
+ BM_elem_attrs_copy(bm, bm, l_a, l_iter);
+ }
+ }
+ }
+ else {
+ BMVert *v_arr[3] = {v_a, v_b, v_a_next};
+ f = BM_face_exists(v_arr, 3);
+ if (f == NULL) {
+ /* fan-fill a triangle */
+ f = BM_face_create_verts(bm, v_arr, 3, NULL, BM_CREATE_NOP, true);
+
+ l_iter = BM_FACE_FIRST_LOOP(f);
+ if (l_b) {
+ BM_elem_attrs_copy(bm, bm, l_b, l_iter);
+ }
+ l_iter = l_iter->next;
+ if (l_a_next) {
+ BM_elem_attrs_copy(bm, bm, l_a_next, l_iter);
+ }
+ l_iter = l_iter->next;
+ if (l_a) {
+ BM_elem_attrs_copy(bm, bm, l_a, l_iter);
+ }
+ }
+ }
+
+ if (f_example && (f_example != f)) {
+ BM_elem_attrs_copy(bm, bm, f_example, f);
+ }
+ BMO_face_flag_enable(bm, f, FACE_OUT);
+ BM_elem_flag_enable(f, BM_ELEM_TAG);
+
+ /* tag all edges of the face, untag the loop edges after */
+ if (use_edgeout) {
+ bm_face_edges_tag_out(bm, f);
+ }
+
+ if (el_a_next == el_a_first) {
+ break;
+ }
+
+ el_a = el_a_next;
+ el_b = el_b_next;
+ }
+ }
+
+ if (el_store_a_len != el_store_b_len) {
+ struct BMEdgeLoopStore *estore_pair[2] = {el_store_a, el_store_b};
+ int i;
+
+ BMOperator op_sub;
+ /* when we have to bridge between different sized edge-loops,
+ * be clever and post-process for best results */
+
+ /* triangulate inline */
+ BMO_op_initf(bm, &op_sub, 0, "triangulate faces=%hf", BM_ELEM_TAG, true);
+ /* calc normals for input faces before executing */
+ {
+ BMOIter siter;
+ BMFace *f;
+ BMO_ITER (f, &siter, op_sub.slots_in, "faces", BM_FACE) {
+ BM_face_normal_update(f);
+ }
+ }
+ BMO_op_exec(bm, &op_sub);
+ BMO_slot_buffer_flag_enable(bm, op_sub.slots_out, "faces.out", BM_FACE, FACE_OUT);
+ BMO_slot_buffer_hflag_enable(bm, op_sub.slots_out, "faces.out", BM_FACE, BM_ELEM_TAG, false);
+ BMO_op_finish(bm, &op_sub);
+
+ /* tag verts on each side so we can restrict rotation of edges to verts on the same side */
+ for (i = 0; i < 2; i++) {
+ LinkData *el;
+ for (el = BM_edgeloop_verts_get(estore_pair[i])->first; el; el = el->next) {
+ BM_elem_flag_set((BMVert *)el->data, BM_ELEM_TAG, i);
+ }
+ }
+
+ BMO_op_initf(bm,
+ &op_sub,
+ 0,
+ "beautify_fill faces=%hf edges=ae use_restrict_tag=%b method=%i",
+ BM_ELEM_TAG,
+ true,
+ 1);
+
+ if (use_edgeout) {
+ BMOIter siter;
+ BMFace *f;
+ BMO_ITER (f, &siter, op_sub.slots_in, "faces", BM_FACE) {
+ BMO_face_flag_enable(bm, f, FACE_OUT);
+ bm_face_edges_tag_out(bm, f);
+ }
+ }
+
+ BMO_op_exec(bm, &op_sub);
+ /* there may also be tagged faces that didnt rotate, mark input */
+
+ if (use_edgeout) {
+ BMOIter siter;
+ BMFace *f;
+ BMO_ITER (f, &siter, op_sub.slots_out, "geom.out", BM_FACE) {
+ BMO_face_flag_enable(bm, f, FACE_OUT);
+ bm_face_edges_tag_out(bm, f);
+ }
+ }
+ else {
+ BMO_slot_buffer_flag_enable(bm, op_sub.slots_out, "geom.out", BM_FACE, FACE_OUT);
+ }
+
+ BMO_op_finish(bm, &op_sub);
+ }
+
+ if (use_edgeout && use_merge == false) {
+ /* we've enabled all face edges above, now disable all loop edges */
+ struct BMEdgeLoopStore *estore_pair[2] = {el_store_a, el_store_b};
+ int i;
+ for (i = 0; i < 2; i++) {
+ LinkData *el;
+ for (el = BM_edgeloop_verts_get(estore_pair[i])->first; el; el = el->next) {
+ LinkData *el_next = BM_EDGELINK_NEXT(estore_pair[i], el);
+ if (el_next) {
+ if (el->data != el_next->data) {
+ BMEdge *e = BM_edge_exists(el->data, el_next->data);
+ BMO_edge_flag_disable(bm, e, EDGE_OUT);
+ }
+ }
+ }
+ }
+ }
+
+ if (el_store_b_free) {
+ BM_edgeloop_free(el_store_b);
+ }
}
void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op)
{
- ListBase eloops = {NULL};
- LinkData *el_store;
-
- /* merge-bridge support */
- const bool use_pairs = BMO_slot_bool_get(op->slots_in, "use_pairs");
- const bool use_merge = BMO_slot_bool_get(op->slots_in, "use_merge");
- const float merge_factor = BMO_slot_float_get(op->slots_in, "merge_factor");
- const bool use_cyclic = BMO_slot_bool_get(op->slots_in, "use_cyclic") && (use_merge == false);
- const int twist_offset = BMO_slot_int_get(op->slots_in, "twist_offset");
- int count;
- bool changed = false;
-
- BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK);
-
- count = BM_mesh_edgeloops_find(bm, &eloops, bm_edge_test_cb, bm);
-
- BM_mesh_edgeloops_calc_center(bm, &eloops);
-
- if (count < 2) {
- BMO_error_raise(bm, op, BMERR_INVALID_SELECTION,
- "Select at least two edge loops");
- goto cleanup;
- }
-
- if (use_pairs && (count % 2)) {
- BMO_error_raise(bm, op, BMERR_INVALID_SELECTION,
- "Select an even number of loops to bridge pairs");
- goto cleanup;
- }
-
- if (use_merge) {
- bool match = true;
- const int eloop_len = BM_edgeloop_length_get(eloops.first);
- for (el_store = eloops.first; el_store; el_store = el_store->next) {
- if (eloop_len != BM_edgeloop_length_get((struct BMEdgeLoopStore *)el_store)) {
- match = false;
- break;
- }
- }
- if (!match) {
- BMO_error_raise(bm, op, BMERR_INVALID_SELECTION,
- "Selected loops must have equal edge counts");
- goto cleanup;
- }
- }
-
- if (count > 2) {
- if (use_pairs) {
- BM_mesh_edgeloops_calc_normal(bm, &eloops);
- }
- BM_mesh_edgeloops_calc_order(bm, &eloops, use_pairs);
- }
-
- for (el_store = eloops.first; el_store; el_store = el_store->next) {
- LinkData *el_store_next = el_store->next;
-
- if (el_store_next == NULL) {
- if (use_cyclic && (count > 2)) {
- el_store_next = eloops.first;
- }
- else {
- break;
- }
- }
-
- bridge_loop_pair(bm,
- (struct BMEdgeLoopStore *)el_store,
- (struct BMEdgeLoopStore *)el_store_next,
- use_merge, merge_factor, twist_offset);
- if (use_pairs) {
- el_store = el_store->next;
- }
- changed = true;
- }
+ ListBase eloops = {NULL};
+ LinkData *el_store;
+
+ /* merge-bridge support */
+ const bool use_pairs = BMO_slot_bool_get(op->slots_in, "use_pairs");
+ const bool use_merge = BMO_slot_bool_get(op->slots_in, "use_merge");
+ const float merge_factor = BMO_slot_float_get(op->slots_in, "merge_factor");
+ const bool use_cyclic = BMO_slot_bool_get(op->slots_in, "use_cyclic") && (use_merge == false);
+ const int twist_offset = BMO_slot_int_get(op->slots_in, "twist_offset");
+ int count;
+ bool changed = false;
+
+ BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK);
+
+ count = BM_mesh_edgeloops_find(bm, &eloops, bm_edge_test_cb, bm);
+
+ BM_mesh_edgeloops_calc_center(bm, &eloops);
+
+ if (count < 2) {
+ BMO_error_raise(bm, op, BMERR_INVALID_SELECTION, "Select at least two edge loops");
+ goto cleanup;
+ }
+
+ if (use_pairs && (count % 2)) {
+ BMO_error_raise(
+ bm, op, BMERR_INVALID_SELECTION, "Select an even number of loops to bridge pairs");
+ goto cleanup;
+ }
+
+ if (use_merge) {
+ bool match = true;
+ const int eloop_len = BM_edgeloop_length_get(eloops.first);
+ for (el_store = eloops.first; el_store; el_store = el_store->next) {
+ if (eloop_len != BM_edgeloop_length_get((struct BMEdgeLoopStore *)el_store)) {
+ match = false;
+ break;
+ }
+ }
+ if (!match) {
+ BMO_error_raise(
+ bm, op, BMERR_INVALID_SELECTION, "Selected loops must have equal edge counts");
+ goto cleanup;
+ }
+ }
+
+ if (count > 2) {
+ if (use_pairs) {
+ BM_mesh_edgeloops_calc_normal(bm, &eloops);
+ }
+ BM_mesh_edgeloops_calc_order(bm, &eloops, use_pairs);
+ }
+
+ for (el_store = eloops.first; el_store; el_store = el_store->next) {
+ LinkData *el_store_next = el_store->next;
+
+ if (el_store_next == NULL) {
+ if (use_cyclic && (count > 2)) {
+ el_store_next = eloops.first;
+ }
+ else {
+ break;
+ }
+ }
+
+ bridge_loop_pair(bm,
+ (struct BMEdgeLoopStore *)el_store,
+ (struct BMEdgeLoopStore *)el_store_next,
+ use_merge,
+ merge_factor,
+ twist_offset);
+ if (use_pairs) {
+ el_store = el_store->next;
+ }
+ changed = true;
+ }
cleanup:
- BM_mesh_edgeloops_free(&eloops);
-
- if (changed) {
- if (use_merge == false) {
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_OUT);
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT);
- }
- }
+ BM_mesh_edgeloops_free(&eloops);
+
+ if (changed) {
+ if (use_merge == false) {
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_OUT);
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT);
+ }
+ }
}
diff --git a/source/blender/bmesh/operators/bmo_connect.c b/source/blender/bmesh/operators/bmo_connect.c
index d3cf3f2d945..e52467614ac 100644
--- a/source/blender/bmesh/operators/bmo_connect.c
+++ b/source/blender/bmesh/operators/bmo_connect.c
@@ -29,167 +29,163 @@
#include "intern/bmesh_operators_private.h" /* own include */
-#define VERT_INPUT 1
+#define VERT_INPUT 1
-#define EDGE_OUT 1
+#define EDGE_OUT 1
/* Edge spans 2 VERT_INPUT's, its a nop,
* but include in "edges.out" */
-#define EDGE_OUT_ADJ 2
+#define EDGE_OUT_ADJ 2
-#define FACE_TAG 2
-#define FACE_EXCLUDE 4
+#define FACE_TAG 2
+#define FACE_EXCLUDE 4
static int bm_face_connect_verts(BMesh *bm, BMFace *f, const bool check_degenerate)
{
- const unsigned pair_split_max = f->len / 2;
- BMLoop *(*loops_split)[2] = BLI_array_alloca(loops_split, pair_split_max);
- STACK_DECLARE(loops_split);
- BMVert *(*verts_pair)[2] = BLI_array_alloca(verts_pair, pair_split_max);
- STACK_DECLARE(verts_pair);
-
- BMLoop *l_tag_prev = NULL, *l_tag_first = NULL;
- BMLoop *l_iter, *l_first;
- uint i;
-
- STACK_INIT(loops_split, pair_split_max);
- STACK_INIT(verts_pair, pair_split_max);
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if (BMO_vert_flag_test(bm, l_iter->v, VERT_INPUT) &&
- /* ensure this vertex isnt part of a contiguous group */
- ((BMO_vert_flag_test(bm, l_iter->prev->v, VERT_INPUT) == 0) ||
- (BMO_vert_flag_test(bm, l_iter->next->v, VERT_INPUT) == 0)))
- {
- if (!l_tag_prev) {
- l_tag_prev = l_tag_first = l_iter;
- continue;
- }
-
- if (!BM_loop_is_adjacent(l_tag_prev, l_iter)) {
- BMEdge *e;
- e = BM_edge_exists(l_tag_prev->v, l_iter->v);
- if (e == NULL || !BMO_edge_flag_test(bm, e, EDGE_OUT)) {
- BMLoop **l_pair = STACK_PUSH_RET(loops_split);
- l_pair[0] = l_tag_prev;
- l_pair[1] = l_iter;
- }
- }
-
- l_tag_prev = l_iter;
- }
- } while ((l_iter = l_iter->next) != l_first);
-
- if (STACK_SIZE(loops_split) == 0) {
- return 0;
- }
-
- if (!BM_loop_is_adjacent(l_tag_first, l_tag_prev) &&
- /* ensure we don't add the same pair twice */
- (((loops_split[0][0] == l_tag_first) &&
- (loops_split[0][1] == l_tag_prev)) == 0))
- {
- BMLoop **l_pair = STACK_PUSH_RET(loops_split);
- l_pair[0] = l_tag_first;
- l_pair[1] = l_tag_prev;
- }
-
- if (check_degenerate) {
- BM_face_splits_check_legal(bm, f, loops_split, STACK_SIZE(loops_split));
- }
- else {
- BM_face_splits_check_optimal(f, loops_split, STACK_SIZE(loops_split));
- }
-
- for (i = 0; i < STACK_SIZE(loops_split); i++) {
- BMVert **v_pair;
- if (loops_split[i][0] == NULL) {
- continue;
- }
-
- v_pair = STACK_PUSH_RET(verts_pair);
- v_pair[0] = loops_split[i][0]->v;
- v_pair[1] = loops_split[i][1]->v;
- }
-
- for (i = 0; i < STACK_SIZE(verts_pair); i++) {
- BMFace *f_new;
- BMLoop *l_new;
- BMLoop *l_a, *l_b;
-
- if ((l_a = BM_face_vert_share_loop(f, verts_pair[i][0])) &&
- (l_b = BM_face_vert_share_loop(f, verts_pair[i][1])))
- {
- f_new = BM_face_split(bm, f, l_a, l_b, &l_new, NULL, false);
- }
- else {
- f_new = NULL;
- l_new = NULL;
- }
-
- f = f_new;
-
- if (!l_new || !f_new) {
- return -1;
- }
- // BMO_face_flag_enable(bm, f_new, FACE_NEW);
- BMO_edge_flag_enable(bm, l_new->e, EDGE_OUT);
- }
-
- return 1;
+ const unsigned pair_split_max = f->len / 2;
+ BMLoop *(*loops_split)[2] = BLI_array_alloca(loops_split, pair_split_max);
+ STACK_DECLARE(loops_split);
+ BMVert *(*verts_pair)[2] = BLI_array_alloca(verts_pair, pair_split_max);
+ STACK_DECLARE(verts_pair);
+
+ BMLoop *l_tag_prev = NULL, *l_tag_first = NULL;
+ BMLoop *l_iter, *l_first;
+ uint i;
+
+ STACK_INIT(loops_split, pair_split_max);
+ STACK_INIT(verts_pair, pair_split_max);
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (BMO_vert_flag_test(bm, l_iter->v, VERT_INPUT) &&
+ /* ensure this vertex isnt part of a contiguous group */
+ ((BMO_vert_flag_test(bm, l_iter->prev->v, VERT_INPUT) == 0) ||
+ (BMO_vert_flag_test(bm, l_iter->next->v, VERT_INPUT) == 0))) {
+ if (!l_tag_prev) {
+ l_tag_prev = l_tag_first = l_iter;
+ continue;
+ }
+
+ if (!BM_loop_is_adjacent(l_tag_prev, l_iter)) {
+ BMEdge *e;
+ e = BM_edge_exists(l_tag_prev->v, l_iter->v);
+ if (e == NULL || !BMO_edge_flag_test(bm, e, EDGE_OUT)) {
+ BMLoop **l_pair = STACK_PUSH_RET(loops_split);
+ l_pair[0] = l_tag_prev;
+ l_pair[1] = l_iter;
+ }
+ }
+
+ l_tag_prev = l_iter;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+
+ if (STACK_SIZE(loops_split) == 0) {
+ return 0;
+ }
+
+ if (!BM_loop_is_adjacent(l_tag_first, l_tag_prev) &&
+ /* ensure we don't add the same pair twice */
+ (((loops_split[0][0] == l_tag_first) && (loops_split[0][1] == l_tag_prev)) == 0)) {
+ BMLoop **l_pair = STACK_PUSH_RET(loops_split);
+ l_pair[0] = l_tag_first;
+ l_pair[1] = l_tag_prev;
+ }
+
+ if (check_degenerate) {
+ BM_face_splits_check_legal(bm, f, loops_split, STACK_SIZE(loops_split));
+ }
+ else {
+ BM_face_splits_check_optimal(f, loops_split, STACK_SIZE(loops_split));
+ }
+
+ for (i = 0; i < STACK_SIZE(loops_split); i++) {
+ BMVert **v_pair;
+ if (loops_split[i][0] == NULL) {
+ continue;
+ }
+
+ v_pair = STACK_PUSH_RET(verts_pair);
+ v_pair[0] = loops_split[i][0]->v;
+ v_pair[1] = loops_split[i][1]->v;
+ }
+
+ for (i = 0; i < STACK_SIZE(verts_pair); i++) {
+ BMFace *f_new;
+ BMLoop *l_new;
+ BMLoop *l_a, *l_b;
+
+ if ((l_a = BM_face_vert_share_loop(f, verts_pair[i][0])) &&
+ (l_b = BM_face_vert_share_loop(f, verts_pair[i][1]))) {
+ f_new = BM_face_split(bm, f, l_a, l_b, &l_new, NULL, false);
+ }
+ else {
+ f_new = NULL;
+ l_new = NULL;
+ }
+
+ f = f_new;
+
+ if (!l_new || !f_new) {
+ return -1;
+ }
+ // BMO_face_flag_enable(bm, f_new, FACE_NEW);
+ BMO_edge_flag_enable(bm, l_new->e, EDGE_OUT);
+ }
+
+ return 1;
}
-
void bmo_connect_verts_exec(BMesh *bm, BMOperator *op)
{
- BMOIter siter;
- BMVert *v;
- BMFace *f;
- const bool check_degenerate = BMO_slot_bool_get(op->slots_in, "check_degenerate");
- BLI_LINKSTACK_DECLARE(faces, BMFace *);
-
- BLI_LINKSTACK_INIT(faces);
-
- /* tag so we won't touch ever (typically hidden faces) */
- BMO_slot_buffer_flag_enable(bm, op->slots_in, "faces_exclude", BM_FACE, FACE_EXCLUDE);
-
- /* add all faces connected to verts */
- BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
- BMIter iter;
- BMLoop *l_iter;
-
- BMO_vert_flag_enable(bm, v, VERT_INPUT);
- BM_ITER_ELEM (l_iter, &iter, v, BM_LOOPS_OF_VERT) {
- f = l_iter->f;
- if (!BMO_face_flag_test(bm, f, FACE_EXCLUDE)) {
- if (!BMO_face_flag_test(bm, f, FACE_TAG)) {
- BMO_face_flag_enable(bm, f, FACE_TAG);
- if (f->len > 3) {
- BLI_LINKSTACK_PUSH(faces, f);
- }
- }
- }
-
- /* flag edges even if these are not newly created
- * this way cut-pairs that include co-linear edges will get
- * predictable output. */
- if (BMO_vert_flag_test(bm, l_iter->prev->v, VERT_INPUT)) {
- BMO_edge_flag_enable(bm, l_iter->prev->e, EDGE_OUT_ADJ);
- }
- if (BMO_vert_flag_test(bm, l_iter->next->v, VERT_INPUT)) {
- BMO_edge_flag_enable(bm, l_iter->e, EDGE_OUT_ADJ);
- }
- }
- }
-
- /* connect faces */
- while ((f = BLI_LINKSTACK_POP(faces))) {
- if (bm_face_connect_verts(bm, f, check_degenerate) == -1) {
- BMO_error_raise(bm, op, BMERR_CONNECTVERT_FAILED, NULL);
- }
- }
-
- BLI_LINKSTACK_FREE(faces);
-
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT | EDGE_OUT_ADJ);
+ BMOIter siter;
+ BMVert *v;
+ BMFace *f;
+ const bool check_degenerate = BMO_slot_bool_get(op->slots_in, "check_degenerate");
+ BLI_LINKSTACK_DECLARE(faces, BMFace *);
+
+ BLI_LINKSTACK_INIT(faces);
+
+ /* tag so we won't touch ever (typically hidden faces) */
+ BMO_slot_buffer_flag_enable(bm, op->slots_in, "faces_exclude", BM_FACE, FACE_EXCLUDE);
+
+ /* add all faces connected to verts */
+ BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
+ BMIter iter;
+ BMLoop *l_iter;
+
+ BMO_vert_flag_enable(bm, v, VERT_INPUT);
+ BM_ITER_ELEM (l_iter, &iter, v, BM_LOOPS_OF_VERT) {
+ f = l_iter->f;
+ if (!BMO_face_flag_test(bm, f, FACE_EXCLUDE)) {
+ if (!BMO_face_flag_test(bm, f, FACE_TAG)) {
+ BMO_face_flag_enable(bm, f, FACE_TAG);
+ if (f->len > 3) {
+ BLI_LINKSTACK_PUSH(faces, f);
+ }
+ }
+ }
+
+ /* flag edges even if these are not newly created
+ * this way cut-pairs that include co-linear edges will get
+ * predictable output. */
+ if (BMO_vert_flag_test(bm, l_iter->prev->v, VERT_INPUT)) {
+ BMO_edge_flag_enable(bm, l_iter->prev->e, EDGE_OUT_ADJ);
+ }
+ if (BMO_vert_flag_test(bm, l_iter->next->v, VERT_INPUT)) {
+ BMO_edge_flag_enable(bm, l_iter->e, EDGE_OUT_ADJ);
+ }
+ }
+ }
+
+ /* connect faces */
+ while ((f = BLI_LINKSTACK_POP(faces))) {
+ if (bm_face_connect_verts(bm, f, check_degenerate) == -1) {
+ BMO_error_raise(bm, op, BMERR_CONNECTVERT_FAILED, NULL);
+ }
+ }
+
+ BLI_LINKSTACK_FREE(faces);
+
+ BMO_slot_buffer_from_enabled_flag(
+ bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT | EDGE_OUT_ADJ);
}
diff --git a/source/blender/bmesh/operators/bmo_connect_concave.c b/source/blender/bmesh/operators/bmo_connect_concave.c
index 98527482f52..0d0c21774c3 100644
--- a/source/blender/bmesh/operators/bmo_connect_concave.c
+++ b/source/blender/bmesh/operators/bmo_connect_concave.c
@@ -43,178 +43,185 @@
#include "intern/bmesh_operators_private.h" /* own include */
-#define EDGE_OUT (1 << 0)
-#define FACE_OUT (1 << 1)
+#define EDGE_OUT (1 << 0)
+#define FACE_OUT (1 << 1)
static int bm_edge_length_cmp(const void *a_, const void *b_)
{
- const BMEdge *e_a = *(const void **)a_;
- const BMEdge *e_b = *(const void **)b_;
-
- int e_a_concave = ((BM_elem_flag_test(e_a->v1, BM_ELEM_TAG)) && (BM_elem_flag_test(e_a->v2, BM_ELEM_TAG)));
- int e_b_concave = ((BM_elem_flag_test(e_b->v1, BM_ELEM_TAG)) && (BM_elem_flag_test(e_b->v2, BM_ELEM_TAG)));
-
- /* merge edges between concave edges last since these
- * are most likely to remain and be the main dividers */
- if (e_a_concave < e_b_concave) { return -1; }
- else if (e_a_concave > e_b_concave) { return 1; }
- else {
- /* otherwise shortest edges last */
- const float e_a_len = BM_edge_calc_length_squared(e_a);
- const float e_b_len = BM_edge_calc_length_squared(e_b);
- if (e_a_len < e_b_len) { return 1; }
- else if (e_a_len > e_b_len) { return -1; }
- else { return 0; }
- }
+ const BMEdge *e_a = *(const void **)a_;
+ const BMEdge *e_b = *(const void **)b_;
+
+ int e_a_concave = ((BM_elem_flag_test(e_a->v1, BM_ELEM_TAG)) &&
+ (BM_elem_flag_test(e_a->v2, BM_ELEM_TAG)));
+ int e_b_concave = ((BM_elem_flag_test(e_b->v1, BM_ELEM_TAG)) &&
+ (BM_elem_flag_test(e_b->v2, BM_ELEM_TAG)));
+
+ /* merge edges between concave edges last since these
+ * are most likely to remain and be the main dividers */
+ if (e_a_concave < e_b_concave) {
+ return -1;
+ }
+ else if (e_a_concave > e_b_concave) {
+ return 1;
+ }
+ else {
+ /* otherwise shortest edges last */
+ const float e_a_len = BM_edge_calc_length_squared(e_a);
+ const float e_b_len = BM_edge_calc_length_squared(e_b);
+ if (e_a_len < e_b_len) {
+ return 1;
+ }
+ else if (e_a_len > e_b_len) {
+ return -1;
+ }
+ else {
+ return 0;
+ }
+ }
}
-static bool bm_face_split_by_concave(
- BMesh *bm, BMFace *f_base, const float eps,
+static bool bm_face_split_by_concave(BMesh *bm,
+ BMFace *f_base,
+ const float eps,
- MemArena *pf_arena,
- struct Heap *pf_heap)
+ MemArena *pf_arena,
+ struct Heap *pf_heap)
{
- const int f_base_len = f_base->len;
- int faces_array_tot = f_base_len - 3;
- int edges_array_tot = f_base_len - 3;
- BMFace **faces_array = BLI_array_alloca(faces_array, faces_array_tot);
- BMEdge **edges_array = BLI_array_alloca(edges_array, edges_array_tot);
- const int quad_method = 0, ngon_method = 0; /* beauty */
- LinkNode *faces_double = NULL;
-
- float normal[3];
- BLI_assert(f_base->len > 3);
-
- copy_v3_v3(normal, f_base->no);
-
- BM_face_triangulate(
- bm, f_base,
- faces_array, &faces_array_tot,
- edges_array, &edges_array_tot,
- &faces_double,
- quad_method, ngon_method, false,
- pf_arena,
- pf_heap);
-
- BLI_assert(edges_array_tot <= f_base_len - 3);
-
- if (faces_array_tot) {
- int i;
- for (i = 0; i < faces_array_tot; i++) {
- BMFace *f = faces_array[i];
- BMO_face_flag_enable(bm, f, FACE_OUT);
- }
- }
- BMO_face_flag_enable(bm, f_base, FACE_OUT);
-
- if (edges_array_tot) {
- int i;
-
- qsort(edges_array, edges_array_tot, sizeof(*edges_array), bm_edge_length_cmp);
-
- for (i = 0; i < edges_array_tot; i++) {
- BMLoop *l_pair[2];
- BMEdge *e = edges_array[i];
- BMO_edge_flag_enable(bm, e, EDGE_OUT);
-
- if (BM_edge_is_contiguous(e) &&
- BM_edge_loop_pair(e, &l_pair[0], &l_pair[1]))
- {
- bool ok = true;
- int j;
- for (j = 0; j < 2; j++) {
- BMLoop *l = l_pair[j];
-
- /* check that merging the edge (on this side)
- * wouldn't result in a convex face-loop.
- *
- * This is the (l->next, l->prev) we would have once joined.
- */
- float cross[3];
- cross_tri_v3(
- cross,
- l->v->co,
- l->radial_next->next->next->v->co,
- l->prev->v->co
- );
-
- if (dot_v3v3(cross, normal) <= eps) {
- ok = false;
- break;
- }
- }
-
- if (ok) {
- BMFace *f_new, *f_pair[2] = {l_pair[0]->f, l_pair[1]->f};
- f_new = BM_faces_join(bm, f_pair, 2, true);
- if (f_new) {
- BMO_face_flag_enable(bm, f_new, FACE_OUT);
- }
- }
- }
- }
- }
-
- BLI_heap_clear(pf_heap, NULL);
-
- while (faces_double) {
- LinkNode *next = faces_double->next;
- BM_face_kill(bm, faces_double->link);
- MEM_freeN(faces_double);
- faces_double = next;
- }
-
- return true;
+ const int f_base_len = f_base->len;
+ int faces_array_tot = f_base_len - 3;
+ int edges_array_tot = f_base_len - 3;
+ BMFace **faces_array = BLI_array_alloca(faces_array, faces_array_tot);
+ BMEdge **edges_array = BLI_array_alloca(edges_array, edges_array_tot);
+ const int quad_method = 0, ngon_method = 0; /* beauty */
+ LinkNode *faces_double = NULL;
+
+ float normal[3];
+ BLI_assert(f_base->len > 3);
+
+ copy_v3_v3(normal, f_base->no);
+
+ BM_face_triangulate(bm,
+ f_base,
+ faces_array,
+ &faces_array_tot,
+ edges_array,
+ &edges_array_tot,
+ &faces_double,
+ quad_method,
+ ngon_method,
+ false,
+ pf_arena,
+ pf_heap);
+
+ BLI_assert(edges_array_tot <= f_base_len - 3);
+
+ if (faces_array_tot) {
+ int i;
+ for (i = 0; i < faces_array_tot; i++) {
+ BMFace *f = faces_array[i];
+ BMO_face_flag_enable(bm, f, FACE_OUT);
+ }
+ }
+ BMO_face_flag_enable(bm, f_base, FACE_OUT);
+
+ if (edges_array_tot) {
+ int i;
+
+ qsort(edges_array, edges_array_tot, sizeof(*edges_array), bm_edge_length_cmp);
+
+ for (i = 0; i < edges_array_tot; i++) {
+ BMLoop *l_pair[2];
+ BMEdge *e = edges_array[i];
+ BMO_edge_flag_enable(bm, e, EDGE_OUT);
+
+ if (BM_edge_is_contiguous(e) && BM_edge_loop_pair(e, &l_pair[0], &l_pair[1])) {
+ bool ok = true;
+ int j;
+ for (j = 0; j < 2; j++) {
+ BMLoop *l = l_pair[j];
+
+ /* check that merging the edge (on this side)
+ * wouldn't result in a convex face-loop.
+ *
+ * This is the (l->next, l->prev) we would have once joined.
+ */
+ float cross[3];
+ cross_tri_v3(cross, l->v->co, l->radial_next->next->next->v->co, l->prev->v->co);
+
+ if (dot_v3v3(cross, normal) <= eps) {
+ ok = false;
+ break;
+ }
+ }
+
+ if (ok) {
+ BMFace *f_new, *f_pair[2] = {l_pair[0]->f, l_pair[1]->f};
+ f_new = BM_faces_join(bm, f_pair, 2, true);
+ if (f_new) {
+ BMO_face_flag_enable(bm, f_new, FACE_OUT);
+ }
+ }
+ }
+ }
+ }
+
+ BLI_heap_clear(pf_heap, NULL);
+
+ while (faces_double) {
+ LinkNode *next = faces_double->next;
+ BM_face_kill(bm, faces_double->link);
+ MEM_freeN(faces_double);
+ faces_double = next;
+ }
+
+ return true;
}
static bool bm_face_convex_tag_verts(BMFace *f)
{
- bool is_concave = false;
- if (f->len > 3) {
- const BMLoop *l_iter, *l_first;
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if (BM_loop_is_convex(l_iter) == false) {
- is_concave = true;
- BM_elem_flag_enable(l_iter->v, BM_ELEM_TAG);
- }
- else {
- BM_elem_flag_disable(l_iter->v, BM_ELEM_TAG);
- }
- } while ((l_iter = l_iter->next) != l_first);
- }
- return is_concave;
+ bool is_concave = false;
+ if (f->len > 3) {
+ const BMLoop *l_iter, *l_first;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (BM_loop_is_convex(l_iter) == false) {
+ is_concave = true;
+ BM_elem_flag_enable(l_iter->v, BM_ELEM_TAG);
+ }
+ else {
+ BM_elem_flag_disable(l_iter->v, BM_ELEM_TAG);
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ return is_concave;
}
void bmo_connect_verts_concave_exec(BMesh *bm, BMOperator *op)
{
- BMOIter siter;
- BMFace *f;
- bool changed = false;
-
- MemArena *pf_arena;
- Heap *pf_heap;
-
- pf_arena = BLI_memarena_new(BLI_POLYFILL_ARENA_SIZE, __func__);
- pf_heap = BLI_heap_new_ex(BLI_POLYFILL_ALLOC_NGON_RESERVE);
-
- BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) {
- if (f->len > 3 && bm_face_convex_tag_verts(f)) {
- if (bm_face_split_by_concave(
- bm, f, FLT_EPSILON,
- pf_arena, pf_heap))
- {
- changed = true;
- }
- }
- }
-
- if (changed) {
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT);
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_OUT);
- }
-
- BLI_memarena_free(pf_arena);
- BLI_heap_free(pf_heap, NULL);
+ BMOIter siter;
+ BMFace *f;
+ bool changed = false;
+
+ MemArena *pf_arena;
+ Heap *pf_heap;
+
+ pf_arena = BLI_memarena_new(BLI_POLYFILL_ARENA_SIZE, __func__);
+ pf_heap = BLI_heap_new_ex(BLI_POLYFILL_ALLOC_NGON_RESERVE);
+
+ BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) {
+ if (f->len > 3 && bm_face_convex_tag_verts(f)) {
+ if (bm_face_split_by_concave(bm, f, FLT_EPSILON, pf_arena, pf_heap)) {
+ changed = true;
+ }
+ }
+ }
+
+ if (changed) {
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT);
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_OUT);
+ }
+
+ BLI_memarena_free(pf_arena);
+ BLI_heap_free(pf_heap, NULL);
}
diff --git a/source/blender/bmesh/operators/bmo_connect_nonplanar.c b/source/blender/bmesh/operators/bmo_connect_nonplanar.c
index 102892626f2..5be4826c7d3 100644
--- a/source/blender/bmesh/operators/bmo_connect_nonplanar.c
+++ b/source/blender/bmesh/operators/bmo_connect_nonplanar.c
@@ -29,153 +29,154 @@
#include "intern/bmesh_operators_private.h" /* own include */
-#define EDGE_OUT (1 << 0)
-#define FACE_OUT (1 << 1)
+#define EDGE_OUT (1 << 0)
+#define FACE_OUT (1 << 1)
/**
* Calculates how non-planar the face subset is.
*/
static float bm_face_subset_calc_planar(BMLoop *l_first, BMLoop *l_last, const float no[3])
{
- float axis_mat[3][3];
- float z_prev, z_curr;
- float delta_z = 0.0f;
+ float axis_mat[3][3];
+ float z_prev, z_curr;
+ float delta_z = 0.0f;
- /* Newell's Method */
- BMLoop *l_iter = l_first;
- BMLoop *l_term = l_last->next;
+ /* Newell's Method */
+ BMLoop *l_iter = l_first;
+ BMLoop *l_term = l_last->next;
- axis_dominant_v3_to_m3(axis_mat, no);
+ axis_dominant_v3_to_m3(axis_mat, no);
- z_prev = dot_m3_v3_row_z(axis_mat, l_last->v->co);
- do {
- z_curr = dot_m3_v3_row_z(axis_mat, l_iter->v->co);
- delta_z += fabsf(z_curr - z_prev);
- z_prev = z_curr;
- } while ((l_iter = l_iter->next) != l_term);
+ z_prev = dot_m3_v3_row_z(axis_mat, l_last->v->co);
+ do {
+ z_curr = dot_m3_v3_row_z(axis_mat, l_iter->v->co);
+ delta_z += fabsf(z_curr - z_prev);
+ z_prev = z_curr;
+ } while ((l_iter = l_iter->next) != l_term);
- return delta_z;
+ return delta_z;
}
static bool bm_face_split_find(BMesh *bm, BMFace *f, BMLoop *l_pair[2], float *r_angle_cos)
{
- BMLoop *l_iter, *l_first;
- BMLoop **l_arr = BLI_array_alloca(l_arr, f->len);
- const uint f_len = f->len;
- uint i_a, i_b;
- bool found = false;
-
- /* angle finding */
- float err_best = FLT_MAX;
- float angle_best_cos = -FLT_MAX;
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- i_a = 0;
- do {
- l_arr[i_a++] = l_iter;
- } while ((l_iter = l_iter->next) != l_first);
-
- /* now for the big search, O(N^2), however faces normally aren't so large */
- for (i_a = 0; i_a < f_len; i_a++) {
- BMLoop *l_a = l_arr[i_a];
- for (i_b = i_a + 2; i_b < f_len; i_b++) {
- BMLoop *l_b = l_arr[i_b];
- /* check these are not touching
- * (we could be smarter here) */
- if (!BM_loop_is_adjacent(l_a, l_b)) {
- /* first calculate normals */
- float no_a[3], no_b[3];
-
- if (BM_face_calc_normal_subset(l_a, l_b, no_a) != 0.0f &&
- BM_face_calc_normal_subset(l_b, l_a, no_b) != 0.0f)
- {
- const float err_a = bm_face_subset_calc_planar(l_a, l_b, no_a);
- const float err_b = bm_face_subset_calc_planar(l_b, l_a, no_b);
- const float err_test = err_a + err_b;
-
- if (err_test < err_best) {
- /* check we're legal (we could batch this) */
- BMLoop *l_split[2] = {l_a, l_b};
- BM_face_splits_check_legal(bm, f, &l_split, 1);
- if (l_split[0]) {
- err_best = err_test;
- l_pair[0] = l_a;
- l_pair[1] = l_b;
-
- angle_best_cos = dot_v3v3(no_a, no_b);
- found = true;
- }
- }
- }
- }
- }
- }
-
- *r_angle_cos = angle_best_cos;
-
- return found;
+ BMLoop *l_iter, *l_first;
+ BMLoop **l_arr = BLI_array_alloca(l_arr, f->len);
+ const uint f_len = f->len;
+ uint i_a, i_b;
+ bool found = false;
+
+ /* angle finding */
+ float err_best = FLT_MAX;
+ float angle_best_cos = -FLT_MAX;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ i_a = 0;
+ do {
+ l_arr[i_a++] = l_iter;
+ } while ((l_iter = l_iter->next) != l_first);
+
+ /* now for the big search, O(N^2), however faces normally aren't so large */
+ for (i_a = 0; i_a < f_len; i_a++) {
+ BMLoop *l_a = l_arr[i_a];
+ for (i_b = i_a + 2; i_b < f_len; i_b++) {
+ BMLoop *l_b = l_arr[i_b];
+ /* check these are not touching
+ * (we could be smarter here) */
+ if (!BM_loop_is_adjacent(l_a, l_b)) {
+ /* first calculate normals */
+ float no_a[3], no_b[3];
+
+ if (BM_face_calc_normal_subset(l_a, l_b, no_a) != 0.0f &&
+ BM_face_calc_normal_subset(l_b, l_a, no_b) != 0.0f) {
+ const float err_a = bm_face_subset_calc_planar(l_a, l_b, no_a);
+ const float err_b = bm_face_subset_calc_planar(l_b, l_a, no_b);
+ const float err_test = err_a + err_b;
+
+ if (err_test < err_best) {
+ /* check we're legal (we could batch this) */
+ BMLoop *l_split[2] = {l_a, l_b};
+ BM_face_splits_check_legal(bm, f, &l_split, 1);
+ if (l_split[0]) {
+ err_best = err_test;
+ l_pair[0] = l_a;
+ l_pair[1] = l_b;
+
+ angle_best_cos = dot_v3v3(no_a, no_b);
+ found = true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ *r_angle_cos = angle_best_cos;
+
+ return found;
}
-static bool bm_face_split_by_angle(BMesh *bm, BMFace *f, BMFace *r_f_pair[2], const float angle_limit_cos)
+static bool bm_face_split_by_angle(BMesh *bm,
+ BMFace *f,
+ BMFace *r_f_pair[2],
+ const float angle_limit_cos)
{
- BMLoop *l_pair[2];
- float angle_cos;
-
- if (bm_face_split_find(bm, f, l_pair, &angle_cos) && (angle_cos < angle_limit_cos)) {
- BMFace *f_new;
- BMLoop *l_new;
-
- f_new = BM_face_split(bm, f, l_pair[0], l_pair[1], &l_new, NULL, false);
- if (f_new) {
- r_f_pair[0] = f;
- r_f_pair[1] = f_new;
-
- BMO_face_flag_enable(bm, f, FACE_OUT);
- BMO_face_flag_enable(bm, f_new, FACE_OUT);
- BMO_edge_flag_enable(bm, l_new->e, EDGE_OUT);
- return true;
- }
- }
-
- return false;
-
+ BMLoop *l_pair[2];
+ float angle_cos;
+
+ if (bm_face_split_find(bm, f, l_pair, &angle_cos) && (angle_cos < angle_limit_cos)) {
+ BMFace *f_new;
+ BMLoop *l_new;
+
+ f_new = BM_face_split(bm, f, l_pair[0], l_pair[1], &l_new, NULL, false);
+ if (f_new) {
+ r_f_pair[0] = f;
+ r_f_pair[1] = f_new;
+
+ BMO_face_flag_enable(bm, f, FACE_OUT);
+ BMO_face_flag_enable(bm, f_new, FACE_OUT);
+ BMO_edge_flag_enable(bm, l_new->e, EDGE_OUT);
+ return true;
+ }
+ }
+
+ return false;
}
void bmo_connect_verts_nonplanar_exec(BMesh *bm, BMOperator *op)
{
- BMOIter siter;
- BMFace *f;
- bool changed = false;
- BLI_LINKSTACK_DECLARE(fstack, BMFace *);
-
- const float angle_limit_cos = cosf(BMO_slot_float_get(op->slots_in, "angle_limit"));
-
- BLI_LINKSTACK_INIT(fstack);
-
- BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) {
- if (f->len > 3) {
- BLI_LINKSTACK_PUSH(fstack, f);
- }
- }
-
- while ((f = BLI_LINKSTACK_POP(fstack))) {
- BMFace *f_pair[2];
- if (bm_face_split_by_angle(bm, f, f_pair, angle_limit_cos)) {
- int j;
- for (j = 0; j < 2; j++) {
- BM_face_normal_update(f_pair[j]);
- if (f_pair[j]->len > 3) {
- BLI_LINKSTACK_PUSH(fstack, f_pair[j]);
- }
- }
- changed = true;
- }
- }
-
- BLI_LINKSTACK_FREE(fstack);
-
- if (changed) {
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT);
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_OUT);
- }
+ BMOIter siter;
+ BMFace *f;
+ bool changed = false;
+ BLI_LINKSTACK_DECLARE(fstack, BMFace *);
+
+ const float angle_limit_cos = cosf(BMO_slot_float_get(op->slots_in, "angle_limit"));
+
+ BLI_LINKSTACK_INIT(fstack);
+
+ BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) {
+ if (f->len > 3) {
+ BLI_LINKSTACK_PUSH(fstack, f);
+ }
+ }
+
+ while ((f = BLI_LINKSTACK_POP(fstack))) {
+ BMFace *f_pair[2];
+ if (bm_face_split_by_angle(bm, f, f_pair, angle_limit_cos)) {
+ int j;
+ for (j = 0; j < 2; j++) {
+ BM_face_normal_update(f_pair[j]);
+ if (f_pair[j]->len > 3) {
+ BLI_LINKSTACK_PUSH(fstack, f_pair[j]);
+ }
+ }
+ changed = true;
+ }
+ }
+
+ BLI_LINKSTACK_FREE(fstack);
+
+ if (changed) {
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT);
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_OUT);
+ }
}
diff --git a/source/blender/bmesh/operators/bmo_connect_pair.c b/source/blender/bmesh/operators/bmo_connect_pair.c
index 41d574aa373..18568c364d6 100644
--- a/source/blender/bmesh/operators/bmo_connect_pair.c
+++ b/source/blender/bmesh/operators/bmo_connect_pair.c
@@ -59,21 +59,22 @@
/* any element we've walked over (only do it once!) */
#define ELE_TOUCHED 4
-#define FACE_WALK_TEST(f) (CHECK_TYPE_INLINE(f, BMFace *), \
- BMO_face_flag_test(pc->bm_bmoflag, f, FACE_EXCLUDE) == 0)
-#define VERT_WALK_TEST(v) (CHECK_TYPE_INLINE(v, BMVert *), \
- BMO_vert_flag_test(pc->bm_bmoflag, v, VERT_EXCLUDE) == 0)
+#define FACE_WALK_TEST(f) \
+ (CHECK_TYPE_INLINE(f, BMFace *), BMO_face_flag_test(pc->bm_bmoflag, f, FACE_EXCLUDE) == 0)
+#define VERT_WALK_TEST(v) \
+ (CHECK_TYPE_INLINE(v, BMVert *), BMO_vert_flag_test(pc->bm_bmoflag, v, VERT_EXCLUDE) == 0)
#if 0
-#define ELE_TOUCH_TEST(e) ( \
- CHECK_TYPE_ANY(e, BMVert *, BMEdge *, BMElem *, BMElemF *), \
- BMO_elem_flag_test(pc->bm_bmoflag, (BMElemF *)e, ELE_TOUCHED) \
-)
+# define ELE_TOUCH_TEST(e) \
+ (CHECK_TYPE_ANY(e, BMVert *, BMEdge *, BMElem *, BMElemF *), \
+ BMO_elem_flag_test(pc->bm_bmoflag, (BMElemF *)e, ELE_TOUCHED))
#endif
-#define ELE_TOUCH_MARK(e) { \
- CHECK_TYPE_ANY(e, BMVert *, BMEdge *, BMElem *, BMElemF *); \
- BMO_elem_flag_enable(pc->bm_bmoflag, (BMElemF *)e, ELE_TOUCHED); \
-} ((void)0)
+#define ELE_TOUCH_MARK(e) \
+ { \
+ CHECK_TYPE_ANY(e, BMVert *, BMEdge *, BMElem *, BMElemF *); \
+ BMO_elem_flag_enable(pc->bm_bmoflag, (BMElemF *)e, ELE_TOUCHED); \
+ } \
+ ((void)0)
#define ELE_TOUCH_TEST_VERT(v) BMO_vert_flag_test(pc->bm_bmoflag, v, ELE_TOUCHED)
// #define ELE_TOUCH_MARK_VERT(v) BMO_vert_flag_enable(pc->bm_bmoflag, (BMElemF *)v, ELE_TOUCHED)
@@ -87,34 +88,34 @@
// #define DEBUG_PRINT
typedef struct PathContext {
- HeapSimple *states;
- float matrix[3][3];
- float axis_sep;
+ HeapSimple *states;
+ float matrix[3][3];
+ float axis_sep;
- /* only to access BMO flags */
- BMesh *bm_bmoflag;
+ /* only to access BMO flags */
+ BMesh *bm_bmoflag;
- BMVert *v_a, *v_b;
+ BMVert *v_a, *v_b;
- BLI_mempool *link_pool;
+ BLI_mempool *link_pool;
} PathContext;
/**
* Single linked list where each item contains state and points to previous path item.
*/
typedef struct PathLink {
- struct PathLink *next;
- BMElem *ele; /* edge or vert */
- BMElem *ele_from; /* edge or face we came from (not 'next->ele') */
+ struct PathLink *next;
+ BMElem *ele; /* edge or vert */
+ BMElem *ele_from; /* edge or face we came from (not 'next->ele') */
} PathLink;
typedef struct PathLinkState {
- /* chain of links */
- struct PathLink *link_last;
+ /* chain of links */
+ struct PathLink *link_last;
- /* length along links */
- float dist;
- float co_prev[3];
+ /* length along links */
+ float dist;
+ float co_prev[3];
} PathLinkState;
/**
@@ -133,91 +134,91 @@ typedef struct PathLinkState {
* \{ */
typedef struct MinDistDir {
- /* distance in both directions (FLT_MAX == uninitialized) */
- float dist_min[2];
- /* direction of the first intersection found */
- float dir[3];
+ /* distance in both directions (FLT_MAX == uninitialized) */
+ float dist_min[2];
+ /* direction of the first intersection found */
+ float dir[3];
} MinDistDir;
-#define MIN_DIST_DIR_INIT {{FLT_MAX, FLT_MAX}}
+#define MIN_DIST_DIR_INIT \
+ { \
+ { \
+ FLT_MAX, FLT_MAX \
+ } \
+ }
static int min_dist_dir_test(MinDistDir *mddir, const float dist_dir[3], const float dist_sq)
{
- if (mddir->dist_min[0] == FLT_MAX) {
- return 0;
- }
- else {
- if (dot_v3v3(dist_dir, mddir->dir) > 0.0f) {
- if (dist_sq < mddir->dist_min[0]) {
- return 0;
- }
- }
- else {
- if (dist_sq < mddir->dist_min[1]) {
- return 1;
- }
- }
- }
-
- return -1;
+ if (mddir->dist_min[0] == FLT_MAX) {
+ return 0;
+ }
+ else {
+ if (dot_v3v3(dist_dir, mddir->dir) > 0.0f) {
+ if (dist_sq < mddir->dist_min[0]) {
+ return 0;
+ }
+ }
+ else {
+ if (dist_sq < mddir->dist_min[1]) {
+ return 1;
+ }
+ }
+ }
+
+ return -1;
}
static void min_dist_dir_update(MinDistDir *dist, const float dist_dir[3])
{
- if (dist->dist_min[0] == FLT_MAX) {
- copy_v3_v3(dist->dir, dist_dir);
- }
+ if (dist->dist_min[0] == FLT_MAX) {
+ copy_v3_v3(dist->dir, dist_dir);
+ }
}
/** \} */
-
-static int state_isect_co_pair(
- const PathContext *pc,
- const float co_a[3], const float co_b[3])
+static int state_isect_co_pair(const PathContext *pc, const float co_a[3], const float co_b[3])
{
- const float diff_a = dot_m3_v3_row_x((float (*)[3])pc->matrix, co_a) - pc->axis_sep;
- const float diff_b = dot_m3_v3_row_x((float (*)[3])pc->matrix, co_b) - pc->axis_sep;
-
- const int test_a = (fabsf(diff_a) < CONNECT_EPS) ? 0 : (diff_a < 0.0f) ? -1 : 1;
- const int test_b = (fabsf(diff_b) < CONNECT_EPS) ? 0 : (diff_b < 0.0f) ? -1 : 1;
-
- if ((test_a && test_b) && (test_a != test_b)) {
- return 1; /* on either side */
- }
- else {
- return 0;
- }
+ const float diff_a = dot_m3_v3_row_x((float(*)[3])pc->matrix, co_a) - pc->axis_sep;
+ const float diff_b = dot_m3_v3_row_x((float(*)[3])pc->matrix, co_b) - pc->axis_sep;
+
+ const int test_a = (fabsf(diff_a) < CONNECT_EPS) ? 0 : (diff_a < 0.0f) ? -1 : 1;
+ const int test_b = (fabsf(diff_b) < CONNECT_EPS) ? 0 : (diff_b < 0.0f) ? -1 : 1;
+
+ if ((test_a && test_b) && (test_a != test_b)) {
+ return 1; /* on either side */
+ }
+ else {
+ return 0;
+ }
}
-static int state_isect_co_exact(
- const PathContext *pc,
- const float co[3])
+static int state_isect_co_exact(const PathContext *pc, const float co[3])
{
- const float diff = dot_m3_v3_row_x((float (*)[3])pc->matrix, co) - pc->axis_sep;
- return (fabsf(diff) <= CONNECT_EPS);
+ const float diff = dot_m3_v3_row_x((float(*)[3])pc->matrix, co) - pc->axis_sep;
+ return (fabsf(diff) <= CONNECT_EPS);
}
-static float state_calc_co_pair_fac(
- const PathContext *pc,
- const float co_a[3], const float co_b[3])
+static float state_calc_co_pair_fac(const PathContext *pc,
+ const float co_a[3],
+ const float co_b[3])
{
- float diff_a, diff_b, diff_tot;
+ float diff_a, diff_b, diff_tot;
- diff_a = fabsf(dot_m3_v3_row_x((float (*)[3])pc->matrix, co_a) - pc->axis_sep);
- diff_b = fabsf(dot_m3_v3_row_x((float (*)[3])pc->matrix, co_b) - pc->axis_sep);
- diff_tot = (diff_a + diff_b);
- return (diff_tot > FLT_EPSILON) ? (diff_a / diff_tot) : 0.5f;
+ diff_a = fabsf(dot_m3_v3_row_x((float(*)[3])pc->matrix, co_a) - pc->axis_sep);
+ diff_b = fabsf(dot_m3_v3_row_x((float(*)[3])pc->matrix, co_b) - pc->axis_sep);
+ diff_tot = (diff_a + diff_b);
+ return (diff_tot > FLT_EPSILON) ? (diff_a / diff_tot) : 0.5f;
}
-static void state_calc_co_pair(
- const PathContext *pc,
- const float co_a[3], const float co_b[3],
- float r_co[3])
+static void state_calc_co_pair(const PathContext *pc,
+ const float co_a[3],
+ const float co_b[3],
+ float r_co[3])
{
- const float fac = state_calc_co_pair_fac(pc, co_a, co_b);
- interp_v3_v3v3(r_co, co_a, co_b, fac);
+ const float fac = state_calc_co_pair_fac(pc, co_a, co_b);
+ interp_v3_v3v3(r_co, co_a, co_b, fac);
}
#ifndef NDEBUG
@@ -227,276 +228,268 @@ static void state_calc_co_pair(
*/
static bool state_link_find(const PathLinkState *state, BMElem *ele)
{
- PathLink *link = state->link_last;
- BLI_assert(ELEM(ele->head.htype, BM_VERT, BM_EDGE, BM_FACE));
- if (link) {
- do {
- if (link->ele == ele) {
- return true;
- }
- } while ((link = link->next));
- }
- return false;
+ PathLink *link = state->link_last;
+ BLI_assert(ELEM(ele->head.htype, BM_VERT, BM_EDGE, BM_FACE));
+ if (link) {
+ do {
+ if (link->ele == ele) {
+ return true;
+ }
+ } while ((link = link->next));
+ }
+ return false;
}
#endif
-static void state_link_add(
- PathContext *pc, PathLinkState *state,
- BMElem *ele, BMElem *ele_from)
+static void state_link_add(PathContext *pc, PathLinkState *state, BMElem *ele, BMElem *ele_from)
{
- PathLink *step_new = BLI_mempool_alloc(pc->link_pool);
- BLI_assert(ele != ele_from);
- BLI_assert(state_link_find(state, ele) == false);
+ PathLink *step_new = BLI_mempool_alloc(pc->link_pool);
+ BLI_assert(ele != ele_from);
+ BLI_assert(state_link_find(state, ele) == false);
- /* never walk onto this again */
- ELE_TOUCH_MARK(ele);
+ /* never walk onto this again */
+ ELE_TOUCH_MARK(ele);
#ifdef DEBUG_PRINT
- printf("%s: adding to state %p, %.4f - ", __func__, state, state->dist);
- if (ele->head.htype == BM_VERT) {
- printf("vert %d, ", BM_elem_index_get(ele));
- }
- else if (ele->head.htype == BM_EDGE) {
- printf("edge %d, ", BM_elem_index_get(ele));
- }
- else {
- BLI_assert(0);
- }
-
- if (ele_from == NULL) {
- printf("from NULL\n");
- }
- else if (ele_from->head.htype == BM_EDGE) {
- printf("from edge %d\n", BM_elem_index_get(ele_from));
- }
- else if (ele_from->head.htype == BM_FACE) {
- printf("from face %d\n", BM_elem_index_get(ele_from));
- }
- else {
- BLI_assert(0);
- }
+ printf("%s: adding to state %p, %.4f - ", __func__, state, state->dist);
+ if (ele->head.htype == BM_VERT) {
+ printf("vert %d, ", BM_elem_index_get(ele));
+ }
+ else if (ele->head.htype == BM_EDGE) {
+ printf("edge %d, ", BM_elem_index_get(ele));
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ if (ele_from == NULL) {
+ printf("from NULL\n");
+ }
+ else if (ele_from->head.htype == BM_EDGE) {
+ printf("from edge %d\n", BM_elem_index_get(ele_from));
+ }
+ else if (ele_from->head.htype == BM_FACE) {
+ printf("from face %d\n", BM_elem_index_get(ele_from));
+ }
+ else {
+ BLI_assert(0);
+ }
#endif
- /* track distance */
- {
- float co[3];
- if (ele->head.htype == BM_VERT) {
- copy_v3_v3(co, ((BMVert *)ele)->co);
- }
- else if (ele->head.htype == BM_EDGE) {
- state_calc_co_pair(pc, ((BMEdge *)ele)->v1->co, ((BMEdge *)ele)->v2->co, co);
- }
- else {
- BLI_assert(0);
- }
-
- /* tally distance */
- if (ele_from) {
- state->dist += len_v3v3(state->co_prev, co);
- }
- copy_v3_v3(state->co_prev, co);
- }
-
- step_new->ele = ele;
- step_new->ele_from = ele_from;
- step_new->next = state->link_last;
- state->link_last = step_new;
+ /* track distance */
+ {
+ float co[3];
+ if (ele->head.htype == BM_VERT) {
+ copy_v3_v3(co, ((BMVert *)ele)->co);
+ }
+ else if (ele->head.htype == BM_EDGE) {
+ state_calc_co_pair(pc, ((BMEdge *)ele)->v1->co, ((BMEdge *)ele)->v2->co, co);
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ /* tally distance */
+ if (ele_from) {
+ state->dist += len_v3v3(state->co_prev, co);
+ }
+ copy_v3_v3(state->co_prev, co);
+ }
+
+ step_new->ele = ele;
+ step_new->ele_from = ele_from;
+ step_new->next = state->link_last;
+ state->link_last = step_new;
}
-static PathLinkState *state_dupe_add(
- PathLinkState *state, const PathLinkState *state_orig)
+static PathLinkState *state_dupe_add(PathLinkState *state, const PathLinkState *state_orig)
{
- state = MEM_mallocN(sizeof(*state), __func__);
- *state = *state_orig;
- return state;
+ state = MEM_mallocN(sizeof(*state), __func__);
+ *state = *state_orig;
+ return state;
}
-static PathLinkState *state_link_add_test(
- PathContext *pc, PathLinkState *state, const PathLinkState *state_orig,
- BMElem *ele, BMElem *ele_from)
+static PathLinkState *state_link_add_test(PathContext *pc,
+ PathLinkState *state,
+ const PathLinkState *state_orig,
+ BMElem *ele,
+ BMElem *ele_from)
{
- const bool is_new = (state_orig->link_last != state->link_last);
- if (is_new) {
- state = state_dupe_add(state, state_orig);
- }
+ const bool is_new = (state_orig->link_last != state->link_last);
+ if (is_new) {
+ state = state_dupe_add(state, state_orig);
+ }
- state_link_add(pc, state, ele, ele_from);
+ state_link_add(pc, state, ele, ele_from);
- /* after adding a link so we use the updated 'state->dist' */
- if (is_new) {
- BLI_heapsimple_insert(pc->states, state->dist, state);
- }
+ /* after adding a link so we use the updated 'state->dist' */
+ if (is_new) {
+ BLI_heapsimple_insert(pc->states, state->dist, state);
+ }
- return state;
+ return state;
}
/* walk around the face edges */
-static PathLinkState *state_step__face_edges(
- PathContext *pc,
- PathLinkState *state, const PathLinkState *state_orig,
- BMLoop *l_iter, BMLoop *l_last,
- MinDistDir *mddir)
+static PathLinkState *state_step__face_edges(PathContext *pc,
+ PathLinkState *state,
+ const PathLinkState *state_orig,
+ BMLoop *l_iter,
+ BMLoop *l_last,
+ MinDistDir *mddir)
{
- BMLoop *l_iter_best[2] = {NULL, NULL};
- int i;
-
- do {
- if (state_isect_co_pair(pc, l_iter->v->co, l_iter->next->v->co)) {
- float dist_test;
- float co_isect[3];
- float dist_dir[3];
- int index;
-
- state_calc_co_pair(pc, l_iter->v->co, l_iter->next->v->co, co_isect);
-
- sub_v3_v3v3(dist_dir, co_isect, state_orig->co_prev);
- dist_test = len_squared_v3(dist_dir);
- if ((index = min_dist_dir_test(mddir, dist_dir, dist_test)) != -1) {
- BMElem *ele_next = (BMElem *)l_iter->e;
- BMElem *ele_next_from = (BMElem *)l_iter->f;
-
- if (FACE_WALK_TEST((BMFace *)ele_next_from) &&
- (ELE_TOUCH_TEST_EDGE((BMEdge *)ele_next) == false))
- {
- min_dist_dir_update(mddir, dist_dir);
- mddir->dist_min[index] = dist_test;
- l_iter_best[index] = l_iter;
- }
- }
- }
- } while ((l_iter = l_iter->next) != l_last);
-
- for (i = 0; i < 2; i++) {
- if ((l_iter = l_iter_best[i])) {
- BMElem *ele_next = (BMElem *)l_iter->e;
- BMElem *ele_next_from = (BMElem *)l_iter->f;
- state = state_link_add_test(pc, state, state_orig, ele_next, ele_next_from);
- }
- }
-
- return state;
+ BMLoop *l_iter_best[2] = {NULL, NULL};
+ int i;
+
+ do {
+ if (state_isect_co_pair(pc, l_iter->v->co, l_iter->next->v->co)) {
+ float dist_test;
+ float co_isect[3];
+ float dist_dir[3];
+ int index;
+
+ state_calc_co_pair(pc, l_iter->v->co, l_iter->next->v->co, co_isect);
+
+ sub_v3_v3v3(dist_dir, co_isect, state_orig->co_prev);
+ dist_test = len_squared_v3(dist_dir);
+ if ((index = min_dist_dir_test(mddir, dist_dir, dist_test)) != -1) {
+ BMElem *ele_next = (BMElem *)l_iter->e;
+ BMElem *ele_next_from = (BMElem *)l_iter->f;
+
+ if (FACE_WALK_TEST((BMFace *)ele_next_from) &&
+ (ELE_TOUCH_TEST_EDGE((BMEdge *)ele_next) == false)) {
+ min_dist_dir_update(mddir, dist_dir);
+ mddir->dist_min[index] = dist_test;
+ l_iter_best[index] = l_iter;
+ }
+ }
+ }
+ } while ((l_iter = l_iter->next) != l_last);
+
+ for (i = 0; i < 2; i++) {
+ if ((l_iter = l_iter_best[i])) {
+ BMElem *ele_next = (BMElem *)l_iter->e;
+ BMElem *ele_next_from = (BMElem *)l_iter->f;
+ state = state_link_add_test(pc, state, state_orig, ele_next, ele_next_from);
+ }
+ }
+
+ return state;
}
/* walk around the face verts */
-static PathLinkState *state_step__face_verts(
- PathContext *pc,
- PathLinkState *state, const PathLinkState *state_orig,
- BMLoop *l_iter, BMLoop *l_last,
- MinDistDir *mddir)
+static PathLinkState *state_step__face_verts(PathContext *pc,
+ PathLinkState *state,
+ const PathLinkState *state_orig,
+ BMLoop *l_iter,
+ BMLoop *l_last,
+ MinDistDir *mddir)
{
- BMLoop *l_iter_best[2] = {NULL, NULL};
- int i;
-
- do {
- if (state_isect_co_exact(pc, l_iter->v->co)) {
- float dist_test;
- const float *co_isect = l_iter->v->co;
- float dist_dir[3];
- int index;
-
- sub_v3_v3v3(dist_dir, co_isect, state_orig->co_prev);
- dist_test = len_squared_v3(dist_dir);
- if ((index = min_dist_dir_test(mddir, dist_dir, dist_test)) != -1) {
- BMElem *ele_next = (BMElem *)l_iter->v;
- BMElem *ele_next_from = (BMElem *)l_iter->f;
-
- if (FACE_WALK_TEST((BMFace *)ele_next_from) &&
- (ELE_TOUCH_TEST_VERT((BMVert *)ele_next) == false))
- {
- min_dist_dir_update(mddir, dist_dir);
- mddir->dist_min[index] = dist_test;
- l_iter_best[index] = l_iter;
- }
- }
- }
- } while ((l_iter = l_iter->next) != l_last);
-
- for (i = 0; i < 2; i++) {
- if ((l_iter = l_iter_best[i])) {
- BMElem *ele_next = (BMElem *)l_iter->v;
- BMElem *ele_next_from = (BMElem *)l_iter->f;
- state = state_link_add_test(pc, state, state_orig, ele_next, ele_next_from);
- }
- }
-
- return state;
+ BMLoop *l_iter_best[2] = {NULL, NULL};
+ int i;
+
+ do {
+ if (state_isect_co_exact(pc, l_iter->v->co)) {
+ float dist_test;
+ const float *co_isect = l_iter->v->co;
+ float dist_dir[3];
+ int index;
+
+ sub_v3_v3v3(dist_dir, co_isect, state_orig->co_prev);
+ dist_test = len_squared_v3(dist_dir);
+ if ((index = min_dist_dir_test(mddir, dist_dir, dist_test)) != -1) {
+ BMElem *ele_next = (BMElem *)l_iter->v;
+ BMElem *ele_next_from = (BMElem *)l_iter->f;
+
+ if (FACE_WALK_TEST((BMFace *)ele_next_from) &&
+ (ELE_TOUCH_TEST_VERT((BMVert *)ele_next) == false)) {
+ min_dist_dir_update(mddir, dist_dir);
+ mddir->dist_min[index] = dist_test;
+ l_iter_best[index] = l_iter;
+ }
+ }
+ }
+ } while ((l_iter = l_iter->next) != l_last);
+
+ for (i = 0; i < 2; i++) {
+ if ((l_iter = l_iter_best[i])) {
+ BMElem *ele_next = (BMElem *)l_iter->v;
+ BMElem *ele_next_from = (BMElem *)l_iter->f;
+ state = state_link_add_test(pc, state, state_orig, ele_next, ele_next_from);
+ }
+ }
+
+ return state;
}
static bool state_step(PathContext *pc, PathLinkState *state)
{
- PathLinkState state_orig = *state;
- BMElem *ele = state->link_last->ele;
- const void *ele_from = state->link_last->ele_from;
-
- if (ele->head.htype == BM_EDGE) {
- BMEdge *e = (BMEdge *)ele;
-
- BMIter liter;
- BMLoop *l_start;
-
- BM_ITER_ELEM (l_start, &liter, e, BM_LOOPS_OF_EDGE) {
- if ((l_start->f != ele_from) &&
- FACE_WALK_TEST(l_start->f))
- {
- MinDistDir mddir = MIN_DIST_DIR_INIT;
- /* very similar to block below */
- state = state_step__face_edges(pc, state, &state_orig,
- l_start->next, l_start, &mddir);
- state = state_step__face_verts(pc, state, &state_orig,
- l_start->next->next, l_start, &mddir);
- }
- }
- }
- else if (ele->head.htype == BM_VERT) {
- BMVert *v = (BMVert *)ele;
-
- /* vert loops */
- {
- BMIter liter;
- BMLoop *l_start;
-
- BM_ITER_ELEM (l_start, &liter, v, BM_LOOPS_OF_VERT) {
- if ((l_start->f != ele_from) &&
- FACE_WALK_TEST(l_start->f))
- {
- MinDistDir mddir = MIN_DIST_DIR_INIT;
- /* very similar to block above */
- state = state_step__face_edges(pc, state, &state_orig,
- l_start->next, l_start->prev, &mddir);
- if (l_start->f->len > 3) {
- /* adjacent verts are handled in state_step__vert_edges */
- state = state_step__face_verts(pc, state, &state_orig,
- l_start->next->next, l_start->prev, &mddir);
- }
- }
- }
- }
-
- /* vert edges */
- {
- BMIter eiter;
- BMEdge *e;
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- BMVert *v_other = BM_edge_other_vert(e, v);
- if (((BMElem *)e != ele_from) &&
- VERT_WALK_TEST(v_other))
- {
- if (state_isect_co_exact(pc, v_other->co)) {
- BMElem *ele_next = (BMElem *)v_other;
- BMElem *ele_next_from = (BMElem *)e;
- if (ELE_TOUCH_TEST_VERT((BMVert *)ele_next) == false) {
- state = state_link_add_test(pc, state, &state_orig, ele_next, ele_next_from);
- }
- }
- }
- }
- }
- }
- else {
- BLI_assert(0);
- }
- return (state_orig.link_last != state->link_last);
+ PathLinkState state_orig = *state;
+ BMElem *ele = state->link_last->ele;
+ const void *ele_from = state->link_last->ele_from;
+
+ if (ele->head.htype == BM_EDGE) {
+ BMEdge *e = (BMEdge *)ele;
+
+ BMIter liter;
+ BMLoop *l_start;
+
+ BM_ITER_ELEM (l_start, &liter, e, BM_LOOPS_OF_EDGE) {
+ if ((l_start->f != ele_from) && FACE_WALK_TEST(l_start->f)) {
+ MinDistDir mddir = MIN_DIST_DIR_INIT;
+ /* very similar to block below */
+ state = state_step__face_edges(pc, state, &state_orig, l_start->next, l_start, &mddir);
+ state = state_step__face_verts(
+ pc, state, &state_orig, l_start->next->next, l_start, &mddir);
+ }
+ }
+ }
+ else if (ele->head.htype == BM_VERT) {
+ BMVert *v = (BMVert *)ele;
+
+ /* vert loops */
+ {
+ BMIter liter;
+ BMLoop *l_start;
+
+ BM_ITER_ELEM (l_start, &liter, v, BM_LOOPS_OF_VERT) {
+ if ((l_start->f != ele_from) && FACE_WALK_TEST(l_start->f)) {
+ MinDistDir mddir = MIN_DIST_DIR_INIT;
+ /* very similar to block above */
+ state = state_step__face_edges(
+ pc, state, &state_orig, l_start->next, l_start->prev, &mddir);
+ if (l_start->f->len > 3) {
+ /* adjacent verts are handled in state_step__vert_edges */
+ state = state_step__face_verts(
+ pc, state, &state_orig, l_start->next->next, l_start->prev, &mddir);
+ }
+ }
+ }
+ }
+
+ /* vert edges */
+ {
+ BMIter eiter;
+ BMEdge *e;
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ BMVert *v_other = BM_edge_other_vert(e, v);
+ if (((BMElem *)e != ele_from) && VERT_WALK_TEST(v_other)) {
+ if (state_isect_co_exact(pc, v_other->co)) {
+ BMElem *ele_next = (BMElem *)v_other;
+ BMElem *ele_next_from = (BMElem *)e;
+ if (ELE_TOUCH_TEST_VERT((BMVert *)ele_next) == false) {
+ state = state_link_add_test(pc, state, &state_orig, ele_next, ele_next_from);
+ }
+ }
+ }
+ }
+ }
+ }
+ else {
+ BLI_assert(0);
+ }
+ return (state_orig.link_last != state->link_last);
}
/**
@@ -504,239 +497,244 @@ static bool state_step(PathContext *pc, PathLinkState *state)
*/
static void bm_vert_pair_to_matrix(BMVert *v_pair[2], float r_unit_mat[3][3])
{
- const float eps = 1e-8f;
+ const float eps = 1e-8f;
- float basis_dir[3];
- float basis_tmp[3];
- float basis_nor[3];
+ float basis_dir[3];
+ float basis_tmp[3];
+ float basis_nor[3];
- sub_v3_v3v3(basis_dir, v_pair[0]->co, v_pair[1]->co);
- normalize_v3(basis_dir);
+ sub_v3_v3v3(basis_dir, v_pair[0]->co, v_pair[1]->co);
+ normalize_v3(basis_dir);
#if 0
- add_v3_v3v3(basis_nor, v_pair[0]->no, v_pair[1]->no);
- cross_v3_v3v3(basis_tmp, basis_nor, basis_dir);
- cross_v3_v3v3(basis_nor, basis_tmp, basis_dir);
+ add_v3_v3v3(basis_nor, v_pair[0]->no, v_pair[1]->no);
+ cross_v3_v3v3(basis_tmp, basis_nor, basis_dir);
+ cross_v3_v3v3(basis_nor, basis_tmp, basis_dir);
#else
- /* align both normals to the directions before combining */
- {
- float basis_nor_a[3];
- float basis_nor_b[3];
-
- /* align normal to direction */
- project_plane_normalized_v3_v3v3(basis_nor_a, v_pair[0]->no, basis_dir);
- project_plane_normalized_v3_v3v3(basis_nor_b, v_pair[1]->no, basis_dir);
-
- /* don't normalize before combining so as normals approach the direction, they have less effect (T46784). */
-
- /* combine the normals */
- /* for flipped faces */
- if (dot_v3v3(basis_nor_a, basis_nor_b) < 0.0f) {
- negate_v3(basis_nor_b);
- }
- add_v3_v3v3(basis_nor, basis_nor_a, basis_nor_b);
- }
+ /* align both normals to the directions before combining */
+ {
+ float basis_nor_a[3];
+ float basis_nor_b[3];
+
+ /* align normal to direction */
+ project_plane_normalized_v3_v3v3(basis_nor_a, v_pair[0]->no, basis_dir);
+ project_plane_normalized_v3_v3v3(basis_nor_b, v_pair[1]->no, basis_dir);
+
+ /* don't normalize before combining so as normals approach the direction, they have less effect (T46784). */
+
+ /* combine the normals */
+ /* for flipped faces */
+ if (dot_v3v3(basis_nor_a, basis_nor_b) < 0.0f) {
+ negate_v3(basis_nor_b);
+ }
+ add_v3_v3v3(basis_nor, basis_nor_a, basis_nor_b);
+ }
#endif
- /* get third axis */
- normalize_v3(basis_nor);
- cross_v3_v3v3(basis_tmp, basis_dir, basis_nor);
-
-
- /* Try get the axis from surrounding faces, fallback to 'ortho_v3_v3' */
- if (UNLIKELY(normalize_v3(basis_tmp) < eps)) {
- /* vertex normals are directly opposite */
-
- /* find the loop with the lowest angle */
- struct { float nor[3]; float angle_cos; } axis_pair[2];
- int i;
-
- for (i = 0; i < 2; i++) {
- BMIter liter;
- BMLoop *l;
-
- zero_v2(axis_pair[i].nor);
- axis_pair[i].angle_cos = -FLT_MAX;
-
- BM_ITER_ELEM (l, &liter, v_pair[i], BM_LOOPS_OF_VERT) {
- float basis_dir_proj[3];
- float angle_cos_test;
-
- /* project basis dir onto the normal to find its closest angle */
- project_plane_normalized_v3_v3v3(basis_dir_proj, basis_dir, l->f->no);
-
- if (normalize_v3(basis_dir_proj) > eps) {
- angle_cos_test = dot_v3v3(basis_dir_proj, basis_dir);
-
- if (angle_cos_test > axis_pair[i].angle_cos) {
- axis_pair[i].angle_cos = angle_cos_test;
- copy_v3_v3(axis_pair[i].nor, basis_dir_proj);
- }
- }
- }
- }
-
- /* create a new 'basis_nor' from the best direction.
- * note: we could add the directions,
- * but this more often gives 45d rotated matrix, so just use the best one. */
- copy_v3_v3(basis_nor, axis_pair[axis_pair[0].angle_cos < axis_pair[1].angle_cos].nor);
- project_plane_normalized_v3_v3v3(basis_nor, basis_nor, basis_dir);
-
- cross_v3_v3v3(basis_tmp, basis_dir, basis_nor);
-
- /* last resort, pick _any_ ortho axis */
- if (UNLIKELY(normalize_v3(basis_tmp) < eps)) {
- ortho_v3_v3(basis_nor, basis_dir);
- normalize_v3(basis_nor);
- cross_v3_v3v3(basis_tmp, basis_dir, basis_nor);
- normalize_v3(basis_tmp);
- }
- }
-
- copy_v3_v3(r_unit_mat[0], basis_tmp);
- copy_v3_v3(r_unit_mat[1], basis_dir);
- copy_v3_v3(r_unit_mat[2], basis_nor);
- if (invert_m3(r_unit_mat) == false) {
- unit_m3(r_unit_mat);
- }
+ /* get third axis */
+ normalize_v3(basis_nor);
+ cross_v3_v3v3(basis_tmp, basis_dir, basis_nor);
+
+ /* Try get the axis from surrounding faces, fallback to 'ortho_v3_v3' */
+ if (UNLIKELY(normalize_v3(basis_tmp) < eps)) {
+ /* vertex normals are directly opposite */
+
+ /* find the loop with the lowest angle */
+ struct {
+ float nor[3];
+ float angle_cos;
+ } axis_pair[2];
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ BMIter liter;
+ BMLoop *l;
+
+ zero_v2(axis_pair[i].nor);
+ axis_pair[i].angle_cos = -FLT_MAX;
+
+ BM_ITER_ELEM (l, &liter, v_pair[i], BM_LOOPS_OF_VERT) {
+ float basis_dir_proj[3];
+ float angle_cos_test;
+
+ /* project basis dir onto the normal to find its closest angle */
+ project_plane_normalized_v3_v3v3(basis_dir_proj, basis_dir, l->f->no);
+
+ if (normalize_v3(basis_dir_proj) > eps) {
+ angle_cos_test = dot_v3v3(basis_dir_proj, basis_dir);
+
+ if (angle_cos_test > axis_pair[i].angle_cos) {
+ axis_pair[i].angle_cos = angle_cos_test;
+ copy_v3_v3(axis_pair[i].nor, basis_dir_proj);
+ }
+ }
+ }
+ }
+
+ /* create a new 'basis_nor' from the best direction.
+ * note: we could add the directions,
+ * but this more often gives 45d rotated matrix, so just use the best one. */
+ copy_v3_v3(basis_nor, axis_pair[axis_pair[0].angle_cos < axis_pair[1].angle_cos].nor);
+ project_plane_normalized_v3_v3v3(basis_nor, basis_nor, basis_dir);
+
+ cross_v3_v3v3(basis_tmp, basis_dir, basis_nor);
+
+ /* last resort, pick _any_ ortho axis */
+ if (UNLIKELY(normalize_v3(basis_tmp) < eps)) {
+ ortho_v3_v3(basis_nor, basis_dir);
+ normalize_v3(basis_nor);
+ cross_v3_v3v3(basis_tmp, basis_dir, basis_nor);
+ normalize_v3(basis_tmp);
+ }
+ }
+
+ copy_v3_v3(r_unit_mat[0], basis_tmp);
+ copy_v3_v3(r_unit_mat[1], basis_dir);
+ copy_v3_v3(r_unit_mat[2], basis_nor);
+ if (invert_m3(r_unit_mat) == false) {
+ unit_m3(r_unit_mat);
+ }
}
void bmo_connect_vert_pair_exec(BMesh *bm, BMOperator *op)
{
- BMOpSlot *op_verts_slot = BMO_slot_get(op->slots_in, "verts");
+ BMOpSlot *op_verts_slot = BMO_slot_get(op->slots_in, "verts");
- PathContext pc;
- PathLinkState state_best = {NULL};
+ PathContext pc;
+ PathLinkState state_best = {NULL};
- if (op_verts_slot->len != 2) {
- /* fail! */
- return;
- }
+ if (op_verts_slot->len != 2) {
+ /* fail! */
+ return;
+ }
- pc.bm_bmoflag = bm;
- pc.v_a = ((BMVert **)op_verts_slot->data.p)[0];
- pc.v_b = ((BMVert **)op_verts_slot->data.p)[1];
+ pc.bm_bmoflag = bm;
+ pc.v_a = ((BMVert **)op_verts_slot->data.p)[0];
+ pc.v_b = ((BMVert **)op_verts_slot->data.p)[1];
- /* fail! */
- if (!(pc.v_a && pc.v_b)) {
- return;
- }
+ /* fail! */
+ if (!(pc.v_a && pc.v_b)) {
+ return;
+ }
#ifdef DEBUG_PRINT
- printf("%s: v_a: %d\n", __func__, BM_elem_index_get(pc.v_a));
- printf("%s: v_b: %d\n", __func__, BM_elem_index_get(pc.v_b));
+ printf("%s: v_a: %d\n", __func__, BM_elem_index_get(pc.v_a));
+ printf("%s: v_b: %d\n", __func__, BM_elem_index_get(pc.v_b));
#endif
- /* tag so we won't touch ever (typically hidden faces) */
- BMO_slot_buffer_flag_enable(bm, op->slots_in, "faces_exclude", BM_FACE, FACE_EXCLUDE);
- BMO_slot_buffer_flag_enable(bm, op->slots_in, "verts_exclude", BM_VERT, VERT_EXCLUDE);
-
- /* setup context */
- {
- pc.states = BLI_heapsimple_new();
- pc.link_pool = BLI_mempool_create(sizeof(PathLink), 0, 512, BLI_MEMPOOL_NOP);
- }
+ /* tag so we won't touch ever (typically hidden faces) */
+ BMO_slot_buffer_flag_enable(bm, op->slots_in, "faces_exclude", BM_FACE, FACE_EXCLUDE);
+ BMO_slot_buffer_flag_enable(bm, op->slots_in, "verts_exclude", BM_VERT, VERT_EXCLUDE);
- /* calculate matrix */
- {
- bm_vert_pair_to_matrix(&pc.v_a, pc.matrix);
- pc.axis_sep = dot_m3_v3_row_x(pc.matrix, pc.v_a->co);
- }
+ /* setup context */
+ {
+ pc.states = BLI_heapsimple_new();
+ pc.link_pool = BLI_mempool_create(sizeof(PathLink), 0, 512, BLI_MEMPOOL_NOP);
+ }
- /* add first vertex */
- {
- PathLinkState *state;
- state = MEM_callocN(sizeof(*state), __func__);
- state_link_add(&pc, state, (BMElem *)pc.v_a, NULL);
- BLI_heapsimple_insert(pc.states, state->dist, state);
- }
+ /* calculate matrix */
+ {
+ bm_vert_pair_to_matrix(&pc.v_a, pc.matrix);
+ pc.axis_sep = dot_m3_v3_row_x(pc.matrix, pc.v_a->co);
+ }
+ /* add first vertex */
+ {
+ PathLinkState *state;
+ state = MEM_callocN(sizeof(*state), __func__);
+ state_link_add(&pc, state, (BMElem *)pc.v_a, NULL);
+ BLI_heapsimple_insert(pc.states, state->dist, state);
+ }
- while (!BLI_heapsimple_is_empty(pc.states)) {
+ while (!BLI_heapsimple_is_empty(pc.states)) {
#ifdef DEBUG_PRINT
- printf("\n%s: stepping %u\n", __func__, BLI_heapsimple_len(pc.states));
+ printf("\n%s: stepping %u\n", __func__, BLI_heapsimple_len(pc.states));
#endif
- while (!BLI_heapsimple_is_empty(pc.states)) {
- PathLinkState *state = BLI_heapsimple_pop_min(pc.states);
+ while (!BLI_heapsimple_is_empty(pc.states)) {
+ PathLinkState *state = BLI_heapsimple_pop_min(pc.states);
- /* either we insert this into 'pc.states' or its freed */
- bool continue_search;
+ /* either we insert this into 'pc.states' or its freed */
+ bool continue_search;
- if (state->link_last->ele == (BMElem *)pc.v_b) {
- /* pass, wait until all are found */
+ if (state->link_last->ele == (BMElem *)pc.v_b) {
+ /* pass, wait until all are found */
#ifdef DEBUG_PRINT
- printf("%s: state %p loop found %.4f\n", __func__, state, state->dist);
+ printf("%s: state %p loop found %.4f\n", __func__, state, state->dist);
#endif
- state_best = *state;
-
- /* we're done, exit all loops */
- BLI_heapsimple_clear(pc.states, MEM_freeN);
- continue_search = false;
- }
- else if (state_step(&pc, state)) {
- continue_search = true;
- }
- else {
- /* didn't reach the end, remove it,
- * links are shared between states so just free the link_pool at the end */
+ state_best = *state;
+
+ /* we're done, exit all loops */
+ BLI_heapsimple_clear(pc.states, MEM_freeN);
+ continue_search = false;
+ }
+ else if (state_step(&pc, state)) {
+ continue_search = true;
+ }
+ else {
+ /* didn't reach the end, remove it,
+ * links are shared between states so just free the link_pool at the end */
#ifdef DEBUG_PRINT
- printf("%s: state %p removed\n", __func__, state);
+ printf("%s: state %p removed\n", __func__, state);
#endif
- continue_search = false;
- }
-
- if (continue_search) {
- BLI_heapsimple_insert(pc.states, state->dist, state);
- }
- else {
- MEM_freeN(state);
- }
- }
- }
-
- if (state_best.link_last) {
- PathLink *link;
-
- /* find the best state */
- link = state_best.link_last;
- do {
- if (link->ele->head.htype == BM_EDGE) {
- BMEdge *e = (BMEdge *)link->ele;
- BMVert *v_new;
- float e_fac = state_calc_co_pair_fac(&pc, e->v1->co, e->v2->co);
- v_new = BM_edge_split(bm, e, e->v1, NULL, e_fac);
- BMO_vert_flag_enable(bm, v_new, VERT_OUT);
- }
- else if (link->ele->head.htype == BM_VERT) {
- BMVert *v = (BMVert *)link->ele;
- BMO_vert_flag_enable(bm, v, VERT_OUT);
- }
- else {
- BLI_assert(0);
- }
- } while ((link = link->next));
- }
-
- BMO_vert_flag_enable(bm, pc.v_a, VERT_OUT);
- BMO_vert_flag_enable(bm, pc.v_b, VERT_OUT);
-
- BLI_mempool_destroy(pc.link_pool);
-
- BLI_heapsimple_free(pc.states, MEM_freeN);
+ continue_search = false;
+ }
+
+ if (continue_search) {
+ BLI_heapsimple_insert(pc.states, state->dist, state);
+ }
+ else {
+ MEM_freeN(state);
+ }
+ }
+ }
+
+ if (state_best.link_last) {
+ PathLink *link;
+
+ /* find the best state */
+ link = state_best.link_last;
+ do {
+ if (link->ele->head.htype == BM_EDGE) {
+ BMEdge *e = (BMEdge *)link->ele;
+ BMVert *v_new;
+ float e_fac = state_calc_co_pair_fac(&pc, e->v1->co, e->v2->co);
+ v_new = BM_edge_split(bm, e, e->v1, NULL, e_fac);
+ BMO_vert_flag_enable(bm, v_new, VERT_OUT);
+ }
+ else if (link->ele->head.htype == BM_VERT) {
+ BMVert *v = (BMVert *)link->ele;
+ BMO_vert_flag_enable(bm, v, VERT_OUT);
+ }
+ else {
+ BLI_assert(0);
+ }
+ } while ((link = link->next));
+ }
+
+ BMO_vert_flag_enable(bm, pc.v_a, VERT_OUT);
+ BMO_vert_flag_enable(bm, pc.v_b, VERT_OUT);
+
+ BLI_mempool_destroy(pc.link_pool);
+
+ BLI_heapsimple_free(pc.states, MEM_freeN);
#if 1
- if (state_best.link_last) {
- BMOperator op_sub;
- BMO_op_initf(bm, &op_sub, 0,
- "connect_verts verts=%fv faces_exclude=%s check_degenerate=%b",
- VERT_OUT, op, "faces_exclude", true);
- BMO_op_exec(bm, &op_sub);
- BMO_slot_copy(&op_sub, slots_out, "edges.out",
- op, slots_out, "edges.out");
- BMO_op_finish(bm, &op_sub);
- }
+ if (state_best.link_last) {
+ BMOperator op_sub;
+ BMO_op_initf(bm,
+ &op_sub,
+ 0,
+ "connect_verts verts=%fv faces_exclude=%s check_degenerate=%b",
+ VERT_OUT,
+ op,
+ "faces_exclude",
+ true);
+ BMO_op_exec(bm, &op_sub);
+ BMO_slot_copy(&op_sub, slots_out, "edges.out", op, slots_out, "edges.out");
+ BMO_op_finish(bm, &op_sub);
+ }
#endif
}
diff --git a/source/blender/bmesh/operators/bmo_create.c b/source/blender/bmesh/operators/bmo_create.c
index 001c3004ec9..c799b177843 100644
--- a/source/blender/bmesh/operators/bmo_create.c
+++ b/source/blender/bmesh/operators/bmo_create.c
@@ -28,8 +28,8 @@
#include "intern/bmesh_operators_private.h" /* own include */
-#define ELE_NEW 1
-#define ELE_OUT 2
+#define ELE_NEW 1
+#define ELE_OUT 2
/* This is what runs when pressing the F key
* doing the best thing here isn't always easy create vs dissolve, its nice to support
@@ -37,269 +37,273 @@
*/
void bmo_contextual_create_exec(BMesh *bm, BMOperator *op)
{
- BMOIter oiter;
- BMHeader *h;
- int totv = 0, tote = 0, totf = 0;
- const short mat_nr = BMO_slot_int_get(op->slots_in, "mat_nr");
- const bool use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth");
-
- /* count number of each element type we were passe */
- BMO_ITER (h, &oiter, op->slots_in, "geom", BM_VERT | BM_EDGE | BM_FACE) {
- switch (h->htype) {
- case BM_VERT:
- BMO_vert_flag_enable(bm, (BMVert *)h, ELE_NEW);
- totv++;
- break;
- case BM_EDGE:
- BMO_edge_flag_enable(bm, (BMEdge *)h, ELE_NEW);
- tote++;
- break;
- case BM_FACE:
- BMO_face_flag_enable(bm, (BMFace *)h, ELE_NEW);
- totf++;
- break;
- }
- }
-
- /* --- Support Edge Creation ---
- * simple case when we only have 2 verts selected.
- */
- if (totv == 2 && tote == 0 && totf == 0) {
- BMVert *verts[2];
- BMEdge *e;
-
- if (BMO_iter_as_array(op->slots_in, "geom", BM_VERT, (void **)verts, 2) == 2) {
- /* create edge */
- e = BM_edge_create(bm, verts[0], verts[1], NULL, BM_CREATE_NO_DOUBLE);
- BMO_edge_flag_enable(bm, e, ELE_OUT);
- tote += 1;
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, ELE_OUT);
- }
- return;
- }
-
-
- /* --- Support for Special Case ---
- * where there is a contiguous edge ring with one isolated vertex.
- *
- * This example shows 2 edges created from 3 verts
- * with 1 free standing vertex. Dotted lines denote the 2 edges that are created.
- *
- * note that this works for any sided shape.
- *
- * +--------+
- * | .
- * | .
- * | .
- * | .
- * +........+ <-- starts out free standing.
- *
- */
-
- /* Here we check for consistency and create 2 edges */
- if (totf == 0 && totv >= 4 && totv == tote + 2) {
- /* find a free standing vertex and 2 endpoint verts */
- BMVert *v, *v_free = NULL, *v_a = NULL, *v_b = NULL;
- bool ok = true;
-
-
- BMO_ITER (v, &oiter, op->slots_in, "geom", BM_VERT) {
- /* count how many flagged edges this vertex uses */
- const int tot_edges = BMO_iter_elem_count_flag(bm, BM_EDGES_OF_VERT, v, ELE_NEW, true);
- if (tot_edges == 0) {
- /* only accept 1 free vert */
- if (v_free == NULL) { v_free = v; }
- else { ok = false; } /* only ever want one of these */
- }
- else if (tot_edges == 1) {
- if (v_a == NULL) { v_a = v; }
- else if (v_b == NULL) { v_b = v; }
- else { ok = false; } /* only ever want 2 of these */
- }
- else if (tot_edges == 2) {
- /* do nothing, regular case */
- }
- else {
- ok = false; /* if a vertex has 3+ edge users then cancel - this is only simple cases */
- }
-
- if (ok == false) {
- break;
- }
- }
-
- if (ok == true && v_free && v_a && v_b) {
- BMEdge *e;
-
- e = BM_edge_create(bm, v_free, v_a, NULL, BM_CREATE_NO_DOUBLE);
- BMO_edge_flag_enable(bm, e, ELE_NEW);
-
- e = BM_edge_create(bm, v_free, v_b, NULL, BM_CREATE_NO_DOUBLE);
- BMO_edge_flag_enable(bm, e, ELE_NEW);
- tote += 2;
- }
- }
- /* --- end special case support, continue as normal --- */
-
-
- /* -------------------------------------------------------------------- */
- /* EdgeNet Create */
- if (tote != 0) {
- /* call edgenet prepare op so additional face creation cases work */
-
- BMOperator op_sub;
- BMO_op_initf(bm, &op_sub, op->flag, "edgenet_prepare edges=%fe", ELE_NEW);
- BMO_op_exec(bm, &op_sub);
- BMO_slot_buffer_flag_enable(bm, op_sub.slots_out, "edges.out", BM_EDGE, ELE_NEW);
- BMO_op_finish(bm, &op_sub);
-
- BMO_op_initf(bm, &op_sub, op->flag,
- "edgenet_fill edges=%fe mat_nr=%i use_smooth=%b sides=%i",
- ELE_NEW, mat_nr, use_smooth, 10000);
-
- BMO_op_exec(bm, &op_sub);
-
- /* return if edge net create did something */
- if (BMO_slot_buffer_count(op_sub.slots_out, "faces.out")) {
- BMO_slot_copy(&op_sub, slots_out, "faces.out",
- op, slots_out, "faces.out");
- BMO_op_finish(bm, &op_sub);
- return;
- }
-
- BMO_op_finish(bm, &op_sub);
- }
-
-
- /* -------------------------------------------------------------------- */
- /* Dissolve Face */
- if (totf != 0) { /* should be (totf > 1)... see below */
- /* note: allow this to run on single faces so running on a single face
- * won't go on to create a face, treating them as random */
- BMOperator op_sub;
- BMO_op_initf(bm, &op_sub, op->flag, "dissolve_faces faces=%ff", ELE_NEW);
- BMO_op_exec(bm, &op_sub);
-
- /* if we dissolved anything, then return */
- if (BMO_slot_buffer_count(op_sub.slots_out, "region.out")) {
- BMO_slot_copy(&op_sub, slots_out, "region.out",
- op, slots_out, "faces.out");
- BMO_op_finish(bm, &op_sub);
- return;
- }
-
- BMO_op_finish(bm, &op_sub);
- }
-
-
- /* -------------------------------------------------------------------- */
- /* Fill EdgeLoop's - fills isolated loops, different from edgenet */
- if (tote > 2) {
- BMOperator op_sub;
- /* note: in most cases 'edgenet_fill' will handle this case since in common cases
- * users fill in empty spaces, however its possible to have an edge selection around
- * existing geometry that makes 'edgenet_fill' fail. */
- BMO_op_initf(bm, &op_sub, op->flag, "edgeloop_fill edges=%fe", ELE_NEW);
- BMO_op_exec(bm, &op_sub);
-
- /* return if edge loop fill did something */
- if (BMO_slot_buffer_count(op_sub.slots_out, "faces.out")) {
- BMO_slot_copy(&op_sub, slots_out, "faces.out",
- op, slots_out, "faces.out");
- BMO_op_finish(bm, &op_sub);
- return;
- }
-
- BMO_op_finish(bm, &op_sub);
- }
-
-
-
- /* -------------------------------------------------------------------- */
- /* Continue with ad-hoc fill methods since operators fail,
- * edge, vcloud... may add more */
-
- if (0) { /* nice feature but perhaps it should be a different tool? */
-
- /* tricky feature for making a line/edge from selection history...
- *
- * Rather then do nothing, when 5+ verts are selected, check if they are in our history,
- * when this is so, we can make edges from them, but _not_ a face,
- * if it is the intention to make a face the user can just hit F again since there will be edges next
- * time around.
- *
- * if all history verts have ELE_NEW flagged and the total number of history verts == totv,
- * then we know the history contains all verts here and we can continue...
- */
-
- BMEditSelection *ese;
- int tot_ese_v = 0;
-
- for (ese = bm->selected.first; ese; ese = ese->next) {
- if (ese->htype == BM_VERT) {
- if (BMO_vert_flag_test(bm, (BMVert *)ese->ele, ELE_NEW)) {
- tot_ese_v++;
- }
- else {
- /* unflagged vert means we are not in sync */
- tot_ese_v = -1;
- break;
- }
- }
- }
-
- if (tot_ese_v == totv) {
- BMVert *v_prev = NULL;
- /* yes, all select-history verts are accounted for, now make edges */
-
- for (ese = bm->selected.first; ese; ese = ese->next) {
- if (ese->htype == BM_VERT) {
- BMVert *v = (BMVert *)ese->ele;
- if (v_prev) {
- BMEdge *e = BM_edge_create(bm, v, v_prev, NULL, BM_CREATE_NO_DOUBLE);
- BMO_edge_flag_enable(bm, e, ELE_OUT);
- }
- v_prev = v;
- }
- }
- }
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, ELE_OUT);
- /* done creating edges */
-
- return;
- }
-
-
- /* -------------------------------------------------------------------- */
- /* Fill Vertex Cloud
- *
- * last resort when all else fails.
- */
- if (totv > 2) {
- /* TODO, some of these vertes may be connected by edges,
- * this connectivity could be used rather than treating
- * them as a bunch of isolated verts. */
-
- BMVert **vert_arr = MEM_mallocN(sizeof(BMVert *) * totv, __func__);
- BMFace *f;
-
- totv = BMO_iter_as_array(op->slots_in, "geom", BM_VERT, (void **)vert_arr, totv);
-
- BM_verts_sort_radial_plane(vert_arr, totv);
-
- /* create edges and find the winding (if faces are attached to any existing edges) */
- f = BM_face_create_ngon_verts(bm, vert_arr, totv, NULL, BM_CREATE_NO_DOUBLE, true, true);
-
- if (f) {
- BMO_face_flag_enable(bm, f, ELE_OUT);
- f->mat_nr = mat_nr;
- if (use_smooth) {
- BM_elem_flag_enable(f, BM_ELEM_SMOOTH);
- }
- BM_face_copy_shared(bm, f, NULL, NULL);
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, ELE_OUT);
- }
-
- MEM_freeN(vert_arr);
- }
+ BMOIter oiter;
+ BMHeader *h;
+ int totv = 0, tote = 0, totf = 0;
+ const short mat_nr = BMO_slot_int_get(op->slots_in, "mat_nr");
+ const bool use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth");
+
+ /* count number of each element type we were passe */
+ BMO_ITER (h, &oiter, op->slots_in, "geom", BM_VERT | BM_EDGE | BM_FACE) {
+ switch (h->htype) {
+ case BM_VERT:
+ BMO_vert_flag_enable(bm, (BMVert *)h, ELE_NEW);
+ totv++;
+ break;
+ case BM_EDGE:
+ BMO_edge_flag_enable(bm, (BMEdge *)h, ELE_NEW);
+ tote++;
+ break;
+ case BM_FACE:
+ BMO_face_flag_enable(bm, (BMFace *)h, ELE_NEW);
+ totf++;
+ break;
+ }
+ }
+
+ /* --- Support Edge Creation ---
+ * simple case when we only have 2 verts selected.
+ */
+ if (totv == 2 && tote == 0 && totf == 0) {
+ BMVert *verts[2];
+ BMEdge *e;
+
+ if (BMO_iter_as_array(op->slots_in, "geom", BM_VERT, (void **)verts, 2) == 2) {
+ /* create edge */
+ e = BM_edge_create(bm, verts[0], verts[1], NULL, BM_CREATE_NO_DOUBLE);
+ BMO_edge_flag_enable(bm, e, ELE_OUT);
+ tote += 1;
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, ELE_OUT);
+ }
+ return;
+ }
+
+ /* --- Support for Special Case ---
+ * where there is a contiguous edge ring with one isolated vertex.
+ *
+ * This example shows 2 edges created from 3 verts
+ * with 1 free standing vertex. Dotted lines denote the 2 edges that are created.
+ *
+ * note that this works for any sided shape.
+ *
+ * +--------+
+ * | .
+ * | .
+ * | .
+ * | .
+ * +........+ <-- starts out free standing.
+ *
+ */
+
+ /* Here we check for consistency and create 2 edges */
+ if (totf == 0 && totv >= 4 && totv == tote + 2) {
+ /* find a free standing vertex and 2 endpoint verts */
+ BMVert *v, *v_free = NULL, *v_a = NULL, *v_b = NULL;
+ bool ok = true;
+
+ BMO_ITER (v, &oiter, op->slots_in, "geom", BM_VERT) {
+ /* count how many flagged edges this vertex uses */
+ const int tot_edges = BMO_iter_elem_count_flag(bm, BM_EDGES_OF_VERT, v, ELE_NEW, true);
+ if (tot_edges == 0) {
+ /* only accept 1 free vert */
+ if (v_free == NULL) {
+ v_free = v;
+ }
+ else {
+ ok = false;
+ } /* only ever want one of these */
+ }
+ else if (tot_edges == 1) {
+ if (v_a == NULL) {
+ v_a = v;
+ }
+ else if (v_b == NULL) {
+ v_b = v;
+ }
+ else {
+ ok = false;
+ } /* only ever want 2 of these */
+ }
+ else if (tot_edges == 2) {
+ /* do nothing, regular case */
+ }
+ else {
+ ok = false; /* if a vertex has 3+ edge users then cancel - this is only simple cases */
+ }
+
+ if (ok == false) {
+ break;
+ }
+ }
+
+ if (ok == true && v_free && v_a && v_b) {
+ BMEdge *e;
+
+ e = BM_edge_create(bm, v_free, v_a, NULL, BM_CREATE_NO_DOUBLE);
+ BMO_edge_flag_enable(bm, e, ELE_NEW);
+
+ e = BM_edge_create(bm, v_free, v_b, NULL, BM_CREATE_NO_DOUBLE);
+ BMO_edge_flag_enable(bm, e, ELE_NEW);
+ tote += 2;
+ }
+ }
+ /* --- end special case support, continue as normal --- */
+
+ /* -------------------------------------------------------------------- */
+ /* EdgeNet Create */
+ if (tote != 0) {
+ /* call edgenet prepare op so additional face creation cases work */
+
+ BMOperator op_sub;
+ BMO_op_initf(bm, &op_sub, op->flag, "edgenet_prepare edges=%fe", ELE_NEW);
+ BMO_op_exec(bm, &op_sub);
+ BMO_slot_buffer_flag_enable(bm, op_sub.slots_out, "edges.out", BM_EDGE, ELE_NEW);
+ BMO_op_finish(bm, &op_sub);
+
+ BMO_op_initf(bm,
+ &op_sub,
+ op->flag,
+ "edgenet_fill edges=%fe mat_nr=%i use_smooth=%b sides=%i",
+ ELE_NEW,
+ mat_nr,
+ use_smooth,
+ 10000);
+
+ BMO_op_exec(bm, &op_sub);
+
+ /* return if edge net create did something */
+ if (BMO_slot_buffer_count(op_sub.slots_out, "faces.out")) {
+ BMO_slot_copy(&op_sub, slots_out, "faces.out", op, slots_out, "faces.out");
+ BMO_op_finish(bm, &op_sub);
+ return;
+ }
+
+ BMO_op_finish(bm, &op_sub);
+ }
+
+ /* -------------------------------------------------------------------- */
+ /* Dissolve Face */
+ if (totf != 0) { /* should be (totf > 1)... see below */
+ /* note: allow this to run on single faces so running on a single face
+ * won't go on to create a face, treating them as random */
+ BMOperator op_sub;
+ BMO_op_initf(bm, &op_sub, op->flag, "dissolve_faces faces=%ff", ELE_NEW);
+ BMO_op_exec(bm, &op_sub);
+
+ /* if we dissolved anything, then return */
+ if (BMO_slot_buffer_count(op_sub.slots_out, "region.out")) {
+ BMO_slot_copy(&op_sub, slots_out, "region.out", op, slots_out, "faces.out");
+ BMO_op_finish(bm, &op_sub);
+ return;
+ }
+
+ BMO_op_finish(bm, &op_sub);
+ }
+
+ /* -------------------------------------------------------------------- */
+ /* Fill EdgeLoop's - fills isolated loops, different from edgenet */
+ if (tote > 2) {
+ BMOperator op_sub;
+ /* note: in most cases 'edgenet_fill' will handle this case since in common cases
+ * users fill in empty spaces, however its possible to have an edge selection around
+ * existing geometry that makes 'edgenet_fill' fail. */
+ BMO_op_initf(bm, &op_sub, op->flag, "edgeloop_fill edges=%fe", ELE_NEW);
+ BMO_op_exec(bm, &op_sub);
+
+ /* return if edge loop fill did something */
+ if (BMO_slot_buffer_count(op_sub.slots_out, "faces.out")) {
+ BMO_slot_copy(&op_sub, slots_out, "faces.out", op, slots_out, "faces.out");
+ BMO_op_finish(bm, &op_sub);
+ return;
+ }
+
+ BMO_op_finish(bm, &op_sub);
+ }
+
+ /* -------------------------------------------------------------------- */
+ /* Continue with ad-hoc fill methods since operators fail,
+ * edge, vcloud... may add more */
+
+ if (0) { /* nice feature but perhaps it should be a different tool? */
+
+ /* tricky feature for making a line/edge from selection history...
+ *
+ * Rather then do nothing, when 5+ verts are selected, check if they are in our history,
+ * when this is so, we can make edges from them, but _not_ a face,
+ * if it is the intention to make a face the user can just hit F again since there will be edges next
+ * time around.
+ *
+ * if all history verts have ELE_NEW flagged and the total number of history verts == totv,
+ * then we know the history contains all verts here and we can continue...
+ */
+
+ BMEditSelection *ese;
+ int tot_ese_v = 0;
+
+ for (ese = bm->selected.first; ese; ese = ese->next) {
+ if (ese->htype == BM_VERT) {
+ if (BMO_vert_flag_test(bm, (BMVert *)ese->ele, ELE_NEW)) {
+ tot_ese_v++;
+ }
+ else {
+ /* unflagged vert means we are not in sync */
+ tot_ese_v = -1;
+ break;
+ }
+ }
+ }
+
+ if (tot_ese_v == totv) {
+ BMVert *v_prev = NULL;
+ /* yes, all select-history verts are accounted for, now make edges */
+
+ for (ese = bm->selected.first; ese; ese = ese->next) {
+ if (ese->htype == BM_VERT) {
+ BMVert *v = (BMVert *)ese->ele;
+ if (v_prev) {
+ BMEdge *e = BM_edge_create(bm, v, v_prev, NULL, BM_CREATE_NO_DOUBLE);
+ BMO_edge_flag_enable(bm, e, ELE_OUT);
+ }
+ v_prev = v;
+ }
+ }
+ }
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, ELE_OUT);
+ /* done creating edges */
+
+ return;
+ }
+
+ /* -------------------------------------------------------------------- */
+ /* Fill Vertex Cloud
+ *
+ * last resort when all else fails.
+ */
+ if (totv > 2) {
+ /* TODO, some of these vertes may be connected by edges,
+ * this connectivity could be used rather than treating
+ * them as a bunch of isolated verts. */
+
+ BMVert **vert_arr = MEM_mallocN(sizeof(BMVert *) * totv, __func__);
+ BMFace *f;
+
+ totv = BMO_iter_as_array(op->slots_in, "geom", BM_VERT, (void **)vert_arr, totv);
+
+ BM_verts_sort_radial_plane(vert_arr, totv);
+
+ /* create edges and find the winding (if faces are attached to any existing edges) */
+ f = BM_face_create_ngon_verts(bm, vert_arr, totv, NULL, BM_CREATE_NO_DOUBLE, true, true);
+
+ if (f) {
+ BMO_face_flag_enable(bm, f, ELE_OUT);
+ f->mat_nr = mat_nr;
+ if (use_smooth) {
+ BM_elem_flag_enable(f, BM_ELEM_SMOOTH);
+ }
+ BM_face_copy_shared(bm, f, NULL, NULL);
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, ELE_OUT);
+ }
+
+ MEM_freeN(vert_arr);
+ }
}
diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c
index d04fe2b7146..9cea982f6bd 100644
--- a/source/blender/bmesh/operators/bmo_dissolve.c
+++ b/source/blender/bmesh/operators/bmo_dissolve.c
@@ -31,603 +31,604 @@
#include "intern/bmesh_operators_private.h"
-
/* ***_ISGC: mark for garbage-collection */
-#define FACE_MARK 1
-#define FACE_ORIG 2
-#define FACE_NEW 4
-#define FACE_TAG 8
+#define FACE_MARK 1
+#define FACE_ORIG 2
+#define FACE_NEW 4
+#define FACE_TAG 8
-#define EDGE_MARK 1
-#define EDGE_TAG 2
-#define EDGE_ISGC 8
+#define EDGE_MARK 1
+#define EDGE_TAG 2
+#define EDGE_ISGC 8
-#define VERT_MARK 1
+#define VERT_MARK 1
#define VERT_MARK_PAIR 4
-#define VERT_TAG 2
-#define VERT_ISGC 8
+#define VERT_TAG 2
+#define VERT_ISGC 8
#define VERT_MARK_TEAR 16
-
-
-static bool UNUSED_FUNCTION(check_hole_in_region) (BMesh *bm, BMFace *f)
+static bool UNUSED_FUNCTION(check_hole_in_region)(BMesh *bm, BMFace *f)
{
- BMWalker regwalker;
- BMIter liter2;
- BMLoop *l2, *l3;
- BMFace *f2;
-
- /* checks if there are any unmarked boundary edges in the face regio */
-
- BMW_init(&regwalker, bm, BMW_ISLAND,
- BMW_MASK_NOP, BMW_MASK_NOP, FACE_MARK,
- BMW_FLAG_NOP,
- BMW_NIL_LAY);
-
- for (f2 = BMW_begin(&regwalker, f); f2; f2 = BMW_step(&regwalker)) {
- BM_ITER_ELEM (l2, &liter2, f2, BM_LOOPS_OF_FACE) {
- l3 = l2->radial_next;
- if (BMO_face_flag_test(bm, l3->f, FACE_MARK) !=
- BMO_face_flag_test(bm, l2->f, FACE_MARK))
- {
- if (!BMO_edge_flag_test(bm, l2->e, EDGE_MARK)) {
- return false;
- }
- }
- }
- }
- BMW_end(&regwalker);
-
- return true;
+ BMWalker regwalker;
+ BMIter liter2;
+ BMLoop *l2, *l3;
+ BMFace *f2;
+
+ /* checks if there are any unmarked boundary edges in the face regio */
+
+ BMW_init(&regwalker,
+ bm,
+ BMW_ISLAND,
+ BMW_MASK_NOP,
+ BMW_MASK_NOP,
+ FACE_MARK,
+ BMW_FLAG_NOP,
+ BMW_NIL_LAY);
+
+ for (f2 = BMW_begin(&regwalker, f); f2; f2 = BMW_step(&regwalker)) {
+ BM_ITER_ELEM (l2, &liter2, f2, BM_LOOPS_OF_FACE) {
+ l3 = l2->radial_next;
+ if (BMO_face_flag_test(bm, l3->f, FACE_MARK) != BMO_face_flag_test(bm, l2->f, FACE_MARK)) {
+ if (!BMO_edge_flag_test(bm, l2->e, EDGE_MARK)) {
+ return false;
+ }
+ }
+ }
+ }
+ BMW_end(&regwalker);
+
+ return true;
}
static void bm_face_split(BMesh *bm, const short oflag, bool use_edge_delete)
{
- BLI_Stack *edge_delete_verts;
- BMIter iter;
- BMVert *v;
-
- if (use_edge_delete) {
- edge_delete_verts = BLI_stack_new(sizeof(BMVert *), __func__);
- }
-
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- if (BMO_vert_flag_test(bm, v, oflag)) {
- if (BM_vert_is_edge_pair(v) == false) {
- BMIter liter;
- BMLoop *l;
- BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
- if (l->f->len > 3) {
- if (BMO_vert_flag_test(bm, l->next->v, oflag) == 0 &&
- BMO_vert_flag_test(bm, l->prev->v, oflag) == 0)
- {
- BM_face_split(bm, l->f, l->next, l->prev, NULL, NULL, true);
- }
- }
- }
-
- if (use_edge_delete) {
- BLI_stack_push(edge_delete_verts, &v);
- }
- }
- }
- }
-
- if (use_edge_delete) {
- while (!BLI_stack_is_empty(edge_delete_verts)) {
- /* remove surrounding edges & faces */
- BLI_stack_pop(edge_delete_verts, &v);
- while (v->e) {
- BM_edge_kill(bm, v->e);
- }
- }
- BLI_stack_free(edge_delete_verts);
- }
+ BLI_Stack *edge_delete_verts;
+ BMIter iter;
+ BMVert *v;
+
+ if (use_edge_delete) {
+ edge_delete_verts = BLI_stack_new(sizeof(BMVert *), __func__);
+ }
+
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BMO_vert_flag_test(bm, v, oflag)) {
+ if (BM_vert_is_edge_pair(v) == false) {
+ BMIter liter;
+ BMLoop *l;
+ BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
+ if (l->f->len > 3) {
+ if (BMO_vert_flag_test(bm, l->next->v, oflag) == 0 &&
+ BMO_vert_flag_test(bm, l->prev->v, oflag) == 0) {
+ BM_face_split(bm, l->f, l->next, l->prev, NULL, NULL, true);
+ }
+ }
+ }
+
+ if (use_edge_delete) {
+ BLI_stack_push(edge_delete_verts, &v);
+ }
+ }
+ }
+ }
+
+ if (use_edge_delete) {
+ while (!BLI_stack_is_empty(edge_delete_verts)) {
+ /* remove surrounding edges & faces */
+ BLI_stack_pop(edge_delete_verts, &v);
+ while (v->e) {
+ BM_edge_kill(bm, v->e);
+ }
+ }
+ BLI_stack_free(edge_delete_verts);
+ }
}
void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op)
{
- BMOIter oiter;
- BMFace *f;
- BMFace ***regions = NULL;
- BMFace **faces = NULL;
- BLI_array_declare(regions);
- BLI_array_declare(faces);
- BMFace *act_face = bm->act_face;
- BMWalker regwalker;
- int i;
-
- const bool use_verts = BMO_slot_bool_get(op->slots_in, "use_verts");
-
- if (use_verts) {
- /* tag verts that start out with only 2 edges,
- * don't remove these later */
- BMIter viter;
- BMVert *v;
-
- BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
- BMO_vert_flag_set(bm, v, VERT_MARK, !BM_vert_is_edge_pair(v));
- }
- }
-
- BMO_slot_buffer_flag_enable(bm, op->slots_in, "faces", BM_FACE, FACE_MARK | FACE_TAG);
-
- /* collect region */
- BMO_ITER (f, &oiter, op->slots_in, "faces", BM_FACE) {
- BMFace *f_iter;
- if (!BMO_face_flag_test(bm, f, FACE_TAG)) {
- continue;
- }
-
- BLI_array_clear(faces);
- faces = NULL; /* forces different allocatio */
-
- BMW_init(&regwalker, bm, BMW_ISLAND_MANIFOLD,
- BMW_MASK_NOP, BMW_MASK_NOP, FACE_MARK,
- BMW_FLAG_NOP, /* no need to check BMW_FLAG_TEST_HIDDEN, faces are already marked by the bmo */
- BMW_NIL_LAY);
-
- for (f_iter = BMW_begin(&regwalker, f); f_iter; f_iter = BMW_step(&regwalker)) {
- BLI_array_append(faces, f_iter);
- }
- BMW_end(&regwalker);
-
- for (i = 0; i < BLI_array_len(faces); i++) {
- f_iter = faces[i];
- BMO_face_flag_disable(bm, f_iter, FACE_TAG);
- BMO_face_flag_enable(bm, f_iter, FACE_ORIG);
- }
-
- if (BMO_error_occurred(bm)) {
- BMO_error_clear(bm);
- BMO_error_raise(bm, op, BMERR_DISSOLVEFACES_FAILED, NULL);
- goto cleanup;
- }
-
- BLI_array_append(faces, NULL);
- BLI_array_append(regions, faces);
- }
-
- /* track how many faces we should end up with */
- int totface_target = bm->totface;
-
- for (i = 0; i < BLI_array_len(regions); i++) {
- BMFace *f_new;
- int tot = 0;
-
- faces = regions[i];
- if (!faces[0]) {
- BMO_error_raise(bm, op, BMERR_DISSOLVEFACES_FAILED,
- "Could not find boundary of dissolve region");
- goto cleanup;
- }
-
- while (faces[tot]) {
- tot++;
- }
-
- f_new = BM_faces_join(bm, faces, tot, true);
-
- if (f_new) {
- /* maintain active face */
- if (act_face && bm->act_face == NULL) {
- bm->act_face = f_new;
- }
- totface_target -= tot - 1;
- }
- else {
- BMO_error_raise(bm, op, BMERR_DISSOLVEFACES_FAILED,
- "Could not create merged face");
- goto cleanup;
- }
-
- /* if making the new face failed (e.g. overlapping test)
- * unmark the original faces for deletion */
- BMO_face_flag_disable(bm, f_new, FACE_ORIG);
- BMO_face_flag_enable(bm, f_new, FACE_NEW);
- }
-
- /* Typically no faces need to be deleted */
- if (totface_target != bm->totface) {
- BMO_op_callf(bm, op->flag, "delete geom=%ff context=%i", FACE_ORIG, DEL_FACES);
- }
-
- if (use_verts) {
- BMIter viter;
- BMVert *v, *v_next;
-
- BM_ITER_MESH_MUTABLE (v, v_next, &viter, bm, BM_VERTS_OF_MESH) {
- if (BMO_vert_flag_test(bm, v, VERT_MARK)) {
- if (BM_vert_is_edge_pair(v)) {
- BM_vert_collapse_edge(bm, v->e, v, true, true);
- }
- }
- }
- }
-
- if (BMO_error_occurred(bm)) {
- goto cleanup;
- }
-
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "region.out", BM_FACE, FACE_NEW);
+ BMOIter oiter;
+ BMFace *f;
+ BMFace ***regions = NULL;
+ BMFace **faces = NULL;
+ BLI_array_declare(regions);
+ BLI_array_declare(faces);
+ BMFace *act_face = bm->act_face;
+ BMWalker regwalker;
+ int i;
+
+ const bool use_verts = BMO_slot_bool_get(op->slots_in, "use_verts");
+
+ if (use_verts) {
+ /* tag verts that start out with only 2 edges,
+ * don't remove these later */
+ BMIter viter;
+ BMVert *v;
+
+ BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
+ BMO_vert_flag_set(bm, v, VERT_MARK, !BM_vert_is_edge_pair(v));
+ }
+ }
+
+ BMO_slot_buffer_flag_enable(bm, op->slots_in, "faces", BM_FACE, FACE_MARK | FACE_TAG);
+
+ /* collect region */
+ BMO_ITER (f, &oiter, op->slots_in, "faces", BM_FACE) {
+ BMFace *f_iter;
+ if (!BMO_face_flag_test(bm, f, FACE_TAG)) {
+ continue;
+ }
+
+ BLI_array_clear(faces);
+ faces = NULL; /* forces different allocatio */
+
+ BMW_init(
+ &regwalker,
+ bm,
+ BMW_ISLAND_MANIFOLD,
+ BMW_MASK_NOP,
+ BMW_MASK_NOP,
+ FACE_MARK,
+ BMW_FLAG_NOP, /* no need to check BMW_FLAG_TEST_HIDDEN, faces are already marked by the bmo */
+ BMW_NIL_LAY);
+
+ for (f_iter = BMW_begin(&regwalker, f); f_iter; f_iter = BMW_step(&regwalker)) {
+ BLI_array_append(faces, f_iter);
+ }
+ BMW_end(&regwalker);
+
+ for (i = 0; i < BLI_array_len(faces); i++) {
+ f_iter = faces[i];
+ BMO_face_flag_disable(bm, f_iter, FACE_TAG);
+ BMO_face_flag_enable(bm, f_iter, FACE_ORIG);
+ }
+
+ if (BMO_error_occurred(bm)) {
+ BMO_error_clear(bm);
+ BMO_error_raise(bm, op, BMERR_DISSOLVEFACES_FAILED, NULL);
+ goto cleanup;
+ }
+
+ BLI_array_append(faces, NULL);
+ BLI_array_append(regions, faces);
+ }
+
+ /* track how many faces we should end up with */
+ int totface_target = bm->totface;
+
+ for (i = 0; i < BLI_array_len(regions); i++) {
+ BMFace *f_new;
+ int tot = 0;
+
+ faces = regions[i];
+ if (!faces[0]) {
+ BMO_error_raise(
+ bm, op, BMERR_DISSOLVEFACES_FAILED, "Could not find boundary of dissolve region");
+ goto cleanup;
+ }
+
+ while (faces[tot]) {
+ tot++;
+ }
+
+ f_new = BM_faces_join(bm, faces, tot, true);
+
+ if (f_new) {
+ /* maintain active face */
+ if (act_face && bm->act_face == NULL) {
+ bm->act_face = f_new;
+ }
+ totface_target -= tot - 1;
+ }
+ else {
+ BMO_error_raise(bm, op, BMERR_DISSOLVEFACES_FAILED, "Could not create merged face");
+ goto cleanup;
+ }
+
+ /* if making the new face failed (e.g. overlapping test)
+ * unmark the original faces for deletion */
+ BMO_face_flag_disable(bm, f_new, FACE_ORIG);
+ BMO_face_flag_enable(bm, f_new, FACE_NEW);
+ }
+
+ /* Typically no faces need to be deleted */
+ if (totface_target != bm->totface) {
+ BMO_op_callf(bm, op->flag, "delete geom=%ff context=%i", FACE_ORIG, DEL_FACES);
+ }
+
+ if (use_verts) {
+ BMIter viter;
+ BMVert *v, *v_next;
+
+ BM_ITER_MESH_MUTABLE (v, v_next, &viter, bm, BM_VERTS_OF_MESH) {
+ if (BMO_vert_flag_test(bm, v, VERT_MARK)) {
+ if (BM_vert_is_edge_pair(v)) {
+ BM_vert_collapse_edge(bm, v->e, v, true, true);
+ }
+ }
+ }
+ }
+
+ if (BMO_error_occurred(bm)) {
+ goto cleanup;
+ }
+
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "region.out", BM_FACE, FACE_NEW);
cleanup:
- /* free/cleanup */
- for (i = 0; i < BLI_array_len(regions); i++) {
- if (regions[i]) {
- MEM_freeN(regions[i]);
- }
- }
-
- BLI_array_free(regions);
+ /* free/cleanup */
+ for (i = 0; i < BLI_array_len(regions); i++) {
+ if (regions[i]) {
+ MEM_freeN(regions[i]);
+ }
+ }
+
+ BLI_array_free(regions);
}
void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op)
{
- /* BMOperator fop; */
- BMFace *act_face = bm->act_face;
- BMOIter eiter;
- BMIter iter;
- BMEdge *e, *e_next;
- BMVert *v, *v_next;
-
- const bool use_verts = BMO_slot_bool_get(op->slots_in, "use_verts");
- const bool use_face_split = BMO_slot_bool_get(op->slots_in, "use_face_split");
-
- if (use_face_split) {
- BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_TAG);
-
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- BMIter itersub;
- int untag_count = 0;
- BM_ITER_ELEM (e, &itersub, v, BM_EDGES_OF_VERT) {
- if (!BMO_edge_flag_test(bm, e, EDGE_TAG)) {
- untag_count++;
- }
- }
-
- /* check that we have 2 edges remaining after dissolve */
- if (untag_count <= 2) {
- BMO_vert_flag_enable(bm, v, VERT_TAG);
- }
- }
-
- bm_face_split(bm, VERT_TAG, false);
- }
-
- if (use_verts) {
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- BMO_vert_flag_set(bm, v, VERT_MARK, !BM_vert_is_edge_pair(v));
- }
- }
-
- /* tag all verts/edges connected to faces */
- BMO_ITER (e, &eiter, op->slots_in, "edges", BM_EDGE) {
- BMFace *f_pair[2];
- if (BM_edge_face_pair(e, &f_pair[0], &f_pair[1])) {
- uint j;
- for (j = 0; j < 2; j++) {
- BMLoop *l_first, *l_iter;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f_pair[j]);
- do {
- BMO_vert_flag_enable(bm, l_iter->v, VERT_ISGC);
- BMO_edge_flag_enable(bm, l_iter->e, EDGE_ISGC);
- } while ((l_iter = l_iter->next) != l_first);
- }
- }
- }
-
- BMO_ITER (e, &eiter, op->slots_in, "edges", BM_EDGE) {
- BMLoop *l_a, *l_b;
- if (BM_edge_loop_pair(e, &l_a, &l_b)) {
- BMFace *f_new;
-
- /* join faces */
- f_new = BM_faces_join_pair(bm, l_a, l_b, false);
-
- if (f_new) {
- /* maintain active face */
- if (act_face && bm->act_face == NULL) {
- bm->act_face = f_new;
- }
- }
- }
- }
-
- /* Cleanup geometry (#BM_faces_join_pair, but it removes geometry we're looping on)
- * so do this in a separate pass instead. */
- BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) {
- if ((e->l == NULL) && BMO_edge_flag_test(bm, e, EDGE_ISGC)) {
- BM_edge_kill(bm, e);
- }
- }
- BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
- if ((v->e == NULL) && BMO_vert_flag_test(bm, v, VERT_ISGC)) {
- BM_vert_kill(bm, v);
- }
- }
- /* done with cleanup */
-
-
- if (use_verts) {
- BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
- if (BMO_vert_flag_test(bm, v, VERT_MARK)) {
- if (BM_vert_is_edge_pair(v)) {
- BM_vert_collapse_edge(bm, v->e, v, true, true);
- }
- }
- }
- }
+ /* BMOperator fop; */
+ BMFace *act_face = bm->act_face;
+ BMOIter eiter;
+ BMIter iter;
+ BMEdge *e, *e_next;
+ BMVert *v, *v_next;
+
+ const bool use_verts = BMO_slot_bool_get(op->slots_in, "use_verts");
+ const bool use_face_split = BMO_slot_bool_get(op->slots_in, "use_face_split");
+
+ if (use_face_split) {
+ BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_TAG);
+
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ BMIter itersub;
+ int untag_count = 0;
+ BM_ITER_ELEM (e, &itersub, v, BM_EDGES_OF_VERT) {
+ if (!BMO_edge_flag_test(bm, e, EDGE_TAG)) {
+ untag_count++;
+ }
+ }
+
+ /* check that we have 2 edges remaining after dissolve */
+ if (untag_count <= 2) {
+ BMO_vert_flag_enable(bm, v, VERT_TAG);
+ }
+ }
+
+ bm_face_split(bm, VERT_TAG, false);
+ }
+
+ if (use_verts) {
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ BMO_vert_flag_set(bm, v, VERT_MARK, !BM_vert_is_edge_pair(v));
+ }
+ }
+
+ /* tag all verts/edges connected to faces */
+ BMO_ITER (e, &eiter, op->slots_in, "edges", BM_EDGE) {
+ BMFace *f_pair[2];
+ if (BM_edge_face_pair(e, &f_pair[0], &f_pair[1])) {
+ uint j;
+ for (j = 0; j < 2; j++) {
+ BMLoop *l_first, *l_iter;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_pair[j]);
+ do {
+ BMO_vert_flag_enable(bm, l_iter->v, VERT_ISGC);
+ BMO_edge_flag_enable(bm, l_iter->e, EDGE_ISGC);
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ }
+ }
+
+ BMO_ITER (e, &eiter, op->slots_in, "edges", BM_EDGE) {
+ BMLoop *l_a, *l_b;
+ if (BM_edge_loop_pair(e, &l_a, &l_b)) {
+ BMFace *f_new;
+
+ /* join faces */
+ f_new = BM_faces_join_pair(bm, l_a, l_b, false);
+
+ if (f_new) {
+ /* maintain active face */
+ if (act_face && bm->act_face == NULL) {
+ bm->act_face = f_new;
+ }
+ }
+ }
+ }
+
+ /* Cleanup geometry (#BM_faces_join_pair, but it removes geometry we're looping on)
+ * so do this in a separate pass instead. */
+ BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) {
+ if ((e->l == NULL) && BMO_edge_flag_test(bm, e, EDGE_ISGC)) {
+ BM_edge_kill(bm, e);
+ }
+ }
+ BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
+ if ((v->e == NULL) && BMO_vert_flag_test(bm, v, VERT_ISGC)) {
+ BM_vert_kill(bm, v);
+ }
+ }
+ /* done with cleanup */
+
+ if (use_verts) {
+ BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BMO_vert_flag_test(bm, v, VERT_MARK)) {
+ if (BM_vert_is_edge_pair(v)) {
+ BM_vert_collapse_edge(bm, v->e, v, true, true);
+ }
+ }
+ }
+ }
}
void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op)
{
- BMOIter oiter;
- BMIter iter;
- BMVert *v, *v_next;
- BMEdge *e, *e_next;
- BMFace *act_face = bm->act_face;
-
- const bool use_face_split = BMO_slot_bool_get(op->slots_in, "use_face_split");
- const bool use_boundary_tear = BMO_slot_bool_get(op->slots_in, "use_boundary_tear");
-
- BMO_ITER (v, &oiter, op->slots_in, "verts", BM_VERT) {
- BMO_vert_flag_enable(bm, v, VERT_MARK | VERT_ISGC);
- }
-
- if (use_face_split) {
- bm_face_split(bm, VERT_MARK, false);
- }
-
- if (use_boundary_tear) {
- BMO_ITER (v, &oiter, op->slots_in, "verts", BM_VERT) {
- if (!BM_vert_is_edge_pair(v)) {
- BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
- if (BM_edge_is_boundary(e)) {
- BMO_vert_flag_enable(bm, v, VERT_MARK_TEAR);
- break;
- }
- }
- }
- }
-
- bm_face_split(bm, VERT_MARK_TEAR, true);
- }
-
- BMO_ITER (v, &oiter, op->slots_in, "verts", BM_VERT) {
- BMIter itersub;
- BMLoop *l_first;
- BMEdge *e_first = NULL;
- BM_ITER_ELEM (l_first, &itersub, v, BM_LOOPS_OF_VERT) {
- BMLoop *l_iter;
- l_iter = l_first;
- do {
- BMO_vert_flag_enable(bm, l_iter->v, VERT_ISGC);
- BMO_edge_flag_enable(bm, l_iter->e, EDGE_ISGC);
- } while ((l_iter = l_iter->next) != l_first);
-
- e_first = l_first->e;
- }
-
- /* important e_first won't be deleted */
- if (e_first) {
- e = e_first;
- do {
- e_next = BM_DISK_EDGE_NEXT(e, v);
- if (BM_edge_is_wire(e)) {
- BM_edge_kill(bm, e);
- }
- } while ((e = e_next) != e_first);
- }
- }
-
- BMO_ITER (v, &oiter, op->slots_in, "verts", BM_VERT) {
- /* tag here so we avoid feedback loop (checking topology as we edit) */
- if (BM_vert_is_edge_pair(v)) {
- BMO_vert_flag_enable(bm, v, VERT_MARK_PAIR);
- }
- }
-
- BMO_ITER (v, &oiter, op->slots_in, "verts", BM_VERT) {
- BMIter itersub;
-
- if (!BMO_vert_flag_test(bm, v, VERT_MARK_PAIR)) {
- BM_ITER_ELEM (e, &itersub, v, BM_EDGES_OF_VERT) {
- BMLoop *l_a, *l_b;
- if (BM_edge_loop_pair(e, &l_a, &l_b)) {
- BMFace *f_new;
-
- /* join faces */
- f_new = BM_faces_join_pair(bm, l_a, l_b, false);
-
- /* maintain active face */
- if (act_face && bm->act_face == NULL) {
- bm->act_face = f_new;
- }
- }
- }
- }
- }
-
- /* Cleanup geometry (#BM_faces_join_pair, but it removes geometry we're looping on)
- * so do this in a separate pass instead. */
- BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) {
- if ((e->l == NULL) && BMO_edge_flag_test(bm, e, EDGE_ISGC)) {
- BM_edge_kill(bm, e);
- }
- }
-
- /* final cleanup */
- BMO_ITER (v, &oiter, op->slots_in, "verts", BM_VERT) {
- if (BM_vert_is_edge_pair(v)) {
- BM_vert_collapse_edge(bm, v->e, v, false, true);
- }
- }
-
- BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
- if ((v->e == NULL) && BMO_vert_flag_test(bm, v, VERT_ISGC)) {
- BM_vert_kill(bm, v);
- }
- }
- /* done with cleanup */
+ BMOIter oiter;
+ BMIter iter;
+ BMVert *v, *v_next;
+ BMEdge *e, *e_next;
+ BMFace *act_face = bm->act_face;
+
+ const bool use_face_split = BMO_slot_bool_get(op->slots_in, "use_face_split");
+ const bool use_boundary_tear = BMO_slot_bool_get(op->slots_in, "use_boundary_tear");
+
+ BMO_ITER (v, &oiter, op->slots_in, "verts", BM_VERT) {
+ BMO_vert_flag_enable(bm, v, VERT_MARK | VERT_ISGC);
+ }
+
+ if (use_face_split) {
+ bm_face_split(bm, VERT_MARK, false);
+ }
+
+ if (use_boundary_tear) {
+ BMO_ITER (v, &oiter, op->slots_in, "verts", BM_VERT) {
+ if (!BM_vert_is_edge_pair(v)) {
+ BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
+ if (BM_edge_is_boundary(e)) {
+ BMO_vert_flag_enable(bm, v, VERT_MARK_TEAR);
+ break;
+ }
+ }
+ }
+ }
+
+ bm_face_split(bm, VERT_MARK_TEAR, true);
+ }
+
+ BMO_ITER (v, &oiter, op->slots_in, "verts", BM_VERT) {
+ BMIter itersub;
+ BMLoop *l_first;
+ BMEdge *e_first = NULL;
+ BM_ITER_ELEM (l_first, &itersub, v, BM_LOOPS_OF_VERT) {
+ BMLoop *l_iter;
+ l_iter = l_first;
+ do {
+ BMO_vert_flag_enable(bm, l_iter->v, VERT_ISGC);
+ BMO_edge_flag_enable(bm, l_iter->e, EDGE_ISGC);
+ } while ((l_iter = l_iter->next) != l_first);
+
+ e_first = l_first->e;
+ }
+
+ /* important e_first won't be deleted */
+ if (e_first) {
+ e = e_first;
+ do {
+ e_next = BM_DISK_EDGE_NEXT(e, v);
+ if (BM_edge_is_wire(e)) {
+ BM_edge_kill(bm, e);
+ }
+ } while ((e = e_next) != e_first);
+ }
+ }
+
+ BMO_ITER (v, &oiter, op->slots_in, "verts", BM_VERT) {
+ /* tag here so we avoid feedback loop (checking topology as we edit) */
+ if (BM_vert_is_edge_pair(v)) {
+ BMO_vert_flag_enable(bm, v, VERT_MARK_PAIR);
+ }
+ }
+
+ BMO_ITER (v, &oiter, op->slots_in, "verts", BM_VERT) {
+ BMIter itersub;
+
+ if (!BMO_vert_flag_test(bm, v, VERT_MARK_PAIR)) {
+ BM_ITER_ELEM (e, &itersub, v, BM_EDGES_OF_VERT) {
+ BMLoop *l_a, *l_b;
+ if (BM_edge_loop_pair(e, &l_a, &l_b)) {
+ BMFace *f_new;
+
+ /* join faces */
+ f_new = BM_faces_join_pair(bm, l_a, l_b, false);
+
+ /* maintain active face */
+ if (act_face && bm->act_face == NULL) {
+ bm->act_face = f_new;
+ }
+ }
+ }
+ }
+ }
+
+ /* Cleanup geometry (#BM_faces_join_pair, but it removes geometry we're looping on)
+ * so do this in a separate pass instead. */
+ BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) {
+ if ((e->l == NULL) && BMO_edge_flag_test(bm, e, EDGE_ISGC)) {
+ BM_edge_kill(bm, e);
+ }
+ }
+
+ /* final cleanup */
+ BMO_ITER (v, &oiter, op->slots_in, "verts", BM_VERT) {
+ if (BM_vert_is_edge_pair(v)) {
+ BM_vert_collapse_edge(bm, v->e, v, false, true);
+ }
+ }
+
+ BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
+ if ((v->e == NULL) && BMO_vert_flag_test(bm, v, VERT_ISGC)) {
+ BM_vert_kill(bm, v);
+ }
+ }
+ /* done with cleanup */
}
/* Limited Dissolve */
void bmo_dissolve_limit_exec(BMesh *bm, BMOperator *op)
{
- BMOpSlot *einput = BMO_slot_get(op->slots_in, "edges");
- BMOpSlot *vinput = BMO_slot_get(op->slots_in, "verts");
- const float angle_max = M_PI_2;
- const float angle_limit = min_ff(angle_max, BMO_slot_float_get(op->slots_in, "angle_limit"));
- const bool do_dissolve_boundaries = BMO_slot_bool_get(op->slots_in, "use_dissolve_boundaries");
- const BMO_Delimit delimit = BMO_slot_int_get(op->slots_in, "delimit");
-
- BM_mesh_decimate_dissolve_ex(bm, angle_limit, do_dissolve_boundaries, delimit,
- (BMVert **)BMO_SLOT_AS_BUFFER(vinput), vinput->len,
- (BMEdge **)BMO_SLOT_AS_BUFFER(einput), einput->len,
- FACE_NEW);
-
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "region.out", BM_FACE, FACE_NEW);
+ BMOpSlot *einput = BMO_slot_get(op->slots_in, "edges");
+ BMOpSlot *vinput = BMO_slot_get(op->slots_in, "verts");
+ const float angle_max = M_PI_2;
+ const float angle_limit = min_ff(angle_max, BMO_slot_float_get(op->slots_in, "angle_limit"));
+ const bool do_dissolve_boundaries = BMO_slot_bool_get(op->slots_in, "use_dissolve_boundaries");
+ const BMO_Delimit delimit = BMO_slot_int_get(op->slots_in, "delimit");
+
+ BM_mesh_decimate_dissolve_ex(bm,
+ angle_limit,
+ do_dissolve_boundaries,
+ delimit,
+ (BMVert **)BMO_SLOT_AS_BUFFER(vinput),
+ vinput->len,
+ (BMEdge **)BMO_SLOT_AS_BUFFER(einput),
+ einput->len,
+ FACE_NEW);
+
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "region.out", BM_FACE, FACE_NEW);
}
-
#define EDGE_MARK 1
#define EDGE_COLLAPSE 2
static void bm_mesh_edge_collapse_flagged(BMesh *bm, const int flag, const short oflag)
{
- BMO_op_callf(bm, flag, "collapse edges=%fe uvs=%b", oflag, true);
+ BMO_op_callf(bm, flag, "collapse edges=%fe uvs=%b", oflag, true);
}
void bmo_dissolve_degenerate_exec(BMesh *bm, BMOperator *op)
{
- const float dist = BMO_slot_float_get(op->slots_in, "dist");
- const float dist_sq = dist * dist;
-
- bool found;
- BMIter eiter;
- BMEdge *e;
-
-
- BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK);
-
- /* collapse zero length edges, this accounts for zero area faces too */
- found = false;
- BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
- if (BMO_edge_flag_test(bm, e, EDGE_MARK)) {
- if (BM_edge_calc_length_squared(e) < dist_sq) {
- BMO_edge_flag_enable(bm, e, EDGE_COLLAPSE);
- found = true;
- }
- }
-
- /* clear all loop tags (checked later) */
- if (e->l) {
- BMLoop *l_iter, *l_first;
- l_iter = l_first = e->l;
- do {
- BM_elem_flag_disable(l_iter, BM_ELEM_TAG);
- } while ((l_iter = l_iter->radial_next) != l_first);
- }
- }
-
- if (found) {
- bm_mesh_edge_collapse_flagged(bm, op->flag, EDGE_COLLAPSE);
- }
-
-
- /* clip degenerate ears from the face */
- found = false;
- BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
- if (e->l && BMO_edge_flag_test(bm, e, EDGE_MARK)) {
- BMLoop *l_iter, *l_first;
- l_iter = l_first = e->l;
- do {
- if (
- /* check the loop hasn't already been tested (and flag not to test again) */
- !BM_elem_flag_test(l_iter, BM_ELEM_TAG) &&
- ((void)BM_elem_flag_enable(l_iter, BM_ELEM_TAG),
-
- /* check we're marked to tested (radial edge already tested) */
- BMO_edge_flag_test(bm, l_iter->prev->e, EDGE_MARK) &&
-
- /* check edges are not already going to be collapsed */
- !BMO_edge_flag_test(bm, l_iter->e, EDGE_COLLAPSE) &&
- !BMO_edge_flag_test(bm, l_iter->prev->e, EDGE_COLLAPSE)))
- {
- /* test if the faces loop (ear) is degenerate */
- float dir_prev[3], len_prev;
- float dir_next[3], len_next;
-
-
- sub_v3_v3v3(dir_prev, l_iter->prev->v->co, l_iter->v->co);
- sub_v3_v3v3(dir_next, l_iter->next->v->co, l_iter->v->co);
-
- len_prev = normalize_v3(dir_prev);
- len_next = normalize_v3(dir_next);
-
- if ((len_v3v3(dir_prev, dir_next) * min_ff(len_prev, len_next)) <= dist) {
- bool reset = false;
-
- if (fabsf(len_prev - len_next) <= dist) {
- /* both edges the same length */
- if (l_iter->f->len == 3) {
- /* ideally this would have been discovered with short edge test above */
- BMO_edge_flag_enable(bm, l_iter->next->e, EDGE_COLLAPSE);
- found = true;
- }
- else {
- /* add a joining edge and tag for removal */
- BMLoop *l_split;
- if (BM_face_split(bm, l_iter->f, l_iter->prev, l_iter->next, &l_split, NULL, true)) {
- BMO_edge_flag_enable(bm, l_split->e, EDGE_COLLAPSE);
- found = true;
- reset = true;
- }
- }
- }
- else if (len_prev < len_next) {
- /* split 'l_iter->e', then join the vert with next */
- BMVert *v_new;
- BMEdge *e_new;
- BMLoop *l_split;
- v_new = BM_edge_split(bm, l_iter->e, l_iter->v, &e_new, len_prev / len_next);
- BLI_assert(v_new == l_iter->next->v);
- (void)v_new;
- if (BM_face_split(bm, l_iter->f, l_iter->prev, l_iter->next, &l_split, NULL, true)) {
- BMO_edge_flag_enable(bm, l_split->e, EDGE_COLLAPSE);
- found = true;
- }
- reset = true;
- }
- else if (len_next < len_prev) {
- /* split 'l_iter->prev->e', then join the vert with next */
- BMVert *v_new;
- BMEdge *e_new;
- BMLoop *l_split;
- v_new = BM_edge_split(bm, l_iter->prev->e, l_iter->v, &e_new, len_next / len_prev);
- BLI_assert(v_new == l_iter->prev->v);
- (void)v_new;
- if (BM_face_split(bm, l_iter->f, l_iter->prev, l_iter->next, &l_split, NULL, true)) {
- BMO_edge_flag_enable(bm, l_split->e, EDGE_COLLAPSE);
- found = true;
- }
- reset = true;
- }
-
- if (reset) {
- /* we can't easily track where we are on the radial edge, reset! */
- l_first = l_iter;
- }
- }
- }
- } while ((l_iter = l_iter->radial_next) != l_first);
- }
- }
-
- if (found) {
- bm_mesh_edge_collapse_flagged(bm, op->flag, EDGE_COLLAPSE);
- }
-
+ const float dist = BMO_slot_float_get(op->slots_in, "dist");
+ const float dist_sq = dist * dist;
+
+ bool found;
+ BMIter eiter;
+ BMEdge *e;
+
+ BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK);
+
+ /* collapse zero length edges, this accounts for zero area faces too */
+ found = false;
+ BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
+ if (BMO_edge_flag_test(bm, e, EDGE_MARK)) {
+ if (BM_edge_calc_length_squared(e) < dist_sq) {
+ BMO_edge_flag_enable(bm, e, EDGE_COLLAPSE);
+ found = true;
+ }
+ }
+
+ /* clear all loop tags (checked later) */
+ if (e->l) {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = e->l;
+ do {
+ BM_elem_flag_disable(l_iter, BM_ELEM_TAG);
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+ }
+
+ if (found) {
+ bm_mesh_edge_collapse_flagged(bm, op->flag, EDGE_COLLAPSE);
+ }
+
+ /* clip degenerate ears from the face */
+ found = false;
+ BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
+ if (e->l && BMO_edge_flag_test(bm, e, EDGE_MARK)) {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = e->l;
+ do {
+ if (
+ /* check the loop hasn't already been tested (and flag not to test again) */
+ !BM_elem_flag_test(l_iter, BM_ELEM_TAG) &&
+ ((void)BM_elem_flag_enable(l_iter, BM_ELEM_TAG),
+
+ /* check we're marked to tested (radial edge already tested) */
+ BMO_edge_flag_test(bm, l_iter->prev->e, EDGE_MARK) &&
+
+ /* check edges are not already going to be collapsed */
+ !BMO_edge_flag_test(bm, l_iter->e, EDGE_COLLAPSE) &&
+ !BMO_edge_flag_test(bm, l_iter->prev->e, EDGE_COLLAPSE))) {
+ /* test if the faces loop (ear) is degenerate */
+ float dir_prev[3], len_prev;
+ float dir_next[3], len_next;
+
+ sub_v3_v3v3(dir_prev, l_iter->prev->v->co, l_iter->v->co);
+ sub_v3_v3v3(dir_next, l_iter->next->v->co, l_iter->v->co);
+
+ len_prev = normalize_v3(dir_prev);
+ len_next = normalize_v3(dir_next);
+
+ if ((len_v3v3(dir_prev, dir_next) * min_ff(len_prev, len_next)) <= dist) {
+ bool reset = false;
+
+ if (fabsf(len_prev - len_next) <= dist) {
+ /* both edges the same length */
+ if (l_iter->f->len == 3) {
+ /* ideally this would have been discovered with short edge test above */
+ BMO_edge_flag_enable(bm, l_iter->next->e, EDGE_COLLAPSE);
+ found = true;
+ }
+ else {
+ /* add a joining edge and tag for removal */
+ BMLoop *l_split;
+ if (BM_face_split(
+ bm, l_iter->f, l_iter->prev, l_iter->next, &l_split, NULL, true)) {
+ BMO_edge_flag_enable(bm, l_split->e, EDGE_COLLAPSE);
+ found = true;
+ reset = true;
+ }
+ }
+ }
+ else if (len_prev < len_next) {
+ /* split 'l_iter->e', then join the vert with next */
+ BMVert *v_new;
+ BMEdge *e_new;
+ BMLoop *l_split;
+ v_new = BM_edge_split(bm, l_iter->e, l_iter->v, &e_new, len_prev / len_next);
+ BLI_assert(v_new == l_iter->next->v);
+ (void)v_new;
+ if (BM_face_split(bm, l_iter->f, l_iter->prev, l_iter->next, &l_split, NULL, true)) {
+ BMO_edge_flag_enable(bm, l_split->e, EDGE_COLLAPSE);
+ found = true;
+ }
+ reset = true;
+ }
+ else if (len_next < len_prev) {
+ /* split 'l_iter->prev->e', then join the vert with next */
+ BMVert *v_new;
+ BMEdge *e_new;
+ BMLoop *l_split;
+ v_new = BM_edge_split(bm, l_iter->prev->e, l_iter->v, &e_new, len_next / len_prev);
+ BLI_assert(v_new == l_iter->prev->v);
+ (void)v_new;
+ if (BM_face_split(bm, l_iter->f, l_iter->prev, l_iter->next, &l_split, NULL, true)) {
+ BMO_edge_flag_enable(bm, l_split->e, EDGE_COLLAPSE);
+ found = true;
+ }
+ reset = true;
+ }
+
+ if (reset) {
+ /* we can't easily track where we are on the radial edge, reset! */
+ l_first = l_iter;
+ }
+ }
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+ }
+
+ if (found) {
+ bm_mesh_edge_collapse_flagged(bm, op->flag, EDGE_COLLAPSE);
+ }
}
diff --git a/source/blender/bmesh/operators/bmo_dupe.c b/source/blender/bmesh/operators/bmo_dupe.c
index 5c7c78eb654..6dd361d62b3 100644
--- a/source/blender/bmesh/operators/bmo_dupe.c
+++ b/source/blender/bmesh/operators/bmo_dupe.c
@@ -30,9 +30,9 @@
#include "intern/bmesh_operators_private.h" /* own include */
/* local flag define */
-#define DUPE_INPUT 1 /* input from operator */
-#define DUPE_NEW 2
-#define DUPE_DONE 4
+#define DUPE_INPUT 1 /* input from operator */
+#define DUPE_NEW 2
+#define DUPE_DONE 4
// #define DUPE_MAPPED 8 // UNUSED
/**
@@ -40,28 +40,30 @@
*
* Copy an existing vertex from one bmesh to another.
*/
-static BMVert *bmo_vert_copy(
- BMOperator *op,
- BMOpSlot *slot_vertmap_out,
- BMesh *bm_dst, BMesh *bm_src, BMVert *v_src, GHash *vhash)
+static BMVert *bmo_vert_copy(BMOperator *op,
+ BMOpSlot *slot_vertmap_out,
+ BMesh *bm_dst,
+ BMesh *bm_src,
+ BMVert *v_src,
+ GHash *vhash)
{
- BMVert *v_dst;
+ BMVert *v_dst;
- /* Create a new vertex */
- v_dst = BM_vert_create(bm_dst, v_src->co, NULL, BM_CREATE_SKIP_CD);
- BMO_slot_map_elem_insert(op, slot_vertmap_out, v_src, v_dst);
- BMO_slot_map_elem_insert(op, slot_vertmap_out, v_dst, v_src);
+ /* Create a new vertex */
+ v_dst = BM_vert_create(bm_dst, v_src->co, NULL, BM_CREATE_SKIP_CD);
+ BMO_slot_map_elem_insert(op, slot_vertmap_out, v_src, v_dst);
+ BMO_slot_map_elem_insert(op, slot_vertmap_out, v_dst, v_src);
- /* Insert new vertex into the vert hash */
- BLI_ghash_insert(vhash, v_src, v_dst);
+ /* Insert new vertex into the vert hash */
+ BLI_ghash_insert(vhash, v_src, v_dst);
- /* Copy attributes */
- BM_elem_attrs_copy(bm_src, bm_dst, v_src, v_dst);
+ /* Copy attributes */
+ BM_elem_attrs_copy(bm_src, bm_dst, v_src, v_dst);
- /* Mark the vert for output */
- BMO_vert_flag_enable(bm_dst, v_dst, DUPE_NEW);
+ /* Mark the vert for output */
+ BMO_vert_flag_enable(bm_dst, v_dst, DUPE_NEW);
- return v_dst;
+ return v_dst;
}
/**
@@ -69,68 +71,69 @@ static BMVert *bmo_vert_copy(
*
* Copy an existing edge from one bmesh to another.
*/
-static BMEdge *bmo_edge_copy(
- BMOperator *op,
- BMOpSlot *slot_edgemap_out,
- BMOpSlot *slot_boundarymap_out,
- BMesh *bm_dst, BMesh *bm_src,
- BMEdge *e_src,
- GHash *vhash, GHash *ehash,
- const bool use_edge_flip_from_face)
+static BMEdge *bmo_edge_copy(BMOperator *op,
+ BMOpSlot *slot_edgemap_out,
+ BMOpSlot *slot_boundarymap_out,
+ BMesh *bm_dst,
+ BMesh *bm_src,
+ BMEdge *e_src,
+ GHash *vhash,
+ GHash *ehash,
+ const bool use_edge_flip_from_face)
{
- BMEdge *e_dst;
- BMVert *e_dst_v1, *e_dst_v2;
- uint rlen;
-
- /* see if any of the neighboring faces are
- * not being duplicated. in that case,
- * add it to the new/old map. */
- /* lookup edge */
- rlen = 0;
- if (e_src->l) {
- BMLoop *l_iter_src, *l_first_src;
- l_iter_src = l_first_src = e_src->l;
- do {
- if (BMO_face_flag_test(bm_src, l_iter_src->f, DUPE_INPUT)) {
- rlen++;
- }
- } while ((l_iter_src = l_iter_src->radial_next) != l_first_src);
- }
-
- /* Lookup v1 and v2 */
- e_dst_v1 = BLI_ghash_lookup(vhash, e_src->v1);
- e_dst_v2 = BLI_ghash_lookup(vhash, e_src->v2);
-
- /* Create a new edge */
- e_dst = BM_edge_create(bm_dst, e_dst_v1, e_dst_v2, NULL, BM_CREATE_SKIP_CD);
- BMO_slot_map_elem_insert(op, slot_edgemap_out, e_src, e_dst);
- BMO_slot_map_elem_insert(op, slot_edgemap_out, e_dst, e_src);
-
- /* add to new/old edge map if necassary */
- if (rlen < 2) {
- /* not sure what non-manifold cases of greater than three
- * radial should do. */
- BMO_slot_map_elem_insert(op, slot_boundarymap_out, e_src, e_dst);
- }
-
- /* Insert new edge into the edge hash */
- BLI_ghash_insert(ehash, e_src, e_dst);
-
- /* Copy attributes */
- BM_elem_attrs_copy(bm_src, bm_dst, e_src, e_dst);
-
- /* Mark the edge for output */
- BMO_edge_flag_enable(bm_dst, e_dst, DUPE_NEW);
-
- if (use_edge_flip_from_face) {
- /* Take winding from previous face (if we had one),
- * otherwise extruding a duplicated edges gives bad normals, see: T62487. */
- if (BM_edge_is_boundary(e_src) && (e_src->l->v == e_src->v1)) {
- BM_edge_verts_swap(e_dst);
- }
- }
-
- return e_dst;
+ BMEdge *e_dst;
+ BMVert *e_dst_v1, *e_dst_v2;
+ uint rlen;
+
+ /* see if any of the neighboring faces are
+ * not being duplicated. in that case,
+ * add it to the new/old map. */
+ /* lookup edge */
+ rlen = 0;
+ if (e_src->l) {
+ BMLoop *l_iter_src, *l_first_src;
+ l_iter_src = l_first_src = e_src->l;
+ do {
+ if (BMO_face_flag_test(bm_src, l_iter_src->f, DUPE_INPUT)) {
+ rlen++;
+ }
+ } while ((l_iter_src = l_iter_src->radial_next) != l_first_src);
+ }
+
+ /* Lookup v1 and v2 */
+ e_dst_v1 = BLI_ghash_lookup(vhash, e_src->v1);
+ e_dst_v2 = BLI_ghash_lookup(vhash, e_src->v2);
+
+ /* Create a new edge */
+ e_dst = BM_edge_create(bm_dst, e_dst_v1, e_dst_v2, NULL, BM_CREATE_SKIP_CD);
+ BMO_slot_map_elem_insert(op, slot_edgemap_out, e_src, e_dst);
+ BMO_slot_map_elem_insert(op, slot_edgemap_out, e_dst, e_src);
+
+ /* add to new/old edge map if necassary */
+ if (rlen < 2) {
+ /* not sure what non-manifold cases of greater than three
+ * radial should do. */
+ BMO_slot_map_elem_insert(op, slot_boundarymap_out, e_src, e_dst);
+ }
+
+ /* Insert new edge into the edge hash */
+ BLI_ghash_insert(ehash, e_src, e_dst);
+
+ /* Copy attributes */
+ BM_elem_attrs_copy(bm_src, bm_dst, e_src, e_dst);
+
+ /* Mark the edge for output */
+ BMO_edge_flag_enable(bm_dst, e_dst, DUPE_NEW);
+
+ if (use_edge_flip_from_face) {
+ /* Take winding from previous face (if we had one),
+ * otherwise extruding a duplicated edges gives bad normals, see: T62487. */
+ if (BM_edge_is_boundary(e_src) && (e_src->l->v == e_src->v1)) {
+ BM_edge_verts_swap(e_dst);
+ }
+ }
+
+ return e_dst;
}
/**
@@ -138,51 +141,50 @@ static BMEdge *bmo_edge_copy(
*
* Copy an existing face from one bmesh to another.
*/
-static BMFace *bmo_face_copy(
- BMOperator *op,
- BMOpSlot *slot_facemap_out,
- BMesh *bm_dst, BMesh *bm_src,
- BMFace *f_src,
- GHash *vhash, GHash *ehash)
+static BMFace *bmo_face_copy(BMOperator *op,
+ BMOpSlot *slot_facemap_out,
+ BMesh *bm_dst,
+ BMesh *bm_src,
+ BMFace *f_src,
+ GHash *vhash,
+ GHash *ehash)
{
- BMFace *f_dst;
- BMVert **vtar = BLI_array_alloca(vtar, f_src->len);
- BMEdge **edar = BLI_array_alloca(edar, f_src->len);
- BMLoop *l_iter_src, *l_iter_dst, *l_first_src;
- int i;
-
- l_first_src = BM_FACE_FIRST_LOOP(f_src);
-
- /* lookup edge */
- l_iter_src = l_first_src;
- i = 0;
- do {
- vtar[i] = BLI_ghash_lookup(vhash, l_iter_src->v);
- edar[i] = BLI_ghash_lookup(ehash, l_iter_src->e);
- i++;
- } while ((l_iter_src = l_iter_src->next) != l_first_src);
-
- /* create new face */
- f_dst = BM_face_create(bm_dst, vtar, edar, f_src->len, NULL, BM_CREATE_SKIP_CD);
- BMO_slot_map_elem_insert(op, slot_facemap_out, f_src, f_dst);
- BMO_slot_map_elem_insert(op, slot_facemap_out, f_dst, f_src);
-
- /* Copy attributes */
- BM_elem_attrs_copy(bm_src, bm_dst, f_src, f_dst);
-
- /* copy per-loop custom data */
- l_iter_src = l_first_src;
- l_iter_dst = BM_FACE_FIRST_LOOP(f_dst);
- do {
- BM_elem_attrs_copy(bm_src, bm_dst, l_iter_src, l_iter_dst);
- } while ((void)
- (l_iter_dst = l_iter_dst->next),
- (l_iter_src = l_iter_src->next) != l_first_src);
-
- /* Mark the face for output */
- BMO_face_flag_enable(bm_dst, f_dst, DUPE_NEW);
-
- return f_dst;
+ BMFace *f_dst;
+ BMVert **vtar = BLI_array_alloca(vtar, f_src->len);
+ BMEdge **edar = BLI_array_alloca(edar, f_src->len);
+ BMLoop *l_iter_src, *l_iter_dst, *l_first_src;
+ int i;
+
+ l_first_src = BM_FACE_FIRST_LOOP(f_src);
+
+ /* lookup edge */
+ l_iter_src = l_first_src;
+ i = 0;
+ do {
+ vtar[i] = BLI_ghash_lookup(vhash, l_iter_src->v);
+ edar[i] = BLI_ghash_lookup(ehash, l_iter_src->e);
+ i++;
+ } while ((l_iter_src = l_iter_src->next) != l_first_src);
+
+ /* create new face */
+ f_dst = BM_face_create(bm_dst, vtar, edar, f_src->len, NULL, BM_CREATE_SKIP_CD);
+ BMO_slot_map_elem_insert(op, slot_facemap_out, f_src, f_dst);
+ BMO_slot_map_elem_insert(op, slot_facemap_out, f_dst, f_src);
+
+ /* Copy attributes */
+ BM_elem_attrs_copy(bm_src, bm_dst, f_src, f_dst);
+
+ /* copy per-loop custom data */
+ l_iter_src = l_first_src;
+ l_iter_dst = BM_FACE_FIRST_LOOP(f_dst);
+ do {
+ BM_elem_attrs_copy(bm_src, bm_dst, l_iter_src, l_iter_dst);
+ } while ((void)(l_iter_dst = l_iter_dst->next), (l_iter_src = l_iter_src->next) != l_first_src);
+
+ /* Mark the face for output */
+ BMO_face_flag_enable(bm_dst, f_dst, DUPE_NEW);
+
+ return f_dst;
}
/**
@@ -192,120 +194,128 @@ static BMFace *bmo_face_copy(
*/
static void bmo_mesh_copy(BMOperator *op, BMesh *bm_dst, BMesh *bm_src)
{
- const bool use_select_history = BMO_slot_bool_get(op->slots_in, "use_select_history");
- const bool use_edge_flip_from_face = BMO_slot_bool_get(op->slots_in, "use_edge_flip_from_face");
-
- BMVert *v = NULL, *v2;
- BMEdge *e = NULL;
- BMFace *f = NULL;
-
- BMIter viter, eiter, fiter;
- GHash *vhash, *ehash;
-
- BMOpSlot *slot_boundary_map_out = BMO_slot_get(op->slots_out, "boundary_map.out");
- BMOpSlot *slot_isovert_map_out = BMO_slot_get(op->slots_out, "isovert_map.out");
-
- BMOpSlot *slot_vert_map_out = BMO_slot_get(op->slots_out, "vert_map.out");
- BMOpSlot *slot_edge_map_out = BMO_slot_get(op->slots_out, "edge_map.out");
- BMOpSlot *slot_face_map_out = BMO_slot_get(op->slots_out, "face_map.out");
-
- /* initialize pointer hashes */
- vhash = BLI_ghash_ptr_new("bmesh dupeops v");
- ehash = BLI_ghash_ptr_new("bmesh dupeops e");
-
- /* duplicate flagged vertices */
- BM_ITER_MESH (v, &viter, bm_src, BM_VERTS_OF_MESH) {
- if (BMO_vert_flag_test(bm_src, v, DUPE_INPUT) &&
- BMO_vert_flag_test(bm_src, v, DUPE_DONE) == false)
- {
- BMIter iter;
- bool isolated = true;
-
- v2 = bmo_vert_copy(op, slot_vert_map_out, bm_dst, bm_src, v, vhash);
-
- BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) {
- if (BMO_face_flag_test(bm_src, f, DUPE_INPUT)) {
- isolated = false;
- break;
- }
- }
-
- if (isolated) {
- BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
- if (BMO_edge_flag_test(bm_src, e, DUPE_INPUT)) {
- isolated = false;
- break;
- }
- }
- }
-
- if (isolated) {
- BMO_slot_map_elem_insert(op, slot_isovert_map_out, v, v2);
- }
-
- BMO_vert_flag_enable(bm_src, v, DUPE_DONE);
- }
- }
-
- /* now we dupe all the edges */
- BM_ITER_MESH (e, &eiter, bm_src, BM_EDGES_OF_MESH) {
- if (BMO_edge_flag_test(bm_src, e, DUPE_INPUT) &&
- BMO_edge_flag_test(bm_src, e, DUPE_DONE) == false)
- {
- /* make sure that verts are copied */
- if (!BMO_vert_flag_test(bm_src, e->v1, DUPE_DONE)) {
- bmo_vert_copy(op, slot_vert_map_out, bm_dst, bm_src, e->v1, vhash);
- BMO_vert_flag_enable(bm_src, e->v1, DUPE_DONE);
- }
- if (!BMO_vert_flag_test(bm_src, e->v2, DUPE_DONE)) {
- bmo_vert_copy(op, slot_vert_map_out, bm_dst, bm_src, e->v2, vhash);
- BMO_vert_flag_enable(bm_src, e->v2, DUPE_DONE);
- }
- /* now copy the actual edge */
- bmo_edge_copy(op, slot_edge_map_out, slot_boundary_map_out,
- bm_dst, bm_src, e, vhash, ehash, use_edge_flip_from_face);
- BMO_edge_flag_enable(bm_src, e, DUPE_DONE);
- }
- }
-
- /* first we dupe all flagged faces and their elements from source */
- BM_ITER_MESH (f, &fiter, bm_src, BM_FACES_OF_MESH) {
- if (BMO_face_flag_test(bm_src, f, DUPE_INPUT)) {
- /* vertex pass */
- BM_ITER_ELEM (v, &viter, f, BM_VERTS_OF_FACE) {
- if (!BMO_vert_flag_test(bm_src, v, DUPE_DONE)) {
- bmo_vert_copy(op, slot_vert_map_out, bm_dst, bm_src, v, vhash);
- BMO_vert_flag_enable(bm_src, v, DUPE_DONE);
- }
- }
-
- /* edge pass */
- BM_ITER_ELEM (e, &eiter, f, BM_EDGES_OF_FACE) {
- if (!BMO_edge_flag_test(bm_src, e, DUPE_DONE)) {
- bmo_edge_copy(op, slot_edge_map_out, slot_boundary_map_out,
- bm_dst, bm_src, e, vhash, ehash, use_edge_flip_from_face);
- BMO_edge_flag_enable(bm_src, e, DUPE_DONE);
- }
- }
-
- bmo_face_copy(op, slot_face_map_out, bm_dst, bm_src, f, vhash, ehash);
- BMO_face_flag_enable(bm_src, f, DUPE_DONE);
- }
- }
-
- /* free pointer hashes */
- BLI_ghash_free(vhash, NULL, NULL);
- BLI_ghash_free(ehash, NULL, NULL);
-
- if (use_select_history) {
- BLI_assert(bm_src == bm_dst);
- BMO_mesh_selected_remap(
- bm_dst,
- slot_vert_map_out,
- slot_edge_map_out,
- slot_face_map_out,
- false);
- }
+ const bool use_select_history = BMO_slot_bool_get(op->slots_in, "use_select_history");
+ const bool use_edge_flip_from_face = BMO_slot_bool_get(op->slots_in, "use_edge_flip_from_face");
+
+ BMVert *v = NULL, *v2;
+ BMEdge *e = NULL;
+ BMFace *f = NULL;
+
+ BMIter viter, eiter, fiter;
+ GHash *vhash, *ehash;
+
+ BMOpSlot *slot_boundary_map_out = BMO_slot_get(op->slots_out, "boundary_map.out");
+ BMOpSlot *slot_isovert_map_out = BMO_slot_get(op->slots_out, "isovert_map.out");
+
+ BMOpSlot *slot_vert_map_out = BMO_slot_get(op->slots_out, "vert_map.out");
+ BMOpSlot *slot_edge_map_out = BMO_slot_get(op->slots_out, "edge_map.out");
+ BMOpSlot *slot_face_map_out = BMO_slot_get(op->slots_out, "face_map.out");
+
+ /* initialize pointer hashes */
+ vhash = BLI_ghash_ptr_new("bmesh dupeops v");
+ ehash = BLI_ghash_ptr_new("bmesh dupeops e");
+
+ /* duplicate flagged vertices */
+ BM_ITER_MESH (v, &viter, bm_src, BM_VERTS_OF_MESH) {
+ if (BMO_vert_flag_test(bm_src, v, DUPE_INPUT) &&
+ BMO_vert_flag_test(bm_src, v, DUPE_DONE) == false) {
+ BMIter iter;
+ bool isolated = true;
+
+ v2 = bmo_vert_copy(op, slot_vert_map_out, bm_dst, bm_src, v, vhash);
+
+ BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) {
+ if (BMO_face_flag_test(bm_src, f, DUPE_INPUT)) {
+ isolated = false;
+ break;
+ }
+ }
+
+ if (isolated) {
+ BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
+ if (BMO_edge_flag_test(bm_src, e, DUPE_INPUT)) {
+ isolated = false;
+ break;
+ }
+ }
+ }
+
+ if (isolated) {
+ BMO_slot_map_elem_insert(op, slot_isovert_map_out, v, v2);
+ }
+
+ BMO_vert_flag_enable(bm_src, v, DUPE_DONE);
+ }
+ }
+
+ /* now we dupe all the edges */
+ BM_ITER_MESH (e, &eiter, bm_src, BM_EDGES_OF_MESH) {
+ if (BMO_edge_flag_test(bm_src, e, DUPE_INPUT) &&
+ BMO_edge_flag_test(bm_src, e, DUPE_DONE) == false) {
+ /* make sure that verts are copied */
+ if (!BMO_vert_flag_test(bm_src, e->v1, DUPE_DONE)) {
+ bmo_vert_copy(op, slot_vert_map_out, bm_dst, bm_src, e->v1, vhash);
+ BMO_vert_flag_enable(bm_src, e->v1, DUPE_DONE);
+ }
+ if (!BMO_vert_flag_test(bm_src, e->v2, DUPE_DONE)) {
+ bmo_vert_copy(op, slot_vert_map_out, bm_dst, bm_src, e->v2, vhash);
+ BMO_vert_flag_enable(bm_src, e->v2, DUPE_DONE);
+ }
+ /* now copy the actual edge */
+ bmo_edge_copy(op,
+ slot_edge_map_out,
+ slot_boundary_map_out,
+ bm_dst,
+ bm_src,
+ e,
+ vhash,
+ ehash,
+ use_edge_flip_from_face);
+ BMO_edge_flag_enable(bm_src, e, DUPE_DONE);
+ }
+ }
+
+ /* first we dupe all flagged faces and their elements from source */
+ BM_ITER_MESH (f, &fiter, bm_src, BM_FACES_OF_MESH) {
+ if (BMO_face_flag_test(bm_src, f, DUPE_INPUT)) {
+ /* vertex pass */
+ BM_ITER_ELEM (v, &viter, f, BM_VERTS_OF_FACE) {
+ if (!BMO_vert_flag_test(bm_src, v, DUPE_DONE)) {
+ bmo_vert_copy(op, slot_vert_map_out, bm_dst, bm_src, v, vhash);
+ BMO_vert_flag_enable(bm_src, v, DUPE_DONE);
+ }
+ }
+
+ /* edge pass */
+ BM_ITER_ELEM (e, &eiter, f, BM_EDGES_OF_FACE) {
+ if (!BMO_edge_flag_test(bm_src, e, DUPE_DONE)) {
+ bmo_edge_copy(op,
+ slot_edge_map_out,
+ slot_boundary_map_out,
+ bm_dst,
+ bm_src,
+ e,
+ vhash,
+ ehash,
+ use_edge_flip_from_face);
+ BMO_edge_flag_enable(bm_src, e, DUPE_DONE);
+ }
+ }
+
+ bmo_face_copy(op, slot_face_map_out, bm_dst, bm_src, f, vhash, ehash);
+ BMO_face_flag_enable(bm_src, f, DUPE_DONE);
+ }
+ }
+
+ /* free pointer hashes */
+ BLI_ghash_free(vhash, NULL, NULL);
+ BLI_ghash_free(ehash, NULL, NULL);
+
+ if (use_select_history) {
+ BLI_assert(bm_src == bm_dst);
+ BMO_mesh_selected_remap(
+ bm_dst, slot_vert_map_out, slot_edge_map_out, slot_face_map_out, false);
+ }
}
/**
@@ -330,26 +340,26 @@ static void bmo_mesh_copy(BMOperator *op, BMesh *bm_dst, BMesh *bm_src)
*/
void bmo_duplicate_exec(BMesh *bm, BMOperator *op)
{
- BMOperator *dupeop = op;
- BMesh *bm_dst = BMO_slot_ptr_get(op->slots_in, "dest");
+ BMOperator *dupeop = op;
+ BMesh *bm_dst = BMO_slot_ptr_get(op->slots_in, "dest");
- if (!bm_dst) {
- bm_dst = bm;
- }
+ if (!bm_dst) {
+ bm_dst = bm;
+ }
- /* flag input */
- BMO_slot_buffer_flag_enable(bm, dupeop->slots_in, "geom", BM_ALL_NOLOOP, DUPE_INPUT);
+ /* flag input */
+ BMO_slot_buffer_flag_enable(bm, dupeop->slots_in, "geom", BM_ALL_NOLOOP, DUPE_INPUT);
- /* use the internal copy function */
- bmo_mesh_copy(dupeop, bm_dst, bm);
+ /* use the internal copy function */
+ bmo_mesh_copy(dupeop, bm_dst, bm);
- /* Output */
- /* First copy the input buffers to output buffers - original data */
- BMO_slot_copy(dupeop, slots_in, "geom",
- dupeop, slots_out, "geom_orig.out");
+ /* Output */
+ /* First copy the input buffers to output buffers - original data */
+ BMO_slot_copy(dupeop, slots_in, "geom", dupeop, slots_out, "geom_orig.out");
- /* Now alloc the new output buffers */
- BMO_slot_buffer_from_enabled_flag(bm, dupeop, dupeop->slots_out, "geom.out", BM_ALL_NOLOOP, DUPE_NEW);
+ /* Now alloc the new output buffers */
+ BMO_slot_buffer_from_enabled_flag(
+ bm, dupeop, dupeop->slots_out, "geom.out", BM_ALL_NOLOOP, DUPE_NEW);
}
#if 0 /* UNUSED */
@@ -359,13 +369,13 @@ void bmo_duplicate_exec(BMesh *bm, BMOperator *op)
* original to new elements) you should run the dupe op manually */
void BMO_dupe_from_flag(BMesh *bm, int htype, const char hflag)
{
- BMOperator dupeop;
+ BMOperator dupeop;
- BMO_op_init(bm, &dupeop, "duplicate");
- BMO_slot_buffer_from_enabled_hflag(bm, &dupeop, "geom", htype, hflag);
+ BMO_op_init(bm, &dupeop, "duplicate");
+ BMO_slot_buffer_from_enabled_hflag(bm, &dupeop, "geom", htype, hflag);
- BMO_op_exec(bm, &dupeop);
- BMO_op_finish(bm, &dupeop);
+ BMO_op_exec(bm, &dupeop);
+ BMO_op_finish(bm, &dupeop);
}
#endif
@@ -393,77 +403,74 @@ void bmo_split_exec(BMesh *bm, BMOperator *op)
{
#define SPLIT_INPUT 1
- BMOperator *splitop = op;
- BMOperator dupeop;
- const bool use_only_faces = BMO_slot_bool_get(op->slots_in, "use_only_faces");
-
- /* initialize our sub-operator */
- BMO_op_init(bm, &dupeop, op->flag, "duplicate");
-
- BMO_slot_copy(splitop, slots_in, "geom",
- &dupeop, slots_in, "geom");
- BMO_op_exec(bm, &dupeop);
-
- BMO_slot_buffer_flag_enable(bm, splitop->slots_in, "geom", BM_ALL_NOLOOP, SPLIT_INPUT);
-
- if (use_only_faces) {
- BMVert *v;
- BMEdge *e;
- BMFace *f;
- BMIter iter, iter2;
-
- /* make sure to remove edges and verts we don't need */
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- bool found = false;
- BM_ITER_ELEM (f, &iter2, e, BM_FACES_OF_EDGE) {
- if (!BMO_face_flag_test(bm, f, SPLIT_INPUT)) {
- found = true;
- break;
- }
- }
- if (found == false) {
- BMO_edge_flag_enable(bm, e, SPLIT_INPUT);
- }
- }
-
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- bool found = false;
- BM_ITER_ELEM (e, &iter2, v, BM_EDGES_OF_VERT) {
- if (!BMO_edge_flag_test(bm, e, SPLIT_INPUT)) {
- found = true;
- break;
- }
- }
- if (found == false) {
- BMO_vert_flag_enable(bm, v, SPLIT_INPUT);
- }
- }
- }
-
- /* connect outputs of dupe to delete, exluding keep geometry */
- BMO_mesh_delete_oflag_context(bm, SPLIT_INPUT, DEL_FACES);
-
- /* now we make our outputs by copying the dupe output */
- BMO_slot_copy(&dupeop, slots_out, "geom.out",
- splitop, slots_out, "geom.out");
-
- /* cleanup */
- BMO_op_finish(bm, &dupeop);
+ BMOperator *splitop = op;
+ BMOperator dupeop;
+ const bool use_only_faces = BMO_slot_bool_get(op->slots_in, "use_only_faces");
+
+ /* initialize our sub-operator */
+ BMO_op_init(bm, &dupeop, op->flag, "duplicate");
+
+ BMO_slot_copy(splitop, slots_in, "geom", &dupeop, slots_in, "geom");
+ BMO_op_exec(bm, &dupeop);
+
+ BMO_slot_buffer_flag_enable(bm, splitop->slots_in, "geom", BM_ALL_NOLOOP, SPLIT_INPUT);
+
+ if (use_only_faces) {
+ BMVert *v;
+ BMEdge *e;
+ BMFace *f;
+ BMIter iter, iter2;
+
+ /* make sure to remove edges and verts we don't need */
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ bool found = false;
+ BM_ITER_ELEM (f, &iter2, e, BM_FACES_OF_EDGE) {
+ if (!BMO_face_flag_test(bm, f, SPLIT_INPUT)) {
+ found = true;
+ break;
+ }
+ }
+ if (found == false) {
+ BMO_edge_flag_enable(bm, e, SPLIT_INPUT);
+ }
+ }
+
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ bool found = false;
+ BM_ITER_ELEM (e, &iter2, v, BM_EDGES_OF_VERT) {
+ if (!BMO_edge_flag_test(bm, e, SPLIT_INPUT)) {
+ found = true;
+ break;
+ }
+ }
+ if (found == false) {
+ BMO_vert_flag_enable(bm, v, SPLIT_INPUT);
+ }
+ }
+ }
+
+ /* connect outputs of dupe to delete, exluding keep geometry */
+ BMO_mesh_delete_oflag_context(bm, SPLIT_INPUT, DEL_FACES);
+
+ /* now we make our outputs by copying the dupe output */
+ BMO_slot_copy(&dupeop, slots_out, "geom.out", splitop, slots_out, "geom.out");
+
+ /* cleanup */
+ BMO_op_finish(bm, &dupeop);
#undef SPLIT_INPUT
}
-
void bmo_delete_exec(BMesh *bm, BMOperator *op)
{
#define DEL_INPUT 1
- BMOperator *delop = op;
+ BMOperator *delop = op;
- /* Mark Buffer */
- BMO_slot_buffer_flag_enable(bm, delop->slots_in, "geom", BM_ALL_NOLOOP, DEL_INPUT);
+ /* Mark Buffer */
+ BMO_slot_buffer_flag_enable(bm, delop->slots_in, "geom", BM_ALL_NOLOOP, DEL_INPUT);
- BMO_mesh_delete_oflag_context(bm, DEL_INPUT, BMO_slot_int_get(op->slots_in, "context"));
+ BMO_mesh_delete_oflag_context(bm, DEL_INPUT, BMO_slot_int_get(op->slots_in, "context"));
#undef DEL_INPUT
}
@@ -476,128 +483,147 @@ void bmo_delete_exec(BMesh *bm, BMOperator *op)
*/
void bmo_spin_exec(BMesh *bm, BMOperator *op)
{
- BMOperator dupop, extop;
- float cent[3], dvec[3];
- float axis[3];
- float rmat[3][3];
- float phi;
- int steps, do_dupli, a;
- bool use_dvec;
-
- BMO_slot_vec_get(op->slots_in, "cent", cent);
- BMO_slot_vec_get(op->slots_in, "axis", axis);
- normalize_v3(axis);
- BMO_slot_vec_get(op->slots_in, "dvec", dvec);
- use_dvec = !is_zero_v3(dvec);
- steps = BMO_slot_int_get(op->slots_in, "steps");
- phi = BMO_slot_float_get(op->slots_in, "angle") / steps;
- do_dupli = BMO_slot_bool_get(op->slots_in, "use_duplicate");
- const bool use_normal_flip = BMO_slot_bool_get(op->slots_in, "use_normal_flip");
- /* Caller needs to perform other sanity checks (such as the spin being 360d). */
- const bool use_merge = BMO_slot_bool_get(op->slots_in, "use_merge") && steps >= 3;
-
- axis_angle_normalized_to_mat3(rmat, axis, phi);
-
- BMVert **vtable = NULL;
- if (use_merge) {
- vtable = MEM_mallocN(sizeof(BMVert *) * bm->totvert, __func__);
- int i = 0;
- BMIter iter;
- BMVert *v;
- BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
- vtable[i] = v;
- /* Evil! store original index in normal,
- * this is duplicated into every other vertex.
- * So we can read the original from the final.
- *
- * The normals must be recalculated anyway. */
- *((int *)&v->no[0]) = i;
- }
- }
-
- BMO_slot_copy(op, slots_in, "geom",
- op, slots_out, "geom_last.out");
- for (a = 0; a < steps; a++) {
- if (do_dupli) {
- BMO_op_initf(bm, &dupop, op->flag, "duplicate geom=%S", op, "geom_last.out");
- BMO_op_exec(bm, &dupop);
- BMO_op_callf(bm, op->flag,
- "rotate cent=%v matrix=%m3 space=%s verts=%S",
- cent, rmat, op, "space", &dupop, "geom.out");
- BMO_slot_copy(&dupop, slots_out, "geom.out",
- op, slots_out, "geom_last.out");
- BMO_op_finish(bm, &dupop);
- }
- else {
- BMO_op_initf(bm, &extop, op->flag,
- "extrude_face_region geom=%S use_normal_flip=%b use_normal_from_adjacent=%b",
- op, "geom_last.out", use_normal_flip && (a == 0), (a != 0));
- BMO_op_exec(bm, &extop);
- if ((use_merge && (a == steps - 1)) == false) {
- BMO_op_callf(bm, op->flag,
- "rotate cent=%v matrix=%m3 space=%s verts=%S",
- cent, rmat, op, "space", &extop, "geom.out");
- BMO_slot_copy(&extop, slots_out, "geom.out",
- op, slots_out, "geom_last.out");
- }
- else {
- /* Merge first/last vertices and edges (maintaining 'geom.out' state). */
- BMOpSlot *slot_geom_out = BMO_slot_get(extop.slots_out, "geom.out");
- BMElem **elem_array = (BMElem **)slot_geom_out->data.buf;
- int elem_array_len = slot_geom_out->len;
- for (int i = 0; i < elem_array_len; ) {
- if (elem_array[i]->head.htype == BM_VERT) {
- BMVert *v_src = (BMVert *)elem_array[i];
- BMVert *v_dst = vtable[*((const int *)&v_src->no[0])];
- BM_vert_splice(bm, v_dst, v_src);
- elem_array_len--;
- elem_array[i] = elem_array[elem_array_len];
- }
- else {
- i++;
- }
- }
- for (int i = 0; i < elem_array_len; ) {
- if (elem_array[i]->head.htype == BM_EDGE) {
- BMEdge *e_src = (BMEdge *)elem_array[i];
- BMEdge *e_dst = BM_edge_find_double(e_src);
- if (e_dst != NULL) {
- BM_edge_splice(bm, e_dst, e_src);
- elem_array_len--;
- elem_array[i] = elem_array[elem_array_len];
- continue;
- }
- }
- i++;
- }
- /* Full copies of faces may cause overlap. */
- for (int i = 0; i < elem_array_len; ) {
- if (elem_array[i]->head.htype == BM_FACE) {
- BMFace *f_src = (BMFace *)elem_array[i];
- BMFace *f_dst = BM_face_find_double(f_src);
- if (f_dst != NULL) {
- BM_face_kill(bm, f_src);
- elem_array_len--;
- elem_array[i] = elem_array[elem_array_len];
- continue;
- }
- }
- i++;
- }
- slot_geom_out->len = elem_array_len;
- }
- BMO_op_finish(bm, &extop);
- }
-
- if (use_dvec) {
- mul_m3_v3(rmat, dvec);
- BMO_op_callf(bm, op->flag,
- "translate vec=%v space=%s verts=%S",
- dvec, op, "space", op, "geom_last.out");
- }
- }
-
- if (vtable) {
- MEM_freeN(vtable);
- }
+ BMOperator dupop, extop;
+ float cent[3], dvec[3];
+ float axis[3];
+ float rmat[3][3];
+ float phi;
+ int steps, do_dupli, a;
+ bool use_dvec;
+
+ BMO_slot_vec_get(op->slots_in, "cent", cent);
+ BMO_slot_vec_get(op->slots_in, "axis", axis);
+ normalize_v3(axis);
+ BMO_slot_vec_get(op->slots_in, "dvec", dvec);
+ use_dvec = !is_zero_v3(dvec);
+ steps = BMO_slot_int_get(op->slots_in, "steps");
+ phi = BMO_slot_float_get(op->slots_in, "angle") / steps;
+ do_dupli = BMO_slot_bool_get(op->slots_in, "use_duplicate");
+ const bool use_normal_flip = BMO_slot_bool_get(op->slots_in, "use_normal_flip");
+ /* Caller needs to perform other sanity checks (such as the spin being 360d). */
+ const bool use_merge = BMO_slot_bool_get(op->slots_in, "use_merge") && steps >= 3;
+
+ axis_angle_normalized_to_mat3(rmat, axis, phi);
+
+ BMVert **vtable = NULL;
+ if (use_merge) {
+ vtable = MEM_mallocN(sizeof(BMVert *) * bm->totvert, __func__);
+ int i = 0;
+ BMIter iter;
+ BMVert *v;
+ BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
+ vtable[i] = v;
+ /* Evil! store original index in normal,
+ * this is duplicated into every other vertex.
+ * So we can read the original from the final.
+ *
+ * The normals must be recalculated anyway. */
+ *((int *)&v->no[0]) = i;
+ }
+ }
+
+ BMO_slot_copy(op, slots_in, "geom", op, slots_out, "geom_last.out");
+ for (a = 0; a < steps; a++) {
+ if (do_dupli) {
+ BMO_op_initf(bm, &dupop, op->flag, "duplicate geom=%S", op, "geom_last.out");
+ BMO_op_exec(bm, &dupop);
+ BMO_op_callf(bm,
+ op->flag,
+ "rotate cent=%v matrix=%m3 space=%s verts=%S",
+ cent,
+ rmat,
+ op,
+ "space",
+ &dupop,
+ "geom.out");
+ BMO_slot_copy(&dupop, slots_out, "geom.out", op, slots_out, "geom_last.out");
+ BMO_op_finish(bm, &dupop);
+ }
+ else {
+ BMO_op_initf(bm,
+ &extop,
+ op->flag,
+ "extrude_face_region geom=%S use_normal_flip=%b use_normal_from_adjacent=%b",
+ op,
+ "geom_last.out",
+ use_normal_flip && (a == 0),
+ (a != 0));
+ BMO_op_exec(bm, &extop);
+ if ((use_merge && (a == steps - 1)) == false) {
+ BMO_op_callf(bm,
+ op->flag,
+ "rotate cent=%v matrix=%m3 space=%s verts=%S",
+ cent,
+ rmat,
+ op,
+ "space",
+ &extop,
+ "geom.out");
+ BMO_slot_copy(&extop, slots_out, "geom.out", op, slots_out, "geom_last.out");
+ }
+ else {
+ /* Merge first/last vertices and edges (maintaining 'geom.out' state). */
+ BMOpSlot *slot_geom_out = BMO_slot_get(extop.slots_out, "geom.out");
+ BMElem **elem_array = (BMElem **)slot_geom_out->data.buf;
+ int elem_array_len = slot_geom_out->len;
+ for (int i = 0; i < elem_array_len;) {
+ if (elem_array[i]->head.htype == BM_VERT) {
+ BMVert *v_src = (BMVert *)elem_array[i];
+ BMVert *v_dst = vtable[*((const int *)&v_src->no[0])];
+ BM_vert_splice(bm, v_dst, v_src);
+ elem_array_len--;
+ elem_array[i] = elem_array[elem_array_len];
+ }
+ else {
+ i++;
+ }
+ }
+ for (int i = 0; i < elem_array_len;) {
+ if (elem_array[i]->head.htype == BM_EDGE) {
+ BMEdge *e_src = (BMEdge *)elem_array[i];
+ BMEdge *e_dst = BM_edge_find_double(e_src);
+ if (e_dst != NULL) {
+ BM_edge_splice(bm, e_dst, e_src);
+ elem_array_len--;
+ elem_array[i] = elem_array[elem_array_len];
+ continue;
+ }
+ }
+ i++;
+ }
+ /* Full copies of faces may cause overlap. */
+ for (int i = 0; i < elem_array_len;) {
+ if (elem_array[i]->head.htype == BM_FACE) {
+ BMFace *f_src = (BMFace *)elem_array[i];
+ BMFace *f_dst = BM_face_find_double(f_src);
+ if (f_dst != NULL) {
+ BM_face_kill(bm, f_src);
+ elem_array_len--;
+ elem_array[i] = elem_array[elem_array_len];
+ continue;
+ }
+ }
+ i++;
+ }
+ slot_geom_out->len = elem_array_len;
+ }
+ BMO_op_finish(bm, &extop);
+ }
+
+ if (use_dvec) {
+ mul_m3_v3(rmat, dvec);
+ BMO_op_callf(bm,
+ op->flag,
+ "translate vec=%v space=%s verts=%S",
+ dvec,
+ op,
+ "space",
+ op,
+ "geom_last.out");
+ }
+ }
+
+ if (vtable) {
+ MEM_freeN(vtable);
+ }
}
diff --git a/source/blender/bmesh/operators/bmo_edgenet.c b/source/blender/bmesh/operators/bmo_edgenet.c
index 4334c7bcdcc..7ab8406a3ec 100644
--- a/source/blender/bmesh/operators/bmo_edgenet.c
+++ b/source/blender/bmesh/operators/bmo_edgenet.c
@@ -30,247 +30,245 @@
#include "intern/bmesh_operators_private.h" /* own include */
-#define EDGE_MARK 1
-#define EDGE_VIS 2
+#define EDGE_MARK 1
+#define EDGE_VIS 2
-#define ELE_NEW 1
+#define ELE_NEW 1
void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op)
{
- BMOperator op_attr;
- BMOIter siter;
- BMFace *f;
- const short mat_nr = BMO_slot_int_get(op->slots_in, "mat_nr");
- const bool use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth");
-// const int sides = BMO_slot_int_get(op->slots_in, "sides");
-
- if (!bm->totvert || !bm->totedge) {
- return;
- }
-
- BM_mesh_elem_hflag_disable_all(bm, BM_EDGE, BM_ELEM_TAG, false);
- BMO_slot_buffer_hflag_enable(bm, op->slots_in, "edges", BM_EDGE, BM_ELEM_TAG, false);
-
- BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false);
- BM_mesh_edgenet(bm, true, true); // TODO, sides
-
- BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG);
-
- BMO_ITER (f, &siter, op->slots_out, "faces.out", BM_FACE) {
- f->mat_nr = mat_nr;
- if (use_smooth) {
- BM_elem_flag_enable(f, BM_ELEM_SMOOTH);
- }
- /* normals are zero'd */
- BM_face_normal_update(f);
- }
-
- /* --- Attribute Fill --- */
- /* may as well since we have the faces already in a buffer */
- BMO_op_initf(bm, &op_attr, op->flag,
- "face_attribute_fill faces=%S use_normals=%b use_data=%b",
- op, "faces.out", true, true);
-
- BMO_op_exec(bm, &op_attr);
-
- /* check if some faces couldn't be touched */
- if (BMO_slot_buffer_count(op_attr.slots_out, "faces_fail.out")) {
- BMO_op_callf(bm, op->flag, "recalc_face_normals faces=%S", &op_attr, "faces_fail.out");
- }
- BMO_op_finish(bm, &op_attr);
-
+ BMOperator op_attr;
+ BMOIter siter;
+ BMFace *f;
+ const short mat_nr = BMO_slot_int_get(op->slots_in, "mat_nr");
+ const bool use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth");
+ // const int sides = BMO_slot_int_get(op->slots_in, "sides");
+
+ if (!bm->totvert || !bm->totedge) {
+ return;
+ }
+
+ BM_mesh_elem_hflag_disable_all(bm, BM_EDGE, BM_ELEM_TAG, false);
+ BMO_slot_buffer_hflag_enable(bm, op->slots_in, "edges", BM_EDGE, BM_ELEM_TAG, false);
+
+ BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false);
+ BM_mesh_edgenet(bm, true, true); // TODO, sides
+
+ BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG);
+
+ BMO_ITER (f, &siter, op->slots_out, "faces.out", BM_FACE) {
+ f->mat_nr = mat_nr;
+ if (use_smooth) {
+ BM_elem_flag_enable(f, BM_ELEM_SMOOTH);
+ }
+ /* normals are zero'd */
+ BM_face_normal_update(f);
+ }
+
+ /* --- Attribute Fill --- */
+ /* may as well since we have the faces already in a buffer */
+ BMO_op_initf(bm,
+ &op_attr,
+ op->flag,
+ "face_attribute_fill faces=%S use_normals=%b use_data=%b",
+ op,
+ "faces.out",
+ true,
+ true);
+
+ BMO_op_exec(bm, &op_attr);
+
+ /* check if some faces couldn't be touched */
+ if (BMO_slot_buffer_count(op_attr.slots_out, "faces_fail.out")) {
+ BMO_op_callf(bm, op->flag, "recalc_face_normals faces=%S", &op_attr, "faces_fail.out");
+ }
+ BMO_op_finish(bm, &op_attr);
}
static BMEdge *edge_next(BMesh *bm, BMEdge *e)
{
- BMIter iter;
- BMEdge *e2;
- int i;
-
- for (i = 0; i < 2; i++) {
- BM_ITER_ELEM (e2, &iter, i ? e->v2 : e->v1, BM_EDGES_OF_VERT) {
- if ((BMO_edge_flag_test(bm, e2, EDGE_MARK)) &&
- (BMO_edge_flag_test(bm, e2, EDGE_VIS) == false) &&
- (e2 != e))
- {
- return e2;
- }
- }
- }
-
- return NULL;
+ BMIter iter;
+ BMEdge *e2;
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ BM_ITER_ELEM (e2, &iter, i ? e->v2 : e->v1, BM_EDGES_OF_VERT) {
+ if ((BMO_edge_flag_test(bm, e2, EDGE_MARK)) &&
+ (BMO_edge_flag_test(bm, e2, EDGE_VIS) == false) && (e2 != e)) {
+ return e2;
+ }
+ }
+ }
+
+ return NULL;
}
void bmo_edgenet_prepare_exec(BMesh *bm, BMOperator *op)
{
- BMOIter siter;
- BMEdge *e;
- BMEdge **edges1 = NULL, **edges2 = NULL, **edges;
- BLI_array_declare(edges1);
- BLI_array_declare(edges2);
- BLI_array_declare(edges);
- bool ok = true;
- int i, count;
-
- BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK);
-
- /* validate that each edge has at most one other tagged edge in the
- * disk cycle around each of it's vertices */
- BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
- for (i = 0; i < 2; i++) {
- count = BMO_iter_elem_count_flag(bm, BM_EDGES_OF_VERT, (i ? e->v2 : e->v1), EDGE_MARK, true);
- if (count > 2) {
- ok = 0;
- break;
- }
- }
-
- if (!ok) {
- break;
- }
- }
-
- /* we don't have valid edge layouts, retur */
- if (!ok) {
- return;
- }
-
- /* find connected loops within the input edge */
- count = 0;
- while (1) {
- BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
- if (!BMO_edge_flag_test(bm, e, EDGE_VIS)) {
- if (BMO_iter_elem_count_flag(bm, BM_EDGES_OF_VERT, e->v1, EDGE_MARK, true) == 1 ||
- BMO_iter_elem_count_flag(bm, BM_EDGES_OF_VERT, e->v2, EDGE_MARK, true) == 1)
- {
- break;
- }
- }
- }
-
- if (!e) {
- break;
- }
-
- if (!count) {
- edges = edges1;
- }
- else if (count == 1) {
- edges = edges2;
- }
- else {
- break;
- }
-
- i = 0;
- while (e) {
- BMO_edge_flag_enable(bm, e, EDGE_VIS);
- BLI_array_grow_one(edges);
- edges[i] = e;
-
- e = edge_next(bm, e);
- i++;
- }
-
- if (!count) {
- edges1 = edges;
- BLI_array_len_set(edges1, BLI_array_len(edges));
- }
- else {
- edges2 = edges;
- BLI_array_len_set(edges2, BLI_array_len(edges));
- }
-
- BLI_array_clear(edges);
- count++;
- }
-
- if (edges1 && BLI_array_len(edges1) > 2 &&
- BM_edge_share_vert_check(edges1[0], edges1[BLI_array_len(edges1) - 1]))
- {
- if (edges2 && BLI_array_len(edges2) > 2 &&
- BM_edge_share_vert_check(edges2[0], edges2[BLI_array_len(edges2) - 1]))
- {
- BLI_array_free(edges1);
- BLI_array_free(edges2);
- return;
- }
- else {
- edges1 = edges2;
- edges2 = NULL;
- }
- }
-
- if (edges2 && BLI_array_len(edges2) > 2 &&
- BM_edge_share_vert_check(edges2[0], edges2[BLI_array_len(edges2) - 1]))
- {
- edges2 = NULL;
- }
-
- /* two unconnected loops, connect the */
- if (edges1 && edges2) {
- BMVert *v1, *v2, *v3, *v4;
- float dvec1[3];
- float dvec2[3];
-
- if (BLI_array_len(edges1) == 1) {
- v1 = edges1[0]->v1;
- v2 = edges1[0]->v2;
- }
- else {
- v1 = BM_vert_in_edge(edges1[1], edges1[0]->v1) ? edges1[0]->v2 : edges1[0]->v1;
- i = BLI_array_len(edges1) - 1;
- v2 = BM_vert_in_edge(edges1[i - 1], edges1[i]->v1) ? edges1[i]->v2 : edges1[i]->v1;
- }
-
- if (BLI_array_len(edges2) == 1) {
- v3 = edges2[0]->v1;
- v4 = edges2[0]->v2;
- }
- else {
- v3 = BM_vert_in_edge(edges2[1], edges2[0]->v1) ? edges2[0]->v2 : edges2[0]->v1;
- i = BLI_array_len(edges2) - 1;
- v4 = BM_vert_in_edge(edges2[i - 1], edges2[i]->v1) ? edges2[i]->v2 : edges2[i]->v1;
- }
-
- /* if there is ever bow-tie quads between two edges the problem is here! [#30367] */
+ BMOIter siter;
+ BMEdge *e;
+ BMEdge **edges1 = NULL, **edges2 = NULL, **edges;
+ BLI_array_declare(edges1);
+ BLI_array_declare(edges2);
+ BLI_array_declare(edges);
+ bool ok = true;
+ int i, count;
+
+ BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK);
+
+ /* validate that each edge has at most one other tagged edge in the
+ * disk cycle around each of it's vertices */
+ BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
+ for (i = 0; i < 2; i++) {
+ count = BMO_iter_elem_count_flag(bm, BM_EDGES_OF_VERT, (i ? e->v2 : e->v1), EDGE_MARK, true);
+ if (count > 2) {
+ ok = 0;
+ break;
+ }
+ }
+
+ if (!ok) {
+ break;
+ }
+ }
+
+ /* we don't have valid edge layouts, retur */
+ if (!ok) {
+ return;
+ }
+
+ /* find connected loops within the input edge */
+ count = 0;
+ while (1) {
+ BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
+ if (!BMO_edge_flag_test(bm, e, EDGE_VIS)) {
+ if (BMO_iter_elem_count_flag(bm, BM_EDGES_OF_VERT, e->v1, EDGE_MARK, true) == 1 ||
+ BMO_iter_elem_count_flag(bm, BM_EDGES_OF_VERT, e->v2, EDGE_MARK, true) == 1) {
+ break;
+ }
+ }
+ }
+
+ if (!e) {
+ break;
+ }
+
+ if (!count) {
+ edges = edges1;
+ }
+ else if (count == 1) {
+ edges = edges2;
+ }
+ else {
+ break;
+ }
+
+ i = 0;
+ while (e) {
+ BMO_edge_flag_enable(bm, e, EDGE_VIS);
+ BLI_array_grow_one(edges);
+ edges[i] = e;
+
+ e = edge_next(bm, e);
+ i++;
+ }
+
+ if (!count) {
+ edges1 = edges;
+ BLI_array_len_set(edges1, BLI_array_len(edges));
+ }
+ else {
+ edges2 = edges;
+ BLI_array_len_set(edges2, BLI_array_len(edges));
+ }
+
+ BLI_array_clear(edges);
+ count++;
+ }
+
+ if (edges1 && BLI_array_len(edges1) > 2 &&
+ BM_edge_share_vert_check(edges1[0], edges1[BLI_array_len(edges1) - 1])) {
+ if (edges2 && BLI_array_len(edges2) > 2 &&
+ BM_edge_share_vert_check(edges2[0], edges2[BLI_array_len(edges2) - 1])) {
+ BLI_array_free(edges1);
+ BLI_array_free(edges2);
+ return;
+ }
+ else {
+ edges1 = edges2;
+ edges2 = NULL;
+ }
+ }
+
+ if (edges2 && BLI_array_len(edges2) > 2 &&
+ BM_edge_share_vert_check(edges2[0], edges2[BLI_array_len(edges2) - 1])) {
+ edges2 = NULL;
+ }
+
+ /* two unconnected loops, connect the */
+ if (edges1 && edges2) {
+ BMVert *v1, *v2, *v3, *v4;
+ float dvec1[3];
+ float dvec2[3];
+
+ if (BLI_array_len(edges1) == 1) {
+ v1 = edges1[0]->v1;
+ v2 = edges1[0]->v2;
+ }
+ else {
+ v1 = BM_vert_in_edge(edges1[1], edges1[0]->v1) ? edges1[0]->v2 : edges1[0]->v1;
+ i = BLI_array_len(edges1) - 1;
+ v2 = BM_vert_in_edge(edges1[i - 1], edges1[i]->v1) ? edges1[i]->v2 : edges1[i]->v1;
+ }
+
+ if (BLI_array_len(edges2) == 1) {
+ v3 = edges2[0]->v1;
+ v4 = edges2[0]->v2;
+ }
+ else {
+ v3 = BM_vert_in_edge(edges2[1], edges2[0]->v1) ? edges2[0]->v2 : edges2[0]->v1;
+ i = BLI_array_len(edges2) - 1;
+ v4 = BM_vert_in_edge(edges2[i - 1], edges2[i]->v1) ? edges2[i]->v2 : edges2[i]->v1;
+ }
+
+ /* if there is ever bow-tie quads between two edges the problem is here! [#30367] */
#if 0
- normal_tri_v3(dvec1, v1->co, v2->co, v4->co);
- normal_tri_v3(dvec2, v1->co, v4->co, v3->co);
+ normal_tri_v3(dvec1, v1->co, v2->co, v4->co);
+ normal_tri_v3(dvec2, v1->co, v4->co, v3->co);
#else
- {
- /* save some CPU cycles and skip the sqrt and 1 subtraction */
- float a1[3], a2[3], a3[3];
- sub_v3_v3v3(a1, v1->co, v2->co);
- sub_v3_v3v3(a2, v1->co, v4->co);
- sub_v3_v3v3(a3, v1->co, v3->co);
- cross_v3_v3v3(dvec1, a1, a2);
- cross_v3_v3v3(dvec2, a2, a3);
- }
+ {
+ /* save some CPU cycles and skip the sqrt and 1 subtraction */
+ float a1[3], a2[3], a3[3];
+ sub_v3_v3v3(a1, v1->co, v2->co);
+ sub_v3_v3v3(a2, v1->co, v4->co);
+ sub_v3_v3v3(a3, v1->co, v3->co);
+ cross_v3_v3v3(dvec1, a1, a2);
+ cross_v3_v3v3(dvec2, a2, a3);
+ }
#endif
- if (dot_v3v3(dvec1, dvec2) < 0.0f) {
- SWAP(BMVert *, v3, v4);
- }
-
- e = BM_edge_create(bm, v1, v3, NULL, BM_CREATE_NO_DOUBLE);
- BMO_edge_flag_enable(bm, e, ELE_NEW);
- e = BM_edge_create(bm, v2, v4, NULL, BM_CREATE_NO_DOUBLE);
- BMO_edge_flag_enable(bm, e, ELE_NEW);
- }
- else if (edges1) {
- BMVert *v1, *v2;
-
- if (BLI_array_len(edges1) > 1) {
- v1 = BM_vert_in_edge(edges1[1], edges1[0]->v1) ? edges1[0]->v2 : edges1[0]->v1;
- i = BLI_array_len(edges1) - 1;
- v2 = BM_vert_in_edge(edges1[i - 1], edges1[i]->v1) ? edges1[i]->v2 : edges1[i]->v1;
- e = BM_edge_create(bm, v1, v2, NULL, BM_CREATE_NO_DOUBLE);
- BMO_edge_flag_enable(bm, e, ELE_NEW);
- }
- }
-
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, ELE_NEW);
-
- BLI_array_free(edges1);
- BLI_array_free(edges2);
+ if (dot_v3v3(dvec1, dvec2) < 0.0f) {
+ SWAP(BMVert *, v3, v4);
+ }
+
+ e = BM_edge_create(bm, v1, v3, NULL, BM_CREATE_NO_DOUBLE);
+ BMO_edge_flag_enable(bm, e, ELE_NEW);
+ e = BM_edge_create(bm, v2, v4, NULL, BM_CREATE_NO_DOUBLE);
+ BMO_edge_flag_enable(bm, e, ELE_NEW);
+ }
+ else if (edges1) {
+ BMVert *v1, *v2;
+
+ if (BLI_array_len(edges1) > 1) {
+ v1 = BM_vert_in_edge(edges1[1], edges1[0]->v1) ? edges1[0]->v2 : edges1[0]->v1;
+ i = BLI_array_len(edges1) - 1;
+ v2 = BM_vert_in_edge(edges1[i - 1], edges1[i]->v1) ? edges1[i]->v2 : edges1[i]->v1;
+ e = BM_edge_create(bm, v1, v2, NULL, BM_CREATE_NO_DOUBLE);
+ BMO_edge_flag_enable(bm, e, ELE_NEW);
+ }
+ }
+
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, ELE_NEW);
+
+ BLI_array_free(edges1);
+ BLI_array_free(edges2);
}
diff --git a/source/blender/bmesh/operators/bmo_extrude.c b/source/blender/bmesh/operators/bmo_extrude.c
index eaf059c7e03..cec7a920abb 100644
--- a/source/blender/bmesh/operators/bmo_extrude.c
+++ b/source/blender/bmesh/operators/bmo_extrude.c
@@ -36,9 +36,9 @@
#define USE_EDGE_REGION_FLAGS
enum {
- EXT_INPUT = 1,
- EXT_KEEP = 2,
- EXT_DEL = 4,
+ EXT_INPUT = 1,
+ EXT_KEEP = 2,
+ EXT_DEL = 4,
};
#define VERT_MARK 1
@@ -49,80 +49,78 @@ enum {
void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op)
{
- const bool use_select_history = BMO_slot_bool_get(op->slots_in, "use_select_history");
- GHash *select_history_map = NULL;
-
- BMOIter siter;
- BMFace *f_org;
-
- if (use_select_history) {
- select_history_map = BM_select_history_map_create(bm);
- }
-
- BMO_ITER (f_org, &siter, op->slots_in, "faces", BM_FACE) {
- BMFace *f_new;
- BMLoop *l_org, *l_org_first;
- BMLoop *l_new;
-
- BMO_face_flag_enable(bm, f_org, EXT_DEL);
-
- f_new = BM_face_copy(bm, bm, f_org, true, true);
- BMO_face_flag_enable(bm, f_new, EXT_KEEP);
-
- if (select_history_map) {
- BMEditSelection *ese;
- ese = BLI_ghash_lookup(select_history_map, f_org);
- if (ese) {
- ese->ele = (BMElem *)f_new;
- }
- }
-
- l_org = l_org_first = BM_FACE_FIRST_LOOP(f_org);
- l_new = BM_FACE_FIRST_LOOP(f_new);
-
- do {
- BMFace *f_side;
- BMLoop *l_side_iter;
-
- BM_elem_attrs_copy(bm, bm, l_org, l_new);
-
- f_side = BM_face_create_quad_tri(bm,
- l_org->next->v, l_new->next->v, l_new->v, l_org->v,
- f_org, BM_CREATE_NOP);
-
- l_side_iter = BM_FACE_FIRST_LOOP(f_side);
-
- BM_elem_attrs_copy(bm, bm, l_org->next, l_side_iter); l_side_iter = l_side_iter->next;
- BM_elem_attrs_copy(bm, bm, l_org->next, l_side_iter); l_side_iter = l_side_iter->next;
- BM_elem_attrs_copy(bm, bm, l_org, l_side_iter); l_side_iter = l_side_iter->next;
- BM_elem_attrs_copy(bm, bm, l_org, l_side_iter);
-
- if (select_history_map) {
- BMEditSelection *ese;
-
- ese = BLI_ghash_lookup(select_history_map, l_org->v);
- if (ese) {
- ese->ele = (BMElem *)l_new->v;
- }
- ese = BLI_ghash_lookup(select_history_map, l_org->e);
- if (ese) {
- ese->ele = (BMElem *)l_new->e;
- }
- }
-
- } while (((void)
- (l_new = l_new->next),
- (l_org = l_org->next)) != l_org_first);
- }
-
- if (select_history_map) {
- BLI_ghash_free(select_history_map, NULL, NULL);
- }
-
- BMO_op_callf(bm, op->flag,
- "delete geom=%ff context=%i",
- EXT_DEL, DEL_ONLYFACES);
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, EXT_KEEP);
+ const bool use_select_history = BMO_slot_bool_get(op->slots_in, "use_select_history");
+ GHash *select_history_map = NULL;
+
+ BMOIter siter;
+ BMFace *f_org;
+
+ if (use_select_history) {
+ select_history_map = BM_select_history_map_create(bm);
+ }
+
+ BMO_ITER (f_org, &siter, op->slots_in, "faces", BM_FACE) {
+ BMFace *f_new;
+ BMLoop *l_org, *l_org_first;
+ BMLoop *l_new;
+
+ BMO_face_flag_enable(bm, f_org, EXT_DEL);
+
+ f_new = BM_face_copy(bm, bm, f_org, true, true);
+ BMO_face_flag_enable(bm, f_new, EXT_KEEP);
+
+ if (select_history_map) {
+ BMEditSelection *ese;
+ ese = BLI_ghash_lookup(select_history_map, f_org);
+ if (ese) {
+ ese->ele = (BMElem *)f_new;
+ }
+ }
+
+ l_org = l_org_first = BM_FACE_FIRST_LOOP(f_org);
+ l_new = BM_FACE_FIRST_LOOP(f_new);
+
+ do {
+ BMFace *f_side;
+ BMLoop *l_side_iter;
+
+ BM_elem_attrs_copy(bm, bm, l_org, l_new);
+
+ f_side = BM_face_create_quad_tri(
+ bm, l_org->next->v, l_new->next->v, l_new->v, l_org->v, f_org, BM_CREATE_NOP);
+
+ l_side_iter = BM_FACE_FIRST_LOOP(f_side);
+
+ BM_elem_attrs_copy(bm, bm, l_org->next, l_side_iter);
+ l_side_iter = l_side_iter->next;
+ BM_elem_attrs_copy(bm, bm, l_org->next, l_side_iter);
+ l_side_iter = l_side_iter->next;
+ BM_elem_attrs_copy(bm, bm, l_org, l_side_iter);
+ l_side_iter = l_side_iter->next;
+ BM_elem_attrs_copy(bm, bm, l_org, l_side_iter);
+
+ if (select_history_map) {
+ BMEditSelection *ese;
+
+ ese = BLI_ghash_lookup(select_history_map, l_org->v);
+ if (ese) {
+ ese->ele = (BMElem *)l_new->v;
+ }
+ ese = BLI_ghash_lookup(select_history_map, l_org->e);
+ if (ese) {
+ ese->ele = (BMElem *)l_new->e;
+ }
+ }
+
+ } while (((void)(l_new = l_new->next), (l_org = l_org->next)) != l_org_first);
+ }
+
+ if (select_history_map) {
+ BLI_ghash_free(select_history_map, NULL, NULL);
+ }
+
+ BMO_op_callf(bm, op->flag, "delete geom=%ff context=%i", EXT_DEL, DEL_ONLYFACES);
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, EXT_KEEP);
}
/**
@@ -137,156 +135,157 @@ void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op)
*/
static void bm_extrude_copy_face_loop_attributes(BMesh *bm, BMFace *f)
{
- /* edge we are extruded from */
- BMLoop *l_first_0 = BM_FACE_FIRST_LOOP(f);
- BMLoop *l_first_1 = l_first_0->next;
- BMLoop *l_first_2 = l_first_1->next;
- BMLoop *l_first_3 = l_first_2->next;
+ /* edge we are extruded from */
+ BMLoop *l_first_0 = BM_FACE_FIRST_LOOP(f);
+ BMLoop *l_first_1 = l_first_0->next;
+ BMLoop *l_first_2 = l_first_1->next;
+ BMLoop *l_first_3 = l_first_2->next;
- BMLoop *l_other_0;
- BMLoop *l_other_1;
+ BMLoop *l_other_0;
+ BMLoop *l_other_1;
- if (UNLIKELY(l_first_0 == l_first_0->radial_next)) {
- return;
- }
+ if (UNLIKELY(l_first_0 == l_first_0->radial_next)) {
+ return;
+ }
- l_other_0 = BM_edge_other_loop(l_first_0->e, l_first_0);
- l_other_1 = BM_edge_other_loop(l_first_0->e, l_first_1);
+ l_other_0 = BM_edge_other_loop(l_first_0->e, l_first_0);
+ l_other_1 = BM_edge_other_loop(l_first_0->e, l_first_1);
- /* copy data */
- BM_elem_attrs_copy(bm, bm, l_other_0->f, f);
- BM_elem_flag_disable(f, BM_ELEM_HIDDEN); /* possibly we copy from a hidden face */
+ /* copy data */
+ BM_elem_attrs_copy(bm, bm, l_other_0->f, f);
+ BM_elem_flag_disable(f, BM_ELEM_HIDDEN); /* possibly we copy from a hidden face */
- BM_elem_attrs_copy(bm, bm, l_other_0, l_first_0);
- BM_elem_attrs_copy(bm, bm, l_other_0, l_first_3);
+ BM_elem_attrs_copy(bm, bm, l_other_0, l_first_0);
+ BM_elem_attrs_copy(bm, bm, l_other_0, l_first_3);
- BM_elem_attrs_copy(bm, bm, l_other_1, l_first_1);
- BM_elem_attrs_copy(bm, bm, l_other_1, l_first_2);
+ BM_elem_attrs_copy(bm, bm, l_other_1, l_first_1);
+ BM_elem_attrs_copy(bm, bm, l_other_1, l_first_2);
}
/* Disable the skin root flag on the input vert, assumes that the vert
* data includes an CD_MVERT_SKIN layer */
static void bm_extrude_disable_skin_root(BMesh *bm, BMVert *v)
{
- MVertSkin *vs;
+ MVertSkin *vs;
- vs = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_MVERT_SKIN);
- vs->flag &= ~MVERT_SKIN_ROOT;
+ vs = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_MVERT_SKIN);
+ vs->flag &= ~MVERT_SKIN_ROOT;
}
void bmo_extrude_edge_only_exec(BMesh *bm, BMOperator *op)
{
- BMOIter siter;
- BMOperator dupeop;
- BMFace *f;
- BMEdge *e, *e_new;
- const bool use_normal_flip = BMO_slot_bool_get(op->slots_in, "use_normal_flip");
-
- BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
- BMO_edge_flag_enable(bm, e, EXT_INPUT);
- BMO_vert_flag_enable(bm, e->v1, EXT_INPUT);
- BMO_vert_flag_enable(bm, e->v2, EXT_INPUT);
- }
-
- BMO_op_initf(
- bm, &dupeop, op->flag,
- "duplicate geom=%fve use_select_history=%b",
- EXT_INPUT, BMO_slot_bool_get(op->slots_in, "use_select_history"));
-
- BMO_op_exec(bm, &dupeop);
-
- /* disable root flag on all new skin nodes */
- if (CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) {
- BMVert *v;
- BMO_ITER (v, &siter, dupeop.slots_out, "geom.out", BM_VERT) {
- bm_extrude_disable_skin_root(bm, v);
- }
- }
-
- for (e = BMO_iter_new(&siter, dupeop.slots_out, "boundary_map.out", 0); e; e = BMO_iter_step(&siter)) {
- BMVert *f_verts[4];
- e_new = BMO_iter_map_value_ptr(&siter);
-
-
- const bool edge_normal_flip = !(e->l && e->v1 != e->l->v);
- if (edge_normal_flip == use_normal_flip) {
- f_verts[0] = e->v1;
- f_verts[1] = e->v2;
- f_verts[2] = e_new->v2;
- f_verts[3] = e_new->v1;
- }
- else {
- f_verts[0] = e->v2;
- f_verts[1] = e->v1;
- f_verts[2] = e_new->v1;
- f_verts[3] = e_new->v2;
- }
- /* not sure what to do about example face, pass NULL for now */
- f = BM_face_create_verts(bm, f_verts, 4, NULL, BM_CREATE_NOP, true);
- bm_extrude_copy_face_loop_attributes(bm, f);
-
- if (BMO_edge_flag_test(bm, e, EXT_INPUT)) {
- e = e_new;
- }
-
- BMO_face_flag_enable(bm, f, EXT_KEEP);
- BMO_edge_flag_enable(bm, e, EXT_KEEP);
- BMO_vert_flag_enable(bm, e->v1, EXT_KEEP);
- BMO_vert_flag_enable(bm, e->v2, EXT_KEEP);
-
- }
-
- BMO_op_finish(bm, &dupeop);
-
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_ALL_NOLOOP, EXT_KEEP);
+ BMOIter siter;
+ BMOperator dupeop;
+ BMFace *f;
+ BMEdge *e, *e_new;
+ const bool use_normal_flip = BMO_slot_bool_get(op->slots_in, "use_normal_flip");
+
+ BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
+ BMO_edge_flag_enable(bm, e, EXT_INPUT);
+ BMO_vert_flag_enable(bm, e->v1, EXT_INPUT);
+ BMO_vert_flag_enable(bm, e->v2, EXT_INPUT);
+ }
+
+ BMO_op_initf(bm,
+ &dupeop,
+ op->flag,
+ "duplicate geom=%fve use_select_history=%b",
+ EXT_INPUT,
+ BMO_slot_bool_get(op->slots_in, "use_select_history"));
+
+ BMO_op_exec(bm, &dupeop);
+
+ /* disable root flag on all new skin nodes */
+ if (CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) {
+ BMVert *v;
+ BMO_ITER (v, &siter, dupeop.slots_out, "geom.out", BM_VERT) {
+ bm_extrude_disable_skin_root(bm, v);
+ }
+ }
+
+ for (e = BMO_iter_new(&siter, dupeop.slots_out, "boundary_map.out", 0); e;
+ e = BMO_iter_step(&siter)) {
+ BMVert *f_verts[4];
+ e_new = BMO_iter_map_value_ptr(&siter);
+
+ const bool edge_normal_flip = !(e->l && e->v1 != e->l->v);
+ if (edge_normal_flip == use_normal_flip) {
+ f_verts[0] = e->v1;
+ f_verts[1] = e->v2;
+ f_verts[2] = e_new->v2;
+ f_verts[3] = e_new->v1;
+ }
+ else {
+ f_verts[0] = e->v2;
+ f_verts[1] = e->v1;
+ f_verts[2] = e_new->v1;
+ f_verts[3] = e_new->v2;
+ }
+ /* not sure what to do about example face, pass NULL for now */
+ f = BM_face_create_verts(bm, f_verts, 4, NULL, BM_CREATE_NOP, true);
+ bm_extrude_copy_face_loop_attributes(bm, f);
+
+ if (BMO_edge_flag_test(bm, e, EXT_INPUT)) {
+ e = e_new;
+ }
+
+ BMO_face_flag_enable(bm, f, EXT_KEEP);
+ BMO_edge_flag_enable(bm, e, EXT_KEEP);
+ BMO_vert_flag_enable(bm, e->v1, EXT_KEEP);
+ BMO_vert_flag_enable(bm, e->v2, EXT_KEEP);
+ }
+
+ BMO_op_finish(bm, &dupeop);
+
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_ALL_NOLOOP, EXT_KEEP);
}
void bmo_extrude_vert_indiv_exec(BMesh *bm, BMOperator *op)
{
- const bool use_select_history = BMO_slot_bool_get(op->slots_in, "use_select_history");
- BMOIter siter;
- BMVert *v, *dupev;
- BMEdge *e;
- const bool has_vskin = CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN);
- GHash *select_history_map = NULL;
-
- if (use_select_history) {
- select_history_map = BM_select_history_map_create(bm);
- }
-
- for (v = BMO_iter_new(&siter, op->slots_in, "verts", BM_VERT); v; v = BMO_iter_step(&siter)) {
- dupev = BM_vert_create(bm, v->co, v, BM_CREATE_NOP);
- BMO_vert_flag_enable(bm, dupev, EXT_KEEP);
-
- if (has_vskin) {
- bm_extrude_disable_skin_root(bm, v);
- }
-
- if (select_history_map) {
- BMEditSelection *ese;
- ese = BLI_ghash_lookup(select_history_map, v);
- if (ese) {
- ese->ele = (BMElem *)dupev;
- }
- }
-
- /* not essential, but ensures face normals from extruded edges are contiguous */
- if (BM_vert_is_wire_endpoint(v)) {
- if (v->e->v1 == v) {
- SWAP(BMVert *, v, dupev);
- }
- }
-
- e = BM_edge_create(bm, v, dupev, NULL, BM_CREATE_NOP);
- BMO_edge_flag_enable(bm, e, EXT_KEEP);
- }
-
- if (select_history_map) {
- BLI_ghash_free(select_history_map, NULL, NULL);
- }
-
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, EXT_KEEP);
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EXT_KEEP);
+ const bool use_select_history = BMO_slot_bool_get(op->slots_in, "use_select_history");
+ BMOIter siter;
+ BMVert *v, *dupev;
+ BMEdge *e;
+ const bool has_vskin = CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN);
+ GHash *select_history_map = NULL;
+
+ if (use_select_history) {
+ select_history_map = BM_select_history_map_create(bm);
+ }
+
+ for (v = BMO_iter_new(&siter, op->slots_in, "verts", BM_VERT); v; v = BMO_iter_step(&siter)) {
+ dupev = BM_vert_create(bm, v->co, v, BM_CREATE_NOP);
+ BMO_vert_flag_enable(bm, dupev, EXT_KEEP);
+
+ if (has_vskin) {
+ bm_extrude_disable_skin_root(bm, v);
+ }
+
+ if (select_history_map) {
+ BMEditSelection *ese;
+ ese = BLI_ghash_lookup(select_history_map, v);
+ if (ese) {
+ ese->ele = (BMElem *)dupev;
+ }
+ }
+
+ /* not essential, but ensures face normals from extruded edges are contiguous */
+ if (BM_vert_is_wire_endpoint(v)) {
+ if (v->e->v1 == v) {
+ SWAP(BMVert *, v, dupev);
+ }
+ }
+
+ e = BM_edge_create(bm, v, dupev, NULL, BM_CREATE_NOP);
+ BMO_edge_flag_enable(bm, e, EXT_KEEP);
+ }
+
+ if (select_history_map) {
+ BLI_ghash_free(select_history_map, NULL, NULL);
+ }
+
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, EXT_KEEP);
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EXT_KEEP);
}
#ifdef USE_EDGE_REGION_FLAGS
@@ -296,280 +295,275 @@ void bmo_extrude_vert_indiv_exec(BMesh *bm, BMOperator *op)
*/
static bool bm_extrude_region_edge_flag(const BMVert *v, char r_e_hflag[2])
{
- BMEdge *e_iter;
- const char hflag_enable = BM_ELEM_SEAM;
- const char hflag_disable = BM_ELEM_SMOOTH;
- bool ok = false;
-
- r_e_hflag[0] = 0x0;
- r_e_hflag[1] = 0xff;
-
- /* clear flags on both disks */
- e_iter = v->e;
- do {
- if (e_iter->l && !BM_edge_is_boundary(e_iter)) {
- r_e_hflag[0] |= e_iter->head.hflag;
- r_e_hflag[1] &= e_iter->head.hflag;
- ok = true;
- }
- } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v)) != v->e);
-
- if (ok) {
- r_e_hflag[0] &= hflag_enable;
- r_e_hflag[1] = hflag_disable & ~r_e_hflag[1];
- }
- return ok;
+ BMEdge *e_iter;
+ const char hflag_enable = BM_ELEM_SEAM;
+ const char hflag_disable = BM_ELEM_SMOOTH;
+ bool ok = false;
+
+ r_e_hflag[0] = 0x0;
+ r_e_hflag[1] = 0xff;
+
+ /* clear flags on both disks */
+ e_iter = v->e;
+ do {
+ if (e_iter->l && !BM_edge_is_boundary(e_iter)) {
+ r_e_hflag[0] |= e_iter->head.hflag;
+ r_e_hflag[1] &= e_iter->head.hflag;
+ ok = true;
+ }
+ } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v)) != v->e);
+
+ if (ok) {
+ r_e_hflag[0] &= hflag_enable;
+ r_e_hflag[1] = hflag_disable & ~r_e_hflag[1];
+ }
+ return ok;
}
-#endif /* USE_EDGE_REGION_FLAGS */
+#endif /* USE_EDGE_REGION_FLAGS */
void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op)
{
- BMOperator dupeop, delop;
- BMOIter siter;
- BMIter iter, fiter, viter;
- BMEdge *e, *e_new;
- BMVert *v;
- BMFace *f;
- bool found, delorig = false;
- BMOpSlot *slot_facemap_out;
- BMOpSlot *slot_edges_exclude;
- const bool use_normal_flip = BMO_slot_bool_get(op->slots_in, "use_normal_flip");
- const bool use_normal_from_adjacent = BMO_slot_bool_get(op->slots_in, "use_normal_from_adjacent");
-
- /* initialize our sub-operators */
- BMO_op_initf(
- bm, &dupeop, op->flag,
- "duplicate use_select_history=%b",
- BMO_slot_bool_get(op->slots_in, "use_select_history"));
-
- BMO_slot_buffer_flag_enable(bm, op->slots_in, "geom", BM_EDGE | BM_FACE, EXT_INPUT);
-
- /* if one flagged face is bordered by an un-flagged face, then we delete
- * original geometry unless caller explicitly asked to keep it. */
- if (!BMO_slot_bool_get(op->slots_in, "use_keep_orig")) {
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
-
- int edge_face_tot;
-
- if (!BMO_edge_flag_test(bm, e, EXT_INPUT)) {
- continue;
- }
-
- found = false; /* found a face that isn't input? */
- edge_face_tot = 0; /* edge/face count */
-
- BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) {
- if (!BMO_face_flag_test(bm, f, EXT_INPUT)) {
- found = true;
- delorig = true;
- break;
- }
-
- edge_face_tot++;
- }
-
- if ((edge_face_tot > 1) && (found == false)) {
- /* edge has a face user, that face isn't extrude input */
- BMO_edge_flag_enable(bm, e, EXT_DEL);
- }
- }
- }
-
- /* calculate verts to delete */
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- if (v->e) { /* only deal with verts attached to geometry [#33651] */
- found = false;
-
- BM_ITER_ELEM (e, &viter, v, BM_EDGES_OF_VERT) {
- if (!BMO_edge_flag_test(bm, e, EXT_INPUT) ||
- !BMO_edge_flag_test(bm, e, EXT_DEL))
- {
- found = true;
- break;
- }
- }
-
- /* avoid an extra loop */
- if (found == true) {
- BM_ITER_ELEM (f, &viter, v, BM_FACES_OF_VERT) {
- if (!BMO_face_flag_test(bm, f, EXT_INPUT)) {
- found = true;
- break;
- }
- }
- }
-
- if (found == false) {
- BMO_vert_flag_enable(bm, v, EXT_DEL);
- }
- }
- }
-
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- if (BMO_face_flag_test(bm, f, EXT_INPUT)) {
- BMO_face_flag_enable(bm, f, EXT_DEL);
- }
- }
-
- if (delorig == true) {
- BMO_op_initf(bm, &delop, op->flag,
- "delete geom=%fvef context=%i",
- EXT_DEL, DEL_ONLYTAGGED);
- }
-
- BMO_slot_copy(op, slots_in, "geom",
- &dupeop, slots_in, "geom");
- BMO_op_exec(bm, &dupeop);
-
- /* disable root flag on all new skin nodes */
- if (CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) {
- BMO_ITER (v, &siter, dupeop.slots_out, "geom.out", BM_VERT) {
- bm_extrude_disable_skin_root(bm, v);
- }
- }
-
- slot_facemap_out = BMO_slot_get(dupeop.slots_out, "face_map.out");
- if (bm->act_face && BMO_face_flag_test(bm, bm->act_face, EXT_INPUT)) {
- bm->act_face = BMO_slot_map_elem_get(slot_facemap_out, bm->act_face);
- }
-
- if (delorig) {
- BMO_op_exec(bm, &delop);
- }
-
- /* if not delorig, reverse loops of original face */
- if (!delorig) {
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- if (BMO_face_flag_test(bm, f, EXT_INPUT)) {
- BM_face_normal_flip(bm, f);
- }
- }
- }
-
- BMO_slot_copy(&dupeop, slots_out, "geom.out",
- op, slots_out, "geom.out");
-
- slot_edges_exclude = BMO_slot_get(op->slots_in, "edges_exclude");
- for (e = BMO_iter_new(&siter, dupeop.slots_out, "boundary_map.out", 0); e; e = BMO_iter_step(&siter)) {
- BMVert *f_verts[4];
+ BMOperator dupeop, delop;
+ BMOIter siter;
+ BMIter iter, fiter, viter;
+ BMEdge *e, *e_new;
+ BMVert *v;
+ BMFace *f;
+ bool found, delorig = false;
+ BMOpSlot *slot_facemap_out;
+ BMOpSlot *slot_edges_exclude;
+ const bool use_normal_flip = BMO_slot_bool_get(op->slots_in, "use_normal_flip");
+ const bool use_normal_from_adjacent = BMO_slot_bool_get(op->slots_in,
+ "use_normal_from_adjacent");
+
+ /* initialize our sub-operators */
+ BMO_op_initf(bm,
+ &dupeop,
+ op->flag,
+ "duplicate use_select_history=%b",
+ BMO_slot_bool_get(op->slots_in, "use_select_history"));
+
+ BMO_slot_buffer_flag_enable(bm, op->slots_in, "geom", BM_EDGE | BM_FACE, EXT_INPUT);
+
+ /* if one flagged face is bordered by an un-flagged face, then we delete
+ * original geometry unless caller explicitly asked to keep it. */
+ if (!BMO_slot_bool_get(op->slots_in, "use_keep_orig")) {
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+
+ int edge_face_tot;
+
+ if (!BMO_edge_flag_test(bm, e, EXT_INPUT)) {
+ continue;
+ }
+
+ found = false; /* found a face that isn't input? */
+ edge_face_tot = 0; /* edge/face count */
+
+ BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) {
+ if (!BMO_face_flag_test(bm, f, EXT_INPUT)) {
+ found = true;
+ delorig = true;
+ break;
+ }
+
+ edge_face_tot++;
+ }
+
+ if ((edge_face_tot > 1) && (found == false)) {
+ /* edge has a face user, that face isn't extrude input */
+ BMO_edge_flag_enable(bm, e, EXT_DEL);
+ }
+ }
+ }
+
+ /* calculate verts to delete */
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (v->e) { /* only deal with verts attached to geometry [#33651] */
+ found = false;
+
+ BM_ITER_ELEM (e, &viter, v, BM_EDGES_OF_VERT) {
+ if (!BMO_edge_flag_test(bm, e, EXT_INPUT) || !BMO_edge_flag_test(bm, e, EXT_DEL)) {
+ found = true;
+ break;
+ }
+ }
+
+ /* avoid an extra loop */
+ if (found == true) {
+ BM_ITER_ELEM (f, &viter, v, BM_FACES_OF_VERT) {
+ if (!BMO_face_flag_test(bm, f, EXT_INPUT)) {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (found == false) {
+ BMO_vert_flag_enable(bm, v, EXT_DEL);
+ }
+ }
+ }
+
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if (BMO_face_flag_test(bm, f, EXT_INPUT)) {
+ BMO_face_flag_enable(bm, f, EXT_DEL);
+ }
+ }
+
+ if (delorig == true) {
+ BMO_op_initf(bm, &delop, op->flag, "delete geom=%fvef context=%i", EXT_DEL, DEL_ONLYTAGGED);
+ }
+
+ BMO_slot_copy(op, slots_in, "geom", &dupeop, slots_in, "geom");
+ BMO_op_exec(bm, &dupeop);
+
+ /* disable root flag on all new skin nodes */
+ if (CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) {
+ BMO_ITER (v, &siter, dupeop.slots_out, "geom.out", BM_VERT) {
+ bm_extrude_disable_skin_root(bm, v);
+ }
+ }
+
+ slot_facemap_out = BMO_slot_get(dupeop.slots_out, "face_map.out");
+ if (bm->act_face && BMO_face_flag_test(bm, bm->act_face, EXT_INPUT)) {
+ bm->act_face = BMO_slot_map_elem_get(slot_facemap_out, bm->act_face);
+ }
+
+ if (delorig) {
+ BMO_op_exec(bm, &delop);
+ }
+
+ /* if not delorig, reverse loops of original face */
+ if (!delorig) {
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if (BMO_face_flag_test(bm, f, EXT_INPUT)) {
+ BM_face_normal_flip(bm, f);
+ }
+ }
+ }
+
+ BMO_slot_copy(&dupeop, slots_out, "geom.out", op, slots_out, "geom.out");
+
+ slot_edges_exclude = BMO_slot_get(op->slots_in, "edges_exclude");
+ for (e = BMO_iter_new(&siter, dupeop.slots_out, "boundary_map.out", 0); e;
+ e = BMO_iter_step(&siter)) {
+ BMVert *f_verts[4];
#ifdef USE_EDGE_REGION_FLAGS
- BMEdge *f_edges[4];
+ BMEdge *f_edges[4];
#endif
- /* this should always be wire, so this is mainly a speedup to avoid map lookup */
- if (BM_edge_is_wire(e) && BMO_slot_map_contains(slot_edges_exclude, e)) {
- BMVert *v1 = e->v1, *v2 = e->v2;
-
- /* The original edge was excluded,
- * this would result in a standalone wire edge - see [#30399] */
- BM_edge_kill(bm, e);
-
- /* kill standalone vertices from this edge - see [#32341] */
- if (!v1->e) {
- BM_vert_kill(bm, v1);
- }
- if (!v2->e) {
- BM_vert_kill(bm, v2);
- }
-
- continue;
- }
-
- /* skip creating face for excluded edges see [#35503] */
- if (BMO_slot_map_contains(slot_edges_exclude, e)) {
- /* simply skip creating the face */
- continue;
- }
-
- e_new = BMO_iter_map_value_ptr(&siter);
-
- if (!e_new) {
- continue;
- }
-
- bool edge_normal_flip;
- if (use_normal_from_adjacent == false) {
- /* Orient loop to give same normal as a loop of 'e_new'
- * if it exists (will be one of the faces from the region),
- * else same normal as a loop of e, if it exists. */
- edge_normal_flip = !(
- e_new->l ?
- (e_new->l->v == e_new->v1) :
- (!e->l || !(e->l->v == e->v1)));
- }
- else {
- /* Special case, needed for repetitive extrusions
- * that use the normals from the previously created faces. */
- edge_normal_flip = !(e->l && e->v1 != e->l->v);
- }
-
- if (edge_normal_flip == use_normal_flip) {
- f_verts[0] = e->v1;
- f_verts[1] = e->v2;
- f_verts[2] = e_new->v2;
- f_verts[3] = e_new->v1;
- }
- else {
- f_verts[0] = e->v2;
- f_verts[1] = e->v1;
- f_verts[2] = e_new->v1;
- f_verts[3] = e_new->v2;
- }
+ /* this should always be wire, so this is mainly a speedup to avoid map lookup */
+ if (BM_edge_is_wire(e) && BMO_slot_map_contains(slot_edges_exclude, e)) {
+ BMVert *v1 = e->v1, *v2 = e->v2;
+
+ /* The original edge was excluded,
+ * this would result in a standalone wire edge - see [#30399] */
+ BM_edge_kill(bm, e);
+
+ /* kill standalone vertices from this edge - see [#32341] */
+ if (!v1->e) {
+ BM_vert_kill(bm, v1);
+ }
+ if (!v2->e) {
+ BM_vert_kill(bm, v2);
+ }
+
+ continue;
+ }
+
+ /* skip creating face for excluded edges see [#35503] */
+ if (BMO_slot_map_contains(slot_edges_exclude, e)) {
+ /* simply skip creating the face */
+ continue;
+ }
+
+ e_new = BMO_iter_map_value_ptr(&siter);
+
+ if (!e_new) {
+ continue;
+ }
+
+ bool edge_normal_flip;
+ if (use_normal_from_adjacent == false) {
+ /* Orient loop to give same normal as a loop of 'e_new'
+ * if it exists (will be one of the faces from the region),
+ * else same normal as a loop of e, if it exists. */
+ edge_normal_flip = !(e_new->l ? (e_new->l->v == e_new->v1) : (!e->l || !(e->l->v == e->v1)));
+ }
+ else {
+ /* Special case, needed for repetitive extrusions
+ * that use the normals from the previously created faces. */
+ edge_normal_flip = !(e->l && e->v1 != e->l->v);
+ }
+
+ if (edge_normal_flip == use_normal_flip) {
+ f_verts[0] = e->v1;
+ f_verts[1] = e->v2;
+ f_verts[2] = e_new->v2;
+ f_verts[3] = e_new->v1;
+ }
+ else {
+ f_verts[0] = e->v2;
+ f_verts[1] = e->v1;
+ f_verts[2] = e_new->v1;
+ f_verts[3] = e_new->v2;
+ }
#ifdef USE_EDGE_REGION_FLAGS
- /* handle new edges */
- f_edges[0] = e;
- f_edges[2] = e_new;
-
- f_edges[1] = BM_edge_exists(f_verts[1], f_verts[2]);
- if (f_edges[1] == NULL) {
- char e_hflag[2];
- bool e_hflag_ok = bm_extrude_region_edge_flag(f_verts[2], e_hflag);
- f_edges[1] = BM_edge_create(bm, f_verts[1], f_verts[2], NULL, BM_CREATE_NOP);
- if (e_hflag_ok) {
- BM_elem_flag_enable(f_edges[1], e_hflag[0]);
- BM_elem_flag_disable(f_edges[1], e_hflag[1]);
- }
- }
-
- f_edges[3] = BM_edge_exists(f_verts[3], f_verts[0]);
- if (f_edges[3] == NULL) {
- char e_hflag[2];
- bool e_hflag_ok = bm_extrude_region_edge_flag(f_verts[3], e_hflag);
- f_edges[3] = BM_edge_create(bm, f_verts[3], f_verts[0], NULL, BM_CREATE_NOP);
- if (e_hflag_ok) {
- BM_elem_flag_enable(f_edges[3], e_hflag[0]);
- BM_elem_flag_disable(f_edges[3], e_hflag[1]);
- }
- }
-
- f = BM_face_create(bm, f_verts, f_edges, 4, NULL, BM_CREATE_NOP);
+ /* handle new edges */
+ f_edges[0] = e;
+ f_edges[2] = e_new;
+
+ f_edges[1] = BM_edge_exists(f_verts[1], f_verts[2]);
+ if (f_edges[1] == NULL) {
+ char e_hflag[2];
+ bool e_hflag_ok = bm_extrude_region_edge_flag(f_verts[2], e_hflag);
+ f_edges[1] = BM_edge_create(bm, f_verts[1], f_verts[2], NULL, BM_CREATE_NOP);
+ if (e_hflag_ok) {
+ BM_elem_flag_enable(f_edges[1], e_hflag[0]);
+ BM_elem_flag_disable(f_edges[1], e_hflag[1]);
+ }
+ }
+
+ f_edges[3] = BM_edge_exists(f_verts[3], f_verts[0]);
+ if (f_edges[3] == NULL) {
+ char e_hflag[2];
+ bool e_hflag_ok = bm_extrude_region_edge_flag(f_verts[3], e_hflag);
+ f_edges[3] = BM_edge_create(bm, f_verts[3], f_verts[0], NULL, BM_CREATE_NOP);
+ if (e_hflag_ok) {
+ BM_elem_flag_enable(f_edges[3], e_hflag[0]);
+ BM_elem_flag_disable(f_edges[3], e_hflag[1]);
+ }
+ }
+
+ f = BM_face_create(bm, f_verts, f_edges, 4, NULL, BM_CREATE_NOP);
#else
- f = BM_face_create_verts(bm, f_verts, 4, NULL, BM_CREATE_NOP, true);
+ f = BM_face_create_verts(bm, f_verts, 4, NULL, BM_CREATE_NOP, true);
#endif
- bm_extrude_copy_face_loop_attributes(bm, f);
- }
-
- /* link isolated vert */
- for (v = BMO_iter_new(&siter, dupeop.slots_out, "isovert_map.out", 0); v; v = BMO_iter_step(&siter)) {
- BMVert *v2 = BMO_iter_map_value_ptr(&siter);
-
- /* not essential, but ensures face normals from extruded edges are contiguous */
- if (BM_vert_is_wire_endpoint(v)) {
- if (v->e->v1 == v) {
- SWAP(BMVert *, v, v2);
- }
- }
-
- BM_edge_create(bm, v, v2, NULL, BM_CREATE_NO_DOUBLE);
- }
-
- /* cleanup */
- if (delorig) {
- BMO_op_finish(bm, &delop);
- }
- BMO_op_finish(bm, &dupeop);
+ bm_extrude_copy_face_loop_attributes(bm, f);
+ }
+
+ /* link isolated vert */
+ for (v = BMO_iter_new(&siter, dupeop.slots_out, "isovert_map.out", 0); v;
+ v = BMO_iter_step(&siter)) {
+ BMVert *v2 = BMO_iter_map_value_ptr(&siter);
+
+ /* not essential, but ensures face normals from extruded edges are contiguous */
+ if (BM_vert_is_wire_endpoint(v)) {
+ if (v->e->v1 == v) {
+ SWAP(BMVert *, v, v2);
+ }
+ }
+
+ BM_edge_create(bm, v, v2, NULL, BM_CREATE_NO_DOUBLE);
+ }
+
+ /* cleanup */
+ if (delorig) {
+ BMO_op_finish(bm, &delop);
+ }
+ BMO_op_finish(bm, &dupeop);
}
/*
@@ -580,231 +574,229 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op)
*/
static void calc_solidify_normals(BMesh *bm)
{
- BMIter viter, eiter, fiter;
- BMVert *v;
- BMEdge *e;
- BMFace *f, *f1, *f2;
- float edge_normal[3];
- int i;
-
- /* can't use BM_edge_face_count because we need to count only marked faces */
- int *edge_face_count = MEM_callocN(sizeof(int) * bm->totedge, __func__);
-
- BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
- BM_elem_flag_enable(v, BM_ELEM_TAG);
- }
-
- BM_mesh_elem_index_ensure(bm, BM_EDGE);
-
- BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
- if (!BMO_face_flag_test(bm, f, FACE_MARK)) {
- continue;
- }
-
- BM_ITER_ELEM (e, &eiter, f, BM_EDGES_OF_FACE) {
-
- /* And mark all edges and vertices on the
- * marked faces */
- BMO_edge_flag_enable(bm, e, EDGE_MARK);
- BMO_vert_flag_enable(bm, e->v1, VERT_MARK);
- BMO_vert_flag_enable(bm, e->v2, VERT_MARK);
- edge_face_count[BM_elem_index_get(e)]++;
- }
- }
-
- BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
- if (!BMO_edge_flag_test(bm, e, EDGE_MARK)) {
- continue;
- }
-
- i = edge_face_count[BM_elem_index_get(e)]++;
-
- if (i == 0 || i > 2) {
- /* Edge & vertices are non-manifold even when considering
- * only marked faces */
- BMO_edge_flag_enable(bm, e, EDGE_NONMAN);
- BMO_vert_flag_enable(bm, e->v1, VERT_NONMAN);
- BMO_vert_flag_enable(bm, e->v2, VERT_NONMAN);
- }
- }
- MEM_freeN(edge_face_count);
- edge_face_count = NULL; /* don't re-use */
-
- BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
- if (!BM_vert_is_manifold(v)) {
- BMO_vert_flag_enable(bm, v, VERT_NONMAN);
- continue;
- }
-
- if (BMO_vert_flag_test(bm, v, VERT_MARK)) {
- zero_v3(v->no);
- }
- }
-
- BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
-
- /* If the edge is not part of a the solidify region
- * its normal should not be considered */
- if (!BMO_edge_flag_test(bm, e, EDGE_MARK)) {
- continue;
- }
-
- /* If the edge joins more than two marked faces high
- * quality normal computation won't work */
- if (BMO_edge_flag_test(bm, e, EDGE_NONMAN)) {
- continue;
- }
-
- f1 = f2 = NULL;
-
- BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) {
- if (BMO_face_flag_test(bm, f, FACE_MARK)) {
- if (f1 == NULL) {
- f1 = f;
- }
- else {
- BLI_assert(f2 == NULL);
- f2 = f;
- }
- }
- }
-
- BLI_assert(f1 != NULL);
-
- if (f2 != NULL) {
- const float angle = angle_normalized_v3v3(f1->no, f2->no);
-
- if (angle > 0.0f) {
- /* two faces using this edge, calculate the edge normal
- * using the angle between the faces as a weighting */
- add_v3_v3v3(edge_normal, f1->no, f2->no);
- normalize_v3_length(edge_normal, angle);
- }
- else {
- /* can't do anything useful here!
- * Set the face index for a vert in case it gets a zero normal */
- BM_elem_flag_disable(e->v1, BM_ELEM_TAG);
- BM_elem_flag_disable(e->v2, BM_ELEM_TAG);
- continue;
- }
- }
- else {
- /* only one face attached to that edge */
- /* an edge without another attached- the weight on this is undefined,
- * M_PI_2 is 90d in radians and that seems good enough */
- copy_v3_v3(edge_normal, f1->no);
- mul_v3_fl(edge_normal, M_PI_2);
- }
-
- add_v3_v3(e->v1->no, edge_normal);
- add_v3_v3(e->v2->no, edge_normal);
- }
-
- /* normalize accumulated vertex normal */
- BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
- if (!BMO_vert_flag_test(bm, v, VERT_MARK)) {
- continue;
- }
-
- if (BMO_vert_flag_test(bm, v, VERT_NONMAN)) {
- /* use standard normals for vertices connected to non-manifold edges */
- BM_vert_normal_update(v);
- }
- else if (normalize_v3(v->no) == 0.0f && !BM_elem_flag_test(v, BM_ELEM_TAG)) {
- /* exceptional case, totally flat. use the normal
- * of any marked face around the vertex */
- BM_ITER_ELEM (f, &fiter, v, BM_FACES_OF_VERT) {
- if (BMO_face_flag_test(bm, f, FACE_MARK)) {
- break;
- }
- }
- copy_v3_v3(v->no, f->no);
- }
- }
+ BMIter viter, eiter, fiter;
+ BMVert *v;
+ BMEdge *e;
+ BMFace *f, *f1, *f2;
+ float edge_normal[3];
+ int i;
+
+ /* can't use BM_edge_face_count because we need to count only marked faces */
+ int *edge_face_count = MEM_callocN(sizeof(int) * bm->totedge, __func__);
+
+ BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
+ BM_elem_flag_enable(v, BM_ELEM_TAG);
+ }
+
+ BM_mesh_elem_index_ensure(bm, BM_EDGE);
+
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ if (!BMO_face_flag_test(bm, f, FACE_MARK)) {
+ continue;
+ }
+
+ BM_ITER_ELEM (e, &eiter, f, BM_EDGES_OF_FACE) {
+
+ /* And mark all edges and vertices on the
+ * marked faces */
+ BMO_edge_flag_enable(bm, e, EDGE_MARK);
+ BMO_vert_flag_enable(bm, e->v1, VERT_MARK);
+ BMO_vert_flag_enable(bm, e->v2, VERT_MARK);
+ edge_face_count[BM_elem_index_get(e)]++;
+ }
+ }
+
+ BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
+ if (!BMO_edge_flag_test(bm, e, EDGE_MARK)) {
+ continue;
+ }
+
+ i = edge_face_count[BM_elem_index_get(e)]++;
+
+ if (i == 0 || i > 2) {
+ /* Edge & vertices are non-manifold even when considering
+ * only marked faces */
+ BMO_edge_flag_enable(bm, e, EDGE_NONMAN);
+ BMO_vert_flag_enable(bm, e->v1, VERT_NONMAN);
+ BMO_vert_flag_enable(bm, e->v2, VERT_NONMAN);
+ }
+ }
+ MEM_freeN(edge_face_count);
+ edge_face_count = NULL; /* don't re-use */
+
+ BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
+ if (!BM_vert_is_manifold(v)) {
+ BMO_vert_flag_enable(bm, v, VERT_NONMAN);
+ continue;
+ }
+
+ if (BMO_vert_flag_test(bm, v, VERT_MARK)) {
+ zero_v3(v->no);
+ }
+ }
+
+ BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
+
+ /* If the edge is not part of a the solidify region
+ * its normal should not be considered */
+ if (!BMO_edge_flag_test(bm, e, EDGE_MARK)) {
+ continue;
+ }
+
+ /* If the edge joins more than two marked faces high
+ * quality normal computation won't work */
+ if (BMO_edge_flag_test(bm, e, EDGE_NONMAN)) {
+ continue;
+ }
+
+ f1 = f2 = NULL;
+
+ BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) {
+ if (BMO_face_flag_test(bm, f, FACE_MARK)) {
+ if (f1 == NULL) {
+ f1 = f;
+ }
+ else {
+ BLI_assert(f2 == NULL);
+ f2 = f;
+ }
+ }
+ }
+
+ BLI_assert(f1 != NULL);
+
+ if (f2 != NULL) {
+ const float angle = angle_normalized_v3v3(f1->no, f2->no);
+
+ if (angle > 0.0f) {
+ /* two faces using this edge, calculate the edge normal
+ * using the angle between the faces as a weighting */
+ add_v3_v3v3(edge_normal, f1->no, f2->no);
+ normalize_v3_length(edge_normal, angle);
+ }
+ else {
+ /* can't do anything useful here!
+ * Set the face index for a vert in case it gets a zero normal */
+ BM_elem_flag_disable(e->v1, BM_ELEM_TAG);
+ BM_elem_flag_disable(e->v2, BM_ELEM_TAG);
+ continue;
+ }
+ }
+ else {
+ /* only one face attached to that edge */
+ /* an edge without another attached- the weight on this is undefined,
+ * M_PI_2 is 90d in radians and that seems good enough */
+ copy_v3_v3(edge_normal, f1->no);
+ mul_v3_fl(edge_normal, M_PI_2);
+ }
+
+ add_v3_v3(e->v1->no, edge_normal);
+ add_v3_v3(e->v2->no, edge_normal);
+ }
+
+ /* normalize accumulated vertex normal */
+ BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
+ if (!BMO_vert_flag_test(bm, v, VERT_MARK)) {
+ continue;
+ }
+
+ if (BMO_vert_flag_test(bm, v, VERT_NONMAN)) {
+ /* use standard normals for vertices connected to non-manifold edges */
+ BM_vert_normal_update(v);
+ }
+ else if (normalize_v3(v->no) == 0.0f && !BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ /* exceptional case, totally flat. use the normal
+ * of any marked face around the vertex */
+ BM_ITER_ELEM (f, &fiter, v, BM_FACES_OF_VERT) {
+ if (BMO_face_flag_test(bm, f, FACE_MARK)) {
+ break;
+ }
+ }
+ copy_v3_v3(v->no, f->no);
+ }
+ }
}
static void solidify_add_thickness(BMesh *bm, const float dist)
{
- BMFace *f;
- BMVert *v;
- BMLoop *l;
- BMIter iter, loopIter;
- float *vert_angles = MEM_callocN(sizeof(float) * bm->totvert * 2, "solidify"); /* 2 in 1 */
- float *vert_accum = vert_angles + bm->totvert;
- int i, index;
-
- BLI_buffer_declare_static(float, face_angles_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
- BLI_buffer_declare_static(float *, verts_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
-
- BM_mesh_elem_index_ensure(bm, BM_VERT);
-
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- if (BMO_face_flag_test(bm, f, FACE_MARK)) {
-
- /* array for passing verts to angle_poly_v3 */
- float *face_angles = BLI_buffer_reinit_data(&face_angles_buf, float, f->len);
- /* array for receiving angles from angle_poly_v3 */
- float **verts = BLI_buffer_reinit_data(&verts_buf, float *, f->len);
-
- BM_ITER_ELEM_INDEX (l, &loopIter, f, BM_LOOPS_OF_FACE, i) {
- verts[i] = l->v->co;
- }
-
- angle_poly_v3(face_angles, (const float **)verts, f->len);
-
- i = 0;
- BM_ITER_ELEM (l, &loopIter, f, BM_LOOPS_OF_FACE) {
- v = l->v;
- index = BM_elem_index_get(v);
- vert_accum[index] += face_angles[i];
- vert_angles[index] += shell_v3v3_normalized_to_dist(v->no, f->no) * face_angles[i];
- i++;
- }
- }
- }
-
- BLI_buffer_free(&face_angles_buf);
- BLI_buffer_free(&verts_buf);
-
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- index = BM_elem_index_get(v);
- if (vert_accum[index]) { /* zero if unselected */
- madd_v3_v3fl(v->co, v->no, dist * (vert_angles[index] / vert_accum[index]));
- }
- }
-
- MEM_freeN(vert_angles);
+ BMFace *f;
+ BMVert *v;
+ BMLoop *l;
+ BMIter iter, loopIter;
+ float *vert_angles = MEM_callocN(sizeof(float) * bm->totvert * 2, "solidify"); /* 2 in 1 */
+ float *vert_accum = vert_angles + bm->totvert;
+ int i, index;
+
+ BLI_buffer_declare_static(float, face_angles_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
+ BLI_buffer_declare_static(float *, verts_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
+
+ BM_mesh_elem_index_ensure(bm, BM_VERT);
+
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if (BMO_face_flag_test(bm, f, FACE_MARK)) {
+
+ /* array for passing verts to angle_poly_v3 */
+ float *face_angles = BLI_buffer_reinit_data(&face_angles_buf, float, f->len);
+ /* array for receiving angles from angle_poly_v3 */
+ float **verts = BLI_buffer_reinit_data(&verts_buf, float *, f->len);
+
+ BM_ITER_ELEM_INDEX(l, &loopIter, f, BM_LOOPS_OF_FACE, i)
+ {
+ verts[i] = l->v->co;
+ }
+
+ angle_poly_v3(face_angles, (const float **)verts, f->len);
+
+ i = 0;
+ BM_ITER_ELEM (l, &loopIter, f, BM_LOOPS_OF_FACE) {
+ v = l->v;
+ index = BM_elem_index_get(v);
+ vert_accum[index] += face_angles[i];
+ vert_angles[index] += shell_v3v3_normalized_to_dist(v->no, f->no) * face_angles[i];
+ i++;
+ }
+ }
+ }
+
+ BLI_buffer_free(&face_angles_buf);
+ BLI_buffer_free(&verts_buf);
+
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ index = BM_elem_index_get(v);
+ if (vert_accum[index]) { /* zero if unselected */
+ madd_v3_v3fl(v->co, v->no, dist * (vert_angles[index] / vert_accum[index]));
+ }
+ }
+
+ MEM_freeN(vert_angles);
}
void bmo_solidify_face_region_exec(BMesh *bm, BMOperator *op)
{
- BMOperator extrudeop;
- BMOperator reverseop;
- float thickness;
-
- thickness = BMO_slot_float_get(op->slots_in, "thickness");
-
- /* Flip original faces (so the shell is extruded inward) */
- BMO_op_init(bm, &reverseop, op->flag, "reverse_faces");
- BMO_slot_bool_set(reverseop.slots_in, "flip_multires", true);
- BMO_slot_copy(op, slots_in, "geom",
- &reverseop, slots_in, "faces");
- BMO_op_exec(bm, &reverseop);
- BMO_op_finish(bm, &reverseop);
-
- /* Extrude the region */
- BMO_op_initf(bm, &extrudeop, op->flag, "extrude_face_region use_keep_orig=%b", true);
- BMO_slot_copy(op, slots_in, "geom",
- &extrudeop, slots_in, "geom");
- BMO_op_exec(bm, &extrudeop);
-
- /* Push the verts of the extruded faces inward to create thickness */
- BMO_slot_buffer_flag_enable(bm, extrudeop.slots_out, "geom.out", BM_FACE, FACE_MARK);
- calc_solidify_normals(bm);
- solidify_add_thickness(bm, thickness);
-
- BMO_slot_copy(&extrudeop, slots_out, "geom.out",
- op, slots_out, "geom.out");
-
- BMO_op_finish(bm, &extrudeop);
+ BMOperator extrudeop;
+ BMOperator reverseop;
+ float thickness;
+
+ thickness = BMO_slot_float_get(op->slots_in, "thickness");
+
+ /* Flip original faces (so the shell is extruded inward) */
+ BMO_op_init(bm, &reverseop, op->flag, "reverse_faces");
+ BMO_slot_bool_set(reverseop.slots_in, "flip_multires", true);
+ BMO_slot_copy(op, slots_in, "geom", &reverseop, slots_in, "faces");
+ BMO_op_exec(bm, &reverseop);
+ BMO_op_finish(bm, &reverseop);
+
+ /* Extrude the region */
+ BMO_op_initf(bm, &extrudeop, op->flag, "extrude_face_region use_keep_orig=%b", true);
+ BMO_slot_copy(op, slots_in, "geom", &extrudeop, slots_in, "geom");
+ BMO_op_exec(bm, &extrudeop);
+
+ /* Push the verts of the extruded faces inward to create thickness */
+ BMO_slot_buffer_flag_enable(bm, extrudeop.slots_out, "geom.out", BM_FACE, FACE_MARK);
+ calc_solidify_normals(bm);
+ solidify_add_thickness(bm, thickness);
+
+ BMO_slot_copy(&extrudeop, slots_out, "geom.out", op, slots_out, "geom.out");
+
+ BMO_op_finish(bm, &extrudeop);
}
diff --git a/source/blender/bmesh/operators/bmo_fill_attribute.c b/source/blender/bmesh/operators/bmo_fill_attribute.c
index b724f6202bd..1e226beffc7 100644
--- a/source/blender/bmesh/operators/bmo_fill_attribute.c
+++ b/source/blender/bmesh/operators/bmo_fill_attribute.c
@@ -32,15 +32,15 @@
*/
static bool bm_loop_is_all_radial_tag(BMLoop *l)
{
- BMLoop *l_iter;
- l_iter = l->radial_next;
- do {
- if (BM_elem_flag_test(l_iter->f, BM_ELEM_TAG) == 0) {
- return false;
- }
- } while ((l_iter = l_iter->radial_next) != l);
-
- return true;
+ BMLoop *l_iter;
+ l_iter = l->radial_next;
+ do {
+ if (BM_elem_flag_test(l_iter->f, BM_ELEM_TAG) == 0) {
+ return false;
+ }
+ } while ((l_iter = l_iter->radial_next) != l);
+
+ return true;
}
/**
@@ -48,122 +48,121 @@ static bool bm_loop_is_all_radial_tag(BMLoop *l)
*/
static bool bm_loop_is_face_untag(const BMLoop *l, void *UNUSED(user_data))
{
- return (BM_elem_flag_test(l->f, BM_ELEM_TAG) == 0);
+ return (BM_elem_flag_test(l->f, BM_ELEM_TAG) == 0);
}
/**
* Copy all attributes from adjacent untagged faces.
*/
-static void bm_face_copy_shared_all(
- BMesh *bm, BMLoop *l,
- const bool use_normals, const bool use_data)
+static void bm_face_copy_shared_all(BMesh *bm,
+ BMLoop *l,
+ const bool use_normals,
+ const bool use_data)
{
- BMLoop *l_other = l->radial_next;
- BMFace *f = l->f, *f_other;
- while (BM_elem_flag_test(l_other->f, BM_ELEM_TAG)) {
- l_other = l_other->radial_next;
- }
- f_other = l_other->f;
-
- if (use_data) {
- /* copy face-attrs */
- BM_elem_attrs_copy(bm, bm, f_other, f);
-
- /* copy loop-attrs */
- BM_face_copy_shared(bm, f, bm_loop_is_face_untag, NULL);
- }
-
- if (use_normals) {
- /* copy winding (flipping) */
- if (l->v == l_other->v) {
- BM_face_normal_flip(bm, f);
- }
- }
+ BMLoop *l_other = l->radial_next;
+ BMFace *f = l->f, *f_other;
+ while (BM_elem_flag_test(l_other->f, BM_ELEM_TAG)) {
+ l_other = l_other->radial_next;
+ }
+ f_other = l_other->f;
+
+ if (use_data) {
+ /* copy face-attrs */
+ BM_elem_attrs_copy(bm, bm, f_other, f);
+
+ /* copy loop-attrs */
+ BM_face_copy_shared(bm, f, bm_loop_is_face_untag, NULL);
+ }
+
+ if (use_normals) {
+ /* copy winding (flipping) */
+ if (l->v == l_other->v) {
+ BM_face_normal_flip(bm, f);
+ }
+ }
}
/**
* Flood fill attributes.
*/
-static uint bmesh_face_attribute_fill(
- BMesh *bm,
- const bool use_normals, const bool use_data)
+static uint bmesh_face_attribute_fill(BMesh *bm, const bool use_normals, const bool use_data)
{
- BLI_LINKSTACK_DECLARE(loop_queue_prev, BMLoop *);
- BLI_LINKSTACK_DECLARE(loop_queue_next, BMLoop *);
-
- BMFace *f;
- BMIter iter;
- BMLoop *l;
-
- uint face_tot = 0;
-
-
- BLI_LINKSTACK_INIT(loop_queue_prev);
- BLI_LINKSTACK_INIT(loop_queue_next);
-
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(f, BM_ELEM_TAG)) {
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if (bm_loop_is_all_radial_tag(l_iter) == false) {
- BLI_LINKSTACK_PUSH(loop_queue_prev, l_iter);
- }
- } while ((l_iter = l_iter->next) != l_first);
- }
- }
-
- while (BLI_LINKSTACK_SIZE(loop_queue_prev)) {
- while ((l = BLI_LINKSTACK_POP(loop_queue_prev))) {
- /* check we're still un-assigned */
- if (BM_elem_flag_test(l->f, BM_ELEM_TAG)) {
- BMLoop *l_iter;
-
- BM_elem_flag_disable(l->f, BM_ELEM_TAG);
-
- l_iter = l->next;
- do {
- BMLoop *l_radial_iter = l_iter->radial_next;
- if (l_radial_iter != l_iter) {
- do {
- if (BM_elem_flag_test(l_radial_iter->f, BM_ELEM_TAG)) {
- BLI_LINKSTACK_PUSH(loop_queue_next, l_radial_iter);
- }
- } while ((l_radial_iter = l_radial_iter->radial_next) != l_iter);
- }
- } while ((l_iter = l_iter->next) != l);
-
- /* do last because of face flipping */
- bm_face_copy_shared_all(bm, l,
- use_normals, use_data);
- face_tot += 1;
- }
- }
-
- BLI_LINKSTACK_SWAP(loop_queue_prev, loop_queue_next);
- }
-
- BLI_LINKSTACK_FREE(loop_queue_prev);
- BLI_LINKSTACK_FREE(loop_queue_next);
-
- return face_tot;
+ BLI_LINKSTACK_DECLARE(loop_queue_prev, BMLoop *);
+ BLI_LINKSTACK_DECLARE(loop_queue_next, BMLoop *);
+
+ BMFace *f;
+ BMIter iter;
+ BMLoop *l;
+
+ uint face_tot = 0;
+
+ BLI_LINKSTACK_INIT(loop_queue_prev);
+ BLI_LINKSTACK_INIT(loop_queue_next);
+
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_TAG)) {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (bm_loop_is_all_radial_tag(l_iter) == false) {
+ BLI_LINKSTACK_PUSH(loop_queue_prev, l_iter);
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ }
+
+ while (BLI_LINKSTACK_SIZE(loop_queue_prev)) {
+ while ((l = BLI_LINKSTACK_POP(loop_queue_prev))) {
+ /* check we're still un-assigned */
+ if (BM_elem_flag_test(l->f, BM_ELEM_TAG)) {
+ BMLoop *l_iter;
+
+ BM_elem_flag_disable(l->f, BM_ELEM_TAG);
+
+ l_iter = l->next;
+ do {
+ BMLoop *l_radial_iter = l_iter->radial_next;
+ if (l_radial_iter != l_iter) {
+ do {
+ if (BM_elem_flag_test(l_radial_iter->f, BM_ELEM_TAG)) {
+ BLI_LINKSTACK_PUSH(loop_queue_next, l_radial_iter);
+ }
+ } while ((l_radial_iter = l_radial_iter->radial_next) != l_iter);
+ }
+ } while ((l_iter = l_iter->next) != l);
+
+ /* do last because of face flipping */
+ bm_face_copy_shared_all(bm, l, use_normals, use_data);
+ face_tot += 1;
+ }
+ }
+
+ BLI_LINKSTACK_SWAP(loop_queue_prev, loop_queue_next);
+ }
+
+ BLI_LINKSTACK_FREE(loop_queue_prev);
+ BLI_LINKSTACK_FREE(loop_queue_next);
+
+ return face_tot;
}
-void bmo_face_attribute_fill_exec(BMesh *bm, BMOperator *op)
+void bmo_face_attribute_fill_exec(BMesh *bm, BMOperator *op)
{
- const bool use_normals = BMO_slot_bool_get(op->slots_in, "use_normals");
- const bool use_data = BMO_slot_bool_get(op->slots_in, "use_data");
+ const bool use_normals = BMO_slot_bool_get(op->slots_in, "use_normals");
+ const bool use_data = BMO_slot_bool_get(op->slots_in, "use_data");
- int face_tot;
+ int face_tot;
- BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false);
- BMO_slot_buffer_hflag_enable(bm, op->slots_in, "faces", BM_FACE, BM_ELEM_TAG, false); /* do inline */
+ BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false);
+ BMO_slot_buffer_hflag_enable(
+ bm, op->slots_in, "faces", BM_FACE, BM_ELEM_TAG, false); /* do inline */
- /* now we can copy adjacent data */
- face_tot = bmesh_face_attribute_fill(bm, use_normals, use_data);
+ /* now we can copy adjacent data */
+ face_tot = bmesh_face_attribute_fill(bm, use_normals, use_data);
- if (face_tot != BMO_slot_buffer_count(op->slots_in, "faces")) {
- /* any remaining tags will be skipped */
- BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces_fail.out", BM_FACE, BM_ELEM_TAG);
- }
+ if (face_tot != BMO_slot_buffer_count(op->slots_in, "faces")) {
+ /* any remaining tags will be skipped */
+ BMO_slot_buffer_from_enabled_hflag(
+ bm, op, op->slots_out, "faces_fail.out", BM_FACE, BM_ELEM_TAG);
+ }
}
diff --git a/source/blender/bmesh/operators/bmo_fill_edgeloop.c b/source/blender/bmesh/operators/bmo_fill_edgeloop.c
index e82072de90f..16f9922b21d 100644
--- a/source/blender/bmesh/operators/bmo_fill_edgeloop.c
+++ b/source/blender/bmesh/operators/bmo_fill_edgeloop.c
@@ -28,125 +28,125 @@
#include "intern/bmesh_operators_private.h" /* own include */
-#define VERT_USED 1
-#define EDGE_MARK 2
-#define ELE_OUT 4
+#define VERT_USED 1
+#define EDGE_MARK 2
+#define ELE_OUT 4
void bmo_edgeloop_fill_exec(BMesh *bm, BMOperator *op)
{
- /* first collect an array of unique from the edges */
- const int tote = BMO_slot_buffer_count(op->slots_in, "edges");
- const int totv = tote; /* these should be the same */
- BMVert **verts = MEM_mallocN(sizeof(*verts) * totv, __func__);
-
- BMVert *v;
- BMEdge *e;
- int i;
- bool ok = true;
-
- BMOIter oiter;
-
- const short mat_nr = BMO_slot_int_get(op->slots_in, "mat_nr");
- const bool use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth");
-
- /* 'VERT_USED' will be disabled, so enable and fill the array */
- i = 0;
- BMO_ITER (e, &oiter, op->slots_in, "edges", BM_EDGE) {
- BMIter viter;
- BMO_edge_flag_enable(bm, e, EDGE_MARK);
- BM_ITER_ELEM (v, &viter, e, BM_VERTS_OF_EDGE) {
- if (BMO_vert_flag_test(bm, v, VERT_USED) == false) {
- if (i == tote) {
- goto cleanup;
- }
-
- BMO_vert_flag_enable(bm, v, VERT_USED);
- verts[i++] = v;
- }
- }
- }
-
- /* we have a different number of verts to edges */
- if (i != tote) {
- goto cleanup;
- }
-
- /* loop over connected flagged edges and fill in faces, this is made slightly more
- * complicated because there may be multiple disconnected loops to fill. */
-
- /* sanity check - that each vertex has 2 edge users */
- for (i = 0; i < totv; i++) {
- v = verts[i];
- /* count how many flagged edges this vertex uses */
- if (BMO_iter_elem_count_flag(bm, BM_EDGES_OF_VERT, v, EDGE_MARK, true) != 2) {
- ok = false;
- break;
- }
- }
-
- if (ok) {
- /* note: in the case of multiple loops, this over-allocs (which is fine) */
- BMVert **f_verts = MEM_mallocN(sizeof(*verts) * totv, __func__);
- BMIter eiter;
-
- /* build array of connected verts and edges */
- BMEdge *e_prev = NULL;
- BMEdge *e_next = NULL;
- int totv_used = 0;
-
- while (totv_used < totv) {
- for (i = 0; i < totv; i++) {
- v = verts[i];
- if (BMO_vert_flag_test(bm, v, VERT_USED)) {
- break;
- }
- }
-
- /* this should never fail, as long as (totv_used < totv)
- * we should have marked verts available */
- BLI_assert(BMO_vert_flag_test(bm, v, VERT_USED));
-
- /* watch it, 'i' is used for final face length */
- i = 0;
- do {
- /* we know that there are 2 edges per vertex so no need to check */
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- if (BMO_edge_flag_test(bm, e, EDGE_MARK)) {
- if (e != e_prev) {
- e_next = e;
- break;
- }
- }
- }
-
- /* fill in the array */
- f_verts[i] = v;
- BMO_vert_flag_disable(bm, v, VERT_USED);
- totv_used++;
-
- /* step over the edges */
- v = BM_edge_other_vert(e_next, v);
- e_prev = e_next;
- i++;
- } while ((v != f_verts[0]));
-
- if (!BM_face_exists(f_verts, i)) {
- BMFace *f;
-
- /* don't use calc_edges option because we already have the edges */
- f = BM_face_create_ngon_verts(bm, f_verts, i, NULL, BM_CREATE_NOP, true, false);
- BMO_face_flag_enable(bm, f, ELE_OUT);
- f->mat_nr = mat_nr;
- if (use_smooth) {
- BM_elem_flag_enable(f, BM_ELEM_SMOOTH);
- }
- }
- }
- MEM_freeN(f_verts);
-
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, ELE_OUT);
- }
+ /* first collect an array of unique from the edges */
+ const int tote = BMO_slot_buffer_count(op->slots_in, "edges");
+ const int totv = tote; /* these should be the same */
+ BMVert **verts = MEM_mallocN(sizeof(*verts) * totv, __func__);
+
+ BMVert *v;
+ BMEdge *e;
+ int i;
+ bool ok = true;
+
+ BMOIter oiter;
+
+ const short mat_nr = BMO_slot_int_get(op->slots_in, "mat_nr");
+ const bool use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth");
+
+ /* 'VERT_USED' will be disabled, so enable and fill the array */
+ i = 0;
+ BMO_ITER (e, &oiter, op->slots_in, "edges", BM_EDGE) {
+ BMIter viter;
+ BMO_edge_flag_enable(bm, e, EDGE_MARK);
+ BM_ITER_ELEM (v, &viter, e, BM_VERTS_OF_EDGE) {
+ if (BMO_vert_flag_test(bm, v, VERT_USED) == false) {
+ if (i == tote) {
+ goto cleanup;
+ }
+
+ BMO_vert_flag_enable(bm, v, VERT_USED);
+ verts[i++] = v;
+ }
+ }
+ }
+
+ /* we have a different number of verts to edges */
+ if (i != tote) {
+ goto cleanup;
+ }
+
+ /* loop over connected flagged edges and fill in faces, this is made slightly more
+ * complicated because there may be multiple disconnected loops to fill. */
+
+ /* sanity check - that each vertex has 2 edge users */
+ for (i = 0; i < totv; i++) {
+ v = verts[i];
+ /* count how many flagged edges this vertex uses */
+ if (BMO_iter_elem_count_flag(bm, BM_EDGES_OF_VERT, v, EDGE_MARK, true) != 2) {
+ ok = false;
+ break;
+ }
+ }
+
+ if (ok) {
+ /* note: in the case of multiple loops, this over-allocs (which is fine) */
+ BMVert **f_verts = MEM_mallocN(sizeof(*verts) * totv, __func__);
+ BMIter eiter;
+
+ /* build array of connected verts and edges */
+ BMEdge *e_prev = NULL;
+ BMEdge *e_next = NULL;
+ int totv_used = 0;
+
+ while (totv_used < totv) {
+ for (i = 0; i < totv; i++) {
+ v = verts[i];
+ if (BMO_vert_flag_test(bm, v, VERT_USED)) {
+ break;
+ }
+ }
+
+ /* this should never fail, as long as (totv_used < totv)
+ * we should have marked verts available */
+ BLI_assert(BMO_vert_flag_test(bm, v, VERT_USED));
+
+ /* watch it, 'i' is used for final face length */
+ i = 0;
+ do {
+ /* we know that there are 2 edges per vertex so no need to check */
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (BMO_edge_flag_test(bm, e, EDGE_MARK)) {
+ if (e != e_prev) {
+ e_next = e;
+ break;
+ }
+ }
+ }
+
+ /* fill in the array */
+ f_verts[i] = v;
+ BMO_vert_flag_disable(bm, v, VERT_USED);
+ totv_used++;
+
+ /* step over the edges */
+ v = BM_edge_other_vert(e_next, v);
+ e_prev = e_next;
+ i++;
+ } while ((v != f_verts[0]));
+
+ if (!BM_face_exists(f_verts, i)) {
+ BMFace *f;
+
+ /* don't use calc_edges option because we already have the edges */
+ f = BM_face_create_ngon_verts(bm, f_verts, i, NULL, BM_CREATE_NOP, true, false);
+ BMO_face_flag_enable(bm, f, ELE_OUT);
+ f->mat_nr = mat_nr;
+ if (use_smooth) {
+ BM_elem_flag_enable(f, BM_ELEM_SMOOTH);
+ }
+ }
+ }
+ MEM_freeN(f_verts);
+
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, ELE_OUT);
+ }
cleanup:
- MEM_freeN(verts);
+ MEM_freeN(verts);
}
diff --git a/source/blender/bmesh/operators/bmo_fill_grid.c b/source/blender/bmesh/operators/bmo_fill_grid.c
index 09c174586f8..b71bd482e3b 100644
--- a/source/blender/bmesh/operators/bmo_fill_grid.c
+++ b/source/blender/bmesh/operators/bmo_fill_grid.c
@@ -33,8 +33,8 @@
#include "BLI_strict_flags.h"
-#define EDGE_MARK 4
-#define FACE_OUT 16
+#define EDGE_MARK 4
+#define FACE_OUT 16
#define BARYCENTRIC_INTERP
@@ -42,65 +42,59 @@
/**
* 2 edge vectors to normal.
*/
-static void quad_edges_to_normal(
- float no[3],
- const float co_a1[3], const float co_a2[3],
- const float co_b1[3], const float co_b2[3])
+static void quad_edges_to_normal(float no[3],
+ const float co_a1[3],
+ const float co_a2[3],
+ const float co_b1[3],
+ const float co_b2[3])
{
- float diff_a[3];
- float diff_b[3];
-
- sub_v3_v3v3(diff_a, co_a2, co_a1);
- sub_v3_v3v3(diff_b, co_b2, co_b1);
- normalize_v3(diff_a);
- normalize_v3(diff_b);
- add_v3_v3v3(no, diff_a, diff_b);
- normalize_v3(no);
+ float diff_a[3];
+ float diff_b[3];
+
+ sub_v3_v3v3(diff_a, co_a2, co_a1);
+ sub_v3_v3v3(diff_b, co_b2, co_b1);
+ normalize_v3(diff_a);
+ normalize_v3(diff_b);
+ add_v3_v3v3(no, diff_a, diff_b);
+ normalize_v3(no);
}
-static void quad_verts_to_barycentric_tri(
- float tri[3][3],
- const float co_a[3],
- const float co_b[3],
+static void quad_verts_to_barycentric_tri(float tri[3][3],
+ const float co_a[3],
+ const float co_b[3],
- const float co_a_next[3],
- const float co_b_next[3],
+ const float co_a_next[3],
+ const float co_b_next[3],
- const float co_a_prev[3],
- const float co_b_prev[3],
- const bool is_flip
- )
+ const float co_a_prev[3],
+ const float co_b_prev[3],
+ const bool is_flip)
{
- float no[3];
-
- copy_v3_v3(tri[0], co_a);
- copy_v3_v3(tri[1], co_b);
-
- quad_edges_to_normal(no,
- co_a, co_a_next,
- co_b, co_b_next);
-
- if (co_a_prev) {
- float no_t[3];
- quad_edges_to_normal(no_t,
- co_a_prev, co_a,
- co_b_prev, co_b);
- add_v3_v3(no, no_t);
- normalize_v3(no);
- }
-
- if (is_flip) {
- negate_v3(no);
- }
- mul_v3_fl(no, len_v3v3(tri[0], tri[1]));
-
- mid_v3_v3v3(tri[2], tri[0], tri[1]);
- add_v3_v3(tri[2], no);
+ float no[3];
+
+ copy_v3_v3(tri[0], co_a);
+ copy_v3_v3(tri[1], co_b);
+
+ quad_edges_to_normal(no, co_a, co_a_next, co_b, co_b_next);
+
+ if (co_a_prev) {
+ float no_t[3];
+ quad_edges_to_normal(no_t, co_a_prev, co_a, co_b_prev, co_b);
+ add_v3_v3(no, no_t);
+ normalize_v3(no);
+ }
+
+ if (is_flip) {
+ negate_v3(no);
+ }
+ mul_v3_fl(no, len_v3v3(tri[0], tri[1]));
+
+ mid_v3_v3v3(tri[2], tri[0], tri[1]);
+ add_v3_v3(tri[2], no);
}
#endif
-
/* -------------------------------------------------------------------- */
/* Handle Loop Pairs */
@@ -110,25 +104,23 @@ static void quad_verts_to_barycentric_tri(
/**
* Assign a loop pair from 2 verts (which _must_ share an edge)
*/
-static void bm_loop_pair_from_verts(
- BMVert *v_a, BMVert *v_b,
- BMLoop *l_pair[2])
+static void bm_loop_pair_from_verts(BMVert *v_a, BMVert *v_b, BMLoop *l_pair[2])
{
- BMEdge *e = BM_edge_exists(v_a, v_b);
- if (e->l) {
- if (e->l->v == v_a) {
- l_pair[0] = e->l;
- l_pair[1] = e->l->next;
- }
- else {
- l_pair[0] = e->l->next;
- l_pair[1] = e->l;
- }
- }
- else {
- l_pair[0] = NULL;
- l_pair[1] = NULL;
- }
+ BMEdge *e = BM_edge_exists(v_a, v_b);
+ if (e->l) {
+ if (e->l->v == v_a) {
+ l_pair[0] = e->l;
+ l_pair[1] = e->l->next;
+ }
+ else {
+ l_pair[0] = e->l->next;
+ l_pair[1] = e->l;
+ }
+ }
+ else {
+ l_pair[0] = NULL;
+ l_pair[1] = NULL;
+ }
}
/**
@@ -138,15 +130,15 @@ static void bm_loop_pair_from_verts(
*/
static void bm_loop_pair_test_copy(BMLoop *l_pair_a[2], BMLoop *l_pair_b[2])
{
- /* if the first one is set, we know the second is too */
- if (l_pair_a[0] && l_pair_b[0] == NULL) {
- l_pair_b[0] = l_pair_a[1];
- l_pair_b[1] = l_pair_a[0];
- }
- else if (l_pair_b[0] && l_pair_a[0] == NULL) {
- l_pair_a[0] = l_pair_b[1];
- l_pair_a[1] = l_pair_b[0];
- }
+ /* if the first one is set, we know the second is too */
+ if (l_pair_a[0] && l_pair_b[0] == NULL) {
+ l_pair_b[0] = l_pair_a[1];
+ l_pair_b[1] = l_pair_a[0];
+ }
+ else if (l_pair_b[0] && l_pair_a[0] == NULL) {
+ l_pair_a[0] = l_pair_b[1];
+ l_pair_a[1] = l_pair_b[0];
+ }
}
/**
@@ -154,576 +146,584 @@ static void bm_loop_pair_test_copy(BMLoop *l_pair_a[2], BMLoop *l_pair_b[2])
*
* \note These weights will be calculated multiple times per vertex.
*/
-static void bm_loop_interp_from_grid_boundary_4(BMesh *bm, BMLoop *l, BMLoop *l_bound[4], const float w[4])
+static void bm_loop_interp_from_grid_boundary_4(BMesh *bm,
+ BMLoop *l,
+ BMLoop *l_bound[4],
+ const float w[4])
{
- const void *l_cdata[4] = {
- l_bound[0]->head.data,
- l_bound[1]->head.data,
- l_bound[2]->head.data,
- l_bound[3]->head.data};
+ const void *l_cdata[4] = {
+ l_bound[0]->head.data, l_bound[1]->head.data, l_bound[2]->head.data, l_bound[3]->head.data};
- CustomData_bmesh_interp(&bm->ldata, l_cdata, w, NULL, 4, l->head.data);
+ CustomData_bmesh_interp(&bm->ldata, l_cdata, w, NULL, 4, l->head.data);
}
-static void bm_loop_interp_from_grid_boundary_2(BMesh *bm, BMLoop *l, BMLoop *l_bound[2], const float t)
+static void bm_loop_interp_from_grid_boundary_2(BMesh *bm,
+ BMLoop *l,
+ BMLoop *l_bound[2],
+ const float t)
{
- const void *l_cdata[2] = {
- l_bound[0]->head.data,
- l_bound[1]->head.data};
+ const void *l_cdata[2] = {l_bound[0]->head.data, l_bound[1]->head.data};
- const float w[2] = {1.0f - t, t};
+ const float w[2] = {1.0f - t, t};
- CustomData_bmesh_interp(&bm->ldata, l_cdata, w, NULL, 2, l->head.data);
+ CustomData_bmesh_interp(&bm->ldata, l_cdata, w, NULL, 2, l->head.data);
}
/** \} */
-
/**
* Avoids calling #barycentric_weights_v2_quad often by caching weights into an array.
*/
-static void barycentric_weights_v2_grid_cache(
- const uint xtot, const uint ytot,
- float (*weight_table)[4])
+static void barycentric_weights_v2_grid_cache(const uint xtot,
+ const uint ytot,
+ float (*weight_table)[4])
{
- float x_step = 1.0f / (float)(xtot - 1);
- float y_step = 1.0f / (float)(ytot - 1);
- uint i = 0;
- float xy_fl[2];
-
- uint x, y;
- for (y = 0; y < ytot; y++) {
- xy_fl[1] = y_step * (float)y;
- for (x = 0; x < xtot; x++) {
- xy_fl[0] = x_step * (float)x;
- {
- const float cos[4][2] = {
- {xy_fl[0], 0.0f},
- {0.0f, xy_fl[1]},
- {xy_fl[0], 1.0f},
- {1.0f, xy_fl[1]}};
- barycentric_weights_v2_quad(UNPACK4(cos), xy_fl, weight_table[i++]);
- }
- }
- }
+ float x_step = 1.0f / (float)(xtot - 1);
+ float y_step = 1.0f / (float)(ytot - 1);
+ uint i = 0;
+ float xy_fl[2];
+
+ uint x, y;
+ for (y = 0; y < ytot; y++) {
+ xy_fl[1] = y_step * (float)y;
+ for (x = 0; x < xtot; x++) {
+ xy_fl[0] = x_step * (float)x;
+ {
+ const float cos[4][2] = {
+ {xy_fl[0], 0.0f}, {0.0f, xy_fl[1]}, {xy_fl[0], 1.0f}, {1.0f, xy_fl[1]}};
+ barycentric_weights_v2_quad(UNPACK4(cos), xy_fl, weight_table[i++]);
+ }
+ }
+ }
}
-
/**
* This may be useful outside the bmesh operator.
*
* \param v_grid: 2d array of verts, all boundary verts must be set, we fill in the middle.
*/
-static void bm_grid_fill_array(
- BMesh *bm, BMVert **v_grid, const uint xtot, unsigned const int ytot,
- const short mat_nr, const bool use_smooth,
- const bool use_flip, const bool use_interp_simple)
+static void bm_grid_fill_array(BMesh *bm,
+ BMVert **v_grid,
+ const uint xtot,
+ unsigned const int ytot,
+ const short mat_nr,
+ const bool use_smooth,
+ const bool use_flip,
+ const bool use_interp_simple)
{
- const bool use_vert_interp = CustomData_has_interp(&bm->vdata);
- const bool use_loop_interp = CustomData_has_interp(&bm->ldata);
- uint x, y;
+ const bool use_vert_interp = CustomData_has_interp(&bm->vdata);
+ const bool use_loop_interp = CustomData_has_interp(&bm->ldata);
+ uint x, y;
- /* for use_loop_interp */
- BMLoop *((*larr_x_a)[2]), *((*larr_x_b)[2]), *((*larr_y_a)[2]), *((*larr_y_b)[2]);
+ /* for use_loop_interp */
+ BMLoop *((*larr_x_a)[2]), *((*larr_x_b)[2]), *((*larr_y_a)[2]), *((*larr_y_b)[2]);
- float (*weight_table)[4];
+ float(*weight_table)[4];
-#define XY(_x, _y) ((_x) + ((_y) * (xtot)))
+#define XY(_x, _y) ((_x) + ((_y) * (xtot)))
#ifdef BARYCENTRIC_INTERP
- float tri_a[3][3];
- float tri_b[3][3];
- float tri_t[3][3]; /* temp */
-
- quad_verts_to_barycentric_tri(
- tri_a,
- v_grid[XY(0, 0)]->co,
- v_grid[XY(xtot - 1, 0)]->co,
- v_grid[XY(0, 1)]->co,
- v_grid[XY(xtot - 1, 1)]->co,
- NULL, NULL,
- false);
-
- quad_verts_to_barycentric_tri(
- tri_b,
- v_grid[XY(0, (ytot - 1))]->co,
- v_grid[XY(xtot - 1, (ytot - 1))]->co,
- v_grid[XY(0, (ytot - 2))]->co,
- v_grid[XY(xtot - 1, (ytot - 2))]->co,
- NULL, NULL,
- true);
+ float tri_a[3][3];
+ float tri_b[3][3];
+ float tri_t[3][3]; /* temp */
+
+ quad_verts_to_barycentric_tri(tri_a,
+ v_grid[XY(0, 0)]->co,
+ v_grid[XY(xtot - 1, 0)]->co,
+ v_grid[XY(0, 1)]->co,
+ v_grid[XY(xtot - 1, 1)]->co,
+ NULL,
+ NULL,
+ false);
+
+ quad_verts_to_barycentric_tri(tri_b,
+ v_grid[XY(0, (ytot - 1))]->co,
+ v_grid[XY(xtot - 1, (ytot - 1))]->co,
+ v_grid[XY(0, (ytot - 2))]->co,
+ v_grid[XY(xtot - 1, (ytot - 2))]->co,
+ NULL,
+ NULL,
+ true);
#endif
- if (use_interp_simple || use_vert_interp || use_loop_interp) {
- weight_table = MEM_mallocN(sizeof(*weight_table) * (size_t)(xtot * ytot), __func__);
- barycentric_weights_v2_grid_cache(xtot, ytot, weight_table);
- }
- else {
- weight_table = NULL;
- }
-
-
- /* Store loops */
- if (use_loop_interp) {
- /* x2 because each edge connects 2 loops */
- larr_x_a = MEM_mallocN(sizeof(*larr_x_a) * (xtot - 1), __func__);
- larr_x_b = MEM_mallocN(sizeof(*larr_x_b) * (xtot - 1), __func__);
-
- larr_y_a = MEM_mallocN(sizeof(*larr_y_a) * (ytot - 1), __func__);
- larr_y_b = MEM_mallocN(sizeof(*larr_y_b) * (ytot - 1), __func__);
-
- /* fill in the loops */
- for (x = 0; x < xtot - 1; x++) {
- bm_loop_pair_from_verts(v_grid[XY(x, 0)], v_grid[XY(x + 1, 0)], larr_x_a[x]);
- bm_loop_pair_from_verts(v_grid[XY(x, ytot - 1)], v_grid[XY(x + 1, ytot - 1)], larr_x_b[x]);
- bm_loop_pair_test_copy(larr_x_a[x], larr_x_b[x]);
- }
-
- for (y = 0; y < ytot - 1; y++) {
- bm_loop_pair_from_verts(v_grid[XY(0, y)], v_grid[XY(0, y + 1)], larr_y_a[y]);
- bm_loop_pair_from_verts(v_grid[XY(xtot - 1, y)], v_grid[XY(xtot - 1, y + 1)], larr_y_b[y]);
- bm_loop_pair_test_copy(larr_y_a[y], larr_y_b[y]);
- }
- }
-
-
- /* Build Verts */
- for (y = 1; y < ytot - 1; y++) {
+ if (use_interp_simple || use_vert_interp || use_loop_interp) {
+ weight_table = MEM_mallocN(sizeof(*weight_table) * (size_t)(xtot * ytot), __func__);
+ barycentric_weights_v2_grid_cache(xtot, ytot, weight_table);
+ }
+ else {
+ weight_table = NULL;
+ }
+
+ /* Store loops */
+ if (use_loop_interp) {
+ /* x2 because each edge connects 2 loops */
+ larr_x_a = MEM_mallocN(sizeof(*larr_x_a) * (xtot - 1), __func__);
+ larr_x_b = MEM_mallocN(sizeof(*larr_x_b) * (xtot - 1), __func__);
+
+ larr_y_a = MEM_mallocN(sizeof(*larr_y_a) * (ytot - 1), __func__);
+ larr_y_b = MEM_mallocN(sizeof(*larr_y_b) * (ytot - 1), __func__);
+
+ /* fill in the loops */
+ for (x = 0; x < xtot - 1; x++) {
+ bm_loop_pair_from_verts(v_grid[XY(x, 0)], v_grid[XY(x + 1, 0)], larr_x_a[x]);
+ bm_loop_pair_from_verts(v_grid[XY(x, ytot - 1)], v_grid[XY(x + 1, ytot - 1)], larr_x_b[x]);
+ bm_loop_pair_test_copy(larr_x_a[x], larr_x_b[x]);
+ }
+
+ for (y = 0; y < ytot - 1; y++) {
+ bm_loop_pair_from_verts(v_grid[XY(0, y)], v_grid[XY(0, y + 1)], larr_y_a[y]);
+ bm_loop_pair_from_verts(v_grid[XY(xtot - 1, y)], v_grid[XY(xtot - 1, y + 1)], larr_y_b[y]);
+ bm_loop_pair_test_copy(larr_y_a[y], larr_y_b[y]);
+ }
+ }
+
+ /* Build Verts */
+ for (y = 1; y < ytot - 1; y++) {
#ifdef BARYCENTRIC_INTERP
- quad_verts_to_barycentric_tri(
- tri_t,
- v_grid[XY(0, y + 0)]->co,
- v_grid[XY(xtot - 1, y + 0)]->co,
- v_grid[XY(0, y + 1)]->co,
- v_grid[XY(xtot - 1, y + 1)]->co,
- v_grid[XY(0, y - 1)]->co,
- v_grid[XY(xtot - 1, y - 1)]->co,
- false);
+ quad_verts_to_barycentric_tri(tri_t,
+ v_grid[XY(0, y + 0)]->co,
+ v_grid[XY(xtot - 1, y + 0)]->co,
+ v_grid[XY(0, y + 1)]->co,
+ v_grid[XY(xtot - 1, y + 1)]->co,
+ v_grid[XY(0, y - 1)]->co,
+ v_grid[XY(xtot - 1, y - 1)]->co,
+ false);
#endif
- for (x = 1; x < xtot - 1; x++) {
- float co[3];
- BMVert *v;
- /* we may want to allow sparse filled arrays, but for now, ensure its empty */
- BLI_assert(v_grid[(y * xtot) + x] == NULL);
+ for (x = 1; x < xtot - 1; x++) {
+ float co[3];
+ BMVert *v;
+ /* we may want to allow sparse filled arrays, but for now, ensure its empty */
+ BLI_assert(v_grid[(y * xtot) + x] == NULL);
- /* place the vertex */
+ /* place the vertex */
#ifdef BARYCENTRIC_INTERP
- if (use_interp_simple == false) {
- float co_a[3], co_b[3];
-
- transform_point_by_tri_v3(
- co_a,
- v_grid[x]->co,
- tri_t[0], tri_t[1], tri_t[2],
- tri_a[0], tri_a[1], tri_a[2]);
- transform_point_by_tri_v3(
- co_b,
- v_grid[(xtot * ytot) + (x - xtot)]->co,
- tri_t[0], tri_t[1], tri_t[2],
- tri_b[0], tri_b[1], tri_b[2]);
-
- interp_v3_v3v3(co, co_a, co_b, (float)y / ((float)ytot - 1));
- }
- else
+ if (use_interp_simple == false) {
+ float co_a[3], co_b[3];
+
+ transform_point_by_tri_v3(
+ co_a, v_grid[x]->co, tri_t[0], tri_t[1], tri_t[2], tri_a[0], tri_a[1], tri_a[2]);
+ transform_point_by_tri_v3(co_b,
+ v_grid[(xtot * ytot) + (x - xtot)]->co,
+ tri_t[0],
+ tri_t[1],
+ tri_t[2],
+ tri_b[0],
+ tri_b[1],
+ tri_b[2]);
+
+ interp_v3_v3v3(co, co_a, co_b, (float)y / ((float)ytot - 1));
+ }
+ else
#endif
- {
- const float *w = weight_table[XY(x, y)];
-
- zero_v3(co);
- madd_v3_v3fl(co, v_grid[XY(x, 0)]->co, w[0]);
- madd_v3_v3fl(co, v_grid[XY(0, y)]->co, w[1]);
- madd_v3_v3fl(co, v_grid[XY(x, ytot - 1)]->co, w[2]);
- madd_v3_v3fl(co, v_grid[XY(xtot - 1, y)]->co, w[3]);
- }
-
- v = BM_vert_create(bm, co, NULL, BM_CREATE_NOP);
- v_grid[(y * xtot) + x] = v;
-
- /* interpolate only along one axis, this could be changed
- * but from user pov gives predictable results since these are selected loop */
- if (use_vert_interp) {
- const float *w = weight_table[XY(x, y)];
-
- const void *v_cdata[4] = {
- v_grid[XY(x, 0)]->head.data,
- v_grid[XY(0, y)]->head.data,
- v_grid[XY(x, ytot - 1)]->head.data,
- v_grid[XY(xtot - 1, y)]->head.data,
- };
-
- CustomData_bmesh_interp(&bm->vdata, v_cdata, w, NULL, 4, v->head.data);
- }
-
- }
- }
-
- /* Build Faces */
- for (x = 0; x < xtot - 1; x++) {
- for (y = 0; y < ytot - 1; y++) {
- BMFace *f;
-
- if (use_flip) {
- f = BM_face_create_quad_tri(
- bm,
- v_grid[XY(x, y + 0)], /* BL */
- v_grid[XY(x, y + 1)], /* TL */
- v_grid[XY(x + 1, y + 1)], /* TR */
- v_grid[XY(x + 1, y + 0)], /* BR */
- NULL,
- BM_CREATE_NOP);
- }
- else {
- f = BM_face_create_quad_tri(
- bm,
- v_grid[XY(x + 1, y + 0)], /* BR */
- v_grid[XY(x + 1, y + 1)], /* TR */
- v_grid[XY(x, y + 1)], /* TL */
- v_grid[XY(x, y + 0)], /* BL */
- NULL,
- BM_CREATE_NOP);
- }
-
-
- if (use_loop_interp && (larr_x_a[x][0] || larr_y_a[y][0])) {
- /* bottom/left/top/right */
- BMLoop *l_quad[4];
- BMLoop *l_bound[4];
- BMLoop *l_tmp;
- uint x_side, y_side, i;
- char interp_from;
-
-
- if (larr_x_a[x][0] && larr_y_a[y][0]) {
- interp_from = 'B'; /* B == both */
- l_tmp = larr_x_a[x][0];
- }
- else if (larr_x_a[x][0]) {
- interp_from = 'X';
- l_tmp = larr_x_a[x][0];
- }
- else {
- interp_from = 'Y';
- l_tmp = larr_y_a[y][0];
- }
-
- BM_elem_attrs_copy(bm, bm, l_tmp->f, f);
-
-
- BM_face_as_array_loop_quad(f, l_quad);
-
- l_tmp = BM_FACE_FIRST_LOOP(f);
-
- if (use_flip) {
- l_quad[0] = l_tmp; l_tmp = l_tmp->next;
- l_quad[1] = l_tmp; l_tmp = l_tmp->next;
- l_quad[3] = l_tmp; l_tmp = l_tmp->next;
- l_quad[2] = l_tmp;
- }
- else {
- l_quad[2] = l_tmp; l_tmp = l_tmp->next;
- l_quad[3] = l_tmp; l_tmp = l_tmp->next;
- l_quad[1] = l_tmp; l_tmp = l_tmp->next;
- l_quad[0] = l_tmp;
- }
-
- i = 0;
-
- for (x_side = 0; x_side < 2; x_side++) {
- for (y_side = 0; y_side < 2; y_side++) {
- if (interp_from == 'B') {
- const float *w = weight_table[XY(x + x_side, y + y_side)];
- l_bound[0] = larr_x_a[x][x_side]; /* B */
- l_bound[1] = larr_y_a[y][y_side]; /* L */
- l_bound[2] = larr_x_b[x][x_side]; /* T */
- l_bound[3] = larr_y_b[y][y_side]; /* R */
-
- bm_loop_interp_from_grid_boundary_4(bm, l_quad[i++], l_bound, w);
- }
- else if (interp_from == 'X') {
- const float t = (float)(y + y_side) / (float)(ytot - 1);
- l_bound[0] = larr_x_a[x][x_side]; /* B */
- l_bound[1] = larr_x_b[x][x_side]; /* T */
-
- bm_loop_interp_from_grid_boundary_2(bm, l_quad[i++], l_bound, t);
- }
- else if (interp_from == 'Y') {
- const float t = (float)(x + x_side) / (float)(xtot - 1);
- l_bound[0] = larr_y_a[y][y_side]; /* L */
- l_bound[1] = larr_y_b[y][y_side]; /* R */
-
- bm_loop_interp_from_grid_boundary_2(bm, l_quad[i++], l_bound, t);
- }
- else {
- BLI_assert(0);
- }
- }
- }
- }
- /* end interp */
-
-
- BMO_face_flag_enable(bm, f, FACE_OUT);
- f->mat_nr = mat_nr;
- if (use_smooth) {
- BM_elem_flag_enable(f, BM_ELEM_SMOOTH);
- }
- }
- }
-
- if (use_loop_interp) {
- MEM_freeN(larr_x_a);
- MEM_freeN(larr_y_a);
- MEM_freeN(larr_x_b);
- MEM_freeN(larr_y_b);
- }
-
- if (weight_table) {
- MEM_freeN(weight_table);
- }
+ {
+ const float *w = weight_table[XY(x, y)];
+
+ zero_v3(co);
+ madd_v3_v3fl(co, v_grid[XY(x, 0)]->co, w[0]);
+ madd_v3_v3fl(co, v_grid[XY(0, y)]->co, w[1]);
+ madd_v3_v3fl(co, v_grid[XY(x, ytot - 1)]->co, w[2]);
+ madd_v3_v3fl(co, v_grid[XY(xtot - 1, y)]->co, w[3]);
+ }
+
+ v = BM_vert_create(bm, co, NULL, BM_CREATE_NOP);
+ v_grid[(y * xtot) + x] = v;
+
+ /* interpolate only along one axis, this could be changed
+ * but from user pov gives predictable results since these are selected loop */
+ if (use_vert_interp) {
+ const float *w = weight_table[XY(x, y)];
+
+ const void *v_cdata[4] = {
+ v_grid[XY(x, 0)]->head.data,
+ v_grid[XY(0, y)]->head.data,
+ v_grid[XY(x, ytot - 1)]->head.data,
+ v_grid[XY(xtot - 1, y)]->head.data,
+ };
+
+ CustomData_bmesh_interp(&bm->vdata, v_cdata, w, NULL, 4, v->head.data);
+ }
+ }
+ }
+
+ /* Build Faces */
+ for (x = 0; x < xtot - 1; x++) {
+ for (y = 0; y < ytot - 1; y++) {
+ BMFace *f;
+
+ if (use_flip) {
+ f = BM_face_create_quad_tri(bm,
+ v_grid[XY(x, y + 0)], /* BL */
+ v_grid[XY(x, y + 1)], /* TL */
+ v_grid[XY(x + 1, y + 1)], /* TR */
+ v_grid[XY(x + 1, y + 0)], /* BR */
+ NULL,
+ BM_CREATE_NOP);
+ }
+ else {
+ f = BM_face_create_quad_tri(bm,
+ v_grid[XY(x + 1, y + 0)], /* BR */
+ v_grid[XY(x + 1, y + 1)], /* TR */
+ v_grid[XY(x, y + 1)], /* TL */
+ v_grid[XY(x, y + 0)], /* BL */
+ NULL,
+ BM_CREATE_NOP);
+ }
+
+ if (use_loop_interp && (larr_x_a[x][0] || larr_y_a[y][0])) {
+ /* bottom/left/top/right */
+ BMLoop *l_quad[4];
+ BMLoop *l_bound[4];
+ BMLoop *l_tmp;
+ uint x_side, y_side, i;
+ char interp_from;
+
+ if (larr_x_a[x][0] && larr_y_a[y][0]) {
+ interp_from = 'B'; /* B == both */
+ l_tmp = larr_x_a[x][0];
+ }
+ else if (larr_x_a[x][0]) {
+ interp_from = 'X';
+ l_tmp = larr_x_a[x][0];
+ }
+ else {
+ interp_from = 'Y';
+ l_tmp = larr_y_a[y][0];
+ }
+
+ BM_elem_attrs_copy(bm, bm, l_tmp->f, f);
+
+ BM_face_as_array_loop_quad(f, l_quad);
+
+ l_tmp = BM_FACE_FIRST_LOOP(f);
+
+ if (use_flip) {
+ l_quad[0] = l_tmp;
+ l_tmp = l_tmp->next;
+ l_quad[1] = l_tmp;
+ l_tmp = l_tmp->next;
+ l_quad[3] = l_tmp;
+ l_tmp = l_tmp->next;
+ l_quad[2] = l_tmp;
+ }
+ else {
+ l_quad[2] = l_tmp;
+ l_tmp = l_tmp->next;
+ l_quad[3] = l_tmp;
+ l_tmp = l_tmp->next;
+ l_quad[1] = l_tmp;
+ l_tmp = l_tmp->next;
+ l_quad[0] = l_tmp;
+ }
+
+ i = 0;
+
+ for (x_side = 0; x_side < 2; x_side++) {
+ for (y_side = 0; y_side < 2; y_side++) {
+ if (interp_from == 'B') {
+ const float *w = weight_table[XY(x + x_side, y + y_side)];
+ l_bound[0] = larr_x_a[x][x_side]; /* B */
+ l_bound[1] = larr_y_a[y][y_side]; /* L */
+ l_bound[2] = larr_x_b[x][x_side]; /* T */
+ l_bound[3] = larr_y_b[y][y_side]; /* R */
+
+ bm_loop_interp_from_grid_boundary_4(bm, l_quad[i++], l_bound, w);
+ }
+ else if (interp_from == 'X') {
+ const float t = (float)(y + y_side) / (float)(ytot - 1);
+ l_bound[0] = larr_x_a[x][x_side]; /* B */
+ l_bound[1] = larr_x_b[x][x_side]; /* T */
+
+ bm_loop_interp_from_grid_boundary_2(bm, l_quad[i++], l_bound, t);
+ }
+ else if (interp_from == 'Y') {
+ const float t = (float)(x + x_side) / (float)(xtot - 1);
+ l_bound[0] = larr_y_a[y][y_side]; /* L */
+ l_bound[1] = larr_y_b[y][y_side]; /* R */
+
+ bm_loop_interp_from_grid_boundary_2(bm, l_quad[i++], l_bound, t);
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ }
+ }
+ /* end interp */
+
+ BMO_face_flag_enable(bm, f, FACE_OUT);
+ f->mat_nr = mat_nr;
+ if (use_smooth) {
+ BM_elem_flag_enable(f, BM_ELEM_SMOOTH);
+ }
+ }
+ }
+
+ if (use_loop_interp) {
+ MEM_freeN(larr_x_a);
+ MEM_freeN(larr_y_a);
+ MEM_freeN(larr_x_b);
+ MEM_freeN(larr_y_b);
+ }
+
+ if (weight_table) {
+ MEM_freeN(weight_table);
+ }
#undef XY
}
-static void bm_grid_fill(
- BMesh *bm,
- struct BMEdgeLoopStore *estore_a, struct BMEdgeLoopStore *estore_b,
- struct BMEdgeLoopStore *estore_rail_a, struct BMEdgeLoopStore *estore_rail_b,
- const short mat_nr, const bool use_smooth, const bool use_interp_simple)
+static void bm_grid_fill(BMesh *bm,
+ struct BMEdgeLoopStore *estore_a,
+ struct BMEdgeLoopStore *estore_b,
+ struct BMEdgeLoopStore *estore_rail_a,
+ struct BMEdgeLoopStore *estore_rail_b,
+ const short mat_nr,
+ const bool use_smooth,
+ const bool use_interp_simple)
{
#define USE_FLIP_DETECT
- const uint xtot = (uint)BM_edgeloop_length_get(estore_a);
- const uint ytot = (uint)BM_edgeloop_length_get(estore_rail_a);
- //BMVert *v;
- uint i;
+ const uint xtot = (uint)BM_edgeloop_length_get(estore_a);
+ const uint ytot = (uint)BM_edgeloop_length_get(estore_rail_a);
+ //BMVert *v;
+ uint i;
#ifdef DEBUG
- uint x, y;
+ uint x, y;
#endif
- LinkData *el;
- bool use_flip = false;
-
- ListBase *lb_a = BM_edgeloop_verts_get(estore_a);
- ListBase *lb_b = BM_edgeloop_verts_get(estore_b);
-
- ListBase *lb_rail_a = BM_edgeloop_verts_get(estore_rail_a);
- ListBase *lb_rail_b = BM_edgeloop_verts_get(estore_rail_b);
-
- BMVert **v_grid = MEM_callocN(sizeof(BMVert *) * (size_t)(xtot * ytot), __func__);
- /**
- * <pre>
- * estore_b
- * +------------------+
- * ^ | |
- * end | | |
- * | | |
- * | |estore_rail_a |estore_rail_b
- * | | |
- * start | | |
- * |estore_a |
- * +------------------+
- * --->
- * start -> end
- * </pre>
- */
-
- BLI_assert(((LinkData *)lb_a->first)->data == ((LinkData *)lb_rail_a->first)->data); /* BL */
- BLI_assert(((LinkData *)lb_b->first)->data == ((LinkData *)lb_rail_a->last)->data); /* TL */
- BLI_assert(((LinkData *)lb_b->last)->data == ((LinkData *)lb_rail_b->last)->data); /* TR */
- BLI_assert(((LinkData *)lb_a->last)->data == ((LinkData *)lb_rail_b->first)->data); /* BR */
-
- for (el = lb_a->first, i = 0; el; el = el->next, i++) { v_grid[i] = el->data; }
- for (el = lb_b->first, i = 0; el; el = el->next, i++) { v_grid[(ytot * xtot) + (i - xtot)] = el->data; }
- for (el = lb_rail_a->first, i = 0; el; el = el->next, i++) { v_grid[xtot * i] = el->data; }
- for (el = lb_rail_b->first, i = 0; el; el = el->next, i++) { v_grid[(xtot * i) + (xtot - 1)] = el->data; }
+ LinkData *el;
+ bool use_flip = false;
+
+ ListBase *lb_a = BM_edgeloop_verts_get(estore_a);
+ ListBase *lb_b = BM_edgeloop_verts_get(estore_b);
+
+ ListBase *lb_rail_a = BM_edgeloop_verts_get(estore_rail_a);
+ ListBase *lb_rail_b = BM_edgeloop_verts_get(estore_rail_b);
+
+ BMVert **v_grid = MEM_callocN(sizeof(BMVert *) * (size_t)(xtot * ytot), __func__);
+ /**
+ * <pre>
+ * estore_b
+ * +------------------+
+ * ^ | |
+ * end | | |
+ * | | |
+ * | |estore_rail_a |estore_rail_b
+ * | | |
+ * start | | |
+ * |estore_a |
+ * +------------------+
+ * --->
+ * start -> end
+ * </pre>
+ */
+
+ BLI_assert(((LinkData *)lb_a->first)->data == ((LinkData *)lb_rail_a->first)->data); /* BL */
+ BLI_assert(((LinkData *)lb_b->first)->data == ((LinkData *)lb_rail_a->last)->data); /* TL */
+ BLI_assert(((LinkData *)lb_b->last)->data == ((LinkData *)lb_rail_b->last)->data); /* TR */
+ BLI_assert(((LinkData *)lb_a->last)->data == ((LinkData *)lb_rail_b->first)->data); /* BR */
+
+ for (el = lb_a->first, i = 0; el; el = el->next, i++) {
+ v_grid[i] = el->data;
+ }
+ for (el = lb_b->first, i = 0; el; el = el->next, i++) {
+ v_grid[(ytot * xtot) + (i - xtot)] = el->data;
+ }
+ for (el = lb_rail_a->first, i = 0; el; el = el->next, i++) {
+ v_grid[xtot * i] = el->data;
+ }
+ for (el = lb_rail_b->first, i = 0; el; el = el->next, i++) {
+ v_grid[(xtot * i) + (xtot - 1)] = el->data;
+ }
#ifdef DEBUG
- for (x = 1; x < xtot - 1; x++) { for (y = 1; y < ytot - 1; y++) { BLI_assert(v_grid[(y * xtot) + x] == NULL); }}
+ for (x = 1; x < xtot - 1; x++) {
+ for (y = 1; y < ytot - 1; y++) {
+ BLI_assert(v_grid[(y * xtot) + x] == NULL);
+ }
+ }
#endif
#ifdef USE_FLIP_DETECT
- {
- ListBase *lb_iter[4] = {lb_a, lb_b, lb_rail_a, lb_rail_b};
- const int lb_iter_dir[4] = {-1, 1, 1, -1};
- int winding_votes = 0;
-
- for (i = 0; i < 4; i++) {
- LinkData *el_next;
- for (el = lb_iter[i]->first; el && (el_next = el->next); el = el->next) {
- BMEdge *e = BM_edge_exists(el->data, el_next->data);
- if (BM_edge_is_boundary(e)) {
- winding_votes += (e->l->v == el->data) ? lb_iter_dir[i] : -lb_iter_dir[i];
- }
- }
- }
- use_flip = (winding_votes < 0);
- }
+ {
+ ListBase *lb_iter[4] = {lb_a, lb_b, lb_rail_a, lb_rail_b};
+ const int lb_iter_dir[4] = {-1, 1, 1, -1};
+ int winding_votes = 0;
+
+ for (i = 0; i < 4; i++) {
+ LinkData *el_next;
+ for (el = lb_iter[i]->first; el && (el_next = el->next); el = el->next) {
+ BMEdge *e = BM_edge_exists(el->data, el_next->data);
+ if (BM_edge_is_boundary(e)) {
+ winding_votes += (e->l->v == el->data) ? lb_iter_dir[i] : -lb_iter_dir[i];
+ }
+ }
+ }
+ use_flip = (winding_votes < 0);
+ }
#endif
-
- bm_grid_fill_array(bm, v_grid, xtot, ytot, mat_nr, use_smooth, use_flip, use_interp_simple);
- MEM_freeN(v_grid);
+ bm_grid_fill_array(bm, v_grid, xtot, ytot, mat_nr, use_smooth, use_flip, use_interp_simple);
+ MEM_freeN(v_grid);
#undef USE_FLIP_DETECT
}
static void bm_edgeloop_flag_set(struct BMEdgeLoopStore *estore, char hflag, bool set)
{
- /* only handle closed loops in this case */
- LinkData *link = BM_edgeloop_verts_get(estore)->first;
- link = link->next;
- while (link) {
- BMEdge *e = BM_edge_exists(link->data, link->prev->data);
- if (e) {
- BM_elem_flag_set(e, hflag, set);
- }
- link = link->next;
- }
+ /* only handle closed loops in this case */
+ LinkData *link = BM_edgeloop_verts_get(estore)->first;
+ link = link->next;
+ while (link) {
+ BMEdge *e = BM_edge_exists(link->data, link->prev->data);
+ if (e) {
+ BM_elem_flag_set(e, hflag, set);
+ }
+ link = link->next;
+ }
}
static bool bm_edge_test_cb(BMEdge *e, void *bm_v)
{
- return BMO_edge_flag_test_bool((BMesh *)bm_v, e, EDGE_MARK);
+ return BMO_edge_flag_test_bool((BMesh *)bm_v, e, EDGE_MARK);
}
static bool bm_edge_test_rail_cb(BMEdge *e, void *UNUSED(bm_v))
{
- /* normally operators dont check for hidden state
- * but alternative would be to pass slot of rail edges */
- if (BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
- return false;
- }
- return BM_edge_is_wire(e) || BM_edge_is_boundary(e);
+ /* normally operators dont check for hidden state
+ * but alternative would be to pass slot of rail edges */
+ if (BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
+ return false;
+ }
+ return BM_edge_is_wire(e) || BM_edge_is_boundary(e);
}
void bmo_grid_fill_exec(BMesh *bm, BMOperator *op)
{
- ListBase eloops = {NULL, NULL};
- ListBase eloops_rail = {NULL, NULL};
- struct BMEdgeLoopStore *estore_a, *estore_b;
- struct BMEdgeLoopStore *estore_rail_a, *estore_rail_b;
- BMVert *v_a_first, *v_a_last;
- BMVert *v_b_first, *v_b_last;
- const short mat_nr = (short)BMO_slot_int_get(op->slots_in, "mat_nr");
- const bool use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth");
- const bool use_interp_simple = BMO_slot_bool_get(op->slots_in, "use_interp_simple");
- GSet *split_edges = NULL;
-
- int count;
- bool changed = false;
- BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK);
-
- count = BM_mesh_edgeloops_find(bm, &eloops, bm_edge_test_cb, (void *)bm);
-
- if (count != 2) {
- BMO_error_raise(bm, op, BMERR_INVALID_SELECTION,
- "Select two edge loops");
- goto cleanup;
- }
-
- estore_a = eloops.first;
- estore_b = eloops.last;
-
- v_a_first = ((LinkData *)BM_edgeloop_verts_get(estore_a)->first)->data;
- v_a_last = ((LinkData *)BM_edgeloop_verts_get(estore_a)->last)->data;
- v_b_first = ((LinkData *)BM_edgeloop_verts_get(estore_b)->first)->data;
- v_b_last = ((LinkData *)BM_edgeloop_verts_get(estore_b)->last)->data;
-
- if (BM_edgeloop_is_closed(estore_a) || BM_edgeloop_is_closed(estore_b)) {
- BMO_error_raise(bm, op, BMERR_INVALID_SELECTION,
- "Closed loops unsupported");
- goto cleanup;
- }
-
- /* ok. all error checking done, now we can find the rail edges */
-
-
- /* cheat here, temp hide all edges so they won't be included in rails
- * this puts the mesh in an invalid state for a short time. */
- bm_edgeloop_flag_set(estore_a, BM_ELEM_HIDDEN, true);
- bm_edgeloop_flag_set(estore_b, BM_ELEM_HIDDEN, true);
-
- if ((BM_mesh_edgeloops_find_path(bm, &eloops_rail, bm_edge_test_rail_cb, bm, v_a_first, v_b_first)) &&
- (BM_mesh_edgeloops_find_path(bm, &eloops_rail, bm_edge_test_rail_cb, bm, v_a_last, v_b_last)))
- {
- estore_rail_a = eloops_rail.first;
- estore_rail_b = eloops_rail.last;
- }
- else {
- BM_mesh_edgeloops_free(&eloops_rail);
-
- if ((BM_mesh_edgeloops_find_path(bm, &eloops_rail, bm_edge_test_rail_cb, bm, v_a_first, v_b_last)) &&
- (BM_mesh_edgeloops_find_path(bm, &eloops_rail, bm_edge_test_rail_cb, bm, v_a_last, v_b_first)))
- {
- estore_rail_a = eloops_rail.first;
- estore_rail_b = eloops_rail.last;
- BM_edgeloop_flip(bm, estore_b);
- }
- else {
- BM_mesh_edgeloops_free(&eloops_rail);
- }
- }
-
- bm_edgeloop_flag_set(estore_a, BM_ELEM_HIDDEN, false);
- bm_edgeloop_flag_set(estore_b, BM_ELEM_HIDDEN, false);
-
-
- if (BLI_listbase_is_empty(&eloops_rail)) {
- BMO_error_raise(bm, op, BMERR_INVALID_SELECTION,
- "Loops are not connected by wire/boundary edges");
- goto cleanup;
- }
-
- BLI_assert(estore_a != estore_b);
- BLI_assert(v_a_last != v_b_last);
-
- if (BM_edgeloop_overlap_check(estore_rail_a, estore_rail_b)) {
- BMO_error_raise(bm, op, BMERR_INVALID_SELECTION,
- "Connecting edge loops overlap");
- goto cleanup;
- }
-
- /* add vertices if needed */
- {
- struct BMEdgeLoopStore *estore_pairs[2][2] = {{estore_a, estore_b}, {estore_rail_a, estore_rail_b}};
- int i;
-
- for (i = 0; i < 2; i++) {
- const int len_a = BM_edgeloop_length_get(estore_pairs[i][0]);
- const int len_b = BM_edgeloop_length_get(estore_pairs[i][1]);
- if (len_a != len_b) {
- if (split_edges == NULL) {
- split_edges = BLI_gset_ptr_new(__func__);
- }
-
- if (len_a < len_b) {
- BM_edgeloop_expand(bm, estore_pairs[i][0], len_b, true, split_edges);
- }
- else {
- BM_edgeloop_expand(bm, estore_pairs[i][1], len_a, true, split_edges);
- }
- }
- }
- }
-
- /* finally we have all edge loops needed */
- bm_grid_fill(bm, estore_a, estore_b, estore_rail_a, estore_rail_b,
- mat_nr, use_smooth, use_interp_simple);
-
- changed = true;
-
- if (split_edges) {
- GSetIterator gs_iter;
- GSET_ITER (gs_iter, split_edges) {
- BMEdge *e = BLI_gsetIterator_getKey(&gs_iter);
- BM_edge_collapse(bm, e, e->v2, true, true);
- }
- BLI_gset_free(split_edges, NULL);
- }
+ ListBase eloops = {NULL, NULL};
+ ListBase eloops_rail = {NULL, NULL};
+ struct BMEdgeLoopStore *estore_a, *estore_b;
+ struct BMEdgeLoopStore *estore_rail_a, *estore_rail_b;
+ BMVert *v_a_first, *v_a_last;
+ BMVert *v_b_first, *v_b_last;
+ const short mat_nr = (short)BMO_slot_int_get(op->slots_in, "mat_nr");
+ const bool use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth");
+ const bool use_interp_simple = BMO_slot_bool_get(op->slots_in, "use_interp_simple");
+ GSet *split_edges = NULL;
+
+ int count;
+ bool changed = false;
+ BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK);
+
+ count = BM_mesh_edgeloops_find(bm, &eloops, bm_edge_test_cb, (void *)bm);
+
+ if (count != 2) {
+ BMO_error_raise(bm, op, BMERR_INVALID_SELECTION, "Select two edge loops");
+ goto cleanup;
+ }
+
+ estore_a = eloops.first;
+ estore_b = eloops.last;
+
+ v_a_first = ((LinkData *)BM_edgeloop_verts_get(estore_a)->first)->data;
+ v_a_last = ((LinkData *)BM_edgeloop_verts_get(estore_a)->last)->data;
+ v_b_first = ((LinkData *)BM_edgeloop_verts_get(estore_b)->first)->data;
+ v_b_last = ((LinkData *)BM_edgeloop_verts_get(estore_b)->last)->data;
+
+ if (BM_edgeloop_is_closed(estore_a) || BM_edgeloop_is_closed(estore_b)) {
+ BMO_error_raise(bm, op, BMERR_INVALID_SELECTION, "Closed loops unsupported");
+ goto cleanup;
+ }
+
+ /* ok. all error checking done, now we can find the rail edges */
+
+ /* cheat here, temp hide all edges so they won't be included in rails
+ * this puts the mesh in an invalid state for a short time. */
+ bm_edgeloop_flag_set(estore_a, BM_ELEM_HIDDEN, true);
+ bm_edgeloop_flag_set(estore_b, BM_ELEM_HIDDEN, true);
+
+ if ((BM_mesh_edgeloops_find_path(
+ bm, &eloops_rail, bm_edge_test_rail_cb, bm, v_a_first, v_b_first)) &&
+ (BM_mesh_edgeloops_find_path(
+ bm, &eloops_rail, bm_edge_test_rail_cb, bm, v_a_last, v_b_last))) {
+ estore_rail_a = eloops_rail.first;
+ estore_rail_b = eloops_rail.last;
+ }
+ else {
+ BM_mesh_edgeloops_free(&eloops_rail);
+
+ if ((BM_mesh_edgeloops_find_path(
+ bm, &eloops_rail, bm_edge_test_rail_cb, bm, v_a_first, v_b_last)) &&
+ (BM_mesh_edgeloops_find_path(
+ bm, &eloops_rail, bm_edge_test_rail_cb, bm, v_a_last, v_b_first))) {
+ estore_rail_a = eloops_rail.first;
+ estore_rail_b = eloops_rail.last;
+ BM_edgeloop_flip(bm, estore_b);
+ }
+ else {
+ BM_mesh_edgeloops_free(&eloops_rail);
+ }
+ }
+
+ bm_edgeloop_flag_set(estore_a, BM_ELEM_HIDDEN, false);
+ bm_edgeloop_flag_set(estore_b, BM_ELEM_HIDDEN, false);
+
+ if (BLI_listbase_is_empty(&eloops_rail)) {
+ BMO_error_raise(
+ bm, op, BMERR_INVALID_SELECTION, "Loops are not connected by wire/boundary edges");
+ goto cleanup;
+ }
+
+ BLI_assert(estore_a != estore_b);
+ BLI_assert(v_a_last != v_b_last);
+
+ if (BM_edgeloop_overlap_check(estore_rail_a, estore_rail_b)) {
+ BMO_error_raise(bm, op, BMERR_INVALID_SELECTION, "Connecting edge loops overlap");
+ goto cleanup;
+ }
+
+ /* add vertices if needed */
+ {
+ struct BMEdgeLoopStore *estore_pairs[2][2] = {{estore_a, estore_b},
+ {estore_rail_a, estore_rail_b}};
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ const int len_a = BM_edgeloop_length_get(estore_pairs[i][0]);
+ const int len_b = BM_edgeloop_length_get(estore_pairs[i][1]);
+ if (len_a != len_b) {
+ if (split_edges == NULL) {
+ split_edges = BLI_gset_ptr_new(__func__);
+ }
+
+ if (len_a < len_b) {
+ BM_edgeloop_expand(bm, estore_pairs[i][0], len_b, true, split_edges);
+ }
+ else {
+ BM_edgeloop_expand(bm, estore_pairs[i][1], len_a, true, split_edges);
+ }
+ }
+ }
+ }
+
+ /* finally we have all edge loops needed */
+ bm_grid_fill(
+ bm, estore_a, estore_b, estore_rail_a, estore_rail_b, mat_nr, use_smooth, use_interp_simple);
+
+ changed = true;
+
+ if (split_edges) {
+ GSetIterator gs_iter;
+ GSET_ITER (gs_iter, split_edges) {
+ BMEdge *e = BLI_gsetIterator_getKey(&gs_iter);
+ BM_edge_collapse(bm, e, e->v2, true, true);
+ }
+ BLI_gset_free(split_edges, NULL);
+ }
cleanup:
- BM_mesh_edgeloops_free(&eloops);
- BM_mesh_edgeloops_free(&eloops_rail);
+ BM_mesh_edgeloops_free(&eloops);
+ BM_mesh_edgeloops_free(&eloops_rail);
- if (changed) {
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_OUT);
- }
+ if (changed) {
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_OUT);
+ }
}
diff --git a/source/blender/bmesh/operators/bmo_fill_holes.c b/source/blender/bmesh/operators/bmo_fill_holes.c
index bf3c4cb1fc7..5801db582e1 100644
--- a/source/blender/bmesh/operators/bmo_fill_holes.c
+++ b/source/blender/bmesh/operators/bmo_fill_holes.c
@@ -29,49 +29,52 @@
void bmo_holes_fill_exec(BMesh *bm, BMOperator *op)
{
- BMOperator op_attr;
- const uint sides = BMO_slot_int_get(op->slots_in, "sides");
-
-
- BM_mesh_elem_hflag_disable_all(bm, BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
- BMO_slot_buffer_hflag_enable(bm, op->slots_in, "edges", BM_EDGE, BM_ELEM_TAG, false);
-
- BM_mesh_edgenet(bm, true, true); // TODO, sides
-
-
- /* bad - remove faces after as a workaround */
- if (sides != 0) {
- BMOIter siter;
- BMFace *f;
-
- BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG);
- BMO_ITER (f, &siter, op->slots_out, "faces.out", BM_FACE) {
- if (f->len > sides) {
- BM_face_kill(bm, f);
- }
- }
- }
-
- BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG);
-
- /* --- Attribute Fill --- */
- /* may as well since we have the faces already in a buffer */
- BMO_op_initf(bm, &op_attr, op->flag,
- "face_attribute_fill faces=%S use_normals=%b use_data=%b",
- op, "faces.out", true, true);
-
- BMO_op_exec(bm, &op_attr);
-
- /* check if some faces couldn't be touched */
- if (BMO_slot_buffer_count(op_attr.slots_out, "faces_fail.out")) {
- BMOIter siter;
- BMFace *f;
-
- BMO_ITER (f, &siter, op_attr.slots_out, "faces_fail.out", BM_FACE) {
- BM_face_normal_update(f); /* normals are zero'd */
- }
-
- BMO_op_callf(bm, op->flag, "recalc_face_normals faces=%S", &op_attr, "faces_fail.out");
- }
- BMO_op_finish(bm, &op_attr);
+ BMOperator op_attr;
+ const uint sides = BMO_slot_int_get(op->slots_in, "sides");
+
+ BM_mesh_elem_hflag_disable_all(bm, BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
+ BMO_slot_buffer_hflag_enable(bm, op->slots_in, "edges", BM_EDGE, BM_ELEM_TAG, false);
+
+ BM_mesh_edgenet(bm, true, true); // TODO, sides
+
+ /* bad - remove faces after as a workaround */
+ if (sides != 0) {
+ BMOIter siter;
+ BMFace *f;
+
+ BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG);
+ BMO_ITER (f, &siter, op->slots_out, "faces.out", BM_FACE) {
+ if (f->len > sides) {
+ BM_face_kill(bm, f);
+ }
+ }
+ }
+
+ BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG);
+
+ /* --- Attribute Fill --- */
+ /* may as well since we have the faces already in a buffer */
+ BMO_op_initf(bm,
+ &op_attr,
+ op->flag,
+ "face_attribute_fill faces=%S use_normals=%b use_data=%b",
+ op,
+ "faces.out",
+ true,
+ true);
+
+ BMO_op_exec(bm, &op_attr);
+
+ /* check if some faces couldn't be touched */
+ if (BMO_slot_buffer_count(op_attr.slots_out, "faces_fail.out")) {
+ BMOIter siter;
+ BMFace *f;
+
+ BMO_ITER (f, &siter, op_attr.slots_out, "faces_fail.out", BM_FACE) {
+ BM_face_normal_update(f); /* normals are zero'd */
+ }
+
+ BMO_op_callf(bm, op->flag, "recalc_face_normals faces=%S", &op_attr, "faces_fail.out");
+ }
+ BMO_op_finish(bm, &op_attr);
}
diff --git a/source/blender/bmesh/operators/bmo_hull.c b/source/blender/bmesh/operators/bmo_hull.c
index 664c4b3f615..46b31ce40d3 100644
--- a/source/blender/bmesh/operators/bmo_hull.c
+++ b/source/blender/bmesh/operators/bmo_hull.c
@@ -22,629 +22,597 @@
#ifdef WITH_BULLET
-#include "MEM_guardedalloc.h"
+# include "MEM_guardedalloc.h"
-#include "BLI_array.h"
-#include "BLI_listbase.h"
-#include "BLI_math.h"
+# include "BLI_array.h"
+# include "BLI_listbase.h"
+# include "BLI_math.h"
-#include "Bullet-C-Api.h"
+# include "Bullet-C-Api.h"
/* XXX: using 128 for totelem and pchunk of mempool, no idea what good
* values would be though */
-#include "bmesh.h"
+# include "bmesh.h"
-#include "intern/bmesh_operators_private.h" /* own include */
+# include "intern/bmesh_operators_private.h" /* own include */
/* Internal operator flags */
typedef enum {
- HULL_FLAG_INPUT = (1 << 0),
+ HULL_FLAG_INPUT = (1 << 0),
- HULL_FLAG_INTERIOR_ELE = (1 << 1),
- HULL_FLAG_OUTPUT_GEOM = (1 << 2),
+ HULL_FLAG_INTERIOR_ELE = (1 << 1),
+ HULL_FLAG_OUTPUT_GEOM = (1 << 2),
- HULL_FLAG_DEL = (1 << 3),
- HULL_FLAG_HOLE = (1 << 4),
+ HULL_FLAG_DEL = (1 << 3),
+ HULL_FLAG_HOLE = (1 << 4),
} HullFlags;
/* Store hull triangles separate from BMesh faces until the end; this
* way we don't have to worry about cleaning up extraneous edges or
* incorrectly deleting existing geometry. */
typedef struct HullTriangle {
- BMVert *v[3];
- float no[3];
- int skip;
+ BMVert *v[3];
+ float no[3];
+ int skip;
} HullTriangle;
-
-
/*************************** Hull Triangles ***************************/
static void hull_add_triangle(
- BMesh *bm, GSet *hull_triangles, BLI_mempool *pool,
- BMVert *v1, BMVert *v2, BMVert *v3)
+ BMesh *bm, GSet *hull_triangles, BLI_mempool *pool, BMVert *v1, BMVert *v2, BMVert *v3)
{
- HullTriangle *t;
- int i;
+ HullTriangle *t;
+ int i;
- t = BLI_mempool_calloc(pool);
- t->v[0] = v1;
- t->v[1] = v2;
- t->v[2] = v3;
+ t = BLI_mempool_calloc(pool);
+ t->v[0] = v1;
+ t->v[1] = v2;
+ t->v[2] = v3;
- /* Mark triangles vertices as not interior */
- for (i = 0; i < 3; i++) {
- BMO_vert_flag_disable(bm, t->v[i], HULL_FLAG_INTERIOR_ELE);
- }
+ /* Mark triangles vertices as not interior */
+ for (i = 0; i < 3; i++) {
+ BMO_vert_flag_disable(bm, t->v[i], HULL_FLAG_INTERIOR_ELE);
+ }
- BLI_gset_insert(hull_triangles, t);
- normal_tri_v3(t->no, v1->co, v2->co, v3->co);
+ BLI_gset_insert(hull_triangles, t);
+ normal_tri_v3(t->no, v1->co, v2->co, v3->co);
}
static BMFace *hull_find_example_face(BMesh *bm, BMEdge *e)
{
- BMIter iter;
- BMFace *f;
-
- BM_ITER_ELEM (f, &iter, e, BM_FACES_OF_EDGE) {
- if (BMO_face_flag_test(bm, f, HULL_FLAG_INPUT) ||
- BMO_face_flag_test(bm, f, HULL_FLAG_OUTPUT_GEOM) == false)
- {
- return f;
- }
- }
-
- return NULL;
+ BMIter iter;
+ BMFace *f;
+
+ BM_ITER_ELEM (f, &iter, e, BM_FACES_OF_EDGE) {
+ if (BMO_face_flag_test(bm, f, HULL_FLAG_INPUT) ||
+ BMO_face_flag_test(bm, f, HULL_FLAG_OUTPUT_GEOM) == false) {
+ return f;
+ }
+ }
+
+ return NULL;
}
static void hull_output_triangles(BMesh *bm, GSet *hull_triangles)
{
- GSetIterator iter;
-
- GSET_ITER (iter, hull_triangles) {
- HullTriangle *t = BLI_gsetIterator_getKey(&iter);
- int i;
-
- if (!t->skip) {
- BMEdge *edges[3] = {
- BM_edge_create(bm, t->v[0], t->v[1], NULL, BM_CREATE_NO_DOUBLE),
- BM_edge_create(bm, t->v[1], t->v[2], NULL, BM_CREATE_NO_DOUBLE),
- BM_edge_create(bm, t->v[2], t->v[0], NULL, BM_CREATE_NO_DOUBLE)
- };
- BMFace *f, *example = NULL;
-
- f = BM_face_exists(t->v, 3);
- if (f != NULL) {
- /* If the operator is run with "use_existing_faces"
- * disabled, but an output face in the hull is the
- * same as a face in the existing mesh, it should not
- * be marked as unused or interior. */
- BMO_face_flag_enable(bm, f, HULL_FLAG_OUTPUT_GEOM);
- BMO_face_flag_disable(bm, f, HULL_FLAG_HOLE);
- BMO_face_flag_disable(bm, f, HULL_FLAG_INTERIOR_ELE);
- }
- else {
- /* Look for an adjacent face that existed before the hull */
- for (i = 0; i < 3; i++) {
- if (!example) {
- example = hull_find_example_face(bm, edges[i]);
- }
- }
-
- /* Create new hull face */
- f = BM_face_create_verts(bm, t->v, 3, example, BM_CREATE_NO_DOUBLE, true);
- BM_face_copy_shared(bm, f, NULL, NULL);
- }
- /* Mark face for 'geom.out' slot and select */
- BMO_face_flag_enable(bm, f, HULL_FLAG_OUTPUT_GEOM);
- BM_face_select_set(bm, f, true);
-
- /* Mark edges for 'geom.out' slot */
- for (i = 0; i < 3; i++) {
- BMO_edge_flag_enable(bm, edges[i], HULL_FLAG_OUTPUT_GEOM);
- }
- }
- else {
- /* Mark input edges for 'geom.out' slot */
- for (i = 0; i < 3; i++) {
- const int next = (i == 2 ? 0 : i + 1);
- BMEdge *e = BM_edge_exists(t->v[i], t->v[next]);
- if (e &&
- BMO_edge_flag_test(bm, e, HULL_FLAG_INPUT) &&
- !BMO_edge_flag_test(bm, e, HULL_FLAG_HOLE))
- {
- BMO_edge_flag_enable(bm, e, HULL_FLAG_OUTPUT_GEOM);
- }
- }
- }
-
- /* Mark verts for 'geom.out' slot */
- for (i = 0; i < 3; i++) {
- BMO_vert_flag_enable(bm, t->v[i], HULL_FLAG_OUTPUT_GEOM);
- }
- }
+ GSetIterator iter;
+
+ GSET_ITER (iter, hull_triangles) {
+ HullTriangle *t = BLI_gsetIterator_getKey(&iter);
+ int i;
+
+ if (!t->skip) {
+ BMEdge *edges[3] = {BM_edge_create(bm, t->v[0], t->v[1], NULL, BM_CREATE_NO_DOUBLE),
+ BM_edge_create(bm, t->v[1], t->v[2], NULL, BM_CREATE_NO_DOUBLE),
+ BM_edge_create(bm, t->v[2], t->v[0], NULL, BM_CREATE_NO_DOUBLE)};
+ BMFace *f, *example = NULL;
+
+ f = BM_face_exists(t->v, 3);
+ if (f != NULL) {
+ /* If the operator is run with "use_existing_faces"
+ * disabled, but an output face in the hull is the
+ * same as a face in the existing mesh, it should not
+ * be marked as unused or interior. */
+ BMO_face_flag_enable(bm, f, HULL_FLAG_OUTPUT_GEOM);
+ BMO_face_flag_disable(bm, f, HULL_FLAG_HOLE);
+ BMO_face_flag_disable(bm, f, HULL_FLAG_INTERIOR_ELE);
+ }
+ else {
+ /* Look for an adjacent face that existed before the hull */
+ for (i = 0; i < 3; i++) {
+ if (!example) {
+ example = hull_find_example_face(bm, edges[i]);
+ }
+ }
+
+ /* Create new hull face */
+ f = BM_face_create_verts(bm, t->v, 3, example, BM_CREATE_NO_DOUBLE, true);
+ BM_face_copy_shared(bm, f, NULL, NULL);
+ }
+ /* Mark face for 'geom.out' slot and select */
+ BMO_face_flag_enable(bm, f, HULL_FLAG_OUTPUT_GEOM);
+ BM_face_select_set(bm, f, true);
+
+ /* Mark edges for 'geom.out' slot */
+ for (i = 0; i < 3; i++) {
+ BMO_edge_flag_enable(bm, edges[i], HULL_FLAG_OUTPUT_GEOM);
+ }
+ }
+ else {
+ /* Mark input edges for 'geom.out' slot */
+ for (i = 0; i < 3; i++) {
+ const int next = (i == 2 ? 0 : i + 1);
+ BMEdge *e = BM_edge_exists(t->v[i], t->v[next]);
+ if (e && BMO_edge_flag_test(bm, e, HULL_FLAG_INPUT) &&
+ !BMO_edge_flag_test(bm, e, HULL_FLAG_HOLE)) {
+ BMO_edge_flag_enable(bm, e, HULL_FLAG_OUTPUT_GEOM);
+ }
+ }
+ }
+
+ /* Mark verts for 'geom.out' slot */
+ for (i = 0; i < 3; i++) {
+ BMO_vert_flag_enable(bm, t->v[i], HULL_FLAG_OUTPUT_GEOM);
+ }
+ }
}
-
-
/***************************** Final Edges ****************************/
typedef struct {
- GHash *edges;
- BLI_mempool *base_pool, *link_pool;
+ GHash *edges;
+ BLI_mempool *base_pool, *link_pool;
} HullFinalEdges;
static LinkData *final_edges_find_link(ListBase *adj, BMVert *v)
{
- LinkData *link;
+ LinkData *link;
- for (link = adj->first; link; link = link->next) {
- if (link->data == v) {
- return link;
- }
- }
+ for (link = adj->first; link; link = link->next) {
+ if (link->data == v) {
+ return link;
+ }
+ }
- return NULL;
+ return NULL;
}
-static int hull_final_edges_lookup(
- HullFinalEdges *final_edges,
- BMVert *v1, BMVert *v2)
+static int hull_final_edges_lookup(HullFinalEdges *final_edges, BMVert *v1, BMVert *v2)
{
- ListBase *adj;
+ ListBase *adj;
- /* Use lower vertex pointer for hash key */
- if (v1 > v2) {
- SWAP(BMVert *, v1, v2);
- }
+ /* Use lower vertex pointer for hash key */
+ if (v1 > v2) {
+ SWAP(BMVert *, v1, v2);
+ }
- adj = BLI_ghash_lookup(final_edges->edges, v1);
- if (!adj) {
- return false;
- }
+ adj = BLI_ghash_lookup(final_edges->edges, v1);
+ if (!adj) {
+ return false;
+ }
- return !!final_edges_find_link(adj, v2);
+ return !!final_edges_find_link(adj, v2);
}
/* Used for checking whether a pre-existing edge lies on the hull */
static HullFinalEdges *hull_final_edges(GSet *hull_triangles)
{
- HullFinalEdges *final_edges;
- GSetIterator iter;
-
- final_edges = MEM_callocN(sizeof(HullFinalEdges), "HullFinalEdges");
- final_edges->edges = BLI_ghash_ptr_new("final edges ghash");
- final_edges->base_pool = BLI_mempool_create(sizeof(ListBase), 0, 128, BLI_MEMPOOL_NOP);
- final_edges->link_pool = BLI_mempool_create(sizeof(LinkData), 0, 128, BLI_MEMPOOL_NOP);
-
- GSET_ITER (iter, hull_triangles) {
- HullTriangle *t = BLI_gsetIterator_getKey(&iter);
- LinkData *link;
- int i;
-
- for (i = 0; i < 3; i++) {
- BMVert *v1 = t->v[i];
- BMVert *v2 = t->v[(i + 1) % 3];
- ListBase *adj;
-
- /* Use lower vertex pointer for hash key */
- if (v1 > v2) {
- SWAP(BMVert *, v1, v2);
- }
-
- adj = BLI_ghash_lookup(final_edges->edges, v1);
- if (!adj) {
- adj = BLI_mempool_calloc(final_edges->base_pool);
- BLI_ghash_insert(final_edges->edges, v1, adj);
- }
-
- if (!final_edges_find_link(adj, v2)) {
- link = BLI_mempool_calloc(final_edges->link_pool);
- link->data = v2;
- BLI_addtail(adj, link);
- }
- }
- }
-
- return final_edges;
+ HullFinalEdges *final_edges;
+ GSetIterator iter;
+
+ final_edges = MEM_callocN(sizeof(HullFinalEdges), "HullFinalEdges");
+ final_edges->edges = BLI_ghash_ptr_new("final edges ghash");
+ final_edges->base_pool = BLI_mempool_create(sizeof(ListBase), 0, 128, BLI_MEMPOOL_NOP);
+ final_edges->link_pool = BLI_mempool_create(sizeof(LinkData), 0, 128, BLI_MEMPOOL_NOP);
+
+ GSET_ITER (iter, hull_triangles) {
+ HullTriangle *t = BLI_gsetIterator_getKey(&iter);
+ LinkData *link;
+ int i;
+
+ for (i = 0; i < 3; i++) {
+ BMVert *v1 = t->v[i];
+ BMVert *v2 = t->v[(i + 1) % 3];
+ ListBase *adj;
+
+ /* Use lower vertex pointer for hash key */
+ if (v1 > v2) {
+ SWAP(BMVert *, v1, v2);
+ }
+
+ adj = BLI_ghash_lookup(final_edges->edges, v1);
+ if (!adj) {
+ adj = BLI_mempool_calloc(final_edges->base_pool);
+ BLI_ghash_insert(final_edges->edges, v1, adj);
+ }
+
+ if (!final_edges_find_link(adj, v2)) {
+ link = BLI_mempool_calloc(final_edges->link_pool);
+ link->data = v2;
+ BLI_addtail(adj, link);
+ }
+ }
+ }
+
+ return final_edges;
}
static void hull_final_edges_free(HullFinalEdges *final_edges)
{
- BLI_ghash_free(final_edges->edges, NULL, NULL);
- BLI_mempool_destroy(final_edges->base_pool);
- BLI_mempool_destroy(final_edges->link_pool);
- MEM_freeN(final_edges);
+ BLI_ghash_free(final_edges->edges, NULL, NULL);
+ BLI_mempool_destroy(final_edges->base_pool);
+ BLI_mempool_destroy(final_edges->link_pool);
+ MEM_freeN(final_edges);
}
-
-
/**************************** Final Output ****************************/
-static void hull_remove_overlapping(
- BMesh *bm, GSet *hull_triangles,
- HullFinalEdges *final_edges)
+static void hull_remove_overlapping(BMesh *bm, GSet *hull_triangles, HullFinalEdges *final_edges)
{
- GSetIterator hull_iter;
-
- GSET_ITER (hull_iter, hull_triangles) {
- HullTriangle *t = BLI_gsetIterator_getKey(&hull_iter);
- BMIter bm_iter1, bm_iter2;
- BMFace *f;
- bool f_on_hull;
-
- BM_ITER_ELEM (f, &bm_iter1, t->v[0], BM_FACES_OF_VERT) {
- BMEdge *e;
-
- /* Check that all the face's edges are on the hull,
- * otherwise can't reuse it */
- f_on_hull = true;
- BM_ITER_ELEM (e, &bm_iter2, f, BM_EDGES_OF_FACE) {
- if (!hull_final_edges_lookup(final_edges, e->v1, e->v2)) {
- f_on_hull = false;
- break;
- }
- }
-
- /* Note: can't change ghash while iterating, so mark
- * with 'skip' flag rather than deleting triangles */
- if (BM_vert_in_face(t->v[1], f) &&
- BM_vert_in_face(t->v[2], f) && f_on_hull)
- {
- t->skip = true;
- BMO_face_flag_disable(bm, f, HULL_FLAG_INTERIOR_ELE);
- BMO_face_flag_enable(bm, f, HULL_FLAG_HOLE);
- }
- }
- }
+ GSetIterator hull_iter;
+
+ GSET_ITER (hull_iter, hull_triangles) {
+ HullTriangle *t = BLI_gsetIterator_getKey(&hull_iter);
+ BMIter bm_iter1, bm_iter2;
+ BMFace *f;
+ bool f_on_hull;
+
+ BM_ITER_ELEM (f, &bm_iter1, t->v[0], BM_FACES_OF_VERT) {
+ BMEdge *e;
+
+ /* Check that all the face's edges are on the hull,
+ * otherwise can't reuse it */
+ f_on_hull = true;
+ BM_ITER_ELEM (e, &bm_iter2, f, BM_EDGES_OF_FACE) {
+ if (!hull_final_edges_lookup(final_edges, e->v1, e->v2)) {
+ f_on_hull = false;
+ break;
+ }
+ }
+
+ /* Note: can't change ghash while iterating, so mark
+ * with 'skip' flag rather than deleting triangles */
+ if (BM_vert_in_face(t->v[1], f) && BM_vert_in_face(t->v[2], f) && f_on_hull) {
+ t->skip = true;
+ BMO_face_flag_disable(bm, f, HULL_FLAG_INTERIOR_ELE);
+ BMO_face_flag_enable(bm, f, HULL_FLAG_HOLE);
+ }
+ }
+ }
}
-static void hull_mark_interior_elements(
- BMesh *bm, BMOperator *op,
- HullFinalEdges *final_edges)
+static void hull_mark_interior_elements(BMesh *bm, BMOperator *op, HullFinalEdges *final_edges)
{
- BMEdge *e;
- BMFace *f;
- BMOIter oiter;
-
- /* Check for interior edges too */
- BMO_ITER (e, &oiter, op->slots_in, "input", BM_EDGE) {
- if (!hull_final_edges_lookup(final_edges, e->v1, e->v2)) {
- BMO_edge_flag_enable(bm, e, HULL_FLAG_INTERIOR_ELE);
- }
- }
-
- /* Mark all input faces as interior, some may be unmarked in
- * hull_remove_overlapping() */
- BMO_ITER (f, &oiter, op->slots_in, "input", BM_FACE) {
- BMO_face_flag_enable(bm, f, HULL_FLAG_INTERIOR_ELE);
- }
+ BMEdge *e;
+ BMFace *f;
+ BMOIter oiter;
+
+ /* Check for interior edges too */
+ BMO_ITER (e, &oiter, op->slots_in, "input", BM_EDGE) {
+ if (!hull_final_edges_lookup(final_edges, e->v1, e->v2)) {
+ BMO_edge_flag_enable(bm, e, HULL_FLAG_INTERIOR_ELE);
+ }
+ }
+
+ /* Mark all input faces as interior, some may be unmarked in
+ * hull_remove_overlapping() */
+ BMO_ITER (f, &oiter, op->slots_in, "input", BM_FACE) {
+ BMO_face_flag_enable(bm, f, HULL_FLAG_INTERIOR_ELE);
+ }
}
static void hull_tag_unused(BMesh *bm, BMOperator *op)
{
- BMIter iter;
- BMOIter oiter;
- BMVert *v;
- BMEdge *e;
- BMFace *f;
-
- /* Mark vertices, edges, and faces that are already marked
- * interior (i.e. were already part of the input, but not part of
- * the hull), but that aren't also used by elements outside the
- * input set */
- BMO_ITER (v, &oiter, op->slots_in, "input", BM_VERT) {
- if (BMO_vert_flag_test(bm, v, HULL_FLAG_INTERIOR_ELE)) {
- bool del = true;
-
- BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
- if (!BMO_edge_flag_test(bm, e, HULL_FLAG_INPUT)) {
- del = false;
- break;
- }
- }
-
- BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) {
- if (!BMO_face_flag_test(bm, f, HULL_FLAG_INPUT)) {
- del = false;
- break;
- }
- }
-
- if (del) {
- BMO_vert_flag_enable(bm, v, HULL_FLAG_DEL);
- }
- }
- }
-
- BMO_ITER (e, &oiter, op->slots_in, "input", BM_EDGE) {
- if (BMO_edge_flag_test(bm, e, HULL_FLAG_INTERIOR_ELE)) {
- bool del = true;
-
- BM_ITER_ELEM (f, &iter, e, BM_FACES_OF_EDGE) {
- if (!BMO_face_flag_test(bm, f, HULL_FLAG_INPUT)) {
- del = false;
- break;
- }
- }
-
- if (del) {
- BMO_edge_flag_enable(bm, e, HULL_FLAG_DEL);
- }
- }
- }
-
- BMO_ITER (f, &oiter, op->slots_in, "input", BM_FACE) {
- if (BMO_face_flag_test(bm, f, HULL_FLAG_INTERIOR_ELE)) {
- BMO_face_flag_enable(bm, f, HULL_FLAG_DEL);
- }
- }
+ BMIter iter;
+ BMOIter oiter;
+ BMVert *v;
+ BMEdge *e;
+ BMFace *f;
+
+ /* Mark vertices, edges, and faces that are already marked
+ * interior (i.e. were already part of the input, but not part of
+ * the hull), but that aren't also used by elements outside the
+ * input set */
+ BMO_ITER (v, &oiter, op->slots_in, "input", BM_VERT) {
+ if (BMO_vert_flag_test(bm, v, HULL_FLAG_INTERIOR_ELE)) {
+ bool del = true;
+
+ BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
+ if (!BMO_edge_flag_test(bm, e, HULL_FLAG_INPUT)) {
+ del = false;
+ break;
+ }
+ }
+
+ BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) {
+ if (!BMO_face_flag_test(bm, f, HULL_FLAG_INPUT)) {
+ del = false;
+ break;
+ }
+ }
+
+ if (del) {
+ BMO_vert_flag_enable(bm, v, HULL_FLAG_DEL);
+ }
+ }
+ }
+
+ BMO_ITER (e, &oiter, op->slots_in, "input", BM_EDGE) {
+ if (BMO_edge_flag_test(bm, e, HULL_FLAG_INTERIOR_ELE)) {
+ bool del = true;
+
+ BM_ITER_ELEM (f, &iter, e, BM_FACES_OF_EDGE) {
+ if (!BMO_face_flag_test(bm, f, HULL_FLAG_INPUT)) {
+ del = false;
+ break;
+ }
+ }
+
+ if (del) {
+ BMO_edge_flag_enable(bm, e, HULL_FLAG_DEL);
+ }
+ }
+ }
+
+ BMO_ITER (f, &oiter, op->slots_in, "input", BM_FACE) {
+ if (BMO_face_flag_test(bm, f, HULL_FLAG_INTERIOR_ELE)) {
+ BMO_face_flag_enable(bm, f, HULL_FLAG_DEL);
+ }
+ }
}
static void hull_tag_holes(BMesh *bm, BMOperator *op)
{
- BMIter iter;
- BMOIter oiter;
- BMFace *f;
- BMEdge *e;
-
- /* Unmark any hole faces if they are isolated or part of a
- * border */
- BMO_ITER (f, &oiter, op->slots_in, "input", BM_FACE) {
- if (BMO_face_flag_test(bm, f, HULL_FLAG_HOLE)) {
- BM_ITER_ELEM (e, &iter, f, BM_EDGES_OF_FACE) {
- if (BM_edge_is_boundary(e)) {
- BMO_face_flag_disable(bm, f, HULL_FLAG_HOLE);
- break;
- }
- }
- }
- }
-
- /* Mark edges too if all adjacent faces are holes and the edge is
- * not already isolated */
- BMO_ITER (e, &oiter, op->slots_in, "input", BM_EDGE) {
- bool hole = true;
- bool any_faces = false;
-
- BM_ITER_ELEM (f, &iter, e, BM_FACES_OF_EDGE) {
- any_faces = true;
- if (!BMO_face_flag_test(bm, f, HULL_FLAG_HOLE)) {
- hole = false;
- break;
- }
- }
-
- if (hole && any_faces) {
- BMO_edge_flag_enable(bm, e, HULL_FLAG_HOLE);
- }
- }
+ BMIter iter;
+ BMOIter oiter;
+ BMFace *f;
+ BMEdge *e;
+
+ /* Unmark any hole faces if they are isolated or part of a
+ * border */
+ BMO_ITER (f, &oiter, op->slots_in, "input", BM_FACE) {
+ if (BMO_face_flag_test(bm, f, HULL_FLAG_HOLE)) {
+ BM_ITER_ELEM (e, &iter, f, BM_EDGES_OF_FACE) {
+ if (BM_edge_is_boundary(e)) {
+ BMO_face_flag_disable(bm, f, HULL_FLAG_HOLE);
+ break;
+ }
+ }
+ }
+ }
+
+ /* Mark edges too if all adjacent faces are holes and the edge is
+ * not already isolated */
+ BMO_ITER (e, &oiter, op->slots_in, "input", BM_EDGE) {
+ bool hole = true;
+ bool any_faces = false;
+
+ BM_ITER_ELEM (f, &iter, e, BM_FACES_OF_EDGE) {
+ any_faces = true;
+ if (!BMO_face_flag_test(bm, f, HULL_FLAG_HOLE)) {
+ hole = false;
+ break;
+ }
+ }
+
+ if (hole && any_faces) {
+ BMO_edge_flag_enable(bm, e, HULL_FLAG_HOLE);
+ }
+ }
}
static int hull_input_vert_count(BMOperator *op)
{
- BMOIter oiter;
- BMVert *v;
- int count = 0;
+ BMOIter oiter;
+ BMVert *v;
+ int count = 0;
- BMO_ITER (v, &oiter, op->slots_in, "input", BM_VERT) {
- count++;
- }
+ BMO_ITER (v, &oiter, op->slots_in, "input", BM_VERT) {
+ count++;
+ }
- return count;
+ return count;
}
-static BMVert **hull_input_verts_copy(
- BMOperator *op,
- const int num_input_verts)
+static BMVert **hull_input_verts_copy(BMOperator *op, const int num_input_verts)
{
- BMOIter oiter;
- BMVert *v;
- BMVert **input_verts = MEM_callocN(sizeof(*input_verts) *
- num_input_verts, AT);
- int i = 0;
+ BMOIter oiter;
+ BMVert *v;
+ BMVert **input_verts = MEM_callocN(sizeof(*input_verts) * num_input_verts, AT);
+ int i = 0;
- BMO_ITER (v, &oiter, op->slots_in, "input", BM_VERT) {
- input_verts[i++] = v;
- }
+ BMO_ITER (v, &oiter, op->slots_in, "input", BM_VERT) {
+ input_verts[i++] = v;
+ }
- return input_verts;
+ return input_verts;
}
-static float (*hull_verts_for_bullet(
- BMVert **input_verts,
- const int num_input_verts))[3]
+static float (*hull_verts_for_bullet(BMVert **input_verts, const int num_input_verts))[3]
{
- float (*coords)[3] = MEM_callocN(sizeof(*coords) * num_input_verts, __func__);
- int i;
+ float(*coords)[3] = MEM_callocN(sizeof(*coords) * num_input_verts, __func__);
+ int i;
- for (i = 0; i < num_input_verts; i++) {
- copy_v3_v3(coords[i], input_verts[i]->co);
- }
+ for (i = 0; i < num_input_verts; i++) {
+ copy_v3_v3(coords[i], input_verts[i]->co);
+ }
- return coords;
+ return coords;
}
-static BMVert **hull_verts_from_bullet(
- plConvexHull hull,
- BMVert **input_verts,
- const int num_input_verts)
+static BMVert **hull_verts_from_bullet(plConvexHull hull,
+ BMVert **input_verts,
+ const int num_input_verts)
{
- const int num_verts = plConvexHullNumVertices(hull);
- BMVert **hull_verts = MEM_mallocN(sizeof(*hull_verts) *
- num_verts, AT);
- int i;
-
- for (i = 0; i < num_verts; i++) {
- float co[3];
- int original_index;
- plConvexHullGetVertex(hull, i, co, &original_index);
-
- if (original_index >= 0 && original_index < num_input_verts) {
- hull_verts[i] = input_verts[original_index];
- }
- else {
- BLI_assert(!"Unexpected new vertex in hull output");
- }
- }
-
- return hull_verts;
+ const int num_verts = plConvexHullNumVertices(hull);
+ BMVert **hull_verts = MEM_mallocN(sizeof(*hull_verts) * num_verts, AT);
+ int i;
+
+ for (i = 0; i < num_verts; i++) {
+ float co[3];
+ int original_index;
+ plConvexHullGetVertex(hull, i, co, &original_index);
+
+ if (original_index >= 0 && original_index < num_input_verts) {
+ hull_verts[i] = input_verts[original_index];
+ }
+ else {
+ BLI_assert(!"Unexpected new vertex in hull output");
+ }
+ }
+
+ return hull_verts;
}
-static void hull_from_bullet(
- BMesh *bm, BMOperator *op,
- GSet *hull_triangles,
- BLI_mempool *pool)
+static void hull_from_bullet(BMesh *bm, BMOperator *op, GSet *hull_triangles, BLI_mempool *pool)
{
- int *fvi = NULL;
- BLI_array_declare(fvi);
+ int *fvi = NULL;
+ BLI_array_declare(fvi);
- BMVert **input_verts;
- float (*coords)[3];
- BMVert **hull_verts;
+ BMVert **input_verts;
+ float(*coords)[3];
+ BMVert **hull_verts;
- plConvexHull hull;
- int i, count = 0;
+ plConvexHull hull;
+ int i, count = 0;
- const int num_input_verts = hull_input_vert_count(op);
+ const int num_input_verts = hull_input_vert_count(op);
- input_verts = hull_input_verts_copy(op, num_input_verts);
- coords = hull_verts_for_bullet(input_verts, num_input_verts);
+ input_verts = hull_input_verts_copy(op, num_input_verts);
+ coords = hull_verts_for_bullet(input_verts, num_input_verts);
- hull = plConvexHullCompute(coords, num_input_verts);
- hull_verts = hull_verts_from_bullet(hull, input_verts, num_input_verts);
+ hull = plConvexHullCompute(coords, num_input_verts);
+ hull_verts = hull_verts_from_bullet(hull, input_verts, num_input_verts);
- count = plConvexHullNumFaces(hull);
- for (i = 0; i < count; i++) {
- const int len = plConvexHullGetFaceSize(hull, i);
+ count = plConvexHullNumFaces(hull);
+ for (i = 0; i < count; i++) {
+ const int len = plConvexHullGetFaceSize(hull, i);
- if (len > 2) {
- BMVert *fv[3];
- int j;
+ if (len > 2) {
+ BMVert *fv[3];
+ int j;
- /* Get face vertex indices */
- BLI_array_clear(fvi);
- BLI_array_grow_items(fvi, len);
- plConvexHullGetFaceVertices(hull, i, fvi);
+ /* Get face vertex indices */
+ BLI_array_clear(fvi);
+ BLI_array_grow_items(fvi, len);
+ plConvexHullGetFaceVertices(hull, i, fvi);
- /* Note: here we throw away any NGons from Bullet and turn
- * them into triangle fans. Would be nice to use these
- * directly, but will have to wait until HullTriangle goes
- * away (TODO) */
- fv[0] = hull_verts[fvi[0]];
- for (j = 2; j < len; j++) {
- fv[1] = hull_verts[fvi[j - 1]];
- fv[2] = hull_verts[fvi[j]];
+ /* Note: here we throw away any NGons from Bullet and turn
+ * them into triangle fans. Would be nice to use these
+ * directly, but will have to wait until HullTriangle goes
+ * away (TODO) */
+ fv[0] = hull_verts[fvi[0]];
+ for (j = 2; j < len; j++) {
+ fv[1] = hull_verts[fvi[j - 1]];
+ fv[2] = hull_verts[fvi[j]];
- hull_add_triangle(bm, hull_triangles, pool,
- fv[0], fv[1], fv[2]);
- }
- }
- }
+ hull_add_triangle(bm, hull_triangles, pool, fv[0], fv[1], fv[2]);
+ }
+ }
+ }
- BLI_array_free(fvi);
+ BLI_array_free(fvi);
- plConvexHullDelete(hull);
+ plConvexHullDelete(hull);
- MEM_freeN(hull_verts);
- MEM_freeN(coords);
- MEM_freeN(input_verts);
+ MEM_freeN(hull_verts);
+ MEM_freeN(coords);
+ MEM_freeN(input_verts);
}
/* Check that there are at least three vertices in the input */
static bool hull_num_input_verts_is_ok(BMOperator *op)
{
- BMOIter oiter;
- BMVert *v;
- int partial_num_verts = 0;
-
- BMO_ITER (v, &oiter, op->slots_in, "input", BM_VERT) {
- partial_num_verts++;
- if (partial_num_verts >= 3) {
- break;
- }
- }
-
- return (partial_num_verts >= 3);
+ BMOIter oiter;
+ BMVert *v;
+ int partial_num_verts = 0;
+
+ BMO_ITER (v, &oiter, op->slots_in, "input", BM_VERT) {
+ partial_num_verts++;
+ if (partial_num_verts >= 3) {
+ break;
+ }
+ }
+
+ return (partial_num_verts >= 3);
}
void bmo_convex_hull_exec(BMesh *bm, BMOperator *op)
{
- HullFinalEdges *final_edges;
- BLI_mempool *hull_pool;
- BMElemF *ele;
- BMOIter oiter;
- GSet *hull_triangles;
-
- /* Verify that at least three verts in the input */
- if (!hull_num_input_verts_is_ok(op)) {
- BMO_error_raise(bm, op, BMERR_CONVEX_HULL_FAILED,
- "Requires at least three vertices");
- return;
- }
-
- /* Tag input elements */
- BMO_ITER (ele, &oiter, op->slots_in, "input", BM_ALL) {
-
- /* Mark all vertices as interior to begin with */
- if (ele->head.htype == BM_VERT) {
- BMO_vert_flag_enable(bm, (BMVert *)ele, HULL_FLAG_INPUT | HULL_FLAG_INTERIOR_ELE);
- }
- else if (ele->head.htype == BM_EDGE) {
- BMO_edge_flag_enable(bm, (BMEdge *)ele, HULL_FLAG_INPUT);
- }
- else {
- BMO_face_flag_enable(bm, (BMFace *)ele, HULL_FLAG_INPUT);
- }
- }
-
- hull_pool = BLI_mempool_create(sizeof(HullTriangle), 0, 128, BLI_MEMPOOL_NOP);
- hull_triangles = BLI_gset_ptr_new("hull_triangles");
-
- hull_from_bullet(bm, op, hull_triangles, hull_pool);
-
- final_edges = hull_final_edges(hull_triangles);
-
- hull_mark_interior_elements(bm, op, final_edges);
-
- /* Remove hull triangles covered by an existing face */
- if (BMO_slot_bool_get(op->slots_in, "use_existing_faces")) {
- hull_remove_overlapping(bm, hull_triangles, final_edges);
-
- hull_tag_holes(bm, op);
- }
-
- /* Done with edges */
- hull_final_edges_free(final_edges);
-
- /* Convert hull triangles to BMesh faces */
- hull_output_triangles(bm, hull_triangles);
- BLI_mempool_destroy(hull_pool);
-
- BLI_gset_free(hull_triangles, NULL);
-
- hull_tag_unused(bm, op);
-
- /* Output slot of input elements that ended up inside the hull
- * rather than part of it */
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_interior.out",
- BM_ALL_NOLOOP, HULL_FLAG_INTERIOR_ELE);
-
- /* Output slot of input elements that ended up inside the hull and
- * are are unused by other geometry. */
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_unused.out",
- BM_ALL_NOLOOP, HULL_FLAG_DEL);
-
- /* Output slot of faces and edges that were in the input and on
- * the hull (useful for cases like bridging where you want to
- * delete some input geometry) */
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_holes.out",
- BM_ALL_NOLOOP, HULL_FLAG_HOLE);
-
- /* Output slot of all hull vertices, faces, and edges */
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out",
- BM_ALL_NOLOOP, HULL_FLAG_OUTPUT_GEOM);
+ HullFinalEdges *final_edges;
+ BLI_mempool *hull_pool;
+ BMElemF *ele;
+ BMOIter oiter;
+ GSet *hull_triangles;
+
+ /* Verify that at least three verts in the input */
+ if (!hull_num_input_verts_is_ok(op)) {
+ BMO_error_raise(bm, op, BMERR_CONVEX_HULL_FAILED, "Requires at least three vertices");
+ return;
+ }
+
+ /* Tag input elements */
+ BMO_ITER (ele, &oiter, op->slots_in, "input", BM_ALL) {
+
+ /* Mark all vertices as interior to begin with */
+ if (ele->head.htype == BM_VERT) {
+ BMO_vert_flag_enable(bm, (BMVert *)ele, HULL_FLAG_INPUT | HULL_FLAG_INTERIOR_ELE);
+ }
+ else if (ele->head.htype == BM_EDGE) {
+ BMO_edge_flag_enable(bm, (BMEdge *)ele, HULL_FLAG_INPUT);
+ }
+ else {
+ BMO_face_flag_enable(bm, (BMFace *)ele, HULL_FLAG_INPUT);
+ }
+ }
+
+ hull_pool = BLI_mempool_create(sizeof(HullTriangle), 0, 128, BLI_MEMPOOL_NOP);
+ hull_triangles = BLI_gset_ptr_new("hull_triangles");
+
+ hull_from_bullet(bm, op, hull_triangles, hull_pool);
+
+ final_edges = hull_final_edges(hull_triangles);
+
+ hull_mark_interior_elements(bm, op, final_edges);
+
+ /* Remove hull triangles covered by an existing face */
+ if (BMO_slot_bool_get(op->slots_in, "use_existing_faces")) {
+ hull_remove_overlapping(bm, hull_triangles, final_edges);
+
+ hull_tag_holes(bm, op);
+ }
+
+ /* Done with edges */
+ hull_final_edges_free(final_edges);
+
+ /* Convert hull triangles to BMesh faces */
+ hull_output_triangles(bm, hull_triangles);
+ BLI_mempool_destroy(hull_pool);
+
+ BLI_gset_free(hull_triangles, NULL);
+
+ hull_tag_unused(bm, op);
+
+ /* Output slot of input elements that ended up inside the hull
+ * rather than part of it */
+ BMO_slot_buffer_from_enabled_flag(
+ bm, op, op->slots_out, "geom_interior.out", BM_ALL_NOLOOP, HULL_FLAG_INTERIOR_ELE);
+
+ /* Output slot of input elements that ended up inside the hull and
+ * are are unused by other geometry. */
+ BMO_slot_buffer_from_enabled_flag(
+ bm, op, op->slots_out, "geom_unused.out", BM_ALL_NOLOOP, HULL_FLAG_DEL);
+
+ /* Output slot of faces and edges that were in the input and on
+ * the hull (useful for cases like bridging where you want to
+ * delete some input geometry) */
+ BMO_slot_buffer_from_enabled_flag(
+ bm, op, op->slots_out, "geom_holes.out", BM_ALL_NOLOOP, HULL_FLAG_HOLE);
+
+ /* Output slot of all hull vertices, faces, and edges */
+ BMO_slot_buffer_from_enabled_flag(
+ bm, op, op->slots_out, "geom.out", BM_ALL_NOLOOP, HULL_FLAG_OUTPUT_GEOM);
}
-#endif /* WITH_BULLET */
+#endif /* WITH_BULLET */
diff --git a/source/blender/bmesh/operators/bmo_inset.c b/source/blender/bmesh/operators/bmo_inset.c
index 3534d798b02..724b974c50f 100644
--- a/source/blender/bmesh/operators/bmo_inset.c
+++ b/source/blender/bmesh/operators/bmo_inset.c
@@ -35,8 +35,7 @@
/* Merge loop-data that diverges, see: T41445 */
#define USE_LOOP_CUSTOMDATA_MERGE
-#define ELE_NEW 1
-
+#define ELE_NEW 1
/* -------------------------------------------------------------------- */
/* Generic Interp Face (use for both types of inset) */
@@ -50,56 +49,59 @@
/* just enough of a face to store interpolation data we can use once the inset is done */
typedef struct InterpFace {
- BMFace *f;
- void **blocks_l;
- void **blocks_v;
- float (*cos_2d)[2];
- float axis_mat[3][3];
+ BMFace *f;
+ void **blocks_l;
+ void **blocks_v;
+ float (*cos_2d)[2];
+ float axis_mat[3][3];
} InterpFace;
/* basically a clone of #BM_vert_interp_from_face */
static void bm_interp_face_store(InterpFace *iface, BMesh *bm, BMFace *f, MemArena *interp_arena)
{
- BMLoop *l_iter, *l_first;
- void **blocks_l = iface->blocks_l = BLI_memarena_alloc(interp_arena, sizeof(*iface->blocks_l) * f->len);
- void **blocks_v = iface->blocks_v = BLI_memarena_alloc(interp_arena, sizeof(*iface->blocks_v) * f->len);
- float (*cos_2d)[2] = iface->cos_2d = BLI_memarena_alloc(interp_arena, sizeof(*iface->cos_2d) * f->len);
- void *axis_mat = iface->axis_mat;
- int i;
-
- BLI_assert(BM_face_is_normal_valid(f));
-
- axis_dominant_v3_to_m3(axis_mat, f->no);
-
- iface->f = f;
-
- i = 0;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co);
- blocks_l[i] = NULL;
- CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, l_iter->head.data, &blocks_l[i]);
- /* if we were not modifying the loops later we would do... */
- // blocks[i] = l_iter->head.data;
-
- blocks_v[i] = NULL;
- CustomData_bmesh_copy_data(&bm->vdata, &bm->vdata, l_iter->v->head.data, &blocks_v[i]);
-
- /* use later for index lookups */
- BM_elem_index_set(l_iter, i); /* set_dirty */
- } while ((void)i++, (l_iter = l_iter->next) != l_first);
- bm->elem_index_dirty |= BM_LOOP;
+ BMLoop *l_iter, *l_first;
+ void **blocks_l = iface->blocks_l = BLI_memarena_alloc(interp_arena,
+ sizeof(*iface->blocks_l) * f->len);
+ void **blocks_v = iface->blocks_v = BLI_memarena_alloc(interp_arena,
+ sizeof(*iface->blocks_v) * f->len);
+ float(*cos_2d)[2] = iface->cos_2d = BLI_memarena_alloc(interp_arena,
+ sizeof(*iface->cos_2d) * f->len);
+ void *axis_mat = iface->axis_mat;
+ int i;
+
+ BLI_assert(BM_face_is_normal_valid(f));
+
+ axis_dominant_v3_to_m3(axis_mat, f->no);
+
+ iface->f = f;
+
+ i = 0;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co);
+ blocks_l[i] = NULL;
+ CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, l_iter->head.data, &blocks_l[i]);
+ /* if we were not modifying the loops later we would do... */
+ // blocks[i] = l_iter->head.data;
+
+ blocks_v[i] = NULL;
+ CustomData_bmesh_copy_data(&bm->vdata, &bm->vdata, l_iter->v->head.data, &blocks_v[i]);
+
+ /* use later for index lookups */
+ BM_elem_index_set(l_iter, i); /* set_dirty */
+ } while ((void)i++, (l_iter = l_iter->next) != l_first);
+ bm->elem_index_dirty |= BM_LOOP;
}
static void bm_interp_face_free(InterpFace *iface, BMesh *bm)
{
- void **blocks_l = iface->blocks_l;
- void **blocks_v = iface->blocks_v;
- int i;
-
- for (i = 0; i < iface->f->len; i++) {
- CustomData_bmesh_free_block(&bm->ldata, &blocks_l[i]);
- CustomData_bmesh_free_block(&bm->vdata, &blocks_v[i]);
- }
+ void **blocks_l = iface->blocks_l;
+ void **blocks_v = iface->blocks_v;
+ int i;
+
+ for (i = 0; i < iface->f->len; i++) {
+ CustomData_bmesh_free_block(&bm->ldata, &blocks_l[i]);
+ CustomData_bmesh_free_block(&bm->vdata, &blocks_v[i]);
+ }
}
#ifdef USE_LOOP_CUSTOMDATA_MERGE
@@ -107,300 +109,294 @@ static void bm_interp_face_free(InterpFace *iface, BMesh *bm)
* This function merges loop customdata (UV's)
* where interpolating the values across the face causes values to diverge.
*/
-static void bm_loop_customdata_merge(
- BMesh *bm,
- BMEdge *e_connect,
- BMLoop *l_a_outer, BMLoop *l_b_outer,
- BMLoop *l_a_inner, BMLoop *l_b_inner)
+static void bm_loop_customdata_merge(BMesh *bm,
+ BMEdge *e_connect,
+ BMLoop *l_a_outer,
+ BMLoop *l_b_outer,
+ BMLoop *l_a_inner,
+ BMLoop *l_b_inner)
{
- /**
- * Check for diverged values at the vert shared by
- * \a l_a_inner & \a l_b_inner.
- *
- * <pre>
- * -----------------------+
- * l_a_outer--> /|<--l_b_outer
- * / |
- * (face a) / |
- * / <--e_connect
- * / |
- * e_a l_a_inner--> / <--l_b_inner
- * -----------------+ |
- * /| |
- * l_a/b_inner_inset| (face b)
- * / | |
- * / |e_b |
- * (inset face(s)) | |
- * / | |
- * </pre>
- */
-
- const bool is_flip = (l_a_inner->next == l_a_outer);
- BMLoop *l_a_inner_inset, *l_b_inner_inset;
- BMEdge *e_a, *e_b;
- int layer_n;
-
- /* paranoid sanity checks */
- BLI_assert(l_a_outer->v == l_b_outer->v);
- BLI_assert(l_a_inner->v == l_b_inner->v);
-
- BLI_assert(l_b_inner->f != l_a_inner->f);
-
- BLI_assert(l_a_outer->f == l_a_inner->f);
- BLI_assert(l_b_outer->f == l_b_inner->f);
-
- (void) e_connect;
- BLI_assert(BM_edge_in_face(e_connect, l_a_inner->f));
- BLI_assert(BM_edge_in_face(e_connect, l_b_inner->f));
-
- if (is_flip) {
- e_a = l_a_inner->prev->e;
- e_b = l_b_inner->e;
- }
- else {
- e_a = l_a_inner->e;
- e_b = l_b_inner->prev->e;
- }
-
- l_a_inner_inset = BM_edge_other_loop(e_a, l_a_inner);
- l_b_inner_inset = BM_edge_other_loop(e_b, l_b_inner);
- BLI_assert(l_a_inner_inset->v == l_b_inner_inset->v);
-
- /* check if there is no chance of diversion */
- if (l_a_inner_inset->f == l_b_inner_inset->f) {
- return;
- }
-
- for (layer_n = 0; layer_n < bm->ldata.totlayer; layer_n++) {
- const int type = bm->ldata.layers[layer_n].type;
- const int offset = bm->ldata.layers[layer_n].offset;
- if (!CustomData_layer_has_math(&bm->ldata, layer_n)) {
- continue;
- }
-
- /* check we begin with merged data */
- if ((CustomData_data_equals(
- type,
- BM_ELEM_CD_GET_VOID_P(l_a_outer, offset),
- BM_ELEM_CD_GET_VOID_P(l_b_outer, offset)) == true)
-
- /* epsilon for comparing UV's is too big, gives noticable problems */
-#if 0
- &&
- /* check if the data ends up diverged */
- (CustomData_data_equals(
- type,
- BM_ELEM_CD_GET_VOID_P(l_a_inner, offset),
- BM_ELEM_CD_GET_VOID_P(l_b_inner, offset)) == false)
-#endif
- )
- {
- /* no need to allocate a temp block:
- * a = (a + b);
- * a *= 0.5f;
- * b = a;
- */
- const void *data_src;
-
- CustomData_data_mix_value(
- type,
- BM_ELEM_CD_GET_VOID_P(l_a_inner_inset, offset),
- BM_ELEM_CD_GET_VOID_P(l_b_inner_inset, offset),
- CDT_MIX_MIX, 0.5f);
- CustomData_data_copy_value(
- type,
- BM_ELEM_CD_GET_VOID_P(l_a_inner_inset, offset),
- BM_ELEM_CD_GET_VOID_P(l_b_inner_inset, offset));
-
- /* use this as a reference (could be 'l_b_inner_inset' too) */
- data_src = BM_ELEM_CD_GET_VOID_P(l_a_inner_inset, offset);
-
- /* check if the 2 faces share an edge */
- if (is_flip ?
- (l_b_inner_inset->e == l_a_inner_inset->prev->e) :
- (l_a_inner_inset->e == l_b_inner_inset->prev->e))
- {
- /* simple case, we have all loops already */
- }
- else {
- /* compare with (l_a_inner / l_b_inner) and assign the blended value if they match */
- BMIter iter;
- BMLoop *l_iter;
- const void *data_cmp_a = BM_ELEM_CD_GET_VOID_P(l_b_inner, offset);
- const void *data_cmp_b = BM_ELEM_CD_GET_VOID_P(l_a_inner, offset);
- BM_ITER_ELEM (l_iter, &iter, l_a_inner_inset->v, BM_LOOPS_OF_VERT) {
- if (BM_elem_flag_test(l_iter->f, BM_ELEM_TAG)) {
- if (!ELEM(l_iter, l_a_inner, l_b_inner, l_a_inner_inset, l_b_inner_inset)) {
- void *data_dst = BM_ELEM_CD_GET_VOID_P(l_iter, offset);
-
- if (CustomData_data_equals(type, data_dst, data_cmp_a) ||
- CustomData_data_equals(type, data_dst, data_cmp_b))
- {
- CustomData_data_copy_value(type, data_src, data_dst);
- }
- }
- }
- }
- }
-
- CustomData_data_copy_value(type, data_src, BM_ELEM_CD_GET_VOID_P(l_b_inner, offset));
- CustomData_data_copy_value(type, data_src, BM_ELEM_CD_GET_VOID_P(l_a_inner, offset));
- }
- }
+ /**
+ * Check for diverged values at the vert shared by
+ * \a l_a_inner & \a l_b_inner.
+ *
+ * <pre>
+ * -----------------------+
+ * l_a_outer--> /|<--l_b_outer
+ * / |
+ * (face a) / |
+ * / <--e_connect
+ * / |
+ * e_a l_a_inner--> / <--l_b_inner
+ * -----------------+ |
+ * /| |
+ * l_a/b_inner_inset| (face b)
+ * / | |
+ * / |e_b |
+ * (inset face(s)) | |
+ * / | |
+ * </pre>
+ */
+
+ const bool is_flip = (l_a_inner->next == l_a_outer);
+ BMLoop *l_a_inner_inset, *l_b_inner_inset;
+ BMEdge *e_a, *e_b;
+ int layer_n;
+
+ /* paranoid sanity checks */
+ BLI_assert(l_a_outer->v == l_b_outer->v);
+ BLI_assert(l_a_inner->v == l_b_inner->v);
+
+ BLI_assert(l_b_inner->f != l_a_inner->f);
+
+ BLI_assert(l_a_outer->f == l_a_inner->f);
+ BLI_assert(l_b_outer->f == l_b_inner->f);
+
+ (void)e_connect;
+ BLI_assert(BM_edge_in_face(e_connect, l_a_inner->f));
+ BLI_assert(BM_edge_in_face(e_connect, l_b_inner->f));
+
+ if (is_flip) {
+ e_a = l_a_inner->prev->e;
+ e_b = l_b_inner->e;
+ }
+ else {
+ e_a = l_a_inner->e;
+ e_b = l_b_inner->prev->e;
+ }
+
+ l_a_inner_inset = BM_edge_other_loop(e_a, l_a_inner);
+ l_b_inner_inset = BM_edge_other_loop(e_b, l_b_inner);
+ BLI_assert(l_a_inner_inset->v == l_b_inner_inset->v);
+
+ /* check if there is no chance of diversion */
+ if (l_a_inner_inset->f == l_b_inner_inset->f) {
+ return;
+ }
+
+ for (layer_n = 0; layer_n < bm->ldata.totlayer; layer_n++) {
+ const int type = bm->ldata.layers[layer_n].type;
+ const int offset = bm->ldata.layers[layer_n].offset;
+ if (!CustomData_layer_has_math(&bm->ldata, layer_n)) {
+ continue;
+ }
+
+ /* check we begin with merged data */
+ if ((CustomData_data_equals(type,
+ BM_ELEM_CD_GET_VOID_P(l_a_outer, offset),
+ BM_ELEM_CD_GET_VOID_P(l_b_outer, offset)) == true)
+
+ /* epsilon for comparing UV's is too big, gives noticable problems */
+# if 0
+ &&
+ /* check if the data ends up diverged */
+ (CustomData_data_equals(
+ type,
+ BM_ELEM_CD_GET_VOID_P(l_a_inner, offset),
+ BM_ELEM_CD_GET_VOID_P(l_b_inner, offset)) == false)
+# endif
+ ) {
+ /* no need to allocate a temp block:
+ * a = (a + b);
+ * a *= 0.5f;
+ * b = a;
+ */
+ const void *data_src;
+
+ CustomData_data_mix_value(type,
+ BM_ELEM_CD_GET_VOID_P(l_a_inner_inset, offset),
+ BM_ELEM_CD_GET_VOID_P(l_b_inner_inset, offset),
+ CDT_MIX_MIX,
+ 0.5f);
+ CustomData_data_copy_value(type,
+ BM_ELEM_CD_GET_VOID_P(l_a_inner_inset, offset),
+ BM_ELEM_CD_GET_VOID_P(l_b_inner_inset, offset));
+
+ /* use this as a reference (could be 'l_b_inner_inset' too) */
+ data_src = BM_ELEM_CD_GET_VOID_P(l_a_inner_inset, offset);
+
+ /* check if the 2 faces share an edge */
+ if (is_flip ? (l_b_inner_inset->e == l_a_inner_inset->prev->e) :
+ (l_a_inner_inset->e == l_b_inner_inset->prev->e)) {
+ /* simple case, we have all loops already */
+ }
+ else {
+ /* compare with (l_a_inner / l_b_inner) and assign the blended value if they match */
+ BMIter iter;
+ BMLoop *l_iter;
+ const void *data_cmp_a = BM_ELEM_CD_GET_VOID_P(l_b_inner, offset);
+ const void *data_cmp_b = BM_ELEM_CD_GET_VOID_P(l_a_inner, offset);
+ BM_ITER_ELEM (l_iter, &iter, l_a_inner_inset->v, BM_LOOPS_OF_VERT) {
+ if (BM_elem_flag_test(l_iter->f, BM_ELEM_TAG)) {
+ if (!ELEM(l_iter, l_a_inner, l_b_inner, l_a_inner_inset, l_b_inner_inset)) {
+ void *data_dst = BM_ELEM_CD_GET_VOID_P(l_iter, offset);
+
+ if (CustomData_data_equals(type, data_dst, data_cmp_a) ||
+ CustomData_data_equals(type, data_dst, data_cmp_b)) {
+ CustomData_data_copy_value(type, data_src, data_dst);
+ }
+ }
+ }
+ }
+ }
+
+ CustomData_data_copy_value(type, data_src, BM_ELEM_CD_GET_VOID_P(l_b_inner, offset));
+ CustomData_data_copy_value(type, data_src, BM_ELEM_CD_GET_VOID_P(l_a_inner, offset));
+ }
+ }
}
-#endif /* USE_LOOP_CUSTOMDATA_MERGE */
-
+#endif /* USE_LOOP_CUSTOMDATA_MERGE */
/* -------------------------------------------------------------------- */
/* Inset Individual */
-static void bmo_face_inset_individual(
- BMesh *bm, BMFace *f, MemArena *interp_arena,
- const float thickness, const float depth,
- const bool use_even_offset, const bool use_relative_offset, const bool use_interpolate)
+static void bmo_face_inset_individual(BMesh *bm,
+ BMFace *f,
+ MemArena *interp_arena,
+ const float thickness,
+ const float depth,
+ const bool use_even_offset,
+ const bool use_relative_offset,
+ const bool use_interpolate)
{
- InterpFace *iface = NULL;
-
- /* stores verts split away from the face (aligned with face verts) */
- BMVert **verts = BLI_array_alloca(verts, f->len);
- /* store edge normals (aligned with face-loop-edges) */
- float (*edge_nors)[3] = BLI_array_alloca(edge_nors, f->len);
- float (*coords)[3] = BLI_array_alloca(coords, f->len);
-
- BMLoop *l_iter, *l_first;
- BMLoop *l_other;
- uint i;
- float e_length_prev;
-
- l_first = BM_FACE_FIRST_LOOP(f);
-
- /* split off all loops */
- l_iter = l_first;
- i = 0;
- do {
- BMVert *v_other = l_iter->v;
- BMVert *v_sep = BM_face_loop_separate(bm, l_iter);
- if (v_sep == v_other) {
- v_other = BM_vert_create(bm, l_iter->v->co, l_iter->v, BM_CREATE_NOP);
- }
- verts[i] = v_other;
-
- /* unrelated to splitting, but calc here */
- BM_edge_calc_face_tangent(l_iter->e, l_iter, edge_nors[i]);
- } while ((void)i++, ((l_iter = l_iter->next) != l_first));
-
-
- /* build rim faces */
- l_iter = l_first;
- i = 0;
- do {
- BMFace *f_new_outer;
- BMVert *v_other = verts[i];
- BMVert *v_other_next = verts[(i + 1) % f->len];
-
- BMEdge *e_other = BM_edge_create(bm, v_other, v_other_next, l_iter->e, BM_CREATE_NO_DOUBLE);
- (void)e_other;
-
- f_new_outer = BM_face_create_quad_tri(bm,
- v_other,
- v_other_next,
- l_iter->next->v,
- l_iter->v,
- f, BM_CREATE_NOP);
- BMO_face_flag_enable(bm, f_new_outer, ELE_NEW);
-
- /* copy loop data */
- l_other = l_iter->radial_next;
- BM_elem_attrs_copy(bm, bm, l_iter->next, l_other->prev);
- BM_elem_attrs_copy(bm, bm, l_iter, l_other->next->next);
-
- if (use_interpolate == false) {
- BM_elem_attrs_copy(bm, bm, l_iter->next, l_other);
- BM_elem_attrs_copy(bm, bm, l_iter, l_other->next);
- }
- } while ((void)i++, ((l_iter = l_iter->next) != l_first));
-
- /* hold interpolation values */
- if (use_interpolate) {
- iface = BLI_memarena_alloc(interp_arena, sizeof(*iface));
- bm_interp_face_store(iface, bm, f, interp_arena);
- }
-
- /* Calculate translation vector for new */
- l_iter = l_first;
- i = 0;
-
- if (depth != 0.0f) {
- e_length_prev = BM_edge_calc_length(l_iter->prev->e);
- }
-
- do {
- const float *eno_prev = edge_nors[(i ? i : f->len) - 1];
- const float *eno_next = edge_nors[i];
- float tvec[3];
- float v_new_co[3];
-
- add_v3_v3v3(tvec, eno_prev, eno_next);
- normalize_v3(tvec);
-
- copy_v3_v3(v_new_co, l_iter->v->co);
-
- if (use_even_offset) {
- mul_v3_fl(tvec, shell_v3v3_mid_normalized_to_dist(eno_prev, eno_next));
- }
-
- /* Modify vertices and their normals */
- if (use_relative_offset) {
- mul_v3_fl(tvec, (BM_edge_calc_length(l_iter->e) + BM_edge_calc_length(l_iter->prev->e)) / 2.0f);
- }
-
- madd_v3_v3fl(v_new_co, tvec, thickness);
-
- /* Set normal, add depth and write new vertex position*/
- copy_v3_v3(l_iter->v->no, f->no);
-
- if (depth != 0.0f) {
- const float e_length = BM_edge_calc_length(l_iter->e);
- const float fac = depth * (use_relative_offset ? ((e_length_prev + e_length) * 0.5f) : 1.0f);
- e_length_prev = e_length;
-
- madd_v3_v3fl(v_new_co, f->no, fac);
- }
-
-
-
- copy_v3_v3(coords[i], v_new_co);
- } while ((void)i++, ((l_iter = l_iter->next) != l_first));
-
- /* update the coords */
- l_iter = l_first;
- i = 0;
- do {
- copy_v3_v3(l_iter->v->co, coords[i]);
- } while ((void)i++, ((l_iter = l_iter->next) != l_first));
-
-
- if (use_interpolate) {
- BM_face_interp_from_face_ex(
- bm, iface->f, iface->f, true,
- (const void **)iface->blocks_l, (const void **)iface->blocks_v,
- iface->cos_2d, iface->axis_mat);
-
- /* build rim faces */
- l_iter = l_first;
- do {
- /* copy loop data */
- l_other = l_iter->radial_next;
-
- BM_elem_attrs_copy(bm, bm, l_iter->next, l_other);
- BM_elem_attrs_copy(bm, bm, l_iter, l_other->next);
- } while ((l_iter = l_iter->next) != l_first);
-
- bm_interp_face_free(iface, bm);
- }
+ InterpFace *iface = NULL;
+
+ /* stores verts split away from the face (aligned with face verts) */
+ BMVert **verts = BLI_array_alloca(verts, f->len);
+ /* store edge normals (aligned with face-loop-edges) */
+ float(*edge_nors)[3] = BLI_array_alloca(edge_nors, f->len);
+ float(*coords)[3] = BLI_array_alloca(coords, f->len);
+
+ BMLoop *l_iter, *l_first;
+ BMLoop *l_other;
+ uint i;
+ float e_length_prev;
+
+ l_first = BM_FACE_FIRST_LOOP(f);
+
+ /* split off all loops */
+ l_iter = l_first;
+ i = 0;
+ do {
+ BMVert *v_other = l_iter->v;
+ BMVert *v_sep = BM_face_loop_separate(bm, l_iter);
+ if (v_sep == v_other) {
+ v_other = BM_vert_create(bm, l_iter->v->co, l_iter->v, BM_CREATE_NOP);
+ }
+ verts[i] = v_other;
+
+ /* unrelated to splitting, but calc here */
+ BM_edge_calc_face_tangent(l_iter->e, l_iter, edge_nors[i]);
+ } while ((void)i++, ((l_iter = l_iter->next) != l_first));
+
+ /* build rim faces */
+ l_iter = l_first;
+ i = 0;
+ do {
+ BMFace *f_new_outer;
+ BMVert *v_other = verts[i];
+ BMVert *v_other_next = verts[(i + 1) % f->len];
+
+ BMEdge *e_other = BM_edge_create(bm, v_other, v_other_next, l_iter->e, BM_CREATE_NO_DOUBLE);
+ (void)e_other;
+
+ f_new_outer = BM_face_create_quad_tri(
+ bm, v_other, v_other_next, l_iter->next->v, l_iter->v, f, BM_CREATE_NOP);
+ BMO_face_flag_enable(bm, f_new_outer, ELE_NEW);
+
+ /* copy loop data */
+ l_other = l_iter->radial_next;
+ BM_elem_attrs_copy(bm, bm, l_iter->next, l_other->prev);
+ BM_elem_attrs_copy(bm, bm, l_iter, l_other->next->next);
+
+ if (use_interpolate == false) {
+ BM_elem_attrs_copy(bm, bm, l_iter->next, l_other);
+ BM_elem_attrs_copy(bm, bm, l_iter, l_other->next);
+ }
+ } while ((void)i++, ((l_iter = l_iter->next) != l_first));
+
+ /* hold interpolation values */
+ if (use_interpolate) {
+ iface = BLI_memarena_alloc(interp_arena, sizeof(*iface));
+ bm_interp_face_store(iface, bm, f, interp_arena);
+ }
+
+ /* Calculate translation vector for new */
+ l_iter = l_first;
+ i = 0;
+
+ if (depth != 0.0f) {
+ e_length_prev = BM_edge_calc_length(l_iter->prev->e);
+ }
+
+ do {
+ const float *eno_prev = edge_nors[(i ? i : f->len) - 1];
+ const float *eno_next = edge_nors[i];
+ float tvec[3];
+ float v_new_co[3];
+
+ add_v3_v3v3(tvec, eno_prev, eno_next);
+ normalize_v3(tvec);
+
+ copy_v3_v3(v_new_co, l_iter->v->co);
+
+ if (use_even_offset) {
+ mul_v3_fl(tvec, shell_v3v3_mid_normalized_to_dist(eno_prev, eno_next));
+ }
+
+ /* Modify vertices and their normals */
+ if (use_relative_offset) {
+ mul_v3_fl(tvec,
+ (BM_edge_calc_length(l_iter->e) + BM_edge_calc_length(l_iter->prev->e)) / 2.0f);
+ }
+
+ madd_v3_v3fl(v_new_co, tvec, thickness);
+
+ /* Set normal, add depth and write new vertex position*/
+ copy_v3_v3(l_iter->v->no, f->no);
+
+ if (depth != 0.0f) {
+ const float e_length = BM_edge_calc_length(l_iter->e);
+ const float fac = depth * (use_relative_offset ? ((e_length_prev + e_length) * 0.5f) : 1.0f);
+ e_length_prev = e_length;
+
+ madd_v3_v3fl(v_new_co, f->no, fac);
+ }
+
+ copy_v3_v3(coords[i], v_new_co);
+ } while ((void)i++, ((l_iter = l_iter->next) != l_first));
+
+ /* update the coords */
+ l_iter = l_first;
+ i = 0;
+ do {
+ copy_v3_v3(l_iter->v->co, coords[i]);
+ } while ((void)i++, ((l_iter = l_iter->next) != l_first));
+
+ if (use_interpolate) {
+ BM_face_interp_from_face_ex(bm,
+ iface->f,
+ iface->f,
+ true,
+ (const void **)iface->blocks_l,
+ (const void **)iface->blocks_v,
+ iface->cos_2d,
+ iface->axis_mat);
+
+ /* build rim faces */
+ l_iter = l_first;
+ do {
+ /* copy loop data */
+ l_other = l_iter->radial_next;
+
+ BM_elem_attrs_copy(bm, bm, l_iter->next, l_other);
+ BM_elem_attrs_copy(bm, bm, l_iter, l_other->next);
+ } while ((l_iter = l_iter->next) != l_first);
+
+ bm_interp_face_free(iface, bm);
+ }
}
-
/**
* Individual Face Inset.
* Find all tagged faces (f), duplicate edges around faces, inset verts of
@@ -409,56 +405,58 @@ static void bmo_face_inset_individual(
*/
void bmo_inset_individual_exec(BMesh *bm, BMOperator *op)
{
- BMFace *f;
-
- BMOIter oiter;
- MemArena *interp_arena = NULL;
-
- const float thickness = BMO_slot_float_get(op->slots_in, "thickness");
- const float depth = BMO_slot_float_get(op->slots_in, "depth");
- const bool use_even_offset = BMO_slot_bool_get(op->slots_in, "use_even_offset");
- const bool use_relative_offset = BMO_slot_bool_get(op->slots_in, "use_relative_offset");
- const bool use_interpolate = BMO_slot_bool_get(op->slots_in, "use_interpolate");
-
- /* Only tag faces in slot */
- BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false);
-
- BMO_slot_buffer_hflag_enable(bm, op->slots_in, "faces", BM_FACE, BM_ELEM_TAG, false);
-
- if (use_interpolate) {
- interp_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
- }
-
- BMO_ITER (f, &oiter, op->slots_in, "faces", BM_FACE) {
- bmo_face_inset_individual(
- bm, f, interp_arena,
- thickness, depth,
- use_even_offset, use_relative_offset, use_interpolate);
-
- if (use_interpolate) {
- BLI_memarena_clear(interp_arena);
- }
- }
-
- /* we could flag new edges/verts too, is it useful? */
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, ELE_NEW);
-
- if (use_interpolate) {
- BLI_memarena_free(interp_arena);
- }
+ BMFace *f;
+
+ BMOIter oiter;
+ MemArena *interp_arena = NULL;
+
+ const float thickness = BMO_slot_float_get(op->slots_in, "thickness");
+ const float depth = BMO_slot_float_get(op->slots_in, "depth");
+ const bool use_even_offset = BMO_slot_bool_get(op->slots_in, "use_even_offset");
+ const bool use_relative_offset = BMO_slot_bool_get(op->slots_in, "use_relative_offset");
+ const bool use_interpolate = BMO_slot_bool_get(op->slots_in, "use_interpolate");
+
+ /* Only tag faces in slot */
+ BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false);
+
+ BMO_slot_buffer_hflag_enable(bm, op->slots_in, "faces", BM_FACE, BM_ELEM_TAG, false);
+
+ if (use_interpolate) {
+ interp_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+ }
+
+ BMO_ITER (f, &oiter, op->slots_in, "faces", BM_FACE) {
+ bmo_face_inset_individual(bm,
+ f,
+ interp_arena,
+ thickness,
+ depth,
+ use_even_offset,
+ use_relative_offset,
+ use_interpolate);
+
+ if (use_interpolate) {
+ BLI_memarena_clear(interp_arena);
+ }
+ }
+
+ /* we could flag new edges/verts too, is it useful? */
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, ELE_NEW);
+
+ if (use_interpolate) {
+ BLI_memarena_free(interp_arena);
+ }
}
-
-
/* -------------------------------------------------------------------- */
/* Inset Region */
typedef struct SplitEdgeInfo {
- float no[3];
- float length;
- BMEdge *e_old;
- BMEdge *e_new;
- BMLoop *l;
+ float no[3];
+ float length;
+ BMEdge *e_old;
+ BMEdge *e_new;
+ BMLoop *l;
} SplitEdgeInfo;
/**
@@ -471,53 +469,52 @@ typedef struct SplitEdgeInfo {
*/
static BMLoop *bm_edge_is_mixed_face_tag(BMLoop *l)
{
- if (LIKELY(l != NULL)) {
- int tot_tag = 0;
- int tot_untag = 0;
- BMLoop *l_iter;
- BMLoop *l_tag = NULL;
- l_iter = l;
- do {
- if (BM_elem_flag_test(l_iter->f, BM_ELEM_TAG)) {
- /* more than one tagged face - bail out early! */
- if (tot_tag == 1) {
- return NULL;
- }
- l_tag = l_iter;
- tot_tag++;
- }
- else {
- tot_untag++;
- }
-
- } while ((l_iter = l_iter->radial_next) != l);
-
- return ((tot_tag == 1) && (tot_untag >= 1)) ? l_tag : NULL;
- }
- else {
- return NULL;
- }
+ if (LIKELY(l != NULL)) {
+ int tot_tag = 0;
+ int tot_untag = 0;
+ BMLoop *l_iter;
+ BMLoop *l_tag = NULL;
+ l_iter = l;
+ do {
+ if (BM_elem_flag_test(l_iter->f, BM_ELEM_TAG)) {
+ /* more than one tagged face - bail out early! */
+ if (tot_tag == 1) {
+ return NULL;
+ }
+ l_tag = l_iter;
+ tot_tag++;
+ }
+ else {
+ tot_untag++;
+ }
+
+ } while ((l_iter = l_iter->radial_next) != l);
+
+ return ((tot_tag == 1) && (tot_untag >= 1)) ? l_tag : NULL;
+ }
+ else {
+ return NULL;
+ }
}
static float bm_edge_info_average_length(BMVert *v, SplitEdgeInfo *edge_info)
{
- BMIter iter;
- BMEdge *e;
-
- float len = 0.0f;
- int tot = 0;
-
-
- BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
- const int i = BM_elem_index_get(e);
- if (i != -1) {
- len += edge_info[i].length;
- tot++;
- }
- }
-
- BLI_assert(tot != 0);
- return len / (float)tot;
+ BMIter iter;
+ BMEdge *e;
+
+ float len = 0.0f;
+ int tot = 0;
+
+ BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
+ const int i = BM_elem_index_get(e);
+ if (i != -1) {
+ len += edge_info[i].length;
+ tot++;
+ }
+ }
+
+ BLI_assert(tot != 0);
+ return len / (float)tot;
}
/**
@@ -532,683 +529,697 @@ static float bm_edge_info_average_length(BMVert *v, SplitEdgeInfo *edge_info)
void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
{
- const bool use_outset = BMO_slot_bool_get(op->slots_in, "use_outset");
- const bool use_boundary = BMO_slot_bool_get(op->slots_in, "use_boundary") && (use_outset == false);
- const bool use_even_offset = BMO_slot_bool_get(op->slots_in, "use_even_offset");
- const bool use_even_boundary = use_even_offset; /* could make own option */
- const bool use_relative_offset = BMO_slot_bool_get(op->slots_in, "use_relative_offset");
- const bool use_edge_rail = BMO_slot_bool_get(op->slots_in, "use_edge_rail");
- const bool use_interpolate = BMO_slot_bool_get(op->slots_in, "use_interpolate");
- const float thickness = BMO_slot_float_get(op->slots_in, "thickness");
- const float depth = BMO_slot_float_get(op->slots_in, "depth");
+ const bool use_outset = BMO_slot_bool_get(op->slots_in, "use_outset");
+ const bool use_boundary = BMO_slot_bool_get(op->slots_in, "use_boundary") &&
+ (use_outset == false);
+ const bool use_even_offset = BMO_slot_bool_get(op->slots_in, "use_even_offset");
+ const bool use_even_boundary = use_even_offset; /* could make own option */
+ const bool use_relative_offset = BMO_slot_bool_get(op->slots_in, "use_relative_offset");
+ const bool use_edge_rail = BMO_slot_bool_get(op->slots_in, "use_edge_rail");
+ const bool use_interpolate = BMO_slot_bool_get(op->slots_in, "use_interpolate");
+ const float thickness = BMO_slot_float_get(op->slots_in, "thickness");
+ const float depth = BMO_slot_float_get(op->slots_in, "depth");
#ifdef USE_LOOP_CUSTOMDATA_MERGE
- const bool has_math_ldata = (use_interpolate && CustomData_has_math(&bm->ldata));
+ const bool has_math_ldata = (use_interpolate && CustomData_has_math(&bm->ldata));
#endif
- int edge_info_len = 0;
-
- BMIter iter;
- SplitEdgeInfo *edge_info;
- SplitEdgeInfo *es;
-
- /* Interpolation Vars */
- /* an array alligned with faces but only fill items which are used. */
- InterpFace **iface_array = NULL;
- int iface_array_len;
- MemArena *interp_arena = NULL;
-
- /* BMVert original location storage */
- const bool use_vert_coords_orig = use_edge_rail;
- MemArena *vert_coords_orig = NULL;
- GHash *vert_coords = NULL;
-
- BMVert *v;
- BMEdge *e;
- BMFace *f;
- int i, k;
-
- if (use_interpolate) {
- interp_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
- /* warning, we could be more clever here and not over alloc */
- iface_array = MEM_callocN(sizeof(*iface_array) * bm->totface, __func__);
- iface_array_len = bm->totface;
- }
-
- if (use_outset == false) {
- BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false);
- BMO_slot_buffer_hflag_enable(bm, op->slots_in, "faces", BM_FACE, BM_ELEM_TAG, false);
- }
- else {
- BM_mesh_elem_hflag_enable_all(bm, BM_FACE, BM_ELEM_TAG, false);
- BMO_slot_buffer_hflag_disable(bm, op->slots_in, "faces", BM_FACE, BM_ELEM_TAG, false);
- BMO_slot_buffer_hflag_disable(bm, op->slots_in, "faces_exclude", BM_FACE, BM_ELEM_TAG, false);
- }
-
- /* first count all inset edges we will split */
- /* fill in array and initialize tagging */
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (
- /* tag if boundary is enabled */
- (use_boundary && BM_edge_is_boundary(e) && BM_elem_flag_test(e->l->f, BM_ELEM_TAG)) ||
-
- /* tag if edge is an interior edge inbetween a tagged and untagged face */
- (bm_edge_is_mixed_face_tag(e->l)))
- {
- /* tag */
- BM_elem_flag_enable(e->v1, BM_ELEM_TAG);
- BM_elem_flag_enable(e->v2, BM_ELEM_TAG);
- BM_elem_flag_enable(e, BM_ELEM_TAG);
-
- BM_elem_index_set(e, edge_info_len); /* set_dirty! */
- edge_info_len++;
- }
- else {
- BM_elem_flag_disable(e->v1, BM_ELEM_TAG);
- BM_elem_flag_disable(e->v2, BM_ELEM_TAG);
- BM_elem_flag_disable(e, BM_ELEM_TAG);
-
- BM_elem_index_set(e, -1); /* set_dirty! */
- }
- }
- bm->elem_index_dirty |= BM_EDGE;
-
- edge_info = MEM_mallocN(edge_info_len * sizeof(SplitEdgeInfo), __func__);
-
- /* fill in array and initialize tagging */
- es = edge_info;
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- i = BM_elem_index_get(e);
- if (i != -1) {
- /* calc edge-split info */
- es->length = BM_edge_calc_length(e);
- es->e_old = e;
- es++;
- /* initialize no and e_new after */
- }
- }
-
-
- if (use_vert_coords_orig) {
- vert_coords_orig = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
- vert_coords = BLI_ghash_ptr_new(__func__);
- }
-
- /* util macros */
-#define VERT_ORIG_STORE(_v) { \
- float *_co = BLI_memarena_alloc(vert_coords_orig, sizeof(float[3])); \
- copy_v3_v3(_co, (_v)->co); \
- BLI_ghash_insert(vert_coords, _v, _co); \
- } (void)0
-#define VERT_ORIG_GET(_v) \
- (const float *)BLI_ghash_lookup_default(vert_coords, (_v), (_v)->co)
- /* memory for the coords isn't given back to the arena,
- * acceptable in this case since it runs a fixed number of times. */
-#define VERT_ORIG_REMOVE(_v) \
- BLI_ghash_remove(vert_coords, (_v), NULL, NULL)
-
-
- for (i = 0, es = edge_info; i < edge_info_len; i++, es++) {
- if ((es->l = bm_edge_is_mixed_face_tag(es->e_old->l))) {
- /* do nothing */
- }
- else {
- es->l = es->e_old->l; /* must be a boundary */
- }
-
- /* run the separate arg */
- if (!BM_edge_is_boundary(es->e_old)) {
- bmesh_kernel_edge_separate(bm, es->e_old, es->l, false);
- }
-
- /* calc edge-split info */
- es->e_new = es->l->e;
- BM_edge_calc_face_tangent(es->e_new, es->l, es->no);
-
- if (es->e_new == es->e_old) { /* happens on boundary edges */
- /* take care here, we're creating this double edge which _must_ have its verts replaced later on */
- es->e_old = BM_edge_create(bm, es->e_new->v1, es->e_new->v2, es->e_new, BM_CREATE_NOP);
- }
-
- /* store index back to original in 'edge_info' */
- BM_elem_index_set(es->e_new, i);
- BM_elem_flag_enable(es->e_new, BM_ELEM_TAG);
-
- /* important to tag again here */
- BM_elem_flag_enable(es->e_new->v1, BM_ELEM_TAG);
- BM_elem_flag_enable(es->e_new->v2, BM_ELEM_TAG);
-
-
- /* initialize interpolation vars */
- /* this could go in its own loop,
- * only use the 'es->l->f' so we don't store loops for faces which have no mixed selection
- *
- * note: faces on the other side of the inset will be interpolated too since this is hard to
- * detect, just allow it even though it will cause some redundant interpolation */
- if (use_interpolate) {
- BMIter viter;
- BM_ITER_ELEM (v, &viter, es->l->e, BM_VERTS_OF_EDGE) {
- BMIter fiter;
- BM_ITER_ELEM (f, &fiter, v, BM_FACES_OF_VERT) {
- const int j = BM_elem_index_get(f);
- if (iface_array[j] == NULL) {
- InterpFace *iface = BLI_memarena_alloc(interp_arena, sizeof(*iface));
- bm_interp_face_store(iface, bm, f, interp_arena);
- iface_array[j] = iface;
- }
- }
- }
- }
- /* done interpolation */
- }
-
- /* show edge normals for debugging */
+ int edge_info_len = 0;
+
+ BMIter iter;
+ SplitEdgeInfo *edge_info;
+ SplitEdgeInfo *es;
+
+ /* Interpolation Vars */
+ /* an array alligned with faces but only fill items which are used. */
+ InterpFace **iface_array = NULL;
+ int iface_array_len;
+ MemArena *interp_arena = NULL;
+
+ /* BMVert original location storage */
+ const bool use_vert_coords_orig = use_edge_rail;
+ MemArena *vert_coords_orig = NULL;
+ GHash *vert_coords = NULL;
+
+ BMVert *v;
+ BMEdge *e;
+ BMFace *f;
+ int i, k;
+
+ if (use_interpolate) {
+ interp_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+ /* warning, we could be more clever here and not over alloc */
+ iface_array = MEM_callocN(sizeof(*iface_array) * bm->totface, __func__);
+ iface_array_len = bm->totface;
+ }
+
+ if (use_outset == false) {
+ BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false);
+ BMO_slot_buffer_hflag_enable(bm, op->slots_in, "faces", BM_FACE, BM_ELEM_TAG, false);
+ }
+ else {
+ BM_mesh_elem_hflag_enable_all(bm, BM_FACE, BM_ELEM_TAG, false);
+ BMO_slot_buffer_hflag_disable(bm, op->slots_in, "faces", BM_FACE, BM_ELEM_TAG, false);
+ BMO_slot_buffer_hflag_disable(bm, op->slots_in, "faces_exclude", BM_FACE, BM_ELEM_TAG, false);
+ }
+
+ /* first count all inset edges we will split */
+ /* fill in array and initialize tagging */
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (
+ /* tag if boundary is enabled */
+ (use_boundary && BM_edge_is_boundary(e) && BM_elem_flag_test(e->l->f, BM_ELEM_TAG)) ||
+
+ /* tag if edge is an interior edge inbetween a tagged and untagged face */
+ (bm_edge_is_mixed_face_tag(e->l))) {
+ /* tag */
+ BM_elem_flag_enable(e->v1, BM_ELEM_TAG);
+ BM_elem_flag_enable(e->v2, BM_ELEM_TAG);
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
+
+ BM_elem_index_set(e, edge_info_len); /* set_dirty! */
+ edge_info_len++;
+ }
+ else {
+ BM_elem_flag_disable(e->v1, BM_ELEM_TAG);
+ BM_elem_flag_disable(e->v2, BM_ELEM_TAG);
+ BM_elem_flag_disable(e, BM_ELEM_TAG);
+
+ BM_elem_index_set(e, -1); /* set_dirty! */
+ }
+ }
+ bm->elem_index_dirty |= BM_EDGE;
+
+ edge_info = MEM_mallocN(edge_info_len * sizeof(SplitEdgeInfo), __func__);
+
+ /* fill in array and initialize tagging */
+ es = edge_info;
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ i = BM_elem_index_get(e);
+ if (i != -1) {
+ /* calc edge-split info */
+ es->length = BM_edge_calc_length(e);
+ es->e_old = e;
+ es++;
+ /* initialize no and e_new after */
+ }
+ }
+
+ if (use_vert_coords_orig) {
+ vert_coords_orig = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+ vert_coords = BLI_ghash_ptr_new(__func__);
+ }
+
+ /* util macros */
+#define VERT_ORIG_STORE(_v) \
+ { \
+ float *_co = BLI_memarena_alloc(vert_coords_orig, sizeof(float[3])); \
+ copy_v3_v3(_co, (_v)->co); \
+ BLI_ghash_insert(vert_coords, _v, _co); \
+ } \
+ (void)0
+#define VERT_ORIG_GET(_v) (const float *)BLI_ghash_lookup_default(vert_coords, (_v), (_v)->co)
+ /* memory for the coords isn't given back to the arena,
+ * acceptable in this case since it runs a fixed number of times. */
+#define VERT_ORIG_REMOVE(_v) BLI_ghash_remove(vert_coords, (_v), NULL, NULL)
+
+ for (i = 0, es = edge_info; i < edge_info_len; i++, es++) {
+ if ((es->l = bm_edge_is_mixed_face_tag(es->e_old->l))) {
+ /* do nothing */
+ }
+ else {
+ es->l = es->e_old->l; /* must be a boundary */
+ }
+
+ /* run the separate arg */
+ if (!BM_edge_is_boundary(es->e_old)) {
+ bmesh_kernel_edge_separate(bm, es->e_old, es->l, false);
+ }
+
+ /* calc edge-split info */
+ es->e_new = es->l->e;
+ BM_edge_calc_face_tangent(es->e_new, es->l, es->no);
+
+ if (es->e_new == es->e_old) { /* happens on boundary edges */
+ /* take care here, we're creating this double edge which _must_ have its verts replaced later on */
+ es->e_old = BM_edge_create(bm, es->e_new->v1, es->e_new->v2, es->e_new, BM_CREATE_NOP);
+ }
+
+ /* store index back to original in 'edge_info' */
+ BM_elem_index_set(es->e_new, i);
+ BM_elem_flag_enable(es->e_new, BM_ELEM_TAG);
+
+ /* important to tag again here */
+ BM_elem_flag_enable(es->e_new->v1, BM_ELEM_TAG);
+ BM_elem_flag_enable(es->e_new->v2, BM_ELEM_TAG);
+
+ /* initialize interpolation vars */
+ /* this could go in its own loop,
+ * only use the 'es->l->f' so we don't store loops for faces which have no mixed selection
+ *
+ * note: faces on the other side of the inset will be interpolated too since this is hard to
+ * detect, just allow it even though it will cause some redundant interpolation */
+ if (use_interpolate) {
+ BMIter viter;
+ BM_ITER_ELEM (v, &viter, es->l->e, BM_VERTS_OF_EDGE) {
+ BMIter fiter;
+ BM_ITER_ELEM (f, &fiter, v, BM_FACES_OF_VERT) {
+ const int j = BM_elem_index_get(f);
+ if (iface_array[j] == NULL) {
+ InterpFace *iface = BLI_memarena_alloc(interp_arena, sizeof(*iface));
+ bm_interp_face_store(iface, bm, f, interp_arena);
+ iface_array[j] = iface;
+ }
+ }
+ }
+ }
+ /* done interpolation */
+ }
+
+ /* show edge normals for debugging */
#if 0
- for (i = 0, es = edge_info; i < edge_info_len; i++, es++) {
- float tvec[3];
- BMVert *v1, *v2;
+ for (i = 0, es = edge_info; i < edge_info_len; i++, es++) {
+ float tvec[3];
+ BMVert *v1, *v2;
- mid_v3_v3v3(tvec, es->e_new->v1->co, es->e_new->v2->co);
+ mid_v3_v3v3(tvec, es->e_new->v1->co, es->e_new->v2->co);
- v1 = BM_vert_create(bm, tvec, NULL, BM_CREATE_NOP);
- v2 = BM_vert_create(bm, tvec, NULL, BM_CREATE_NOP);
- madd_v3_v3fl(v2->co, es->no, 0.1f);
- BM_edge_create(bm, v1, v2, NULL, 0);
- }
+ v1 = BM_vert_create(bm, tvec, NULL, BM_CREATE_NOP);
+ v2 = BM_vert_create(bm, tvec, NULL, BM_CREATE_NOP);
+ madd_v3_v3fl(v2->co, es->no, 0.1f);
+ BM_edge_create(bm, v1, v2, NULL, 0);
+ }
#endif
- /* execute the split and position verts, it would be most obvious to loop over verts
- * here but don't do this since we will be splitting them off (iterating stuff you modify is bad juju)
- * instead loop over edges then their verts */
- for (i = 0, es = edge_info; i < edge_info_len; i++, es++) {
- for (int j = 0; j < 2; j++) {
- v = (j == 0) ? es->e_new->v1 : es->e_new->v2;
-
- /* end confusing part - just pretend this is a typical loop on verts */
-
- /* only split of tagged verts - used by separated edges */
-
- /* comment the first part because we know this verts in a tagged face */
- if (/* v->e && */BM_elem_flag_test(v, BM_ELEM_TAG)) {
- BMVert **vout;
- int r_vout_len;
- BMVert *v_glue = NULL;
-
- /* disable touching twice, this _will_ happen if the flags not disabled */
- BM_elem_flag_disable(v, BM_ELEM_TAG);
-
- bmesh_kernel_vert_separate(bm, v, &vout, &r_vout_len, false);
- v = NULL; /* don't use again */
-
- /* in some cases the edge doesn't split off */
- if (r_vout_len == 1) {
- if (use_vert_coords_orig) {
- VERT_ORIG_STORE(vout[0]);
- }
- MEM_freeN(vout);
- continue;
- }
-
- for (k = 0; k < r_vout_len; k++) {
- BMVert *v_split = vout[k]; /* only to avoid vout[k] all over */
-
- /* need to check if this vertex is from a */
- int vert_edge_tag_tot = 0;
- int vecpair[2];
-
- if (use_vert_coords_orig) {
- VERT_ORIG_STORE(v_split);
- }
-
- /* find adjacent */
- BM_ITER_ELEM (e, &iter, v_split, BM_EDGES_OF_VERT) {
- if (BM_elem_flag_test(e, BM_ELEM_TAG) &&
- e->l && BM_elem_flag_test(e->l->f, BM_ELEM_TAG))
- {
- if (vert_edge_tag_tot < 2) {
- vecpair[vert_edge_tag_tot] = BM_elem_index_get(e);
- BLI_assert(vecpair[vert_edge_tag_tot] != -1);
- }
-
- vert_edge_tag_tot++;
- }
- }
-
- if (vert_edge_tag_tot != 0) {
- float tvec[3];
-
- if (vert_edge_tag_tot >= 2) { /* 2 edge users - common case */
- /* now there are 2 cases to check for,
- *
- * if both edges use the same face OR both faces have the same normal,
- * ...then we can calculate an edge that fits nicely between the 2 edge normals.
- *
- * Otherwise use the shared edge OR the corner defined by these 2 face normals,
- * when both edges faces are adjacent this works best but even when this vertex
- * fans out faces it should work ok.
- */
-
- SplitEdgeInfo *e_info_a = &edge_info[vecpair[0]];
- SplitEdgeInfo *e_info_b = &edge_info[vecpair[1]];
-
- BMFace *f_a = e_info_a->l->f;
- BMFace *f_b = e_info_b->l->f;
-
- /* set to true when we're not in-between (e_info_a->no, e_info_b->no) exactly
- * in this case use a check the angle of the tvec when calculating shell thickness */
- bool is_mid = true;
-
- /* we use this as either the normal OR to find the right direction for the
- * cross product between both face normals */
- add_v3_v3v3(tvec, e_info_a->no, e_info_b->no);
-
- if (use_edge_rail == false) {
- /* pass */
- }
- else if (f_a != f_b) {
- /* these lookups are very quick */
- BMLoop *l_other_a = BM_loop_other_vert_loop(e_info_a->l, v_split);
- BMLoop *l_other_b = BM_loop_other_vert_loop(e_info_b->l, v_split);
-
- if (l_other_a->v == l_other_b->v) {
- /* both edges faces are adjacent, but we don't need to know the shared edge
- * having both verts is enough. */
- const float *co_other;
-
- /* note that we can't use 'l_other_a->v' directly since it
- * may be inset and give a feedback loop. */
- if (use_vert_coords_orig) {
- co_other = VERT_ORIG_GET(l_other_a->v);
- }
- else {
- co_other = l_other_a->v->co;
- }
-
- sub_v3_v3v3(tvec, co_other, v_split->co);
- is_mid = false;
- }
-
- /* distable gives odd results at times, see [#39288] */
+ /* execute the split and position verts, it would be most obvious to loop over verts
+ * here but don't do this since we will be splitting them off (iterating stuff you modify is bad juju)
+ * instead loop over edges then their verts */
+ for (i = 0, es = edge_info; i < edge_info_len; i++, es++) {
+ for (int j = 0; j < 2; j++) {
+ v = (j == 0) ? es->e_new->v1 : es->e_new->v2;
+
+ /* end confusing part - just pretend this is a typical loop on verts */
+
+ /* only split of tagged verts - used by separated edges */
+
+ /* comment the first part because we know this verts in a tagged face */
+ if (/* v->e && */ BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ BMVert **vout;
+ int r_vout_len;
+ BMVert *v_glue = NULL;
+
+ /* disable touching twice, this _will_ happen if the flags not disabled */
+ BM_elem_flag_disable(v, BM_ELEM_TAG);
+
+ bmesh_kernel_vert_separate(bm, v, &vout, &r_vout_len, false);
+ v = NULL; /* don't use again */
+
+ /* in some cases the edge doesn't split off */
+ if (r_vout_len == 1) {
+ if (use_vert_coords_orig) {
+ VERT_ORIG_STORE(vout[0]);
+ }
+ MEM_freeN(vout);
+ continue;
+ }
+
+ for (k = 0; k < r_vout_len; k++) {
+ BMVert *v_split = vout[k]; /* only to avoid vout[k] all over */
+
+ /* need to check if this vertex is from a */
+ int vert_edge_tag_tot = 0;
+ int vecpair[2];
+
+ if (use_vert_coords_orig) {
+ VERT_ORIG_STORE(v_split);
+ }
+
+ /* find adjacent */
+ BM_ITER_ELEM (e, &iter, v_split, BM_EDGES_OF_VERT) {
+ if (BM_elem_flag_test(e, BM_ELEM_TAG) && e->l &&
+ BM_elem_flag_test(e->l->f, BM_ELEM_TAG)) {
+ if (vert_edge_tag_tot < 2) {
+ vecpair[vert_edge_tag_tot] = BM_elem_index_get(e);
+ BLI_assert(vecpair[vert_edge_tag_tot] != -1);
+ }
+
+ vert_edge_tag_tot++;
+ }
+ }
+
+ if (vert_edge_tag_tot != 0) {
+ float tvec[3];
+
+ if (vert_edge_tag_tot >= 2) { /* 2 edge users - common case */
+ /* now there are 2 cases to check for,
+ *
+ * if both edges use the same face OR both faces have the same normal,
+ * ...then we can calculate an edge that fits nicely between the 2 edge normals.
+ *
+ * Otherwise use the shared edge OR the corner defined by these 2 face normals,
+ * when both edges faces are adjacent this works best but even when this vertex
+ * fans out faces it should work ok.
+ */
+
+ SplitEdgeInfo *e_info_a = &edge_info[vecpair[0]];
+ SplitEdgeInfo *e_info_b = &edge_info[vecpair[1]];
+
+ BMFace *f_a = e_info_a->l->f;
+ BMFace *f_b = e_info_b->l->f;
+
+ /* set to true when we're not in-between (e_info_a->no, e_info_b->no) exactly
+ * in this case use a check the angle of the tvec when calculating shell thickness */
+ bool is_mid = true;
+
+ /* we use this as either the normal OR to find the right direction for the
+ * cross product between both face normals */
+ add_v3_v3v3(tvec, e_info_a->no, e_info_b->no);
+
+ if (use_edge_rail == false) {
+ /* pass */
+ }
+ else if (f_a != f_b) {
+ /* these lookups are very quick */
+ BMLoop *l_other_a = BM_loop_other_vert_loop(e_info_a->l, v_split);
+ BMLoop *l_other_b = BM_loop_other_vert_loop(e_info_b->l, v_split);
+
+ if (l_other_a->v == l_other_b->v) {
+ /* both edges faces are adjacent, but we don't need to know the shared edge
+ * having both verts is enough. */
+ const float *co_other;
+
+ /* note that we can't use 'l_other_a->v' directly since it
+ * may be inset and give a feedback loop. */
+ if (use_vert_coords_orig) {
+ co_other = VERT_ORIG_GET(l_other_a->v);
+ }
+ else {
+ co_other = l_other_a->v->co;
+ }
+
+ sub_v3_v3v3(tvec, co_other, v_split->co);
+ is_mid = false;
+ }
+
+ /* distable gives odd results at times, see [#39288] */
#if 0
- else if (compare_v3v3(f_a->no, f_b->no, 0.001f) == false) {
- /* epsilon increased to fix [#32329] */
-
- /* faces don't touch,
- * just get cross product of their normals, its *good enough*
- */
- float tno[3];
- cross_v3_v3v3(tno, f_a->no, f_b->no);
- if (dot_v3v3(tvec, tno) < 0.0f) {
- negate_v3(tno);
- }
- copy_v3_v3(tvec, tno);
- is_mid = false;
- }
+ else if (compare_v3v3(f_a->no, f_b->no, 0.001f) == false) {
+ /* epsilon increased to fix [#32329] */
+
+ /* faces don't touch,
+ * just get cross product of their normals, its *good enough*
+ */
+ float tno[3];
+ cross_v3_v3v3(tno, f_a->no, f_b->no);
+ if (dot_v3v3(tvec, tno) < 0.0f) {
+ negate_v3(tno);
+ }
+ copy_v3_v3(tvec, tno);
+ is_mid = false;
+ }
#endif
- }
- normalize_v3(tvec);
-
- /* scale by edge angle */
- if (use_even_offset) {
- if (is_mid) {
- mul_v3_fl(tvec, shell_v3v3_mid_normalized_to_dist(e_info_a->no,
- e_info_b->no));
- }
- else {
- /* use the largest angle */
- mul_v3_fl(tvec,
- shell_v3v3_normalized_to_dist(tvec,
- len_squared_v3v3(tvec, e_info_a->no) >
- len_squared_v3v3(tvec, e_info_b->no) ?
- e_info_a->no : e_info_b->no));
- }
- }
-
- /* scale relative to edge lengths */
- if (use_relative_offset) {
- mul_v3_fl(tvec, (edge_info[vecpair[0]].length + edge_info[vecpair[1]].length) / 2.0f);
- }
- }
- else if (vert_edge_tag_tot == 1) { /* 1 edge user - boundary vert, not so common */
- const float *e_no_a = edge_info[vecpair[0]].no;
-
- if (use_even_boundary) {
-
- /* This case where only one edge attached to v_split
- * is used - ei - the face to inset is on a boundary.
- *
- * We want the inset to align flush with the
- * boundary edge, not the normal of the interior
- * <--- edge which would give an unsightly bump.
- * --+-------------------------+---------------+--
- * |^v_other ^e_other /^v_split |
- * | / |
- * | / |
- * | / <- tag split edge |
- * | / |
- * | / |
- * | / |
- * --+-----------------+-----------------------+--
- * | |
- * | |
- *
- * note, the fact we are doing location comparisons on verts that are moved about
- * doesn't matter because the direction will remain the same in this case.
- */
-
- BMEdge *e_other;
- BMVert *v_other;
- /* loop will always be either next of prev */
- BMLoop *l = v_split->e->l;
- if (l->prev->v == v_split) {
- l = l->prev;
- }
- else if (l->next->v == v_split) {
- l = l->next;
- }
- else if (l->v == v_split) {
- /* pass */
- }
- else {
- /* should never happen */
- BLI_assert(0);
- }
-
- /* find the edge which is _not_ being split here */
- if (!BM_elem_flag_test(l->e, BM_ELEM_TAG)) {
- e_other = l->e;
- }
- else if (!BM_elem_flag_test(l->prev->e, BM_ELEM_TAG)) {
- e_other = l->prev->e;
- }
- else {
- BLI_assert(0);
- e_other = NULL;
- }
-
- v_other = BM_edge_other_vert(e_other, v_split);
- sub_v3_v3v3(tvec, v_other->co, v_split->co);
- normalize_v3(tvec);
-
- if (use_even_offset) {
- mul_v3_fl(tvec, shell_v3v3_normalized_to_dist(e_no_a, tvec));
- }
- }
- else {
- copy_v3_v3(tvec, e_no_a);
- }
-
- /* use_even_offset - doesn't apply here */
-
- /* scale relative to edge length */
- if (use_relative_offset) {
- mul_v3_fl(tvec, edge_info[vecpair[0]].length);
- }
- }
- else {
- /* should never happen */
- BLI_assert(0);
- zero_v3(tvec);
- }
-
- /* apply the offset */
- madd_v3_v3fl(v_split->co, tvec, thickness);
- }
-
- /* this saves expensive/slow glue check for common cases */
- if (r_vout_len > 2) {
- bool ok = true;
- /* last step, NULL this vertex if has a tagged face */
- BM_ITER_ELEM (f, &iter, v_split, BM_FACES_OF_VERT) {
- if (BM_elem_flag_test(f, BM_ELEM_TAG)) {
- ok = false;
- break;
- }
- }
-
- if (ok) {
- if (v_glue == NULL) {
- v_glue = v_split;
- }
- else {
- if (BM_vert_splice(bm, v_glue, v_split)) {
- if (use_vert_coords_orig) {
- VERT_ORIG_REMOVE(v_split);
- }
- }
- }
- }
- }
- /* end glue */
-
- }
- MEM_freeN(vout);
- }
- }
- }
-
- if (use_vert_coords_orig) {
- BLI_memarena_free(vert_coords_orig);
- BLI_ghash_free(vert_coords, NULL, NULL);
- }
-
- if (use_interpolate) {
- for (i = 0; i < iface_array_len; i++) {
- if (iface_array[i]) {
- InterpFace *iface = iface_array[i];
- BM_face_interp_from_face_ex(
- bm, iface->f, iface->f, true,
- (const void **)iface->blocks_l, (const void **)iface->blocks_v,
- iface->cos_2d, iface->axis_mat);
- }
- }
- }
-
- /* create faces */
- for (i = 0, es = edge_info; i < edge_info_len; i++, es++) {
- BMVert *varr[4] = {NULL};
- int j;
- /* get the verts in the correct order */
- BM_edge_ordered_verts_ex(es->e_new, &varr[1], &varr[0], es->l);
+ }
+ normalize_v3(tvec);
+
+ /* scale by edge angle */
+ if (use_even_offset) {
+ if (is_mid) {
+ mul_v3_fl(tvec, shell_v3v3_mid_normalized_to_dist(e_info_a->no, e_info_b->no));
+ }
+ else {
+ /* use the largest angle */
+ mul_v3_fl(
+ tvec,
+ shell_v3v3_normalized_to_dist(tvec,
+ len_squared_v3v3(tvec, e_info_a->no) >
+ len_squared_v3v3(tvec, e_info_b->no) ?
+ e_info_a->no :
+ e_info_b->no));
+ }
+ }
+
+ /* scale relative to edge lengths */
+ if (use_relative_offset) {
+ mul_v3_fl(tvec,
+ (edge_info[vecpair[0]].length + edge_info[vecpair[1]].length) / 2.0f);
+ }
+ }
+ else if (vert_edge_tag_tot == 1) { /* 1 edge user - boundary vert, not so common */
+ const float *e_no_a = edge_info[vecpair[0]].no;
+
+ if (use_even_boundary) {
+
+ /* This case where only one edge attached to v_split
+ * is used - ei - the face to inset is on a boundary.
+ *
+ * We want the inset to align flush with the
+ * boundary edge, not the normal of the interior
+ * <--- edge which would give an unsightly bump.
+ * --+-------------------------+---------------+--
+ * |^v_other ^e_other /^v_split |
+ * | / |
+ * | / |
+ * | / <- tag split edge |
+ * | / |
+ * | / |
+ * | / |
+ * --+-----------------+-----------------------+--
+ * | |
+ * | |
+ *
+ * note, the fact we are doing location comparisons on verts that are moved about
+ * doesn't matter because the direction will remain the same in this case.
+ */
+
+ BMEdge *e_other;
+ BMVert *v_other;
+ /* loop will always be either next of prev */
+ BMLoop *l = v_split->e->l;
+ if (l->prev->v == v_split) {
+ l = l->prev;
+ }
+ else if (l->next->v == v_split) {
+ l = l->next;
+ }
+ else if (l->v == v_split) {
+ /* pass */
+ }
+ else {
+ /* should never happen */
+ BLI_assert(0);
+ }
+
+ /* find the edge which is _not_ being split here */
+ if (!BM_elem_flag_test(l->e, BM_ELEM_TAG)) {
+ e_other = l->e;
+ }
+ else if (!BM_elem_flag_test(l->prev->e, BM_ELEM_TAG)) {
+ e_other = l->prev->e;
+ }
+ else {
+ BLI_assert(0);
+ e_other = NULL;
+ }
+
+ v_other = BM_edge_other_vert(e_other, v_split);
+ sub_v3_v3v3(tvec, v_other->co, v_split->co);
+ normalize_v3(tvec);
+
+ if (use_even_offset) {
+ mul_v3_fl(tvec, shell_v3v3_normalized_to_dist(e_no_a, tvec));
+ }
+ }
+ else {
+ copy_v3_v3(tvec, e_no_a);
+ }
+
+ /* use_even_offset - doesn't apply here */
+
+ /* scale relative to edge length */
+ if (use_relative_offset) {
+ mul_v3_fl(tvec, edge_info[vecpair[0]].length);
+ }
+ }
+ else {
+ /* should never happen */
+ BLI_assert(0);
+ zero_v3(tvec);
+ }
+
+ /* apply the offset */
+ madd_v3_v3fl(v_split->co, tvec, thickness);
+ }
+
+ /* this saves expensive/slow glue check for common cases */
+ if (r_vout_len > 2) {
+ bool ok = true;
+ /* last step, NULL this vertex if has a tagged face */
+ BM_ITER_ELEM (f, &iter, v_split, BM_FACES_OF_VERT) {
+ if (BM_elem_flag_test(f, BM_ELEM_TAG)) {
+ ok = false;
+ break;
+ }
+ }
+
+ if (ok) {
+ if (v_glue == NULL) {
+ v_glue = v_split;
+ }
+ else {
+ if (BM_vert_splice(bm, v_glue, v_split)) {
+ if (use_vert_coords_orig) {
+ VERT_ORIG_REMOVE(v_split);
+ }
+ }
+ }
+ }
+ }
+ /* end glue */
+ }
+ MEM_freeN(vout);
+ }
+ }
+ }
+
+ if (use_vert_coords_orig) {
+ BLI_memarena_free(vert_coords_orig);
+ BLI_ghash_free(vert_coords, NULL, NULL);
+ }
+
+ if (use_interpolate) {
+ for (i = 0; i < iface_array_len; i++) {
+ if (iface_array[i]) {
+ InterpFace *iface = iface_array[i];
+ BM_face_interp_from_face_ex(bm,
+ iface->f,
+ iface->f,
+ true,
+ (const void **)iface->blocks_l,
+ (const void **)iface->blocks_v,
+ iface->cos_2d,
+ iface->axis_mat);
+ }
+ }
+ }
+
+ /* create faces */
+ for (i = 0, es = edge_info; i < edge_info_len; i++, es++) {
+ BMVert *varr[4] = {NULL};
+ int j;
+ /* get the verts in the correct order */
+ BM_edge_ordered_verts_ex(es->e_new, &varr[1], &varr[0], es->l);
#if 0
- if (varr[0] == es->e_new->v1) {
- varr[2] = es->e_old->v2;
- varr[3] = es->e_old->v1;
- }
- else {
- varr[2] = es->e_old->v1;
- varr[3] = es->e_old->v2;
- }
- j = 4;
+ if (varr[0] == es->e_new->v1) {
+ varr[2] = es->e_old->v2;
+ varr[3] = es->e_old->v1;
+ }
+ else {
+ varr[2] = es->e_old->v1;
+ varr[3] = es->e_old->v2;
+ }
+ j = 4;
#else
- /* slightly trickier check - since we can't assume the verts are split */
- j = 2; /* 2 edges are set */
- if (varr[0] == es->e_new->v1) {
- if (es->e_old->v2 != es->e_new->v2) { varr[j++] = es->e_old->v2; }
- if (es->e_old->v1 != es->e_new->v1) { varr[j++] = es->e_old->v1; }
- }
- else {
- if (es->e_old->v1 != es->e_new->v1) { varr[j++] = es->e_old->v1; }
- if (es->e_old->v2 != es->e_new->v2) { varr[j++] = es->e_old->v2; }
- }
-
- if (j == 2) {
- /* can't make face! */
- continue;
- }
+ /* slightly trickier check - since we can't assume the verts are split */
+ j = 2; /* 2 edges are set */
+ if (varr[0] == es->e_new->v1) {
+ if (es->e_old->v2 != es->e_new->v2) {
+ varr[j++] = es->e_old->v2;
+ }
+ if (es->e_old->v1 != es->e_new->v1) {
+ varr[j++] = es->e_old->v1;
+ }
+ }
+ else {
+ if (es->e_old->v1 != es->e_new->v1) {
+ varr[j++] = es->e_old->v1;
+ }
+ if (es->e_old->v2 != es->e_new->v2) {
+ varr[j++] = es->e_old->v2;
+ }
+ }
+
+ if (j == 2) {
+ /* can't make face! */
+ continue;
+ }
#endif
- /* no need to check doubles, we KNOW there won't be any */
- /* yes - reverse face is correct in this case */
- f = BM_face_create_verts(bm, varr, j, es->l->f, BM_CREATE_NOP, true);
- BMO_face_flag_enable(bm, f, ELE_NEW);
-
- /* copy for loop data, otherwise UV's and vcols are no good.
- * tiny speedup here we could be more clever and copy from known adjacent data
- * also - we could attempt to interpolate the loop data, this would be much slower but more useful too */
+ /* no need to check doubles, we KNOW there won't be any */
+ /* yes - reverse face is correct in this case */
+ f = BM_face_create_verts(bm, varr, j, es->l->f, BM_CREATE_NOP, true);
+ BMO_face_flag_enable(bm, f, ELE_NEW);
+
+ /* copy for loop data, otherwise UV's and vcols are no good.
+ * tiny speedup here we could be more clever and copy from known adjacent data
+ * also - we could attempt to interpolate the loop data, this would be much slower but more useful too */
#if 0
- /* don't use this because face boundaries have no adjacent loops and won't be filled in.
- * instead copy from the opposite side with the code below */
- BM_face_copy_shared(bm, f, NULL, NULL);
+ /* don't use this because face boundaries have no adjacent loops and won't be filled in.
+ * instead copy from the opposite side with the code below */
+ BM_face_copy_shared(bm, f, NULL, NULL);
#else
- {
- /* 2 inner loops on the edge between the new face and the original */
- BMLoop *l_a;
- BMLoop *l_b;
- BMLoop *l_a_other;
- BMLoop *l_b_other;
-
- l_a = BM_FACE_FIRST_LOOP(f);
- l_b = l_a->next;
-
- /* we know this side has a radial_next because of the order of created verts in the quad */
- l_a_other = BM_edge_other_loop(l_a->e, l_a);
- l_b_other = BM_edge_other_loop(l_a->e, l_b);
- BM_elem_attrs_copy(bm, bm, l_a_other, l_a);
- BM_elem_attrs_copy(bm, bm, l_b_other, l_b);
-
- BLI_assert(l_a->f != l_a_other->f);
- BLI_assert(l_b->f != l_b_other->f);
-
- /* step around to the opposite side of the quad - warning, this may have no other edges! */
- l_a = l_a->next->next;
- l_b = l_a->next;
-
- /**
- * Loops vars from newly created face (face_a/b)
- * <pre>
- * l_a->e & l_b->prev->e
- * +------------------------------------+
- * |\ l_a l_b /|
- * | \ l_a->prev->e l_b->e / |
- * | \ l_a->prev l_b->next / |
- * | +----------------------------+ |
- * | |l_a_other ^ l_b_other| |
- * | | l_b->next->e &... | |
- * | | l_a->prev->prev->e | |
- * | | (inset face) | |
- * | +----------------------------+ |
- * | / \ |
- * | / \ |
- * |/ \|
- * +------------------------------------+
- * </pre>
- */
-
- /* swap a<->b intentionally */
- if (use_interpolate) {
- InterpFace *iface = iface_array[BM_elem_index_get(es->l->f)];
- const int i_a = BM_elem_index_get(l_a_other);
- const int i_b = BM_elem_index_get(l_b_other);
- CustomData_bmesh_free_block_data(&bm->ldata, l_b->head.data);
- CustomData_bmesh_free_block_data(&bm->ldata, l_a->head.data);
- CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, iface->blocks_l[i_a], &l_b->head.data);
- CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, iface->blocks_l[i_b], &l_a->head.data);
-
-#ifdef USE_LOOP_CUSTOMDATA_MERGE
- if (has_math_ldata) {
- BMEdge *e_connect;
-
- /* connecting edge 'a' */
- e_connect = l_a->prev->e;
- if (BM_edge_is_manifold(e_connect)) {
- bm_loop_customdata_merge(
- bm, e_connect,
- l_a, BM_edge_other_loop(e_connect, l_a),
- l_a->prev, BM_edge_other_loop(e_connect, l_a->prev));
- }
-
- /* connecting edge 'b' */
- e_connect = l_b->e;
- if (BM_edge_is_manifold(e_connect)) {
- /* swap arg order to maintain winding */
- bm_loop_customdata_merge(
- bm, e_connect,
- l_b, BM_edge_other_loop(e_connect, l_b),
- l_b->next, BM_edge_other_loop(e_connect, l_b->next));
- }
- }
-#endif /* USE_LOOP_CUSTOMDATA_MERGE */
- }
- else {
- BM_elem_attrs_copy(bm, bm, l_a_other, l_b);
- BM_elem_attrs_copy(bm, bm, l_b_other, l_a);
- }
- }
- }
+ {
+ /* 2 inner loops on the edge between the new face and the original */
+ BMLoop *l_a;
+ BMLoop *l_b;
+ BMLoop *l_a_other;
+ BMLoop *l_b_other;
+
+ l_a = BM_FACE_FIRST_LOOP(f);
+ l_b = l_a->next;
+
+ /* we know this side has a radial_next because of the order of created verts in the quad */
+ l_a_other = BM_edge_other_loop(l_a->e, l_a);
+ l_b_other = BM_edge_other_loop(l_a->e, l_b);
+ BM_elem_attrs_copy(bm, bm, l_a_other, l_a);
+ BM_elem_attrs_copy(bm, bm, l_b_other, l_b);
+
+ BLI_assert(l_a->f != l_a_other->f);
+ BLI_assert(l_b->f != l_b_other->f);
+
+ /* step around to the opposite side of the quad - warning, this may have no other edges! */
+ l_a = l_a->next->next;
+ l_b = l_a->next;
+
+ /**
+ * Loops vars from newly created face (face_a/b)
+ * <pre>
+ * l_a->e & l_b->prev->e
+ * +------------------------------------+
+ * |\ l_a l_b /|
+ * | \ l_a->prev->e l_b->e / |
+ * | \ l_a->prev l_b->next / |
+ * | +----------------------------+ |
+ * | |l_a_other ^ l_b_other| |
+ * | | l_b->next->e &... | |
+ * | | l_a->prev->prev->e | |
+ * | | (inset face) | |
+ * | +----------------------------+ |
+ * | / \ |
+ * | / \ |
+ * |/ \|
+ * +------------------------------------+
+ * </pre>
+ */
+
+ /* swap a<->b intentionally */
+ if (use_interpolate) {
+ InterpFace *iface = iface_array[BM_elem_index_get(es->l->f)];
+ const int i_a = BM_elem_index_get(l_a_other);
+ const int i_b = BM_elem_index_get(l_b_other);
+ CustomData_bmesh_free_block_data(&bm->ldata, l_b->head.data);
+ CustomData_bmesh_free_block_data(&bm->ldata, l_a->head.data);
+ CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, iface->blocks_l[i_a], &l_b->head.data);
+ CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, iface->blocks_l[i_b], &l_a->head.data);
+
+# ifdef USE_LOOP_CUSTOMDATA_MERGE
+ if (has_math_ldata) {
+ BMEdge *e_connect;
+
+ /* connecting edge 'a' */
+ e_connect = l_a->prev->e;
+ if (BM_edge_is_manifold(e_connect)) {
+ bm_loop_customdata_merge(bm,
+ e_connect,
+ l_a,
+ BM_edge_other_loop(e_connect, l_a),
+ l_a->prev,
+ BM_edge_other_loop(e_connect, l_a->prev));
+ }
+
+ /* connecting edge 'b' */
+ e_connect = l_b->e;
+ if (BM_edge_is_manifold(e_connect)) {
+ /* swap arg order to maintain winding */
+ bm_loop_customdata_merge(bm,
+ e_connect,
+ l_b,
+ BM_edge_other_loop(e_connect, l_b),
+ l_b->next,
+ BM_edge_other_loop(e_connect, l_b->next));
+ }
+ }
+# endif /* USE_LOOP_CUSTOMDATA_MERGE */
+ }
+ else {
+ BM_elem_attrs_copy(bm, bm, l_a_other, l_b);
+ BM_elem_attrs_copy(bm, bm, l_b_other, l_a);
+ }
+ }
+ }
#endif
- if (use_interpolate) {
- for (i = 0; i < iface_array_len; i++) {
- if (iface_array[i]) {
- bm_interp_face_free(iface_array[i], bm);
- }
- }
-
- BLI_memarena_free(interp_arena);
- MEM_freeN(iface_array);
- }
-
- /* we could flag new edges/verts too, is it useful? */
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, ELE_NEW);
-
- /* cheap feature to add depth to the inset */
- if (depth != 0.0f) {
- float (*varr_co)[3];
- BMOIter oiter;
-
- /* we need to re-calculate tagged normals, but for this purpose we can copy tagged verts from the
- * faces they inset from, */
- for (i = 0, es = edge_info; i < edge_info_len; i++, es++) {
- zero_v3(es->e_new->v1->no);
- zero_v3(es->e_new->v2->no);
- }
- for (i = 0, es = edge_info; i < edge_info_len; i++, es++) {
- const float *no = es->l->f->no;
- add_v3_v3(es->e_new->v1->no, no);
- add_v3_v3(es->e_new->v2->no, no);
- }
- for (i = 0, es = edge_info; i < edge_info_len; i++, es++) {
- /* annoying, avoid normalizing twice */
- if (len_squared_v3(es->e_new->v1->no) != 1.0f) {
- normalize_v3(es->e_new->v1->no);
- }
- if (len_squared_v3(es->e_new->v2->no) != 1.0f) {
- normalize_v3(es->e_new->v2->no);
- }
- }
- /* done correcting edge verts normals */
-
- /* untag verts */
- BM_mesh_elem_hflag_disable_all(bm, BM_VERT, BM_ELEM_TAG, false);
-
- /* tag face verts */
- BMO_ITER (f, &oiter, op->slots_in, "faces", BM_FACE) {
- BM_ITER_ELEM (v, &iter, f, BM_VERTS_OF_FACE) {
- BM_elem_flag_enable(v, BM_ELEM_TAG);
- }
- }
-
- /* do in 2 passes so moving the verts doesn't feed back into face angle checks
- * which BM_vert_calc_shell_factor uses. */
-
- /* over allocate */
- varr_co = MEM_callocN(sizeof(*varr_co) * bm->totvert, __func__);
-
- BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
- if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
- const float fac = (depth *
- (use_relative_offset ? bm_edge_info_average_length(v, edge_info) : 1.0f) *
- (use_even_boundary ? BM_vert_calc_shell_factor(v) : 1.0f));
- madd_v3_v3v3fl(varr_co[i], v->co, v->no, fac);
- }
- }
-
- BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
- if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
- copy_v3_v3(v->co, varr_co[i]);
- }
- }
- MEM_freeN(varr_co);
- }
-
- MEM_freeN(edge_info);
-}
+ if (use_interpolate) {
+ for (i = 0; i < iface_array_len; i++) {
+ if (iface_array[i]) {
+ bm_interp_face_free(iface_array[i], bm);
+ }
+ }
+
+ BLI_memarena_free(interp_arena);
+ MEM_freeN(iface_array);
+ }
+
+ /* we could flag new edges/verts too, is it useful? */
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, ELE_NEW);
+
+ /* cheap feature to add depth to the inset */
+ if (depth != 0.0f) {
+ float(*varr_co)[3];
+ BMOIter oiter;
+
+ /* we need to re-calculate tagged normals, but for this purpose we can copy tagged verts from the
+ * faces they inset from, */
+ for (i = 0, es = edge_info; i < edge_info_len; i++, es++) {
+ zero_v3(es->e_new->v1->no);
+ zero_v3(es->e_new->v2->no);
+ }
+ for (i = 0, es = edge_info; i < edge_info_len; i++, es++) {
+ const float *no = es->l->f->no;
+ add_v3_v3(es->e_new->v1->no, no);
+ add_v3_v3(es->e_new->v2->no, no);
+ }
+ for (i = 0, es = edge_info; i < edge_info_len; i++, es++) {
+ /* annoying, avoid normalizing twice */
+ if (len_squared_v3(es->e_new->v1->no) != 1.0f) {
+ normalize_v3(es->e_new->v1->no);
+ }
+ if (len_squared_v3(es->e_new->v2->no) != 1.0f) {
+ normalize_v3(es->e_new->v2->no);
+ }
+ }
+ /* done correcting edge verts normals */
+
+ /* untag verts */
+ BM_mesh_elem_hflag_disable_all(bm, BM_VERT, BM_ELEM_TAG, false);
+
+ /* tag face verts */
+ BMO_ITER (f, &oiter, op->slots_in, "faces", BM_FACE) {
+ BM_ITER_ELEM (v, &iter, f, BM_VERTS_OF_FACE) {
+ BM_elem_flag_enable(v, BM_ELEM_TAG);
+ }
+ }
+
+ /* do in 2 passes so moving the verts doesn't feed back into face angle checks
+ * which BM_vert_calc_shell_factor uses. */
+
+ /* over allocate */
+ varr_co = MEM_callocN(sizeof(*varr_co) * bm->totvert, __func__);
+
+ BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
+ if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ const float fac = (depth *
+ (use_relative_offset ? bm_edge_info_average_length(v, edge_info) :
+ 1.0f) *
+ (use_even_boundary ? BM_vert_calc_shell_factor(v) : 1.0f));
+ madd_v3_v3v3fl(varr_co[i], v->co, v->no, fac);
+ }
+ }
+
+ BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
+ if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ copy_v3_v3(v->co, varr_co[i]);
+ }
+ }
+ MEM_freeN(varr_co);
+ }
+
+ MEM_freeN(edge_info);
+ }
diff --git a/source/blender/bmesh/operators/bmo_join_triangles.c b/source/blender/bmesh/operators/bmo_join_triangles.c
index 19d01cb2e08..9734dab7ca4 100644
--- a/source/blender/bmesh/operators/bmo_join_triangles.c
+++ b/source/blender/bmesh/operators/bmo_join_triangles.c
@@ -37,342 +37,333 @@
#include "intern/bmesh_operators_private.h" /* own include */
/* assumes edges are validated before reaching this poin */
-static float quad_calc_error(
- const float v1[3], const float v2[3],
- const float v3[3], const float v4[3])
+static float quad_calc_error(const float v1[3],
+ const float v2[3],
+ const float v3[3],
+ const float v4[3])
{
- /* gives a 'weight' to a pair of triangles that join an edge to decide how good a join they would make */
- /* Note: this is more complicated than it needs to be and should be cleaned up.. */
- float error = 0.0f;
+ /* gives a 'weight' to a pair of triangles that join an edge to decide how good a join they would make */
+ /* Note: this is more complicated than it needs to be and should be cleaned up.. */
+ float error = 0.0f;
- /* Normal difference */
- {
- float n1[3], n2[3];
- float angle_a, angle_b;
- float diff;
+ /* Normal difference */
+ {
+ float n1[3], n2[3];
+ float angle_a, angle_b;
+ float diff;
- normal_tri_v3(n1, v1, v2, v3);
- normal_tri_v3(n2, v1, v3, v4);
- angle_a = (compare_v3v3(n1, n2, FLT_EPSILON)) ? 0.0f : angle_normalized_v3v3(n1, n2);
+ normal_tri_v3(n1, v1, v2, v3);
+ normal_tri_v3(n2, v1, v3, v4);
+ angle_a = (compare_v3v3(n1, n2, FLT_EPSILON)) ? 0.0f : angle_normalized_v3v3(n1, n2);
- normal_tri_v3(n1, v2, v3, v4);
- normal_tri_v3(n2, v4, v1, v2);
- angle_b = (compare_v3v3(n1, n2, FLT_EPSILON)) ? 0.0f : angle_normalized_v3v3(n1, n2);
+ normal_tri_v3(n1, v2, v3, v4);
+ normal_tri_v3(n2, v4, v1, v2);
+ angle_b = (compare_v3v3(n1, n2, FLT_EPSILON)) ? 0.0f : angle_normalized_v3v3(n1, n2);
- diff = (angle_a + angle_b) / (float)(M_PI * 2);
+ diff = (angle_a + angle_b) / (float)(M_PI * 2);
- error += diff;
- }
+ error += diff;
+ }
- /* Colinearity */
- {
- float edge_vecs[4][3];
- float diff;
+ /* Colinearity */
+ {
+ float edge_vecs[4][3];
+ float diff;
- sub_v3_v3v3(edge_vecs[0], v1, v2);
- sub_v3_v3v3(edge_vecs[1], v2, v3);
- sub_v3_v3v3(edge_vecs[2], v3, v4);
- sub_v3_v3v3(edge_vecs[3], v4, v1);
+ sub_v3_v3v3(edge_vecs[0], v1, v2);
+ sub_v3_v3v3(edge_vecs[1], v2, v3);
+ sub_v3_v3v3(edge_vecs[2], v3, v4);
+ sub_v3_v3v3(edge_vecs[3], v4, v1);
- normalize_v3(edge_vecs[0]);
- normalize_v3(edge_vecs[1]);
- normalize_v3(edge_vecs[2]);
- normalize_v3(edge_vecs[3]);
+ normalize_v3(edge_vecs[0]);
+ normalize_v3(edge_vecs[1]);
+ normalize_v3(edge_vecs[2]);
+ normalize_v3(edge_vecs[3]);
- /* a completely skinny face is 'pi' after halving */
- diff = (fabsf(angle_normalized_v3v3(edge_vecs[0], edge_vecs[1]) - (float)M_PI_2) +
- fabsf(angle_normalized_v3v3(edge_vecs[1], edge_vecs[2]) - (float)M_PI_2) +
- fabsf(angle_normalized_v3v3(edge_vecs[2], edge_vecs[3]) - (float)M_PI_2) +
- fabsf(angle_normalized_v3v3(edge_vecs[3], edge_vecs[0]) - (float)M_PI_2)) / (float)(M_PI * 2);
+ /* a completely skinny face is 'pi' after halving */
+ diff = (fabsf(angle_normalized_v3v3(edge_vecs[0], edge_vecs[1]) - (float)M_PI_2) +
+ fabsf(angle_normalized_v3v3(edge_vecs[1], edge_vecs[2]) - (float)M_PI_2) +
+ fabsf(angle_normalized_v3v3(edge_vecs[2], edge_vecs[3]) - (float)M_PI_2) +
+ fabsf(angle_normalized_v3v3(edge_vecs[3], edge_vecs[0]) - (float)M_PI_2)) /
+ (float)(M_PI * 2);
- error += diff;
- }
+ error += diff;
+ }
- /* Concavity */
- {
- float area_min, area_max, area_a, area_b;
- float diff;
+ /* Concavity */
+ {
+ float area_min, area_max, area_a, area_b;
+ float diff;
- area_a = area_tri_v3(v1, v2, v3) + area_tri_v3(v1, v3, v4);
- area_b = area_tri_v3(v2, v3, v4) + area_tri_v3(v4, v1, v2);
+ area_a = area_tri_v3(v1, v2, v3) + area_tri_v3(v1, v3, v4);
+ area_b = area_tri_v3(v2, v3, v4) + area_tri_v3(v4, v1, v2);
- area_min = min_ff(area_a, area_b);
- area_max = max_ff(area_a, area_b);
+ area_min = min_ff(area_a, area_b);
+ area_max = max_ff(area_a, area_b);
- diff = area_max ? (1.0f - (area_min / area_max)) : 1.0f;
+ diff = area_max ? (1.0f - (area_min / area_max)) : 1.0f;
- error += diff;
- }
+ error += diff;
+ }
- return error;
+ return error;
}
static void bm_edge_to_quad_verts(const BMEdge *e, const BMVert *r_v_quad[4])
{
- BLI_assert(e->l->f->len == 3 && e->l->radial_next->f->len == 3);
- BLI_assert(BM_edge_is_manifold(e));
- r_v_quad[0] = e->l->v;
- r_v_quad[1] = e->l->prev->v;
- r_v_quad[2] = e->l->next->v;
- r_v_quad[3] = e->l->radial_next->prev->v;
+ BLI_assert(e->l->f->len == 3 && e->l->radial_next->f->len == 3);
+ BLI_assert(BM_edge_is_manifold(e));
+ r_v_quad[0] = e->l->v;
+ r_v_quad[1] = e->l->prev->v;
+ r_v_quad[2] = e->l->next->v;
+ r_v_quad[3] = e->l->radial_next->prev->v;
}
/* cache customdata delimiters */
struct DelimitData_CD {
- int cd_type;
- int cd_size;
- int cd_offset;
- int cd_offset_end;
+ int cd_type;
+ int cd_size;
+ int cd_offset;
+ int cd_offset_end;
};
struct DelimitData {
- uint do_seam : 1;
- uint do_sharp : 1;
- uint do_mat : 1;
- uint do_angle_face : 1;
- uint do_angle_shape : 1;
+ uint do_seam : 1;
+ uint do_sharp : 1;
+ uint do_mat : 1;
+ uint do_angle_face : 1;
+ uint do_angle_shape : 1;
- float angle_face;
- float angle_face__cos;
+ float angle_face;
+ float angle_face__cos;
- float angle_shape;
+ float angle_shape;
- struct DelimitData_CD cdata[4];
- int cdata_len;
+ struct DelimitData_CD cdata[4];
+ int cdata_len;
};
-static bool bm_edge_is_contiguous_loop_cd_all(
- const BMEdge *e, const struct DelimitData_CD *delimit_data)
+static bool bm_edge_is_contiguous_loop_cd_all(const BMEdge *e,
+ const struct DelimitData_CD *delimit_data)
{
- int cd_offset;
- for (cd_offset = delimit_data->cd_offset;
- cd_offset < delimit_data->cd_offset_end;
- cd_offset += delimit_data->cd_size)
- {
- if (BM_edge_is_contiguous_loop_cd(e, delimit_data->cd_type, cd_offset) == false) {
- return false;
- }
- }
-
- return true;
+ int cd_offset;
+ for (cd_offset = delimit_data->cd_offset; cd_offset < delimit_data->cd_offset_end;
+ cd_offset += delimit_data->cd_size) {
+ if (BM_edge_is_contiguous_loop_cd(e, delimit_data->cd_type, cd_offset) == false) {
+ return false;
+ }
+ }
+
+ return true;
}
-static bool bm_edge_delimit_cdata(
- CustomData *ldata, CustomDataType type,
- struct DelimitData_CD *r_delim_cd)
+static bool bm_edge_delimit_cdata(CustomData *ldata,
+ CustomDataType type,
+ struct DelimitData_CD *r_delim_cd)
{
- const int layer_len = CustomData_number_of_layers(ldata, type);
- r_delim_cd->cd_type = type;
- r_delim_cd->cd_size = CustomData_sizeof(r_delim_cd->cd_type);
- r_delim_cd->cd_offset = CustomData_get_n_offset(ldata, type, 0);
- r_delim_cd->cd_offset_end = r_delim_cd->cd_size * layer_len;
- return (r_delim_cd->cd_offset != -1);
+ const int layer_len = CustomData_number_of_layers(ldata, type);
+ r_delim_cd->cd_type = type;
+ r_delim_cd->cd_size = CustomData_sizeof(r_delim_cd->cd_type);
+ r_delim_cd->cd_offset = CustomData_get_n_offset(ldata, type, 0);
+ r_delim_cd->cd_offset_end = r_delim_cd->cd_size * layer_len;
+ return (r_delim_cd->cd_offset != -1);
}
-static float bm_edge_is_delimit(
- const BMEdge *e,
- const struct DelimitData *delimit_data)
+static float bm_edge_is_delimit(const BMEdge *e, const struct DelimitData *delimit_data)
{
- BMFace *f_a = e->l->f, *f_b = e->l->radial_next->f;
+ BMFace *f_a = e->l->f, *f_b = e->l->radial_next->f;
#if 0
- const bool is_contig = BM_edge_is_contiguous(e);
- float angle;
+ const bool is_contig = BM_edge_is_contiguous(e);
+ float angle;
#endif
- if ((delimit_data->do_seam) &&
- (BM_elem_flag_test(e, BM_ELEM_SEAM)))
- {
- goto fail;
- }
-
- if ((delimit_data->do_sharp) &&
- (BM_elem_flag_test(e, BM_ELEM_SMOOTH) == 0))
- {
- goto fail;
- }
-
- if ((delimit_data->do_mat) &&
- (f_a->mat_nr != f_b->mat_nr))
- {
- goto fail;
- }
-
- if (delimit_data->do_angle_face) {
- if (dot_v3v3(f_a->no, f_b->no) < delimit_data->angle_face__cos) {
- goto fail;
- }
- }
-
- if (delimit_data->do_angle_shape) {
- const BMVert *verts[4];
- bm_edge_to_quad_verts(e, verts);
-
- /* if we're checking the shape at all, a flipped face is out of the question */
- if (is_quad_flip_v3(verts[0]->co, verts[1]->co, verts[2]->co, verts[3]->co)) {
- goto fail;
- }
- else {
- float edge_vecs[4][3];
-
- sub_v3_v3v3(edge_vecs[0], verts[0]->co, verts[1]->co);
- sub_v3_v3v3(edge_vecs[1], verts[1]->co, verts[2]->co);
- sub_v3_v3v3(edge_vecs[2], verts[2]->co, verts[3]->co);
- sub_v3_v3v3(edge_vecs[3], verts[3]->co, verts[0]->co);
-
- normalize_v3(edge_vecs[0]);
- normalize_v3(edge_vecs[1]);
- normalize_v3(edge_vecs[2]);
- normalize_v3(edge_vecs[3]);
-
- if ((fabsf(angle_normalized_v3v3(edge_vecs[0], edge_vecs[1]) - (float)M_PI_2) > delimit_data->angle_shape) ||
- (fabsf(angle_normalized_v3v3(edge_vecs[1], edge_vecs[2]) - (float)M_PI_2) > delimit_data->angle_shape) ||
- (fabsf(angle_normalized_v3v3(edge_vecs[2], edge_vecs[3]) - (float)M_PI_2) > delimit_data->angle_shape) ||
- (fabsf(angle_normalized_v3v3(edge_vecs[3], edge_vecs[0]) - (float)M_PI_2) > delimit_data->angle_shape))
- {
- goto fail;
- }
- }
- }
-
- if (delimit_data->cdata_len) {
- int i;
- for (i = 0; i < delimit_data->cdata_len; i++) {
- if (!bm_edge_is_contiguous_loop_cd_all(e, &delimit_data->cdata[i])) {
- goto fail;
- }
- }
- }
-
- return false;
+ if ((delimit_data->do_seam) && (BM_elem_flag_test(e, BM_ELEM_SEAM))) {
+ goto fail;
+ }
+
+ if ((delimit_data->do_sharp) && (BM_elem_flag_test(e, BM_ELEM_SMOOTH) == 0)) {
+ goto fail;
+ }
+
+ if ((delimit_data->do_mat) && (f_a->mat_nr != f_b->mat_nr)) {
+ goto fail;
+ }
+
+ if (delimit_data->do_angle_face) {
+ if (dot_v3v3(f_a->no, f_b->no) < delimit_data->angle_face__cos) {
+ goto fail;
+ }
+ }
+
+ if (delimit_data->do_angle_shape) {
+ const BMVert *verts[4];
+ bm_edge_to_quad_verts(e, verts);
+
+ /* if we're checking the shape at all, a flipped face is out of the question */
+ if (is_quad_flip_v3(verts[0]->co, verts[1]->co, verts[2]->co, verts[3]->co)) {
+ goto fail;
+ }
+ else {
+ float edge_vecs[4][3];
+
+ sub_v3_v3v3(edge_vecs[0], verts[0]->co, verts[1]->co);
+ sub_v3_v3v3(edge_vecs[1], verts[1]->co, verts[2]->co);
+ sub_v3_v3v3(edge_vecs[2], verts[2]->co, verts[3]->co);
+ sub_v3_v3v3(edge_vecs[3], verts[3]->co, verts[0]->co);
+
+ normalize_v3(edge_vecs[0]);
+ normalize_v3(edge_vecs[1]);
+ normalize_v3(edge_vecs[2]);
+ normalize_v3(edge_vecs[3]);
+
+ if ((fabsf(angle_normalized_v3v3(edge_vecs[0], edge_vecs[1]) - (float)M_PI_2) >
+ delimit_data->angle_shape) ||
+ (fabsf(angle_normalized_v3v3(edge_vecs[1], edge_vecs[2]) - (float)M_PI_2) >
+ delimit_data->angle_shape) ||
+ (fabsf(angle_normalized_v3v3(edge_vecs[2], edge_vecs[3]) - (float)M_PI_2) >
+ delimit_data->angle_shape) ||
+ (fabsf(angle_normalized_v3v3(edge_vecs[3], edge_vecs[0]) - (float)M_PI_2) >
+ delimit_data->angle_shape)) {
+ goto fail;
+ }
+ }
+ }
+
+ if (delimit_data->cdata_len) {
+ int i;
+ for (i = 0; i < delimit_data->cdata_len; i++) {
+ if (!bm_edge_is_contiguous_loop_cd_all(e, &delimit_data->cdata[i])) {
+ goto fail;
+ }
+ }
+ }
+
+ return false;
fail:
- return true;
+ return true;
}
-
-#define EDGE_MARK (1 << 0)
+#define EDGE_MARK (1 << 0)
#define FACE_OUT (1 << 0)
-#define FACE_INPUT (1 << 2)
+#define FACE_INPUT (1 << 2)
void bmo_join_triangles_exec(BMesh *bm, BMOperator *op)
{
- float angle_face, angle_shape;
-
- BMIter iter;
- BMOIter siter;
- BMFace *f;
- BMEdge *e;
- /* data: edge-to-join, sort_value: error weight */
- struct SortPtrByFloat *jedges;
- unsigned i, totedge;
- uint totedge_tag = 0;
-
- struct DelimitData delimit_data = {0};
-
- delimit_data.do_seam = BMO_slot_bool_get(op->slots_in, "cmp_seam");
- delimit_data.do_sharp = BMO_slot_bool_get(op->slots_in, "cmp_sharp");
- delimit_data.do_mat = BMO_slot_bool_get(op->slots_in, "cmp_materials");
-
- angle_face = BMO_slot_float_get(op->slots_in, "angle_face_threshold");
- if (angle_face < DEG2RADF(180.0f)) {
- delimit_data.angle_face = angle_face;
- delimit_data.angle_face__cos = cosf(angle_face);
- delimit_data.do_angle_face = true;
- }
- else {
- delimit_data.do_angle_face = false;
- }
-
- angle_shape = BMO_slot_float_get(op->slots_in, "angle_shape_threshold");
- if (angle_shape < DEG2RADF(180.0f)) {
- delimit_data.angle_shape = angle_shape;
- delimit_data.do_angle_shape = true;
- }
- else {
- delimit_data.do_angle_shape = false;
- }
-
- if (BMO_slot_bool_get(op->slots_in, "cmp_uvs") &&
- bm_edge_delimit_cdata(&bm->ldata, CD_MLOOPUV, &delimit_data.cdata[delimit_data.cdata_len]))
- {
- delimit_data.cdata_len += 1;
- }
-
- delimit_data.cdata[delimit_data.cdata_len].cd_offset = -1;
- if (BMO_slot_bool_get(op->slots_in, "cmp_vcols") &&
- bm_edge_delimit_cdata(&bm->ldata, CD_MLOOPCOL, &delimit_data.cdata[delimit_data.cdata_len]))
- {
- delimit_data.cdata_len += 1;
- }
-
- /* flag all edges of all input face */
- BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) {
- if (f->len == 3) {
- BMO_face_flag_enable(bm, f, FACE_INPUT);
- }
- }
-
- /* flag edges surrounded by 2 flagged triangles */
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- BMFace *f_a, *f_b;
- if (BM_edge_face_pair(e, &f_a, &f_b) &&
- (BMO_face_flag_test(bm, f_a, FACE_INPUT) &&
- BMO_face_flag_test(bm, f_b, FACE_INPUT)))
- {
- if (!bm_edge_is_delimit(e, &delimit_data)) {
- BMO_edge_flag_enable(bm, e, EDGE_MARK);
- totedge_tag++;
- }
- }
- }
-
- if (totedge_tag == 0) {
- return;
- }
-
- /* over alloc, some of the edges will be delimited */
- jedges = MEM_mallocN(sizeof(*jedges) * totedge_tag, __func__);
-
- i = 0;
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- const BMVert *verts[4];
- float error;
-
- if (!BMO_edge_flag_test(bm, e, EDGE_MARK)) {
- continue;
- }
-
- bm_edge_to_quad_verts(e, verts);
-
- error = quad_calc_error(verts[0]->co, verts[1]->co, verts[2]->co, verts[3]->co);
-
- jedges[i].data = e;
- jedges[i].sort_value = error;
- i++;
- }
-
- totedge = i;
- qsort(jedges, totedge, sizeof(*jedges), BLI_sortutil_cmp_float);
-
- for (i = 0; i < totedge; i++) {
- BMLoop *l_a, *l_b;
-
- e = jedges[i].data;
- l_a = e->l;
- l_b = e->l->radial_next;
-
- /* check if another edge already claimed this face */
- if ((l_a->f->len == 3) && (l_b->f->len == 3)) {
- BMFace *f_new;
- f_new = BM_faces_join_pair(bm, l_a, l_b, true);
- if (f_new) {
- BMO_face_flag_enable(bm, f_new, FACE_OUT);
- }
- }
- }
-
- MEM_freeN(jedges);
-
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_OUT);
+ float angle_face, angle_shape;
+
+ BMIter iter;
+ BMOIter siter;
+ BMFace *f;
+ BMEdge *e;
+ /* data: edge-to-join, sort_value: error weight */
+ struct SortPtrByFloat *jedges;
+ unsigned i, totedge;
+ uint totedge_tag = 0;
+
+ struct DelimitData delimit_data = {0};
+
+ delimit_data.do_seam = BMO_slot_bool_get(op->slots_in, "cmp_seam");
+ delimit_data.do_sharp = BMO_slot_bool_get(op->slots_in, "cmp_sharp");
+ delimit_data.do_mat = BMO_slot_bool_get(op->slots_in, "cmp_materials");
+
+ angle_face = BMO_slot_float_get(op->slots_in, "angle_face_threshold");
+ if (angle_face < DEG2RADF(180.0f)) {
+ delimit_data.angle_face = angle_face;
+ delimit_data.angle_face__cos = cosf(angle_face);
+ delimit_data.do_angle_face = true;
+ }
+ else {
+ delimit_data.do_angle_face = false;
+ }
+
+ angle_shape = BMO_slot_float_get(op->slots_in, "angle_shape_threshold");
+ if (angle_shape < DEG2RADF(180.0f)) {
+ delimit_data.angle_shape = angle_shape;
+ delimit_data.do_angle_shape = true;
+ }
+ else {
+ delimit_data.do_angle_shape = false;
+ }
+
+ if (BMO_slot_bool_get(op->slots_in, "cmp_uvs") &&
+ bm_edge_delimit_cdata(&bm->ldata, CD_MLOOPUV, &delimit_data.cdata[delimit_data.cdata_len])) {
+ delimit_data.cdata_len += 1;
+ }
+
+ delimit_data.cdata[delimit_data.cdata_len].cd_offset = -1;
+ if (BMO_slot_bool_get(op->slots_in, "cmp_vcols") &&
+ bm_edge_delimit_cdata(
+ &bm->ldata, CD_MLOOPCOL, &delimit_data.cdata[delimit_data.cdata_len])) {
+ delimit_data.cdata_len += 1;
+ }
+
+ /* flag all edges of all input face */
+ BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) {
+ if (f->len == 3) {
+ BMO_face_flag_enable(bm, f, FACE_INPUT);
+ }
+ }
+
+ /* flag edges surrounded by 2 flagged triangles */
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ BMFace *f_a, *f_b;
+ if (BM_edge_face_pair(e, &f_a, &f_b) &&
+ (BMO_face_flag_test(bm, f_a, FACE_INPUT) && BMO_face_flag_test(bm, f_b, FACE_INPUT))) {
+ if (!bm_edge_is_delimit(e, &delimit_data)) {
+ BMO_edge_flag_enable(bm, e, EDGE_MARK);
+ totedge_tag++;
+ }
+ }
+ }
+
+ if (totedge_tag == 0) {
+ return;
+ }
+
+ /* over alloc, some of the edges will be delimited */
+ jedges = MEM_mallocN(sizeof(*jedges) * totedge_tag, __func__);
+
+ i = 0;
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ const BMVert *verts[4];
+ float error;
+
+ if (!BMO_edge_flag_test(bm, e, EDGE_MARK)) {
+ continue;
+ }
+
+ bm_edge_to_quad_verts(e, verts);
+
+ error = quad_calc_error(verts[0]->co, verts[1]->co, verts[2]->co, verts[3]->co);
+
+ jedges[i].data = e;
+ jedges[i].sort_value = error;
+ i++;
+ }
+
+ totedge = i;
+ qsort(jedges, totedge, sizeof(*jedges), BLI_sortutil_cmp_float);
+
+ for (i = 0; i < totedge; i++) {
+ BMLoop *l_a, *l_b;
+
+ e = jedges[i].data;
+ l_a = e->l;
+ l_b = e->l->radial_next;
+
+ /* check if another edge already claimed this face */
+ if ((l_a->f->len == 3) && (l_b->f->len == 3)) {
+ BMFace *f_new;
+ f_new = BM_faces_join_pair(bm, l_a, l_b, true);
+ if (f_new) {
+ BMO_face_flag_enable(bm, f_new, FACE_OUT);
+ }
+ }
+ }
+
+ MEM_freeN(jedges);
+
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_OUT);
}
diff --git a/source/blender/bmesh/operators/bmo_mesh_conv.c b/source/blender/bmesh/operators/bmo_mesh_conv.c
index 5db189a6748..2c76074ad79 100644
--- a/source/blender/bmesh/operators/bmo_mesh_conv.c
+++ b/source/blender/bmesh/operators/bmo_mesh_conv.c
@@ -22,7 +22,6 @@
* into a Bmesh, and back again.
*/
-
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
#include "DNA_key_types.h"
@@ -36,39 +35,40 @@
void bmo_mesh_to_bmesh_exec(BMesh *bm, BMOperator *op)
{
- Object *ob = BMO_slot_ptr_get(op->slots_in, "object");
- Mesh *me = BMO_slot_ptr_get(op->slots_in, "mesh");
- bool set_key = BMO_slot_bool_get(op->slots_in, "use_shapekey");
+ Object *ob = BMO_slot_ptr_get(op->slots_in, "object");
+ Mesh *me = BMO_slot_ptr_get(op->slots_in, "mesh");
+ bool set_key = BMO_slot_bool_get(op->slots_in, "use_shapekey");
- BM_mesh_bm_from_me(
- bm, me, (&(struct BMeshFromMeshParams){
- .use_shapekey = set_key, .active_shapekey = ob->shapenr,
- }));
+ BM_mesh_bm_from_me(bm,
+ me,
+ (&(struct BMeshFromMeshParams){
+ .use_shapekey = set_key,
+ .active_shapekey = ob->shapenr,
+ }));
- if (me->key && ob->shapenr > me->key->totkey) {
- ob->shapenr = me->key->totkey - 1;
- }
+ if (me->key && ob->shapenr > me->key->totkey) {
+ ob->shapenr = me->key->totkey - 1;
+ }
}
void bmo_object_load_bmesh_exec(BMesh *bm, BMOperator *op)
{
- Object *ob = BMO_slot_ptr_get(op->slots_in, "object");
- /* Scene *scene = BMO_slot_ptr_get(op, "scene"); */
- Mesh *me = ob->data;
+ Object *ob = BMO_slot_ptr_get(op->slots_in, "object");
+ /* Scene *scene = BMO_slot_ptr_get(op, "scene"); */
+ Mesh *me = ob->data;
- BMO_op_callf(bm, op->flag,
- "bmesh_to_mesh mesh=%p object=%p",
- me, ob);
+ BMO_op_callf(bm, op->flag, "bmesh_to_mesh mesh=%p object=%p", me, ob);
}
void bmo_bmesh_to_mesh_exec(BMesh *bm, BMOperator *op)
{
- Mesh *me = BMO_slot_ptr_get(op->slots_in, "mesh");
- /* Object *ob = BMO_slot_ptr_get(op, "object"); */
+ Mesh *me = BMO_slot_ptr_get(op->slots_in, "mesh");
+ /* Object *ob = BMO_slot_ptr_get(op, "object"); */
- BM_mesh_bm_to_me(
- G.main, bm, me,
- (&(struct BMeshToMeshParams){
- .calc_object_remap = true,
- }));
+ BM_mesh_bm_to_me(G.main,
+ bm,
+ me,
+ (&(struct BMeshToMeshParams){
+ .calc_object_remap = true,
+ }));
}
diff --git a/source/blender/bmesh/operators/bmo_mirror.c b/source/blender/bmesh/operators/bmo_mirror.c
index 2ef96d1df03..36297b3f816 100644
--- a/source/blender/bmesh/operators/bmo_mirror.c
+++ b/source/blender/bmesh/operators/bmo_mirror.c
@@ -31,87 +31,87 @@
#include "bmesh.h"
#include "intern/bmesh_operators_private.h" /* own include */
-#define ELE_NEW 1
+#define ELE_NEW 1
void bmo_mirror_exec(BMesh *bm, BMOperator *op)
{
- BMOperator dupeop, weldop;
- BMOIter siter;
- BMIter iter;
- BMVert *v, **vmap;
- int vmap_size = 0;
- float mtx[4][4];
- float imtx[4][4];
- float scale[3] = {1.0f, 1.0f, 1.0f};
- float dist = BMO_slot_float_get(op->slots_in, "merge_dist");
- int i, ototvert;
- int axis = BMO_slot_int_get(op->slots_in, "axis");
- bool mirror_u = BMO_slot_bool_get(op->slots_in, "mirror_u");
- bool mirror_v = BMO_slot_bool_get(op->slots_in, "mirror_v");
- BMOpSlot *slot_targetmap;
-
- ototvert = bm->totvert;
-
- BMO_slot_mat4_get(op->slots_in, "matrix", mtx);
- invert_m4_m4(imtx, mtx);
-
- BMO_op_initf(bm, &dupeop, op->flag, "duplicate geom=%s", op, "geom");
- BMO_op_exec(bm, &dupeop);
-
- BMO_slot_buffer_flag_enable(bm, dupeop.slots_out, "geom.out", BM_ALL_NOLOOP, ELE_NEW);
-
- /* create old -> new mappin */
- vmap = BMO_iter_as_arrayN(dupeop.slots_out, "geom.out", BM_VERT, &vmap_size, NULL, 0);
-
- /* feed old data to transform bmo */
- scale[axis] = -1.0f;
- BMO_op_callf(bm, op->flag, "transform verts=%fv matrix=%m4", ELE_NEW, mtx);
- BMO_op_callf(bm, op->flag, "scale verts=%fv vec=%v", ELE_NEW, scale);
- BMO_op_callf(bm, op->flag, "transform verts=%fv matrix=%m4", ELE_NEW, imtx);
-
- BMO_op_init(bm, &weldop, op->flag, "weld_verts");
-
- slot_targetmap = BMO_slot_get(weldop.slots_in, "targetmap");
-
- v = BM_iter_new(&iter, bm, BM_VERTS_OF_MESH, NULL);
- for (i = 0; i < ototvert; i++) {
- if (fabsf(v->co[axis]) <= dist) {
- BLI_assert(vmap_size >= i);
- BMO_slot_map_elem_insert(&weldop, slot_targetmap, vmap[i], v);
- }
- v = BM_iter_step(&iter);
- }
-
- if (mirror_u || mirror_v) {
- BMFace *f;
- BMLoop *l;
- MLoopUV *luv;
- const int totlayer = CustomData_number_of_layers(&bm->ldata, CD_MLOOPUV);
- BMIter liter;
-
- BMO_ITER (f, &siter, dupeop.slots_out, "geom.out", BM_FACE) {
- BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- for (i = 0; i < totlayer; i++) {
- luv = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPUV, i);
- if (mirror_u) {
- luv->uv[0] = 1.0f - luv->uv[0];
- }
- if (mirror_v) {
- luv->uv[1] = 1.0f - luv->uv[1];
- }
- }
- }
- }
- }
-
- BMO_op_exec(bm, &weldop);
-
- BMO_op_finish(bm, &weldop);
- BMO_op_finish(bm, &dupeop);
-
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_ALL_NOLOOP, ELE_NEW);
-
- if (vmap) {
- MEM_freeN(vmap);
- }
+ BMOperator dupeop, weldop;
+ BMOIter siter;
+ BMIter iter;
+ BMVert *v, **vmap;
+ int vmap_size = 0;
+ float mtx[4][4];
+ float imtx[4][4];
+ float scale[3] = {1.0f, 1.0f, 1.0f};
+ float dist = BMO_slot_float_get(op->slots_in, "merge_dist");
+ int i, ototvert;
+ int axis = BMO_slot_int_get(op->slots_in, "axis");
+ bool mirror_u = BMO_slot_bool_get(op->slots_in, "mirror_u");
+ bool mirror_v = BMO_slot_bool_get(op->slots_in, "mirror_v");
+ BMOpSlot *slot_targetmap;
+
+ ototvert = bm->totvert;
+
+ BMO_slot_mat4_get(op->slots_in, "matrix", mtx);
+ invert_m4_m4(imtx, mtx);
+
+ BMO_op_initf(bm, &dupeop, op->flag, "duplicate geom=%s", op, "geom");
+ BMO_op_exec(bm, &dupeop);
+
+ BMO_slot_buffer_flag_enable(bm, dupeop.slots_out, "geom.out", BM_ALL_NOLOOP, ELE_NEW);
+
+ /* create old -> new mappin */
+ vmap = BMO_iter_as_arrayN(dupeop.slots_out, "geom.out", BM_VERT, &vmap_size, NULL, 0);
+
+ /* feed old data to transform bmo */
+ scale[axis] = -1.0f;
+ BMO_op_callf(bm, op->flag, "transform verts=%fv matrix=%m4", ELE_NEW, mtx);
+ BMO_op_callf(bm, op->flag, "scale verts=%fv vec=%v", ELE_NEW, scale);
+ BMO_op_callf(bm, op->flag, "transform verts=%fv matrix=%m4", ELE_NEW, imtx);
+
+ BMO_op_init(bm, &weldop, op->flag, "weld_verts");
+
+ slot_targetmap = BMO_slot_get(weldop.slots_in, "targetmap");
+
+ v = BM_iter_new(&iter, bm, BM_VERTS_OF_MESH, NULL);
+ for (i = 0; i < ototvert; i++) {
+ if (fabsf(v->co[axis]) <= dist) {
+ BLI_assert(vmap_size >= i);
+ BMO_slot_map_elem_insert(&weldop, slot_targetmap, vmap[i], v);
+ }
+ v = BM_iter_step(&iter);
+ }
+
+ if (mirror_u || mirror_v) {
+ BMFace *f;
+ BMLoop *l;
+ MLoopUV *luv;
+ const int totlayer = CustomData_number_of_layers(&bm->ldata, CD_MLOOPUV);
+ BMIter liter;
+
+ BMO_ITER (f, &siter, dupeop.slots_out, "geom.out", BM_FACE) {
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ for (i = 0; i < totlayer; i++) {
+ luv = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPUV, i);
+ if (mirror_u) {
+ luv->uv[0] = 1.0f - luv->uv[0];
+ }
+ if (mirror_v) {
+ luv->uv[1] = 1.0f - luv->uv[1];
+ }
+ }
+ }
+ }
+ }
+
+ BMO_op_exec(bm, &weldop);
+
+ BMO_op_finish(bm, &weldop);
+ BMO_op_finish(bm, &dupeop);
+
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_ALL_NOLOOP, ELE_NEW);
+
+ if (vmap) {
+ MEM_freeN(vmap);
+ }
}
diff --git a/source/blender/bmesh/operators/bmo_normals.c b/source/blender/bmesh/operators/bmo_normals.c
index f91f15ee881..ee55165244b 100644
--- a/source/blender/bmesh/operators/bmo_normals.c
+++ b/source/blender/bmesh/operators/bmo_normals.c
@@ -31,13 +31,13 @@
/********* righthand faces implementation ****** */
-#define FACE_FLAG (1 << 0)
-#define FACE_FLIP (1 << 1)
-#define FACE_TEMP (1 << 2)
+#define FACE_FLAG (1 << 0)
+#define FACE_FLIP (1 << 1)
+#define FACE_TEMP (1 << 2)
static bool bmo_recalc_normal_loop_filter_cb(const BMLoop *l, void *UNUSED(user_data))
{
- return BM_edge_is_manifold(l->e);
+ return BM_edge_is_manifold(l->e);
}
/**
@@ -69,116 +69,116 @@ static bool bmo_recalc_normal_loop_filter_cb(const BMLoop *l, void *UNUSED(user_
/**
* \return a face index in \a faces and set \a r_is_flip if the face is flipped away from the center.
*/
-static int recalc_face_normals_find_index(BMesh *bm, BMFace **faces, const int faces_len, bool *r_is_flip)
+static int recalc_face_normals_find_index(BMesh *bm,
+ BMFace **faces,
+ const int faces_len,
+ bool *r_is_flip)
{
- const float eps = FLT_EPSILON;
- float cent_area_accum = 0.0f;
- float cent[3];
- const float cent_fac = 1.0f / (float)faces_len;
-
- bool is_flip = false;
- int f_start_index;
- int i;
-
- /* Search for the best loop. Members are compared in-order defined here. */
- struct {
- /* Squared distance from the center to the loops vertex 'l->v'.
- * The normalized direction between the center and this vertex is also used for the dot-products below. */
- float dist_sq;
- /* Signed dot product using the normalized edge vector,
- * (best of 'l->prev->v' or 'l->next->v'). */
- float edge_dot;
- /* Unsigned dot product using the loop-normal
- * (sign is used to check if we need to flip) */
- float loop_dot;
- } best, test;
-
- UNUSED_VARS_NDEBUG(bm);
-
- zero_v3(cent);
-
- /* first calculate the center */
- for (i = 0; i < faces_len; i++) {
- float f_cent[3];
- const float f_area = BM_face_calc_area(faces[i]);
- BM_face_calc_center_median_weighted(faces[i], f_cent);
- madd_v3_v3fl(cent, f_cent, cent_fac * f_area);
- cent_area_accum += f_area;
-
- BLI_assert(BMO_face_flag_test(bm, faces[i], FACE_TEMP) == 0);
- BLI_assert(BM_face_is_normal_valid(faces[i]));
- }
-
- if (cent_area_accum != 0.0f) {
- mul_v3_fl(cent, 1.0f / cent_area_accum);
- }
-
- /* Distances must start above zero,
- * or we can't do meaningful calculations based on the direction to the center */
- best.dist_sq = eps;
- best.edge_dot = best.loop_dot = -FLT_MAX;
-
- /* used in degenerate cases only */
- f_start_index = 0;
-
- /**
- * Find the outer-most vertex, comparing distance to the center,
- * then the outer-most loop attached to that vertex.
- *
- * Important this is correctly detected,
- * where casting a ray from the center wont hit any loops past this one.
- * Otherwise the result may be incorrect.
- */
- for (i = 0; i < faces_len; i++) {
- BMLoop *l_iter, *l_first;
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(faces[i]);
- do {
- bool is_best_dist_sq;
- float dir[3];
- sub_v3_v3v3(dir, l_iter->v->co, cent);
- test.dist_sq = len_squared_v3(dir);
- is_best_dist_sq = (test.dist_sq > best.dist_sq);
- if (is_best_dist_sq || (test.dist_sq == best.dist_sq)) {
- float edge_dir_pair[2][3];
- mul_v3_fl(dir, 1.0f / sqrtf(test.dist_sq));
-
- sub_v3_v3v3(edge_dir_pair[0], l_iter->next->v->co, l_iter->v->co);
- sub_v3_v3v3(edge_dir_pair[1], l_iter->prev->v->co, l_iter->v->co);
-
- if ((normalize_v3(edge_dir_pair[0]) > eps) &&
- (normalize_v3(edge_dir_pair[1]) > eps))
- {
- bool is_best_edge_dot;
- test.edge_dot = max_ff(dot_v3v3(dir, edge_dir_pair[0]),
- dot_v3v3(dir, edge_dir_pair[1]));
- is_best_edge_dot = (test.edge_dot > best.edge_dot);
- if (is_best_dist_sq || is_best_edge_dot || (test.edge_dot == best.edge_dot)) {
- float loop_dir[3];
- cross_v3_v3v3(loop_dir, edge_dir_pair[0], edge_dir_pair[1]);
- if (normalize_v3(loop_dir) > eps) {
- float loop_dir_dot;
- /* Highly unlikely the furthest loop is also the concave part of an ngon,
- * but it can be contrived with _very_ non-planar faces - so better check. */
- if (UNLIKELY(dot_v3v3(loop_dir, l_iter->f->no) < 0.0f)) {
- negate_v3(loop_dir);
- }
- loop_dir_dot = dot_v3v3(dir, loop_dir);
- test.loop_dot = fabsf(loop_dir_dot);
- if (is_best_dist_sq || is_best_edge_dot || (test.loop_dot > best.loop_dot)) {
- best = test;
- f_start_index = i;
- is_flip = (loop_dir_dot < 0.0f);
- }
- }
- }
- }
- }
- } while ((l_iter = l_iter->next) != l_first);
- }
-
- *r_is_flip = is_flip;
- return f_start_index;
+ const float eps = FLT_EPSILON;
+ float cent_area_accum = 0.0f;
+ float cent[3];
+ const float cent_fac = 1.0f / (float)faces_len;
+
+ bool is_flip = false;
+ int f_start_index;
+ int i;
+
+ /* Search for the best loop. Members are compared in-order defined here. */
+ struct {
+ /* Squared distance from the center to the loops vertex 'l->v'.
+ * The normalized direction between the center and this vertex is also used for the dot-products below. */
+ float dist_sq;
+ /* Signed dot product using the normalized edge vector,
+ * (best of 'l->prev->v' or 'l->next->v'). */
+ float edge_dot;
+ /* Unsigned dot product using the loop-normal
+ * (sign is used to check if we need to flip) */
+ float loop_dot;
+ } best, test;
+
+ UNUSED_VARS_NDEBUG(bm);
+
+ zero_v3(cent);
+
+ /* first calculate the center */
+ for (i = 0; i < faces_len; i++) {
+ float f_cent[3];
+ const float f_area = BM_face_calc_area(faces[i]);
+ BM_face_calc_center_median_weighted(faces[i], f_cent);
+ madd_v3_v3fl(cent, f_cent, cent_fac * f_area);
+ cent_area_accum += f_area;
+
+ BLI_assert(BMO_face_flag_test(bm, faces[i], FACE_TEMP) == 0);
+ BLI_assert(BM_face_is_normal_valid(faces[i]));
+ }
+
+ if (cent_area_accum != 0.0f) {
+ mul_v3_fl(cent, 1.0f / cent_area_accum);
+ }
+
+ /* Distances must start above zero,
+ * or we can't do meaningful calculations based on the direction to the center */
+ best.dist_sq = eps;
+ best.edge_dot = best.loop_dot = -FLT_MAX;
+
+ /* used in degenerate cases only */
+ f_start_index = 0;
+
+ /**
+ * Find the outer-most vertex, comparing distance to the center,
+ * then the outer-most loop attached to that vertex.
+ *
+ * Important this is correctly detected,
+ * where casting a ray from the center wont hit any loops past this one.
+ * Otherwise the result may be incorrect.
+ */
+ for (i = 0; i < faces_len; i++) {
+ BMLoop *l_iter, *l_first;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(faces[i]);
+ do {
+ bool is_best_dist_sq;
+ float dir[3];
+ sub_v3_v3v3(dir, l_iter->v->co, cent);
+ test.dist_sq = len_squared_v3(dir);
+ is_best_dist_sq = (test.dist_sq > best.dist_sq);
+ if (is_best_dist_sq || (test.dist_sq == best.dist_sq)) {
+ float edge_dir_pair[2][3];
+ mul_v3_fl(dir, 1.0f / sqrtf(test.dist_sq));
+
+ sub_v3_v3v3(edge_dir_pair[0], l_iter->next->v->co, l_iter->v->co);
+ sub_v3_v3v3(edge_dir_pair[1], l_iter->prev->v->co, l_iter->v->co);
+
+ if ((normalize_v3(edge_dir_pair[0]) > eps) && (normalize_v3(edge_dir_pair[1]) > eps)) {
+ bool is_best_edge_dot;
+ test.edge_dot = max_ff(dot_v3v3(dir, edge_dir_pair[0]), dot_v3v3(dir, edge_dir_pair[1]));
+ is_best_edge_dot = (test.edge_dot > best.edge_dot);
+ if (is_best_dist_sq || is_best_edge_dot || (test.edge_dot == best.edge_dot)) {
+ float loop_dir[3];
+ cross_v3_v3v3(loop_dir, edge_dir_pair[0], edge_dir_pair[1]);
+ if (normalize_v3(loop_dir) > eps) {
+ float loop_dir_dot;
+ /* Highly unlikely the furthest loop is also the concave part of an ngon,
+ * but it can be contrived with _very_ non-planar faces - so better check. */
+ if (UNLIKELY(dot_v3v3(loop_dir, l_iter->f->no) < 0.0f)) {
+ negate_v3(loop_dir);
+ }
+ loop_dir_dot = dot_v3v3(dir, loop_dir);
+ test.loop_dot = fabsf(loop_dir_dot);
+ if (is_best_dist_sq || is_best_edge_dot || (test.loop_dot > best.loop_dot)) {
+ best = test;
+ f_start_index = i;
+ is_flip = (loop_dir_dot < 0.0f);
+ }
+ }
+ }
+ }
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+
+ *r_is_flip = is_flip;
+ return f_start_index;
}
/**
@@ -190,58 +190,61 @@ static int recalc_face_normals_find_index(BMesh *bm, BMFace **faces, const int f
* \param faces_len: Length of \a faces
* \param oflag: Flag to check before doing the actual face flipping.
*/
-static void bmo_recalc_face_normals_array(BMesh *bm, BMFace **faces, const int faces_len, const short oflag)
+static void bmo_recalc_face_normals_array(BMesh *bm,
+ BMFace **faces,
+ const int faces_len,
+ const short oflag)
{
- int i, f_start_index;
- const short oflag_flip = oflag | FACE_FLIP;
- bool is_flip;
-
- BMFace *f;
-
- BLI_LINKSTACK_DECLARE(fstack, BMFace *);
-
- f_start_index = recalc_face_normals_find_index(bm, faces, faces_len, &is_flip);
-
- if (is_flip) {
- BMO_face_flag_enable(bm, faces[f_start_index], FACE_FLIP);
- }
-
- /* now that we've found our starting face, make all connected faces
- * have the same winding. this is done recursively, using a manual
- * stack (if we use simple function recursion, we'd end up overloading
- * the stack on large meshes). */
- BLI_LINKSTACK_INIT(fstack);
-
- BLI_LINKSTACK_PUSH(fstack, faces[f_start_index]);
- BMO_face_flag_enable(bm, faces[f_start_index], FACE_TEMP);
-
- while ((f = BLI_LINKSTACK_POP(fstack))) {
- const bool flip_state = BMO_face_flag_test_bool(bm, f, FACE_FLIP);
- BMLoop *l_iter, *l_first;
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- BMLoop *l_other = l_iter->radial_next;
-
- if ((l_other != l_iter) && bmo_recalc_normal_loop_filter_cb(l_iter, NULL)) {
- if (!BMO_face_flag_test(bm, l_other->f, FACE_TEMP)) {
- BMO_face_flag_enable(bm, l_other->f, FACE_TEMP);
- BMO_face_flag_set(bm, l_other->f, FACE_FLIP, (l_other->v == l_iter->v) != flip_state);
- BLI_LINKSTACK_PUSH(fstack, l_other->f);
- }
- }
- } while ((l_iter = l_iter->next) != l_first);
- }
-
- BLI_LINKSTACK_FREE(fstack);
-
- /* apply flipping to oflag'd faces */
- for (i = 0; i < faces_len; i++) {
- if (BMO_face_flag_test(bm, faces[i], oflag_flip) == oflag_flip) {
- BM_face_normal_flip(bm, faces[i]);
- }
- BMO_face_flag_disable(bm, faces[i], FACE_TEMP);
- }
+ int i, f_start_index;
+ const short oflag_flip = oflag | FACE_FLIP;
+ bool is_flip;
+
+ BMFace *f;
+
+ BLI_LINKSTACK_DECLARE(fstack, BMFace *);
+
+ f_start_index = recalc_face_normals_find_index(bm, faces, faces_len, &is_flip);
+
+ if (is_flip) {
+ BMO_face_flag_enable(bm, faces[f_start_index], FACE_FLIP);
+ }
+
+ /* now that we've found our starting face, make all connected faces
+ * have the same winding. this is done recursively, using a manual
+ * stack (if we use simple function recursion, we'd end up overloading
+ * the stack on large meshes). */
+ BLI_LINKSTACK_INIT(fstack);
+
+ BLI_LINKSTACK_PUSH(fstack, faces[f_start_index]);
+ BMO_face_flag_enable(bm, faces[f_start_index], FACE_TEMP);
+
+ while ((f = BLI_LINKSTACK_POP(fstack))) {
+ const bool flip_state = BMO_face_flag_test_bool(bm, f, FACE_FLIP);
+ BMLoop *l_iter, *l_first;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BMLoop *l_other = l_iter->radial_next;
+
+ if ((l_other != l_iter) && bmo_recalc_normal_loop_filter_cb(l_iter, NULL)) {
+ if (!BMO_face_flag_test(bm, l_other->f, FACE_TEMP)) {
+ BMO_face_flag_enable(bm, l_other->f, FACE_TEMP);
+ BMO_face_flag_set(bm, l_other->f, FACE_FLIP, (l_other->v == l_iter->v) != flip_state);
+ BLI_LINKSTACK_PUSH(fstack, l_other->f);
+ }
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+
+ BLI_LINKSTACK_FREE(fstack);
+
+ /* apply flipping to oflag'd faces */
+ for (i = 0; i < faces_len; i++) {
+ if (BMO_face_flag_test(bm, faces[i], oflag_flip) == oflag_flip) {
+ BM_face_normal_flip(bm, faces[i]);
+ }
+ BMO_face_flag_disable(bm, faces[i], FACE_TEMP);
+ }
}
/*
@@ -254,41 +257,39 @@ static void bmo_recalc_face_normals_array(BMesh *bm, BMFace **faces, const int f
void bmo_recalc_face_normals_exec(BMesh *bm, BMOperator *op)
{
- int *groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totface, __func__);
- BMFace **faces_grp = MEM_mallocN(sizeof(*faces_grp) * bm->totface, __func__);
+ int *groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totface, __func__);
+ BMFace **faces_grp = MEM_mallocN(sizeof(*faces_grp) * bm->totface, __func__);
- int (*group_index)[2];
- const int group_tot = BM_mesh_calc_face_groups(
- bm, groups_array, &group_index,
- bmo_recalc_normal_loop_filter_cb, NULL,
- 0, BM_EDGE);
- int i;
+ int(*group_index)[2];
+ const int group_tot = BM_mesh_calc_face_groups(
+ bm, groups_array, &group_index, bmo_recalc_normal_loop_filter_cb, NULL, 0, BM_EDGE);
+ int i;
- BMO_slot_buffer_flag_enable(bm, op->slots_in, "faces", BM_FACE, FACE_FLAG);
+ BMO_slot_buffer_flag_enable(bm, op->slots_in, "faces", BM_FACE, FACE_FLAG);
- BM_mesh_elem_table_ensure(bm, BM_FACE);
+ BM_mesh_elem_table_ensure(bm, BM_FACE);
- for (i = 0; i < group_tot; i++) {
- const int fg_sta = group_index[i][0];
- const int fg_len = group_index[i][1];
- int j;
- bool is_calc = false;
+ for (i = 0; i < group_tot; i++) {
+ const int fg_sta = group_index[i][0];
+ const int fg_len = group_index[i][1];
+ int j;
+ bool is_calc = false;
- for (j = 0; j < fg_len; j++) {
- faces_grp[j] = BM_face_at_index(bm, groups_array[fg_sta + j]);
+ for (j = 0; j < fg_len; j++) {
+ faces_grp[j] = BM_face_at_index(bm, groups_array[fg_sta + j]);
- if (is_calc == false) {
- is_calc = BMO_face_flag_test_bool(bm, faces_grp[j], FACE_FLAG);
- }
- }
+ if (is_calc == false) {
+ is_calc = BMO_face_flag_test_bool(bm, faces_grp[j], FACE_FLAG);
+ }
+ }
- if (is_calc) {
- bmo_recalc_face_normals_array(bm, faces_grp, fg_len, FACE_FLAG);
- }
- }
+ if (is_calc) {
+ bmo_recalc_face_normals_array(bm, faces_grp, fg_len, FACE_FLAG);
+ }
+ }
- MEM_freeN(faces_grp);
+ MEM_freeN(faces_grp);
- MEM_freeN(groups_array);
- MEM_freeN(group_index);
+ MEM_freeN(groups_array);
+ MEM_freeN(group_index);
}
diff --git a/source/blender/bmesh/operators/bmo_offset_edgeloops.c b/source/blender/bmesh/operators/bmo_offset_edgeloops.c
index 9bf48eaeb96..37b2133e0e4 100644
--- a/source/blender/bmesh/operators/bmo_offset_edgeloops.c
+++ b/source/blender/bmesh/operators/bmo_offset_edgeloops.c
@@ -37,249 +37,239 @@
#define USE_CAP_OPTION
-#define ELE_NEW (1 << 0)
+#define ELE_NEW (1 << 0)
#ifdef USE_CAP_OPTION
-#define ELE_VERT_ENDPOINT (1 << 1)
+# define ELE_VERT_ENDPOINT (1 << 1)
#endif
/* set for debugging */
#define OFFSET 0.0f
-static BMFace *bm_face_split_walk_back(
- BMesh *bm, BMLoop *l_src,
- BMLoop **r_l)
+static BMFace *bm_face_split_walk_back(BMesh *bm, BMLoop *l_src, BMLoop **r_l)
{
- float (*cos)[3];
- BMLoop *l_dst;
- BMFace *f;
- int num, i;
+ float(*cos)[3];
+ BMLoop *l_dst;
+ BMFace *f;
+ int num, i;
- for (l_dst = l_src->prev, num = 0; BM_elem_index_get(l_dst->prev->v) != -1; l_dst = l_dst->prev, num++) {
- /* pass */
- }
+ for (l_dst = l_src->prev, num = 0; BM_elem_index_get(l_dst->prev->v) != -1;
+ l_dst = l_dst->prev, num++) {
+ /* pass */
+ }
- BLI_assert(num != 0);
+ BLI_assert(num != 0);
- cos = BLI_array_alloca(
- cos, num);
+ cos = BLI_array_alloca(cos, num);
- for (l_dst = l_src->prev, i = 0; BM_elem_index_get(l_dst->prev->v) != -1; l_dst = l_dst->prev, i++) {
- copy_v3_v3(cos[num - (i + 1)], l_dst->v->co);
- }
+ for (l_dst = l_src->prev, i = 0; BM_elem_index_get(l_dst->prev->v) != -1;
+ l_dst = l_dst->prev, i++) {
+ copy_v3_v3(cos[num - (i + 1)], l_dst->v->co);
+ }
- f = BM_face_split_n( bm, l_src->f, l_dst->prev, l_src->next, cos, num, r_l, NULL);
+ f = BM_face_split_n(bm, l_src->f, l_dst->prev, l_src->next, cos, num, r_l, NULL);
- return f;
+ return f;
}
void bmo_offset_edgeloops_exec(BMesh *bm, BMOperator *op)
{
- const int edges_num = BMO_slot_buffer_count(op->slots_in, "edges");
- BMVert **verts;
- STACK_DECLARE(verts);
- int i;
+ const int edges_num = BMO_slot_buffer_count(op->slots_in, "edges");
+ BMVert **verts;
+ STACK_DECLARE(verts);
+ int i;
#ifdef USE_CAP_OPTION
- bool use_cap_endpoint = BMO_slot_bool_get(op->slots_in, "use_cap_endpoint");
- int v_edges_max = 0;
+ bool use_cap_endpoint = BMO_slot_bool_get(op->slots_in, "use_cap_endpoint");
+ int v_edges_max = 0;
#endif
- BMOIter oiter;
-
- /* only so we can detect new verts (index == -1) */
- BM_mesh_elem_index_ensure(bm, BM_VERT);
-
- BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
-
- /* over alloc */
- verts = MEM_mallocN(sizeof(*verts) * (edges_num * 2), __func__);
-
- STACK_INIT(verts, (edges_num * 2));
-
- {
- BMEdge *e;
- BMO_ITER (e, &oiter, op->slots_in, "edges", BM_EDGE) {
- int j;
-
- BM_elem_flag_enable(e, BM_ELEM_TAG);
-
- for (j = 0; j < 2; j++) {
- BMVert *v_edge = *(&(e->v1) + j);
- if (!BM_elem_flag_test(v_edge, BM_ELEM_TAG)) {
- BM_elem_flag_enable(v_edge, BM_ELEM_TAG);
- STACK_PUSH(verts, v_edge);
- }
- }
- }
- }
-
-
- /* -------------------------------------------------------------------- */
- /* Remove verts only used by tagged edges */
-
- for (i = 0; i < STACK_SIZE(verts); i++) {
- BMIter iter;
- int flag = 0;
- BMEdge *e;
-
- BM_ITER_ELEM (e, &iter, verts[i], BM_EDGES_OF_VERT) {
- flag |= BM_elem_flag_test(e, BM_ELEM_TAG) ? 1 : 2;
- if (flag == (1 | 2)) {
- break;
- }
- }
-
- /* only boundary verts are interesting */
- if (flag != (1 | 2)) {
- STACK_REMOVE(verts, i);
- }
- }
-
- /* possible but unlikely we have no mixed vertices */
- if (UNLIKELY(STACK_SIZE(verts) == 0)) {
- MEM_freeN(verts);
- return;
- }
-
- /* main loop */
- for (i = 0; i < STACK_SIZE(verts); i++) {
- int v_edges_num = 0;
- int v_edges_num_untag = 0;
- BMVert *v = verts[i];
- BMIter iter;
- BMEdge *e;
-
- BM_ITER_ELEM (e, &iter, verts[i], BM_EDGES_OF_VERT) {
- if (!BM_elem_flag_test(e, BM_ELEM_TAG)) {
- BMVert *v_other;
- BMIter liter;
- BMLoop *l;
-
- BM_ITER_ELEM (l, &liter, e, BM_LOOPS_OF_EDGE) {
- BM_elem_flag_enable(l->f, BM_ELEM_TAG);
- }
-
- v_other = BM_edge_other_vert(e, v);
- BM_edge_split(bm, e, v_other, NULL, 1.0f - OFFSET);
- }
- else {
- v_edges_num_untag += 1;
- }
-
- v_edges_num += 1;
- }
+ BMOIter oiter;
+
+ /* only so we can detect new verts (index == -1) */
+ BM_mesh_elem_index_ensure(bm, BM_VERT);
+
+ BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
+
+ /* over alloc */
+ verts = MEM_mallocN(sizeof(*verts) * (edges_num * 2), __func__);
+
+ STACK_INIT(verts, (edges_num * 2));
+
+ {
+ BMEdge *e;
+ BMO_ITER (e, &oiter, op->slots_in, "edges", BM_EDGE) {
+ int j;
+
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
+
+ for (j = 0; j < 2; j++) {
+ BMVert *v_edge = *(&(e->v1) + j);
+ if (!BM_elem_flag_test(v_edge, BM_ELEM_TAG)) {
+ BM_elem_flag_enable(v_edge, BM_ELEM_TAG);
+ STACK_PUSH(verts, v_edge);
+ }
+ }
+ }
+ }
+
+ /* -------------------------------------------------------------------- */
+ /* Remove verts only used by tagged edges */
+
+ for (i = 0; i < STACK_SIZE(verts); i++) {
+ BMIter iter;
+ int flag = 0;
+ BMEdge *e;
+
+ BM_ITER_ELEM (e, &iter, verts[i], BM_EDGES_OF_VERT) {
+ flag |= BM_elem_flag_test(e, BM_ELEM_TAG) ? 1 : 2;
+ if (flag == (1 | 2)) {
+ break;
+ }
+ }
+
+ /* only boundary verts are interesting */
+ if (flag != (1 | 2)) {
+ STACK_REMOVE(verts, i);
+ }
+ }
+
+ /* possible but unlikely we have no mixed vertices */
+ if (UNLIKELY(STACK_SIZE(verts) == 0)) {
+ MEM_freeN(verts);
+ return;
+ }
+
+ /* main loop */
+ for (i = 0; i < STACK_SIZE(verts); i++) {
+ int v_edges_num = 0;
+ int v_edges_num_untag = 0;
+ BMVert *v = verts[i];
+ BMIter iter;
+ BMEdge *e;
+
+ BM_ITER_ELEM (e, &iter, verts[i], BM_EDGES_OF_VERT) {
+ if (!BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ BMVert *v_other;
+ BMIter liter;
+ BMLoop *l;
+
+ BM_ITER_ELEM (l, &liter, e, BM_LOOPS_OF_EDGE) {
+ BM_elem_flag_enable(l->f, BM_ELEM_TAG);
+ }
+
+ v_other = BM_edge_other_vert(e, v);
+ BM_edge_split(bm, e, v_other, NULL, 1.0f - OFFSET);
+ }
+ else {
+ v_edges_num_untag += 1;
+ }
+
+ v_edges_num += 1;
+ }
#ifdef USE_CAP_OPTION
- if (v_edges_num_untag == 1) {
- BMO_vert_flag_enable(bm, v, ELE_VERT_ENDPOINT);
- }
+ if (v_edges_num_untag == 1) {
+ BMO_vert_flag_enable(bm, v, ELE_VERT_ENDPOINT);
+ }
- CLAMP_MIN(v_edges_max, v_edges_num);
+ CLAMP_MIN(v_edges_max, v_edges_num);
#endif
+ }
- }
+ for (i = 0; i < STACK_SIZE(verts); i++) {
+ BMVert *v = verts[i];
+ BMIter liter;
+ BMLoop *l;
-
- for (i = 0; i < STACK_SIZE(verts); i++) {
- BMVert *v = verts[i];
- BMIter liter;
- BMLoop *l;
-
- BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
- if (BM_elem_flag_test(l->f, BM_ELEM_TAG) &&
- (l->f->len != 3))
- {
- BMFace *f_cmp = l->f;
- if ((BM_elem_index_get(l->next->v) == -1) &&
- (BM_elem_index_get(l->prev->v) == -1))
- {
+ BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
+ if (BM_elem_flag_test(l->f, BM_ELEM_TAG) && (l->f->len != 3)) {
+ BMFace *f_cmp = l->f;
+ if ((BM_elem_index_get(l->next->v) == -1) && (BM_elem_index_get(l->prev->v) == -1)) {
#ifdef USE_CAP_OPTION
- if (use_cap_endpoint || (BMO_vert_flag_test(bm, v, ELE_VERT_ENDPOINT) == 0))
+ if (use_cap_endpoint || (BMO_vert_flag_test(bm, v, ELE_VERT_ENDPOINT) == 0))
#endif
- {
- BMLoop *l_new;
- BM_face_split(bm, l->f, l->prev, l->next, &l_new, NULL, true);
- BLI_assert(f_cmp == l->f);
- BLI_assert(f_cmp != l_new->f);
- UNUSED_VARS_NDEBUG(f_cmp);
- BMO_edge_flag_enable(bm, l_new->e, ELE_NEW);
- }
- }
- else if (l->f->len > 4) {
- if (BM_elem_flag_test(l->e, BM_ELEM_TAG) !=
- BM_elem_flag_test(l->prev->e, BM_ELEM_TAG))
- {
- if (BM_elem_index_get(l->next->v) == -1) {
- if (BM_elem_index_get(l->prev->prev->v) == -1) {
- BMLoop *l_new;
- BM_face_split(bm, l->f, l->prev->prev, l->next, &l_new, NULL, true);
- BLI_assert(f_cmp == l->f);
- BLI_assert(f_cmp != l_new->f);
- BMO_edge_flag_enable(bm, l_new->e, ELE_NEW);
- BM_elem_flag_disable(l->f, BM_ELEM_TAG);
- }
- else {
- /* walk backwards */
- BMLoop *l_new;
- bm_face_split_walk_back(bm, l, &l_new);
- do {
- BMO_edge_flag_enable(bm, l_new->e, ELE_NEW);
- l_new = l_new->next;
- } while (BM_vert_is_edge_pair(l_new->v));
- BM_elem_flag_disable(l->f, BM_ELEM_TAG);
- }
- }
-
- /* Note: instead of duplicate code in alternate direction,
- * we can be sure to hit the other vertex, so the code above runs. */
+ {
+ BMLoop *l_new;
+ BM_face_split(bm, l->f, l->prev, l->next, &l_new, NULL, true);
+ BLI_assert(f_cmp == l->f);
+ BLI_assert(f_cmp != l_new->f);
+ UNUSED_VARS_NDEBUG(f_cmp);
+ BMO_edge_flag_enable(bm, l_new->e, ELE_NEW);
+ }
+ }
+ else if (l->f->len > 4) {
+ if (BM_elem_flag_test(l->e, BM_ELEM_TAG) != BM_elem_flag_test(l->prev->e, BM_ELEM_TAG)) {
+ if (BM_elem_index_get(l->next->v) == -1) {
+ if (BM_elem_index_get(l->prev->prev->v) == -1) {
+ BMLoop *l_new;
+ BM_face_split(bm, l->f, l->prev->prev, l->next, &l_new, NULL, true);
+ BLI_assert(f_cmp == l->f);
+ BLI_assert(f_cmp != l_new->f);
+ BMO_edge_flag_enable(bm, l_new->e, ELE_NEW);
+ BM_elem_flag_disable(l->f, BM_ELEM_TAG);
+ }
+ else {
+ /* walk backwards */
+ BMLoop *l_new;
+ bm_face_split_walk_back(bm, l, &l_new);
+ do {
+ BMO_edge_flag_enable(bm, l_new->e, ELE_NEW);
+ l_new = l_new->next;
+ } while (BM_vert_is_edge_pair(l_new->v));
+ BM_elem_flag_disable(l->f, BM_ELEM_TAG);
+ }
+ }
+
+ /* Note: instead of duplicate code in alternate direction,
+ * we can be sure to hit the other vertex, so the code above runs. */
#if 0
- else if (BM_elem_index_get(l->prev->v) == -1) {
- if (BM_elem_index_get(l->next->next->v) == -1) {
- /* pass */
- }
- }
+ else if (BM_elem_index_get(l->prev->v) == -1) {
+ if (BM_elem_index_get(l->next->next->v) == -1) {
+ /* pass */
+ }
+ }
#endif
- }
- }
- }
- }
- }
+ }
+ }
+ }
+ }
+ }
#ifdef USE_CAP_OPTION
- if (use_cap_endpoint == false) {
- BMVert **varr = BLI_array_alloca(varr, v_edges_max);
- STACK_DECLARE(varr);
- BMVert *v;
-
- for (i = 0; i < STACK_SIZE(verts); i++) {
- BMIter iter;
- BMEdge *e;
-
- v = verts[i];
-
- STACK_INIT(varr, v_edges_max);
-
- BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
- BMVert *v_other;
- v_other = BM_edge_other_vert(e, v);
- if (BM_elem_index_get(v_other) == -1) {
- if (BM_vert_is_edge_pair(v_other)) {
- /* defer bmesh_kernel_join_edge_kill_vert to avoid looping over data we're removing */
- v_other->e = e;
- STACK_PUSH(varr, v_other);
- }
- }
- }
-
- while ((v = STACK_POP(varr))) {
- bmesh_kernel_join_edge_kill_vert(bm, v->e, v, true, false, false);
- }
- }
- }
+ if (use_cap_endpoint == false) {
+ BMVert **varr = BLI_array_alloca(varr, v_edges_max);
+ STACK_DECLARE(varr);
+ BMVert *v;
+
+ for (i = 0; i < STACK_SIZE(verts); i++) {
+ BMIter iter;
+ BMEdge *e;
+
+ v = verts[i];
+
+ STACK_INIT(varr, v_edges_max);
+
+ BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
+ BMVert *v_other;
+ v_other = BM_edge_other_vert(e, v);
+ if (BM_elem_index_get(v_other) == -1) {
+ if (BM_vert_is_edge_pair(v_other)) {
+ /* defer bmesh_kernel_join_edge_kill_vert to avoid looping over data we're removing */
+ v_other->e = e;
+ STACK_PUSH(varr, v_other);
+ }
+ }
+ }
+
+ while ((v = STACK_POP(varr))) {
+ bmesh_kernel_join_edge_kill_vert(bm, v->e, v, true, false, false);
+ }
+ }
+ }
#endif
- MEM_freeN(verts);
+ MEM_freeN(verts);
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, ELE_NEW);
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, ELE_NEW);
}
diff --git a/source/blender/bmesh/operators/bmo_planar_faces.c b/source/blender/bmesh/operators/bmo_planar_faces.c
index f5a0e6aec74..ca336175f19 100644
--- a/source/blender/bmesh/operators/bmo_planar_faces.c
+++ b/source/blender/bmesh/operators/bmo_planar_faces.c
@@ -33,122 +33,124 @@
#define ELE_FACE_ADJUST (1 << 1)
struct VertAccum {
- float co[3];
- int co_tot;
+ float co[3];
+ int co_tot;
};
void bmo_planar_faces_exec(BMesh *bm, BMOperator *op)
{
- const float fac = BMO_slot_float_get(op->slots_in, "factor");
- const int iterations = BMO_slot_int_get(op->slots_in, "iterations");
- const int faces_num = BMO_slot_buffer_count(op->slots_in, "faces");
+ const float fac = BMO_slot_float_get(op->slots_in, "factor");
+ const int iterations = BMO_slot_int_get(op->slots_in, "iterations");
+ const int faces_num = BMO_slot_buffer_count(op->slots_in, "faces");
- const float eps = 0.00001f;
- const float eps_sq = SQUARE(eps);
+ const float eps = 0.00001f;
+ const float eps_sq = SQUARE(eps);
- BMOIter oiter;
- BMFace *f;
- BLI_mempool *vert_accum_pool;
- GHash *vaccum_map;
- float (*faces_center)[3];
- int i, iter_step, shared_vert_num;
+ BMOIter oiter;
+ BMFace *f;
+ BLI_mempool *vert_accum_pool;
+ GHash *vaccum_map;
+ float(*faces_center)[3];
+ int i, iter_step, shared_vert_num;
- faces_center = MEM_mallocN(sizeof(*faces_center) * faces_num, __func__);
+ faces_center = MEM_mallocN(sizeof(*faces_center) * faces_num, __func__);
- shared_vert_num = 0;
- BMO_ITER_INDEX (f, &oiter, op->slots_in, "faces", BM_FACE, i) {
- BMLoop *l_iter, *l_first;
+ shared_vert_num = 0;
+ BMO_ITER_INDEX(f, &oiter, op->slots_in, "faces", BM_FACE, i)
+ {
+ BMLoop *l_iter, *l_first;
- if (f->len == 3) {
- continue;
- }
+ if (f->len == 3) {
+ continue;
+ }
- BM_face_calc_center_median_weighted(f, faces_center[i]);
+ BM_face_calc_center_median_weighted(f, faces_center[i]);
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if (!BMO_vert_flag_test(bm, l_iter->v, ELE_VERT_ADJUST)) {
- BMO_vert_flag_enable(bm, l_iter->v, ELE_VERT_ADJUST);
- shared_vert_num += 1;
- }
- } while ((l_iter = l_iter->next) != l_first);
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (!BMO_vert_flag_test(bm, l_iter->v, ELE_VERT_ADJUST)) {
+ BMO_vert_flag_enable(bm, l_iter->v, ELE_VERT_ADJUST);
+ shared_vert_num += 1;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
- BMO_face_flag_enable(bm, f, ELE_FACE_ADJUST);
- }
+ BMO_face_flag_enable(bm, f, ELE_FACE_ADJUST);
+ }
- vert_accum_pool = BLI_mempool_create(sizeof(struct VertAccum), 0, 512, BLI_MEMPOOL_NOP);
- vaccum_map = BLI_ghash_ptr_new_ex(__func__, shared_vert_num);
+ vert_accum_pool = BLI_mempool_create(sizeof(struct VertAccum), 0, 512, BLI_MEMPOOL_NOP);
+ vaccum_map = BLI_ghash_ptr_new_ex(__func__, shared_vert_num);
- for (iter_step = 0; iter_step < iterations; iter_step++) {
- GHashIterator gh_iter;
- bool changed = false;
+ for (iter_step = 0; iter_step < iterations; iter_step++) {
+ GHashIterator gh_iter;
+ bool changed = false;
- BMO_ITER_INDEX (f, &oiter, op->slots_in, "faces", BM_FACE, i) {
- BMLoop *l_iter, *l_first;
- float plane[4];
+ BMO_ITER_INDEX(f, &oiter, op->slots_in, "faces", BM_FACE, i)
+ {
+ BMLoop *l_iter, *l_first;
+ float plane[4];
- if (!BMO_face_flag_test(bm, f, ELE_FACE_ADJUST)) {
- continue;
- }
- BMO_face_flag_disable(bm, f, ELE_FACE_ADJUST);
+ if (!BMO_face_flag_test(bm, f, ELE_FACE_ADJUST)) {
+ continue;
+ }
+ BMO_face_flag_disable(bm, f, ELE_FACE_ADJUST);
- BLI_assert(f->len != 3);
+ BLI_assert(f->len != 3);
- /* keep original face data (else we 'move' the face) */
+ /* keep original face data (else we 'move' the face) */
#if 0
- BM_face_normal_update(f);
- BM_face_calc_center_median_weighted(f, f_center);
+ BM_face_normal_update(f);
+ BM_face_calc_center_median_weighted(f, f_center);
#endif
- plane_from_point_normal_v3(plane, faces_center[i], f->no);
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- struct VertAccum *va;
- void **va_p;
- float co[3];
-
- if (!BLI_ghash_ensure_p(vaccum_map, l_iter->v, &va_p)) {
- *va_p = BLI_mempool_calloc(vert_accum_pool);
- }
- va = *va_p;
-
- closest_to_plane_normalized_v3(co, plane, l_iter->v->co);
- va->co_tot += 1;
-
- interp_v3_v3v3(va->co, va->co, co, 1.0f / (float)va->co_tot);
- } while ((l_iter = l_iter->next) != l_first);
- }
-
- GHASH_ITER (gh_iter, vaccum_map) {
- BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
- struct VertAccum *va = BLI_ghashIterator_getValue(&gh_iter);
- BMIter iter;
-
- if (len_squared_v3v3(v->co, va->co) > eps_sq) {
- BMO_vert_flag_enable(bm, v, ELE_VERT_ADJUST);
- interp_v3_v3v3(v->co, v->co, va->co, fac);
- changed = true;
- }
-
- /* tag for re-calculation */
- BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) {
- if (f->len != 3) {
- BMO_face_flag_enable(bm, f, ELE_FACE_ADJUST);
- }
- }
- }
-
- /* if nothing changed, break out early */
- if (changed == false) {
- break;
- }
-
- BLI_ghash_clear(vaccum_map, NULL, NULL);
- BLI_mempool_clear(vert_accum_pool);
- }
-
- MEM_freeN(faces_center);
- BLI_ghash_free(vaccum_map, NULL, NULL);
- BLI_mempool_destroy(vert_accum_pool);
+ plane_from_point_normal_v3(plane, faces_center[i], f->no);
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ struct VertAccum *va;
+ void **va_p;
+ float co[3];
+
+ if (!BLI_ghash_ensure_p(vaccum_map, l_iter->v, &va_p)) {
+ *va_p = BLI_mempool_calloc(vert_accum_pool);
+ }
+ va = *va_p;
+
+ closest_to_plane_normalized_v3(co, plane, l_iter->v->co);
+ va->co_tot += 1;
+
+ interp_v3_v3v3(va->co, va->co, co, 1.0f / (float)va->co_tot);
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+
+ GHASH_ITER (gh_iter, vaccum_map) {
+ BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
+ struct VertAccum *va = BLI_ghashIterator_getValue(&gh_iter);
+ BMIter iter;
+
+ if (len_squared_v3v3(v->co, va->co) > eps_sq) {
+ BMO_vert_flag_enable(bm, v, ELE_VERT_ADJUST);
+ interp_v3_v3v3(v->co, v->co, va->co, fac);
+ changed = true;
+ }
+
+ /* tag for re-calculation */
+ BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) {
+ if (f->len != 3) {
+ BMO_face_flag_enable(bm, f, ELE_FACE_ADJUST);
+ }
+ }
+ }
+
+ /* if nothing changed, break out early */
+ if (changed == false) {
+ break;
+ }
+
+ BLI_ghash_clear(vaccum_map, NULL, NULL);
+ BLI_mempool_clear(vert_accum_pool);
+ }
+
+ MEM_freeN(faces_center);
+ BLI_ghash_free(vaccum_map, NULL, NULL);
+ BLI_mempool_destroy(vert_accum_pool);
}
diff --git a/source/blender/bmesh/operators/bmo_poke.c b/source/blender/bmesh/operators/bmo_poke.c
index 2d2a13f3207..f57a2285e4a 100644
--- a/source/blender/bmesh/operators/bmo_poke.c
+++ b/source/blender/bmesh/operators/bmo_poke.c
@@ -41,113 +41,114 @@
*/
void bmo_poke_exec(BMesh *bm, BMOperator *op)
{
- const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
- BMOIter oiter;
- BMFace *f;
-
- const float offset = BMO_slot_float_get(op->slots_in, "offset");
- const bool use_relative_offset = BMO_slot_bool_get(op->slots_in, "use_relative_offset");
- const int center_mode = BMO_slot_int_get(op->slots_in, "center_mode");
- void (*bm_face_calc_center_fn)(const BMFace *f, float r_cent[3]);
-
- switch (center_mode) {
- case BMOP_POKE_MEDIAN_WEIGHTED:
- bm_face_calc_center_fn = BM_face_calc_center_median_weighted;
- break;
- case BMOP_POKE_BOUNDS:
- bm_face_calc_center_fn = BM_face_calc_center_bounds;
- break;
- case BMOP_POKE_MEDIAN:
- bm_face_calc_center_fn = BM_face_calc_center_median;
- break;
- default:
- BLI_assert(0);
- return;
- }
-
- BMO_ITER (f, &oiter, op->slots_in, "faces", BM_FACE) {
- BMFace *f_new;
- float f_center[3], f_center_mean[3];
- BMVert *v_center = NULL;
- BMLoop *l_iter, *l_first;
- /* only interpolate the central loop from the face once,
- * then copy to all others in the fan */
- BMLoop *l_center_example;
-
- /* 1.0 or the average length from the center to the face verts */
- float offset_fac;
-
- int i;
-
- bm_face_calc_center_fn(f, f_center);
- v_center = BM_vert_create(bm, f_center, NULL, BM_CREATE_NOP);
- BMO_vert_flag_enable(bm, v_center, ELE_NEW);
-
- if (cd_loop_mdisp_offset != -1) {
- if (center_mode == BMOP_POKE_MEDIAN) {
- copy_v3_v3(f_center_mean, f_center);
- }
- else {
- BM_face_calc_center_median(f, f_center_mean);
- }
- }
-
- /* handled by BM_loop_interp_from_face */
- // BM_vert_interp_from_face(bm, v_center, f);
-
- if (use_relative_offset) {
- offset_fac = 0.0f;
- }
- else {
- offset_fac = 1.0f;
- }
-
- i = 0;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- BMLoop *l_new;
-
- f_new = BM_face_create_quad_tri(bm, l_iter->v, l_iter->next->v, v_center, NULL, f, BM_CREATE_NOP);
- l_new = BM_FACE_FIRST_LOOP(f_new);
-
- if (i == 0) {
- l_center_example = l_new->prev;
- BM_loop_interp_from_face(bm, l_center_example, f, true, false);
- }
- else {
- BM_elem_attrs_copy(bm, bm, l_center_example, l_new->prev);
- }
-
- /* Copy Loop Data */
- BM_elem_attrs_copy(bm, bm, l_iter, l_new);
- BM_elem_attrs_copy(bm, bm, l_iter->next, l_new->next);
-
- BMO_face_flag_enable(bm, f_new, ELE_NEW);
-
- if (cd_loop_mdisp_offset != -1) {
- float f_new_center[3];
- BM_face_calc_center_median(f_new, f_new_center);
- BM_face_interp_multires_ex(bm, f_new, f, f_new_center, f_center, cd_loop_mdisp_offset);
- }
-
- if (use_relative_offset) {
- offset_fac += len_v3v3(f_center, l_iter->v->co);
- }
-
- } while ((void)i++, (l_iter = l_iter->next) != l_first);
-
- if (use_relative_offset) {
- offset_fac /= (float)f->len;
- }
- /* else remain at 1.0 */
-
- copy_v3_v3(v_center->no, f->no);
- madd_v3_v3fl(v_center->co, v_center->no, offset * offset_fac);
-
- /* Kill Face */
- BM_face_kill(bm, f);
- }
-
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, ELE_NEW);
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, ELE_NEW);
+ const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
+ BMOIter oiter;
+ BMFace *f;
+
+ const float offset = BMO_slot_float_get(op->slots_in, "offset");
+ const bool use_relative_offset = BMO_slot_bool_get(op->slots_in, "use_relative_offset");
+ const int center_mode = BMO_slot_int_get(op->slots_in, "center_mode");
+ void (*bm_face_calc_center_fn)(const BMFace *f, float r_cent[3]);
+
+ switch (center_mode) {
+ case BMOP_POKE_MEDIAN_WEIGHTED:
+ bm_face_calc_center_fn = BM_face_calc_center_median_weighted;
+ break;
+ case BMOP_POKE_BOUNDS:
+ bm_face_calc_center_fn = BM_face_calc_center_bounds;
+ break;
+ case BMOP_POKE_MEDIAN:
+ bm_face_calc_center_fn = BM_face_calc_center_median;
+ break;
+ default:
+ BLI_assert(0);
+ return;
+ }
+
+ BMO_ITER (f, &oiter, op->slots_in, "faces", BM_FACE) {
+ BMFace *f_new;
+ float f_center[3], f_center_mean[3];
+ BMVert *v_center = NULL;
+ BMLoop *l_iter, *l_first;
+ /* only interpolate the central loop from the face once,
+ * then copy to all others in the fan */
+ BMLoop *l_center_example;
+
+ /* 1.0 or the average length from the center to the face verts */
+ float offset_fac;
+
+ int i;
+
+ bm_face_calc_center_fn(f, f_center);
+ v_center = BM_vert_create(bm, f_center, NULL, BM_CREATE_NOP);
+ BMO_vert_flag_enable(bm, v_center, ELE_NEW);
+
+ if (cd_loop_mdisp_offset != -1) {
+ if (center_mode == BMOP_POKE_MEDIAN) {
+ copy_v3_v3(f_center_mean, f_center);
+ }
+ else {
+ BM_face_calc_center_median(f, f_center_mean);
+ }
+ }
+
+ /* handled by BM_loop_interp_from_face */
+ // BM_vert_interp_from_face(bm, v_center, f);
+
+ if (use_relative_offset) {
+ offset_fac = 0.0f;
+ }
+ else {
+ offset_fac = 1.0f;
+ }
+
+ i = 0;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BMLoop *l_new;
+
+ f_new = BM_face_create_quad_tri(
+ bm, l_iter->v, l_iter->next->v, v_center, NULL, f, BM_CREATE_NOP);
+ l_new = BM_FACE_FIRST_LOOP(f_new);
+
+ if (i == 0) {
+ l_center_example = l_new->prev;
+ BM_loop_interp_from_face(bm, l_center_example, f, true, false);
+ }
+ else {
+ BM_elem_attrs_copy(bm, bm, l_center_example, l_new->prev);
+ }
+
+ /* Copy Loop Data */
+ BM_elem_attrs_copy(bm, bm, l_iter, l_new);
+ BM_elem_attrs_copy(bm, bm, l_iter->next, l_new->next);
+
+ BMO_face_flag_enable(bm, f_new, ELE_NEW);
+
+ if (cd_loop_mdisp_offset != -1) {
+ float f_new_center[3];
+ BM_face_calc_center_median(f_new, f_new_center);
+ BM_face_interp_multires_ex(bm, f_new, f, f_new_center, f_center, cd_loop_mdisp_offset);
+ }
+
+ if (use_relative_offset) {
+ offset_fac += len_v3v3(f_center, l_iter->v->co);
+ }
+
+ } while ((void)i++, (l_iter = l_iter->next) != l_first);
+
+ if (use_relative_offset) {
+ offset_fac /= (float)f->len;
+ }
+ /* else remain at 1.0 */
+
+ copy_v3_v3(v_center->no, f->no);
+ madd_v3_v3fl(v_center->co, v_center->no, offset * offset_fac);
+
+ /* Kill Face */
+ BM_face_kill(bm, f);
+ }
+
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, ELE_NEW);
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, ELE_NEW);
}
diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c
index ae9adfbcbba..bea7c56b1d4 100644
--- a/source/blender/bmesh/operators/bmo_primitive.c
+++ b/source/blender/bmesh/operators/bmo_primitive.c
@@ -31,787 +31,760 @@
#include "bmesh.h"
#include "intern/bmesh_operators_private.h"
-
/* ************************ primitives ******************* */
static const float icovert[12][3] = {
- {0.0f, 0.0f, -200.0f},
- {144.72f, -105.144f, -89.443f},
- {-55.277f, -170.128, -89.443f},
- {-178.885f, 0.0f, -89.443f},
- {-55.277f, 170.128f, -89.443f},
- {144.72f, 105.144f, -89.443f},
- {55.277f, -170.128f, 89.443f},
- {-144.72f, -105.144f, 89.443f},
- {-144.72f, 105.144f, 89.443f},
- {55.277f, 170.128f, 89.443f},
- {178.885f, 0.0f, 89.443f},
- {0.0f, 0.0f, 200.0f},
+ {0.0f, 0.0f, -200.0f},
+ {144.72f, -105.144f, -89.443f},
+ {-55.277f, -170.128, -89.443f},
+ {-178.885f, 0.0f, -89.443f},
+ {-55.277f, 170.128f, -89.443f},
+ {144.72f, 105.144f, -89.443f},
+ {55.277f, -170.128f, 89.443f},
+ {-144.72f, -105.144f, 89.443f},
+ {-144.72f, 105.144f, 89.443f},
+ {55.277f, 170.128f, 89.443f},
+ {178.885f, 0.0f, 89.443f},
+ {0.0f, 0.0f, 200.0f},
};
static const short icoface[20][3] = {
- {0, 1, 2},
- {1, 0, 5},
- {0, 2, 3},
- {0, 3, 4},
- {0, 4, 5},
- {1, 5, 10},
- {2, 1, 6},
- {3, 2, 7},
- {4, 3, 8},
- {5, 4, 9},
- {1, 10, 6},
- {2, 6, 7},
- {3, 7, 8},
- {4, 8, 9},
- {5, 9, 10},
- {6, 10, 11},
- {7, 6, 11},
- {8, 7, 11},
- {9, 8, 11},
- {10, 9, 11},
+ {0, 1, 2}, {1, 0, 5}, {0, 2, 3}, {0, 3, 4}, {0, 4, 5}, {1, 5, 10}, {2, 1, 6},
+ {3, 2, 7}, {4, 3, 8}, {5, 4, 9}, {1, 10, 6}, {2, 6, 7}, {3, 7, 8}, {4, 8, 9},
+ {5, 9, 10}, {6, 10, 11}, {7, 6, 11}, {8, 7, 11}, {9, 8, 11}, {10, 9, 11},
};
-static const float icouvs[60][2] =
-{
- {0.818181f, 0.000000f}, {0.727272f, 0.157461f}, {0.909090f, 0.157461f},
- {0.727272f, 0.157461f}, {0.636363f, 0.000000f}, {0.545454f, 0.157461f},
- {0.090909f, 0.000000f}, {0.000000f, 0.157461f}, {0.181818f, 0.157461f},
- {0.272727f, 0.000000f}, {0.181818f, 0.157461f}, {0.363636f, 0.157461f},
- {0.454545f, 0.000000f}, {0.363636f, 0.157461f}, {0.545454f, 0.157461f},
- {0.727272f, 0.157461f}, {0.545454f, 0.157461f}, {0.636363f, 0.314921f},
- {0.909090f, 0.157461f}, {0.727272f, 0.157461f}, {0.818181f, 0.314921f},
- {0.181818f, 0.157461f}, {0.000000f, 0.157461f}, {0.090909f, 0.314921f},
- {0.363636f, 0.157461f}, {0.181818f, 0.157461f}, {0.272727f, 0.314921f},
- {0.545454f, 0.157461f}, {0.363636f, 0.157461f}, {0.454545f, 0.314921f},
- {0.727272f, 0.157461f}, {0.636363f, 0.314921f}, {0.818181f, 0.314921f},
- {0.909090f, 0.157461f}, {0.818181f, 0.314921f}, {1.000000f, 0.314921f},
- {0.181818f, 0.157461f}, {0.090909f, 0.314921f}, {0.272727f, 0.314921f},
- {0.363636f, 0.157461f}, {0.272727f, 0.314921f}, {0.454545f, 0.314921f},
- {0.545454f, 0.157461f}, {0.454545f, 0.314921f}, {0.636363f, 0.314921f},
- {0.818181f, 0.314921f}, {0.636363f, 0.314921f}, {0.727272f, 0.472382f},
- {1.000000f, 0.314921f}, {0.818181f, 0.314921f}, {0.909090f, 0.472382f},
- {0.272727f, 0.314921f}, {0.090909f, 0.314921f}, {0.181818f, 0.472382f},
- {0.454545f, 0.314921f}, {0.272727f, 0.314921f}, {0.363636f, 0.472382f},
- {0.636363f, 0.314921f}, {0.454545f, 0.314921f}, {0.545454f, 0.472382f},
+static const float icouvs[60][2] = {
+ {0.818181f, 0.000000f}, {0.727272f, 0.157461f}, {0.909090f, 0.157461f}, {0.727272f, 0.157461f},
+ {0.636363f, 0.000000f}, {0.545454f, 0.157461f}, {0.090909f, 0.000000f}, {0.000000f, 0.157461f},
+ {0.181818f, 0.157461f}, {0.272727f, 0.000000f}, {0.181818f, 0.157461f}, {0.363636f, 0.157461f},
+ {0.454545f, 0.000000f}, {0.363636f, 0.157461f}, {0.545454f, 0.157461f}, {0.727272f, 0.157461f},
+ {0.545454f, 0.157461f}, {0.636363f, 0.314921f}, {0.909090f, 0.157461f}, {0.727272f, 0.157461f},
+ {0.818181f, 0.314921f}, {0.181818f, 0.157461f}, {0.000000f, 0.157461f}, {0.090909f, 0.314921f},
+ {0.363636f, 0.157461f}, {0.181818f, 0.157461f}, {0.272727f, 0.314921f}, {0.545454f, 0.157461f},
+ {0.363636f, 0.157461f}, {0.454545f, 0.314921f}, {0.727272f, 0.157461f}, {0.636363f, 0.314921f},
+ {0.818181f, 0.314921f}, {0.909090f, 0.157461f}, {0.818181f, 0.314921f}, {1.000000f, 0.314921f},
+ {0.181818f, 0.157461f}, {0.090909f, 0.314921f}, {0.272727f, 0.314921f}, {0.363636f, 0.157461f},
+ {0.272727f, 0.314921f}, {0.454545f, 0.314921f}, {0.545454f, 0.157461f}, {0.454545f, 0.314921f},
+ {0.636363f, 0.314921f}, {0.818181f, 0.314921f}, {0.636363f, 0.314921f}, {0.727272f, 0.472382f},
+ {1.000000f, 0.314921f}, {0.818181f, 0.314921f}, {0.909090f, 0.472382f}, {0.272727f, 0.314921f},
+ {0.090909f, 0.314921f}, {0.181818f, 0.472382f}, {0.454545f, 0.314921f}, {0.272727f, 0.314921f},
+ {0.363636f, 0.472382f}, {0.636363f, 0.314921f}, {0.454545f, 0.314921f}, {0.545454f, 0.472382f},
};
-
static const int monkeyo = 4;
static const int monkeynv = 271;
static const int monkeynf = 250;
static const signed char monkeyv[271][3] = {
- {-71, 21, 98}, {-63, 12, 88}, {-57, 7, 74}, {-82, -3, 79}, {-82, 4, 92},
- {-82, 17, 100}, {-92, 21, 102}, {-101, 12, 95}, {-107, 7, 83},
- {-117, 31, 84}, {-109, 31, 95}, {-96, 31, 102}, {-92, 42, 102},
- {-101, 50, 95}, {-107, 56, 83}, {-82, 66, 79}, {-82, 58, 92},
- {-82, 46, 100}, {-71, 42, 98}, {-63, 50, 88}, {-57, 56, 74},
- {-47, 31, 72}, {-55, 31, 86}, {-67, 31, 97}, {-66, 31, 99},
- {-70, 43, 100}, {-82, 48, 103}, {-93, 43, 105}, {-98, 31, 105},
- {-93, 20, 105}, {-82, 31, 106}, {-82, 15, 103}, {-70, 20, 100},
- {-127, 55, 95}, {-127, 45, 105}, {-127, -87, 94}, {-127, -41, 100},
- {-127, -24, 102}, {-127, -99, 92}, {-127, 52, 77}, {-127, 73, 73},
- {-127, 115, -70}, {-127, 72, -109}, {-127, 9, -106}, {-127, -49, -45},
- {-101, -24, 72}, {-87, -56, 73}, {-82, -89, 73}, {-80, -114, 68},
- {-85, -121, 67}, {-104, -124, 71}, {-127, -126, 74}, {-71, -18, 68},
- {-46, -5, 69}, {-21, 19, 57}, {-17, 55, 76}, {-36, 62, 80},
- {-64, 77, 88}, {-86, 97, 94}, {-107, 92, 97}, {-119, 63, 96},
- {-106, 53, 99}, {-111, 39, 98}, {-101, 12, 95}, {-79, 2, 90},
- {-64, 8, 86}, {-47, 24, 83}, {-45, 38, 83}, {-50, 48, 85},
- {-72, 56, 92}, {-95, 60, 97}, {-127, -98, 94}, {-113, -92, 94},
- {-112, -107, 91}, {-119, -113, 89}, {-127, -114, 88}, {-127, -25, 96},
- {-127, -18, 95}, {-114, -19, 95}, {-111, -29, 96}, {-116, -37, 95},
- {-76, -6, 86}, {-48, 7, 80}, {-34, 26, 77}, {-32, 48, 84},
- {-39, 53, 93}, {-71, 70, 102}, {-87, 82, 107}, {-101, 79, 109},
- {-114, 55, 108}, {-111, -13, 104}, {-100, -57, 91}, {-95, -90, 88},
- {-93, -105, 85}, {-97, -117, 81}, {-106, -119, 81}, {-127, -121, 82},
- {-127, 6, 93}, {-127, 27, 98}, {-85, 61, 95}, {-106, 18, 96},
- {-110, 27, 97}, {-112, -88, 94}, {-117, -57, 96}, {-127, -57, 96},
- {-127, -42, 95}, {-115, -35, 100}, {-110, -29, 102}, {-113, -17, 100},
- {-122, -16, 100}, {-127, -26, 106}, {-121, -19, 104}, {-115, -20, 104},
- {-113, -29, 106}, {-117, -32, 103}, {-127, -37, 103}, {-94, -40, 71},
- {-106, -31, 91}, {-104, -40, 91}, {-97, -32, 71}, {-127, -112, 88},
- {-121, -111, 88}, {-115, -105, 91}, {-115, -95, 93}, {-127, -100, 84},
- {-115, -96, 85}, {-115, -104, 82}, {-121, -109, 81}, {-127, -110, 81},
- {-105, 28, 100}, {-103, 20, 99}, {-84, 55, 97}, {-92, 54, 99},
- {-73, 51, 99}, {-55, 45, 89}, {-52, 37, 88}, {-53, 25, 87},
- {-66, 13, 92}, {-79, 8, 95}, {-98, 14, 100}, {-104, 38, 100},
- {-100, 48, 100}, {-97, 46, 97}, {-102, 38, 97}, {-96, 16, 97},
- {-79, 11, 93}, {-68, 15, 90}, {-57, 27, 86}, {-56, 36, 86},
- {-59, 43, 87}, {-74, 50, 96}, {-91, 51, 98}, {-84, 52, 96},
- {-101, 22, 96}, {-102, 29, 96}, {-113, 59, 78}, {-102, 85, 79},
- {-84, 88, 76}, {-65, 71, 71}, {-40, 58, 63}, {-25, 52, 59},
- {-28, 21, 48}, {-50, 0, 53}, {-71, -12, 60}, {-127, 115, 37},
- {-127, 126, -10}, {-127, -25, -86}, {-127, -59, 24}, {-127, -125, 59},
- {-127, -103, 44}, {-127, -73, 41}, {-127, -62, 36}, {-18, 30, 7},
- {-17, 41, -6}, {-28, 34, -56}, {-68, 56, -90}, {-33, -6, 9},
- {-51, -16, -21}, {-45, -1, -55}, {-84, 7, -85}, {-97, -45, 52},
- {-104, -53, 33}, {-90, -91, 49}, {-95, -64, 50}, {-85, -117, 51},
- {-109, -97, 47}, {-111, -69, 46}, {-106, -121, 56}, {-99, -36, 55},
- {-100, -29, 60}, {-101, -22, 64}, {-100, -50, 21}, {-89, -40, -34},
- {-83, -19, -69}, {-69, 111, -49}, {-69, 119, -9}, {-69, 109, 30},
- {-68, 67, 55}, {-34, 52, 43}, {-46, 58, 36}, {-45, 90, 7},
- {-25, 72, 16}, {-25, 79, -15}, {-45, 96, -25}, {-45, 87, -57},
- {-25, 69, -46}, {-48, 42, -75}, {-65, 3, -70}, {-22, 42, -26},
- {-75, -22, 19}, {-72, -25, -27}, {-13, 52, -30}, {-28, -18, -16},
- {6, -13, -42}, {37, 7, -55}, {46, 41, -54}, {31, 65, -54},
- {4, 61, -40}, {3, 53, -37}, {25, 56, -50}, {35, 37, -52},
- {28, 10, -52}, {5, -5, -39}, {-21, -9, -17}, {-9, 46, -28},
- {-6, 39, -37}, {-14, -3, -27}, {6, 0, -47}, {25, 12, -57},
- {31, 32, -57}, {23, 46, -56}, {4, 44, -46}, {-19, 37, -27},
- {-20, 22, -35}, {-30, 12, -35}, {-22, 11, -35}, {-19, 2, -35},
- {-23, -2, -35}, {-34, 0, -9}, {-35, -3, -22}, {-35, 5, -24},
- {-25, 26, -27}, {-13, 31, -34}, {-13, 30, -41}, {-23, -2, -41},
- {-18, 2, -41}, {-21, 10, -41}, {-29, 12, -41}, {-19, 22, -41},
- {6, 42, -53}, {25, 44, -62}, {34, 31, -63}, {28, 11, -62},
- {7, 0, -54}, {-14, -2, -34}, {-5, 37, -44}, {-13, 14, -42},
- {-7, 8, -43}, {1, 16, -47}, {-4, 22, -45}, {3, 30, -48},
- {8, 24, -49}, {15, 27, -50}, {12, 35, -50}, {4, 56, -62},
- {33, 60, -70}, {48, 38, -64}, {41, 7, -68}, {6, -11, -63},
- {-26, -16, -42}, {-17, 49, -49},
+ {-71, 21, 98}, {-63, 12, 88}, {-57, 7, 74}, {-82, -3, 79}, {-82, 4, 92},
+ {-82, 17, 100}, {-92, 21, 102}, {-101, 12, 95}, {-107, 7, 83}, {-117, 31, 84},
+ {-109, 31, 95}, {-96, 31, 102}, {-92, 42, 102}, {-101, 50, 95}, {-107, 56, 83},
+ {-82, 66, 79}, {-82, 58, 92}, {-82, 46, 100}, {-71, 42, 98}, {-63, 50, 88},
+ {-57, 56, 74}, {-47, 31, 72}, {-55, 31, 86}, {-67, 31, 97}, {-66, 31, 99},
+ {-70, 43, 100}, {-82, 48, 103}, {-93, 43, 105}, {-98, 31, 105}, {-93, 20, 105},
+ {-82, 31, 106}, {-82, 15, 103}, {-70, 20, 100}, {-127, 55, 95}, {-127, 45, 105},
+ {-127, -87, 94}, {-127, -41, 100}, {-127, -24, 102}, {-127, -99, 92}, {-127, 52, 77},
+ {-127, 73, 73}, {-127, 115, -70}, {-127, 72, -109}, {-127, 9, -106}, {-127, -49, -45},
+ {-101, -24, 72}, {-87, -56, 73}, {-82, -89, 73}, {-80, -114, 68}, {-85, -121, 67},
+ {-104, -124, 71}, {-127, -126, 74}, {-71, -18, 68}, {-46, -5, 69}, {-21, 19, 57},
+ {-17, 55, 76}, {-36, 62, 80}, {-64, 77, 88}, {-86, 97, 94}, {-107, 92, 97},
+ {-119, 63, 96}, {-106, 53, 99}, {-111, 39, 98}, {-101, 12, 95}, {-79, 2, 90},
+ {-64, 8, 86}, {-47, 24, 83}, {-45, 38, 83}, {-50, 48, 85}, {-72, 56, 92},
+ {-95, 60, 97}, {-127, -98, 94}, {-113, -92, 94}, {-112, -107, 91}, {-119, -113, 89},
+ {-127, -114, 88}, {-127, -25, 96}, {-127, -18, 95}, {-114, -19, 95}, {-111, -29, 96},
+ {-116, -37, 95}, {-76, -6, 86}, {-48, 7, 80}, {-34, 26, 77}, {-32, 48, 84},
+ {-39, 53, 93}, {-71, 70, 102}, {-87, 82, 107}, {-101, 79, 109}, {-114, 55, 108},
+ {-111, -13, 104}, {-100, -57, 91}, {-95, -90, 88}, {-93, -105, 85}, {-97, -117, 81},
+ {-106, -119, 81}, {-127, -121, 82}, {-127, 6, 93}, {-127, 27, 98}, {-85, 61, 95},
+ {-106, 18, 96}, {-110, 27, 97}, {-112, -88, 94}, {-117, -57, 96}, {-127, -57, 96},
+ {-127, -42, 95}, {-115, -35, 100}, {-110, -29, 102}, {-113, -17, 100}, {-122, -16, 100},
+ {-127, -26, 106}, {-121, -19, 104}, {-115, -20, 104}, {-113, -29, 106}, {-117, -32, 103},
+ {-127, -37, 103}, {-94, -40, 71}, {-106, -31, 91}, {-104, -40, 91}, {-97, -32, 71},
+ {-127, -112, 88}, {-121, -111, 88}, {-115, -105, 91}, {-115, -95, 93}, {-127, -100, 84},
+ {-115, -96, 85}, {-115, -104, 82}, {-121, -109, 81}, {-127, -110, 81}, {-105, 28, 100},
+ {-103, 20, 99}, {-84, 55, 97}, {-92, 54, 99}, {-73, 51, 99}, {-55, 45, 89},
+ {-52, 37, 88}, {-53, 25, 87}, {-66, 13, 92}, {-79, 8, 95}, {-98, 14, 100},
+ {-104, 38, 100}, {-100, 48, 100}, {-97, 46, 97}, {-102, 38, 97}, {-96, 16, 97},
+ {-79, 11, 93}, {-68, 15, 90}, {-57, 27, 86}, {-56, 36, 86}, {-59, 43, 87},
+ {-74, 50, 96}, {-91, 51, 98}, {-84, 52, 96}, {-101, 22, 96}, {-102, 29, 96},
+ {-113, 59, 78}, {-102, 85, 79}, {-84, 88, 76}, {-65, 71, 71}, {-40, 58, 63},
+ {-25, 52, 59}, {-28, 21, 48}, {-50, 0, 53}, {-71, -12, 60}, {-127, 115, 37},
+ {-127, 126, -10}, {-127, -25, -86}, {-127, -59, 24}, {-127, -125, 59}, {-127, -103, 44},
+ {-127, -73, 41}, {-127, -62, 36}, {-18, 30, 7}, {-17, 41, -6}, {-28, 34, -56},
+ {-68, 56, -90}, {-33, -6, 9}, {-51, -16, -21}, {-45, -1, -55}, {-84, 7, -85},
+ {-97, -45, 52}, {-104, -53, 33}, {-90, -91, 49}, {-95, -64, 50}, {-85, -117, 51},
+ {-109, -97, 47}, {-111, -69, 46}, {-106, -121, 56}, {-99, -36, 55}, {-100, -29, 60},
+ {-101, -22, 64}, {-100, -50, 21}, {-89, -40, -34}, {-83, -19, -69}, {-69, 111, -49},
+ {-69, 119, -9}, {-69, 109, 30}, {-68, 67, 55}, {-34, 52, 43}, {-46, 58, 36},
+ {-45, 90, 7}, {-25, 72, 16}, {-25, 79, -15}, {-45, 96, -25}, {-45, 87, -57},
+ {-25, 69, -46}, {-48, 42, -75}, {-65, 3, -70}, {-22, 42, -26}, {-75, -22, 19},
+ {-72, -25, -27}, {-13, 52, -30}, {-28, -18, -16}, {6, -13, -42}, {37, 7, -55},
+ {46, 41, -54}, {31, 65, -54}, {4, 61, -40}, {3, 53, -37}, {25, 56, -50},
+ {35, 37, -52}, {28, 10, -52}, {5, -5, -39}, {-21, -9, -17}, {-9, 46, -28},
+ {-6, 39, -37}, {-14, -3, -27}, {6, 0, -47}, {25, 12, -57}, {31, 32, -57},
+ {23, 46, -56}, {4, 44, -46}, {-19, 37, -27}, {-20, 22, -35}, {-30, 12, -35},
+ {-22, 11, -35}, {-19, 2, -35}, {-23, -2, -35}, {-34, 0, -9}, {-35, -3, -22},
+ {-35, 5, -24}, {-25, 26, -27}, {-13, 31, -34}, {-13, 30, -41}, {-23, -2, -41},
+ {-18, 2, -41}, {-21, 10, -41}, {-29, 12, -41}, {-19, 22, -41}, {6, 42, -53},
+ {25, 44, -62}, {34, 31, -63}, {28, 11, -62}, {7, 0, -54}, {-14, -2, -34},
+ {-5, 37, -44}, {-13, 14, -42}, {-7, 8, -43}, {1, 16, -47}, {-4, 22, -45},
+ {3, 30, -48}, {8, 24, -49}, {15, 27, -50}, {12, 35, -50}, {4, 56, -62},
+ {33, 60, -70}, {48, 38, -64}, {41, 7, -68}, {6, -11, -63}, {-26, -16, -42},
+ {-17, 49, -49},
};
static signed char monkeyf[250][4] = {
- {27, 4, 5, 26}, {25, 4, 5, 24}, {3, 6, 5, 4}, {1, 6, 5, 2}, {5, 6, 7, 4},
- {3, 6, 7, 2}, {5, 8, 7, 6}, {3, 8, 7, 4}, {7, 8, 9, 6},
- {5, 8, 9, 4}, {7, 10, 9, 8}, {5, 10, 9, 6}, {9, 10, 11, 8},
- {7, 10, 11, 6}, {9, 12, 11, 10}, {7, 12, 11, 8}, {11, 6, 13, 12},
- {5, 4, 13, 12}, {3, -2, 13, 12}, {-3, -4, 13, 12}, {-5, -10, 13, 12},
- {-11, -12, 14, 12}, {-13, -18, 14, 13}, {-19, 4, 5, 13}, {10, 12, 4, 4},
- {10, 11, 9, 9}, {8, 7, 9, 9}, {7, 5, 6, 6}, {6, 3, 4, 4},
- {5, 1, 2, 2}, {4, -1, 0, 0}, {3, -3, -2, -2}, {22, 67, 68, 23},
- {20, 65, 66, 21}, {18, 63, 64, 19}, {16, 61, 62, 17}, {14, 59, 60, 15},
- {12, 19, 48, 57}, {18, 19, 48, 47}, {18, 19, 48, 47}, {18, 19, 48, 47},
- {18, 19, 48, 47}, {18, 19, 48, 47}, {18, 19, 48, 47}, {18, 19, 48, 47},
- {18, 19, 48, 47}, {18, -9, -8, 47}, {18, 27, 45, 46}, {26, 55, 43, 44},
- {24, 41, 42, 54}, {22, 39, 40, 23}, {20, 37, 38, 21}, {18, 35, 36, 19},
- {16, 33, 34, 17}, {14, 31, 32, 15}, {12, 39, 30, 13}, {11, 48, 45, 38},
- {8, 36, -19, 9}, {8, -20, 44, 47}, {42, 45, 46, 43}, {18, 19, 40, 39},
- {16, 17, 38, 37}, {14, 15, 36, 35}, {32, 44, 43, 33}, {12, 33, 32, 42},
- {19, 44, 43, 42}, {40, 41, 42, -27}, {8, 9, 39, -28}, {15, 43, 42, 16},
- {13, 43, 42, 14}, {11, 43, 42, 12}, {9, -30, 42, 10}, {37, 12, 38, -32},
- {-33, 37, 45, 46}, {-33, 40, 41, 39}, {38, 40, 41, 37}, {36, 40, 41, 35},
- {34, 40, 41, 33}, {36, 39, 38, 37}, {35, 40, 39, 38}, {1, 2, 14, 21},
- {1, 2, 40, 13}, {1, 2, 40, 39}, {1, 24, 12, 39}, {-34, 36, 38, 11},
- {35, 38, 36, 37}, {-37, 8, 35, 37}, {-11, -12, -45, 40}, {-11, -12, 39, 38},
- {-11, -12, 37, 36}, {-11, -12, 35, 34}, {33, 34, 40, 41}, {33, 34, 38, 39},
- {33, 34, 36, 37}, {33, -52, 34, 35}, {33, 37, 36, 34}, {33, 35, 34, 34},
- {8, 7, 37, 36}, {-32, 7, 35, 46}, {-34, -33, 45, 46}, {4, -33, 43, 34},
- {-34, -33, 41, 42}, {-34, -33, 39, 40}, {-34, -33, 37, 38}, {-34, -33, 35, 36},
- {-34, -33, 33, 34}, {-34, -33, 31, 32}, {-34, -4, 28, 30}, {-5, -34, 28, 27},
- {-35, -44, 36, 27}, {26, 35, 36, 45}, {24, 25, 44, 45}, {25, 23, 44, 42},
- {25, 24, 41, 40}, {25, 24, 39, 38}, {25, 24, 37, 36}, {25, 24, 35, 34},
- {25, 24, 33, 32}, {25, 24, 31, 30}, {15, 24, 29, 38}, {25, 24, 27, 26},
- {23, 12, 37, 26}, {11, 12, 35, 36}, {-86, -59, 36, -80}, {-60, -61, 36, 35},
- {-62, -63, 36, 35}, {-64, -65, 36, 35}, {-66, -67, 36, 35}, {-68, -69, 36, 35},
- {-70, -71, 36, 35}, {-72, -73, 36, 35}, {-74, -75, 36, 35}, {42, 43, 53, 58},
- {40, 41, 57, 56}, {38, 39, 55, 57}, {-81, -80, 37, 56}, {-83, -82, 55, 52},
- {-85, -84, 51, 49}, {-87, -86, 48, 49}, {47, 50, 51, 48}, {46, 48, 51, 49},
- {43, 46, 49, 44}, {-92, -91, 45, 42}, {-23, 49, 50, -20}, {-94, 40, 48, -24},
- {-96, -22, 48, 49}, {-97, 48, 21, -90}, {-100, 36, 50, 23}, {22, 49, 48, -100},
- {-101, 47, 46, 22}, {21, 45, 35, 25}, {33, 34, 44, 41}, {13, 14, 28, 24},
- {-107, 26, 30, -106}, {14, 46, 45, 15}, {14, 44, 43, -110}, {-111, 42, 23, -110},
- {6, 7, 45, 46}, {45, 44, 47, 46}, {45, 46, 47, 48}, {47, 46, 49, 48},
- {17, 49, 47, 48}, {17, 36, 46, 48}, {35, 36, 44, 45}, {35, 36, 40, 43},
- {35, 36, 38, 39}, {-4, -3, 37, 35}, {-123, 34, 33, 1}, {-9, -8, -7, -6},
- {-10, -7, 32, -125}, {-127, -11, -126, -126}, {-7, -6, 5, 31}, {4, 5, 33, 30},
- {4, 39, 33, 32}, {4, 35, 32, 38}, {20, 21, 39, 38}, {4, 37, 38, 5},
- {-11, -10, 36, 3}, {-11, 15, 14, 35}, {13, 16, 34, 34}, {-13, 14, 13, 13},
- {-3, 1, 30, 29}, {-3, 28, 29, 1}, {-2, 31, 28, -1}, {12, 13, 27, 30},
- {-2, 26, 12, 12}, {35, 29, 42, 36}, {34, 35, 36, 33}, {32, 35, 36, 31},
- {30, 35, 36, 29}, {28, 35, 36, 27}, {26, 35, 36, 25}, {34, 39, 38, 35},
- {32, 39, 38, 33}, {30, 39, 38, 31}, {28, 39, 38, 29}, {26, 39, 38, 27},
- {25, 31, 32, 38}, {-18, -17, 45, 44}, {-18, 17, 28, 44}, {-24, -20, 42, -23},
- {11, 35, 27, 14}, {25, 28, 39, 41}, {37, 41, 40, 38}, {34, 40, 36, 35},
- {32, 40, 39, 33}, {30, 39, 31, 40}, {21, 29, 39, 22}, {-31, 37, 28, 4},
- {-32, 33, 35, 36}, {32, 33, 34, 34}, {18, 35, 36, 48}, {34, 25, 40, 35},
- {24, 25, 38, 39}, {24, 25, 36, 37}, {24, 25, 34, 35}, {24, 25, 32, 33},
- {24, 13, 41, 31}, {17, 11, 41, 35}, {15, 16, 34, 35}, {13, 14, 34, 35},
- {11, 12, 34, 35}, {9, 10, 34, 35}, {7, 8, 34, 35}, {26, 25, 37, 36},
- {35, 36, 37, 38}, {37, 36, 39, 38}, {37, 38, 39, 40}, {25, 31, 36, 39},
- {18, 34, 35, 30}, {17, 22, 30, 33}, {19, 29, 21, 20}, {16, 26, 29, 17},
- {24, 29, 28, 25}, {22, 31, 28, 23}, {20, 31, 30, 21}, {18, 31, 30, 19},
- {16, 30, 17, 17}, {-21, -22, 35, 34}, {-21, -22, 33, 32}, {-21, -22, 31, 30},
- {-21, -22, 29, 28}, {-21, -22, 27, 26}, {-28, -22, 25, 31}, {24, 28, 29, 30},
- {23, 24, 26, 27}, {23, 24, 25, 25}, {-69, -35, -32, 27}, {-70, 26, 25, -66},
- {-68, -67, 24, -33},
+ {27, 4, 5, 26}, {25, 4, 5, 24}, {3, 6, 5, 4},
+ {1, 6, 5, 2}, {5, 6, 7, 4}, {3, 6, 7, 2},
+ {5, 8, 7, 6}, {3, 8, 7, 4}, {7, 8, 9, 6},
+ {5, 8, 9, 4}, {7, 10, 9, 8}, {5, 10, 9, 6},
+ {9, 10, 11, 8}, {7, 10, 11, 6}, {9, 12, 11, 10},
+ {7, 12, 11, 8}, {11, 6, 13, 12}, {5, 4, 13, 12},
+ {3, -2, 13, 12}, {-3, -4, 13, 12}, {-5, -10, 13, 12},
+ {-11, -12, 14, 12}, {-13, -18, 14, 13}, {-19, 4, 5, 13},
+ {10, 12, 4, 4}, {10, 11, 9, 9}, {8, 7, 9, 9},
+ {7, 5, 6, 6}, {6, 3, 4, 4}, {5, 1, 2, 2},
+ {4, -1, 0, 0}, {3, -3, -2, -2}, {22, 67, 68, 23},
+ {20, 65, 66, 21}, {18, 63, 64, 19}, {16, 61, 62, 17},
+ {14, 59, 60, 15}, {12, 19, 48, 57}, {18, 19, 48, 47},
+ {18, 19, 48, 47}, {18, 19, 48, 47}, {18, 19, 48, 47},
+ {18, 19, 48, 47}, {18, 19, 48, 47}, {18, 19, 48, 47},
+ {18, 19, 48, 47}, {18, -9, -8, 47}, {18, 27, 45, 46},
+ {26, 55, 43, 44}, {24, 41, 42, 54}, {22, 39, 40, 23},
+ {20, 37, 38, 21}, {18, 35, 36, 19}, {16, 33, 34, 17},
+ {14, 31, 32, 15}, {12, 39, 30, 13}, {11, 48, 45, 38},
+ {8, 36, -19, 9}, {8, -20, 44, 47}, {42, 45, 46, 43},
+ {18, 19, 40, 39}, {16, 17, 38, 37}, {14, 15, 36, 35},
+ {32, 44, 43, 33}, {12, 33, 32, 42}, {19, 44, 43, 42},
+ {40, 41, 42, -27}, {8, 9, 39, -28}, {15, 43, 42, 16},
+ {13, 43, 42, 14}, {11, 43, 42, 12}, {9, -30, 42, 10},
+ {37, 12, 38, -32}, {-33, 37, 45, 46}, {-33, 40, 41, 39},
+ {38, 40, 41, 37}, {36, 40, 41, 35}, {34, 40, 41, 33},
+ {36, 39, 38, 37}, {35, 40, 39, 38}, {1, 2, 14, 21},
+ {1, 2, 40, 13}, {1, 2, 40, 39}, {1, 24, 12, 39},
+ {-34, 36, 38, 11}, {35, 38, 36, 37}, {-37, 8, 35, 37},
+ {-11, -12, -45, 40}, {-11, -12, 39, 38}, {-11, -12, 37, 36},
+ {-11, -12, 35, 34}, {33, 34, 40, 41}, {33, 34, 38, 39},
+ {33, 34, 36, 37}, {33, -52, 34, 35}, {33, 37, 36, 34},
+ {33, 35, 34, 34}, {8, 7, 37, 36}, {-32, 7, 35, 46},
+ {-34, -33, 45, 46}, {4, -33, 43, 34}, {-34, -33, 41, 42},
+ {-34, -33, 39, 40}, {-34, -33, 37, 38}, {-34, -33, 35, 36},
+ {-34, -33, 33, 34}, {-34, -33, 31, 32}, {-34, -4, 28, 30},
+ {-5, -34, 28, 27}, {-35, -44, 36, 27}, {26, 35, 36, 45},
+ {24, 25, 44, 45}, {25, 23, 44, 42}, {25, 24, 41, 40},
+ {25, 24, 39, 38}, {25, 24, 37, 36}, {25, 24, 35, 34},
+ {25, 24, 33, 32}, {25, 24, 31, 30}, {15, 24, 29, 38},
+ {25, 24, 27, 26}, {23, 12, 37, 26}, {11, 12, 35, 36},
+ {-86, -59, 36, -80}, {-60, -61, 36, 35}, {-62, -63, 36, 35},
+ {-64, -65, 36, 35}, {-66, -67, 36, 35}, {-68, -69, 36, 35},
+ {-70, -71, 36, 35}, {-72, -73, 36, 35}, {-74, -75, 36, 35},
+ {42, 43, 53, 58}, {40, 41, 57, 56}, {38, 39, 55, 57},
+ {-81, -80, 37, 56}, {-83, -82, 55, 52}, {-85, -84, 51, 49},
+ {-87, -86, 48, 49}, {47, 50, 51, 48}, {46, 48, 51, 49},
+ {43, 46, 49, 44}, {-92, -91, 45, 42}, {-23, 49, 50, -20},
+ {-94, 40, 48, -24}, {-96, -22, 48, 49}, {-97, 48, 21, -90},
+ {-100, 36, 50, 23}, {22, 49, 48, -100}, {-101, 47, 46, 22},
+ {21, 45, 35, 25}, {33, 34, 44, 41}, {13, 14, 28, 24},
+ {-107, 26, 30, -106}, {14, 46, 45, 15}, {14, 44, 43, -110},
+ {-111, 42, 23, -110}, {6, 7, 45, 46}, {45, 44, 47, 46},
+ {45, 46, 47, 48}, {47, 46, 49, 48}, {17, 49, 47, 48},
+ {17, 36, 46, 48}, {35, 36, 44, 45}, {35, 36, 40, 43},
+ {35, 36, 38, 39}, {-4, -3, 37, 35}, {-123, 34, 33, 1},
+ {-9, -8, -7, -6}, {-10, -7, 32, -125}, {-127, -11, -126, -126},
+ {-7, -6, 5, 31}, {4, 5, 33, 30}, {4, 39, 33, 32},
+ {4, 35, 32, 38}, {20, 21, 39, 38}, {4, 37, 38, 5},
+ {-11, -10, 36, 3}, {-11, 15, 14, 35}, {13, 16, 34, 34},
+ {-13, 14, 13, 13}, {-3, 1, 30, 29}, {-3, 28, 29, 1},
+ {-2, 31, 28, -1}, {12, 13, 27, 30}, {-2, 26, 12, 12},
+ {35, 29, 42, 36}, {34, 35, 36, 33}, {32, 35, 36, 31},
+ {30, 35, 36, 29}, {28, 35, 36, 27}, {26, 35, 36, 25},
+ {34, 39, 38, 35}, {32, 39, 38, 33}, {30, 39, 38, 31},
+ {28, 39, 38, 29}, {26, 39, 38, 27}, {25, 31, 32, 38},
+ {-18, -17, 45, 44}, {-18, 17, 28, 44}, {-24, -20, 42, -23},
+ {11, 35, 27, 14}, {25, 28, 39, 41}, {37, 41, 40, 38},
+ {34, 40, 36, 35}, {32, 40, 39, 33}, {30, 39, 31, 40},
+ {21, 29, 39, 22}, {-31, 37, 28, 4}, {-32, 33, 35, 36},
+ {32, 33, 34, 34}, {18, 35, 36, 48}, {34, 25, 40, 35},
+ {24, 25, 38, 39}, {24, 25, 36, 37}, {24, 25, 34, 35},
+ {24, 25, 32, 33}, {24, 13, 41, 31}, {17, 11, 41, 35},
+ {15, 16, 34, 35}, {13, 14, 34, 35}, {11, 12, 34, 35},
+ {9, 10, 34, 35}, {7, 8, 34, 35}, {26, 25, 37, 36},
+ {35, 36, 37, 38}, {37, 36, 39, 38}, {37, 38, 39, 40},
+ {25, 31, 36, 39}, {18, 34, 35, 30}, {17, 22, 30, 33},
+ {19, 29, 21, 20}, {16, 26, 29, 17}, {24, 29, 28, 25},
+ {22, 31, 28, 23}, {20, 31, 30, 21}, {18, 31, 30, 19},
+ {16, 30, 17, 17}, {-21, -22, 35, 34}, {-21, -22, 33, 32},
+ {-21, -22, 31, 30}, {-21, -22, 29, 28}, {-21, -22, 27, 26},
+ {-28, -22, 25, 31}, {24, 28, 29, 30}, {23, 24, 26, 27},
+ {23, 24, 25, 25}, {-69, -35, -32, 27}, {-70, 26, 25, -66},
+ {-68, -67, 24, -33},
};
-static const float monkeyuvs[] =
-{
- 0.890955f, 0.590063f, 0.870622f, 0.589649f, 0.860081f, 0.560115f, 0.904571f, 0.559404f,
- 0.856226f, 0.850547f, 0.868067f, 0.821510f, 0.888398f, 0.821999f, 0.900640f, 0.853232f,
- 0.904571f, 0.559404f, 0.860081f, 0.560115f, 0.853018f, 0.521562f, 0.920166f, 0.524546f,
- 0.847458f, 0.888748f, 0.856226f, 0.850547f, 0.900640f, 0.853232f, 0.914672f, 0.888748f,
- 0.860081f, 0.560115f, 0.828900f, 0.590771f, 0.798481f, 0.569535f, 0.853018f, 0.521562f,
- 0.795104f, 0.838402f, 0.826436f, 0.818537f, 0.856226f, 0.850547f, 0.847458f, 0.888748f,
- 0.870622f, 0.589649f, 0.854402f, 0.604754f, 0.828900f, 0.590771f, 0.860081f, 0.560115f,
- 0.826436f, 0.818537f, 0.852534f, 0.805700f, 0.868067f, 0.821510f, 0.856226f, 0.850547f,
- 0.854402f, 0.604754f, 0.854107f, 0.625459f, 0.828171f, 0.633354f, 0.828900f, 0.590771f,
- 0.827598f, 0.775964f, 0.853157f, 0.785002f, 0.852534f, 0.805700f, 0.826436f, 0.818537f,
- 0.828900f, 0.590771f, 0.828171f, 0.633354f, 0.791018f, 0.645443f, 0.798481f, 0.569535f,
- 0.791018f, 0.762238f, 0.827598f, 0.775964f, 0.826436f, 0.818537f, 0.795104f, 0.838402f,
- 0.828171f, 0.633354f, 0.855181f, 0.668527f, 0.842358f, 0.702491f, 0.791018f, 0.645443f,
- 0.844839f, 0.707525f, 0.856142f, 0.742025f, 0.827598f, 0.775964f, 0.791018f, 0.762238f,
- 0.854107f, 0.625459f, 0.867508f, 0.642291f, 0.855181f, 0.668527f, 0.828171f, 0.633354f,
- 0.856142f, 0.742025f, 0.867293f, 0.768782f, 0.853157f, 0.785002f, 0.827598f, 0.775964f,
- 0.867508f, 0.642291f, 0.890474f, 0.641909f, 0.900375f, 0.666964f, 0.855181f, 0.668527f,
- 0.901223f, 0.745592f, 0.890219f, 0.770183f, 0.867293f, 0.768782f, 0.856142f, 0.742025f,
- 0.855181f, 0.668527f, 0.900375f, 0.666964f, 0.918898f, 0.699697f, 0.842358f, 0.702491f,
- 0.921180f, 0.713713f, 0.901223f, 0.745592f, 0.856142f, 0.742025f, 0.844839f, 0.707525f,
- 0.900375f, 0.666964f, 0.931889f, 0.636832f, 0.968392f, 0.645333f, 0.918898f, 0.699697f,
- 0.968213f, 0.770220f, 0.931368f, 0.777093f, 0.901223f, 0.745592f, 0.921180f, 0.713713f,
- 0.890474f, 0.641909f, 0.905882f, 0.627902f, 0.931889f, 0.636832f, 0.900375f, 0.666964f,
- 0.931368f, 0.777093f, 0.904990f, 0.784860f, 0.890219f, 0.770183f, 0.901223f, 0.745592f,
- 0.905882f, 0.627902f, 0.906232f, 0.605742f, 0.933717f, 0.593037f, 0.931889f, 0.636832f,
- 0.931250f, 0.820926f, 0.904357f, 0.807013f, 0.904990f, 0.784860f, 0.931368f, 0.777093f,
- 0.931889f, 0.636832f, 0.933717f, 0.593037f, 0.968392f, 0.573812f, 0.968392f, 0.645333f,
- 0.965038f, 0.841671f, 0.931250f, 0.820926f, 0.931368f, 0.777093f, 0.968213f, 0.770220f,
- 0.933717f, 0.593037f, 0.904571f, 0.559404f, 0.920166f, 0.524546f, 0.968392f, 0.573812f,
- 0.914672f, 0.888748f, 0.900640f, 0.853232f, 0.931250f, 0.820926f, 0.965038f, 0.841671f,
- 0.906232f, 0.605742f, 0.890955f, 0.590063f, 0.904571f, 0.559404f, 0.933717f, 0.593037f,
- 0.900640f, 0.853232f, 0.888398f, 0.821999f, 0.904357f, 0.807013f, 0.931250f, 0.820926f,
- 0.890955f, 0.590063f, 0.906232f, 0.605742f, 0.902359f, 0.607909f, 0.889591f, 0.593275f,
- 0.900583f, 0.804677f, 0.904357f, 0.807013f, 0.888398f, 0.821999f, 0.887178f, 0.818729f,
- 0.906232f, 0.605742f, 0.905882f, 0.627902f, 0.899781f, 0.626257f, 0.902359f, 0.607909f,
- 0.898822f, 0.786233f, 0.904990f, 0.784860f, 0.904357f, 0.807013f, 0.900583f, 0.804677f,
- 0.905882f, 0.627902f, 0.890474f, 0.641909f, 0.887842f, 0.636527f, 0.899781f, 0.626257f,
- 0.887351f, 0.775442f, 0.890219f, 0.770183f, 0.904990f, 0.784860f, 0.898822f, 0.786233f,
- 0.890474f, 0.641909f, 0.867508f, 0.642291f, 0.870908f, 0.635245f, 0.887842f, 0.636527f,
- 0.870376f, 0.775972f, 0.867293f, 0.768782f, 0.890219f, 0.770183f, 0.887351f, 0.775442f,
- 0.867508f, 0.642291f, 0.854107f, 0.625459f, 0.859881f, 0.623942f, 0.870908f, 0.635245f,
- 0.858859f, 0.786774f, 0.853157f, 0.785002f, 0.867293f, 0.768782f, 0.870376f, 0.775972f,
- 0.854107f, 0.625459f, 0.854402f, 0.604754f, 0.859664f, 0.608186f, 0.859881f, 0.623942f,
- 0.857942f, 0.802505f, 0.852534f, 0.805700f, 0.853157f, 0.785002f, 0.858859f, 0.786774f,
- 0.854402f, 0.604754f, 0.870622f, 0.589649f, 0.871664f, 0.593961f, 0.859664f, 0.608186f,
- 0.869299f, 0.817249f, 0.868067f, 0.821510f, 0.852534f, 0.805700f, 0.857942f, 0.802505f,
- 0.870622f, 0.589649f, 0.890955f, 0.590063f, 0.889591f, 0.593275f, 0.871664f, 0.593961f,
- 0.887178f, 0.818729f, 0.888398f, 0.821999f, 0.868067f, 0.821510f, 0.869299f, 0.817249f,
- 0.879400f, 0.616512f, 0.871664f, 0.593961f, 0.889591f, 0.593275f,
- 0.887178f, 0.818729f, 0.869299f, 0.817249f, 0.878029f, 0.795063f,
- 0.859664f, 0.608186f, 0.871664f, 0.593961f, 0.879400f, 0.616512f,
- 0.878029f, 0.795063f, 0.869299f, 0.817249f, 0.857942f, 0.802505f,
- 0.879400f, 0.616512f, 0.859881f, 0.623942f, 0.859664f, 0.608186f,
- 0.857942f, 0.802505f, 0.858859f, 0.786774f, 0.878029f, 0.795063f,
- 0.879400f, 0.616512f, 0.870908f, 0.635245f, 0.859881f, 0.623942f,
- 0.858859f, 0.786774f, 0.870376f, 0.775972f, 0.878029f, 0.795063f,
- 0.879400f, 0.616512f, 0.887842f, 0.636527f, 0.870908f, 0.635245f,
- 0.870376f, 0.775972f, 0.887351f, 0.775442f, 0.878029f, 0.795063f,
- 0.879400f, 0.616512f, 0.899781f, 0.626257f, 0.887842f, 0.636527f,
- 0.887351f, 0.775442f, 0.898822f, 0.786233f, 0.878029f, 0.795063f,
- 0.879400f, 0.616512f, 0.902359f, 0.607909f, 0.899781f, 0.626257f,
- 0.898822f, 0.786233f, 0.900583f, 0.804677f, 0.878029f, 0.795063f,
- 0.879400f, 0.616512f, 0.889591f, 0.593275f, 0.902359f, 0.607909f,
- 0.900583f, 0.804677f, 0.887178f, 0.818729f, 0.878029f, 0.795063f,
- 0.540260f, 0.053805f, 0.536419f, 0.062072f, 0.518925f, 0.059681f, 0.518916f, 0.050294f,
- 0.518925f, 0.059681f, 0.501452f, 0.062043f, 0.497626f, 0.053770f, 0.518916f, 0.050294f,
- 0.551930f, 0.058338f, 0.542788f, 0.064089f, 0.536419f, 0.062072f, 0.540260f, 0.053805f,
- 0.501452f, 0.062043f, 0.495083f, 0.064047f, 0.485955f, 0.058273f, 0.497626f, 0.053770f,
- 0.555073f, 0.061900f, 0.546290f, 0.072669f, 0.542788f, 0.064089f, 0.551930f, 0.058338f,
- 0.495083f, 0.064047f, 0.491565f, 0.072625f, 0.482805f, 0.061829f, 0.485955f, 0.058273f,
- 0.563812f, 0.076586f, 0.548333f, 0.084893f, 0.546290f, 0.072669f, 0.555073f, 0.061900f,
- 0.491565f, 0.072625f, 0.489507f, 0.084858f, 0.474014f, 0.076511f, 0.482805f, 0.061829f,
- 0.583135f, 0.108495f, 0.555621f, 0.121749f, 0.548333f, 0.084893f, 0.563812f, 0.076586f,
- 0.489507f, 0.084858f, 0.482177f, 0.121781f, 0.454527f, 0.108481f, 0.474014f, 0.076511f,
- 0.605512f, 0.165134f, 0.647395f, 0.200502f, 0.621513f, 0.227818f, 0.553118f, 0.209599f,
- 0.416514f, 0.229490f, 0.389677f, 0.201890f, 0.432024f, 0.165644f, 0.485339f, 0.210053f,
- 0.647395f, 0.200502f, 0.676379f, 0.233241f, 0.664761f, 0.253225f, 0.621513f, 0.227818f,
- 0.372747f, 0.256357f, 0.360308f, 0.235899f, 0.389677f, 0.201890f, 0.416514f, 0.229490f,
- 0.676379f, 0.233241f, 0.715342f, 0.265392f, 0.683908f, 0.279995f, 0.664761f, 0.253225f,
- 0.353696f, 0.284606f, 0.320452f, 0.270303f, 0.360308f, 0.235899f, 0.372747f, 0.256357f,
- 0.715342f, 0.265392f, 0.707254f, 0.310054f, 0.687515f, 0.311539f, 0.683908f, 0.279995f,
- 0.351187f, 0.317440f, 0.330721f, 0.316853f, 0.320452f, 0.270303f, 0.353696f, 0.284606f,
- 0.707254f, 0.310054f, 0.697446f, 0.332673f, 0.676824f, 0.323937f, 0.687515f, 0.311539f,
- 0.362723f, 0.329722f, 0.341964f, 0.339667f, 0.330721f, 0.316853f, 0.351187f, 0.317440f,
- 0.697446f, 0.332673f, 0.662817f, 0.372521f, 0.639050f, 0.357330f, 0.676824f, 0.323937f,
- 0.402772f, 0.362131f, 0.379297f, 0.378686f, 0.341964f, 0.339667f, 0.362723f, 0.329722f,
- 0.662817f, 0.372521f, 0.626842f, 0.395792f, 0.618316f, 0.375151f, 0.639050f, 0.357330f,
- 0.424583f, 0.379267f, 0.416915f, 0.400552f, 0.379297f, 0.378686f, 0.402772f, 0.362131f,
- 0.626842f, 0.395792f, 0.604826f, 0.397804f, 0.600808f, 0.377857f, 0.618316f, 0.375151f,
- 0.442396f, 0.381222f, 0.439252f, 0.401540f, 0.416915f, 0.400552f, 0.424583f, 0.379267f,
- 0.604826f, 0.397804f, 0.553095f, 0.390512f, 0.559674f, 0.357011f, 0.600808f, 0.377857f,
- 0.482938f, 0.358497f, 0.490934f, 0.391862f, 0.439252f, 0.401540f, 0.442396f, 0.381222f,
- 0.553095f, 0.390512f, 0.521923f, 0.386009f, 0.521086f, 0.343868f, 0.559674f, 0.357011f,
- 0.521086f, 0.343868f, 0.521923f, 0.386009f, 0.490934f, 0.391862f, 0.482938f, 0.358497f,
- 0.577279f, 0.340156f, 0.599845f, 0.344815f, 0.600808f, 0.377857f, 0.559674f, 0.357011f,
- 0.442396f, 0.381222f, 0.441977f, 0.347815f, 0.464579f, 0.342230f, 0.482938f, 0.358497f,
- 0.599845f, 0.344815f, 0.615546f, 0.342005f, 0.618316f, 0.375151f, 0.600808f, 0.377857f,
- 0.424583f, 0.379267f, 0.425972f, 0.345582f, 0.441977f, 0.347815f, 0.442396f, 0.381222f,
- 0.634472f, 0.332311f, 0.639050f, 0.357330f, 0.618316f, 0.375151f, 0.615546f, 0.342005f,
- 0.424583f, 0.379267f, 0.402772f, 0.362131f, 0.406362f, 0.336480f, 0.425972f, 0.345582f,
- 0.662406f, 0.312804f, 0.676824f, 0.323937f, 0.639050f, 0.357330f, 0.634472f, 0.332311f,
- 0.402772f, 0.362131f, 0.362723f, 0.329722f, 0.377061f, 0.317685f, 0.406362f, 0.336480f,
- 0.668440f, 0.297958f, 0.687515f, 0.311539f, 0.676824f, 0.323937f, 0.662406f, 0.312804f,
- 0.362723f, 0.329722f, 0.351187f, 0.317440f, 0.370304f, 0.302644f, 0.377061f, 0.317685f,
- 0.664101f, 0.277872f, 0.683908f, 0.279995f, 0.687515f, 0.311539f, 0.668440f, 0.297958f,
- 0.351187f, 0.317440f, 0.353696f, 0.284606f, 0.374100f, 0.281778f, 0.370304f, 0.302644f,
- 0.639236f, 0.253047f, 0.664761f, 0.253225f, 0.683908f, 0.279995f, 0.664101f, 0.277872f,
- 0.353696f, 0.284606f, 0.372747f, 0.256357f, 0.398938f, 0.255633f, 0.374100f, 0.281778f,
- 0.613992f, 0.242662f, 0.621513f, 0.227818f, 0.664761f, 0.253225f, 0.639236f, 0.253047f,
- 0.372747f, 0.256357f, 0.416514f, 0.229490f, 0.424464f, 0.244473f, 0.398938f, 0.255633f,
- 0.572941f, 0.258564f, 0.553118f, 0.209599f, 0.621513f, 0.227818f, 0.613992f, 0.242662f,
- 0.416514f, 0.229490f, 0.485339f, 0.210053f, 0.466409f, 0.259709f, 0.424464f, 0.244473f,
- 0.572941f, 0.258564f, 0.563905f, 0.272007f, 0.519760f, 0.248864f, 0.553118f, 0.209599f,
- 0.519760f, 0.248864f, 0.475886f, 0.273078f, 0.466409f, 0.259709f, 0.485339f, 0.210053f,
- 0.577279f, 0.340156f, 0.559674f, 0.357011f, 0.521086f, 0.343868f, 0.558527f, 0.316594f,
- 0.521086f, 0.343868f, 0.482938f, 0.358497f, 0.464579f, 0.342230f, 0.482619f, 0.317843f,
- 0.558527f, 0.316594f, 0.521086f, 0.343868f, 0.520277f, 0.294764f, 0.556923f, 0.291214f,
- 0.520277f, 0.294764f, 0.521086f, 0.343868f, 0.482619f, 0.317843f, 0.483433f, 0.292249f,
- 0.519760f, 0.248864f, 0.563905f, 0.272007f, 0.556923f, 0.291214f, 0.520277f, 0.294764f,
- 0.483433f, 0.292249f, 0.475886f, 0.273078f, 0.519760f, 0.248864f, 0.520277f, 0.294764f,
- 0.525483f, 0.068967f, 0.518928f, 0.067899f, 0.518925f, 0.059681f, 0.536419f, 0.062072f,
- 0.518925f, 0.059681f, 0.518928f, 0.067899f, 0.512375f, 0.068956f, 0.501452f, 0.062043f,
- 0.531231f, 0.073829f, 0.525483f, 0.068967f, 0.536419f, 0.062072f, 0.542788f, 0.064089f,
- 0.501452f, 0.062043f, 0.512375f, 0.068956f, 0.506626f, 0.073811f, 0.495083f, 0.064047f,
- 0.531019f, 0.087431f, 0.531231f, 0.073829f, 0.542788f, 0.064089f, 0.546290f, 0.072669f,
- 0.495083f, 0.064047f, 0.506626f, 0.073811f, 0.506827f, 0.087416f, 0.491565f, 0.072625f,
- 0.555621f, 0.121749f, 0.532042f, 0.127713f, 0.532669f, 0.090920f, 0.548333f, 0.084893f,
- 0.505177f, 0.090908f, 0.505828f, 0.127728f, 0.482177f, 0.121781f, 0.489507f, 0.084858f,
- 0.531019f, 0.087431f, 0.546290f, 0.072669f, 0.548333f, 0.084893f, 0.532669f, 0.090920f,
- 0.489507f, 0.084858f, 0.491565f, 0.072625f, 0.506827f, 0.087416f, 0.505177f, 0.090908f,
- 0.538112f, 0.158382f, 0.518981f, 0.151749f, 0.518941f, 0.128358f, 0.532042f, 0.127713f,
- 0.518941f, 0.128358f, 0.518981f, 0.151749f, 0.499851f, 0.158434f, 0.505828f, 0.127728f,
- 0.532669f, 0.090920f, 0.532042f, 0.127713f, 0.518941f, 0.128358f, 0.518925f, 0.093952f,
- 0.518941f, 0.128358f, 0.505828f, 0.127728f, 0.505177f, 0.090908f, 0.518925f, 0.093952f,
- 0.518927f, 0.085180f, 0.531019f, 0.087431f, 0.532669f, 0.090920f, 0.518925f, 0.093952f,
- 0.505177f, 0.090908f, 0.506827f, 0.087416f, 0.518927f, 0.085180f, 0.518925f, 0.093952f,
- 0.548362f, 0.173560f, 0.537959f, 0.175966f, 0.535214f, 0.166808f, 0.538112f, 0.158382f,
- 0.502799f, 0.166857f, 0.500100f, 0.176033f, 0.489683f, 0.173693f, 0.499851f, 0.158434f,
- 0.544281f, 0.193366f, 0.537248f, 0.187577f, 0.537959f, 0.175966f, 0.548362f, 0.173560f,
- 0.500100f, 0.176033f, 0.500890f, 0.187571f, 0.493996f, 0.193428f, 0.489683f, 0.173693f,
- 0.519841f, 0.200843f, 0.528757f, 0.191785f, 0.537248f, 0.187577f, 0.544281f, 0.193366f,
- 0.500890f, 0.187571f, 0.509219f, 0.191626f, 0.519841f, 0.200843f, 0.493996f, 0.193428f,
- 0.517577f, 0.190607f, 0.519132f, 0.185382f, 0.528757f, 0.191785f, 0.519841f, 0.200843f,
- 0.509219f, 0.191626f, 0.519132f, 0.185382f, 0.517577f, 0.190607f, 0.519841f, 0.200843f,
- 0.518981f, 0.151749f, 0.538112f, 0.158382f, 0.535214f, 0.166808f, 0.518998f, 0.159028f,
- 0.502799f, 0.166857f, 0.499851f, 0.158434f, 0.518981f, 0.151749f, 0.518998f, 0.159028f,
- 0.518998f, 0.159028f, 0.535214f, 0.166808f, 0.531131f, 0.171631f, 0.519016f, 0.165599f,
- 0.506910f, 0.171667f, 0.502799f, 0.166857f, 0.518998f, 0.159028f, 0.519016f, 0.165599f,
- 0.519132f, 0.185382f, 0.519099f, 0.179457f, 0.528222f, 0.186316f, 0.528757f, 0.191785f,
- 0.509787f, 0.186260f, 0.519099f, 0.179457f, 0.519132f, 0.185382f, 0.509219f, 0.191626f,
- 0.528757f, 0.191785f, 0.528222f, 0.186316f, 0.533528f, 0.184215f, 0.537248f, 0.187577f,
- 0.504547f, 0.184206f, 0.509787f, 0.186260f, 0.509219f, 0.191626f, 0.500890f, 0.187571f,
- 0.537248f, 0.187577f, 0.533528f, 0.184215f, 0.533449f, 0.176739f, 0.537959f, 0.175966f,
- 0.504604f, 0.176791f, 0.504547f, 0.184206f, 0.500890f, 0.187571f, 0.500100f, 0.176033f,
- 0.537959f, 0.175966f, 0.533449f, 0.176739f, 0.531131f, 0.171631f, 0.535214f, 0.166808f,
- 0.506910f, 0.171667f, 0.504604f, 0.176791f, 0.500100f, 0.176033f, 0.502799f, 0.166857f,
- 0.519099f, 0.179457f, 0.533449f, 0.176739f, 0.533528f, 0.184215f, 0.528222f, 0.186316f,
- 0.504547f, 0.184206f, 0.504604f, 0.176791f, 0.519099f, 0.179457f, 0.509787f, 0.186260f,
- 0.519099f, 0.179457f, 0.519016f, 0.165599f, 0.531131f, 0.171631f, 0.533449f, 0.176739f,
- 0.506910f, 0.171667f, 0.519016f, 0.165599f, 0.519099f, 0.179457f, 0.504604f, 0.176791f,
- 0.519841f, 0.200843f, 0.544281f, 0.193366f, 0.553118f, 0.209599f, 0.519760f, 0.248864f,
- 0.485339f, 0.210053f, 0.493996f, 0.193428f, 0.519841f, 0.200843f, 0.519760f, 0.248864f,
- 0.544281f, 0.193366f, 0.548362f, 0.173560f, 0.561572f, 0.167779f, 0.553118f, 0.209599f,
- 0.476363f, 0.167996f, 0.489683f, 0.173693f, 0.493996f, 0.193428f, 0.485339f, 0.210053f,
- 0.548362f, 0.173560f, 0.538112f, 0.158382f, 0.559475f, 0.149319f, 0.561572f, 0.167779f,
- 0.478371f, 0.149447f, 0.499851f, 0.158434f, 0.489683f, 0.173693f, 0.476363f, 0.167996f,
- 0.538112f, 0.158382f, 0.532042f, 0.127713f, 0.555621f, 0.121749f, 0.559475f, 0.149319f,
- 0.482177f, 0.121781f, 0.505828f, 0.127728f, 0.499851f, 0.158434f, 0.478371f, 0.149447f,
- 0.583135f, 0.108495f, 0.596138f, 0.133426f, 0.559475f, 0.149319f, 0.555621f, 0.121749f,
- 0.478371f, 0.149447f, 0.441395f, 0.133592f, 0.454527f, 0.108481f, 0.482177f, 0.121781f,
- 0.596138f, 0.133426f, 0.601169f, 0.147885f, 0.561572f, 0.167779f, 0.559475f, 0.149319f,
- 0.476363f, 0.167996f, 0.436337f, 0.148194f, 0.441395f, 0.133592f, 0.478371f, 0.149447f,
- 0.605512f, 0.165134f, 0.553118f, 0.209599f, 0.561572f, 0.167779f, 0.601169f, 0.147885f,
- 0.476363f, 0.167996f, 0.485339f, 0.210053f, 0.432024f, 0.165644f, 0.436337f, 0.148194f,
- 0.531019f, 0.087431f, 0.518927f, 0.085180f, 0.518925f, 0.083865f, 0.528933f, 0.084957f,
- 0.518925f, 0.083865f, 0.518927f, 0.085180f, 0.506827f, 0.087416f, 0.508915f, 0.084945f,
- 0.531231f, 0.073829f, 0.531019f, 0.087431f, 0.528933f, 0.084957f, 0.529036f, 0.075429f,
- 0.508915f, 0.084945f, 0.506827f, 0.087416f, 0.506626f, 0.073811f, 0.508820f, 0.075415f,
- 0.525483f, 0.068967f, 0.531231f, 0.073829f, 0.529036f, 0.075429f, 0.523751f, 0.070508f,
- 0.508820f, 0.075415f, 0.506626f, 0.073811f, 0.512375f, 0.068956f, 0.514106f, 0.070501f,
- 0.518928f, 0.067899f, 0.525483f, 0.068967f, 0.523751f, 0.070508f, 0.518929f, 0.069468f,
- 0.514106f, 0.070501f, 0.512375f, 0.068956f, 0.518928f, 0.067899f, 0.518929f, 0.069468f,
- 0.518929f, 0.069468f, 0.523751f, 0.070508f, 0.521560f, 0.074970f, 0.518928f, 0.074259f,
- 0.516297f, 0.074966f, 0.514106f, 0.070501f, 0.518929f, 0.069468f, 0.518928f, 0.074259f,
- 0.523751f, 0.070508f, 0.529036f, 0.075429f, 0.524236f, 0.076691f, 0.521560f, 0.074970f,
- 0.513619f, 0.076684f, 0.508820f, 0.075415f, 0.514106f, 0.070501f, 0.516297f, 0.074966f,
- 0.529036f, 0.075429f, 0.528933f, 0.084957f, 0.524601f, 0.079886f, 0.524236f, 0.076691f,
- 0.513252f, 0.079879f, 0.508915f, 0.084945f, 0.508820f, 0.075415f, 0.513619f, 0.076684f,
- 0.528933f, 0.084957f, 0.518925f, 0.083865f, 0.518926f, 0.079331f, 0.524601f, 0.079886f,
- 0.518926f, 0.079331f, 0.518925f, 0.083865f, 0.508915f, 0.084945f, 0.513252f, 0.079879f,
- 0.518926f, 0.079331f, 0.518928f, 0.074259f, 0.521560f, 0.074970f, 0.524601f, 0.079886f,
- 0.516297f, 0.074966f, 0.518928f, 0.074259f, 0.518926f, 0.079331f, 0.513252f, 0.079879f,
- 0.524601f, 0.079886f, 0.521560f, 0.074970f, 0.524236f, 0.076691f,
- 0.513619f, 0.076684f, 0.516297f, 0.074966f, 0.513252f, 0.079879f,
- 0.556923f, 0.291214f, 0.563905f, 0.272007f, 0.571787f, 0.277295f, 0.568351f, 0.292904f,
- 0.468070f, 0.278617f, 0.475886f, 0.273078f, 0.483433f, 0.292249f, 0.471978f, 0.294282f,
- 0.558527f, 0.316594f, 0.556923f, 0.291214f, 0.568351f, 0.292904f, 0.573085f, 0.311386f,
- 0.471978f, 0.294282f, 0.483433f, 0.292249f, 0.482619f, 0.317843f, 0.467790f, 0.313081f,
- 0.577279f, 0.340156f, 0.558527f, 0.316594f, 0.573085f, 0.311386f, 0.584855f, 0.327708f,
- 0.467790f, 0.313081f, 0.482619f, 0.317843f, 0.464579f, 0.342230f, 0.456477f, 0.329961f,
- 0.563905f, 0.272007f, 0.572941f, 0.258564f, 0.580734f, 0.266620f, 0.571787f, 0.277295f,
- 0.458737f, 0.268049f, 0.466409f, 0.259709f, 0.475886f, 0.273078f, 0.468070f, 0.278617f,
- 0.572941f, 0.258564f, 0.613992f, 0.242662f, 0.611720f, 0.255725f, 0.580734f, 0.266620f,
- 0.427062f, 0.257728f, 0.424464f, 0.244473f, 0.466409f, 0.259709f, 0.458737f, 0.268049f,
- 0.613992f, 0.242662f, 0.639236f, 0.253047f, 0.632494f, 0.262853f, 0.611720f, 0.255725f,
- 0.406068f, 0.265508f, 0.398938f, 0.255633f, 0.424464f, 0.244473f, 0.427062f, 0.257728f,
- 0.639236f, 0.253047f, 0.664101f, 0.277872f, 0.653658f, 0.279971f, 0.632494f, 0.262853f,
- 0.384904f, 0.283634f, 0.374100f, 0.281778f, 0.398938f, 0.255633f, 0.406068f, 0.265508f,
- 0.664101f, 0.277872f, 0.668440f, 0.297958f, 0.656064f, 0.297636f, 0.653658f, 0.279971f,
- 0.383015f, 0.301864f, 0.370304f, 0.302644f, 0.374100f, 0.281778f, 0.384904f, 0.283634f,
- 0.668440f, 0.297958f, 0.662406f, 0.312804f, 0.652752f, 0.310186f, 0.656064f, 0.297636f,
- 0.386858f, 0.314615f, 0.377061f, 0.317685f, 0.370304f, 0.302644f, 0.383015f, 0.301864f,
- 0.662406f, 0.312804f, 0.634472f, 0.332311f, 0.629040f, 0.323864f, 0.652752f, 0.310186f,
- 0.411556f, 0.327673f, 0.406362f, 0.336480f, 0.377061f, 0.317685f, 0.386858f, 0.314615f,
- 0.634472f, 0.332311f, 0.615546f, 0.342005f, 0.614408f, 0.331972f, 0.629040f, 0.323864f,
- 0.426727f, 0.335361f, 0.425972f, 0.345582f, 0.406362f, 0.336480f, 0.411556f, 0.327673f,
- 0.615546f, 0.342005f, 0.599845f, 0.344815f, 0.601033f, 0.333624f, 0.614408f, 0.331972f,
- 0.440344f, 0.336537f, 0.441977f, 0.347815f, 0.425972f, 0.345582f, 0.426727f, 0.335361f,
- 0.599845f, 0.344815f, 0.577279f, 0.340156f, 0.584855f, 0.327708f, 0.601033f, 0.333624f,
- 0.456477f, 0.329961f, 0.464579f, 0.342230f, 0.441977f, 0.347815f, 0.440344f, 0.336537f,
- 0.601033f, 0.333624f, 0.584855f, 0.327708f, 0.590644f, 0.321516f, 0.601799f, 0.328453f,
- 0.450408f, 0.323919f, 0.456477f, 0.329961f, 0.440344f, 0.336537f, 0.439372f, 0.331331f,
- 0.614408f, 0.331972f, 0.601033f, 0.333624f, 0.601799f, 0.328453f, 0.613335f, 0.327083f,
- 0.439372f, 0.331331f, 0.440344f, 0.336537f, 0.426727f, 0.335361f, 0.427623f, 0.330358f,
- 0.629040f, 0.323864f, 0.614408f, 0.331972f, 0.613335f, 0.327083f, 0.626851f, 0.320513f,
- 0.427623f, 0.330358f, 0.426727f, 0.335361f, 0.411556f, 0.327673f, 0.413648f, 0.324175f,
- 0.652752f, 0.310186f, 0.629040f, 0.323864f, 0.626851f, 0.320513f, 0.646248f, 0.306421f,
- 0.413648f, 0.324175f, 0.411556f, 0.327673f, 0.386858f, 0.314615f, 0.393381f, 0.310510f,
- 0.656064f, 0.297636f, 0.652752f, 0.310186f, 0.646248f, 0.306421f, 0.649541f, 0.296225f,
- 0.393381f, 0.310510f, 0.386858f, 0.314615f, 0.383015f, 0.301864f, 0.389662f, 0.300183f,
- 0.653658f, 0.279971f, 0.656064f, 0.297636f, 0.649541f, 0.296225f, 0.647785f, 0.283486f,
- 0.389662f, 0.300183f, 0.383015f, 0.301864f, 0.384904f, 0.283634f, 0.391040f, 0.287071f,
- 0.632494f, 0.262853f, 0.653658f, 0.279971f, 0.647785f, 0.283486f, 0.629829f, 0.267263f,
- 0.391040f, 0.287071f, 0.384904f, 0.283634f, 0.406068f, 0.265508f, 0.408893f, 0.269959f,
- 0.611720f, 0.255725f, 0.632494f, 0.262853f, 0.629829f, 0.267263f, 0.612641f, 0.261560f,
- 0.408893f, 0.269959f, 0.406068f, 0.265508f, 0.427062f, 0.257728f, 0.426254f, 0.263693f,
- 0.580734f, 0.266620f, 0.611720f, 0.255725f, 0.612641f, 0.261560f, 0.585166f, 0.270991f,
- 0.426254f, 0.263693f, 0.427062f, 0.257728f, 0.458737f, 0.268049f, 0.454369f, 0.272583f,
- 0.571787f, 0.277295f, 0.580734f, 0.266620f, 0.585166f, 0.270991f, 0.578124f, 0.281900f,
- 0.454369f, 0.272583f, 0.458737f, 0.268049f, 0.468070f, 0.278617f, 0.461798f, 0.283441f,
- 0.584855f, 0.327708f, 0.573085f, 0.311386f, 0.579548f, 0.309340f, 0.590644f, 0.321516f,
- 0.461204f, 0.311233f, 0.467790f, 0.313081f, 0.456477f, 0.329961f, 0.450408f, 0.323919f,
- 0.573085f, 0.311386f, 0.568351f, 0.292904f, 0.577524f, 0.293776f, 0.579548f, 0.309340f,
- 0.462754f, 0.295432f, 0.471978f, 0.294282f, 0.467790f, 0.313081f, 0.461204f, 0.311233f,
- 0.568351f, 0.292904f, 0.571787f, 0.277295f, 0.578124f, 0.281900f, 0.577524f, 0.293776f,
- 0.461798f, 0.283441f, 0.468070f, 0.278617f, 0.471978f, 0.294282f, 0.462754f, 0.295432f,
- 0.521923f, 0.386009f, 0.553095f, 0.390512f, 0.553209f, 0.433063f, 0.523031f, 0.433628f,
- 0.492809f, 0.434538f, 0.490934f, 0.391862f, 0.521923f, 0.386009f, 0.523031f, 0.433628f,
- 0.553095f, 0.390512f, 0.604826f, 0.397804f, 0.609819f, 0.431516f, 0.553209f, 0.433063f,
- 0.435860f, 0.435740f, 0.439252f, 0.401540f, 0.490934f, 0.391862f, 0.492809f, 0.434538f,
- 0.604826f, 0.397804f, 0.626842f, 0.395792f, 0.648174f, 0.419316f, 0.609819f, 0.431516f,
- 0.396518f, 0.425416f, 0.416915f, 0.400552f, 0.439252f, 0.401540f, 0.435860f, 0.435740f,
- 0.626842f, 0.395792f, 0.662817f, 0.372521f, 0.692106f, 0.388274f, 0.648174f, 0.419316f,
- 0.350292f, 0.396229f, 0.379297f, 0.378686f, 0.416915f, 0.400552f, 0.396518f, 0.425416f,
- 0.662817f, 0.372521f, 0.697446f, 0.332673f, 0.726332f, 0.341754f, 0.692106f, 0.388274f,
- 0.312756f, 0.350588f, 0.341964f, 0.339667f, 0.379297f, 0.378686f, 0.350292f, 0.396229f,
- 0.697446f, 0.332673f, 0.707254f, 0.310054f, 0.735879f, 0.312112f, 0.726332f, 0.341754f,
- 0.301067f, 0.320593f, 0.330721f, 0.316853f, 0.341964f, 0.339667f, 0.312756f, 0.350588f,
- 0.707254f, 0.310054f, 0.715342f, 0.265392f, 0.729900f, 0.256393f, 0.735879f, 0.312112f,
- 0.304876f, 0.261087f, 0.320452f, 0.270303f, 0.330721f, 0.316853f, 0.301067f, 0.320593f,
- 0.715342f, 0.265392f, 0.676379f, 0.233241f, 0.698172f, 0.216906f, 0.729900f, 0.256393f,
- 0.337414f, 0.219179f, 0.360308f, 0.235899f, 0.320452f, 0.270303f, 0.304876f, 0.261087f,
- 0.676379f, 0.233241f, 0.647395f, 0.200502f, 0.663103f, 0.190671f, 0.698172f, 0.216906f,
- 0.373474f, 0.191872f, 0.389677f, 0.201890f, 0.360308f, 0.235899f, 0.337414f, 0.219179f,
- 0.626908f, 0.015608f, 0.649444f, 0.022378f, 0.660451f, 0.076084f, 0.621440f, 0.048089f,
- 0.376796f, 0.075296f, 0.388827f, 0.021586f, 0.411318f, 0.015131f, 0.416419f, 0.047631f,
- 0.567460f, 0.000144f, 0.626908f, 0.015608f, 0.621440f, 0.048089f, 0.577206f, 0.032801f,
- 0.416419f, 0.047631f, 0.411318f, 0.015131f, 0.470636f, 0.000144f, 0.460782f, 0.032656f,
- 0.518922f, 0.024886f, 0.567460f, 0.000144f, 0.577206f, 0.032801f, 0.547413f, 0.041724f,
- 0.460782f, 0.032656f, 0.470636f, 0.000144f, 0.518922f, 0.024886f, 0.490511f, 0.041669f,
- 0.540260f, 0.053805f, 0.518916f, 0.050294f, 0.518922f, 0.024886f, 0.547413f, 0.041724f,
- 0.518922f, 0.024886f, 0.518916f, 0.050294f, 0.497626f, 0.053770f, 0.490511f, 0.041669f,
- 0.551930f, 0.058338f, 0.540260f, 0.053805f, 0.547413f, 0.041724f, 0.558059f, 0.053871f,
- 0.490511f, 0.041669f, 0.497626f, 0.053770f, 0.485955f, 0.058273f, 0.479842f, 0.053785f,
- 0.555073f, 0.061900f, 0.551930f, 0.058338f, 0.558059f, 0.053871f, 0.576951f, 0.057998f,
- 0.479842f, 0.053785f, 0.485955f, 0.058273f, 0.482805f, 0.061829f, 0.460920f, 0.057845f,
- 0.563812f, 0.076586f, 0.555073f, 0.061900f, 0.576951f, 0.057998f, 0.611687f, 0.078268f,
- 0.460920f, 0.057845f, 0.482805f, 0.061829f, 0.474014f, 0.076511f, 0.425932f, 0.077985f,
- 0.576951f, 0.057998f, 0.577206f, 0.032801f, 0.621440f, 0.048089f, 0.611687f, 0.078268f,
- 0.416419f, 0.047631f, 0.460782f, 0.032656f, 0.460920f, 0.057845f, 0.425932f, 0.077985f,
- 0.576951f, 0.057998f, 0.558059f, 0.053871f, 0.547413f, 0.041724f, 0.577206f, 0.032801f,
- 0.490511f, 0.041669f, 0.479842f, 0.053785f, 0.460920f, 0.057845f, 0.460782f, 0.032656f,
- 0.626663f, 0.111357f, 0.611687f, 0.078268f, 0.621440f, 0.048089f, 0.660451f, 0.076084f,
- 0.416419f, 0.047631f, 0.425932f, 0.077985f, 0.410618f, 0.111244f, 0.376796f, 0.075296f,
- 0.583135f, 0.108495f, 0.563812f, 0.076586f, 0.611687f, 0.078268f, 0.626663f, 0.111357f,
- 0.425932f, 0.077985f, 0.474014f, 0.076511f, 0.454527f, 0.108481f, 0.410618f, 0.111244f,
- 0.596138f, 0.133426f, 0.629482f, 0.130456f, 0.623495f, 0.146796f, 0.601169f, 0.147885f,
- 0.413741f, 0.147158f, 0.407648f, 0.130594f, 0.441395f, 0.133592f, 0.436337f, 0.148194f,
- 0.583135f, 0.108495f, 0.626663f, 0.111357f, 0.629482f, 0.130456f, 0.596138f, 0.133426f,
- 0.407648f, 0.130594f, 0.410618f, 0.111244f, 0.454527f, 0.108481f, 0.441395f, 0.133592f,
- 0.605512f, 0.165134f, 0.601169f, 0.147885f, 0.623495f, 0.146796f, 0.619303f, 0.159841f,
- 0.413741f, 0.147158f, 0.436337f, 0.148194f, 0.432024f, 0.165644f, 0.418035f, 0.160361f,
- 0.605512f, 0.165134f, 0.619303f, 0.159841f, 0.663103f, 0.190671f, 0.647395f, 0.200502f,
- 0.373474f, 0.191872f, 0.418035f, 0.160361f, 0.432024f, 0.165644f, 0.389677f, 0.201890f,
- 0.945900f, 0.079569f, 0.886245f, 0.121777f, 0.849114f, 0.099732f, 0.891780f, 0.036916f,
- 0.183115f, 0.092127f, 0.141314f, 0.112482f, 0.078961f, 0.060719f, 0.142277f, 0.021467f,
- 0.891780f, 0.036916f, 0.849114f, 0.099732f, 0.788458f, 0.080826f, 0.805584f, 0.010786f,
- 0.246353f, 0.076510f, 0.183115f, 0.092127f, 0.142277f, 0.021467f, 0.232648f, 0.003484f,
- 0.805584f, 0.010786f, 0.788458f, 0.080826f, 0.687018f, 0.077204f, 0.672384f, 0.022201f,
- 0.349875f, 0.075955f, 0.246353f, 0.076510f, 0.232648f, 0.003484f, 0.365979f, 0.020991f,
- 0.672384f, 0.022201f, 0.687018f, 0.077204f, 0.660451f, 0.076084f, 0.649444f, 0.022378f,
- 0.376796f, 0.075296f, 0.349875f, 0.075955f, 0.365979f, 0.020991f, 0.388827f, 0.021586f,
- 0.626663f, 0.111357f, 0.660451f, 0.076084f, 0.687018f, 0.077204f, 0.629482f, 0.130456f,
- 0.349875f, 0.075955f, 0.376796f, 0.075296f, 0.410618f, 0.111244f, 0.407648f, 0.130594f,
- 0.729900f, 0.256393f, 0.698172f, 0.216906f, 0.760215f, 0.193244f, 0.789046f, 0.233323f,
- 0.271553f, 0.193871f, 0.337414f, 0.219179f, 0.304876f, 0.261087f, 0.241255f, 0.236977f,
- 0.994525f, 0.167705f, 0.909112f, 0.183261f, 0.886245f, 0.121777f, 0.945900f, 0.079569f,
- 0.141314f, 0.112482f, 0.107928f, 0.179083f, 0.011829f, 0.155367f, 0.078961f, 0.060719f,
- 0.911671f, 0.402429f, 0.862868f, 0.338556f, 0.894128f, 0.301884f, 0.962901f, 0.344752f,
- 0.123776f, 0.315519f, 0.160557f, 0.356821f, 0.106400f, 0.432652f, 0.043968f, 0.367038f,
- 0.962901f, 0.344752f, 0.894128f, 0.301884f, 0.915360f, 0.259804f, 0.999856f, 0.254640f,
- 0.098965f, 0.266968f, 0.123776f, 0.315519f, 0.043968f, 0.367038f, 0.000144f, 0.259113f,
- 0.999856f, 0.254640f, 0.915360f, 0.259804f, 0.909112f, 0.183261f, 0.994525f, 0.167705f,
- 0.107928f, 0.179083f, 0.098965f, 0.266968f, 0.000144f, 0.259113f, 0.011829f, 0.155367f,
- 0.749542f, 0.334683f, 0.735879f, 0.312112f, 0.766337f, 0.300809f, 0.789162f, 0.313727f,
- 0.267408f, 0.310142f, 0.301067f, 0.320593f, 0.288183f, 0.346496f, 0.242992f, 0.325552f,
- 0.789162f, 0.313727f, 0.766337f, 0.300809f, 0.815314f, 0.276388f, 0.846174f, 0.293397f,
- 0.213065f, 0.285164f, 0.267408f, 0.310142f, 0.242992f, 0.325552f, 0.178537f, 0.304983f,
- 0.846174f, 0.293397f, 0.815314f, 0.276388f, 0.845007f, 0.256352f, 0.873517f, 0.265922f,
- 0.179662f, 0.263312f, 0.213065f, 0.285164f, 0.178537f, 0.304983f, 0.147089f, 0.274284f,
- 0.873517f, 0.265922f, 0.845007f, 0.256352f, 0.859075f, 0.228168f, 0.886999f, 0.233769f,
- 0.162803f, 0.231720f, 0.179662f, 0.263312f, 0.147089f, 0.274284f, 0.131514f, 0.237587f,
- 0.842355f, 0.195160f, 0.875030f, 0.184705f, 0.886999f, 0.233769f, 0.859075f, 0.228168f,
- 0.131514f, 0.237587f, 0.145224f, 0.182749f, 0.176788f, 0.196179f, 0.162803f, 0.231720f,
- 0.909112f, 0.183261f, 0.915360f, 0.259804f, 0.886999f, 0.233769f, 0.875030f, 0.184705f,
- 0.131514f, 0.237587f, 0.098965f, 0.266968f, 0.107928f, 0.179083f, 0.145224f, 0.182749f,
- 0.915360f, 0.259804f, 0.894128f, 0.301884f, 0.873517f, 0.265922f, 0.886999f, 0.233769f,
- 0.147089f, 0.274284f, 0.123776f, 0.315519f, 0.098965f, 0.266968f, 0.131514f, 0.237587f,
- 0.894128f, 0.301884f, 0.862868f, 0.338556f, 0.846174f, 0.293397f, 0.873517f, 0.265922f,
- 0.178537f, 0.304983f, 0.160557f, 0.356821f, 0.123776f, 0.315519f, 0.147089f, 0.274284f,
- 0.862868f, 0.338556f, 0.794286f, 0.364062f, 0.789162f, 0.313727f, 0.846174f, 0.293397f,
- 0.242992f, 0.325552f, 0.239776f, 0.382592f, 0.160557f, 0.356821f, 0.178537f, 0.304983f,
- 0.770185f, 0.379538f, 0.749542f, 0.334683f, 0.789162f, 0.313727f, 0.794286f, 0.364062f,
- 0.242992f, 0.325552f, 0.288183f, 0.346496f, 0.268122f, 0.398737f, 0.239776f, 0.382592f,
- 0.845499f, 0.449967f, 0.794286f, 0.364062f, 0.862868f, 0.338556f, 0.911671f, 0.402429f,
- 0.160557f, 0.356821f, 0.239776f, 0.382592f, 0.185281f, 0.484099f, 0.106400f, 0.432652f,
- 0.815858f, 0.445381f, 0.770572f, 0.444261f, 0.755700f, 0.418603f, 0.770185f, 0.379538f,
- 0.287033f, 0.442912f, 0.271364f, 0.473316f, 0.219260f, 0.477186f, 0.268122f, 0.398737f,
- 0.815858f, 0.445381f, 0.770185f, 0.379538f, 0.794286f, 0.364062f, 0.845499f, 0.449967f,
- 0.239776f, 0.382592f, 0.268122f, 0.398737f, 0.219260f, 0.477186f, 0.185281f, 0.484099f,
- 0.819845f, 0.468071f, 0.815858f, 0.445381f, 0.845499f, 0.449967f,
- 0.185281f, 0.484099f, 0.219260f, 0.477186f, 0.215894f, 0.503605f,
- 0.735879f, 0.312112f, 0.729900f, 0.256393f, 0.789046f, 0.233323f, 0.766337f, 0.300809f,
- 0.241255f, 0.236977f, 0.304876f, 0.261087f, 0.301067f, 0.320593f, 0.267408f, 0.310142f,
- 0.789046f, 0.233323f, 0.809631f, 0.233887f, 0.815314f, 0.276388f, 0.766337f, 0.300809f,
- 0.213065f, 0.285164f, 0.219168f, 0.237388f, 0.241255f, 0.236977f, 0.267408f, 0.310142f,
- 0.809631f, 0.233887f, 0.829287f, 0.219562f, 0.845007f, 0.256352f, 0.815314f, 0.276388f,
- 0.179662f, 0.263312f, 0.199067f, 0.222464f, 0.219168f, 0.237388f, 0.213065f, 0.285164f,
- 0.842355f, 0.195160f, 0.859075f, 0.228168f, 0.845007f, 0.256352f, 0.829287f, 0.219562f,
- 0.179662f, 0.263312f, 0.162803f, 0.231720f, 0.176788f, 0.196179f, 0.199067f, 0.222464f,
- 0.687018f, 0.077204f, 0.788458f, 0.080826f, 0.786480f, 0.117591f, 0.715482f, 0.139727f,
- 0.246666f, 0.114850f, 0.246353f, 0.076510f, 0.349875f, 0.075955f, 0.319538f, 0.139409f,
- 0.760215f, 0.193244f, 0.715482f, 0.139727f, 0.786480f, 0.117591f, 0.785486f, 0.152330f,
- 0.246666f, 0.114850f, 0.319538f, 0.139409f, 0.271553f, 0.193871f, 0.245969f, 0.151002f,
- 0.698172f, 0.216906f, 0.663103f, 0.190671f, 0.715482f, 0.139727f, 0.760215f, 0.193244f,
- 0.319538f, 0.139409f, 0.373474f, 0.191872f, 0.337414f, 0.219179f, 0.271553f, 0.193871f,
- 0.663103f, 0.190671f, 0.623495f, 0.146796f, 0.629482f, 0.130456f, 0.715482f, 0.139727f,
- 0.407648f, 0.130594f, 0.413741f, 0.147158f, 0.373474f, 0.191872f, 0.319538f, 0.139409f,
- 0.629482f, 0.130456f, 0.687018f, 0.077204f, 0.715482f, 0.139727f,
- 0.319538f, 0.139409f, 0.349875f, 0.075955f, 0.407648f, 0.130594f,
- 0.663103f, 0.190671f, 0.619303f, 0.159841f, 0.623495f, 0.146796f,
- 0.413741f, 0.147158f, 0.418035f, 0.160361f, 0.373474f, 0.191872f,
- 0.842355f, 0.195160f, 0.837382f, 0.156361f, 0.858171f, 0.137775f, 0.875030f, 0.184705f,
- 0.171653f, 0.132294f, 0.196622f, 0.155241f, 0.176788f, 0.196179f, 0.145224f, 0.182749f,
- 0.909112f, 0.183261f, 0.875030f, 0.184705f, 0.858171f, 0.137775f, 0.886245f, 0.121777f,
- 0.171653f, 0.132294f, 0.145224f, 0.182749f, 0.107928f, 0.179083f, 0.141314f, 0.112482f,
- 0.785486f, 0.152330f, 0.786480f, 0.117591f, 0.858171f, 0.137775f, 0.837382f, 0.156361f,
- 0.171653f, 0.132294f, 0.246666f, 0.114850f, 0.245969f, 0.151002f, 0.196622f, 0.155241f,
- 0.788458f, 0.080826f, 0.849114f, 0.099732f, 0.858171f, 0.137775f, 0.786480f, 0.117591f,
- 0.171653f, 0.132294f, 0.183115f, 0.092127f, 0.246353f, 0.076510f, 0.246666f, 0.114850f,
- 0.886245f, 0.121777f, 0.858171f, 0.137775f, 0.849114f, 0.099732f,
- 0.183115f, 0.092127f, 0.171653f, 0.132294f, 0.141314f, 0.112482f,
- 0.506166f, 0.904851f, 0.432388f, 0.894943f, 0.438797f, 0.870229f, 0.491058f, 0.881714f,
- 0.315867f, 0.868209f, 0.321637f, 0.893225f, 0.247207f, 0.901159f, 0.263032f, 0.878321f,
- 0.506166f, 0.904851f, 0.491058f, 0.881714f, 0.572792f, 0.860484f, 0.604825f, 0.879946f,
- 0.181486f, 0.854693f, 0.263032f, 0.878321f, 0.247207f, 0.901159f, 0.148729f, 0.873349f,
- 0.604825f, 0.879946f, 0.572792f, 0.860484f, 0.586396f, 0.793977f, 0.619962f, 0.791615f,
- 0.169745f, 0.787474f, 0.181486f, 0.854693f, 0.148729f, 0.873349f, 0.136063f, 0.784093f,
- 0.619962f, 0.791615f, 0.586396f, 0.793977f, 0.549027f, 0.746412f, 0.563786f, 0.739211f,
- 0.208656f, 0.740879f, 0.169745f, 0.787474f, 0.136063f, 0.784093f, 0.194086f, 0.733241f,
- 0.563786f, 0.739211f, 0.549027f, 0.746412f, 0.500314f, 0.711729f, 0.508270f, 0.697693f,
- 0.258399f, 0.707497f, 0.208656f, 0.740879f, 0.194086f, 0.733241f, 0.250811f, 0.693249f,
- 0.508270f, 0.697693f, 0.500314f, 0.711729f, 0.438641f, 0.680683f, 0.434803f, 0.658882f,
- 0.320962f, 0.677959f, 0.258399f, 0.707497f, 0.250811f, 0.693249f, 0.325318f, 0.656224f,
- 0.500314f, 0.711729f, 0.505666f, 0.730944f, 0.452955f, 0.700023f, 0.438641f, 0.680683f,
- 0.306136f, 0.696976f, 0.252524f, 0.726592f, 0.258399f, 0.707497f, 0.320962f, 0.677959f,
- 0.549027f, 0.746412f, 0.542850f, 0.755753f, 0.505666f, 0.730944f, 0.500314f, 0.711729f,
- 0.252524f, 0.726592f, 0.214575f, 0.750414f, 0.208656f, 0.740879f, 0.258399f, 0.707497f,
- 0.586396f, 0.793977f, 0.568148f, 0.787367f, 0.542850f, 0.755753f, 0.549027f, 0.746412f,
- 0.214575f, 0.750414f, 0.188269f, 0.781375f, 0.169745f, 0.787474f, 0.208656f, 0.740879f,
- 0.572792f, 0.860484f, 0.555495f, 0.826352f, 0.568148f, 0.787367f, 0.586396f, 0.793977f,
- 0.188269f, 0.781375f, 0.199850f, 0.820889f, 0.181486f, 0.854693f, 0.169745f, 0.787474f,
- 0.491058f, 0.881714f, 0.501231f, 0.844356f, 0.555495f, 0.826352f, 0.572792f, 0.860484f,
- 0.199850f, 0.820889f, 0.253846f, 0.840502f, 0.263032f, 0.878321f, 0.181486f, 0.854693f,
- 0.491058f, 0.881714f, 0.438797f, 0.870229f, 0.457832f, 0.840040f, 0.501231f, 0.844356f,
- 0.297562f, 0.837358f, 0.315867f, 0.868209f, 0.263032f, 0.878321f, 0.253846f, 0.840502f,
- 0.760215f, 0.193244f, 0.785486f, 0.152330f, 0.796021f, 0.176969f, 0.783193f, 0.187449f,
- 0.233625f, 0.175620f, 0.245969f, 0.151002f, 0.271553f, 0.193871f, 0.246955f, 0.187075f,
- 0.391039f, 0.611891f, 0.434803f, 0.658882f, 0.438641f, 0.680683f, 0.394766f, 0.686125f,
- 0.320962f, 0.677959f, 0.325318f, 0.656224f, 0.369913f, 0.610196f, 0.364838f, 0.684445f,
- 0.789046f, 0.233323f, 0.760215f, 0.193244f, 0.783193f, 0.187449f, 0.809631f, 0.233887f,
- 0.246955f, 0.187075f, 0.271553f, 0.193871f, 0.241255f, 0.236977f, 0.219168f, 0.237388f,
- 0.391747f, 0.862097f, 0.401605f, 0.841460f, 0.438797f, 0.870229f, 0.432388f, 0.894943f,
- 0.315867f, 0.868209f, 0.354026f, 0.840297f, 0.363377f, 0.861308f, 0.321637f, 0.893225f,
- 0.438641f, 0.680683f, 0.452955f, 0.700023f, 0.435018f, 0.718280f, 0.394766f, 0.686125f,
- 0.323658f, 0.715731f, 0.306136f, 0.696976f, 0.320962f, 0.677959f, 0.364838f, 0.684445f,
- 0.433669f, 0.729661f, 0.384658f, 0.710299f, 0.394766f, 0.686125f, 0.435018f, 0.718280f,
- 0.364838f, 0.684445f, 0.374400f, 0.708969f, 0.324726f, 0.727177f, 0.323658f, 0.715731f,
- 0.410995f, 0.747662f, 0.384658f, 0.710299f, 0.433669f, 0.729661f, 0.427812f, 0.742828f,
- 0.324726f, 0.727177f, 0.374400f, 0.708969f, 0.347028f, 0.745816f, 0.330270f, 0.740536f,
- 0.418086f, 0.784946f, 0.384657f, 0.795423f, 0.384658f, 0.710299f, 0.410995f, 0.747662f,
- 0.374400f, 0.708969f, 0.372270f, 0.794472f, 0.338952f, 0.783073f, 0.347028f, 0.745816f,
- 0.401605f, 0.841460f, 0.384657f, 0.795423f, 0.418086f, 0.784946f, 0.431333f, 0.817535f,
- 0.338952f, 0.783073f, 0.372270f, 0.794472f, 0.354026f, 0.840297f, 0.324790f, 0.815460f,
- 0.438797f, 0.870229f, 0.401605f, 0.841460f, 0.431333f, 0.817535f, 0.457832f, 0.840040f,
- 0.324790f, 0.815460f, 0.354026f, 0.840297f, 0.315867f, 0.868209f, 0.297562f, 0.837358f,
- 0.809631f, 0.233887f, 0.816266f, 0.203086f, 0.825107f, 0.209762f, 0.829287f, 0.219562f,
- 0.199767f, 0.214827f, 0.209828f, 0.206161f, 0.219168f, 0.237388f, 0.199067f, 0.222464f,
- 0.809631f, 0.233887f, 0.783193f, 0.187449f, 0.802192f, 0.184609f, 0.816266f, 0.203086f,
- 0.226485f, 0.183086f, 0.246955f, 0.187075f, 0.219168f, 0.237388f, 0.209828f, 0.206161f,
- 0.783193f, 0.187449f, 0.796021f, 0.176969f, 0.802192f, 0.184609f,
- 0.226485f, 0.183086f, 0.233625f, 0.175620f, 0.246955f, 0.187075f,
- 0.457832f, 0.840040f, 0.431333f, 0.817535f, 0.448505f, 0.804621f, 0.473386f, 0.824700f,
- 0.307886f, 0.802031f, 0.324790f, 0.815460f, 0.297562f, 0.837358f, 0.282357f, 0.821525f,
- 0.431333f, 0.817535f, 0.418086f, 0.784946f, 0.435868f, 0.779569f, 0.448505f, 0.804621f,
- 0.321237f, 0.777208f, 0.338952f, 0.783073f, 0.324790f, 0.815460f, 0.307886f, 0.802031f,
- 0.418086f, 0.784946f, 0.410995f, 0.747662f, 0.423718f, 0.754191f, 0.435868f, 0.779569f,
- 0.334089f, 0.752045f, 0.347028f, 0.745816f, 0.338952f, 0.783073f, 0.321237f, 0.777208f,
- 0.410995f, 0.747662f, 0.427812f, 0.742828f, 0.437950f, 0.749777f, 0.423718f, 0.754191f,
- 0.319919f, 0.747250f, 0.330270f, 0.740536f, 0.347028f, 0.745816f, 0.334089f, 0.752045f,
- 0.427812f, 0.742828f, 0.433669f, 0.729661f, 0.445392f, 0.731997f, 0.437950f, 0.749777f,
- 0.312907f, 0.729222f, 0.324726f, 0.727177f, 0.330270f, 0.740536f, 0.319919f, 0.747250f,
- 0.433669f, 0.729661f, 0.435018f, 0.718280f, 0.440995f, 0.724383f, 0.445392f, 0.731997f,
- 0.317510f, 0.721697f, 0.323658f, 0.715731f, 0.324726f, 0.727177f, 0.312907f, 0.729222f,
- 0.435018f, 0.718280f, 0.452955f, 0.700023f, 0.455277f, 0.713731f, 0.440995f, 0.724383f,
- 0.303460f, 0.710657f, 0.306136f, 0.696976f, 0.323658f, 0.715731f, 0.317510f, 0.721697f,
- 0.501231f, 0.844356f, 0.457832f, 0.840040f, 0.473386f, 0.824700f, 0.512485f, 0.828811f,
- 0.282357f, 0.821525f, 0.297562f, 0.837358f, 0.253846f, 0.840502f, 0.242975f, 0.824574f,
- 0.555495f, 0.826352f, 0.501231f, 0.844356f, 0.512485f, 0.828811f, 0.550942f, 0.811814f,
- 0.242975f, 0.824574f, 0.253846f, 0.840502f, 0.199850f, 0.820889f, 0.204839f, 0.806417f,
- 0.568148f, 0.787367f, 0.555495f, 0.826352f, 0.550942f, 0.811814f, 0.552139f, 0.787682f,
- 0.204839f, 0.806417f, 0.199850f, 0.820889f, 0.188269f, 0.781375f, 0.204331f, 0.782156f,
- 0.542850f, 0.755753f, 0.568148f, 0.787367f, 0.552139f, 0.787682f, 0.539407f, 0.764539f,
- 0.204331f, 0.782156f, 0.188269f, 0.781375f, 0.214575f, 0.750414f, 0.217774f, 0.759319f,
- 0.505666f, 0.730944f, 0.542850f, 0.755753f, 0.539407f, 0.764539f, 0.508439f, 0.743135f,
- 0.217774f, 0.759319f, 0.214575f, 0.750414f, 0.252524f, 0.726592f, 0.249419f, 0.738732f,
- 0.452955f, 0.700023f, 0.505666f, 0.730944f, 0.508439f, 0.743135f, 0.455277f, 0.713731f,
- 0.249419f, 0.738732f, 0.252524f, 0.726592f, 0.306136f, 0.696976f, 0.303460f, 0.710657f,
- 0.437950f, 0.749777f, 0.445392f, 0.731997f, 0.470841f, 0.748408f, 0.454776f, 0.761665f,
- 0.286960f, 0.745020f, 0.312907f, 0.729222f, 0.319919f, 0.747250f, 0.302729f, 0.758742f,
- 0.454776f, 0.761665f, 0.470841f, 0.748408f, 0.488870f, 0.770464f, 0.475403f, 0.783904f,
- 0.268291f, 0.766661f, 0.286960f, 0.745020f, 0.302729f, 0.758742f, 0.281439f, 0.780511f,
- 0.475403f, 0.783904f, 0.488870f, 0.770464f, 0.503673f, 0.787562f, 0.494476f, 0.802470f,
- 0.252972f, 0.783410f, 0.268291f, 0.766661f, 0.281439f, 0.780511f, 0.261790f, 0.798626f,
- 0.494476f, 0.802470f, 0.503673f, 0.787562f, 0.518562f, 0.791602f, 0.516802f, 0.807339f,
- 0.237920f, 0.787045f, 0.252972f, 0.783410f, 0.261790f, 0.798626f, 0.239243f, 0.802891f,
- 0.512485f, 0.828811f, 0.473386f, 0.824700f, 0.494476f, 0.802470f, 0.516802f, 0.807339f,
- 0.261790f, 0.798626f, 0.282357f, 0.821525f, 0.242975f, 0.824574f, 0.239243f, 0.802891f,
- 0.448505f, 0.804621f, 0.475403f, 0.783904f, 0.494476f, 0.802470f, 0.473386f, 0.824700f,
- 0.261790f, 0.798626f, 0.281439f, 0.780511f, 0.307886f, 0.802031f, 0.282357f, 0.821525f,
- 0.448505f, 0.804621f, 0.435868f, 0.779569f, 0.454776f, 0.761665f, 0.475403f, 0.783904f,
- 0.302729f, 0.758742f, 0.321237f, 0.777208f, 0.307886f, 0.802031f, 0.281439f, 0.780511f,
- 0.437950f, 0.749777f, 0.454776f, 0.761665f, 0.435868f, 0.779569f, 0.423718f, 0.754191f,
- 0.321237f, 0.777208f, 0.302729f, 0.758742f, 0.319919f, 0.747250f, 0.334089f, 0.752045f,
- 0.440995f, 0.724383f, 0.455277f, 0.713731f, 0.470841f, 0.748408f, 0.445392f, 0.731997f,
- 0.286960f, 0.745020f, 0.303460f, 0.710657f, 0.317510f, 0.721697f, 0.312907f, 0.729222f,
- 0.508439f, 0.743135f, 0.488870f, 0.770464f, 0.470841f, 0.748408f, 0.455277f, 0.713731f,
- 0.286960f, 0.745020f, 0.268291f, 0.766661f, 0.249419f, 0.738732f, 0.303460f, 0.710657f,
- 0.539407f, 0.764539f, 0.503673f, 0.787562f, 0.488870f, 0.770464f, 0.508439f, 0.743135f,
- 0.268291f, 0.766661f, 0.252972f, 0.783410f, 0.217774f, 0.759319f, 0.249419f, 0.738732f,
- 0.552139f, 0.787682f, 0.518562f, 0.791602f, 0.503673f, 0.787562f, 0.539407f, 0.764539f,
- 0.252972f, 0.783410f, 0.237920f, 0.787045f, 0.204331f, 0.782156f, 0.217774f, 0.759319f,
- 0.550942f, 0.811814f, 0.516802f, 0.807339f, 0.518562f, 0.791602f, 0.552139f, 0.787682f,
- 0.237920f, 0.787045f, 0.239243f, 0.802891f, 0.204839f, 0.806417f, 0.204331f, 0.782156f,
- 0.512485f, 0.828811f, 0.516802f, 0.807339f, 0.550942f, 0.811814f,
- 0.204839f, 0.806417f, 0.239243f, 0.802891f, 0.242975f, 0.824574f,
- 0.508270f, 0.697693f, 0.434803f, 0.658882f, 0.484068f, 0.628776f, 0.543385f, 0.683538f,
- 0.276936f, 0.625067f, 0.325318f, 0.656224f, 0.250811f, 0.693249f, 0.216123f, 0.678120f,
- 0.563786f, 0.739211f, 0.508270f, 0.697693f, 0.543385f, 0.683538f, 0.581052f, 0.726933f,
- 0.216123f, 0.678120f, 0.250811f, 0.693249f, 0.194086f, 0.733241f, 0.177176f, 0.720426f,
- 0.619962f, 0.791615f, 0.563786f, 0.739211f, 0.581052f, 0.726933f, 0.616701f, 0.759965f,
- 0.177176f, 0.720426f, 0.194086f, 0.733241f, 0.136063f, 0.784093f, 0.140379f, 0.752377f,
- 0.707492f, 0.759884f, 0.619962f, 0.791615f, 0.616701f, 0.759965f, 0.660647f, 0.741167f,
- 0.140379f, 0.752377f, 0.136063f, 0.784093f, 0.049526f, 0.748824f, 0.097038f, 0.732052f,
- 0.745511f, 0.652100f, 0.707492f, 0.759884f, 0.660647f, 0.741167f, 0.677256f, 0.670436f,
- 0.097038f, 0.732052f, 0.049526f, 0.748824f, 0.019409f, 0.639749f, 0.083564f, 0.662038f,
- 0.740843f, 0.572428f, 0.745511f, 0.652100f, 0.677256f, 0.670436f, 0.671403f, 0.592656f,
- 0.083564f, 0.662038f, 0.019409f, 0.639749f, 0.033664f, 0.564403f, 0.092820f, 0.589862f,
- 0.677256f, 0.670436f, 0.543385f, 0.683538f, 0.484068f, 0.628776f, 0.671403f, 0.592656f,
- 0.276936f, 0.625067f, 0.216123f, 0.678120f, 0.083564f, 0.662038f, 0.092820f, 0.589862f,
- 0.677256f, 0.670436f, 0.660647f, 0.741167f, 0.581052f, 0.726933f, 0.543385f, 0.683538f,
- 0.177176f, 0.720426f, 0.097038f, 0.732052f, 0.083564f, 0.662038f, 0.216123f, 0.678120f,
- 0.660647f, 0.741167f, 0.616701f, 0.759965f, 0.581052f, 0.726933f,
- 0.177176f, 0.720426f, 0.140379f, 0.752377f, 0.097038f, 0.732052f,
- 0.842355f, 0.195160f, 0.829287f, 0.219562f, 0.834578f, 0.206879f, 0.834705f, 0.206959f,
- 0.033664f, 0.564403f, 0.051216f, 0.522659f, 0.145041f, 0.562595f, 0.092820f, 0.589862f,
- 0.620420f, 0.565675f, 0.671403f, 0.592656f, 0.484068f, 0.628776f, 0.498072f, 0.552315f,
- 0.276936f, 0.625067f, 0.092820f, 0.589862f, 0.145041f, 0.562595f, 0.264218f, 0.550140f,
- 0.391039f, 0.611891f, 0.498072f, 0.552315f, 0.484068f, 0.628776f, 0.434803f, 0.658882f,
- 0.276936f, 0.625067f, 0.264218f, 0.550140f, 0.369913f, 0.610196f, 0.325318f, 0.656224f,
+static const float monkeyuvs[] = {
+ 0.890955f, 0.590063f, 0.870622f, 0.589649f, 0.860081f, 0.560115f, 0.904571f, 0.559404f,
+ 0.856226f, 0.850547f, 0.868067f, 0.821510f, 0.888398f, 0.821999f, 0.900640f, 0.853232f,
+ 0.904571f, 0.559404f, 0.860081f, 0.560115f, 0.853018f, 0.521562f, 0.920166f, 0.524546f,
+ 0.847458f, 0.888748f, 0.856226f, 0.850547f, 0.900640f, 0.853232f, 0.914672f, 0.888748f,
+ 0.860081f, 0.560115f, 0.828900f, 0.590771f, 0.798481f, 0.569535f, 0.853018f, 0.521562f,
+ 0.795104f, 0.838402f, 0.826436f, 0.818537f, 0.856226f, 0.850547f, 0.847458f, 0.888748f,
+ 0.870622f, 0.589649f, 0.854402f, 0.604754f, 0.828900f, 0.590771f, 0.860081f, 0.560115f,
+ 0.826436f, 0.818537f, 0.852534f, 0.805700f, 0.868067f, 0.821510f, 0.856226f, 0.850547f,
+ 0.854402f, 0.604754f, 0.854107f, 0.625459f, 0.828171f, 0.633354f, 0.828900f, 0.590771f,
+ 0.827598f, 0.775964f, 0.853157f, 0.785002f, 0.852534f, 0.805700f, 0.826436f, 0.818537f,
+ 0.828900f, 0.590771f, 0.828171f, 0.633354f, 0.791018f, 0.645443f, 0.798481f, 0.569535f,
+ 0.791018f, 0.762238f, 0.827598f, 0.775964f, 0.826436f, 0.818537f, 0.795104f, 0.838402f,
+ 0.828171f, 0.633354f, 0.855181f, 0.668527f, 0.842358f, 0.702491f, 0.791018f, 0.645443f,
+ 0.844839f, 0.707525f, 0.856142f, 0.742025f, 0.827598f, 0.775964f, 0.791018f, 0.762238f,
+ 0.854107f, 0.625459f, 0.867508f, 0.642291f, 0.855181f, 0.668527f, 0.828171f, 0.633354f,
+ 0.856142f, 0.742025f, 0.867293f, 0.768782f, 0.853157f, 0.785002f, 0.827598f, 0.775964f,
+ 0.867508f, 0.642291f, 0.890474f, 0.641909f, 0.900375f, 0.666964f, 0.855181f, 0.668527f,
+ 0.901223f, 0.745592f, 0.890219f, 0.770183f, 0.867293f, 0.768782f, 0.856142f, 0.742025f,
+ 0.855181f, 0.668527f, 0.900375f, 0.666964f, 0.918898f, 0.699697f, 0.842358f, 0.702491f,
+ 0.921180f, 0.713713f, 0.901223f, 0.745592f, 0.856142f, 0.742025f, 0.844839f, 0.707525f,
+ 0.900375f, 0.666964f, 0.931889f, 0.636832f, 0.968392f, 0.645333f, 0.918898f, 0.699697f,
+ 0.968213f, 0.770220f, 0.931368f, 0.777093f, 0.901223f, 0.745592f, 0.921180f, 0.713713f,
+ 0.890474f, 0.641909f, 0.905882f, 0.627902f, 0.931889f, 0.636832f, 0.900375f, 0.666964f,
+ 0.931368f, 0.777093f, 0.904990f, 0.784860f, 0.890219f, 0.770183f, 0.901223f, 0.745592f,
+ 0.905882f, 0.627902f, 0.906232f, 0.605742f, 0.933717f, 0.593037f, 0.931889f, 0.636832f,
+ 0.931250f, 0.820926f, 0.904357f, 0.807013f, 0.904990f, 0.784860f, 0.931368f, 0.777093f,
+ 0.931889f, 0.636832f, 0.933717f, 0.593037f, 0.968392f, 0.573812f, 0.968392f, 0.645333f,
+ 0.965038f, 0.841671f, 0.931250f, 0.820926f, 0.931368f, 0.777093f, 0.968213f, 0.770220f,
+ 0.933717f, 0.593037f, 0.904571f, 0.559404f, 0.920166f, 0.524546f, 0.968392f, 0.573812f,
+ 0.914672f, 0.888748f, 0.900640f, 0.853232f, 0.931250f, 0.820926f, 0.965038f, 0.841671f,
+ 0.906232f, 0.605742f, 0.890955f, 0.590063f, 0.904571f, 0.559404f, 0.933717f, 0.593037f,
+ 0.900640f, 0.853232f, 0.888398f, 0.821999f, 0.904357f, 0.807013f, 0.931250f, 0.820926f,
+ 0.890955f, 0.590063f, 0.906232f, 0.605742f, 0.902359f, 0.607909f, 0.889591f, 0.593275f,
+ 0.900583f, 0.804677f, 0.904357f, 0.807013f, 0.888398f, 0.821999f, 0.887178f, 0.818729f,
+ 0.906232f, 0.605742f, 0.905882f, 0.627902f, 0.899781f, 0.626257f, 0.902359f, 0.607909f,
+ 0.898822f, 0.786233f, 0.904990f, 0.784860f, 0.904357f, 0.807013f, 0.900583f, 0.804677f,
+ 0.905882f, 0.627902f, 0.890474f, 0.641909f, 0.887842f, 0.636527f, 0.899781f, 0.626257f,
+ 0.887351f, 0.775442f, 0.890219f, 0.770183f, 0.904990f, 0.784860f, 0.898822f, 0.786233f,
+ 0.890474f, 0.641909f, 0.867508f, 0.642291f, 0.870908f, 0.635245f, 0.887842f, 0.636527f,
+ 0.870376f, 0.775972f, 0.867293f, 0.768782f, 0.890219f, 0.770183f, 0.887351f, 0.775442f,
+ 0.867508f, 0.642291f, 0.854107f, 0.625459f, 0.859881f, 0.623942f, 0.870908f, 0.635245f,
+ 0.858859f, 0.786774f, 0.853157f, 0.785002f, 0.867293f, 0.768782f, 0.870376f, 0.775972f,
+ 0.854107f, 0.625459f, 0.854402f, 0.604754f, 0.859664f, 0.608186f, 0.859881f, 0.623942f,
+ 0.857942f, 0.802505f, 0.852534f, 0.805700f, 0.853157f, 0.785002f, 0.858859f, 0.786774f,
+ 0.854402f, 0.604754f, 0.870622f, 0.589649f, 0.871664f, 0.593961f, 0.859664f, 0.608186f,
+ 0.869299f, 0.817249f, 0.868067f, 0.821510f, 0.852534f, 0.805700f, 0.857942f, 0.802505f,
+ 0.870622f, 0.589649f, 0.890955f, 0.590063f, 0.889591f, 0.593275f, 0.871664f, 0.593961f,
+ 0.887178f, 0.818729f, 0.888398f, 0.821999f, 0.868067f, 0.821510f, 0.869299f, 0.817249f,
+ 0.879400f, 0.616512f, 0.871664f, 0.593961f, 0.889591f, 0.593275f, 0.887178f, 0.818729f,
+ 0.869299f, 0.817249f, 0.878029f, 0.795063f, 0.859664f, 0.608186f, 0.871664f, 0.593961f,
+ 0.879400f, 0.616512f, 0.878029f, 0.795063f, 0.869299f, 0.817249f, 0.857942f, 0.802505f,
+ 0.879400f, 0.616512f, 0.859881f, 0.623942f, 0.859664f, 0.608186f, 0.857942f, 0.802505f,
+ 0.858859f, 0.786774f, 0.878029f, 0.795063f, 0.879400f, 0.616512f, 0.870908f, 0.635245f,
+ 0.859881f, 0.623942f, 0.858859f, 0.786774f, 0.870376f, 0.775972f, 0.878029f, 0.795063f,
+ 0.879400f, 0.616512f, 0.887842f, 0.636527f, 0.870908f, 0.635245f, 0.870376f, 0.775972f,
+ 0.887351f, 0.775442f, 0.878029f, 0.795063f, 0.879400f, 0.616512f, 0.899781f, 0.626257f,
+ 0.887842f, 0.636527f, 0.887351f, 0.775442f, 0.898822f, 0.786233f, 0.878029f, 0.795063f,
+ 0.879400f, 0.616512f, 0.902359f, 0.607909f, 0.899781f, 0.626257f, 0.898822f, 0.786233f,
+ 0.900583f, 0.804677f, 0.878029f, 0.795063f, 0.879400f, 0.616512f, 0.889591f, 0.593275f,
+ 0.902359f, 0.607909f, 0.900583f, 0.804677f, 0.887178f, 0.818729f, 0.878029f, 0.795063f,
+ 0.540260f, 0.053805f, 0.536419f, 0.062072f, 0.518925f, 0.059681f, 0.518916f, 0.050294f,
+ 0.518925f, 0.059681f, 0.501452f, 0.062043f, 0.497626f, 0.053770f, 0.518916f, 0.050294f,
+ 0.551930f, 0.058338f, 0.542788f, 0.064089f, 0.536419f, 0.062072f, 0.540260f, 0.053805f,
+ 0.501452f, 0.062043f, 0.495083f, 0.064047f, 0.485955f, 0.058273f, 0.497626f, 0.053770f,
+ 0.555073f, 0.061900f, 0.546290f, 0.072669f, 0.542788f, 0.064089f, 0.551930f, 0.058338f,
+ 0.495083f, 0.064047f, 0.491565f, 0.072625f, 0.482805f, 0.061829f, 0.485955f, 0.058273f,
+ 0.563812f, 0.076586f, 0.548333f, 0.084893f, 0.546290f, 0.072669f, 0.555073f, 0.061900f,
+ 0.491565f, 0.072625f, 0.489507f, 0.084858f, 0.474014f, 0.076511f, 0.482805f, 0.061829f,
+ 0.583135f, 0.108495f, 0.555621f, 0.121749f, 0.548333f, 0.084893f, 0.563812f, 0.076586f,
+ 0.489507f, 0.084858f, 0.482177f, 0.121781f, 0.454527f, 0.108481f, 0.474014f, 0.076511f,
+ 0.605512f, 0.165134f, 0.647395f, 0.200502f, 0.621513f, 0.227818f, 0.553118f, 0.209599f,
+ 0.416514f, 0.229490f, 0.389677f, 0.201890f, 0.432024f, 0.165644f, 0.485339f, 0.210053f,
+ 0.647395f, 0.200502f, 0.676379f, 0.233241f, 0.664761f, 0.253225f, 0.621513f, 0.227818f,
+ 0.372747f, 0.256357f, 0.360308f, 0.235899f, 0.389677f, 0.201890f, 0.416514f, 0.229490f,
+ 0.676379f, 0.233241f, 0.715342f, 0.265392f, 0.683908f, 0.279995f, 0.664761f, 0.253225f,
+ 0.353696f, 0.284606f, 0.320452f, 0.270303f, 0.360308f, 0.235899f, 0.372747f, 0.256357f,
+ 0.715342f, 0.265392f, 0.707254f, 0.310054f, 0.687515f, 0.311539f, 0.683908f, 0.279995f,
+ 0.351187f, 0.317440f, 0.330721f, 0.316853f, 0.320452f, 0.270303f, 0.353696f, 0.284606f,
+ 0.707254f, 0.310054f, 0.697446f, 0.332673f, 0.676824f, 0.323937f, 0.687515f, 0.311539f,
+ 0.362723f, 0.329722f, 0.341964f, 0.339667f, 0.330721f, 0.316853f, 0.351187f, 0.317440f,
+ 0.697446f, 0.332673f, 0.662817f, 0.372521f, 0.639050f, 0.357330f, 0.676824f, 0.323937f,
+ 0.402772f, 0.362131f, 0.379297f, 0.378686f, 0.341964f, 0.339667f, 0.362723f, 0.329722f,
+ 0.662817f, 0.372521f, 0.626842f, 0.395792f, 0.618316f, 0.375151f, 0.639050f, 0.357330f,
+ 0.424583f, 0.379267f, 0.416915f, 0.400552f, 0.379297f, 0.378686f, 0.402772f, 0.362131f,
+ 0.626842f, 0.395792f, 0.604826f, 0.397804f, 0.600808f, 0.377857f, 0.618316f, 0.375151f,
+ 0.442396f, 0.381222f, 0.439252f, 0.401540f, 0.416915f, 0.400552f, 0.424583f, 0.379267f,
+ 0.604826f, 0.397804f, 0.553095f, 0.390512f, 0.559674f, 0.357011f, 0.600808f, 0.377857f,
+ 0.482938f, 0.358497f, 0.490934f, 0.391862f, 0.439252f, 0.401540f, 0.442396f, 0.381222f,
+ 0.553095f, 0.390512f, 0.521923f, 0.386009f, 0.521086f, 0.343868f, 0.559674f, 0.357011f,
+ 0.521086f, 0.343868f, 0.521923f, 0.386009f, 0.490934f, 0.391862f, 0.482938f, 0.358497f,
+ 0.577279f, 0.340156f, 0.599845f, 0.344815f, 0.600808f, 0.377857f, 0.559674f, 0.357011f,
+ 0.442396f, 0.381222f, 0.441977f, 0.347815f, 0.464579f, 0.342230f, 0.482938f, 0.358497f,
+ 0.599845f, 0.344815f, 0.615546f, 0.342005f, 0.618316f, 0.375151f, 0.600808f, 0.377857f,
+ 0.424583f, 0.379267f, 0.425972f, 0.345582f, 0.441977f, 0.347815f, 0.442396f, 0.381222f,
+ 0.634472f, 0.332311f, 0.639050f, 0.357330f, 0.618316f, 0.375151f, 0.615546f, 0.342005f,
+ 0.424583f, 0.379267f, 0.402772f, 0.362131f, 0.406362f, 0.336480f, 0.425972f, 0.345582f,
+ 0.662406f, 0.312804f, 0.676824f, 0.323937f, 0.639050f, 0.357330f, 0.634472f, 0.332311f,
+ 0.402772f, 0.362131f, 0.362723f, 0.329722f, 0.377061f, 0.317685f, 0.406362f, 0.336480f,
+ 0.668440f, 0.297958f, 0.687515f, 0.311539f, 0.676824f, 0.323937f, 0.662406f, 0.312804f,
+ 0.362723f, 0.329722f, 0.351187f, 0.317440f, 0.370304f, 0.302644f, 0.377061f, 0.317685f,
+ 0.664101f, 0.277872f, 0.683908f, 0.279995f, 0.687515f, 0.311539f, 0.668440f, 0.297958f,
+ 0.351187f, 0.317440f, 0.353696f, 0.284606f, 0.374100f, 0.281778f, 0.370304f, 0.302644f,
+ 0.639236f, 0.253047f, 0.664761f, 0.253225f, 0.683908f, 0.279995f, 0.664101f, 0.277872f,
+ 0.353696f, 0.284606f, 0.372747f, 0.256357f, 0.398938f, 0.255633f, 0.374100f, 0.281778f,
+ 0.613992f, 0.242662f, 0.621513f, 0.227818f, 0.664761f, 0.253225f, 0.639236f, 0.253047f,
+ 0.372747f, 0.256357f, 0.416514f, 0.229490f, 0.424464f, 0.244473f, 0.398938f, 0.255633f,
+ 0.572941f, 0.258564f, 0.553118f, 0.209599f, 0.621513f, 0.227818f, 0.613992f, 0.242662f,
+ 0.416514f, 0.229490f, 0.485339f, 0.210053f, 0.466409f, 0.259709f, 0.424464f, 0.244473f,
+ 0.572941f, 0.258564f, 0.563905f, 0.272007f, 0.519760f, 0.248864f, 0.553118f, 0.209599f,
+ 0.519760f, 0.248864f, 0.475886f, 0.273078f, 0.466409f, 0.259709f, 0.485339f, 0.210053f,
+ 0.577279f, 0.340156f, 0.559674f, 0.357011f, 0.521086f, 0.343868f, 0.558527f, 0.316594f,
+ 0.521086f, 0.343868f, 0.482938f, 0.358497f, 0.464579f, 0.342230f, 0.482619f, 0.317843f,
+ 0.558527f, 0.316594f, 0.521086f, 0.343868f, 0.520277f, 0.294764f, 0.556923f, 0.291214f,
+ 0.520277f, 0.294764f, 0.521086f, 0.343868f, 0.482619f, 0.317843f, 0.483433f, 0.292249f,
+ 0.519760f, 0.248864f, 0.563905f, 0.272007f, 0.556923f, 0.291214f, 0.520277f, 0.294764f,
+ 0.483433f, 0.292249f, 0.475886f, 0.273078f, 0.519760f, 0.248864f, 0.520277f, 0.294764f,
+ 0.525483f, 0.068967f, 0.518928f, 0.067899f, 0.518925f, 0.059681f, 0.536419f, 0.062072f,
+ 0.518925f, 0.059681f, 0.518928f, 0.067899f, 0.512375f, 0.068956f, 0.501452f, 0.062043f,
+ 0.531231f, 0.073829f, 0.525483f, 0.068967f, 0.536419f, 0.062072f, 0.542788f, 0.064089f,
+ 0.501452f, 0.062043f, 0.512375f, 0.068956f, 0.506626f, 0.073811f, 0.495083f, 0.064047f,
+ 0.531019f, 0.087431f, 0.531231f, 0.073829f, 0.542788f, 0.064089f, 0.546290f, 0.072669f,
+ 0.495083f, 0.064047f, 0.506626f, 0.073811f, 0.506827f, 0.087416f, 0.491565f, 0.072625f,
+ 0.555621f, 0.121749f, 0.532042f, 0.127713f, 0.532669f, 0.090920f, 0.548333f, 0.084893f,
+ 0.505177f, 0.090908f, 0.505828f, 0.127728f, 0.482177f, 0.121781f, 0.489507f, 0.084858f,
+ 0.531019f, 0.087431f, 0.546290f, 0.072669f, 0.548333f, 0.084893f, 0.532669f, 0.090920f,
+ 0.489507f, 0.084858f, 0.491565f, 0.072625f, 0.506827f, 0.087416f, 0.505177f, 0.090908f,
+ 0.538112f, 0.158382f, 0.518981f, 0.151749f, 0.518941f, 0.128358f, 0.532042f, 0.127713f,
+ 0.518941f, 0.128358f, 0.518981f, 0.151749f, 0.499851f, 0.158434f, 0.505828f, 0.127728f,
+ 0.532669f, 0.090920f, 0.532042f, 0.127713f, 0.518941f, 0.128358f, 0.518925f, 0.093952f,
+ 0.518941f, 0.128358f, 0.505828f, 0.127728f, 0.505177f, 0.090908f, 0.518925f, 0.093952f,
+ 0.518927f, 0.085180f, 0.531019f, 0.087431f, 0.532669f, 0.090920f, 0.518925f, 0.093952f,
+ 0.505177f, 0.090908f, 0.506827f, 0.087416f, 0.518927f, 0.085180f, 0.518925f, 0.093952f,
+ 0.548362f, 0.173560f, 0.537959f, 0.175966f, 0.535214f, 0.166808f, 0.538112f, 0.158382f,
+ 0.502799f, 0.166857f, 0.500100f, 0.176033f, 0.489683f, 0.173693f, 0.499851f, 0.158434f,
+ 0.544281f, 0.193366f, 0.537248f, 0.187577f, 0.537959f, 0.175966f, 0.548362f, 0.173560f,
+ 0.500100f, 0.176033f, 0.500890f, 0.187571f, 0.493996f, 0.193428f, 0.489683f, 0.173693f,
+ 0.519841f, 0.200843f, 0.528757f, 0.191785f, 0.537248f, 0.187577f, 0.544281f, 0.193366f,
+ 0.500890f, 0.187571f, 0.509219f, 0.191626f, 0.519841f, 0.200843f, 0.493996f, 0.193428f,
+ 0.517577f, 0.190607f, 0.519132f, 0.185382f, 0.528757f, 0.191785f, 0.519841f, 0.200843f,
+ 0.509219f, 0.191626f, 0.519132f, 0.185382f, 0.517577f, 0.190607f, 0.519841f, 0.200843f,
+ 0.518981f, 0.151749f, 0.538112f, 0.158382f, 0.535214f, 0.166808f, 0.518998f, 0.159028f,
+ 0.502799f, 0.166857f, 0.499851f, 0.158434f, 0.518981f, 0.151749f, 0.518998f, 0.159028f,
+ 0.518998f, 0.159028f, 0.535214f, 0.166808f, 0.531131f, 0.171631f, 0.519016f, 0.165599f,
+ 0.506910f, 0.171667f, 0.502799f, 0.166857f, 0.518998f, 0.159028f, 0.519016f, 0.165599f,
+ 0.519132f, 0.185382f, 0.519099f, 0.179457f, 0.528222f, 0.186316f, 0.528757f, 0.191785f,
+ 0.509787f, 0.186260f, 0.519099f, 0.179457f, 0.519132f, 0.185382f, 0.509219f, 0.191626f,
+ 0.528757f, 0.191785f, 0.528222f, 0.186316f, 0.533528f, 0.184215f, 0.537248f, 0.187577f,
+ 0.504547f, 0.184206f, 0.509787f, 0.186260f, 0.509219f, 0.191626f, 0.500890f, 0.187571f,
+ 0.537248f, 0.187577f, 0.533528f, 0.184215f, 0.533449f, 0.176739f, 0.537959f, 0.175966f,
+ 0.504604f, 0.176791f, 0.504547f, 0.184206f, 0.500890f, 0.187571f, 0.500100f, 0.176033f,
+ 0.537959f, 0.175966f, 0.533449f, 0.176739f, 0.531131f, 0.171631f, 0.535214f, 0.166808f,
+ 0.506910f, 0.171667f, 0.504604f, 0.176791f, 0.500100f, 0.176033f, 0.502799f, 0.166857f,
+ 0.519099f, 0.179457f, 0.533449f, 0.176739f, 0.533528f, 0.184215f, 0.528222f, 0.186316f,
+ 0.504547f, 0.184206f, 0.504604f, 0.176791f, 0.519099f, 0.179457f, 0.509787f, 0.186260f,
+ 0.519099f, 0.179457f, 0.519016f, 0.165599f, 0.531131f, 0.171631f, 0.533449f, 0.176739f,
+ 0.506910f, 0.171667f, 0.519016f, 0.165599f, 0.519099f, 0.179457f, 0.504604f, 0.176791f,
+ 0.519841f, 0.200843f, 0.544281f, 0.193366f, 0.553118f, 0.209599f, 0.519760f, 0.248864f,
+ 0.485339f, 0.210053f, 0.493996f, 0.193428f, 0.519841f, 0.200843f, 0.519760f, 0.248864f,
+ 0.544281f, 0.193366f, 0.548362f, 0.173560f, 0.561572f, 0.167779f, 0.553118f, 0.209599f,
+ 0.476363f, 0.167996f, 0.489683f, 0.173693f, 0.493996f, 0.193428f, 0.485339f, 0.210053f,
+ 0.548362f, 0.173560f, 0.538112f, 0.158382f, 0.559475f, 0.149319f, 0.561572f, 0.167779f,
+ 0.478371f, 0.149447f, 0.499851f, 0.158434f, 0.489683f, 0.173693f, 0.476363f, 0.167996f,
+ 0.538112f, 0.158382f, 0.532042f, 0.127713f, 0.555621f, 0.121749f, 0.559475f, 0.149319f,
+ 0.482177f, 0.121781f, 0.505828f, 0.127728f, 0.499851f, 0.158434f, 0.478371f, 0.149447f,
+ 0.583135f, 0.108495f, 0.596138f, 0.133426f, 0.559475f, 0.149319f, 0.555621f, 0.121749f,
+ 0.478371f, 0.149447f, 0.441395f, 0.133592f, 0.454527f, 0.108481f, 0.482177f, 0.121781f,
+ 0.596138f, 0.133426f, 0.601169f, 0.147885f, 0.561572f, 0.167779f, 0.559475f, 0.149319f,
+ 0.476363f, 0.167996f, 0.436337f, 0.148194f, 0.441395f, 0.133592f, 0.478371f, 0.149447f,
+ 0.605512f, 0.165134f, 0.553118f, 0.209599f, 0.561572f, 0.167779f, 0.601169f, 0.147885f,
+ 0.476363f, 0.167996f, 0.485339f, 0.210053f, 0.432024f, 0.165644f, 0.436337f, 0.148194f,
+ 0.531019f, 0.087431f, 0.518927f, 0.085180f, 0.518925f, 0.083865f, 0.528933f, 0.084957f,
+ 0.518925f, 0.083865f, 0.518927f, 0.085180f, 0.506827f, 0.087416f, 0.508915f, 0.084945f,
+ 0.531231f, 0.073829f, 0.531019f, 0.087431f, 0.528933f, 0.084957f, 0.529036f, 0.075429f,
+ 0.508915f, 0.084945f, 0.506827f, 0.087416f, 0.506626f, 0.073811f, 0.508820f, 0.075415f,
+ 0.525483f, 0.068967f, 0.531231f, 0.073829f, 0.529036f, 0.075429f, 0.523751f, 0.070508f,
+ 0.508820f, 0.075415f, 0.506626f, 0.073811f, 0.512375f, 0.068956f, 0.514106f, 0.070501f,
+ 0.518928f, 0.067899f, 0.525483f, 0.068967f, 0.523751f, 0.070508f, 0.518929f, 0.069468f,
+ 0.514106f, 0.070501f, 0.512375f, 0.068956f, 0.518928f, 0.067899f, 0.518929f, 0.069468f,
+ 0.518929f, 0.069468f, 0.523751f, 0.070508f, 0.521560f, 0.074970f, 0.518928f, 0.074259f,
+ 0.516297f, 0.074966f, 0.514106f, 0.070501f, 0.518929f, 0.069468f, 0.518928f, 0.074259f,
+ 0.523751f, 0.070508f, 0.529036f, 0.075429f, 0.524236f, 0.076691f, 0.521560f, 0.074970f,
+ 0.513619f, 0.076684f, 0.508820f, 0.075415f, 0.514106f, 0.070501f, 0.516297f, 0.074966f,
+ 0.529036f, 0.075429f, 0.528933f, 0.084957f, 0.524601f, 0.079886f, 0.524236f, 0.076691f,
+ 0.513252f, 0.079879f, 0.508915f, 0.084945f, 0.508820f, 0.075415f, 0.513619f, 0.076684f,
+ 0.528933f, 0.084957f, 0.518925f, 0.083865f, 0.518926f, 0.079331f, 0.524601f, 0.079886f,
+ 0.518926f, 0.079331f, 0.518925f, 0.083865f, 0.508915f, 0.084945f, 0.513252f, 0.079879f,
+ 0.518926f, 0.079331f, 0.518928f, 0.074259f, 0.521560f, 0.074970f, 0.524601f, 0.079886f,
+ 0.516297f, 0.074966f, 0.518928f, 0.074259f, 0.518926f, 0.079331f, 0.513252f, 0.079879f,
+ 0.524601f, 0.079886f, 0.521560f, 0.074970f, 0.524236f, 0.076691f, 0.513619f, 0.076684f,
+ 0.516297f, 0.074966f, 0.513252f, 0.079879f, 0.556923f, 0.291214f, 0.563905f, 0.272007f,
+ 0.571787f, 0.277295f, 0.568351f, 0.292904f, 0.468070f, 0.278617f, 0.475886f, 0.273078f,
+ 0.483433f, 0.292249f, 0.471978f, 0.294282f, 0.558527f, 0.316594f, 0.556923f, 0.291214f,
+ 0.568351f, 0.292904f, 0.573085f, 0.311386f, 0.471978f, 0.294282f, 0.483433f, 0.292249f,
+ 0.482619f, 0.317843f, 0.467790f, 0.313081f, 0.577279f, 0.340156f, 0.558527f, 0.316594f,
+ 0.573085f, 0.311386f, 0.584855f, 0.327708f, 0.467790f, 0.313081f, 0.482619f, 0.317843f,
+ 0.464579f, 0.342230f, 0.456477f, 0.329961f, 0.563905f, 0.272007f, 0.572941f, 0.258564f,
+ 0.580734f, 0.266620f, 0.571787f, 0.277295f, 0.458737f, 0.268049f, 0.466409f, 0.259709f,
+ 0.475886f, 0.273078f, 0.468070f, 0.278617f, 0.572941f, 0.258564f, 0.613992f, 0.242662f,
+ 0.611720f, 0.255725f, 0.580734f, 0.266620f, 0.427062f, 0.257728f, 0.424464f, 0.244473f,
+ 0.466409f, 0.259709f, 0.458737f, 0.268049f, 0.613992f, 0.242662f, 0.639236f, 0.253047f,
+ 0.632494f, 0.262853f, 0.611720f, 0.255725f, 0.406068f, 0.265508f, 0.398938f, 0.255633f,
+ 0.424464f, 0.244473f, 0.427062f, 0.257728f, 0.639236f, 0.253047f, 0.664101f, 0.277872f,
+ 0.653658f, 0.279971f, 0.632494f, 0.262853f, 0.384904f, 0.283634f, 0.374100f, 0.281778f,
+ 0.398938f, 0.255633f, 0.406068f, 0.265508f, 0.664101f, 0.277872f, 0.668440f, 0.297958f,
+ 0.656064f, 0.297636f, 0.653658f, 0.279971f, 0.383015f, 0.301864f, 0.370304f, 0.302644f,
+ 0.374100f, 0.281778f, 0.384904f, 0.283634f, 0.668440f, 0.297958f, 0.662406f, 0.312804f,
+ 0.652752f, 0.310186f, 0.656064f, 0.297636f, 0.386858f, 0.314615f, 0.377061f, 0.317685f,
+ 0.370304f, 0.302644f, 0.383015f, 0.301864f, 0.662406f, 0.312804f, 0.634472f, 0.332311f,
+ 0.629040f, 0.323864f, 0.652752f, 0.310186f, 0.411556f, 0.327673f, 0.406362f, 0.336480f,
+ 0.377061f, 0.317685f, 0.386858f, 0.314615f, 0.634472f, 0.332311f, 0.615546f, 0.342005f,
+ 0.614408f, 0.331972f, 0.629040f, 0.323864f, 0.426727f, 0.335361f, 0.425972f, 0.345582f,
+ 0.406362f, 0.336480f, 0.411556f, 0.327673f, 0.615546f, 0.342005f, 0.599845f, 0.344815f,
+ 0.601033f, 0.333624f, 0.614408f, 0.331972f, 0.440344f, 0.336537f, 0.441977f, 0.347815f,
+ 0.425972f, 0.345582f, 0.426727f, 0.335361f, 0.599845f, 0.344815f, 0.577279f, 0.340156f,
+ 0.584855f, 0.327708f, 0.601033f, 0.333624f, 0.456477f, 0.329961f, 0.464579f, 0.342230f,
+ 0.441977f, 0.347815f, 0.440344f, 0.336537f, 0.601033f, 0.333624f, 0.584855f, 0.327708f,
+ 0.590644f, 0.321516f, 0.601799f, 0.328453f, 0.450408f, 0.323919f, 0.456477f, 0.329961f,
+ 0.440344f, 0.336537f, 0.439372f, 0.331331f, 0.614408f, 0.331972f, 0.601033f, 0.333624f,
+ 0.601799f, 0.328453f, 0.613335f, 0.327083f, 0.439372f, 0.331331f, 0.440344f, 0.336537f,
+ 0.426727f, 0.335361f, 0.427623f, 0.330358f, 0.629040f, 0.323864f, 0.614408f, 0.331972f,
+ 0.613335f, 0.327083f, 0.626851f, 0.320513f, 0.427623f, 0.330358f, 0.426727f, 0.335361f,
+ 0.411556f, 0.327673f, 0.413648f, 0.324175f, 0.652752f, 0.310186f, 0.629040f, 0.323864f,
+ 0.626851f, 0.320513f, 0.646248f, 0.306421f, 0.413648f, 0.324175f, 0.411556f, 0.327673f,
+ 0.386858f, 0.314615f, 0.393381f, 0.310510f, 0.656064f, 0.297636f, 0.652752f, 0.310186f,
+ 0.646248f, 0.306421f, 0.649541f, 0.296225f, 0.393381f, 0.310510f, 0.386858f, 0.314615f,
+ 0.383015f, 0.301864f, 0.389662f, 0.300183f, 0.653658f, 0.279971f, 0.656064f, 0.297636f,
+ 0.649541f, 0.296225f, 0.647785f, 0.283486f, 0.389662f, 0.300183f, 0.383015f, 0.301864f,
+ 0.384904f, 0.283634f, 0.391040f, 0.287071f, 0.632494f, 0.262853f, 0.653658f, 0.279971f,
+ 0.647785f, 0.283486f, 0.629829f, 0.267263f, 0.391040f, 0.287071f, 0.384904f, 0.283634f,
+ 0.406068f, 0.265508f, 0.408893f, 0.269959f, 0.611720f, 0.255725f, 0.632494f, 0.262853f,
+ 0.629829f, 0.267263f, 0.612641f, 0.261560f, 0.408893f, 0.269959f, 0.406068f, 0.265508f,
+ 0.427062f, 0.257728f, 0.426254f, 0.263693f, 0.580734f, 0.266620f, 0.611720f, 0.255725f,
+ 0.612641f, 0.261560f, 0.585166f, 0.270991f, 0.426254f, 0.263693f, 0.427062f, 0.257728f,
+ 0.458737f, 0.268049f, 0.454369f, 0.272583f, 0.571787f, 0.277295f, 0.580734f, 0.266620f,
+ 0.585166f, 0.270991f, 0.578124f, 0.281900f, 0.454369f, 0.272583f, 0.458737f, 0.268049f,
+ 0.468070f, 0.278617f, 0.461798f, 0.283441f, 0.584855f, 0.327708f, 0.573085f, 0.311386f,
+ 0.579548f, 0.309340f, 0.590644f, 0.321516f, 0.461204f, 0.311233f, 0.467790f, 0.313081f,
+ 0.456477f, 0.329961f, 0.450408f, 0.323919f, 0.573085f, 0.311386f, 0.568351f, 0.292904f,
+ 0.577524f, 0.293776f, 0.579548f, 0.309340f, 0.462754f, 0.295432f, 0.471978f, 0.294282f,
+ 0.467790f, 0.313081f, 0.461204f, 0.311233f, 0.568351f, 0.292904f, 0.571787f, 0.277295f,
+ 0.578124f, 0.281900f, 0.577524f, 0.293776f, 0.461798f, 0.283441f, 0.468070f, 0.278617f,
+ 0.471978f, 0.294282f, 0.462754f, 0.295432f, 0.521923f, 0.386009f, 0.553095f, 0.390512f,
+ 0.553209f, 0.433063f, 0.523031f, 0.433628f, 0.492809f, 0.434538f, 0.490934f, 0.391862f,
+ 0.521923f, 0.386009f, 0.523031f, 0.433628f, 0.553095f, 0.390512f, 0.604826f, 0.397804f,
+ 0.609819f, 0.431516f, 0.553209f, 0.433063f, 0.435860f, 0.435740f, 0.439252f, 0.401540f,
+ 0.490934f, 0.391862f, 0.492809f, 0.434538f, 0.604826f, 0.397804f, 0.626842f, 0.395792f,
+ 0.648174f, 0.419316f, 0.609819f, 0.431516f, 0.396518f, 0.425416f, 0.416915f, 0.400552f,
+ 0.439252f, 0.401540f, 0.435860f, 0.435740f, 0.626842f, 0.395792f, 0.662817f, 0.372521f,
+ 0.692106f, 0.388274f, 0.648174f, 0.419316f, 0.350292f, 0.396229f, 0.379297f, 0.378686f,
+ 0.416915f, 0.400552f, 0.396518f, 0.425416f, 0.662817f, 0.372521f, 0.697446f, 0.332673f,
+ 0.726332f, 0.341754f, 0.692106f, 0.388274f, 0.312756f, 0.350588f, 0.341964f, 0.339667f,
+ 0.379297f, 0.378686f, 0.350292f, 0.396229f, 0.697446f, 0.332673f, 0.707254f, 0.310054f,
+ 0.735879f, 0.312112f, 0.726332f, 0.341754f, 0.301067f, 0.320593f, 0.330721f, 0.316853f,
+ 0.341964f, 0.339667f, 0.312756f, 0.350588f, 0.707254f, 0.310054f, 0.715342f, 0.265392f,
+ 0.729900f, 0.256393f, 0.735879f, 0.312112f, 0.304876f, 0.261087f, 0.320452f, 0.270303f,
+ 0.330721f, 0.316853f, 0.301067f, 0.320593f, 0.715342f, 0.265392f, 0.676379f, 0.233241f,
+ 0.698172f, 0.216906f, 0.729900f, 0.256393f, 0.337414f, 0.219179f, 0.360308f, 0.235899f,
+ 0.320452f, 0.270303f, 0.304876f, 0.261087f, 0.676379f, 0.233241f, 0.647395f, 0.200502f,
+ 0.663103f, 0.190671f, 0.698172f, 0.216906f, 0.373474f, 0.191872f, 0.389677f, 0.201890f,
+ 0.360308f, 0.235899f, 0.337414f, 0.219179f, 0.626908f, 0.015608f, 0.649444f, 0.022378f,
+ 0.660451f, 0.076084f, 0.621440f, 0.048089f, 0.376796f, 0.075296f, 0.388827f, 0.021586f,
+ 0.411318f, 0.015131f, 0.416419f, 0.047631f, 0.567460f, 0.000144f, 0.626908f, 0.015608f,
+ 0.621440f, 0.048089f, 0.577206f, 0.032801f, 0.416419f, 0.047631f, 0.411318f, 0.015131f,
+ 0.470636f, 0.000144f, 0.460782f, 0.032656f, 0.518922f, 0.024886f, 0.567460f, 0.000144f,
+ 0.577206f, 0.032801f, 0.547413f, 0.041724f, 0.460782f, 0.032656f, 0.470636f, 0.000144f,
+ 0.518922f, 0.024886f, 0.490511f, 0.041669f, 0.540260f, 0.053805f, 0.518916f, 0.050294f,
+ 0.518922f, 0.024886f, 0.547413f, 0.041724f, 0.518922f, 0.024886f, 0.518916f, 0.050294f,
+ 0.497626f, 0.053770f, 0.490511f, 0.041669f, 0.551930f, 0.058338f, 0.540260f, 0.053805f,
+ 0.547413f, 0.041724f, 0.558059f, 0.053871f, 0.490511f, 0.041669f, 0.497626f, 0.053770f,
+ 0.485955f, 0.058273f, 0.479842f, 0.053785f, 0.555073f, 0.061900f, 0.551930f, 0.058338f,
+ 0.558059f, 0.053871f, 0.576951f, 0.057998f, 0.479842f, 0.053785f, 0.485955f, 0.058273f,
+ 0.482805f, 0.061829f, 0.460920f, 0.057845f, 0.563812f, 0.076586f, 0.555073f, 0.061900f,
+ 0.576951f, 0.057998f, 0.611687f, 0.078268f, 0.460920f, 0.057845f, 0.482805f, 0.061829f,
+ 0.474014f, 0.076511f, 0.425932f, 0.077985f, 0.576951f, 0.057998f, 0.577206f, 0.032801f,
+ 0.621440f, 0.048089f, 0.611687f, 0.078268f, 0.416419f, 0.047631f, 0.460782f, 0.032656f,
+ 0.460920f, 0.057845f, 0.425932f, 0.077985f, 0.576951f, 0.057998f, 0.558059f, 0.053871f,
+ 0.547413f, 0.041724f, 0.577206f, 0.032801f, 0.490511f, 0.041669f, 0.479842f, 0.053785f,
+ 0.460920f, 0.057845f, 0.460782f, 0.032656f, 0.626663f, 0.111357f, 0.611687f, 0.078268f,
+ 0.621440f, 0.048089f, 0.660451f, 0.076084f, 0.416419f, 0.047631f, 0.425932f, 0.077985f,
+ 0.410618f, 0.111244f, 0.376796f, 0.075296f, 0.583135f, 0.108495f, 0.563812f, 0.076586f,
+ 0.611687f, 0.078268f, 0.626663f, 0.111357f, 0.425932f, 0.077985f, 0.474014f, 0.076511f,
+ 0.454527f, 0.108481f, 0.410618f, 0.111244f, 0.596138f, 0.133426f, 0.629482f, 0.130456f,
+ 0.623495f, 0.146796f, 0.601169f, 0.147885f, 0.413741f, 0.147158f, 0.407648f, 0.130594f,
+ 0.441395f, 0.133592f, 0.436337f, 0.148194f, 0.583135f, 0.108495f, 0.626663f, 0.111357f,
+ 0.629482f, 0.130456f, 0.596138f, 0.133426f, 0.407648f, 0.130594f, 0.410618f, 0.111244f,
+ 0.454527f, 0.108481f, 0.441395f, 0.133592f, 0.605512f, 0.165134f, 0.601169f, 0.147885f,
+ 0.623495f, 0.146796f, 0.619303f, 0.159841f, 0.413741f, 0.147158f, 0.436337f, 0.148194f,
+ 0.432024f, 0.165644f, 0.418035f, 0.160361f, 0.605512f, 0.165134f, 0.619303f, 0.159841f,
+ 0.663103f, 0.190671f, 0.647395f, 0.200502f, 0.373474f, 0.191872f, 0.418035f, 0.160361f,
+ 0.432024f, 0.165644f, 0.389677f, 0.201890f, 0.945900f, 0.079569f, 0.886245f, 0.121777f,
+ 0.849114f, 0.099732f, 0.891780f, 0.036916f, 0.183115f, 0.092127f, 0.141314f, 0.112482f,
+ 0.078961f, 0.060719f, 0.142277f, 0.021467f, 0.891780f, 0.036916f, 0.849114f, 0.099732f,
+ 0.788458f, 0.080826f, 0.805584f, 0.010786f, 0.246353f, 0.076510f, 0.183115f, 0.092127f,
+ 0.142277f, 0.021467f, 0.232648f, 0.003484f, 0.805584f, 0.010786f, 0.788458f, 0.080826f,
+ 0.687018f, 0.077204f, 0.672384f, 0.022201f, 0.349875f, 0.075955f, 0.246353f, 0.076510f,
+ 0.232648f, 0.003484f, 0.365979f, 0.020991f, 0.672384f, 0.022201f, 0.687018f, 0.077204f,
+ 0.660451f, 0.076084f, 0.649444f, 0.022378f, 0.376796f, 0.075296f, 0.349875f, 0.075955f,
+ 0.365979f, 0.020991f, 0.388827f, 0.021586f, 0.626663f, 0.111357f, 0.660451f, 0.076084f,
+ 0.687018f, 0.077204f, 0.629482f, 0.130456f, 0.349875f, 0.075955f, 0.376796f, 0.075296f,
+ 0.410618f, 0.111244f, 0.407648f, 0.130594f, 0.729900f, 0.256393f, 0.698172f, 0.216906f,
+ 0.760215f, 0.193244f, 0.789046f, 0.233323f, 0.271553f, 0.193871f, 0.337414f, 0.219179f,
+ 0.304876f, 0.261087f, 0.241255f, 0.236977f, 0.994525f, 0.167705f, 0.909112f, 0.183261f,
+ 0.886245f, 0.121777f, 0.945900f, 0.079569f, 0.141314f, 0.112482f, 0.107928f, 0.179083f,
+ 0.011829f, 0.155367f, 0.078961f, 0.060719f, 0.911671f, 0.402429f, 0.862868f, 0.338556f,
+ 0.894128f, 0.301884f, 0.962901f, 0.344752f, 0.123776f, 0.315519f, 0.160557f, 0.356821f,
+ 0.106400f, 0.432652f, 0.043968f, 0.367038f, 0.962901f, 0.344752f, 0.894128f, 0.301884f,
+ 0.915360f, 0.259804f, 0.999856f, 0.254640f, 0.098965f, 0.266968f, 0.123776f, 0.315519f,
+ 0.043968f, 0.367038f, 0.000144f, 0.259113f, 0.999856f, 0.254640f, 0.915360f, 0.259804f,
+ 0.909112f, 0.183261f, 0.994525f, 0.167705f, 0.107928f, 0.179083f, 0.098965f, 0.266968f,
+ 0.000144f, 0.259113f, 0.011829f, 0.155367f, 0.749542f, 0.334683f, 0.735879f, 0.312112f,
+ 0.766337f, 0.300809f, 0.789162f, 0.313727f, 0.267408f, 0.310142f, 0.301067f, 0.320593f,
+ 0.288183f, 0.346496f, 0.242992f, 0.325552f, 0.789162f, 0.313727f, 0.766337f, 0.300809f,
+ 0.815314f, 0.276388f, 0.846174f, 0.293397f, 0.213065f, 0.285164f, 0.267408f, 0.310142f,
+ 0.242992f, 0.325552f, 0.178537f, 0.304983f, 0.846174f, 0.293397f, 0.815314f, 0.276388f,
+ 0.845007f, 0.256352f, 0.873517f, 0.265922f, 0.179662f, 0.263312f, 0.213065f, 0.285164f,
+ 0.178537f, 0.304983f, 0.147089f, 0.274284f, 0.873517f, 0.265922f, 0.845007f, 0.256352f,
+ 0.859075f, 0.228168f, 0.886999f, 0.233769f, 0.162803f, 0.231720f, 0.179662f, 0.263312f,
+ 0.147089f, 0.274284f, 0.131514f, 0.237587f, 0.842355f, 0.195160f, 0.875030f, 0.184705f,
+ 0.886999f, 0.233769f, 0.859075f, 0.228168f, 0.131514f, 0.237587f, 0.145224f, 0.182749f,
+ 0.176788f, 0.196179f, 0.162803f, 0.231720f, 0.909112f, 0.183261f, 0.915360f, 0.259804f,
+ 0.886999f, 0.233769f, 0.875030f, 0.184705f, 0.131514f, 0.237587f, 0.098965f, 0.266968f,
+ 0.107928f, 0.179083f, 0.145224f, 0.182749f, 0.915360f, 0.259804f, 0.894128f, 0.301884f,
+ 0.873517f, 0.265922f, 0.886999f, 0.233769f, 0.147089f, 0.274284f, 0.123776f, 0.315519f,
+ 0.098965f, 0.266968f, 0.131514f, 0.237587f, 0.894128f, 0.301884f, 0.862868f, 0.338556f,
+ 0.846174f, 0.293397f, 0.873517f, 0.265922f, 0.178537f, 0.304983f, 0.160557f, 0.356821f,
+ 0.123776f, 0.315519f, 0.147089f, 0.274284f, 0.862868f, 0.338556f, 0.794286f, 0.364062f,
+ 0.789162f, 0.313727f, 0.846174f, 0.293397f, 0.242992f, 0.325552f, 0.239776f, 0.382592f,
+ 0.160557f, 0.356821f, 0.178537f, 0.304983f, 0.770185f, 0.379538f, 0.749542f, 0.334683f,
+ 0.789162f, 0.313727f, 0.794286f, 0.364062f, 0.242992f, 0.325552f, 0.288183f, 0.346496f,
+ 0.268122f, 0.398737f, 0.239776f, 0.382592f, 0.845499f, 0.449967f, 0.794286f, 0.364062f,
+ 0.862868f, 0.338556f, 0.911671f, 0.402429f, 0.160557f, 0.356821f, 0.239776f, 0.382592f,
+ 0.185281f, 0.484099f, 0.106400f, 0.432652f, 0.815858f, 0.445381f, 0.770572f, 0.444261f,
+ 0.755700f, 0.418603f, 0.770185f, 0.379538f, 0.287033f, 0.442912f, 0.271364f, 0.473316f,
+ 0.219260f, 0.477186f, 0.268122f, 0.398737f, 0.815858f, 0.445381f, 0.770185f, 0.379538f,
+ 0.794286f, 0.364062f, 0.845499f, 0.449967f, 0.239776f, 0.382592f, 0.268122f, 0.398737f,
+ 0.219260f, 0.477186f, 0.185281f, 0.484099f, 0.819845f, 0.468071f, 0.815858f, 0.445381f,
+ 0.845499f, 0.449967f, 0.185281f, 0.484099f, 0.219260f, 0.477186f, 0.215894f, 0.503605f,
+ 0.735879f, 0.312112f, 0.729900f, 0.256393f, 0.789046f, 0.233323f, 0.766337f, 0.300809f,
+ 0.241255f, 0.236977f, 0.304876f, 0.261087f, 0.301067f, 0.320593f, 0.267408f, 0.310142f,
+ 0.789046f, 0.233323f, 0.809631f, 0.233887f, 0.815314f, 0.276388f, 0.766337f, 0.300809f,
+ 0.213065f, 0.285164f, 0.219168f, 0.237388f, 0.241255f, 0.236977f, 0.267408f, 0.310142f,
+ 0.809631f, 0.233887f, 0.829287f, 0.219562f, 0.845007f, 0.256352f, 0.815314f, 0.276388f,
+ 0.179662f, 0.263312f, 0.199067f, 0.222464f, 0.219168f, 0.237388f, 0.213065f, 0.285164f,
+ 0.842355f, 0.195160f, 0.859075f, 0.228168f, 0.845007f, 0.256352f, 0.829287f, 0.219562f,
+ 0.179662f, 0.263312f, 0.162803f, 0.231720f, 0.176788f, 0.196179f, 0.199067f, 0.222464f,
+ 0.687018f, 0.077204f, 0.788458f, 0.080826f, 0.786480f, 0.117591f, 0.715482f, 0.139727f,
+ 0.246666f, 0.114850f, 0.246353f, 0.076510f, 0.349875f, 0.075955f, 0.319538f, 0.139409f,
+ 0.760215f, 0.193244f, 0.715482f, 0.139727f, 0.786480f, 0.117591f, 0.785486f, 0.152330f,
+ 0.246666f, 0.114850f, 0.319538f, 0.139409f, 0.271553f, 0.193871f, 0.245969f, 0.151002f,
+ 0.698172f, 0.216906f, 0.663103f, 0.190671f, 0.715482f, 0.139727f, 0.760215f, 0.193244f,
+ 0.319538f, 0.139409f, 0.373474f, 0.191872f, 0.337414f, 0.219179f, 0.271553f, 0.193871f,
+ 0.663103f, 0.190671f, 0.623495f, 0.146796f, 0.629482f, 0.130456f, 0.715482f, 0.139727f,
+ 0.407648f, 0.130594f, 0.413741f, 0.147158f, 0.373474f, 0.191872f, 0.319538f, 0.139409f,
+ 0.629482f, 0.130456f, 0.687018f, 0.077204f, 0.715482f, 0.139727f, 0.319538f, 0.139409f,
+ 0.349875f, 0.075955f, 0.407648f, 0.130594f, 0.663103f, 0.190671f, 0.619303f, 0.159841f,
+ 0.623495f, 0.146796f, 0.413741f, 0.147158f, 0.418035f, 0.160361f, 0.373474f, 0.191872f,
+ 0.842355f, 0.195160f, 0.837382f, 0.156361f, 0.858171f, 0.137775f, 0.875030f, 0.184705f,
+ 0.171653f, 0.132294f, 0.196622f, 0.155241f, 0.176788f, 0.196179f, 0.145224f, 0.182749f,
+ 0.909112f, 0.183261f, 0.875030f, 0.184705f, 0.858171f, 0.137775f, 0.886245f, 0.121777f,
+ 0.171653f, 0.132294f, 0.145224f, 0.182749f, 0.107928f, 0.179083f, 0.141314f, 0.112482f,
+ 0.785486f, 0.152330f, 0.786480f, 0.117591f, 0.858171f, 0.137775f, 0.837382f, 0.156361f,
+ 0.171653f, 0.132294f, 0.246666f, 0.114850f, 0.245969f, 0.151002f, 0.196622f, 0.155241f,
+ 0.788458f, 0.080826f, 0.849114f, 0.099732f, 0.858171f, 0.137775f, 0.786480f, 0.117591f,
+ 0.171653f, 0.132294f, 0.183115f, 0.092127f, 0.246353f, 0.076510f, 0.246666f, 0.114850f,
+ 0.886245f, 0.121777f, 0.858171f, 0.137775f, 0.849114f, 0.099732f, 0.183115f, 0.092127f,
+ 0.171653f, 0.132294f, 0.141314f, 0.112482f, 0.506166f, 0.904851f, 0.432388f, 0.894943f,
+ 0.438797f, 0.870229f, 0.491058f, 0.881714f, 0.315867f, 0.868209f, 0.321637f, 0.893225f,
+ 0.247207f, 0.901159f, 0.263032f, 0.878321f, 0.506166f, 0.904851f, 0.491058f, 0.881714f,
+ 0.572792f, 0.860484f, 0.604825f, 0.879946f, 0.181486f, 0.854693f, 0.263032f, 0.878321f,
+ 0.247207f, 0.901159f, 0.148729f, 0.873349f, 0.604825f, 0.879946f, 0.572792f, 0.860484f,
+ 0.586396f, 0.793977f, 0.619962f, 0.791615f, 0.169745f, 0.787474f, 0.181486f, 0.854693f,
+ 0.148729f, 0.873349f, 0.136063f, 0.784093f, 0.619962f, 0.791615f, 0.586396f, 0.793977f,
+ 0.549027f, 0.746412f, 0.563786f, 0.739211f, 0.208656f, 0.740879f, 0.169745f, 0.787474f,
+ 0.136063f, 0.784093f, 0.194086f, 0.733241f, 0.563786f, 0.739211f, 0.549027f, 0.746412f,
+ 0.500314f, 0.711729f, 0.508270f, 0.697693f, 0.258399f, 0.707497f, 0.208656f, 0.740879f,
+ 0.194086f, 0.733241f, 0.250811f, 0.693249f, 0.508270f, 0.697693f, 0.500314f, 0.711729f,
+ 0.438641f, 0.680683f, 0.434803f, 0.658882f, 0.320962f, 0.677959f, 0.258399f, 0.707497f,
+ 0.250811f, 0.693249f, 0.325318f, 0.656224f, 0.500314f, 0.711729f, 0.505666f, 0.730944f,
+ 0.452955f, 0.700023f, 0.438641f, 0.680683f, 0.306136f, 0.696976f, 0.252524f, 0.726592f,
+ 0.258399f, 0.707497f, 0.320962f, 0.677959f, 0.549027f, 0.746412f, 0.542850f, 0.755753f,
+ 0.505666f, 0.730944f, 0.500314f, 0.711729f, 0.252524f, 0.726592f, 0.214575f, 0.750414f,
+ 0.208656f, 0.740879f, 0.258399f, 0.707497f, 0.586396f, 0.793977f, 0.568148f, 0.787367f,
+ 0.542850f, 0.755753f, 0.549027f, 0.746412f, 0.214575f, 0.750414f, 0.188269f, 0.781375f,
+ 0.169745f, 0.787474f, 0.208656f, 0.740879f, 0.572792f, 0.860484f, 0.555495f, 0.826352f,
+ 0.568148f, 0.787367f, 0.586396f, 0.793977f, 0.188269f, 0.781375f, 0.199850f, 0.820889f,
+ 0.181486f, 0.854693f, 0.169745f, 0.787474f, 0.491058f, 0.881714f, 0.501231f, 0.844356f,
+ 0.555495f, 0.826352f, 0.572792f, 0.860484f, 0.199850f, 0.820889f, 0.253846f, 0.840502f,
+ 0.263032f, 0.878321f, 0.181486f, 0.854693f, 0.491058f, 0.881714f, 0.438797f, 0.870229f,
+ 0.457832f, 0.840040f, 0.501231f, 0.844356f, 0.297562f, 0.837358f, 0.315867f, 0.868209f,
+ 0.263032f, 0.878321f, 0.253846f, 0.840502f, 0.760215f, 0.193244f, 0.785486f, 0.152330f,
+ 0.796021f, 0.176969f, 0.783193f, 0.187449f, 0.233625f, 0.175620f, 0.245969f, 0.151002f,
+ 0.271553f, 0.193871f, 0.246955f, 0.187075f, 0.391039f, 0.611891f, 0.434803f, 0.658882f,
+ 0.438641f, 0.680683f, 0.394766f, 0.686125f, 0.320962f, 0.677959f, 0.325318f, 0.656224f,
+ 0.369913f, 0.610196f, 0.364838f, 0.684445f, 0.789046f, 0.233323f, 0.760215f, 0.193244f,
+ 0.783193f, 0.187449f, 0.809631f, 0.233887f, 0.246955f, 0.187075f, 0.271553f, 0.193871f,
+ 0.241255f, 0.236977f, 0.219168f, 0.237388f, 0.391747f, 0.862097f, 0.401605f, 0.841460f,
+ 0.438797f, 0.870229f, 0.432388f, 0.894943f, 0.315867f, 0.868209f, 0.354026f, 0.840297f,
+ 0.363377f, 0.861308f, 0.321637f, 0.893225f, 0.438641f, 0.680683f, 0.452955f, 0.700023f,
+ 0.435018f, 0.718280f, 0.394766f, 0.686125f, 0.323658f, 0.715731f, 0.306136f, 0.696976f,
+ 0.320962f, 0.677959f, 0.364838f, 0.684445f, 0.433669f, 0.729661f, 0.384658f, 0.710299f,
+ 0.394766f, 0.686125f, 0.435018f, 0.718280f, 0.364838f, 0.684445f, 0.374400f, 0.708969f,
+ 0.324726f, 0.727177f, 0.323658f, 0.715731f, 0.410995f, 0.747662f, 0.384658f, 0.710299f,
+ 0.433669f, 0.729661f, 0.427812f, 0.742828f, 0.324726f, 0.727177f, 0.374400f, 0.708969f,
+ 0.347028f, 0.745816f, 0.330270f, 0.740536f, 0.418086f, 0.784946f, 0.384657f, 0.795423f,
+ 0.384658f, 0.710299f, 0.410995f, 0.747662f, 0.374400f, 0.708969f, 0.372270f, 0.794472f,
+ 0.338952f, 0.783073f, 0.347028f, 0.745816f, 0.401605f, 0.841460f, 0.384657f, 0.795423f,
+ 0.418086f, 0.784946f, 0.431333f, 0.817535f, 0.338952f, 0.783073f, 0.372270f, 0.794472f,
+ 0.354026f, 0.840297f, 0.324790f, 0.815460f, 0.438797f, 0.870229f, 0.401605f, 0.841460f,
+ 0.431333f, 0.817535f, 0.457832f, 0.840040f, 0.324790f, 0.815460f, 0.354026f, 0.840297f,
+ 0.315867f, 0.868209f, 0.297562f, 0.837358f, 0.809631f, 0.233887f, 0.816266f, 0.203086f,
+ 0.825107f, 0.209762f, 0.829287f, 0.219562f, 0.199767f, 0.214827f, 0.209828f, 0.206161f,
+ 0.219168f, 0.237388f, 0.199067f, 0.222464f, 0.809631f, 0.233887f, 0.783193f, 0.187449f,
+ 0.802192f, 0.184609f, 0.816266f, 0.203086f, 0.226485f, 0.183086f, 0.246955f, 0.187075f,
+ 0.219168f, 0.237388f, 0.209828f, 0.206161f, 0.783193f, 0.187449f, 0.796021f, 0.176969f,
+ 0.802192f, 0.184609f, 0.226485f, 0.183086f, 0.233625f, 0.175620f, 0.246955f, 0.187075f,
+ 0.457832f, 0.840040f, 0.431333f, 0.817535f, 0.448505f, 0.804621f, 0.473386f, 0.824700f,
+ 0.307886f, 0.802031f, 0.324790f, 0.815460f, 0.297562f, 0.837358f, 0.282357f, 0.821525f,
+ 0.431333f, 0.817535f, 0.418086f, 0.784946f, 0.435868f, 0.779569f, 0.448505f, 0.804621f,
+ 0.321237f, 0.777208f, 0.338952f, 0.783073f, 0.324790f, 0.815460f, 0.307886f, 0.802031f,
+ 0.418086f, 0.784946f, 0.410995f, 0.747662f, 0.423718f, 0.754191f, 0.435868f, 0.779569f,
+ 0.334089f, 0.752045f, 0.347028f, 0.745816f, 0.338952f, 0.783073f, 0.321237f, 0.777208f,
+ 0.410995f, 0.747662f, 0.427812f, 0.742828f, 0.437950f, 0.749777f, 0.423718f, 0.754191f,
+ 0.319919f, 0.747250f, 0.330270f, 0.740536f, 0.347028f, 0.745816f, 0.334089f, 0.752045f,
+ 0.427812f, 0.742828f, 0.433669f, 0.729661f, 0.445392f, 0.731997f, 0.437950f, 0.749777f,
+ 0.312907f, 0.729222f, 0.324726f, 0.727177f, 0.330270f, 0.740536f, 0.319919f, 0.747250f,
+ 0.433669f, 0.729661f, 0.435018f, 0.718280f, 0.440995f, 0.724383f, 0.445392f, 0.731997f,
+ 0.317510f, 0.721697f, 0.323658f, 0.715731f, 0.324726f, 0.727177f, 0.312907f, 0.729222f,
+ 0.435018f, 0.718280f, 0.452955f, 0.700023f, 0.455277f, 0.713731f, 0.440995f, 0.724383f,
+ 0.303460f, 0.710657f, 0.306136f, 0.696976f, 0.323658f, 0.715731f, 0.317510f, 0.721697f,
+ 0.501231f, 0.844356f, 0.457832f, 0.840040f, 0.473386f, 0.824700f, 0.512485f, 0.828811f,
+ 0.282357f, 0.821525f, 0.297562f, 0.837358f, 0.253846f, 0.840502f, 0.242975f, 0.824574f,
+ 0.555495f, 0.826352f, 0.501231f, 0.844356f, 0.512485f, 0.828811f, 0.550942f, 0.811814f,
+ 0.242975f, 0.824574f, 0.253846f, 0.840502f, 0.199850f, 0.820889f, 0.204839f, 0.806417f,
+ 0.568148f, 0.787367f, 0.555495f, 0.826352f, 0.550942f, 0.811814f, 0.552139f, 0.787682f,
+ 0.204839f, 0.806417f, 0.199850f, 0.820889f, 0.188269f, 0.781375f, 0.204331f, 0.782156f,
+ 0.542850f, 0.755753f, 0.568148f, 0.787367f, 0.552139f, 0.787682f, 0.539407f, 0.764539f,
+ 0.204331f, 0.782156f, 0.188269f, 0.781375f, 0.214575f, 0.750414f, 0.217774f, 0.759319f,
+ 0.505666f, 0.730944f, 0.542850f, 0.755753f, 0.539407f, 0.764539f, 0.508439f, 0.743135f,
+ 0.217774f, 0.759319f, 0.214575f, 0.750414f, 0.252524f, 0.726592f, 0.249419f, 0.738732f,
+ 0.452955f, 0.700023f, 0.505666f, 0.730944f, 0.508439f, 0.743135f, 0.455277f, 0.713731f,
+ 0.249419f, 0.738732f, 0.252524f, 0.726592f, 0.306136f, 0.696976f, 0.303460f, 0.710657f,
+ 0.437950f, 0.749777f, 0.445392f, 0.731997f, 0.470841f, 0.748408f, 0.454776f, 0.761665f,
+ 0.286960f, 0.745020f, 0.312907f, 0.729222f, 0.319919f, 0.747250f, 0.302729f, 0.758742f,
+ 0.454776f, 0.761665f, 0.470841f, 0.748408f, 0.488870f, 0.770464f, 0.475403f, 0.783904f,
+ 0.268291f, 0.766661f, 0.286960f, 0.745020f, 0.302729f, 0.758742f, 0.281439f, 0.780511f,
+ 0.475403f, 0.783904f, 0.488870f, 0.770464f, 0.503673f, 0.787562f, 0.494476f, 0.802470f,
+ 0.252972f, 0.783410f, 0.268291f, 0.766661f, 0.281439f, 0.780511f, 0.261790f, 0.798626f,
+ 0.494476f, 0.802470f, 0.503673f, 0.787562f, 0.518562f, 0.791602f, 0.516802f, 0.807339f,
+ 0.237920f, 0.787045f, 0.252972f, 0.783410f, 0.261790f, 0.798626f, 0.239243f, 0.802891f,
+ 0.512485f, 0.828811f, 0.473386f, 0.824700f, 0.494476f, 0.802470f, 0.516802f, 0.807339f,
+ 0.261790f, 0.798626f, 0.282357f, 0.821525f, 0.242975f, 0.824574f, 0.239243f, 0.802891f,
+ 0.448505f, 0.804621f, 0.475403f, 0.783904f, 0.494476f, 0.802470f, 0.473386f, 0.824700f,
+ 0.261790f, 0.798626f, 0.281439f, 0.780511f, 0.307886f, 0.802031f, 0.282357f, 0.821525f,
+ 0.448505f, 0.804621f, 0.435868f, 0.779569f, 0.454776f, 0.761665f, 0.475403f, 0.783904f,
+ 0.302729f, 0.758742f, 0.321237f, 0.777208f, 0.307886f, 0.802031f, 0.281439f, 0.780511f,
+ 0.437950f, 0.749777f, 0.454776f, 0.761665f, 0.435868f, 0.779569f, 0.423718f, 0.754191f,
+ 0.321237f, 0.777208f, 0.302729f, 0.758742f, 0.319919f, 0.747250f, 0.334089f, 0.752045f,
+ 0.440995f, 0.724383f, 0.455277f, 0.713731f, 0.470841f, 0.748408f, 0.445392f, 0.731997f,
+ 0.286960f, 0.745020f, 0.303460f, 0.710657f, 0.317510f, 0.721697f, 0.312907f, 0.729222f,
+ 0.508439f, 0.743135f, 0.488870f, 0.770464f, 0.470841f, 0.748408f, 0.455277f, 0.713731f,
+ 0.286960f, 0.745020f, 0.268291f, 0.766661f, 0.249419f, 0.738732f, 0.303460f, 0.710657f,
+ 0.539407f, 0.764539f, 0.503673f, 0.787562f, 0.488870f, 0.770464f, 0.508439f, 0.743135f,
+ 0.268291f, 0.766661f, 0.252972f, 0.783410f, 0.217774f, 0.759319f, 0.249419f, 0.738732f,
+ 0.552139f, 0.787682f, 0.518562f, 0.791602f, 0.503673f, 0.787562f, 0.539407f, 0.764539f,
+ 0.252972f, 0.783410f, 0.237920f, 0.787045f, 0.204331f, 0.782156f, 0.217774f, 0.759319f,
+ 0.550942f, 0.811814f, 0.516802f, 0.807339f, 0.518562f, 0.791602f, 0.552139f, 0.787682f,
+ 0.237920f, 0.787045f, 0.239243f, 0.802891f, 0.204839f, 0.806417f, 0.204331f, 0.782156f,
+ 0.512485f, 0.828811f, 0.516802f, 0.807339f, 0.550942f, 0.811814f, 0.204839f, 0.806417f,
+ 0.239243f, 0.802891f, 0.242975f, 0.824574f, 0.508270f, 0.697693f, 0.434803f, 0.658882f,
+ 0.484068f, 0.628776f, 0.543385f, 0.683538f, 0.276936f, 0.625067f, 0.325318f, 0.656224f,
+ 0.250811f, 0.693249f, 0.216123f, 0.678120f, 0.563786f, 0.739211f, 0.508270f, 0.697693f,
+ 0.543385f, 0.683538f, 0.581052f, 0.726933f, 0.216123f, 0.678120f, 0.250811f, 0.693249f,
+ 0.194086f, 0.733241f, 0.177176f, 0.720426f, 0.619962f, 0.791615f, 0.563786f, 0.739211f,
+ 0.581052f, 0.726933f, 0.616701f, 0.759965f, 0.177176f, 0.720426f, 0.194086f, 0.733241f,
+ 0.136063f, 0.784093f, 0.140379f, 0.752377f, 0.707492f, 0.759884f, 0.619962f, 0.791615f,
+ 0.616701f, 0.759965f, 0.660647f, 0.741167f, 0.140379f, 0.752377f, 0.136063f, 0.784093f,
+ 0.049526f, 0.748824f, 0.097038f, 0.732052f, 0.745511f, 0.652100f, 0.707492f, 0.759884f,
+ 0.660647f, 0.741167f, 0.677256f, 0.670436f, 0.097038f, 0.732052f, 0.049526f, 0.748824f,
+ 0.019409f, 0.639749f, 0.083564f, 0.662038f, 0.740843f, 0.572428f, 0.745511f, 0.652100f,
+ 0.677256f, 0.670436f, 0.671403f, 0.592656f, 0.083564f, 0.662038f, 0.019409f, 0.639749f,
+ 0.033664f, 0.564403f, 0.092820f, 0.589862f, 0.677256f, 0.670436f, 0.543385f, 0.683538f,
+ 0.484068f, 0.628776f, 0.671403f, 0.592656f, 0.276936f, 0.625067f, 0.216123f, 0.678120f,
+ 0.083564f, 0.662038f, 0.092820f, 0.589862f, 0.677256f, 0.670436f, 0.660647f, 0.741167f,
+ 0.581052f, 0.726933f, 0.543385f, 0.683538f, 0.177176f, 0.720426f, 0.097038f, 0.732052f,
+ 0.083564f, 0.662038f, 0.216123f, 0.678120f, 0.660647f, 0.741167f, 0.616701f, 0.759965f,
+ 0.581052f, 0.726933f, 0.177176f, 0.720426f, 0.140379f, 0.752377f, 0.097038f, 0.732052f,
+ 0.842355f, 0.195160f, 0.829287f, 0.219562f, 0.834578f, 0.206879f, 0.834705f, 0.206959f,
+ 0.033664f, 0.564403f, 0.051216f, 0.522659f, 0.145041f, 0.562595f, 0.092820f, 0.589862f,
+ 0.620420f, 0.565675f, 0.671403f, 0.592656f, 0.484068f, 0.628776f, 0.498072f, 0.552315f,
+ 0.276936f, 0.625067f, 0.092820f, 0.589862f, 0.145041f, 0.562595f, 0.264218f, 0.550140f,
+ 0.391039f, 0.611891f, 0.498072f, 0.552315f, 0.484068f, 0.628776f, 0.434803f, 0.658882f,
+ 0.276936f, 0.625067f, 0.264218f, 0.550140f, 0.369913f, 0.610196f, 0.325318f, 0.656224f,
};
-#define VERT_MARK 1
+#define VERT_MARK 1
-#define EDGE_ORIG 1
-#define EDGE_MARK 2
+#define EDGE_ORIG 1
+#define EDGE_MARK 2
-#define FACE_MARK 1
-#define FACE_NEW 2
+#define FACE_MARK 1
+#define FACE_NEW 2
void bmo_create_grid_exec(BMesh *bm, BMOperator *op)
{
- BMOpSlot *slot_verts_out = BMO_slot_get(op->slots_out, "verts.out");
-
- const float dia = BMO_slot_float_get(op->slots_in, "size");
- const uint xtot = max_ii(2, BMO_slot_int_get(op->slots_in, "x_segments"));
- const uint ytot = max_ii(2, BMO_slot_int_get(op->slots_in, "y_segments"));
- const float xtot_inv2 = 2.0f / (xtot - 1);
- const float ytot_inv2 = 2.0f / (ytot - 1);
+ BMOpSlot *slot_verts_out = BMO_slot_get(op->slots_out, "verts.out");
- const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
- const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs");
+ const float dia = BMO_slot_float_get(op->slots_in, "size");
+ const uint xtot = max_ii(2, BMO_slot_int_get(op->slots_in, "x_segments"));
+ const uint ytot = max_ii(2, BMO_slot_int_get(op->slots_in, "y_segments"));
+ const float xtot_inv2 = 2.0f / (xtot - 1);
+ const float ytot_inv2 = 2.0f / (ytot - 1);
- BMVert **varr;
- BMVert *vquad[4];
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+ const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs");
- float mat[4][4];
- float vec[3], tvec[3];
+ BMVert **varr;
+ BMVert *vquad[4];
- uint x, y, i;
+ float mat[4][4];
+ float vec[3], tvec[3];
+ uint x, y, i;
- BMO_slot_mat4_get(op->slots_in, "matrix", mat);
+ BMO_slot_mat4_get(op->slots_in, "matrix", mat);
- BMO_slot_buffer_alloc(op, op->slots_out, "verts.out", xtot * ytot);
- varr = (BMVert **)slot_verts_out->data.buf;
+ BMO_slot_buffer_alloc(op, op->slots_out, "verts.out", xtot * ytot);
+ varr = (BMVert **)slot_verts_out->data.buf;
- i = 0;
- vec[2] = 0.0f;
- for (y = 0; y < ytot; y++) {
- vec[1] = ((y * ytot_inv2) - 1.0f) * dia;
- for (x = 0; x < xtot; x++) {
- vec[0] = ((x * xtot_inv2) - 1.0f) * dia;
- mul_v3_m4v3(tvec, mat, vec);
- varr[i] = BM_vert_create(bm, tvec, NULL, BM_CREATE_NOP);
- BMO_vert_flag_enable(bm, varr[i], VERT_MARK);
- i++;
- }
- }
+ i = 0;
+ vec[2] = 0.0f;
+ for (y = 0; y < ytot; y++) {
+ vec[1] = ((y * ytot_inv2) - 1.0f) * dia;
+ for (x = 0; x < xtot; x++) {
+ vec[0] = ((x * xtot_inv2) - 1.0f) * dia;
+ mul_v3_m4v3(tvec, mat, vec);
+ varr[i] = BM_vert_create(bm, tvec, NULL, BM_CREATE_NOP);
+ BMO_vert_flag_enable(bm, varr[i], VERT_MARK);
+ i++;
+ }
+ }
-#define XY(_x, _y) ((_x) + ((_y) * (xtot)))
+#define XY(_x, _y) ((_x) + ((_y) * (xtot)))
- for (y = 1; y < ytot; y++) {
- for (x = 1; x < xtot; x++) {
- BMFace *f;
+ for (y = 1; y < ytot; y++) {
+ for (x = 1; x < xtot; x++) {
+ BMFace *f;
- vquad[0] = varr[XY(x - 1, y - 1)];
- vquad[1] = varr[XY(x, y - 1)];
- vquad[2] = varr[XY(x, y)];
- vquad[3] = varr[XY(x - 1, y)];
+ vquad[0] = varr[XY(x - 1, y - 1)];
+ vquad[1] = varr[XY(x, y - 1)];
+ vquad[2] = varr[XY(x, y)];
+ vquad[3] = varr[XY(x - 1, y)];
- f = BM_face_create_verts(bm, vquad, 4, NULL, BM_CREATE_NOP, true);
- if (calc_uvs) {
- BMO_face_flag_enable(bm, f, FACE_MARK);
- }
- }
- }
+ f = BM_face_create_verts(bm, vquad, 4, NULL, BM_CREATE_NOP, true);
+ if (calc_uvs) {
+ BMO_face_flag_enable(bm, f, FACE_MARK);
+ }
+ }
+ }
#undef XY
- if (calc_uvs) {
- BM_mesh_calc_uvs_grid(bm, xtot, ytot, FACE_MARK, cd_loop_uv_offset);
- }
+ if (calc_uvs) {
+ BM_mesh_calc_uvs_grid(bm, xtot, ytot, FACE_MARK, cd_loop_uv_offset);
+ }
}
/**
@@ -822,334 +795,343 @@ void bmo_create_grid_exec(BMesh *bm, BMOperator *op)
* \param y_segments: The y-resolution of the grid
* \param oflag: The flag to check faces with.
*/
-void BM_mesh_calc_uvs_grid(
- BMesh *bm, const uint x_segments, const uint y_segments,
- const short oflag, const int cd_loop_uv_offset)
+void BM_mesh_calc_uvs_grid(BMesh *bm,
+ const uint x_segments,
+ const uint y_segments,
+ const short oflag,
+ const int cd_loop_uv_offset)
{
- BMFace *f;
- BMLoop *l;
- BMIter iter, liter;
-
- const float dx = 1.0f / (float)(x_segments - 1);
- const float dy = 1.0f / (float)(y_segments - 1);
- float x = 0.0f;
- float y = dy;
-
- int loop_index;
-
- BLI_assert(cd_loop_uv_offset != -1);
-
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- if (!BMO_face_flag_test(bm, f, oflag)) {
- continue;
- }
-
- BM_ITER_ELEM_INDEX (l, &liter, f, BM_LOOPS_OF_FACE, loop_index) {
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
-
- switch (loop_index) {
- case 0:
- y -= dy;
- break;
- case 1:
- x += dx;
- break;
- case 2:
- y += dy;
- break;
- case 3:
- x -= dx;
- break;
- default:
- break;
- }
-
- luv->uv[0] = x;
- luv->uv[1] = y;
- }
-
- x += dx;
- if (x >= 1.0f) {
- x = 0.0f;
- y += dy;
- }
- }
+ BMFace *f;
+ BMLoop *l;
+ BMIter iter, liter;
+
+ const float dx = 1.0f / (float)(x_segments - 1);
+ const float dy = 1.0f / (float)(y_segments - 1);
+ float x = 0.0f;
+ float y = dy;
+
+ int loop_index;
+
+ BLI_assert(cd_loop_uv_offset != -1);
+
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if (!BMO_face_flag_test(bm, f, oflag)) {
+ continue;
+ }
+
+ BM_ITER_ELEM_INDEX(l, &liter, f, BM_LOOPS_OF_FACE, loop_index)
+ {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+
+ switch (loop_index) {
+ case 0:
+ y -= dy;
+ break;
+ case 1:
+ x += dx;
+ break;
+ case 2:
+ y += dy;
+ break;
+ case 3:
+ x -= dx;
+ break;
+ default:
+ break;
+ }
+
+ luv->uv[0] = x;
+ luv->uv[1] = y;
+ }
+
+ x += dx;
+ if (x >= 1.0f) {
+ x = 0.0f;
+ y += dy;
+ }
+ }
}
void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op)
{
- const float dia = BMO_slot_float_get(op->slots_in, "diameter");
- const int seg = BMO_slot_int_get(op->slots_in, "u_segments");
- const int tot = BMO_slot_int_get(op->slots_in, "v_segments");
-
- const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
- const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs");
-
- BMOperator bmop, prevop;
- BMVert *eve, *preveve;
- BMEdge *e;
- BMIter iter;
- const float axis[3] = {0, 0, 1};
- float vec[3], mat[4][4], cmat[3][3];
- float phi, phid;
- int a;
-
- BMO_slot_mat4_get(op->slots_in, "matrix", mat);
-
- phid = 2.0f * (float)M_PI / tot;
- /* phi = 0.25f * (float)M_PI; */ /* UNUSED */
-
- /* one segment first */
- phi = 0;
- phid /= 2;
- for (a = 0; a <= tot; a++) {
- /* Going in this direction, then edge extruding, makes normals face outward */
- vec[0] = 0.0;
- vec[1] = dia * sinf(phi);
- vec[2] = dia * cosf(phi);
- eve = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
- BMO_vert_flag_enable(bm, eve, VERT_MARK);
-
- if (a != 0) {
- e = BM_edge_create(bm, preveve, eve, NULL, BM_CREATE_NOP);
- BMO_edge_flag_enable(bm, e, EDGE_ORIG);
- }
-
- phi += phid;
- preveve = eve;
- }
-
- /* extrude and rotate; negative phi to make normals face outward */
- axis_angle_to_mat3(cmat, axis, -(M_PI * 2) / seg);
-
- for (a = 0; a < seg; a++) {
- if (a) {
- BMO_op_initf(bm, &bmop, op->flag, "extrude_edge_only edges=%S", &prevop, "geom.out");
- BMO_op_exec(bm, &bmop);
- BMO_op_finish(bm, &prevop);
- }
- else {
- BMO_op_initf(bm, &bmop, op->flag, "extrude_edge_only edges=%fe", EDGE_ORIG);
- BMO_op_exec(bm, &bmop);
- }
-
- BMO_slot_buffer_flag_enable(bm, bmop.slots_out, "geom.out", BM_VERT, VERT_MARK);
- BMO_op_callf(bm, op->flag, "rotate cent=%v matrix=%m3 verts=%S", vec, cmat, &bmop, "geom.out");
-
- prevop = bmop;
- }
-
- if (a) {
- BMO_op_finish(bm, &bmop);
- }
-
- {
- float len, len2, vec2[3];
-
- len = 2 *dia * sinf(phid / 2.0f);
-
- /* length of one segment in shortest parallen */
- vec[0] = dia * sinf(phid);
- vec[1] = 0.0f;
- vec[2] = dia * cosf(phid);
-
- mul_v3_m3v3(vec2, cmat, vec);
- len2 = len_v3v3(vec, vec2);
-
- /* use shortest segment length divided by 3 as merge threshold */
- BMO_op_callf(bm, op->flag, "remove_doubles verts=%fv dist=%f", VERT_MARK, min_ff(len, len2) / 3.0f);
- }
-
- if (calc_uvs) {
- BMFace *f;
- BMLoop *l;
- BMIter fiter, liter;
-
- /* We cannot tag faces for UVs computing above, so we have to do it now, based on all its vertices
- * being tagged. */
- BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
- bool valid = true;
-
- BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- if (!BMO_vert_flag_test(bm, l->v, VERT_MARK)) {
- valid = false;
- break;
- }
- }
-
- if (valid) {
- BMO_face_flag_enable(bm, f, FACE_MARK);
- }
- }
-
- BM_mesh_calc_uvs_sphere(bm, FACE_MARK, cd_loop_uv_offset);
- }
-
- /* and now do imat */
- BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
- if (BMO_vert_flag_test(bm, eve, VERT_MARK)) {
- mul_m4_v3(mat, eve->co);
- }
- }
-
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK);
+ const float dia = BMO_slot_float_get(op->slots_in, "diameter");
+ const int seg = BMO_slot_int_get(op->slots_in, "u_segments");
+ const int tot = BMO_slot_int_get(op->slots_in, "v_segments");
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+ const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs");
+
+ BMOperator bmop, prevop;
+ BMVert *eve, *preveve;
+ BMEdge *e;
+ BMIter iter;
+ const float axis[3] = {0, 0, 1};
+ float vec[3], mat[4][4], cmat[3][3];
+ float phi, phid;
+ int a;
+
+ BMO_slot_mat4_get(op->slots_in, "matrix", mat);
+
+ phid = 2.0f * (float)M_PI / tot;
+ /* phi = 0.25f * (float)M_PI; */ /* UNUSED */
+
+ /* one segment first */
+ phi = 0;
+ phid /= 2;
+ for (a = 0; a <= tot; a++) {
+ /* Going in this direction, then edge extruding, makes normals face outward */
+ vec[0] = 0.0;
+ vec[1] = dia * sinf(phi);
+ vec[2] = dia * cosf(phi);
+ eve = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
+ BMO_vert_flag_enable(bm, eve, VERT_MARK);
+
+ if (a != 0) {
+ e = BM_edge_create(bm, preveve, eve, NULL, BM_CREATE_NOP);
+ BMO_edge_flag_enable(bm, e, EDGE_ORIG);
+ }
+
+ phi += phid;
+ preveve = eve;
+ }
+
+ /* extrude and rotate; negative phi to make normals face outward */
+ axis_angle_to_mat3(cmat, axis, -(M_PI * 2) / seg);
+
+ for (a = 0; a < seg; a++) {
+ if (a) {
+ BMO_op_initf(bm, &bmop, op->flag, "extrude_edge_only edges=%S", &prevop, "geom.out");
+ BMO_op_exec(bm, &bmop);
+ BMO_op_finish(bm, &prevop);
+ }
+ else {
+ BMO_op_initf(bm, &bmop, op->flag, "extrude_edge_only edges=%fe", EDGE_ORIG);
+ BMO_op_exec(bm, &bmop);
+ }
+
+ BMO_slot_buffer_flag_enable(bm, bmop.slots_out, "geom.out", BM_VERT, VERT_MARK);
+ BMO_op_callf(bm, op->flag, "rotate cent=%v matrix=%m3 verts=%S", vec, cmat, &bmop, "geom.out");
+
+ prevop = bmop;
+ }
+
+ if (a) {
+ BMO_op_finish(bm, &bmop);
+ }
+
+ {
+ float len, len2, vec2[3];
+
+ len = 2 * dia * sinf(phid / 2.0f);
+
+ /* length of one segment in shortest parallen */
+ vec[0] = dia * sinf(phid);
+ vec[1] = 0.0f;
+ vec[2] = dia * cosf(phid);
+
+ mul_v3_m3v3(vec2, cmat, vec);
+ len2 = len_v3v3(vec, vec2);
+
+ /* use shortest segment length divided by 3 as merge threshold */
+ BMO_op_callf(
+ bm, op->flag, "remove_doubles verts=%fv dist=%f", VERT_MARK, min_ff(len, len2) / 3.0f);
+ }
+
+ if (calc_uvs) {
+ BMFace *f;
+ BMLoop *l;
+ BMIter fiter, liter;
+
+ /* We cannot tag faces for UVs computing above, so we have to do it now, based on all its vertices
+ * being tagged. */
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ bool valid = true;
+
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ if (!BMO_vert_flag_test(bm, l->v, VERT_MARK)) {
+ valid = false;
+ break;
+ }
+ }
+
+ if (valid) {
+ BMO_face_flag_enable(bm, f, FACE_MARK);
+ }
+ }
+
+ BM_mesh_calc_uvs_sphere(bm, FACE_MARK, cd_loop_uv_offset);
+ }
+
+ /* and now do imat */
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BMO_vert_flag_test(bm, eve, VERT_MARK)) {
+ mul_m4_v3(mat, eve->co);
+ }
+ }
+
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK);
}
void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op)
{
- const float dia = BMO_slot_float_get(op->slots_in, "diameter");
- const float dia_div = dia / 200.0f;
- const int subdiv = BMO_slot_int_get(op->slots_in, "subdivisions");
-
- const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
- const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs");
-
- BMVert *eva[12];
- BMVert *v;
- BMIter liter;
- BMIter viter;
- BMLoop *l;
- float vec[3], mat[4][4] /* , phi, phid */;
- int a;
-
- BMO_slot_mat4_get(op->slots_in, "matrix", mat);
-
- /* phid = 2.0f * (float)M_PI / subdiv; */ /* UNUSED */
- /* phi = 0.25f * (float)M_PI; */ /* UNUSED */
-
-
- for (a = 0; a < 12; a++) {
- vec[0] = dia_div * icovert[a][0];
- vec[1] = dia_div * icovert[a][1];
- vec[2] = dia_div * icovert[a][2];
- eva[a] = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
-
- BMO_vert_flag_enable(bm, eva[a], VERT_MARK);
- }
-
- int uvi = 0;
- for (a = 0; a < 20; a++) {
- BMFace *f;
- BMVert *v1, *v2, *v3;
-
- v1 = eva[icoface[a][0]];
- v2 = eva[icoface[a][1]];
- v3 = eva[icoface[a][2]];
-
- f = BM_face_create_quad_tri(bm, v1, v2, v3, NULL, NULL, BM_CREATE_NOP);
-
- BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- BMO_edge_flag_enable(bm, l->e, EDGE_MARK);
- }
-
- /* Set the UVs here, the iteration order of the faces is not guaranteed,
- * so it's best to set the UVs right after the face is created. */
- if (calc_uvs) {
- int loop_index;
- BM_ITER_ELEM_INDEX (l, &liter, f, BM_LOOPS_OF_FACE, loop_index) {
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- luv->uv[0] = icouvs[uvi][0];
- luv->uv[1] = icouvs[uvi][1];
- uvi++;
- }
- }
- }
-
- if (subdiv > 1) {
- BMOperator bmop;
-
- BMO_op_initf(bm, &bmop, op->flag,
- "subdivide_edges edges=%fe "
- "smooth=%f "
- "cuts=%i "
- "use_grid_fill=%b use_sphere=%b",
- EDGE_MARK, dia, (1 << (subdiv - 1)) - 1,
- true, true);
-
- BMO_op_exec(bm, &bmop);
- BMO_slot_buffer_flag_enable(bm, bmop.slots_out, "geom.out", BM_VERT, VERT_MARK);
- BMO_slot_buffer_flag_enable(bm, bmop.slots_out, "geom.out", BM_EDGE, EDGE_MARK);
- BMO_op_finish(bm, &bmop);
- }
-
-
-
- /* must transform after because of sphere subdivision */
- BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
- if (BMO_vert_flag_test(bm, v, VERT_MARK)) {
- mul_m4_v3(mat, v->co);
- }
- }
-
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK);
+ const float dia = BMO_slot_float_get(op->slots_in, "diameter");
+ const float dia_div = dia / 200.0f;
+ const int subdiv = BMO_slot_int_get(op->slots_in, "subdivisions");
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+ const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs");
+
+ BMVert *eva[12];
+ BMVert *v;
+ BMIter liter;
+ BMIter viter;
+ BMLoop *l;
+ float vec[3], mat[4][4] /* , phi, phid */;
+ int a;
+
+ BMO_slot_mat4_get(op->slots_in, "matrix", mat);
+
+ /* phid = 2.0f * (float)M_PI / subdiv; */ /* UNUSED */
+ /* phi = 0.25f * (float)M_PI; */ /* UNUSED */
+
+ for (a = 0; a < 12; a++) {
+ vec[0] = dia_div * icovert[a][0];
+ vec[1] = dia_div * icovert[a][1];
+ vec[2] = dia_div * icovert[a][2];
+ eva[a] = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
+
+ BMO_vert_flag_enable(bm, eva[a], VERT_MARK);
+ }
+
+ int uvi = 0;
+ for (a = 0; a < 20; a++) {
+ BMFace *f;
+ BMVert *v1, *v2, *v3;
+
+ v1 = eva[icoface[a][0]];
+ v2 = eva[icoface[a][1]];
+ v3 = eva[icoface[a][2]];
+
+ f = BM_face_create_quad_tri(bm, v1, v2, v3, NULL, NULL, BM_CREATE_NOP);
+
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ BMO_edge_flag_enable(bm, l->e, EDGE_MARK);
+ }
+
+ /* Set the UVs here, the iteration order of the faces is not guaranteed,
+ * so it's best to set the UVs right after the face is created. */
+ if (calc_uvs) {
+ int loop_index;
+ BM_ITER_ELEM_INDEX(l, &liter, f, BM_LOOPS_OF_FACE, loop_index)
+ {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ luv->uv[0] = icouvs[uvi][0];
+ luv->uv[1] = icouvs[uvi][1];
+ uvi++;
+ }
+ }
+ }
+
+ if (subdiv > 1) {
+ BMOperator bmop;
+
+ BMO_op_initf(bm,
+ &bmop,
+ op->flag,
+ "subdivide_edges edges=%fe "
+ "smooth=%f "
+ "cuts=%i "
+ "use_grid_fill=%b use_sphere=%b",
+ EDGE_MARK,
+ dia,
+ (1 << (subdiv - 1)) - 1,
+ true,
+ true);
+
+ BMO_op_exec(bm, &bmop);
+ BMO_slot_buffer_flag_enable(bm, bmop.slots_out, "geom.out", BM_VERT, VERT_MARK);
+ BMO_slot_buffer_flag_enable(bm, bmop.slots_out, "geom.out", BM_EDGE, EDGE_MARK);
+ BMO_op_finish(bm, &bmop);
+ }
+
+ /* must transform after because of sphere subdivision */
+ BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
+ if (BMO_vert_flag_test(bm, v, VERT_MARK)) {
+ mul_m4_v3(mat, v->co);
+ }
+ }
+
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK);
}
static void bm_mesh_calc_uvs_sphere_face(BMFace *f, const int cd_loop_uv_offset)
{
- float *uvs[4];
- BMLoop *l;
- BMIter iter;
- float dx;
- int loop_index, loop_index_max_x;
-
- BLI_assert(f->len <= 4);
-
- /* If face has 3 vertices, it's a polar face, in which case we need to
- * compute a nearby to determine its latitude. */
- float avgx = 0.0f, avgy = 0.0f;
- BM_ITER_ELEM_INDEX (l, &iter, f, BM_LOOPS_OF_FACE, loop_index) {
- if (f->len == 3) {
- avgx += l->v->co[0];
- avgy += l->v->co[1];
- }
- }
- avgx /= 3.0f;
- avgy /= 3.0f;
-
- BM_ITER_ELEM_INDEX (l, &iter, f, BM_LOOPS_OF_FACE, loop_index) {
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- float x = l->v->co[0];
- float y = l->v->co[1];
- float z = l->v->co[2];
- float len = len_v3(l->v->co);
-
- /* Use neigboring point to compute angle for poles. */
- float theta;
- if (f->len == 3 && fabsf(x) < 0.0001f && fabsf(y) < 0.0001f) {
- theta = atan2f(avgy, avgx);
- }
- else {
- theta = atan2f(y, x);
- }
-
- /* Shift borderline coordinates to the left. */
- if (fabsf(theta - (float)M_PI) < 0.0001f) {
- theta = -M_PI;
- }
-
- float phi = saacos(z / len);
- luv->uv[0] = 0.5f + theta / ((float)M_PI * 2);
- luv->uv[1] = 1.0f - phi / (float)M_PI;
-
- uvs[loop_index] = luv->uv;
- }
-
- /* Fix awkwardly-wrapping UVs */
- loop_index_max_x = 0;
- for (loop_index = 1; loop_index < f->len; loop_index++) {
- if (uvs[loop_index][0] > uvs[loop_index_max_x][0]) {
- loop_index_max_x = loop_index;
- }
- }
-
- for (loop_index = 0; loop_index < f->len; loop_index++) {
- if (loop_index != loop_index_max_x) {
- dx = uvs[loop_index_max_x][0] - uvs[loop_index][0];
- if (dx > 0.5f) {
- uvs[loop_index][0] += 1.0f;
- }
- }
- }
+ float *uvs[4];
+ BMLoop *l;
+ BMIter iter;
+ float dx;
+ int loop_index, loop_index_max_x;
+
+ BLI_assert(f->len <= 4);
+
+ /* If face has 3 vertices, it's a polar face, in which case we need to
+ * compute a nearby to determine its latitude. */
+ float avgx = 0.0f, avgy = 0.0f;
+ BM_ITER_ELEM_INDEX(l, &iter, f, BM_LOOPS_OF_FACE, loop_index)
+ {
+ if (f->len == 3) {
+ avgx += l->v->co[0];
+ avgy += l->v->co[1];
+ }
+ }
+ avgx /= 3.0f;
+ avgy /= 3.0f;
+
+ BM_ITER_ELEM_INDEX(l, &iter, f, BM_LOOPS_OF_FACE, loop_index)
+ {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ float x = l->v->co[0];
+ float y = l->v->co[1];
+ float z = l->v->co[2];
+ float len = len_v3(l->v->co);
+
+ /* Use neigboring point to compute angle for poles. */
+ float theta;
+ if (f->len == 3 && fabsf(x) < 0.0001f && fabsf(y) < 0.0001f) {
+ theta = atan2f(avgy, avgx);
+ }
+ else {
+ theta = atan2f(y, x);
+ }
+
+ /* Shift borderline coordinates to the left. */
+ if (fabsf(theta - (float)M_PI) < 0.0001f) {
+ theta = -M_PI;
+ }
+
+ float phi = saacos(z / len);
+ luv->uv[0] = 0.5f + theta / ((float)M_PI * 2);
+ luv->uv[1] = 1.0f - phi / (float)M_PI;
+
+ uvs[loop_index] = luv->uv;
+ }
+
+ /* Fix awkwardly-wrapping UVs */
+ loop_index_max_x = 0;
+ for (loop_index = 1; loop_index < f->len; loop_index++) {
+ if (uvs[loop_index][0] > uvs[loop_index_max_x][0]) {
+ loop_index_max_x = loop_index;
+ }
+ }
+
+ for (loop_index = 0; loop_index < f->len; loop_index++) {
+ if (loop_index != loop_index_max_x) {
+ dx = uvs[loop_index_max_x][0] - uvs[loop_index][0];
+ if (dx > 0.5f) {
+ uvs[loop_index][0] += 1.0f;
+ }
+ }
+ }
}
/**
@@ -1158,211 +1140,213 @@ static void bm_mesh_calc_uvs_sphere_face(BMFace *f, const int cd_loop_uv_offset)
* \param bm: The BMesh to operate on
* \param oflag: The flag to check faces with.
*/
-void BM_mesh_calc_uvs_sphere(
- BMesh *bm,
- const short oflag, const int cd_loop_uv_offset)
+void BM_mesh_calc_uvs_sphere(BMesh *bm, const short oflag, const int cd_loop_uv_offset)
{
- BMFace *f;
- BMIter iter;
-
- BLI_assert(cd_loop_uv_offset != -1); /* caller is responsible for giving us UVs */
-
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- if (!BMO_face_flag_test(bm, f, oflag)) {
- continue;
- }
-
- bm_mesh_calc_uvs_sphere_face(f, cd_loop_uv_offset);
- }
-
- BMIter iter2;
- BMLoop *l;
- int loop_index;
- float minx = 1.0f;
-
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- if (!BMO_face_flag_test(bm, f, oflag)) {
- continue;
- }
- BM_ITER_ELEM_INDEX (l, &iter2, f, BM_LOOPS_OF_FACE, loop_index) {
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- if (luv->uv[0] < minx) {
- minx = luv->uv[0];
- }
- }
- }
-
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- if (!BMO_face_flag_test(bm, f, oflag)) {
- continue;
- }
- BM_ITER_ELEM_INDEX (l, &iter2, f, BM_LOOPS_OF_FACE, loop_index) {
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- luv->uv[0] -= minx;
- }
- }
+ BMFace *f;
+ BMIter iter;
+
+ BLI_assert(cd_loop_uv_offset != -1); /* caller is responsible for giving us UVs */
+
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if (!BMO_face_flag_test(bm, f, oflag)) {
+ continue;
+ }
+
+ bm_mesh_calc_uvs_sphere_face(f, cd_loop_uv_offset);
+ }
+
+ BMIter iter2;
+ BMLoop *l;
+ int loop_index;
+ float minx = 1.0f;
+
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if (!BMO_face_flag_test(bm, f, oflag)) {
+ continue;
+ }
+ BM_ITER_ELEM_INDEX(l, &iter2, f, BM_LOOPS_OF_FACE, loop_index)
+ {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ if (luv->uv[0] < minx) {
+ minx = luv->uv[0];
+ }
+ }
+ }
+
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if (!BMO_face_flag_test(bm, f, oflag)) {
+ continue;
+ }
+ BM_ITER_ELEM_INDEX(l, &iter2, f, BM_LOOPS_OF_FACE, loop_index)
+ {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ luv->uv[0] -= minx;
+ }
+ }
}
void bmo_create_monkey_exec(BMesh *bm, BMOperator *op)
{
- BMVert **tv = MEM_mallocN(sizeof(*tv) * monkeynv * 2, "tv");
- float mat[4][4];
- int i;
-
- BMO_slot_mat4_get(op->slots_in, "matrix", mat);
-
- const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
- const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs");
-
- for (i = 0; i < monkeynv; i++) {
- float v[3];
-
- /* rotate to face in the -Y axis */
- v[0] = (monkeyv[i][0] + 127) / 128.0;
- v[2] = monkeyv[i][1] / 128.0;
- v[1] = monkeyv[i][2] / -128.0;
-
- tv[i] = BM_vert_create(bm, v, NULL, BM_CREATE_NOP);
- BMO_vert_flag_enable(bm, tv[i], VERT_MARK);
-
- if (fabsf(v[0] = -v[0]) < 0.001f) {
- tv[monkeynv + i] = tv[i];
- }
- else {
- BMVert *eve = BM_vert_create(bm, v, NULL, BM_CREATE_NOP);
- mul_m4_v3(mat, eve->co);
- tv[monkeynv + i] = eve;
- }
-
- BMO_vert_flag_enable(bm, tv[monkeynv + i], VERT_MARK);
-
- mul_m4_v3(mat, tv[i]->co);
- }
-
- int uvi = 0;
- for (i = 0; i < monkeynf; i++) {
- BMFace *f_new_a = BM_face_create_quad_tri(bm,
- tv[monkeyf[i][0] + i - monkeyo],
- tv[monkeyf[i][1] + i - monkeyo],
- tv[monkeyf[i][2] + i - monkeyo],
- (monkeyf[i][3] != monkeyf[i][2]) ? tv[monkeyf[i][3] + i - monkeyo] : NULL,
- NULL, BM_CREATE_NOP);
-
- BMFace *f_new_b = BM_face_create_quad_tri(bm,
- tv[monkeynv + monkeyf[i][2] + i - monkeyo],
- tv[monkeynv + monkeyf[i][1] + i - monkeyo],
- tv[monkeynv + monkeyf[i][0] + i - monkeyo],
- (monkeyf[i][3] != monkeyf[i][2]) ? tv[monkeynv + monkeyf[i][3] + i - monkeyo] : NULL,
- NULL, BM_CREATE_NOP);
-
- /* Set the UVs here, the iteration order of the faces is not guaranteed,
- * so it's best to set the UVs right after the face is created. */
- if (calc_uvs) {
- BMLoop *l;
- BMIter liter;
- BM_ITER_ELEM (l, &liter, f_new_a, BM_LOOPS_OF_FACE) {
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- luv->uv[0] = monkeyuvs[uvi * 2 + 0];
- luv->uv[1] = monkeyuvs[uvi * 2 + 1];
- uvi++;
- }
- BM_ITER_ELEM (l, &liter, f_new_b, BM_LOOPS_OF_FACE) {
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- luv->uv[0] = monkeyuvs[uvi * 2 + 0];
- luv->uv[1] = monkeyuvs[uvi * 2 + 1];
- uvi++;
- }
-
- }
- }
-
- MEM_freeN(tv);
-
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK);
+ BMVert **tv = MEM_mallocN(sizeof(*tv) * monkeynv * 2, "tv");
+ float mat[4][4];
+ int i;
+
+ BMO_slot_mat4_get(op->slots_in, "matrix", mat);
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+ const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs");
+
+ for (i = 0; i < monkeynv; i++) {
+ float v[3];
+
+ /* rotate to face in the -Y axis */
+ v[0] = (monkeyv[i][0] + 127) / 128.0;
+ v[2] = monkeyv[i][1] / 128.0;
+ v[1] = monkeyv[i][2] / -128.0;
+
+ tv[i] = BM_vert_create(bm, v, NULL, BM_CREATE_NOP);
+ BMO_vert_flag_enable(bm, tv[i], VERT_MARK);
+
+ if (fabsf(v[0] = -v[0]) < 0.001f) {
+ tv[monkeynv + i] = tv[i];
+ }
+ else {
+ BMVert *eve = BM_vert_create(bm, v, NULL, BM_CREATE_NOP);
+ mul_m4_v3(mat, eve->co);
+ tv[monkeynv + i] = eve;
+ }
+
+ BMO_vert_flag_enable(bm, tv[monkeynv + i], VERT_MARK);
+
+ mul_m4_v3(mat, tv[i]->co);
+ }
+
+ int uvi = 0;
+ for (i = 0; i < monkeynf; i++) {
+ BMFace *f_new_a = BM_face_create_quad_tri(
+ bm,
+ tv[monkeyf[i][0] + i - monkeyo],
+ tv[monkeyf[i][1] + i - monkeyo],
+ tv[monkeyf[i][2] + i - monkeyo],
+ (monkeyf[i][3] != monkeyf[i][2]) ? tv[monkeyf[i][3] + i - monkeyo] : NULL,
+ NULL,
+ BM_CREATE_NOP);
+
+ BMFace *f_new_b = BM_face_create_quad_tri(
+ bm,
+ tv[monkeynv + monkeyf[i][2] + i - monkeyo],
+ tv[monkeynv + monkeyf[i][1] + i - monkeyo],
+ tv[monkeynv + monkeyf[i][0] + i - monkeyo],
+ (monkeyf[i][3] != monkeyf[i][2]) ? tv[monkeynv + monkeyf[i][3] + i - monkeyo] : NULL,
+ NULL,
+ BM_CREATE_NOP);
+
+ /* Set the UVs here, the iteration order of the faces is not guaranteed,
+ * so it's best to set the UVs right after the face is created. */
+ if (calc_uvs) {
+ BMLoop *l;
+ BMIter liter;
+ BM_ITER_ELEM (l, &liter, f_new_a, BM_LOOPS_OF_FACE) {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ luv->uv[0] = monkeyuvs[uvi * 2 + 0];
+ luv->uv[1] = monkeyuvs[uvi * 2 + 1];
+ uvi++;
+ }
+ BM_ITER_ELEM (l, &liter, f_new_b, BM_LOOPS_OF_FACE) {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ luv->uv[0] = monkeyuvs[uvi * 2 + 0];
+ luv->uv[1] = monkeyuvs[uvi * 2 + 1];
+ uvi++;
+ }
+ }
+ }
+
+ MEM_freeN(tv);
+
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK);
}
-
void bmo_create_circle_exec(BMesh *bm, BMOperator *op)
{
- const float radius = BMO_slot_float_get(op->slots_in, "radius");
- const int segs = BMO_slot_int_get(op->slots_in, "segments");
- const bool cap_ends = BMO_slot_bool_get(op->slots_in, "cap_ends");
- const bool cap_tris = BMO_slot_bool_get(op->slots_in, "cap_tris");
+ const float radius = BMO_slot_float_get(op->slots_in, "radius");
+ const int segs = BMO_slot_int_get(op->slots_in, "segments");
+ const bool cap_ends = BMO_slot_bool_get(op->slots_in, "cap_ends");
+ const bool cap_tris = BMO_slot_bool_get(op->slots_in, "cap_tris");
- const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
- const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs");
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+ const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs");
- BMVert *v1, *lastv1 = NULL, *cent1, *firstv1 = NULL;
- float vec[3], mat[4][4], phi, phid;
- int a;
+ BMVert *v1, *lastv1 = NULL, *cent1, *firstv1 = NULL;
+ float vec[3], mat[4][4], phi, phid;
+ int a;
- if (!segs) {
- return;
- }
+ if (!segs) {
+ return;
+ }
- BMO_slot_mat4_get(op->slots_in, "matrix", mat);
+ BMO_slot_mat4_get(op->slots_in, "matrix", mat);
- phid = 2.0f * (float)M_PI / segs;
- phi = 0;
+ phid = 2.0f * (float)M_PI / segs;
+ phi = 0;
- if (cap_ends) {
- zero_v3(vec);
- mul_m4_v3(mat, vec);
+ if (cap_ends) {
+ zero_v3(vec);
+ mul_m4_v3(mat, vec);
- cent1 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
- BMO_vert_flag_enable(bm, cent1, VERT_MARK);
- }
+ cent1 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
+ BMO_vert_flag_enable(bm, cent1, VERT_MARK);
+ }
- for (a = 0; a < segs; a++, phi += phid) {
- /* Going this way ends up with normal(s) upward */
- vec[0] = -radius * sinf(phi);
- vec[1] = radius * cosf(phi);
- vec[2] = 0.0f;
- mul_m4_v3(mat, vec);
- v1 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
+ for (a = 0; a < segs; a++, phi += phid) {
+ /* Going this way ends up with normal(s) upward */
+ vec[0] = -radius * sinf(phi);
+ vec[1] = radius * cosf(phi);
+ vec[2] = 0.0f;
+ mul_m4_v3(mat, vec);
+ v1 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
- BMO_vert_flag_enable(bm, v1, VERT_MARK);
+ BMO_vert_flag_enable(bm, v1, VERT_MARK);
- if (lastv1) {
- BM_edge_create(bm, v1, lastv1, NULL, BM_CREATE_NOP);
- }
+ if (lastv1) {
+ BM_edge_create(bm, v1, lastv1, NULL, BM_CREATE_NOP);
+ }
- if (a && cap_ends) {
- BMFace *f;
+ if (a && cap_ends) {
+ BMFace *f;
- f = BM_face_create_quad_tri(bm, cent1, lastv1, v1, NULL, NULL, BM_CREATE_NOP);
- BMO_face_flag_enable(bm, f, FACE_NEW);
- }
+ f = BM_face_create_quad_tri(bm, cent1, lastv1, v1, NULL, NULL, BM_CREATE_NOP);
+ BMO_face_flag_enable(bm, f, FACE_NEW);
+ }
- if (!firstv1) {
- firstv1 = v1;
- }
+ if (!firstv1) {
+ firstv1 = v1;
+ }
- lastv1 = v1;
- }
+ lastv1 = v1;
+ }
- if (!a) {
- return;
- }
+ if (!a) {
+ return;
+ }
- BM_edge_create(bm, firstv1, lastv1, NULL, 0);
+ BM_edge_create(bm, firstv1, lastv1, NULL, 0);
- if (cap_ends) {
- BMFace *f;
+ if (cap_ends) {
+ BMFace *f;
- f = BM_face_create_quad_tri(bm, cent1, v1, firstv1, NULL, NULL, BM_CREATE_NOP);
- BMO_face_flag_enable(bm, f, FACE_NEW);
+ f = BM_face_create_quad_tri(bm, cent1, v1, firstv1, NULL, NULL, BM_CREATE_NOP);
+ BMO_face_flag_enable(bm, f, FACE_NEW);
- if (calc_uvs) {
- BM_mesh_calc_uvs_circle(bm, mat, radius, FACE_NEW, cd_loop_uv_offset);
- }
- }
+ if (calc_uvs) {
+ BM_mesh_calc_uvs_circle(bm, mat, radius, FACE_NEW, cd_loop_uv_offset);
+ }
+ }
- if (!cap_tris) {
- BMO_op_callf(bm, op->flag, "dissolve_faces faces=%ff", FACE_NEW);
- }
+ if (!cap_tris) {
+ BMO_op_callf(bm, op->flag, "dissolve_faces faces=%ff", FACE_NEW);
+ }
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK);
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK);
}
/**
@@ -1374,163 +1358,162 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op)
* \param oflag: The flag to check faces with.
*/
void BM_mesh_calc_uvs_circle(
- BMesh *bm, float mat[4][4], const float radius,
- const short oflag, const int cd_loop_uv_offset)
+ BMesh *bm, float mat[4][4], const float radius, const short oflag, const int cd_loop_uv_offset)
{
- BMFace *f;
- BMLoop *l;
- BMIter fiter, liter;
+ BMFace *f;
+ BMLoop *l;
+ BMIter fiter, liter;
- const float uv_scale = 0.5f / radius;
- const float uv_center = 0.5f;
+ const float uv_scale = 0.5f / radius;
+ const float uv_center = 0.5f;
- float inv_mat[4][4];
+ float inv_mat[4][4];
- BLI_assert(cd_loop_uv_offset != -1); /* caller must ensure we have UVs already */
+ BLI_assert(cd_loop_uv_offset != -1); /* caller must ensure we have UVs already */
- invert_m4_m4(inv_mat, mat);
+ invert_m4_m4(inv_mat, mat);
- BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
- if (!BMO_face_flag_test(bm, f, oflag)) {
- continue;
- }
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ if (!BMO_face_flag_test(bm, f, oflag)) {
+ continue;
+ }
- BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- float uv_vco[3];
- copy_v3_v3(uv_vco, l->v->co);
- /* transform back into the unit circle flat on the Z-axis */
- mul_m4_v3(inv_mat, uv_vco);
+ float uv_vco[3];
+ copy_v3_v3(uv_vco, l->v->co);
+ /* transform back into the unit circle flat on the Z-axis */
+ mul_m4_v3(inv_mat, uv_vco);
- /* then just take those coords for UVs */
- luv->uv[0] = uv_center + uv_scale * uv_vco[0];
- luv->uv[1] = uv_center + uv_scale * uv_vco[1];
- }
- }
+ /* then just take those coords for UVs */
+ luv->uv[0] = uv_center + uv_scale * uv_vco[0];
+ luv->uv[1] = uv_center + uv_scale * uv_vco[1];
+ }
+ }
}
void bmo_create_cone_exec(BMesh *bm, BMOperator *op)
{
- BMVert *v1, *v2, *lastv1 = NULL, *lastv2 = NULL, *cent1, *cent2, *firstv1, *firstv2;
- BMFace *f;
- float vec[3], mat[4][4], phi, phid;
- float dia1 = BMO_slot_float_get(op->slots_in, "diameter1");
- float dia2 = BMO_slot_float_get(op->slots_in, "diameter2");
- float depth = BMO_slot_float_get(op->slots_in, "depth");
- int segs = BMO_slot_int_get(op->slots_in, "segments");
- const bool cap_ends = BMO_slot_bool_get(op->slots_in, "cap_ends");
- const bool cap_tris = BMO_slot_bool_get(op->slots_in, "cap_tris");
-
- const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
- const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs");
- int a;
-
- if (!segs) {
- return;
- }
-
- BMO_slot_mat4_get(op->slots_in, "matrix", mat);
-
- phid = 2.0f * (float)M_PI / segs;
- phi = 0;
-
- depth *= 0.5f;
- if (cap_ends) {
- vec[0] = vec[1] = 0.0f;
- vec[2] = -depth;
- mul_m4_v3(mat, vec);
-
- cent1 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
-
- vec[0] = vec[1] = 0.0f;
- vec[2] = depth;
- mul_m4_v3(mat, vec);
-
- cent2 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
-
- BMO_vert_flag_enable(bm, cent1, VERT_MARK);
- BMO_vert_flag_enable(bm, cent2, VERT_MARK);
- }
-
- for (a = 0; a < segs; a++, phi += phid) {
- vec[0] = dia1 * sinf(phi);
- vec[1] = dia1 * cosf(phi);
- vec[2] = -depth;
- mul_m4_v3(mat, vec);
- v1 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
-
- vec[0] = dia2 * sinf(phi);
- vec[1] = dia2 * cosf(phi);
- vec[2] = depth;
- mul_m4_v3(mat, vec);
- v2 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
-
- BMO_vert_flag_enable(bm, v1, VERT_MARK);
- BMO_vert_flag_enable(bm, v2, VERT_MARK);
-
- if (a) {
- if (cap_ends) {
- f = BM_face_create_quad_tri(bm, cent1, lastv1, v1, NULL, NULL, BM_CREATE_NOP);
- if (calc_uvs) {
- BMO_face_flag_enable(bm, f, FACE_MARK);
- }
- BMO_face_flag_enable(bm, f, FACE_NEW);
-
- f = BM_face_create_quad_tri(bm, cent2, v2, lastv2, NULL, NULL, BM_CREATE_NOP);
- if (calc_uvs) {
- BMO_face_flag_enable(bm, f, FACE_MARK);
- }
- BMO_face_flag_enable(bm, f, FACE_NEW);
- }
-
- f = BM_face_create_quad_tri(bm, lastv1, lastv2, v2, v1, NULL, BM_CREATE_NOP);
- if (calc_uvs) {
- BMO_face_flag_enable(bm, f, FACE_MARK);
- }
- }
- else {
- firstv1 = v1;
- firstv2 = v2;
- }
-
- lastv1 = v1;
- lastv2 = v2;
- }
-
- if (!a) {
- return;
- }
-
- if (cap_ends) {
- f = BM_face_create_quad_tri(bm, cent1, v1, firstv1, NULL, NULL, BM_CREATE_NOP);
- if (calc_uvs) {
- BMO_face_flag_enable(bm, f, FACE_MARK);
- }
- BMO_face_flag_enable(bm, f, FACE_NEW);
-
- f = BM_face_create_quad_tri(bm, cent2, firstv2, v2, NULL, NULL, BM_CREATE_NOP);
- if (calc_uvs) {
- BMO_face_flag_enable(bm, f, FACE_MARK);
- }
- BMO_face_flag_enable(bm, f, FACE_NEW);
- }
-
- f = BM_face_create_quad_tri(bm, v1, v2, firstv2, firstv1, NULL, BM_CREATE_NOP);
- if (calc_uvs) {
- BMO_face_flag_enable(bm, f, FACE_MARK);
- }
-
- if (calc_uvs) {
- BM_mesh_calc_uvs_cone(bm, mat, dia2, dia1, segs, cap_ends, FACE_MARK, cd_loop_uv_offset);
- }
-
- if (!cap_tris) {
- BMO_op_callf(bm, op->flag, "dissolve_faces faces=%ff", FACE_NEW);
- }
-
- BMO_op_callf(bm, op->flag, "remove_doubles verts=%fv dist=%f", VERT_MARK, 0.000001);
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK);
+ BMVert *v1, *v2, *lastv1 = NULL, *lastv2 = NULL, *cent1, *cent2, *firstv1, *firstv2;
+ BMFace *f;
+ float vec[3], mat[4][4], phi, phid;
+ float dia1 = BMO_slot_float_get(op->slots_in, "diameter1");
+ float dia2 = BMO_slot_float_get(op->slots_in, "diameter2");
+ float depth = BMO_slot_float_get(op->slots_in, "depth");
+ int segs = BMO_slot_int_get(op->slots_in, "segments");
+ const bool cap_ends = BMO_slot_bool_get(op->slots_in, "cap_ends");
+ const bool cap_tris = BMO_slot_bool_get(op->slots_in, "cap_tris");
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+ const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs");
+ int a;
+
+ if (!segs) {
+ return;
+ }
+
+ BMO_slot_mat4_get(op->slots_in, "matrix", mat);
+
+ phid = 2.0f * (float)M_PI / segs;
+ phi = 0;
+
+ depth *= 0.5f;
+ if (cap_ends) {
+ vec[0] = vec[1] = 0.0f;
+ vec[2] = -depth;
+ mul_m4_v3(mat, vec);
+
+ cent1 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
+
+ vec[0] = vec[1] = 0.0f;
+ vec[2] = depth;
+ mul_m4_v3(mat, vec);
+
+ cent2 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
+
+ BMO_vert_flag_enable(bm, cent1, VERT_MARK);
+ BMO_vert_flag_enable(bm, cent2, VERT_MARK);
+ }
+
+ for (a = 0; a < segs; a++, phi += phid) {
+ vec[0] = dia1 * sinf(phi);
+ vec[1] = dia1 * cosf(phi);
+ vec[2] = -depth;
+ mul_m4_v3(mat, vec);
+ v1 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
+
+ vec[0] = dia2 * sinf(phi);
+ vec[1] = dia2 * cosf(phi);
+ vec[2] = depth;
+ mul_m4_v3(mat, vec);
+ v2 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
+
+ BMO_vert_flag_enable(bm, v1, VERT_MARK);
+ BMO_vert_flag_enable(bm, v2, VERT_MARK);
+
+ if (a) {
+ if (cap_ends) {
+ f = BM_face_create_quad_tri(bm, cent1, lastv1, v1, NULL, NULL, BM_CREATE_NOP);
+ if (calc_uvs) {
+ BMO_face_flag_enable(bm, f, FACE_MARK);
+ }
+ BMO_face_flag_enable(bm, f, FACE_NEW);
+
+ f = BM_face_create_quad_tri(bm, cent2, v2, lastv2, NULL, NULL, BM_CREATE_NOP);
+ if (calc_uvs) {
+ BMO_face_flag_enable(bm, f, FACE_MARK);
+ }
+ BMO_face_flag_enable(bm, f, FACE_NEW);
+ }
+
+ f = BM_face_create_quad_tri(bm, lastv1, lastv2, v2, v1, NULL, BM_CREATE_NOP);
+ if (calc_uvs) {
+ BMO_face_flag_enable(bm, f, FACE_MARK);
+ }
+ }
+ else {
+ firstv1 = v1;
+ firstv2 = v2;
+ }
+
+ lastv1 = v1;
+ lastv2 = v2;
+ }
+
+ if (!a) {
+ return;
+ }
+
+ if (cap_ends) {
+ f = BM_face_create_quad_tri(bm, cent1, v1, firstv1, NULL, NULL, BM_CREATE_NOP);
+ if (calc_uvs) {
+ BMO_face_flag_enable(bm, f, FACE_MARK);
+ }
+ BMO_face_flag_enable(bm, f, FACE_NEW);
+
+ f = BM_face_create_quad_tri(bm, cent2, firstv2, v2, NULL, NULL, BM_CREATE_NOP);
+ if (calc_uvs) {
+ BMO_face_flag_enable(bm, f, FACE_MARK);
+ }
+ BMO_face_flag_enable(bm, f, FACE_NEW);
+ }
+
+ f = BM_face_create_quad_tri(bm, v1, v2, firstv2, firstv1, NULL, BM_CREATE_NOP);
+ if (calc_uvs) {
+ BMO_face_flag_enable(bm, f, FACE_MARK);
+ }
+
+ if (calc_uvs) {
+ BM_mesh_calc_uvs_cone(bm, mat, dia2, dia1, segs, cap_ends, FACE_MARK, cd_loop_uv_offset);
+ }
+
+ if (!cap_tris) {
+ BMO_op_callf(bm, op->flag, "dissolve_faces faces=%ff", FACE_NEW);
+ }
+
+ BMO_op_callf(bm, op->flag, "remove_doubles verts=%fv dist=%f", VERT_MARK, 0.000001);
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK);
}
/**
@@ -1544,159 +1527,167 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op)
* \param cap_ends: Whether the ends of the cone/cylinder are filled or not.
* \param oflag: The flag to check faces with.
*/
-void BM_mesh_calc_uvs_cone(
- BMesh *bm, float mat[4][4],
- const float radius_top, const float radius_bottom, const int segments, const bool cap_ends,
- const short oflag, const int cd_loop_uv_offset)
+void BM_mesh_calc_uvs_cone(BMesh *bm,
+ float mat[4][4],
+ const float radius_top,
+ const float radius_bottom,
+ const int segments,
+ const bool cap_ends,
+ const short oflag,
+ const int cd_loop_uv_offset)
{
- BMFace *f;
- BMLoop *l;
- BMIter fiter, liter;
-
- const float uv_width = 1.0f / (float)segments;
- const float uv_height = cap_ends ? 0.5f : 1.0f;
-
- /* Note that all this allows us to handle all cases (real cone, truncated cone, with or without ends capped)
- * with a single common code. */
- const float uv_center_y = cap_ends ? 0.25f : 0.5f;
- const float uv_center_x_top = cap_ends ? 0.25f : 0.5f;
- const float uv_center_x_bottom = cap_ends ? 0.75f : 0.5f;
- const float uv_radius = cap_ends ? 0.24f : 0.5f;
-
- /* Using the opposite's end uv_scale as fallback allows us to handle 'real cone' case. */
- const float uv_scale_top = (radius_top != 0.0f) ? (uv_radius / radius_top) :
- ((radius_bottom != 0.0f) ? (uv_radius / radius_bottom) : uv_radius);
- const float uv_scale_bottom = (radius_bottom != 0.0f) ? (uv_radius / radius_bottom) :
- uv_scale_top;
-
- float local_up[3] = {0.0f, 0.0f, 1.0f};
-
- float x, y;
- float inv_mat[4][4];
- int loop_index;
-
- mul_mat3_m4_v3(mat, local_up); /* transform the upvector like we did the cone itself, without location. */
- normalize_v3(local_up); /* remove global scaling... */
-
- invert_m4_m4(inv_mat, mat);
-
- BLI_assert(cd_loop_uv_offset != -1); /* caller is responsible for ensuring the mesh has UVs */
-
- x = 1.0f;
- y = 1.0f - uv_height;
-
- BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
- if (!BMO_face_flag_test(bm, f, oflag)) {
- continue;
- }
-
- if (f->len == 4 && radius_top && radius_bottom) {
- /* side face - so unwrap it in a rectangle */
- BM_ITER_ELEM_INDEX (l, &liter, f, BM_LOOPS_OF_FACE, loop_index) {
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
-
- switch (loop_index) {
- case 0:
- /* Continue in the last position */
- break;
- case 1:
- y += uv_height;
- break;
- case 2:
- x -= uv_width;
- break;
- case 3:
- y -= uv_height;
- break;
- default:
- break;
- }
-
- luv->uv[0] = x;
- luv->uv[1] = y;
- }
- }
- else {
- /* top or bottom face - so unwrap it by transforming back to a circle and using the X/Y coords */
- BM_face_normal_update(f);
-
- BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- float uv_vco[3];
-
- mul_v3_m4v3(uv_vco, inv_mat, l->v->co);
-
- if (dot_v3v3(f->no, local_up) > 0.0f) { /* if this is a top face of the cone */
- luv->uv[0] = uv_center_x_top + uv_vco[0] * uv_scale_top;
- luv->uv[1] = uv_center_y + uv_vco[1] * uv_scale_top;
- }
- else {
- luv->uv[0] = uv_center_x_bottom + uv_vco[0] * uv_scale_bottom;
- luv->uv[1] = uv_center_y + uv_vco[1] * uv_scale_bottom;
- }
- }
- }
- }
+ BMFace *f;
+ BMLoop *l;
+ BMIter fiter, liter;
+
+ const float uv_width = 1.0f / (float)segments;
+ const float uv_height = cap_ends ? 0.5f : 1.0f;
+
+ /* Note that all this allows us to handle all cases (real cone, truncated cone, with or without ends capped)
+ * with a single common code. */
+ const float uv_center_y = cap_ends ? 0.25f : 0.5f;
+ const float uv_center_x_top = cap_ends ? 0.25f : 0.5f;
+ const float uv_center_x_bottom = cap_ends ? 0.75f : 0.5f;
+ const float uv_radius = cap_ends ? 0.24f : 0.5f;
+
+ /* Using the opposite's end uv_scale as fallback allows us to handle 'real cone' case. */
+ const float uv_scale_top = (radius_top != 0.0f) ?
+ (uv_radius / radius_top) :
+ ((radius_bottom != 0.0f) ? (uv_radius / radius_bottom) :
+ uv_radius);
+ const float uv_scale_bottom = (radius_bottom != 0.0f) ? (uv_radius / radius_bottom) :
+ uv_scale_top;
+
+ float local_up[3] = {0.0f, 0.0f, 1.0f};
+
+ float x, y;
+ float inv_mat[4][4];
+ int loop_index;
+
+ mul_mat3_m4_v3(
+ mat, local_up); /* transform the upvector like we did the cone itself, without location. */
+ normalize_v3(local_up); /* remove global scaling... */
+
+ invert_m4_m4(inv_mat, mat);
+
+ BLI_assert(cd_loop_uv_offset != -1); /* caller is responsible for ensuring the mesh has UVs */
+
+ x = 1.0f;
+ y = 1.0f - uv_height;
+
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ if (!BMO_face_flag_test(bm, f, oflag)) {
+ continue;
+ }
+
+ if (f->len == 4 && radius_top && radius_bottom) {
+ /* side face - so unwrap it in a rectangle */
+ BM_ITER_ELEM_INDEX(l, &liter, f, BM_LOOPS_OF_FACE, loop_index)
+ {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+
+ switch (loop_index) {
+ case 0:
+ /* Continue in the last position */
+ break;
+ case 1:
+ y += uv_height;
+ break;
+ case 2:
+ x -= uv_width;
+ break;
+ case 3:
+ y -= uv_height;
+ break;
+ default:
+ break;
+ }
+
+ luv->uv[0] = x;
+ luv->uv[1] = y;
+ }
+ }
+ else {
+ /* top or bottom face - so unwrap it by transforming back to a circle and using the X/Y coords */
+ BM_face_normal_update(f);
+
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ float uv_vco[3];
+
+ mul_v3_m4v3(uv_vco, inv_mat, l->v->co);
+
+ if (dot_v3v3(f->no, local_up) > 0.0f) { /* if this is a top face of the cone */
+ luv->uv[0] = uv_center_x_top + uv_vco[0] * uv_scale_top;
+ luv->uv[1] = uv_center_y + uv_vco[1] * uv_scale_top;
+ }
+ else {
+ luv->uv[0] = uv_center_x_bottom + uv_vco[0] * uv_scale_bottom;
+ luv->uv[1] = uv_center_y + uv_vco[1] * uv_scale_bottom;
+ }
+ }
+ }
+ }
}
void bmo_create_cube_exec(BMesh *bm, BMOperator *op)
{
- BMVert *verts[8];
- float mat[4][4];
- float off = BMO_slot_float_get(op->slots_in, "size") / 2.0f;
-
- const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
- const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs");
-
- /* rotation order set to match 'BM_mesh_calc_uvs_cube' */
- const char faces[6][4] = {
- {0, 1, 3, 2},
- {2, 3, 7, 6},
- {6, 7, 5, 4},
- {4, 5, 1, 0},
- {2, 6, 4, 0},
- {7, 3, 1, 5},
- };
-
- BMO_slot_mat4_get(op->slots_in, "matrix", mat);
-
- if (!off) {
- off = 0.5f;
- }
- int i = 0;
-
- for (int x = -1; x < 2; x += 2) {
- for (int y = -1; y < 2; y += 2) {
- for (int z = -1; z < 2; z += 2) {
- float vec[3] = {(float)x * off, (float)y * off, (float)z * off};
- mul_m4_v3(mat, vec);
- verts[i] = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
- BMO_vert_flag_enable(bm, verts[i], VERT_MARK);
- i++;
- }
- }
- }
-
- for (i = 0; i < ARRAY_SIZE(faces); i++) {
- BMFace *f;
- BMVert *quad[4] = {
- verts[faces[i][0]],
- verts[faces[i][1]],
- verts[faces[i][2]],
- verts[faces[i][3]],
- };
-
- f = BM_face_create_verts(bm, quad, 4, NULL, BM_CREATE_NOP, true);
- if (calc_uvs) {
- BMO_face_flag_enable(bm, f, FACE_MARK);
- }
- }
-
- if (calc_uvs) {
- BM_mesh_calc_uvs_cube(bm, FACE_MARK);
- }
-
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK);
+ BMVert *verts[8];
+ float mat[4][4];
+ float off = BMO_slot_float_get(op->slots_in, "size") / 2.0f;
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+ const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs");
+
+ /* rotation order set to match 'BM_mesh_calc_uvs_cube' */
+ const char faces[6][4] = {
+ {0, 1, 3, 2},
+ {2, 3, 7, 6},
+ {6, 7, 5, 4},
+ {4, 5, 1, 0},
+ {2, 6, 4, 0},
+ {7, 3, 1, 5},
+ };
+
+ BMO_slot_mat4_get(op->slots_in, "matrix", mat);
+
+ if (!off) {
+ off = 0.5f;
+ }
+ int i = 0;
+
+ for (int x = -1; x < 2; x += 2) {
+ for (int y = -1; y < 2; y += 2) {
+ for (int z = -1; z < 2; z += 2) {
+ float vec[3] = {(float)x * off, (float)y * off, (float)z * off};
+ mul_m4_v3(mat, vec);
+ verts[i] = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP);
+ BMO_vert_flag_enable(bm, verts[i], VERT_MARK);
+ i++;
+ }
+ }
+ }
+
+ for (i = 0; i < ARRAY_SIZE(faces); i++) {
+ BMFace *f;
+ BMVert *quad[4] = {
+ verts[faces[i][0]],
+ verts[faces[i][1]],
+ verts[faces[i][2]],
+ verts[faces[i][3]],
+ };
+
+ f = BM_face_create_verts(bm, quad, 4, NULL, BM_CREATE_NOP, true);
+ if (calc_uvs) {
+ BMO_face_flag_enable(bm, f, FACE_MARK);
+ }
+ }
+
+ if (calc_uvs) {
+ BM_mesh_calc_uvs_cube(bm, FACE_MARK);
+ }
+
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK);
}
/**
@@ -1710,59 +1701,60 @@ void bmo_create_cube_exec(BMesh *bm, BMOperator *op)
*/
void BM_mesh_calc_uvs_cube(BMesh *bm, const short oflag)
{
- BMFace *f;
- BMLoop *l;
- BMIter fiter, liter;
- const float width = 0.25f;
-
- const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
-
- float x = 0.375f;
- float y = 0.0f;
-
- int loop_index;
-
- BLI_assert(cd_loop_uv_offset != -1); /* the caller can ensure that we have UVs */
-
- BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
- if (!BMO_face_flag_test(bm, f, oflag)) {
- continue;
- }
-
- BM_ITER_ELEM_INDEX (l, &liter, f, BM_LOOPS_OF_FACE, loop_index) {
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
-
- luv->uv[0] = x;
- luv->uv[1] = y;
-
- switch (loop_index) {
- case 0:
- x += width;
- break;
- case 1:
- y += width;
- break;
- case 2:
- x -= width;
- break;
- case 3:
- y -= width;
- break;
- default:
- break;
- }
- }
-
- if (y >= 0.75f && x > 0.125f) {
- x = 0.125f;
- y = 0.5f;
- }
- else if (x <= 0.125f) {
- x = 0.625f;
- y = 0.5f;
- }
- else {
- y += 0.25f;
- }
- }
+ BMFace *f;
+ BMLoop *l;
+ BMIter fiter, liter;
+ const float width = 0.25f;
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+
+ float x = 0.375f;
+ float y = 0.0f;
+
+ int loop_index;
+
+ BLI_assert(cd_loop_uv_offset != -1); /* the caller can ensure that we have UVs */
+
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ if (!BMO_face_flag_test(bm, f, oflag)) {
+ continue;
+ }
+
+ BM_ITER_ELEM_INDEX(l, &liter, f, BM_LOOPS_OF_FACE, loop_index)
+ {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+
+ luv->uv[0] = x;
+ luv->uv[1] = y;
+
+ switch (loop_index) {
+ case 0:
+ x += width;
+ break;
+ case 1:
+ y += width;
+ break;
+ case 2:
+ x -= width;
+ break;
+ case 3:
+ y -= width;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (y >= 0.75f && x > 0.125f) {
+ x = 0.125f;
+ y = 0.5f;
+ }
+ else if (x <= 0.125f) {
+ x = 0.625f;
+ y = 0.5f;
+ }
+ else {
+ y += 0.25f;
+ }
+ }
}
diff --git a/source/blender/bmesh/operators/bmo_removedoubles.c b/source/blender/bmesh/operators/bmo_removedoubles.c
index e59bad0d682..144d944e939 100644
--- a/source/blender/bmesh/operators/bmo_removedoubles.c
+++ b/source/blender/bmesh/operators/bmo_removedoubles.c
@@ -36,149 +36,150 @@
static void remdoubles_splitface(BMFace *f, BMesh *bm, BMOperator *op, BMOpSlot *slot_targetmap)
{
- BMIter liter;
- BMLoop *l, *l_tar, *l_double;
- bool split = false;
-
- BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- BMVert *v_tar = BMO_slot_map_elem_get(slot_targetmap, l->v);
- /* ok: if v_tar is NULL (e.g. not in the map) then it's
- * a target vert, otherwise it's a double */
- if (v_tar) {
- l_tar = BM_face_vert_share_loop(f, v_tar);
-
- if (l_tar && (l_tar != l) && !BM_loop_is_adjacent(l_tar, l)) {
- l_double = l;
- split = true;
- break;
- }
- }
- }
-
- if (split) {
- BMLoop *l_new;
- BMFace *f_new;
-
- f_new = BM_face_split(bm, f, l_double, l_tar, &l_new, NULL, false);
-
- remdoubles_splitface(f, bm, op, slot_targetmap);
- remdoubles_splitface(f_new, bm, op, slot_targetmap);
- }
+ BMIter liter;
+ BMLoop *l, *l_tar, *l_double;
+ bool split = false;
+
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ BMVert *v_tar = BMO_slot_map_elem_get(slot_targetmap, l->v);
+ /* ok: if v_tar is NULL (e.g. not in the map) then it's
+ * a target vert, otherwise it's a double */
+ if (v_tar) {
+ l_tar = BM_face_vert_share_loop(f, v_tar);
+
+ if (l_tar && (l_tar != l) && !BM_loop_is_adjacent(l_tar, l)) {
+ l_double = l;
+ split = true;
+ break;
+ }
+ }
+ }
+
+ if (split) {
+ BMLoop *l_new;
+ BMFace *f_new;
+
+ f_new = BM_face_split(bm, f, l_double, l_tar, &l_new, NULL, false);
+
+ remdoubles_splitface(f, bm, op, slot_targetmap);
+ remdoubles_splitface(f_new, bm, op, slot_targetmap);
+ }
}
-#define ELE_DEL 1
-#define EDGE_COL 2
-#define VERT_IN_FACE 4
+#define ELE_DEL 1
+#define EDGE_COL 2
+#define VERT_IN_FACE 4
/**
* helper function for bmo_weld_verts_exec so we can use stack memory
*/
-static BMFace *remdoubles_createface(BMesh *bm, BMFace *f, BMOpSlot *slot_targetmap, bool *r_created)
+static BMFace *remdoubles_createface(BMesh *bm,
+ BMFace *f,
+ BMOpSlot *slot_targetmap,
+ bool *r_created)
{
- BMEdge *e_new;
+ BMEdge *e_new;
- BMEdge **edges = BLI_array_alloca(edges, f->len); /* new ordered edges */
- BMVert **verts = BLI_array_alloca(verts, f->len); /* new ordered verts */
- BMLoop **loops = BLI_array_alloca(loops, f->len); /* original ordered loops to copy attrs into the new face */
+ BMEdge **edges = BLI_array_alloca(edges, f->len); /* new ordered edges */
+ BMVert **verts = BLI_array_alloca(verts, f->len); /* new ordered verts */
+ BMLoop **loops = BLI_array_alloca(
+ loops, f->len); /* original ordered loops to copy attrs into the new face */
- STACK_DECLARE(edges);
- STACK_DECLARE(loops);
- STACK_DECLARE(verts);
+ STACK_DECLARE(edges);
+ STACK_DECLARE(loops);
+ STACK_DECLARE(verts);
- STACK_INIT(edges, f->len);
- STACK_INIT(loops, f->len);
- STACK_INIT(verts, f->len);
+ STACK_INIT(edges, f->len);
+ STACK_INIT(loops, f->len);
+ STACK_INIT(verts, f->len);
- *r_created = false;
+ *r_created = false;
- {
+ {
#define LOOP_MAP_VERT_INIT(l_init, v_map, is_del) \
- v_map = l_init->v; \
- is_del = BMO_vert_flag_test_bool(bm, v_map, ELE_DEL); \
- if (is_del) { \
- v_map = BMO_slot_map_elem_get(slot_targetmap, v_map); \
- } ((void)0)
-
-
- BMLoop *l_first, *l_curr, *l_next;
- BMVert *v_curr;
- bool is_del_v_curr;
-
- l_curr = l_first = BM_FACE_FIRST_LOOP(f);
- LOOP_MAP_VERT_INIT(l_curr, v_curr, is_del_v_curr);
-
- do {
- BMVert *v_next;
- bool is_del_v_next;
-
- l_next = l_curr->next;
- LOOP_MAP_VERT_INIT(l_next, v_next, is_del_v_next);
-
- /* only search for a new edge if one of the verts is mapped */
- if ((is_del_v_curr || is_del_v_next) == 0) {
- e_new = l_curr->e;
- }
- else if (v_curr == v_next) {
- e_new = NULL; /* skip */
- }
- else {
- e_new = BM_edge_exists(v_curr, v_next);
- BLI_assert(e_new); /* never fails */
- }
-
- if (e_new) {
- if (UNLIKELY(BMO_vert_flag_test(bm, v_curr, VERT_IN_FACE))) {
- /* we can't make the face, bail out */
- STACK_CLEAR(edges);
- goto finally;
- }
- BMO_vert_flag_enable(bm, v_curr, VERT_IN_FACE);
-
- STACK_PUSH(edges, e_new);
- STACK_PUSH(loops, l_curr);
- STACK_PUSH(verts, v_curr);
- }
-
- v_curr = v_next;
- is_del_v_curr = is_del_v_next;
- } while ((l_curr = l_next) != l_first);
+ v_map = l_init->v; \
+ is_del = BMO_vert_flag_test_bool(bm, v_map, ELE_DEL); \
+ if (is_del) { \
+ v_map = BMO_slot_map_elem_get(slot_targetmap, v_map); \
+ } \
+ ((void)0)
+
+ BMLoop *l_first, *l_curr, *l_next;
+ BMVert *v_curr;
+ bool is_del_v_curr;
+
+ l_curr = l_first = BM_FACE_FIRST_LOOP(f);
+ LOOP_MAP_VERT_INIT(l_curr, v_curr, is_del_v_curr);
+
+ do {
+ BMVert *v_next;
+ bool is_del_v_next;
+
+ l_next = l_curr->next;
+ LOOP_MAP_VERT_INIT(l_next, v_next, is_del_v_next);
+
+ /* only search for a new edge if one of the verts is mapped */
+ if ((is_del_v_curr || is_del_v_next) == 0) {
+ e_new = l_curr->e;
+ }
+ else if (v_curr == v_next) {
+ e_new = NULL; /* skip */
+ }
+ else {
+ e_new = BM_edge_exists(v_curr, v_next);
+ BLI_assert(e_new); /* never fails */
+ }
+
+ if (e_new) {
+ if (UNLIKELY(BMO_vert_flag_test(bm, v_curr, VERT_IN_FACE))) {
+ /* we can't make the face, bail out */
+ STACK_CLEAR(edges);
+ goto finally;
+ }
+ BMO_vert_flag_enable(bm, v_curr, VERT_IN_FACE);
+
+ STACK_PUSH(edges, e_new);
+ STACK_PUSH(loops, l_curr);
+ STACK_PUSH(verts, v_curr);
+ }
+
+ v_curr = v_next;
+ is_del_v_curr = is_del_v_next;
+ } while ((l_curr = l_next) != l_first);
#undef LOOP_MAP_VERT_INIT
+ }
- }
-
-finally:
- {
- uint i;
- for (i = 0; i < STACK_SIZE(verts); i++) {
- BMO_vert_flag_disable(bm, verts[i], VERT_IN_FACE);
- }
- }
-
- if (STACK_SIZE(edges) >= 3) {
- BMFace *f_new = BM_face_exists(verts, STACK_SIZE(verts));
- if (f_new) {
- return f_new;
- }
- f_new = BM_face_create(bm, verts, edges, STACK_SIZE(edges), f, BM_CREATE_NOP);
- BLI_assert(f_new != f);
-
- if (f_new) {
- uint i = 0;
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f_new);
- do {
- BM_elem_attrs_copy(bm, bm, loops[i], l_iter);
- } while ((void)i++, (l_iter = l_iter->next) != l_first);
-
- *r_created = true;
- return f_new;
- }
- }
-
- return NULL;
+finally : {
+ uint i;
+ for (i = 0; i < STACK_SIZE(verts); i++) {
+ BMO_vert_flag_disable(bm, verts[i], VERT_IN_FACE);
+ }
}
+ if (STACK_SIZE(edges) >= 3) {
+ BMFace *f_new = BM_face_exists(verts, STACK_SIZE(verts));
+ if (f_new) {
+ return f_new;
+ }
+ f_new = BM_face_create(bm, verts, edges, STACK_SIZE(edges), f, BM_CREATE_NOP);
+ BLI_assert(f_new != f);
+
+ if (f_new) {
+ uint i = 0;
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_new);
+ do {
+ BM_elem_attrs_copy(bm, bm, loops[i], l_iter);
+ } while ((void)i++, (l_iter = l_iter->next) != l_first);
+
+ *r_created = true;
+ return f_new;
+ }
+ }
+
+ return NULL;
+}
/**
* \note with 'targetmap', multiple 'keys' are currently supported, though no callers should be using.
@@ -186,547 +187,550 @@ finally:
*/
void bmo_weld_verts_exec(BMesh *bm, BMOperator *op)
{
- BMIter iter, liter;
- BMVert *v;
- BMEdge *e;
- BMLoop *l;
- BMFace *f;
- BMOpSlot *slot_targetmap = BMO_slot_get(op->slots_in, "targetmap");
-
- /* Maintain selection history. */
- const bool has_selected = !BLI_listbase_is_empty(&bm->selected);
- const bool use_targetmap_all = has_selected;
- GHash *targetmap_all = NULL;
- if (use_targetmap_all) {
- /* Map deleted to keep elem. */
- targetmap_all = BLI_ghash_ptr_new(__func__);
- }
-
- /* mark merge verts for deletion */
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- BMVert *v_dst = BMO_slot_map_elem_get(slot_targetmap, v);
- if (v_dst != NULL) {
- BMO_vert_flag_enable(bm, v, ELE_DEL);
-
- /* merge the vertex flags, else we get randomly selected/unselected verts */
- BM_elem_flag_merge_ex(v, v_dst, BM_ELEM_HIDDEN);
-
- if (use_targetmap_all) {
- BLI_assert(v != v_dst);
- BLI_ghash_insert(targetmap_all, v, v_dst);
- }
- }
- }
-
- /* check if any faces are getting their own corners merged
- * together, split face if so */
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- remdoubles_splitface(f, bm, op, slot_targetmap);
- }
-
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- BMVert *v1, *v2;
- const bool is_del_v1 = BMO_vert_flag_test_bool(bm, (v1 = e->v1), ELE_DEL);
- const bool is_del_v2 = BMO_vert_flag_test_bool(bm, (v2 = e->v2), ELE_DEL);
-
- if (is_del_v1 || is_del_v2) {
- if (is_del_v1) {
- v1 = BMO_slot_map_elem_get(slot_targetmap, v1);
- }
- if (is_del_v2) {
- v2 = BMO_slot_map_elem_get(slot_targetmap, v2);
- }
-
- if (v1 == v2) {
- BMO_edge_flag_enable(bm, e, EDGE_COL);
- }
- else {
- /* always merge flags, even for edges we already created */
- BMEdge *e_new = BM_edge_exists(v1, v2);
- if (e_new == NULL) {
- e_new = BM_edge_create(bm, v1, v2, e, BM_CREATE_NOP);
- }
- BM_elem_flag_merge_ex(e_new, e, BM_ELEM_HIDDEN);
- if (use_targetmap_all) {
- BLI_assert(e != e_new);
- BLI_ghash_insert(targetmap_all, e, e_new);
- }
- }
-
- BMO_edge_flag_enable(bm, e, ELE_DEL);
- }
- }
-
- /* faces get "modified" by creating new faces here, then at the
- * end the old faces are deleted */
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- bool vert_delete = false;
- int edge_collapse = 0;
-
- BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- if (BMO_vert_flag_test(bm, l->v, ELE_DEL)) {
- vert_delete = true;
- }
- if (BMO_edge_flag_test(bm, l->e, EDGE_COL)) {
- edge_collapse++;
- }
- }
-
- if (vert_delete) {
- bool use_in_place = false;
- BMFace *f_new = NULL;
- BMO_face_flag_enable(bm, f, ELE_DEL);
-
- if (f->len - edge_collapse >= 3) {
- bool created;
- f_new = remdoubles_createface(bm, f, slot_targetmap, &created);
- /* do this so we don't need to return a list of created faces */
- if (f_new) {
- if (created) {
- bmesh_face_swap_data(f_new, f);
-
- if (bm->use_toolflags) {
- SWAP(BMFlagLayer *, ((BMFace_OFlag *)f)->oflags, ((BMFace_OFlag *)f_new)->oflags);
- }
-
- BMO_face_flag_disable(bm, f, ELE_DEL);
- BM_face_kill(bm, f_new);
- use_in_place = true;
- }
- else {
- BM_elem_flag_merge_ex(f_new, f, BM_ELEM_HIDDEN);
- }
- }
- }
-
- if ((use_in_place == false) && (f_new != NULL)) {
- BLI_assert(f != f_new);
- if (use_targetmap_all) {
- BLI_ghash_insert(targetmap_all, f, f_new);
- }
- if (bm->act_face && (f == bm->act_face)) {
- bm->act_face = f_new;
- }
- }
- }
- }
-
- if (has_selected) {
- BM_select_history_merge_from_targetmap(bm, targetmap_all, targetmap_all, targetmap_all, true);
- }
-
- if (use_targetmap_all) {
- BLI_ghash_free(targetmap_all, NULL, NULL);
- }
-
- BMO_mesh_delete_oflag_context(bm, ELE_DEL, DEL_ONLYTAGGED);
+ BMIter iter, liter;
+ BMVert *v;
+ BMEdge *e;
+ BMLoop *l;
+ BMFace *f;
+ BMOpSlot *slot_targetmap = BMO_slot_get(op->slots_in, "targetmap");
+
+ /* Maintain selection history. */
+ const bool has_selected = !BLI_listbase_is_empty(&bm->selected);
+ const bool use_targetmap_all = has_selected;
+ GHash *targetmap_all = NULL;
+ if (use_targetmap_all) {
+ /* Map deleted to keep elem. */
+ targetmap_all = BLI_ghash_ptr_new(__func__);
+ }
+
+ /* mark merge verts for deletion */
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ BMVert *v_dst = BMO_slot_map_elem_get(slot_targetmap, v);
+ if (v_dst != NULL) {
+ BMO_vert_flag_enable(bm, v, ELE_DEL);
+
+ /* merge the vertex flags, else we get randomly selected/unselected verts */
+ BM_elem_flag_merge_ex(v, v_dst, BM_ELEM_HIDDEN);
+
+ if (use_targetmap_all) {
+ BLI_assert(v != v_dst);
+ BLI_ghash_insert(targetmap_all, v, v_dst);
+ }
+ }
+ }
+
+ /* check if any faces are getting their own corners merged
+ * together, split face if so */
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ remdoubles_splitface(f, bm, op, slot_targetmap);
+ }
+
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ BMVert *v1, *v2;
+ const bool is_del_v1 = BMO_vert_flag_test_bool(bm, (v1 = e->v1), ELE_DEL);
+ const bool is_del_v2 = BMO_vert_flag_test_bool(bm, (v2 = e->v2), ELE_DEL);
+
+ if (is_del_v1 || is_del_v2) {
+ if (is_del_v1) {
+ v1 = BMO_slot_map_elem_get(slot_targetmap, v1);
+ }
+ if (is_del_v2) {
+ v2 = BMO_slot_map_elem_get(slot_targetmap, v2);
+ }
+
+ if (v1 == v2) {
+ BMO_edge_flag_enable(bm, e, EDGE_COL);
+ }
+ else {
+ /* always merge flags, even for edges we already created */
+ BMEdge *e_new = BM_edge_exists(v1, v2);
+ if (e_new == NULL) {
+ e_new = BM_edge_create(bm, v1, v2, e, BM_CREATE_NOP);
+ }
+ BM_elem_flag_merge_ex(e_new, e, BM_ELEM_HIDDEN);
+ if (use_targetmap_all) {
+ BLI_assert(e != e_new);
+ BLI_ghash_insert(targetmap_all, e, e_new);
+ }
+ }
+
+ BMO_edge_flag_enable(bm, e, ELE_DEL);
+ }
+ }
+
+ /* faces get "modified" by creating new faces here, then at the
+ * end the old faces are deleted */
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ bool vert_delete = false;
+ int edge_collapse = 0;
+
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ if (BMO_vert_flag_test(bm, l->v, ELE_DEL)) {
+ vert_delete = true;
+ }
+ if (BMO_edge_flag_test(bm, l->e, EDGE_COL)) {
+ edge_collapse++;
+ }
+ }
+
+ if (vert_delete) {
+ bool use_in_place = false;
+ BMFace *f_new = NULL;
+ BMO_face_flag_enable(bm, f, ELE_DEL);
+
+ if (f->len - edge_collapse >= 3) {
+ bool created;
+ f_new = remdoubles_createface(bm, f, slot_targetmap, &created);
+ /* do this so we don't need to return a list of created faces */
+ if (f_new) {
+ if (created) {
+ bmesh_face_swap_data(f_new, f);
+
+ if (bm->use_toolflags) {
+ SWAP(BMFlagLayer *, ((BMFace_OFlag *)f)->oflags, ((BMFace_OFlag *)f_new)->oflags);
+ }
+
+ BMO_face_flag_disable(bm, f, ELE_DEL);
+ BM_face_kill(bm, f_new);
+ use_in_place = true;
+ }
+ else {
+ BM_elem_flag_merge_ex(f_new, f, BM_ELEM_HIDDEN);
+ }
+ }
+ }
+
+ if ((use_in_place == false) && (f_new != NULL)) {
+ BLI_assert(f != f_new);
+ if (use_targetmap_all) {
+ BLI_ghash_insert(targetmap_all, f, f_new);
+ }
+ if (bm->act_face && (f == bm->act_face)) {
+ bm->act_face = f_new;
+ }
+ }
+ }
+ }
+
+ if (has_selected) {
+ BM_select_history_merge_from_targetmap(bm, targetmap_all, targetmap_all, targetmap_all, true);
+ }
+
+ if (use_targetmap_all) {
+ BLI_ghash_free(targetmap_all, NULL, NULL);
+ }
+
+ BMO_mesh_delete_oflag_context(bm, ELE_DEL, DEL_ONLYTAGGED);
}
-#define VERT_KEEP 8
-#define VERT_IN 32
+#define VERT_KEEP 8
+#define VERT_IN 32
-#define EDGE_MARK 1
+#define EDGE_MARK 1
void bmo_pointmerge_facedata_exec(BMesh *bm, BMOperator *op)
{
- BMOIter siter;
- BMIter iter;
- BMVert *v, *vert_snap;
- BMLoop *l, *l_first = NULL;
- float fac;
- int i, tot;
-
- vert_snap = BMO_slot_buffer_get_single(BMO_slot_get(op->slots_in, "vert_snap"));
- tot = BM_vert_face_count(vert_snap);
-
- if (!tot) {
- return;
- }
-
- fac = 1.0f / tot;
- BM_ITER_ELEM (l, &iter, vert_snap, BM_LOOPS_OF_VERT) {
- if (l_first == NULL) {
- l_first = l;
- }
-
- for (i = 0; i < bm->ldata.totlayer; i++) {
- if (CustomData_layer_has_math(&bm->ldata, i)) {
- const int type = bm->ldata.layers[i].type;
- const int offset = bm->ldata.layers[i].offset;
- void *e1, *e2;
-
- e1 = BM_ELEM_CD_GET_VOID_P(l_first, offset);
- e2 = BM_ELEM_CD_GET_VOID_P(l, offset);
-
- CustomData_data_multiply(type, e2, fac);
-
- if (l != l_first) {
- CustomData_data_add(type, e1, e2);
- }
- }
- }
- }
-
- BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
- BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
- if (l == l_first) {
- continue;
- }
-
- CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, l_first->head.data, &l->head.data);
- }
- }
+ BMOIter siter;
+ BMIter iter;
+ BMVert *v, *vert_snap;
+ BMLoop *l, *l_first = NULL;
+ float fac;
+ int i, tot;
+
+ vert_snap = BMO_slot_buffer_get_single(BMO_slot_get(op->slots_in, "vert_snap"));
+ tot = BM_vert_face_count(vert_snap);
+
+ if (!tot) {
+ return;
+ }
+
+ fac = 1.0f / tot;
+ BM_ITER_ELEM (l, &iter, vert_snap, BM_LOOPS_OF_VERT) {
+ if (l_first == NULL) {
+ l_first = l;
+ }
+
+ for (i = 0; i < bm->ldata.totlayer; i++) {
+ if (CustomData_layer_has_math(&bm->ldata, i)) {
+ const int type = bm->ldata.layers[i].type;
+ const int offset = bm->ldata.layers[i].offset;
+ void *e1, *e2;
+
+ e1 = BM_ELEM_CD_GET_VOID_P(l_first, offset);
+ e2 = BM_ELEM_CD_GET_VOID_P(l, offset);
+
+ CustomData_data_multiply(type, e2, fac);
+
+ if (l != l_first) {
+ CustomData_data_add(type, e1, e2);
+ }
+ }
+ }
+ }
+
+ BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
+ BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
+ if (l == l_first) {
+ continue;
+ }
+
+ CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, l_first->head.data, &l->head.data);
+ }
+ }
}
void bmo_average_vert_facedata_exec(BMesh *bm, BMOperator *op)
{
- BMOIter siter;
- BMIter iter;
- BMVert *v;
- BMLoop *l /* , *firstl = NULL */;
- CDBlockBytes min, max;
- int i;
-
- for (i = 0; i < bm->ldata.totlayer; i++) {
- const int type = bm->ldata.layers[i].type;
- const int offset = bm->ldata.layers[i].offset;
-
- if (!CustomData_layer_has_math(&bm->ldata, i)) {
- continue;
- }
-
- CustomData_data_initminmax(type, &min, &max);
-
- BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
- BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
- void *block = BM_ELEM_CD_GET_VOID_P(l, offset);
- CustomData_data_dominmax(type, block, &min, &max);
- }
- }
-
- CustomData_data_multiply(type, &min, 0.5f);
- CustomData_data_multiply(type, &max, 0.5f);
- CustomData_data_add(type, &min, &max);
-
- BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
- BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
- void *block = BM_ELEM_CD_GET_VOID_P(l, offset);
- CustomData_data_copy_value(type, &min, block);
- }
- }
- }
+ BMOIter siter;
+ BMIter iter;
+ BMVert *v;
+ BMLoop *l /* , *firstl = NULL */;
+ CDBlockBytes min, max;
+ int i;
+
+ for (i = 0; i < bm->ldata.totlayer; i++) {
+ const int type = bm->ldata.layers[i].type;
+ const int offset = bm->ldata.layers[i].offset;
+
+ if (!CustomData_layer_has_math(&bm->ldata, i)) {
+ continue;
+ }
+
+ CustomData_data_initminmax(type, &min, &max);
+
+ BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
+ BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
+ void *block = BM_ELEM_CD_GET_VOID_P(l, offset);
+ CustomData_data_dominmax(type, block, &min, &max);
+ }
+ }
+
+ CustomData_data_multiply(type, &min, 0.5f);
+ CustomData_data_multiply(type, &max, 0.5f);
+ CustomData_data_add(type, &min, &max);
+
+ BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
+ BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
+ void *block = BM_ELEM_CD_GET_VOID_P(l, offset);
+ CustomData_data_copy_value(type, &min, block);
+ }
+ }
+ }
}
void bmo_pointmerge_exec(BMesh *bm, BMOperator *op)
{
- BMOperator weldop;
- BMOIter siter;
- BMVert *v, *vert_snap = NULL;
- float vec[3];
- BMOpSlot *slot_targetmap;
-
- BMO_slot_vec_get(op->slots_in, "merge_co", vec);
-
- //BMO_op_callf(bm, op->flag, "collapse_uvs edges=%s", op, "edges");
- BMO_op_init(bm, &weldop, op->flag, "weld_verts");
-
- slot_targetmap = BMO_slot_get(weldop.slots_in, "targetmap");
-
- BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
- if (!vert_snap) {
- vert_snap = v;
- copy_v3_v3(vert_snap->co, vec);
- }
- else {
- BMO_slot_map_elem_insert(&weldop, slot_targetmap, v, vert_snap);
- }
- }
-
- BMO_op_exec(bm, &weldop);
- BMO_op_finish(bm, &weldop);
+ BMOperator weldop;
+ BMOIter siter;
+ BMVert *v, *vert_snap = NULL;
+ float vec[3];
+ BMOpSlot *slot_targetmap;
+
+ BMO_slot_vec_get(op->slots_in, "merge_co", vec);
+
+ //BMO_op_callf(bm, op->flag, "collapse_uvs edges=%s", op, "edges");
+ BMO_op_init(bm, &weldop, op->flag, "weld_verts");
+
+ slot_targetmap = BMO_slot_get(weldop.slots_in, "targetmap");
+
+ BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
+ if (!vert_snap) {
+ vert_snap = v;
+ copy_v3_v3(vert_snap->co, vec);
+ }
+ else {
+ BMO_slot_map_elem_insert(&weldop, slot_targetmap, v, vert_snap);
+ }
+ }
+
+ BMO_op_exec(bm, &weldop);
+ BMO_op_finish(bm, &weldop);
}
void bmo_collapse_exec(BMesh *bm, BMOperator *op)
{
- BMOperator weldop;
- BMWalker walker;
- BMIter iter;
- BMEdge *e;
- BLI_Stack *edge_stack;
- BMOpSlot *slot_targetmap;
+ BMOperator weldop;
+ BMWalker walker;
+ BMIter iter;
+ BMEdge *e;
+ BLI_Stack *edge_stack;
+ BMOpSlot *slot_targetmap;
- if (BMO_slot_bool_get(op->slots_in, "uvs")) {
- BMO_op_callf(bm, op->flag, "collapse_uvs edges=%s", op, "edges");
- }
+ if (BMO_slot_bool_get(op->slots_in, "uvs")) {
+ BMO_op_callf(bm, op->flag, "collapse_uvs edges=%s", op, "edges");
+ }
- BMO_op_init(bm, &weldop, op->flag, "weld_verts");
- slot_targetmap = BMO_slot_get(weldop.slots_in, "targetmap");
+ BMO_op_init(bm, &weldop, op->flag, "weld_verts");
+ slot_targetmap = BMO_slot_get(weldop.slots_in, "targetmap");
- BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK);
+ BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK);
- BMW_init(&walker, bm, BMW_VERT_SHELL,
- BMW_MASK_NOP, EDGE_MARK, BMW_MASK_NOP,
- BMW_FLAG_NOP, /* no need to use BMW_FLAG_TEST_HIDDEN, already marked data */
- BMW_NIL_LAY);
+ BMW_init(&walker,
+ bm,
+ BMW_VERT_SHELL,
+ BMW_MASK_NOP,
+ EDGE_MARK,
+ BMW_MASK_NOP,
+ BMW_FLAG_NOP, /* no need to use BMW_FLAG_TEST_HIDDEN, already marked data */
+ BMW_NIL_LAY);
- edge_stack = BLI_stack_new(sizeof(BMEdge *), __func__);
+ edge_stack = BLI_stack_new(sizeof(BMEdge *), __func__);
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- float center[3];
- int count = 0;
- BMVert *v_tar;
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ float center[3];
+ int count = 0;
+ BMVert *v_tar;
- zero_v3(center);
+ zero_v3(center);
- if (!BMO_edge_flag_test(bm, e, EDGE_MARK)) {
- continue;
- }
+ if (!BMO_edge_flag_test(bm, e, EDGE_MARK)) {
+ continue;
+ }
- BLI_assert(BLI_stack_is_empty(edge_stack));
+ BLI_assert(BLI_stack_is_empty(edge_stack));
- for (e = BMW_begin(&walker, e->v1); e; e = BMW_step(&walker)) {
- BLI_stack_push(edge_stack, &e);
+ for (e = BMW_begin(&walker, e->v1); e; e = BMW_step(&walker)) {
+ BLI_stack_push(edge_stack, &e);
- add_v3_v3(center, e->v1->co);
- add_v3_v3(center, e->v2->co);
+ add_v3_v3(center, e->v1->co);
+ add_v3_v3(center, e->v2->co);
- count += 2;
+ count += 2;
- /* prevent adding to slot_targetmap multiple times */
- BM_elem_flag_disable(e->v1, BM_ELEM_TAG);
- BM_elem_flag_disable(e->v2, BM_ELEM_TAG);
- }
+ /* prevent adding to slot_targetmap multiple times */
+ BM_elem_flag_disable(e->v1, BM_ELEM_TAG);
+ BM_elem_flag_disable(e->v2, BM_ELEM_TAG);
+ }
- if (!BLI_stack_is_empty(edge_stack)) {
- mul_v3_fl(center, 1.0f / count);
+ if (!BLI_stack_is_empty(edge_stack)) {
+ mul_v3_fl(center, 1.0f / count);
- /* snap edges to a point. for initial testing purposes anyway */
- e = *(BMEdge **)BLI_stack_peek(edge_stack);
- v_tar = e->v1;
+ /* snap edges to a point. for initial testing purposes anyway */
+ e = *(BMEdge **)BLI_stack_peek(edge_stack);
+ v_tar = e->v1;
- while (!BLI_stack_is_empty(edge_stack)) {
- uint j;
- BLI_stack_pop(edge_stack, &e);
+ while (!BLI_stack_is_empty(edge_stack)) {
+ uint j;
+ BLI_stack_pop(edge_stack, &e);
- for (j = 0; j < 2; j++) {
- BMVert *v_src = *((&e->v1) + j);
+ for (j = 0; j < 2; j++) {
+ BMVert *v_src = *((&e->v1) + j);
- copy_v3_v3(v_src->co, center);
- if ((v_src != v_tar) && !BM_elem_flag_test(v_src, BM_ELEM_TAG)) {
- BM_elem_flag_enable(v_src, BM_ELEM_TAG);
- BMO_slot_map_elem_insert(&weldop, slot_targetmap, v_src, v_tar);
- }
- }
- }
- }
- }
+ copy_v3_v3(v_src->co, center);
+ if ((v_src != v_tar) && !BM_elem_flag_test(v_src, BM_ELEM_TAG)) {
+ BM_elem_flag_enable(v_src, BM_ELEM_TAG);
+ BMO_slot_map_elem_insert(&weldop, slot_targetmap, v_src, v_tar);
+ }
+ }
+ }
+ }
+ }
- BLI_stack_free(edge_stack);
+ BLI_stack_free(edge_stack);
- BMO_op_exec(bm, &weldop);
- BMO_op_finish(bm, &weldop);
+ BMO_op_exec(bm, &weldop);
+ BMO_op_finish(bm, &weldop);
- BMW_end(&walker);
+ BMW_end(&walker);
}
/* uv collapse function */
static void bmo_collapsecon_do_layer(BMesh *bm, const int layer, const short oflag)
{
- const int type = bm->ldata.layers[layer].type;
- const int offset = bm->ldata.layers[layer].offset;
- BMIter iter, liter;
- BMFace *f;
- BMLoop *l, *l2;
- BMWalker walker;
- BLI_Stack *block_stack;
- CDBlockBytes min, max;
-
- BMW_init(&walker, bm, BMW_LOOPDATA_ISLAND,
- BMW_MASK_NOP, oflag, BMW_MASK_NOP,
- BMW_FLAG_NOP, /* no need to use BMW_FLAG_TEST_HIDDEN, already marked data */
- layer);
-
- block_stack = BLI_stack_new(sizeof(void *), __func__);
-
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- if (BMO_edge_flag_test(bm, l->e, oflag)) {
- /* walk */
- BLI_assert(BLI_stack_is_empty(block_stack));
-
- CustomData_data_initminmax(type, &min, &max);
- for (l2 = BMW_begin(&walker, l); l2; l2 = BMW_step(&walker)) {
- void *block = BM_ELEM_CD_GET_VOID_P(l2, offset);
- CustomData_data_dominmax(type, block, &min, &max);
- BLI_stack_push(block_stack, &block);
- }
-
- if (!BLI_stack_is_empty(block_stack)) {
- CustomData_data_multiply(type, &min, 0.5f);
- CustomData_data_multiply(type, &max, 0.5f);
- CustomData_data_add(type, &min, &max);
-
- /* snap CD (uv, vcol) points to their centroid */
- while (!BLI_stack_is_empty(block_stack)) {
- void *block;
- BLI_stack_pop(block_stack, &block);
- CustomData_data_copy_value(type, &min, block);
- }
- }
- }
- }
- }
-
- BLI_stack_free(block_stack);
-
- BMW_end(&walker);
+ const int type = bm->ldata.layers[layer].type;
+ const int offset = bm->ldata.layers[layer].offset;
+ BMIter iter, liter;
+ BMFace *f;
+ BMLoop *l, *l2;
+ BMWalker walker;
+ BLI_Stack *block_stack;
+ CDBlockBytes min, max;
+
+ BMW_init(&walker,
+ bm,
+ BMW_LOOPDATA_ISLAND,
+ BMW_MASK_NOP,
+ oflag,
+ BMW_MASK_NOP,
+ BMW_FLAG_NOP, /* no need to use BMW_FLAG_TEST_HIDDEN, already marked data */
+ layer);
+
+ block_stack = BLI_stack_new(sizeof(void *), __func__);
+
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ if (BMO_edge_flag_test(bm, l->e, oflag)) {
+ /* walk */
+ BLI_assert(BLI_stack_is_empty(block_stack));
+
+ CustomData_data_initminmax(type, &min, &max);
+ for (l2 = BMW_begin(&walker, l); l2; l2 = BMW_step(&walker)) {
+ void *block = BM_ELEM_CD_GET_VOID_P(l2, offset);
+ CustomData_data_dominmax(type, block, &min, &max);
+ BLI_stack_push(block_stack, &block);
+ }
+
+ if (!BLI_stack_is_empty(block_stack)) {
+ CustomData_data_multiply(type, &min, 0.5f);
+ CustomData_data_multiply(type, &max, 0.5f);
+ CustomData_data_add(type, &min, &max);
+
+ /* snap CD (uv, vcol) points to their centroid */
+ while (!BLI_stack_is_empty(block_stack)) {
+ void *block;
+ BLI_stack_pop(block_stack, &block);
+ CustomData_data_copy_value(type, &min, block);
+ }
+ }
+ }
+ }
+ }
+
+ BLI_stack_free(block_stack);
+
+ BMW_end(&walker);
}
void bmo_collapse_uvs_exec(BMesh *bm, BMOperator *op)
{
- const short oflag = EDGE_MARK;
- int i;
+ const short oflag = EDGE_MARK;
+ int i;
- /* check flags dont change once set */
+ /* check flags dont change once set */
#ifndef NDEBUG
- int tot_test;
+ int tot_test;
#endif
- if (!CustomData_has_math(&bm->ldata)) {
- return;
- }
+ if (!CustomData_has_math(&bm->ldata)) {
+ return;
+ }
- BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, oflag);
+ BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, oflag);
#ifndef NDEBUG
- tot_test = BM_iter_mesh_count_flag(BM_EDGES_OF_MESH, bm, oflag, true);
+ tot_test = BM_iter_mesh_count_flag(BM_EDGES_OF_MESH, bm, oflag, true);
#endif
- for (i = 0; i < bm->ldata.totlayer; i++) {
- if (CustomData_layer_has_math(&bm->ldata, i)) {
- bmo_collapsecon_do_layer(bm, i, oflag);
- }
- }
+ for (i = 0; i < bm->ldata.totlayer; i++) {
+ if (CustomData_layer_has_math(&bm->ldata, i)) {
+ bmo_collapsecon_do_layer(bm, i, oflag);
+ }
+ }
#ifndef NDEBUG
- BLI_assert(tot_test == BM_iter_mesh_count_flag(BM_EDGES_OF_MESH, bm, EDGE_MARK, true));
+ BLI_assert(tot_test == BM_iter_mesh_count_flag(BM_EDGES_OF_MESH, bm, EDGE_MARK, true));
#endif
-
}
-static void bmesh_find_doubles_common(
- BMesh *bm, BMOperator *op,
- BMOperator *optarget, BMOpSlot *optarget_slot)
+static void bmesh_find_doubles_common(BMesh *bm,
+ BMOperator *op,
+ BMOperator *optarget,
+ BMOpSlot *optarget_slot)
{
- const BMOpSlot *slot_verts = BMO_slot_get(op->slots_in, "verts");
- BMVert * const *verts = (BMVert **)slot_verts->data.buf;
- const int verts_len = slot_verts->len;
-
- bool has_keep_vert = false;
- bool found_duplicates = false;
-
- const float dist = BMO_slot_float_get(op->slots_in, "dist");
-
- /* Test whether keep_verts arg exists and is non-empty */
- if (BMO_slot_exists(op->slots_in, "keep_verts")) {
- BMOIter oiter;
- has_keep_vert = BMO_iter_new(&oiter, op->slots_in, "keep_verts", BM_VERT) != NULL;
- }
-
- /* Flag keep_verts */
- if (has_keep_vert) {
- BMO_slot_buffer_flag_enable(bm, op->slots_in, "keep_verts", BM_VERT, VERT_KEEP);
- }
-
- int *duplicates = MEM_mallocN(sizeof(int) * verts_len, __func__);
- {
- KDTree_3d *tree = BLI_kdtree_3d_new(verts_len);
- for (int i = 0; i < verts_len; i++) {
- BLI_kdtree_3d_insert(tree, i, verts[i]->co);
- if (has_keep_vert && BMO_vert_flag_test(bm, verts[i], VERT_KEEP)) {
- duplicates[i] = i;
- }
- else {
- duplicates[i] = -1;
- }
- }
-
- BLI_kdtree_3d_balance(tree);
- found_duplicates = BLI_kdtree_3d_calc_duplicates_fast(tree, dist, false, duplicates) != 0;
- BLI_kdtree_3d_free(tree);
- }
-
- if (found_duplicates) {
- for (int i = 0; i < verts_len; i++) {
- BMVert *v_check = verts[i];
- if (duplicates[i] == -1) {
- /* nop (others can use as target) */
- }
- else if (duplicates[i] == i) {
- /* keep (others can use as target) */
- }
- else {
- BMVert *v_other = verts[duplicates[i]];
- BLI_assert(ELEM(duplicates[duplicates[i]], -1, duplicates[i]));
- BMO_slot_map_elem_insert(optarget, optarget_slot, v_check, v_other);
- }
- }
- }
-
- MEM_freeN(duplicates);
+ const BMOpSlot *slot_verts = BMO_slot_get(op->slots_in, "verts");
+ BMVert *const *verts = (BMVert **)slot_verts->data.buf;
+ const int verts_len = slot_verts->len;
+
+ bool has_keep_vert = false;
+ bool found_duplicates = false;
+
+ const float dist = BMO_slot_float_get(op->slots_in, "dist");
+
+ /* Test whether keep_verts arg exists and is non-empty */
+ if (BMO_slot_exists(op->slots_in, "keep_verts")) {
+ BMOIter oiter;
+ has_keep_vert = BMO_iter_new(&oiter, op->slots_in, "keep_verts", BM_VERT) != NULL;
+ }
+
+ /* Flag keep_verts */
+ if (has_keep_vert) {
+ BMO_slot_buffer_flag_enable(bm, op->slots_in, "keep_verts", BM_VERT, VERT_KEEP);
+ }
+
+ int *duplicates = MEM_mallocN(sizeof(int) * verts_len, __func__);
+ {
+ KDTree_3d *tree = BLI_kdtree_3d_new(verts_len);
+ for (int i = 0; i < verts_len; i++) {
+ BLI_kdtree_3d_insert(tree, i, verts[i]->co);
+ if (has_keep_vert && BMO_vert_flag_test(bm, verts[i], VERT_KEEP)) {
+ duplicates[i] = i;
+ }
+ else {
+ duplicates[i] = -1;
+ }
+ }
+
+ BLI_kdtree_3d_balance(tree);
+ found_duplicates = BLI_kdtree_3d_calc_duplicates_fast(tree, dist, false, duplicates) != 0;
+ BLI_kdtree_3d_free(tree);
+ }
+
+ if (found_duplicates) {
+ for (int i = 0; i < verts_len; i++) {
+ BMVert *v_check = verts[i];
+ if (duplicates[i] == -1) {
+ /* nop (others can use as target) */
+ }
+ else if (duplicates[i] == i) {
+ /* keep (others can use as target) */
+ }
+ else {
+ BMVert *v_other = verts[duplicates[i]];
+ BLI_assert(ELEM(duplicates[duplicates[i]], -1, duplicates[i]));
+ BMO_slot_map_elem_insert(optarget, optarget_slot, v_check, v_other);
+ }
+ }
+ }
+
+ MEM_freeN(duplicates);
}
void bmo_remove_doubles_exec(BMesh *bm, BMOperator *op)
{
- BMOperator weldop;
- BMOpSlot *slot_targetmap;
-
- BMO_op_init(bm, &weldop, op->flag, "weld_verts");
- slot_targetmap = BMO_slot_get(weldop.slots_in, "targetmap");
- bmesh_find_doubles_common(bm, op,
- &weldop, slot_targetmap);
- BMO_op_exec(bm, &weldop);
- BMO_op_finish(bm, &weldop);
+ BMOperator weldop;
+ BMOpSlot *slot_targetmap;
+
+ BMO_op_init(bm, &weldop, op->flag, "weld_verts");
+ slot_targetmap = BMO_slot_get(weldop.slots_in, "targetmap");
+ bmesh_find_doubles_common(bm, op, &weldop, slot_targetmap);
+ BMO_op_exec(bm, &weldop);
+ BMO_op_finish(bm, &weldop);
}
-
void bmo_find_doubles_exec(BMesh *bm, BMOperator *op)
{
- BMOpSlot *slot_targetmap_out;
- slot_targetmap_out = BMO_slot_get(op->slots_out, "targetmap.out");
- bmesh_find_doubles_common(bm, op,
- op, slot_targetmap_out);
+ BMOpSlot *slot_targetmap_out;
+ slot_targetmap_out = BMO_slot_get(op->slots_out, "targetmap.out");
+ bmesh_find_doubles_common(bm, op, op, slot_targetmap_out);
}
void bmo_automerge_exec(BMesh *bm, BMOperator *op)
{
- BMOperator findop, weldop;
- BMIter viter;
- BMVert *v;
-
- /* The "verts" input sent to this op is the set of verts that
- * can be merged away into any other verts. Mark all other verts
- * as VERT_KEEP. */
- BMO_slot_buffer_flag_enable(bm, op->slots_in, "verts", BM_VERT, VERT_IN);
- BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
- if (!BMO_vert_flag_test(bm, v, VERT_IN)) {
- BMO_vert_flag_enable(bm, v, VERT_KEEP);
- }
- }
-
- /* Search for doubles among all vertices, but only merge non-VERT_KEEP
- * vertices into VERT_KEEP vertices. */
- BMO_op_initf(bm, &findop, op->flag, "find_doubles verts=%av keep_verts=%fv", VERT_KEEP);
- BMO_slot_copy(op, slots_in, "dist",
- &findop, slots_in, "dist");
- BMO_op_exec(bm, &findop);
-
- /* weld the vertices */
- BMO_op_init(bm, &weldop, op->flag, "weld_verts");
- BMO_slot_copy(&findop, slots_out, "targetmap.out",
- &weldop, slots_in, "targetmap");
- BMO_op_exec(bm, &weldop);
-
- BMO_op_finish(bm, &findop);
- BMO_op_finish(bm, &weldop);
+ BMOperator findop, weldop;
+ BMIter viter;
+ BMVert *v;
+
+ /* The "verts" input sent to this op is the set of verts that
+ * can be merged away into any other verts. Mark all other verts
+ * as VERT_KEEP. */
+ BMO_slot_buffer_flag_enable(bm, op->slots_in, "verts", BM_VERT, VERT_IN);
+ BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
+ if (!BMO_vert_flag_test(bm, v, VERT_IN)) {
+ BMO_vert_flag_enable(bm, v, VERT_KEEP);
+ }
+ }
+
+ /* Search for doubles among all vertices, but only merge non-VERT_KEEP
+ * vertices into VERT_KEEP vertices. */
+ BMO_op_initf(bm, &findop, op->flag, "find_doubles verts=%av keep_verts=%fv", VERT_KEEP);
+ BMO_slot_copy(op, slots_in, "dist", &findop, slots_in, "dist");
+ BMO_op_exec(bm, &findop);
+
+ /* weld the vertices */
+ BMO_op_init(bm, &weldop, op->flag, "weld_verts");
+ BMO_slot_copy(&findop, slots_out, "targetmap.out", &weldop, slots_in, "targetmap");
+ BMO_op_exec(bm, &weldop);
+
+ BMO_op_finish(bm, &findop);
+ BMO_op_finish(bm, &weldop);
}
diff --git a/source/blender/bmesh/operators/bmo_rotate_edges.c b/source/blender/bmesh/operators/bmo_rotate_edges.c
index bfc7ba75763..e017806df0d 100644
--- a/source/blender/bmesh/operators/bmo_rotate_edges.c
+++ b/source/blender/bmesh/operators/bmo_rotate_edges.c
@@ -29,33 +29,33 @@
#include "intern/bmesh_operators_private.h" /* own include */
-#define EDGE_OUT 1
+#define EDGE_OUT 1
#define FACE_MARK 1
/**
* Rotate edges where every edge has it's own faces (we can rotate in any order).
*/
-static void bm_rotate_edges_simple(
- BMesh *bm, BMOperator *op,
- const short check_flag, const bool use_ccw)
+static void bm_rotate_edges_simple(BMesh *bm,
+ BMOperator *op,
+ const short check_flag,
+ const bool use_ccw)
{
- BMOIter siter;
- BMEdge *e;
-
- BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
- /**
- * this ends up being called twice, could add option to not to call check in
- * #BM_edge_rotate to get some extra speed */
- if (BM_edge_rotate_check(e)) {
- BMEdge *e_rotate = BM_edge_rotate(bm, e, use_ccw, check_flag);
- if (e_rotate != NULL) {
- BMO_edge_flag_enable(bm, e_rotate, EDGE_OUT);
- }
- }
- }
+ BMOIter siter;
+ BMEdge *e;
+
+ BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
+ /**
+ * this ends up being called twice, could add option to not to call check in
+ * #BM_edge_rotate to get some extra speed */
+ if (BM_edge_rotate_check(e)) {
+ BMEdge *e_rotate = BM_edge_rotate(bm, e, use_ccw, check_flag);
+ if (e_rotate != NULL) {
+ BMO_edge_flag_enable(bm, e_rotate, EDGE_OUT);
+ }
+ }
+ }
}
-
/**
* Edge length is just a way of ordering that's independent of order in the edges argument,
* we could use some other method since ideally all edges will be rotated,
@@ -63,7 +63,7 @@ static void bm_rotate_edges_simple(
*/
static float bm_edge_calc_rotate_cost(const BMEdge *e)
{
- return -BM_edge_calc_length_squared(e);
+ return -BM_edge_calc_length_squared(e);
}
/**
@@ -71,25 +71,25 @@ static float bm_edge_calc_rotate_cost(const BMEdge *e)
*/
static float bm_edge_rotate_is_boundary(const BMEdge *e)
{
- /* Number of adjacent shared faces. */
- int count = 0;
- BMLoop *l_radial_iter = e->l;
- do {
- /* Skip this edge. */
- BMLoop *l_iter = l_radial_iter->next;
- do {
- BMEdge *e_iter = l_iter->e;
- const int e_iter_index = BM_elem_index_get(e_iter);
- if ((e_iter_index != -1)) {
- if (count == 1) {
- return false;
- }
- count += 1;
- break;
- }
- } while ((l_iter = l_iter->next) != l_radial_iter);
- } while ((l_radial_iter = l_radial_iter->radial_next) != e->l);
- return true;
+ /* Number of adjacent shared faces. */
+ int count = 0;
+ BMLoop *l_radial_iter = e->l;
+ do {
+ /* Skip this edge. */
+ BMLoop *l_iter = l_radial_iter->next;
+ do {
+ BMEdge *e_iter = l_iter->e;
+ const int e_iter_index = BM_elem_index_get(e_iter);
+ if ((e_iter_index != -1)) {
+ if (count == 1) {
+ return false;
+ }
+ count += 1;
+ break;
+ }
+ } while ((l_iter = l_iter->next) != l_radial_iter);
+ } while ((l_radial_iter = l_radial_iter->radial_next) != e->l);
+ return true;
}
/**
@@ -97,172 +97,171 @@ static float bm_edge_rotate_is_boundary(const BMEdge *e)
* edges which could not rotate need to be re-considered after neighbors are rotated.
*/
static void bm_rotate_edges_shared(
- BMesh *bm, BMOperator *op,
- short check_flag, const bool use_ccw, const int edges_len)
+ BMesh *bm, BMOperator *op, short check_flag, const bool use_ccw, const int edges_len)
{
- Heap *heap = BLI_heap_new_ex(edges_len);
- HeapNode **eheap_table = MEM_mallocN(sizeof(*eheap_table) * edges_len, __func__);
- int edges_len_rotate = 0;
-
- {
- BMIter iter;
- BMEdge *e;
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- BM_elem_index_set(e, -1); /* set_dirty! */
- }
- bm->elem_index_dirty |= BM_EDGE;
- }
-
- {
- BMOIter siter;
- BMEdge *e;
- uint i;
- BMO_ITER_INDEX (e, &siter, op->slots_in, "edges", BM_EDGE, i) {
- BM_elem_index_set(e, BM_edge_is_manifold(e) ? i : -1); /* set_dirty! */
- eheap_table[i] = NULL;
- }
- }
-
- /* First operate on boundary edges, this is often all that's needed,
- * regions that have no boundaries are handles after. */
- enum {
- PASS_TYPE_BOUNDARY = 0,
- PASS_TYPE_ALL = 1,
- PASS_TYPE_DONE = 2,
- };
- uint pass_type = PASS_TYPE_BOUNDARY;
-
-
- while ((pass_type != PASS_TYPE_DONE) && (edges_len_rotate != edges_len)) {
- BLI_assert(BLI_heap_is_empty(heap));
- {
- BMOIter siter;
- BMEdge *e;
- uint i;
- BMO_ITER_INDEX (e, &siter, op->slots_in, "edges", BM_EDGE, i) {
- BLI_assert(eheap_table[i] == NULL);
-
- bool ok = (BM_elem_index_get(e) != -1) && BM_edge_rotate_check(e);
-
- if (ok) {
- if (pass_type == PASS_TYPE_BOUNDARY) {
- ok = bm_edge_rotate_is_boundary(e);
- }
- }
-
- if (ok) {
- float cost = bm_edge_calc_rotate_cost(e);
- if (pass_type == PASS_TYPE_BOUNDARY) {
- /* Trick to ensure once started, non boundaries are handled before other boundary edges.
- * This means the first longest boundary defines the starting point which is rotated
- * until all its connected edges are exhausted and the next boundary is popped off the heap.
- *
- * Without this we may rotate from different starting points and meet in the middle
- * with obviously uneven topology.
- *
- * Move from negative to positive value, inverting so large values are still handled first.
- */
- cost = cost != 0.0f ? -1.0f / cost : FLT_MAX;
- }
- eheap_table[i] = BLI_heap_insert(heap, cost, e);
- }
- }
- }
-
- if (BLI_heap_is_empty(heap)) {
- pass_type += 1;
- continue;
- }
-
- const int edges_len_rotate_prev = edges_len_rotate;
- while (!BLI_heap_is_empty(heap)) {
- BMEdge *e_best = BLI_heap_pop_min(heap);
- eheap_table[BM_elem_index_get(e_best)] = NULL;
-
- /* No problem if this fails, re-evaluate if faces connected to this edge are touched. */
- if (BM_edge_rotate_check(e_best)) {
- BMEdge *e_rotate = BM_edge_rotate(bm, e_best, use_ccw, check_flag);
- if (e_rotate != NULL) {
- BMO_edge_flag_enable(bm, e_rotate, EDGE_OUT);
-
- /* invalidate so we don't try touch this again. */
- BM_elem_index_set(e_rotate, -1); /* set_dirty! */
-
- edges_len_rotate += 1;
-
- /* Note: we could validate all edges which have not been rotated
- * (not just previously degenerate edges).
- * However there is no real need - they can be left until they're popped off the queue. */
-
- /* We don't know the exact topology after rotating the edge,
- * so loop over all faces attached to the new edge, typically this will only be two faces. */
- BMLoop *l_radial_iter = e_rotate->l;
- do {
- /* Skip this edge. */
- BMLoop *l_iter = l_radial_iter->next;
- do {
- BMEdge *e_iter = l_iter->e;
- const int e_iter_index = BM_elem_index_get(e_iter);
- if ((e_iter_index != -1) && (eheap_table[e_iter_index] == NULL)) {
- if (BM_edge_rotate_check(e_iter)) {
- /* Previously degenerate, now valid. */
- float cost = bm_edge_calc_rotate_cost(e_iter);
- eheap_table[e_iter_index] = BLI_heap_insert(heap, cost, e_iter);
- }
- }
- } while ((l_iter = l_iter->next) != l_radial_iter);
- } while ((l_radial_iter = l_radial_iter->radial_next) != e_rotate->l);
- }
- }
- }
-
- /* If no actions were taken, move onto the next pass. */
- if (edges_len_rotate == edges_len_rotate_prev) {
- pass_type += 1;
- continue;
- }
- }
-
- BLI_heap_free(heap, NULL);
- MEM_freeN(eheap_table);
+ Heap *heap = BLI_heap_new_ex(edges_len);
+ HeapNode **eheap_table = MEM_mallocN(sizeof(*eheap_table) * edges_len, __func__);
+ int edges_len_rotate = 0;
+
+ {
+ BMIter iter;
+ BMEdge *e;
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ BM_elem_index_set(e, -1); /* set_dirty! */
+ }
+ bm->elem_index_dirty |= BM_EDGE;
+ }
+
+ {
+ BMOIter siter;
+ BMEdge *e;
+ uint i;
+ BMO_ITER_INDEX(e, &siter, op->slots_in, "edges", BM_EDGE, i)
+ {
+ BM_elem_index_set(e, BM_edge_is_manifold(e) ? i : -1); /* set_dirty! */
+ eheap_table[i] = NULL;
+ }
+ }
+
+ /* First operate on boundary edges, this is often all that's needed,
+ * regions that have no boundaries are handles after. */
+ enum {
+ PASS_TYPE_BOUNDARY = 0,
+ PASS_TYPE_ALL = 1,
+ PASS_TYPE_DONE = 2,
+ };
+ uint pass_type = PASS_TYPE_BOUNDARY;
+
+ while ((pass_type != PASS_TYPE_DONE) && (edges_len_rotate != edges_len)) {
+ BLI_assert(BLI_heap_is_empty(heap));
+ {
+ BMOIter siter;
+ BMEdge *e;
+ uint i;
+ BMO_ITER_INDEX(e, &siter, op->slots_in, "edges", BM_EDGE, i)
+ {
+ BLI_assert(eheap_table[i] == NULL);
+
+ bool ok = (BM_elem_index_get(e) != -1) && BM_edge_rotate_check(e);
+
+ if (ok) {
+ if (pass_type == PASS_TYPE_BOUNDARY) {
+ ok = bm_edge_rotate_is_boundary(e);
+ }
+ }
+
+ if (ok) {
+ float cost = bm_edge_calc_rotate_cost(e);
+ if (pass_type == PASS_TYPE_BOUNDARY) {
+ /* Trick to ensure once started, non boundaries are handled before other boundary edges.
+ * This means the first longest boundary defines the starting point which is rotated
+ * until all its connected edges are exhausted and the next boundary is popped off the heap.
+ *
+ * Without this we may rotate from different starting points and meet in the middle
+ * with obviously uneven topology.
+ *
+ * Move from negative to positive value, inverting so large values are still handled first.
+ */
+ cost = cost != 0.0f ? -1.0f / cost : FLT_MAX;
+ }
+ eheap_table[i] = BLI_heap_insert(heap, cost, e);
+ }
+ }
+ }
+
+ if (BLI_heap_is_empty(heap)) {
+ pass_type += 1;
+ continue;
+ }
+
+ const int edges_len_rotate_prev = edges_len_rotate;
+ while (!BLI_heap_is_empty(heap)) {
+ BMEdge *e_best = BLI_heap_pop_min(heap);
+ eheap_table[BM_elem_index_get(e_best)] = NULL;
+
+ /* No problem if this fails, re-evaluate if faces connected to this edge are touched. */
+ if (BM_edge_rotate_check(e_best)) {
+ BMEdge *e_rotate = BM_edge_rotate(bm, e_best, use_ccw, check_flag);
+ if (e_rotate != NULL) {
+ BMO_edge_flag_enable(bm, e_rotate, EDGE_OUT);
+
+ /* invalidate so we don't try touch this again. */
+ BM_elem_index_set(e_rotate, -1); /* set_dirty! */
+
+ edges_len_rotate += 1;
+
+ /* Note: we could validate all edges which have not been rotated
+ * (not just previously degenerate edges).
+ * However there is no real need - they can be left until they're popped off the queue. */
+
+ /* We don't know the exact topology after rotating the edge,
+ * so loop over all faces attached to the new edge, typically this will only be two faces. */
+ BMLoop *l_radial_iter = e_rotate->l;
+ do {
+ /* Skip this edge. */
+ BMLoop *l_iter = l_radial_iter->next;
+ do {
+ BMEdge *e_iter = l_iter->e;
+ const int e_iter_index = BM_elem_index_get(e_iter);
+ if ((e_iter_index != -1) && (eheap_table[e_iter_index] == NULL)) {
+ if (BM_edge_rotate_check(e_iter)) {
+ /* Previously degenerate, now valid. */
+ float cost = bm_edge_calc_rotate_cost(e_iter);
+ eheap_table[e_iter_index] = BLI_heap_insert(heap, cost, e_iter);
+ }
+ }
+ } while ((l_iter = l_iter->next) != l_radial_iter);
+ } while ((l_radial_iter = l_radial_iter->radial_next) != e_rotate->l);
+ }
+ }
+ }
+
+ /* If no actions were taken, move onto the next pass. */
+ if (edges_len_rotate == edges_len_rotate_prev) {
+ pass_type += 1;
+ continue;
+ }
+ }
+
+ BLI_heap_free(heap, NULL);
+ MEM_freeN(eheap_table);
}
void bmo_rotate_edges_exec(BMesh *bm, BMOperator *op)
{
- BMOIter siter;
- BMEdge *e;
- const int edges_len = BMO_slot_buffer_count(op->slots_in, "edges");
- const bool use_ccw = BMO_slot_bool_get(op->slots_in, "use_ccw");
- const bool is_single = (edges_len == 1);
- short check_flag = is_single ?
- BM_EDGEROT_CHECK_EXISTS :
- BM_EDGEROT_CHECK_EXISTS | BM_EDGEROT_CHECK_DEGENERATE;
-
- bool is_simple = true;
- if (is_single == false) {
- BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
- BMFace *f_pair[2];
- if (BM_edge_face_pair(e, &f_pair[0], &f_pair[1])) {
- for (uint i = 0; i < ARRAY_SIZE(f_pair); i += 1) {
- if (BMO_face_flag_test(bm, f_pair[i], FACE_MARK)) {
- is_simple = false;
- break;
- }
- BMO_face_flag_enable(bm, f_pair[i], FACE_MARK);
- }
- if (is_simple == false) {
- break;
- }
- }
- }
- }
-
- if (is_simple) {
- bm_rotate_edges_simple(bm, op, check_flag, use_ccw);
- }
- else {
- bm_rotate_edges_shared(bm, op, check_flag, use_ccw, edges_len);
- }
-
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT);
+ BMOIter siter;
+ BMEdge *e;
+ const int edges_len = BMO_slot_buffer_count(op->slots_in, "edges");
+ const bool use_ccw = BMO_slot_bool_get(op->slots_in, "use_ccw");
+ const bool is_single = (edges_len == 1);
+ short check_flag = is_single ? BM_EDGEROT_CHECK_EXISTS :
+ BM_EDGEROT_CHECK_EXISTS | BM_EDGEROT_CHECK_DEGENERATE;
+
+ bool is_simple = true;
+ if (is_single == false) {
+ BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
+ BMFace *f_pair[2];
+ if (BM_edge_face_pair(e, &f_pair[0], &f_pair[1])) {
+ for (uint i = 0; i < ARRAY_SIZE(f_pair); i += 1) {
+ if (BMO_face_flag_test(bm, f_pair[i], FACE_MARK)) {
+ is_simple = false;
+ break;
+ }
+ BMO_face_flag_enable(bm, f_pair[i], FACE_MARK);
+ }
+ if (is_simple == false) {
+ break;
+ }
+ }
+ }
+ }
+
+ if (is_simple) {
+ bm_rotate_edges_simple(bm, op, check_flag, use_ccw);
+ }
+ else {
+ bm_rotate_edges_shared(bm, op, check_flag, use_ccw, edges_len);
+ }
+
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT);
}
diff --git a/source/blender/bmesh/operators/bmo_smooth_laplacian.c b/source/blender/bmesh/operators/bmo_smooth_laplacian.c
index bf376a757ef..85f62241782 100644
--- a/source/blender/bmesh/operators/bmo_smooth_laplacian.c
+++ b/source/blender/bmesh/operators/bmo_smooth_laplacian.c
@@ -26,7 +26,6 @@
#include "eigen_capi.h"
-
#include "bmesh.h"
#include "intern/bmesh_operators_private.h" /* own include */
@@ -37,23 +36,23 @@
#define SMOOTH_LAPLACIAN_MIN_EDGE_PERCENTAGE 0.15f
struct BLaplacianSystem {
- float *eweights; /* Length weights per Edge */
- float (*fweights)[3]; /* Cotangent weights per face */
- float *ring_areas; /* Total area per ring*/
- float *vlengths; /* Total sum of lengths(edges) per vertice*/
- float *vweights; /* Total sum of weights per vertice*/
- int numEdges; /* Number of edges*/
- int numFaces; /* Number of faces*/
- int numVerts; /* Number of verts*/
- short *zerola; /* Is zero area or length*/
-
- /* Pointers to data*/
- BMesh *bm;
- BMOperator *op;
- LinearSolver *context;
-
- /*Data*/
- float min_area;
+ float *eweights; /* Length weights per Edge */
+ float (*fweights)[3]; /* Cotangent weights per face */
+ float *ring_areas; /* Total area per ring*/
+ float *vlengths; /* Total sum of lengths(edges) per vertice*/
+ float *vweights; /* Total sum of weights per vertice*/
+ int numEdges; /* Number of edges*/
+ int numFaces; /* Number of faces*/
+ int numVerts; /* Number of verts*/
+ short *zerola; /* Is zero area or length*/
+
+ /* Pointers to data*/
+ BMesh *bm;
+ BMOperator *op;
+ LinearSolver *context;
+
+ /*Data*/
+ float min_area;
};
typedef struct BLaplacianSystem LaplacianSystem;
@@ -64,87 +63,89 @@ static void delete_laplacian_system(LaplacianSystem *sys);
static void delete_void_pointer(void *data);
static void fill_laplacian_matrix(LaplacianSystem *sys);
static void memset_laplacian_system(LaplacianSystem *sys, int val);
-static void validate_solution(LaplacianSystem *sys, int usex, int usey, int usez, int preserve_volume);
-static void volume_preservation(BMOperator *op, float vini, float vend, int usex, int usey, int usez);
+static void validate_solution(
+ LaplacianSystem *sys, int usex, int usey, int usez, int preserve_volume);
+static void volume_preservation(
+ BMOperator *op, float vini, float vend, int usex, int usey, int usez);
static void delete_void_pointer(void *data)
{
- if (data) {
- MEM_freeN(data);
- }
+ if (data) {
+ MEM_freeN(data);
+ }
}
static void delete_laplacian_system(LaplacianSystem *sys)
{
- delete_void_pointer(sys->eweights);
- delete_void_pointer(sys->fweights);
- delete_void_pointer(sys->ring_areas);
- delete_void_pointer(sys->vlengths);
- delete_void_pointer(sys->vweights);
- delete_void_pointer(sys->zerola);
- if (sys->context) {
- EIG_linear_solver_delete(sys->context);
- }
- sys->bm = NULL;
- sys->op = NULL;
- MEM_freeN(sys);
+ delete_void_pointer(sys->eweights);
+ delete_void_pointer(sys->fweights);
+ delete_void_pointer(sys->ring_areas);
+ delete_void_pointer(sys->vlengths);
+ delete_void_pointer(sys->vweights);
+ delete_void_pointer(sys->zerola);
+ if (sys->context) {
+ EIG_linear_solver_delete(sys->context);
+ }
+ sys->bm = NULL;
+ sys->op = NULL;
+ MEM_freeN(sys);
}
static void memset_laplacian_system(LaplacianSystem *sys, int val)
{
- memset(sys->eweights, val, sizeof(float) * sys->numEdges);
- memset(sys->fweights, val, sizeof(float) * sys->numFaces * 3);
- memset(sys->ring_areas, val, sizeof(float) * sys->numVerts);
- memset(sys->vlengths, val, sizeof(float) * sys->numVerts);
- memset(sys->vweights, val, sizeof(float) * sys->numVerts);
- memset(sys->zerola, val, sizeof(short) * sys->numVerts);
+ memset(sys->eweights, val, sizeof(float) * sys->numEdges);
+ memset(sys->fweights, val, sizeof(float) * sys->numFaces * 3);
+ memset(sys->ring_areas, val, sizeof(float) * sys->numVerts);
+ memset(sys->vlengths, val, sizeof(float) * sys->numVerts);
+ memset(sys->vweights, val, sizeof(float) * sys->numVerts);
+ memset(sys->zerola, val, sizeof(short) * sys->numVerts);
}
static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, int a_numVerts)
{
- LaplacianSystem *sys;
- sys = MEM_callocN(sizeof(LaplacianSystem), "ModLaplSmoothSystem");
- sys->numEdges = a_numEdges;
- sys->numFaces = a_numFaces;
- sys->numVerts = a_numVerts;
-
- sys->eweights = MEM_callocN(sizeof(float) * sys->numEdges, "ModLaplSmoothEWeight");
- if (!sys->eweights) {
- delete_laplacian_system(sys);
- return NULL;
- }
-
- sys->fweights = MEM_callocN(sizeof(float) * 3 * sys->numFaces, "ModLaplSmoothFWeight");
- if (!sys->fweights) {
- delete_laplacian_system(sys);
- return NULL;
- }
-
- sys->ring_areas = MEM_callocN(sizeof(float) * sys->numVerts, "ModLaplSmoothRingAreas");
- if (!sys->ring_areas) {
- delete_laplacian_system(sys);
- return NULL;
- }
-
- sys->vlengths = MEM_callocN(sizeof(float) * sys->numVerts, "ModLaplSmoothVlengths");
- if (!sys->vlengths) {
- delete_laplacian_system(sys);
- return NULL;
- }
-
- sys->vweights = MEM_callocN(sizeof(float) * sys->numVerts, "ModLaplSmoothVweights");
- if (!sys->vweights) {
- delete_laplacian_system(sys);
- return NULL;
- }
-
- sys->zerola = MEM_callocN(sizeof(short) * sys->numVerts, "ModLaplSmoothZeloa");
- if (!sys->zerola) {
- delete_laplacian_system(sys);
- return NULL;
- }
-
- return sys;
+ LaplacianSystem *sys;
+ sys = MEM_callocN(sizeof(LaplacianSystem), "ModLaplSmoothSystem");
+ sys->numEdges = a_numEdges;
+ sys->numFaces = a_numFaces;
+ sys->numVerts = a_numVerts;
+
+ sys->eweights = MEM_callocN(sizeof(float) * sys->numEdges, "ModLaplSmoothEWeight");
+ if (!sys->eweights) {
+ delete_laplacian_system(sys);
+ return NULL;
+ }
+
+ sys->fweights = MEM_callocN(sizeof(float) * 3 * sys->numFaces, "ModLaplSmoothFWeight");
+ if (!sys->fweights) {
+ delete_laplacian_system(sys);
+ return NULL;
+ }
+
+ sys->ring_areas = MEM_callocN(sizeof(float) * sys->numVerts, "ModLaplSmoothRingAreas");
+ if (!sys->ring_areas) {
+ delete_laplacian_system(sys);
+ return NULL;
+ }
+
+ sys->vlengths = MEM_callocN(sizeof(float) * sys->numVerts, "ModLaplSmoothVlengths");
+ if (!sys->vlengths) {
+ delete_laplacian_system(sys);
+ return NULL;
+ }
+
+ sys->vweights = MEM_callocN(sizeof(float) * sys->numVerts, "ModLaplSmoothVweights");
+ if (!sys->vweights) {
+ delete_laplacian_system(sys);
+ return NULL;
+ }
+
+ sys->zerola = MEM_callocN(sizeof(short) * sys->numVerts, "ModLaplSmoothZeloa");
+ if (!sys->zerola) {
+ delete_laplacian_system(sys);
+ return NULL;
+ }
+
+ return sys;
}
/**
@@ -165,387 +166,398 @@ static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, in
static void init_laplacian_matrix(LaplacianSystem *sys)
{
- float areaf;
- float *v1, *v2, *v3, *v4;
- float w1, w2, w3, w4;
- int i, j;
- bool has_4_vert;
- uint idv1, idv2, idv3, idv4, idv[4];
- BMEdge *e;
- BMFace *f;
- BMIter eiter;
- BMIter fiter;
- BMIter vi;
- BMVert *vn;
- BMVert *vf[4];
-
- BM_ITER_MESH_INDEX (e, &eiter, sys->bm, BM_EDGES_OF_MESH, j) {
- if (!BM_elem_flag_test(e, BM_ELEM_SELECT) && BM_edge_is_boundary(e)) {
- v1 = e->v1->co;
- v2 = e->v2->co;
- idv1 = BM_elem_index_get(e->v1);
- idv2 = BM_elem_index_get(e->v2);
-
- w1 = len_v3v3(v1, v2);
- if (w1 > sys->min_area) {
- w1 = 1.0f / w1;
- i = BM_elem_index_get(e);
- sys->eweights[i] = w1;
- sys->vlengths[idv1] += w1;
- sys->vlengths[idv2] += w1;
- }
- else {
- sys->zerola[idv1] = 1;
- sys->zerola[idv2] = 1;
- }
- }
- }
-
- BM_ITER_MESH (f, &fiter, sys->bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
-
- BM_ITER_ELEM_INDEX (vn, &vi, f, BM_VERTS_OF_FACE, i) {
- vf[i] = vn;
- }
- has_4_vert = (i == 4) ? 1 : 0;
- idv1 = BM_elem_index_get(vf[0]);
- idv2 = BM_elem_index_get(vf[1]);
- idv3 = BM_elem_index_get(vf[2]);
- idv4 = has_4_vert ? BM_elem_index_get(vf[3]) : 0;
-
- v1 = vf[0]->co;
- v2 = vf[1]->co;
- v3 = vf[2]->co;
- v4 = has_4_vert ? vf[3]->co : NULL;
-
- if (has_4_vert) {
- areaf = area_quad_v3(v1, v2, v3, v4);
- }
- else {
- areaf = area_tri_v3(v1, v2, v3);
- }
-
- if (fabsf(areaf) < sys->min_area) {
- sys->zerola[idv1] = 1;
- sys->zerola[idv2] = 1;
- sys->zerola[idv3] = 1;
- if (has_4_vert) {
- sys->zerola[idv4] = 1;
- }
- }
-
- sys->ring_areas[idv1] += areaf;
- sys->ring_areas[idv2] += areaf;
- sys->ring_areas[idv3] += areaf;
- if (has_4_vert) {
- sys->ring_areas[idv4] += areaf;
- }
-
- if (has_4_vert) {
-
- idv[0] = idv1;
- idv[1] = idv2;
- idv[2] = idv3;
- idv[3] = idv4;
-
- for (j = 0; j < 4; j++) {
- idv1 = idv[j];
- idv2 = idv[(j + 1) % 4];
- idv3 = idv[(j + 2) % 4];
- idv4 = idv[(j + 3) % 4];
-
- v1 = vf[j]->co;
- v2 = vf[(j + 1) % 4]->co;
- v3 = vf[(j + 2) % 4]->co;
- v4 = vf[(j + 3) % 4]->co;
-
- w2 = cotangent_tri_weight_v3(v4, v1, v2) + cotangent_tri_weight_v3(v3, v1, v2);
- w3 = cotangent_tri_weight_v3(v2, v3, v1) + cotangent_tri_weight_v3(v4, v1, v3);
- w4 = cotangent_tri_weight_v3(v2, v4, v1) + cotangent_tri_weight_v3(v3, v4, v1);
-
- sys->vweights[idv1] += (w2 + w3 + w4) / 4.0f;
- }
- }
- else {
- i = BM_elem_index_get(f);
-
- w1 = cotangent_tri_weight_v3(v1, v2, v3);
- w2 = cotangent_tri_weight_v3(v2, v3, v1);
- w3 = cotangent_tri_weight_v3(v3, v1, v2);
-
- sys->fweights[i][0] += w1;
- sys->fweights[i][1] += w2;
- sys->fweights[i][2] += w3;
-
- sys->vweights[idv1] += w2 + w3;
- sys->vweights[idv2] += w1 + w3;
- sys->vweights[idv3] += w1 + w2;
- }
- }
- }
+ float areaf;
+ float *v1, *v2, *v3, *v4;
+ float w1, w2, w3, w4;
+ int i, j;
+ bool has_4_vert;
+ uint idv1, idv2, idv3, idv4, idv[4];
+ BMEdge *e;
+ BMFace *f;
+ BMIter eiter;
+ BMIter fiter;
+ BMIter vi;
+ BMVert *vn;
+ BMVert *vf[4];
+
+ BM_ITER_MESH_INDEX (e, &eiter, sys->bm, BM_EDGES_OF_MESH, j) {
+ if (!BM_elem_flag_test(e, BM_ELEM_SELECT) && BM_edge_is_boundary(e)) {
+ v1 = e->v1->co;
+ v2 = e->v2->co;
+ idv1 = BM_elem_index_get(e->v1);
+ idv2 = BM_elem_index_get(e->v2);
+
+ w1 = len_v3v3(v1, v2);
+ if (w1 > sys->min_area) {
+ w1 = 1.0f / w1;
+ i = BM_elem_index_get(e);
+ sys->eweights[i] = w1;
+ sys->vlengths[idv1] += w1;
+ sys->vlengths[idv2] += w1;
+ }
+ else {
+ sys->zerola[idv1] = 1;
+ sys->zerola[idv2] = 1;
+ }
+ }
+ }
+
+ BM_ITER_MESH (f, &fiter, sys->bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+
+ BM_ITER_ELEM_INDEX(vn, &vi, f, BM_VERTS_OF_FACE, i)
+ {
+ vf[i] = vn;
+ }
+ has_4_vert = (i == 4) ? 1 : 0;
+ idv1 = BM_elem_index_get(vf[0]);
+ idv2 = BM_elem_index_get(vf[1]);
+ idv3 = BM_elem_index_get(vf[2]);
+ idv4 = has_4_vert ? BM_elem_index_get(vf[3]) : 0;
+
+ v1 = vf[0]->co;
+ v2 = vf[1]->co;
+ v3 = vf[2]->co;
+ v4 = has_4_vert ? vf[3]->co : NULL;
+
+ if (has_4_vert) {
+ areaf = area_quad_v3(v1, v2, v3, v4);
+ }
+ else {
+ areaf = area_tri_v3(v1, v2, v3);
+ }
+
+ if (fabsf(areaf) < sys->min_area) {
+ sys->zerola[idv1] = 1;
+ sys->zerola[idv2] = 1;
+ sys->zerola[idv3] = 1;
+ if (has_4_vert) {
+ sys->zerola[idv4] = 1;
+ }
+ }
+
+ sys->ring_areas[idv1] += areaf;
+ sys->ring_areas[idv2] += areaf;
+ sys->ring_areas[idv3] += areaf;
+ if (has_4_vert) {
+ sys->ring_areas[idv4] += areaf;
+ }
+
+ if (has_4_vert) {
+
+ idv[0] = idv1;
+ idv[1] = idv2;
+ idv[2] = idv3;
+ idv[3] = idv4;
+
+ for (j = 0; j < 4; j++) {
+ idv1 = idv[j];
+ idv2 = idv[(j + 1) % 4];
+ idv3 = idv[(j + 2) % 4];
+ idv4 = idv[(j + 3) % 4];
+
+ v1 = vf[j]->co;
+ v2 = vf[(j + 1) % 4]->co;
+ v3 = vf[(j + 2) % 4]->co;
+ v4 = vf[(j + 3) % 4]->co;
+
+ w2 = cotangent_tri_weight_v3(v4, v1, v2) + cotangent_tri_weight_v3(v3, v1, v2);
+ w3 = cotangent_tri_weight_v3(v2, v3, v1) + cotangent_tri_weight_v3(v4, v1, v3);
+ w4 = cotangent_tri_weight_v3(v2, v4, v1) + cotangent_tri_weight_v3(v3, v4, v1);
+
+ sys->vweights[idv1] += (w2 + w3 + w4) / 4.0f;
+ }
+ }
+ else {
+ i = BM_elem_index_get(f);
+
+ w1 = cotangent_tri_weight_v3(v1, v2, v3);
+ w2 = cotangent_tri_weight_v3(v2, v3, v1);
+ w3 = cotangent_tri_weight_v3(v3, v1, v2);
+
+ sys->fweights[i][0] += w1;
+ sys->fweights[i][1] += w2;
+ sys->fweights[i][2] += w3;
+
+ sys->vweights[idv1] += w2 + w3;
+ sys->vweights[idv2] += w1 + w3;
+ sys->vweights[idv3] += w1 + w2;
+ }
+ }
+ }
}
static void fill_laplacian_matrix(LaplacianSystem *sys)
{
- float *v1, *v2, *v3, *v4;
- float w2, w3, w4;
- int i, j;
- bool has_4_vert;
- uint idv1, idv2, idv3, idv4, idv[4];
-
- BMEdge *e;
- BMFace *f;
- BMIter eiter;
- BMIter fiter;
- BMIter vi;
- BMVert *vn;
- BMVert *vf[4];
-
- BM_ITER_MESH (f, &fiter, sys->bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- BM_ITER_ELEM_INDEX (vn, &vi, f, BM_VERTS_OF_FACE, i) {
- vf[i] = vn;
- }
- has_4_vert = (i == 4) ? 1 : 0;
- if (has_4_vert) {
- idv[0] = BM_elem_index_get(vf[0]);
- idv[1] = BM_elem_index_get(vf[1]);
- idv[2] = BM_elem_index_get(vf[2]);
- idv[3] = BM_elem_index_get(vf[3]);
- for (j = 0; j < 4; j++) {
- idv1 = idv[j];
- idv2 = idv[(j + 1) % 4];
- idv3 = idv[(j + 2) % 4];
- idv4 = idv[(j + 3) % 4];
-
- v1 = vf[j]->co;
- v2 = vf[(j + 1) % 4]->co;
- v3 = vf[(j + 2) % 4]->co;
- v4 = vf[(j + 3) % 4]->co;
-
- w2 = cotangent_tri_weight_v3(v4, v1, v2) + cotangent_tri_weight_v3(v3, v1, v2);
- w3 = cotangent_tri_weight_v3(v2, v3, v1) + cotangent_tri_weight_v3(v4, v1, v3);
- w4 = cotangent_tri_weight_v3(v2, v4, v1) + cotangent_tri_weight_v3(v3, v4, v1);
-
- w2 = w2 / 4.0f;
- w3 = w3 / 4.0f;
- w4 = w4 / 4.0f;
-
- if (!vert_is_boundary(vf[j]) && sys->zerola[idv1] == 0) {
- EIG_linear_solver_matrix_add(sys->context, idv1, idv2, w2 * sys->vweights[idv1]);
- EIG_linear_solver_matrix_add(sys->context, idv1, idv3, w3 * sys->vweights[idv1]);
- EIG_linear_solver_matrix_add(sys->context, idv1, idv4, w4 * sys->vweights[idv1]);
- }
- }
- }
- else {
- idv1 = BM_elem_index_get(vf[0]);
- idv2 = BM_elem_index_get(vf[1]);
- idv3 = BM_elem_index_get(vf[2]);
- /* Is ring if number of faces == number of edges around vertice*/
- i = BM_elem_index_get(f);
- if (!vert_is_boundary(vf[0]) && sys->zerola[idv1] == 0) {
- EIG_linear_solver_matrix_add(sys->context, idv1, idv2, sys->fweights[i][2] * sys->vweights[idv1]);
- EIG_linear_solver_matrix_add(sys->context, idv1, idv3, sys->fweights[i][1] * sys->vweights[idv1]);
- }
- if (!vert_is_boundary(vf[1]) && sys->zerola[idv2] == 0) {
- EIG_linear_solver_matrix_add(sys->context, idv2, idv1, sys->fweights[i][2] * sys->vweights[idv2]);
- EIG_linear_solver_matrix_add(sys->context, idv2, idv3, sys->fweights[i][0] * sys->vweights[idv2]);
- }
- if (!vert_is_boundary(vf[2]) && sys->zerola[idv3] == 0) {
- EIG_linear_solver_matrix_add(sys->context, idv3, idv1, sys->fweights[i][1] * sys->vweights[idv3]);
- EIG_linear_solver_matrix_add(sys->context, idv3, idv2, sys->fweights[i][0] * sys->vweights[idv3]);
- }
- }
- }
- }
- BM_ITER_MESH (e, &eiter, sys->bm, BM_EDGES_OF_MESH) {
- if (!BM_elem_flag_test(e, BM_ELEM_SELECT) && BM_edge_is_boundary(e)) {
- v1 = e->v1->co;
- v2 = e->v2->co;
- idv1 = BM_elem_index_get(e->v1);
- idv2 = BM_elem_index_get(e->v2);
- if (sys->zerola[idv1] == 0 && sys->zerola[idv2] == 0) {
- i = BM_elem_index_get(e);
- EIG_linear_solver_matrix_add(sys->context, idv1, idv2, sys->eweights[i] * sys->vlengths[idv1]);
- EIG_linear_solver_matrix_add(sys->context, idv2, idv1, sys->eweights[i] * sys->vlengths[idv2]);
- }
- }
- }
+ float *v1, *v2, *v3, *v4;
+ float w2, w3, w4;
+ int i, j;
+ bool has_4_vert;
+ uint idv1, idv2, idv3, idv4, idv[4];
+
+ BMEdge *e;
+ BMFace *f;
+ BMIter eiter;
+ BMIter fiter;
+ BMIter vi;
+ BMVert *vn;
+ BMVert *vf[4];
+
+ BM_ITER_MESH (f, &fiter, sys->bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ BM_ITER_ELEM_INDEX(vn, &vi, f, BM_VERTS_OF_FACE, i)
+ {
+ vf[i] = vn;
+ }
+ has_4_vert = (i == 4) ? 1 : 0;
+ if (has_4_vert) {
+ idv[0] = BM_elem_index_get(vf[0]);
+ idv[1] = BM_elem_index_get(vf[1]);
+ idv[2] = BM_elem_index_get(vf[2]);
+ idv[3] = BM_elem_index_get(vf[3]);
+ for (j = 0; j < 4; j++) {
+ idv1 = idv[j];
+ idv2 = idv[(j + 1) % 4];
+ idv3 = idv[(j + 2) % 4];
+ idv4 = idv[(j + 3) % 4];
+
+ v1 = vf[j]->co;
+ v2 = vf[(j + 1) % 4]->co;
+ v3 = vf[(j + 2) % 4]->co;
+ v4 = vf[(j + 3) % 4]->co;
+
+ w2 = cotangent_tri_weight_v3(v4, v1, v2) + cotangent_tri_weight_v3(v3, v1, v2);
+ w3 = cotangent_tri_weight_v3(v2, v3, v1) + cotangent_tri_weight_v3(v4, v1, v3);
+ w4 = cotangent_tri_weight_v3(v2, v4, v1) + cotangent_tri_weight_v3(v3, v4, v1);
+
+ w2 = w2 / 4.0f;
+ w3 = w3 / 4.0f;
+ w4 = w4 / 4.0f;
+
+ if (!vert_is_boundary(vf[j]) && sys->zerola[idv1] == 0) {
+ EIG_linear_solver_matrix_add(sys->context, idv1, idv2, w2 * sys->vweights[idv1]);
+ EIG_linear_solver_matrix_add(sys->context, idv1, idv3, w3 * sys->vweights[idv1]);
+ EIG_linear_solver_matrix_add(sys->context, idv1, idv4, w4 * sys->vweights[idv1]);
+ }
+ }
+ }
+ else {
+ idv1 = BM_elem_index_get(vf[0]);
+ idv2 = BM_elem_index_get(vf[1]);
+ idv3 = BM_elem_index_get(vf[2]);
+ /* Is ring if number of faces == number of edges around vertice*/
+ i = BM_elem_index_get(f);
+ if (!vert_is_boundary(vf[0]) && sys->zerola[idv1] == 0) {
+ EIG_linear_solver_matrix_add(
+ sys->context, idv1, idv2, sys->fweights[i][2] * sys->vweights[idv1]);
+ EIG_linear_solver_matrix_add(
+ sys->context, idv1, idv3, sys->fweights[i][1] * sys->vweights[idv1]);
+ }
+ if (!vert_is_boundary(vf[1]) && sys->zerola[idv2] == 0) {
+ EIG_linear_solver_matrix_add(
+ sys->context, idv2, idv1, sys->fweights[i][2] * sys->vweights[idv2]);
+ EIG_linear_solver_matrix_add(
+ sys->context, idv2, idv3, sys->fweights[i][0] * sys->vweights[idv2]);
+ }
+ if (!vert_is_boundary(vf[2]) && sys->zerola[idv3] == 0) {
+ EIG_linear_solver_matrix_add(
+ sys->context, idv3, idv1, sys->fweights[i][1] * sys->vweights[idv3]);
+ EIG_linear_solver_matrix_add(
+ sys->context, idv3, idv2, sys->fweights[i][0] * sys->vweights[idv3]);
+ }
+ }
+ }
+ }
+ BM_ITER_MESH (e, &eiter, sys->bm, BM_EDGES_OF_MESH) {
+ if (!BM_elem_flag_test(e, BM_ELEM_SELECT) && BM_edge_is_boundary(e)) {
+ v1 = e->v1->co;
+ v2 = e->v2->co;
+ idv1 = BM_elem_index_get(e->v1);
+ idv2 = BM_elem_index_get(e->v2);
+ if (sys->zerola[idv1] == 0 && sys->zerola[idv2] == 0) {
+ i = BM_elem_index_get(e);
+ EIG_linear_solver_matrix_add(
+ sys->context, idv1, idv2, sys->eweights[i] * sys->vlengths[idv1]);
+ EIG_linear_solver_matrix_add(
+ sys->context, idv2, idv1, sys->eweights[i] * sys->vlengths[idv2]);
+ }
+ }
+ }
}
static bool vert_is_boundary(BMVert *v)
{
- BMEdge *ed;
- BMFace *f;
- BMIter ei;
- BMIter fi;
- BM_ITER_ELEM (ed, &ei, v, BM_EDGES_OF_VERT) {
- if (BM_edge_is_boundary(ed)) {
- return 1;
- }
- }
- BM_ITER_ELEM (f, &fi, v, BM_FACES_OF_VERT) {
- if (!BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- return 1;
- }
- }
- return 0;
+ BMEdge *ed;
+ BMFace *f;
+ BMIter ei;
+ BMIter fi;
+ BM_ITER_ELEM (ed, &ei, v, BM_EDGES_OF_VERT) {
+ if (BM_edge_is_boundary(ed)) {
+ return 1;
+ }
+ }
+ BM_ITER_ELEM (f, &fi, v, BM_FACES_OF_VERT) {
+ if (!BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ return 1;
+ }
+ }
+ return 0;
}
-static void volume_preservation(BMOperator *op, float vini, float vend, int usex, int usey, int usez)
+static void volume_preservation(
+ BMOperator *op, float vini, float vend, int usex, int usey, int usez)
{
- float beta;
- BMOIter siter;
- BMVert *v;
-
- if (vend != 0.0f) {
- beta = pow(vini / vend, 1.0f / 3.0f);
- BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
- if (usex) {
- v->co[0] *= beta;
- }
- if (usey) {
- v->co[1] *= beta;
- }
- if (usez) {
- v->co[2] *= beta;
- }
-
- }
- }
+ float beta;
+ BMOIter siter;
+ BMVert *v;
+
+ if (vend != 0.0f) {
+ beta = pow(vini / vend, 1.0f / 3.0f);
+ BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
+ if (usex) {
+ v->co[0] *= beta;
+ }
+ if (usey) {
+ v->co[1] *= beta;
+ }
+ if (usez) {
+ v->co[2] *= beta;
+ }
+ }
+ }
}
-static void validate_solution(LaplacianSystem *sys, int usex, int usey, int usez, int preserve_volume)
+static void validate_solution(
+ LaplacianSystem *sys, int usex, int usey, int usez, int preserve_volume)
{
- int m_vertex_id;
- float leni, lene;
- float vini, vend;
- float *vi1, *vi2, ve1[3], ve2[3];
- uint idv1, idv2;
- BMOIter siter;
- BMVert *v;
- BMEdge *e;
- BMIter eiter;
-
- BM_ITER_MESH (e, &eiter, sys->bm, BM_EDGES_OF_MESH) {
- idv1 = BM_elem_index_get(e->v1);
- idv2 = BM_elem_index_get(e->v2);
- vi1 = e->v1->co;
- vi2 = e->v2->co;
- ve1[0] = EIG_linear_solver_variable_get(sys->context, 0, idv1);
- ve1[1] = EIG_linear_solver_variable_get(sys->context, 1, idv1);
- ve1[2] = EIG_linear_solver_variable_get(sys->context, 2, idv1);
- ve2[0] = EIG_linear_solver_variable_get(sys->context, 0, idv2);
- ve2[1] = EIG_linear_solver_variable_get(sys->context, 1, idv2);
- ve2[2] = EIG_linear_solver_variable_get(sys->context, 2, idv2);
- leni = len_v3v3(vi1, vi2);
- lene = len_v3v3(ve1, ve2);
- if (lene > leni * SMOOTH_LAPLACIAN_MAX_EDGE_PERCENTAGE || lene < leni * SMOOTH_LAPLACIAN_MIN_EDGE_PERCENTAGE) {
- sys->zerola[idv1] = 1;
- sys->zerola[idv2] = 1;
- }
- }
-
- if (preserve_volume) {
- vini = BM_mesh_calc_volume(sys->bm, false);
- }
- BMO_ITER (v, &siter, sys->op->slots_in, "verts", BM_VERT) {
- m_vertex_id = BM_elem_index_get(v);
- if (sys->zerola[m_vertex_id] == 0) {
- if (usex) {
- v->co[0] = EIG_linear_solver_variable_get(sys->context, 0, m_vertex_id);
- }
- if (usey) {
- v->co[1] = EIG_linear_solver_variable_get(sys->context, 1, m_vertex_id);
- }
- if (usez) {
- v->co[2] = EIG_linear_solver_variable_get(sys->context, 2, m_vertex_id);
- }
- }
- }
- if (preserve_volume) {
- vend = BM_mesh_calc_volume(sys->bm, false);
- volume_preservation(sys->op, vini, vend, usex, usey, usez);
- }
-
+ int m_vertex_id;
+ float leni, lene;
+ float vini, vend;
+ float *vi1, *vi2, ve1[3], ve2[3];
+ uint idv1, idv2;
+ BMOIter siter;
+ BMVert *v;
+ BMEdge *e;
+ BMIter eiter;
+
+ BM_ITER_MESH (e, &eiter, sys->bm, BM_EDGES_OF_MESH) {
+ idv1 = BM_elem_index_get(e->v1);
+ idv2 = BM_elem_index_get(e->v2);
+ vi1 = e->v1->co;
+ vi2 = e->v2->co;
+ ve1[0] = EIG_linear_solver_variable_get(sys->context, 0, idv1);
+ ve1[1] = EIG_linear_solver_variable_get(sys->context, 1, idv1);
+ ve1[2] = EIG_linear_solver_variable_get(sys->context, 2, idv1);
+ ve2[0] = EIG_linear_solver_variable_get(sys->context, 0, idv2);
+ ve2[1] = EIG_linear_solver_variable_get(sys->context, 1, idv2);
+ ve2[2] = EIG_linear_solver_variable_get(sys->context, 2, idv2);
+ leni = len_v3v3(vi1, vi2);
+ lene = len_v3v3(ve1, ve2);
+ if (lene > leni * SMOOTH_LAPLACIAN_MAX_EDGE_PERCENTAGE ||
+ lene < leni * SMOOTH_LAPLACIAN_MIN_EDGE_PERCENTAGE) {
+ sys->zerola[idv1] = 1;
+ sys->zerola[idv2] = 1;
+ }
+ }
+
+ if (preserve_volume) {
+ vini = BM_mesh_calc_volume(sys->bm, false);
+ }
+ BMO_ITER (v, &siter, sys->op->slots_in, "verts", BM_VERT) {
+ m_vertex_id = BM_elem_index_get(v);
+ if (sys->zerola[m_vertex_id] == 0) {
+ if (usex) {
+ v->co[0] = EIG_linear_solver_variable_get(sys->context, 0, m_vertex_id);
+ }
+ if (usey) {
+ v->co[1] = EIG_linear_solver_variable_get(sys->context, 1, m_vertex_id);
+ }
+ if (usez) {
+ v->co[2] = EIG_linear_solver_variable_get(sys->context, 2, m_vertex_id);
+ }
+ }
+ }
+ if (preserve_volume) {
+ vend = BM_mesh_calc_volume(sys->bm, false);
+ volume_preservation(sys->op, vini, vend, usex, usey, usez);
+ }
}
void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op)
{
- int i;
- int m_vertex_id;
- bool usex, usey, usez, preserve_volume;
- float lambda_factor, lambda_border;
- float w;
- BMOIter siter;
- BMVert *v;
- LaplacianSystem *sys;
-
- if (bm->totface == 0) {
- return;
- }
- sys = init_laplacian_system(bm->totedge, bm->totface, bm->totvert);
- if (!sys) {
- return;
- }
- sys->bm = bm;
- sys->op = op;
-
- memset_laplacian_system(sys, 0);
-
- BM_mesh_elem_index_ensure(bm, BM_VERT);
- lambda_factor = BMO_slot_float_get(op->slots_in, "lambda_factor");
- lambda_border = BMO_slot_float_get(op->slots_in, "lambda_border");
- sys->min_area = 0.00001f;
- usex = BMO_slot_bool_get(op->slots_in, "use_x");
- usey = BMO_slot_bool_get(op->slots_in, "use_y");
- usez = BMO_slot_bool_get(op->slots_in, "use_z");
- preserve_volume = BMO_slot_bool_get(op->slots_in, "preserve_volume");
-
-
- sys->context = EIG_linear_least_squares_solver_new(bm->totvert, bm->totvert, 3);
-
- for (i = 0; i < bm->totvert; i++) {
- EIG_linear_solver_variable_lock(sys->context, i);
- }
- BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
- m_vertex_id = BM_elem_index_get(v);
- EIG_linear_solver_variable_unlock(sys->context, m_vertex_id);
- EIG_linear_solver_variable_set(sys->context, 0, m_vertex_id, v->co[0]);
- EIG_linear_solver_variable_set(sys->context, 1, m_vertex_id, v->co[1]);
- EIG_linear_solver_variable_set(sys->context, 2, m_vertex_id, v->co[2]);
- }
-
- init_laplacian_matrix(sys);
- BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
- m_vertex_id = BM_elem_index_get(v);
- EIG_linear_solver_right_hand_side_add(sys->context, 0, m_vertex_id, v->co[0]);
- EIG_linear_solver_right_hand_side_add(sys->context, 1, m_vertex_id, v->co[1]);
- EIG_linear_solver_right_hand_side_add(sys->context, 2, m_vertex_id, v->co[2]);
- i = m_vertex_id;
- if (sys->zerola[i] == 0) {
- w = sys->vweights[i] * sys->ring_areas[i];
- sys->vweights[i] = (w == 0.0f) ? 0.0f : -lambda_factor / (4.0f * w);
- w = sys->vlengths[i];
- sys->vlengths[i] = (w == 0.0f) ? 0.0f : -lambda_border * 2.0f / w;
-
- if (!vert_is_boundary(v)) {
- EIG_linear_solver_matrix_add(sys->context, i, i, 1.0f + lambda_factor / (4.0f * sys->ring_areas[i]));
- }
- else {
- EIG_linear_solver_matrix_add(sys->context, i, i, 1.0f + lambda_border * 2.0f);
- }
- }
- else {
- EIG_linear_solver_matrix_add(sys->context, i, i, 1.0f);
- }
- }
- fill_laplacian_matrix(sys);
-
- if (EIG_linear_solver_solve(sys->context) ) {
- validate_solution(sys, usex, usey, usez, preserve_volume);
- }
-
- delete_laplacian_system(sys);
+ int i;
+ int m_vertex_id;
+ bool usex, usey, usez, preserve_volume;
+ float lambda_factor, lambda_border;
+ float w;
+ BMOIter siter;
+ BMVert *v;
+ LaplacianSystem *sys;
+
+ if (bm->totface == 0) {
+ return;
+ }
+ sys = init_laplacian_system(bm->totedge, bm->totface, bm->totvert);
+ if (!sys) {
+ return;
+ }
+ sys->bm = bm;
+ sys->op = op;
+
+ memset_laplacian_system(sys, 0);
+
+ BM_mesh_elem_index_ensure(bm, BM_VERT);
+ lambda_factor = BMO_slot_float_get(op->slots_in, "lambda_factor");
+ lambda_border = BMO_slot_float_get(op->slots_in, "lambda_border");
+ sys->min_area = 0.00001f;
+ usex = BMO_slot_bool_get(op->slots_in, "use_x");
+ usey = BMO_slot_bool_get(op->slots_in, "use_y");
+ usez = BMO_slot_bool_get(op->slots_in, "use_z");
+ preserve_volume = BMO_slot_bool_get(op->slots_in, "preserve_volume");
+
+ sys->context = EIG_linear_least_squares_solver_new(bm->totvert, bm->totvert, 3);
+
+ for (i = 0; i < bm->totvert; i++) {
+ EIG_linear_solver_variable_lock(sys->context, i);
+ }
+ BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
+ m_vertex_id = BM_elem_index_get(v);
+ EIG_linear_solver_variable_unlock(sys->context, m_vertex_id);
+ EIG_linear_solver_variable_set(sys->context, 0, m_vertex_id, v->co[0]);
+ EIG_linear_solver_variable_set(sys->context, 1, m_vertex_id, v->co[1]);
+ EIG_linear_solver_variable_set(sys->context, 2, m_vertex_id, v->co[2]);
+ }
+
+ init_laplacian_matrix(sys);
+ BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
+ m_vertex_id = BM_elem_index_get(v);
+ EIG_linear_solver_right_hand_side_add(sys->context, 0, m_vertex_id, v->co[0]);
+ EIG_linear_solver_right_hand_side_add(sys->context, 1, m_vertex_id, v->co[1]);
+ EIG_linear_solver_right_hand_side_add(sys->context, 2, m_vertex_id, v->co[2]);
+ i = m_vertex_id;
+ if (sys->zerola[i] == 0) {
+ w = sys->vweights[i] * sys->ring_areas[i];
+ sys->vweights[i] = (w == 0.0f) ? 0.0f : -lambda_factor / (4.0f * w);
+ w = sys->vlengths[i];
+ sys->vlengths[i] = (w == 0.0f) ? 0.0f : -lambda_border * 2.0f / w;
+
+ if (!vert_is_boundary(v)) {
+ EIG_linear_solver_matrix_add(
+ sys->context, i, i, 1.0f + lambda_factor / (4.0f * sys->ring_areas[i]));
+ }
+ else {
+ EIG_linear_solver_matrix_add(sys->context, i, i, 1.0f + lambda_border * 2.0f);
+ }
+ }
+ else {
+ EIG_linear_solver_matrix_add(sys->context, i, i, 1.0f);
+ }
+ }
+ fill_laplacian_matrix(sys);
+
+ if (EIG_linear_solver_solve(sys->context)) {
+ validate_solution(sys, usex, usey, usez, preserve_volume);
+ }
+
+ delete_laplacian_system(sys);
}
diff --git a/source/blender/bmesh/operators/bmo_split_edges.c b/source/blender/bmesh/operators/bmo_split_edges.c
index e0728c6539b..d030a6e11b0 100644
--- a/source/blender/bmesh/operators/bmo_split_edges.c
+++ b/source/blender/bmesh/operators/bmo_split_edges.c
@@ -27,22 +27,21 @@
#include "intern/bmesh_operators_private.h" /* own include */
-
/* keep this operator fast, its used in a modifier */
void bmo_split_edges_exec(BMesh *bm, BMOperator *op)
{
- const bool use_verts = BMO_slot_bool_get(op->slots_in, "use_verts");
+ const bool use_verts = BMO_slot_bool_get(op->slots_in, "use_verts");
- BM_mesh_elem_hflag_disable_all(bm, BM_EDGE, BM_ELEM_TAG, false);
- BMO_slot_buffer_hflag_enable(bm, op->slots_in, "edges", BM_EDGE, BM_ELEM_TAG, false);
+ BM_mesh_elem_hflag_disable_all(bm, BM_EDGE, BM_ELEM_TAG, false);
+ BMO_slot_buffer_hflag_enable(bm, op->slots_in, "edges", BM_EDGE, BM_ELEM_TAG, false);
- if (use_verts) {
- /* this slows down the operation but its ok because the modifier doesn't use */
- BMO_slot_buffer_hflag_enable(bm, op->slots_in, "verts", BM_VERT, BM_ELEM_TAG, false);
- }
+ if (use_verts) {
+ /* this slows down the operation but its ok because the modifier doesn't use */
+ BMO_slot_buffer_hflag_enable(bm, op->slots_in, "verts", BM_VERT, BM_ELEM_TAG, false);
+ }
- /* this is where everything happens */
- BM_mesh_edgesplit(bm, use_verts, true, false);
+ /* this is where everything happens */
+ BM_mesh_edgesplit(bm, use_verts, true, false);
- BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "edges.out", BM_EDGE, BM_ELEM_TAG);
+ BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "edges.out", BM_EDGE, BM_ELEM_TAG);
}
diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c
index 6b7f81aabb6..869c61832f9 100644
--- a/source/blender/bmesh/operators/bmo_subdivide.c
+++ b/source/blender/bmesh/operators/bmo_subdivide.c
@@ -30,53 +30,53 @@
#include "BKE_customdata.h"
-
#include "bmesh.h"
#include "intern/bmesh_private.h"
#include "intern/bmesh_operators_private.h"
typedef struct SubDParams {
- int numcuts;
- float smooth;
- int smooth_falloff;
- float fractal;
- float along_normal;
- //int beauty;
- bool use_smooth;
- bool use_smooth_even;
- bool use_sphere;
- bool use_fractal;
- int seed;
- BMOperator *op;
- BMOpSlot *slot_edge_percents; /* BMO_slot_get(params->op->slots_in, "edge_percents"); */
- BMOpSlot *slot_custom_patterns; /* BMO_slot_get(params->op->slots_in, "custom_patterns"); */
- float fractal_ofs[3];
-
- /* rumtime storage for shape key */
- struct {
- int cd_vert_shape_offset;
- int cd_vert_shape_offset_tmp;
- int totlayer;
-
- /* shapekey holding displaced vertex coordinates for current geometry */
- int tmpkey;
- } shape_info;
+ int numcuts;
+ float smooth;
+ int smooth_falloff;
+ float fractal;
+ float along_normal;
+ //int beauty;
+ bool use_smooth;
+ bool use_smooth_even;
+ bool use_sphere;
+ bool use_fractal;
+ int seed;
+ BMOperator *op;
+ BMOpSlot *slot_edge_percents; /* BMO_slot_get(params->op->slots_in, "edge_percents"); */
+ BMOpSlot *slot_custom_patterns; /* BMO_slot_get(params->op->slots_in, "custom_patterns"); */
+ float fractal_ofs[3];
+
+ /* rumtime storage for shape key */
+ struct {
+ int cd_vert_shape_offset;
+ int cd_vert_shape_offset_tmp;
+ int totlayer;
+
+ /* shapekey holding displaced vertex coordinates for current geometry */
+ int tmpkey;
+ } shape_info;
} SubDParams;
static void bmo_subd_init_shape_info(BMesh *bm, SubDParams *params)
{
- const int skey = CustomData_number_of_layers(&bm->vdata, CD_SHAPEKEY) - 1;
- params->shape_info.tmpkey = skey;
- params->shape_info.cd_vert_shape_offset = CustomData_get_offset(&bm->vdata, CD_SHAPEKEY);
- params->shape_info.cd_vert_shape_offset_tmp = CustomData_get_n_offset(&bm->vdata, CD_SHAPEKEY, skey);
- params->shape_info.totlayer = CustomData_number_of_layers(&bm->vdata, CD_SHAPEKEY);
-
+ const int skey = CustomData_number_of_layers(&bm->vdata, CD_SHAPEKEY) - 1;
+ params->shape_info.tmpkey = skey;
+ params->shape_info.cd_vert_shape_offset = CustomData_get_offset(&bm->vdata, CD_SHAPEKEY);
+ params->shape_info.cd_vert_shape_offset_tmp = CustomData_get_n_offset(
+ &bm->vdata, CD_SHAPEKEY, skey);
+ params->shape_info.totlayer = CustomData_number_of_layers(&bm->vdata, CD_SHAPEKEY);
}
-typedef void (*subd_pattern_fill_fp)(
- BMesh *bm, BMFace *face, BMVert **verts,
- const SubDParams *params);
+typedef void (*subd_pattern_fill_fp)(BMesh *bm,
+ BMFace *face,
+ BMVert **verts,
+ const SubDParams *params);
/*
* note: this is a pattern-based edge subdivider.
@@ -84,11 +84,11 @@ typedef void (*subd_pattern_fill_fp)(
* then executes functions to cut them.
*/
typedef struct SubDPattern {
- int seledges[20]; /* selected edges mask, for splitting */
+ int seledges[20]; /* selected edges mask, for splitting */
- /* verts starts at the first new vert cut, not the first vert in the face */
- subd_pattern_fill_fp connectexec;
- int len; /* total number of verts, before any subdivision */
+ /* verts starts at the first new vert cut, not the first vert in the face */
+ subd_pattern_fill_fp connectexec;
+ int len; /* total number of verts, before any subdivision */
} SubDPattern;
/* generic subdivision rules:
@@ -101,15 +101,15 @@ typedef struct SubDPattern {
*/
/* flags for all elements share a common bitfield space */
-#define SUBD_SPLIT 1
+#define SUBD_SPLIT 1
-#define EDGE_PERCENT 2
+#define EDGE_PERCENT 2
/* I don't think new faces are flagged, currently, but
* better safe than sorry. */
-#define FACE_CUSTOMFILL 4
-#define ELE_INNER 8
-#define ELE_SPLIT 16
+#define FACE_CUSTOMFILL 4
+#define ELE_INNER 8
+#define ELE_SPLIT 16
/* see bug [#32665], 0.00005 means a we get face splits at a little under 1.0 degrees */
#define FLT_FACE_SPLIT_EPSILON 0.00005f
@@ -131,335 +131,342 @@ typedef struct SubDPattern {
* edge subdivision */
static BMEdge *connect_smallest_face(BMesh *bm, BMVert *v_a, BMVert *v_b, BMFace **r_f_new)
{
- BMLoop *l_a, *l_b;
- BMFace *f;
-
- /* this isn't the best thing in the world. it doesn't handle cases where there's
- * multiple faces yet. that might require a convexity test to figure out which
- * face is "best" and who knows what for non-manifold conditions.
- *
- * note: we allow adjacent here, since theres no chance this happens.
- */
- f = BM_vert_pair_share_face_by_len(v_a, v_b, &l_a, &l_b, true);
+ BMLoop *l_a, *l_b;
+ BMFace *f;
+ /* this isn't the best thing in the world. it doesn't handle cases where there's
+ * multiple faces yet. that might require a convexity test to figure out which
+ * face is "best" and who knows what for non-manifold conditions.
+ *
+ * note: we allow adjacent here, since theres no chance this happens.
+ */
+ f = BM_vert_pair_share_face_by_len(v_a, v_b, &l_a, &l_b, true);
- if (f) {
- BMFace *f_new;
- BMLoop *l_new;
+ if (f) {
+ BMFace *f_new;
+ BMLoop *l_new;
- BLI_assert(!BM_loop_is_adjacent(l_a, l_b));
+ BLI_assert(!BM_loop_is_adjacent(l_a, l_b));
- f_new = BM_face_split(bm, f, l_a, l_b, &l_new, NULL, false);
+ f_new = BM_face_split(bm, f, l_a, l_b, &l_new, NULL, false);
- if (r_f_new) {
- *r_f_new = f_new;
- }
- return l_new ? l_new->e : NULL;
- }
+ if (r_f_new) {
+ *r_f_new = f_new;
+ }
+ return l_new ? l_new->e : NULL;
+ }
- return NULL;
+ return NULL;
}
/**
* Specialized slerp that uses a sphere defined by each points normal.
*/
static void interp_slerp_co_no_v3(
- const float co_a[3], const float no_a[3],
- const float co_b[3], const float no_b[3],
- const float no_dir[3], /* caller already knows, avoid normalize */
- float fac,
- float r_co[3])
+ const float co_a[3],
+ const float no_a[3],
+ const float co_b[3],
+ const float no_b[3],
+ const float no_dir[3], /* caller already knows, avoid normalize */
+ float fac,
+ float r_co[3])
{
- /* center of the sphere defined by both normals */
- float center[3];
+ /* center of the sphere defined by both normals */
+ float center[3];
- BLI_assert(len_squared_v3v3(no_a, no_b) != 0);
+ BLI_assert(len_squared_v3v3(no_a, no_b) != 0);
- /* calculate sphere 'center' */
- {
- /* use point on plane to */
- float no_mid[3], no_ortho[3];
- /* pass this as an arg instead */
+ /* calculate sphere 'center' */
+ {
+ /* use point on plane to */
+ float no_mid[3], no_ortho[3];
+ /* pass this as an arg instead */
#if 0
- float no_dir[3];
+ float no_dir[3];
#endif
- add_v3_v3v3(no_mid, no_a, no_b);
- normalize_v3(no_mid);
+ add_v3_v3v3(no_mid, no_a, no_b);
+ normalize_v3(no_mid);
#if 0
- sub_v3_v3v3(no_dir, co_a, co_b);
- normalize_v3(no_dir);
+ sub_v3_v3v3(no_dir, co_a, co_b);
+ normalize_v3(no_dir);
#endif
- /* axis of slerp */
- bool center_ok = false;
- cross_v3_v3v3(no_ortho, no_mid, no_dir);
- if (normalize_v3(no_ortho) != 0.0f) {
- float plane_a[4], plane_b[4], plane_c[4];
- float v_a_no_ortho[3], v_b_no_ortho[3];
-
- /* create planes */
- cross_v3_v3v3(v_a_no_ortho, no_ortho, no_a);
- cross_v3_v3v3(v_b_no_ortho, no_ortho, no_b);
- project_v3_plane(v_a_no_ortho, no_ortho, v_a_no_ortho);
- project_v3_plane(v_b_no_ortho, no_ortho, v_b_no_ortho);
-
- plane_from_point_normal_v3(plane_a, co_a, v_a_no_ortho);
- plane_from_point_normal_v3(plane_b, co_b, v_b_no_ortho);
- plane_from_point_normal_v3(plane_c, co_b, no_ortho);
-
- /* find the sphere center from 3 planes */
- if (isect_plane_plane_plane_v3(plane_a, plane_b, plane_c, center)) {
- center_ok = true;
- }
- }
- if (center_ok == false) {
- mid_v3_v3v3(center, co_a, co_b);
- }
- }
-
- /* calculate the final output 'r_co' */
- {
- float ofs_a[3], ofs_b[3], ofs_slerp[3];
- float dist_a, dist_b;
-
- sub_v3_v3v3(ofs_a, co_a, center);
- sub_v3_v3v3(ofs_b, co_b, center);
-
- dist_a = normalize_v3(ofs_a);
- dist_b = normalize_v3(ofs_b);
-
- if (interp_v3_v3v3_slerp(ofs_slerp, ofs_a, ofs_b, fac)) {
- madd_v3_v3v3fl(r_co, center, ofs_slerp, interpf(dist_b, dist_a, fac));
- }
- else {
- interp_v3_v3v3(r_co, co_a, co_b, fac);
- }
- }
+ /* axis of slerp */
+ bool center_ok = false;
+ cross_v3_v3v3(no_ortho, no_mid, no_dir);
+ if (normalize_v3(no_ortho) != 0.0f) {
+ float plane_a[4], plane_b[4], plane_c[4];
+ float v_a_no_ortho[3], v_b_no_ortho[3];
+
+ /* create planes */
+ cross_v3_v3v3(v_a_no_ortho, no_ortho, no_a);
+ cross_v3_v3v3(v_b_no_ortho, no_ortho, no_b);
+ project_v3_plane(v_a_no_ortho, no_ortho, v_a_no_ortho);
+ project_v3_plane(v_b_no_ortho, no_ortho, v_b_no_ortho);
+
+ plane_from_point_normal_v3(plane_a, co_a, v_a_no_ortho);
+ plane_from_point_normal_v3(plane_b, co_b, v_b_no_ortho);
+ plane_from_point_normal_v3(plane_c, co_b, no_ortho);
+
+ /* find the sphere center from 3 planes */
+ if (isect_plane_plane_plane_v3(plane_a, plane_b, plane_c, center)) {
+ center_ok = true;
+ }
+ }
+ if (center_ok == false) {
+ mid_v3_v3v3(center, co_a, co_b);
+ }
+ }
+
+ /* calculate the final output 'r_co' */
+ {
+ float ofs_a[3], ofs_b[3], ofs_slerp[3];
+ float dist_a, dist_b;
+
+ sub_v3_v3v3(ofs_a, co_a, center);
+ sub_v3_v3v3(ofs_b, co_b, center);
+
+ dist_a = normalize_v3(ofs_a);
+ dist_b = normalize_v3(ofs_b);
+
+ if (interp_v3_v3v3_slerp(ofs_slerp, ofs_a, ofs_b, fac)) {
+ madd_v3_v3v3fl(r_co, center, ofs_slerp, interpf(dist_b, dist_a, fac));
+ }
+ else {
+ interp_v3_v3v3(r_co, co_a, co_b, fac);
+ }
+ }
}
/* calculates offset for co, based on fractal, sphere or smooth settings */
-static void alter_co(
- BMVert *v, BMEdge *UNUSED(e_orig),
- const SubDParams *params, const float perc,
- const BMVert *v_a, const BMVert *v_b)
+static void alter_co(BMVert *v,
+ BMEdge *UNUSED(e_orig),
+ const SubDParams *params,
+ const float perc,
+ const BMVert *v_a,
+ const BMVert *v_b)
{
- float *co = BM_ELEM_CD_GET_VOID_P(v, params->shape_info.cd_vert_shape_offset_tmp);
- int i;
+ float *co = BM_ELEM_CD_GET_VOID_P(v, params->shape_info.cd_vert_shape_offset_tmp);
+ int i;
- copy_v3_v3(co, v->co);
+ copy_v3_v3(co, v->co);
- if (UNLIKELY(params->use_sphere)) { /* subdivide sphere */
- normalize_v3_length(co, params->smooth);
- }
- else if (params->use_smooth) {
- /* calculating twice and blending gives smoother results,
- * removing visible seams. */
+ if (UNLIKELY(params->use_sphere)) { /* subdivide sphere */
+ normalize_v3_length(co, params->smooth);
+ }
+ else if (params->use_smooth) {
+ /* calculating twice and blending gives smoother results,
+ * removing visible seams. */
#define USE_SPHERE_DUAL_BLEND
- const float eps_unit_vec = 1e-5f;
- float smooth;
- float no_dir[3];
+ const float eps_unit_vec = 1e-5f;
+ float smooth;
+ float no_dir[3];
#ifdef USE_SPHERE_DUAL_BLEND
- float no_reflect[3], co_a[3], co_b[3];
+ float no_reflect[3], co_a[3], co_b[3];
#endif
- sub_v3_v3v3(no_dir, v_a->co, v_b->co);
- normalize_v3(no_dir);
+ sub_v3_v3v3(no_dir, v_a->co, v_b->co);
+ normalize_v3(no_dir);
#ifndef USE_SPHERE_DUAL_BLEND
- if (len_squared_v3v3(v_a->no, v_b->no) < eps_unit_vec) {
- interp_v3_v3v3(co, v_a->co, v_b->co, perc);
- }
- else {
- interp_slerp_co_no_v3(v_a->co, v_a->no, v_b->co, v_b->no, no_dir, perc, co);
- }
+ if (len_squared_v3v3(v_a->no, v_b->no) < eps_unit_vec) {
+ interp_v3_v3v3(co, v_a->co, v_b->co, perc);
+ }
+ else {
+ interp_slerp_co_no_v3(v_a->co, v_a->no, v_b->co, v_b->no, no_dir, perc, co);
+ }
#else
- /* sphere-a */
- reflect_v3_v3v3(no_reflect, v_a->no, no_dir);
- if (len_squared_v3v3(v_a->no, no_reflect) < eps_unit_vec) {
- interp_v3_v3v3(co_a, v_a->co, v_b->co, perc);
- }
- else {
- interp_slerp_co_no_v3(v_a->co, v_a->no, v_b->co, no_reflect, no_dir, perc, co_a);
- }
-
- /* sphere-b */
- reflect_v3_v3v3(no_reflect, v_b->no, no_dir);
- if (len_squared_v3v3(v_b->no, no_reflect) < eps_unit_vec) {
- interp_v3_v3v3(co_b, v_a->co, v_b->co, perc);
- }
- else {
- interp_slerp_co_no_v3(v_a->co, no_reflect, v_b->co, v_b->no, no_dir, perc, co_b);
- }
-
- /* blend both spheres */
- interp_v3_v3v3(co, co_a, co_b, perc);
-#endif /* USE_SPHERE_DUAL_BLEND */
-
- /* apply falloff */
- if (params->smooth_falloff == SUBD_FALLOFF_LIN) {
- smooth = 1.0f;
- }
- else {
- smooth = fabsf(1.0f - 2.0f * fabsf(0.5f - perc));
- smooth = 1.0f + bmesh_subd_falloff_calc(params->smooth_falloff, smooth);
- }
-
- if (params->use_smooth_even) {
- smooth *= shell_v3v3_mid_normalized_to_dist(v_a->no, v_b->no);
- }
-
- smooth *= params->smooth;
- if (smooth != 1.0f) {
- float co_flat[3];
- interp_v3_v3v3(co_flat, v_a->co, v_b->co, perc);
- interp_v3_v3v3(co, co_flat, co, smooth);
- }
+ /* sphere-a */
+ reflect_v3_v3v3(no_reflect, v_a->no, no_dir);
+ if (len_squared_v3v3(v_a->no, no_reflect) < eps_unit_vec) {
+ interp_v3_v3v3(co_a, v_a->co, v_b->co, perc);
+ }
+ else {
+ interp_slerp_co_no_v3(v_a->co, v_a->no, v_b->co, no_reflect, no_dir, perc, co_a);
+ }
+
+ /* sphere-b */
+ reflect_v3_v3v3(no_reflect, v_b->no, no_dir);
+ if (len_squared_v3v3(v_b->no, no_reflect) < eps_unit_vec) {
+ interp_v3_v3v3(co_b, v_a->co, v_b->co, perc);
+ }
+ else {
+ interp_slerp_co_no_v3(v_a->co, no_reflect, v_b->co, v_b->no, no_dir, perc, co_b);
+ }
+
+ /* blend both spheres */
+ interp_v3_v3v3(co, co_a, co_b, perc);
+#endif /* USE_SPHERE_DUAL_BLEND */
+
+ /* apply falloff */
+ if (params->smooth_falloff == SUBD_FALLOFF_LIN) {
+ smooth = 1.0f;
+ }
+ else {
+ smooth = fabsf(1.0f - 2.0f * fabsf(0.5f - perc));
+ smooth = 1.0f + bmesh_subd_falloff_calc(params->smooth_falloff, smooth);
+ }
+
+ if (params->use_smooth_even) {
+ smooth *= shell_v3v3_mid_normalized_to_dist(v_a->no, v_b->no);
+ }
+
+ smooth *= params->smooth;
+ if (smooth != 1.0f) {
+ float co_flat[3];
+ interp_v3_v3v3(co_flat, v_a->co, v_b->co, perc);
+ interp_v3_v3v3(co, co_flat, co, smooth);
+ }
#undef USE_SPHERE_DUAL_BLEND
- }
-
- if (params->use_fractal) {
- float normal[3], co2[3], base1[3], base2[3], tvec[3];
- const float len = len_v3v3(v_a->co, v_b->co);
- float fac;
-
- fac = params->fractal * len;
-
- mid_v3_v3v3(normal, v_a->no, v_b->no);
- ortho_basis_v3v3_v3(base1, base2, normal);
-
- add_v3_v3v3(co2, v->co, params->fractal_ofs);
- mul_v3_fl(co2, 10.0f);
-
- tvec[0] = fac * (BLI_gTurbulence(1.0, co2[0], co2[1], co2[2], 15, 0, 2) - 0.5f);
- tvec[1] = fac * (BLI_gTurbulence(1.0, co2[1], co2[0], co2[2], 15, 0, 2) - 0.5f);
- tvec[2] = fac * (BLI_gTurbulence(1.0, co2[1], co2[2], co2[0], 15, 0, 2) - 0.5f);
-
- /* add displacement */
- madd_v3_v3fl(co, normal, tvec[0]);
- madd_v3_v3fl(co, base1, tvec[1] * (1.0f - params->along_normal));
- madd_v3_v3fl(co, base2, tvec[2] * (1.0f - params->along_normal));
- }
-
- /* apply the new difference to the rest of the shape keys,
- * note that this doesn't take rotations into account, we _could_ support
- * this by getting the normals and coords for each shape key and
- * re-calculate the smooth value for each but this is quite involved.
- * for now its ok to simply apply the difference IMHO - campbell */
-
- if (params->shape_info.totlayer > 1) {
- float tvec[3];
-
- sub_v3_v3v3(tvec, v->co, co);
-
- /* skip the last layer since its the temp */
- i = params->shape_info.totlayer - 1;
- co = BM_ELEM_CD_GET_VOID_P(v, params->shape_info.cd_vert_shape_offset);
- while (i--) {
- BLI_assert(co != BM_ELEM_CD_GET_VOID_P(v, params->shape_info.cd_vert_shape_offset_tmp));
- sub_v3_v3(co += 3, tvec);
- }
- }
+ }
+
+ if (params->use_fractal) {
+ float normal[3], co2[3], base1[3], base2[3], tvec[3];
+ const float len = len_v3v3(v_a->co, v_b->co);
+ float fac;
+
+ fac = params->fractal * len;
+
+ mid_v3_v3v3(normal, v_a->no, v_b->no);
+ ortho_basis_v3v3_v3(base1, base2, normal);
+
+ add_v3_v3v3(co2, v->co, params->fractal_ofs);
+ mul_v3_fl(co2, 10.0f);
+
+ tvec[0] = fac * (BLI_gTurbulence(1.0, co2[0], co2[1], co2[2], 15, 0, 2) - 0.5f);
+ tvec[1] = fac * (BLI_gTurbulence(1.0, co2[1], co2[0], co2[2], 15, 0, 2) - 0.5f);
+ tvec[2] = fac * (BLI_gTurbulence(1.0, co2[1], co2[2], co2[0], 15, 0, 2) - 0.5f);
+
+ /* add displacement */
+ madd_v3_v3fl(co, normal, tvec[0]);
+ madd_v3_v3fl(co, base1, tvec[1] * (1.0f - params->along_normal));
+ madd_v3_v3fl(co, base2, tvec[2] * (1.0f - params->along_normal));
+ }
+
+ /* apply the new difference to the rest of the shape keys,
+ * note that this doesn't take rotations into account, we _could_ support
+ * this by getting the normals and coords for each shape key and
+ * re-calculate the smooth value for each but this is quite involved.
+ * for now its ok to simply apply the difference IMHO - campbell */
+
+ if (params->shape_info.totlayer > 1) {
+ float tvec[3];
+
+ sub_v3_v3v3(tvec, v->co, co);
+
+ /* skip the last layer since its the temp */
+ i = params->shape_info.totlayer - 1;
+ co = BM_ELEM_CD_GET_VOID_P(v, params->shape_info.cd_vert_shape_offset);
+ while (i--) {
+ BLI_assert(co != BM_ELEM_CD_GET_VOID_P(v, params->shape_info.cd_vert_shape_offset_tmp));
+ sub_v3_v3(co += 3, tvec);
+ }
+ }
}
/* assumes in the edge is the correct interpolated vertices already */
/* percent defines the interpolation, rad and flag are for special options */
/* results in new vertex with correct coordinate, vertex normal and weight group info */
-static BMVert *bm_subdivide_edge_addvert(
- BMesh *bm, BMEdge *edge, BMEdge *e_orig,
- const SubDParams *params,
- const float factor_edge_split, const float factor_subd,
- BMVert *v_a, BMVert *v_b,
- BMEdge **r_edge)
+static BMVert *bm_subdivide_edge_addvert(BMesh *bm,
+ BMEdge *edge,
+ BMEdge *e_orig,
+ const SubDParams *params,
+ const float factor_edge_split,
+ const float factor_subd,
+ BMVert *v_a,
+ BMVert *v_b,
+ BMEdge **r_edge)
{
- BMVert *v_new;
-
- v_new = BM_edge_split(bm, edge, edge->v1, r_edge, factor_edge_split);
-
- BMO_vert_flag_enable(bm, v_new, ELE_INNER);
-
- /* offset for smooth or sphere or fractal */
- alter_co(v_new, e_orig, params, factor_subd, v_a, v_b);
-
-#if 0 //BMESH_TODO
- /* clip if needed by mirror modifier */
- if (edge->v1->f2) {
- if (edge->v1->f2 & edge->v2->f2 & 1) {
- co[0] = 0.0f;
- }
- if (edge->v1->f2 & edge->v2->f2 & 2) {
- co[1] = 0.0f;
- }
- if (edge->v1->f2 & edge->v2->f2 & 4) {
- co[2] = 0.0f;
- }
- }
+ BMVert *v_new;
+
+ v_new = BM_edge_split(bm, edge, edge->v1, r_edge, factor_edge_split);
+
+ BMO_vert_flag_enable(bm, v_new, ELE_INNER);
+
+ /* offset for smooth or sphere or fractal */
+ alter_co(v_new, e_orig, params, factor_subd, v_a, v_b);
+
+#if 0 //BMESH_TODO
+ /* clip if needed by mirror modifier */
+ if (edge->v1->f2) {
+ if (edge->v1->f2 & edge->v2->f2 & 1) {
+ co[0] = 0.0f;
+ }
+ if (edge->v1->f2 & edge->v2->f2 & 2) {
+ co[1] = 0.0f;
+ }
+ if (edge->v1->f2 & edge->v2->f2 & 4) {
+ co[2] = 0.0f;
+ }
+ }
#endif
- interp_v3_v3v3(v_new->no, v_a->no, v_b->no, factor_subd);
- normalize_v3(v_new->no);
+ interp_v3_v3v3(v_new->no, v_a->no, v_b->no, factor_subd);
+ normalize_v3(v_new->no);
- return v_new;
+ return v_new;
}
-static BMVert *subdivide_edge_num(
- BMesh *bm, BMEdge *edge, BMEdge *e_orig,
- int curpoint, int totpoint, const SubDParams *params,
- BMVert *v_a, BMVert *v_b,
- BMEdge **r_edge)
+static BMVert *subdivide_edge_num(BMesh *bm,
+ BMEdge *edge,
+ BMEdge *e_orig,
+ int curpoint,
+ int totpoint,
+ const SubDParams *params,
+ BMVert *v_a,
+ BMVert *v_b,
+ BMEdge **r_edge)
{
- BMVert *v_new;
- float factor_edge_split, factor_subd;
-
- if (BMO_edge_flag_test(bm, edge, EDGE_PERCENT) && totpoint == 1) {
- factor_edge_split = BMO_slot_map_float_get(params->slot_edge_percents, edge);
- factor_subd = 0.0f;
- }
- else {
- factor_edge_split = 1.0f / (float)(totpoint + 1 - curpoint);
- factor_subd = (float)(curpoint + 1) / (float)(totpoint + 1);
- }
-
- v_new = bm_subdivide_edge_addvert(
- bm, edge, e_orig, params,
- factor_edge_split, factor_subd,
- v_a, v_b, r_edge);
- return v_new;
+ BMVert *v_new;
+ float factor_edge_split, factor_subd;
+
+ if (BMO_edge_flag_test(bm, edge, EDGE_PERCENT) && totpoint == 1) {
+ factor_edge_split = BMO_slot_map_float_get(params->slot_edge_percents, edge);
+ factor_subd = 0.0f;
+ }
+ else {
+ factor_edge_split = 1.0f / (float)(totpoint + 1 - curpoint);
+ factor_subd = (float)(curpoint + 1) / (float)(totpoint + 1);
+ }
+
+ v_new = bm_subdivide_edge_addvert(
+ bm, edge, e_orig, params, factor_edge_split, factor_subd, v_a, v_b, r_edge);
+ return v_new;
}
static void bm_subdivide_multicut(
- BMesh *bm, BMEdge *edge, const SubDParams *params,
- BMVert *v_a, BMVert *v_b)
+ BMesh *bm, BMEdge *edge, const SubDParams *params, BMVert *v_a, BMVert *v_b)
{
- BMEdge *eed = edge, *e_new, e_tmp = *edge;
- BMVert *v, v1_tmp = *edge->v1, v2_tmp = *edge->v2, *v1 = edge->v1, *v2 = edge->v2;
- int i, numcuts = params->numcuts;
-
- e_tmp.v1 = &v1_tmp;
- e_tmp.v2 = &v2_tmp;
-
- for (i = 0; i < numcuts; i++) {
- v = subdivide_edge_num(bm, eed, &e_tmp, i, params->numcuts, params, v_a, v_b, &e_new);
-
- BMO_vert_flag_enable(bm, v, SUBD_SPLIT | ELE_SPLIT);
- BMO_edge_flag_enable(bm, eed, SUBD_SPLIT | ELE_SPLIT);
- BMO_edge_flag_enable(bm, e_new, SUBD_SPLIT | ELE_SPLIT);
-
- BM_CHECK_ELEMENT(v);
- if (v->e) {
- BM_CHECK_ELEMENT(v->e);
- }
- if (v->e && v->e->l) {
- BM_CHECK_ELEMENT(v->e->l->f);
- }
- }
-
- alter_co(v1, &e_tmp, params, 0, &v1_tmp, &v2_tmp);
- alter_co(v2, &e_tmp, params, 1.0, &v1_tmp, &v2_tmp);
+ BMEdge *eed = edge, *e_new, e_tmp = *edge;
+ BMVert *v, v1_tmp = *edge->v1, v2_tmp = *edge->v2, *v1 = edge->v1, *v2 = edge->v2;
+ int i, numcuts = params->numcuts;
+
+ e_tmp.v1 = &v1_tmp;
+ e_tmp.v2 = &v2_tmp;
+
+ for (i = 0; i < numcuts; i++) {
+ v = subdivide_edge_num(bm, eed, &e_tmp, i, params->numcuts, params, v_a, v_b, &e_new);
+
+ BMO_vert_flag_enable(bm, v, SUBD_SPLIT | ELE_SPLIT);
+ BMO_edge_flag_enable(bm, eed, SUBD_SPLIT | ELE_SPLIT);
+ BMO_edge_flag_enable(bm, e_new, SUBD_SPLIT | ELE_SPLIT);
+
+ BM_CHECK_ELEMENT(v);
+ if (v->e) {
+ BM_CHECK_ELEMENT(v->e);
+ }
+ if (v->e && v->e->l) {
+ BM_CHECK_ELEMENT(v->e->l->f);
+ }
+ }
+
+ alter_co(v1, &e_tmp, params, 0, &v1_tmp, &v2_tmp);
+ alter_co(v2, &e_tmp, params, 1.0, &v1_tmp, &v2_tmp);
}
/* note: the patterns are rotated as necessary to
@@ -476,42 +483,42 @@ static void bm_subdivide_multicut(
* v4---v0---v1
* </pre>
*/
-static void quad_1edge_split(BMesh *bm, BMFace *UNUSED(face),
- BMVert **verts, const SubDParams *params)
+static void quad_1edge_split(BMesh *bm,
+ BMFace *UNUSED(face),
+ BMVert **verts,
+ const SubDParams *params)
{
- BMFace *f_new;
- int i, add, numcuts = params->numcuts;
-
- /* if it's odd, the middle face is a quad, otherwise it's a triangle */
- if ((numcuts % 2) == 0) {
- add = 2;
- for (i = 0; i < numcuts; i++) {
- if (i == numcuts / 2) {
- add -= 1;
- }
- connect_smallest_face(bm, verts[i], verts[numcuts + add], &f_new);
- }
- }
- else {
- add = 2;
- for (i = 0; i < numcuts; i++) {
- connect_smallest_face(bm, verts[i], verts[numcuts + add], &f_new);
- if (i == numcuts / 2) {
- add -= 1;
- connect_smallest_face(bm, verts[i], verts[numcuts + add], &f_new);
- }
- }
-
- }
+ BMFace *f_new;
+ int i, add, numcuts = params->numcuts;
+
+ /* if it's odd, the middle face is a quad, otherwise it's a triangle */
+ if ((numcuts % 2) == 0) {
+ add = 2;
+ for (i = 0; i < numcuts; i++) {
+ if (i == numcuts / 2) {
+ add -= 1;
+ }
+ connect_smallest_face(bm, verts[i], verts[numcuts + add], &f_new);
+ }
+ }
+ else {
+ add = 2;
+ for (i = 0; i < numcuts; i++) {
+ connect_smallest_face(bm, verts[i], verts[numcuts + add], &f_new);
+ if (i == numcuts / 2) {
+ add -= 1;
+ connect_smallest_face(bm, verts[i], verts[numcuts + add], &f_new);
+ }
+ }
+ }
}
static const SubDPattern quad_1edge = {
- {1, 0, 0, 0},
- quad_1edge_split,
- 4,
+ {1, 0, 0, 0},
+ quad_1edge_split,
+ 4,
};
-
/**
* <pre>
* v6--------v5
@@ -522,22 +529,24 @@ static const SubDPattern quad_1edge = {
* v7-v0--v1-v2
* </pre>
*/
-static void quad_2edge_split_path(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
+static void quad_2edge_split_path(BMesh *bm,
+ BMFace *UNUSED(face),
+ BMVert **verts,
const SubDParams *params)
{
- BMFace *f_new;
- int i, numcuts = params->numcuts;
+ BMFace *f_new;
+ int i, numcuts = params->numcuts;
- for (i = 0; i < numcuts; i++) {
- connect_smallest_face(bm, verts[i], verts[numcuts + (numcuts - i)], &f_new);
- }
- connect_smallest_face(bm, verts[numcuts * 2 + 3], verts[numcuts * 2 + 1], &f_new);
+ for (i = 0; i < numcuts; i++) {
+ connect_smallest_face(bm, verts[i], verts[numcuts + (numcuts - i)], &f_new);
+ }
+ connect_smallest_face(bm, verts[numcuts * 2 + 3], verts[numcuts * 2 + 1], &f_new);
}
static const SubDPattern quad_2edge_path = {
- {1, 1, 0, 0},
- quad_2edge_split_path,
- 4,
+ {1, 1, 0, 0},
+ quad_2edge_split_path,
+ 4,
};
/**
@@ -550,36 +559,38 @@ static const SubDPattern quad_2edge_path = {
* v7-v0--v1-v2
* </pre>
*/
-static void quad_2edge_split_innervert(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
+static void quad_2edge_split_innervert(BMesh *bm,
+ BMFace *UNUSED(face),
+ BMVert **verts,
const SubDParams *params)
{
- BMFace *f_new;
- BMVert *v, *v_last;
- BMEdge *e, *e_new, e_tmp;
- int i, numcuts = params->numcuts;
+ BMFace *f_new;
+ BMVert *v, *v_last;
+ BMEdge *e, *e_new, e_tmp;
+ int i, numcuts = params->numcuts;
- v_last = verts[numcuts];
+ v_last = verts[numcuts];
- for (i = numcuts - 1; i >= 0; i--) {
- e = connect_smallest_face(bm, verts[i], verts[numcuts + (numcuts - i)], &f_new);
+ for (i = numcuts - 1; i >= 0; i--) {
+ e = connect_smallest_face(bm, verts[i], verts[numcuts + (numcuts - i)], &f_new);
- e_tmp = *e;
- v = bm_subdivide_edge_addvert(bm, e, &e_tmp, params, 0.5f, 0.5f, e->v1, e->v2, &e_new);
+ e_tmp = *e;
+ v = bm_subdivide_edge_addvert(bm, e, &e_tmp, params, 0.5f, 0.5f, e->v1, e->v2, &e_new);
- if (i != numcuts - 1) {
- connect_smallest_face(bm, v_last, v, &f_new);
- }
+ if (i != numcuts - 1) {
+ connect_smallest_face(bm, v_last, v, &f_new);
+ }
- v_last = v;
- }
+ v_last = v;
+ }
- connect_smallest_face(bm, v_last, verts[numcuts * 2 + 2], &f_new);
+ connect_smallest_face(bm, v_last, verts[numcuts * 2 + 2], &f_new);
}
static const SubDPattern quad_2edge_innervert = {
- {1, 1, 0, 0},
- quad_2edge_split_innervert,
- 4,
+ {1, 1, 0, 0},
+ quad_2edge_split_innervert,
+ 4,
};
/**
@@ -592,25 +603,27 @@ static const SubDPattern quad_2edge_innervert = {
* v7-v0--v1-v2
* </pre>
*/
-static void quad_2edge_split_fan(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
+static void quad_2edge_split_fan(BMesh *bm,
+ BMFace *UNUSED(face),
+ BMVert **verts,
const SubDParams *params)
{
- BMFace *f_new;
- /* BMVert *v; */ /* UNUSED */
- /* BMVert *v_last = verts[2]; */ /* UNUSED */
- /* BMEdge *e, *e_new; */ /* UNUSED */
- int i, numcuts = params->numcuts;
-
- for (i = 0; i < numcuts; i++) {
- connect_smallest_face(bm, verts[i], verts[numcuts * 2 + 2], &f_new);
- connect_smallest_face(bm, verts[numcuts + (numcuts - i)], verts[numcuts * 2 + 2], &f_new);
- }
+ BMFace *f_new;
+ /* BMVert *v; */ /* UNUSED */
+ /* BMVert *v_last = verts[2]; */ /* UNUSED */
+ /* BMEdge *e, *e_new; */ /* UNUSED */
+ int i, numcuts = params->numcuts;
+
+ for (i = 0; i < numcuts; i++) {
+ connect_smallest_face(bm, verts[i], verts[numcuts * 2 + 2], &f_new);
+ connect_smallest_face(bm, verts[numcuts + (numcuts - i)], verts[numcuts * 2 + 2], &f_new);
+ }
}
static const SubDPattern quad_2edge_fan = {
- {1, 1, 0, 0},
- quad_2edge_split_fan,
- 4,
+ {1, 1, 0, 0},
+ quad_2edge_split_fan,
+ 4,
};
/**
@@ -625,31 +638,33 @@ static const SubDPattern quad_2edge_fan = {
* v9-v0--v1-v2
* </pre>
*/
-static void quad_3edge_split(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
+static void quad_3edge_split(BMesh *bm,
+ BMFace *UNUSED(face),
+ BMVert **verts,
const SubDParams *params)
{
- BMFace *f_new;
- int i, add = 0, numcuts = params->numcuts;
-
- for (i = 0; i < numcuts; i++) {
- if (i == numcuts / 2) {
- if (numcuts % 2 != 0) {
- connect_smallest_face(bm, verts[numcuts - i - 1 + add], verts[i + numcuts + 1], &f_new);
- }
- add = numcuts * 2 + 2;
- }
- connect_smallest_face(bm, verts[numcuts - i - 1 + add], verts[i + numcuts + 1], &f_new);
- }
-
- for (i = 0; i < numcuts / 2 + 1; i++) {
- connect_smallest_face(bm, verts[i], verts[(numcuts - i) + numcuts * 2 + 1], &f_new);
- }
+ BMFace *f_new;
+ int i, add = 0, numcuts = params->numcuts;
+
+ for (i = 0; i < numcuts; i++) {
+ if (i == numcuts / 2) {
+ if (numcuts % 2 != 0) {
+ connect_smallest_face(bm, verts[numcuts - i - 1 + add], verts[i + numcuts + 1], &f_new);
+ }
+ add = numcuts * 2 + 2;
+ }
+ connect_smallest_face(bm, verts[numcuts - i - 1 + add], verts[i + numcuts + 1], &f_new);
+ }
+
+ for (i = 0; i < numcuts / 2 + 1; i++) {
+ connect_smallest_face(bm, verts[i], verts[(numcuts - i) + numcuts * 2 + 1], &f_new);
+ }
}
static const SubDPattern quad_3edge = {
- {1, 1, 1, 0},
- quad_3edge_split,
- 4,
+ {1, 1, 1, 0},
+ quad_3edge_split,
+ 4,
};
/**
@@ -664,74 +679,75 @@ static const SubDPattern quad_3edge = {
* it goes from bottom up
* </pre>
*/
-static void quad_4edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
+static void quad_4edge_subdivide(BMesh *bm,
+ BMFace *UNUSED(face),
+ BMVert **verts,
const SubDParams *params)
{
- BMFace *f_new;
- BMVert *v, *v1, *v2;
- BMEdge *e, *e_new, e_tmp;
- BMVert **lines;
- int numcuts = params->numcuts;
- int i, j, a, b, s = numcuts + 2 /* , totv = numcuts * 4 + 4 */;
-
- lines = MEM_callocN(sizeof(BMVert *) * (numcuts + 2) * (numcuts + 2), "q_4edge_split");
- /* build a 2-dimensional array of verts,
- * containing every vert (and all new ones)
- * in the face */
-
- /* first line */
- for (i = 0; i < numcuts + 2; i++) {
- lines[i] = verts[numcuts * 3 + 2 + (numcuts - i + 1)];
- }
-
- /* last line */
- for (i = 0; i < numcuts + 2; i++) {
- lines[(s - 1) * s + i] = verts[numcuts + i];
- }
-
- /* first and last members of middle lines */
- for (i = 0; i < numcuts; i++) {
- a = i;
- b = numcuts + 1 + numcuts + 1 + (numcuts - i - 1);
-
- e = connect_smallest_face(bm, verts[a], verts[b], &f_new);
- if (!e) {
- continue;
- }
-
- BMO_edge_flag_enable(bm, e, ELE_INNER);
- BMO_face_flag_enable(bm, f_new, ELE_INNER);
-
-
- v1 = lines[(i + 1) * s] = verts[a];
- v2 = lines[(i + 1) * s + s - 1] = verts[b];
-
- e_tmp = *e;
- for (a = 0; a < numcuts; a++) {
- v = subdivide_edge_num(bm, e, &e_tmp, a, numcuts, params, v1, v2, &e_new);
-
- BMESH_ASSERT(v != NULL);
-
- BMO_edge_flag_enable(bm, e_new, ELE_INNER);
- lines[(i + 1) * s + a + 1] = v;
- }
- }
-
- for (i = 1; i < numcuts + 2; i++) {
- for (j = 1; j <= numcuts; j++) {
- a = i * s + j;
- b = (i - 1) * s + j;
- e = connect_smallest_face(bm, lines[a], lines[b], &f_new);
- if (!e) {
- continue;
- }
-
- BMO_edge_flag_enable(bm, e, ELE_INNER);
- BMO_face_flag_enable(bm, f_new, ELE_INNER);
- }
- }
-
- MEM_freeN(lines);
+ BMFace *f_new;
+ BMVert *v, *v1, *v2;
+ BMEdge *e, *e_new, e_tmp;
+ BMVert **lines;
+ int numcuts = params->numcuts;
+ int i, j, a, b, s = numcuts + 2 /* , totv = numcuts * 4 + 4 */;
+
+ lines = MEM_callocN(sizeof(BMVert *) * (numcuts + 2) * (numcuts + 2), "q_4edge_split");
+ /* build a 2-dimensional array of verts,
+ * containing every vert (and all new ones)
+ * in the face */
+
+ /* first line */
+ for (i = 0; i < numcuts + 2; i++) {
+ lines[i] = verts[numcuts * 3 + 2 + (numcuts - i + 1)];
+ }
+
+ /* last line */
+ for (i = 0; i < numcuts + 2; i++) {
+ lines[(s - 1) * s + i] = verts[numcuts + i];
+ }
+
+ /* first and last members of middle lines */
+ for (i = 0; i < numcuts; i++) {
+ a = i;
+ b = numcuts + 1 + numcuts + 1 + (numcuts - i - 1);
+
+ e = connect_smallest_face(bm, verts[a], verts[b], &f_new);
+ if (!e) {
+ continue;
+ }
+
+ BMO_edge_flag_enable(bm, e, ELE_INNER);
+ BMO_face_flag_enable(bm, f_new, ELE_INNER);
+
+ v1 = lines[(i + 1) * s] = verts[a];
+ v2 = lines[(i + 1) * s + s - 1] = verts[b];
+
+ e_tmp = *e;
+ for (a = 0; a < numcuts; a++) {
+ v = subdivide_edge_num(bm, e, &e_tmp, a, numcuts, params, v1, v2, &e_new);
+
+ BMESH_ASSERT(v != NULL);
+
+ BMO_edge_flag_enable(bm, e_new, ELE_INNER);
+ lines[(i + 1) * s + a + 1] = v;
+ }
+ }
+
+ for (i = 1; i < numcuts + 2; i++) {
+ for (j = 1; j <= numcuts; j++) {
+ a = i * s + j;
+ b = (i - 1) * s + j;
+ e = connect_smallest_face(bm, lines[a], lines[b], &f_new);
+ if (!e) {
+ continue;
+ }
+
+ BMO_edge_flag_enable(bm, e, ELE_INNER);
+ BMO_face_flag_enable(bm, f_new, ELE_INNER);
+ }
+ }
+
+ MEM_freeN(lines);
}
/**
@@ -746,21 +762,23 @@ static void quad_4edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts
* s s
* </pre>
*/
-static void tri_1edge_split(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
+static void tri_1edge_split(BMesh *bm,
+ BMFace *UNUSED(face),
+ BMVert **verts,
const SubDParams *params)
{
- BMFace *f_new;
- int i, numcuts = params->numcuts;
+ BMFace *f_new;
+ int i, numcuts = params->numcuts;
- for (i = 0; i < numcuts; i++) {
- connect_smallest_face(bm, verts[i], verts[numcuts + 1], &f_new);
- }
+ for (i = 0; i < numcuts; i++) {
+ connect_smallest_face(bm, verts[i], verts[numcuts + 1], &f_new);
+ }
}
static const SubDPattern tri_1edge = {
- {1, 0, 0},
- tri_1edge_split,
- 3,
+ {1, 0, 0},
+ tri_1edge_split,
+ 3,
};
/**
@@ -775,615 +793,636 @@ static const SubDPattern tri_1edge = {
* s s
* </pre>
*/
-static void tri_3edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
+static void tri_3edge_subdivide(BMesh *bm,
+ BMFace *UNUSED(face),
+ BMVert **verts,
const SubDParams *params)
{
- BMFace *f_new;
- BMEdge *e, *e_new, e_tmp;
- BMVert ***lines, *v, v1_tmp, v2_tmp;
- void *stackarr[1];
- int i, j, a, b, numcuts = params->numcuts;
-
- /* number of verts in each lin */
- lines = MEM_callocN(sizeof(void *) * (numcuts + 2), "triangle vert table");
-
- lines[0] = (BMVert **) stackarr;
- lines[0][0] = verts[numcuts * 2 + 1];
-
- lines[numcuts + 1] = MEM_callocN(sizeof(void *) * (numcuts + 2), "triangle vert table 2");
- for (i = 0; i < numcuts; i++) {
- lines[numcuts + 1][i + 1] = verts[i];
- }
- lines[numcuts + 1][0] = verts[numcuts * 3 + 2];
- lines[numcuts + 1][numcuts + 1] = verts[numcuts];
-
- for (i = 0; i < numcuts; i++) {
- lines[i + 1] = MEM_callocN(sizeof(void *) * (2 + i), "triangle vert table row");
- a = numcuts * 2 + 2 + i;
- b = numcuts + numcuts - i;
- e = connect_smallest_face(bm, verts[a], verts[b], &f_new);
- if (!e) {
- goto cleanup;
- }
-
- BMO_edge_flag_enable(bm, e, ELE_INNER);
- BMO_face_flag_enable(bm, f_new, ELE_INNER);
-
- lines[i + 1][0] = verts[a];
- lines[i + 1][i + 1] = verts[b];
-
- e_tmp = *e;
- v1_tmp = *verts[a];
- v2_tmp = *verts[b];
- e_tmp.v1 = &v1_tmp;
- e_tmp.v2 = &v2_tmp;
- for (j = 0; j < i; j++) {
- v = subdivide_edge_num(bm, e, &e_tmp, j, i, params, verts[a], verts[b], &e_new);
- lines[i + 1][j + 1] = v;
-
- BMO_edge_flag_enable(bm, e_new, ELE_INNER);
- }
- }
-
- /**
- * <pre>
- * v5
- * / \
- * s v6/---\ v4 s
- * / \ / \
- * sv7/---v---\ v3 s
- * / \/ \/ \
- * v8--v0--v1--v2
- * s s
- * </pre>
- */
- for (i = 1; i <= numcuts; i++) {
- for (j = 0; j < i; j++) {
- e = connect_smallest_face(bm, lines[i][j], lines[i + 1][j + 1], &f_new);
-
- BMO_edge_flag_enable(bm, e, ELE_INNER);
- BMO_face_flag_enable(bm, f_new, ELE_INNER);
-
- e = connect_smallest_face(bm, lines[i][j + 1], lines[i + 1][j + 1], &f_new);
-
- BMO_edge_flag_enable(bm, e, ELE_INNER);
- BMO_face_flag_enable(bm, f_new, ELE_INNER);
- }
- }
+ BMFace *f_new;
+ BMEdge *e, *e_new, e_tmp;
+ BMVert ***lines, *v, v1_tmp, v2_tmp;
+ void *stackarr[1];
+ int i, j, a, b, numcuts = params->numcuts;
+
+ /* number of verts in each lin */
+ lines = MEM_callocN(sizeof(void *) * (numcuts + 2), "triangle vert table");
+
+ lines[0] = (BMVert **)stackarr;
+ lines[0][0] = verts[numcuts * 2 + 1];
+
+ lines[numcuts + 1] = MEM_callocN(sizeof(void *) * (numcuts + 2), "triangle vert table 2");
+ for (i = 0; i < numcuts; i++) {
+ lines[numcuts + 1][i + 1] = verts[i];
+ }
+ lines[numcuts + 1][0] = verts[numcuts * 3 + 2];
+ lines[numcuts + 1][numcuts + 1] = verts[numcuts];
+
+ for (i = 0; i < numcuts; i++) {
+ lines[i + 1] = MEM_callocN(sizeof(void *) * (2 + i), "triangle vert table row");
+ a = numcuts * 2 + 2 + i;
+ b = numcuts + numcuts - i;
+ e = connect_smallest_face(bm, verts[a], verts[b], &f_new);
+ if (!e) {
+ goto cleanup;
+ }
+
+ BMO_edge_flag_enable(bm, e, ELE_INNER);
+ BMO_face_flag_enable(bm, f_new, ELE_INNER);
+
+ lines[i + 1][0] = verts[a];
+ lines[i + 1][i + 1] = verts[b];
+
+ e_tmp = *e;
+ v1_tmp = *verts[a];
+ v2_tmp = *verts[b];
+ e_tmp.v1 = &v1_tmp;
+ e_tmp.v2 = &v2_tmp;
+ for (j = 0; j < i; j++) {
+ v = subdivide_edge_num(bm, e, &e_tmp, j, i, params, verts[a], verts[b], &e_new);
+ lines[i + 1][j + 1] = v;
+
+ BMO_edge_flag_enable(bm, e_new, ELE_INNER);
+ }
+ }
+
+ /**
+ * <pre>
+ * v5
+ * / \
+ * s v6/---\ v4 s
+ * / \ / \
+ * sv7/---v---\ v3 s
+ * / \/ \/ \
+ * v8--v0--v1--v2
+ * s s
+ * </pre>
+ */
+ for (i = 1; i <= numcuts; i++) {
+ for (j = 0; j < i; j++) {
+ e = connect_smallest_face(bm, lines[i][j], lines[i + 1][j + 1], &f_new);
+
+ BMO_edge_flag_enable(bm, e, ELE_INNER);
+ BMO_face_flag_enable(bm, f_new, ELE_INNER);
+
+ e = connect_smallest_face(bm, lines[i][j + 1], lines[i + 1][j + 1], &f_new);
+
+ BMO_edge_flag_enable(bm, e, ELE_INNER);
+ BMO_face_flag_enable(bm, f_new, ELE_INNER);
+ }
+ }
cleanup:
- for (i = 1; i < numcuts + 2; i++) {
- if (lines[i]) {
- MEM_freeN(lines[i]);
- }
- }
+ for (i = 1; i < numcuts + 2; i++) {
+ if (lines[i]) {
+ MEM_freeN(lines[i]);
+ }
+ }
- MEM_freeN(lines);
+ MEM_freeN(lines);
}
static const SubDPattern tri_3edge = {
- {1, 1, 1},
- tri_3edge_subdivide,
- 3,
+ {1, 1, 1},
+ tri_3edge_subdivide,
+ 3,
};
-
static const SubDPattern quad_4edge = {
- {1, 1, 1, 1},
- quad_4edge_subdivide,
- 4,
+ {1, 1, 1, 1},
+ quad_4edge_subdivide,
+ 4,
};
static const SubDPattern *patterns[] = {
- NULL, /* quad single edge pattern is inserted here */
- NULL, /* quad corner vert pattern is inserted here */
- NULL, /* tri single edge pattern is inserted here */
- NULL,
- &quad_3edge,
- NULL,
+ NULL, /* quad single edge pattern is inserted here */
+ NULL, /* quad corner vert pattern is inserted here */
+ NULL, /* tri single edge pattern is inserted here */
+ NULL,
+ &quad_3edge,
+ NULL,
};
-#define PATTERNS_TOT ARRAY_SIZE(patterns)
+#define PATTERNS_TOT ARRAY_SIZE(patterns)
typedef struct SubDFaceData {
- BMVert *start;
- const SubDPattern *pat;
- int totedgesel; /* only used if pat was NULL, e.g. no pattern was found */
- BMFace *face;
+ BMVert *start;
+ const SubDPattern *pat;
+ int totedgesel; /* only used if pat was NULL, e.g. no pattern was found */
+ BMFace *face;
} SubDFaceData;
void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
{
- BMOpSlot *einput;
- const SubDPattern *pat;
- SubDParams params;
- BLI_Stack *facedata;
- BMIter viter, fiter, liter;
- BMVert *v, **verts = NULL;
- BMEdge *edge;
- BMEdge **edges = NULL;
- BLI_array_declare(edges);
- BMLoop *(*loops_split)[2] = NULL;
- BLI_array_declare(loops_split);
- BMLoop **loops = NULL;
- BLI_array_declare(loops);
- BMLoop *l_new, *l;
- BMFace *face;
- BLI_array_declare(verts);
- float smooth, fractal, along_normal;
- bool use_sphere, use_single_edge, use_grid_fill, use_only_quads;
- int cornertype, seed, i, j, a, b, numcuts, totesel, smooth_falloff;
-
- BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, SUBD_SPLIT);
-
- numcuts = BMO_slot_int_get(op->slots_in, "cuts");
- seed = BMO_slot_int_get(op->slots_in, "seed");
- smooth = BMO_slot_float_get(op->slots_in, "smooth");
- smooth_falloff = BMO_slot_int_get(op->slots_in, "smooth_falloff");
- fractal = BMO_slot_float_get(op->slots_in, "fractal");
- along_normal = BMO_slot_float_get(op->slots_in, "along_normal");
- cornertype = BMO_slot_int_get(op->slots_in, "quad_corner_type");
-
- use_single_edge = BMO_slot_bool_get(op->slots_in, "use_single_edge");
- use_grid_fill = BMO_slot_bool_get(op->slots_in, "use_grid_fill");
- use_only_quads = BMO_slot_bool_get(op->slots_in, "use_only_quads");
- use_sphere = BMO_slot_bool_get(op->slots_in, "use_sphere");
-
- patterns[1] = NULL;
- /* straight cut is patterns[1] == NULL */
- switch (cornertype) {
- case SUBD_CORNER_PATH:
- patterns[1] = &quad_2edge_path;
- break;
- case SUBD_CORNER_INNERVERT:
- patterns[1] = &quad_2edge_innervert;
- break;
- case SUBD_CORNER_FAN:
- patterns[1] = &quad_2edge_fan;
- break;
- }
-
- if (use_single_edge) {
- patterns[0] = &quad_1edge;
- patterns[2] = &tri_1edge;
- }
- else {
- patterns[0] = NULL;
- patterns[2] = NULL;
- }
-
- if (use_grid_fill) {
- patterns[3] = &quad_4edge;
- patterns[5] = &tri_3edge;
- }
- else {
- patterns[3] = NULL;
- patterns[5] = NULL;
- }
-
- /* add a temporary shapekey layer to store displacements on current geometry */
- BM_data_layer_add(bm, &bm->vdata, CD_SHAPEKEY);
-
- bmo_subd_init_shape_info(bm, &params);
-
- BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
- float *co = BM_ELEM_CD_GET_VOID_P(v, params.shape_info.cd_vert_shape_offset_tmp);
- copy_v3_v3(co, v->co);
- }
-
- /* first go through and tag edges */
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_in, "edges", BM_EDGE, SUBD_SPLIT);
-
- params.numcuts = numcuts;
- params.op = op;
- params.slot_edge_percents = BMO_slot_get(op->slots_in, "edge_percents");
- params.slot_custom_patterns = BMO_slot_get(op->slots_in, "custom_patterns");
- params.smooth = smooth;
- params.smooth_falloff = smooth_falloff;
- params.seed = seed;
- params.fractal = fractal;
- params.along_normal = along_normal;
- params.use_smooth = (smooth != 0.0f);
- params.use_smooth_even = BMO_slot_bool_get(op->slots_in, "use_smooth_even");
- params.use_fractal = (fractal != 0.0f);
- params.use_sphere = use_sphere;
-
- if (params.use_fractal) {
- RNG *rng = BLI_rng_new_srandom(seed);
-
- params.fractal_ofs[0] = BLI_rng_get_float(rng) * 200.0f;
- params.fractal_ofs[1] = BLI_rng_get_float(rng) * 200.0f;
- params.fractal_ofs[2] = BLI_rng_get_float(rng) * 200.0f;
-
- BLI_rng_free(rng);
- }
-
- BMO_slot_map_to_flag(bm, op->slots_in, "custom_patterns",
- BM_FACE, FACE_CUSTOMFILL);
-
- BMO_slot_map_to_flag(bm, op->slots_in, "edge_percents",
- BM_EDGE, EDGE_PERCENT);
-
-
- facedata = BLI_stack_new(sizeof(SubDFaceData), __func__);
-
- BM_ITER_MESH (face, &fiter, bm, BM_FACES_OF_MESH) {
- BMEdge *e1 = NULL, *e2 = NULL;
- float vec1[3], vec2[3];
- bool matched = false;
-
- /* skip non-quads if requested */
- if (use_only_quads && face->len != 4) {
- continue;
- }
-
- /* figure out which pattern to use */
-
- BLI_array_clear(edges);
- BLI_array_clear(verts);
-
- BLI_array_grow_items(edges, face->len);
- BLI_array_grow_items(verts, face->len);
-
- totesel = 0;
- BM_ITER_ELEM_INDEX (l_new, &liter, face, BM_LOOPS_OF_FACE, i) {
- edges[i] = l_new->e;
- verts[i] = l_new->v;
-
- if (BMO_edge_flag_test(bm, edges[i], SUBD_SPLIT)) {
- if (!e1) { e1 = edges[i]; }
- else { e2 = edges[i]; }
-
- totesel++;
- }
- }
-
- /* make sure the two edges have a valid angle to each other */
- if (totesel == 2 && BM_edge_share_vert_check(e1, e2)) {
- sub_v3_v3v3(vec1, e1->v2->co, e1->v1->co);
- sub_v3_v3v3(vec2, e2->v2->co, e2->v1->co);
- normalize_v3(vec1);
- normalize_v3(vec2);
-
- if (fabsf(dot_v3v3(vec1, vec2)) > 1.0f - FLT_FACE_SPLIT_EPSILON) {
- totesel = 0;
- }
- }
-
- if (BMO_face_flag_test(bm, face, FACE_CUSTOMFILL)) {
- pat = *BMO_slot_map_data_get(params.slot_custom_patterns, face);
- for (i = 0; i < pat->len; i++) {
- matched = 1;
- for (j = 0; j < pat->len; j++) {
- a = (j + i) % pat->len;
- if ((!!BMO_edge_flag_test(bm, edges[a], SUBD_SPLIT)) != (!!pat->seledges[j])) {
- matched = 0;
- break;
- }
- }
- if (matched) {
- SubDFaceData *fd;
-
- fd = BLI_stack_push_r(facedata);
- fd->pat = pat;
- fd->start = verts[i];
- fd->face = face;
- fd->totedgesel = totesel;
- BMO_face_flag_enable(bm, face, SUBD_SPLIT);
- break;
- }
- }
-
- /* obvously don't test for other patterns matching */
- continue;
- }
-
- for (i = 0; i < PATTERNS_TOT; i++) {
- pat = patterns[i];
- if (!pat) {
- continue;
- }
-
- if (pat->len == face->len) {
- for (a = 0; a < pat->len; a++) {
- matched = 1;
- for (b = 0; b < pat->len; b++) {
- j = (b + a) % pat->len;
- if ((!!BMO_edge_flag_test(bm, edges[j], SUBD_SPLIT)) != (!!pat->seledges[b])) {
- matched = 0;
- break;
- }
- }
- if (matched) {
- break;
- }
- }
- if (matched) {
- SubDFaceData *fd;
-
- BMO_face_flag_enable(bm, face, SUBD_SPLIT);
-
- fd = BLI_stack_push_r(facedata);
- fd->pat = pat;
- fd->start = verts[a];
- fd->face = face;
- fd->totedgesel = totesel;
- break;
- }
- }
-
- }
-
- if (!matched && totesel) {
- SubDFaceData *fd;
-
- BMO_face_flag_enable(bm, face, SUBD_SPLIT);
-
- /* must initialize all members here */
- fd = BLI_stack_push_r(facedata);
- fd->start = NULL;
- fd->pat = NULL;
- fd->totedgesel = totesel;
- fd->face = face;
- }
- }
-
- einput = BMO_slot_get(op->slots_in, "edges");
-
- /* go through and split edges */
- for (i = 0; i < einput->len; i++) {
- edge = einput->data.buf[i];
- bm_subdivide_multicut(bm, edge, &params, edge->v1, edge->v2);
- }
-
- /* copy original-geometry displacements to current coordinates */
- BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
- const float *co = BM_ELEM_CD_GET_VOID_P(v, params.shape_info.cd_vert_shape_offset_tmp);
- copy_v3_v3(v->co, co);
- }
-
- for (; !BLI_stack_is_empty(facedata); BLI_stack_discard(facedata)) {
- SubDFaceData *fd = BLI_stack_peek(facedata);
-
- face = fd->face;
-
- /* figure out which pattern to use */
- BLI_array_clear(verts);
-
- pat = fd->pat;
-
- if (!pat && fd->totedgesel == 2) {
- int vlen;
-
- /* ok, no pattern. we still may be able to do something */
- BLI_array_clear(loops);
- BLI_array_clear(loops_split);
-
- /* for case of two edges, connecting them shouldn't be too hard */
- BLI_array_grow_items(loops, face->len);
- BM_ITER_ELEM_INDEX (l, &liter, face, BM_LOOPS_OF_FACE, a) {
- loops[a] = l;
- }
-
- vlen = BLI_array_len(loops);
-
- /* find the boundary of one of the split edges */
- for (a = 1; a < vlen; a++) {
- if (!BMO_vert_flag_test(bm, loops[a - 1]->v, ELE_INNER) &&
- BMO_vert_flag_test(bm, loops[a]->v, ELE_INNER))
- {
- break;
- }
- }
-
- if (BMO_vert_flag_test(bm, loops[(a + numcuts + 1) % vlen]->v, ELE_INNER)) {
- b = (a + numcuts + 1) % vlen;
- }
- else {
- /* find the boundary of the other edge. */
- for (j = 0; j < vlen; j++) {
- b = (j + a + numcuts + 1) % vlen;
- if (!BMO_vert_flag_test(bm, loops[b == 0 ? vlen - 1 : b - 1]->v, ELE_INNER) &&
- BMO_vert_flag_test(bm, loops[b]->v, ELE_INNER))
- {
- break;
- }
- }
- }
-
- b += numcuts - 1;
-
- BLI_array_grow_items(loops_split, numcuts);
- for (j = 0; j < numcuts; j++) {
- bool ok = true;
-
- /* Check for special case: [#32500]
- * This edge pair could be used by more than one face,
- * in this case it used to (2.63), split both faces along the same verts
- * while it could be calculated which face should do the split,
- * it's ambiguous, so in this case we're better off to skip them as exceptional cases
- * and not try to be clever guessing which face to cut up.
- *
- * To avoid this case we need to check:
- * Do the verts of each share a face besides the one we are subdividing,
- * (but not connect to make an edge of that face).
- */
- {
- BMLoop *other_loop;
- BMIter other_fiter;
- BM_ITER_ELEM (other_loop, &other_fiter, loops[a]->v, BM_LOOPS_OF_VERT) {
- if (other_loop->f != face) {
- if (BM_vert_in_face(loops[b]->v, other_loop->f)) {
- /* we assume that these verts are not making an edge in the face */
- BLI_assert(other_loop->prev->v != loops[a]->v);
- BLI_assert(other_loop->next->v != loops[a]->v);
-
- ok = false;
- break;
- }
- }
- }
- }
-
-
- if (ok == true) {
- loops_split[j][0] = loops[a];
- loops_split[j][1] = loops[b];
- }
- else {
- loops_split[j][0] = NULL;
- loops_split[j][1] = NULL;
- }
-
- b = (b - 1) % vlen;
- a = (a + 1) % vlen;
- }
-
- /* Since these are newly created vertices, we don't need to worry about them being legal,
- * ... though there are some cases we _should_ check for
- * - concave corner of an ngon.
- * - 2 edges being used in 2+ ngons.
- */
-// BM_face_splits_check_legal(bm, face, loops_split, BLI_array_len(loops_split));
-
- for (j = 0; j < BLI_array_len(loops_split); j++) {
- if (loops_split[j][0]) {
- BMFace *f_new;
- BLI_assert(BM_edge_exists(loops_split[j][0]->v, loops_split[j][1]->v) == NULL);
- f_new = BM_face_split(bm, face, loops_split[j][0], loops_split[j][1], &l_new, NULL, false);
- if (f_new) {
- BMO_edge_flag_enable(bm, l_new->e, ELE_INNER);
- }
- }
- }
-
- continue;
- }
- else if (!pat) {
- continue;
- }
-
- a = 0;
- BM_ITER_ELEM_INDEX (l_new, &liter, face, BM_LOOPS_OF_FACE, j) {
- if (l_new->v == fd->start) {
- a = j + 1;
- break;
- }
- }
-
- BLI_array_grow_items(verts, face->len);
-
- BM_ITER_ELEM_INDEX (l_new, &liter, face, BM_LOOPS_OF_FACE, j) {
- b = (j - a + face->len) % face->len;
- verts[b] = l_new->v;
- }
-
- BM_CHECK_ELEMENT(face);
- pat->connectexec(bm, face, verts, &params);
- }
-
- /* copy original-geometry displacements to current coordinates */
- BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
- const float *co = BM_ELEM_CD_GET_VOID_P(v, params.shape_info.cd_vert_shape_offset_tmp);
- copy_v3_v3(v->co, co);
- }
-
- BM_data_layer_free_n(bm, &bm->vdata, CD_SHAPEKEY, params.shape_info.tmpkey);
-
- BLI_stack_free(facedata);
- if (edges) {
- BLI_array_free(edges);
- }
- if (verts) {
- BLI_array_free(verts);
- }
- BLI_array_free(loops_split);
- BLI_array_free(loops);
-
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_inner.out", BM_ALL_NOLOOP, ELE_INNER);
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_split.out", BM_ALL_NOLOOP, ELE_SPLIT);
-
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_ALL_NOLOOP, ELE_INNER | ELE_SPLIT | SUBD_SPLIT);
+ BMOpSlot *einput;
+ const SubDPattern *pat;
+ SubDParams params;
+ BLI_Stack *facedata;
+ BMIter viter, fiter, liter;
+ BMVert *v, **verts = NULL;
+ BMEdge *edge;
+ BMEdge **edges = NULL;
+ BLI_array_declare(edges);
+ BMLoop *(*loops_split)[2] = NULL;
+ BLI_array_declare(loops_split);
+ BMLoop **loops = NULL;
+ BLI_array_declare(loops);
+ BMLoop *l_new, *l;
+ BMFace *face;
+ BLI_array_declare(verts);
+ float smooth, fractal, along_normal;
+ bool use_sphere, use_single_edge, use_grid_fill, use_only_quads;
+ int cornertype, seed, i, j, a, b, numcuts, totesel, smooth_falloff;
+
+ BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, SUBD_SPLIT);
+
+ numcuts = BMO_slot_int_get(op->slots_in, "cuts");
+ seed = BMO_slot_int_get(op->slots_in, "seed");
+ smooth = BMO_slot_float_get(op->slots_in, "smooth");
+ smooth_falloff = BMO_slot_int_get(op->slots_in, "smooth_falloff");
+ fractal = BMO_slot_float_get(op->slots_in, "fractal");
+ along_normal = BMO_slot_float_get(op->slots_in, "along_normal");
+ cornertype = BMO_slot_int_get(op->slots_in, "quad_corner_type");
+
+ use_single_edge = BMO_slot_bool_get(op->slots_in, "use_single_edge");
+ use_grid_fill = BMO_slot_bool_get(op->slots_in, "use_grid_fill");
+ use_only_quads = BMO_slot_bool_get(op->slots_in, "use_only_quads");
+ use_sphere = BMO_slot_bool_get(op->slots_in, "use_sphere");
+
+ patterns[1] = NULL;
+ /* straight cut is patterns[1] == NULL */
+ switch (cornertype) {
+ case SUBD_CORNER_PATH:
+ patterns[1] = &quad_2edge_path;
+ break;
+ case SUBD_CORNER_INNERVERT:
+ patterns[1] = &quad_2edge_innervert;
+ break;
+ case SUBD_CORNER_FAN:
+ patterns[1] = &quad_2edge_fan;
+ break;
+ }
+
+ if (use_single_edge) {
+ patterns[0] = &quad_1edge;
+ patterns[2] = &tri_1edge;
+ }
+ else {
+ patterns[0] = NULL;
+ patterns[2] = NULL;
+ }
+
+ if (use_grid_fill) {
+ patterns[3] = &quad_4edge;
+ patterns[5] = &tri_3edge;
+ }
+ else {
+ patterns[3] = NULL;
+ patterns[5] = NULL;
+ }
+
+ /* add a temporary shapekey layer to store displacements on current geometry */
+ BM_data_layer_add(bm, &bm->vdata, CD_SHAPEKEY);
+
+ bmo_subd_init_shape_info(bm, &params);
+
+ BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
+ float *co = BM_ELEM_CD_GET_VOID_P(v, params.shape_info.cd_vert_shape_offset_tmp);
+ copy_v3_v3(co, v->co);
+ }
+
+ /* first go through and tag edges */
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_in, "edges", BM_EDGE, SUBD_SPLIT);
+
+ params.numcuts = numcuts;
+ params.op = op;
+ params.slot_edge_percents = BMO_slot_get(op->slots_in, "edge_percents");
+ params.slot_custom_patterns = BMO_slot_get(op->slots_in, "custom_patterns");
+ params.smooth = smooth;
+ params.smooth_falloff = smooth_falloff;
+ params.seed = seed;
+ params.fractal = fractal;
+ params.along_normal = along_normal;
+ params.use_smooth = (smooth != 0.0f);
+ params.use_smooth_even = BMO_slot_bool_get(op->slots_in, "use_smooth_even");
+ params.use_fractal = (fractal != 0.0f);
+ params.use_sphere = use_sphere;
+
+ if (params.use_fractal) {
+ RNG *rng = BLI_rng_new_srandom(seed);
+
+ params.fractal_ofs[0] = BLI_rng_get_float(rng) * 200.0f;
+ params.fractal_ofs[1] = BLI_rng_get_float(rng) * 200.0f;
+ params.fractal_ofs[2] = BLI_rng_get_float(rng) * 200.0f;
+
+ BLI_rng_free(rng);
+ }
+
+ BMO_slot_map_to_flag(bm, op->slots_in, "custom_patterns", BM_FACE, FACE_CUSTOMFILL);
+
+ BMO_slot_map_to_flag(bm, op->slots_in, "edge_percents", BM_EDGE, EDGE_PERCENT);
+
+ facedata = BLI_stack_new(sizeof(SubDFaceData), __func__);
+
+ BM_ITER_MESH (face, &fiter, bm, BM_FACES_OF_MESH) {
+ BMEdge *e1 = NULL, *e2 = NULL;
+ float vec1[3], vec2[3];
+ bool matched = false;
+
+ /* skip non-quads if requested */
+ if (use_only_quads && face->len != 4) {
+ continue;
+ }
+
+ /* figure out which pattern to use */
+
+ BLI_array_clear(edges);
+ BLI_array_clear(verts);
+
+ BLI_array_grow_items(edges, face->len);
+ BLI_array_grow_items(verts, face->len);
+
+ totesel = 0;
+ BM_ITER_ELEM_INDEX(l_new, &liter, face, BM_LOOPS_OF_FACE, i)
+ {
+ edges[i] = l_new->e;
+ verts[i] = l_new->v;
+
+ if (BMO_edge_flag_test(bm, edges[i], SUBD_SPLIT)) {
+ if (!e1) {
+ e1 = edges[i];
+ }
+ else {
+ e2 = edges[i];
+ }
+
+ totesel++;
+ }
+ }
+
+ /* make sure the two edges have a valid angle to each other */
+ if (totesel == 2 && BM_edge_share_vert_check(e1, e2)) {
+ sub_v3_v3v3(vec1, e1->v2->co, e1->v1->co);
+ sub_v3_v3v3(vec2, e2->v2->co, e2->v1->co);
+ normalize_v3(vec1);
+ normalize_v3(vec2);
+
+ if (fabsf(dot_v3v3(vec1, vec2)) > 1.0f - FLT_FACE_SPLIT_EPSILON) {
+ totesel = 0;
+ }
+ }
+
+ if (BMO_face_flag_test(bm, face, FACE_CUSTOMFILL)) {
+ pat = *BMO_slot_map_data_get(params.slot_custom_patterns, face);
+ for (i = 0; i < pat->len; i++) {
+ matched = 1;
+ for (j = 0; j < pat->len; j++) {
+ a = (j + i) % pat->len;
+ if ((!!BMO_edge_flag_test(bm, edges[a], SUBD_SPLIT)) != (!!pat->seledges[j])) {
+ matched = 0;
+ break;
+ }
+ }
+ if (matched) {
+ SubDFaceData *fd;
+
+ fd = BLI_stack_push_r(facedata);
+ fd->pat = pat;
+ fd->start = verts[i];
+ fd->face = face;
+ fd->totedgesel = totesel;
+ BMO_face_flag_enable(bm, face, SUBD_SPLIT);
+ break;
+ }
+ }
+
+ /* obvously don't test for other patterns matching */
+ continue;
+ }
+
+ for (i = 0; i < PATTERNS_TOT; i++) {
+ pat = patterns[i];
+ if (!pat) {
+ continue;
+ }
+
+ if (pat->len == face->len) {
+ for (a = 0; a < pat->len; a++) {
+ matched = 1;
+ for (b = 0; b < pat->len; b++) {
+ j = (b + a) % pat->len;
+ if ((!!BMO_edge_flag_test(bm, edges[j], SUBD_SPLIT)) != (!!pat->seledges[b])) {
+ matched = 0;
+ break;
+ }
+ }
+ if (matched) {
+ break;
+ }
+ }
+ if (matched) {
+ SubDFaceData *fd;
+
+ BMO_face_flag_enable(bm, face, SUBD_SPLIT);
+
+ fd = BLI_stack_push_r(facedata);
+ fd->pat = pat;
+ fd->start = verts[a];
+ fd->face = face;
+ fd->totedgesel = totesel;
+ break;
+ }
+ }
+ }
+
+ if (!matched && totesel) {
+ SubDFaceData *fd;
+
+ BMO_face_flag_enable(bm, face, SUBD_SPLIT);
+
+ /* must initialize all members here */
+ fd = BLI_stack_push_r(facedata);
+ fd->start = NULL;
+ fd->pat = NULL;
+ fd->totedgesel = totesel;
+ fd->face = face;
+ }
+ }
+
+ einput = BMO_slot_get(op->slots_in, "edges");
+
+ /* go through and split edges */
+ for (i = 0; i < einput->len; i++) {
+ edge = einput->data.buf[i];
+ bm_subdivide_multicut(bm, edge, &params, edge->v1, edge->v2);
+ }
+
+ /* copy original-geometry displacements to current coordinates */
+ BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
+ const float *co = BM_ELEM_CD_GET_VOID_P(v, params.shape_info.cd_vert_shape_offset_tmp);
+ copy_v3_v3(v->co, co);
+ }
+
+ for (; !BLI_stack_is_empty(facedata); BLI_stack_discard(facedata)) {
+ SubDFaceData *fd = BLI_stack_peek(facedata);
+
+ face = fd->face;
+
+ /* figure out which pattern to use */
+ BLI_array_clear(verts);
+
+ pat = fd->pat;
+
+ if (!pat && fd->totedgesel == 2) {
+ int vlen;
+
+ /* ok, no pattern. we still may be able to do something */
+ BLI_array_clear(loops);
+ BLI_array_clear(loops_split);
+
+ /* for case of two edges, connecting them shouldn't be too hard */
+ BLI_array_grow_items(loops, face->len);
+ BM_ITER_ELEM_INDEX(l, &liter, face, BM_LOOPS_OF_FACE, a)
+ {
+ loops[a] = l;
+ }
+
+ vlen = BLI_array_len(loops);
+
+ /* find the boundary of one of the split edges */
+ for (a = 1; a < vlen; a++) {
+ if (!BMO_vert_flag_test(bm, loops[a - 1]->v, ELE_INNER) &&
+ BMO_vert_flag_test(bm, loops[a]->v, ELE_INNER)) {
+ break;
+ }
+ }
+
+ if (BMO_vert_flag_test(bm, loops[(a + numcuts + 1) % vlen]->v, ELE_INNER)) {
+ b = (a + numcuts + 1) % vlen;
+ }
+ else {
+ /* find the boundary of the other edge. */
+ for (j = 0; j < vlen; j++) {
+ b = (j + a + numcuts + 1) % vlen;
+ if (!BMO_vert_flag_test(bm, loops[b == 0 ? vlen - 1 : b - 1]->v, ELE_INNER) &&
+ BMO_vert_flag_test(bm, loops[b]->v, ELE_INNER)) {
+ break;
+ }
+ }
+ }
+
+ b += numcuts - 1;
+
+ BLI_array_grow_items(loops_split, numcuts);
+ for (j = 0; j < numcuts; j++) {
+ bool ok = true;
+
+ /* Check for special case: [#32500]
+ * This edge pair could be used by more than one face,
+ * in this case it used to (2.63), split both faces along the same verts
+ * while it could be calculated which face should do the split,
+ * it's ambiguous, so in this case we're better off to skip them as exceptional cases
+ * and not try to be clever guessing which face to cut up.
+ *
+ * To avoid this case we need to check:
+ * Do the verts of each share a face besides the one we are subdividing,
+ * (but not connect to make an edge of that face).
+ */
+ {
+ BMLoop *other_loop;
+ BMIter other_fiter;
+ BM_ITER_ELEM (other_loop, &other_fiter, loops[a]->v, BM_LOOPS_OF_VERT) {
+ if (other_loop->f != face) {
+ if (BM_vert_in_face(loops[b]->v, other_loop->f)) {
+ /* we assume that these verts are not making an edge in the face */
+ BLI_assert(other_loop->prev->v != loops[a]->v);
+ BLI_assert(other_loop->next->v != loops[a]->v);
+
+ ok = false;
+ break;
+ }
+ }
+ }
+ }
+
+ if (ok == true) {
+ loops_split[j][0] = loops[a];
+ loops_split[j][1] = loops[b];
+ }
+ else {
+ loops_split[j][0] = NULL;
+ loops_split[j][1] = NULL;
+ }
+
+ b = (b - 1) % vlen;
+ a = (a + 1) % vlen;
+ }
+
+ /* Since these are newly created vertices, we don't need to worry about them being legal,
+ * ... though there are some cases we _should_ check for
+ * - concave corner of an ngon.
+ * - 2 edges being used in 2+ ngons.
+ */
+ // BM_face_splits_check_legal(bm, face, loops_split, BLI_array_len(loops_split));
+
+ for (j = 0; j < BLI_array_len(loops_split); j++) {
+ if (loops_split[j][0]) {
+ BMFace *f_new;
+ BLI_assert(BM_edge_exists(loops_split[j][0]->v, loops_split[j][1]->v) == NULL);
+ f_new = BM_face_split(
+ bm, face, loops_split[j][0], loops_split[j][1], &l_new, NULL, false);
+ if (f_new) {
+ BMO_edge_flag_enable(bm, l_new->e, ELE_INNER);
+ }
+ }
+ }
+
+ continue;
+ }
+ else if (!pat) {
+ continue;
+ }
+
+ a = 0;
+ BM_ITER_ELEM_INDEX(l_new, &liter, face, BM_LOOPS_OF_FACE, j)
+ {
+ if (l_new->v == fd->start) {
+ a = j + 1;
+ break;
+ }
+ }
+
+ BLI_array_grow_items(verts, face->len);
+
+ BM_ITER_ELEM_INDEX(l_new, &liter, face, BM_LOOPS_OF_FACE, j)
+ {
+ b = (j - a + face->len) % face->len;
+ verts[b] = l_new->v;
+ }
+
+ BM_CHECK_ELEMENT(face);
+ pat->connectexec(bm, face, verts, &params);
+ }
+
+ /* copy original-geometry displacements to current coordinates */
+ BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
+ const float *co = BM_ELEM_CD_GET_VOID_P(v, params.shape_info.cd_vert_shape_offset_tmp);
+ copy_v3_v3(v->co, co);
+ }
+
+ BM_data_layer_free_n(bm, &bm->vdata, CD_SHAPEKEY, params.shape_info.tmpkey);
+
+ BLI_stack_free(facedata);
+ if (edges) {
+ BLI_array_free(edges);
+ }
+ if (verts) {
+ BLI_array_free(verts);
+ }
+ BLI_array_free(loops_split);
+ BLI_array_free(loops);
+
+ BMO_slot_buffer_from_enabled_flag(
+ bm, op, op->slots_out, "geom_inner.out", BM_ALL_NOLOOP, ELE_INNER);
+ BMO_slot_buffer_from_enabled_flag(
+ bm, op, op->slots_out, "geom_split.out", BM_ALL_NOLOOP, ELE_SPLIT);
+
+ BMO_slot_buffer_from_enabled_flag(
+ bm, op, op->slots_out, "geom.out", BM_ALL_NOLOOP, ELE_INNER | ELE_SPLIT | SUBD_SPLIT);
}
/* editmesh-emulating function */
-void BM_mesh_esubdivide(
- BMesh *bm, const char edge_hflag,
- const float smooth, const short smooth_falloff, const bool use_smooth_even,
- const float fractal, const float along_normal,
- const int numcuts,
- const int seltype, const int cornertype,
- const short use_single_edge, const short use_grid_fill,
- const short use_only_quads,
- const int seed)
+void BM_mesh_esubdivide(BMesh *bm,
+ const char edge_hflag,
+ const float smooth,
+ const short smooth_falloff,
+ const bool use_smooth_even,
+ const float fractal,
+ const float along_normal,
+ const int numcuts,
+ const int seltype,
+ const int cornertype,
+ const short use_single_edge,
+ const short use_grid_fill,
+ const short use_only_quads,
+ const int seed)
{
- BMOperator op;
-
- /* use_sphere isnt exposed here since its only used for new primitives */
- BMO_op_initf(bm, &op, BMO_FLAG_DEFAULTS,
- "subdivide_edges edges=%he "
- "smooth=%f smooth_falloff=%i use_smooth_even=%b "
- "fractal=%f along_normal=%f "
- "cuts=%i "
- "quad_corner_type=%i "
- "use_single_edge=%b use_grid_fill=%b "
- "use_only_quads=%b "
- "seed=%i",
- edge_hflag,
- smooth, smooth_falloff, use_smooth_even,
- fractal, along_normal,
- numcuts,
- cornertype,
- use_single_edge, use_grid_fill,
- use_only_quads,
- seed);
-
- BMO_op_exec(bm, &op);
-
- switch (seltype) {
- case SUBDIV_SELECT_NONE:
- break;
- case SUBDIV_SELECT_ORIG:
- /* set the newly created data to be selected */
- BMO_slot_buffer_hflag_enable(bm, op.slots_out, "geom_inner.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, true);
- BM_mesh_select_flush(bm);
- break;
- case SUBDIV_SELECT_INNER:
- BMO_slot_buffer_hflag_enable(bm, op.slots_out, "geom_inner.out", BM_EDGE | BM_VERT, BM_ELEM_SELECT, true);
- break;
- case SUBDIV_SELECT_LOOPCUT:
- /* deselect input */
- BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
- BMO_slot_buffer_hflag_enable(bm, op.slots_out, "geom_inner.out", BM_EDGE, BM_ELEM_SELECT, true);
- break;
- }
-
- BMO_op_finish(bm, &op);
+ BMOperator op;
+
+ /* use_sphere isnt exposed here since its only used for new primitives */
+ BMO_op_initf(bm,
+ &op,
+ BMO_FLAG_DEFAULTS,
+ "subdivide_edges edges=%he "
+ "smooth=%f smooth_falloff=%i use_smooth_even=%b "
+ "fractal=%f along_normal=%f "
+ "cuts=%i "
+ "quad_corner_type=%i "
+ "use_single_edge=%b use_grid_fill=%b "
+ "use_only_quads=%b "
+ "seed=%i",
+ edge_hflag,
+ smooth,
+ smooth_falloff,
+ use_smooth_even,
+ fractal,
+ along_normal,
+ numcuts,
+ cornertype,
+ use_single_edge,
+ use_grid_fill,
+ use_only_quads,
+ seed);
+
+ BMO_op_exec(bm, &op);
+
+ switch (seltype) {
+ case SUBDIV_SELECT_NONE:
+ break;
+ case SUBDIV_SELECT_ORIG:
+ /* set the newly created data to be selected */
+ BMO_slot_buffer_hflag_enable(
+ bm, op.slots_out, "geom_inner.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, true);
+ BM_mesh_select_flush(bm);
+ break;
+ case SUBDIV_SELECT_INNER:
+ BMO_slot_buffer_hflag_enable(
+ bm, op.slots_out, "geom_inner.out", BM_EDGE | BM_VERT, BM_ELEM_SELECT, true);
+ break;
+ case SUBDIV_SELECT_LOOPCUT:
+ /* deselect input */
+ BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
+ BMO_slot_buffer_hflag_enable(
+ bm, op.slots_out, "geom_inner.out", BM_EDGE, BM_ELEM_SELECT, true);
+ break;
+ }
+
+ BMO_op_finish(bm, &op);
}
void bmo_bisect_edges_exec(BMesh *bm, BMOperator *op)
{
- BMOIter siter;
- BMEdge *e;
- SubDParams params = {0};
+ BMOIter siter;
+ BMEdge *e;
+ SubDParams params = {0};
- params.numcuts = BMO_slot_int_get(op->slots_in, "cuts");
- params.op = op;
- params.slot_edge_percents = BMO_slot_get(op->slots_in, "edge_percents");
+ params.numcuts = BMO_slot_int_get(op->slots_in, "cuts");
+ params.op = op;
+ params.slot_edge_percents = BMO_slot_get(op->slots_in, "edge_percents");
- BM_data_layer_add(bm, &bm->vdata, CD_SHAPEKEY);
+ BM_data_layer_add(bm, &bm->vdata, CD_SHAPEKEY);
- bmo_subd_init_shape_info(bm, &params);
+ bmo_subd_init_shape_info(bm, &params);
- /* tag edges in map */
- BMO_slot_map_to_flag(bm, op->slots_in, "edge_percents", BM_EDGE, EDGE_PERCENT);
+ /* tag edges in map */
+ BMO_slot_map_to_flag(bm, op->slots_in, "edge_percents", BM_EDGE, EDGE_PERCENT);
- /* go through and split edges */
- BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
- bm_subdivide_multicut(bm, e, &params, e->v1, e->v2);
- }
+ /* go through and split edges */
+ BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
+ bm_subdivide_multicut(bm, e, &params, e->v1, e->v2);
+ }
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_split.out", BM_ALL_NOLOOP, ELE_SPLIT);
+ BMO_slot_buffer_from_enabled_flag(
+ bm, op, op->slots_out, "geom_split.out", BM_ALL_NOLOOP, ELE_SPLIT);
- BM_data_layer_free_n(bm, &bm->vdata, CD_SHAPEKEY, params.shape_info.tmpkey);
+ BM_data_layer_free_n(bm, &bm->vdata, CD_SHAPEKEY, params.shape_info.tmpkey);
}
diff --git a/source/blender/bmesh/operators/bmo_subdivide_edgering.c b/source/blender/bmesh/operators/bmo_subdivide_edgering.c
index 8c5ee4ede3d..c6d2910d214 100644
--- a/source/blender/bmesh/operators/bmo_subdivide_edgering.c
+++ b/source/blender/bmesh/operators/bmo_subdivide_edgering.c
@@ -45,16 +45,15 @@
#include "intern/bmesh_operators_private.h" /* own include */
-#define VERT_SHARED (1 << 0)
+#define VERT_SHARED (1 << 0)
-#define EDGE_RING (1 << 0)
-#define EDGE_RIM (1 << 1)
-#define EDGE_IN_STACK (1 << 2)
-
-#define FACE_OUT (1 << 0)
-#define FACE_SHARED (1 << 1)
-#define FACE_IN_STACK (1 << 2)
+#define EDGE_RING (1 << 0)
+#define EDGE_RIM (1 << 1)
+#define EDGE_IN_STACK (1 << 2)
+#define FACE_OUT (1 << 0)
+#define FACE_SHARED (1 << 1)
+#define FACE_IN_STACK (1 << 2)
/* -------------------------------------------------------------------- */
/* Specialized Utility Funcs */
@@ -62,138 +61,140 @@
#ifndef NDEBUG
static uint bm_verts_tag_count(BMesh *bm)
{
- int count = 0;
- BMIter iter;
- BMVert *v;
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
- count++;
- }
- }
- return count;
+ int count = 0;
+ BMIter iter;
+ BMVert *v;
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ count++;
+ }
+ }
+ return count;
}
#endif
-static float bezier_handle_calc_length_v3(
- const float co_a[3], const float no_a[3],
- const float co_b[3], const float no_b[3])
+static float bezier_handle_calc_length_v3(const float co_a[3],
+ const float no_a[3],
+ const float co_b[3],
+ const float no_b[3])
{
- const float dot = dot_v3v3(no_a, no_b);
- /* gives closest approx at a circle with 2 parallel handles */
- float fac = 1.333333f;
- float len;
- if (dot < 0.0f) {
- /* scale down to 0.666 if we point directly at each other rough but ok */
- /* TODO, current blend from dot may not be optimal but its also a detail */
- const float t = 1.0f + dot;
- fac = (fac * t) + (0.75f * (1.0f - t));
- }
+ const float dot = dot_v3v3(no_a, no_b);
+ /* gives closest approx at a circle with 2 parallel handles */
+ float fac = 1.333333f;
+ float len;
+ if (dot < 0.0f) {
+ /* scale down to 0.666 if we point directly at each other rough but ok */
+ /* TODO, current blend from dot may not be optimal but its also a detail */
+ const float t = 1.0f + dot;
+ fac = (fac * t) + (0.75f * (1.0f - t));
+ }
#if 0
- len = len_v3v3(co_a, co_b);
+ len = len_v3v3(co_a, co_b);
#else
- /* 2d length projected on plane of normals */
- {
- float co_a_ofs[3];
- cross_v3_v3v3(co_a_ofs, no_a, no_b);
- if (len_squared_v3(co_a_ofs) > FLT_EPSILON) {
- add_v3_v3(co_a_ofs, co_a);
- closest_to_line_v3(co_a_ofs, co_b, co_a, co_a_ofs);
- }
- else {
- copy_v3_v3(co_a_ofs, co_a);
- }
- len = len_v3v3(co_a_ofs, co_b);
- }
+ /* 2d length projected on plane of normals */
+ {
+ float co_a_ofs[3];
+ cross_v3_v3v3(co_a_ofs, no_a, no_b);
+ if (len_squared_v3(co_a_ofs) > FLT_EPSILON) {
+ add_v3_v3(co_a_ofs, co_a);
+ closest_to_line_v3(co_a_ofs, co_b, co_a, co_a_ofs);
+ }
+ else {
+ copy_v3_v3(co_a_ofs, co_a);
+ }
+ len = len_v3v3(co_a_ofs, co_b);
+ }
#endif
- return (len * 0.5f) * fac;
+ return (len * 0.5f) * fac;
}
static void bm_edgeloop_vert_tag(struct BMEdgeLoopStore *el_store, const bool tag)
{
- LinkData *node = BM_edgeloop_verts_get(el_store)->first;
- do {
- BM_elem_flag_set((BMVert *)node->data, BM_ELEM_TAG, tag);
- } while ((node = node->next));
+ LinkData *node = BM_edgeloop_verts_get(el_store)->first;
+ do {
+ BM_elem_flag_set((BMVert *)node->data, BM_ELEM_TAG, tag);
+ } while ((node = node->next));
}
-static void bmo_edgeloop_vert_tag(BMesh *bm, struct BMEdgeLoopStore *el_store, const short oflag, const bool tag)
+static void bmo_edgeloop_vert_tag(BMesh *bm,
+ struct BMEdgeLoopStore *el_store,
+ const short oflag,
+ const bool tag)
{
- LinkData *node = BM_edgeloop_verts_get(el_store)->first;
- do {
- BMO_vert_flag_set(bm, (BMVert *)node->data, oflag, tag);
- } while ((node = node->next));
+ LinkData *node = BM_edgeloop_verts_get(el_store)->first;
+ do {
+ BMO_vert_flag_set(bm, (BMVert *)node->data, oflag, tag);
+ } while ((node = node->next));
}
static bool bmo_face_is_vert_tag_all(BMesh *bm, BMFace *f, short oflag)
{
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if (!BMO_vert_flag_test(bm, l_iter->v, oflag)) {
- return false;
- }
- } while ((l_iter = l_iter->next) != l_first);
- return true;
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (!BMO_vert_flag_test(bm, l_iter->v, oflag)) {
+ return false;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ return true;
}
static bool bm_vert_is_tag_edge_connect(BMesh *bm, BMVert *v)
{
- BMIter eiter;
- BMEdge *e;
-
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- if (BMO_edge_flag_test(bm, e, EDGE_RING)) {
- BMVert *v_other = BM_edge_other_vert(e, v);
- if (BM_elem_flag_test(v_other, BM_ELEM_TAG)) {
- return true;
- }
- }
- }
- return false;
+ BMIter eiter;
+ BMEdge *e;
+
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (BMO_edge_flag_test(bm, e, EDGE_RING)) {
+ BMVert *v_other = BM_edge_other_vert(e, v);
+ if (BM_elem_flag_test(v_other, BM_ELEM_TAG)) {
+ return true;
+ }
+ }
+ }
+ return false;
}
/* for now we need full overlap,
* supporting partial overlap could be done but gets complicated
* when trimming endpoints is not enough to ensure consistency.
*/
-static bool bm_edgeloop_check_overlap_all(
- BMesh *bm,
- struct BMEdgeLoopStore *el_store_a,
- struct BMEdgeLoopStore *el_store_b)
+static bool bm_edgeloop_check_overlap_all(BMesh *bm,
+ struct BMEdgeLoopStore *el_store_a,
+ struct BMEdgeLoopStore *el_store_b)
{
- bool has_overlap = true;
- LinkData *node;
+ bool has_overlap = true;
+ LinkData *node;
- ListBase *lb_a = BM_edgeloop_verts_get(el_store_a);
- ListBase *lb_b = BM_edgeloop_verts_get(el_store_b);
+ ListBase *lb_a = BM_edgeloop_verts_get(el_store_a);
+ ListBase *lb_b = BM_edgeloop_verts_get(el_store_b);
- bm_edgeloop_vert_tag(el_store_a, false);
- bm_edgeloop_vert_tag(el_store_b, true);
+ bm_edgeloop_vert_tag(el_store_a, false);
+ bm_edgeloop_vert_tag(el_store_b, true);
- for (node = lb_a->first; node; node = node->next) {
- if (bm_vert_is_tag_edge_connect(bm, node->data) == false) {
- has_overlap = false;
- goto finally;
- }
- }
+ for (node = lb_a->first; node; node = node->next) {
+ if (bm_vert_is_tag_edge_connect(bm, node->data) == false) {
+ has_overlap = false;
+ goto finally;
+ }
+ }
- bm_edgeloop_vert_tag(el_store_a, true);
- bm_edgeloop_vert_tag(el_store_b, false);
+ bm_edgeloop_vert_tag(el_store_a, true);
+ bm_edgeloop_vert_tag(el_store_b, false);
- for (node = lb_b->first; node; node = node->next) {
- if (bm_vert_is_tag_edge_connect(bm, node->data) == false) {
- has_overlap = false;
- goto finally;
- }
- }
+ for (node = lb_b->first; node; node = node->next) {
+ if (bm_vert_is_tag_edge_connect(bm, node->data) == false) {
+ has_overlap = false;
+ goto finally;
+ }
+ }
finally:
- bm_edgeloop_vert_tag(el_store_a, false);
- bm_edgeloop_vert_tag(el_store_b, false);
- return has_overlap;
-
+ bm_edgeloop_vert_tag(el_store_a, false);
+ bm_edgeloop_vert_tag(el_store_b, false);
+ return has_overlap;
}
/* -------------------------------------------------------------------- */
@@ -201,114 +202,111 @@ finally:
/* key (ordered loop pointers) */
static GSet *bm_edgering_pair_calc(BMesh *bm, ListBase *eloops_rim)
{
- /**
- * Method for for finding pairs:
- *
- * - first create (vert -> eloop) mapping.
- * - loop over all eloops.
- * - take first vertex of the eloop (any vertex will do)
- * - loop over all edges of the vertex.
- * - use the edge-verts and (vert -> eloop) map
- * to create a pair of eloop pointers, add these to a hash.
- *
- * \note, each loop pair will be found twice.
- * could sort and optimize this but not really so important.
- */
-
- GSet *eloop_pair_gs = BLI_gset_pair_new(__func__);
- GHash *vert_eloop_gh = BLI_ghash_ptr_new(__func__);
-
- struct BMEdgeLoopStore *el_store;
-
- /* create vert -> eloop map */
- for (el_store = eloops_rim->first; el_store; el_store = BM_EDGELOOP_NEXT(el_store)) {
- LinkData *node = BM_edgeloop_verts_get(el_store)->first;
- do {
- BLI_ghash_insert(vert_eloop_gh, node->data, el_store);
- } while ((node = node->next));
- }
-
-
- /* collect eloop pairs */
- for (el_store = eloops_rim->first; el_store; el_store = BM_EDGELOOP_NEXT(el_store)) {
- BMIter eiter;
- BMEdge *e;
-
- BMVert *v = ((LinkData *)BM_edgeloop_verts_get(el_store)->first)->data;
-
- BM_ITER_ELEM (e, &eiter, (BMVert *)v, BM_EDGES_OF_VERT) {
- if (BMO_edge_flag_test(bm, e, EDGE_RING)) {
- struct BMEdgeLoopStore *el_store_other;
- BMVert *v_other = BM_edge_other_vert(e, v);
- GHashPair pair_test;
-
- el_store_other = BLI_ghash_lookup(vert_eloop_gh, v_other);
-
- /* in rare cases we cant find a match */
- if (el_store_other) {
- pair_test.first = el_store;
- pair_test.second = el_store_other;
-
- if (pair_test.first > pair_test.second) {
- SWAP(const void *, pair_test.first, pair_test.second);
- }
-
- void **pair_key_p;
- if (!BLI_gset_ensure_p_ex(eloop_pair_gs, &pair_test, &pair_key_p)) {
- *pair_key_p = BLI_ghashutil_pairalloc(pair_test.first, pair_test.second);
- }
- }
- }
- }
- }
-
- BLI_ghash_free(vert_eloop_gh, NULL, NULL);
-
- if (BLI_gset_len(eloop_pair_gs) == 0) {
- BLI_gset_free(eloop_pair_gs, NULL);
- eloop_pair_gs = NULL;
- }
-
- return eloop_pair_gs;
+ /**
+ * Method for for finding pairs:
+ *
+ * - first create (vert -> eloop) mapping.
+ * - loop over all eloops.
+ * - take first vertex of the eloop (any vertex will do)
+ * - loop over all edges of the vertex.
+ * - use the edge-verts and (vert -> eloop) map
+ * to create a pair of eloop pointers, add these to a hash.
+ *
+ * \note, each loop pair will be found twice.
+ * could sort and optimize this but not really so important.
+ */
+
+ GSet *eloop_pair_gs = BLI_gset_pair_new(__func__);
+ GHash *vert_eloop_gh = BLI_ghash_ptr_new(__func__);
+
+ struct BMEdgeLoopStore *el_store;
+
+ /* create vert -> eloop map */
+ for (el_store = eloops_rim->first; el_store; el_store = BM_EDGELOOP_NEXT(el_store)) {
+ LinkData *node = BM_edgeloop_verts_get(el_store)->first;
+ do {
+ BLI_ghash_insert(vert_eloop_gh, node->data, el_store);
+ } while ((node = node->next));
+ }
+
+ /* collect eloop pairs */
+ for (el_store = eloops_rim->first; el_store; el_store = BM_EDGELOOP_NEXT(el_store)) {
+ BMIter eiter;
+ BMEdge *e;
+
+ BMVert *v = ((LinkData *)BM_edgeloop_verts_get(el_store)->first)->data;
+
+ BM_ITER_ELEM (e, &eiter, (BMVert *)v, BM_EDGES_OF_VERT) {
+ if (BMO_edge_flag_test(bm, e, EDGE_RING)) {
+ struct BMEdgeLoopStore *el_store_other;
+ BMVert *v_other = BM_edge_other_vert(e, v);
+ GHashPair pair_test;
+
+ el_store_other = BLI_ghash_lookup(vert_eloop_gh, v_other);
+
+ /* in rare cases we cant find a match */
+ if (el_store_other) {
+ pair_test.first = el_store;
+ pair_test.second = el_store_other;
+
+ if (pair_test.first > pair_test.second) {
+ SWAP(const void *, pair_test.first, pair_test.second);
+ }
+
+ void **pair_key_p;
+ if (!BLI_gset_ensure_p_ex(eloop_pair_gs, &pair_test, &pair_key_p)) {
+ *pair_key_p = BLI_ghashutil_pairalloc(pair_test.first, pair_test.second);
+ }
+ }
+ }
+ }
+ }
+
+ BLI_ghash_free(vert_eloop_gh, NULL, NULL);
+
+ if (BLI_gset_len(eloop_pair_gs) == 0) {
+ BLI_gset_free(eloop_pair_gs, NULL);
+ eloop_pair_gs = NULL;
+ }
+
+ return eloop_pair_gs;
}
-
/* -------------------------------------------------------------------- */
/* Subdivide an edge 'n' times and return an open edgeloop */
-static void bm_edge_subdiv_as_loop(BMesh *bm, ListBase *eloops, BMEdge *e, BMVert *v_a, const int cuts)
+static void bm_edge_subdiv_as_loop(
+ BMesh *bm, ListBase *eloops, BMEdge *e, BMVert *v_a, const int cuts)
{
- struct BMEdgeLoopStore *eloop;
- BMVert **v_arr = BLI_array_alloca(v_arr, cuts + 2);
- BMVert *v_b;
- BLI_assert(BM_vert_in_edge(e, v_a));
-
- v_b = BM_edge_other_vert(e, v_a);
-
- BM_edge_split_n(bm, e, cuts, &v_arr[1]);
- if (v_a == e->v1) {
- v_arr[0] = v_a;
- v_arr[cuts + 1] = v_b;
- }
- else {
- v_arr[0] = v_b;
- v_arr[cuts + 1] = v_a;
- }
-
- eloop = BM_edgeloop_from_verts(v_arr, cuts + 2, false);
-
- if (v_a == e->v1) {
- BM_edgeloop_flip(bm, eloop);
- }
-
- BLI_addtail(eloops, eloop);
+ struct BMEdgeLoopStore *eloop;
+ BMVert **v_arr = BLI_array_alloca(v_arr, cuts + 2);
+ BMVert *v_b;
+ BLI_assert(BM_vert_in_edge(e, v_a));
+
+ v_b = BM_edge_other_vert(e, v_a);
+
+ BM_edge_split_n(bm, e, cuts, &v_arr[1]);
+ if (v_a == e->v1) {
+ v_arr[0] = v_a;
+ v_arr[cuts + 1] = v_b;
+ }
+ else {
+ v_arr[0] = v_b;
+ v_arr[cuts + 1] = v_a;
+ }
+
+ eloop = BM_edgeloop_from_verts(v_arr, cuts + 2, false);
+
+ if (v_a == e->v1) {
+ BM_edgeloop_flip(bm, eloop);
+ }
+
+ BLI_addtail(eloops, eloop);
}
-
/* -------------------------------------------------------------------- */
/* LoopPair Cache (struct and util funcs) */
-
/**
* Use for finding spline handle direction from surrounding faces.
*
@@ -321,64 +319,64 @@ static void bm_edge_subdiv_as_loop(BMesh *bm, ListBase *eloops, BMEdge *e, BMVer
*/
static void bm_vert_calc_surface_tangent(BMesh *bm, BMVert *v, float r_no[3])
{
- BMIter eiter;
- BMEdge *e;
-
- /* get outer normal, fallback to inner (if this vertex is on a boundary) */
- bool found_outer = false, found_inner = false, found_outer_tag = false;
-
- float no_outer[3] = {0.0f}, no_inner[3] = {0.0f};
-
- /* first find rim edges, typically we will only add 2 normals */
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- if (UNLIKELY(BM_edge_is_wire(e))) {
- /* pass - this may confuse things */
- }
- else if (BMO_edge_flag_test(bm, e, EDGE_RIM)) {
- BMIter liter;
- BMLoop *l;
- BM_ITER_ELEM (l, &liter, e, BM_LOOPS_OF_EDGE) {
- /* use unmarked (surrounding) faces to create surface tangent */
- float no[3];
- // BM_face_normal_update(l->f);
- BM_edge_calc_face_tangent(e, l, no);
- if (BMO_face_flag_test(bm, l->f, FACE_SHARED)) {
- add_v3_v3(no_inner, no);
- found_inner = true;
- }
- else {
- add_v3_v3(no_outer, no);
- found_outer = true;
-
- /* other side is used too, blend midway */
- if (BMO_face_flag_test(bm, l->f, FACE_OUT)) {
- found_outer_tag = true;
- }
- }
- }
- }
- }
-
- /* detect if this vertex is in-between 2 loops (when blending multiple),
- * if so - take both inner and outer into account */
-
- if (found_inner && found_outer_tag) {
- /* blend between the 2 */
- negate_v3(no_outer);
- normalize_v3(no_outer);
- normalize_v3(no_inner);
- add_v3_v3v3(r_no, no_outer, no_inner);
- normalize_v3(r_no);
- }
- else if (found_outer) {
- negate_v3(no_outer);
- normalize_v3_v3(r_no, no_outer);
- }
- else {
- /* we always have inner geometry */
- BLI_assert(found_inner == true);
- normalize_v3_v3(r_no, no_inner);
- }
+ BMIter eiter;
+ BMEdge *e;
+
+ /* get outer normal, fallback to inner (if this vertex is on a boundary) */
+ bool found_outer = false, found_inner = false, found_outer_tag = false;
+
+ float no_outer[3] = {0.0f}, no_inner[3] = {0.0f};
+
+ /* first find rim edges, typically we will only add 2 normals */
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (UNLIKELY(BM_edge_is_wire(e))) {
+ /* pass - this may confuse things */
+ }
+ else if (BMO_edge_flag_test(bm, e, EDGE_RIM)) {
+ BMIter liter;
+ BMLoop *l;
+ BM_ITER_ELEM (l, &liter, e, BM_LOOPS_OF_EDGE) {
+ /* use unmarked (surrounding) faces to create surface tangent */
+ float no[3];
+ // BM_face_normal_update(l->f);
+ BM_edge_calc_face_tangent(e, l, no);
+ if (BMO_face_flag_test(bm, l->f, FACE_SHARED)) {
+ add_v3_v3(no_inner, no);
+ found_inner = true;
+ }
+ else {
+ add_v3_v3(no_outer, no);
+ found_outer = true;
+
+ /* other side is used too, blend midway */
+ if (BMO_face_flag_test(bm, l->f, FACE_OUT)) {
+ found_outer_tag = true;
+ }
+ }
+ }
+ }
+ }
+
+ /* detect if this vertex is in-between 2 loops (when blending multiple),
+ * if so - take both inner and outer into account */
+
+ if (found_inner && found_outer_tag) {
+ /* blend between the 2 */
+ negate_v3(no_outer);
+ normalize_v3(no_outer);
+ normalize_v3(no_inner);
+ add_v3_v3v3(r_no, no_outer, no_inner);
+ normalize_v3(r_no);
+ }
+ else if (found_outer) {
+ negate_v3(no_outer);
+ normalize_v3_v3(r_no, no_outer);
+ }
+ else {
+ /* we always have inner geometry */
+ BLI_assert(found_inner == true);
+ normalize_v3_v3(r_no, no_inner);
+ }
}
/**
@@ -387,21 +385,21 @@ static void bm_vert_calc_surface_tangent(BMesh *bm, BMVert *v, float r_no[3])
*/
static void bm_faces_share_tag_flush(BMesh *bm, BMEdge **e_arr, const uint e_arr_len)
{
- uint i;
-
- for (i = 0; i < e_arr_len; i++) {
- BMEdge *e = e_arr[i];
- BMLoop *l_iter, *l_first;
-
- l_iter = l_first = e->l;
- do {
- if (!BMO_face_flag_test(bm, l_iter->f, FACE_SHARED)) {
- if (bmo_face_is_vert_tag_all(bm, l_iter->f, VERT_SHARED)) {
- BMO_face_flag_enable(bm, l_iter->f, FACE_SHARED);
- }
- }
- } while ((l_iter = l_iter->radial_next) != l_first);
- }
+ uint i;
+
+ for (i = 0; i < e_arr_len; i++) {
+ BMEdge *e = e_arr[i];
+ BMLoop *l_iter, *l_first;
+
+ l_iter = l_first = e->l;
+ do {
+ if (!BMO_face_flag_test(bm, l_iter->f, FACE_SHARED)) {
+ if (bmo_face_is_vert_tag_all(bm, l_iter->f, VERT_SHARED)) {
+ BMO_face_flag_enable(bm, l_iter->f, FACE_SHARED);
+ }
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
}
/**
@@ -409,17 +407,17 @@ static void bm_faces_share_tag_flush(BMesh *bm, BMEdge **e_arr, const uint e_arr
*/
static void bm_faces_share_tag_clear(BMesh *bm, BMEdge **e_arr_iter, const uint e_arr_len_iter)
{
- uint i;
+ uint i;
- for (i = 0; i < e_arr_len_iter; i++) {
- BMEdge *e = e_arr_iter[i];
- BMLoop *l_iter, *l_first;
+ for (i = 0; i < e_arr_len_iter; i++) {
+ BMEdge *e = e_arr_iter[i];
+ BMLoop *l_iter, *l_first;
- l_iter = l_first = e->l;
- do {
- BMO_face_flag_disable(bm, l_iter->f, FACE_SHARED);
- } while ((l_iter = l_iter->radial_next) != l_first);
- }
+ l_iter = l_first = e->l;
+ do {
+ BMO_face_flag_disable(bm, l_iter->f, FACE_SHARED);
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
}
/**
@@ -430,388 +428,392 @@ static void bm_faces_share_tag_clear(BMesh *bm, BMEdge **e_arr_iter, const uint
* but may be extended for other uses.
*/
typedef struct LoopPairStore {
- /* handle array for splines */
- float (*nors_a)[3];
- float (*nors_b)[3];
-
- /* since we don't have reliable index values into the array,
- * store a map (BMVert -> index) */
- GHash *nors_gh_a;
- GHash *nors_gh_b;
+ /* handle array for splines */
+ float (*nors_a)[3];
+ float (*nors_b)[3];
+
+ /* since we don't have reliable index values into the array,
+ * store a map (BMVert -> index) */
+ GHash *nors_gh_a;
+ GHash *nors_gh_b;
} LoopPairStore;
-static LoopPairStore *bm_edgering_pair_store_create(
- BMesh *bm,
- struct BMEdgeLoopStore *el_store_a,
- struct BMEdgeLoopStore *el_store_b,
- const int interp_mode)
+static LoopPairStore *bm_edgering_pair_store_create(BMesh *bm,
+ struct BMEdgeLoopStore *el_store_a,
+ struct BMEdgeLoopStore *el_store_b,
+ const int interp_mode)
{
- LoopPairStore *lpair = MEM_mallocN(sizeof(*lpair), __func__);
-
- if (interp_mode == SUBD_RING_INTERP_SURF) {
- const uint len_a = BM_edgeloop_length_get(el_store_a);
- const uint len_b = BM_edgeloop_length_get(el_store_b);
- const uint e_arr_a_len = len_a - (BM_edgeloop_is_closed(el_store_a) ? 0 : 1);
- const uint e_arr_b_len = len_b - (BM_edgeloop_is_closed(el_store_b) ? 0 : 1);
- BMEdge **e_arr_a = BLI_array_alloca(e_arr_a, e_arr_a_len);
- BMEdge **e_arr_b = BLI_array_alloca(e_arr_b, e_arr_b_len);
- uint i;
-
- struct BMEdgeLoopStore *el_store_pair[2] = {el_store_a, el_store_b};
- uint side_index;
- float (*nors_pair[2])[3];
- GHash *nors_gh_pair[2];
-
- BM_edgeloop_edges_get(el_store_a, e_arr_a);
- BM_edgeloop_edges_get(el_store_b, e_arr_b);
-
- lpair->nors_a = MEM_mallocN(sizeof(*lpair->nors_a) * len_a, __func__);
- lpair->nors_b = MEM_mallocN(sizeof(*lpair->nors_b) * len_b, __func__);
-
- nors_pair[0] = lpair->nors_a;
- nors_pair[1] = lpair->nors_b;
-
- lpair->nors_gh_a = BLI_ghash_ptr_new(__func__);
- lpair->nors_gh_b = BLI_ghash_ptr_new(__func__);
-
- nors_gh_pair[0] = lpair->nors_gh_a;
- nors_gh_pair[1] = lpair->nors_gh_b;
-
- /* now calculate nor */
-
- /* all other verts must _not_ be tagged */
- bmo_edgeloop_vert_tag(bm, el_store_a, VERT_SHARED, true);
- bmo_edgeloop_vert_tag(bm, el_store_b, VERT_SHARED, true);
-
- /* tag all faces that are in-between both loops */
- bm_faces_share_tag_flush(bm, e_arr_a, e_arr_a_len);
- bm_faces_share_tag_flush(bm, e_arr_b, e_arr_b_len);
-
- /* now we have all data we need, calculate vertex spline nor! */
- for (side_index = 0; side_index < 2; side_index++) {
- /* iter vars */
- struct BMEdgeLoopStore *el_store = el_store_pair[side_index];
- ListBase *lb = BM_edgeloop_verts_get(el_store);
- GHash *nors_gh_iter = nors_gh_pair[side_index];
- float (*nor)[3] = nors_pair[side_index];
-
- LinkData *v_iter;
-
- for (v_iter = lb->first, i = 0; v_iter; v_iter = v_iter->next, i++) {
- BMVert *v = v_iter->data;
- bm_vert_calc_surface_tangent(bm, v, nor[i]);
- BLI_ghash_insert(nors_gh_iter, v, POINTER_FROM_UINT(i));
- }
- }
-
- /* cleanup verts share */
- bmo_edgeloop_vert_tag(bm, el_store_a, VERT_SHARED, false);
- bmo_edgeloop_vert_tag(bm, el_store_b, VERT_SHARED, false);
-
- /* cleanup faces share */
- bm_faces_share_tag_clear(bm, e_arr_a, e_arr_a_len);
- bm_faces_share_tag_clear(bm, e_arr_b, e_arr_b_len);
- }
- return lpair;
+ LoopPairStore *lpair = MEM_mallocN(sizeof(*lpair), __func__);
+
+ if (interp_mode == SUBD_RING_INTERP_SURF) {
+ const uint len_a = BM_edgeloop_length_get(el_store_a);
+ const uint len_b = BM_edgeloop_length_get(el_store_b);
+ const uint e_arr_a_len = len_a - (BM_edgeloop_is_closed(el_store_a) ? 0 : 1);
+ const uint e_arr_b_len = len_b - (BM_edgeloop_is_closed(el_store_b) ? 0 : 1);
+ BMEdge **e_arr_a = BLI_array_alloca(e_arr_a, e_arr_a_len);
+ BMEdge **e_arr_b = BLI_array_alloca(e_arr_b, e_arr_b_len);
+ uint i;
+
+ struct BMEdgeLoopStore *el_store_pair[2] = {el_store_a, el_store_b};
+ uint side_index;
+ float(*nors_pair[2])[3];
+ GHash *nors_gh_pair[2];
+
+ BM_edgeloop_edges_get(el_store_a, e_arr_a);
+ BM_edgeloop_edges_get(el_store_b, e_arr_b);
+
+ lpair->nors_a = MEM_mallocN(sizeof(*lpair->nors_a) * len_a, __func__);
+ lpair->nors_b = MEM_mallocN(sizeof(*lpair->nors_b) * len_b, __func__);
+
+ nors_pair[0] = lpair->nors_a;
+ nors_pair[1] = lpair->nors_b;
+
+ lpair->nors_gh_a = BLI_ghash_ptr_new(__func__);
+ lpair->nors_gh_b = BLI_ghash_ptr_new(__func__);
+
+ nors_gh_pair[0] = lpair->nors_gh_a;
+ nors_gh_pair[1] = lpair->nors_gh_b;
+
+ /* now calculate nor */
+
+ /* all other verts must _not_ be tagged */
+ bmo_edgeloop_vert_tag(bm, el_store_a, VERT_SHARED, true);
+ bmo_edgeloop_vert_tag(bm, el_store_b, VERT_SHARED, true);
+
+ /* tag all faces that are in-between both loops */
+ bm_faces_share_tag_flush(bm, e_arr_a, e_arr_a_len);
+ bm_faces_share_tag_flush(bm, e_arr_b, e_arr_b_len);
+
+ /* now we have all data we need, calculate vertex spline nor! */
+ for (side_index = 0; side_index < 2; side_index++) {
+ /* iter vars */
+ struct BMEdgeLoopStore *el_store = el_store_pair[side_index];
+ ListBase *lb = BM_edgeloop_verts_get(el_store);
+ GHash *nors_gh_iter = nors_gh_pair[side_index];
+ float(*nor)[3] = nors_pair[side_index];
+
+ LinkData *v_iter;
+
+ for (v_iter = lb->first, i = 0; v_iter; v_iter = v_iter->next, i++) {
+ BMVert *v = v_iter->data;
+ bm_vert_calc_surface_tangent(bm, v, nor[i]);
+ BLI_ghash_insert(nors_gh_iter, v, POINTER_FROM_UINT(i));
+ }
+ }
+
+ /* cleanup verts share */
+ bmo_edgeloop_vert_tag(bm, el_store_a, VERT_SHARED, false);
+ bmo_edgeloop_vert_tag(bm, el_store_b, VERT_SHARED, false);
+
+ /* cleanup faces share */
+ bm_faces_share_tag_clear(bm, e_arr_a, e_arr_a_len);
+ bm_faces_share_tag_clear(bm, e_arr_b, e_arr_b_len);
+ }
+ return lpair;
}
-static void bm_edgering_pair_store_free(
- LoopPairStore *lpair,
- const int interp_mode)
+static void bm_edgering_pair_store_free(LoopPairStore *lpair, const int interp_mode)
{
- if (interp_mode == SUBD_RING_INTERP_SURF) {
- MEM_freeN(lpair->nors_a);
- MEM_freeN(lpair->nors_b);
-
- BLI_ghash_free(lpair->nors_gh_a, NULL, NULL);
- BLI_ghash_free(lpair->nors_gh_b, NULL, NULL);
- }
- MEM_freeN(lpair);
+ if (interp_mode == SUBD_RING_INTERP_SURF) {
+ MEM_freeN(lpair->nors_a);
+ MEM_freeN(lpair->nors_b);
+
+ BLI_ghash_free(lpair->nors_gh_a, NULL, NULL);
+ BLI_ghash_free(lpair->nors_gh_b, NULL, NULL);
+ }
+ MEM_freeN(lpair);
}
-
/* -------------------------------------------------------------------- */
/* Interpolation Function */
-static void bm_edgering_pair_interpolate(
- BMesh *bm, LoopPairStore *lpair,
- struct BMEdgeLoopStore *el_store_a,
- struct BMEdgeLoopStore *el_store_b,
- ListBase *eloops_ring,
- const int interp_mode, const int cuts, const float smooth,
- const float *falloff_cache)
+static void bm_edgering_pair_interpolate(BMesh *bm,
+ LoopPairStore *lpair,
+ struct BMEdgeLoopStore *el_store_a,
+ struct BMEdgeLoopStore *el_store_b,
+ ListBase *eloops_ring,
+ const int interp_mode,
+ const int cuts,
+ const float smooth,
+ const float *falloff_cache)
{
- const int resolu = cuts + 2;
- const int dims = 3;
- bool is_a_no_valid, is_b_no_valid;
- int i;
-
- float el_store_a_co[3], el_store_b_co[3];
- float el_store_a_no[3], el_store_b_no[3];
-
- struct BMEdgeLoopStore *el_store_ring;
-
- float (*coord_array_main)[3] = NULL;
-
- BM_edgeloop_calc_center(bm, el_store_a);
- BM_edgeloop_calc_center(bm, el_store_b);
-
- is_a_no_valid = BM_edgeloop_calc_normal(bm, el_store_a);
- is_b_no_valid = BM_edgeloop_calc_normal(bm, el_store_b);
-
- copy_v3_v3(el_store_a_co, BM_edgeloop_center_get(el_store_a));
- copy_v3_v3(el_store_b_co, BM_edgeloop_center_get(el_store_b));
-
- /* correct normals need to be flipped to face each other
- * we know both normals point in the same direction so one will need flipping */
- {
- float el_dir[3];
- float no[3];
- sub_v3_v3v3(el_dir, el_store_a_co, el_store_b_co);
- normalize_v3_v3(no, el_dir);
-
- if (is_a_no_valid == false) {
- is_a_no_valid = BM_edgeloop_calc_normal_aligned(bm, el_store_a, no);
- }
- if (is_b_no_valid == false) {
- is_b_no_valid = BM_edgeloop_calc_normal_aligned(bm, el_store_b, no);
- }
- (void)is_a_no_valid, (void)is_b_no_valid;
-
- copy_v3_v3(el_store_a_no, BM_edgeloop_normal_get(el_store_a));
- copy_v3_v3(el_store_b_no, BM_edgeloop_normal_get(el_store_b));
-
- if (dot_v3v3(el_store_a_no, el_dir) > 0.0f) {
- negate_v3(el_store_a_no);
- }
- if (dot_v3v3(el_store_b_no, el_dir) < 0.0f) {
- negate_v3(el_store_b_no);
- }
-
- }
- /* now normals are correct, don't touch! */
-
-
- /* calculate the center spline, multiple */
- if ((interp_mode == SUBD_RING_INTERP_PATH) || falloff_cache) {
- float handle_a[3], handle_b[3];
- float handle_len;
-
- handle_len = bezier_handle_calc_length_v3(el_store_a_co, el_store_a_no,
- el_store_b_co, el_store_b_no) * smooth;
-
- mul_v3_v3fl(handle_a, el_store_a_no, handle_len);
- mul_v3_v3fl(handle_b, el_store_b_no, handle_len);
-
- add_v3_v3(handle_a, el_store_a_co);
- add_v3_v3(handle_b, el_store_b_co);
-
- coord_array_main = MEM_mallocN(dims * (resolu) * sizeof(float), __func__);
-
- for (i = 0; i < dims; i++) {
- BKE_curve_forward_diff_bezier(el_store_a_co[i], handle_a[i], handle_b[i], el_store_b_co[i],
- ((float *)coord_array_main) + i, resolu - 1, sizeof(float) * dims);
- }
- }
-
- switch (interp_mode) {
- case SUBD_RING_INTERP_LINEAR:
- {
- if (falloff_cache) {
- float (*coord_array)[3] = MEM_mallocN(dims * (resolu) * sizeof(float), __func__);
- for (i = 0; i < resolu; i++) {
- interp_v3_v3v3(coord_array[i], el_store_a_co, el_store_b_co, (float)i / (float)(resolu - 1));
- }
-
- for (el_store_ring = eloops_ring->first;
- el_store_ring;
- el_store_ring = BM_EDGELOOP_NEXT(el_store_ring))
- {
- ListBase *lb_ring = BM_edgeloop_verts_get(el_store_ring);
- LinkData *v_iter;
-
- for (v_iter = lb_ring->first, i = 0; v_iter; v_iter = v_iter->next, i++) {
- if (i > 0 && i < resolu - 1) {
- /* shape */
- if (falloff_cache) {
- interp_v3_v3v3(((BMVert *)v_iter->data)->co,
- coord_array[i], ((BMVert *)v_iter->data)->co, falloff_cache[i]);
- }
- }
- }
- }
-
- MEM_freeN(coord_array);
-
- }
-
- break;
- }
- case SUBD_RING_INTERP_PATH:
- {
- float (*direction_array)[3] = MEM_mallocN(dims * (resolu) * sizeof(float), __func__);
- float (*quat_array)[4] = MEM_mallocN(resolu * sizeof(*quat_array), __func__);
- float (*tri_array)[3][3] = MEM_mallocN(resolu * sizeof(*tri_array), __func__);
- float (*tri_sta)[3], (*tri_end)[3], (*tri_tmp)[3];
-
- /* very similar to make_bevel_list_3D_minimum_twist */
-
- /* calculate normals */
- copy_v3_v3(direction_array[0], el_store_a_no);
- negate_v3_v3(direction_array[resolu - 1], el_store_b_no);
- for (i = 1; i < resolu - 1; i++) {
- bisect_v3_v3v3v3(direction_array[i],
- coord_array_main[i - 1], coord_array_main[i], coord_array_main[i + 1]);
- }
-
- vec_to_quat(quat_array[0], direction_array[0], 5, 1);
- normalize_qt(quat_array[0]);
-
- for (i = 1; i < resolu; i++) {
- float angle = angle_normalized_v3v3(direction_array[i - 1], direction_array[i]);
- // BLI_assert(angle < DEG2RADF(90.0f));
- if (angle > 0.0f) { /* otherwise we can keep as is */
- float cross_tmp[3];
- float q[4];
- cross_v3_v3v3(cross_tmp, direction_array[i - 1], direction_array[i]);
- axis_angle_to_quat(q, cross_tmp, angle);
- mul_qt_qtqt(quat_array[i], q, quat_array[i - 1]);
- normalize_qt(quat_array[i]);
- }
- else {
- copy_qt_qt(quat_array[i], quat_array[i - 1]);
- }
- }
-
- /* init base tri */
- for (i = 0; i < resolu; i++) {
- int j;
-
- const float shape_size = falloff_cache ? falloff_cache[i] : 1.0f;
-
- tri_tmp = tri_array[i];
-
- /* create the triangle and transform */
- for (j = 0; j < 3; j++) {
- zero_v3(tri_tmp[j]);
- if (j == 1) { tri_tmp[j][0] = shape_size; }
- else if (j == 2) { tri_tmp[j][1] = shape_size; }
- mul_qt_v3(quat_array[i], tri_tmp[j]);
- add_v3_v3(tri_tmp[j], coord_array_main[i]);
- }
- }
-
- tri_sta = tri_array[0];
- tri_end = tri_array[resolu - 1];
-
- for (el_store_ring = eloops_ring->first;
- el_store_ring;
- el_store_ring = BM_EDGELOOP_NEXT(el_store_ring))
- {
- ListBase *lb_ring = BM_edgeloop_verts_get(el_store_ring);
- LinkData *v_iter;
-
- BMVert *v_a = ((LinkData *)lb_ring->first)->data;
- BMVert *v_b = ((LinkData *)lb_ring->last)->data;
-
- /* skip first and last */
- for (v_iter = ((LinkData *)lb_ring->first)->next, i = 1;
- v_iter != lb_ring->last;
- v_iter = v_iter->next, i++)
- {
- float co_a[3], co_b[3];
-
- tri_tmp = tri_array[i];
-
- transform_point_by_tri_v3(co_a, v_a->co, UNPACK3(tri_tmp), UNPACK3(tri_sta));
- transform_point_by_tri_v3(co_b, v_b->co, UNPACK3(tri_tmp), UNPACK3(tri_end));
-
- interp_v3_v3v3(((BMVert *)v_iter->data)->co, co_a, co_b, (float)i / (float)(resolu - 1));
- }
- }
-
- MEM_freeN(direction_array);
- MEM_freeN(quat_array);
- MEM_freeN(tri_array);
- break;
- }
- case SUBD_RING_INTERP_SURF:
- {
- float (*coord_array)[3] = MEM_mallocN(dims * (resolu) * sizeof(float), __func__);
-
- /* calculate a bezier handle per edge ring */
- for (el_store_ring = eloops_ring->first;
- el_store_ring;
- el_store_ring = BM_EDGELOOP_NEXT(el_store_ring))
- {
- ListBase *lb_ring = BM_edgeloop_verts_get(el_store_ring);
- LinkData *v_iter;
-
- BMVert *v_a = ((LinkData *)lb_ring->first)->data;
- BMVert *v_b = ((LinkData *)lb_ring->last)->data;
-
- float co_a[3], no_a[3], handle_a[3], co_b[3], no_b[3], handle_b[3];
- float handle_len;
-
- copy_v3_v3(co_a, v_a->co);
- copy_v3_v3(co_b, v_b->co);
-
- /* don't calculate normals here else we get into feedback loop
- * when subdividing 2+ connected edge rings */
+ const int resolu = cuts + 2;
+ const int dims = 3;
+ bool is_a_no_valid, is_b_no_valid;
+ int i;
+
+ float el_store_a_co[3], el_store_b_co[3];
+ float el_store_a_no[3], el_store_b_no[3];
+
+ struct BMEdgeLoopStore *el_store_ring;
+
+ float(*coord_array_main)[3] = NULL;
+
+ BM_edgeloop_calc_center(bm, el_store_a);
+ BM_edgeloop_calc_center(bm, el_store_b);
+
+ is_a_no_valid = BM_edgeloop_calc_normal(bm, el_store_a);
+ is_b_no_valid = BM_edgeloop_calc_normal(bm, el_store_b);
+
+ copy_v3_v3(el_store_a_co, BM_edgeloop_center_get(el_store_a));
+ copy_v3_v3(el_store_b_co, BM_edgeloop_center_get(el_store_b));
+
+ /* correct normals need to be flipped to face each other
+ * we know both normals point in the same direction so one will need flipping */
+ {
+ float el_dir[3];
+ float no[3];
+ sub_v3_v3v3(el_dir, el_store_a_co, el_store_b_co);
+ normalize_v3_v3(no, el_dir);
+
+ if (is_a_no_valid == false) {
+ is_a_no_valid = BM_edgeloop_calc_normal_aligned(bm, el_store_a, no);
+ }
+ if (is_b_no_valid == false) {
+ is_b_no_valid = BM_edgeloop_calc_normal_aligned(bm, el_store_b, no);
+ }
+ (void)is_a_no_valid, (void)is_b_no_valid;
+
+ copy_v3_v3(el_store_a_no, BM_edgeloop_normal_get(el_store_a));
+ copy_v3_v3(el_store_b_no, BM_edgeloop_normal_get(el_store_b));
+
+ if (dot_v3v3(el_store_a_no, el_dir) > 0.0f) {
+ negate_v3(el_store_a_no);
+ }
+ if (dot_v3v3(el_store_b_no, el_dir) < 0.0f) {
+ negate_v3(el_store_b_no);
+ }
+ }
+ /* now normals are correct, don't touch! */
+
+ /* calculate the center spline, multiple */
+ if ((interp_mode == SUBD_RING_INTERP_PATH) || falloff_cache) {
+ float handle_a[3], handle_b[3];
+ float handle_len;
+
+ handle_len = bezier_handle_calc_length_v3(
+ el_store_a_co, el_store_a_no, el_store_b_co, el_store_b_no) *
+ smooth;
+
+ mul_v3_v3fl(handle_a, el_store_a_no, handle_len);
+ mul_v3_v3fl(handle_b, el_store_b_no, handle_len);
+
+ add_v3_v3(handle_a, el_store_a_co);
+ add_v3_v3(handle_b, el_store_b_co);
+
+ coord_array_main = MEM_mallocN(dims * (resolu) * sizeof(float), __func__);
+
+ for (i = 0; i < dims; i++) {
+ BKE_curve_forward_diff_bezier(el_store_a_co[i],
+ handle_a[i],
+ handle_b[i],
+ el_store_b_co[i],
+ ((float *)coord_array_main) + i,
+ resolu - 1,
+ sizeof(float) * dims);
+ }
+ }
+
+ switch (interp_mode) {
+ case SUBD_RING_INTERP_LINEAR: {
+ if (falloff_cache) {
+ float(*coord_array)[3] = MEM_mallocN(dims * (resolu) * sizeof(float), __func__);
+ for (i = 0; i < resolu; i++) {
+ interp_v3_v3v3(
+ coord_array[i], el_store_a_co, el_store_b_co, (float)i / (float)(resolu - 1));
+ }
+
+ for (el_store_ring = eloops_ring->first; el_store_ring;
+ el_store_ring = BM_EDGELOOP_NEXT(el_store_ring)) {
+ ListBase *lb_ring = BM_edgeloop_verts_get(el_store_ring);
+ LinkData *v_iter;
+
+ for (v_iter = lb_ring->first, i = 0; v_iter; v_iter = v_iter->next, i++) {
+ if (i > 0 && i < resolu - 1) {
+ /* shape */
+ if (falloff_cache) {
+ interp_v3_v3v3(((BMVert *)v_iter->data)->co,
+ coord_array[i],
+ ((BMVert *)v_iter->data)->co,
+ falloff_cache[i]);
+ }
+ }
+ }
+ }
+
+ MEM_freeN(coord_array);
+ }
+
+ break;
+ }
+ case SUBD_RING_INTERP_PATH: {
+ float(*direction_array)[3] = MEM_mallocN(dims * (resolu) * sizeof(float), __func__);
+ float(*quat_array)[4] = MEM_mallocN(resolu * sizeof(*quat_array), __func__);
+ float(*tri_array)[3][3] = MEM_mallocN(resolu * sizeof(*tri_array), __func__);
+ float(*tri_sta)[3], (*tri_end)[3], (*tri_tmp)[3];
+
+ /* very similar to make_bevel_list_3D_minimum_twist */
+
+ /* calculate normals */
+ copy_v3_v3(direction_array[0], el_store_a_no);
+ negate_v3_v3(direction_array[resolu - 1], el_store_b_no);
+ for (i = 1; i < resolu - 1; i++) {
+ bisect_v3_v3v3v3(direction_array[i],
+ coord_array_main[i - 1],
+ coord_array_main[i],
+ coord_array_main[i + 1]);
+ }
+
+ vec_to_quat(quat_array[0], direction_array[0], 5, 1);
+ normalize_qt(quat_array[0]);
+
+ for (i = 1; i < resolu; i++) {
+ float angle = angle_normalized_v3v3(direction_array[i - 1], direction_array[i]);
+ // BLI_assert(angle < DEG2RADF(90.0f));
+ if (angle > 0.0f) { /* otherwise we can keep as is */
+ float cross_tmp[3];
+ float q[4];
+ cross_v3_v3v3(cross_tmp, direction_array[i - 1], direction_array[i]);
+ axis_angle_to_quat(q, cross_tmp, angle);
+ mul_qt_qtqt(quat_array[i], q, quat_array[i - 1]);
+ normalize_qt(quat_array[i]);
+ }
+ else {
+ copy_qt_qt(quat_array[i], quat_array[i - 1]);
+ }
+ }
+
+ /* init base tri */
+ for (i = 0; i < resolu; i++) {
+ int j;
+
+ const float shape_size = falloff_cache ? falloff_cache[i] : 1.0f;
+
+ tri_tmp = tri_array[i];
+
+ /* create the triangle and transform */
+ for (j = 0; j < 3; j++) {
+ zero_v3(tri_tmp[j]);
+ if (j == 1) {
+ tri_tmp[j][0] = shape_size;
+ }
+ else if (j == 2) {
+ tri_tmp[j][1] = shape_size;
+ }
+ mul_qt_v3(quat_array[i], tri_tmp[j]);
+ add_v3_v3(tri_tmp[j], coord_array_main[i]);
+ }
+ }
+
+ tri_sta = tri_array[0];
+ tri_end = tri_array[resolu - 1];
+
+ for (el_store_ring = eloops_ring->first; el_store_ring;
+ el_store_ring = BM_EDGELOOP_NEXT(el_store_ring)) {
+ ListBase *lb_ring = BM_edgeloop_verts_get(el_store_ring);
+ LinkData *v_iter;
+
+ BMVert *v_a = ((LinkData *)lb_ring->first)->data;
+ BMVert *v_b = ((LinkData *)lb_ring->last)->data;
+
+ /* skip first and last */
+ for (v_iter = ((LinkData *)lb_ring->first)->next, i = 1; v_iter != lb_ring->last;
+ v_iter = v_iter->next, i++) {
+ float co_a[3], co_b[3];
+
+ tri_tmp = tri_array[i];
+
+ transform_point_by_tri_v3(co_a, v_a->co, UNPACK3(tri_tmp), UNPACK3(tri_sta));
+ transform_point_by_tri_v3(co_b, v_b->co, UNPACK3(tri_tmp), UNPACK3(tri_end));
+
+ interp_v3_v3v3(((BMVert *)v_iter->data)->co, co_a, co_b, (float)i / (float)(resolu - 1));
+ }
+ }
+
+ MEM_freeN(direction_array);
+ MEM_freeN(quat_array);
+ MEM_freeN(tri_array);
+ break;
+ }
+ case SUBD_RING_INTERP_SURF: {
+ float(*coord_array)[3] = MEM_mallocN(dims * (resolu) * sizeof(float), __func__);
+
+ /* calculate a bezier handle per edge ring */
+ for (el_store_ring = eloops_ring->first; el_store_ring;
+ el_store_ring = BM_EDGELOOP_NEXT(el_store_ring)) {
+ ListBase *lb_ring = BM_edgeloop_verts_get(el_store_ring);
+ LinkData *v_iter;
+
+ BMVert *v_a = ((LinkData *)lb_ring->first)->data;
+ BMVert *v_b = ((LinkData *)lb_ring->last)->data;
+
+ float co_a[3], no_a[3], handle_a[3], co_b[3], no_b[3], handle_b[3];
+ float handle_len;
+
+ copy_v3_v3(co_a, v_a->co);
+ copy_v3_v3(co_b, v_b->co);
+
+ /* don't calculate normals here else we get into feedback loop
+ * when subdividing 2+ connected edge rings */
#if 0
- bm_vert_calc_surface_tangent(bm, v_a, no_a);
- bm_vert_calc_surface_tangent(bm, v_b, no_b);
+ bm_vert_calc_surface_tangent(bm, v_a, no_a);
+ bm_vert_calc_surface_tangent(bm, v_b, no_b);
#else
- {
- const uint index_a = POINTER_AS_UINT(BLI_ghash_lookup(lpair->nors_gh_a, v_a));
- const uint index_b = POINTER_AS_UINT(BLI_ghash_lookup(lpair->nors_gh_b, v_b));
+ {
+ const uint index_a = POINTER_AS_UINT(BLI_ghash_lookup(lpair->nors_gh_a, v_a));
+ const uint index_b = POINTER_AS_UINT(BLI_ghash_lookup(lpair->nors_gh_b, v_b));
- BLI_assert(BLI_ghash_haskey(lpair->nors_gh_a, v_a));
- BLI_assert(BLI_ghash_haskey(lpair->nors_gh_b, v_b));
+ BLI_assert(BLI_ghash_haskey(lpair->nors_gh_a, v_a));
+ BLI_assert(BLI_ghash_haskey(lpair->nors_gh_b, v_b));
- copy_v3_v3(no_a, lpair->nors_a[index_a]);
- copy_v3_v3(no_b, lpair->nors_b[index_b]);
- }
+ copy_v3_v3(no_a, lpair->nors_a[index_a]);
+ copy_v3_v3(no_b, lpair->nors_b[index_b]);
+ }
#endif
- handle_len = bezier_handle_calc_length_v3(co_a, no_a, co_b, no_b) * smooth;
-
- mul_v3_v3fl(handle_a, no_a, handle_len);
- mul_v3_v3fl(handle_b, no_b, handle_len);
-
- add_v3_v3(handle_a, co_a);
- add_v3_v3(handle_b, co_b);
-
- for (i = 0; i < dims; i++) {
- BKE_curve_forward_diff_bezier(co_a[i], handle_a[i], handle_b[i], co_b[i],
- ((float *)coord_array) + i, resolu - 1, sizeof(float) * dims);
- }
-
- /* skip first and last */
- for (v_iter = ((LinkData *)lb_ring->first)->next, i = 1;
- v_iter != lb_ring->last;
- v_iter = v_iter->next, i++)
- {
- if (i > 0 && i < resolu - 1) {
- copy_v3_v3(((BMVert *)v_iter->data)->co, coord_array[i]);
-
- /* shape */
- if (falloff_cache) {
- interp_v3_v3v3(((BMVert *)v_iter->data)->co,
- coord_array_main[i], ((BMVert *)v_iter->data)->co, falloff_cache[i]);
- }
- }
- }
- }
-
- MEM_freeN(coord_array);
-
- break;
- }
- }
-
- if (coord_array_main) {
- MEM_freeN(coord_array_main);
- }
+ handle_len = bezier_handle_calc_length_v3(co_a, no_a, co_b, no_b) * smooth;
+
+ mul_v3_v3fl(handle_a, no_a, handle_len);
+ mul_v3_v3fl(handle_b, no_b, handle_len);
+
+ add_v3_v3(handle_a, co_a);
+ add_v3_v3(handle_b, co_b);
+
+ for (i = 0; i < dims; i++) {
+ BKE_curve_forward_diff_bezier(co_a[i],
+ handle_a[i],
+ handle_b[i],
+ co_b[i],
+ ((float *)coord_array) + i,
+ resolu - 1,
+ sizeof(float) * dims);
+ }
+
+ /* skip first and last */
+ for (v_iter = ((LinkData *)lb_ring->first)->next, i = 1; v_iter != lb_ring->last;
+ v_iter = v_iter->next, i++) {
+ if (i > 0 && i < resolu - 1) {
+ copy_v3_v3(((BMVert *)v_iter->data)->co, coord_array[i]);
+
+ /* shape */
+ if (falloff_cache) {
+ interp_v3_v3v3(((BMVert *)v_iter->data)->co,
+ coord_array_main[i],
+ ((BMVert *)v_iter->data)->co,
+ falloff_cache[i]);
+ }
+ }
+ }
+ }
+
+ MEM_freeN(coord_array);
+
+ break;
+ }
+ }
+
+ if (coord_array_main) {
+ MEM_freeN(coord_array_main);
+ }
}
/**
@@ -819,418 +821,410 @@ static void bm_edgering_pair_interpolate(
*/
static void bm_face_slice(BMesh *bm, BMLoop *l, const int cuts)
{
- /* TODO, interpolate edge data */
- BMLoop *l_new = l;
- int i;
-
- for (i = 0; i < cuts; i++) {
- /* no chance of double */
- BM_face_split(bm, l_new->f, l_new->prev, l_new->next->next, &l_new, NULL, false);
- if (l_new->f->len < l_new->radial_next->f->len) {
- l_new = l_new->radial_next;
- }
- BMO_face_flag_enable(bm, l_new->f, FACE_OUT);
- BMO_face_flag_enable(bm, l_new->radial_next->f, FACE_OUT);
- }
+ /* TODO, interpolate edge data */
+ BMLoop *l_new = l;
+ int i;
+
+ for (i = 0; i < cuts; i++) {
+ /* no chance of double */
+ BM_face_split(bm, l_new->f, l_new->prev, l_new->next->next, &l_new, NULL, false);
+ if (l_new->f->len < l_new->radial_next->f->len) {
+ l_new = l_new->radial_next;
+ }
+ BMO_face_flag_enable(bm, l_new->f, FACE_OUT);
+ BMO_face_flag_enable(bm, l_new->radial_next->f, FACE_OUT);
+ }
}
static bool bm_edgering_pair_order_is_flipped(BMesh *UNUSED(bm),
struct BMEdgeLoopStore *el_store_a,
- struct BMEdgeLoopStore *el_store_b )
+ struct BMEdgeLoopStore *el_store_b)
{
- ListBase *lb_a = BM_edgeloop_verts_get(el_store_a);
- ListBase *lb_b = BM_edgeloop_verts_get(el_store_b);
-
- LinkData *v_iter_a_first = lb_a->first;
- LinkData *v_iter_b_first = lb_b->first;
-
- LinkData *v_iter_a_step = v_iter_a_first;
- LinkData *v_iter_b_step = v_iter_b_first;
-
- /* we _must_ have same starting edge shared */
- BLI_assert(BM_edge_exists(v_iter_a_first->data, v_iter_b_first->data));
-
- /* step around any fan-faces on both sides */
- do {
- v_iter_a_step = v_iter_a_step->next;
- } while (v_iter_a_step &&
- ((BM_edge_exists(v_iter_a_step->data, v_iter_b_first->data)) ||
- (BM_edge_exists(v_iter_a_step->data, v_iter_b_first->next->data))));
- do {
- v_iter_b_step = v_iter_b_step->next;
- } while (v_iter_b_step &&
- ((BM_edge_exists(v_iter_b_step->data, v_iter_a_first->data)) ||
- (BM_edge_exists(v_iter_b_step->data, v_iter_a_first->next->data))));
-
- v_iter_a_step = v_iter_a_step ? v_iter_a_step->prev : lb_a->last;
- v_iter_b_step = v_iter_b_step ? v_iter_b_step->prev : lb_b->last;
-
- return !(BM_edge_exists(v_iter_a_step->data, v_iter_b_step->data) ||
- BM_edge_exists(v_iter_a_first->next->data, v_iter_b_step->data) ||
- BM_edge_exists(v_iter_b_first->next->data, v_iter_a_step->data));
+ ListBase *lb_a = BM_edgeloop_verts_get(el_store_a);
+ ListBase *lb_b = BM_edgeloop_verts_get(el_store_b);
+
+ LinkData *v_iter_a_first = lb_a->first;
+ LinkData *v_iter_b_first = lb_b->first;
+
+ LinkData *v_iter_a_step = v_iter_a_first;
+ LinkData *v_iter_b_step = v_iter_b_first;
+
+ /* we _must_ have same starting edge shared */
+ BLI_assert(BM_edge_exists(v_iter_a_first->data, v_iter_b_first->data));
+
+ /* step around any fan-faces on both sides */
+ do {
+ v_iter_a_step = v_iter_a_step->next;
+ } while (v_iter_a_step && ((BM_edge_exists(v_iter_a_step->data, v_iter_b_first->data)) ||
+ (BM_edge_exists(v_iter_a_step->data, v_iter_b_first->next->data))));
+ do {
+ v_iter_b_step = v_iter_b_step->next;
+ } while (v_iter_b_step && ((BM_edge_exists(v_iter_b_step->data, v_iter_a_first->data)) ||
+ (BM_edge_exists(v_iter_b_step->data, v_iter_a_first->next->data))));
+
+ v_iter_a_step = v_iter_a_step ? v_iter_a_step->prev : lb_a->last;
+ v_iter_b_step = v_iter_b_step ? v_iter_b_step->prev : lb_b->last;
+
+ return !(BM_edge_exists(v_iter_a_step->data, v_iter_b_step->data) ||
+ BM_edge_exists(v_iter_a_first->next->data, v_iter_b_step->data) ||
+ BM_edge_exists(v_iter_b_first->next->data, v_iter_a_step->data));
}
/**
* Takes 2 edge loops that share edges,
* sort their verts and rotates the list so the lined up.
*/
-static void bm_edgering_pair_order(
- BMesh *bm,
- struct BMEdgeLoopStore *el_store_a,
- struct BMEdgeLoopStore *el_store_b)
+static void bm_edgering_pair_order(BMesh *bm,
+ struct BMEdgeLoopStore *el_store_a,
+ struct BMEdgeLoopStore *el_store_b)
{
- ListBase *lb_a = BM_edgeloop_verts_get(el_store_a);
- ListBase *lb_b = BM_edgeloop_verts_get(el_store_b);
-
- LinkData *node;
-
- bm_edgeloop_vert_tag(el_store_a, false);
- bm_edgeloop_vert_tag(el_store_b, true);
-
- /* before going much further, get ourselves in order
- * - align loops (not strictly necessary but handy)
- * - ensure winding is set for both loops */
- if (BM_edgeloop_is_closed(el_store_a) && BM_edgeloop_is_closed(el_store_b)) {
- BMIter eiter;
- BMEdge *e;
- BMVert *v_other;
-
- node = lb_a->first;
-
- BM_ITER_ELEM (e, &eiter, (BMVert *)node->data, BM_EDGES_OF_VERT) {
- if (BMO_edge_flag_test(bm, e, EDGE_RING)) {
- v_other = BM_edge_other_vert(e, (BMVert *)node->data);
- if (BM_elem_flag_test(v_other, BM_ELEM_TAG)) {
- break;
- }
- else {
- v_other = NULL;
- }
- }
- }
- BLI_assert(v_other != NULL);
-
- for (node = lb_b->first; node; node = node->next) {
- if (node->data == v_other) {
- break;
- }
- }
- BLI_assert(node != NULL);
-
- BLI_listbase_rotate_first(lb_b, node);
-
- /* now check we are winding the same way */
- if (bm_edgering_pair_order_is_flipped(bm, el_store_a, el_store_b)) {
- BM_edgeloop_flip(bm, el_store_b);
- /* re-ensure the first node */
- BLI_listbase_rotate_first(lb_b, node);
- }
-
- /* sanity checks that we are aligned & winding now */
- BLI_assert(bm_edgering_pair_order_is_flipped(bm, el_store_a, el_store_b) == false);
- }
- else {
- /* if we dont share and edge - flip */
- BMEdge *e = BM_edge_exists(((LinkData *)lb_a->first)->data,
- ((LinkData *)lb_b->first)->data);
- if (e == NULL || !BMO_edge_flag_test(bm, e, EDGE_RING)) {
- BM_edgeloop_flip(bm, el_store_b);
- }
- }
-
- /* for cases with multiple loops */
- bm_edgeloop_vert_tag(el_store_b, false);
+ ListBase *lb_a = BM_edgeloop_verts_get(el_store_a);
+ ListBase *lb_b = BM_edgeloop_verts_get(el_store_b);
+
+ LinkData *node;
+
+ bm_edgeloop_vert_tag(el_store_a, false);
+ bm_edgeloop_vert_tag(el_store_b, true);
+
+ /* before going much further, get ourselves in order
+ * - align loops (not strictly necessary but handy)
+ * - ensure winding is set for both loops */
+ if (BM_edgeloop_is_closed(el_store_a) && BM_edgeloop_is_closed(el_store_b)) {
+ BMIter eiter;
+ BMEdge *e;
+ BMVert *v_other;
+
+ node = lb_a->first;
+
+ BM_ITER_ELEM (e, &eiter, (BMVert *)node->data, BM_EDGES_OF_VERT) {
+ if (BMO_edge_flag_test(bm, e, EDGE_RING)) {
+ v_other = BM_edge_other_vert(e, (BMVert *)node->data);
+ if (BM_elem_flag_test(v_other, BM_ELEM_TAG)) {
+ break;
+ }
+ else {
+ v_other = NULL;
+ }
+ }
+ }
+ BLI_assert(v_other != NULL);
+
+ for (node = lb_b->first; node; node = node->next) {
+ if (node->data == v_other) {
+ break;
+ }
+ }
+ BLI_assert(node != NULL);
+
+ BLI_listbase_rotate_first(lb_b, node);
+
+ /* now check we are winding the same way */
+ if (bm_edgering_pair_order_is_flipped(bm, el_store_a, el_store_b)) {
+ BM_edgeloop_flip(bm, el_store_b);
+ /* re-ensure the first node */
+ BLI_listbase_rotate_first(lb_b, node);
+ }
+
+ /* sanity checks that we are aligned & winding now */
+ BLI_assert(bm_edgering_pair_order_is_flipped(bm, el_store_a, el_store_b) == false);
+ }
+ else {
+ /* if we dont share and edge - flip */
+ BMEdge *e = BM_edge_exists(((LinkData *)lb_a->first)->data, ((LinkData *)lb_b->first)->data);
+ if (e == NULL || !BMO_edge_flag_test(bm, e, EDGE_RING)) {
+ BM_edgeloop_flip(bm, el_store_b);
+ }
+ }
+
+ /* for cases with multiple loops */
+ bm_edgeloop_vert_tag(el_store_b, false);
}
-
/**
* Take 2 edge loops, do a subdivision on connecting edges.
*
* \note loops are _not_ aligned.
*/
-static void bm_edgering_pair_subdiv(
- BMesh *bm,
- struct BMEdgeLoopStore *el_store_a,
- struct BMEdgeLoopStore *el_store_b,
- ListBase *eloops_ring,
- const int cuts)
+static void bm_edgering_pair_subdiv(BMesh *bm,
+ struct BMEdgeLoopStore *el_store_a,
+ struct BMEdgeLoopStore *el_store_b,
+ ListBase *eloops_ring,
+ const int cuts)
{
- ListBase *lb_a = BM_edgeloop_verts_get(el_store_a);
- // ListBase *lb_b = BM_edgeloop_verts_get(el_store_b);
- const int stack_max = max_ii(BM_edgeloop_length_get(el_store_a),
- BM_edgeloop_length_get(el_store_b)) * 2;
- BMEdge **edges_ring_arr = BLI_array_alloca(edges_ring_arr, stack_max);
- BMFace **faces_ring_arr = BLI_array_alloca(faces_ring_arr, stack_max);
- STACK_DECLARE(edges_ring_arr);
- STACK_DECLARE(faces_ring_arr);
- struct BMEdgeLoopStore *el_store_ring;
- LinkData *node;
- BMEdge *e;
- BMFace *f;
-
- STACK_INIT(edges_ring_arr, stack_max);
- STACK_INIT(faces_ring_arr, stack_max);
-
- bm_edgeloop_vert_tag(el_store_a, false);
- bm_edgeloop_vert_tag(el_store_b, true);
-
- for (node = lb_a->first; node; node = node->next) {
- BMIter eiter;
-
- BM_ITER_ELEM (e, &eiter, (BMVert *)node->data, BM_EDGES_OF_VERT) {
- if (!BMO_edge_flag_test(bm, e, EDGE_IN_STACK)) {
- BMVert *v_other = BM_edge_other_vert(e, (BMVert *)node->data);
- if (BM_elem_flag_test(v_other, BM_ELEM_TAG)) {
- BMIter fiter;
-
- BMO_edge_flag_enable(bm, e, EDGE_IN_STACK);
- STACK_PUSH(edges_ring_arr, e);
-
- /* add faces to the stack */
- BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) {
- if (BMO_face_flag_test(bm, f, FACE_OUT)) {
- if (!BMO_face_flag_test(bm, f, FACE_IN_STACK)) {
- BMO_face_flag_enable(bm, f, FACE_IN_STACK);
- STACK_PUSH(faces_ring_arr, f);
- }
- }
- }
- }
- }
- }
- }
-
- while ((e = STACK_POP(edges_ring_arr))) {
- /* found opposite edge */
- BMVert *v_other;
-
- BMO_edge_flag_disable(bm, e, EDGE_IN_STACK);
-
- /* unrelated to subdiv, but if we _don't_ clear flag, multiple rings fail */
- BMO_edge_flag_disable(bm, e, EDGE_RING);
-
- v_other = BM_elem_flag_test(e->v1, BM_ELEM_TAG) ? e->v1 : e->v2;
- bm_edge_subdiv_as_loop(bm, eloops_ring, e, v_other, cuts);
- }
-
- while ((f = STACK_POP(faces_ring_arr))) {
- BMLoop *l_iter, *l_first;
-
- BMO_face_flag_disable(bm, f, FACE_IN_STACK);
-
- /* Check each edge of the face */
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if (BMO_edge_flag_test(bm, l_iter->e, EDGE_RIM)) {
- bm_face_slice(bm, l_iter, cuts);
- break;
- }
- } while ((l_iter = l_iter->next) != l_first);
- }
-
-
- /* clear tags so subdiv verts don't get tagged too */
- for (el_store_ring = eloops_ring->first;
- el_store_ring;
- el_store_ring = BM_EDGELOOP_NEXT(el_store_ring))
- {
- bm_edgeloop_vert_tag(el_store_ring, false);
- }
-
- /* cleanup after */
- bm_edgeloop_vert_tag(el_store_b, false);
+ ListBase *lb_a = BM_edgeloop_verts_get(el_store_a);
+ // ListBase *lb_b = BM_edgeloop_verts_get(el_store_b);
+ const int stack_max = max_ii(BM_edgeloop_length_get(el_store_a),
+ BM_edgeloop_length_get(el_store_b)) *
+ 2;
+ BMEdge **edges_ring_arr = BLI_array_alloca(edges_ring_arr, stack_max);
+ BMFace **faces_ring_arr = BLI_array_alloca(faces_ring_arr, stack_max);
+ STACK_DECLARE(edges_ring_arr);
+ STACK_DECLARE(faces_ring_arr);
+ struct BMEdgeLoopStore *el_store_ring;
+ LinkData *node;
+ BMEdge *e;
+ BMFace *f;
+
+ STACK_INIT(edges_ring_arr, stack_max);
+ STACK_INIT(faces_ring_arr, stack_max);
+
+ bm_edgeloop_vert_tag(el_store_a, false);
+ bm_edgeloop_vert_tag(el_store_b, true);
+
+ for (node = lb_a->first; node; node = node->next) {
+ BMIter eiter;
+
+ BM_ITER_ELEM (e, &eiter, (BMVert *)node->data, BM_EDGES_OF_VERT) {
+ if (!BMO_edge_flag_test(bm, e, EDGE_IN_STACK)) {
+ BMVert *v_other = BM_edge_other_vert(e, (BMVert *)node->data);
+ if (BM_elem_flag_test(v_other, BM_ELEM_TAG)) {
+ BMIter fiter;
+
+ BMO_edge_flag_enable(bm, e, EDGE_IN_STACK);
+ STACK_PUSH(edges_ring_arr, e);
+
+ /* add faces to the stack */
+ BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) {
+ if (BMO_face_flag_test(bm, f, FACE_OUT)) {
+ if (!BMO_face_flag_test(bm, f, FACE_IN_STACK)) {
+ BMO_face_flag_enable(bm, f, FACE_IN_STACK);
+ STACK_PUSH(faces_ring_arr, f);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ while ((e = STACK_POP(edges_ring_arr))) {
+ /* found opposite edge */
+ BMVert *v_other;
+
+ BMO_edge_flag_disable(bm, e, EDGE_IN_STACK);
+
+ /* unrelated to subdiv, but if we _don't_ clear flag, multiple rings fail */
+ BMO_edge_flag_disable(bm, e, EDGE_RING);
+
+ v_other = BM_elem_flag_test(e->v1, BM_ELEM_TAG) ? e->v1 : e->v2;
+ bm_edge_subdiv_as_loop(bm, eloops_ring, e, v_other, cuts);
+ }
+
+ while ((f = STACK_POP(faces_ring_arr))) {
+ BMLoop *l_iter, *l_first;
+
+ BMO_face_flag_disable(bm, f, FACE_IN_STACK);
+
+ /* Check each edge of the face */
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (BMO_edge_flag_test(bm, l_iter->e, EDGE_RIM)) {
+ bm_face_slice(bm, l_iter, cuts);
+ break;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+
+ /* clear tags so subdiv verts don't get tagged too */
+ for (el_store_ring = eloops_ring->first; el_store_ring;
+ el_store_ring = BM_EDGELOOP_NEXT(el_store_ring)) {
+ bm_edgeloop_vert_tag(el_store_ring, false);
+ }
+
+ /* cleanup after */
+ bm_edgeloop_vert_tag(el_store_b, false);
}
-static void bm_edgering_pair_ringsubd(
- BMesh *bm, LoopPairStore *lpair,
- struct BMEdgeLoopStore *el_store_a,
- struct BMEdgeLoopStore *el_store_b,
- const int interp_mode, const int cuts, const float smooth,
- const float *falloff_cache)
+static void bm_edgering_pair_ringsubd(BMesh *bm,
+ LoopPairStore *lpair,
+ struct BMEdgeLoopStore *el_store_a,
+ struct BMEdgeLoopStore *el_store_b,
+ const int interp_mode,
+ const int cuts,
+ const float smooth,
+ const float *falloff_cache)
{
- ListBase eloops_ring = {NULL};
- bm_edgering_pair_order(bm, el_store_a, el_store_b);
- bm_edgering_pair_subdiv(bm, el_store_a, el_store_b, &eloops_ring, cuts);
- bm_edgering_pair_interpolate(bm, lpair, el_store_a, el_store_b, &eloops_ring,
- interp_mode, cuts, smooth, falloff_cache);
- BM_mesh_edgeloops_free(&eloops_ring);
+ ListBase eloops_ring = {NULL};
+ bm_edgering_pair_order(bm, el_store_a, el_store_b);
+ bm_edgering_pair_subdiv(bm, el_store_a, el_store_b, &eloops_ring, cuts);
+ bm_edgering_pair_interpolate(
+ bm, lpair, el_store_a, el_store_b, &eloops_ring, interp_mode, cuts, smooth, falloff_cache);
+ BM_mesh_edgeloops_free(&eloops_ring);
}
static bool bm_edge_rim_test_cb(BMEdge *e, void *bm_v)
{
- BMesh *bm = bm_v;
- return BMO_edge_flag_test_bool(bm, e, EDGE_RIM);
+ BMesh *bm = bm_v;
+ return BMO_edge_flag_test_bool(bm, e, EDGE_RIM);
}
-
/* keep this operator fast, its used in a modifier */
void bmo_subdivide_edgering_exec(BMesh *bm, BMOperator *op)
{
- ListBase eloops_rim = {NULL};
- BMOIter siter;
- BMEdge *e;
- int count;
- bool changed = false;
-
- const int cuts = BMO_slot_int_get(op->slots_in, "cuts");
- const int interp_mode = BMO_slot_int_get(op->slots_in, "interp_mode");
- const float smooth = BMO_slot_float_get(op->slots_in, "smooth");
- const int resolu = cuts + 2;
-
- /* optional 'shape' */
- const int profile_shape = BMO_slot_int_get(op->slots_in, "profile_shape");
- const float profile_shape_factor = BMO_slot_float_get(op->slots_in, "profile_shape_factor");
- float *falloff_cache = (profile_shape_factor != 0.0f) ? BLI_array_alloca(falloff_cache, cuts + 2) : NULL;
-
- BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_RING);
-
- BM_mesh_elem_hflag_disable_all(bm, BM_VERT, BM_ELEM_TAG, false);
-
- /* -------------------------------------------------------------------- */
- /* flag outer edges (loops defined as edges on the bounds of the edge ring) */
-
- BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
- BMIter fiter;
- BMFace *f;
-
- BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) {
- /* could support ngons, other areas would need updating too, see T48926. */
- if ((f->len <= 4) && !BMO_face_flag_test(bm, f, FACE_OUT)) {
- BMIter liter;
- BMLoop *l;
- bool ok = false;
-
- /* check at least 2 edges in the face are rings */
- BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- if (BMO_edge_flag_test(bm, l->e, EDGE_RING) && e != l->e) {
- ok = true;
- break;
- }
- }
-
- if (ok) {
- BMO_face_flag_enable(bm, f, FACE_OUT);
-
- BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- if (!BMO_edge_flag_test(bm, l->e, EDGE_RING)) {
- BMO_edge_flag_enable(bm, l->e, EDGE_RIM);
- }
- }
- }
- }
- }
- }
-
-
- /* -------------------------------------------------------------------- */
- /* Cache falloff for each step (symmetrical) */
-
- if (falloff_cache) {
- int i;
- for (i = 0; i < resolu; i++) {
- float shape_size = 1.0f;
- float fac = (float)i / (float)(resolu - 1);
- fac = fabsf(1.0f - 2.0f * fabsf(0.5f - fac));
- fac = bmesh_subd_falloff_calc(profile_shape, fac);
- shape_size += fac * profile_shape_factor;
-
- falloff_cache[i] = shape_size;
- }
- }
-
-
- /* -------------------------------------------------------------------- */
- /* Execute subdivision on all ring pairs */
-
- count = BM_mesh_edgeloops_find(bm, &eloops_rim, bm_edge_rim_test_cb, (void *)bm);
-
- if (count < 2) {
- BMO_error_raise(bm, op, BMERR_INVALID_SELECTION,
- "No edge rings found");
- goto cleanup;
- }
- else if (count == 2) {
- /* this case could be removed,
- * but simple to avoid 'bm_edgering_pair_calc' in this case since theres only one. */
- struct BMEdgeLoopStore *el_store_a = eloops_rim.first;
- struct BMEdgeLoopStore *el_store_b = eloops_rim.last;
- LoopPairStore *lpair;
-
- if (bm_edgeloop_check_overlap_all(bm, el_store_a, el_store_b)) {
- lpair = bm_edgering_pair_store_create(bm, el_store_a, el_store_b, interp_mode);
- }
- else {
- lpair = NULL;
- }
-
- if (lpair) {
- bm_edgering_pair_ringsubd(bm, lpair, el_store_a, el_store_b,
- interp_mode, cuts, smooth, falloff_cache);
- bm_edgering_pair_store_free(lpair, interp_mode);
- changed = true;
- }
- else {
- BMO_error_raise(bm, op, BMERR_INVALID_SELECTION,
- "Edge-ring pair isn't connected");
- goto cleanup;
- }
- }
- else {
- GSetIterator gs_iter;
- int i;
-
- GSet *eloop_pairs_gs = bm_edgering_pair_calc(bm, &eloops_rim);
- LoopPairStore **lpair_arr;
-
- if (eloop_pairs_gs == NULL) {
- BMO_error_raise(bm, op, BMERR_INVALID_SELECTION,
- "Edge-rings are not connected");
- goto cleanup;
- }
-
- lpair_arr = BLI_array_alloca(lpair_arr, BLI_gset_len(eloop_pairs_gs));
-
- /* first cache pairs */
- GSET_ITER_INDEX (gs_iter, eloop_pairs_gs, i) {
- GHashPair *eloop_pair = BLI_gsetIterator_getKey(&gs_iter);
- struct BMEdgeLoopStore *el_store_a = (void *)eloop_pair->first;
- struct BMEdgeLoopStore *el_store_b = (void *)eloop_pair->second;
- LoopPairStore *lpair;
-
- if (bm_edgeloop_check_overlap_all(bm, el_store_a, el_store_b)) {
- lpair = bm_edgering_pair_store_create(bm, el_store_a, el_store_b, interp_mode);
- }
- else {
- lpair = NULL;
- }
- lpair_arr[i] = lpair;
-
- BLI_assert(bm_verts_tag_count(bm) == 0);
- }
-
- GSET_ITER_INDEX (gs_iter, eloop_pairs_gs, i) {
- GHashPair *eloop_pair = BLI_gsetIterator_getKey(&gs_iter);
- struct BMEdgeLoopStore *el_store_a = (void *)eloop_pair->first;
- struct BMEdgeLoopStore *el_store_b = (void *)eloop_pair->second;
- LoopPairStore *lpair = lpair_arr[i];
-
- if (lpair) {
- bm_edgering_pair_ringsubd(bm, lpair, el_store_a, el_store_b,
- interp_mode, cuts, smooth, falloff_cache);
- bm_edgering_pair_store_free(lpair, interp_mode);
- changed = true;
- }
-
- BLI_assert(bm_verts_tag_count(bm) == 0);
- }
- BLI_gset_free(eloop_pairs_gs, MEM_freeN);
- }
+ ListBase eloops_rim = {NULL};
+ BMOIter siter;
+ BMEdge *e;
+ int count;
+ bool changed = false;
+
+ const int cuts = BMO_slot_int_get(op->slots_in, "cuts");
+ const int interp_mode = BMO_slot_int_get(op->slots_in, "interp_mode");
+ const float smooth = BMO_slot_float_get(op->slots_in, "smooth");
+ const int resolu = cuts + 2;
+
+ /* optional 'shape' */
+ const int profile_shape = BMO_slot_int_get(op->slots_in, "profile_shape");
+ const float profile_shape_factor = BMO_slot_float_get(op->slots_in, "profile_shape_factor");
+ float *falloff_cache = (profile_shape_factor != 0.0f) ?
+ BLI_array_alloca(falloff_cache, cuts + 2) :
+ NULL;
+
+ BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_RING);
+
+ BM_mesh_elem_hflag_disable_all(bm, BM_VERT, BM_ELEM_TAG, false);
+
+ /* -------------------------------------------------------------------- */
+ /* flag outer edges (loops defined as edges on the bounds of the edge ring) */
+
+ BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
+ BMIter fiter;
+ BMFace *f;
+
+ BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) {
+ /* could support ngons, other areas would need updating too, see T48926. */
+ if ((f->len <= 4) && !BMO_face_flag_test(bm, f, FACE_OUT)) {
+ BMIter liter;
+ BMLoop *l;
+ bool ok = false;
+
+ /* check at least 2 edges in the face are rings */
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ if (BMO_edge_flag_test(bm, l->e, EDGE_RING) && e != l->e) {
+ ok = true;
+ break;
+ }
+ }
+
+ if (ok) {
+ BMO_face_flag_enable(bm, f, FACE_OUT);
+
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ if (!BMO_edge_flag_test(bm, l->e, EDGE_RING)) {
+ BMO_edge_flag_enable(bm, l->e, EDGE_RIM);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* -------------------------------------------------------------------- */
+ /* Cache falloff for each step (symmetrical) */
+
+ if (falloff_cache) {
+ int i;
+ for (i = 0; i < resolu; i++) {
+ float shape_size = 1.0f;
+ float fac = (float)i / (float)(resolu - 1);
+ fac = fabsf(1.0f - 2.0f * fabsf(0.5f - fac));
+ fac = bmesh_subd_falloff_calc(profile_shape, fac);
+ shape_size += fac * profile_shape_factor;
+
+ falloff_cache[i] = shape_size;
+ }
+ }
+
+ /* -------------------------------------------------------------------- */
+ /* Execute subdivision on all ring pairs */
+
+ count = BM_mesh_edgeloops_find(bm, &eloops_rim, bm_edge_rim_test_cb, (void *)bm);
+
+ if (count < 2) {
+ BMO_error_raise(bm, op, BMERR_INVALID_SELECTION, "No edge rings found");
+ goto cleanup;
+ }
+ else if (count == 2) {
+ /* this case could be removed,
+ * but simple to avoid 'bm_edgering_pair_calc' in this case since theres only one. */
+ struct BMEdgeLoopStore *el_store_a = eloops_rim.first;
+ struct BMEdgeLoopStore *el_store_b = eloops_rim.last;
+ LoopPairStore *lpair;
+
+ if (bm_edgeloop_check_overlap_all(bm, el_store_a, el_store_b)) {
+ lpair = bm_edgering_pair_store_create(bm, el_store_a, el_store_b, interp_mode);
+ }
+ else {
+ lpair = NULL;
+ }
+
+ if (lpair) {
+ bm_edgering_pair_ringsubd(
+ bm, lpair, el_store_a, el_store_b, interp_mode, cuts, smooth, falloff_cache);
+ bm_edgering_pair_store_free(lpair, interp_mode);
+ changed = true;
+ }
+ else {
+ BMO_error_raise(bm, op, BMERR_INVALID_SELECTION, "Edge-ring pair isn't connected");
+ goto cleanup;
+ }
+ }
+ else {
+ GSetIterator gs_iter;
+ int i;
+
+ GSet *eloop_pairs_gs = bm_edgering_pair_calc(bm, &eloops_rim);
+ LoopPairStore **lpair_arr;
+
+ if (eloop_pairs_gs == NULL) {
+ BMO_error_raise(bm, op, BMERR_INVALID_SELECTION, "Edge-rings are not connected");
+ goto cleanup;
+ }
+
+ lpair_arr = BLI_array_alloca(lpair_arr, BLI_gset_len(eloop_pairs_gs));
+
+ /* first cache pairs */
+ GSET_ITER_INDEX(gs_iter, eloop_pairs_gs, i)
+ {
+ GHashPair *eloop_pair = BLI_gsetIterator_getKey(&gs_iter);
+ struct BMEdgeLoopStore *el_store_a = (void *)eloop_pair->first;
+ struct BMEdgeLoopStore *el_store_b = (void *)eloop_pair->second;
+ LoopPairStore *lpair;
+
+ if (bm_edgeloop_check_overlap_all(bm, el_store_a, el_store_b)) {
+ lpair = bm_edgering_pair_store_create(bm, el_store_a, el_store_b, interp_mode);
+ }
+ else {
+ lpair = NULL;
+ }
+ lpair_arr[i] = lpair;
+
+ BLI_assert(bm_verts_tag_count(bm) == 0);
+ }
+
+ GSET_ITER_INDEX(gs_iter, eloop_pairs_gs, i)
+ {
+ GHashPair *eloop_pair = BLI_gsetIterator_getKey(&gs_iter);
+ struct BMEdgeLoopStore *el_store_a = (void *)eloop_pair->first;
+ struct BMEdgeLoopStore *el_store_b = (void *)eloop_pair->second;
+ LoopPairStore *lpair = lpair_arr[i];
+
+ if (lpair) {
+ bm_edgering_pair_ringsubd(
+ bm, lpair, el_store_a, el_store_b, interp_mode, cuts, smooth, falloff_cache);
+ bm_edgering_pair_store_free(lpair, interp_mode);
+ changed = true;
+ }
+
+ BLI_assert(bm_verts_tag_count(bm) == 0);
+ }
+ BLI_gset_free(eloop_pairs_gs, MEM_freeN);
+ }
cleanup:
- BM_mesh_edgeloops_free(&eloops_rim);
+ BM_mesh_edgeloops_free(&eloops_rim);
- /* flag output */
- if (changed) {
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_OUT);
- }
+ /* flag output */
+ if (changed) {
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_OUT);
+ }
}
diff --git a/source/blender/bmesh/operators/bmo_symmetrize.c b/source/blender/bmesh/operators/bmo_symmetrize.c
index 0df3759ae8b..31c61f28ea9 100644
--- a/source/blender/bmesh/operators/bmo_symmetrize.c
+++ b/source/blender/bmesh/operators/bmo_symmetrize.c
@@ -30,74 +30,77 @@
void bmo_symmetrize_exec(BMesh *bm, BMOperator *op)
{
- const float dist = BMO_slot_float_get(op->slots_in, "dist");
- const int direction = BMO_slot_int_get(op->slots_in, "direction");
- const int axis = direction % 3;
+ const float dist = BMO_slot_float_get(op->slots_in, "dist");
+ const int direction = BMO_slot_int_get(op->slots_in, "direction");
+ const int axis = direction % 3;
- BMOperator op_bisect;
- BMOperator op_dupe;
- BMOperator op_weld;
+ BMOperator op_bisect;
+ BMOperator op_dupe;
+ BMOperator op_weld;
- BMOpSlot *slot_vertmap;
- BMOpSlot *slot_targetmap;
+ BMOpSlot *slot_vertmap;
+ BMOpSlot *slot_targetmap;
- float plane_no[3];
- float scale[3];
+ float plane_no[3];
+ float scale[3];
- BMOIter siter;
- BMVert *v;
+ BMOIter siter;
+ BMVert *v;
- copy_v3_fl(plane_no, 0.0f);
- copy_v3_fl(scale, 1.0f);
+ copy_v3_fl(plane_no, 0.0f);
+ copy_v3_fl(scale, 1.0f);
- plane_no[axis] = direction > 2 ? -1.0f : 1.0f;
- scale[axis] *= -1.0f;
+ plane_no[axis] = direction > 2 ? -1.0f : 1.0f;
+ scale[axis] *= -1.0f;
- /* Cut in half */
- BMO_op_initf(bm, &op_bisect, op->flag,
- "bisect_plane geom=%s plane_no=%v dist=%f clear_outer=%b use_snap_center=%b",
- op, "input", plane_no, dist, true, true);
+ /* Cut in half */
+ BMO_op_initf(bm,
+ &op_bisect,
+ op->flag,
+ "bisect_plane geom=%s plane_no=%v dist=%f clear_outer=%b use_snap_center=%b",
+ op,
+ "input",
+ plane_no,
+ dist,
+ true,
+ true);
- BMO_op_exec(bm, &op_bisect);
+ BMO_op_exec(bm, &op_bisect);
- /* Duplicate */
- BMO_op_initf(bm, &op_dupe, op->flag,
- "duplicate geom=%S",
- &op_bisect, "geom.out");
+ /* Duplicate */
+ BMO_op_initf(bm, &op_dupe, op->flag, "duplicate geom=%S", &op_bisect, "geom.out");
- BMO_op_exec(bm, &op_dupe);
+ BMO_op_exec(bm, &op_dupe);
- /* Flag for output (some will be merged) */
- BMO_slot_buffer_flag_enable(bm, op_bisect.slots_out, "geom.out", BM_ALL_NOLOOP, ELE_OUT);
- BMO_slot_buffer_flag_enable(bm, op_dupe.slots_out, "geom.out", BM_ALL_NOLOOP, ELE_OUT);
+ /* Flag for output (some will be merged) */
+ BMO_slot_buffer_flag_enable(bm, op_bisect.slots_out, "geom.out", BM_ALL_NOLOOP, ELE_OUT);
+ BMO_slot_buffer_flag_enable(bm, op_dupe.slots_out, "geom.out", BM_ALL_NOLOOP, ELE_OUT);
+ BMO_op_callf(bm, op->flag, "scale verts=%S vec=%v", &op_dupe, "geom.out", scale);
- BMO_op_callf(bm, op->flag, "scale verts=%S vec=%v", &op_dupe, "geom.out", scale);
+ /* important 'flip_multires' is disabled,
+ * otherwise multi-res data will be reversed, see: T47788 */
+ BMO_op_callf(bm, op->flag, "reverse_faces faces=%S", &op_dupe, "geom.out");
- /* important 'flip_multires' is disabled,
- * otherwise multi-res data will be reversed, see: T47788 */
- BMO_op_callf(bm, op->flag, "reverse_faces faces=%S", &op_dupe, "geom.out");
+ /* Weld verts */
+ BMO_op_init(bm, &op_weld, op->flag, "weld_verts");
+ slot_vertmap = BMO_slot_get(op_dupe.slots_out, "vert_map.out");
+ slot_targetmap = BMO_slot_get(op_weld.slots_in, "targetmap");
- /* Weld verts */
- BMO_op_init(bm, &op_weld, op->flag, "weld_verts");
+ BMO_ITER (v, &siter, op_bisect.slots_out, "geom_cut.out", BM_VERT) {
+ BMVert *v_dupe = BMO_slot_map_elem_get(slot_vertmap, v);
+ BMO_slot_map_elem_insert(&op_weld, slot_targetmap, v_dupe, v);
+ }
- slot_vertmap = BMO_slot_get(op_dupe.slots_out, "vert_map.out");
- slot_targetmap = BMO_slot_get(op_weld.slots_in, "targetmap");
+ BMO_op_exec(bm, &op_weld);
- BMO_ITER (v, &siter, op_bisect.slots_out, "geom_cut.out", BM_VERT) {
- BMVert *v_dupe = BMO_slot_map_elem_get(slot_vertmap, v);
- BMO_slot_map_elem_insert(&op_weld, slot_targetmap, v_dupe, v);
- }
+ /* Cleanup */
+ BMO_op_finish(bm, &op_weld);
- BMO_op_exec(bm, &op_weld);
+ BMO_op_finish(bm, &op_dupe);
+ BMO_op_finish(bm, &op_bisect);
- /* Cleanup */
- BMO_op_finish(bm, &op_weld);
-
- BMO_op_finish(bm, &op_dupe);
- BMO_op_finish(bm, &op_bisect);
-
- /* Create output */
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_ALL_NOLOOP, ELE_OUT);
+ /* Create output */
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_ALL_NOLOOP, ELE_OUT);
}
diff --git a/source/blender/bmesh/operators/bmo_triangulate.c b/source/blender/bmesh/operators/bmo_triangulate.c
index 35f5c40a213..f2a4f85acf9 100644
--- a/source/blender/bmesh/operators/bmo_triangulate.c
+++ b/source/blender/bmesh/operators/bmo_triangulate.c
@@ -32,240 +32,241 @@
#include "bmesh_tools.h"
#include "intern/bmesh_operators_private.h"
-
-#define ELE_NEW 1
-#define EDGE_MARK 4
+#define ELE_NEW 1
+#define EDGE_MARK 4
void bmo_triangulate_exec(BMesh *bm, BMOperator *op)
{
- const int quad_method = BMO_slot_int_get(op->slots_in, "quad_method");
- const int ngon_method = BMO_slot_int_get(op->slots_in, "ngon_method");
-
- BMOpSlot *slot_facemap_out = BMO_slot_get(op->slots_out, "face_map.out");
- BMOpSlot *slot_facemap_double_out = BMO_slot_get(op->slots_out, "face_map_double.out");
+ const int quad_method = BMO_slot_int_get(op->slots_in, "quad_method");
+ const int ngon_method = BMO_slot_int_get(op->slots_in, "ngon_method");
- BM_mesh_elem_hflag_disable_all(bm, BM_FACE | BM_EDGE, BM_ELEM_TAG, false);
- BMO_slot_buffer_hflag_enable(bm, op->slots_in, "faces", BM_FACE, BM_ELEM_TAG, false);
+ BMOpSlot *slot_facemap_out = BMO_slot_get(op->slots_out, "face_map.out");
+ BMOpSlot *slot_facemap_double_out = BMO_slot_get(op->slots_out, "face_map_double.out");
- BM_mesh_triangulate(bm, quad_method, ngon_method, 4, true, op, slot_facemap_out, slot_facemap_double_out);
+ BM_mesh_elem_hflag_disable_all(bm, BM_FACE | BM_EDGE, BM_ELEM_TAG, false);
+ BMO_slot_buffer_hflag_enable(bm, op->slots_in, "faces", BM_FACE, BM_ELEM_TAG, false);
- BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "edges.out", BM_EDGE, BM_ELEM_TAG);
- BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG);
+ BM_mesh_triangulate(
+ bm, quad_method, ngon_method, 4, true, op, slot_facemap_out, slot_facemap_double_out);
+ BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "edges.out", BM_EDGE, BM_ELEM_TAG);
+ BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG);
}
struct SortNormal {
- float value; /* keep first */
- float no[3];
+ float value; /* keep first */
+ float no[3];
};
void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op)
{
- const bool use_beauty = BMO_slot_bool_get(op->slots_in, "use_beauty");
- const bool use_dissolve = BMO_slot_bool_get(op->slots_in, "use_dissolve");
- BMOIter siter;
- BMEdge *e;
- ScanFillContext sf_ctx;
- /* ScanFillEdge *sf_edge; */ /* UNUSED */
- ScanFillFace *sf_tri;
- GHash *sf_vert_map;
- float normal[3];
- const int scanfill_flag = BLI_SCANFILL_CALC_HOLES | BLI_SCANFILL_CALC_POLYS | BLI_SCANFILL_CALC_LOOSE;
- uint nors_tot;
- bool calc_winding = false;
-
- sf_vert_map = BLI_ghash_ptr_new_ex(__func__, BMO_slot_buffer_count(op->slots_in, "edges"));
-
- BMO_slot_vec_get(op->slots_in, "normal", normal);
-
- BLI_scanfill_begin(&sf_ctx);
-
- BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
- ScanFillVert *sf_verts[2];
- BMVert **e_verts = &e->v1;
- uint i;
-
- BMO_edge_flag_enable(bm, e, EDGE_MARK);
-
- calc_winding = (calc_winding || BM_edge_is_boundary(e));
-
- for (i = 0; i < 2; i++) {
- if ((sf_verts[i] = BLI_ghash_lookup(sf_vert_map, e_verts[i])) == NULL) {
- sf_verts[i] = BLI_scanfill_vert_add(&sf_ctx, e_verts[i]->co);
- sf_verts[i]->tmp.p = e_verts[i];
- BLI_ghash_insert(sf_vert_map, e_verts[i], sf_verts[i]);
- }
- }
-
- /* sf_edge = */ BLI_scanfill_edge_add(&sf_ctx, UNPACK2(sf_verts));
- /* sf_edge->tmp.p = e; */ /* UNUSED */
- }
- nors_tot = BLI_ghash_len(sf_vert_map);
- BLI_ghash_free(sf_vert_map, NULL, NULL);
-
-
- if (is_zero_v3(normal)) {
- /* calculate the normal from the cross product of vert-edge pairs.
- * Since we don't know winding, just accumulate */
- ScanFillVert *sf_vert;
- struct SortNormal *nors;
- uint i;
- bool is_degenerate = true;
-
- nors = MEM_mallocN(sizeof(*nors) * nors_tot, __func__);
-
- for (sf_vert = sf_ctx.fillvertbase.first, i = 0; sf_vert; sf_vert = sf_vert->next, i++) {
- BMVert *v = sf_vert->tmp.p;
- BMIter eiter;
- BMEdge *e_pair[2];
- uint e_index = 0;
-
- nors[i].value = -1.0f;
-
- /* only use if 'is_degenerate' stays true */
- add_v3_v3(normal, v->no);
-
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- if (BMO_edge_flag_test(bm, e, EDGE_MARK)) {
- if (e_index == 2) {
- e_index = 0;
- break;
- }
- e_pair[e_index++] = e;
- }
- }
-
- if (e_index == 2) {
- float dir_a[3], dir_b[3];
-
- is_degenerate = false;
-
- sub_v3_v3v3(dir_a, v->co, BM_edge_other_vert(e_pair[0], v)->co);
- sub_v3_v3v3(dir_b, v->co, BM_edge_other_vert(e_pair[1], v)->co);
-
- cross_v3_v3v3(nors[i].no, dir_a, dir_b);
- nors[i].value = len_squared_v3(nors[i].no);
-
- /* only to get deterministic behavior (for initial normal) */
- if (len_squared_v3(dir_a) > len_squared_v3(dir_b)) {
- negate_v3(nors[i].no);
- }
- }
- }
-
- if (UNLIKELY(is_degenerate)) {
- /* no vertices have 2 edges?
- * in this case fall back to the average vertex normals */
- }
- else {
- qsort(nors, nors_tot, sizeof(*nors), BLI_sortutil_cmp_float_reverse);
-
- copy_v3_v3(normal, nors[0].no);
- for (i = 0; i < nors_tot; i++) {
- if (UNLIKELY(nors[i].value == -1.0f)) {
- break;
- }
- if (dot_v3v3(normal, nors[i].no) < 0.0f) {
- negate_v3(nors[i].no);
- }
- add_v3_v3(normal, nors[i].no);
- }
- normalize_v3(normal);
- }
-
- MEM_freeN(nors);
- }
- else {
- calc_winding = false;
- }
-
- /* in this case we almost certainly have degenerate geometry,
- * better set a fallback value as a last resort */
- if (UNLIKELY(normalize_v3(normal) == 0.0f)) {
- normal[2] = 1.0f;
- }
-
- BLI_scanfill_calc_ex(&sf_ctx, scanfill_flag, normal);
-
-
- /* if we have existing faces, base winding on those */
- if (calc_winding) {
- int winding_votes = 0;
- for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
- BMVert *v_tri[3] = {sf_tri->v1->tmp.p, sf_tri->v2->tmp.p, sf_tri->v3->tmp.p};
- uint i, i_prev;
-
- for (i = 0, i_prev = 2; i < 3; i_prev = i++) {
- e = BM_edge_exists(v_tri[i], v_tri[i_prev]);
- if (e && BM_edge_is_boundary(e) && BMO_edge_flag_test(bm, e, EDGE_MARK)) {
- winding_votes += (e->l->v == v_tri[i]) ? 1 : -1;
- }
- }
- }
-
- if (winding_votes < 0) {
- for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
- SWAP(struct ScanFillVert *, sf_tri->v2, sf_tri->v3);
- }
- }
- }
-
-
- for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
- BMFace *f;
- BMLoop *l;
- BMIter liter;
-
- f = BM_face_create_quad_tri(bm,
- sf_tri->v1->tmp.p, sf_tri->v2->tmp.p, sf_tri->v3->tmp.p, NULL,
- NULL, BM_CREATE_NO_DOUBLE);
-
- BMO_face_flag_enable(bm, f, ELE_NEW);
- BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- if (!BMO_edge_flag_test(bm, l->e, EDGE_MARK)) {
- BMO_edge_flag_enable(bm, l->e, ELE_NEW);
- }
- }
- }
-
- BLI_scanfill_end(&sf_ctx);
-
- if (use_beauty) {
- BMOperator bmop;
-
- BMO_op_initf(bm, &bmop, op->flag, "beautify_fill faces=%ff edges=%Fe", ELE_NEW, EDGE_MARK);
- BMO_op_exec(bm, &bmop);
- BMO_slot_buffer_flag_enable(bm, bmop.slots_out, "geom.out", BM_FACE | BM_EDGE, ELE_NEW);
- BMO_op_finish(bm, &bmop);
- }
-
- if (use_dissolve) {
- BMEdge *e_next;
- BMIter iter;
-
- BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) {
- if (BMO_edge_flag_test(bm, e, ELE_NEW)) {
- /* in rare cases the edges face will have already been removed from the edge */
- if (LIKELY(BM_edge_is_manifold(e))) {
- BMFace *f_new = BM_faces_join_pair(bm, e->l, e->l->radial_next, false);
- if (f_new) {
- BMO_face_flag_enable(bm, f_new, ELE_NEW);
- BM_edge_kill(bm, e);
- }
- else {
- BMO_error_clear(bm);
- }
- }
- else if (e->l == NULL) {
- BM_edge_kill(bm, e);
- }
- else {
- /* Edges with 1 or 3+ faces attached,
- * most likely caused by a degenerate mesh. */
- }
- }
- }
- }
-
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_EDGE | BM_FACE, ELE_NEW);
+ const bool use_beauty = BMO_slot_bool_get(op->slots_in, "use_beauty");
+ const bool use_dissolve = BMO_slot_bool_get(op->slots_in, "use_dissolve");
+ BMOIter siter;
+ BMEdge *e;
+ ScanFillContext sf_ctx;
+ /* ScanFillEdge *sf_edge; */ /* UNUSED */
+ ScanFillFace *sf_tri;
+ GHash *sf_vert_map;
+ float normal[3];
+ const int scanfill_flag = BLI_SCANFILL_CALC_HOLES | BLI_SCANFILL_CALC_POLYS |
+ BLI_SCANFILL_CALC_LOOSE;
+ uint nors_tot;
+ bool calc_winding = false;
+
+ sf_vert_map = BLI_ghash_ptr_new_ex(__func__, BMO_slot_buffer_count(op->slots_in, "edges"));
+
+ BMO_slot_vec_get(op->slots_in, "normal", normal);
+
+ BLI_scanfill_begin(&sf_ctx);
+
+ BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) {
+ ScanFillVert *sf_verts[2];
+ BMVert **e_verts = &e->v1;
+ uint i;
+
+ BMO_edge_flag_enable(bm, e, EDGE_MARK);
+
+ calc_winding = (calc_winding || BM_edge_is_boundary(e));
+
+ for (i = 0; i < 2; i++) {
+ if ((sf_verts[i] = BLI_ghash_lookup(sf_vert_map, e_verts[i])) == NULL) {
+ sf_verts[i] = BLI_scanfill_vert_add(&sf_ctx, e_verts[i]->co);
+ sf_verts[i]->tmp.p = e_verts[i];
+ BLI_ghash_insert(sf_vert_map, e_verts[i], sf_verts[i]);
+ }
+ }
+
+ /* sf_edge = */ BLI_scanfill_edge_add(&sf_ctx, UNPACK2(sf_verts));
+ /* sf_edge->tmp.p = e; */ /* UNUSED */
+ }
+ nors_tot = BLI_ghash_len(sf_vert_map);
+ BLI_ghash_free(sf_vert_map, NULL, NULL);
+
+ if (is_zero_v3(normal)) {
+ /* calculate the normal from the cross product of vert-edge pairs.
+ * Since we don't know winding, just accumulate */
+ ScanFillVert *sf_vert;
+ struct SortNormal *nors;
+ uint i;
+ bool is_degenerate = true;
+
+ nors = MEM_mallocN(sizeof(*nors) * nors_tot, __func__);
+
+ for (sf_vert = sf_ctx.fillvertbase.first, i = 0; sf_vert; sf_vert = sf_vert->next, i++) {
+ BMVert *v = sf_vert->tmp.p;
+ BMIter eiter;
+ BMEdge *e_pair[2];
+ uint e_index = 0;
+
+ nors[i].value = -1.0f;
+
+ /* only use if 'is_degenerate' stays true */
+ add_v3_v3(normal, v->no);
+
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (BMO_edge_flag_test(bm, e, EDGE_MARK)) {
+ if (e_index == 2) {
+ e_index = 0;
+ break;
+ }
+ e_pair[e_index++] = e;
+ }
+ }
+
+ if (e_index == 2) {
+ float dir_a[3], dir_b[3];
+
+ is_degenerate = false;
+
+ sub_v3_v3v3(dir_a, v->co, BM_edge_other_vert(e_pair[0], v)->co);
+ sub_v3_v3v3(dir_b, v->co, BM_edge_other_vert(e_pair[1], v)->co);
+
+ cross_v3_v3v3(nors[i].no, dir_a, dir_b);
+ nors[i].value = len_squared_v3(nors[i].no);
+
+ /* only to get deterministic behavior (for initial normal) */
+ if (len_squared_v3(dir_a) > len_squared_v3(dir_b)) {
+ negate_v3(nors[i].no);
+ }
+ }
+ }
+
+ if (UNLIKELY(is_degenerate)) {
+ /* no vertices have 2 edges?
+ * in this case fall back to the average vertex normals */
+ }
+ else {
+ qsort(nors, nors_tot, sizeof(*nors), BLI_sortutil_cmp_float_reverse);
+
+ copy_v3_v3(normal, nors[0].no);
+ for (i = 0; i < nors_tot; i++) {
+ if (UNLIKELY(nors[i].value == -1.0f)) {
+ break;
+ }
+ if (dot_v3v3(normal, nors[i].no) < 0.0f) {
+ negate_v3(nors[i].no);
+ }
+ add_v3_v3(normal, nors[i].no);
+ }
+ normalize_v3(normal);
+ }
+
+ MEM_freeN(nors);
+ }
+ else {
+ calc_winding = false;
+ }
+
+ /* in this case we almost certainly have degenerate geometry,
+ * better set a fallback value as a last resort */
+ if (UNLIKELY(normalize_v3(normal) == 0.0f)) {
+ normal[2] = 1.0f;
+ }
+
+ BLI_scanfill_calc_ex(&sf_ctx, scanfill_flag, normal);
+
+ /* if we have existing faces, base winding on those */
+ if (calc_winding) {
+ int winding_votes = 0;
+ for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
+ BMVert *v_tri[3] = {sf_tri->v1->tmp.p, sf_tri->v2->tmp.p, sf_tri->v3->tmp.p};
+ uint i, i_prev;
+
+ for (i = 0, i_prev = 2; i < 3; i_prev = i++) {
+ e = BM_edge_exists(v_tri[i], v_tri[i_prev]);
+ if (e && BM_edge_is_boundary(e) && BMO_edge_flag_test(bm, e, EDGE_MARK)) {
+ winding_votes += (e->l->v == v_tri[i]) ? 1 : -1;
+ }
+ }
+ }
+
+ if (winding_votes < 0) {
+ for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
+ SWAP(struct ScanFillVert *, sf_tri->v2, sf_tri->v3);
+ }
+ }
+ }
+
+ for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
+ BMFace *f;
+ BMLoop *l;
+ BMIter liter;
+
+ f = BM_face_create_quad_tri(bm,
+ sf_tri->v1->tmp.p,
+ sf_tri->v2->tmp.p,
+ sf_tri->v3->tmp.p,
+ NULL,
+ NULL,
+ BM_CREATE_NO_DOUBLE);
+
+ BMO_face_flag_enable(bm, f, ELE_NEW);
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ if (!BMO_edge_flag_test(bm, l->e, EDGE_MARK)) {
+ BMO_edge_flag_enable(bm, l->e, ELE_NEW);
+ }
+ }
+ }
+
+ BLI_scanfill_end(&sf_ctx);
+
+ if (use_beauty) {
+ BMOperator bmop;
+
+ BMO_op_initf(bm, &bmop, op->flag, "beautify_fill faces=%ff edges=%Fe", ELE_NEW, EDGE_MARK);
+ BMO_op_exec(bm, &bmop);
+ BMO_slot_buffer_flag_enable(bm, bmop.slots_out, "geom.out", BM_FACE | BM_EDGE, ELE_NEW);
+ BMO_op_finish(bm, &bmop);
+ }
+
+ if (use_dissolve) {
+ BMEdge *e_next;
+ BMIter iter;
+
+ BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BMO_edge_flag_test(bm, e, ELE_NEW)) {
+ /* in rare cases the edges face will have already been removed from the edge */
+ if (LIKELY(BM_edge_is_manifold(e))) {
+ BMFace *f_new = BM_faces_join_pair(bm, e->l, e->l->radial_next, false);
+ if (f_new) {
+ BMO_face_flag_enable(bm, f_new, ELE_NEW);
+ BM_edge_kill(bm, e);
+ }
+ else {
+ BMO_error_clear(bm);
+ }
+ }
+ else if (e->l == NULL) {
+ BM_edge_kill(bm, e);
+ }
+ else {
+ /* Edges with 1 or 3+ faces attached,
+ * most likely caused by a degenerate mesh. */
+ }
+ }
+ }
+ }
+
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_EDGE | BM_FACE, ELE_NEW);
}
diff --git a/source/blender/bmesh/operators/bmo_unsubdivide.c b/source/blender/bmesh/operators/bmo_unsubdivide.c
index cd95cda3088..c5de6df34a7 100644
--- a/source/blender/bmesh/operators/bmo_unsubdivide.c
+++ b/source/blender/bmesh/operators/bmo_unsubdivide.c
@@ -34,24 +34,24 @@
*/
void bmo_unsubdivide_exec(BMesh *bm, BMOperator *op)
{
- BMVert *v;
- BMIter iter;
-
- const int iterations = max_ii(1, BMO_slot_int_get(op->slots_in, "iterations"));
-
- BMOpSlot *vinput = BMO_slot_get(op->slots_in, "verts");
- BMVert **vinput_arr = (BMVert **)vinput->data.buf;
- int v_index;
-
- /* tag verts */
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- BM_elem_flag_disable(v, BM_ELEM_TAG);
- }
- for (v_index = 0; v_index < vinput->len; v_index++) {
- v = vinput_arr[v_index];
- BM_elem_flag_enable(v, BM_ELEM_TAG);
- }
-
- /* do all the real work here */
- BM_mesh_decimate_unsubdivide_ex(bm, iterations, true);
+ BMVert *v;
+ BMIter iter;
+
+ const int iterations = max_ii(1, BMO_slot_int_get(op->slots_in, "iterations"));
+
+ BMOpSlot *vinput = BMO_slot_get(op->slots_in, "verts");
+ BMVert **vinput_arr = (BMVert **)vinput->data.buf;
+ int v_index;
+
+ /* tag verts */
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_elem_flag_disable(v, BM_ELEM_TAG);
+ }
+ for (v_index = 0; v_index < vinput->len; v_index++) {
+ v = vinput_arr[v_index];
+ BM_elem_flag_enable(v, BM_ELEM_TAG);
+ }
+
+ /* do all the real work here */
+ BM_mesh_decimate_unsubdivide_ex(bm, iterations, true);
}
diff --git a/source/blender/bmesh/operators/bmo_utils.c b/source/blender/bmesh/operators/bmo_utils.c
index 2439b5fe2b2..6495f2b0afe 100644
--- a/source/blender/bmesh/operators/bmo_utils.c
+++ b/source/blender/bmesh/operators/bmo_utils.c
@@ -38,396 +38,391 @@
void bmo_create_vert_exec(BMesh *bm, BMOperator *op)
{
- float vec[3];
+ float vec[3];
- BMO_slot_vec_get(op->slots_in, "co", vec);
+ BMO_slot_vec_get(op->slots_in, "co", vec);
- BMO_vert_flag_enable(bm, BM_vert_create(bm, vec, NULL, BM_CREATE_NOP), ELE_NEW);
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "vert.out", BM_VERT, ELE_NEW);
+ BMO_vert_flag_enable(bm, BM_vert_create(bm, vec, NULL, BM_CREATE_NOP), ELE_NEW);
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "vert.out", BM_VERT, ELE_NEW);
}
void bmo_transform_exec(BMesh *UNUSED(bm), BMOperator *op)
{
- BMOIter iter;
- BMVert *v;
- float mat[4][4], mat_space[4][4], imat_space[4][4];
+ BMOIter iter;
+ BMVert *v;
+ float mat[4][4], mat_space[4][4], imat_space[4][4];
- BMO_slot_mat4_get(op->slots_in, "matrix", mat);
- BMO_slot_mat4_get(op->slots_in, "space", mat_space);
+ BMO_slot_mat4_get(op->slots_in, "matrix", mat);
+ BMO_slot_mat4_get(op->slots_in, "space", mat_space);
- if (!is_zero_m4(mat_space)) {
- invert_m4_m4(imat_space, mat_space);
- mul_m4_series(mat, imat_space, mat, mat_space);
- }
+ if (!is_zero_m4(mat_space)) {
+ invert_m4_m4(imat_space, mat_space);
+ mul_m4_series(mat, imat_space, mat, mat_space);
+ }
- BMO_ITER (v, &iter, op->slots_in, "verts", BM_VERT) {
- mul_m4_v3(mat, v->co);
- }
+ BMO_ITER (v, &iter, op->slots_in, "verts", BM_VERT) {
+ mul_m4_v3(mat, v->co);
+ }
}
void bmo_translate_exec(BMesh *bm, BMOperator *op)
{
- float mat[4][4], vec[3];
+ float mat[4][4], vec[3];
- BMO_slot_vec_get(op->slots_in, "vec", vec);
+ BMO_slot_vec_get(op->slots_in, "vec", vec);
- unit_m4(mat);
- copy_v3_v3(mat[3], vec);
+ unit_m4(mat);
+ copy_v3_v3(mat[3], vec);
- BMO_op_callf(bm, op->flag, "transform matrix=%m4 space=%s verts=%s", mat, op, "space", op, "verts");
+ BMO_op_callf(
+ bm, op->flag, "transform matrix=%m4 space=%s verts=%s", mat, op, "space", op, "verts");
}
void bmo_scale_exec(BMesh *bm, BMOperator *op)
{
- float mat[3][3], vec[3];
+ float mat[3][3], vec[3];
- BMO_slot_vec_get(op->slots_in, "vec", vec);
+ BMO_slot_vec_get(op->slots_in, "vec", vec);
- unit_m3(mat);
- mat[0][0] = vec[0];
- mat[1][1] = vec[1];
- mat[2][2] = vec[2];
+ unit_m3(mat);
+ mat[0][0] = vec[0];
+ mat[1][1] = vec[1];
+ mat[2][2] = vec[2];
- BMO_op_callf(bm, op->flag, "transform matrix=%m3 space=%s verts=%s", mat, op, "space", op, "verts");
+ BMO_op_callf(
+ bm, op->flag, "transform matrix=%m3 space=%s verts=%s", mat, op, "space", op, "verts");
}
void bmo_rotate_exec(BMesh *bm, BMOperator *op)
{
- float center[3];
- float mat[4][4];
+ float center[3];
+ float mat[4][4];
- BMO_slot_vec_get(op->slots_in, "cent", center);
- BMO_slot_mat4_get(op->slots_in, "matrix", mat);
- transform_pivot_set_m4(mat, center);
+ BMO_slot_vec_get(op->slots_in, "cent", center);
+ BMO_slot_mat4_get(op->slots_in, "matrix", mat);
+ transform_pivot_set_m4(mat, center);
- BMO_op_callf(bm, op->flag, "transform matrix=%m4 space=%s verts=%s", mat, op, "space", op, "verts");
+ BMO_op_callf(
+ bm, op->flag, "transform matrix=%m4 space=%s verts=%s", mat, op, "space", op, "verts");
}
void bmo_reverse_faces_exec(BMesh *bm, BMOperator *op)
{
- const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
- const bool use_loop_mdisp_flip = BMO_slot_bool_get(op->slots_in, "flip_multires");
- BMOIter siter;
- BMFace *f;
-
- BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) {
- BM_face_normal_flip_ex(bm, f, cd_loop_mdisp_offset, use_loop_mdisp_flip);
- }
+ const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
+ const bool use_loop_mdisp_flip = BMO_slot_bool_get(op->slots_in, "flip_multires");
+ BMOIter siter;
+ BMFace *f;
+
+ BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) {
+ BM_face_normal_flip_ex(bm, f, cd_loop_mdisp_offset, use_loop_mdisp_flip);
+ }
}
-
-#define SEL_FLAG 1
-#define SEL_ORIG 2
+#define SEL_FLAG 1
+#define SEL_ORIG 2
static void bmo_face_flag_set_flush(BMesh *bm, BMFace *f, const short oflag, const bool value)
{
- BMLoop *l_iter;
- BMLoop *l_first;
-
- BMO_face_flag_set(bm, f, oflag, value);
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- BMO_edge_flag_set(bm, l_iter->e, oflag, value);
- BMO_vert_flag_set(bm, l_iter->v, oflag, value);
- } while ((l_iter = l_iter->next) != l_first);
+ BMLoop *l_iter;
+ BMLoop *l_first;
+
+ BMO_face_flag_set(bm, f, oflag, value);
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BMO_edge_flag_set(bm, l_iter->e, oflag, value);
+ BMO_vert_flag_set(bm, l_iter->v, oflag, value);
+ } while ((l_iter = l_iter->next) != l_first);
}
-
-static void bmo_region_extend_expand(
- BMesh *bm, BMOperator *op,
- const bool use_faces, const bool use_faces_step)
+static void bmo_region_extend_expand(BMesh *bm,
+ BMOperator *op,
+ const bool use_faces,
+ const bool use_faces_step)
{
- BMOIter siter;
-
- if (!use_faces) {
- BMVert *v;
-
- BMO_ITER (v, &siter, op->slots_in, "geom", BM_VERT) {
- bool found = false;
-
- {
- BMIter eiter;
- BMEdge *e;
-
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- if (!BMO_edge_flag_test(bm, e, SEL_ORIG) &&
- !BM_elem_flag_test(e, BM_ELEM_HIDDEN))
- {
- found = true;
- break;
- }
- }
- }
-
- if (found) {
- if (!use_faces_step) {
- BMIter eiter;
- BMEdge *e;
-
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- if (!BMO_edge_flag_test(bm, e, SEL_FLAG) &&
- !BM_elem_flag_test(e, BM_ELEM_HIDDEN))
- {
- BMO_edge_flag_enable(bm, e, SEL_FLAG);
- BMO_vert_flag_enable(bm, BM_edge_other_vert(e, v), SEL_FLAG);
- }
- }
- }
- else {
- BMIter fiter;
- BMFace *f;
-
- BM_ITER_ELEM (f, &fiter, v, BM_FACES_OF_VERT) {
- if (!BMO_face_flag_test(bm, f, SEL_FLAG) &&
- !BM_elem_flag_test(f, BM_ELEM_HIDDEN))
- {
- bmo_face_flag_set_flush(bm, f, SEL_FLAG, true);
- }
- }
-
- /* handle wire edges (when stepping over faces) */
- {
- BMIter eiter;
- BMEdge *e;
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- if (BM_edge_is_wire(e)) {
- if (!BMO_edge_flag_test(bm, e, SEL_FLAG) &&
- !BM_elem_flag_test(e, BM_ELEM_HIDDEN))
- {
- BMO_edge_flag_enable(bm, e, SEL_FLAG);
- BMO_vert_flag_enable(bm, BM_edge_other_vert(e, v), SEL_FLAG);
- }
- }
- }
- }
- }
- }
- }
- }
- else {
- BMFace *f;
-
- BMO_ITER (f, &siter, op->slots_in, "geom", BM_FACE) {
- BMIter liter;
- BMLoop *l;
-
- BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- if (!use_faces_step) {
- BMIter fiter;
- BMFace *f_other;
-
- BM_ITER_ELEM (f_other, &fiter, l->e, BM_FACES_OF_EDGE) {
- if (!BMO_face_flag_test(bm, f_other, SEL_ORIG | SEL_FLAG) &&
- !BM_elem_flag_test(f_other, BM_ELEM_HIDDEN))
- {
- BMO_face_flag_enable(bm, f_other, SEL_FLAG);
- }
- }
- }
- else {
- BMIter fiter;
- BMFace *f_other;
-
- BM_ITER_ELEM (f_other, &fiter, l->v, BM_FACES_OF_VERT) {
- if (!BMO_face_flag_test(bm, f_other, SEL_ORIG | SEL_FLAG) &&
- !BM_elem_flag_test(f_other, BM_ELEM_HIDDEN))
- {
- BMO_face_flag_enable(bm, f_other, SEL_FLAG);
- }
- }
- }
- }
- }
- }
+ BMOIter siter;
+
+ if (!use_faces) {
+ BMVert *v;
+
+ BMO_ITER (v, &siter, op->slots_in, "geom", BM_VERT) {
+ bool found = false;
+
+ {
+ BMIter eiter;
+ BMEdge *e;
+
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (!BMO_edge_flag_test(bm, e, SEL_ORIG) && !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (found) {
+ if (!use_faces_step) {
+ BMIter eiter;
+ BMEdge *e;
+
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (!BMO_edge_flag_test(bm, e, SEL_FLAG) && !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
+ BMO_edge_flag_enable(bm, e, SEL_FLAG);
+ BMO_vert_flag_enable(bm, BM_edge_other_vert(e, v), SEL_FLAG);
+ }
+ }
+ }
+ else {
+ BMIter fiter;
+ BMFace *f;
+
+ BM_ITER_ELEM (f, &fiter, v, BM_FACES_OF_VERT) {
+ if (!BMO_face_flag_test(bm, f, SEL_FLAG) && !BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+ bmo_face_flag_set_flush(bm, f, SEL_FLAG, true);
+ }
+ }
+
+ /* handle wire edges (when stepping over faces) */
+ {
+ BMIter eiter;
+ BMEdge *e;
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (BM_edge_is_wire(e)) {
+ if (!BMO_edge_flag_test(bm, e, SEL_FLAG) &&
+ !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
+ BMO_edge_flag_enable(bm, e, SEL_FLAG);
+ BMO_vert_flag_enable(bm, BM_edge_other_vert(e, v), SEL_FLAG);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else {
+ BMFace *f;
+
+ BMO_ITER (f, &siter, op->slots_in, "geom", BM_FACE) {
+ BMIter liter;
+ BMLoop *l;
+
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ if (!use_faces_step) {
+ BMIter fiter;
+ BMFace *f_other;
+
+ BM_ITER_ELEM (f_other, &fiter, l->e, BM_FACES_OF_EDGE) {
+ if (!BMO_face_flag_test(bm, f_other, SEL_ORIG | SEL_FLAG) &&
+ !BM_elem_flag_test(f_other, BM_ELEM_HIDDEN)) {
+ BMO_face_flag_enable(bm, f_other, SEL_FLAG);
+ }
+ }
+ }
+ else {
+ BMIter fiter;
+ BMFace *f_other;
+
+ BM_ITER_ELEM (f_other, &fiter, l->v, BM_FACES_OF_VERT) {
+ if (!BMO_face_flag_test(bm, f_other, SEL_ORIG | SEL_FLAG) &&
+ !BM_elem_flag_test(f_other, BM_ELEM_HIDDEN)) {
+ BMO_face_flag_enable(bm, f_other, SEL_FLAG);
+ }
+ }
+ }
+ }
+ }
+ }
}
-static void bmo_region_extend_contract(
- BMesh *bm, BMOperator *op,
- const bool use_faces, const bool use_faces_step)
+static void bmo_region_extend_contract(BMesh *bm,
+ BMOperator *op,
+ const bool use_faces,
+ const bool use_faces_step)
{
- BMOIter siter;
-
- if (!use_faces) {
- BMVert *v;
-
- BMO_ITER (v, &siter, op->slots_in, "geom", BM_VERT) {
- bool found = false;
-
- if (!use_faces_step) {
- BMIter eiter;
- BMEdge *e;
-
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- if (!BMO_edge_flag_test(bm, e, SEL_ORIG)) {
- found = true;
- break;
- }
- }
- }
- else {
- BMIter fiter;
- BMFace *f;
-
- BM_ITER_ELEM (f, &fiter, v, BM_FACES_OF_VERT) {
- if (!BMO_face_flag_test(bm, f, SEL_ORIG)) {
- found = true;
- break;
- }
- }
-
- /* handle wire edges (when stepping over faces) */
- if (!found) {
- BMIter eiter;
- BMEdge *e;
-
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- if (BM_edge_is_wire(e)) {
- if (!BMO_edge_flag_test(bm, e, SEL_ORIG)) {
- found = true;
- break;
- }
- }
- }
- }
- }
-
- if (found) {
- BMIter eiter;
- BMEdge *e;
-
- BMO_vert_flag_enable(bm, v, SEL_FLAG);
-
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- BMO_edge_flag_enable(bm, e, SEL_FLAG);
- }
- }
- }
- }
- else {
- BMFace *f;
-
- BMO_ITER (f, &siter, op->slots_in, "geom", BM_FACE) {
- BMIter liter;
- BMLoop *l;
-
- BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
-
- if (!use_faces_step) {
- BMIter fiter;
- BMFace *f_other;
-
- BM_ITER_ELEM (f_other, &fiter, l->e, BM_FACES_OF_EDGE) {
- if (!BMO_face_flag_test(bm, f_other, SEL_ORIG)) {
- BMO_face_flag_enable(bm, f, SEL_FLAG);
- break;
- }
- }
- }
- else {
- BMIter fiter;
- BMFace *f_other;
-
- BM_ITER_ELEM (f_other, &fiter, l->v, BM_FACES_OF_VERT) {
- if (!BMO_face_flag_test(bm, f_other, SEL_ORIG)) {
- BMO_face_flag_enable(bm, f, SEL_FLAG);
- break;
- }
- }
- }
- }
- }
- }
+ BMOIter siter;
+
+ if (!use_faces) {
+ BMVert *v;
+
+ BMO_ITER (v, &siter, op->slots_in, "geom", BM_VERT) {
+ bool found = false;
+
+ if (!use_faces_step) {
+ BMIter eiter;
+ BMEdge *e;
+
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (!BMO_edge_flag_test(bm, e, SEL_ORIG)) {
+ found = true;
+ break;
+ }
+ }
+ }
+ else {
+ BMIter fiter;
+ BMFace *f;
+
+ BM_ITER_ELEM (f, &fiter, v, BM_FACES_OF_VERT) {
+ if (!BMO_face_flag_test(bm, f, SEL_ORIG)) {
+ found = true;
+ break;
+ }
+ }
+
+ /* handle wire edges (when stepping over faces) */
+ if (!found) {
+ BMIter eiter;
+ BMEdge *e;
+
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (BM_edge_is_wire(e)) {
+ if (!BMO_edge_flag_test(bm, e, SEL_ORIG)) {
+ found = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (found) {
+ BMIter eiter;
+ BMEdge *e;
+
+ BMO_vert_flag_enable(bm, v, SEL_FLAG);
+
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ BMO_edge_flag_enable(bm, e, SEL_FLAG);
+ }
+ }
+ }
+ }
+ else {
+ BMFace *f;
+
+ BMO_ITER (f, &siter, op->slots_in, "geom", BM_FACE) {
+ BMIter liter;
+ BMLoop *l;
+
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+
+ if (!use_faces_step) {
+ BMIter fiter;
+ BMFace *f_other;
+
+ BM_ITER_ELEM (f_other, &fiter, l->e, BM_FACES_OF_EDGE) {
+ if (!BMO_face_flag_test(bm, f_other, SEL_ORIG)) {
+ BMO_face_flag_enable(bm, f, SEL_FLAG);
+ break;
+ }
+ }
+ }
+ else {
+ BMIter fiter;
+ BMFace *f_other;
+
+ BM_ITER_ELEM (f_other, &fiter, l->v, BM_FACES_OF_VERT) {
+ if (!BMO_face_flag_test(bm, f_other, SEL_ORIG)) {
+ BMO_face_flag_enable(bm, f, SEL_FLAG);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
}
void bmo_region_extend_exec(BMesh *bm, BMOperator *op)
{
- const bool use_faces = BMO_slot_bool_get(op->slots_in, "use_faces");
- const bool use_face_step = BMO_slot_bool_get(op->slots_in, "use_face_step");
- const bool constrict = BMO_slot_bool_get(op->slots_in, "use_contract");
+ const bool use_faces = BMO_slot_bool_get(op->slots_in, "use_faces");
+ const bool use_face_step = BMO_slot_bool_get(op->slots_in, "use_face_step");
+ const bool constrict = BMO_slot_bool_get(op->slots_in, "use_contract");
- BMO_slot_buffer_flag_enable(bm, op->slots_in, "geom", BM_ALL_NOLOOP, SEL_ORIG);
+ BMO_slot_buffer_flag_enable(bm, op->slots_in, "geom", BM_ALL_NOLOOP, SEL_ORIG);
- if (constrict) {
- bmo_region_extend_contract(bm, op, use_faces, use_face_step);
- }
- else {
- bmo_region_extend_expand(bm, op, use_faces, use_face_step);
- }
+ if (constrict) {
+ bmo_region_extend_contract(bm, op, use_faces, use_face_step);
+ }
+ else {
+ bmo_region_extend_expand(bm, op, use_faces, use_face_step);
+ }
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_ALL_NOLOOP, SEL_FLAG);
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_ALL_NOLOOP, SEL_FLAG);
}
void bmo_smooth_vert_exec(BMesh *UNUSED(bm), BMOperator *op)
{
- BMOIter siter;
- BMIter iter;
- BMVert *v;
- BMEdge *e;
- float (*cos)[3] = MEM_mallocN(sizeof(*cos) * BMO_slot_buffer_count(op->slots_in, "verts"), __func__);
- float *co, *co2, clip_dist = BMO_slot_float_get(op->slots_in, "clip_dist");
- const float fac = BMO_slot_float_get(op->slots_in, "factor");
- int i, j, clipx, clipy, clipz;
- int xaxis, yaxis, zaxis;
-
- clipx = BMO_slot_bool_get(op->slots_in, "mirror_clip_x");
- clipy = BMO_slot_bool_get(op->slots_in, "mirror_clip_y");
- clipz = BMO_slot_bool_get(op->slots_in, "mirror_clip_z");
-
- xaxis = BMO_slot_bool_get(op->slots_in, "use_axis_x");
- yaxis = BMO_slot_bool_get(op->slots_in, "use_axis_y");
- zaxis = BMO_slot_bool_get(op->slots_in, "use_axis_z");
-
- i = 0;
- BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
-
- co = cos[i];
- zero_v3(co);
-
- j = 0;
- BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
- co2 = BM_edge_other_vert(e, v)->co;
- add_v3_v3v3(co, co, co2);
- j += 1;
- }
-
- if (!j) {
- copy_v3_v3(co, v->co);
- i++;
- continue;
- }
-
- mul_v3_fl(co, 1.0f / (float)j);
- interp_v3_v3v3(co, v->co, co, fac);
-
- if (clipx && fabsf(v->co[0]) <= clip_dist) {
- co[0] = 0.0f;
- }
- if (clipy && fabsf(v->co[1]) <= clip_dist) {
- co[1] = 0.0f;
- }
- if (clipz && fabsf(v->co[2]) <= clip_dist) {
- co[2] = 0.0f;
- }
-
- i++;
- }
-
- i = 0;
- BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
- if (xaxis) {
- v->co[0] = cos[i][0];
- }
- if (yaxis) {
- v->co[1] = cos[i][1];
- }
- if (zaxis) {
- v->co[2] = cos[i][2];
- }
-
- i++;
- }
-
- MEM_freeN(cos);
+ BMOIter siter;
+ BMIter iter;
+ BMVert *v;
+ BMEdge *e;
+ float(*cos)[3] = MEM_mallocN(sizeof(*cos) * BMO_slot_buffer_count(op->slots_in, "verts"),
+ __func__);
+ float *co, *co2, clip_dist = BMO_slot_float_get(op->slots_in, "clip_dist");
+ const float fac = BMO_slot_float_get(op->slots_in, "factor");
+ int i, j, clipx, clipy, clipz;
+ int xaxis, yaxis, zaxis;
+
+ clipx = BMO_slot_bool_get(op->slots_in, "mirror_clip_x");
+ clipy = BMO_slot_bool_get(op->slots_in, "mirror_clip_y");
+ clipz = BMO_slot_bool_get(op->slots_in, "mirror_clip_z");
+
+ xaxis = BMO_slot_bool_get(op->slots_in, "use_axis_x");
+ yaxis = BMO_slot_bool_get(op->slots_in, "use_axis_y");
+ zaxis = BMO_slot_bool_get(op->slots_in, "use_axis_z");
+
+ i = 0;
+ BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
+
+ co = cos[i];
+ zero_v3(co);
+
+ j = 0;
+ BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
+ co2 = BM_edge_other_vert(e, v)->co;
+ add_v3_v3v3(co, co, co2);
+ j += 1;
+ }
+
+ if (!j) {
+ copy_v3_v3(co, v->co);
+ i++;
+ continue;
+ }
+
+ mul_v3_fl(co, 1.0f / (float)j);
+ interp_v3_v3v3(co, v->co, co, fac);
+
+ if (clipx && fabsf(v->co[0]) <= clip_dist) {
+ co[0] = 0.0f;
+ }
+ if (clipy && fabsf(v->co[1]) <= clip_dist) {
+ co[1] = 0.0f;
+ }
+ if (clipz && fabsf(v->co[2]) <= clip_dist) {
+ co[2] = 0.0f;
+ }
+
+ i++;
+ }
+
+ i = 0;
+ BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) {
+ if (xaxis) {
+ v->co[0] = cos[i][0];
+ }
+ if (yaxis) {
+ v->co[1] = cos[i][1];
+ }
+ if (zaxis) {
+ v->co[2] = cos[i][2];
+ }
+
+ i++;
+ }
+
+ MEM_freeN(cos);
}
/**************************************************************************** *
@@ -436,64 +431,64 @@ void bmo_smooth_vert_exec(BMesh *UNUSED(bm), BMOperator *op)
void bmo_rotate_uvs_exec(BMesh *bm, BMOperator *op)
{
- BMOIter fs_iter; /* selected faces iterator */
- BMFace *fs; /* current face */
- BMIter l_iter; /* iteration loop */
-
- const bool use_ccw = BMO_slot_bool_get(op->slots_in, "use_ccw");
- const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
-
- if (cd_loop_uv_offset != -1) {
- BMO_ITER (fs, &fs_iter, op->slots_in, "faces", BM_FACE) {
- if (use_ccw == false) { /* same loops direction */
- BMLoop *lf; /* current face loops */
- MLoopUV *f_luv; /* first face loop uv */
- float p_uv[2]; /* previous uvs */
- float t_uv[2]; /* tmp uvs */
-
- int n = 0;
- BM_ITER_ELEM (lf, &l_iter, fs, BM_LOOPS_OF_FACE) {
- /* current loop uv is the previous loop uv */
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(lf, cd_loop_uv_offset);
- if (n == 0) {
- f_luv = luv;
- copy_v2_v2(p_uv, luv->uv);
- }
- else {
- copy_v2_v2(t_uv, luv->uv);
- copy_v2_v2(luv->uv, p_uv);
- copy_v2_v2(p_uv, t_uv);
- }
- n++;
- }
-
- copy_v2_v2(f_luv->uv, p_uv);
- }
- else { /* counter loop direction */
- BMLoop *lf; /* current face loops */
- MLoopUV *p_luv; /* previous loop uv */
- MLoopUV *luv;
- float t_uv[2]; /* current uvs */
-
- int n = 0;
- BM_ITER_ELEM (lf, &l_iter, fs, BM_LOOPS_OF_FACE) {
- /* previous loop uv is the current loop uv */
- luv = BM_ELEM_CD_GET_VOID_P(lf, cd_loop_uv_offset);
- if (n == 0) {
- p_luv = luv;
- copy_v2_v2(t_uv, luv->uv);
- }
- else {
- copy_v2_v2(p_luv->uv, luv->uv);
- p_luv = luv;
- }
- n++;
- }
-
- copy_v2_v2(luv->uv, t_uv);
- }
- }
- }
+ BMOIter fs_iter; /* selected faces iterator */
+ BMFace *fs; /* current face */
+ BMIter l_iter; /* iteration loop */
+
+ const bool use_ccw = BMO_slot_bool_get(op->slots_in, "use_ccw");
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+
+ if (cd_loop_uv_offset != -1) {
+ BMO_ITER (fs, &fs_iter, op->slots_in, "faces", BM_FACE) {
+ if (use_ccw == false) { /* same loops direction */
+ BMLoop *lf; /* current face loops */
+ MLoopUV *f_luv; /* first face loop uv */
+ float p_uv[2]; /* previous uvs */
+ float t_uv[2]; /* tmp uvs */
+
+ int n = 0;
+ BM_ITER_ELEM (lf, &l_iter, fs, BM_LOOPS_OF_FACE) {
+ /* current loop uv is the previous loop uv */
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(lf, cd_loop_uv_offset);
+ if (n == 0) {
+ f_luv = luv;
+ copy_v2_v2(p_uv, luv->uv);
+ }
+ else {
+ copy_v2_v2(t_uv, luv->uv);
+ copy_v2_v2(luv->uv, p_uv);
+ copy_v2_v2(p_uv, t_uv);
+ }
+ n++;
+ }
+
+ copy_v2_v2(f_luv->uv, p_uv);
+ }
+ else { /* counter loop direction */
+ BMLoop *lf; /* current face loops */
+ MLoopUV *p_luv; /* previous loop uv */
+ MLoopUV *luv;
+ float t_uv[2]; /* current uvs */
+
+ int n = 0;
+ BM_ITER_ELEM (lf, &l_iter, fs, BM_LOOPS_OF_FACE) {
+ /* previous loop uv is the current loop uv */
+ luv = BM_ELEM_CD_GET_VOID_P(lf, cd_loop_uv_offset);
+ if (n == 0) {
+ p_luv = luv;
+ copy_v2_v2(t_uv, luv->uv);
+ }
+ else {
+ copy_v2_v2(p_luv->uv, luv->uv);
+ p_luv = luv;
+ }
+ n++;
+ }
+
+ copy_v2_v2(luv->uv, t_uv);
+ }
+ }
+ }
}
/**************************************************************************** *
@@ -502,35 +497,37 @@ void bmo_rotate_uvs_exec(BMesh *bm, BMOperator *op)
static void bm_face_reverse_uvs(BMFace *f, const int cd_loop_uv_offset)
{
- BMIter iter;
- BMLoop *l;
- int i;
-
- float (*uvs)[2] = BLI_array_alloca(uvs, f->len);
-
- BM_ITER_ELEM_INDEX (l, &iter, f, BM_LOOPS_OF_FACE, i) {
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- copy_v2_v2(uvs[i], luv->uv);
- }
-
- /* now that we have the uvs in the array, reverse! */
- BM_ITER_ELEM_INDEX (l, &iter, f, BM_LOOPS_OF_FACE, i) {
- /* current loop uv is the previous loop uv */
- MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- copy_v2_v2(luv->uv, uvs[(f->len - i - 1)]);
- }
+ BMIter iter;
+ BMLoop *l;
+ int i;
+
+ float(*uvs)[2] = BLI_array_alloca(uvs, f->len);
+
+ BM_ITER_ELEM_INDEX(l, &iter, f, BM_LOOPS_OF_FACE, i)
+ {
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ copy_v2_v2(uvs[i], luv->uv);
+ }
+
+ /* now that we have the uvs in the array, reverse! */
+ BM_ITER_ELEM_INDEX(l, &iter, f, BM_LOOPS_OF_FACE, i)
+ {
+ /* current loop uv is the previous loop uv */
+ MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ copy_v2_v2(luv->uv, uvs[(f->len - i - 1)]);
+ }
}
void bmo_reverse_uvs_exec(BMesh *bm, BMOperator *op)
{
- BMOIter iter;
- BMFace *f;
- const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
-
- if (cd_loop_uv_offset != -1) {
- BMO_ITER (f, &iter, op->slots_in, "faces", BM_FACE) {
- bm_face_reverse_uvs(f, cd_loop_uv_offset);
- }
- }
+ BMOIter iter;
+ BMFace *f;
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+
+ if (cd_loop_uv_offset != -1) {
+ BMO_ITER (f, &iter, op->slots_in, "faces", BM_FACE) {
+ bm_face_reverse_uvs(f, cd_loop_uv_offset);
+ }
+ }
}
/**************************************************************************** *
@@ -539,64 +536,64 @@ void bmo_reverse_uvs_exec(BMesh *bm, BMOperator *op)
void bmo_rotate_colors_exec(BMesh *bm, BMOperator *op)
{
- BMOIter fs_iter; /* selected faces iterator */
- BMFace *fs; /* current face */
- BMIter l_iter; /* iteration loop */
-
- const bool use_ccw = BMO_slot_bool_get(op->slots_in, "use_ccw");
- const int cd_loop_color_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPCOL);
-
- if (cd_loop_color_offset != -1) {
- BMO_ITER (fs, &fs_iter, op->slots_in, "faces", BM_FACE) {
- if (use_ccw == false) { /* same loops direction */
- BMLoop *lf; /* current face loops */
- MLoopCol *f_lcol; /* first face loop color */
- MLoopCol p_col; /* previous color */
- MLoopCol t_col; /* tmp color */
-
- int n = 0;
- BM_ITER_ELEM (lf, &l_iter, fs, BM_LOOPS_OF_FACE) {
- /* current loop color is the previous loop color */
- MLoopCol *lcol = BM_ELEM_CD_GET_VOID_P(lf, cd_loop_color_offset);
- if (n == 0) {
- f_lcol = lcol;
- p_col = *lcol;
- }
- else {
- t_col = *lcol;
- *lcol = p_col;
- p_col = t_col;
- }
- n++;
- }
-
- *f_lcol = p_col;
- }
- else { /* counter loop direction */
- BMLoop *lf; /* current face loops */
- MLoopCol *p_lcol; /* previous loop color */
- MLoopCol *lcol;
- MLoopCol t_col; /* current color */
-
- int n = 0;
- BM_ITER_ELEM (lf, &l_iter, fs, BM_LOOPS_OF_FACE) {
- /* previous loop color is the current loop color */
- lcol = BM_ELEM_CD_GET_VOID_P(lf, cd_loop_color_offset);
- if (n == 0) {
- p_lcol = lcol;
- t_col = *lcol;
- }
- else {
- *p_lcol = *lcol;
- p_lcol = lcol;
- }
- n++;
- }
-
- *lcol = t_col;
- }
- }
- }
+ BMOIter fs_iter; /* selected faces iterator */
+ BMFace *fs; /* current face */
+ BMIter l_iter; /* iteration loop */
+
+ const bool use_ccw = BMO_slot_bool_get(op->slots_in, "use_ccw");
+ const int cd_loop_color_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPCOL);
+
+ if (cd_loop_color_offset != -1) {
+ BMO_ITER (fs, &fs_iter, op->slots_in, "faces", BM_FACE) {
+ if (use_ccw == false) { /* same loops direction */
+ BMLoop *lf; /* current face loops */
+ MLoopCol *f_lcol; /* first face loop color */
+ MLoopCol p_col; /* previous color */
+ MLoopCol t_col; /* tmp color */
+
+ int n = 0;
+ BM_ITER_ELEM (lf, &l_iter, fs, BM_LOOPS_OF_FACE) {
+ /* current loop color is the previous loop color */
+ MLoopCol *lcol = BM_ELEM_CD_GET_VOID_P(lf, cd_loop_color_offset);
+ if (n == 0) {
+ f_lcol = lcol;
+ p_col = *lcol;
+ }
+ else {
+ t_col = *lcol;
+ *lcol = p_col;
+ p_col = t_col;
+ }
+ n++;
+ }
+
+ *f_lcol = p_col;
+ }
+ else { /* counter loop direction */
+ BMLoop *lf; /* current face loops */
+ MLoopCol *p_lcol; /* previous loop color */
+ MLoopCol *lcol;
+ MLoopCol t_col; /* current color */
+
+ int n = 0;
+ BM_ITER_ELEM (lf, &l_iter, fs, BM_LOOPS_OF_FACE) {
+ /* previous loop color is the current loop color */
+ lcol = BM_ELEM_CD_GET_VOID_P(lf, cd_loop_color_offset);
+ if (n == 0) {
+ p_lcol = lcol;
+ t_col = *lcol;
+ }
+ else {
+ *p_lcol = *lcol;
+ p_lcol = lcol;
+ }
+ n++;
+ }
+
+ *lcol = t_col;
+ }
+ }
+ }
}
/*************************************************************************** *
@@ -604,33 +601,35 @@ void bmo_rotate_colors_exec(BMesh *bm, BMOperator *op)
*************************************************************************** */
static void bm_face_reverse_colors(BMFace *f, const int cd_loop_color_offset)
{
- BMIter iter;
- BMLoop *l;
- int i;
-
- MLoopCol *cols = BLI_array_alloca(cols, f->len);
-
- BM_ITER_ELEM_INDEX (l, &iter, f, BM_LOOPS_OF_FACE, i) {
- MLoopCol *lcol = BM_ELEM_CD_GET_VOID_P(l, cd_loop_color_offset);
- cols[i] = *lcol;
- }
-
- /* now that we have the uvs in the array, reverse! */
- BM_ITER_ELEM_INDEX (l, &iter, f, BM_LOOPS_OF_FACE, i) {
- /* current loop uv is the previous loop color */
- MLoopCol *lcol = BM_ELEM_CD_GET_VOID_P(l, cd_loop_color_offset);
- *lcol = cols[(f->len - i - 1)];
- }
+ BMIter iter;
+ BMLoop *l;
+ int i;
+
+ MLoopCol *cols = BLI_array_alloca(cols, f->len);
+
+ BM_ITER_ELEM_INDEX(l, &iter, f, BM_LOOPS_OF_FACE, i)
+ {
+ MLoopCol *lcol = BM_ELEM_CD_GET_VOID_P(l, cd_loop_color_offset);
+ cols[i] = *lcol;
+ }
+
+ /* now that we have the uvs in the array, reverse! */
+ BM_ITER_ELEM_INDEX(l, &iter, f, BM_LOOPS_OF_FACE, i)
+ {
+ /* current loop uv is the previous loop color */
+ MLoopCol *lcol = BM_ELEM_CD_GET_VOID_P(l, cd_loop_color_offset);
+ *lcol = cols[(f->len - i - 1)];
+ }
}
void bmo_reverse_colors_exec(BMesh *bm, BMOperator *op)
{
- BMOIter iter;
- BMFace *f;
- const int cd_loop_color_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPCOL);
-
- if (cd_loop_color_offset != -1) {
- BMO_ITER (f, &iter, op->slots_in, "faces", BM_FACE) {
- bm_face_reverse_colors(f, cd_loop_color_offset);
- }
- }
+ BMOIter iter;
+ BMFace *f;
+ const int cd_loop_color_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPCOL);
+
+ if (cd_loop_color_offset != -1) {
+ BMO_ITER (f, &iter, op->slots_in, "faces", BM_FACE) {
+ bm_face_reverse_colors(f, cd_loop_color_offset);
+ }
+ }
}
diff --git a/source/blender/bmesh/operators/bmo_wireframe.c b/source/blender/bmesh/operators/bmo_wireframe.c
index dcce9dbfb01..dc8a8d03eef 100644
--- a/source/blender/bmesh/operators/bmo_wireframe.c
+++ b/source/blender/bmesh/operators/bmo_wireframe.c
@@ -31,32 +31,36 @@
#include "intern/bmesh_operators_private.h" /* own include */
-
void bmo_wireframe_exec(BMesh *bm, BMOperator *op)
{
- const float offset = BMO_slot_float_get(op->slots_in, "thickness");
- const float offset_fac = BMO_slot_float_get(op->slots_in, "offset");
- const bool use_replace = BMO_slot_bool_get(op->slots_in, "use_replace");
- const bool use_boundary = BMO_slot_bool_get(op->slots_in, "use_boundary");
- const bool use_even_offset = BMO_slot_bool_get(op->slots_in, "use_even_offset");
- const bool use_relative_offset = BMO_slot_bool_get(op->slots_in, "use_relative_offset");
- const bool use_crease = BMO_slot_bool_get(op->slots_in, "use_crease");
- const float crease_weight = BMO_slot_float_get(op->slots_in, "crease_weight");
-
- BM_mesh_elem_hflag_disable_all(bm, BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
- BMO_slot_buffer_hflag_enable(bm, op->slots_in, "faces", BM_FACE, BM_ELEM_TAG, false);
-
- BM_mesh_wireframe(
- bm,
- offset, offset_fac, 0.0f,
- use_replace,
- use_boundary,
- use_even_offset, use_relative_offset,
- use_crease, crease_weight,
- /* dummy vgroup */
- -1, false,
- 0, MAXMAT,
- true);
-
- BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG);
+ const float offset = BMO_slot_float_get(op->slots_in, "thickness");
+ const float offset_fac = BMO_slot_float_get(op->slots_in, "offset");
+ const bool use_replace = BMO_slot_bool_get(op->slots_in, "use_replace");
+ const bool use_boundary = BMO_slot_bool_get(op->slots_in, "use_boundary");
+ const bool use_even_offset = BMO_slot_bool_get(op->slots_in, "use_even_offset");
+ const bool use_relative_offset = BMO_slot_bool_get(op->slots_in, "use_relative_offset");
+ const bool use_crease = BMO_slot_bool_get(op->slots_in, "use_crease");
+ const float crease_weight = BMO_slot_float_get(op->slots_in, "crease_weight");
+
+ BM_mesh_elem_hflag_disable_all(bm, BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
+ BMO_slot_buffer_hflag_enable(bm, op->slots_in, "faces", BM_FACE, BM_ELEM_TAG, false);
+
+ BM_mesh_wireframe(bm,
+ offset,
+ offset_fac,
+ 0.0f,
+ use_replace,
+ use_boundary,
+ use_even_offset,
+ use_relative_offset,
+ use_crease,
+ crease_weight,
+ /* dummy vgroup */
+ -1,
+ false,
+ 0,
+ MAXMAT,
+ true);
+
+ BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG);
}