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
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')
-rw-r--r--source/blender/bmesh/CMakeLists.txt286
-rw-r--r--source/blender/bmesh/bmesh.h2
-rw-r--r--source/blender/bmesh/bmesh_class.h399
-rw-r--r--source/blender/bmesh/intern/bmesh_callback_generic.c19
-rw-r--r--source/blender/bmesh/intern/bmesh_callback_generic.h10
-rw-r--r--source/blender/bmesh/intern/bmesh_construct.c1182
-rw-r--r--source/blender/bmesh/intern/bmesh_construct.h60
-rw-r--r--source/blender/bmesh/intern/bmesh_core.c4127
-rw-r--r--source/blender/bmesh/intern/bmesh_core.h159
-rw-r--r--source/blender/bmesh/intern/bmesh_delete.c535
-rw-r--r--source/blender/bmesh/intern/bmesh_delete.h4
-rw-r--r--source/blender/bmesh/intern/bmesh_edgeloop.c1274
-rw-r--r--source/blender/bmesh/intern/bmesh_edgeloop.h83
-rw-r--r--source/blender/bmesh/intern/bmesh_error.h48
-rw-r--r--source/blender/bmesh/intern/bmesh_inline.h64
-rw-r--r--source/blender/bmesh/intern/bmesh_interp.c1823
-rw-r--r--source/blender/bmesh/intern/bmesh_interp.h84
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators.c863
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators.h246
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators_inline.h269
-rw-r--r--source/blender/bmesh/intern/bmesh_log.c1331
-rw-r--r--source/blender/bmesh/intern/bmesh_log.h4
-rw-r--r--source/blender/bmesh/intern/bmesh_marking.c2075
-rw-r--r--source/blender/bmesh/intern/bmesh_marking.h101
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.c4242
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.h125
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_conv.c1962
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_conv.h46
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_validate.c339
-rw-r--r--source/blender/bmesh/intern/bmesh_mods.c1504
-rw-r--r--source/blender/bmesh/intern/bmesh_mods.h88
-rw-r--r--source/blender/bmesh/intern/bmesh_opdefines.c2644
-rw-r--r--source/blender/bmesh/intern/bmesh_operator_api.h639
-rw-r--r--source/blender/bmesh/intern/bmesh_operator_api_inline.h230
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.c2788
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.h171
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.c2349
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.h120
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon_edgenet.c2699
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon_edgenet.h28
-rw-r--r--source/blender/bmesh/intern/bmesh_private.h58
-rw-r--r--source/blender/bmesh/intern/bmesh_query.c3274
-rw-r--r--source/blender/bmesh/intern/bmesh_query.h295
-rw-r--r--source/blender/bmesh/intern/bmesh_query_inline.h105
-rw-r--r--source/blender/bmesh/intern/bmesh_structure.c744
-rw-r--r--source/blender/bmesh/intern/bmesh_structure.h77
-rw-r--r--source/blender/bmesh/intern/bmesh_structure_inline.h50
-rw-r--r--source/blender/bmesh/intern/bmesh_walkers.c204
-rw-r--r--source/blender/bmesh/intern/bmesh_walkers.h126
-rw-r--r--source/blender/bmesh/intern/bmesh_walkers_impl.c2286
-rw-r--r--source/blender/bmesh/intern/bmesh_walkers_private.h66
-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
-rw-r--r--source/blender/bmesh/tools/bmesh_beautify.c645
-rw-r--r--source/blender/bmesh/tools/bmesh_beautify.h23
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c10981
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.h27
-rw-r--r--source/blender/bmesh/tools/bmesh_bisect_plane.c784
-rw-r--r--source/blender/bmesh/tools/bmesh_bisect_plane.h11
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate.h34
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate_collapse.c2397
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate_dissolve.c887
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c541
-rw-r--r--source/blender/bmesh/tools/bmesh_edgenet.c707
-rw-r--r--source/blender/bmesh/tools/bmesh_edgenet.h4
-rw-r--r--source/blender/bmesh/tools/bmesh_edgesplit.c195
-rw-r--r--source/blender/bmesh/tools/bmesh_edgesplit.h8
-rw-r--r--source/blender/bmesh/tools/bmesh_intersect.c2670
-rw-r--r--source/blender/bmesh/tools/bmesh_intersect.h30
-rw-r--r--source/blender/bmesh/tools/bmesh_path.c932
-rw-r--r--source/blender/bmesh/tools/bmesh_path.h37
-rw-r--r--source/blender/bmesh/tools/bmesh_path_region.c733
-rw-r--r--source/blender/bmesh/tools/bmesh_path_region.h30
-rw-r--r--source/blender/bmesh/tools/bmesh_region_match.c2183
-rw-r--r--source/blender/bmesh/tools/bmesh_region_match.h8
-rw-r--r--source/blender/bmesh/tools/bmesh_separate.c177
-rw-r--r--source/blender/bmesh/tools/bmesh_separate.h4
-rw-r--r--source/blender/bmesh/tools/bmesh_triangulate.c224
-rw-r--r--source/blender/bmesh/tools/bmesh_triangulate.h14
-rw-r--r--source/blender/bmesh/tools/bmesh_wireframe.c1078
-rw-r--r--source/blender/bmesh/tools/bmesh_wireframe.h33
117 files changed, 47177 insertions, 46600 deletions
diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt
index 04e44585a4f..4ba9d13c8a0 100644
--- a/source/blender/bmesh/CMakeLists.txt
+++ b/source/blender/bmesh/CMakeLists.txt
@@ -19,15 +19,15 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- .
- ../blenkernel
- ../blenlib
- ../blentranslation
- ../makesdna
- ../../../intern/guardedalloc
- ../../../intern/atomic
- ../../../intern/eigen
- ../../../extern/rangetree
+ .
+ ../blenkernel
+ ../blenlib
+ ../blentranslation
+ ../makesdna
+ ../../../intern/guardedalloc
+ ../../../intern/atomic
+ ../../../intern/eigen
+ ../../../extern/rangetree
)
set(INC_SYS
@@ -35,160 +35,160 @@ set(INC_SYS
)
set(SRC
- # Naming convention for BMesh operators is: bmo_*action*_*details*.c
- operators/bmo_beautify.c
- operators/bmo_bevel.c
- operators/bmo_bisect_plane.c
- operators/bmo_bridge.c
- operators/bmo_connect.c
- operators/bmo_connect_concave.c
- operators/bmo_connect_nonplanar.c
- operators/bmo_connect_pair.c
- operators/bmo_create.c
- operators/bmo_dissolve.c
- operators/bmo_dupe.c
- operators/bmo_edgenet.c
- operators/bmo_extrude.c
- operators/bmo_fill_attribute.c
- operators/bmo_fill_edgeloop.c
- operators/bmo_fill_grid.c
- operators/bmo_fill_holes.c
- operators/bmo_hull.c
- operators/bmo_inset.c
- operators/bmo_join_triangles.c
- operators/bmo_mesh_conv.c
- operators/bmo_mirror.c
- operators/bmo_normals.c
- operators/bmo_offset_edgeloops.c
- operators/bmo_planar_faces.c
- operators/bmo_poke.c
- operators/bmo_primitive.c
- operators/bmo_removedoubles.c
- operators/bmo_rotate_edges.c
- operators/bmo_smooth_laplacian.c
- operators/bmo_split_edges.c
- operators/bmo_subdivide.c
- operators/bmo_subdivide_edgering.c
- operators/bmo_symmetrize.c
- operators/bmo_triangulate.c
- operators/bmo_unsubdivide.c
- operators/bmo_utils.c
- operators/bmo_wireframe.c
+ # Naming convention for BMesh operators is: bmo_*action*_*details*.c
+ operators/bmo_beautify.c
+ operators/bmo_bevel.c
+ operators/bmo_bisect_plane.c
+ operators/bmo_bridge.c
+ operators/bmo_connect.c
+ operators/bmo_connect_concave.c
+ operators/bmo_connect_nonplanar.c
+ operators/bmo_connect_pair.c
+ operators/bmo_create.c
+ operators/bmo_dissolve.c
+ operators/bmo_dupe.c
+ operators/bmo_edgenet.c
+ operators/bmo_extrude.c
+ operators/bmo_fill_attribute.c
+ operators/bmo_fill_edgeloop.c
+ operators/bmo_fill_grid.c
+ operators/bmo_fill_holes.c
+ operators/bmo_hull.c
+ operators/bmo_inset.c
+ operators/bmo_join_triangles.c
+ operators/bmo_mesh_conv.c
+ operators/bmo_mirror.c
+ operators/bmo_normals.c
+ operators/bmo_offset_edgeloops.c
+ operators/bmo_planar_faces.c
+ operators/bmo_poke.c
+ operators/bmo_primitive.c
+ operators/bmo_removedoubles.c
+ operators/bmo_rotate_edges.c
+ operators/bmo_smooth_laplacian.c
+ operators/bmo_split_edges.c
+ operators/bmo_subdivide.c
+ operators/bmo_subdivide_edgering.c
+ operators/bmo_symmetrize.c
+ operators/bmo_triangulate.c
+ operators/bmo_unsubdivide.c
+ operators/bmo_utils.c
+ operators/bmo_wireframe.c
- intern/bmesh_callback_generic.c
- intern/bmesh_callback_generic.h
- intern/bmesh_construct.c
- intern/bmesh_construct.h
- intern/bmesh_core.c
- intern/bmesh_core.h
- intern/bmesh_delete.c
- intern/bmesh_delete.h
- intern/bmesh_edgeloop.c
- intern/bmesh_edgeloop.h
- intern/bmesh_inline.h
- intern/bmesh_interp.c
- intern/bmesh_interp.h
- intern/bmesh_iterators.c
- intern/bmesh_iterators.h
- intern/bmesh_iterators_inline.h
- intern/bmesh_log.c
- intern/bmesh_log.h
- intern/bmesh_marking.c
- intern/bmesh_marking.h
- intern/bmesh_mesh.c
- intern/bmesh_mesh.h
- intern/bmesh_mesh_conv.c
- intern/bmesh_mesh_conv.h
- intern/bmesh_mesh_validate.c
- intern/bmesh_mesh_validate.h
- intern/bmesh_mods.c
- intern/bmesh_mods.h
- intern/bmesh_opdefines.c
- intern/bmesh_operator_api_inline.h
- intern/bmesh_operators.c
- intern/bmesh_operators.h
- intern/bmesh_operators_private.h
- intern/bmesh_polygon.c
- intern/bmesh_polygon.h
- intern/bmesh_polygon_edgenet.c
- intern/bmesh_polygon_edgenet.h
- intern/bmesh_private.h
- intern/bmesh_query.c
- intern/bmesh_query.h
- intern/bmesh_query_inline.h
- intern/bmesh_structure.c
- intern/bmesh_structure.h
- intern/bmesh_structure_inline.h
- intern/bmesh_walkers.c
- intern/bmesh_walkers.h
- intern/bmesh_walkers_impl.c
- intern/bmesh_walkers_private.h
+ intern/bmesh_callback_generic.c
+ intern/bmesh_callback_generic.h
+ intern/bmesh_construct.c
+ intern/bmesh_construct.h
+ intern/bmesh_core.c
+ intern/bmesh_core.h
+ intern/bmesh_delete.c
+ intern/bmesh_delete.h
+ intern/bmesh_edgeloop.c
+ intern/bmesh_edgeloop.h
+ intern/bmesh_inline.h
+ intern/bmesh_interp.c
+ intern/bmesh_interp.h
+ intern/bmesh_iterators.c
+ intern/bmesh_iterators.h
+ intern/bmesh_iterators_inline.h
+ intern/bmesh_log.c
+ intern/bmesh_log.h
+ intern/bmesh_marking.c
+ intern/bmesh_marking.h
+ intern/bmesh_mesh.c
+ intern/bmesh_mesh.h
+ intern/bmesh_mesh_conv.c
+ intern/bmesh_mesh_conv.h
+ intern/bmesh_mesh_validate.c
+ intern/bmesh_mesh_validate.h
+ intern/bmesh_mods.c
+ intern/bmesh_mods.h
+ intern/bmesh_opdefines.c
+ intern/bmesh_operator_api_inline.h
+ intern/bmesh_operators.c
+ intern/bmesh_operators.h
+ intern/bmesh_operators_private.h
+ intern/bmesh_polygon.c
+ intern/bmesh_polygon.h
+ intern/bmesh_polygon_edgenet.c
+ intern/bmesh_polygon_edgenet.h
+ intern/bmesh_private.h
+ intern/bmesh_query.c
+ intern/bmesh_query.h
+ intern/bmesh_query_inline.h
+ intern/bmesh_structure.c
+ intern/bmesh_structure.h
+ intern/bmesh_structure_inline.h
+ intern/bmesh_walkers.c
+ intern/bmesh_walkers.h
+ intern/bmesh_walkers_impl.c
+ intern/bmesh_walkers_private.h
- intern/bmesh_error.h
- intern/bmesh_operator_api.h
+ intern/bmesh_error.h
+ intern/bmesh_operator_api.h
- tools/bmesh_beautify.c
- tools/bmesh_beautify.h
- tools/bmesh_bevel.c
- tools/bmesh_bevel.h
- tools/bmesh_bisect_plane.c
- tools/bmesh_bisect_plane.h
- tools/bmesh_decimate.h
- tools/bmesh_decimate_collapse.c
- tools/bmesh_decimate_dissolve.c
- tools/bmesh_decimate_unsubdivide.c
- tools/bmesh_edgenet.c
- tools/bmesh_edgenet.h
- tools/bmesh_edgesplit.c
- tools/bmesh_edgesplit.h
- tools/bmesh_intersect.c
- tools/bmesh_intersect.h
- tools/bmesh_path.c
- tools/bmesh_path.h
- tools/bmesh_path_region.c
- tools/bmesh_path_region.h
- tools/bmesh_region_match.c
- tools/bmesh_region_match.h
- tools/bmesh_separate.c
- tools/bmesh_separate.h
- tools/bmesh_triangulate.c
- tools/bmesh_triangulate.h
- tools/bmesh_wireframe.c
- tools/bmesh_wireframe.h
+ tools/bmesh_beautify.c
+ tools/bmesh_beautify.h
+ tools/bmesh_bevel.c
+ tools/bmesh_bevel.h
+ tools/bmesh_bisect_plane.c
+ tools/bmesh_bisect_plane.h
+ tools/bmesh_decimate.h
+ tools/bmesh_decimate_collapse.c
+ tools/bmesh_decimate_dissolve.c
+ tools/bmesh_decimate_unsubdivide.c
+ tools/bmesh_edgenet.c
+ tools/bmesh_edgenet.h
+ tools/bmesh_edgesplit.c
+ tools/bmesh_edgesplit.h
+ tools/bmesh_intersect.c
+ tools/bmesh_intersect.h
+ tools/bmesh_path.c
+ tools/bmesh_path.h
+ tools/bmesh_path_region.c
+ tools/bmesh_path_region.h
+ tools/bmesh_region_match.c
+ tools/bmesh_region_match.h
+ tools/bmesh_separate.c
+ tools/bmesh_separate.h
+ tools/bmesh_triangulate.c
+ tools/bmesh_triangulate.h
+ tools/bmesh_wireframe.c
+ tools/bmesh_wireframe.h
- bmesh_class.h
+ bmesh_class.h
- # public includes
- bmesh.h
- bmesh_tools.h
+ # public includes
+ bmesh.h
+ bmesh_tools.h
)
set(LIB
- bf_blenkernel
- bf_blenlib
- extern_rangetree
+ bf_blenkernel
+ bf_blenlib
+ extern_rangetree
)
if(MSVC AND NOT MSVC_CLANG)
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX /wd4101")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX /wd4101")
endif()
if(WITH_BULLET)
- list(APPEND INC_SYS
- ${BULLET_INCLUDE_DIRS}
- )
- list(APPEND LIB
- extern_bullet
- )
- add_definitions(-DWITH_BULLET)
+ list(APPEND INC_SYS
+ ${BULLET_INCLUDE_DIRS}
+ )
+ list(APPEND LIB
+ extern_bullet
+ )
+ add_definitions(-DWITH_BULLET)
endif()
if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
+ add_definitions(-DWITH_INTERNATIONAL)
endif()
if(WITH_FREESTYLE)
- add_definitions(-DWITH_FREESTYLE)
+ add_definitions(-DWITH_FREESTYLE)
endif()
blender_add_lib(bf_bmesh "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/bmesh/bmesh.h b/source/blender/bmesh/bmesh.h
index afedf4998a0..dce6b8b79ec 100644
--- a/source/blender/bmesh/bmesh.h
+++ b/source/blender/bmesh/bmesh.h
@@ -179,7 +179,7 @@
extern "C" {
#endif
-#include "DNA_listBase.h" /* selection history uses */
+#include "DNA_listBase.h" /* selection history uses */
#include "DNA_customdata_types.h" /* BMesh struct in bmesh_class.h uses */
#include <stdlib.h>
diff --git a/source/blender/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h
index a9cafb7b13e..220a5b3a5f5 100644
--- a/source/blender/bmesh/bmesh_class.h
+++ b/source/blender/bmesh/bmesh_class.h
@@ -58,23 +58,23 @@ struct BLI_mempool;
* 4: some elements for internal record keeping.
*/
typedef struct BMHeader {
- void *data; /* customdata layers */
- int index; /* notes:
- * - Use BM_elem_index_get/set macros for index
- * - Uninitialized to -1 so we can easily tell its not set.
- * - Used for edge/vert/face/loop, check BMesh.elem_index_dirty for valid index values,
- * this is abused by various tools which set it dirty.
- * - For loops this is used for sorting during tessellation. */
-
- char htype; /* element geometric type (verts/edges/loops/faces) */
- char hflag; /* this would be a CD layer, see below */
-
- /* internal use only!
- * note,.we are very picky about not bloating this struct
- * but in this case its padded up to 16 bytes anyway,
- * so adding a flag here gives no increase in size */
- char api_flag;
-// char _pad;
+ void *data; /* customdata layers */
+ int index; /* notes:
+ * - Use BM_elem_index_get/set macros for index
+ * - Uninitialized to -1 so we can easily tell its not set.
+ * - Used for edge/vert/face/loop, check BMesh.elem_index_dirty for valid index values,
+ * this is abused by various tools which set it dirty.
+ * - For loops this is used for sorting during tessellation. */
+
+ char htype; /* element geometric type (verts/edges/loops/faces) */
+ char hflag; /* this would be a CD layer, see below */
+
+ /* internal use only!
+ * note,.we are very picky about not bloating this struct
+ * but in this case its padded up to 16 bytes anyway,
+ * so adding a flag here gives no increase in size */
+ char api_flag;
+ // char _pad;
} BMHeader;
BLI_STATIC_ASSERT((sizeof(BMHeader) <= 16), "BMHeader size has grown!");
@@ -84,290 +84,284 @@ BLI_STATIC_ASSERT((sizeof(BMHeader) <= 16), "BMHeader size has grown!");
* active layer, and properly update when switching active layers.*/
typedef struct BMVert {
- BMHeader head;
+ BMHeader head;
- float co[3]; /* vertex coordinates */
- float no[3]; /* vertex normal */
+ float co[3]; /* vertex coordinates */
+ float no[3]; /* vertex normal */
- /* pointer to (any) edge using this vertex (for disk cycles)
- *
- * note: some higher level functions set this to different edges that use this vertex,
- * which is a bit of an abuse of internal bmesh data but also works OK for now (use with care!).
- */
- struct BMEdge *e;
+ /* pointer to (any) edge using this vertex (for disk cycles)
+ *
+ * note: some higher level functions set this to different edges that use this vertex,
+ * which is a bit of an abuse of internal bmesh data but also works OK for now (use with care!).
+ */
+ struct BMEdge *e;
} BMVert;
typedef struct BMVert_OFlag {
- BMVert base;
- struct BMFlagLayer *oflags;
+ BMVert base;
+ struct BMFlagLayer *oflags;
} BMVert_OFlag;
/* disk link structure, only used by edges */
typedef struct BMDiskLink {
- struct BMEdge *next, *prev;
+ struct BMEdge *next, *prev;
} BMDiskLink;
typedef struct BMEdge {
- BMHeader head;
+ BMHeader head;
- struct BMVert *v1, *v2; /* vertices (unordered) */
+ struct BMVert *v1, *v2; /* vertices (unordered) */
- /* the list of loops around the edge (use l->radial_prev/next)
- * to access the other loops using the edge */
- struct BMLoop *l;
+ /* the list of loops around the edge (use l->radial_prev/next)
+ * to access the other loops using the edge */
+ struct BMLoop *l;
- /* disk cycle pointers
- * relative data: d1 indicates indicates the next/prev edge around vertex v1 and d2 does the same for v2 */
- BMDiskLink v1_disk_link, v2_disk_link;
+ /* disk cycle pointers
+ * relative data: d1 indicates indicates the next/prev edge around vertex v1 and d2 does the same for v2 */
+ BMDiskLink v1_disk_link, v2_disk_link;
} BMEdge;
typedef struct BMEdge_OFlag {
- BMEdge base;
- struct BMFlagLayer *oflags;
+ BMEdge base;
+ struct BMFlagLayer *oflags;
} BMEdge_OFlag;
typedef struct BMLoop {
- BMHeader head;
- /* notice no flags layer */
+ BMHeader head;
+ /* notice no flags layer */
- struct BMVert *v;
- struct BMEdge *e; /* edge, using verts (v, next->v) */
- struct BMFace *f;
+ struct BMVert *v;
+ struct BMEdge *e; /* edge, using verts (v, next->v) */
+ struct BMFace *f;
- /* circular linked list of loops which all use the same edge as this one '->e',
- * but not necessarily the same vertex (can be either v1 or v2 of our own '->e') */
- struct BMLoop *radial_next, *radial_prev;
+ /* circular linked list of loops which all use the same edge as this one '->e',
+ * but not necessarily the same vertex (can be either v1 or v2 of our own '->e') */
+ struct BMLoop *radial_next, *radial_prev;
- /* these were originally commented as private but are used all over the code */
- /* can't use ListBase API, due to head */
- struct BMLoop *next, *prev; /* next/prev verts around the face */
+ /* these were originally commented as private but are used all over the code */
+ /* can't use ListBase API, due to head */
+ struct BMLoop *next, *prev; /* next/prev verts around the face */
} BMLoop;
/* can cast BMFace/BMEdge/BMVert, but NOT BMLoop, since these don't have a flag layer */
typedef struct BMElemF {
- BMHeader head;
+ BMHeader head;
} BMElemF;
/* can cast anything to this, including BMLoop */
typedef struct BMElem {
- BMHeader head;
+ BMHeader head;
} BMElem;
#ifdef USE_BMESH_HOLES
/* eventually, this structure will be used for supporting holes in faces */
typedef struct BMLoopList {
- struct BMLoopList *next, *prev;
- struct BMLoop *first, *last;
+ struct BMLoopList *next, *prev;
+ struct BMLoop *first, *last;
} BMLoopList;
#endif
typedef struct BMFace {
- BMHeader head;
+ BMHeader head;
#ifdef USE_BMESH_HOLES
- int totbounds; /*total boundaries, is one plus the number of holes in the face*/
- ListBase loops;
+ int totbounds; /*total boundaries, is one plus the number of holes in the face*/
+ ListBase loops;
#else
- BMLoop *l_first;
+ BMLoop *l_first;
#endif
- int len; /* number of vertices in the face */
- float no[3]; /* face normal */
- short mat_nr; /* material index */
-// short _pad[3];
+ int len; /* number of vertices in the face */
+ float no[3]; /* face normal */
+ short mat_nr; /* material index */
+ // short _pad[3];
} BMFace;
typedef struct BMFace_OFlag {
- BMFace base;
- struct BMFlagLayer *oflags;
+ BMFace base;
+ struct BMFlagLayer *oflags;
} BMFace_OFlag;
typedef struct BMFlagLayer {
- short f; /* flags */
+ short f; /* flags */
} BMFlagLayer;
// #pragma GCC diagnostic ignored "-Wpadded"
typedef struct BMesh {
- int totvert, totedge, totloop, totface;
- int totvertsel, totedgesel, totfacesel;
+ int totvert, totedge, totloop, totface;
+ int totvertsel, totedgesel, totfacesel;
- /* flag index arrays as being dirty so we can check if they are clean and
- * avoid looping over the entire vert/edge/face/loop array in those cases.
- * valid flags are - BM_VERT | BM_EDGE | BM_FACE | BM_LOOP. */
- char elem_index_dirty;
+ /* flag index arrays as being dirty so we can check if they are clean and
+ * avoid looping over the entire vert/edge/face/loop array in those cases.
+ * valid flags are - BM_VERT | BM_EDGE | BM_FACE | BM_LOOP. */
+ char elem_index_dirty;
- /* flag array table as being dirty so we know when its safe to use it,
- * or when it needs to be re-created */
- char elem_table_dirty;
+ /* flag array table as being dirty so we know when its safe to use it,
+ * or when it needs to be re-created */
+ char elem_table_dirty;
+ /* element pools */
+ struct BLI_mempool *vpool, *epool, *lpool, *fpool;
- /* element pools */
- struct BLI_mempool *vpool, *epool, *lpool, *fpool;
+ /* mempool lookup tables (optional)
+ * index tables, to map indices to elements via
+ * BM_mesh_elem_table_ensure and associated functions. don't
+ * touch this or read it directly.\
+ * Use BM_mesh_elem_table_ensure(), BM_vert/edge/face_at_index() */
+ BMVert **vtable;
+ BMEdge **etable;
+ BMFace **ftable;
- /* mempool lookup tables (optional)
- * index tables, to map indices to elements via
- * BM_mesh_elem_table_ensure and associated functions. don't
- * touch this or read it directly.\
- * Use BM_mesh_elem_table_ensure(), BM_vert/edge/face_at_index() */
- BMVert **vtable;
- BMEdge **etable;
- BMFace **ftable;
+ /* size of allocated tables */
+ int vtable_tot;
+ int etable_tot;
+ int ftable_tot;
- /* size of allocated tables */
- int vtable_tot;
- int etable_tot;
- int ftable_tot;
+ /* operator api stuff (must be all NULL or all alloc'd) */
+ struct BLI_mempool *vtoolflagpool, *etoolflagpool, *ftoolflagpool;
- /* operator api stuff (must be all NULL or all alloc'd) */
- struct BLI_mempool *vtoolflagpool, *etoolflagpool, *ftoolflagpool;
+ uint use_toolflags : 1;
- uint use_toolflags : 1;
+ int toolflag_index;
+ struct BMOperator *currentop;
- int toolflag_index;
- struct BMOperator *currentop;
-
- CustomData vdata, edata, ldata, pdata;
+ CustomData vdata, edata, ldata, pdata;
#ifdef USE_BMESH_HOLES
- struct BLI_mempool *looplistpool;
+ struct BLI_mempool *looplistpool;
#endif
- struct MLoopNorSpaceArray *lnor_spacearr;
- char spacearr_dirty;
+ struct MLoopNorSpaceArray *lnor_spacearr;
+ char spacearr_dirty;
- /* should be copy of scene select mode */
- /* stored in BMEditMesh too, this is a bit confusing,
- * make sure they're in sync!
- * Only use when the edit mesh cant be accessed - campbell */
- short selectmode;
+ /* should be copy of scene select mode */
+ /* stored in BMEditMesh too, this is a bit confusing,
+ * make sure they're in sync!
+ * Only use when the edit mesh cant be accessed - campbell */
+ short selectmode;
- /* ID of the shape key this bmesh came from */
- int shapenr;
+ /* ID of the shape key this bmesh came from */
+ int shapenr;
- int totflags;
- ListBase selected;
+ int totflags;
+ ListBase selected;
- BMFace *act_face;
+ BMFace *act_face;
- ListBase errorstack;
+ ListBase errorstack;
- void *py_handle;
+ void *py_handle;
} BMesh;
/* BMHeader->htype (char) */
enum {
- BM_VERT = 1,
- BM_EDGE = 2,
- BM_LOOP = 4,
- BM_FACE = 8,
+ BM_VERT = 1,
+ BM_EDGE = 2,
+ BM_LOOP = 4,
+ BM_FACE = 8,
};
typedef struct BMLoopNorEditData {
- int loop_index;
- BMLoop *loop;
- float niloc[3];
- float nloc[3];
- float *loc;
- short *clnors_data;
+ int loop_index;
+ BMLoop *loop;
+ float niloc[3];
+ float nloc[3];
+ float *loc;
+ short *clnors_data;
} BMLoopNorEditData;
typedef struct BMLoopNorEditDataArray {
- BMLoopNorEditData *lnor_editdata;
- /* This one has full amount of loops, used to map loop index to actual BMLoopNorEditData struct. */
- BMLoopNorEditData **lidx_to_lnor_editdata;
+ BMLoopNorEditData *lnor_editdata;
+ /* This one has full amount of loops, used to map loop index to actual BMLoopNorEditData struct. */
+ BMLoopNorEditData **lidx_to_lnor_editdata;
- int cd_custom_normal_offset;
- int totloop;
+ int cd_custom_normal_offset;
+ int totloop;
} BMLoopNorEditDataArray;
#define BM_ALL (BM_VERT | BM_EDGE | BM_LOOP | BM_FACE)
#define BM_ALL_NOLOOP (BM_VERT | BM_EDGE | BM_FACE)
enum {
- BM_SPACEARR_DIRTY = 1 << 0,
- BM_SPACEARR_DIRTY_ALL = 1 << 1,
- BM_SPACEARR_BMO_SET = 1 << 2,
+ BM_SPACEARR_DIRTY = 1 << 0,
+ BM_SPACEARR_DIRTY_ALL = 1 << 1,
+ BM_SPACEARR_BMO_SET = 1 << 2,
};
/* args for _Generic */
#define _BM_GENERIC_TYPE_ELEM_NONCONST \
- void *, BMVert *, BMEdge *, BMLoop *, BMFace *, \
- BMVert_OFlag *, BMEdge_OFlag *, BMFace_OFlag *, \
- BMElem *, BMElemF *, BMHeader *
+ void *, BMVert *, BMEdge *, BMLoop *, BMFace *, BMVert_OFlag *, BMEdge_OFlag *, BMFace_OFlag *, \
+ BMElem *, BMElemF *, BMHeader *
#define _BM_GENERIC_TYPE_ELEM_CONST \
- const void *, const BMVert *, const BMEdge *, const BMLoop *, const BMFace *, \
- const BMVert_OFlag *, const BMEdge_OFlag *, const BMFace_OFlag *, \
- const BMElem *, const BMElemF *, const BMHeader *, \
- void * const, BMVert * const, BMEdge * const, BMLoop * const, BMFace * const, \
- BMElem * const, BMElemF * const, BMHeader * const
+ const void *, const BMVert *, const BMEdge *, const BMLoop *, const BMFace *, \
+ const BMVert_OFlag *, const BMEdge_OFlag *, const BMFace_OFlag *, const BMElem *, \
+ const BMElemF *, const BMHeader *, void *const, BMVert *const, BMEdge *const, \
+ BMLoop *const, BMFace *const, BMElem *const, BMElemF *const, BMHeader *const
-#define BM_CHECK_TYPE_ELEM_CONST(ele) \
- CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPES_CONST)
+#define BM_CHECK_TYPE_ELEM_CONST(ele) CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPES_CONST)
-#define BM_CHECK_TYPE_ELEM_NONCONST(ele) \
- CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_ELEM_NONCONST)
+#define BM_CHECK_TYPE_ELEM_NONCONST(ele) CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_ELEM_NONCONST)
#define BM_CHECK_TYPE_ELEM(ele) \
- CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_ELEM_NONCONST, _BM_GENERIC_TYPE_ELEM_CONST)
+ CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_ELEM_NONCONST, _BM_GENERIC_TYPE_ELEM_CONST)
/* vert */
#define _BM_GENERIC_TYPE_VERT_NONCONST BMVert *, BMVert_OFlag *
#define _BM_GENERIC_TYPE_VERT_CONST const BMVert *, const BMVert_OFlag *
#define BM_CHECK_TYPE_VERT_CONST(ele) CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_VERT_CONST)
#define BM_CHECK_TYPE_VERT_NONCONST(ele) CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_ELEM_NONCONST)
-#define BM_CHECK_TYPE_VERT(ele) CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_VERT_NONCONST, _BM_GENERIC_TYPE_VERT_CONST)
+#define BM_CHECK_TYPE_VERT(ele) \
+ CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_VERT_NONCONST, _BM_GENERIC_TYPE_VERT_CONST)
/* edge */
#define _BM_GENERIC_TYPE_EDGE_NONCONST BMEdge *, BMEdge_OFlag *
#define _BM_GENERIC_TYPE_EDGE_CONST const BMEdge *, const BMEdge_OFlag *
#define BM_CHECK_TYPE_EDGE_CONST(ele) CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_EDGE_CONST)
#define BM_CHECK_TYPE_EDGE_NONCONST(ele) CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_ELEM_NONCONST)
-#define BM_CHECK_TYPE_EDGE(ele) CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_EDGE_NONCONST, _BM_GENERIC_TYPE_EDGE_CONST)
+#define BM_CHECK_TYPE_EDGE(ele) \
+ CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_EDGE_NONCONST, _BM_GENERIC_TYPE_EDGE_CONST)
/* face */
#define _BM_GENERIC_TYPE_FACE_NONCONST BMFace *, BMFace_OFlag *
#define _BM_GENERIC_TYPE_FACE_CONST const BMFace *, const BMFace_OFlag *
#define BM_CHECK_TYPE_FACE_CONST(ele) CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_FACE_CONST)
#define BM_CHECK_TYPE_FACE_NONCONST(ele) CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_ELEM_NONCONST)
-#define BM_CHECK_TYPE_FACE(ele) CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_FACE_NONCONST, _BM_GENERIC_TYPE_FACE_CONST)
-
-
+#define BM_CHECK_TYPE_FACE(ele) \
+ CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_FACE_NONCONST, _BM_GENERIC_TYPE_FACE_CONST)
/* Assignment from a void* to a typed pointer is not allowed in C++,
* casting the LHS to void works fine though.
*/
#ifdef __cplusplus
-#define BM_CHECK_TYPE_ELEM_ASSIGN(ele) \
- (BM_CHECK_TYPE_ELEM(ele)), *((void **)&ele)
+# define BM_CHECK_TYPE_ELEM_ASSIGN(ele) (BM_CHECK_TYPE_ELEM(ele)), *((void **)&ele)
#else
-#define BM_CHECK_TYPE_ELEM_ASSIGN(ele) \
- (BM_CHECK_TYPE_ELEM(ele)), ele
+# define BM_CHECK_TYPE_ELEM_ASSIGN(ele) (BM_CHECK_TYPE_ELEM(ele)), ele
#endif
/* BMHeader->hflag (char) */
enum {
- BM_ELEM_SELECT = (1 << 0),
- BM_ELEM_HIDDEN = (1 << 1),
- BM_ELEM_SEAM = (1 << 2),
- /**
- * used for faces and edges, note from the user POV,
- * this is a sharp edge when disabled */
- BM_ELEM_SMOOTH = (1 << 3),
- /**
- * internal flag, used for ensuring correct normals
- * during multires interpolation, and any other time
- * when temp tagging is handy.
- * always assume dirty & clear before use. */
- BM_ELEM_TAG = (1 << 4),
-
- BM_ELEM_DRAW = (1 << 5), /* edge display */
-
- /* spare tag, assumed dirty, use define in each function to name based on use */
- // _BM_ELEM_TAG_ALT = (1 << 6), // UNUSED
- /**
- * For low level internal API tagging,
- * since tools may want to tag verts and not have functions clobber them.
- * Leave cleared! */
- BM_ELEM_INTERNAL_TAG = (1 << 7),
+ BM_ELEM_SELECT = (1 << 0),
+ BM_ELEM_HIDDEN = (1 << 1),
+ BM_ELEM_SEAM = (1 << 2),
+ /**
+ * used for faces and edges, note from the user POV,
+ * this is a sharp edge when disabled */
+ BM_ELEM_SMOOTH = (1 << 3),
+ /**
+ * internal flag, used for ensuring correct normals
+ * during multires interpolation, and any other time
+ * when temp tagging is handy.
+ * always assume dirty & clear before use. */
+ BM_ELEM_TAG = (1 << 4),
+
+ BM_ELEM_DRAW = (1 << 5), /* edge display */
+
+ /* spare tag, assumed dirty, use define in each function to name based on use */
+ // _BM_ELEM_TAG_ALT = (1 << 6), // UNUSED
+ /**
+ * For low level internal API tagging,
+ * since tools may want to tag verts and not have functions clobber them.
+ * Leave cleared! */
+ BM_ELEM_INTERNAL_TAG = (1 << 7),
};
struct BPy_BMGeneric;
@@ -380,32 +374,43 @@ typedef bool (*BMFaceFilterFunc)(const BMFace *, void *user_data);
typedef bool (*BMLoopFilterFunc)(const BMLoop *, void *user_data);
/* defines */
-#define BM_ELEM_CD_SET_INT(ele, offset, f) { CHECK_TYPE_NONCONST(ele); \
- assert(offset != -1); *((int *)((char *)(ele)->head.data + (offset))) = (f); } (void)0
+#define BM_ELEM_CD_SET_INT(ele, offset, f) \
+ { \
+ CHECK_TYPE_NONCONST(ele); \
+ assert(offset != -1); \
+ *((int *)((char *)(ele)->head.data + (offset))) = (f); \
+ } \
+ (void)0
#define BM_ELEM_CD_GET_INT(ele, offset) \
- (assert(offset != -1), *((int *)((char *)(ele)->head.data + (offset))))
+ (assert(offset != -1), *((int *)((char *)(ele)->head.data + (offset))))
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
-#define BM_ELEM_CD_GET_VOID_P(ele, offset) \
- (assert(offset != -1), \
- _Generic(ele, \
- GENERIC_TYPE_ANY( POINTER_OFFSET((ele)->head.data, offset), _BM_GENERIC_TYPE_ELEM_NONCONST), \
- GENERIC_TYPE_ANY((const void *)POINTER_OFFSET((ele)->head.data, offset), _BM_GENERIC_TYPE_ELEM_CONST)) \
- )
+# define BM_ELEM_CD_GET_VOID_P(ele, offset) \
+ (assert(offset != -1), \
+ _Generic(ele, \
+ GENERIC_TYPE_ANY(POINTER_OFFSET((ele)->head.data, offset), \
+ _BM_GENERIC_TYPE_ELEM_NONCONST), \
+ GENERIC_TYPE_ANY((const void *)POINTER_OFFSET((ele)->head.data, offset), \
+ _BM_GENERIC_TYPE_ELEM_CONST)))
#else
-#define BM_ELEM_CD_GET_VOID_P(ele, offset) \
- (assert(offset != -1), (void *)((char *)(ele)->head.data + (offset)))
+# define BM_ELEM_CD_GET_VOID_P(ele, offset) \
+ (assert(offset != -1), (void *)((char *)(ele)->head.data + (offset)))
#endif
-#define BM_ELEM_CD_SET_FLOAT(ele, offset, f) { CHECK_TYPE_NONCONST(ele); \
- assert(offset != -1); *((float *)((char *)(ele)->head.data + (offset))) = (f); } (void)0
+#define BM_ELEM_CD_SET_FLOAT(ele, offset, f) \
+ { \
+ CHECK_TYPE_NONCONST(ele); \
+ assert(offset != -1); \
+ *((float *)((char *)(ele)->head.data + (offset))) = (f); \
+ } \
+ (void)0
#define BM_ELEM_CD_GET_FLOAT(ele, offset) \
- (assert(offset != -1), *((float *)((char *)(ele)->head.data + (offset))))
+ (assert(offset != -1), *((float *)((char *)(ele)->head.data + (offset))))
#define BM_ELEM_CD_GET_FLOAT_AS_UCHAR(ele, offset) \
- (assert(offset != -1), (uchar)(BM_ELEM_CD_GET_FLOAT(ele, offset) * 255.0f))
+ (assert(offset != -1), (uchar)(BM_ELEM_CD_GET_FLOAT(ele, offset) * 255.0f))
/*forward declarations*/
@@ -415,14 +420,16 @@ typedef bool (*BMLoopFilterFunc)(const BMLoop *, void *user_data);
# define BM_FACE_FIRST_LOOP(p) ((p)->l_first)
#endif
-#define BM_DISK_EDGE_NEXT(e, v) ( \
- CHECK_TYPE_INLINE(e, BMEdge *), CHECK_TYPE_INLINE(v, BMVert *), \
- BLI_assert(BM_vert_in_edge(e, v)), \
- (((&e->v1_disk_link)[v == e->v2]).next))
-#define BM_DISK_EDGE_PREV(e, v) ( \
- CHECK_TYPE_INLINE(e, BMEdge *), CHECK_TYPE_INLINE(v, BMVert *), \
- BLI_assert(BM_vert_in_edge(e, v)), \
- (((&e->v1_disk_link)[v == e->v2]).prev))
+#define BM_DISK_EDGE_NEXT(e, v) \
+ (CHECK_TYPE_INLINE(e, BMEdge *), \
+ CHECK_TYPE_INLINE(v, BMVert *), \
+ BLI_assert(BM_vert_in_edge(e, v)), \
+ (((&e->v1_disk_link)[v == e->v2]).next))
+#define BM_DISK_EDGE_PREV(e, v) \
+ (CHECK_TYPE_INLINE(e, BMEdge *), \
+ CHECK_TYPE_INLINE(v, BMVert *), \
+ BLI_assert(BM_vert_in_edge(e, v)), \
+ (((&e->v1_disk_link)[v == e->v2]).prev))
/**
* size to use for stack arrays when dealing with NGons,
diff --git a/source/blender/bmesh/intern/bmesh_callback_generic.c b/source/blender/bmesh/intern/bmesh_callback_generic.c
index 07a23cd0471..27e808895cd 100644
--- a/source/blender/bmesh/intern/bmesh_callback_generic.c
+++ b/source/blender/bmesh/intern/bmesh_callback_generic.c
@@ -28,29 +28,28 @@
bool BM_elem_cb_check_hflag_ex(BMElem *ele, void *user_data)
{
- const uint hflag_pair = POINTER_AS_INT(user_data);
- const char hflag_p = (hflag_pair & 0xff);
- const char hflag_n = (hflag_pair >> 8);
+ const uint hflag_pair = POINTER_AS_INT(user_data);
+ const char hflag_p = (hflag_pair & 0xff);
+ const char hflag_n = (hflag_pair >> 8);
- return ((BM_elem_flag_test(ele, hflag_p) != 0) &&
- (BM_elem_flag_test(ele, hflag_n) == 0));
+ return ((BM_elem_flag_test(ele, hflag_p) != 0) && (BM_elem_flag_test(ele, hflag_n) == 0));
}
bool BM_elem_cb_check_hflag_enabled(BMElem *ele, void *user_data)
{
- const char hflag = POINTER_AS_INT(user_data);
+ const char hflag = POINTER_AS_INT(user_data);
- return (BM_elem_flag_test(ele, hflag) != 0);
+ return (BM_elem_flag_test(ele, hflag) != 0);
}
bool BM_elem_cb_check_hflag_disabled(BMElem *ele, void *user_data)
{
- const char hflag = POINTER_AS_INT(user_data);
+ const char hflag = POINTER_AS_INT(user_data);
- return (BM_elem_flag_test(ele, hflag) == 0);
+ return (BM_elem_flag_test(ele, hflag) == 0);
}
bool BM_elem_cb_check_elem_not_equal(BMElem *ele, void *user_data)
{
- return (ele != user_data);
+ return (ele != user_data);
}
diff --git a/source/blender/bmesh/intern/bmesh_callback_generic.h b/source/blender/bmesh/intern/bmesh_callback_generic.h
index d17e7a68ac8..5191bd31873 100644
--- a/source/blender/bmesh/intern/bmesh_callback_generic.h
+++ b/source/blender/bmesh/intern/bmesh_callback_generic.h
@@ -27,15 +27,13 @@ bool BM_elem_cb_check_hflag_ex(BMElem *, void *user_data);
bool BM_elem_cb_check_elem_not_equal(BMElem *ele, void *user_data);
#define BM_elem_cb_check_hflag_ex_simple(type, hflag_p, hflag_n) \
- (bool (*)(type, void *))BM_elem_cb_check_hflag_ex, \
- POINTER_FROM_UINT(((hflag_p) | (hflag_n << 8)))
+ (bool (*)(type, void *)) BM_elem_cb_check_hflag_ex, \
+ POINTER_FROM_UINT(((hflag_p) | (hflag_n << 8)))
#define BM_elem_cb_check_hflag_enabled_simple(type, hflag_p) \
- (bool (*)(type, void *))BM_elem_cb_check_hflag_enabled, \
- POINTER_FROM_UINT((hflag_p))
+ (bool (*)(type, void *)) BM_elem_cb_check_hflag_enabled, POINTER_FROM_UINT((hflag_p))
#define BM_elem_cb_check_hflag_disabled_simple(type, hflag_n) \
- (bool (*)(type, void *))BM_elem_cb_check_hflag_disabled, \
- POINTER_FROM_UINT(hflag_n)
+ (bool (*)(type, void *)) BM_elem_cb_check_hflag_disabled, POINTER_FROM_UINT(hflag_n)
#endif /* __BMESH_CALLBACK_GENERIC_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c
index c24a5b21b6c..0528a550be4 100644
--- a/source/blender/bmesh/intern/bmesh_construct.c
+++ b/source/blender/bmesh/intern/bmesh_construct.c
@@ -38,7 +38,6 @@
#define SELECT 1
-
/**
* Fill in a vertex array from an edge array.
*
@@ -46,15 +45,15 @@
*/
bool BM_verts_from_edges(BMVert **vert_arr, BMEdge **edge_arr, const int len)
{
- int i, i_prev = len - 1;
- for (i = 0; i < len; i++) {
- vert_arr[i] = BM_edge_share_vert(edge_arr[i_prev], edge_arr[i]);
- if (vert_arr[i] == NULL) {
- return false;
- }
- i_prev = i;
- }
- return true;
+ int i, i_prev = len - 1;
+ for (i = 0; i < len; i++) {
+ vert_arr[i] = BM_edge_share_vert(edge_arr[i_prev], edge_arr[i]);
+ if (vert_arr[i] == NULL) {
+ return false;
+ }
+ i_prev = i;
+ }
+ return true;
}
/**
@@ -64,15 +63,15 @@ bool BM_verts_from_edges(BMVert **vert_arr, BMEdge **edge_arr, const int len)
*/
bool BM_edges_from_verts(BMEdge **edge_arr, BMVert **vert_arr, const int len)
{
- int i, i_prev = len - 1;
- for (i = 0; i < len; i++) {
- edge_arr[i_prev] = BM_edge_exists(vert_arr[i_prev], vert_arr[i]);
- if (edge_arr[i_prev] == NULL) {
- return false;
- }
- i_prev = i;
- }
- return true;
+ int i, i_prev = len - 1;
+ for (i = 0; i < len; i++) {
+ edge_arr[i_prev] = BM_edge_exists(vert_arr[i_prev], vert_arr[i]);
+ if (edge_arr[i_prev] == NULL) {
+ return false;
+ }
+ i_prev = i;
+ }
+ return true;
}
/**
@@ -81,17 +80,20 @@ bool BM_edges_from_verts(BMEdge **edge_arr, BMVert **vert_arr, const int len)
*/
void BM_edges_from_verts_ensure(BMesh *bm, BMEdge **edge_arr, BMVert **vert_arr, const int len)
{
- int i, i_prev = len - 1;
- for (i = 0; i < len; i++) {
- edge_arr[i_prev] = BM_edge_create(bm, vert_arr[i_prev], vert_arr[i], NULL, BM_CREATE_NO_DOUBLE);
- i_prev = i;
- }
+ int i, i_prev = len - 1;
+ for (i = 0; i < len; i++) {
+ edge_arr[i_prev] = BM_edge_create(
+ bm, vert_arr[i_prev], vert_arr[i], NULL, BM_CREATE_NO_DOUBLE);
+ i_prev = i;
+ }
}
/* prototypes */
-static void bm_loop_attrs_copy(
- BMesh *source_mesh, BMesh *target_mesh,
- const BMLoop *source_loop, BMLoop *target_loop, uint64_t cd_mask);
+static void bm_loop_attrs_copy(BMesh *source_mesh,
+ BMesh *target_mesh,
+ const BMLoop *source_loop,
+ BMLoop *target_loop,
+ uint64_t cd_mask);
/**
* \brief Make Quad/Triangle
@@ -107,13 +109,16 @@ static void bm_loop_attrs_copy(
* of the vertices in the vertex array.
*/
-BMFace *BM_face_create_quad_tri(
- BMesh *bm,
- BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
- const BMFace *f_example, const eBMCreateFlag create_flag)
+BMFace *BM_face_create_quad_tri(BMesh *bm,
+ BMVert *v1,
+ BMVert *v2,
+ BMVert *v3,
+ BMVert *v4,
+ const BMFace *f_example,
+ const eBMCreateFlag create_flag)
{
- BMVert *vtar[4] = {v1, v2, v3, v4};
- return BM_face_create_verts(bm, vtar, v4 ? 4 : 3, f_example, create_flag, true);
+ BMVert *vtar[4] = {v1, v2, v3, v4};
+ return BM_face_create_verts(bm, vtar, v4 ? 4 : 3, f_example, create_flag, true);
}
/**
@@ -125,55 +130,52 @@ BMFace *BM_face_create_quad_tri(
* this is done since the face may not be completely surrounded by faces,
* this way: a quad with 2 connected quads on either side will still get all 4 loops updated
*/
-void BM_face_copy_shared(
- BMesh *bm, BMFace *f,
- BMLoopFilterFunc filter_fn, void *user_data)
+void BM_face_copy_shared(BMesh *bm, BMFace *f, BMLoopFilterFunc filter_fn, void *user_data)
{
- BMLoop *l_first;
- BMLoop *l_iter;
+ BMLoop *l_first;
+ BMLoop *l_iter;
#ifdef DEBUG
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- BLI_assert(BM_ELEM_API_FLAG_TEST(l_iter, _FLAG_OVERLAP) == 0);
- } while ((l_iter = l_iter->next) != l_first);
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BLI_assert(BM_ELEM_API_FLAG_TEST(l_iter, _FLAG_OVERLAP) == 0);
+ } while ((l_iter = l_iter->next) != l_first);
#endif
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- BMLoop *l_other = l_iter->radial_next;
-
- if (l_other && l_other != l_iter) {
- BMLoop *l_src[2];
- BMLoop *l_dst[2] = {l_iter, l_iter->next};
- uint j;
-
- if (l_other->v == l_iter->v) {
- l_src[0] = l_other;
- l_src[1] = l_other->next;
- }
- else {
- l_src[0] = l_other->next;
- l_src[1] = l_other;
- }
-
- for (j = 0; j < 2; j++) {
- BLI_assert(l_dst[j]->v == l_src[j]->v);
- if (BM_ELEM_API_FLAG_TEST(l_dst[j], _FLAG_OVERLAP) == 0) {
- if ((filter_fn == NULL) || filter_fn(l_src[j], user_data)) {
- bm_loop_attrs_copy(bm, bm, l_src[j], l_dst[j], 0x0);
- BM_ELEM_API_FLAG_ENABLE(l_dst[j], _FLAG_OVERLAP);
- }
- }
- }
- }
- } while ((l_iter = l_iter->next) != l_first);
-
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- BM_ELEM_API_FLAG_DISABLE(l_iter, _FLAG_OVERLAP);
- } while ((l_iter = l_iter->next) != l_first);
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BMLoop *l_other = l_iter->radial_next;
+
+ if (l_other && l_other != l_iter) {
+ BMLoop *l_src[2];
+ BMLoop *l_dst[2] = {l_iter, l_iter->next};
+ uint j;
+
+ if (l_other->v == l_iter->v) {
+ l_src[0] = l_other;
+ l_src[1] = l_other->next;
+ }
+ else {
+ l_src[0] = l_other->next;
+ l_src[1] = l_other;
+ }
+
+ for (j = 0; j < 2; j++) {
+ BLI_assert(l_dst[j]->v == l_src[j]->v);
+ if (BM_ELEM_API_FLAG_TEST(l_dst[j], _FLAG_OVERLAP) == 0) {
+ if ((filter_fn == NULL) || filter_fn(l_src[j], user_data)) {
+ bm_loop_attrs_copy(bm, bm, l_src[j], l_dst[j], 0x0);
+ BM_ELEM_API_FLAG_ENABLE(l_dst[j], _FLAG_OVERLAP);
+ }
+ }
+ }
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BM_ELEM_API_FLAG_DISABLE(l_iter, _FLAG_OVERLAP);
+ } while ((l_iter = l_iter->next) != l_first);
}
/**
@@ -183,80 +185,80 @@ void BM_face_copy_shared(
*
* All arrays must be \a len long.
*/
-static bool bm_edges_sort_winding(
- BMVert *v1, BMVert *v2,
- BMEdge **edges, const int len,
- BMEdge **edges_sort, BMVert **verts_sort)
+static bool bm_edges_sort_winding(BMVert *v1,
+ BMVert *v2,
+ BMEdge **edges,
+ const int len,
+ BMEdge **edges_sort,
+ BMVert **verts_sort)
{
- BMEdge *e_iter, *e_first;
- BMVert *v_iter;
- int i;
-
- /* all flags _must_ be cleared on exit! */
- for (i = 0; i < len; i++) {
- BM_ELEM_API_FLAG_ENABLE(edges[i], _FLAG_MF);
- BM_ELEM_API_FLAG_ENABLE(edges[i]->v1, _FLAG_MV);
- BM_ELEM_API_FLAG_ENABLE(edges[i]->v2, _FLAG_MV);
- }
-
- /* find first edge */
- i = 0;
- v_iter = v1;
- e_iter = e_first = v1->e;
- do {
- if (BM_ELEM_API_FLAG_TEST(e_iter, _FLAG_MF) &&
- (BM_edge_other_vert(e_iter, v_iter) == v2))
- {
- i = 1;
- break;
- }
- } while ((e_iter = bmesh_disk_edge_next(e_iter, v_iter)) != e_first);
- if (i == 0) {
- goto error;
- }
-
- i = 0;
- do {
- /* entering loop will always succeed */
- if (BM_ELEM_API_FLAG_TEST(e_iter, _FLAG_MF)) {
- if (UNLIKELY(BM_ELEM_API_FLAG_TEST(v_iter, _FLAG_MV) == false)) {
- /* vert is in loop multiple times */
- goto error;
- }
-
- BM_ELEM_API_FLAG_DISABLE(e_iter, _FLAG_MF);
- edges_sort[i] = e_iter;
-
- BM_ELEM_API_FLAG_DISABLE(v_iter, _FLAG_MV);
- verts_sort[i] = v_iter;
-
- i += 1;
-
- /* walk onto the next vertex */
- v_iter = BM_edge_other_vert(e_iter, v_iter);
- if (i == len) {
- if (UNLIKELY(v_iter != verts_sort[0])) {
- goto error;
- }
- break;
- }
-
- e_first = e_iter;
- }
- } while ((e_iter = bmesh_disk_edge_next(e_iter, v_iter)) != e_first);
-
- if (i == len) {
- return true;
- }
+ BMEdge *e_iter, *e_first;
+ BMVert *v_iter;
+ int i;
+
+ /* all flags _must_ be cleared on exit! */
+ for (i = 0; i < len; i++) {
+ BM_ELEM_API_FLAG_ENABLE(edges[i], _FLAG_MF);
+ BM_ELEM_API_FLAG_ENABLE(edges[i]->v1, _FLAG_MV);
+ BM_ELEM_API_FLAG_ENABLE(edges[i]->v2, _FLAG_MV);
+ }
+
+ /* find first edge */
+ i = 0;
+ v_iter = v1;
+ e_iter = e_first = v1->e;
+ do {
+ if (BM_ELEM_API_FLAG_TEST(e_iter, _FLAG_MF) && (BM_edge_other_vert(e_iter, v_iter) == v2)) {
+ i = 1;
+ break;
+ }
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v_iter)) != e_first);
+ if (i == 0) {
+ goto error;
+ }
+
+ i = 0;
+ do {
+ /* entering loop will always succeed */
+ if (BM_ELEM_API_FLAG_TEST(e_iter, _FLAG_MF)) {
+ if (UNLIKELY(BM_ELEM_API_FLAG_TEST(v_iter, _FLAG_MV) == false)) {
+ /* vert is in loop multiple times */
+ goto error;
+ }
+
+ BM_ELEM_API_FLAG_DISABLE(e_iter, _FLAG_MF);
+ edges_sort[i] = e_iter;
+
+ BM_ELEM_API_FLAG_DISABLE(v_iter, _FLAG_MV);
+ verts_sort[i] = v_iter;
+
+ i += 1;
+
+ /* walk onto the next vertex */
+ v_iter = BM_edge_other_vert(e_iter, v_iter);
+ if (i == len) {
+ if (UNLIKELY(v_iter != verts_sort[0])) {
+ goto error;
+ }
+ break;
+ }
+
+ e_first = e_iter;
+ }
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v_iter)) != e_first);
+
+ if (i == len) {
+ return true;
+ }
error:
- for (i = 0; i < len; i++) {
- BM_ELEM_API_FLAG_DISABLE(edges[i], _FLAG_MF);
- BM_ELEM_API_FLAG_DISABLE(edges[i]->v1, _FLAG_MV);
- BM_ELEM_API_FLAG_DISABLE(edges[i]->v2, _FLAG_MV);
- }
+ for (i = 0; i < len; i++) {
+ BM_ELEM_API_FLAG_DISABLE(edges[i], _FLAG_MF);
+ BM_ELEM_API_FLAG_DISABLE(edges[i]->v1, _FLAG_MV);
+ BM_ELEM_API_FLAG_DISABLE(edges[i]->v2, _FLAG_MV);
+ }
- return false;
+ return false;
}
/**
@@ -273,20 +275,24 @@ error:
* #BM_face_create should be considered over this function as it
* avoids some unnecessary work.
*/
-BMFace *BM_face_create_ngon(
- BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, const int len,
- const BMFace *f_example, const eBMCreateFlag create_flag)
+BMFace *BM_face_create_ngon(BMesh *bm,
+ BMVert *v1,
+ BMVert *v2,
+ BMEdge **edges,
+ const int len,
+ const BMFace *f_example,
+ const eBMCreateFlag create_flag)
{
- BMEdge **edges_sort = BLI_array_alloca(edges_sort, len);
- BMVert **verts_sort = BLI_array_alloca(verts_sort, len);
+ BMEdge **edges_sort = BLI_array_alloca(edges_sort, len);
+ BMVert **verts_sort = BLI_array_alloca(verts_sort, len);
- BLI_assert(len && v1 && v2 && edges && bm);
+ BLI_assert(len && v1 && v2 && edges && bm);
- if (bm_edges_sort_winding(v1, v2, edges, len, edges_sort, verts_sort)) {
- return BM_face_create(bm, verts_sort, edges_sort, len, f_example, create_flag);
- }
+ if (bm_edges_sort_winding(v1, v2, edges, len, edges_sort, verts_sort)) {
+ return BM_face_create(bm, verts_sort, edges_sort, len, f_example, create_flag);
+ }
- return NULL;
+ return NULL;
}
/**
@@ -297,70 +303,69 @@ BMFace *BM_face_create_ngon(
* - Optionally create edges between vertices.
* - Uses verts so no need to find edges (handy when you only have verts)
*/
-BMFace *BM_face_create_ngon_verts(
- BMesh *bm, BMVert **vert_arr, const int len,
- const BMFace *f_example, const eBMCreateFlag create_flag,
- const bool calc_winding, const bool create_edges)
+BMFace *BM_face_create_ngon_verts(BMesh *bm,
+ BMVert **vert_arr,
+ const int len,
+ const BMFace *f_example,
+ const eBMCreateFlag create_flag,
+ const bool calc_winding,
+ const bool create_edges)
{
- BMEdge **edge_arr = BLI_array_alloca(edge_arr, len);
- uint winding[2] = {0, 0};
- int i, i_prev = len - 1;
- BMVert *v_winding[2] = {vert_arr[i_prev], vert_arr[0]};
-
- BLI_assert(len > 2);
-
- for (i = 0; i < len; i++) {
- if (create_edges) {
- edge_arr[i] = BM_edge_create(bm, vert_arr[i_prev], vert_arr[i], NULL, BM_CREATE_NO_DOUBLE);
- }
- else {
- edge_arr[i] = BM_edge_exists(vert_arr[i_prev], vert_arr[i]);
- if (edge_arr[i] == NULL) {
- return NULL;
- }
- }
-
- if (calc_winding) {
- /* the edge may exist already and be attached to a face
- * in this case we can find the best winding to use for the new face */
- if (edge_arr[i]->l) {
- BMVert *test_v1, *test_v2;
- /* we want to use the reverse winding to the existing order */
- BM_edge_ordered_verts(edge_arr[i], &test_v2, &test_v1);
- winding[(vert_arr[i_prev] == test_v2)]++;
- BLI_assert(vert_arr[i_prev] == test_v2 || vert_arr[i_prev] == test_v1);
- }
- }
-
- i_prev = i;
- }
-
- /* --- */
-
- if (calc_winding) {
- if (winding[0] < winding[1]) {
- winding[0] = 1;
- winding[1] = 0;
- }
- else {
- winding[0] = 0;
- winding[1] = 1;
- }
- }
- else {
- winding[0] = 0;
- winding[1] = 1;
- }
-
- /* --- */
-
- /* create the face */
- return BM_face_create_ngon(
- bm,
- v_winding[winding[0]],
- v_winding[winding[1]],
- edge_arr, len,
- f_example, create_flag);
+ BMEdge **edge_arr = BLI_array_alloca(edge_arr, len);
+ uint winding[2] = {0, 0};
+ int i, i_prev = len - 1;
+ BMVert *v_winding[2] = {vert_arr[i_prev], vert_arr[0]};
+
+ BLI_assert(len > 2);
+
+ for (i = 0; i < len; i++) {
+ if (create_edges) {
+ edge_arr[i] = BM_edge_create(bm, vert_arr[i_prev], vert_arr[i], NULL, BM_CREATE_NO_DOUBLE);
+ }
+ else {
+ edge_arr[i] = BM_edge_exists(vert_arr[i_prev], vert_arr[i]);
+ if (edge_arr[i] == NULL) {
+ return NULL;
+ }
+ }
+
+ if (calc_winding) {
+ /* the edge may exist already and be attached to a face
+ * in this case we can find the best winding to use for the new face */
+ if (edge_arr[i]->l) {
+ BMVert *test_v1, *test_v2;
+ /* we want to use the reverse winding to the existing order */
+ BM_edge_ordered_verts(edge_arr[i], &test_v2, &test_v1);
+ winding[(vert_arr[i_prev] == test_v2)]++;
+ BLI_assert(vert_arr[i_prev] == test_v2 || vert_arr[i_prev] == test_v1);
+ }
+ }
+
+ i_prev = i;
+ }
+
+ /* --- */
+
+ if (calc_winding) {
+ if (winding[0] < winding[1]) {
+ winding[0] = 1;
+ winding[1] = 0;
+ }
+ else {
+ winding[0] = 0;
+ winding[1] = 1;
+ }
+ }
+ else {
+ winding[0] = 0;
+ winding[1] = 1;
+ }
+
+ /* --- */
+
+ /* create the face */
+ return BM_face_create_ngon(
+ bm, v_winding[winding[0]], v_winding[winding[1]], edge_arr, len, f_example, create_flag);
}
/**
@@ -381,158 +386,166 @@ BMFace *BM_face_create_ngon_verts(
*/
void BM_verts_sort_radial_plane(BMVert **vert_arr, int len)
{
- struct SortIntByFloat *vang = BLI_array_alloca(vang, len);
- BMVert **vert_arr_map = BLI_array_alloca(vert_arr_map, len);
-
- float totv_inv = 1.0f / (float)len;
- int i = 0;
+ struct SortIntByFloat *vang = BLI_array_alloca(vang, len);
+ BMVert **vert_arr_map = BLI_array_alloca(vert_arr_map, len);
- float cent[3], nor[3];
+ float totv_inv = 1.0f / (float)len;
+ int i = 0;
- const float *far = NULL, *far_cross = NULL;
+ float cent[3], nor[3];
- float far_vec[3];
- float far_cross_vec[3];
- float sign_vec[3]; /* work out if we are pos/neg angle */
+ const float *far = NULL, *far_cross = NULL;
- float far_dist_sq, far_dist_max_sq;
- float far_cross_dist, far_cross_best = 0.0f;
+ float far_vec[3];
+ float far_cross_vec[3];
+ float sign_vec[3]; /* work out if we are pos/neg angle */
- /* get the center point and collect vector array since we loop over these a lot */
- zero_v3(cent);
- for (i = 0; i < len; i++) {
- madd_v3_v3fl(cent, vert_arr[i]->co, totv_inv);
- }
+ float far_dist_sq, far_dist_max_sq;
+ float far_cross_dist, far_cross_best = 0.0f;
+ /* get the center point and collect vector array since we loop over these a lot */
+ zero_v3(cent);
+ for (i = 0; i < len; i++) {
+ madd_v3_v3fl(cent, vert_arr[i]->co, totv_inv);
+ }
- /* find the far point from cent */
- far_dist_max_sq = 0.0f;
- for (i = 0; i < len; i++) {
- far_dist_sq = len_squared_v3v3(vert_arr[i]->co, cent);
- if (far_dist_sq > far_dist_max_sq || far == NULL) {
- far = vert_arr[i]->co;
- far_dist_max_sq = far_dist_sq;
- }
- }
+ /* find the far point from cent */
+ far_dist_max_sq = 0.0f;
+ for (i = 0; i < len; i++) {
+ far_dist_sq = len_squared_v3v3(vert_arr[i]->co, cent);
+ if (far_dist_sq > far_dist_max_sq || far == NULL) {
+ far = vert_arr[i]->co;
+ far_dist_max_sq = far_dist_sq;
+ }
+ }
- sub_v3_v3v3(far_vec, far, cent);
- // far_dist = len_v3(far_vec); /* real dist */ /* UNUSED */
+ sub_v3_v3v3(far_vec, far, cent);
+ // far_dist = len_v3(far_vec); /* real dist */ /* UNUSED */
- /* --- */
+ /* --- */
- /* find a point 90deg about to compare with */
- far_cross_best = 0.0f;
- for (i = 0; i < len; i++) {
+ /* find a point 90deg about to compare with */
+ far_cross_best = 0.0f;
+ for (i = 0; i < len; i++) {
- if (far == vert_arr[i]->co) {
- continue;
- }
+ if (far == vert_arr[i]->co) {
+ continue;
+ }
- sub_v3_v3v3(far_cross_vec, vert_arr[i]->co, cent);
- far_cross_dist = normalize_v3(far_cross_vec);
+ sub_v3_v3v3(far_cross_vec, vert_arr[i]->co, cent);
+ far_cross_dist = normalize_v3(far_cross_vec);
- /* more of a weight then a distance */
- far_cross_dist = (/* first we want to have a value close to zero mapped to 1 */
- 1.0f - fabsf(dot_v3v3(far_vec, far_cross_vec)) *
+ /* more of a weight then a distance */
+ far_cross_dist = (/* first we want to have a value close to zero mapped to 1 */
+ 1.0f - fabsf(dot_v3v3(far_vec, far_cross_vec)) *
- /* second we multiply by the distance
- * so points close to the center are not preferred */
- far_cross_dist);
+ /* second we multiply by the distance
+ * so points close to the center are not preferred */
+ far_cross_dist);
- if (far_cross_dist > far_cross_best || far_cross == NULL) {
- far_cross = vert_arr[i]->co;
- far_cross_best = far_cross_dist;
- }
- }
+ if (far_cross_dist > far_cross_best || far_cross == NULL) {
+ far_cross = vert_arr[i]->co;
+ far_cross_best = far_cross_dist;
+ }
+ }
- sub_v3_v3v3(far_cross_vec, far_cross, cent);
+ sub_v3_v3v3(far_cross_vec, far_cross, cent);
- /* --- */
+ /* --- */
- /* now we have 2 vectors we can have a cross product */
- cross_v3_v3v3(nor, far_vec, far_cross_vec);
- normalize_v3(nor);
- cross_v3_v3v3(sign_vec, far_vec, nor); /* this vector should match 'far_cross_vec' closely */
+ /* now we have 2 vectors we can have a cross product */
+ cross_v3_v3v3(nor, far_vec, far_cross_vec);
+ normalize_v3(nor);
+ cross_v3_v3v3(sign_vec, far_vec, nor); /* this vector should match 'far_cross_vec' closely */
- /* --- */
+ /* --- */
- /* now calculate every points angle around the normal (signed) */
- for (i = 0; i < len; i++) {
- vang[i].sort_value = angle_signed_on_axis_v3v3v3_v3(far, cent, vert_arr[i]->co, nor);
- vang[i].data = i;
- vert_arr_map[i] = vert_arr[i];
- }
+ /* now calculate every points angle around the normal (signed) */
+ for (i = 0; i < len; i++) {
+ vang[i].sort_value = angle_signed_on_axis_v3v3v3_v3(far, cent, vert_arr[i]->co, nor);
+ vang[i].data = i;
+ vert_arr_map[i] = vert_arr[i];
+ }
- /* sort by angle and magic! - we have our ngon */
- qsort(vang, len, sizeof(*vang), BLI_sortutil_cmp_float);
+ /* sort by angle and magic! - we have our ngon */
+ qsort(vang, len, sizeof(*vang), BLI_sortutil_cmp_float);
- /* --- */
+ /* --- */
- for (i = 0; i < len; i++) {
- vert_arr[i] = vert_arr_map[vang[i].data];
- }
+ for (i = 0; i < len; i++) {
+ vert_arr[i] = vert_arr_map[vang[i].data];
+ }
}
/*************************************************************/
-
-static void bm_vert_attrs_copy(
- BMesh *source_mesh, BMesh *target_mesh,
- const BMVert *source_vertex, BMVert *target_vertex, uint64_t cd_mask)
+static void bm_vert_attrs_copy(BMesh *source_mesh,
+ BMesh *target_mesh,
+ const BMVert *source_vertex,
+ BMVert *target_vertex,
+ uint64_t cd_mask)
{
- if ((source_mesh == target_mesh) && (source_vertex == target_vertex)) {
- BLI_assert(!"BMVert: source and targer match");
- return;
- }
- if ((cd_mask & CD_MASK_NORMAL) == 0) {
- copy_v3_v3(target_vertex->no, source_vertex->no);
- }
- CustomData_bmesh_free_block_data(&target_mesh->vdata, target_vertex->head.data);
- CustomData_bmesh_copy_data(&source_mesh->vdata, &target_mesh->vdata,
- source_vertex->head.data, &target_vertex->head.data);
+ if ((source_mesh == target_mesh) && (source_vertex == target_vertex)) {
+ BLI_assert(!"BMVert: source and targer match");
+ return;
+ }
+ if ((cd_mask & CD_MASK_NORMAL) == 0) {
+ copy_v3_v3(target_vertex->no, source_vertex->no);
+ }
+ CustomData_bmesh_free_block_data(&target_mesh->vdata, target_vertex->head.data);
+ CustomData_bmesh_copy_data(&source_mesh->vdata,
+ &target_mesh->vdata,
+ source_vertex->head.data,
+ &target_vertex->head.data);
}
-static void bm_edge_attrs_copy(
- BMesh *source_mesh, BMesh *target_mesh,
- const BMEdge *source_edge, BMEdge *target_edge, uint64_t UNUSED(cd_mask))
+static void bm_edge_attrs_copy(BMesh *source_mesh,
+ BMesh *target_mesh,
+ const BMEdge *source_edge,
+ BMEdge *target_edge,
+ uint64_t UNUSED(cd_mask))
{
- if ((source_mesh == target_mesh) && (source_edge == target_edge)) {
- BLI_assert(!"BMEdge: source and targer match");
- return;
- }
- CustomData_bmesh_free_block_data(&target_mesh->edata, target_edge->head.data);
- CustomData_bmesh_copy_data(&source_mesh->edata, &target_mesh->edata,
- source_edge->head.data, &target_edge->head.data);
+ if ((source_mesh == target_mesh) && (source_edge == target_edge)) {
+ BLI_assert(!"BMEdge: source and targer match");
+ return;
+ }
+ CustomData_bmesh_free_block_data(&target_mesh->edata, target_edge->head.data);
+ CustomData_bmesh_copy_data(
+ &source_mesh->edata, &target_mesh->edata, source_edge->head.data, &target_edge->head.data);
}
-static void bm_loop_attrs_copy(
- BMesh *source_mesh, BMesh *target_mesh,
- const BMLoop *source_loop, BMLoop *target_loop, uint64_t UNUSED(cd_mask))
+static void bm_loop_attrs_copy(BMesh *source_mesh,
+ BMesh *target_mesh,
+ const BMLoop *source_loop,
+ BMLoop *target_loop,
+ uint64_t UNUSED(cd_mask))
{
- if ((source_mesh == target_mesh) && (source_loop == target_loop)) {
- BLI_assert(!"BMLoop: source and targer match");
- return;
- }
- CustomData_bmesh_free_block_data(&target_mesh->ldata, target_loop->head.data);
- CustomData_bmesh_copy_data(&source_mesh->ldata, &target_mesh->ldata,
- source_loop->head.data, &target_loop->head.data);
+ if ((source_mesh == target_mesh) && (source_loop == target_loop)) {
+ BLI_assert(!"BMLoop: source and targer match");
+ return;
+ }
+ CustomData_bmesh_free_block_data(&target_mesh->ldata, target_loop->head.data);
+ CustomData_bmesh_copy_data(
+ &source_mesh->ldata, &target_mesh->ldata, source_loop->head.data, &target_loop->head.data);
}
-static void bm_face_attrs_copy(
- BMesh *source_mesh, BMesh *target_mesh,
- const BMFace *source_face, BMFace *target_face, uint64_t cd_mask)
+static void bm_face_attrs_copy(BMesh *source_mesh,
+ BMesh *target_mesh,
+ const BMFace *source_face,
+ BMFace *target_face,
+ uint64_t cd_mask)
{
- if ((source_mesh == target_mesh) && (source_face == target_face)) {
- BLI_assert(!"BMFace: source and targer match");
- return;
- }
- if ((cd_mask & CD_MASK_NORMAL) == 0) {
- copy_v3_v3(target_face->no, source_face->no);
- }
- CustomData_bmesh_free_block_data(&target_mesh->pdata, target_face->head.data);
- CustomData_bmesh_copy_data(&source_mesh->pdata, &target_mesh->pdata,
- source_face->head.data, &target_face->head.data);
- target_face->mat_nr = source_face->mat_nr;
+ if ((source_mesh == target_mesh) && (source_face == target_face)) {
+ BLI_assert(!"BMFace: source and targer match");
+ return;
+ }
+ if ((cd_mask & CD_MASK_NORMAL) == 0) {
+ copy_v3_v3(target_face->no, source_face->no);
+ }
+ CustomData_bmesh_free_block_data(&target_mesh->pdata, target_face->head.data);
+ CustomData_bmesh_copy_data(
+ &source_mesh->pdata, &target_mesh->pdata, source_face->head.data, &target_face->head.data);
+ target_face->mat_nr = source_face->mat_nr;
}
/* BMESH_TODO: Special handling for hide flags? */
@@ -542,304 +555,293 @@ static void bm_face_attrs_copy(
* Copies attributes, e.g. customdata, header flags, etc, from one element
* to another of the same type.
*/
-void BM_elem_attrs_copy_ex(
- BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v, void *ele_dst_v,
- const char hflag_mask, const uint64_t cd_mask)
+void BM_elem_attrs_copy_ex(BMesh *bm_src,
+ BMesh *bm_dst,
+ const void *ele_src_v,
+ void *ele_dst_v,
+ const char hflag_mask,
+ const uint64_t cd_mask)
{
- const BMHeader *ele_src = ele_src_v;
- BMHeader *ele_dst = ele_dst_v;
-
- BLI_assert(ele_src->htype == ele_dst->htype);
- BLI_assert(ele_src != ele_dst);
-
- /* Only support normal layer at the moment. */
- BLI_assert((cd_mask & ~CD_MASK_NORMAL) == 0);
-
- if ((hflag_mask & BM_ELEM_SELECT) == 0) {
- /* First we copy select */
- if (BM_elem_flag_test((BMElem *)ele_src, BM_ELEM_SELECT)) {
- BM_elem_select_set(bm_dst, (BMElem *)ele_dst, true);
- }
- }
-
- /* Now we copy flags */
- if (hflag_mask == 0) {
- ele_dst->hflag = ele_src->hflag;
- }
- else if (hflag_mask == 0xff) {
- /* pass */
- }
- else {
- ele_dst->hflag = ((ele_dst->hflag & hflag_mask) | (ele_src->hflag & ~hflag_mask));
- }
-
- /* Copy specific attributes */
- switch (ele_dst->htype) {
- case BM_VERT:
- bm_vert_attrs_copy(bm_src, bm_dst, (const BMVert *)ele_src, (BMVert *)ele_dst, cd_mask);
- break;
- case BM_EDGE:
- bm_edge_attrs_copy(bm_src, bm_dst, (const BMEdge *)ele_src, (BMEdge *)ele_dst, cd_mask);
- break;
- case BM_LOOP:
- bm_loop_attrs_copy(bm_src, bm_dst, (const BMLoop *)ele_src, (BMLoop *)ele_dst, cd_mask);
- break;
- case BM_FACE:
- bm_face_attrs_copy(bm_src, bm_dst, (const BMFace *)ele_src, (BMFace *)ele_dst, cd_mask);
- break;
- default:
- BLI_assert(0);
- break;
- }
+ const BMHeader *ele_src = ele_src_v;
+ BMHeader *ele_dst = ele_dst_v;
+
+ BLI_assert(ele_src->htype == ele_dst->htype);
+ BLI_assert(ele_src != ele_dst);
+
+ /* Only support normal layer at the moment. */
+ BLI_assert((cd_mask & ~CD_MASK_NORMAL) == 0);
+
+ if ((hflag_mask & BM_ELEM_SELECT) == 0) {
+ /* First we copy select */
+ if (BM_elem_flag_test((BMElem *)ele_src, BM_ELEM_SELECT)) {
+ BM_elem_select_set(bm_dst, (BMElem *)ele_dst, true);
+ }
+ }
+
+ /* Now we copy flags */
+ if (hflag_mask == 0) {
+ ele_dst->hflag = ele_src->hflag;
+ }
+ else if (hflag_mask == 0xff) {
+ /* pass */
+ }
+ else {
+ ele_dst->hflag = ((ele_dst->hflag & hflag_mask) | (ele_src->hflag & ~hflag_mask));
+ }
+
+ /* Copy specific attributes */
+ switch (ele_dst->htype) {
+ case BM_VERT:
+ bm_vert_attrs_copy(bm_src, bm_dst, (const BMVert *)ele_src, (BMVert *)ele_dst, cd_mask);
+ break;
+ case BM_EDGE:
+ bm_edge_attrs_copy(bm_src, bm_dst, (const BMEdge *)ele_src, (BMEdge *)ele_dst, cd_mask);
+ break;
+ case BM_LOOP:
+ bm_loop_attrs_copy(bm_src, bm_dst, (const BMLoop *)ele_src, (BMLoop *)ele_dst, cd_mask);
+ break;
+ case BM_FACE:
+ bm_face_attrs_copy(bm_src, bm_dst, (const BMFace *)ele_src, (BMFace *)ele_dst, cd_mask);
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
}
void BM_elem_attrs_copy(BMesh *bm_src, BMesh *bm_dst, const void *ele_src, void *ele_dst)
{
- /* BMESH_TODO, default 'use_flags' to false */
- BM_elem_attrs_copy_ex(bm_src, bm_dst, ele_src, ele_dst, BM_ELEM_SELECT, 0x0);
+ /* BMESH_TODO, default 'use_flags' to false */
+ BM_elem_attrs_copy_ex(bm_src, bm_dst, ele_src, ele_dst, BM_ELEM_SELECT, 0x0);
}
void BM_elem_select_copy(BMesh *bm_dst, void *ele_dst_v, const void *ele_src_v)
{
- BMHeader *ele_dst = ele_dst_v;
- const BMHeader *ele_src = ele_src_v;
+ BMHeader *ele_dst = ele_dst_v;
+ const BMHeader *ele_src = ele_src_v;
- BLI_assert(ele_src->htype == ele_dst->htype);
+ BLI_assert(ele_src->htype == ele_dst->htype);
- if ((ele_src->hflag & BM_ELEM_SELECT) != (ele_dst->hflag & BM_ELEM_SELECT)) {
- BM_elem_select_set(bm_dst, (BMElem *)ele_dst, (ele_src->hflag & BM_ELEM_SELECT) != 0);
- }
+ if ((ele_src->hflag & BM_ELEM_SELECT) != (ele_dst->hflag & BM_ELEM_SELECT)) {
+ BM_elem_select_set(bm_dst, (BMElem *)ele_dst, (ele_src->hflag & BM_ELEM_SELECT) != 0);
+ }
}
/* helper function for 'BM_mesh_copy' */
static BMFace *bm_mesh_copy_new_face(
- BMesh *bm_new, BMesh *bm_old,
- BMVert **vtable, BMEdge **etable,
- BMFace *f)
+ BMesh *bm_new, BMesh *bm_old, BMVert **vtable, BMEdge **etable, BMFace *f)
{
- BMLoop **loops = BLI_array_alloca(loops, f->len);
- BMVert **verts = BLI_array_alloca(verts, f->len);
- BMEdge **edges = BLI_array_alloca(edges, f->len);
-
- BMFace *f_new;
- BMLoop *l_iter, *l_first;
- int j;
-
- j = 0;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- loops[j] = l_iter;
- verts[j] = vtable[BM_elem_index_get(l_iter->v)];
- edges[j] = etable[BM_elem_index_get(l_iter->e)];
- j++;
- } while ((l_iter = l_iter->next) != l_first);
-
- f_new = BM_face_create(bm_new, verts, edges, f->len, NULL, BM_CREATE_SKIP_CD);
-
- if (UNLIKELY(f_new == NULL)) {
- return NULL;
- }
-
- /* use totface in case adding some faces fails */
- BM_elem_index_set(f_new, (bm_new->totface - 1)); /* set_inline */
-
- BM_elem_attrs_copy_ex(bm_old, bm_new, f, f_new, 0xff, 0x0);
- f_new->head.hflag = f->head.hflag; /* low level! don't do this for normal api use */
-
- j = 0;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f_new);
- do {
- BM_elem_attrs_copy(bm_old, bm_new, loops[j], l_iter);
- j++;
- } while ((l_iter = l_iter->next) != l_first);
-
- return f_new;
+ BMLoop **loops = BLI_array_alloca(loops, f->len);
+ BMVert **verts = BLI_array_alloca(verts, f->len);
+ BMEdge **edges = BLI_array_alloca(edges, f->len);
+
+ BMFace *f_new;
+ BMLoop *l_iter, *l_first;
+ int j;
+
+ j = 0;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ loops[j] = l_iter;
+ verts[j] = vtable[BM_elem_index_get(l_iter->v)];
+ edges[j] = etable[BM_elem_index_get(l_iter->e)];
+ j++;
+ } while ((l_iter = l_iter->next) != l_first);
+
+ f_new = BM_face_create(bm_new, verts, edges, f->len, NULL, BM_CREATE_SKIP_CD);
+
+ if (UNLIKELY(f_new == NULL)) {
+ return NULL;
+ }
+
+ /* use totface in case adding some faces fails */
+ BM_elem_index_set(f_new, (bm_new->totface - 1)); /* set_inline */
+
+ BM_elem_attrs_copy_ex(bm_old, bm_new, f, f_new, 0xff, 0x0);
+ f_new->head.hflag = f->head.hflag; /* low level! don't do this for normal api use */
+
+ j = 0;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_new);
+ do {
+ BM_elem_attrs_copy(bm_old, bm_new, loops[j], l_iter);
+ j++;
+ } while ((l_iter = l_iter->next) != l_first);
+
+ return f_new;
}
void BM_mesh_copy_init_customdata(BMesh *bm_dst, BMesh *bm_src, const BMAllocTemplate *allocsize)
{
- if (allocsize == NULL) {
- allocsize = &bm_mesh_allocsize_default;
- }
-
- CustomData_copy(&bm_src->vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_CALLOC, 0);
- CustomData_copy(&bm_src->edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_CALLOC, 0);
- CustomData_copy(&bm_src->ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_CALLOC, 0);
- CustomData_copy(&bm_src->pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_CALLOC, 0);
-
- CustomData_bmesh_init_pool(&bm_dst->vdata, allocsize->totvert, BM_VERT);
- CustomData_bmesh_init_pool(&bm_dst->edata, allocsize->totedge, BM_EDGE);
- CustomData_bmesh_init_pool(&bm_dst->ldata, allocsize->totloop, BM_LOOP);
- CustomData_bmesh_init_pool(&bm_dst->pdata, allocsize->totface, BM_FACE);
+ if (allocsize == NULL) {
+ allocsize = &bm_mesh_allocsize_default;
+ }
+
+ CustomData_copy(&bm_src->vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_CALLOC, 0);
+ CustomData_copy(&bm_src->edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_CALLOC, 0);
+ CustomData_copy(&bm_src->ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_CALLOC, 0);
+ CustomData_copy(&bm_src->pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_CALLOC, 0);
+
+ CustomData_bmesh_init_pool(&bm_dst->vdata, allocsize->totvert, BM_VERT);
+ CustomData_bmesh_init_pool(&bm_dst->edata, allocsize->totedge, BM_EDGE);
+ CustomData_bmesh_init_pool(&bm_dst->ldata, allocsize->totloop, BM_LOOP);
+ CustomData_bmesh_init_pool(&bm_dst->pdata, allocsize->totface, BM_FACE);
}
-
BMesh *BM_mesh_copy(BMesh *bm_old)
{
- BMesh *bm_new;
- BMVert *v, *v_new, **vtable = NULL;
- BMEdge *e, *e_new, **etable = NULL;
- BMFace *f, *f_new, **ftable = NULL;
- BMElem **eletable;
- BMEditSelection *ese;
- BMIter iter;
- int i;
- const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_BM(bm_old);
-
- /* allocate a bmesh */
- bm_new = BM_mesh_create(
- &allocsize,
- &((struct BMeshCreateParams){.use_toolflags = bm_old->use_toolflags,}));
-
- BM_mesh_copy_init_customdata(bm_new, bm_old, &allocsize);
-
- vtable = MEM_mallocN(sizeof(BMVert *) * bm_old->totvert, "BM_mesh_copy vtable");
- etable = MEM_mallocN(sizeof(BMEdge *) * bm_old->totedge, "BM_mesh_copy etable");
- ftable = MEM_mallocN(sizeof(BMFace *) * bm_old->totface, "BM_mesh_copy ftable");
-
- BM_ITER_MESH_INDEX (v, &iter, bm_old, BM_VERTS_OF_MESH, i) {
- /* copy between meshes so cant use 'example' argument */
- v_new = BM_vert_create(bm_new, v->co, NULL, BM_CREATE_SKIP_CD);
- BM_elem_attrs_copy_ex(bm_old, bm_new, v, v_new, 0xff, 0x0);
- v_new->head.hflag = v->head.hflag; /* low level! don't do this for normal api use */
- vtable[i] = v_new;
- BM_elem_index_set(v, i); /* set_inline */
- BM_elem_index_set(v_new, i); /* set_inline */
- }
- bm_old->elem_index_dirty &= ~BM_VERT;
- bm_new->elem_index_dirty &= ~BM_VERT;
-
- /* safety check */
- BLI_assert(i == bm_old->totvert);
-
- BM_ITER_MESH_INDEX (e, &iter, bm_old, BM_EDGES_OF_MESH, i) {
- e_new = BM_edge_create(bm_new,
- vtable[BM_elem_index_get(e->v1)],
- vtable[BM_elem_index_get(e->v2)],
- e, BM_CREATE_SKIP_CD);
-
- BM_elem_attrs_copy_ex(bm_old, bm_new, e, e_new, 0xff, 0x0);
- e_new->head.hflag = e->head.hflag; /* low level! don't do this for normal api use */
- etable[i] = e_new;
- BM_elem_index_set(e, i); /* set_inline */
- BM_elem_index_set(e_new, i); /* set_inline */
- }
- bm_old->elem_index_dirty &= ~BM_EDGE;
- bm_new->elem_index_dirty &= ~BM_EDGE;
-
- /* safety check */
- BLI_assert(i == bm_old->totedge);
-
- BM_ITER_MESH_INDEX (f, &iter, bm_old, BM_FACES_OF_MESH, i) {
- BM_elem_index_set(f, i); /* set_inline */
-
- f_new = bm_mesh_copy_new_face(bm_new, bm_old, vtable, etable, f);
-
- ftable[i] = f_new;
-
- if (f == bm_old->act_face) {
- bm_new->act_face = f_new;
- }
- }
- bm_old->elem_index_dirty &= ~BM_FACE;
- bm_new->elem_index_dirty &= ~BM_FACE;
-
-
- /* low level! don't do this for normal api use */
- bm_new->totvertsel = bm_old->totvertsel;
- bm_new->totedgesel = bm_old->totedgesel;
- bm_new->totfacesel = bm_old->totfacesel;
-
- /* safety check */
- BLI_assert(i == bm_old->totface);
-
- /* copy over edit selection history */
- for (ese = bm_old->selected.first; ese; ese = ese->next) {
- BMElem *ele = NULL;
-
- switch (ese->htype) {
- case BM_VERT:
- eletable = (BMElem **)vtable;
- break;
- case BM_EDGE:
- eletable = (BMElem **)etable;
- break;
- case BM_FACE:
- eletable = (BMElem **)ftable;
- break;
- default:
- eletable = NULL;
- break;
- }
-
- if (eletable) {
- ele = eletable[BM_elem_index_get(ese->ele)];
- if (ele) {
- BM_select_history_store(bm_new, ele);
- }
- }
- }
-
- MEM_freeN(etable);
- MEM_freeN(vtable);
- MEM_freeN(ftable);
-
- return bm_new;
+ BMesh *bm_new;
+ BMVert *v, *v_new, **vtable = NULL;
+ BMEdge *e, *e_new, **etable = NULL;
+ BMFace *f, *f_new, **ftable = NULL;
+ BMElem **eletable;
+ BMEditSelection *ese;
+ BMIter iter;
+ int i;
+ const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_BM(bm_old);
+
+ /* allocate a bmesh */
+ bm_new = BM_mesh_create(&allocsize,
+ &((struct BMeshCreateParams){
+ .use_toolflags = bm_old->use_toolflags,
+ }));
+
+ BM_mesh_copy_init_customdata(bm_new, bm_old, &allocsize);
+
+ vtable = MEM_mallocN(sizeof(BMVert *) * bm_old->totvert, "BM_mesh_copy vtable");
+ etable = MEM_mallocN(sizeof(BMEdge *) * bm_old->totedge, "BM_mesh_copy etable");
+ ftable = MEM_mallocN(sizeof(BMFace *) * bm_old->totface, "BM_mesh_copy ftable");
+
+ BM_ITER_MESH_INDEX (v, &iter, bm_old, BM_VERTS_OF_MESH, i) {
+ /* copy between meshes so cant use 'example' argument */
+ v_new = BM_vert_create(bm_new, v->co, NULL, BM_CREATE_SKIP_CD);
+ BM_elem_attrs_copy_ex(bm_old, bm_new, v, v_new, 0xff, 0x0);
+ v_new->head.hflag = v->head.hflag; /* low level! don't do this for normal api use */
+ vtable[i] = v_new;
+ BM_elem_index_set(v, i); /* set_inline */
+ BM_elem_index_set(v_new, i); /* set_inline */
+ }
+ bm_old->elem_index_dirty &= ~BM_VERT;
+ bm_new->elem_index_dirty &= ~BM_VERT;
+
+ /* safety check */
+ BLI_assert(i == bm_old->totvert);
+
+ BM_ITER_MESH_INDEX (e, &iter, bm_old, BM_EDGES_OF_MESH, i) {
+ e_new = BM_edge_create(bm_new,
+ vtable[BM_elem_index_get(e->v1)],
+ vtable[BM_elem_index_get(e->v2)],
+ e,
+ BM_CREATE_SKIP_CD);
+
+ BM_elem_attrs_copy_ex(bm_old, bm_new, e, e_new, 0xff, 0x0);
+ e_new->head.hflag = e->head.hflag; /* low level! don't do this for normal api use */
+ etable[i] = e_new;
+ BM_elem_index_set(e, i); /* set_inline */
+ BM_elem_index_set(e_new, i); /* set_inline */
+ }
+ bm_old->elem_index_dirty &= ~BM_EDGE;
+ bm_new->elem_index_dirty &= ~BM_EDGE;
+
+ /* safety check */
+ BLI_assert(i == bm_old->totedge);
+
+ BM_ITER_MESH_INDEX (f, &iter, bm_old, BM_FACES_OF_MESH, i) {
+ BM_elem_index_set(f, i); /* set_inline */
+
+ f_new = bm_mesh_copy_new_face(bm_new, bm_old, vtable, etable, f);
+
+ ftable[i] = f_new;
+
+ if (f == bm_old->act_face) {
+ bm_new->act_face = f_new;
+ }
+ }
+ bm_old->elem_index_dirty &= ~BM_FACE;
+ bm_new->elem_index_dirty &= ~BM_FACE;
+
+ /* low level! don't do this for normal api use */
+ bm_new->totvertsel = bm_old->totvertsel;
+ bm_new->totedgesel = bm_old->totedgesel;
+ bm_new->totfacesel = bm_old->totfacesel;
+
+ /* safety check */
+ BLI_assert(i == bm_old->totface);
+
+ /* copy over edit selection history */
+ for (ese = bm_old->selected.first; ese; ese = ese->next) {
+ BMElem *ele = NULL;
+
+ switch (ese->htype) {
+ case BM_VERT:
+ eletable = (BMElem **)vtable;
+ break;
+ case BM_EDGE:
+ eletable = (BMElem **)etable;
+ break;
+ case BM_FACE:
+ eletable = (BMElem **)ftable;
+ break;
+ default:
+ eletable = NULL;
+ break;
+ }
+
+ if (eletable) {
+ ele = eletable[BM_elem_index_get(ese->ele)];
+ if (ele) {
+ BM_select_history_store(bm_new, ele);
+ }
+ }
+ }
+
+ MEM_freeN(etable);
+ MEM_freeN(vtable);
+ MEM_freeN(ftable);
+
+ return bm_new;
}
/* ME -> BM */
-char BM_vert_flag_from_mflag(const char meflag)
+char BM_vert_flag_from_mflag(const char meflag)
{
- return ( ((meflag & SELECT) ? BM_ELEM_SELECT : 0) |
- ((meflag & ME_HIDE) ? BM_ELEM_HIDDEN : 0)
- );
+ return (((meflag & SELECT) ? BM_ELEM_SELECT : 0) | ((meflag & ME_HIDE) ? BM_ELEM_HIDDEN : 0));
}
char BM_edge_flag_from_mflag(const short meflag)
{
- return ( ((meflag & SELECT) ? BM_ELEM_SELECT : 0) |
- ((meflag & ME_SEAM) ? BM_ELEM_SEAM : 0) |
- ((meflag & ME_EDGEDRAW) ? BM_ELEM_DRAW : 0) |
- ((meflag & ME_SHARP) == 0 ? BM_ELEM_SMOOTH : 0) | /* invert */
- ((meflag & ME_HIDE) ? BM_ELEM_HIDDEN : 0)
- );
+ return (((meflag & SELECT) ? BM_ELEM_SELECT : 0) | ((meflag & ME_SEAM) ? BM_ELEM_SEAM : 0) |
+ ((meflag & ME_EDGEDRAW) ? BM_ELEM_DRAW : 0) |
+ ((meflag & ME_SHARP) == 0 ? BM_ELEM_SMOOTH : 0) | /* invert */
+ ((meflag & ME_HIDE) ? BM_ELEM_HIDDEN : 0));
}
-char BM_face_flag_from_mflag(const char meflag)
+char BM_face_flag_from_mflag(const char meflag)
{
- return ( ((meflag & ME_FACE_SEL) ? BM_ELEM_SELECT : 0) |
- ((meflag & ME_SMOOTH) ? BM_ELEM_SMOOTH : 0) |
- ((meflag & ME_HIDE) ? BM_ELEM_HIDDEN : 0)
- );
+ return (((meflag & ME_FACE_SEL) ? BM_ELEM_SELECT : 0) |
+ ((meflag & ME_SMOOTH) ? BM_ELEM_SMOOTH : 0) | ((meflag & ME_HIDE) ? BM_ELEM_HIDDEN : 0));
}
/* BM -> ME */
-char BM_vert_flag_to_mflag(BMVert *eve)
+char BM_vert_flag_to_mflag(BMVert *eve)
{
- const char hflag = eve->head.hflag;
+ const char hflag = eve->head.hflag;
- return ( ((hflag & BM_ELEM_SELECT) ? SELECT : 0) |
- ((hflag & BM_ELEM_HIDDEN) ? ME_HIDE : 0)
- );
+ return (((hflag & BM_ELEM_SELECT) ? SELECT : 0) | ((hflag & BM_ELEM_HIDDEN) ? ME_HIDE : 0));
}
short BM_edge_flag_to_mflag(BMEdge *eed)
{
- const char hflag = eed->head.hflag;
-
- return ( ((hflag & BM_ELEM_SELECT) ? SELECT : 0) |
- ((hflag & BM_ELEM_SEAM) ? ME_SEAM : 0) |
- ((hflag & BM_ELEM_DRAW) ? ME_EDGEDRAW : 0) |
- ((hflag & BM_ELEM_SMOOTH) == 0 ? ME_SHARP : 0) |
- ((hflag & BM_ELEM_HIDDEN) ? ME_HIDE : 0) |
- ((BM_edge_is_wire(eed)) ? ME_LOOSEEDGE : 0) | /* not typical */
- ME_EDGERENDER
- );
+ const char hflag = eed->head.hflag;
+
+ return (((hflag & BM_ELEM_SELECT) ? SELECT : 0) | ((hflag & BM_ELEM_SEAM) ? ME_SEAM : 0) |
+ ((hflag & BM_ELEM_DRAW) ? ME_EDGEDRAW : 0) |
+ ((hflag & BM_ELEM_SMOOTH) == 0 ? ME_SHARP : 0) |
+ ((hflag & BM_ELEM_HIDDEN) ? ME_HIDE : 0) |
+ ((BM_edge_is_wire(eed)) ? ME_LOOSEEDGE : 0) | /* not typical */
+ ME_EDGERENDER);
}
-char BM_face_flag_to_mflag(BMFace *efa)
+char BM_face_flag_to_mflag(BMFace *efa)
{
- const char hflag = efa->head.hflag;
+ const char hflag = efa->head.hflag;
- return ( ((hflag & BM_ELEM_SELECT) ? ME_FACE_SEL : 0) |
- ((hflag & BM_ELEM_SMOOTH) ? ME_SMOOTH : 0) |
- ((hflag & BM_ELEM_HIDDEN) ? ME_HIDE : 0)
- );
+ return (((hflag & BM_ELEM_SELECT) ? ME_FACE_SEL : 0) |
+ ((hflag & BM_ELEM_SMOOTH) ? ME_SMOOTH : 0) | ((hflag & BM_ELEM_HIDDEN) ? ME_HIDE : 0));
}
diff --git a/source/blender/bmesh/intern/bmesh_construct.h b/source/blender/bmesh/intern/bmesh_construct.h
index 0dfa0a81b91..0b285979369 100644
--- a/source/blender/bmesh/intern/bmesh_construct.h
+++ b/source/blender/bmesh/intern/bmesh_construct.h
@@ -29,38 +29,52 @@ bool BM_edges_from_verts(BMEdge **edge_arr, BMVert **vert_arr, const int len);
void BM_edges_from_verts_ensure(BMesh *bm, BMEdge **edge_arr, BMVert **vert_arr, const int len);
/* sort before creation */
-void BM_verts_sort_radial_plane(BMVert **vert_arr, int len);
+void BM_verts_sort_radial_plane(BMVert **vert_arr, int len);
-BMFace *BM_face_create_quad_tri(
- BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
- const BMFace *f_example, const eBMCreateFlag create_flag);
+BMFace *BM_face_create_quad_tri(BMesh *bm,
+ BMVert *v1,
+ BMVert *v2,
+ BMVert *v3,
+ BMVert *v4,
+ const BMFace *f_example,
+ const eBMCreateFlag create_flag);
-void BM_face_copy_shared(
- BMesh *bm, BMFace *f,
- BMLoopFilterFunc filter_fn, void *user_data);
+void BM_face_copy_shared(BMesh *bm, BMFace *f, BMLoopFilterFunc filter_fn, void *user_data);
-BMFace *BM_face_create_ngon(
- BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, const int len,
- const BMFace *f_example, const eBMCreateFlag create_flag);
-BMFace *BM_face_create_ngon_verts(
- BMesh *bm, BMVert **vert_arr, const int len,
- const BMFace *f_example, const eBMCreateFlag create_flag,
- const bool calc_winding, const bool create_edges);
+BMFace *BM_face_create_ngon(BMesh *bm,
+ BMVert *v1,
+ BMVert *v2,
+ BMEdge **edges,
+ const int len,
+ const BMFace *f_example,
+ const eBMCreateFlag create_flag);
+BMFace *BM_face_create_ngon_verts(BMesh *bm,
+ BMVert **vert_arr,
+ const int len,
+ const BMFace *f_example,
+ const eBMCreateFlag create_flag,
+ const bool calc_winding,
+ const bool create_edges);
-void BM_elem_attrs_copy_ex(
- BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v, void *ele_dst_v,
- const char hflag_mask, const uint64_t cd_mask);
+void BM_elem_attrs_copy_ex(BMesh *bm_src,
+ BMesh *bm_dst,
+ const void *ele_src_v,
+ void *ele_dst_v,
+ const char hflag_mask,
+ const uint64_t cd_mask);
void BM_elem_attrs_copy(BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v, void *ele_dst_v);
void BM_elem_select_copy(BMesh *bm_dst, void *ele_dst_v, const void *ele_src_v);
-void BM_mesh_copy_init_customdata(BMesh *bm_dst, BMesh *bm_src, const struct BMAllocTemplate *allocsize);
+void BM_mesh_copy_init_customdata(BMesh *bm_dst,
+ BMesh *bm_src,
+ const struct BMAllocTemplate *allocsize);
BMesh *BM_mesh_copy(BMesh *bm_old);
-char BM_face_flag_from_mflag(const char mflag);
-char BM_edge_flag_from_mflag(const short mflag);
-char BM_vert_flag_from_mflag(const char mflag);
-char BM_face_flag_to_mflag(BMFace *f);
+char BM_face_flag_from_mflag(const char mflag);
+char BM_edge_flag_from_mflag(const short mflag);
+char BM_vert_flag_from_mflag(const char mflag);
+char BM_face_flag_to_mflag(BMFace *f);
short BM_edge_flag_to_mflag(BMEdge *e);
-char BM_vert_flag_to_mflag(BMVert *v);
+char BM_vert_flag_to_mflag(BMVert *v);
#endif /* __BMESH_CONSTRUCT_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c
index 58b83cd0586..5dcf6acad57 100644
--- a/source/blender/bmesh/intern/bmesh_core.c
+++ b/source/blender/bmesh/intern/bmesh_core.c
@@ -43,96 +43,97 @@
// #define USE_DEBUG_INDEX_MEMCHECK
#ifdef USE_DEBUG_INDEX_MEMCHECK
-#define DEBUG_MEMCHECK_INDEX_INVALIDATE(ele) \
- { \
- int undef_idx; \
- BM_elem_index_set(ele, undef_idx); /* set_ok_invalid */ \
- } (void)0
+# define DEBUG_MEMCHECK_INDEX_INVALIDATE(ele) \
+ { \
+ int undef_idx; \
+ BM_elem_index_set(ele, undef_idx); /* set_ok_invalid */ \
+ } \
+ (void)0
#endif
/**
* \brief Main function for creating a new vertex.
*/
-BMVert *BM_vert_create(
- BMesh *bm, const float co[3],
- const BMVert *v_example, const eBMCreateFlag create_flag)
+BMVert *BM_vert_create(BMesh *bm,
+ const float co[3],
+ const BMVert *v_example,
+ const eBMCreateFlag create_flag)
{
- BMVert *v = BLI_mempool_alloc(bm->vpool);
+ BMVert *v = BLI_mempool_alloc(bm->vpool);
- BLI_assert((v_example == NULL) || (v_example->head.htype == BM_VERT));
- BLI_assert(!(create_flag & 1));
+ BLI_assert((v_example == NULL) || (v_example->head.htype == BM_VERT));
+ BLI_assert(!(create_flag & 1));
- /* --- assign all members --- */
- v->head.data = NULL;
+ /* --- assign all members --- */
+ v->head.data = NULL;
#ifdef USE_DEBUG_INDEX_MEMCHECK
- DEBUG_MEMCHECK_INDEX_INVALIDATE(v)
+ DEBUG_MEMCHECK_INDEX_INVALIDATE(v)
#else
- BM_elem_index_set(v, -1); /* set_ok_invalid */
+ BM_elem_index_set(v, -1); /* set_ok_invalid */
#endif
- v->head.htype = BM_VERT;
- v->head.hflag = 0;
- v->head.api_flag = 0;
-
- /* allocate flags */
- if (bm->use_toolflags) {
- ((BMVert_OFlag *)v)->oflags = bm->vtoolflagpool ? BLI_mempool_calloc(bm->vtoolflagpool) : NULL;
- }
-
- /* 'v->no' is handled by BM_elem_attrs_copy */
- if (co) {
- copy_v3_v3(v->co, co);
- }
- else {
- zero_v3(v->co);
- }
- /* 'v->no' set below */
-
- v->e = NULL;
- /* --- done --- */
-
-
- /* disallow this flag for verts - its meaningless */
- BLI_assert((create_flag & BM_CREATE_NO_DOUBLE) == 0);
-
- /* may add to middle of the pool */
- bm->elem_index_dirty |= BM_VERT;
- bm->elem_table_dirty |= BM_VERT;
-
- bm->totvert++;
-
- if (!(create_flag & BM_CREATE_SKIP_CD)) {
- if (v_example) {
- int *keyi;
-
- /* handles 'v->no' too */
- BM_elem_attrs_copy(bm, bm, v_example, v);
-
- /* exception: don't copy the original shapekey index */
- keyi = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_SHAPE_KEYINDEX);
- if (keyi) {
- *keyi = ORIGINDEX_NONE;
- }
- }
- else {
- CustomData_bmesh_set_default(&bm->vdata, &v->head.data);
- zero_v3(v->no);
- }
- }
- else {
- if (v_example) {
- copy_v3_v3(v->no, v_example->no);
- }
- else {
- zero_v3(v->no);
- }
- }
-
- BM_CHECK_ELEMENT(v);
-
- return v;
+ v->head.htype = BM_VERT;
+ v->head.hflag = 0;
+ v->head.api_flag = 0;
+
+ /* allocate flags */
+ if (bm->use_toolflags) {
+ ((BMVert_OFlag *)v)->oflags = bm->vtoolflagpool ? BLI_mempool_calloc(bm->vtoolflagpool) : NULL;
+ }
+
+ /* 'v->no' is handled by BM_elem_attrs_copy */
+ if (co) {
+ copy_v3_v3(v->co, co);
+ }
+ else {
+ zero_v3(v->co);
+ }
+ /* 'v->no' set below */
+
+ v->e = NULL;
+ /* --- done --- */
+
+ /* disallow this flag for verts - its meaningless */
+ BLI_assert((create_flag & BM_CREATE_NO_DOUBLE) == 0);
+
+ /* may add to middle of the pool */
+ bm->elem_index_dirty |= BM_VERT;
+ bm->elem_table_dirty |= BM_VERT;
+
+ bm->totvert++;
+
+ if (!(create_flag & BM_CREATE_SKIP_CD)) {
+ if (v_example) {
+ int *keyi;
+
+ /* handles 'v->no' too */
+ BM_elem_attrs_copy(bm, bm, v_example, v);
+
+ /* exception: don't copy the original shapekey index */
+ keyi = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_SHAPE_KEYINDEX);
+ if (keyi) {
+ *keyi = ORIGINDEX_NONE;
+ }
+ }
+ else {
+ CustomData_bmesh_set_default(&bm->vdata, &v->head.data);
+ zero_v3(v->no);
+ }
+ }
+ else {
+ if (v_example) {
+ copy_v3_v3(v->no, v_example->no);
+ }
+ else {
+ zero_v3(v->no);
+ }
+ }
+
+ BM_CHECK_ELEMENT(v);
+
+ return v;
}
/**
@@ -142,70 +143,67 @@ BMVert *BM_vert_create(
* so unless you need a unique edge or know the edge won't exist, you should call with \a no_double = true
*/
BMEdge *BM_edge_create(
- BMesh *bm, BMVert *v1, BMVert *v2,
- const BMEdge *e_example, const eBMCreateFlag create_flag)
+ BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *e_example, const eBMCreateFlag create_flag)
{
- BMEdge *e;
+ BMEdge *e;
- BLI_assert(v1 != v2);
- BLI_assert(v1->head.htype == BM_VERT && v2->head.htype == BM_VERT);
- BLI_assert((e_example == NULL) || (e_example->head.htype == BM_EDGE));
- BLI_assert(!(create_flag & 1));
+ BLI_assert(v1 != v2);
+ BLI_assert(v1->head.htype == BM_VERT && v2->head.htype == BM_VERT);
+ BLI_assert((e_example == NULL) || (e_example->head.htype == BM_EDGE));
+ BLI_assert(!(create_flag & 1));
- if ((create_flag & BM_CREATE_NO_DOUBLE) && (e = BM_edge_exists(v1, v2))) {
- return e;
- }
+ if ((create_flag & BM_CREATE_NO_DOUBLE) && (e = BM_edge_exists(v1, v2))) {
+ return e;
+ }
- e = BLI_mempool_alloc(bm->epool);
+ e = BLI_mempool_alloc(bm->epool);
-
- /* --- assign all members --- */
- e->head.data = NULL;
+ /* --- assign all members --- */
+ e->head.data = NULL;
#ifdef USE_DEBUG_INDEX_MEMCHECK
- DEBUG_MEMCHECK_INDEX_INVALIDATE(e)
+ DEBUG_MEMCHECK_INDEX_INVALIDATE(e)
#else
- BM_elem_index_set(e, -1); /* set_ok_invalid */
+ BM_elem_index_set(e, -1); /* set_ok_invalid */
#endif
- e->head.htype = BM_EDGE;
- e->head.hflag = BM_ELEM_SMOOTH | BM_ELEM_DRAW;
- e->head.api_flag = 0;
-
- /* allocate flags */
- if (bm->use_toolflags) {
- ((BMEdge_OFlag *)e)->oflags = bm->etoolflagpool ? BLI_mempool_calloc(bm->etoolflagpool) : NULL;
- }
+ e->head.htype = BM_EDGE;
+ e->head.hflag = BM_ELEM_SMOOTH | BM_ELEM_DRAW;
+ e->head.api_flag = 0;
- e->v1 = v1;
- e->v2 = v2;
- e->l = NULL;
+ /* allocate flags */
+ if (bm->use_toolflags) {
+ ((BMEdge_OFlag *)e)->oflags = bm->etoolflagpool ? BLI_mempool_calloc(bm->etoolflagpool) : NULL;
+ }
- memset(&e->v1_disk_link, 0, sizeof(BMDiskLink) * 2);
- /* --- done --- */
+ e->v1 = v1;
+ e->v2 = v2;
+ e->l = NULL;
+ memset(&e->v1_disk_link, 0, sizeof(BMDiskLink) * 2);
+ /* --- done --- */
- bmesh_disk_edge_append(e, e->v1);
- bmesh_disk_edge_append(e, e->v2);
+ bmesh_disk_edge_append(e, e->v1);
+ bmesh_disk_edge_append(e, e->v2);
- /* may add to middle of the pool */
- bm->elem_index_dirty |= BM_EDGE;
- bm->elem_table_dirty |= BM_EDGE;
+ /* may add to middle of the pool */
+ bm->elem_index_dirty |= BM_EDGE;
+ bm->elem_table_dirty |= BM_EDGE;
- bm->totedge++;
+ bm->totedge++;
- if (!(create_flag & BM_CREATE_SKIP_CD)) {
- if (e_example) {
- BM_elem_attrs_copy(bm, bm, e_example, e);
- }
- else {
- CustomData_bmesh_set_default(&bm->edata, &e->head.data);
- }
- }
+ if (!(create_flag & BM_CREATE_SKIP_CD)) {
+ if (e_example) {
+ BM_elem_attrs_copy(bm, bm, e_example, e);
+ }
+ else {
+ CustomData_bmesh_set_default(&bm->edata, &e->head.data);
+ }
+ }
- BM_CHECK_ELEMENT(e);
+ BM_CHECK_ELEMENT(e);
- return e;
+ return e;
}
/**
@@ -213,150 +211,151 @@ BMEdge *BM_edge_create(
* since this is a low level API and we shouldn't attempt to be clever and guess whats intended.
* In cases where copying adjacent loop-data is useful, see #BM_face_copy_shared.
*/
-static BMLoop *bm_loop_create(
- BMesh *bm, BMVert *v, BMEdge *e, BMFace *f,
- const BMLoop *l_example, const eBMCreateFlag create_flag)
+static BMLoop *bm_loop_create(BMesh *bm,
+ BMVert *v,
+ BMEdge *e,
+ BMFace *f,
+ const BMLoop *l_example,
+ const eBMCreateFlag create_flag)
{
- BMLoop *l = NULL;
+ BMLoop *l = NULL;
- l = BLI_mempool_alloc(bm->lpool);
+ l = BLI_mempool_alloc(bm->lpool);
- BLI_assert((l_example == NULL) || (l_example->head.htype == BM_LOOP));
- BLI_assert(!(create_flag & 1));
+ BLI_assert((l_example == NULL) || (l_example->head.htype == BM_LOOP));
+ BLI_assert(!(create_flag & 1));
#ifndef NDEBUG
- if (l_example) {
- /* ensure passing a loop is either sharing the same vertex, or entirely disconnected
- * use to catch mistake passing in loop offset-by-one. */
- BLI_assert((v == l_example->v) || !ELEM(v, l_example->prev->v, l_example->next->v));
- }
+ if (l_example) {
+ /* ensure passing a loop is either sharing the same vertex, or entirely disconnected
+ * use to catch mistake passing in loop offset-by-one. */
+ BLI_assert((v == l_example->v) || !ELEM(v, l_example->prev->v, l_example->next->v));
+ }
#endif
- /* --- assign all members --- */
- l->head.data = NULL;
+ /* --- assign all members --- */
+ l->head.data = NULL;
#ifdef USE_DEBUG_INDEX_MEMCHECK
- DEBUG_MEMCHECK_INDEX_INVALIDATE(l)
+ DEBUG_MEMCHECK_INDEX_INVALIDATE(l)
#else
- BM_elem_index_set(l, -1); /* set_ok_invalid */
+ BM_elem_index_set(l, -1); /* set_ok_invalid */
#endif
- l->head.htype = BM_LOOP;
- l->head.hflag = 0;
- l->head.api_flag = 0;
-
- l->v = v;
- l->e = e;
- l->f = f;
-
- l->radial_next = NULL;
- l->radial_prev = NULL;
- l->next = NULL;
- l->prev = NULL;
- /* --- done --- */
-
- /* may add to middle of the pool */
- bm->elem_index_dirty |= BM_LOOP;
-
- bm->totloop++;
-
- if (!(create_flag & BM_CREATE_SKIP_CD)) {
- if (l_example) {
- /* no need to copy attrs, just handle customdata */
- // BM_elem_attrs_copy(bm, bm, l_example, l);
- CustomData_bmesh_free_block_data(&bm->ldata, l->head.data);
- CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, l_example->head.data, &l->head.data);
- }
- else {
- CustomData_bmesh_set_default(&bm->ldata, &l->head.data);
- }
- }
-
- return l;
+ l->head.htype = BM_LOOP;
+ l->head.hflag = 0;
+ l->head.api_flag = 0;
+
+ l->v = v;
+ l->e = e;
+ l->f = f;
+
+ l->radial_next = NULL;
+ l->radial_prev = NULL;
+ l->next = NULL;
+ l->prev = NULL;
+ /* --- done --- */
+
+ /* may add to middle of the pool */
+ bm->elem_index_dirty |= BM_LOOP;
+
+ bm->totloop++;
+
+ if (!(create_flag & BM_CREATE_SKIP_CD)) {
+ if (l_example) {
+ /* no need to copy attrs, just handle customdata */
+ // BM_elem_attrs_copy(bm, bm, l_example, l);
+ CustomData_bmesh_free_block_data(&bm->ldata, l->head.data);
+ CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, l_example->head.data, &l->head.data);
+ }
+ else {
+ CustomData_bmesh_set_default(&bm->ldata, &l->head.data);
+ }
+ }
+
+ return l;
}
static BMLoop *bm_face_boundary_add(
- BMesh *bm, BMFace *f, BMVert *startv, BMEdge *starte,
- const eBMCreateFlag create_flag)
+ BMesh *bm, BMFace *f, BMVert *startv, BMEdge *starte, const eBMCreateFlag create_flag)
{
#ifdef USE_BMESH_HOLES
- BMLoopList *lst = BLI_mempool_calloc(bm->looplistpool);
+ BMLoopList *lst = BLI_mempool_calloc(bm->looplistpool);
#endif
- BMLoop *l = bm_loop_create(bm, startv, starte, f, NULL /* starte->l */, create_flag);
+ BMLoop *l = bm_loop_create(bm, startv, starte, f, NULL /* starte->l */, create_flag);
- bmesh_radial_loop_append(starte, l);
+ bmesh_radial_loop_append(starte, l);
#ifdef USE_BMESH_HOLES
- lst->first = lst->last = l;
- BLI_addtail(&f->loops, lst);
+ lst->first = lst->last = l;
+ BLI_addtail(&f->loops, lst);
#else
- f->l_first = l;
+ f->l_first = l;
#endif
- return l;
+ return l;
}
BMFace *BM_face_copy(
- BMesh *bm_dst, BMesh *bm_src, BMFace *f,
- const bool copy_verts, const bool copy_edges)
+ BMesh *bm_dst, BMesh *bm_src, BMFace *f, const bool copy_verts, const bool copy_edges)
{
- BMVert **verts = BLI_array_alloca(verts, f->len);
- BMEdge **edges = BLI_array_alloca(edges, f->len);
- BMLoop *l_iter;
- BMLoop *l_first;
- BMLoop *l_copy;
- BMFace *f_copy;
- int i;
-
- BLI_assert((bm_dst == bm_src) || (copy_verts && copy_edges));
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- i = 0;
- do {
- if (copy_verts) {
- verts[i] = BM_vert_create(bm_dst, l_iter->v->co, l_iter->v, BM_CREATE_NOP);
- }
- else {
- verts[i] = l_iter->v;
- }
- i++;
- } while ((l_iter = l_iter->next) != l_first);
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- i = 0;
- do {
- if (copy_edges) {
- BMVert *v1, *v2;
-
- if (l_iter->e->v1 == verts[i]) {
- v1 = verts[i];
- v2 = verts[(i + 1) % f->len];
- }
- else {
- v2 = verts[i];
- v1 = verts[(i + 1) % f->len];
- }
-
- edges[i] = BM_edge_create(bm_dst, v1, v2, l_iter->e, BM_CREATE_NOP);
- }
- else {
- edges[i] = l_iter->e;
- }
- i++;
- } while ((l_iter = l_iter->next) != l_first);
-
- f_copy = BM_face_create(bm_dst, verts, edges, f->len, NULL, BM_CREATE_SKIP_CD);
-
- BM_elem_attrs_copy(bm_src, bm_dst, f, f_copy);
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- l_copy = BM_FACE_FIRST_LOOP(f_copy);
- do {
- BM_elem_attrs_copy(bm_src, bm_dst, l_iter, l_copy);
- l_copy = l_copy->next;
- } while ((l_iter = l_iter->next) != l_first);
-
- return f_copy;
+ BMVert **verts = BLI_array_alloca(verts, f->len);
+ BMEdge **edges = BLI_array_alloca(edges, f->len);
+ BMLoop *l_iter;
+ BMLoop *l_first;
+ BMLoop *l_copy;
+ BMFace *f_copy;
+ int i;
+
+ BLI_assert((bm_dst == bm_src) || (copy_verts && copy_edges));
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ i = 0;
+ do {
+ if (copy_verts) {
+ verts[i] = BM_vert_create(bm_dst, l_iter->v->co, l_iter->v, BM_CREATE_NOP);
+ }
+ else {
+ verts[i] = l_iter->v;
+ }
+ i++;
+ } while ((l_iter = l_iter->next) != l_first);
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ i = 0;
+ do {
+ if (copy_edges) {
+ BMVert *v1, *v2;
+
+ if (l_iter->e->v1 == verts[i]) {
+ v1 = verts[i];
+ v2 = verts[(i + 1) % f->len];
+ }
+ else {
+ v2 = verts[i];
+ v1 = verts[(i + 1) % f->len];
+ }
+
+ edges[i] = BM_edge_create(bm_dst, v1, v2, l_iter->e, BM_CREATE_NOP);
+ }
+ else {
+ edges[i] = l_iter->e;
+ }
+ i++;
+ } while ((l_iter = l_iter->next) != l_first);
+
+ f_copy = BM_face_create(bm_dst, verts, edges, f->len, NULL, BM_CREATE_SKIP_CD);
+
+ BM_elem_attrs_copy(bm_src, bm_dst, f, f_copy);
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ l_copy = BM_FACE_FIRST_LOOP(f_copy);
+ do {
+ BM_elem_attrs_copy(bm_src, bm_dst, l_iter, l_copy);
+ l_copy = l_copy->next;
+ } while ((l_iter = l_iter->next) != l_first);
+
+ return f_copy;
}
/**
@@ -367,51 +366,49 @@ BMFace *BM_face_copy(
*/
BLI_INLINE BMFace *bm_face_create__internal(BMesh *bm)
{
- BMFace *f;
+ BMFace *f;
- f = BLI_mempool_alloc(bm->fpool);
+ f = BLI_mempool_alloc(bm->fpool);
-
- /* --- assign all members --- */
- f->head.data = NULL;
+ /* --- assign all members --- */
+ f->head.data = NULL;
#ifdef USE_DEBUG_INDEX_MEMCHECK
- DEBUG_MEMCHECK_INDEX_INVALIDATE(f)
+ DEBUG_MEMCHECK_INDEX_INVALIDATE(f)
#else
- BM_elem_index_set(f, -1); /* set_ok_invalid */
+ BM_elem_index_set(f, -1); /* set_ok_invalid */
#endif
- f->head.htype = BM_FACE;
- f->head.hflag = 0;
- f->head.api_flag = 0;
+ f->head.htype = BM_FACE;
+ f->head.hflag = 0;
+ f->head.api_flag = 0;
- /* allocate flags */
- if (bm->use_toolflags) {
- ((BMFace_OFlag *)f)->oflags = bm->ftoolflagpool ? BLI_mempool_calloc(bm->ftoolflagpool) : NULL;
- }
+ /* allocate flags */
+ if (bm->use_toolflags) {
+ ((BMFace_OFlag *)f)->oflags = bm->ftoolflagpool ? BLI_mempool_calloc(bm->ftoolflagpool) : NULL;
+ }
#ifdef USE_BMESH_HOLES
- BLI_listbase_clear(&f->loops);
+ BLI_listbase_clear(&f->loops);
#else
- f->l_first = NULL;
+ f->l_first = NULL;
#endif
- f->len = 0;
- /* caller must initialize */
- // zero_v3(f->no);
- f->mat_nr = 0;
- /* --- done --- */
-
+ f->len = 0;
+ /* caller must initialize */
+ // zero_v3(f->no);
+ f->mat_nr = 0;
+ /* --- done --- */
- /* may add to middle of the pool */
- bm->elem_index_dirty |= BM_FACE;
- bm->elem_table_dirty |= BM_FACE;
+ /* may add to middle of the pool */
+ bm->elem_index_dirty |= BM_FACE;
+ bm->elem_table_dirty |= BM_FACE;
- bm->totface++;
+ bm->totface++;
#ifdef USE_BMESH_HOLES
- f->totbounds = 0;
+ f->totbounds = 0;
#endif
- return f;
+ return f;
}
/**
@@ -423,91 +420,97 @@ BLI_INLINE BMFace *bm_face_create__internal(BMesh *bm)
* \param len: Length of the face
* \param create_flag: Options for creating the face
*/
-BMFace *BM_face_create(
- BMesh *bm, BMVert **verts, BMEdge **edges, const int len,
- const BMFace *f_example, const eBMCreateFlag create_flag)
+BMFace *BM_face_create(BMesh *bm,
+ BMVert **verts,
+ BMEdge **edges,
+ const int len,
+ const BMFace *f_example,
+ const eBMCreateFlag create_flag)
{
- BMFace *f = NULL;
- BMLoop *l, *startl, *lastl;
- int i;
-
- BLI_assert((f_example == NULL) || (f_example->head.htype == BM_FACE));
- BLI_assert(!(create_flag & 1));
-
- if (len == 0) {
- /* just return NULL for now */
- return NULL;
- }
-
- if (create_flag & BM_CREATE_NO_DOUBLE) {
- /* Check if face already exists */
- f = BM_face_exists(verts, len);
- if (f != NULL) {
- return f;
- }
- }
-
- f = bm_face_create__internal(bm);
-
- startl = lastl = bm_face_boundary_add(bm, f, verts[0], edges[0], create_flag);
-
- for (i = 1; i < len; i++) {
- l = bm_loop_create(bm, verts[i], edges[i], f, NULL /* edges[i]->l */, create_flag);
-
- bmesh_radial_loop_append(edges[i], l);
-
- l->prev = lastl;
- lastl->next = l;
- lastl = l;
- }
-
- startl->prev = lastl;
- lastl->next = startl;
-
- f->len = len;
-
- if (!(create_flag & BM_CREATE_SKIP_CD)) {
- if (f_example) {
- BM_elem_attrs_copy(bm, bm, f_example, f);
- }
- else {
- CustomData_bmesh_set_default(&bm->pdata, &f->head.data);
- zero_v3(f->no);
- }
- }
- else {
- if (f_example) {
- copy_v3_v3(f->no, f_example->no);
- }
- else {
- zero_v3(f->no);
- }
- }
-
- BM_CHECK_ELEMENT(f);
-
- return f;
+ BMFace *f = NULL;
+ BMLoop *l, *startl, *lastl;
+ int i;
+
+ BLI_assert((f_example == NULL) || (f_example->head.htype == BM_FACE));
+ BLI_assert(!(create_flag & 1));
+
+ if (len == 0) {
+ /* just return NULL for now */
+ return NULL;
+ }
+
+ if (create_flag & BM_CREATE_NO_DOUBLE) {
+ /* Check if face already exists */
+ f = BM_face_exists(verts, len);
+ if (f != NULL) {
+ return f;
+ }
+ }
+
+ f = bm_face_create__internal(bm);
+
+ startl = lastl = bm_face_boundary_add(bm, f, verts[0], edges[0], create_flag);
+
+ for (i = 1; i < len; i++) {
+ l = bm_loop_create(bm, verts[i], edges[i], f, NULL /* edges[i]->l */, create_flag);
+
+ bmesh_radial_loop_append(edges[i], l);
+
+ l->prev = lastl;
+ lastl->next = l;
+ lastl = l;
+ }
+
+ startl->prev = lastl;
+ lastl->next = startl;
+
+ f->len = len;
+
+ if (!(create_flag & BM_CREATE_SKIP_CD)) {
+ if (f_example) {
+ BM_elem_attrs_copy(bm, bm, f_example, f);
+ }
+ else {
+ CustomData_bmesh_set_default(&bm->pdata, &f->head.data);
+ zero_v3(f->no);
+ }
+ }
+ else {
+ if (f_example) {
+ copy_v3_v3(f->no, f_example->no);
+ }
+ else {
+ zero_v3(f->no);
+ }
+ }
+
+ BM_CHECK_ELEMENT(f);
+
+ return f;
}
/**
* Wrapper for #BM_face_create when you don't have an edge array
*/
-BMFace *BM_face_create_verts(
- BMesh *bm, BMVert **vert_arr, const int len,
- const BMFace *f_example, const eBMCreateFlag create_flag, const bool create_edges)
+BMFace *BM_face_create_verts(BMesh *bm,
+ BMVert **vert_arr,
+ const int len,
+ const BMFace *f_example,
+ const eBMCreateFlag create_flag,
+ const bool create_edges)
{
- BMEdge **edge_arr = BLI_array_alloca(edge_arr, len);
-
- if (create_edges) {
- BM_edges_from_verts_ensure(bm, edge_arr, vert_arr, len);
- }
- else {
- if (BM_edges_from_verts(edge_arr, vert_arr, len) == false) {
- return NULL;
- }
- }
-
- return BM_face_create(bm, vert_arr, edge_arr, len, f_example, create_flag);
+ BMEdge **edge_arr = BLI_array_alloca(edge_arr, len);
+
+ if (create_edges) {
+ BM_edges_from_verts_ensure(bm, edge_arr, vert_arr, len);
+ }
+ else {
+ if (BM_edges_from_verts(edge_arr, vert_arr, len) == false) {
+ return NULL;
+ }
+ }
+
+ return BM_face_create(bm, vert_arr, edge_arr, len, f_example, create_flag);
}
#ifndef NDEBUG
@@ -520,221 +523,217 @@ BMFace *BM_face_create_verts(
*/
int bmesh_elem_check(void *element, const char htype)
{
- BMHeader *head = element;
- enum {
- IS_NULL = (1 << 0),
- IS_WRONG_TYPE = (1 << 1),
-
- IS_VERT_WRONG_EDGE_TYPE = (1 << 2),
-
- IS_EDGE_NULL_DISK_LINK = (1 << 3),
- IS_EDGE_WRONG_LOOP_TYPE = (1 << 4),
- IS_EDGE_WRONG_FACE_TYPE = (1 << 5),
- IS_EDGE_NULL_RADIAL_LINK = (1 << 6),
- IS_EDGE_ZERO_FACE_LENGTH = (1 << 7),
-
- IS_LOOP_WRONG_FACE_TYPE = (1 << 8),
- IS_LOOP_WRONG_EDGE_TYPE = (1 << 9),
- IS_LOOP_WRONG_VERT_TYPE = (1 << 10),
- IS_LOOP_VERT_NOT_IN_EDGE = (1 << 11),
- IS_LOOP_NULL_CYCLE_LINK = (1 << 12),
- IS_LOOP_ZERO_FACE_LENGTH = (1 << 13),
- IS_LOOP_WRONG_FACE_LENGTH = (1 << 14),
- IS_LOOP_WRONG_RADIAL_LENGTH = (1 << 15),
-
- IS_FACE_NULL_LOOP = (1 << 16),
- IS_FACE_WRONG_LOOP_FACE = (1 << 17),
- IS_FACE_NULL_EDGE = (1 << 18),
- IS_FACE_NULL_VERT = (1 << 19),
- IS_FACE_LOOP_VERT_NOT_IN_EDGE = (1 << 20),
- IS_FACE_LOOP_WRONG_RADIAL_LENGTH = (1 << 21),
- IS_FACE_LOOP_WRONG_DISK_LENGTH = (1 << 22),
- IS_FACE_LOOP_DUPE_LOOP = (1 << 23),
- IS_FACE_LOOP_DUPE_VERT = (1 << 24),
- IS_FACE_LOOP_DUPE_EDGE = (1 << 25),
- IS_FACE_WRONG_LENGTH = (1 << 26),
- } err = 0;
-
- if (!element) {
- return IS_NULL;
- }
-
- if (head->htype != htype) {
- return IS_WRONG_TYPE;
- }
-
- switch (htype) {
- case BM_VERT:
- {
- BMVert *v = element;
- if (v->e && v->e->head.htype != BM_EDGE) {
- err |= IS_VERT_WRONG_EDGE_TYPE;
- }
- break;
- }
- case BM_EDGE:
- {
- BMEdge *e = element;
- if (e->v1_disk_link.prev == NULL ||
- e->v2_disk_link.prev == NULL ||
- e->v1_disk_link.next == NULL ||
- e->v2_disk_link.next == NULL)
- {
- err |= IS_EDGE_NULL_DISK_LINK;
- }
-
- if (e->l && e->l->head.htype != BM_LOOP) {
- err |= IS_EDGE_WRONG_LOOP_TYPE;
- }
- if (e->l && e->l->f->head.htype != BM_FACE) {
- err |= IS_EDGE_WRONG_FACE_TYPE;
- }
- if (e->l && (e->l->radial_next == NULL || e->l->radial_prev == NULL)) {
- err |= IS_EDGE_NULL_RADIAL_LINK;
- }
- if (e->l && e->l->f->len <= 0) {
- err |= IS_EDGE_ZERO_FACE_LENGTH;
- }
- break;
- }
- case BM_LOOP:
- {
- BMLoop *l = element, *l2;
- int i;
-
- if (l->f->head.htype != BM_FACE) {
- err |= IS_LOOP_WRONG_FACE_TYPE;
- }
- if (l->e->head.htype != BM_EDGE) {
- err |= IS_LOOP_WRONG_EDGE_TYPE;
- }
- if (l->v->head.htype != BM_VERT) {
- err |= IS_LOOP_WRONG_VERT_TYPE;
- }
- if (!BM_vert_in_edge(l->e, l->v)) {
- fprintf(stderr, "%s: fatal bmesh error (vert not in edge)! (bmesh internal error)\n", __func__);
- err |= IS_LOOP_VERT_NOT_IN_EDGE;
- }
-
- if (l->radial_next == NULL || l->radial_prev == NULL) {
- err |= IS_LOOP_NULL_CYCLE_LINK;
- }
- if (l->f->len <= 0) {
- err |= IS_LOOP_ZERO_FACE_LENGTH;
- }
-
- /* validate boundary loop -- invalid for hole loops, of course,
- * but we won't be allowing those for a while yet */
- l2 = l;
- i = 0;
- do {
- if (i >= BM_NGON_MAX) {
- break;
- }
-
- i++;
- } while ((l2 = l2->next) != l);
-
- if (i != l->f->len || l2 != l) {
- err |= IS_LOOP_WRONG_FACE_LENGTH;
- }
-
- if (!bmesh_radial_validate(bmesh_radial_length(l), l)) {
- err |= IS_LOOP_WRONG_RADIAL_LENGTH;
- }
-
- break;
- }
- case BM_FACE:
- {
- BMFace *f = element;
- BMLoop *l_iter;
- BMLoop *l_first;
- int len = 0;
-
-#ifdef USE_BMESH_HOLES
- if (!f->loops.first)
-#else
- if (!f->l_first)
-#endif
- {
- err |= IS_FACE_NULL_LOOP;
- }
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if (l_iter->f != f) {
- fprintf(stderr, "%s: loop inside one face points to another! (bmesh internal error)\n", __func__);
- err |= IS_FACE_WRONG_LOOP_FACE;
- }
-
- if (!l_iter->e) {
- err |= IS_FACE_NULL_EDGE;
- }
- if (!l_iter->v) {
- err |= IS_FACE_NULL_VERT;
- }
- if (l_iter->e && l_iter->v) {
- if (!BM_vert_in_edge(l_iter->e, l_iter->v) ||
- !BM_vert_in_edge(l_iter->e, l_iter->next->v))
- {
- err |= IS_FACE_LOOP_VERT_NOT_IN_EDGE;
- }
-
- if (!bmesh_radial_validate(bmesh_radial_length(l_iter), l_iter)) {
- err |= IS_FACE_LOOP_WRONG_RADIAL_LENGTH;
- }
-
- if (bmesh_disk_count_at_most(l_iter->v, 2) < 2) {
- err |= IS_FACE_LOOP_WRONG_DISK_LENGTH;
- }
- }
-
- /* check for duplicates */
- if (BM_ELEM_API_FLAG_TEST(l_iter, _FLAG_ELEM_CHECK)) {
- err |= IS_FACE_LOOP_DUPE_LOOP;
- }
- BM_ELEM_API_FLAG_ENABLE(l_iter, _FLAG_ELEM_CHECK);
- if (l_iter->v) {
- if (BM_ELEM_API_FLAG_TEST(l_iter->v, _FLAG_ELEM_CHECK)) {
- err |= IS_FACE_LOOP_DUPE_VERT;
- }
- BM_ELEM_API_FLAG_ENABLE(l_iter->v, _FLAG_ELEM_CHECK);
- }
- if (l_iter->e) {
- if (BM_ELEM_API_FLAG_TEST(l_iter->e, _FLAG_ELEM_CHECK)) {
- err |= IS_FACE_LOOP_DUPE_EDGE;
- }
- BM_ELEM_API_FLAG_ENABLE(l_iter->e, _FLAG_ELEM_CHECK);
- }
-
- len++;
- } while ((l_iter = l_iter->next) != l_first);
-
- /* cleanup duplicates flag */
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- BM_ELEM_API_FLAG_DISABLE(l_iter, _FLAG_ELEM_CHECK);
- if (l_iter->v) {
- BM_ELEM_API_FLAG_DISABLE(l_iter->v, _FLAG_ELEM_CHECK);
- }
- if (l_iter->e) {
- BM_ELEM_API_FLAG_DISABLE(l_iter->e, _FLAG_ELEM_CHECK);
- }
- } while ((l_iter = l_iter->next) != l_first);
-
- if (len != f->len) {
- err |= IS_FACE_WRONG_LENGTH;
- }
- break;
- }
- default:
- BLI_assert(0);
- break;
- }
-
- BMESH_ASSERT(err == 0);
-
- return err;
+ BMHeader *head = element;
+ enum {
+ IS_NULL = (1 << 0),
+ IS_WRONG_TYPE = (1 << 1),
+
+ IS_VERT_WRONG_EDGE_TYPE = (1 << 2),
+
+ IS_EDGE_NULL_DISK_LINK = (1 << 3),
+ IS_EDGE_WRONG_LOOP_TYPE = (1 << 4),
+ IS_EDGE_WRONG_FACE_TYPE = (1 << 5),
+ IS_EDGE_NULL_RADIAL_LINK = (1 << 6),
+ IS_EDGE_ZERO_FACE_LENGTH = (1 << 7),
+
+ IS_LOOP_WRONG_FACE_TYPE = (1 << 8),
+ IS_LOOP_WRONG_EDGE_TYPE = (1 << 9),
+ IS_LOOP_WRONG_VERT_TYPE = (1 << 10),
+ IS_LOOP_VERT_NOT_IN_EDGE = (1 << 11),
+ IS_LOOP_NULL_CYCLE_LINK = (1 << 12),
+ IS_LOOP_ZERO_FACE_LENGTH = (1 << 13),
+ IS_LOOP_WRONG_FACE_LENGTH = (1 << 14),
+ IS_LOOP_WRONG_RADIAL_LENGTH = (1 << 15),
+
+ IS_FACE_NULL_LOOP = (1 << 16),
+ IS_FACE_WRONG_LOOP_FACE = (1 << 17),
+ IS_FACE_NULL_EDGE = (1 << 18),
+ IS_FACE_NULL_VERT = (1 << 19),
+ IS_FACE_LOOP_VERT_NOT_IN_EDGE = (1 << 20),
+ IS_FACE_LOOP_WRONG_RADIAL_LENGTH = (1 << 21),
+ IS_FACE_LOOP_WRONG_DISK_LENGTH = (1 << 22),
+ IS_FACE_LOOP_DUPE_LOOP = (1 << 23),
+ IS_FACE_LOOP_DUPE_VERT = (1 << 24),
+ IS_FACE_LOOP_DUPE_EDGE = (1 << 25),
+ IS_FACE_WRONG_LENGTH = (1 << 26),
+ } err = 0;
+
+ if (!element) {
+ return IS_NULL;
+ }
+
+ if (head->htype != htype) {
+ return IS_WRONG_TYPE;
+ }
+
+ switch (htype) {
+ case BM_VERT: {
+ BMVert *v = element;
+ if (v->e && v->e->head.htype != BM_EDGE) {
+ err |= IS_VERT_WRONG_EDGE_TYPE;
+ }
+ break;
+ }
+ case BM_EDGE: {
+ BMEdge *e = element;
+ if (e->v1_disk_link.prev == NULL || e->v2_disk_link.prev == NULL ||
+ e->v1_disk_link.next == NULL || e->v2_disk_link.next == NULL) {
+ err |= IS_EDGE_NULL_DISK_LINK;
+ }
+
+ if (e->l && e->l->head.htype != BM_LOOP) {
+ err |= IS_EDGE_WRONG_LOOP_TYPE;
+ }
+ if (e->l && e->l->f->head.htype != BM_FACE) {
+ err |= IS_EDGE_WRONG_FACE_TYPE;
+ }
+ if (e->l && (e->l->radial_next == NULL || e->l->radial_prev == NULL)) {
+ err |= IS_EDGE_NULL_RADIAL_LINK;
+ }
+ if (e->l && e->l->f->len <= 0) {
+ err |= IS_EDGE_ZERO_FACE_LENGTH;
+ }
+ break;
+ }
+ case BM_LOOP: {
+ BMLoop *l = element, *l2;
+ int i;
+
+ if (l->f->head.htype != BM_FACE) {
+ err |= IS_LOOP_WRONG_FACE_TYPE;
+ }
+ if (l->e->head.htype != BM_EDGE) {
+ err |= IS_LOOP_WRONG_EDGE_TYPE;
+ }
+ if (l->v->head.htype != BM_VERT) {
+ err |= IS_LOOP_WRONG_VERT_TYPE;
+ }
+ if (!BM_vert_in_edge(l->e, l->v)) {
+ fprintf(stderr,
+ "%s: fatal bmesh error (vert not in edge)! (bmesh internal error)\n",
+ __func__);
+ err |= IS_LOOP_VERT_NOT_IN_EDGE;
+ }
+
+ if (l->radial_next == NULL || l->radial_prev == NULL) {
+ err |= IS_LOOP_NULL_CYCLE_LINK;
+ }
+ if (l->f->len <= 0) {
+ err |= IS_LOOP_ZERO_FACE_LENGTH;
+ }
+
+ /* validate boundary loop -- invalid for hole loops, of course,
+ * but we won't be allowing those for a while yet */
+ l2 = l;
+ i = 0;
+ do {
+ if (i >= BM_NGON_MAX) {
+ break;
+ }
+
+ i++;
+ } while ((l2 = l2->next) != l);
+
+ if (i != l->f->len || l2 != l) {
+ err |= IS_LOOP_WRONG_FACE_LENGTH;
+ }
+
+ if (!bmesh_radial_validate(bmesh_radial_length(l), l)) {
+ err |= IS_LOOP_WRONG_RADIAL_LENGTH;
+ }
+
+ break;
+ }
+ case BM_FACE: {
+ BMFace *f = element;
+ BMLoop *l_iter;
+ BMLoop *l_first;
+ int len = 0;
+
+# ifdef USE_BMESH_HOLES
+ if (!f->loops.first)
+# else
+ if (!f->l_first)
+# endif
+ {
+ err |= IS_FACE_NULL_LOOP;
+ }
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (l_iter->f != f) {
+ fprintf(stderr,
+ "%s: loop inside one face points to another! (bmesh internal error)\n",
+ __func__);
+ err |= IS_FACE_WRONG_LOOP_FACE;
+ }
+
+ if (!l_iter->e) {
+ err |= IS_FACE_NULL_EDGE;
+ }
+ if (!l_iter->v) {
+ err |= IS_FACE_NULL_VERT;
+ }
+ if (l_iter->e && l_iter->v) {
+ if (!BM_vert_in_edge(l_iter->e, l_iter->v) ||
+ !BM_vert_in_edge(l_iter->e, l_iter->next->v)) {
+ err |= IS_FACE_LOOP_VERT_NOT_IN_EDGE;
+ }
+
+ if (!bmesh_radial_validate(bmesh_radial_length(l_iter), l_iter)) {
+ err |= IS_FACE_LOOP_WRONG_RADIAL_LENGTH;
+ }
+
+ if (bmesh_disk_count_at_most(l_iter->v, 2) < 2) {
+ err |= IS_FACE_LOOP_WRONG_DISK_LENGTH;
+ }
+ }
+
+ /* check for duplicates */
+ if (BM_ELEM_API_FLAG_TEST(l_iter, _FLAG_ELEM_CHECK)) {
+ err |= IS_FACE_LOOP_DUPE_LOOP;
+ }
+ BM_ELEM_API_FLAG_ENABLE(l_iter, _FLAG_ELEM_CHECK);
+ if (l_iter->v) {
+ if (BM_ELEM_API_FLAG_TEST(l_iter->v, _FLAG_ELEM_CHECK)) {
+ err |= IS_FACE_LOOP_DUPE_VERT;
+ }
+ BM_ELEM_API_FLAG_ENABLE(l_iter->v, _FLAG_ELEM_CHECK);
+ }
+ if (l_iter->e) {
+ if (BM_ELEM_API_FLAG_TEST(l_iter->e, _FLAG_ELEM_CHECK)) {
+ err |= IS_FACE_LOOP_DUPE_EDGE;
+ }
+ BM_ELEM_API_FLAG_ENABLE(l_iter->e, _FLAG_ELEM_CHECK);
+ }
+
+ len++;
+ } while ((l_iter = l_iter->next) != l_first);
+
+ /* cleanup duplicates flag */
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BM_ELEM_API_FLAG_DISABLE(l_iter, _FLAG_ELEM_CHECK);
+ if (l_iter->v) {
+ BM_ELEM_API_FLAG_DISABLE(l_iter->v, _FLAG_ELEM_CHECK);
+ }
+ if (l_iter->e) {
+ BM_ELEM_API_FLAG_DISABLE(l_iter->e, _FLAG_ELEM_CHECK);
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+
+ if (len != f->len) {
+ err |= IS_FACE_WRONG_LENGTH;
+ }
+ break;
+ }
+ default:
+ BLI_assert(0);
+ break;
+ }
+
+ BMESH_ASSERT(err == 0);
+
+ return err;
}
#endif /* NDEBUG */
@@ -745,20 +744,20 @@ int bmesh_elem_check(void *element, const char htype)
*/
static void bm_kill_only_vert(BMesh *bm, BMVert *v)
{
- bm->totvert--;
- bm->elem_index_dirty |= BM_VERT;
- bm->elem_table_dirty |= BM_VERT;
+ bm->totvert--;
+ bm->elem_index_dirty |= BM_VERT;
+ bm->elem_table_dirty |= BM_VERT;
- BM_select_history_remove(bm, v);
+ BM_select_history_remove(bm, v);
- if (v->head.data) {
- CustomData_bmesh_free_block(&bm->vdata, &v->head.data);
- }
+ if (v->head.data) {
+ CustomData_bmesh_free_block(&bm->vdata, &v->head.data);
+ }
- if (bm->vtoolflagpool) {
- BLI_mempool_free(bm->vtoolflagpool, ((BMVert_OFlag *)v)->oflags);
- }
- BLI_mempool_free(bm->vpool, v);
+ if (bm->vtoolflagpool) {
+ BLI_mempool_free(bm->vtoolflagpool, ((BMVert_OFlag *)v)->oflags);
+ }
+ BLI_mempool_free(bm->vpool, v);
}
/**
@@ -767,20 +766,20 @@ static void bm_kill_only_vert(BMesh *bm, BMVert *v)
*/
static void bm_kill_only_edge(BMesh *bm, BMEdge *e)
{
- bm->totedge--;
- bm->elem_index_dirty |= BM_EDGE;
- bm->elem_table_dirty |= BM_EDGE;
+ bm->totedge--;
+ bm->elem_index_dirty |= BM_EDGE;
+ bm->elem_table_dirty |= BM_EDGE;
- BM_select_history_remove(bm, (BMElem *)e);
+ BM_select_history_remove(bm, (BMElem *)e);
- if (e->head.data) {
- CustomData_bmesh_free_block(&bm->edata, &e->head.data);
- }
+ if (e->head.data) {
+ CustomData_bmesh_free_block(&bm->edata, &e->head.data);
+ }
- if (bm->etoolflagpool) {
- BLI_mempool_free(bm->etoolflagpool, ((BMEdge_OFlag *)e)->oflags);
- }
- BLI_mempool_free(bm->epool, e);
+ if (bm->etoolflagpool) {
+ BLI_mempool_free(bm->etoolflagpool, ((BMEdge_OFlag *)e)->oflags);
+ }
+ BLI_mempool_free(bm->epool, e);
}
/**
@@ -789,24 +788,24 @@ static void bm_kill_only_edge(BMesh *bm, BMEdge *e)
*/
static void bm_kill_only_face(BMesh *bm, BMFace *f)
{
- if (bm->act_face == f) {
- bm->act_face = NULL;
- }
+ if (bm->act_face == f) {
+ bm->act_face = NULL;
+ }
- bm->totface--;
- bm->elem_index_dirty |= BM_FACE;
- bm->elem_table_dirty |= BM_FACE;
+ bm->totface--;
+ bm->elem_index_dirty |= BM_FACE;
+ bm->elem_table_dirty |= BM_FACE;
- BM_select_history_remove(bm, (BMElem *)f);
+ BM_select_history_remove(bm, (BMElem *)f);
- if (f->head.data) {
- CustomData_bmesh_free_block(&bm->pdata, &f->head.data);
- }
+ if (f->head.data) {
+ CustomData_bmesh_free_block(&bm->pdata, &f->head.data);
+ }
- if (bm->ftoolflagpool) {
- BLI_mempool_free(bm->ftoolflagpool, ((BMFace_OFlag *)f)->oflags);
- }
- BLI_mempool_free(bm->fpool, f);
+ if (bm->ftoolflagpool) {
+ BLI_mempool_free(bm->ftoolflagpool, ((BMFace_OFlag *)f)->oflags);
+ }
+ BLI_mempool_free(bm->fpool, f);
}
/**
@@ -815,13 +814,13 @@ static void bm_kill_only_face(BMesh *bm, BMFace *f)
*/
static void bm_kill_only_loop(BMesh *bm, BMLoop *l)
{
- bm->totloop--;
- bm->elem_index_dirty |= BM_LOOP;
- if (l->head.data) {
- CustomData_bmesh_free_block(&bm->ldata, &l->head.data);
- }
+ bm->totloop--;
+ bm->elem_index_dirty |= BM_LOOP;
+ if (l->head.data) {
+ CustomData_bmesh_free_block(&bm->ldata, &l->head.data);
+ }
- BLI_mempool_free(bm->lpool, l);
+ BLI_mempool_free(bm->lpool, l);
}
/**
@@ -830,19 +829,19 @@ static void bm_kill_only_loop(BMesh *bm, BMLoop *l)
*/
void BM_face_edges_kill(BMesh *bm, BMFace *f)
{
- BMEdge **edges = BLI_array_alloca(edges, f->len);
- BMLoop *l_iter;
- BMLoop *l_first;
- int i = 0;
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- edges[i++] = l_iter->e;
- } while ((l_iter = l_iter->next) != l_first);
-
- for (i = 0; i < f->len; i++) {
- BM_edge_kill(bm, edges[i]);
- }
+ BMEdge **edges = BLI_array_alloca(edges, f->len);
+ BMLoop *l_iter;
+ BMLoop *l_first;
+ int i = 0;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ edges[i++] = l_iter->e;
+ } while ((l_iter = l_iter->next) != l_first);
+
+ for (i = 0; i < f->len; i++) {
+ BM_edge_kill(bm, edges[i]);
+ }
}
/**
@@ -851,19 +850,19 @@ void BM_face_edges_kill(BMesh *bm, BMFace *f)
*/
void BM_face_verts_kill(BMesh *bm, BMFace *f)
{
- BMVert **verts = BLI_array_alloca(verts, f->len);
- BMLoop *l_iter;
- BMLoop *l_first;
- int i = 0;
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- verts[i++] = l_iter->v;
- } while ((l_iter = l_iter->next) != l_first);
-
- for (i = 0; i < f->len; i++) {
- BM_vert_kill(bm, verts[i]);
- }
+ BMVert **verts = BLI_array_alloca(verts, f->len);
+ BMLoop *l_iter;
+ BMLoop *l_first;
+ int i = 0;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ verts[i++] = l_iter->v;
+ } while ((l_iter = l_iter->next) != l_first);
+
+ for (i = 0; i < f->len; i++) {
+ BM_vert_kill(bm, verts[i]);
+ }
}
/**
@@ -872,45 +871,45 @@ void BM_face_verts_kill(BMesh *bm, BMFace *f)
void BM_face_kill(BMesh *bm, BMFace *f)
{
#ifdef USE_BMESH_HOLES
- BMLoopList *ls, *ls_next;
+ BMLoopList *ls, *ls_next;
#endif
#ifdef NDEBUG
- /* check length since we may be removing degenerate faces */
- if (f->len >= 3) {
- BM_CHECK_ELEMENT(f);
- }
+ /* check length since we may be removing degenerate faces */
+ if (f->len >= 3) {
+ BM_CHECK_ELEMENT(f);
+ }
#endif
#ifdef USE_BMESH_HOLES
- for (ls = f->loops.first; ls; ls = ls_next)
+ for (ls = f->loops.first; ls; ls = ls_next)
#else
- if (f->l_first)
+ if (f->l_first)
#endif
- {
- BMLoop *l_iter, *l_next, *l_first;
+ {
+ BMLoop *l_iter, *l_next, *l_first;
#ifdef USE_BMESH_HOLES
- ls_next = ls->next;
- l_iter = l_first = ls->first;
+ ls_next = ls->next;
+ l_iter = l_first = ls->first;
#else
- l_iter = l_first = f->l_first;
+ l_iter = l_first = f->l_first;
#endif
- do {
- l_next = l_iter->next;
+ do {
+ l_next = l_iter->next;
- bmesh_radial_loop_remove(l_iter->e, l_iter);
- bm_kill_only_loop(bm, l_iter);
+ bmesh_radial_loop_remove(l_iter->e, l_iter);
+ bm_kill_only_loop(bm, l_iter);
- } while ((l_iter = l_next) != l_first);
+ } while ((l_iter = l_next) != l_first);
#ifdef USE_BMESH_HOLES
- BLI_mempool_free(bm->looplistpool, ls);
+ BLI_mempool_free(bm->looplistpool, ls);
#endif
- }
+ }
- bm_kill_only_face(bm, f);
+ bm_kill_only_face(bm, f);
}
/**
@@ -920,56 +919,56 @@ void BM_face_kill(BMesh *bm, BMFace *f)
void BM_face_kill_loose(BMesh *bm, BMFace *f)
{
#ifdef USE_BMESH_HOLES
- BMLoopList *ls, *ls_next;
+ BMLoopList *ls, *ls_next;
#endif
- BM_CHECK_ELEMENT(f);
+ BM_CHECK_ELEMENT(f);
#ifdef USE_BMESH_HOLES
- for (ls = f->loops.first; ls; ls = ls_next)
+ for (ls = f->loops.first; ls; ls = ls_next)
#else
- if (f->l_first)
+ if (f->l_first)
#endif
- {
- BMLoop *l_iter, *l_next, *l_first;
+ {
+ BMLoop *l_iter, *l_next, *l_first;
#ifdef USE_BMESH_HOLES
- ls_next = ls->next;
- l_iter = l_first = ls->first;
+ ls_next = ls->next;
+ l_iter = l_first = ls->first;
#else
- l_iter = l_first = f->l_first;
+ l_iter = l_first = f->l_first;
#endif
- do {
- BMEdge *e;
- l_next = l_iter->next;
+ do {
+ BMEdge *e;
+ l_next = l_iter->next;
- e = l_iter->e;
- bmesh_radial_loop_remove(e, l_iter);
- bm_kill_only_loop(bm, l_iter);
+ e = l_iter->e;
+ bmesh_radial_loop_remove(e, l_iter);
+ bm_kill_only_loop(bm, l_iter);
- if (e->l == NULL) {
- BMVert *v1 = e->v1, *v2 = e->v2;
+ if (e->l == NULL) {
+ BMVert *v1 = e->v1, *v2 = e->v2;
- bmesh_disk_edge_remove(e, e->v1);
- bmesh_disk_edge_remove(e, e->v2);
- bm_kill_only_edge(bm, e);
+ bmesh_disk_edge_remove(e, e->v1);
+ bmesh_disk_edge_remove(e, e->v2);
+ bm_kill_only_edge(bm, e);
- if (v1->e == NULL) {
- bm_kill_only_vert(bm, v1);
- }
- if (v2->e == NULL) {
- bm_kill_only_vert(bm, v2);
- }
- }
- } while ((l_iter = l_next) != l_first);
+ if (v1->e == NULL) {
+ bm_kill_only_vert(bm, v1);
+ }
+ if (v2->e == NULL) {
+ bm_kill_only_vert(bm, v2);
+ }
+ }
+ } while ((l_iter = l_next) != l_first);
#ifdef USE_BMESH_HOLES
- BLI_mempool_free(bm->looplistpool, ls);
+ BLI_mempool_free(bm->looplistpool, ls);
#endif
- }
+ }
- bm_kill_only_face(bm, f);
+ bm_kill_only_face(bm, f);
}
/**
@@ -977,14 +976,14 @@ void BM_face_kill_loose(BMesh *bm, BMFace *f)
*/
void BM_edge_kill(BMesh *bm, BMEdge *e)
{
- while (e->l) {
- BM_face_kill(bm, e->l->f);
- }
+ while (e->l) {
+ BM_face_kill(bm, e->l->f);
+ }
- bmesh_disk_edge_remove(e, e->v1);
- bmesh_disk_edge_remove(e, e->v2);
+ bmesh_disk_edge_remove(e, e->v1);
+ bmesh_disk_edge_remove(e, e->v2);
- bm_kill_only_edge(bm, e);
+ bm_kill_only_edge(bm, e);
}
/**
@@ -992,11 +991,11 @@ void BM_edge_kill(BMesh *bm, BMEdge *e)
*/
void BM_vert_kill(BMesh *bm, BMVert *v)
{
- while (v->e) {
- BM_edge_kill(bm, v->e);
- }
+ while (v->e) {
+ BM_edge_kill(bm, v->e);
+ }
- bm_kill_only_vert(bm, v);
+ bm_kill_only_vert(bm, v);
}
/********** private disk and radial cycle functions ********** */
@@ -1006,14 +1005,14 @@ void BM_vert_kill(BMesh *bm, BMVert *v)
*/
static int UNUSED_FUNCTION(bm_loop_length)(BMLoop *l)
{
- BMLoop *l_first = l;
- int i = 0;
+ BMLoop *l_first = l;
+ int i = 0;
- do {
- i++;
- } while ((l = l->next) != l_first);
+ do {
+ i++;
+ } while ((l = l->next) != l_first);
- return i;
+ return i;
}
/**
@@ -1025,126 +1024,127 @@ static int UNUSED_FUNCTION(bm_loop_length)(BMLoop *l)
* \param use_loop_mdisp_flip: When set, flip the Z-depth of the mdisp,
* (use when flipping normals, disable when mirroring, eg: symmetrize).
*/
-void bmesh_kernel_loop_reverse(
- BMesh *bm, BMFace *f,
- const int cd_loop_mdisp_offset, const bool use_loop_mdisp_flip)
+void bmesh_kernel_loop_reverse(BMesh *bm,
+ BMFace *f,
+ const int cd_loop_mdisp_offset,
+ const bool use_loop_mdisp_flip)
{
- BMLoop *l_first = f->l_first;
+ BMLoop *l_first = f->l_first;
- /* track previous cycles radial state */
- BMEdge *e_prev = l_first->prev->e;
- BMLoop *l_prev_radial_next = l_first->prev->radial_next;
- BMLoop *l_prev_radial_prev = l_first->prev->radial_prev;
- bool is_prev_boundary = l_prev_radial_next == l_prev_radial_next->radial_next;
+ /* track previous cycles radial state */
+ BMEdge *e_prev = l_first->prev->e;
+ BMLoop *l_prev_radial_next = l_first->prev->radial_next;
+ BMLoop *l_prev_radial_prev = l_first->prev->radial_prev;
+ bool is_prev_boundary = l_prev_radial_next == l_prev_radial_next->radial_next;
- BMLoop *l_iter = l_first;
- do {
- BMEdge *e_iter = l_iter->e;
- BMLoop *l_iter_radial_next = l_iter->radial_next;
- BMLoop *l_iter_radial_prev = l_iter->radial_prev;
- bool is_iter_boundary = l_iter_radial_next == l_iter_radial_next->radial_next;
+ BMLoop *l_iter = l_first;
+ do {
+ BMEdge *e_iter = l_iter->e;
+ BMLoop *l_iter_radial_next = l_iter->radial_next;
+ BMLoop *l_iter_radial_prev = l_iter->radial_prev;
+ bool is_iter_boundary = l_iter_radial_next == l_iter_radial_next->radial_next;
#if 0
- bmesh_radial_loop_remove(e_iter, l_iter);
- bmesh_radial_loop_append(e_prev, l_iter);
+ bmesh_radial_loop_remove(e_iter, l_iter);
+ bmesh_radial_loop_append(e_prev, l_iter);
#else
- /* inline loop reversal */
- if (is_prev_boundary) {
- /* boundary */
- l_iter->radial_next = l_iter;
- l_iter->radial_prev = l_iter;
- }
- else {
- /* non-boundary, replace radial links */
- l_iter->radial_next = l_prev_radial_next;
- l_iter->radial_prev = l_prev_radial_prev;
- l_prev_radial_next->radial_prev = l_iter;
- l_prev_radial_prev->radial_next = l_iter;
- }
-
- if (e_iter->l == l_iter) {
- e_iter->l = l_iter->next;
- }
- l_iter->e = e_prev;
+ /* inline loop reversal */
+ if (is_prev_boundary) {
+ /* boundary */
+ l_iter->radial_next = l_iter;
+ l_iter->radial_prev = l_iter;
+ }
+ else {
+ /* non-boundary, replace radial links */
+ l_iter->radial_next = l_prev_radial_next;
+ l_iter->radial_prev = l_prev_radial_prev;
+ l_prev_radial_next->radial_prev = l_iter;
+ l_prev_radial_prev->radial_next = l_iter;
+ }
+
+ if (e_iter->l == l_iter) {
+ e_iter->l = l_iter->next;
+ }
+ l_iter->e = e_prev;
#endif
- SWAP(BMLoop *, l_iter->next, l_iter->prev);
+ SWAP(BMLoop *, l_iter->next, l_iter->prev);
- if (cd_loop_mdisp_offset != -1) {
- MDisps *md = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_mdisp_offset);
- BKE_mesh_mdisp_flip(md, use_loop_mdisp_flip);
- }
+ if (cd_loop_mdisp_offset != -1) {
+ MDisps *md = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_mdisp_offset);
+ BKE_mesh_mdisp_flip(md, use_loop_mdisp_flip);
+ }
- e_prev = e_iter;
- l_prev_radial_next = l_iter_radial_next;
- l_prev_radial_prev = l_iter_radial_prev;
- is_prev_boundary = is_iter_boundary;
+ e_prev = e_iter;
+ l_prev_radial_next = l_iter_radial_next;
+ l_prev_radial_prev = l_iter_radial_prev;
+ is_prev_boundary = is_iter_boundary;
- /* step to next (now swapped) */
- } while ((l_iter = l_iter->prev) != l_first);
+ /* step to next (now swapped) */
+ } while ((l_iter = l_iter->prev) != l_first);
#ifndef NDEBUG
- /* validate radial */
- int i;
- for (i = 0, l_iter = l_first; i < f->len; i++, l_iter = l_iter->next) {
- BM_CHECK_ELEMENT(l_iter);
- BM_CHECK_ELEMENT(l_iter->e);
- BM_CHECK_ELEMENT(l_iter->v);
- BM_CHECK_ELEMENT(l_iter->f);
- }
-
- BM_CHECK_ELEMENT(f);
+ /* validate radial */
+ int i;
+ for (i = 0, l_iter = l_first; i < f->len; i++, l_iter = l_iter->next) {
+ BM_CHECK_ELEMENT(l_iter);
+ BM_CHECK_ELEMENT(l_iter->e);
+ BM_CHECK_ELEMENT(l_iter->v);
+ BM_CHECK_ELEMENT(l_iter->f);
+ }
+
+ BM_CHECK_ELEMENT(f);
#endif
- /* Loop indices are no more valid! */
- bm->elem_index_dirty |= BM_LOOP;
+ /* Loop indices are no more valid! */
+ bm->elem_index_dirty |= BM_LOOP;
}
static void bm_elements_systag_enable(void *veles, int tot, const char api_flag)
{
- BMHeader **eles = veles;
- int i;
+ BMHeader **eles = veles;
+ int i;
- for (i = 0; i < tot; i++) {
- BM_ELEM_API_FLAG_ENABLE((BMElemF *)eles[i], api_flag);
- }
+ for (i = 0; i < tot; i++) {
+ BM_ELEM_API_FLAG_ENABLE((BMElemF *)eles[i], api_flag);
+ }
}
static void bm_elements_systag_disable(void *veles, int tot, const char api_flag)
{
- BMHeader **eles = veles;
- int i;
+ BMHeader **eles = veles;
+ int i;
- for (i = 0; i < tot; i++) {
- BM_ELEM_API_FLAG_DISABLE((BMElemF *)eles[i], api_flag);
- }
+ for (i = 0; i < tot; i++) {
+ BM_ELEM_API_FLAG_DISABLE((BMElemF *)eles[i], api_flag);
+ }
}
static int bm_loop_systag_count_radial(BMLoop *l, const char api_flag)
{
- BMLoop *l_iter = l;
- int i = 0;
- do {
- i += BM_ELEM_API_FLAG_TEST(l_iter->f, api_flag) ? 1 : 0;
- } while ((l_iter = l_iter->radial_next) != l);
+ BMLoop *l_iter = l;
+ int i = 0;
+ do {
+ i += BM_ELEM_API_FLAG_TEST(l_iter->f, api_flag) ? 1 : 0;
+ } while ((l_iter = l_iter->radial_next) != l);
- return i;
+ return i;
}
static int UNUSED_FUNCTION(bm_vert_systag_count_disk)(BMVert *v, const char api_flag)
{
- BMEdge *e = v->e;
- int i = 0;
+ BMEdge *e = v->e;
+ int i = 0;
- if (!e) {
- return 0;
- }
+ if (!e) {
+ return 0;
+ }
- do {
- i += BM_ELEM_API_FLAG_TEST(e, api_flag) ? 1 : 0;
- } while ((e = bmesh_disk_edge_next(e, v)) != v->e);
+ do {
+ i += BM_ELEM_API_FLAG_TEST(e, api_flag) ? 1 : 0;
+ } while ((e = bmesh_disk_edge_next(e, v)) != v->e);
- return i;
+ return i;
}
/**
@@ -1153,31 +1153,31 @@ static int UNUSED_FUNCTION(bm_vert_systag_count_disk)(BMVert *v, const char api_
*/
static bool bm_vert_is_manifold_flagged(BMVert *v, const char api_flag)
{
- BMEdge *e = v->e;
+ BMEdge *e = v->e;
- if (!e) {
- return false;
- }
+ if (!e) {
+ return false;
+ }
- do {
- BMLoop *l = e->l;
+ do {
+ BMLoop *l = e->l;
- if (!l) {
- return false;
- }
+ if (!l) {
+ return false;
+ }
- if (BM_edge_is_boundary(l->e)) {
- return false;
- }
+ if (BM_edge_is_boundary(l->e)) {
+ return false;
+ }
- do {
- if (!BM_ELEM_API_FLAG_TEST(l->f, api_flag)) {
- return false;
- }
- } while ((l = l->radial_next) != e->l);
- } while ((e = bmesh_disk_edge_next(e, v)) != v->e);
+ do {
+ if (!BM_ELEM_API_FLAG_TEST(l->f, api_flag)) {
+ return false;
+ }
+ } while ((l = l->radial_next) != e->l);
+ } while ((e = bmesh_disk_edge_next(e, v)) != v->e);
- return true;
+ return true;
}
/* Mid-level Topology Manipulation Functions */
@@ -1198,216 +1198,218 @@ static bool bm_vert_is_manifold_flagged(BMVert *v, const char api_flag)
*/
BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del)
{
- BMFace *f, *f_new;
+ BMFace *f, *f_new;
#ifdef USE_BMESH_HOLES
- BMLoopList *lst;
- ListBase holes = {NULL, NULL};
+ BMLoopList *lst;
+ ListBase holes = {NULL, NULL};
#endif
- BMLoop *l_iter;
- BMLoop *l_first;
- BMEdge **edges = NULL;
- BMEdge **deledges = NULL;
- BMVert **delverts = NULL;
- BLI_array_staticdeclare(edges, BM_DEFAULT_NGON_STACK_SIZE);
- BLI_array_staticdeclare(deledges, BM_DEFAULT_NGON_STACK_SIZE);
- BLI_array_staticdeclare(delverts, BM_DEFAULT_NGON_STACK_SIZE);
- BMVert *v1 = NULL, *v2 = NULL;
- int i;
- const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
-
- if (UNLIKELY(!totface)) {
- BMESH_ASSERT(0);
- return NULL;
- }
-
- if (totface == 1) {
- return faces[0];
- }
-
- bm_elements_systag_enable(faces, totface, _FLAG_JF);
-
- for (i = 0; i < totface; i++) {
- f = faces[i];
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- int rlen = bm_loop_systag_count_radial(l_iter, _FLAG_JF);
-
- if (rlen > 2) {
- /* Input faces do not form a contiguous manifold region */
- goto error;
- }
- else if (rlen == 1) {
- BLI_array_append(edges, l_iter->e);
-
- if (!v1) {
- v1 = l_iter->v;
- v2 = BM_edge_other_vert(l_iter->e, l_iter->v);
- }
- }
- else if (rlen == 2) {
- const bool d1 = bm_vert_is_manifold_flagged(l_iter->e->v1, _FLAG_JF);
- const bool d2 = bm_vert_is_manifold_flagged(l_iter->e->v2, _FLAG_JF);
-
- if (!d1 && !d2 && !BM_ELEM_API_FLAG_TEST(l_iter->e, _FLAG_JF)) {
- /* don't remove an edge it makes up the side of another face
- * else this will remove the face as well - campbell */
- if (!BM_edge_face_count_is_over(l_iter->e, 2)) {
- if (do_del) {
- BLI_array_append(deledges, l_iter->e);
- }
- BM_ELEM_API_FLAG_ENABLE(l_iter->e, _FLAG_JF);
- }
- }
- else {
- if (d1 && !BM_ELEM_API_FLAG_TEST(l_iter->e->v1, _FLAG_JF)) {
- if (do_del) {
- BLI_array_append(delverts, l_iter->e->v1);
- }
- BM_ELEM_API_FLAG_ENABLE(l_iter->e->v1, _FLAG_JF);
- }
-
- if (d2 && !BM_ELEM_API_FLAG_TEST(l_iter->e->v2, _FLAG_JF)) {
- if (do_del) {
- BLI_array_append(delverts, l_iter->e->v2);
- }
- BM_ELEM_API_FLAG_ENABLE(l_iter->e->v2, _FLAG_JF);
- }
- }
- }
- } while ((l_iter = l_iter->next) != l_first);
+ BMLoop *l_iter;
+ BMLoop *l_first;
+ BMEdge **edges = NULL;
+ BMEdge **deledges = NULL;
+ BMVert **delverts = NULL;
+ BLI_array_staticdeclare(edges, BM_DEFAULT_NGON_STACK_SIZE);
+ BLI_array_staticdeclare(deledges, BM_DEFAULT_NGON_STACK_SIZE);
+ BLI_array_staticdeclare(delverts, BM_DEFAULT_NGON_STACK_SIZE);
+ BMVert *v1 = NULL, *v2 = NULL;
+ int i;
+ const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
+
+ if (UNLIKELY(!totface)) {
+ BMESH_ASSERT(0);
+ return NULL;
+ }
+
+ if (totface == 1) {
+ return faces[0];
+ }
+
+ bm_elements_systag_enable(faces, totface, _FLAG_JF);
+
+ for (i = 0; i < totface; i++) {
+ f = faces[i];
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ int rlen = bm_loop_systag_count_radial(l_iter, _FLAG_JF);
+
+ if (rlen > 2) {
+ /* Input faces do not form a contiguous manifold region */
+ goto error;
+ }
+ else if (rlen == 1) {
+ BLI_array_append(edges, l_iter->e);
+
+ if (!v1) {
+ v1 = l_iter->v;
+ v2 = BM_edge_other_vert(l_iter->e, l_iter->v);
+ }
+ }
+ else if (rlen == 2) {
+ const bool d1 = bm_vert_is_manifold_flagged(l_iter->e->v1, _FLAG_JF);
+ const bool d2 = bm_vert_is_manifold_flagged(l_iter->e->v2, _FLAG_JF);
+
+ if (!d1 && !d2 && !BM_ELEM_API_FLAG_TEST(l_iter->e, _FLAG_JF)) {
+ /* don't remove an edge it makes up the side of another face
+ * else this will remove the face as well - campbell */
+ if (!BM_edge_face_count_is_over(l_iter->e, 2)) {
+ if (do_del) {
+ BLI_array_append(deledges, l_iter->e);
+ }
+ BM_ELEM_API_FLAG_ENABLE(l_iter->e, _FLAG_JF);
+ }
+ }
+ else {
+ if (d1 && !BM_ELEM_API_FLAG_TEST(l_iter->e->v1, _FLAG_JF)) {
+ if (do_del) {
+ BLI_array_append(delverts, l_iter->e->v1);
+ }
+ BM_ELEM_API_FLAG_ENABLE(l_iter->e->v1, _FLAG_JF);
+ }
+
+ if (d2 && !BM_ELEM_API_FLAG_TEST(l_iter->e->v2, _FLAG_JF)) {
+ if (do_del) {
+ BLI_array_append(delverts, l_iter->e->v2);
+ }
+ BM_ELEM_API_FLAG_ENABLE(l_iter->e->v2, _FLAG_JF);
+ }
+ }
+ }
+ } while ((l_iter = l_iter->next) != l_first);
#ifdef USE_BMESH_HOLES
- for (lst = f->loops.first; lst; lst = lst->next) {
- if (lst == f->loops.first) {
- continue;
- }
-
- BLI_remlink(&f->loops, lst);
- BLI_addtail(&holes, lst);
- }
+ for (lst = f->loops.first; lst; lst = lst->next) {
+ if (lst == f->loops.first) {
+ continue;
+ }
+
+ BLI_remlink(&f->loops, lst);
+ BLI_addtail(&holes, lst);
+ }
#endif
-
- }
-
- /* create region face */
- f_new = BLI_array_len(edges) ?
- BM_face_create_ngon(bm, v1, v2, edges, BLI_array_len(edges), faces[0], BM_CREATE_NOP) : NULL;
- if (UNLIKELY(f_new == NULL)) {
- /* Invalid boundary region to join faces */
- goto error;
- }
-
- /* copy over loop data */
- l_iter = l_first = BM_FACE_FIRST_LOOP(f_new);
- do {
- BMLoop *l2 = l_iter->radial_next;
-
- do {
- if (BM_ELEM_API_FLAG_TEST(l2->f, _FLAG_JF)) {
- break;
- }
- l2 = l2->radial_next;
- } while (l2 != l_iter);
-
- if (l2 != l_iter) {
- /* loops share an edge, shared vert depends on winding */
- if (l2->v != l_iter->v) {
- l2 = l2->next;
- }
- BLI_assert(l_iter->v == l2->v);
-
- BM_elem_attrs_copy(bm, bm, l2, l_iter);
- }
- } while ((l_iter = l_iter->next) != l_first);
+ }
+
+ /* create region face */
+ f_new = BLI_array_len(edges) ?
+ BM_face_create_ngon(
+ bm, v1, v2, edges, BLI_array_len(edges), faces[0], BM_CREATE_NOP) :
+ NULL;
+ if (UNLIKELY(f_new == NULL)) {
+ /* Invalid boundary region to join faces */
+ goto error;
+ }
+
+ /* copy over loop data */
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_new);
+ do {
+ BMLoop *l2 = l_iter->radial_next;
+
+ do {
+ if (BM_ELEM_API_FLAG_TEST(l2->f, _FLAG_JF)) {
+ break;
+ }
+ l2 = l2->radial_next;
+ } while (l2 != l_iter);
+
+ if (l2 != l_iter) {
+ /* loops share an edge, shared vert depends on winding */
+ if (l2->v != l_iter->v) {
+ l2 = l2->next;
+ }
+ BLI_assert(l_iter->v == l2->v);
+
+ BM_elem_attrs_copy(bm, bm, l2, l_iter);
+ }
+ } while ((l_iter = l_iter->next) != l_first);
#ifdef USE_BMESH_HOLES
- /* add holes */
- BLI_movelisttolist(&f_new->loops, &holes);
-
- /* update loop face pointer */
- for (lst = f_new->loops.first; lst; lst = lst->next) {
- l_iter = l_first = lst->first;
- do {
- l_iter->f = f_new;
- } while ((l_iter = l_iter->next) != l_first);
- }
+ /* add holes */
+ BLI_movelisttolist(&f_new->loops, &holes);
+
+ /* update loop face pointer */
+ for (lst = f_new->loops.first; lst; lst = lst->next) {
+ l_iter = l_first = lst->first;
+ do {
+ l_iter->f = f_new;
+ } while ((l_iter = l_iter->next) != l_first);
+ }
#endif
- bm_elements_systag_disable(faces, totface, _FLAG_JF);
- BM_ELEM_API_FLAG_DISABLE(f_new, _FLAG_JF);
-
- /* handle multi-res data */
- if (cd_loop_mdisp_offset != -1) {
- float f_center[3];
- float (*faces_center)[3] = BLI_array_alloca(faces_center, totface);
-
- BM_face_calc_center_median(f_new, f_center);
- for (i = 0; i < totface; i++) {
- BM_face_calc_center_median(faces[i], faces_center[i]);
- }
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(f_new);
- do {
- for (i = 0; i < totface; i++) {
- BM_loop_interp_multires_ex(bm, l_iter, faces[i], f_center, faces_center[i], cd_loop_mdisp_offset);
- }
- } while ((l_iter = l_iter->next) != l_first);
- }
-
- /* delete old geometry */
- if (do_del) {
- for (i = 0; i < BLI_array_len(deledges); i++) {
- BM_edge_kill(bm, deledges[i]);
- }
-
- for (i = 0; i < BLI_array_len(delverts); i++) {
- BM_vert_kill(bm, delverts[i]);
- }
- }
- else {
- /* otherwise we get both old and new faces */
- for (i = 0; i < totface; i++) {
- BM_face_kill(bm, faces[i]);
- }
- }
-
- BLI_array_free(edges);
- BLI_array_free(deledges);
- BLI_array_free(delverts);
-
- BM_CHECK_ELEMENT(f_new);
- return f_new;
+ bm_elements_systag_disable(faces, totface, _FLAG_JF);
+ BM_ELEM_API_FLAG_DISABLE(f_new, _FLAG_JF);
+
+ /* handle multi-res data */
+ if (cd_loop_mdisp_offset != -1) {
+ float f_center[3];
+ float(*faces_center)[3] = BLI_array_alloca(faces_center, totface);
+
+ BM_face_calc_center_median(f_new, f_center);
+ for (i = 0; i < totface; i++) {
+ BM_face_calc_center_median(faces[i], faces_center[i]);
+ }
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_new);
+ do {
+ for (i = 0; i < totface; i++) {
+ BM_loop_interp_multires_ex(
+ bm, l_iter, faces[i], f_center, faces_center[i], cd_loop_mdisp_offset);
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+
+ /* delete old geometry */
+ if (do_del) {
+ for (i = 0; i < BLI_array_len(deledges); i++) {
+ BM_edge_kill(bm, deledges[i]);
+ }
+
+ for (i = 0; i < BLI_array_len(delverts); i++) {
+ BM_vert_kill(bm, delverts[i]);
+ }
+ }
+ else {
+ /* otherwise we get both old and new faces */
+ for (i = 0; i < totface; i++) {
+ BM_face_kill(bm, faces[i]);
+ }
+ }
+
+ BLI_array_free(edges);
+ BLI_array_free(deledges);
+ BLI_array_free(delverts);
+
+ BM_CHECK_ELEMENT(f_new);
+ return f_new;
error:
- bm_elements_systag_disable(faces, totface, _FLAG_JF);
- BLI_array_free(edges);
- BLI_array_free(deledges);
- BLI_array_free(delverts);
+ bm_elements_systag_disable(faces, totface, _FLAG_JF);
+ BLI_array_free(edges);
+ BLI_array_free(deledges);
+ BLI_array_free(delverts);
- return NULL;
+ return NULL;
}
static BMFace *bm_face_create__sfme(BMesh *bm, BMFace *f_example)
{
- BMFace *f;
+ BMFace *f;
#ifdef USE_BMESH_HOLES
- BMLoopList *lst;
+ BMLoopList *lst;
#endif
- f = bm_face_create__internal(bm);
+ f = bm_face_create__internal(bm);
#ifdef USE_BMESH_HOLES
- lst = BLI_mempool_calloc(bm->looplistpool);
- BLI_addtail(&f->loops, lst);
+ lst = BLI_mempool_calloc(bm->looplistpool);
+ BLI_addtail(&f->loops, lst);
#endif
#ifdef USE_BMESH_HOLES
- f->totbounds = 1;
+ f->totbounds = 1;
#endif
- BM_elem_attrs_copy(bm, bm, f_example, f);
+ BM_elem_attrs_copy(bm, bm, f_example, f);
- return f;
+ return f;
}
/**
@@ -1447,141 +1449,143 @@ static BMFace *bm_face_create__sfme(BMesh *bm, BMFace *f_example)
*
* \return A BMFace pointer
*/
-BMFace *bmesh_kernel_split_face_make_edge(
- BMesh *bm, BMFace *f, BMLoop *l_v1, BMLoop *l_v2,
- BMLoop **r_l,
+BMFace *bmesh_kernel_split_face_make_edge(BMesh *bm,
+ BMFace *f,
+ BMLoop *l_v1,
+ BMLoop *l_v2,
+ BMLoop **r_l,
#ifdef USE_BMESH_HOLES
- ListBase *holes,
+ ListBase *holes,
#endif
- BMEdge *e_example,
- const bool no_double)
+ BMEdge *e_example,
+ const bool no_double)
{
#ifdef USE_BMESH_HOLES
- BMLoopList *lst, *lst2;
+ BMLoopList *lst, *lst2;
#else
- int first_loop_f1;
+ int first_loop_f1;
#endif
- BMFace *f2;
- BMLoop *l_iter, *l_first;
- BMLoop *l_f1 = NULL, *l_f2 = NULL;
- BMEdge *e;
- BMVert *v1 = l_v1->v, *v2 = l_v2->v;
- int f1len, f2len;
+ BMFace *f2;
+ BMLoop *l_iter, *l_first;
+ BMLoop *l_f1 = NULL, *l_f2 = NULL;
+ BMEdge *e;
+ BMVert *v1 = l_v1->v, *v2 = l_v2->v;
+ int f1len, f2len;
- BLI_assert(f == l_v1->f && f == l_v2->f);
+ BLI_assert(f == l_v1->f && f == l_v2->f);
- /* allocate new edge between v1 and v2 */
- e = BM_edge_create(bm, v1, v2, e_example, no_double ? BM_CREATE_NO_DOUBLE : BM_CREATE_NOP);
+ /* allocate new edge between v1 and v2 */
+ e = BM_edge_create(bm, v1, v2, e_example, no_double ? BM_CREATE_NO_DOUBLE : BM_CREATE_NOP);
- f2 = bm_face_create__sfme(bm, f);
- l_f1 = bm_loop_create(bm, v2, e, f, l_v2, 0);
- l_f2 = bm_loop_create(bm, v1, e, f2, l_v1, 0);
+ f2 = bm_face_create__sfme(bm, f);
+ l_f1 = bm_loop_create(bm, v2, e, f, l_v2, 0);
+ l_f2 = bm_loop_create(bm, v1, e, f2, l_v1, 0);
- l_f1->prev = l_v2->prev;
- l_f2->prev = l_v1->prev;
- l_v2->prev->next = l_f1;
- l_v1->prev->next = l_f2;
+ l_f1->prev = l_v2->prev;
+ l_f2->prev = l_v1->prev;
+ l_v2->prev->next = l_f1;
+ l_v1->prev->next = l_f2;
- l_f1->next = l_v1;
- l_f2->next = l_v2;
- l_v1->prev = l_f1;
- l_v2->prev = l_f2;
+ l_f1->next = l_v1;
+ l_f2->next = l_v2;
+ l_v1->prev = l_f1;
+ l_v2->prev = l_f2;
#ifdef USE_BMESH_HOLES
- lst = f->loops.first;
- lst2 = f2->loops.first;
+ lst = f->loops.first;
+ lst2 = f2->loops.first;
- lst2->first = lst2->last = l_f2;
- lst->first = lst->last = l_f1;
+ lst2->first = lst2->last = l_f2;
+ lst->first = lst->last = l_f1;
#else
- /* find which of the faces the original first loop is in */
- l_iter = l_first = l_f1;
- first_loop_f1 = 0;
- do {
- if (l_iter == f->l_first) {
- first_loop_f1 = 1;
- }
- } while ((l_iter = l_iter->next) != l_first);
-
- if (first_loop_f1) {
- /* original first loop was in f1, find a suitable first loop for f2
- * which is as similar as possible to f1. the order matters for tools
- * such as duplifaces. */
- if (f->l_first->prev == l_f1) {
- f2->l_first = l_f2->prev;
- }
- else if (f->l_first->next == l_f1) {
- f2->l_first = l_f2->next;
- }
- else {
- f2->l_first = l_f2;
- }
- }
- else {
- /* original first loop was in f2, further do same as above */
- f2->l_first = f->l_first;
-
- if (f->l_first->prev == l_f2) {
- f->l_first = l_f1->prev;
- }
- else if (f->l_first->next == l_f2) {
- f->l_first = l_f1->next;
- }
- else {
- f->l_first = l_f1;
- }
- }
+ /* find which of the faces the original first loop is in */
+ l_iter = l_first = l_f1;
+ first_loop_f1 = 0;
+ do {
+ if (l_iter == f->l_first) {
+ first_loop_f1 = 1;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+
+ if (first_loop_f1) {
+ /* original first loop was in f1, find a suitable first loop for f2
+ * which is as similar as possible to f1. the order matters for tools
+ * such as duplifaces. */
+ if (f->l_first->prev == l_f1) {
+ f2->l_first = l_f2->prev;
+ }
+ else if (f->l_first->next == l_f1) {
+ f2->l_first = l_f2->next;
+ }
+ else {
+ f2->l_first = l_f2;
+ }
+ }
+ else {
+ /* original first loop was in f2, further do same as above */
+ f2->l_first = f->l_first;
+
+ if (f->l_first->prev == l_f2) {
+ f->l_first = l_f1->prev;
+ }
+ else if (f->l_first->next == l_f2) {
+ f->l_first = l_f1->next;
+ }
+ else {
+ f->l_first = l_f1;
+ }
+ }
#endif
- /* validate both loop */
- /* I don't know how many loops are supposed to be in each face at this point! FIXME */
+ /* validate both loop */
+ /* I don't know how many loops are supposed to be in each face at this point! FIXME */
- /* go through all of f2's loops and make sure they point to it properly */
- l_iter = l_first = BM_FACE_FIRST_LOOP(f2);
- f2len = 0;
- do {
- l_iter->f = f2;
- f2len++;
- } while ((l_iter = l_iter->next) != l_first);
+ /* go through all of f2's loops and make sure they point to it properly */
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f2);
+ f2len = 0;
+ do {
+ l_iter->f = f2;
+ f2len++;
+ } while ((l_iter = l_iter->next) != l_first);
- /* link up the new loops into the new edges radial */
- bmesh_radial_loop_append(e, l_f1);
- bmesh_radial_loop_append(e, l_f2);
+ /* link up the new loops into the new edges radial */
+ bmesh_radial_loop_append(e, l_f1);
+ bmesh_radial_loop_append(e, l_f2);
- f2->len = f2len;
+ f2->len = f2len;
- f1len = 0;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- f1len++;
- } while ((l_iter = l_iter->next) != l_first);
+ f1len = 0;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ f1len++;
+ } while ((l_iter = l_iter->next) != l_first);
- f->len = f1len;
+ f->len = f1len;
- if (r_l) {
- *r_l = l_f2;
- }
+ if (r_l) {
+ *r_l = l_f2;
+ }
#ifdef USE_BMESH_HOLES
- if (holes) {
- BLI_movelisttolist(&f2->loops, holes);
- }
- else {
- /* this code is not significant until holes actually work */
- //printf("warning: call to split face euler without holes argument; holes will be tossed.\n");
- for (lst = f->loops.last; lst != f->loops.first; lst = lst2) {
- lst2 = lst->prev;
- BLI_mempool_free(bm->looplistpool, lst);
- }
- }
+ if (holes) {
+ BLI_movelisttolist(&f2->loops, holes);
+ }
+ else {
+ /* this code is not significant until holes actually work */
+ //printf("warning: call to split face euler without holes argument; holes will be tossed.\n");
+ for (lst = f->loops.last; lst != f->loops.first; lst = lst2) {
+ lst2 = lst->prev;
+ BLI_mempool_free(bm->looplistpool, lst);
+ }
+ }
#endif
- BM_CHECK_ELEMENT(e);
- BM_CHECK_ELEMENT(f);
- BM_CHECK_ELEMENT(f2);
+ BM_CHECK_ELEMENT(e);
+ BM_CHECK_ELEMENT(f);
+ BM_CHECK_ELEMENT(f2);
- return f2;
+ return f2;
}
/**
@@ -1604,156 +1608,155 @@ BMFace *bmesh_kernel_split_face_make_edge(
*/
BMVert *bmesh_kernel_split_edge_make_vert(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e)
{
- BMLoop *l_next;
- BMEdge *e_new;
- BMVert *v_new, *v_old;
+ BMLoop *l_next;
+ BMEdge *e_new;
+ BMVert *v_new, *v_old;
#ifndef NDEBUG
- int valence1, valence2;
- bool edok;
- int i;
+ int valence1, valence2;
+ bool edok;
+ int i;
#endif
- BLI_assert(BM_vert_in_edge(e, tv) != false);
+ BLI_assert(BM_vert_in_edge(e, tv) != false);
- v_old = BM_edge_other_vert(e, tv);
+ v_old = BM_edge_other_vert(e, tv);
#ifndef NDEBUG
- valence1 = bmesh_disk_count(v_old);
- valence2 = bmesh_disk_count(tv);
+ valence1 = bmesh_disk_count(v_old);
+ valence2 = bmesh_disk_count(tv);
#endif
- /* order of 'e_new' verts should match 'e'
- * (so extruded faces don't flip) */
- v_new = BM_vert_create(bm, tv->co, tv, BM_CREATE_NOP);
- e_new = BM_edge_create(bm, tv, v_new, e, BM_CREATE_NOP);
+ /* order of 'e_new' verts should match 'e'
+ * (so extruded faces don't flip) */
+ v_new = BM_vert_create(bm, tv->co, tv, BM_CREATE_NOP);
+ e_new = BM_edge_create(bm, tv, v_new, e, BM_CREATE_NOP);
- bmesh_disk_edge_remove(e_new, tv);
- bmesh_disk_edge_remove(e_new, v_new);
+ bmesh_disk_edge_remove(e_new, tv);
+ bmesh_disk_edge_remove(e_new, v_new);
- bmesh_disk_vert_replace(e, v_new, tv);
+ bmesh_disk_vert_replace(e, v_new, tv);
- /* add e_new to v_new's disk cycle */
- bmesh_disk_edge_append(e_new, v_new);
+ /* add e_new to v_new's disk cycle */
+ bmesh_disk_edge_append(e_new, v_new);
- /* add e_new to tv's disk cycle */
- bmesh_disk_edge_append(e_new, tv);
+ /* add e_new to tv's disk cycle */
+ bmesh_disk_edge_append(e_new, tv);
#ifndef NDEBUG
- /* verify disk cycles */
- edok = bmesh_disk_validate(valence1, v_old->e, v_old);
- BMESH_ASSERT(edok != false);
- edok = bmesh_disk_validate(valence2, tv->e, tv);
- BMESH_ASSERT(edok != false);
- edok = bmesh_disk_validate(2, v_new->e, v_new);
- BMESH_ASSERT(edok != false);
+ /* verify disk cycles */
+ edok = bmesh_disk_validate(valence1, v_old->e, v_old);
+ BMESH_ASSERT(edok != false);
+ edok = bmesh_disk_validate(valence2, tv->e, tv);
+ BMESH_ASSERT(edok != false);
+ edok = bmesh_disk_validate(2, v_new->e, v_new);
+ BMESH_ASSERT(edok != false);
#endif
- /* Split the radial cycle if present */
- l_next = e->l;
- e->l = NULL;
- if (l_next) {
- BMLoop *l_new, *l;
+ /* Split the radial cycle if present */
+ l_next = e->l;
+ e->l = NULL;
+ if (l_next) {
+ BMLoop *l_new, *l;
#ifndef NDEBUG
- int radlen = bmesh_radial_length(l_next);
+ int radlen = bmesh_radial_length(l_next);
#endif
- bool is_first = true;
-
- /* Take the next loop. Remove it from radial. Split it. Append to appropriate radials */
- while (l_next) {
- l = l_next;
- l->f->len++;
- l_next = l_next != l_next->radial_next ? l_next->radial_next : NULL;
- bmesh_radial_loop_unlink(l);
-
- l_new = bm_loop_create(bm, NULL, NULL, l->f, l, 0);
- l_new->prev = l;
- l_new->next = l->next;
- l_new->prev->next = l_new;
- l_new->next->prev = l_new;
- l_new->v = v_new;
-
- /* assign the correct edge to the correct loop */
- if (BM_verts_in_edge(l_new->v, l_new->next->v, e)) {
- l_new->e = e;
- l->e = e_new;
-
- /* append l into e_new's rad cycle */
- if (is_first) {
- is_first = false;
- l->radial_next = l->radial_prev = NULL;
- }
-
- bmesh_radial_loop_append(l_new->e, l_new);
- bmesh_radial_loop_append(l->e, l);
- }
- else if (BM_verts_in_edge(l_new->v, l_new->next->v, e_new)) {
- l_new->e = e_new;
- l->e = e;
-
- /* append l into e_new's rad cycle */
- if (is_first) {
- is_first = false;
- l->radial_next = l->radial_prev = NULL;
- }
-
- bmesh_radial_loop_append(l_new->e, l_new);
- bmesh_radial_loop_append(l->e, l);
- }
-
- }
+ bool is_first = true;
+
+ /* Take the next loop. Remove it from radial. Split it. Append to appropriate radials */
+ while (l_next) {
+ l = l_next;
+ l->f->len++;
+ l_next = l_next != l_next->radial_next ? l_next->radial_next : NULL;
+ bmesh_radial_loop_unlink(l);
+
+ l_new = bm_loop_create(bm, NULL, NULL, l->f, l, 0);
+ l_new->prev = l;
+ l_new->next = l->next;
+ l_new->prev->next = l_new;
+ l_new->next->prev = l_new;
+ l_new->v = v_new;
+
+ /* assign the correct edge to the correct loop */
+ if (BM_verts_in_edge(l_new->v, l_new->next->v, e)) {
+ l_new->e = e;
+ l->e = e_new;
+
+ /* append l into e_new's rad cycle */
+ if (is_first) {
+ is_first = false;
+ l->radial_next = l->radial_prev = NULL;
+ }
+
+ bmesh_radial_loop_append(l_new->e, l_new);
+ bmesh_radial_loop_append(l->e, l);
+ }
+ else if (BM_verts_in_edge(l_new->v, l_new->next->v, e_new)) {
+ l_new->e = e_new;
+ l->e = e;
+
+ /* append l into e_new's rad cycle */
+ if (is_first) {
+ is_first = false;
+ l->radial_next = l->radial_prev = NULL;
+ }
+
+ bmesh_radial_loop_append(l_new->e, l_new);
+ bmesh_radial_loop_append(l->e, l);
+ }
+ }
#ifndef NDEBUG
- /* verify length of radial cycle */
- edok = bmesh_radial_validate(radlen, e->l);
- BMESH_ASSERT(edok != false);
- edok = bmesh_radial_validate(radlen, e_new->l);
- BMESH_ASSERT(edok != false);
-
- /* verify loop->v and loop->next->v pointers for e */
- for (i = 0, l = e->l; i < radlen; i++, l = l->radial_next) {
- BMESH_ASSERT(l->e == e);
- //BMESH_ASSERT(l->radial_next == l);
- BMESH_ASSERT(!(l->prev->e != e_new && l->next->e != e_new));
-
- edok = BM_verts_in_edge(l->v, l->next->v, e);
- BMESH_ASSERT(edok != false);
- BMESH_ASSERT(l->v != l->next->v);
- BMESH_ASSERT(l->e != l->next->e);
-
- /* verify loop cycle for kloop->f */
- BM_CHECK_ELEMENT(l);
- BM_CHECK_ELEMENT(l->v);
- BM_CHECK_ELEMENT(l->e);
- BM_CHECK_ELEMENT(l->f);
- }
- /* verify loop->v and loop->next->v pointers for e_new */
- for (i = 0, l = e_new->l; i < radlen; i++, l = l->radial_next) {
- BMESH_ASSERT(l->e == e_new);
- // BMESH_ASSERT(l->radial_next == l);
- BMESH_ASSERT(!(l->prev->e != e && l->next->e != e));
- edok = BM_verts_in_edge(l->v, l->next->v, e_new);
- BMESH_ASSERT(edok != false);
- BMESH_ASSERT(l->v != l->next->v);
- BMESH_ASSERT(l->e != l->next->e);
-
- BM_CHECK_ELEMENT(l);
- BM_CHECK_ELEMENT(l->v);
- BM_CHECK_ELEMENT(l->e);
- BM_CHECK_ELEMENT(l->f);
- }
+ /* verify length of radial cycle */
+ edok = bmesh_radial_validate(radlen, e->l);
+ BMESH_ASSERT(edok != false);
+ edok = bmesh_radial_validate(radlen, e_new->l);
+ BMESH_ASSERT(edok != false);
+
+ /* verify loop->v and loop->next->v pointers for e */
+ for (i = 0, l = e->l; i < radlen; i++, l = l->radial_next) {
+ BMESH_ASSERT(l->e == e);
+ //BMESH_ASSERT(l->radial_next == l);
+ BMESH_ASSERT(!(l->prev->e != e_new && l->next->e != e_new));
+
+ edok = BM_verts_in_edge(l->v, l->next->v, e);
+ BMESH_ASSERT(edok != false);
+ BMESH_ASSERT(l->v != l->next->v);
+ BMESH_ASSERT(l->e != l->next->e);
+
+ /* verify loop cycle for kloop->f */
+ BM_CHECK_ELEMENT(l);
+ BM_CHECK_ELEMENT(l->v);
+ BM_CHECK_ELEMENT(l->e);
+ BM_CHECK_ELEMENT(l->f);
+ }
+ /* verify loop->v and loop->next->v pointers for e_new */
+ for (i = 0, l = e_new->l; i < radlen; i++, l = l->radial_next) {
+ BMESH_ASSERT(l->e == e_new);
+ // BMESH_ASSERT(l->radial_next == l);
+ BMESH_ASSERT(!(l->prev->e != e && l->next->e != e));
+ edok = BM_verts_in_edge(l->v, l->next->v, e_new);
+ BMESH_ASSERT(edok != false);
+ BMESH_ASSERT(l->v != l->next->v);
+ BMESH_ASSERT(l->e != l->next->e);
+
+ BM_CHECK_ELEMENT(l);
+ BM_CHECK_ELEMENT(l->v);
+ BM_CHECK_ELEMENT(l->e);
+ BM_CHECK_ELEMENT(l->f);
+ }
#endif
- }
-
- BM_CHECK_ELEMENT(e_new);
- BM_CHECK_ELEMENT(v_new);
- BM_CHECK_ELEMENT(v_old);
- BM_CHECK_ELEMENT(e);
- BM_CHECK_ELEMENT(tv);
-
- if (r_e) {
- *r_e = e_new;
- }
- return v_new;
+ }
+
+ BM_CHECK_ELEMENT(e_new);
+ BM_CHECK_ELEMENT(v_new);
+ BM_CHECK_ELEMENT(v_old);
+ BM_CHECK_ELEMENT(e);
+ BM_CHECK_ELEMENT(tv);
+
+ if (r_e) {
+ *r_e = e_new;
+ }
+ return v_new;
}
/**
@@ -1786,153 +1789,154 @@ BMVert *bmesh_kernel_split_edge_make_vert(BMesh *bm, BMVert *tv, BMEdge *e, BMEd
* faces with just 2 edges. It is up to the caller to decide what to do with
* these faces.
*/
-BMEdge *bmesh_kernel_join_edge_kill_vert(
- BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
- const bool do_del, const bool check_edge_double,
- const bool kill_degenerate_faces)
+BMEdge *bmesh_kernel_join_edge_kill_vert(BMesh *bm,
+ BMEdge *e_kill,
+ BMVert *v_kill,
+ const bool do_del,
+ const bool check_edge_double,
+ const bool kill_degenerate_faces)
{
- BMEdge *e_old;
- BMVert *v_old, *v_target;
- BMLoop *l_kill;
+ BMEdge *e_old;
+ BMVert *v_old, *v_target;
+ BMLoop *l_kill;
#ifndef NDEBUG
- int radlen, i;
- bool edok;
+ int radlen, i;
+ bool edok;
#endif
- BLI_assert(BM_vert_in_edge(e_kill, v_kill));
+ BLI_assert(BM_vert_in_edge(e_kill, v_kill));
- if (BM_vert_in_edge(e_kill, v_kill) == 0) {
- return NULL;
- }
+ if (BM_vert_in_edge(e_kill, v_kill) == 0) {
+ return NULL;
+ }
- if (bmesh_disk_count_at_most(v_kill, 3) == 2) {
+ if (bmesh_disk_count_at_most(v_kill, 3) == 2) {
#ifndef NDEBUG
- int valence1, valence2;
- BMLoop *l;
+ int valence1, valence2;
+ BMLoop *l;
#endif
- e_old = bmesh_disk_edge_next(e_kill, v_kill);
- v_target = BM_edge_other_vert(e_kill, v_kill);
- v_old = BM_edge_other_vert(e_old, v_kill);
+ e_old = bmesh_disk_edge_next(e_kill, v_kill);
+ v_target = BM_edge_other_vert(e_kill, v_kill);
+ v_old = BM_edge_other_vert(e_old, v_kill);
- /* check for double edges */
- if (BM_verts_in_edge(v_kill, v_target, e_old)) {
- return NULL;
- }
- else {
- BMEdge *e_splice;
- BLI_SMALLSTACK_DECLARE(faces_degenerate, BMFace *);
- BMLoop *l_kill_next;
+ /* check for double edges */
+ if (BM_verts_in_edge(v_kill, v_target, e_old)) {
+ return NULL;
+ }
+ else {
+ BMEdge *e_splice;
+ BLI_SMALLSTACK_DECLARE(faces_degenerate, BMFace *);
+ BMLoop *l_kill_next;
#ifndef NDEBUG
- /* For verification later, count valence of 'v_old' and 'v_target' */
- valence1 = bmesh_disk_count(v_old);
- valence2 = bmesh_disk_count(v_target);
+ /* For verification later, count valence of 'v_old' and 'v_target' */
+ valence1 = bmesh_disk_count(v_old);
+ valence2 = bmesh_disk_count(v_target);
#endif
- if (check_edge_double) {
- e_splice = BM_edge_exists(v_target, v_old);
- }
+ if (check_edge_double) {
+ e_splice = BM_edge_exists(v_target, v_old);
+ }
- bmesh_disk_vert_replace(e_old, v_target, v_kill);
+ bmesh_disk_vert_replace(e_old, v_target, v_kill);
- /* remove e_kill from 'v_target's disk cycle */
- bmesh_disk_edge_remove(e_kill, v_target);
+ /* remove e_kill from 'v_target's disk cycle */
+ bmesh_disk_edge_remove(e_kill, v_target);
#ifndef NDEBUG
- /* deal with radial cycle of e_kill */
- radlen = bmesh_radial_length(e_kill->l);
+ /* deal with radial cycle of e_kill */
+ radlen = bmesh_radial_length(e_kill->l);
#endif
- if (e_kill->l) {
-
-
- /* fix the neighboring loops of all loops in e_kill's radial cycle */
- l_kill = e_kill->l;
- do {
- /* relink loops and fix vertex pointer */
- if (l_kill->next->v == v_kill) {
- l_kill->next->v = v_target;
- }
-
- l_kill->next->prev = l_kill->prev;
- l_kill->prev->next = l_kill->next;
- if (BM_FACE_FIRST_LOOP(l_kill->f) == l_kill) {
- BM_FACE_FIRST_LOOP(l_kill->f) = l_kill->next;
- }
-
- /* fix len attribute of face */
- l_kill->f->len--;
- if (kill_degenerate_faces) {
- if (l_kill->f->len < 3) {
- BLI_SMALLSTACK_PUSH(faces_degenerate, l_kill->f);
- }
- }
- l_kill_next = l_kill->radial_next;
-
- bm_kill_only_loop(bm, l_kill);
-
- } while ((l_kill = l_kill_next) != e_kill->l);
- /* `e_kill->l` is invalid but the edge is freed next. */
+ if (e_kill->l) {
+
+ /* fix the neighboring loops of all loops in e_kill's radial cycle */
+ l_kill = e_kill->l;
+ do {
+ /* relink loops and fix vertex pointer */
+ if (l_kill->next->v == v_kill) {
+ l_kill->next->v = v_target;
+ }
+
+ l_kill->next->prev = l_kill->prev;
+ l_kill->prev->next = l_kill->next;
+ if (BM_FACE_FIRST_LOOP(l_kill->f) == l_kill) {
+ BM_FACE_FIRST_LOOP(l_kill->f) = l_kill->next;
+ }
+
+ /* fix len attribute of face */
+ l_kill->f->len--;
+ if (kill_degenerate_faces) {
+ if (l_kill->f->len < 3) {
+ BLI_SMALLSTACK_PUSH(faces_degenerate, l_kill->f);
+ }
+ }
+ l_kill_next = l_kill->radial_next;
+
+ bm_kill_only_loop(bm, l_kill);
+
+ } while ((l_kill = l_kill_next) != e_kill->l);
+ /* `e_kill->l` is invalid but the edge is freed next. */
#ifndef NDEBUG
- /* Validate radial cycle of e_old */
- edok = bmesh_radial_validate(radlen, e_old->l);
- BMESH_ASSERT(edok != false);
+ /* Validate radial cycle of e_old */
+ edok = bmesh_radial_validate(radlen, e_old->l);
+ BMESH_ASSERT(edok != false);
#endif
- }
- /* deallocate edge */
- bm_kill_only_edge(bm, e_kill);
-
- /* deallocate vertex */
- if (do_del) {
- bm_kill_only_vert(bm, v_kill);
- }
- else {
- v_kill->e = NULL;
- }
+ }
+ /* deallocate edge */
+ bm_kill_only_edge(bm, e_kill);
+
+ /* deallocate vertex */
+ if (do_del) {
+ bm_kill_only_vert(bm, v_kill);
+ }
+ else {
+ v_kill->e = NULL;
+ }
#ifndef NDEBUG
- /* Validate disk cycle lengths of 'v_old', 'v_target' are unchanged */
- edok = bmesh_disk_validate(valence1, v_old->e, v_old);
- BMESH_ASSERT(edok != false);
- edok = bmesh_disk_validate(valence2, v_target->e, v_target);
- BMESH_ASSERT(edok != false);
-
- /* Validate loop cycle of all faces attached to 'e_old' */
- for (i = 0, l = e_old->l; i < radlen; i++, l = l->radial_next) {
- BMESH_ASSERT(l->e == e_old);
- edok = BM_verts_in_edge(l->v, l->next->v, e_old);
- BMESH_ASSERT(edok != false);
- edok = bmesh_loop_validate(l->f);
- BMESH_ASSERT(edok != false);
-
- BM_CHECK_ELEMENT(l);
- BM_CHECK_ELEMENT(l->v);
- BM_CHECK_ELEMENT(l->e);
- BM_CHECK_ELEMENT(l->f);
- }
+ /* Validate disk cycle lengths of 'v_old', 'v_target' are unchanged */
+ edok = bmesh_disk_validate(valence1, v_old->e, v_old);
+ BMESH_ASSERT(edok != false);
+ edok = bmesh_disk_validate(valence2, v_target->e, v_target);
+ BMESH_ASSERT(edok != false);
+
+ /* Validate loop cycle of all faces attached to 'e_old' */
+ for (i = 0, l = e_old->l; i < radlen; i++, l = l->radial_next) {
+ BMESH_ASSERT(l->e == e_old);
+ edok = BM_verts_in_edge(l->v, l->next->v, e_old);
+ BMESH_ASSERT(edok != false);
+ edok = bmesh_loop_validate(l->f);
+ BMESH_ASSERT(edok != false);
+
+ BM_CHECK_ELEMENT(l);
+ BM_CHECK_ELEMENT(l->v);
+ BM_CHECK_ELEMENT(l->e);
+ BM_CHECK_ELEMENT(l->f);
+ }
#endif
- if (check_edge_double) {
- if (e_splice) {
- /* removes e_splice */
- BM_edge_splice(bm, e_old, e_splice);
- }
- }
-
- if (kill_degenerate_faces) {
- BMFace *f_kill;
- while ((f_kill = BLI_SMALLSTACK_POP(faces_degenerate))) {
- BM_face_kill(bm, f_kill);
- }
- }
-
- BM_CHECK_ELEMENT(v_old);
- BM_CHECK_ELEMENT(v_target);
- BM_CHECK_ELEMENT(e_old);
-
- return e_old;
- }
- }
- return NULL;
+ if (check_edge_double) {
+ if (e_splice) {
+ /* removes e_splice */
+ BM_edge_splice(bm, e_old, e_splice);
+ }
+ }
+
+ if (kill_degenerate_faces) {
+ BMFace *f_kill;
+ while ((f_kill = BLI_SMALLSTACK_POP(faces_degenerate))) {
+ BM_face_kill(bm, f_kill);
+ }
+ }
+
+ BM_CHECK_ELEMENT(v_old);
+ BM_CHECK_ELEMENT(v_target);
+ BM_CHECK_ELEMENT(e_old);
+
+ return e_old;
+ }
+ }
+ return NULL;
}
/**
@@ -1952,85 +1956,87 @@ BMEdge *bmesh_kernel_join_edge_kill_vert(
* +-+-+-+ +-+-+-+
* </pre>
*/
-BMVert *bmesh_kernel_join_vert_kill_edge(
- BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
- const bool do_del, const bool check_edge_double,
- const bool kill_degenerate_faces)
+BMVert *bmesh_kernel_join_vert_kill_edge(BMesh *bm,
+ BMEdge *e_kill,
+ BMVert *v_kill,
+ const bool do_del,
+ const bool check_edge_double,
+ const bool kill_degenerate_faces)
{
- BLI_SMALLSTACK_DECLARE(faces_degenerate, BMFace *);
- BMVert *v_target = BM_edge_other_vert(e_kill, v_kill);
-
- BLI_assert(BM_vert_in_edge(e_kill, v_kill));
-
- if (e_kill->l) {
- BMLoop *l_kill, *l_first, *l_kill_next;
- l_kill = l_first = e_kill->l;
- do {
- /* relink loops and fix vertex pointer */
- if (l_kill->next->v == v_kill) {
- l_kill->next->v = v_target;
- }
-
- l_kill->next->prev = l_kill->prev;
- l_kill->prev->next = l_kill->next;
- if (BM_FACE_FIRST_LOOP(l_kill->f) == l_kill) {
- BM_FACE_FIRST_LOOP(l_kill->f) = l_kill->next;
- }
-
- /* fix len attribute of face */
- l_kill->f->len--;
- if (kill_degenerate_faces) {
- if (l_kill->f->len < 3) {
- BLI_SMALLSTACK_PUSH(faces_degenerate, l_kill->f);
- }
- }
- l_kill_next = l_kill->radial_next;
-
- bm_kill_only_loop(bm, l_kill);
-
- } while ((l_kill = l_kill_next) != l_first);
-
- e_kill->l = NULL;
- }
-
- BM_edge_kill(bm, e_kill);
- BM_CHECK_ELEMENT(v_kill);
- BM_CHECK_ELEMENT(v_target);
-
- if (v_target->e && v_kill->e) {
- /* inline BM_vert_splice(bm, v_target, v_kill); */
- BMEdge *e;
- while ((e = v_kill->e)) {
- BMEdge *e_target;
-
- if (check_edge_double) {
- e_target = BM_edge_exists(v_target, BM_edge_other_vert(e, v_kill));
- }
-
- bmesh_edge_vert_swap(e, v_target, v_kill);
- BLI_assert(e->v1 != e->v2);
-
- if (check_edge_double) {
- if (e_target) {
- BM_edge_splice(bm, e_target, e);
- }
- }
- }
- }
-
- if (kill_degenerate_faces) {
- BMFace *f_kill;
- while ((f_kill = BLI_SMALLSTACK_POP(faces_degenerate))) {
- BM_face_kill(bm, f_kill);
- }
- }
-
- if (do_del) {
- BLI_assert(v_kill->e == NULL);
- bm_kill_only_vert(bm, v_kill);
- }
-
- return v_target;
+ BLI_SMALLSTACK_DECLARE(faces_degenerate, BMFace *);
+ BMVert *v_target = BM_edge_other_vert(e_kill, v_kill);
+
+ BLI_assert(BM_vert_in_edge(e_kill, v_kill));
+
+ if (e_kill->l) {
+ BMLoop *l_kill, *l_first, *l_kill_next;
+ l_kill = l_first = e_kill->l;
+ do {
+ /* relink loops and fix vertex pointer */
+ if (l_kill->next->v == v_kill) {
+ l_kill->next->v = v_target;
+ }
+
+ l_kill->next->prev = l_kill->prev;
+ l_kill->prev->next = l_kill->next;
+ if (BM_FACE_FIRST_LOOP(l_kill->f) == l_kill) {
+ BM_FACE_FIRST_LOOP(l_kill->f) = l_kill->next;
+ }
+
+ /* fix len attribute of face */
+ l_kill->f->len--;
+ if (kill_degenerate_faces) {
+ if (l_kill->f->len < 3) {
+ BLI_SMALLSTACK_PUSH(faces_degenerate, l_kill->f);
+ }
+ }
+ l_kill_next = l_kill->radial_next;
+
+ bm_kill_only_loop(bm, l_kill);
+
+ } while ((l_kill = l_kill_next) != l_first);
+
+ e_kill->l = NULL;
+ }
+
+ BM_edge_kill(bm, e_kill);
+ BM_CHECK_ELEMENT(v_kill);
+ BM_CHECK_ELEMENT(v_target);
+
+ if (v_target->e && v_kill->e) {
+ /* inline BM_vert_splice(bm, v_target, v_kill); */
+ BMEdge *e;
+ while ((e = v_kill->e)) {
+ BMEdge *e_target;
+
+ if (check_edge_double) {
+ e_target = BM_edge_exists(v_target, BM_edge_other_vert(e, v_kill));
+ }
+
+ bmesh_edge_vert_swap(e, v_target, v_kill);
+ BLI_assert(e->v1 != e->v2);
+
+ if (check_edge_double) {
+ if (e_target) {
+ BM_edge_splice(bm, e_target, e);
+ }
+ }
+ }
+ }
+
+ if (kill_degenerate_faces) {
+ BMFace *f_kill;
+ while ((f_kill = BLI_SMALLSTACK_POP(faces_degenerate))) {
+ BM_face_kill(bm, f_kill);
+ }
+ }
+
+ if (do_del) {
+ BLI_assert(v_kill->e == NULL);
+ bm_kill_only_vert(bm, v_kill);
+ }
+
+ return v_target;
}
/**
@@ -2066,129 +2072,124 @@ BMVert *bmesh_kernel_join_vert_kill_edge(
*/
BMFace *bmesh_kernel_join_face_kill_edge(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
{
- BMLoop *l_iter, *l_f1 = NULL, *l_f2 = NULL;
- int newlen = 0, i, f1len = 0, f2len = 0;
- bool edok;
- /* can't join a face to itself */
- if (f1 == f2) {
- return NULL;
- }
-
- /* validate that edge is 2-manifold edge */
- if (!BM_edge_is_manifold(e)) {
- return NULL;
- }
-
- /* verify that e is in both f1 and f2 */
- f1len = f1->len;
- f2len = f2->len;
-
- if (!((l_f1 = BM_face_edge_share_loop(f1, e)) &&
- (l_f2 = BM_face_edge_share_loop(f2, e))))
- {
- return NULL;
- }
-
- /* validate direction of f2's loop cycle is compatible */
- if (l_f1->v == l_f2->v) {
- return NULL;
- }
-
- /* validate that for each face, each vertex has another edge in its disk cycle that is
- * not e, and not shared. */
- if (BM_edge_in_face(l_f1->next->e, f2) ||
- BM_edge_in_face(l_f1->prev->e, f2) ||
- BM_edge_in_face(l_f2->next->e, f1) ||
- BM_edge_in_face(l_f2->prev->e, f1) )
- {
- return NULL;
- }
-
- /* validate only one shared edge */
- if (BM_face_share_edge_count(f1, f2) > 1) {
- return NULL;
- }
-
- /* validate no internal join */
- {
- bool is_dupe = false;
-
- /* TODO: skip clearing once this is ensured. */
- for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f2); i < f2len; i++, l_iter = l_iter->next) {
- BM_elem_flag_disable(l_iter->v, BM_ELEM_INTERNAL_TAG);
- }
-
- for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f1); i < f1len; i++, l_iter = l_iter->next) {
- BM_elem_flag_set(l_iter->v, BM_ELEM_INTERNAL_TAG, l_iter != l_f1);
- }
- for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f2); i < f2len; i++, l_iter = l_iter->next) {
- if (l_iter != l_f2) {
- /* as soon as a duplicate is found, bail out */
- if (BM_elem_flag_test(l_iter->v, BM_ELEM_INTERNAL_TAG)) {
- is_dupe = true;
- break;
- }
- }
- }
- /* Cleanup tags. */
- for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f1); i < f1len; i++, l_iter = l_iter->next) {
- BM_elem_flag_disable(l_iter->v, BM_ELEM_INTERNAL_TAG);
- }
- if (is_dupe) {
- return NULL;
- }
- }
-
- /* join the two loop */
- l_f1->prev->next = l_f2->next;
- l_f2->next->prev = l_f1->prev;
-
- l_f1->next->prev = l_f2->prev;
- l_f2->prev->next = l_f1->next;
-
- /* if l_f1 was baseloop, make l_f1->next the base. */
- if (BM_FACE_FIRST_LOOP(f1) == l_f1) {
- BM_FACE_FIRST_LOOP(f1) = l_f1->next;
- }
-
- /* increase length of f1 */
- f1->len += (f2->len - 2);
-
- /* make sure each loop points to the proper face */
- newlen = f1->len;
- for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f1); i < newlen; i++, l_iter = l_iter->next) {
- l_iter->f = f1;
- }
-
- /* remove edge from the disk cycle of its two vertices */
- bmesh_disk_edge_remove(l_f1->e, l_f1->e->v1);
- bmesh_disk_edge_remove(l_f1->e, l_f1->e->v2);
-
- /* deallocate edge and its two loops as well as f2 */
- if (bm->etoolflagpool) {
- BLI_mempool_free(bm->etoolflagpool, ((BMEdge_OFlag *)l_f1->e)->oflags);
- }
- BLI_mempool_free(bm->epool, l_f1->e);
- bm->totedge--;
- BLI_mempool_free(bm->lpool, l_f1);
- bm->totloop--;
- BLI_mempool_free(bm->lpool, l_f2);
- bm->totloop--;
- if (bm->ftoolflagpool) {
- BLI_mempool_free(bm->ftoolflagpool, ((BMFace_OFlag *)f2)->oflags);
- }
- BLI_mempool_free(bm->fpool, f2);
- bm->totface--;
- /* account for both above */
- bm->elem_index_dirty |= BM_EDGE | BM_LOOP | BM_FACE;
-
- BM_CHECK_ELEMENT(f1);
-
- /* validate the new loop cycle */
- edok = bmesh_loop_validate(f1);
- BMESH_ASSERT(edok != false);
-
- return f1;
+ BMLoop *l_iter, *l_f1 = NULL, *l_f2 = NULL;
+ int newlen = 0, i, f1len = 0, f2len = 0;
+ bool edok;
+ /* can't join a face to itself */
+ if (f1 == f2) {
+ return NULL;
+ }
+
+ /* validate that edge is 2-manifold edge */
+ if (!BM_edge_is_manifold(e)) {
+ return NULL;
+ }
+
+ /* verify that e is in both f1 and f2 */
+ f1len = f1->len;
+ f2len = f2->len;
+
+ if (!((l_f1 = BM_face_edge_share_loop(f1, e)) && (l_f2 = BM_face_edge_share_loop(f2, e)))) {
+ return NULL;
+ }
+
+ /* validate direction of f2's loop cycle is compatible */
+ if (l_f1->v == l_f2->v) {
+ return NULL;
+ }
+
+ /* validate that for each face, each vertex has another edge in its disk cycle that is
+ * not e, and not shared. */
+ if (BM_edge_in_face(l_f1->next->e, f2) || BM_edge_in_face(l_f1->prev->e, f2) ||
+ BM_edge_in_face(l_f2->next->e, f1) || BM_edge_in_face(l_f2->prev->e, f1)) {
+ return NULL;
+ }
+
+ /* validate only one shared edge */
+ if (BM_face_share_edge_count(f1, f2) > 1) {
+ return NULL;
+ }
+
+ /* validate no internal join */
+ {
+ bool is_dupe = false;
+
+ /* TODO: skip clearing once this is ensured. */
+ for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f2); i < f2len; i++, l_iter = l_iter->next) {
+ BM_elem_flag_disable(l_iter->v, BM_ELEM_INTERNAL_TAG);
+ }
+
+ for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f1); i < f1len; i++, l_iter = l_iter->next) {
+ BM_elem_flag_set(l_iter->v, BM_ELEM_INTERNAL_TAG, l_iter != l_f1);
+ }
+ for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f2); i < f2len; i++, l_iter = l_iter->next) {
+ if (l_iter != l_f2) {
+ /* as soon as a duplicate is found, bail out */
+ if (BM_elem_flag_test(l_iter->v, BM_ELEM_INTERNAL_TAG)) {
+ is_dupe = true;
+ break;
+ }
+ }
+ }
+ /* Cleanup tags. */
+ for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f1); i < f1len; i++, l_iter = l_iter->next) {
+ BM_elem_flag_disable(l_iter->v, BM_ELEM_INTERNAL_TAG);
+ }
+ if (is_dupe) {
+ return NULL;
+ }
+ }
+
+ /* join the two loop */
+ l_f1->prev->next = l_f2->next;
+ l_f2->next->prev = l_f1->prev;
+
+ l_f1->next->prev = l_f2->prev;
+ l_f2->prev->next = l_f1->next;
+
+ /* if l_f1 was baseloop, make l_f1->next the base. */
+ if (BM_FACE_FIRST_LOOP(f1) == l_f1) {
+ BM_FACE_FIRST_LOOP(f1) = l_f1->next;
+ }
+
+ /* increase length of f1 */
+ f1->len += (f2->len - 2);
+
+ /* make sure each loop points to the proper face */
+ newlen = f1->len;
+ for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f1); i < newlen; i++, l_iter = l_iter->next) {
+ l_iter->f = f1;
+ }
+
+ /* remove edge from the disk cycle of its two vertices */
+ bmesh_disk_edge_remove(l_f1->e, l_f1->e->v1);
+ bmesh_disk_edge_remove(l_f1->e, l_f1->e->v2);
+
+ /* deallocate edge and its two loops as well as f2 */
+ if (bm->etoolflagpool) {
+ BLI_mempool_free(bm->etoolflagpool, ((BMEdge_OFlag *)l_f1->e)->oflags);
+ }
+ BLI_mempool_free(bm->epool, l_f1->e);
+ bm->totedge--;
+ BLI_mempool_free(bm->lpool, l_f1);
+ bm->totloop--;
+ BLI_mempool_free(bm->lpool, l_f2);
+ bm->totloop--;
+ if (bm->ftoolflagpool) {
+ BLI_mempool_free(bm->ftoolflagpool, ((BMFace_OFlag *)f2)->oflags);
+ }
+ BLI_mempool_free(bm->fpool, f2);
+ bm->totface--;
+ /* account for both above */
+ bm->elem_index_dirty |= BM_EDGE | BM_LOOP | BM_FACE;
+
+ BM_CHECK_ELEMENT(f1);
+
+ /* validate the new loop cycle */
+ edok = bmesh_loop_validate(f1);
+ BMESH_ASSERT(edok != false);
+
+ return f1;
}
/**
@@ -2198,46 +2199,45 @@ BMFace *bmesh_kernel_join_face_kill_edge(BMesh *bm, BMFace *f1, BMFace *f2, BMEd
*/
bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b)
{
- bool is_double = false;
+ bool is_double = false;
- BLI_assert(BM_edge_exists(v_a, v_b) == false);
+ BLI_assert(BM_edge_exists(v_a, v_b) == false);
- if (v_a->e && v_b->e) {
- BMEdge *e, *e_first;
+ if (v_a->e && v_b->e) {
+ BMEdge *e, *e_first;
#define VERT_VISIT _FLAG_WALK
- /* tag 'v_a' */
- e = e_first = v_a->e;
- do {
- BMVert *v_other = BM_edge_other_vert(e, v_a);
- BLI_assert(!BM_ELEM_API_FLAG_TEST(v_other, VERT_VISIT));
- BM_ELEM_API_FLAG_ENABLE(v_other, VERT_VISIT);
- } while ((e = BM_DISK_EDGE_NEXT(e, v_a)) != e_first);
-
- /* check 'v_b' connects to 'v_a' edges */
- e = e_first = v_b->e;
- do {
- BMVert *v_other = BM_edge_other_vert(e, v_b);
- if (BM_ELEM_API_FLAG_TEST(v_other, VERT_VISIT)) {
- is_double = true;
- break;
- }
- } while ((e = BM_DISK_EDGE_NEXT(e, v_b)) != e_first);
-
- /* cleanup */
- e = e_first = v_a->e;
- do {
- BMVert *v_other = BM_edge_other_vert(e, v_a);
- BLI_assert(BM_ELEM_API_FLAG_TEST(v_other, VERT_VISIT));
- BM_ELEM_API_FLAG_DISABLE(v_other, VERT_VISIT);
- } while ((e = BM_DISK_EDGE_NEXT(e, v_a)) != e_first);
+ /* tag 'v_a' */
+ e = e_first = v_a->e;
+ do {
+ BMVert *v_other = BM_edge_other_vert(e, v_a);
+ BLI_assert(!BM_ELEM_API_FLAG_TEST(v_other, VERT_VISIT));
+ BM_ELEM_API_FLAG_ENABLE(v_other, VERT_VISIT);
+ } while ((e = BM_DISK_EDGE_NEXT(e, v_a)) != e_first);
+
+ /* check 'v_b' connects to 'v_a' edges */
+ e = e_first = v_b->e;
+ do {
+ BMVert *v_other = BM_edge_other_vert(e, v_b);
+ if (BM_ELEM_API_FLAG_TEST(v_other, VERT_VISIT)) {
+ is_double = true;
+ break;
+ }
+ } while ((e = BM_DISK_EDGE_NEXT(e, v_b)) != e_first);
+
+ /* cleanup */
+ e = e_first = v_a->e;
+ do {
+ BMVert *v_other = BM_edge_other_vert(e, v_a);
+ BLI_assert(BM_ELEM_API_FLAG_TEST(v_other, VERT_VISIT));
+ BM_ELEM_API_FLAG_DISABLE(v_other, VERT_VISIT);
+ } while ((e = BM_DISK_EDGE_NEXT(e, v_a)) != e_first);
#undef VERT_VISIT
+ }
- }
-
- return is_double;
+ return is_double;
}
/**
@@ -2254,38 +2254,37 @@ bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b)
*/
bool BM_vert_splice(BMesh *bm, BMVert *v_dst, BMVert *v_src)
{
- BMEdge *e;
+ BMEdge *e;
- /* verts already spliced */
- if (v_src == v_dst) {
- return false;
- }
+ /* verts already spliced */
+ if (v_src == v_dst) {
+ return false;
+ }
- BLI_assert(BM_vert_pair_share_face_check(v_src, v_dst) == false);
+ BLI_assert(BM_vert_pair_share_face_check(v_src, v_dst) == false);
- /* move all the edges from 'v_src' disk to 'v_dst' */
- while ((e = v_src->e)) {
- bmesh_edge_vert_swap(e, v_dst, v_src);
- BLI_assert(e->v1 != e->v2);
- }
+ /* move all the edges from 'v_src' disk to 'v_dst' */
+ while ((e = v_src->e)) {
+ bmesh_edge_vert_swap(e, v_dst, v_src);
+ BLI_assert(e->v1 != e->v2);
+ }
- BM_CHECK_ELEMENT(v_src);
- BM_CHECK_ELEMENT(v_dst);
+ BM_CHECK_ELEMENT(v_src);
+ BM_CHECK_ELEMENT(v_dst);
- /* 'v_src' is unused now, and can be killed */
- BM_vert_kill(bm, v_src);
+ /* 'v_src' is unused now, and can be killed */
+ BM_vert_kill(bm, v_src);
- return true;
+ return true;
}
-
/** \name BM_vert_separate, bmesh_kernel_vert_separate and friends
* \{ */
/* BM_edge_face_count(e) >= 1 */
BLI_INLINE bool bm_edge_supports_separate(const BMEdge *e)
{
- return (e->l && e->l->radial_next != e->l);
+ return (e->l && e->l->radial_next != e->l);
}
/**
@@ -2300,114 +2299,113 @@ BLI_INLINE bool bm_edge_supports_separate(const BMEdge *e)
* \return Success
*/
void bmesh_kernel_vert_separate(
- BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len,
- const bool copy_select)
+ BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, const bool copy_select)
{
- int v_edges_num = 0;
+ int v_edges_num = 0;
- /* Detailed notes on array use since this is stack memory, we have to be careful */
+ /* Detailed notes on array use since this is stack memory, we have to be careful */
- /* newly created vertices, only use when 'r_vout' is set
- * (total size will be number of fans) */
- BLI_SMALLSTACK_DECLARE(verts_new, BMVert *);
- /* fill with edges from the face-fan, clearing on completion
- * (total size will be max fan edge count) */
- BLI_SMALLSTACK_DECLARE(edges, BMEdge *);
- /* temp store edges to walk over when filling 'edges',
- * (total size will be max radial edges of any edge) */
- BLI_SMALLSTACK_DECLARE(edges_search, BMEdge *);
+ /* newly created vertices, only use when 'r_vout' is set
+ * (total size will be number of fans) */
+ BLI_SMALLSTACK_DECLARE(verts_new, BMVert *);
+ /* fill with edges from the face-fan, clearing on completion
+ * (total size will be max fan edge count) */
+ BLI_SMALLSTACK_DECLARE(edges, BMEdge *);
+ /* temp store edges to walk over when filling 'edges',
+ * (total size will be max radial edges of any edge) */
+ BLI_SMALLSTACK_DECLARE(edges_search, BMEdge *);
- /* number of resulting verts, include self */
- int verts_num = 1;
- /* track the total number of edges handled, so we know when we've found the last fan */
- int edges_found = 0;
+ /* number of resulting verts, include self */
+ int verts_num = 1;
+ /* track the total number of edges handled, so we know when we've found the last fan */
+ int edges_found = 0;
#define EDGE_VISIT _FLAG_WALK
- /* count and flag at once */
- if (v->e) {
- BMEdge *e_first, *e_iter;
- e_iter = e_first = v->e;
- do {
- v_edges_num += 1;
-
- BLI_assert(!BM_ELEM_API_FLAG_TEST(e_iter, EDGE_VISIT));
- BM_ELEM_API_FLAG_ENABLE(e_iter, EDGE_VISIT);
- } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
- }
-
- while (true) {
- /* Considering only edges and faces incident on vertex v, walk
- * the edges & collect in the 'edges' list for splitting */
-
- BMEdge *e = v->e;
- BM_ELEM_API_FLAG_DISABLE(e, EDGE_VISIT);
-
- do {
- BLI_assert(!BM_ELEM_API_FLAG_TEST(e, EDGE_VISIT));
- BLI_SMALLSTACK_PUSH(edges, e);
- edges_found += 1;
-
- if (e->l) {
- BMLoop *l_iter, *l_first;
- l_iter = l_first = e->l;
- do {
- BMLoop *l_adjacent = (l_iter->v == v) ? l_iter->prev : l_iter->next;
- BLI_assert(BM_vert_in_edge(l_adjacent->e, v));
- if (BM_ELEM_API_FLAG_TEST(l_adjacent->e, EDGE_VISIT)) {
- BM_ELEM_API_FLAG_DISABLE(l_adjacent->e, EDGE_VISIT);
- BLI_SMALLSTACK_PUSH(edges_search, l_adjacent->e);
- }
- } while ((l_iter = l_iter->radial_next) != l_first);
- }
- } while ((e = BLI_SMALLSTACK_POP(edges_search)));
-
- /* now we have all edges connected to 'v->e' */
-
- BLI_assert(edges_found <= v_edges_num);
-
- if (edges_found == v_edges_num) {
- /* We're done! The remaining edges in 'edges' form the last fan,
- * which can be left as is.
- * if 'edges' were alloc'd it'd be freed here. */
- break;
- }
- else {
- BMVert *v_new;
-
- v_new = BM_vert_create(bm, v->co, v, BM_CREATE_NOP);
- if (copy_select) {
- BM_elem_select_copy(bm, v_new, v);
- }
-
- while ((e = BLI_SMALLSTACK_POP(edges))) {
- bmesh_edge_vert_swap(e, v_new, v);
- }
-
- if (r_vout) {
- BLI_SMALLSTACK_PUSH(verts_new, v_new);
- }
- verts_num += 1;
- }
- }
+ /* count and flag at once */
+ if (v->e) {
+ BMEdge *e_first, *e_iter;
+ e_iter = e_first = v->e;
+ do {
+ v_edges_num += 1;
+
+ BLI_assert(!BM_ELEM_API_FLAG_TEST(e_iter, EDGE_VISIT));
+ BM_ELEM_API_FLAG_ENABLE(e_iter, EDGE_VISIT);
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
+ }
+
+ while (true) {
+ /* Considering only edges and faces incident on vertex v, walk
+ * the edges & collect in the 'edges' list for splitting */
+
+ BMEdge *e = v->e;
+ BM_ELEM_API_FLAG_DISABLE(e, EDGE_VISIT);
+
+ do {
+ BLI_assert(!BM_ELEM_API_FLAG_TEST(e, EDGE_VISIT));
+ BLI_SMALLSTACK_PUSH(edges, e);
+ edges_found += 1;
+
+ if (e->l) {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = e->l;
+ do {
+ BMLoop *l_adjacent = (l_iter->v == v) ? l_iter->prev : l_iter->next;
+ BLI_assert(BM_vert_in_edge(l_adjacent->e, v));
+ if (BM_ELEM_API_FLAG_TEST(l_adjacent->e, EDGE_VISIT)) {
+ BM_ELEM_API_FLAG_DISABLE(l_adjacent->e, EDGE_VISIT);
+ BLI_SMALLSTACK_PUSH(edges_search, l_adjacent->e);
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+ } while ((e = BLI_SMALLSTACK_POP(edges_search)));
+
+ /* now we have all edges connected to 'v->e' */
+
+ BLI_assert(edges_found <= v_edges_num);
+
+ if (edges_found == v_edges_num) {
+ /* We're done! The remaining edges in 'edges' form the last fan,
+ * which can be left as is.
+ * if 'edges' were alloc'd it'd be freed here. */
+ break;
+ }
+ else {
+ BMVert *v_new;
+
+ v_new = BM_vert_create(bm, v->co, v, BM_CREATE_NOP);
+ if (copy_select) {
+ BM_elem_select_copy(bm, v_new, v);
+ }
+
+ while ((e = BLI_SMALLSTACK_POP(edges))) {
+ bmesh_edge_vert_swap(e, v_new, v);
+ }
+
+ if (r_vout) {
+ BLI_SMALLSTACK_PUSH(verts_new, v_new);
+ }
+ verts_num += 1;
+ }
+ }
#undef EDGE_VISIT
- /* flags are clean now, handle return values */
+ /* flags are clean now, handle return values */
- if (r_vout_len != NULL) {
- *r_vout_len = verts_num;
- }
+ if (r_vout_len != NULL) {
+ *r_vout_len = verts_num;
+ }
- if (r_vout != NULL) {
- BMVert **verts;
+ if (r_vout != NULL) {
+ BMVert **verts;
- verts = MEM_mallocN(sizeof(BMVert *) * verts_num, __func__);
- *r_vout = verts;
+ verts = MEM_mallocN(sizeof(BMVert *) * verts_num, __func__);
+ *r_vout = verts;
- verts[0] = v;
- BLI_SMALLSTACK_AS_TABLE(verts_new, &verts[1]);
- }
+ verts[0] = v;
+ BLI_SMALLSTACK_AS_TABLE(verts_new, &verts[1]);
+ }
}
/**
@@ -2430,131 +2428,132 @@ void bmesh_kernel_vert_separate(
*/
static void bmesh_kernel_vert_separate__cleanup(BMesh *bm, LinkNode *edges_separate)
{
- do {
- LinkNode *n_orig = edges_separate->link;
- do {
- LinkNode *n_prev = n_orig;
- LinkNode *n_step = n_orig->next;
- BMEdge *e_orig = n_orig->link;
- do {
- BMEdge *e = n_step->link;
- BLI_assert(e != e_orig);
- if ((e->v1 == e_orig->v1) && (e->v2 == e_orig->v2) &&
- BM_edge_splice(bm, e_orig, e))
- {
- /* don't visit again */
- n_prev->next = n_step->next;
- }
- else {
- n_prev = n_step;
- }
- } while ((n_step = n_step->next));
-
- } while ((n_orig = n_orig->next) && n_orig->next);
- } while ((edges_separate = edges_separate->next));
+ do {
+ LinkNode *n_orig = edges_separate->link;
+ do {
+ LinkNode *n_prev = n_orig;
+ LinkNode *n_step = n_orig->next;
+ BMEdge *e_orig = n_orig->link;
+ do {
+ BMEdge *e = n_step->link;
+ BLI_assert(e != e_orig);
+ if ((e->v1 == e_orig->v1) && (e->v2 == e_orig->v2) && BM_edge_splice(bm, e_orig, e)) {
+ /* don't visit again */
+ n_prev->next = n_step->next;
+ }
+ else {
+ n_prev = n_step;
+ }
+ } while ((n_step = n_step->next));
+
+ } while ((n_orig = n_orig->next) && n_orig->next);
+ } while ((edges_separate = edges_separate->next));
}
/**
* High level function which wraps both #bmesh_kernel_vert_separate and #bmesh_kernel_edge_separate
*/
-void BM_vert_separate(
- BMesh *bm, BMVert *v,
- BMEdge **e_in, int e_in_len,
- const bool copy_select,
- BMVert ***r_vout, int *r_vout_len)
+void BM_vert_separate(BMesh *bm,
+ BMVert *v,
+ BMEdge **e_in,
+ int e_in_len,
+ const bool copy_select,
+ BMVert ***r_vout,
+ int *r_vout_len)
{
- LinkNode *edges_separate = NULL;
- int i;
-
- for (i = 0; i < e_in_len; i++) {
- BMEdge *e = e_in[i];
- if (bm_edge_supports_separate(e)) {
- LinkNode *edges_orig = NULL;
- do {
- BMLoop *l_sep = e->l;
- bmesh_kernel_edge_separate(bm, e, l_sep, copy_select);
- BLI_linklist_prepend_alloca(&edges_orig, l_sep->e);
- BLI_assert(e != l_sep->e);
- } while (bm_edge_supports_separate(e));
- BLI_linklist_prepend_alloca(&edges_orig, e);
- BLI_linklist_prepend_alloca(&edges_separate, edges_orig);
- }
- }
-
- bmesh_kernel_vert_separate(bm, v, r_vout, r_vout_len, copy_select);
-
- if (edges_separate) {
- bmesh_kernel_vert_separate__cleanup(bm, edges_separate);
- }
+ LinkNode *edges_separate = NULL;
+ int i;
+
+ for (i = 0; i < e_in_len; i++) {
+ BMEdge *e = e_in[i];
+ if (bm_edge_supports_separate(e)) {
+ LinkNode *edges_orig = NULL;
+ do {
+ BMLoop *l_sep = e->l;
+ bmesh_kernel_edge_separate(bm, e, l_sep, copy_select);
+ BLI_linklist_prepend_alloca(&edges_orig, l_sep->e);
+ BLI_assert(e != l_sep->e);
+ } while (bm_edge_supports_separate(e));
+ BLI_linklist_prepend_alloca(&edges_orig, e);
+ BLI_linklist_prepend_alloca(&edges_separate, edges_orig);
+ }
+ }
+
+ bmesh_kernel_vert_separate(bm, v, r_vout, r_vout_len, copy_select);
+
+ if (edges_separate) {
+ bmesh_kernel_vert_separate__cleanup(bm, edges_separate);
+ }
}
-
/**
* A version of #BM_vert_separate which takes a flag.
*/
-void BM_vert_separate_hflag(
- BMesh *bm, BMVert *v,
- const char hflag,
- const bool copy_select,
- BMVert ***r_vout, int *r_vout_len)
+void BM_vert_separate_hflag(BMesh *bm,
+ BMVert *v,
+ const char hflag,
+ const bool copy_select,
+ BMVert ***r_vout,
+ int *r_vout_len)
{
- LinkNode *edges_separate = NULL;
- BMEdge *e_iter, *e_first;
-
- e_iter = e_first = v->e;
- do {
- if (BM_elem_flag_test(e_iter, hflag)) {
- BMEdge *e = e_iter;
- if (bm_edge_supports_separate(e)) {
- LinkNode *edges_orig = NULL;
- do {
- BMLoop *l_sep = e->l;
- bmesh_kernel_edge_separate(bm, e, l_sep, copy_select);
- /* trick to avoid looping over separated edges */
- if (edges_separate == NULL && edges_orig == NULL) {
- e_first = l_sep->e;
- }
- BLI_linklist_prepend_alloca(&edges_orig, l_sep->e);
- BLI_assert(e != l_sep->e);
- } while (bm_edge_supports_separate(e));
- BLI_linklist_prepend_alloca(&edges_orig, e);
- BLI_linklist_prepend_alloca(&edges_separate, edges_orig);
- }
- }
- } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v)) != e_first);
-
- bmesh_kernel_vert_separate(bm, v, r_vout, r_vout_len, copy_select);
-
- if (edges_separate) {
- bmesh_kernel_vert_separate__cleanup(bm, edges_separate);
- }
+ LinkNode *edges_separate = NULL;
+ BMEdge *e_iter, *e_first;
+
+ e_iter = e_first = v->e;
+ do {
+ if (BM_elem_flag_test(e_iter, hflag)) {
+ BMEdge *e = e_iter;
+ if (bm_edge_supports_separate(e)) {
+ LinkNode *edges_orig = NULL;
+ do {
+ BMLoop *l_sep = e->l;
+ bmesh_kernel_edge_separate(bm, e, l_sep, copy_select);
+ /* trick to avoid looping over separated edges */
+ if (edges_separate == NULL && edges_orig == NULL) {
+ e_first = l_sep->e;
+ }
+ BLI_linklist_prepend_alloca(&edges_orig, l_sep->e);
+ BLI_assert(e != l_sep->e);
+ } while (bm_edge_supports_separate(e));
+ BLI_linklist_prepend_alloca(&edges_orig, e);
+ BLI_linklist_prepend_alloca(&edges_separate, edges_orig);
+ }
+ }
+ } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v)) != e_first);
+
+ bmesh_kernel_vert_separate(bm, v, r_vout, r_vout_len, copy_select);
+
+ if (edges_separate) {
+ bmesh_kernel_vert_separate__cleanup(bm, edges_separate);
+ }
}
-void BM_vert_separate_tested_edges(
- BMesh *UNUSED(bm), BMVert *v_dst, BMVert *v_src,
- bool (*testfn)(BMEdge *, void *arg), void *arg)
+void BM_vert_separate_tested_edges(BMesh *UNUSED(bm),
+ BMVert *v_dst,
+ BMVert *v_src,
+ bool (*testfn)(BMEdge *, void *arg),
+ void *arg)
{
- LinkNode *edges_hflag = NULL;
- BMEdge *e_iter, *e_first;
-
- e_iter = e_first = v_src->e;
- do {
- if (testfn(e_iter, arg)) {
- BLI_linklist_prepend_alloca(&edges_hflag, e_iter);
- }
- } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v_src)) != e_first);
-
- if (edges_hflag) {
- do {
- e_iter = edges_hflag->link;
- bmesh_disk_vert_replace(e_iter, v_dst, v_src);
- } while ((edges_hflag = edges_hflag->next));
- }
+ LinkNode *edges_hflag = NULL;
+ BMEdge *e_iter, *e_first;
+
+ e_iter = e_first = v_src->e;
+ do {
+ if (testfn(e_iter, arg)) {
+ BLI_linklist_prepend_alloca(&edges_hflag, e_iter);
+ }
+ } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v_src)) != e_first);
+
+ if (edges_hflag) {
+ do {
+ e_iter = edges_hflag->link;
+ bmesh_disk_vert_replace(e_iter, v_dst, v_src);
+ } while ((edges_hflag = edges_hflag->next));
+ }
}
/** \} */
-
/**
* \brief Splice Edge
*
@@ -2567,35 +2566,35 @@ void BM_vert_separate_tested_edges(
*/
bool BM_edge_splice(BMesh *bm, BMEdge *e_dst, BMEdge *e_src)
{
- BMLoop *l;
+ BMLoop *l;
- if (!BM_vert_in_edge(e_src, e_dst->v1) || !BM_vert_in_edge(e_src, e_dst->v2)) {
- /* not the same vertices can't splice */
+ if (!BM_vert_in_edge(e_src, e_dst->v1) || !BM_vert_in_edge(e_src, e_dst->v2)) {
+ /* not the same vertices can't splice */
- /* the caller should really make sure this doesn't happen ever
- * so assert on release builds */
- BLI_assert(0);
+ /* the caller should really make sure this doesn't happen ever
+ * so assert on release builds */
+ BLI_assert(0);
- return false;
- }
+ return false;
+ }
- while (e_src->l) {
- l = e_src->l;
- BLI_assert(BM_vert_in_edge(e_dst, l->v));
- BLI_assert(BM_vert_in_edge(e_dst, l->next->v));
- bmesh_radial_loop_remove(e_src, l);
- bmesh_radial_loop_append(e_dst, l);
- }
+ while (e_src->l) {
+ l = e_src->l;
+ BLI_assert(BM_vert_in_edge(e_dst, l->v));
+ BLI_assert(BM_vert_in_edge(e_dst, l->next->v));
+ bmesh_radial_loop_remove(e_src, l);
+ bmesh_radial_loop_append(e_dst, l);
+ }
- BLI_assert(bmesh_radial_length(e_src->l) == 0);
+ BLI_assert(bmesh_radial_length(e_src->l) == 0);
- BM_CHECK_ELEMENT(e_src);
- BM_CHECK_ELEMENT(e_dst);
+ BM_CHECK_ELEMENT(e_src);
+ BM_CHECK_ELEMENT(e_dst);
- /* removes from disks too */
- BM_edge_kill(bm, e_src);
+ /* removes from disks too */
+ BM_edge_kill(bm, e_src);
- return true;
+ return true;
}
/**
@@ -2609,41 +2608,39 @@ bool BM_edge_splice(BMesh *bm, BMEdge *e_dst, BMEdge *e_src)
* \note Does nothing if \a l_sep is already the only loop in the
* edge radial.
*/
-void bmesh_kernel_edge_separate(
- BMesh *bm, BMEdge *e, BMLoop *l_sep,
- const bool copy_select)
+void bmesh_kernel_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep, const bool copy_select)
{
- BMEdge *e_new;
+ BMEdge *e_new;
#ifndef NDEBUG
- const int radlen = bmesh_radial_length(e->l);
+ const int radlen = bmesh_radial_length(e->l);
#endif
- BLI_assert(l_sep->e == e);
- BLI_assert(e->l);
+ BLI_assert(l_sep->e == e);
+ BLI_assert(e->l);
- if (BM_edge_is_boundary(e)) {
- BLI_assert(0); /* no cut required */
- return;
- }
+ if (BM_edge_is_boundary(e)) {
+ BLI_assert(0); /* no cut required */
+ return;
+ }
- if (l_sep == e->l) {
- e->l = l_sep->radial_next;
- }
+ if (l_sep == e->l) {
+ e->l = l_sep->radial_next;
+ }
- e_new = BM_edge_create(bm, e->v1, e->v2, e, BM_CREATE_NOP);
- bmesh_radial_loop_remove(e, l_sep);
- bmesh_radial_loop_append(e_new, l_sep);
- l_sep->e = e_new;
+ e_new = BM_edge_create(bm, e->v1, e->v2, e, BM_CREATE_NOP);
+ bmesh_radial_loop_remove(e, l_sep);
+ bmesh_radial_loop_append(e_new, l_sep);
+ l_sep->e = e_new;
- if (copy_select) {
- BM_elem_select_copy(bm, e_new, e);
- }
+ if (copy_select) {
+ BM_elem_select_copy(bm, e_new, e);
+ }
- BLI_assert(bmesh_radial_length(e->l) == radlen - 1);
- BLI_assert(bmesh_radial_length(e_new->l) == 1);
+ BLI_assert(bmesh_radial_length(e->l) == radlen - 1);
+ BLI_assert(bmesh_radial_length(e_new->l) == 1);
- BM_CHECK_ELEMENT(e_new);
- BM_CHECK_ELEMENT(e);
+ BM_CHECK_ELEMENT(e_new);
+ BM_CHECK_ELEMENT(e);
}
/**
@@ -2657,64 +2654,64 @@ void bmesh_kernel_edge_separate(
*/
BMVert *bmesh_kernel_unglue_region_make_vert(BMesh *bm, BMLoop *l_sep)
{
- BMVert *v_new = NULL;
- BMVert *v_sep = l_sep->v;
- BMEdge *e_iter;
- BMEdge *edges[2];
- int i;
-
- /* peel the face from the edge radials on both sides of the
- * loop vert, disconnecting the face from its fan */
- if (!BM_edge_is_boundary(l_sep->e)) {
- bmesh_kernel_edge_separate(bm, l_sep->e, l_sep, false);
- }
- if (!BM_edge_is_boundary(l_sep->prev->e)) {
- bmesh_kernel_edge_separate(bm, l_sep->prev->e, l_sep->prev, false);
- }
-
- /* do inline, below */
+ BMVert *v_new = NULL;
+ BMVert *v_sep = l_sep->v;
+ BMEdge *e_iter;
+ BMEdge *edges[2];
+ int i;
+
+ /* peel the face from the edge radials on both sides of the
+ * loop vert, disconnecting the face from its fan */
+ if (!BM_edge_is_boundary(l_sep->e)) {
+ bmesh_kernel_edge_separate(bm, l_sep->e, l_sep, false);
+ }
+ if (!BM_edge_is_boundary(l_sep->prev->e)) {
+ bmesh_kernel_edge_separate(bm, l_sep->prev->e, l_sep->prev, false);
+ }
+
+ /* do inline, below */
#if 0
- if (BM_vert_edge_count_is_equal(v_sep, 2)) {
- return v_sep;
- }
+ if (BM_vert_edge_count_is_equal(v_sep, 2)) {
+ return v_sep;
+ }
#endif
- /* Search for an edge unattached to this loop */
- e_iter = v_sep->e;
- while (!ELEM(e_iter, l_sep->e, l_sep->prev->e)) {
- e_iter = bmesh_disk_edge_next(e_iter, v_sep);
+ /* Search for an edge unattached to this loop */
+ e_iter = v_sep->e;
+ while (!ELEM(e_iter, l_sep->e, l_sep->prev->e)) {
+ e_iter = bmesh_disk_edge_next(e_iter, v_sep);
- /* We've come back around to the initial edge, all touch this loop.
- * If there are still only two edges out of v_sep,
- * then this whole URMV was just a no-op, so exit now. */
- if (e_iter == v_sep->e) {
- BLI_assert(BM_vert_edge_count_is_equal(v_sep, 2));
- return v_sep;
- }
- }
+ /* We've come back around to the initial edge, all touch this loop.
+ * If there are still only two edges out of v_sep,
+ * then this whole URMV was just a no-op, so exit now. */
+ if (e_iter == v_sep->e) {
+ BLI_assert(BM_vert_edge_count_is_equal(v_sep, 2));
+ return v_sep;
+ }
+ }
- v_sep->e = l_sep->e;
+ v_sep->e = l_sep->e;
- v_new = BM_vert_create(bm, v_sep->co, v_sep, BM_CREATE_NOP);
+ v_new = BM_vert_create(bm, v_sep->co, v_sep, BM_CREATE_NOP);
- edges[0] = l_sep->e;
- edges[1] = l_sep->prev->e;
+ edges[0] = l_sep->e;
+ edges[1] = l_sep->prev->e;
- for (i = 0; i < ARRAY_SIZE(edges); i++) {
- BMEdge *e = edges[i];
- bmesh_edge_vert_swap(e, v_new, v_sep);
- }
+ for (i = 0; i < ARRAY_SIZE(edges); i++) {
+ BMEdge *e = edges[i];
+ bmesh_edge_vert_swap(e, v_new, v_sep);
+ }
- BLI_assert(v_sep != l_sep->v);
- BLI_assert(v_sep->e != l_sep->v->e);
+ BLI_assert(v_sep != l_sep->v);
+ BLI_assert(v_sep->e != l_sep->v->e);
- BM_CHECK_ELEMENT(l_sep);
- BM_CHECK_ELEMENT(v_sep);
- BM_CHECK_ELEMENT(edges[0]);
- BM_CHECK_ELEMENT(edges[1]);
- BM_CHECK_ELEMENT(v_new);
+ BM_CHECK_ELEMENT(l_sep);
+ BM_CHECK_ELEMENT(v_sep);
+ BM_CHECK_ELEMENT(edges[0]);
+ BM_CHECK_ELEMENT(edges[1]);
+ BM_CHECK_ELEMENT(v_new);
- return v_new;
+ return v_new;
}
/**
@@ -2724,186 +2721,184 @@ BMVert *bmesh_kernel_unglue_region_make_vert(BMesh *bm, BMLoop *l_sep)
*
* This function handles the details of finding fans boundaries.
*/
-BMVert *bmesh_kernel_unglue_region_make_vert_multi(
- BMesh *bm, BMLoop **larr, int larr_len)
+BMVert *bmesh_kernel_unglue_region_make_vert_multi(BMesh *bm, BMLoop **larr, int larr_len)
{
- BMVert *v_sep = larr[0]->v;
- BMVert *v_new;
- int edges_len = 0;
- int i;
- /* any edges not owned by 'larr' loops connected to 'v_sep'? */
- bool is_mixed_edge_any = false;
- /* any loops not owned by 'larr' radially connected to 'larr' loop edges? */
- bool is_mixed_loop_any = false;
+ BMVert *v_sep = larr[0]->v;
+ BMVert *v_new;
+ int edges_len = 0;
+ int i;
+ /* any edges not owned by 'larr' loops connected to 'v_sep'? */
+ bool is_mixed_edge_any = false;
+ /* any loops not owned by 'larr' radially connected to 'larr' loop edges? */
+ bool is_mixed_loop_any = false;
#define LOOP_VISIT _FLAG_WALK
#define EDGE_VISIT _FLAG_WALK
- for (i = 0; i < larr_len; i++) {
- BMLoop *l_sep = larr[i];
-
- /* all must be from the same vert! */
- BLI_assert(v_sep == l_sep->v);
-
- BLI_assert(!BM_ELEM_API_FLAG_TEST(l_sep, LOOP_VISIT));
- BM_ELEM_API_FLAG_ENABLE(l_sep, LOOP_VISIT);
-
- /* weak! but it makes it simpler to check for edges to split
- * while doing a radial loop (where loops may be adjacent) */
- BM_ELEM_API_FLAG_ENABLE(l_sep->next, LOOP_VISIT);
- BM_ELEM_API_FLAG_ENABLE(l_sep->prev, LOOP_VISIT);
-
- BMLoop *loop_pair[2] = {l_sep, l_sep->prev};
- for (int j = 0; j < ARRAY_SIZE(loop_pair); j++) {
- BMEdge *e = loop_pair[j]->e;
- if (!BM_ELEM_API_FLAG_TEST(e, EDGE_VISIT)) {
- BM_ELEM_API_FLAG_ENABLE(e, EDGE_VISIT);
- edges_len += 1;
- }
- }
- }
-
- BMEdge **edges = BLI_array_alloca(edges, edges_len);
- STACK_DECLARE(edges);
-
- STACK_INIT(edges, edges_len);
-
- {
- BMEdge *e_first, *e_iter;
- e_iter = e_first = v_sep->e;
- do {
- if (BM_ELEM_API_FLAG_TEST(e_iter, EDGE_VISIT)) {
- BMLoop *l_iter, *l_first;
- bool is_mixed_loop = false;
-
- l_iter = l_first = e_iter->l;
- do {
- if (!BM_ELEM_API_FLAG_TEST(l_iter, LOOP_VISIT)) {
- is_mixed_loop = true;
- break;
- }
- } while ((l_iter = l_iter->radial_next) != l_first);
-
- if (is_mixed_loop) {
- /* ensure the first loop is one we don't own so we can do a quick check below
- * on the edge's loop-flag to see if the edge is mixed or not. */
- e_iter->l = l_iter;
-
- is_mixed_loop_any = true;
- }
-
- STACK_PUSH(edges, e_iter);
- }
- else {
- /* at least one edge attached isn't connected to our loops */
- is_mixed_edge_any = true;
- }
- } while ((e_iter = bmesh_disk_edge_next(e_iter, v_sep)) != e_first);
- }
-
- BLI_assert(edges_len == STACK_SIZE(edges));
-
- if (is_mixed_loop_any == false && is_mixed_edge_any == false) {
- /* all loops in 'larr' are the sole owners of their edges.
- * nothing to split away from, this is a no-op */
- v_new = v_sep;
- }
- else {
- v_new = BM_vert_create(bm, v_sep->co, v_sep, BM_CREATE_NOP);
-
- for (i = 0; i < STACK_SIZE(edges); i++) {
- BMEdge *e = edges[i];
- BMLoop *l_iter, *l_first, *l_next;
- BMEdge *e_new;
-
- /* disable so copied edge isn't left dirty (loop edges are cleared last too) */
- BM_ELEM_API_FLAG_DISABLE(e, EDGE_VISIT);
-
- /* will always be false when (is_mixed_loop_any == false) */
- if (!BM_ELEM_API_FLAG_TEST(e->l, LOOP_VISIT)) {
- /* edge has some loops owned by us, some owned by other loops */
- BMVert *e_new_v_pair[2];
-
- if (e->v1 == v_sep) {
- e_new_v_pair[0] = v_new;
- e_new_v_pair[1] = e->v2;
- }
- else {
- BLI_assert(v_sep == e->v2);
- e_new_v_pair[0] = e->v1;
- e_new_v_pair[1] = v_new;
- }
-
- e_new = BM_edge_create(bm, UNPACK2(e_new_v_pair), e, BM_CREATE_NOP);
-
- /* now moved all loops from 'larr' to this newly created edge */
- l_iter = l_first = e->l;
- do {
- l_next = l_iter->radial_next;
- if (BM_ELEM_API_FLAG_TEST(l_iter, LOOP_VISIT)) {
- bmesh_radial_loop_remove(e, l_iter);
- bmesh_radial_loop_append(e_new, l_iter);
- l_iter->e = e_new;
- }
- } while ((l_iter = l_next) != l_first);
- }
- else {
- /* we own the edge entirely, replace the vert */
- bmesh_disk_vert_replace(e, v_new, v_sep);
- }
-
- /* loop vert is handled last! */
- }
- }
-
- for (i = 0; i < larr_len; i++) {
- BMLoop *l_sep = larr[i];
-
- l_sep->v = v_new;
-
- BLI_assert(BM_ELEM_API_FLAG_TEST(l_sep, LOOP_VISIT));
- BLI_assert(BM_ELEM_API_FLAG_TEST(l_sep->prev, LOOP_VISIT));
- BLI_assert(BM_ELEM_API_FLAG_TEST(l_sep->next, LOOP_VISIT));
- BM_ELEM_API_FLAG_DISABLE(l_sep, LOOP_VISIT);
- BM_ELEM_API_FLAG_DISABLE(l_sep->prev, LOOP_VISIT);
- BM_ELEM_API_FLAG_DISABLE(l_sep->next, LOOP_VISIT);
-
-
- BM_ELEM_API_FLAG_DISABLE(l_sep->prev->e, EDGE_VISIT);
- BM_ELEM_API_FLAG_DISABLE(l_sep->e, EDGE_VISIT);
- }
+ for (i = 0; i < larr_len; i++) {
+ BMLoop *l_sep = larr[i];
+
+ /* all must be from the same vert! */
+ BLI_assert(v_sep == l_sep->v);
+
+ BLI_assert(!BM_ELEM_API_FLAG_TEST(l_sep, LOOP_VISIT));
+ BM_ELEM_API_FLAG_ENABLE(l_sep, LOOP_VISIT);
+
+ /* weak! but it makes it simpler to check for edges to split
+ * while doing a radial loop (where loops may be adjacent) */
+ BM_ELEM_API_FLAG_ENABLE(l_sep->next, LOOP_VISIT);
+ BM_ELEM_API_FLAG_ENABLE(l_sep->prev, LOOP_VISIT);
+
+ BMLoop *loop_pair[2] = {l_sep, l_sep->prev};
+ for (int j = 0; j < ARRAY_SIZE(loop_pair); j++) {
+ BMEdge *e = loop_pair[j]->e;
+ if (!BM_ELEM_API_FLAG_TEST(e, EDGE_VISIT)) {
+ BM_ELEM_API_FLAG_ENABLE(e, EDGE_VISIT);
+ edges_len += 1;
+ }
+ }
+ }
+
+ BMEdge **edges = BLI_array_alloca(edges, edges_len);
+ STACK_DECLARE(edges);
+
+ STACK_INIT(edges, edges_len);
+
+ {
+ BMEdge *e_first, *e_iter;
+ e_iter = e_first = v_sep->e;
+ do {
+ if (BM_ELEM_API_FLAG_TEST(e_iter, EDGE_VISIT)) {
+ BMLoop *l_iter, *l_first;
+ bool is_mixed_loop = false;
+
+ l_iter = l_first = e_iter->l;
+ do {
+ if (!BM_ELEM_API_FLAG_TEST(l_iter, LOOP_VISIT)) {
+ is_mixed_loop = true;
+ break;
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
+
+ if (is_mixed_loop) {
+ /* ensure the first loop is one we don't own so we can do a quick check below
+ * on the edge's loop-flag to see if the edge is mixed or not. */
+ e_iter->l = l_iter;
+
+ is_mixed_loop_any = true;
+ }
+
+ STACK_PUSH(edges, e_iter);
+ }
+ else {
+ /* at least one edge attached isn't connected to our loops */
+ is_mixed_edge_any = true;
+ }
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v_sep)) != e_first);
+ }
+
+ BLI_assert(edges_len == STACK_SIZE(edges));
+
+ if (is_mixed_loop_any == false && is_mixed_edge_any == false) {
+ /* all loops in 'larr' are the sole owners of their edges.
+ * nothing to split away from, this is a no-op */
+ v_new = v_sep;
+ }
+ else {
+ v_new = BM_vert_create(bm, v_sep->co, v_sep, BM_CREATE_NOP);
+
+ for (i = 0; i < STACK_SIZE(edges); i++) {
+ BMEdge *e = edges[i];
+ BMLoop *l_iter, *l_first, *l_next;
+ BMEdge *e_new;
+
+ /* disable so copied edge isn't left dirty (loop edges are cleared last too) */
+ BM_ELEM_API_FLAG_DISABLE(e, EDGE_VISIT);
+
+ /* will always be false when (is_mixed_loop_any == false) */
+ if (!BM_ELEM_API_FLAG_TEST(e->l, LOOP_VISIT)) {
+ /* edge has some loops owned by us, some owned by other loops */
+ BMVert *e_new_v_pair[2];
+
+ if (e->v1 == v_sep) {
+ e_new_v_pair[0] = v_new;
+ e_new_v_pair[1] = e->v2;
+ }
+ else {
+ BLI_assert(v_sep == e->v2);
+ e_new_v_pair[0] = e->v1;
+ e_new_v_pair[1] = v_new;
+ }
+
+ e_new = BM_edge_create(bm, UNPACK2(e_new_v_pair), e, BM_CREATE_NOP);
+
+ /* now moved all loops from 'larr' to this newly created edge */
+ l_iter = l_first = e->l;
+ do {
+ l_next = l_iter->radial_next;
+ if (BM_ELEM_API_FLAG_TEST(l_iter, LOOP_VISIT)) {
+ bmesh_radial_loop_remove(e, l_iter);
+ bmesh_radial_loop_append(e_new, l_iter);
+ l_iter->e = e_new;
+ }
+ } while ((l_iter = l_next) != l_first);
+ }
+ else {
+ /* we own the edge entirely, replace the vert */
+ bmesh_disk_vert_replace(e, v_new, v_sep);
+ }
+
+ /* loop vert is handled last! */
+ }
+ }
+
+ for (i = 0; i < larr_len; i++) {
+ BMLoop *l_sep = larr[i];
+
+ l_sep->v = v_new;
+
+ BLI_assert(BM_ELEM_API_FLAG_TEST(l_sep, LOOP_VISIT));
+ BLI_assert(BM_ELEM_API_FLAG_TEST(l_sep->prev, LOOP_VISIT));
+ BLI_assert(BM_ELEM_API_FLAG_TEST(l_sep->next, LOOP_VISIT));
+ BM_ELEM_API_FLAG_DISABLE(l_sep, LOOP_VISIT);
+ BM_ELEM_API_FLAG_DISABLE(l_sep->prev, LOOP_VISIT);
+ BM_ELEM_API_FLAG_DISABLE(l_sep->next, LOOP_VISIT);
+
+ BM_ELEM_API_FLAG_DISABLE(l_sep->prev->e, EDGE_VISIT);
+ BM_ELEM_API_FLAG_DISABLE(l_sep->e, EDGE_VISIT);
+ }
#undef LOOP_VISIT
#undef EDGE_VISIT
- return v_new;
+ return v_new;
}
static void bmesh_edge_vert_swap__recursive(BMEdge *e, BMVert *v_dst, BMVert *v_src)
{
- BMLoop *l_iter, *l_first;
-
- BLI_assert(ELEM(v_src, e->v1, e->v2));
- bmesh_disk_vert_replace(e, v_dst, v_src);
-
- l_iter = l_first = e->l;
- do {
- if (l_iter->v == v_src) {
- l_iter->v = v_dst;
- if (BM_vert_in_edge(l_iter->prev->e, v_src)) {
- bmesh_edge_vert_swap__recursive(l_iter->prev->e, v_dst, v_src);
- }
- }
- else if (l_iter->next->v == v_src) {
- l_iter->next->v = v_dst;
- if (BM_vert_in_edge(l_iter->next->e, v_src)) {
- bmesh_edge_vert_swap__recursive(l_iter->next->e, v_dst, v_src);
- }
- }
- else {
- BLI_assert(l_iter->prev->v != v_src);
- }
- } while ((l_iter = l_iter->radial_next) != l_first);
+ BMLoop *l_iter, *l_first;
+
+ BLI_assert(ELEM(v_src, e->v1, e->v2));
+ bmesh_disk_vert_replace(e, v_dst, v_src);
+
+ l_iter = l_first = e->l;
+ do {
+ if (l_iter->v == v_src) {
+ l_iter->v = v_dst;
+ if (BM_vert_in_edge(l_iter->prev->e, v_src)) {
+ bmesh_edge_vert_swap__recursive(l_iter->prev->e, v_dst, v_src);
+ }
+ }
+ else if (l_iter->next->v == v_src) {
+ l_iter->next->v = v_dst;
+ if (BM_vert_in_edge(l_iter->next->e, v_src)) {
+ bmesh_edge_vert_swap__recursive(l_iter->next->e, v_dst, v_src);
+ }
+ }
+ else {
+ BLI_assert(l_iter->prev->v != v_src);
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
}
/**
@@ -2912,11 +2907,11 @@ static void bmesh_edge_vert_swap__recursive(BMEdge *e, BMVert *v_dst, BMVert *v_
*/
BMVert *bmesh_kernel_unglue_region_make_vert_multi_isolated(BMesh *bm, BMLoop *l_sep)
{
- BMVert *v_new = BM_vert_create(bm, l_sep->v->co, l_sep->v, BM_CREATE_NOP);
- /* passing either 'l_sep->e', 'l_sep->prev->e' will work */
- bmesh_edge_vert_swap__recursive(l_sep->e, v_new, l_sep->v);
- BLI_assert(l_sep->v == v_new);
- return v_new;
+ BMVert *v_new = BM_vert_create(bm, l_sep->v->co, l_sep->v, BM_CREATE_NOP);
+ /* passing either 'l_sep->e', 'l_sep->prev->e' will work */
+ bmesh_edge_vert_swap__recursive(l_sep->e, v_new, l_sep->v);
+ BLI_assert(l_sep->v == v_new);
+ return v_new;
}
/**
@@ -2926,23 +2921,23 @@ BMVert *bmesh_kernel_unglue_region_make_vert_multi_isolated(BMesh *bm, BMLoop *l
*/
void bmesh_face_swap_data(BMFace *f_a, BMFace *f_b)
{
- BMLoop *l_iter, *l_first;
+ BMLoop *l_iter, *l_first;
- BLI_assert(f_a != f_b);
+ BLI_assert(f_a != f_b);
- l_iter = l_first = BM_FACE_FIRST_LOOP(f_a);
- do {
- l_iter->f = f_b;
- } while ((l_iter = l_iter->next) != l_first);
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_a);
+ do {
+ l_iter->f = f_b;
+ } while ((l_iter = l_iter->next) != l_first);
- l_iter = l_first = BM_FACE_FIRST_LOOP(f_b);
- do {
- l_iter->f = f_a;
- } while ((l_iter = l_iter->next) != l_first);
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_b);
+ do {
+ l_iter->f = f_a;
+ } while ((l_iter = l_iter->next) != l_first);
- SWAP(BMFace, (*f_a), (*f_b));
+ SWAP(BMFace, (*f_a), (*f_b));
- /* swap back */
- SWAP(void *, f_a->head.data, f_b->head.data);
- SWAP(int, f_a->head.index, f_b->head.index);
+ /* swap back */
+ SWAP(void *, f_a->head.data, f_b->head.data);
+ SWAP(int, f_a->head.index, f_b->head.index);
}
diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h
index dc20b8afaac..3308f93d5d3 100644
--- a/source/blender/bmesh/intern/bmesh_core.h
+++ b/source/blender/bmesh/intern/bmesh_core.h
@@ -22,96 +22,107 @@
*/
BMFace *BM_face_copy(
- BMesh *bm_dst, BMesh *bm_src, BMFace *f,
- const bool copy_verts, const bool copy_edges);
+ BMesh *bm_dst, BMesh *bm_src, BMFace *f, const bool copy_verts, const bool copy_edges);
typedef enum eBMCreateFlag {
- BM_CREATE_NOP = 0,
- /* faces and edges only */
- BM_CREATE_NO_DOUBLE = (1 << 1),
- /* Skip CustomData - for all element types data,
- * use if we immediately write customdata into the element so this skips copying from 'example'
- * args or setting defaults, speeds up conversion when data is converted all at once. */
- BM_CREATE_SKIP_CD = (1 << 2),
+ BM_CREATE_NOP = 0,
+ /* faces and edges only */
+ BM_CREATE_NO_DOUBLE = (1 << 1),
+ /* Skip CustomData - for all element types data,
+ * use if we immediately write customdata into the element so this skips copying from 'example'
+ * args or setting defaults, speeds up conversion when data is converted all at once. */
+ BM_CREATE_SKIP_CD = (1 << 2),
} eBMCreateFlag;
-BMVert *BM_vert_create(
- BMesh *bm, const float co[3],
- const BMVert *v_example, const eBMCreateFlag create_flag);
+BMVert *BM_vert_create(BMesh *bm,
+ const float co[3],
+ const BMVert *v_example,
+ const eBMCreateFlag create_flag);
BMEdge *BM_edge_create(
- BMesh *bm, BMVert *v1, BMVert *v2,
- const BMEdge *e_example, const eBMCreateFlag create_flag);
-BMFace *BM_face_create(
- BMesh *bm, BMVert **verts, BMEdge **edges, const int len,
- const BMFace *f_example, const eBMCreateFlag create_flag);
-BMFace *BM_face_create_verts(
- BMesh *bm, BMVert **verts, const int len,
- const BMFace *f_example, const eBMCreateFlag create_flag,
- const bool create_edges);
-
-void BM_face_edges_kill(BMesh *bm, BMFace *f);
-void BM_face_verts_kill(BMesh *bm, BMFace *f);
-
-void BM_face_kill_loose(BMesh *bm, BMFace *f);
-
-void BM_face_kill(BMesh *bm, BMFace *f);
-void BM_edge_kill(BMesh *bm, BMEdge *e);
-void BM_vert_kill(BMesh *bm, BMVert *v);
-
-bool BM_edge_splice(BMesh *bm, BMEdge *e_dst, BMEdge *e_src);
-bool BM_vert_splice(BMesh *bm, BMVert *v_dst, BMVert *v_src);
-bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b);
-
-void bmesh_kernel_loop_reverse(
- BMesh *bm, BMFace *f,
- const int cd_loop_mdisp_offset, const bool use_loop_mdisp_flip);
-
-void bmesh_face_swap_data(BMFace *f_a, BMFace *f_b);
+ BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *e_example, const eBMCreateFlag create_flag);
+BMFace *BM_face_create(BMesh *bm,
+ BMVert **verts,
+ BMEdge **edges,
+ const int len,
+ const BMFace *f_example,
+ const eBMCreateFlag create_flag);
+BMFace *BM_face_create_verts(BMesh *bm,
+ BMVert **verts,
+ const int len,
+ const BMFace *f_example,
+ const eBMCreateFlag create_flag,
+ const bool create_edges);
+
+void BM_face_edges_kill(BMesh *bm, BMFace *f);
+void BM_face_verts_kill(BMesh *bm, BMFace *f);
+
+void BM_face_kill_loose(BMesh *bm, BMFace *f);
+
+void BM_face_kill(BMesh *bm, BMFace *f);
+void BM_edge_kill(BMesh *bm, BMEdge *e);
+void BM_vert_kill(BMesh *bm, BMVert *v);
+
+bool BM_edge_splice(BMesh *bm, BMEdge *e_dst, BMEdge *e_src);
+bool BM_vert_splice(BMesh *bm, BMVert *v_dst, BMVert *v_src);
+bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b);
+
+void bmesh_kernel_loop_reverse(BMesh *bm,
+ BMFace *f,
+ const int cd_loop_mdisp_offset,
+ const bool use_loop_mdisp_flip);
+
+void bmesh_face_swap_data(BMFace *f_a, BMFace *f_b);
BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del);
-void BM_vert_separate(
- BMesh *bm, BMVert *v, BMEdge **e_in, int e_in_len, const bool copy_select,
- BMVert ***r_vout, int *r_vout_len);
-void BM_vert_separate_hflag(
- BMesh *bm, BMVert *v, const char hflag, const bool copy_select,
- BMVert ***r_vout, int *r_vout_len);
+void BM_vert_separate(BMesh *bm,
+ BMVert *v,
+ BMEdge **e_in,
+ int e_in_len,
+ const bool copy_select,
+ BMVert ***r_vout,
+ int *r_vout_len);
+void BM_vert_separate_hflag(BMesh *bm,
+ BMVert *v,
+ const char hflag,
+ const bool copy_select,
+ BMVert ***r_vout,
+ int *r_vout_len);
void BM_vert_separate_tested_edges(
- BMesh *bm, BMVert *v_dst, BMVert *v_src,
- bool (*testfn)(BMEdge *, void *arg), void *arg);
+ BMesh *bm, BMVert *v_dst, BMVert *v_src, bool (*testfn)(BMEdge *, void *arg), void *arg);
/**
* BMesh Kernel: For modifying structure.
*
* Names are on the verbose side but these are only for low-level access.
*/
-void bmesh_kernel_vert_separate(
- BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len,
- const bool copy_select);
-void bmesh_kernel_edge_separate(
- BMesh *bm, BMEdge *e, BMLoop *l_sep,
- const bool copy_select);
-
-BMFace *bmesh_kernel_split_face_make_edge(
- BMesh *bm, BMFace *f,
- BMLoop *l1, BMLoop *l2,
- BMLoop **r_l,
+void bmesh_kernel_vert_separate(
+ BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, const bool copy_select);
+void bmesh_kernel_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep, const bool copy_select);
+
+BMFace *bmesh_kernel_split_face_make_edge(BMesh *bm,
+ BMFace *f,
+ BMLoop *l1,
+ BMLoop *l2,
+ BMLoop **r_l,
#ifdef USE_BMESH_HOLES
- ListBase *holes,
+ ListBase *holes,
#endif
- BMEdge *example,
- const bool no_double
- );
-
-BMVert *bmesh_kernel_split_edge_make_vert(
- BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e);
-BMEdge *bmesh_kernel_join_edge_kill_vert(
- BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
- const bool do_del, const bool check_edge_splice,
- const bool kill_degenerate_faces);
-BMVert *bmesh_kernel_join_vert_kill_edge(
- BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
- const bool do_del, const bool check_edge_double,
- const bool kill_degenerate_faces);
+ BMEdge *example,
+ const bool no_double);
+
+BMVert *bmesh_kernel_split_edge_make_vert(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e);
+BMEdge *bmesh_kernel_join_edge_kill_vert(BMesh *bm,
+ BMEdge *e_kill,
+ BMVert *v_kill,
+ const bool do_del,
+ const bool check_edge_splice,
+ const bool kill_degenerate_faces);
+BMVert *bmesh_kernel_join_vert_kill_edge(BMesh *bm,
+ BMEdge *e_kill,
+ BMVert *v_kill,
+ const bool do_del,
+ const bool check_edge_double,
+ const bool kill_degenerate_faces);
BMFace *bmesh_kernel_join_face_kill_edge(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e);
BMVert *bmesh_kernel_unglue_region_make_vert(BMesh *bm, BMLoop *l_sep);
diff --git a/source/blender/bmesh/intern/bmesh_delete.c b/source/blender/bmesh/intern/bmesh_delete.c
index 23fe8a31b41..4e2c81c80c3 100644
--- a/source/blender/bmesh/intern/bmesh_delete.c
+++ b/source/blender/bmesh/intern/bmesh_delete.c
@@ -23,13 +23,11 @@
* BM remove functions.
*/
-
#include "BLI_utildefines.h"
#include "bmesh.h"
#include "intern/bmesh_private.h"
-
/* -------------------------------------------------------------------- */
/* BMO functions */
@@ -42,63 +40,63 @@
*/
static void bmo_remove_tagged_faces(BMesh *bm, const short oflag)
{
- BMFace *f, *f_next;
- BMIter iter;
-
- BM_ITER_MESH_MUTABLE (f, f_next, &iter, bm, BM_FACES_OF_MESH) {
- if (BMO_face_flag_test(bm, f, oflag)) {
- BM_face_kill(bm, f);
- }
- }
+ BMFace *f, *f_next;
+ BMIter iter;
+
+ BM_ITER_MESH_MUTABLE (f, f_next, &iter, bm, BM_FACES_OF_MESH) {
+ if (BMO_face_flag_test(bm, f, oflag)) {
+ BM_face_kill(bm, f);
+ }
+ }
}
static void bmo_remove_tagged_edges(BMesh *bm, const short oflag)
{
- BMEdge *e, *e_next;
- BMIter iter;
-
- BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) {
- if (BMO_edge_flag_test(bm, e, oflag)) {
- BM_edge_kill(bm, e);
- }
- }
+ BMEdge *e, *e_next;
+ BMIter iter;
+
+ BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BMO_edge_flag_test(bm, e, oflag)) {
+ BM_edge_kill(bm, e);
+ }
+ }
}
static void bmo_remove_tagged_verts(BMesh *bm, const short oflag)
{
- BMVert *v, *v_next;
- BMIter iter;
-
- BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
- if (BMO_vert_flag_test(bm, v, oflag)) {
- BM_vert_kill(bm, v);
- }
- }
+ BMVert *v, *v_next;
+ BMIter iter;
+
+ BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BMO_vert_flag_test(bm, v, oflag)) {
+ BM_vert_kill(bm, v);
+ }
+ }
}
static void bmo_remove_tagged_verts_loose(BMesh *bm, const short oflag)
{
- BMVert *v, *v_next;
- BMIter iter;
-
- BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
- if (BMO_vert_flag_test(bm, v, oflag) && (v->e == NULL)) {
- BM_vert_kill(bm, v);
- }
- }
+ BMVert *v, *v_next;
+ BMIter iter;
+
+ BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BMO_vert_flag_test(bm, v, oflag) && (v->e == NULL)) {
+ BM_vert_kill(bm, v);
+ }
+ }
}
void BMO_mesh_delete_oflag_tagged(BMesh *bm, const short oflag, const char htype)
{
- if (htype & BM_FACE) {
- bmo_remove_tagged_faces(bm, oflag);
- }
- if (htype & BM_EDGE) {
- bmo_remove_tagged_edges(bm, oflag);
- }
- if (htype & BM_VERT) {
- bmo_remove_tagged_verts(bm, oflag);
- }
+ if (htype & BM_FACE) {
+ bmo_remove_tagged_faces(bm, oflag);
+ }
+ if (htype & BM_EDGE) {
+ bmo_remove_tagged_edges(bm, oflag);
+ }
+ if (htype & BM_VERT) {
+ bmo_remove_tagged_verts(bm, oflag);
+ }
}
/**
@@ -107,111 +105,104 @@ void BMO_mesh_delete_oflag_tagged(BMesh *bm, const short oflag, const char htype
*/
void BMO_mesh_delete_oflag_context(BMesh *bm, const short oflag, const int type)
{
- BMEdge *e;
- BMFace *f;
-
- BMIter eiter;
- BMIter fiter;
-
- switch (type) {
- case DEL_VERTS:
- {
- bmo_remove_tagged_verts(bm, oflag);
-
- break;
- }
- case DEL_EDGES:
- {
- /* flush down to vert */
- BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
- if (BMO_edge_flag_test(bm, e, oflag)) {
- BMO_vert_flag_enable(bm, e->v1, oflag);
- BMO_vert_flag_enable(bm, e->v2, oflag);
- }
- }
- bmo_remove_tagged_edges(bm, oflag);
- bmo_remove_tagged_verts_loose(bm, oflag);
-
- break;
- }
- case DEL_EDGESFACES:
- {
- bmo_remove_tagged_edges(bm, oflag);
-
- break;
- }
- case DEL_ONLYFACES:
- {
- bmo_remove_tagged_faces(bm, oflag);
-
- break;
- }
- case DEL_ONLYTAGGED:
- {
- BMO_mesh_delete_oflag_tagged(bm, oflag, BM_ALL_NOLOOP);
-
- break;
- }
- case DEL_FACES:
- case DEL_FACES_KEEP_BOUNDARY:
- {
- /* go through and mark all edges and all verts of all faces for delete */
- BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
- if (BMO_face_flag_test(bm, f, oflag)) {
- BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
- BMLoop *l_iter;
-
- l_iter = l_first;
- do {
- BMO_vert_flag_enable(bm, l_iter->v, oflag);
- BMO_edge_flag_enable(bm, l_iter->e, oflag);
- } while ((l_iter = l_iter->next) != l_first);
- }
- }
- /* now go through and mark all remaining faces all edges for keeping */
- BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
- if (!BMO_face_flag_test(bm, f, oflag)) {
- BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
- BMLoop *l_iter;
-
- l_iter = l_first;
- do {
- BMO_vert_flag_disable(bm, l_iter->v, oflag);
- BMO_edge_flag_disable(bm, l_iter->e, oflag);
- } while ((l_iter = l_iter->next) != l_first);
- }
- }
- /* also mark all the vertices of remaining edges for keeping */
- BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
-
- /* Only exception to normal 'DEL_FACES' logic. */
- if (type == DEL_FACES_KEEP_BOUNDARY) {
- if (BM_edge_is_boundary(e)) {
- BMO_edge_flag_disable(bm, e, oflag);
- }
- }
-
- if (!BMO_edge_flag_test(bm, e, oflag)) {
- BMO_vert_flag_disable(bm, e->v1, oflag);
- BMO_vert_flag_disable(bm, e->v2, oflag);
- }
- }
-
- /* now delete marked face */
- bmo_remove_tagged_faces(bm, oflag);
- /* delete marked edge */
- bmo_remove_tagged_edges(bm, oflag);
- /* remove loose vertice */
- bmo_remove_tagged_verts(bm, oflag);
-
- break;
- }
- }
+ BMEdge *e;
+ BMFace *f;
+
+ BMIter eiter;
+ BMIter fiter;
+
+ switch (type) {
+ case DEL_VERTS: {
+ bmo_remove_tagged_verts(bm, oflag);
+
+ break;
+ }
+ case DEL_EDGES: {
+ /* flush down to vert */
+ BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
+ if (BMO_edge_flag_test(bm, e, oflag)) {
+ BMO_vert_flag_enable(bm, e->v1, oflag);
+ BMO_vert_flag_enable(bm, e->v2, oflag);
+ }
+ }
+ bmo_remove_tagged_edges(bm, oflag);
+ bmo_remove_tagged_verts_loose(bm, oflag);
+
+ break;
+ }
+ case DEL_EDGESFACES: {
+ bmo_remove_tagged_edges(bm, oflag);
+
+ break;
+ }
+ case DEL_ONLYFACES: {
+ bmo_remove_tagged_faces(bm, oflag);
+
+ break;
+ }
+ case DEL_ONLYTAGGED: {
+ BMO_mesh_delete_oflag_tagged(bm, oflag, BM_ALL_NOLOOP);
+
+ break;
+ }
+ case DEL_FACES:
+ case DEL_FACES_KEEP_BOUNDARY: {
+ /* go through and mark all edges and all verts of all faces for delete */
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ if (BMO_face_flag_test(bm, f, oflag)) {
+ BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
+ BMLoop *l_iter;
+
+ l_iter = l_first;
+ do {
+ BMO_vert_flag_enable(bm, l_iter->v, oflag);
+ BMO_edge_flag_enable(bm, l_iter->e, oflag);
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ }
+ /* now go through and mark all remaining faces all edges for keeping */
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ if (!BMO_face_flag_test(bm, f, oflag)) {
+ BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
+ BMLoop *l_iter;
+
+ l_iter = l_first;
+ do {
+ BMO_vert_flag_disable(bm, l_iter->v, oflag);
+ BMO_edge_flag_disable(bm, l_iter->e, oflag);
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ }
+ /* also mark all the vertices of remaining edges for keeping */
+ BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
+
+ /* Only exception to normal 'DEL_FACES' logic. */
+ if (type == DEL_FACES_KEEP_BOUNDARY) {
+ if (BM_edge_is_boundary(e)) {
+ BMO_edge_flag_disable(bm, e, oflag);
+ }
+ }
+
+ if (!BMO_edge_flag_test(bm, e, oflag)) {
+ BMO_vert_flag_disable(bm, e->v1, oflag);
+ BMO_vert_flag_disable(bm, e->v2, oflag);
+ }
+ }
+
+ /* now delete marked face */
+ bmo_remove_tagged_faces(bm, oflag);
+ /* delete marked edge */
+ bmo_remove_tagged_edges(bm, oflag);
+ /* remove loose vertice */
+ bmo_remove_tagged_verts(bm, oflag);
+
+ break;
+ }
+ }
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* BM functions
*
@@ -225,63 +216,63 @@ void BMO_mesh_delete_oflag_context(BMesh *bm, const short oflag, const int type)
static void bm_remove_tagged_faces(BMesh *bm, const char hflag)
{
- BMFace *f, *f_next;
- BMIter iter;
-
- BM_ITER_MESH_MUTABLE (f, f_next, &iter, bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(f, hflag)) {
- BM_face_kill(bm, f);
- }
- }
+ BMFace *f, *f_next;
+ BMIter iter;
+
+ BM_ITER_MESH_MUTABLE (f, f_next, &iter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, hflag)) {
+ BM_face_kill(bm, f);
+ }
+ }
}
static void bm_remove_tagged_edges(BMesh *bm, const char hflag)
{
- BMEdge *e, *e_next;
- BMIter iter;
-
- BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, hflag)) {
- BM_edge_kill(bm, e);
- }
- }
+ BMEdge *e, *e_next;
+ BMIter iter;
+
+ BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, hflag)) {
+ BM_edge_kill(bm, e);
+ }
+ }
}
static void bm_remove_tagged_verts(BMesh *bm, const char hflag)
{
- BMVert *v, *v_next;
- BMIter iter;
-
- BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, hflag)) {
- BM_vert_kill(bm, v);
- }
- }
+ BMVert *v, *v_next;
+ BMIter iter;
+
+ BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, hflag)) {
+ BM_vert_kill(bm, v);
+ }
+ }
}
static void bm_remove_tagged_verts_loose(BMesh *bm, const char hflag)
{
- BMVert *v, *v_next;
- BMIter iter;
-
- BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, hflag) && (v->e == NULL)) {
- BM_vert_kill(bm, v);
- }
- }
+ BMVert *v, *v_next;
+ BMIter iter;
+
+ BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, hflag) && (v->e == NULL)) {
+ BM_vert_kill(bm, v);
+ }
+ }
}
void BM_mesh_delete_hflag_tagged(BMesh *bm, const char hflag, const char htype)
{
- if (htype & BM_FACE) {
- bm_remove_tagged_faces(bm, hflag);
- }
- if (htype & BM_EDGE) {
- bm_remove_tagged_edges(bm, hflag);
- }
- if (htype & BM_VERT) {
- bm_remove_tagged_verts(bm, hflag);
- }
+ if (htype & BM_FACE) {
+ bm_remove_tagged_faces(bm, hflag);
+ }
+ if (htype & BM_EDGE) {
+ bm_remove_tagged_edges(bm, hflag);
+ }
+ if (htype & BM_VERT) {
+ bm_remove_tagged_verts(bm, hflag);
+ }
}
/**
@@ -290,96 +281,90 @@ void BM_mesh_delete_hflag_tagged(BMesh *bm, const char hflag, const char htype)
*/
void BM_mesh_delete_hflag_context(BMesh *bm, const char hflag, const int type)
{
- BMEdge *e;
- BMFace *f;
-
- BMIter eiter;
- BMIter fiter;
-
- switch (type) {
- case DEL_VERTS:
- {
- bm_remove_tagged_verts(bm, hflag);
-
- break;
- }
- case DEL_EDGES:
- {
- /* flush down to vert */
- BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, hflag)) {
- BM_elem_flag_enable(e->v1, hflag);
- BM_elem_flag_enable(e->v2, hflag);
- }
- }
- bm_remove_tagged_edges(bm, hflag);
- bm_remove_tagged_verts_loose(bm, hflag);
-
- break;
- }
- case DEL_EDGESFACES:
- {
- bm_remove_tagged_edges(bm, hflag);
-
- break;
- }
- case DEL_ONLYFACES:
- {
- bm_remove_tagged_faces(bm, hflag);
-
- break;
- }
- case DEL_ONLYTAGGED:
- {
- BM_mesh_delete_hflag_tagged(bm, hflag, BM_ALL_NOLOOP);
-
- break;
- }
- case DEL_FACES:
- {
- /* go through and mark all edges and all verts of all faces for delete */
- BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(f, hflag)) {
- BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
- BMLoop *l_iter;
-
- l_iter = l_first;
- do {
- BM_elem_flag_enable(l_iter->v, hflag);
- BM_elem_flag_enable(l_iter->e, hflag);
- } while ((l_iter = l_iter->next) != l_first);
- }
- }
- /* now go through and mark all remaining faces all edges for keeping */
- BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(f, hflag)) {
- BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
- BMLoop *l_iter;
-
- l_iter = l_first;
- do {
- BM_elem_flag_disable(l_iter->v, hflag);
- BM_elem_flag_disable(l_iter->e, hflag);
- } while ((l_iter = l_iter->next) != l_first);
- }
- }
- /* also mark all the vertices of remaining edges for keeping */
- BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
- if (!BM_elem_flag_test(e, hflag)) {
- BM_elem_flag_disable(e->v1, hflag);
- BM_elem_flag_disable(e->v2, hflag);
- }
- }
- /* now delete marked face */
- bm_remove_tagged_faces(bm, hflag);
- /* delete marked edge */
- bm_remove_tagged_edges(bm, hflag);
- /* remove loose vertice */
- bm_remove_tagged_verts(bm, hflag);
-
- break;
- }
- }
+ BMEdge *e;
+ BMFace *f;
+
+ BMIter eiter;
+ BMIter fiter;
+
+ switch (type) {
+ case DEL_VERTS: {
+ bm_remove_tagged_verts(bm, hflag);
+
+ break;
+ }
+ case DEL_EDGES: {
+ /* flush down to vert */
+ BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, hflag)) {
+ BM_elem_flag_enable(e->v1, hflag);
+ BM_elem_flag_enable(e->v2, hflag);
+ }
+ }
+ bm_remove_tagged_edges(bm, hflag);
+ bm_remove_tagged_verts_loose(bm, hflag);
+
+ break;
+ }
+ case DEL_EDGESFACES: {
+ bm_remove_tagged_edges(bm, hflag);
+
+ break;
+ }
+ case DEL_ONLYFACES: {
+ bm_remove_tagged_faces(bm, hflag);
+
+ break;
+ }
+ case DEL_ONLYTAGGED: {
+ BM_mesh_delete_hflag_tagged(bm, hflag, BM_ALL_NOLOOP);
+
+ break;
+ }
+ case DEL_FACES: {
+ /* go through and mark all edges and all verts of all faces for delete */
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, hflag)) {
+ BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
+ BMLoop *l_iter;
+
+ l_iter = l_first;
+ do {
+ BM_elem_flag_enable(l_iter->v, hflag);
+ BM_elem_flag_enable(l_iter->e, hflag);
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ }
+ /* now go through and mark all remaining faces all edges for keeping */
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(f, hflag)) {
+ BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
+ BMLoop *l_iter;
+
+ l_iter = l_first;
+ do {
+ BM_elem_flag_disable(l_iter->v, hflag);
+ BM_elem_flag_disable(l_iter->e, hflag);
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ }
+ /* also mark all the vertices of remaining edges for keeping */
+ BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
+ if (!BM_elem_flag_test(e, hflag)) {
+ BM_elem_flag_disable(e->v1, hflag);
+ BM_elem_flag_disable(e->v2, hflag);
+ }
+ }
+ /* now delete marked face */
+ bm_remove_tagged_faces(bm, hflag);
+ /* delete marked edge */
+ bm_remove_tagged_edges(bm, hflag);
+ /* remove loose vertice */
+ bm_remove_tagged_verts(bm, hflag);
+
+ break;
+ }
+ }
}
/** \} */
diff --git a/source/blender/bmesh/intern/bmesh_delete.h b/source/blender/bmesh/intern/bmesh_delete.h
index 616485b242e..d41f26baddd 100644
--- a/source/blender/bmesh/intern/bmesh_delete.h
+++ b/source/blender/bmesh/intern/bmesh_delete.h
@@ -22,9 +22,9 @@
*/
void BMO_mesh_delete_oflag_tagged(BMesh *bm, const short oflag, const char htype);
-void BM_mesh_delete_hflag_tagged(BMesh *bm, const char hflag, const char htype);
+void BM_mesh_delete_hflag_tagged(BMesh *bm, const char hflag, const char htype);
void BMO_mesh_delete_oflag_context(BMesh *bm, const short oflag, const int type);
-void BM_mesh_delete_hflag_context(BMesh *bm, const char hflag, const int type);
+void BM_mesh_delete_hflag_context(BMesh *bm, const char hflag, const int type);
#endif /* __BMESH_DELETE_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_edgeloop.c b/source/blender/bmesh/intern/bmesh_edgeloop.c
index 1f8661c3e04..a802515a3b2 100644
--- a/source/blender/bmesh/intern/bmesh_edgeloop.c
+++ b/source/blender/bmesh/intern/bmesh_edgeloop.c
@@ -33,15 +33,15 @@
#include "bmesh.h"
-#include "bmesh_edgeloop.h" /* own include */
+#include "bmesh_edgeloop.h" /* own include */
typedef struct BMEdgeLoopStore {
- struct BMEdgeLoopStore *next, *prev;
- ListBase verts;
- int flag;
- int len;
- /* optional values to calc */
- float co[3], no[3];
+ struct BMEdgeLoopStore *next, *prev;
+ ListBase verts;
+ int flag;
+ int len;
+ /* optional values to calc */
+ float co[3], no[3];
} BMEdgeLoopStore;
#define BM_EDGELOOP_IS_CLOSED (1 << 0)
@@ -50,26 +50,24 @@ typedef struct BMEdgeLoopStore {
/* -------------------------------------------------------------------- */
/* BM_mesh_edgeloops_find & Util Functions */
-static int bm_vert_other_tag(
- BMVert *v, BMVert *v_prev,
- BMEdge **r_e)
+static int bm_vert_other_tag(BMVert *v, BMVert *v_prev, BMEdge **r_e)
{
- BMIter iter;
- BMEdge *e, *e_next = NULL;
- uint count = 0;
-
- BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
- if (BM_elem_flag_test(e, BM_ELEM_INTERNAL_TAG)) {
- BMVert *v_other = BM_edge_other_vert(e, v);
- if (v_other != v_prev) {
- e_next = e;
- count++;
- }
- }
- }
-
- *r_e = e_next;
- return count;
+ BMIter iter;
+ BMEdge *e, *e_next = NULL;
+ uint count = 0;
+
+ BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
+ if (BM_elem_flag_test(e, BM_ELEM_INTERNAL_TAG)) {
+ BMVert *v_other = BM_edge_other_vert(e, v);
+ if (v_other != v_prev) {
+ e_next = e;
+ count++;
+ }
+ }
+ }
+
+ *r_e = e_next;
+ return count;
}
/**
@@ -77,117 +75,115 @@ static int bm_vert_other_tag(
*/
static bool bm_loop_build(BMEdgeLoopStore *el_store, BMVert *v_prev, BMVert *v, int dir)
{
- void (*add_fn)(ListBase *, void *) = dir == 1 ? BLI_addhead : BLI_addtail;
- BMEdge *e_next;
- BMVert *v_next;
- BMVert *v_first = v;
-
- BLI_assert(ABS(dir) == 1);
-
- if (!BM_elem_flag_test(v, BM_ELEM_INTERNAL_TAG)) {
- return true;
- }
-
- while (v) {
- LinkData *node = MEM_callocN(sizeof(*node), __func__);
- int count;
- node->data = v;
- add_fn(&el_store->verts, node);
- el_store->len++;
- BM_elem_flag_disable(v, BM_ELEM_INTERNAL_TAG);
-
- count = bm_vert_other_tag(v, v_prev, &e_next);
- if (count == 1) {
- v_next = BM_edge_other_vert(e_next, v);
- BM_elem_flag_disable(e_next, BM_ELEM_INTERNAL_TAG);
- if (UNLIKELY(v_next == v_first)) {
- el_store->flag |= BM_EDGELOOP_IS_CLOSED;
- v_next = NULL;
- }
- }
- else if (count == 0) {
- /* pass */
- v_next = NULL;
- }
- else {
- v_next = NULL;
- return false;
- }
-
- v_prev = v;
- v = v_next;
- }
-
- return true;
+ void (*add_fn)(ListBase *, void *) = dir == 1 ? BLI_addhead : BLI_addtail;
+ BMEdge *e_next;
+ BMVert *v_next;
+ BMVert *v_first = v;
+
+ BLI_assert(ABS(dir) == 1);
+
+ if (!BM_elem_flag_test(v, BM_ELEM_INTERNAL_TAG)) {
+ return true;
+ }
+
+ while (v) {
+ LinkData *node = MEM_callocN(sizeof(*node), __func__);
+ int count;
+ node->data = v;
+ add_fn(&el_store->verts, node);
+ el_store->len++;
+ BM_elem_flag_disable(v, BM_ELEM_INTERNAL_TAG);
+
+ count = bm_vert_other_tag(v, v_prev, &e_next);
+ if (count == 1) {
+ v_next = BM_edge_other_vert(e_next, v);
+ BM_elem_flag_disable(e_next, BM_ELEM_INTERNAL_TAG);
+ if (UNLIKELY(v_next == v_first)) {
+ el_store->flag |= BM_EDGELOOP_IS_CLOSED;
+ v_next = NULL;
+ }
+ }
+ else if (count == 0) {
+ /* pass */
+ v_next = NULL;
+ }
+ else {
+ v_next = NULL;
+ return false;
+ }
+
+ v_prev = v;
+ v = v_next;
+ }
+
+ return true;
}
/**
* \return listbase of listbases, each linking to a vertex.
*/
-int BM_mesh_edgeloops_find(
- BMesh *bm, ListBase *r_eloops,
- bool (*test_fn)(BMEdge *, void *user_data), void *user_data)
+int BM_mesh_edgeloops_find(BMesh *bm,
+ ListBase *r_eloops,
+ bool (*test_fn)(BMEdge *, void *user_data),
+ void *user_data)
{
- BMIter iter;
- BMEdge *e;
- BMVert *v;
- int count = 0;
-
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- BM_elem_flag_disable(v, BM_ELEM_INTERNAL_TAG);
- }
-
- /* first flush edges to tags, and tag verts */
- BLI_Stack *edge_stack = BLI_stack_new(sizeof(BMEdge *), __func__);
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- BLI_assert(!BM_elem_flag_test(e, BM_ELEM_INTERNAL_TAG));
- if (test_fn(e, user_data)) {
- BM_elem_flag_enable(e, BM_ELEM_INTERNAL_TAG);
- BM_elem_flag_enable(e->v1, BM_ELEM_INTERNAL_TAG);
- BM_elem_flag_enable(e->v2, BM_ELEM_INTERNAL_TAG);
- BLI_stack_push(edge_stack, (void *)&e);
- }
- else {
- BM_elem_flag_disable(e, BM_ELEM_INTERNAL_TAG);
- }
- }
-
- const uint edges_len = BLI_stack_count(edge_stack);
- BMEdge **edges = MEM_mallocN(sizeof(*edges) * edges_len, __func__);
- BLI_stack_pop_n_reverse(edge_stack, edges, BLI_stack_count(edge_stack));
- BLI_stack_free(edge_stack);
-
- for (uint i = 0; i < edges_len; i += 1) {
- e = edges[i];
- if (BM_elem_flag_test(e, BM_ELEM_INTERNAL_TAG)) {
- BMEdgeLoopStore *el_store = MEM_callocN(sizeof(BMEdgeLoopStore), __func__);
-
- /* add both directions */
- if (bm_loop_build(el_store, e->v1, e->v2, 1) &&
- bm_loop_build(el_store, e->v2, e->v1, -1) &&
- el_store->len > 1)
- {
- BLI_addtail(r_eloops, el_store);
- count++;
- }
- else {
- BM_edgeloop_free(el_store);
- }
- }
- }
-
- for (uint i = 0; i < edges_len; i += 1) {
- e = edges[i];
- BM_elem_flag_disable(e, BM_ELEM_INTERNAL_TAG);
- BM_elem_flag_disable(e->v1, BM_ELEM_INTERNAL_TAG);
- BM_elem_flag_disable(e->v2, BM_ELEM_INTERNAL_TAG);
- }
-
- MEM_freeN(edges);
- return count;
+ BMIter iter;
+ BMEdge *e;
+ BMVert *v;
+ int count = 0;
+
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_elem_flag_disable(v, BM_ELEM_INTERNAL_TAG);
+ }
+
+ /* first flush edges to tags, and tag verts */
+ BLI_Stack *edge_stack = BLI_stack_new(sizeof(BMEdge *), __func__);
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ BLI_assert(!BM_elem_flag_test(e, BM_ELEM_INTERNAL_TAG));
+ if (test_fn(e, user_data)) {
+ BM_elem_flag_enable(e, BM_ELEM_INTERNAL_TAG);
+ BM_elem_flag_enable(e->v1, BM_ELEM_INTERNAL_TAG);
+ BM_elem_flag_enable(e->v2, BM_ELEM_INTERNAL_TAG);
+ BLI_stack_push(edge_stack, (void *)&e);
+ }
+ else {
+ BM_elem_flag_disable(e, BM_ELEM_INTERNAL_TAG);
+ }
+ }
+
+ const uint edges_len = BLI_stack_count(edge_stack);
+ BMEdge **edges = MEM_mallocN(sizeof(*edges) * edges_len, __func__);
+ BLI_stack_pop_n_reverse(edge_stack, edges, BLI_stack_count(edge_stack));
+ BLI_stack_free(edge_stack);
+
+ for (uint i = 0; i < edges_len; i += 1) {
+ e = edges[i];
+ if (BM_elem_flag_test(e, BM_ELEM_INTERNAL_TAG)) {
+ BMEdgeLoopStore *el_store = MEM_callocN(sizeof(BMEdgeLoopStore), __func__);
+
+ /* add both directions */
+ if (bm_loop_build(el_store, e->v1, e->v2, 1) && bm_loop_build(el_store, e->v2, e->v1, -1) &&
+ el_store->len > 1) {
+ BLI_addtail(r_eloops, el_store);
+ count++;
+ }
+ else {
+ BM_edgeloop_free(el_store);
+ }
+ }
+ }
+
+ for (uint i = 0; i < edges_len; i += 1) {
+ e = edges[i];
+ BM_elem_flag_disable(e, BM_ELEM_INTERNAL_TAG);
+ BM_elem_flag_disable(e->v1, BM_ELEM_INTERNAL_TAG);
+ BM_elem_flag_disable(e->v2, BM_ELEM_INTERNAL_TAG);
+ }
+
+ MEM_freeN(edges);
+ return count;
}
-
/* -------------------------------------------------------------------- */
/* BM_mesh_edgeloops_find_path & Util Functions */
@@ -196,310 +192,312 @@ int BM_mesh_edgeloops_find(
* Add to
*/
struct VertStep {
- struct VertStep *next, *prev;
- BMVert *v;
+ struct VertStep *next, *prev;
+ BMVert *v;
};
static void vs_add(
- BLI_mempool *vs_pool, ListBase *lb,
- BMVert *v, BMEdge *e_prev, const int iter_tot)
+ BLI_mempool *vs_pool, ListBase *lb, BMVert *v, BMEdge *e_prev, const int iter_tot)
{
- struct VertStep *vs_new = BLI_mempool_alloc(vs_pool);
- vs_new->v = v;
+ struct VertStep *vs_new = BLI_mempool_alloc(vs_pool);
+ vs_new->v = v;
- BM_elem_index_set(v, iter_tot); /* set_dirty */
+ BM_elem_index_set(v, iter_tot); /* set_dirty */
- /* This edge stores a direct path back to the original vertex so we can
- * backtrack without having to store an array of previous verts. */
+ /* This edge stores a direct path back to the original vertex so we can
+ * backtrack without having to store an array of previous verts. */
- /* WARNING - setting the edge is not common practice
- * but currently harmless, take care. */
- BLI_assert(BM_vert_in_edge(e_prev, v));
- v->e = e_prev;
+ /* WARNING - setting the edge is not common practice
+ * but currently harmless, take care. */
+ BLI_assert(BM_vert_in_edge(e_prev, v));
+ v->e = e_prev;
- BLI_addtail(lb, vs_new);
+ BLI_addtail(lb, vs_new);
}
-static bool bm_loop_path_build_step(BLI_mempool *vs_pool, ListBase *lb, const int dir, BMVert *v_match[2])
+static bool bm_loop_path_build_step(BLI_mempool *vs_pool,
+ ListBase *lb,
+ const int dir,
+ BMVert *v_match[2])
{
- ListBase lb_tmp = {NULL, NULL};
- struct VertStep *vs, *vs_next;
- BLI_assert(ABS(dir) == 1);
-
- for (vs = lb->first; vs; vs = vs_next) {
- BMIter iter;
- BMEdge *e;
- /* these values will be the same every iteration */
- const int vs_iter_tot = BM_elem_index_get(vs->v);
- const int vs_iter_next = vs_iter_tot + dir;
-
- vs_next = vs->next;
-
- BM_ITER_ELEM (e, &iter, vs->v, BM_EDGES_OF_VERT) {
- if (BM_elem_flag_test(e, BM_ELEM_INTERNAL_TAG)) {
- BMVert *v_next = BM_edge_other_vert(e, vs->v);
- const int v_next_index = BM_elem_index_get(v_next);
- /* not essential to clear flag but prevents more checking next time round */
- BM_elem_flag_disable(e, BM_ELEM_INTERNAL_TAG);
- if (v_next_index == 0) {
- vs_add(vs_pool, &lb_tmp, v_next, e, vs_iter_next);
- }
- else if ((dir < 0) == (v_next_index < 0)) {
- /* on the same side - do nothing */
- }
- else {
- /* we have met out match! (vertices from different sides meet) */
- if (dir == 1) {
- v_match[0] = vs->v;
- v_match[1] = v_next;
- }
- else {
- v_match[0] = v_next;
- v_match[1] = vs->v;
- }
- /* normally we would manage memory of remaining items in (lb, lb_tmp),
- * but search is done, vs_pool will get destroyed immediately */
- return true;
- }
- }
- }
-
- BLI_mempool_free(vs_pool, vs);
- }
- /* bm->elem_index_dirty |= BM_VERT; */ /* Commented because used in a loop, and this flag has already been set. */
-
- /* lb is now full of free'd items, overwrite */
- *lb = lb_tmp;
-
- return (BLI_listbase_is_empty(lb) == false);
+ ListBase lb_tmp = {NULL, NULL};
+ struct VertStep *vs, *vs_next;
+ BLI_assert(ABS(dir) == 1);
+
+ for (vs = lb->first; vs; vs = vs_next) {
+ BMIter iter;
+ BMEdge *e;
+ /* these values will be the same every iteration */
+ const int vs_iter_tot = BM_elem_index_get(vs->v);
+ const int vs_iter_next = vs_iter_tot + dir;
+
+ vs_next = vs->next;
+
+ BM_ITER_ELEM (e, &iter, vs->v, BM_EDGES_OF_VERT) {
+ if (BM_elem_flag_test(e, BM_ELEM_INTERNAL_TAG)) {
+ BMVert *v_next = BM_edge_other_vert(e, vs->v);
+ const int v_next_index = BM_elem_index_get(v_next);
+ /* not essential to clear flag but prevents more checking next time round */
+ BM_elem_flag_disable(e, BM_ELEM_INTERNAL_TAG);
+ if (v_next_index == 0) {
+ vs_add(vs_pool, &lb_tmp, v_next, e, vs_iter_next);
+ }
+ else if ((dir < 0) == (v_next_index < 0)) {
+ /* on the same side - do nothing */
+ }
+ else {
+ /* we have met out match! (vertices from different sides meet) */
+ if (dir == 1) {
+ v_match[0] = vs->v;
+ v_match[1] = v_next;
+ }
+ else {
+ v_match[0] = v_next;
+ v_match[1] = vs->v;
+ }
+ /* normally we would manage memory of remaining items in (lb, lb_tmp),
+ * but search is done, vs_pool will get destroyed immediately */
+ return true;
+ }
+ }
+ }
+
+ BLI_mempool_free(vs_pool, vs);
+ }
+ /* bm->elem_index_dirty |= BM_VERT; */ /* Commented because used in a loop, and this flag has already been set. */
+
+ /* lb is now full of free'd items, overwrite */
+ *lb = lb_tmp;
+
+ return (BLI_listbase_is_empty(lb) == false);
}
-bool BM_mesh_edgeloops_find_path(
- BMesh *bm, ListBase *r_eloops,
- bool (*test_fn)(BMEdge *, void *user_data), void *user_data,
- BMVert *v_src, BMVert *v_dst)
+bool BM_mesh_edgeloops_find_path(BMesh *bm,
+ ListBase *r_eloops,
+ bool (*test_fn)(BMEdge *, void *user_data),
+ void *user_data,
+ BMVert *v_src,
+ BMVert *v_dst)
{
- BMIter iter;
- BMEdge *e;
- bool found = false;
-
- BLI_assert(v_src != v_dst);
-
- {
- BMVert *v;
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- BM_elem_index_set(v, 0);
- BM_elem_flag_disable(v, BM_ELEM_INTERNAL_TAG);
- }
- }
- bm->elem_index_dirty |= BM_VERT;
-
- /* first flush edges to tags, and tag verts */
- int edges_len;
- BMEdge **edges;
-
- if (test_fn) {
- BLI_Stack *edge_stack = BLI_stack_new(sizeof(BMEdge *), __func__);
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (test_fn(e, user_data)) {
- BM_elem_flag_enable(e, BM_ELEM_INTERNAL_TAG);
- BM_elem_flag_enable(e->v1, BM_ELEM_INTERNAL_TAG);
- BM_elem_flag_enable(e->v2, BM_ELEM_INTERNAL_TAG);
- BLI_stack_push(edge_stack, (void *)&e);
- }
- else {
- BM_elem_flag_disable(e, BM_ELEM_INTERNAL_TAG);
- }
- }
- edges_len = BLI_stack_count(edge_stack);
- edges = MEM_mallocN(sizeof(*edges) * edges_len, __func__);
- BLI_stack_pop_n_reverse(edge_stack, edges, BLI_stack_count(edge_stack));
- BLI_stack_free(edge_stack);
- }
- else {
- int i = 0;
- edges_len = bm->totedge;
- edges = MEM_mallocN(sizeof(*edges) * edges_len, __func__);
-
- BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
- BM_elem_flag_enable(e, BM_ELEM_INTERNAL_TAG);
- BM_elem_flag_enable(e->v1, BM_ELEM_INTERNAL_TAG);
- BM_elem_flag_enable(e->v2, BM_ELEM_INTERNAL_TAG);
- edges[i] = e;
- }
- }
-
- /* prime the lists and begin search */
- {
- BMVert *v_match[2] = {NULL, NULL};
- ListBase lb_src = {NULL, NULL};
- ListBase lb_dst = {NULL, NULL};
- BLI_mempool *vs_pool = BLI_mempool_create(sizeof(struct VertStep), 0, 512, BLI_MEMPOOL_NOP);
-
- /* edge args are dummy */
- vs_add(vs_pool, &lb_src, v_src, v_src->e, 1);
- vs_add(vs_pool, &lb_dst, v_dst, v_dst->e, -1);
- bm->elem_index_dirty |= BM_VERT;
-
- do {
- if ((bm_loop_path_build_step(vs_pool, &lb_src, 1, v_match) == false) || v_match[0]) {
- break;
- }
- if ((bm_loop_path_build_step(vs_pool, &lb_dst, -1, v_match) == false) || v_match[0]) {
- break;
- }
- } while (true);
-
- BLI_mempool_destroy(vs_pool);
-
- if (v_match[0]) {
- BMEdgeLoopStore *el_store = MEM_callocN(sizeof(BMEdgeLoopStore), __func__);
- BMVert *v;
-
- /* build loop from edge pointers */
- v = v_match[0];
- while (true) {
- LinkData *node = MEM_callocN(sizeof(*node), __func__);
- node->data = v;
- BLI_addhead(&el_store->verts, node);
- el_store->len++;
- if (v == v_src) {
- break;
- }
- v = BM_edge_other_vert(v->e, v);
- }
-
- v = v_match[1];
- while (true) {
- LinkData *node = MEM_callocN(sizeof(*node), __func__);
- node->data = v;
- BLI_addtail(&el_store->verts, node);
- el_store->len++;
- if (v == v_dst) {
- break;
- }
- v = BM_edge_other_vert(v->e, v);
- }
-
-
- BLI_addtail(r_eloops, el_store);
-
- found = true;
- }
- }
-
- for (uint i = 0; i < edges_len; i += 1) {
- e = edges[i];
- BM_elem_flag_disable(e, BM_ELEM_INTERNAL_TAG);
- BM_elem_flag_disable(e->v1, BM_ELEM_INTERNAL_TAG);
- BM_elem_flag_disable(e->v2, BM_ELEM_INTERNAL_TAG);
- }
- MEM_freeN(edges);
-
- return found;
+ BMIter iter;
+ BMEdge *e;
+ bool found = false;
+
+ BLI_assert(v_src != v_dst);
+
+ {
+ BMVert *v;
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_elem_index_set(v, 0);
+ BM_elem_flag_disable(v, BM_ELEM_INTERNAL_TAG);
+ }
+ }
+ bm->elem_index_dirty |= BM_VERT;
+
+ /* first flush edges to tags, and tag verts */
+ int edges_len;
+ BMEdge **edges;
+
+ if (test_fn) {
+ BLI_Stack *edge_stack = BLI_stack_new(sizeof(BMEdge *), __func__);
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (test_fn(e, user_data)) {
+ BM_elem_flag_enable(e, BM_ELEM_INTERNAL_TAG);
+ BM_elem_flag_enable(e->v1, BM_ELEM_INTERNAL_TAG);
+ BM_elem_flag_enable(e->v2, BM_ELEM_INTERNAL_TAG);
+ BLI_stack_push(edge_stack, (void *)&e);
+ }
+ else {
+ BM_elem_flag_disable(e, BM_ELEM_INTERNAL_TAG);
+ }
+ }
+ edges_len = BLI_stack_count(edge_stack);
+ edges = MEM_mallocN(sizeof(*edges) * edges_len, __func__);
+ BLI_stack_pop_n_reverse(edge_stack, edges, BLI_stack_count(edge_stack));
+ BLI_stack_free(edge_stack);
+ }
+ else {
+ int i = 0;
+ edges_len = bm->totedge;
+ edges = MEM_mallocN(sizeof(*edges) * edges_len, __func__);
+
+ BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
+ BM_elem_flag_enable(e, BM_ELEM_INTERNAL_TAG);
+ BM_elem_flag_enable(e->v1, BM_ELEM_INTERNAL_TAG);
+ BM_elem_flag_enable(e->v2, BM_ELEM_INTERNAL_TAG);
+ edges[i] = e;
+ }
+ }
+
+ /* prime the lists and begin search */
+ {
+ BMVert *v_match[2] = {NULL, NULL};
+ ListBase lb_src = {NULL, NULL};
+ ListBase lb_dst = {NULL, NULL};
+ BLI_mempool *vs_pool = BLI_mempool_create(sizeof(struct VertStep), 0, 512, BLI_MEMPOOL_NOP);
+
+ /* edge args are dummy */
+ vs_add(vs_pool, &lb_src, v_src, v_src->e, 1);
+ vs_add(vs_pool, &lb_dst, v_dst, v_dst->e, -1);
+ bm->elem_index_dirty |= BM_VERT;
+
+ do {
+ if ((bm_loop_path_build_step(vs_pool, &lb_src, 1, v_match) == false) || v_match[0]) {
+ break;
+ }
+ if ((bm_loop_path_build_step(vs_pool, &lb_dst, -1, v_match) == false) || v_match[0]) {
+ break;
+ }
+ } while (true);
+
+ BLI_mempool_destroy(vs_pool);
+
+ if (v_match[0]) {
+ BMEdgeLoopStore *el_store = MEM_callocN(sizeof(BMEdgeLoopStore), __func__);
+ BMVert *v;
+
+ /* build loop from edge pointers */
+ v = v_match[0];
+ while (true) {
+ LinkData *node = MEM_callocN(sizeof(*node), __func__);
+ node->data = v;
+ BLI_addhead(&el_store->verts, node);
+ el_store->len++;
+ if (v == v_src) {
+ break;
+ }
+ v = BM_edge_other_vert(v->e, v);
+ }
+
+ v = v_match[1];
+ while (true) {
+ LinkData *node = MEM_callocN(sizeof(*node), __func__);
+ node->data = v;
+ BLI_addtail(&el_store->verts, node);
+ el_store->len++;
+ if (v == v_dst) {
+ break;
+ }
+ v = BM_edge_other_vert(v->e, v);
+ }
+
+ BLI_addtail(r_eloops, el_store);
+
+ found = true;
+ }
+ }
+
+ for (uint i = 0; i < edges_len; i += 1) {
+ e = edges[i];
+ BM_elem_flag_disable(e, BM_ELEM_INTERNAL_TAG);
+ BM_elem_flag_disable(e->v1, BM_ELEM_INTERNAL_TAG);
+ BM_elem_flag_disable(e->v2, BM_ELEM_INTERNAL_TAG);
+ }
+ MEM_freeN(edges);
+
+ return found;
}
-
/* -------------------------------------------------------------------- */
/* BM_mesh_edgeloops_xxx utility function */
void BM_mesh_edgeloops_free(ListBase *eloops)
{
- BMEdgeLoopStore *el_store;
- while ((el_store = BLI_pophead(eloops))) {
- BM_edgeloop_free(el_store);
- }
+ BMEdgeLoopStore *el_store;
+ while ((el_store = BLI_pophead(eloops))) {
+ BM_edgeloop_free(el_store);
+ }
}
void BM_mesh_edgeloops_calc_center(BMesh *bm, ListBase *eloops)
{
- BMEdgeLoopStore *el_store;
- for (el_store = eloops->first; el_store; el_store = el_store->next) {
- BM_edgeloop_calc_center(bm, el_store);
- }
+ BMEdgeLoopStore *el_store;
+ for (el_store = eloops->first; el_store; el_store = el_store->next) {
+ BM_edgeloop_calc_center(bm, el_store);
+ }
}
void BM_mesh_edgeloops_calc_normal(BMesh *bm, ListBase *eloops)
{
- BMEdgeLoopStore *el_store;
- for (el_store = eloops->first; el_store; el_store = el_store->next) {
- BM_edgeloop_calc_normal(bm, el_store);
- }
+ BMEdgeLoopStore *el_store;
+ for (el_store = eloops->first; el_store; el_store = el_store->next) {
+ BM_edgeloop_calc_normal(bm, el_store);
+ }
}
void BM_mesh_edgeloops_calc_normal_aligned(BMesh *bm, ListBase *eloops, const float no_align[3])
{
- BMEdgeLoopStore *el_store;
- for (el_store = eloops->first; el_store; el_store = el_store->next) {
- BM_edgeloop_calc_normal_aligned(bm, el_store, no_align);
- }
+ BMEdgeLoopStore *el_store;
+ for (el_store = eloops->first; el_store; el_store = el_store->next) {
+ BM_edgeloop_calc_normal_aligned(bm, el_store, no_align);
+ }
}
void BM_mesh_edgeloops_calc_order(BMesh *UNUSED(bm), ListBase *eloops, const bool use_normals)
{
- ListBase eloops_ordered = {NULL};
- BMEdgeLoopStore *el_store;
- float cent[3];
- int tot = 0;
- zero_v3(cent);
- /* assumes we calculated centers already */
- for (el_store = eloops->first; el_store; el_store = el_store->next, tot++) {
- add_v3_v3(cent, el_store->co);
- }
- mul_v3_fl(cent, 1.0f / (float)tot);
-
- /* find far outest loop */
- {
- BMEdgeLoopStore *el_store_best = NULL;
- float len_best_sq = -1.0f;
- for (el_store = eloops->first; el_store; el_store = el_store->next) {
- const float len_sq = len_squared_v3v3(cent, el_store->co);
- if (len_sq > len_best_sq) {
- len_best_sq = len_sq;
- el_store_best = el_store;
- }
- }
-
- BLI_remlink(eloops, el_store_best);
- BLI_addtail(&eloops_ordered, el_store_best);
- }
-
- /* not so efficient re-ordering */
- while (eloops->first) {
- BMEdgeLoopStore *el_store_best = NULL;
- const float *co = ((BMEdgeLoopStore *)eloops_ordered.last)->co;
- const float *no = ((BMEdgeLoopStore *)eloops_ordered.last)->no;
- float len_best_sq = FLT_MAX;
-
- if (use_normals) {
- BLI_ASSERT_UNIT_V3(no);
- }
-
- for (el_store = eloops->first; el_store; el_store = el_store->next) {
- float len_sq;
- if (use_normals) {
- /* scale the length by how close the loops are to pointing at eachother */
- float dir[3];
- sub_v3_v3v3(dir, co, el_store->co);
- len_sq = normalize_v3(dir);
- len_sq = len_sq * ((1.0f - fabsf(dot_v3v3(dir, no))) +
- (1.0f - fabsf(dot_v3v3(dir, el_store->no))));
- }
- else {
- len_sq = len_squared_v3v3(co, el_store->co);
- }
-
- if (len_sq < len_best_sq) {
- len_best_sq = len_sq;
- el_store_best = el_store;
- }
- }
-
- BLI_remlink(eloops, el_store_best);
- BLI_addtail(&eloops_ordered, el_store_best);
- }
-
- *eloops = eloops_ordered;
+ ListBase eloops_ordered = {NULL};
+ BMEdgeLoopStore *el_store;
+ float cent[3];
+ int tot = 0;
+ zero_v3(cent);
+ /* assumes we calculated centers already */
+ for (el_store = eloops->first; el_store; el_store = el_store->next, tot++) {
+ add_v3_v3(cent, el_store->co);
+ }
+ mul_v3_fl(cent, 1.0f / (float)tot);
+
+ /* find far outest loop */
+ {
+ BMEdgeLoopStore *el_store_best = NULL;
+ float len_best_sq = -1.0f;
+ for (el_store = eloops->first; el_store; el_store = el_store->next) {
+ const float len_sq = len_squared_v3v3(cent, el_store->co);
+ if (len_sq > len_best_sq) {
+ len_best_sq = len_sq;
+ el_store_best = el_store;
+ }
+ }
+
+ BLI_remlink(eloops, el_store_best);
+ BLI_addtail(&eloops_ordered, el_store_best);
+ }
+
+ /* not so efficient re-ordering */
+ while (eloops->first) {
+ BMEdgeLoopStore *el_store_best = NULL;
+ const float *co = ((BMEdgeLoopStore *)eloops_ordered.last)->co;
+ const float *no = ((BMEdgeLoopStore *)eloops_ordered.last)->no;
+ float len_best_sq = FLT_MAX;
+
+ if (use_normals) {
+ BLI_ASSERT_UNIT_V3(no);
+ }
+
+ for (el_store = eloops->first; el_store; el_store = el_store->next) {
+ float len_sq;
+ if (use_normals) {
+ /* scale the length by how close the loops are to pointing at eachother */
+ float dir[3];
+ sub_v3_v3v3(dir, co, el_store->co);
+ len_sq = normalize_v3(dir);
+ len_sq = len_sq *
+ ((1.0f - fabsf(dot_v3v3(dir, no))) + (1.0f - fabsf(dot_v3v3(dir, el_store->no))));
+ }
+ else {
+ len_sq = len_squared_v3v3(co, el_store->co);
+ }
+
+ if (len_sq < len_best_sq) {
+ len_best_sq = len_sq;
+ el_store_best = el_store;
+ }
+ }
+
+ BLI_remlink(eloops, el_store_best);
+ BLI_addtail(&eloops_ordered, el_store_best);
+ }
+
+ *eloops = eloops_ordered;
}
/* -------------------------------------------------------------------- */
@@ -508,60 +506,60 @@ void BM_mesh_edgeloops_calc_order(BMesh *UNUSED(bm), ListBase *eloops, const boo
/* return new edgeloops */
BMEdgeLoopStore *BM_edgeloop_copy(BMEdgeLoopStore *el_store)
{
- BMEdgeLoopStore *el_store_copy = MEM_mallocN(sizeof(*el_store), __func__);
- *el_store_copy = *el_store;
- BLI_duplicatelist(&el_store_copy->verts, &el_store->verts);
- return el_store_copy;
+ BMEdgeLoopStore *el_store_copy = MEM_mallocN(sizeof(*el_store), __func__);
+ *el_store_copy = *el_store;
+ BLI_duplicatelist(&el_store_copy->verts, &el_store->verts);
+ return el_store_copy;
}
BMEdgeLoopStore *BM_edgeloop_from_verts(BMVert **v_arr, const int v_arr_tot, bool is_closed)
{
- BMEdgeLoopStore *el_store = MEM_callocN(sizeof(*el_store), __func__);
- int i;
- for (i = 0; i < v_arr_tot; i++) {
- LinkData *node = MEM_callocN(sizeof(*node), __func__);
- node->data = v_arr[i];
- BLI_addtail(&el_store->verts, node);
- }
- el_store->len = v_arr_tot;
- if (is_closed) {
- el_store->flag |= BM_EDGELOOP_IS_CLOSED;
- }
- return el_store;
+ BMEdgeLoopStore *el_store = MEM_callocN(sizeof(*el_store), __func__);
+ int i;
+ for (i = 0; i < v_arr_tot; i++) {
+ LinkData *node = MEM_callocN(sizeof(*node), __func__);
+ node->data = v_arr[i];
+ BLI_addtail(&el_store->verts, node);
+ }
+ el_store->len = v_arr_tot;
+ if (is_closed) {
+ el_store->flag |= BM_EDGELOOP_IS_CLOSED;
+ }
+ return el_store;
}
void BM_edgeloop_free(BMEdgeLoopStore *el_store)
{
- BLI_freelistN(&el_store->verts);
- MEM_freeN(el_store);
+ BLI_freelistN(&el_store->verts);
+ MEM_freeN(el_store);
}
bool BM_edgeloop_is_closed(BMEdgeLoopStore *el_store)
{
- return (el_store->flag & BM_EDGELOOP_IS_CLOSED) != 0;
+ return (el_store->flag & BM_EDGELOOP_IS_CLOSED) != 0;
}
ListBase *BM_edgeloop_verts_get(BMEdgeLoopStore *el_store)
{
- return &el_store->verts;
+ return &el_store->verts;
}
int BM_edgeloop_length_get(BMEdgeLoopStore *el_store)
{
- return el_store->len;
+ return el_store->len;
}
const float *BM_edgeloop_normal_get(struct BMEdgeLoopStore *el_store)
{
- return el_store->no;
+ return el_store->no;
}
const float *BM_edgeloop_center_get(struct BMEdgeLoopStore *el_store)
{
- return el_store->co;
+ return el_store->co;
}
-#define NODE_AS_V(n) ((BMVert *)((LinkData *)n)->data)
+#define NODE_AS_V(n) ((BMVert *)((LinkData *)n)->data)
#define NODE_AS_CO(n) ((BMVert *)((LinkData *)n)->data)->co
/**
@@ -569,92 +567,89 @@ const float *BM_edgeloop_center_get(struct BMEdgeLoopStore *el_store)
*/
void BM_edgeloop_edges_get(struct BMEdgeLoopStore *el_store, BMEdge **e_arr)
{
- LinkData *node;
- int i = 0;
- for (node = el_store->verts.first; node && node->next; node = node->next) {
- e_arr[i++] = BM_edge_exists(NODE_AS_V(node), NODE_AS_V(node->next));
- BLI_assert(e_arr[i - 1] != NULL);
- }
-
- if (el_store->flag & BM_EDGELOOP_IS_CLOSED) {
- e_arr[i] = BM_edge_exists(NODE_AS_V(el_store->verts.first), NODE_AS_V(el_store->verts.last));
- BLI_assert(e_arr[i] != NULL);
- }
- BLI_assert(el_store->len == i + 1);
+ LinkData *node;
+ int i = 0;
+ for (node = el_store->verts.first; node && node->next; node = node->next) {
+ e_arr[i++] = BM_edge_exists(NODE_AS_V(node), NODE_AS_V(node->next));
+ BLI_assert(e_arr[i - 1] != NULL);
+ }
+
+ if (el_store->flag & BM_EDGELOOP_IS_CLOSED) {
+ e_arr[i] = BM_edge_exists(NODE_AS_V(el_store->verts.first), NODE_AS_V(el_store->verts.last));
+ BLI_assert(e_arr[i] != NULL);
+ }
+ BLI_assert(el_store->len == i + 1);
}
void BM_edgeloop_calc_center(BMesh *UNUSED(bm), BMEdgeLoopStore *el_store)
{
- LinkData *node_curr = el_store->verts.last;
- LinkData *node_prev = ((LinkData *)el_store->verts.last)->prev;
- LinkData *node_first = el_store->verts.first;
- LinkData *node_next = node_first;
-
- const float *v_prev = NODE_AS_CO(node_prev);
- const float *v_curr = NODE_AS_CO(node_curr);
- const float *v_next = NODE_AS_CO(node_next);
-
- float totw = 0.0f;
- float w_prev;
-
- zero_v3(el_store->co);
-
- w_prev = len_v3v3(v_prev, v_curr);
- do {
- const float w_curr = len_v3v3(v_curr, v_next);
- const float w = (w_curr + w_prev);
- madd_v3_v3fl(el_store->co, v_curr, w);
- totw += w;
- w_prev = w_curr;
-
-
- node_prev = node_curr;
- node_curr = node_next;
- node_next = node_next->next;
-
- if (node_next == NULL) {
- break;
- }
- v_prev = v_curr;
- v_curr = v_next;
- v_next = NODE_AS_CO(node_next);
- } while (1);
-
- if (totw != 0.0f) {
- mul_v3_fl(el_store->co, 1.0f / (float) totw);
- }
-
+ LinkData *node_curr = el_store->verts.last;
+ LinkData *node_prev = ((LinkData *)el_store->verts.last)->prev;
+ LinkData *node_first = el_store->verts.first;
+ LinkData *node_next = node_first;
+
+ const float *v_prev = NODE_AS_CO(node_prev);
+ const float *v_curr = NODE_AS_CO(node_curr);
+ const float *v_next = NODE_AS_CO(node_next);
+
+ float totw = 0.0f;
+ float w_prev;
+
+ zero_v3(el_store->co);
+
+ w_prev = len_v3v3(v_prev, v_curr);
+ do {
+ const float w_curr = len_v3v3(v_curr, v_next);
+ const float w = (w_curr + w_prev);
+ madd_v3_v3fl(el_store->co, v_curr, w);
+ totw += w;
+ w_prev = w_curr;
+
+ node_prev = node_curr;
+ node_curr = node_next;
+ node_next = node_next->next;
+
+ if (node_next == NULL) {
+ break;
+ }
+ v_prev = v_curr;
+ v_curr = v_next;
+ v_next = NODE_AS_CO(node_next);
+ } while (1);
+
+ if (totw != 0.0f) {
+ mul_v3_fl(el_store->co, 1.0f / (float)totw);
+ }
}
bool BM_edgeloop_calc_normal(BMesh *UNUSED(bm), BMEdgeLoopStore *el_store)
{
- LinkData *node_curr = el_store->verts.first;
- const float *v_prev = NODE_AS_CO(el_store->verts.last);
- const float *v_curr = NODE_AS_CO(node_curr);
-
- zero_v3(el_store->no);
-
- /* Newell's Method */
- do {
- add_newell_cross_v3_v3v3(el_store->no, v_prev, v_curr);
-
- if ((node_curr = node_curr->next)) {
- v_prev = v_curr;
- v_curr = NODE_AS_CO(node_curr);
- }
- else {
- break;
- }
- } while (true);
-
- if (UNLIKELY(normalize_v3(el_store->no) < EDGELOOP_EPS)) {
- el_store->no[2] = 1.0f; /* other axis set to 0.0 */
- return false;
-
- }
- else {
- return true;
- }
+ LinkData *node_curr = el_store->verts.first;
+ const float *v_prev = NODE_AS_CO(el_store->verts.last);
+ const float *v_curr = NODE_AS_CO(node_curr);
+
+ zero_v3(el_store->no);
+
+ /* Newell's Method */
+ do {
+ add_newell_cross_v3_v3v3(el_store->no, v_prev, v_curr);
+
+ if ((node_curr = node_curr->next)) {
+ v_prev = v_curr;
+ v_curr = NODE_AS_CO(node_curr);
+ }
+ else {
+ break;
+ }
+ } while (true);
+
+ if (UNLIKELY(normalize_v3(el_store->no) < EDGELOOP_EPS)) {
+ el_store->no[2] = 1.0f; /* other axis set to 0.0 */
+ return false;
+ }
+ else {
+ return true;
+ }
}
/**
@@ -663,159 +658,164 @@ bool BM_edgeloop_calc_normal(BMesh *UNUSED(bm), BMEdgeLoopStore *el_store)
*
* Instead use an alignment vector and calculate the normal based on that.
*/
-bool BM_edgeloop_calc_normal_aligned(BMesh *UNUSED(bm), BMEdgeLoopStore *el_store, const float no_align[3])
+bool BM_edgeloop_calc_normal_aligned(BMesh *UNUSED(bm),
+ BMEdgeLoopStore *el_store,
+ const float no_align[3])
{
- LinkData *node_curr = el_store->verts.first;
- const float *v_prev = NODE_AS_CO(el_store->verts.last);
- const float *v_curr = NODE_AS_CO(node_curr);
-
- zero_v3(el_store->no);
-
- /* Own Method */
- do {
- float cross[3], no[3], dir[3];
- sub_v3_v3v3(dir, v_curr, v_prev);
- cross_v3_v3v3(cross, no_align, dir);
- cross_v3_v3v3(no, dir, cross);
- add_v3_v3(el_store->no, no);
-
- if ((node_curr = node_curr->next)) {
- v_prev = v_curr;
- v_curr = NODE_AS_CO(node_curr);
- }
- else {
- break;
- }
- } while (true);
-
- if (UNLIKELY(normalize_v3(el_store->no) < EDGELOOP_EPS)) {
- el_store->no[2] = 1.0f; /* other axis set to 0.0 */
- return false;
- }
- else {
- return true;
- }
+ LinkData *node_curr = el_store->verts.first;
+ const float *v_prev = NODE_AS_CO(el_store->verts.last);
+ const float *v_curr = NODE_AS_CO(node_curr);
+
+ zero_v3(el_store->no);
+
+ /* Own Method */
+ do {
+ float cross[3], no[3], dir[3];
+ sub_v3_v3v3(dir, v_curr, v_prev);
+ cross_v3_v3v3(cross, no_align, dir);
+ cross_v3_v3v3(no, dir, cross);
+ add_v3_v3(el_store->no, no);
+
+ if ((node_curr = node_curr->next)) {
+ v_prev = v_curr;
+ v_curr = NODE_AS_CO(node_curr);
+ }
+ else {
+ break;
+ }
+ } while (true);
+
+ if (UNLIKELY(normalize_v3(el_store->no) < EDGELOOP_EPS)) {
+ el_store->no[2] = 1.0f; /* other axis set to 0.0 */
+ return false;
+ }
+ else {
+ return true;
+ }
}
-
-
void BM_edgeloop_flip(BMesh *UNUSED(bm), BMEdgeLoopStore *el_store)
{
- negate_v3(el_store->no);
- BLI_listbase_reverse(&el_store->verts);
+ negate_v3(el_store->no);
+ BLI_listbase_reverse(&el_store->verts);
}
void BM_edgeloop_expand(
- BMesh *bm, BMEdgeLoopStore *el_store, int el_store_len,
- bool split, GSet *split_edges)
+ BMesh *bm, BMEdgeLoopStore *el_store, int el_store_len, bool split, GSet *split_edges)
{
- bool split_swap = true;
-
-#define EDGE_SPLIT(node_copy, node_other) { \
- BMVert *v_split, *v_other = (node_other)->data; \
- BMEdge *e_split, *e_other = BM_edge_exists((node_copy)->data, v_other); \
- v_split = BM_edge_split(bm, e_other, split_swap ? (node_copy)->data : v_other, &e_split, 0.0f); \
- v_split->e = e_split; \
- BLI_assert(v_split == e_split->v2); \
- BLI_gset_insert(split_edges, e_split); \
- (node_copy)->data = v_split; \
- } ((void)0)
-
- /* first double until we are more than half as big */
- while ((el_store->len * 2) < el_store_len) {
- LinkData *node_curr = el_store->verts.first;
- while (node_curr) {
- LinkData *node_curr_copy = MEM_dupallocN(node_curr);
- if (split == false) {
- BLI_insertlinkafter(&el_store->verts, node_curr, node_curr_copy);
- node_curr = node_curr_copy->next;
- }
- else {
- if (node_curr->next || (el_store->flag & BM_EDGELOOP_IS_CLOSED)) {
- EDGE_SPLIT(node_curr_copy, node_curr->next ? node_curr->next : (LinkData *)el_store->verts.first);
- BLI_insertlinkafter(&el_store->verts, node_curr, node_curr_copy);
- node_curr = node_curr_copy->next;
- }
- else {
- EDGE_SPLIT(node_curr_copy, node_curr->prev);
- BLI_insertlinkbefore(&el_store->verts, node_curr, node_curr_copy);
- node_curr = node_curr->next;
- }
- split_swap = !split_swap;
- }
- el_store->len++;
- }
- split_swap = !split_swap;
- }
-
- if (el_store->len < el_store_len) {
- LinkData *node_curr = el_store->verts.first;
-
- int iter_prev = 0;
- BLI_FOREACH_SPARSE_RANGE(el_store->len, (el_store_len - el_store->len), iter) {
- while (iter_prev < iter) {
- node_curr = node_curr->next;
- iter_prev += 1;
- }
-
- LinkData *node_curr_copy;
- node_curr_copy = MEM_dupallocN(node_curr);
- if (split == false) {
- BLI_insertlinkafter(&el_store->verts, node_curr, node_curr_copy);
- node_curr = node_curr_copy->next;
- }
- else {
- if (node_curr->next || (el_store->flag & BM_EDGELOOP_IS_CLOSED)) {
- EDGE_SPLIT(node_curr_copy,
- node_curr->next ? node_curr->next : (LinkData *)el_store->verts.first);
- BLI_insertlinkafter(&el_store->verts, node_curr, node_curr_copy);
- node_curr = node_curr_copy->next;
- }
- else {
- EDGE_SPLIT(node_curr_copy, node_curr->prev);
- BLI_insertlinkbefore(&el_store->verts, node_curr, node_curr_copy);
- node_curr = node_curr->next;
- }
- split_swap = !split_swap;
- }
- el_store->len++;
- iter_prev += 1;
- }
- }
+ bool split_swap = true;
+
+#define EDGE_SPLIT(node_copy, node_other) \
+ { \
+ BMVert *v_split, *v_other = (node_other)->data; \
+ BMEdge *e_split, *e_other = BM_edge_exists((node_copy)->data, v_other); \
+ v_split = BM_edge_split( \
+ bm, e_other, split_swap ? (node_copy)->data : v_other, &e_split, 0.0f); \
+ v_split->e = e_split; \
+ BLI_assert(v_split == e_split->v2); \
+ BLI_gset_insert(split_edges, e_split); \
+ (node_copy)->data = v_split; \
+ } \
+ ((void)0)
+
+ /* first double until we are more than half as big */
+ while ((el_store->len * 2) < el_store_len) {
+ LinkData *node_curr = el_store->verts.first;
+ while (node_curr) {
+ LinkData *node_curr_copy = MEM_dupallocN(node_curr);
+ if (split == false) {
+ BLI_insertlinkafter(&el_store->verts, node_curr, node_curr_copy);
+ node_curr = node_curr_copy->next;
+ }
+ else {
+ if (node_curr->next || (el_store->flag & BM_EDGELOOP_IS_CLOSED)) {
+ EDGE_SPLIT(node_curr_copy,
+ node_curr->next ? node_curr->next : (LinkData *)el_store->verts.first);
+ BLI_insertlinkafter(&el_store->verts, node_curr, node_curr_copy);
+ node_curr = node_curr_copy->next;
+ }
+ else {
+ EDGE_SPLIT(node_curr_copy, node_curr->prev);
+ BLI_insertlinkbefore(&el_store->verts, node_curr, node_curr_copy);
+ node_curr = node_curr->next;
+ }
+ split_swap = !split_swap;
+ }
+ el_store->len++;
+ }
+ split_swap = !split_swap;
+ }
+
+ if (el_store->len < el_store_len) {
+ LinkData *node_curr = el_store->verts.first;
+
+ int iter_prev = 0;
+ BLI_FOREACH_SPARSE_RANGE(el_store->len, (el_store_len - el_store->len), iter)
+ {
+ while (iter_prev < iter) {
+ node_curr = node_curr->next;
+ iter_prev += 1;
+ }
+
+ LinkData *node_curr_copy;
+ node_curr_copy = MEM_dupallocN(node_curr);
+ if (split == false) {
+ BLI_insertlinkafter(&el_store->verts, node_curr, node_curr_copy);
+ node_curr = node_curr_copy->next;
+ }
+ else {
+ if (node_curr->next || (el_store->flag & BM_EDGELOOP_IS_CLOSED)) {
+ EDGE_SPLIT(node_curr_copy,
+ node_curr->next ? node_curr->next : (LinkData *)el_store->verts.first);
+ BLI_insertlinkafter(&el_store->verts, node_curr, node_curr_copy);
+ node_curr = node_curr_copy->next;
+ }
+ else {
+ EDGE_SPLIT(node_curr_copy, node_curr->prev);
+ BLI_insertlinkbefore(&el_store->verts, node_curr, node_curr_copy);
+ node_curr = node_curr->next;
+ }
+ split_swap = !split_swap;
+ }
+ el_store->len++;
+ iter_prev += 1;
+ }
+ }
#undef BKE_FOREACH_SUBSET_OF_RANGE
#undef EDGE_SPLIT
- BLI_assert(el_store->len == el_store_len);
+ BLI_assert(el_store->len == el_store_len);
}
-bool BM_edgeloop_overlap_check(struct BMEdgeLoopStore *el_store_a, struct BMEdgeLoopStore *el_store_b)
+bool BM_edgeloop_overlap_check(struct BMEdgeLoopStore *el_store_a,
+ struct BMEdgeLoopStore *el_store_b)
{
- LinkData *node;
-
- /* A little more efficient if 'a' as smaller. */
- if (el_store_a->len > el_store_b->len) {
- SWAP(BMEdgeLoopStore *, el_store_a, el_store_b);
- }
-
- /* init */
- for (node = el_store_a->verts.first; node; node = node->next) {
- BM_elem_flag_enable((BMVert *)node->data, BM_ELEM_INTERNAL_TAG);
- }
- for (node = el_store_b->verts.first; node; node = node->next) {
- BM_elem_flag_disable((BMVert *)node->data, BM_ELEM_INTERNAL_TAG);
- }
-
- /* Check 'a' (clear as we go). */
- for (node = el_store_a->verts.first; node; node = node->next) {
- if (!BM_elem_flag_test((BMVert *)node->data, BM_ELEM_INTERNAL_TAG)) {
- /* Finish clearing 'a', leave tag clean. */
- while ((node = node->next)) {
- BM_elem_flag_disable((BMVert *)node->data, BM_ELEM_INTERNAL_TAG);
- }
- return true;
- }
- BM_elem_flag_disable((BMVert *)node->data, BM_ELEM_INTERNAL_TAG);
- }
- return false;
+ LinkData *node;
+
+ /* A little more efficient if 'a' as smaller. */
+ if (el_store_a->len > el_store_b->len) {
+ SWAP(BMEdgeLoopStore *, el_store_a, el_store_b);
+ }
+
+ /* init */
+ for (node = el_store_a->verts.first; node; node = node->next) {
+ BM_elem_flag_enable((BMVert *)node->data, BM_ELEM_INTERNAL_TAG);
+ }
+ for (node = el_store_b->verts.first; node; node = node->next) {
+ BM_elem_flag_disable((BMVert *)node->data, BM_ELEM_INTERNAL_TAG);
+ }
+
+ /* Check 'a' (clear as we go). */
+ for (node = el_store_a->verts.first; node; node = node->next) {
+ if (!BM_elem_flag_test((BMVert *)node->data, BM_ELEM_INTERNAL_TAG)) {
+ /* Finish clearing 'a', leave tag clean. */
+ while ((node = node->next)) {
+ BM_elem_flag_disable((BMVert *)node->data, BM_ELEM_INTERNAL_TAG);
+ }
+ return true;
+ }
+ BM_elem_flag_disable((BMVert *)node->data, BM_ELEM_INTERNAL_TAG);
+ }
+ return false;
}
diff --git a/source/blender/bmesh/intern/bmesh_edgeloop.h b/source/blender/bmesh/intern/bmesh_edgeloop.h
index e21a62bc25f..7701c680ae9 100644
--- a/source/blender/bmesh/intern/bmesh_edgeloop.h
+++ b/source/blender/bmesh/intern/bmesh_edgeloop.h
@@ -29,51 +29,60 @@ struct GSet;
struct ListBase;
/* multiple edgeloops (ListBase) */
-int BM_mesh_edgeloops_find(
- BMesh *bm, struct ListBase *r_lb,
- bool (*test_fn)(BMEdge *, void *user_data), void *user_data);
-bool BM_mesh_edgeloops_find_path(
- BMesh *bm, ListBase *r_eloops,
- bool (*test_fn)(BMEdge *, void *user_data), void *user_data,
- BMVert *v_src, BMVert *v_dst);
-
-void BM_mesh_edgeloops_free(struct ListBase *eloops);
-void BM_mesh_edgeloops_calc_center(BMesh *bm, struct ListBase *eloops);
-void BM_mesh_edgeloops_calc_normal(BMesh *bm, struct ListBase *eloops);
-void BM_mesh_edgeloops_calc_normal_aligned(
- BMesh *bm, struct ListBase *eloops,
- const float no_align[3]);
-void BM_mesh_edgeloops_calc_order(BMesh *UNUSED(bm), ListBase *eloops, const bool use_normals);
+int BM_mesh_edgeloops_find(BMesh *bm,
+ struct ListBase *r_lb,
+ bool (*test_fn)(BMEdge *, void *user_data),
+ void *user_data);
+bool BM_mesh_edgeloops_find_path(BMesh *bm,
+ ListBase *r_eloops,
+ bool (*test_fn)(BMEdge *, void *user_data),
+ void *user_data,
+ BMVert *v_src,
+ BMVert *v_dst);
+void BM_mesh_edgeloops_free(struct ListBase *eloops);
+void BM_mesh_edgeloops_calc_center(BMesh *bm, struct ListBase *eloops);
+void BM_mesh_edgeloops_calc_normal(BMesh *bm, struct ListBase *eloops);
+void BM_mesh_edgeloops_calc_normal_aligned(BMesh *bm,
+ struct ListBase *eloops,
+ const float no_align[3]);
+void BM_mesh_edgeloops_calc_order(BMesh *UNUSED(bm), ListBase *eloops, const bool use_normals);
/* single edgeloop */
struct BMEdgeLoopStore *BM_edgeloop_copy(struct BMEdgeLoopStore *el_store);
-struct BMEdgeLoopStore *BM_edgeloop_from_verts(BMVert **v_arr, const int v_arr_tot, bool is_closed);
+struct BMEdgeLoopStore *BM_edgeloop_from_verts(BMVert **v_arr,
+ const int v_arr_tot,
+ bool is_closed);
-void BM_edgeloop_free(struct BMEdgeLoopStore *el_store);
-bool BM_edgeloop_is_closed(struct BMEdgeLoopStore *el_store);
-int BM_edgeloop_length_get(struct BMEdgeLoopStore *el_store);
-struct ListBase *BM_edgeloop_verts_get(struct BMEdgeLoopStore *el_store);
-const float *BM_edgeloop_normal_get(struct BMEdgeLoopStore *el_store);
-const float *BM_edgeloop_center_get(struct BMEdgeLoopStore *el_store);
-void BM_edgeloop_edges_get(struct BMEdgeLoopStore *el_store, BMEdge **e_arr);
-void BM_edgeloop_calc_center(BMesh *bm, struct BMEdgeLoopStore *el_store);
-bool BM_edgeloop_calc_normal(BMesh *bm, struct BMEdgeLoopStore *el_store);
-bool BM_edgeloop_calc_normal_aligned(
- BMesh *bm, struct BMEdgeLoopStore *el_store,
- const float no_align[3]);
-void BM_edgeloop_flip(BMesh *bm, struct BMEdgeLoopStore *el_store);
-void BM_edgeloop_expand(
- BMesh *bm, struct BMEdgeLoopStore *el_store, int el_store_len,
- bool split, struct GSet *split_edges);
+void BM_edgeloop_free(struct BMEdgeLoopStore *el_store);
+bool BM_edgeloop_is_closed(struct BMEdgeLoopStore *el_store);
+int BM_edgeloop_length_get(struct BMEdgeLoopStore *el_store);
+struct ListBase *BM_edgeloop_verts_get(struct BMEdgeLoopStore *el_store);
+const float *BM_edgeloop_normal_get(struct BMEdgeLoopStore *el_store);
+const float *BM_edgeloop_center_get(struct BMEdgeLoopStore *el_store);
+void BM_edgeloop_edges_get(struct BMEdgeLoopStore *el_store, BMEdge **e_arr);
+void BM_edgeloop_calc_center(BMesh *bm, struct BMEdgeLoopStore *el_store);
+bool BM_edgeloop_calc_normal(BMesh *bm, struct BMEdgeLoopStore *el_store);
+bool BM_edgeloop_calc_normal_aligned(BMesh *bm,
+ struct BMEdgeLoopStore *el_store,
+ const float no_align[3]);
+void BM_edgeloop_flip(BMesh *bm, struct BMEdgeLoopStore *el_store);
+void BM_edgeloop_expand(BMesh *bm,
+ struct BMEdgeLoopStore *el_store,
+ int el_store_len,
+ bool split,
+ struct GSet *split_edges);
-bool BM_edgeloop_overlap_check(struct BMEdgeLoopStore *el_store_a, struct BMEdgeLoopStore *el_store_b);
+bool BM_edgeloop_overlap_check(struct BMEdgeLoopStore *el_store_a,
+ struct BMEdgeLoopStore *el_store_b);
#define BM_EDGELINK_NEXT(el_store, elink) \
- (elink)->next ? elink->next : (BM_edgeloop_is_closed(el_store) ? BM_edgeloop_verts_get(el_store)->first : NULL)
+ (elink)->next ? \
+ elink->next : \
+ (BM_edgeloop_is_closed(el_store) ? BM_edgeloop_verts_get(el_store)->first : NULL)
#define BM_EDGELOOP_NEXT(el_store) \
- (CHECK_TYPE_INLINE(el_store, struct BMEdgeLoopStore *), \
- (struct BMEdgeLoopStore *)((LinkData *)el_store)->next)
+ (CHECK_TYPE_INLINE(el_store, struct BMEdgeLoopStore *), \
+ (struct BMEdgeLoopStore *)((LinkData *)el_store)->next)
-#endif /* __BMESH_EDGELOOP_H__ */
+#endif /* __BMESH_EDGELOOP_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_error.h b/source/blender/bmesh/intern/bmesh_error.h
index 0035a43dc1e..b5235c64215 100644
--- a/source/blender/bmesh/intern/bmesh_error.h
+++ b/source/blender/bmesh/intern/bmesh_error.h
@@ -29,11 +29,11 @@ void BMO_error_raise(BMesh *bm, BMOperator *owner, int errcode, const char *msg)
/* gets the topmost error from the stack.
* returns error code or 0 if no error.*/
-int BMO_error_get(BMesh *bm, const char **msg, BMOperator **op);
+int BMO_error_get(BMesh *bm, const char **msg, BMOperator **op);
bool BMO_error_occurred(BMesh *bm);
/* same as geterror, only pops the error off the stack as well */
-int BMO_error_pop(BMesh *bm, const char **msg, BMOperator **op);
+int BMO_error_pop(BMesh *bm, const char **msg, BMOperator **op);
void BMO_error_clear(BMesh *bm);
/* this is meant for handling errors, like self-intersection test failures.
@@ -48,24 +48,24 @@ void BMO_error_clear(BMesh *bm);
*/
#define BM_ELEM_INDEX_VALIDATE(_bm, _msg_a, _msg_b) \
- BM_mesh_elem_index_validate(_bm, __FILE__ ":" STRINGIFY(__LINE__), __func__, _msg_a, _msg_b)
+ BM_mesh_elem_index_validate(_bm, __FILE__ ":" STRINGIFY(__LINE__), __func__, _msg_a, _msg_b)
/*------ error code defines -------*/
/*error messages*/
enum {
- BMERR_SELF_INTERSECTING = 1,
- BMERR_DISSOLVEDISK_FAILED,
- BMERR_CONNECTVERT_FAILED,
- BMERR_WALKER_FAILED,
- BMERR_DISSOLVEFACES_FAILED,
- BMERR_TESSELLATION,
- BMERR_NONMANIFOLD,
- BMERR_INVALID_SELECTION,
- BMERR_MESH_ERROR,
- BMERR_CONVEX_HULL_FAILED,
-
- BMERR_TOTAL,
+ BMERR_SELF_INTERSECTING = 1,
+ BMERR_DISSOLVEDISK_FAILED,
+ BMERR_CONNECTVERT_FAILED,
+ BMERR_WALKER_FAILED,
+ BMERR_DISSOLVEFACES_FAILED,
+ BMERR_TESSELLATION,
+ BMERR_NONMANIFOLD,
+ BMERR_INVALID_SELECTION,
+ BMERR_MESH_ERROR,
+ BMERR_CONVEX_HULL_FAILED,
+
+ BMERR_TOTAL,
};
/* BMESH_ASSERT */
@@ -77,13 +77,15 @@ enum {
/* this is meant to be higher level then BLI_assert(),
* its enabled even when in Release mode*/
-#define BMESH_ASSERT(a) \
- (void)((!(a)) ? ( \
- ( \
- fprintf(stderr, \
- "BMESH_ASSERT failed: %s, %s(), %d at \'%s\'\n", \
- __FILE__, __func__, __LINE__, STRINGIFY(a)), \
- _BMESH_DUMMY_ABORT(), \
- NULL)) : NULL)
+#define BMESH_ASSERT(a) \
+ (void)((!(a)) ? ((fprintf(stderr, \
+ "BMESH_ASSERT failed: %s, %s(), %d at \'%s\'\n", \
+ __FILE__, \
+ __func__, \
+ __LINE__, \
+ STRINGIFY(a)), \
+ _BMESH_DUMMY_ABORT(), \
+ NULL)) : \
+ NULL)
#endif /* __BMESH_ERROR_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_inline.h b/source/blender/bmesh/intern/bmesh_inline.h
index 549fc90fe40..13691776a27 100644
--- a/source/blender/bmesh/intern/bmesh_inline.h
+++ b/source/blender/bmesh/intern/bmesh_inline.h
@@ -24,66 +24,74 @@
#define __BMESH_INLINE_H__
/* stuff for dealing with header flags */
-#define BM_elem_flag_test( ele, hflag) _bm_elem_flag_test (&(ele)->head, hflag)
-#define BM_elem_flag_test_bool(ele, hflag) _bm_elem_flag_test_bool(&(ele)->head, hflag)
-#define BM_elem_flag_enable( ele, hflag) _bm_elem_flag_enable (&(ele)->head, hflag)
-#define BM_elem_flag_disable( ele, hflag) _bm_elem_flag_disable (&(ele)->head, hflag)
-#define BM_elem_flag_set( ele, hflag, val) _bm_elem_flag_set (&(ele)->head, hflag, val)
-#define BM_elem_flag_toggle( ele, hflag) _bm_elem_flag_toggle (&(ele)->head, hflag)
-#define BM_elem_flag_merge( ele_a, ele_b) _bm_elem_flag_merge (&(ele_a)->head, &(ele_b)->head)
-#define BM_elem_flag_merge_ex( ele_a, ele_b, hflag_and)_bm_elem_flag_merge_ex (&(ele_a)->head, &(ele_b)->head, hflag_and)
-#define BM_elem_flag_merge_into(ele, ele_a, ele_b)_bm_elem_flag_merge_into (&(ele)->head, &(ele_a)->head, &(ele_b)->head)
+#define BM_elem_flag_test(ele, hflag) _bm_elem_flag_test(&(ele)->head, hflag)
+#define BM_elem_flag_test_bool(ele, hflag) _bm_elem_flag_test_bool(&(ele)->head, hflag)
+#define BM_elem_flag_enable(ele, hflag) _bm_elem_flag_enable(&(ele)->head, hflag)
+#define BM_elem_flag_disable(ele, hflag) _bm_elem_flag_disable(&(ele)->head, hflag)
+#define BM_elem_flag_set(ele, hflag, val) _bm_elem_flag_set(&(ele)->head, hflag, val)
+#define BM_elem_flag_toggle(ele, hflag) _bm_elem_flag_toggle(&(ele)->head, hflag)
+#define BM_elem_flag_merge(ele_a, ele_b) _bm_elem_flag_merge(&(ele_a)->head, &(ele_b)->head)
+#define BM_elem_flag_merge_ex(ele_a, ele_b, hflag_and) \
+ _bm_elem_flag_merge_ex(&(ele_a)->head, &(ele_b)->head, hflag_and)
+#define BM_elem_flag_merge_into(ele, ele_a, ele_b) \
+ _bm_elem_flag_merge_into(&(ele)->head, &(ele_a)->head, &(ele_b)->head)
ATTR_WARN_UNUSED_RESULT
BLI_INLINE char _bm_elem_flag_test(const BMHeader *head, const char hflag)
{
- return head->hflag & hflag;
+ return head->hflag & hflag;
}
ATTR_WARN_UNUSED_RESULT
BLI_INLINE bool _bm_elem_flag_test_bool(const BMHeader *head, const char hflag)
{
- return (head->hflag & hflag) != 0;
+ return (head->hflag & hflag) != 0;
}
BLI_INLINE void _bm_elem_flag_enable(BMHeader *head, const char hflag)
{
- head->hflag |= hflag;
+ head->hflag |= hflag;
}
BLI_INLINE void _bm_elem_flag_disable(BMHeader *head, const char hflag)
{
- head->hflag &= (char)~hflag;
+ head->hflag &= (char)~hflag;
}
BLI_INLINE void _bm_elem_flag_set(BMHeader *head, const char hflag, const int val)
{
- if (val) { _bm_elem_flag_enable(head, hflag); }
- else { _bm_elem_flag_disable(head, hflag); }
+ if (val) {
+ _bm_elem_flag_enable(head, hflag);
+ }
+ else {
+ _bm_elem_flag_disable(head, hflag);
+ }
}
BLI_INLINE void _bm_elem_flag_toggle(BMHeader *head, const char hflag)
{
- head->hflag ^= hflag;
+ head->hflag ^= hflag;
}
BLI_INLINE void _bm_elem_flag_merge(BMHeader *head_a, BMHeader *head_b)
{
- head_a->hflag = head_b->hflag = head_a->hflag | head_b->hflag;
+ head_a->hflag = head_b->hflag = head_a->hflag | head_b->hflag;
}
BLI_INLINE void _bm_elem_flag_merge_ex(BMHeader *head_a, BMHeader *head_b, const char hflag_and)
{
- if (((head_a->hflag & head_b->hflag) & hflag_and) == 0) {
- head_a->hflag &= ~hflag_and;
- head_b->hflag &= ~hflag_and;
- }
- _bm_elem_flag_merge(head_a, head_b);
+ if (((head_a->hflag & head_b->hflag) & hflag_and) == 0) {
+ head_a->hflag &= ~hflag_and;
+ head_b->hflag &= ~hflag_and;
+ }
+ _bm_elem_flag_merge(head_a, head_b);
}
-BLI_INLINE void _bm_elem_flag_merge_into(BMHeader *head, const BMHeader *head_a, const BMHeader *head_b)
+BLI_INLINE void _bm_elem_flag_merge_into(BMHeader *head,
+ const BMHeader *head_a,
+ const BMHeader *head_b)
{
- head->hflag = head_a->hflag | head_b->hflag;
+ head->hflag = head_a->hflag | head_b->hflag;
}
/**
@@ -114,18 +122,18 @@ BLI_INLINE void _bm_elem_flag_merge_into(BMHeader *head, const BMHeader *head_a,
*
* - campbell */
-#define BM_elem_index_get(ele) _bm_elem_index_get(&(ele)->head)
-#define BM_elem_index_set(ele, index) _bm_elem_index_set(&(ele)->head, index)
+#define BM_elem_index_get(ele) _bm_elem_index_get(&(ele)->head)
+#define BM_elem_index_set(ele, index) _bm_elem_index_set(&(ele)->head, index)
BLI_INLINE void _bm_elem_index_set(BMHeader *head, const int index)
{
- head->index = index;
+ head->index = index;
}
ATTR_WARN_UNUSED_RESULT
BLI_INLINE int _bm_elem_index_get(const BMHeader *head)
{
- return head->index;
+ return head->index;
}
#endif /* __BMESH_INLINE_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c
index 11d6df430c3..c58521297dd 100644
--- a/source/blender/bmesh/intern/bmesh_interp.c
+++ b/source/blender/bmesh/intern/bmesh_interp.c
@@ -40,41 +40,45 @@
#include "intern/bmesh_private.h"
/* edge and vertex share, currently theres no need to have different logic */
-static void bm_data_interp_from_elem(
- CustomData *data_layer, const BMElem *ele_src_1, const BMElem *ele_src_2,
- BMElem *ele_dst, const float fac)
+static void bm_data_interp_from_elem(CustomData *data_layer,
+ const BMElem *ele_src_1,
+ const BMElem *ele_src_2,
+ BMElem *ele_dst,
+ const float fac)
{
- if (ele_src_1->head.data && ele_src_2->head.data) {
- /* first see if we can avoid interpolation */
- if (fac <= 0.0f) {
- if (ele_src_1 == ele_dst) {
- /* do nothing */
- }
- else {
- CustomData_bmesh_free_block_data(data_layer, ele_dst->head.data);
- CustomData_bmesh_copy_data(data_layer, data_layer, ele_src_1->head.data, &ele_dst->head.data);
- }
- }
- else if (fac >= 1.0f) {
- if (ele_src_2 == ele_dst) {
- /* do nothing */
- }
- else {
- CustomData_bmesh_free_block_data(data_layer, ele_dst->head.data);
- CustomData_bmesh_copy_data(data_layer, data_layer, ele_src_2->head.data, &ele_dst->head.data);
- }
- }
- else {
- const void *src[2];
- float w[2];
-
- src[0] = ele_src_1->head.data;
- src[1] = ele_src_2->head.data;
- w[0] = 1.0f - fac;
- w[1] = fac;
- CustomData_bmesh_interp(data_layer, src, w, NULL, 2, ele_dst->head.data);
- }
- }
+ if (ele_src_1->head.data && ele_src_2->head.data) {
+ /* first see if we can avoid interpolation */
+ if (fac <= 0.0f) {
+ if (ele_src_1 == ele_dst) {
+ /* do nothing */
+ }
+ else {
+ CustomData_bmesh_free_block_data(data_layer, ele_dst->head.data);
+ CustomData_bmesh_copy_data(
+ data_layer, data_layer, ele_src_1->head.data, &ele_dst->head.data);
+ }
+ }
+ else if (fac >= 1.0f) {
+ if (ele_src_2 == ele_dst) {
+ /* do nothing */
+ }
+ else {
+ CustomData_bmesh_free_block_data(data_layer, ele_dst->head.data);
+ CustomData_bmesh_copy_data(
+ data_layer, data_layer, ele_src_2->head.data, &ele_dst->head.data);
+ }
+ }
+ else {
+ const void *src[2];
+ float w[2];
+
+ src[0] = ele_src_1->head.data;
+ src[1] = ele_src_2->head.data;
+ w[0] = 1.0f - fac;
+ w[1] = fac;
+ CustomData_bmesh_interp(data_layer, src, w, NULL, 2, ele_dst->head.data);
+ }
+ }
}
/**
@@ -84,9 +88,11 @@ static void bm_data_interp_from_elem(
*
* \note This is an exact match to #BM_data_interp_from_edges
*/
-void BM_data_interp_from_verts(BMesh *bm, const BMVert *v_src_1, const BMVert *v_src_2, BMVert *v_dst, const float fac)
+void BM_data_interp_from_verts(
+ BMesh *bm, const BMVert *v_src_1, const BMVert *v_src_2, BMVert *v_dst, const float fac)
{
- bm_data_interp_from_elem(&bm->vdata, (const BMElem *)v_src_1, (const BMElem *)v_src_2, (BMElem *)v_dst, fac);
+ bm_data_interp_from_elem(
+ &bm->vdata, (const BMElem *)v_src_1, (const BMElem *)v_src_2, (BMElem *)v_dst, fac);
}
/**
@@ -96,9 +102,11 @@ void BM_data_interp_from_verts(BMesh *bm, const BMVert *v_src_1, const BMVert *v
*
* \note This is an exact match to #BM_data_interp_from_verts
*/
-void BM_data_interp_from_edges(BMesh *bm, const BMEdge *e_src_1, const BMEdge *e_src_2, BMEdge *e_dst, const float fac)
+void BM_data_interp_from_edges(
+ BMesh *bm, const BMEdge *e_src_1, const BMEdge *e_src_2, BMEdge *e_dst, const float fac)
{
- bm_data_interp_from_elem(&bm->edata, (const BMElem *)e_src_1, (const BMElem *)e_src_2, (BMElem *)e_dst, fac);
+ bm_data_interp_from_elem(
+ &bm->edata, (const BMElem *)e_src_1, (const BMElem *)e_src_2, (BMElem *)e_dst, fac);
}
/**
@@ -109,7 +117,7 @@ void BM_data_interp_from_edges(BMesh *bm, const BMEdge *e_src_1, const BMEdge *e
*/
static void UNUSED_FUNCTION(BM_Data_Vert_Average)(BMesh *UNUSED(bm), BMFace *UNUSED(f))
{
- // BMIter iter;
+ // BMIter iter;
}
/**
@@ -118,44 +126,48 @@ static void UNUSED_FUNCTION(BM_Data_Vert_Average)(BMesh *UNUSED(bm), BMFace *UNU
* Walks around the faces of \a e and interpolates
* the loop data between two sources.
*/
-void BM_data_interp_face_vert_edge(
- BMesh *bm, const BMVert *v_src_1, const BMVert *UNUSED(v_src_2), BMVert *v, BMEdge *e, const float fac)
+void BM_data_interp_face_vert_edge(BMesh *bm,
+ const BMVert *v_src_1,
+ const BMVert *UNUSED(v_src_2),
+ BMVert *v,
+ BMEdge *e,
+ const float fac)
{
- float w[2];
- BMLoop *l_v1 = NULL, *l_v = NULL, *l_v2 = NULL;
- BMLoop *l_iter = NULL;
-
- if (!e->l) {
- return;
- }
-
- w[1] = 1.0f - fac;
- w[0] = fac;
-
- l_iter = e->l;
- do {
- if (l_iter->v == v_src_1) {
- l_v1 = l_iter;
- l_v = l_v1->next;
- l_v2 = l_v->next;
- }
- else if (l_iter->v == v) {
- l_v1 = l_iter->next;
- l_v = l_iter;
- l_v2 = l_iter->prev;
- }
-
- if (!l_v1 || !l_v2) {
- return;
- }
- else {
- const void *src[2];
- src[0] = l_v1->head.data;
- src[1] = l_v2->head.data;
-
- CustomData_bmesh_interp(&bm->ldata, src, w, NULL, 2, l_v->head.data);
- }
- } while ((l_iter = l_iter->radial_next) != e->l);
+ float w[2];
+ BMLoop *l_v1 = NULL, *l_v = NULL, *l_v2 = NULL;
+ BMLoop *l_iter = NULL;
+
+ if (!e->l) {
+ return;
+ }
+
+ w[1] = 1.0f - fac;
+ w[0] = fac;
+
+ l_iter = e->l;
+ do {
+ if (l_iter->v == v_src_1) {
+ l_v1 = l_iter;
+ l_v = l_v1->next;
+ l_v2 = l_v->next;
+ }
+ else if (l_iter->v == v) {
+ l_v1 = l_iter->next;
+ l_v = l_iter;
+ l_v2 = l_iter->prev;
+ }
+
+ if (!l_v1 || !l_v2) {
+ return;
+ }
+ else {
+ const void *src[2];
+ src[0] = l_v1->head.data;
+ src[1] = l_v2->head.data;
+
+ CustomData_bmesh_interp(&bm->ldata, src, w, NULL, 2, l_v->head.data);
+ }
+ } while ((l_iter = l_iter->radial_next) != e->l);
}
/**
@@ -166,61 +178,65 @@ void BM_data_interp_face_vert_edge(
*
* \note Only handles loop customdata. multires is handled.
*/
-void BM_face_interp_from_face_ex(
- BMesh *bm, BMFace *f_dst, const BMFace *f_src, const bool do_vertex,
- const void **blocks_l, const void **blocks_v, float (*cos_2d)[2], float axis_mat[3][3])
+void BM_face_interp_from_face_ex(BMesh *bm,
+ BMFace *f_dst,
+ const BMFace *f_src,
+ const bool do_vertex,
+ const void **blocks_l,
+ const void **blocks_v,
+ float (*cos_2d)[2],
+ float axis_mat[3][3])
{
- BMLoop *l_iter;
- BMLoop *l_first;
-
- float *w = BLI_array_alloca(w, f_src->len);
- float co[2];
- int i;
-
- if (f_src != f_dst) {
- BM_elem_attrs_copy(bm, bm, f_src, f_dst);
- }
-
- /* interpolate */
- i = 0;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f_dst);
- do {
- mul_v2_m3v3(co, axis_mat, l_iter->v->co);
- interp_weights_poly_v2(w, cos_2d, f_src->len, co);
- CustomData_bmesh_interp(&bm->ldata, blocks_l, w, NULL, f_src->len, l_iter->head.data);
- if (do_vertex) {
- CustomData_bmesh_interp(&bm->vdata, blocks_v, w, NULL, f_src->len, l_iter->v->head.data);
- }
- } while ((void)i++, (l_iter = l_iter->next) != l_first);
+ BMLoop *l_iter;
+ BMLoop *l_first;
+
+ float *w = BLI_array_alloca(w, f_src->len);
+ float co[2];
+ int i;
+
+ if (f_src != f_dst) {
+ BM_elem_attrs_copy(bm, bm, f_src, f_dst);
+ }
+
+ /* interpolate */
+ i = 0;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_dst);
+ do {
+ mul_v2_m3v3(co, axis_mat, l_iter->v->co);
+ interp_weights_poly_v2(w, cos_2d, f_src->len, co);
+ CustomData_bmesh_interp(&bm->ldata, blocks_l, w, NULL, f_src->len, l_iter->head.data);
+ if (do_vertex) {
+ CustomData_bmesh_interp(&bm->vdata, blocks_v, w, NULL, f_src->len, l_iter->v->head.data);
+ }
+ } while ((void)i++, (l_iter = l_iter->next) != l_first);
}
void BM_face_interp_from_face(BMesh *bm, BMFace *f_dst, const BMFace *f_src, const bool do_vertex)
{
- BMLoop *l_iter;
- BMLoop *l_first;
-
- const void **blocks_l = BLI_array_alloca(blocks_l, f_src->len);
- const void **blocks_v = do_vertex ? BLI_array_alloca(blocks_v, f_src->len) : NULL;
- float (*cos_2d)[2] = BLI_array_alloca(cos_2d, f_src->len);
- float axis_mat[3][3]; /* use normal to transform into 2d xy coords */
- int i;
-
- /* convert the 3d coords into 2d for projection */
- BLI_assert(BM_face_is_normal_valid(f_src));
- axis_dominant_v3_to_m3(axis_mat, f_src->no);
-
- i = 0;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f_src);
- do {
- mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co);
- blocks_l[i] = l_iter->head.data;
- if (do_vertex) {
- blocks_v[i] = l_iter->v->head.data;
- }
- } while ((void)i++, (l_iter = l_iter->next) != l_first);
-
- BM_face_interp_from_face_ex(bm, f_dst, f_src, do_vertex,
- blocks_l, blocks_v, cos_2d, axis_mat);
+ BMLoop *l_iter;
+ BMLoop *l_first;
+
+ const void **blocks_l = BLI_array_alloca(blocks_l, f_src->len);
+ const void **blocks_v = do_vertex ? BLI_array_alloca(blocks_v, f_src->len) : NULL;
+ float(*cos_2d)[2] = BLI_array_alloca(cos_2d, f_src->len);
+ float axis_mat[3][3]; /* use normal to transform into 2d xy coords */
+ int i;
+
+ /* convert the 3d coords into 2d for projection */
+ BLI_assert(BM_face_is_normal_valid(f_src));
+ axis_dominant_v3_to_m3(axis_mat, f_src->no);
+
+ i = 0;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_src);
+ do {
+ mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co);
+ blocks_l[i] = l_iter->head.data;
+ if (do_vertex) {
+ blocks_v[i] = l_iter->v->head.data;
+ }
+ } while ((void)i++, (l_iter = l_iter->next) != l_first);
+
+ BM_face_interp_from_face_ex(bm, f_dst, f_src, do_vertex, blocks_l, blocks_v, cos_2d, axis_mat);
}
/**
@@ -237,283 +253,318 @@ void BM_face_interp_from_face(BMesh *bm, BMFace *f_dst, const BMFace *f_src, con
* y
* </pre>
*/
-static int compute_mdisp_quad(
- const BMLoop *l, const float l_f_center[3],
- float v1[3], float v2[3], float v3[3], float v4[3],
- float e1[3], float e2[3])
+static int compute_mdisp_quad(const BMLoop *l,
+ const float l_f_center[3],
+ float v1[3],
+ float v2[3],
+ float v3[3],
+ float v4[3],
+ float e1[3],
+ float e2[3])
{
- float n[3], p[3];
+ float n[3], p[3];
#ifndef NDEBUG
- {
- float cent[3];
- /* computer center */
- BM_face_calc_center_median(l->f, cent);
- BLI_assert(equals_v3v3(cent, l_f_center));
- }
+ {
+ float cent[3];
+ /* computer center */
+ BM_face_calc_center_median(l->f, cent);
+ BLI_assert(equals_v3v3(cent, l_f_center));
+ }
#endif
- mid_v3_v3v3(p, l->prev->v->co, l->v->co);
- mid_v3_v3v3(n, l->next->v->co, l->v->co);
+ mid_v3_v3v3(p, l->prev->v->co, l->v->co);
+ mid_v3_v3v3(n, l->next->v->co, l->v->co);
- copy_v3_v3(v1, l_f_center);
- copy_v3_v3(v2, p);
- copy_v3_v3(v3, l->v->co);
- copy_v3_v3(v4, n);
+ copy_v3_v3(v1, l_f_center);
+ copy_v3_v3(v2, p);
+ copy_v3_v3(v3, l->v->co);
+ copy_v3_v3(v4, n);
- sub_v3_v3v3(e1, v2, v1);
- sub_v3_v3v3(e2, v3, v4);
+ sub_v3_v3v3(e1, v2, v1);
+ sub_v3_v3v3(e2, v3, v4);
- return 1;
+ return 1;
}
-static bool quad_co(
- const float v1[3], const float v2[3], const float v3[3], const float v4[3],
- const float p[3], const float n[3],
- float r_uv[2])
+static bool quad_co(const float v1[3],
+ const float v2[3],
+ const float v3[3],
+ const float v4[3],
+ const float p[3],
+ const float n[3],
+ float r_uv[2])
{
- float projverts[5][3], n2[3];
- float origin[2] = {0.0f, 0.0f};
- int i;
+ float projverts[5][3], n2[3];
+ float origin[2] = {0.0f, 0.0f};
+ int i;
- /* project points into 2d along normal */
- copy_v3_v3(projverts[0], v1);
- copy_v3_v3(projverts[1], v2);
- copy_v3_v3(projverts[2], v3);
- copy_v3_v3(projverts[3], v4);
- copy_v3_v3(projverts[4], p);
+ /* project points into 2d along normal */
+ copy_v3_v3(projverts[0], v1);
+ copy_v3_v3(projverts[1], v2);
+ copy_v3_v3(projverts[2], v3);
+ copy_v3_v3(projverts[3], v4);
+ copy_v3_v3(projverts[4], p);
- normal_quad_v3(n2, projverts[0], projverts[1], projverts[2], projverts[3]);
+ normal_quad_v3(n2, projverts[0], projverts[1], projverts[2], projverts[3]);
- if (dot_v3v3(n, n2) < -FLT_EPSILON) {
- return false;
- }
+ if (dot_v3v3(n, n2) < -FLT_EPSILON) {
+ return false;
+ }
- /* rotate */
- poly_rotate_plane(n, projverts, 5);
+ /* rotate */
+ poly_rotate_plane(n, projverts, 5);
- /* subtract origin */
- for (i = 0; i < 4; i++) {
- sub_v2_v2(projverts[i], projverts[4]);
- }
+ /* subtract origin */
+ for (i = 0; i < 4; i++) {
+ sub_v2_v2(projverts[i], projverts[4]);
+ }
- if (!isect_point_quad_v2(origin, projverts[0], projverts[1], projverts[2], projverts[3])) {
- return false;
- }
+ if (!isect_point_quad_v2(origin, projverts[0], projverts[1], projverts[2], projverts[3])) {
+ return false;
+ }
- resolve_quad_uv_v2(r_uv, origin, projverts[0], projverts[3], projverts[2], projverts[1]);
+ resolve_quad_uv_v2(r_uv, origin, projverts[0], projverts[3], projverts[2], projverts[1]);
- return true;
+ return true;
}
-static void mdisp_axis_from_quad(
- float v1[3], float v2[3], float UNUSED(v3[3]), float v4[3],
- float r_axis_x[3], float r_axis_y[3])
+static void mdisp_axis_from_quad(float v1[3],
+ float v2[3],
+ float UNUSED(v3[3]),
+ float v4[3],
+ float r_axis_x[3],
+ float r_axis_y[3])
{
- sub_v3_v3v3(r_axis_x, v4, v1);
- sub_v3_v3v3(r_axis_y, v2, v1);
+ sub_v3_v3v3(r_axis_x, v4, v1);
+ sub_v3_v3v3(r_axis_y, v2, v1);
- normalize_v3(r_axis_x);
- normalize_v3(r_axis_y);
+ normalize_v3(r_axis_x);
+ normalize_v3(r_axis_y);
}
/* tl is loop to project onto, l is loop whose internal displacement, co, is being
* projected. x and y are location in loop's mdisps grid of point co. */
-static bool mdisp_in_mdispquad(
- BMLoop *l_src, BMLoop *l_dst, const float l_dst_f_center[3],
- const float p[3], int res,
- float r_axis_x[3], float r_axis_y[3], float r_uv[2])
+static bool mdisp_in_mdispquad(BMLoop *l_src,
+ BMLoop *l_dst,
+ const float l_dst_f_center[3],
+ const float p[3],
+ int res,
+ float r_axis_x[3],
+ float r_axis_y[3],
+ float r_uv[2])
{
- float v1[3], v2[3], c[3], v3[3], v4[3], e1[3], e2[3];
- float eps = FLT_EPSILON * 4000;
-
- if (is_zero_v3(l_src->v->no)) {
- BM_vert_normal_update_all(l_src->v);
- }
- if (is_zero_v3(l_dst->v->no)) {
- BM_vert_normal_update_all(l_dst->v);
- }
-
- compute_mdisp_quad(l_dst, l_dst_f_center, v1, v2, v3, v4, e1, e2);
-
- /* expand quad a bit */
- mid_v3_v3v3v3v3(c, v1, v2, v3, v4);
-
- sub_v3_v3(v1, c); sub_v3_v3(v2, c);
- sub_v3_v3(v3, c); sub_v3_v3(v4, c);
- mul_v3_fl(v1, 1.0f + eps); mul_v3_fl(v2, 1.0f + eps);
- mul_v3_fl(v3, 1.0f + eps); mul_v3_fl(v4, 1.0f + eps);
- add_v3_v3(v1, c); add_v3_v3(v2, c);
- add_v3_v3(v3, c); add_v3_v3(v4, c);
-
- if (!quad_co(v1, v2, v3, v4, p, l_src->v->no, r_uv)) {
- return 0;
- }
-
- mul_v2_fl(r_uv, (float)(res - 1));
-
- mdisp_axis_from_quad(v1, v2, v3, v4, r_axis_x, r_axis_y);
-
- return 1;
+ float v1[3], v2[3], c[3], v3[3], v4[3], e1[3], e2[3];
+ float eps = FLT_EPSILON * 4000;
+
+ if (is_zero_v3(l_src->v->no)) {
+ BM_vert_normal_update_all(l_src->v);
+ }
+ if (is_zero_v3(l_dst->v->no)) {
+ BM_vert_normal_update_all(l_dst->v);
+ }
+
+ compute_mdisp_quad(l_dst, l_dst_f_center, v1, v2, v3, v4, e1, e2);
+
+ /* expand quad a bit */
+ mid_v3_v3v3v3v3(c, v1, v2, v3, v4);
+
+ sub_v3_v3(v1, c);
+ sub_v3_v3(v2, c);
+ sub_v3_v3(v3, c);
+ sub_v3_v3(v4, c);
+ mul_v3_fl(v1, 1.0f + eps);
+ mul_v3_fl(v2, 1.0f + eps);
+ mul_v3_fl(v3, 1.0f + eps);
+ mul_v3_fl(v4, 1.0f + eps);
+ add_v3_v3(v1, c);
+ add_v3_v3(v2, c);
+ add_v3_v3(v3, c);
+ add_v3_v3(v4, c);
+
+ if (!quad_co(v1, v2, v3, v4, p, l_src->v->no, r_uv)) {
+ return 0;
+ }
+
+ mul_v2_fl(r_uv, (float)(res - 1));
+
+ mdisp_axis_from_quad(v1, v2, v3, v4, r_axis_x, r_axis_y);
+
+ return 1;
}
-static float bm_loop_flip_equotion(
- float mat[2][2], float b[2], const float target_axis_x[3], const float target_axis_y[3],
- const float coord[3], int i, int j)
+static float bm_loop_flip_equotion(float mat[2][2],
+ float b[2],
+ const float target_axis_x[3],
+ const float target_axis_y[3],
+ const float coord[3],
+ int i,
+ int j)
{
- mat[0][0] = target_axis_x[i];
- mat[0][1] = target_axis_y[i];
- mat[1][0] = target_axis_x[j];
- mat[1][1] = target_axis_y[j];
- b[0] = coord[i];
- b[1] = coord[j];
-
- return cross_v2v2(mat[0], mat[1]);
+ mat[0][0] = target_axis_x[i];
+ mat[0][1] = target_axis_y[i];
+ mat[1][0] = target_axis_x[j];
+ mat[1][1] = target_axis_y[j];
+ b[0] = coord[i];
+ b[1] = coord[j];
+
+ return cross_v2v2(mat[0], mat[1]);
}
-static void bm_loop_flip_disp(
- const float source_axis_x[3], const float source_axis_y[3],
- const float target_axis_x[3], const float target_axis_y[3], float disp[3])
+static void bm_loop_flip_disp(const float source_axis_x[3],
+ const float source_axis_y[3],
+ const float target_axis_x[3],
+ const float target_axis_y[3],
+ float disp[3])
{
- float vx[3], vy[3], coord[3];
- float n[3], vec[3];
- float b[2], mat[2][2], d;
-
- mul_v3_v3fl(vx, source_axis_x, disp[0]);
- mul_v3_v3fl(vy, source_axis_y, disp[1]);
- add_v3_v3v3(coord, vx, vy);
-
- /* project displacement from source grid plane onto target grid plane */
- cross_v3_v3v3(n, target_axis_x, target_axis_y);
- project_v3_v3v3(vec, coord, n);
- sub_v3_v3v3(coord, coord, vec);
-
- d = bm_loop_flip_equotion(mat, b, target_axis_x, target_axis_y, coord, 0, 1);
-
- if (fabsf(d) < 1e-4f) {
- d = bm_loop_flip_equotion(mat, b, target_axis_x, target_axis_y, coord, 0, 2);
- if (fabsf(d) < 1e-4f) {
- d = bm_loop_flip_equotion(mat, b, target_axis_x, target_axis_y, coord, 1, 2);
- }
- }
-
- disp[0] = (b[0] * mat[1][1] - mat[0][1] * b[1]) / d;
- disp[1] = (mat[0][0] * b[1] - b[0] * mat[1][0]) / d;
+ float vx[3], vy[3], coord[3];
+ float n[3], vec[3];
+ float b[2], mat[2][2], d;
+
+ mul_v3_v3fl(vx, source_axis_x, disp[0]);
+ mul_v3_v3fl(vy, source_axis_y, disp[1]);
+ add_v3_v3v3(coord, vx, vy);
+
+ /* project displacement from source grid plane onto target grid plane */
+ cross_v3_v3v3(n, target_axis_x, target_axis_y);
+ project_v3_v3v3(vec, coord, n);
+ sub_v3_v3v3(coord, coord, vec);
+
+ d = bm_loop_flip_equotion(mat, b, target_axis_x, target_axis_y, coord, 0, 1);
+
+ if (fabsf(d) < 1e-4f) {
+ d = bm_loop_flip_equotion(mat, b, target_axis_x, target_axis_y, coord, 0, 2);
+ if (fabsf(d) < 1e-4f) {
+ d = bm_loop_flip_equotion(mat, b, target_axis_x, target_axis_y, coord, 1, 2);
+ }
+ }
+
+ disp[0] = (b[0] * mat[1][1] - mat[0][1] * b[1]) / d;
+ disp[1] = (mat[0][0] * b[1] - b[0] * mat[1][0]) / d;
}
-
typedef struct BMLoopInterpMultiresData {
- BMLoop *l_dst;
- BMLoop *l_src_first;
- int cd_loop_mdisp_offset;
+ BMLoop *l_dst;
+ BMLoop *l_src_first;
+ int cd_loop_mdisp_offset;
- MDisps *md_dst;
- const float *f_src_center;
+ MDisps *md_dst;
+ const float *f_src_center;
- float *axis_x, *axis_y;
- float *v1, *v4;
- float *e1, *e2;
+ float *axis_x, *axis_y;
+ float *v1, *v4;
+ float *e1, *e2;
- int res;
- float d;
+ int res;
+ float d;
} BMLoopInterpMultiresData;
-static void loop_interp_multires_cb(
- void *__restrict userdata,
- const int ix,
- const ParallelRangeTLS *__restrict UNUSED(tls))
+static void loop_interp_multires_cb(void *__restrict userdata,
+ const int ix,
+ const ParallelRangeTLS *__restrict UNUSED(tls))
{
- BMLoopInterpMultiresData *data = userdata;
+ BMLoopInterpMultiresData *data = userdata;
- BMLoop *l_first = data->l_src_first;
- BMLoop *l_dst = data->l_dst;
- const int cd_loop_mdisp_offset = data->cd_loop_mdisp_offset;
+ BMLoop *l_first = data->l_src_first;
+ BMLoop *l_dst = data->l_dst;
+ const int cd_loop_mdisp_offset = data->cd_loop_mdisp_offset;
- MDisps *md_dst = data->md_dst;
- const float *f_src_center = data->f_src_center;
+ MDisps *md_dst = data->md_dst;
+ const float *f_src_center = data->f_src_center;
- float *axis_x = data->axis_x;
- float *axis_y = data->axis_y;
+ float *axis_x = data->axis_x;
+ float *axis_y = data->axis_y;
- float *v1 = data->v1;
- float *v4 = data->v4;
- float *e1 = data->e1;
- float *e2 = data->e2;
+ float *v1 = data->v1;
+ float *v4 = data->v4;
+ float *e1 = data->e1;
+ float *e2 = data->e2;
- const int res = data->res;
- const float d = data->d;
+ const int res = data->res;
+ const float d = data->d;
- float x = d * ix, y;
- int iy;
- for (y = 0.0f, iy = 0; iy < res; y += d, iy++) {
- BMLoop *l_iter = l_first;
- float co1[3], co2[3], co[3];
+ float x = d * ix, y;
+ int iy;
+ for (y = 0.0f, iy = 0; iy < res; y += d, iy++) {
+ BMLoop *l_iter = l_first;
+ float co1[3], co2[3], co[3];
- madd_v3_v3v3fl(co1, v1, e1, y);
- madd_v3_v3v3fl(co2, v4, e2, y);
- interp_v3_v3v3(co, co1, co2, x);
+ madd_v3_v3v3fl(co1, v1, e1, y);
+ madd_v3_v3v3fl(co2, v4, e2, y);
+ interp_v3_v3v3(co, co1, co2, x);
- do {
- MDisps *md_src;
- float src_axis_x[3], src_axis_y[3];
- float uv[2];
+ do {
+ MDisps *md_src;
+ float src_axis_x[3], src_axis_y[3];
+ float uv[2];
- md_src = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_mdisp_offset);
+ md_src = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_mdisp_offset);
- if (mdisp_in_mdispquad(l_dst, l_iter, f_src_center, co, res, src_axis_x, src_axis_y, uv)) {
- old_mdisps_bilinear(md_dst->disps[iy * res + ix], md_src->disps, res, uv[0], uv[1]);
- bm_loop_flip_disp(src_axis_x, src_axis_y, axis_x, axis_y, md_dst->disps[iy * res + ix]);
+ if (mdisp_in_mdispquad(l_dst, l_iter, f_src_center, co, res, src_axis_x, src_axis_y, uv)) {
+ old_mdisps_bilinear(md_dst->disps[iy * res + ix], md_src->disps, res, uv[0], uv[1]);
+ bm_loop_flip_disp(src_axis_x, src_axis_y, axis_x, axis_y, md_dst->disps[iy * res + ix]);
- break;
- }
- } while ((l_iter = l_iter->next) != l_first);
- }
+ break;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
}
-void BM_loop_interp_multires_ex(
- BMesh *UNUSED(bm), BMLoop *l_dst, const BMFace *f_src,
- const float f_dst_center[3], const float f_src_center[3], const int cd_loop_mdisp_offset)
+void BM_loop_interp_multires_ex(BMesh *UNUSED(bm),
+ BMLoop *l_dst,
+ const BMFace *f_src,
+ const float f_dst_center[3],
+ const float f_src_center[3],
+ const int cd_loop_mdisp_offset)
{
- MDisps *md_dst;
- float v1[3], v2[3], v3[3], v4[3] = {0.0f, 0.0f, 0.0f}, e1[3], e2[3];
- float axis_x[3], axis_y[3];
-
- /* ignore 2-edged faces */
- if (UNLIKELY(l_dst->f->len < 3)) {
- return;
- }
-
- md_dst = BM_ELEM_CD_GET_VOID_P(l_dst, cd_loop_mdisp_offset);
- compute_mdisp_quad(l_dst, f_dst_center, v1, v2, v3, v4, e1, e2);
-
- /* if no disps data allocate a new grid, the size of the first grid in f_src. */
- if (!md_dst->totdisp) {
- const MDisps *md_src = BM_ELEM_CD_GET_VOID_P(BM_FACE_FIRST_LOOP(f_src), cd_loop_mdisp_offset);
-
- md_dst->totdisp = md_src->totdisp;
- md_dst->level = md_src->level;
- if (md_dst->totdisp) {
- md_dst->disps = MEM_callocN(sizeof(float) * 3 * md_dst->totdisp, __func__);
- }
- else {
- return;
- }
- }
-
- mdisp_axis_from_quad(v1, v2, v3, v4, axis_x, axis_y);
-
- const int res = (int)sqrt(md_dst->totdisp);
- BMLoopInterpMultiresData data = {
- .l_dst = l_dst, .l_src_first = BM_FACE_FIRST_LOOP(f_src),
- .cd_loop_mdisp_offset = cd_loop_mdisp_offset,
- .md_dst = md_dst, .f_src_center = f_src_center,
- .axis_x = axis_x, .axis_y = axis_y, .v1 = v1, .v4 = v4, .e1 = e1, .e2 = e2,
- .res = res, .d = 1.0f / (float)(res - 1),
- };
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = (res > 5);
- BLI_task_parallel_range(0, res, &data, loop_interp_multires_cb, &settings);
+ MDisps *md_dst;
+ float v1[3], v2[3], v3[3], v4[3] = {0.0f, 0.0f, 0.0f}, e1[3], e2[3];
+ float axis_x[3], axis_y[3];
+
+ /* ignore 2-edged faces */
+ if (UNLIKELY(l_dst->f->len < 3)) {
+ return;
+ }
+
+ md_dst = BM_ELEM_CD_GET_VOID_P(l_dst, cd_loop_mdisp_offset);
+ compute_mdisp_quad(l_dst, f_dst_center, v1, v2, v3, v4, e1, e2);
+
+ /* if no disps data allocate a new grid, the size of the first grid in f_src. */
+ if (!md_dst->totdisp) {
+ const MDisps *md_src = BM_ELEM_CD_GET_VOID_P(BM_FACE_FIRST_LOOP(f_src), cd_loop_mdisp_offset);
+
+ md_dst->totdisp = md_src->totdisp;
+ md_dst->level = md_src->level;
+ if (md_dst->totdisp) {
+ md_dst->disps = MEM_callocN(sizeof(float) * 3 * md_dst->totdisp, __func__);
+ }
+ else {
+ return;
+ }
+ }
+
+ mdisp_axis_from_quad(v1, v2, v3, v4, axis_x, axis_y);
+
+ const int res = (int)sqrt(md_dst->totdisp);
+ BMLoopInterpMultiresData data = {
+ .l_dst = l_dst,
+ .l_src_first = BM_FACE_FIRST_LOOP(f_src),
+ .cd_loop_mdisp_offset = cd_loop_mdisp_offset,
+ .md_dst = md_dst,
+ .f_src_center = f_src_center,
+ .axis_x = axis_x,
+ .axis_y = axis_y,
+ .v1 = v1,
+ .v4 = v4,
+ .e1 = e1,
+ .e2 = e2,
+ .res = res,
+ .d = 1.0f / (float)(res - 1),
+ };
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.use_threading = (res > 5);
+ BLI_task_parallel_range(0, res, &data, loop_interp_multires_cb, &settings);
}
/**
@@ -521,45 +572,47 @@ void BM_loop_interp_multires_ex(
*/
void BM_loop_interp_multires(BMesh *bm, BMLoop *l_dst, const BMFace *f_src)
{
- const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
+ const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
- if (cd_loop_mdisp_offset != -1) {
- float f_dst_center[3];
- float f_src_center[3];
+ if (cd_loop_mdisp_offset != -1) {
+ float f_dst_center[3];
+ float f_src_center[3];
- BM_face_calc_center_median(l_dst->f, f_dst_center);
- BM_face_calc_center_median(f_src, f_src_center);
+ BM_face_calc_center_median(l_dst->f, f_dst_center);
+ BM_face_calc_center_median(f_src, f_src_center);
- BM_loop_interp_multires_ex(bm, l_dst, f_src, f_dst_center, f_src_center, cd_loop_mdisp_offset);
- }
+ BM_loop_interp_multires_ex(bm, l_dst, f_src, f_dst_center, f_src_center, cd_loop_mdisp_offset);
+ }
}
-void BM_face_interp_multires_ex(
- BMesh *bm, BMFace *f_dst, const BMFace *f_src,
- const float f_dst_center[3], const float f_src_center[3], const int cd_loop_mdisp_offset)
+void BM_face_interp_multires_ex(BMesh *bm,
+ BMFace *f_dst,
+ const BMFace *f_src,
+ const float f_dst_center[3],
+ const float f_src_center[3],
+ const int cd_loop_mdisp_offset)
{
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f_dst);
- do {
- BM_loop_interp_multires_ex(
- bm, l_iter, f_src,
- f_dst_center, f_src_center, cd_loop_mdisp_offset);
- } while ((l_iter = l_iter->next) != l_first);
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_dst);
+ do {
+ BM_loop_interp_multires_ex(
+ bm, l_iter, f_src, f_dst_center, f_src_center, cd_loop_mdisp_offset);
+ } while ((l_iter = l_iter->next) != l_first);
}
void BM_face_interp_multires(BMesh *bm, BMFace *f_dst, const BMFace *f_src)
{
- const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
+ const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
- if (cd_loop_mdisp_offset != -1) {
- float f_dst_center[3];
- float f_src_center[3];
+ if (cd_loop_mdisp_offset != -1) {
+ float f_dst_center[3];
+ float f_src_center[3];
- BM_face_calc_center_median(f_dst, f_dst_center);
- BM_face_calc_center_median(f_src, f_src_center);
+ BM_face_calc_center_median(f_dst, f_dst_center);
+ BM_face_calc_center_median(f_src, f_src_center);
- BM_face_interp_multires_ex(bm, f_dst, f_src, f_dst_center, f_src_center, cd_loop_mdisp_offset);
- }
+ BM_face_interp_multires_ex(bm, f_dst, f_src, f_dst_center, f_src_center, cd_loop_mdisp_offset);
+ }
}
/**
@@ -568,110 +621,110 @@ void BM_face_interp_multires(BMesh *bm, BMFace *f_dst, const BMFace *f_src)
*/
void BM_face_multires_bounds_smooth(BMesh *bm, BMFace *f)
{
- const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
- BMLoop *l;
- BMIter liter;
-
- if (cd_loop_mdisp_offset == -1) {
- return;
- }
-
- BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- MDisps *mdp = BM_ELEM_CD_GET_VOID_P(l->prev, cd_loop_mdisp_offset);
- MDisps *mdl = BM_ELEM_CD_GET_VOID_P(l, cd_loop_mdisp_offset);
- MDisps *mdn = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_mdisp_offset);
- float co1[3];
- int sides;
- int y;
-
- /**
- * mdisps is a grid of displacements, ordered thus:
- * <pre>
- * v4/next
- * |
- * | v1/cent-----mid2 ---> x
- * | | |
- * | | |
- * v2/prev---mid1-----v3/cur
- * |
- * V
- * y
- * </pre>
- */
-
- sides = (int)sqrt(mdp->totdisp);
- for (y = 0; y < sides; y++) {
- mid_v3_v3v3(co1, mdn->disps[y * sides], mdl->disps[y]);
-
- copy_v3_v3(mdn->disps[y * sides], co1);
- copy_v3_v3(mdl->disps[y], co1);
- }
- }
-
- BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- MDisps *mdl1 = BM_ELEM_CD_GET_VOID_P(l, cd_loop_mdisp_offset);
- MDisps *mdl2;
- float co1[3], co2[3], co[3];
- int sides;
- int y;
-
- /**
- * mdisps is a grid of displacements, ordered thus:
- * <pre>
- * v4/next
- * |
- * | v1/cent-----mid2 ---> x
- * | | |
- * | | |
- * v2/prev---mid1-----v3/cur
- * |
- * V
- * y
- * </pre>
- */
-
- if (l->radial_next == l) {
- continue;
- }
-
- if (l->radial_next->v == l->v) {
- mdl2 = BM_ELEM_CD_GET_VOID_P(l->radial_next, cd_loop_mdisp_offset);
- }
- else {
- mdl2 = BM_ELEM_CD_GET_VOID_P(l->radial_next->next, cd_loop_mdisp_offset);
- }
-
- sides = (int)sqrt(mdl1->totdisp);
- for (y = 0; y < sides; y++) {
- int a1, a2, o1, o2;
-
- if (l->v != l->radial_next->v) {
- a1 = sides * y + sides - 2;
- a2 = (sides - 2) * sides + y;
-
- o1 = sides * y + sides - 1;
- o2 = (sides - 1) * sides + y;
- }
- else {
- a1 = sides * y + sides - 2;
- a2 = sides * y + sides - 2;
- o1 = sides * y + sides - 1;
- o2 = sides * y + sides - 1;
- }
-
- /* magic blending numbers, hardcoded! */
- add_v3_v3v3(co1, mdl1->disps[a1], mdl2->disps[a2]);
- mul_v3_fl(co1, 0.18);
-
- add_v3_v3v3(co2, mdl1->disps[o1], mdl2->disps[o2]);
- mul_v3_fl(co2, 0.32);
-
- add_v3_v3v3(co, co1, co2);
-
- copy_v3_v3(mdl1->disps[o1], co);
- copy_v3_v3(mdl2->disps[o2], co);
- }
- }
+ const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
+ BMLoop *l;
+ BMIter liter;
+
+ if (cd_loop_mdisp_offset == -1) {
+ return;
+ }
+
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ MDisps *mdp = BM_ELEM_CD_GET_VOID_P(l->prev, cd_loop_mdisp_offset);
+ MDisps *mdl = BM_ELEM_CD_GET_VOID_P(l, cd_loop_mdisp_offset);
+ MDisps *mdn = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_mdisp_offset);
+ float co1[3];
+ int sides;
+ int y;
+
+ /**
+ * mdisps is a grid of displacements, ordered thus:
+ * <pre>
+ * v4/next
+ * |
+ * | v1/cent-----mid2 ---> x
+ * | | |
+ * | | |
+ * v2/prev---mid1-----v3/cur
+ * |
+ * V
+ * y
+ * </pre>
+ */
+
+ sides = (int)sqrt(mdp->totdisp);
+ for (y = 0; y < sides; y++) {
+ mid_v3_v3v3(co1, mdn->disps[y * sides], mdl->disps[y]);
+
+ copy_v3_v3(mdn->disps[y * sides], co1);
+ copy_v3_v3(mdl->disps[y], co1);
+ }
+ }
+
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ MDisps *mdl1 = BM_ELEM_CD_GET_VOID_P(l, cd_loop_mdisp_offset);
+ MDisps *mdl2;
+ float co1[3], co2[3], co[3];
+ int sides;
+ int y;
+
+ /**
+ * mdisps is a grid of displacements, ordered thus:
+ * <pre>
+ * v4/next
+ * |
+ * | v1/cent-----mid2 ---> x
+ * | | |
+ * | | |
+ * v2/prev---mid1-----v3/cur
+ * |
+ * V
+ * y
+ * </pre>
+ */
+
+ if (l->radial_next == l) {
+ continue;
+ }
+
+ if (l->radial_next->v == l->v) {
+ mdl2 = BM_ELEM_CD_GET_VOID_P(l->radial_next, cd_loop_mdisp_offset);
+ }
+ else {
+ mdl2 = BM_ELEM_CD_GET_VOID_P(l->radial_next->next, cd_loop_mdisp_offset);
+ }
+
+ sides = (int)sqrt(mdl1->totdisp);
+ for (y = 0; y < sides; y++) {
+ int a1, a2, o1, o2;
+
+ if (l->v != l->radial_next->v) {
+ a1 = sides * y + sides - 2;
+ a2 = (sides - 2) * sides + y;
+
+ o1 = sides * y + sides - 1;
+ o2 = (sides - 1) * sides + y;
+ }
+ else {
+ a1 = sides * y + sides - 2;
+ a2 = sides * y + sides - 2;
+ o1 = sides * y + sides - 1;
+ o2 = sides * y + sides - 1;
+ }
+
+ /* magic blending numbers, hardcoded! */
+ add_v3_v3v3(co1, mdl1->disps[a1], mdl2->disps[a2]);
+ mul_v3_fl(co1, 0.18);
+
+ add_v3_v3v3(co2, mdl1->disps[o1], mdl2->disps[o2]);
+ mul_v3_fl(co2, 0.32);
+
+ add_v3_v3v3(co, co1, co2);
+
+ copy_v3_v3(mdl1->disps[o1], co);
+ copy_v3_v3(mdl2->disps[o2], co);
+ }
+ }
}
/**
@@ -679,290 +732,288 @@ void BM_face_multires_bounds_smooth(BMesh *bm, BMFace *f)
* if do_vertex is true, target's vert data will also get interpolated.
*/
void BM_loop_interp_from_face(
- BMesh *bm, BMLoop *l_dst, const BMFace *f_src,
- const bool do_vertex, const bool do_multires)
+ BMesh *bm, BMLoop *l_dst, const BMFace *f_src, const bool do_vertex, const bool do_multires)
{
- BMLoop *l_iter;
- BMLoop *l_first;
- const void **vblocks = do_vertex ? BLI_array_alloca(vblocks, f_src->len) : NULL;
- const void **blocks = BLI_array_alloca(blocks, f_src->len);
- float (*cos_2d)[2] = BLI_array_alloca(cos_2d, f_src->len);
- float *w = BLI_array_alloca(w, f_src->len);
- float axis_mat[3][3]; /* use normal to transform into 2d xy coords */
- float co[2];
- int i;
-
- /* convert the 3d coords into 2d for projection */
- BLI_assert(BM_face_is_normal_valid(f_src));
- axis_dominant_v3_to_m3(axis_mat, f_src->no);
-
- i = 0;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f_src);
- do {
- mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co);
- blocks[i] = l_iter->head.data;
-
- if (do_vertex) {
- vblocks[i] = l_iter->v->head.data;
- }
- } while ((void)i++, (l_iter = l_iter->next) != l_first);
-
- mul_v2_m3v3(co, axis_mat, l_dst->v->co);
-
- /* interpolate */
- interp_weights_poly_v2(w, cos_2d, f_src->len, co);
- CustomData_bmesh_interp(&bm->ldata, blocks, w, NULL, f_src->len, l_dst->head.data);
- if (do_vertex) {
- CustomData_bmesh_interp(&bm->vdata, vblocks, w, NULL, f_src->len, l_dst->v->head.data);
- }
-
- if (do_multires) {
- BM_loop_interp_multires(bm, l_dst, f_src);
- }
+ BMLoop *l_iter;
+ BMLoop *l_first;
+ const void **vblocks = do_vertex ? BLI_array_alloca(vblocks, f_src->len) : NULL;
+ const void **blocks = BLI_array_alloca(blocks, f_src->len);
+ float(*cos_2d)[2] = BLI_array_alloca(cos_2d, f_src->len);
+ float *w = BLI_array_alloca(w, f_src->len);
+ float axis_mat[3][3]; /* use normal to transform into 2d xy coords */
+ float co[2];
+ int i;
+
+ /* convert the 3d coords into 2d for projection */
+ BLI_assert(BM_face_is_normal_valid(f_src));
+ axis_dominant_v3_to_m3(axis_mat, f_src->no);
+
+ i = 0;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_src);
+ do {
+ mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co);
+ blocks[i] = l_iter->head.data;
+
+ if (do_vertex) {
+ vblocks[i] = l_iter->v->head.data;
+ }
+ } while ((void)i++, (l_iter = l_iter->next) != l_first);
+
+ mul_v2_m3v3(co, axis_mat, l_dst->v->co);
+
+ /* interpolate */
+ interp_weights_poly_v2(w, cos_2d, f_src->len, co);
+ CustomData_bmesh_interp(&bm->ldata, blocks, w, NULL, f_src->len, l_dst->head.data);
+ if (do_vertex) {
+ CustomData_bmesh_interp(&bm->vdata, vblocks, w, NULL, f_src->len, l_dst->v->head.data);
+ }
+
+ if (do_multires) {
+ BM_loop_interp_multires(bm, l_dst, f_src);
+ }
}
-
void BM_vert_interp_from_face(BMesh *bm, BMVert *v_dst, const BMFace *f_src)
{
- BMLoop *l_iter;
- BMLoop *l_first;
- const void **blocks = BLI_array_alloca(blocks, f_src->len);
- float (*cos_2d)[2] = BLI_array_alloca(cos_2d, f_src->len);
- float *w = BLI_array_alloca(w, f_src->len);
- float axis_mat[3][3]; /* use normal to transform into 2d xy coords */
- float co[2];
- int i;
-
- /* convert the 3d coords into 2d for projection */
- BLI_assert(BM_face_is_normal_valid(f_src));
- axis_dominant_v3_to_m3(axis_mat, f_src->no);
-
- i = 0;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f_src);
- do {
- mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co);
- blocks[i] = l_iter->v->head.data;
- } while ((void)i++, (l_iter = l_iter->next) != l_first);
-
- mul_v2_m3v3(co, axis_mat, v_dst->co);
-
- /* interpolate */
- interp_weights_poly_v2(w, cos_2d, f_src->len, co);
- CustomData_bmesh_interp(&bm->vdata, blocks, w, NULL, f_src->len, v_dst->head.data);
+ BMLoop *l_iter;
+ BMLoop *l_first;
+ const void **blocks = BLI_array_alloca(blocks, f_src->len);
+ float(*cos_2d)[2] = BLI_array_alloca(cos_2d, f_src->len);
+ float *w = BLI_array_alloca(w, f_src->len);
+ float axis_mat[3][3]; /* use normal to transform into 2d xy coords */
+ float co[2];
+ int i;
+
+ /* convert the 3d coords into 2d for projection */
+ BLI_assert(BM_face_is_normal_valid(f_src));
+ axis_dominant_v3_to_m3(axis_mat, f_src->no);
+
+ i = 0;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_src);
+ do {
+ mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co);
+ blocks[i] = l_iter->v->head.data;
+ } while ((void)i++, (l_iter = l_iter->next) != l_first);
+
+ mul_v2_m3v3(co, axis_mat, v_dst->co);
+
+ /* interpolate */
+ interp_weights_poly_v2(w, cos_2d, f_src->len, co);
+ CustomData_bmesh_interp(&bm->vdata, blocks, w, NULL, f_src->len, v_dst->head.data);
}
static void update_data_blocks(BMesh *bm, CustomData *olddata, CustomData *data)
{
- BMIter iter;
- BLI_mempool *oldpool = olddata->pool;
- void *block;
-
- if (data == &bm->vdata) {
- BMVert *eve;
-
- CustomData_bmesh_init_pool(data, bm->totvert, BM_VERT);
-
- BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
- block = NULL;
- CustomData_bmesh_set_default(data, &block);
- CustomData_bmesh_copy_data(olddata, data, eve->head.data, &block);
- CustomData_bmesh_free_block(olddata, &eve->head.data);
- eve->head.data = block;
- }
- }
- else if (data == &bm->edata) {
- BMEdge *eed;
-
- CustomData_bmesh_init_pool(data, bm->totedge, BM_EDGE);
-
- BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
- block = NULL;
- CustomData_bmesh_set_default(data, &block);
- CustomData_bmesh_copy_data(olddata, data, eed->head.data, &block);
- CustomData_bmesh_free_block(olddata, &eed->head.data);
- eed->head.data = block;
- }
- }
- else if (data == &bm->ldata) {
- BMIter liter;
- BMFace *efa;
- BMLoop *l;
-
- CustomData_bmesh_init_pool(data, bm->totloop, BM_LOOP);
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- block = NULL;
- CustomData_bmesh_set_default(data, &block);
- CustomData_bmesh_copy_data(olddata, data, l->head.data, &block);
- CustomData_bmesh_free_block(olddata, &l->head.data);
- l->head.data = block;
- }
- }
- }
- else if (data == &bm->pdata) {
- BMFace *efa;
-
- CustomData_bmesh_init_pool(data, bm->totface, BM_FACE);
-
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- block = NULL;
- CustomData_bmesh_set_default(data, &block);
- CustomData_bmesh_copy_data(olddata, data, efa->head.data, &block);
- CustomData_bmesh_free_block(olddata, &efa->head.data);
- efa->head.data = block;
- }
- }
- else {
- /* should never reach this! */
- BLI_assert(0);
- }
-
- if (oldpool) {
- /* this should never happen but can when dissolve fails - [#28960] */
- BLI_assert(data->pool != oldpool);
-
- BLI_mempool_destroy(oldpool);
- }
+ BMIter iter;
+ BLI_mempool *oldpool = olddata->pool;
+ void *block;
+
+ if (data == &bm->vdata) {
+ BMVert *eve;
+
+ CustomData_bmesh_init_pool(data, bm->totvert, BM_VERT);
+
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ block = NULL;
+ CustomData_bmesh_set_default(data, &block);
+ CustomData_bmesh_copy_data(olddata, data, eve->head.data, &block);
+ CustomData_bmesh_free_block(olddata, &eve->head.data);
+ eve->head.data = block;
+ }
+ }
+ else if (data == &bm->edata) {
+ BMEdge *eed;
+
+ CustomData_bmesh_init_pool(data, bm->totedge, BM_EDGE);
+
+ BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
+ block = NULL;
+ CustomData_bmesh_set_default(data, &block);
+ CustomData_bmesh_copy_data(olddata, data, eed->head.data, &block);
+ CustomData_bmesh_free_block(olddata, &eed->head.data);
+ eed->head.data = block;
+ }
+ }
+ else if (data == &bm->ldata) {
+ BMIter liter;
+ BMFace *efa;
+ BMLoop *l;
+
+ CustomData_bmesh_init_pool(data, bm->totloop, BM_LOOP);
+ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ block = NULL;
+ CustomData_bmesh_set_default(data, &block);
+ CustomData_bmesh_copy_data(olddata, data, l->head.data, &block);
+ CustomData_bmesh_free_block(olddata, &l->head.data);
+ l->head.data = block;
+ }
+ }
+ }
+ else if (data == &bm->pdata) {
+ BMFace *efa;
+
+ CustomData_bmesh_init_pool(data, bm->totface, BM_FACE);
+
+ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
+ block = NULL;
+ CustomData_bmesh_set_default(data, &block);
+ CustomData_bmesh_copy_data(olddata, data, efa->head.data, &block);
+ CustomData_bmesh_free_block(olddata, &efa->head.data);
+ efa->head.data = block;
+ }
+ }
+ else {
+ /* should never reach this! */
+ BLI_assert(0);
+ }
+
+ if (oldpool) {
+ /* this should never happen but can when dissolve fails - [#28960] */
+ BLI_assert(data->pool != oldpool);
+
+ BLI_mempool_destroy(oldpool);
+ }
}
void BM_data_layer_add(BMesh *bm, CustomData *data, int type)
{
- CustomData olddata;
+ CustomData olddata;
- olddata = *data;
- olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL;
+ olddata = *data;
+ olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL;
- /* the pool is now owned by olddata and must not be shared */
- data->pool = NULL;
+ /* the pool is now owned by olddata and must not be shared */
+ data->pool = NULL;
- CustomData_add_layer(data, type, CD_DEFAULT, NULL, 0);
+ CustomData_add_layer(data, type, CD_DEFAULT, NULL, 0);
- update_data_blocks(bm, &olddata, data);
- if (olddata.layers) {
- MEM_freeN(olddata.layers);
- }
+ update_data_blocks(bm, &olddata, data);
+ if (olddata.layers) {
+ MEM_freeN(olddata.layers);
+ }
}
void BM_data_layer_add_named(BMesh *bm, CustomData *data, int type, const char *name)
{
- CustomData olddata;
+ CustomData olddata;
- olddata = *data;
- olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL;
+ olddata = *data;
+ olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL;
- /* the pool is now owned by olddata and must not be shared */
- data->pool = NULL;
+ /* the pool is now owned by olddata and must not be shared */
+ data->pool = NULL;
- CustomData_add_layer_named(data, type, CD_DEFAULT, NULL, 0, name);
+ CustomData_add_layer_named(data, type, CD_DEFAULT, NULL, 0, name);
- update_data_blocks(bm, &olddata, data);
- if (olddata.layers) {
- MEM_freeN(olddata.layers);
- }
+ update_data_blocks(bm, &olddata, data);
+ if (olddata.layers) {
+ MEM_freeN(olddata.layers);
+ }
}
void BM_data_layer_free(BMesh *bm, CustomData *data, int type)
{
- CustomData olddata;
- bool has_layer;
+ CustomData olddata;
+ bool has_layer;
- olddata = *data;
- olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL;
+ olddata = *data;
+ olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL;
- /* the pool is now owned by olddata and must not be shared */
- data->pool = NULL;
+ /* the pool is now owned by olddata and must not be shared */
+ data->pool = NULL;
- has_layer = CustomData_free_layer_active(data, type, 0);
- /* assert because its expensive to realloc - better not do if layer isnt present */
- BLI_assert(has_layer != false);
- UNUSED_VARS_NDEBUG(has_layer);
+ has_layer = CustomData_free_layer_active(data, type, 0);
+ /* assert because its expensive to realloc - better not do if layer isnt present */
+ BLI_assert(has_layer != false);
+ UNUSED_VARS_NDEBUG(has_layer);
- update_data_blocks(bm, &olddata, data);
- if (olddata.layers) {
- MEM_freeN(olddata.layers);
- }
+ update_data_blocks(bm, &olddata, data);
+ if (olddata.layers) {
+ MEM_freeN(olddata.layers);
+ }
}
void BM_data_layer_free_n(BMesh *bm, CustomData *data, int type, int n)
{
- CustomData olddata;
- bool has_layer;
+ CustomData olddata;
+ bool has_layer;
- olddata = *data;
- olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL;
+ olddata = *data;
+ olddata.layers = (olddata.layers) ? MEM_dupallocN(olddata.layers) : NULL;
- /* the pool is now owned by olddata and must not be shared */
- data->pool = NULL;
+ /* the pool is now owned by olddata and must not be shared */
+ data->pool = NULL;
- has_layer = CustomData_free_layer(data, type, 0, CustomData_get_layer_index_n(data, type, n));
- /* assert because its expensive to realloc - better not do if layer isnt present */
- BLI_assert(has_layer != false);
- UNUSED_VARS_NDEBUG(has_layer);
+ has_layer = CustomData_free_layer(data, type, 0, CustomData_get_layer_index_n(data, type, n));
+ /* assert because its expensive to realloc - better not do if layer isnt present */
+ BLI_assert(has_layer != false);
+ UNUSED_VARS_NDEBUG(has_layer);
- update_data_blocks(bm, &olddata, data);
- if (olddata.layers) {
- MEM_freeN(olddata.layers);
- }
+ update_data_blocks(bm, &olddata, data);
+ if (olddata.layers) {
+ MEM_freeN(olddata.layers);
+ }
}
void BM_data_layer_copy(BMesh *bm, CustomData *data, int type, int src_n, int dst_n)
{
- BMIter iter;
-
- if (&bm->vdata == data) {
- BMVert *eve;
-
- BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
- void *ptr = CustomData_bmesh_get_n(data, eve->head.data, type, src_n);
- CustomData_bmesh_set_n(data, eve->head.data, type, dst_n, ptr);
- }
- }
- else if (&bm->edata == data) {
- BMEdge *eed;
-
- BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
- void *ptr = CustomData_bmesh_get_n(data, eed->head.data, type, src_n);
- CustomData_bmesh_set_n(data, eed->head.data, type, dst_n, ptr);
- }
- }
- else if (&bm->pdata == data) {
- BMFace *efa;
-
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- void *ptr = CustomData_bmesh_get_n(data, efa->head.data, type, src_n);
- CustomData_bmesh_set_n(data, efa->head.data, type, dst_n, ptr);
- }
- }
- else if (&bm->ldata == data) {
- BMIter liter;
- BMFace *efa;
- BMLoop *l;
-
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- void *ptr = CustomData_bmesh_get_n(data, l->head.data, type, src_n);
- CustomData_bmesh_set_n(data, l->head.data, type, dst_n, ptr);
- }
- }
- }
- else {
- /* should never reach this! */
- BLI_assert(0);
- }
+ BMIter iter;
+
+ if (&bm->vdata == data) {
+ BMVert *eve;
+
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+ void *ptr = CustomData_bmesh_get_n(data, eve->head.data, type, src_n);
+ CustomData_bmesh_set_n(data, eve->head.data, type, dst_n, ptr);
+ }
+ }
+ else if (&bm->edata == data) {
+ BMEdge *eed;
+
+ BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
+ void *ptr = CustomData_bmesh_get_n(data, eed->head.data, type, src_n);
+ CustomData_bmesh_set_n(data, eed->head.data, type, dst_n, ptr);
+ }
+ }
+ else if (&bm->pdata == data) {
+ BMFace *efa;
+
+ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
+ void *ptr = CustomData_bmesh_get_n(data, efa->head.data, type, src_n);
+ CustomData_bmesh_set_n(data, efa->head.data, type, dst_n, ptr);
+ }
+ }
+ else if (&bm->ldata == data) {
+ BMIter liter;
+ BMFace *efa;
+ BMLoop *l;
+
+ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ void *ptr = CustomData_bmesh_get_n(data, l->head.data, type, src_n);
+ CustomData_bmesh_set_n(data, l->head.data, type, dst_n, ptr);
+ }
+ }
+ }
+ else {
+ /* should never reach this! */
+ BLI_assert(0);
+ }
}
float BM_elem_float_data_get(CustomData *cd, void *element, int type)
{
- const float *f = CustomData_bmesh_get(cd, ((BMHeader *)element)->data, type);
- return f ? *f : 0.0f;
+ const float *f = CustomData_bmesh_get(cd, ((BMHeader *)element)->data, type);
+ return f ? *f : 0.0f;
}
void BM_elem_float_data_set(CustomData *cd, void *element, int type, const float val)
{
- float *f = CustomData_bmesh_get(cd, ((BMHeader *)element)->data, type);
- if (f) {
- *f = val;
- }
+ float *f = CustomData_bmesh_get(cd, ((BMHeader *)element)->data, type);
+ if (f) {
+ *f = val;
+ }
}
/** \name Loop interpolation functions: BM_vert_loop_groups_data_layer_***
@@ -984,51 +1035,51 @@ void BM_elem_float_data_set(CustomData *cd, void *element, int type, const float
* \{ */
struct LoopWalkCtx {
- /* same for all groups */
- int type;
- int cd_layer_offset;
- const float *loop_weights;
- MemArena *arena;
-
- /* --- Per loop fan vars --- */
-
- /* reference for this contiguous fan */
- const void *data_ref;
- int data_len;
-
- /* accumulate 'LoopGroupCD.weight' to make unit length */
- float weight_accum;
-
- /* both arrays the size of the 'BM_vert_face_count(v)'
- * each contiguous fan gets a slide of these arrays */
- void **data_array;
- int *data_index_array;
- float *weight_array;
+ /* same for all groups */
+ int type;
+ int cd_layer_offset;
+ const float *loop_weights;
+ MemArena *arena;
+
+ /* --- Per loop fan vars --- */
+
+ /* reference for this contiguous fan */
+ const void *data_ref;
+ int data_len;
+
+ /* accumulate 'LoopGroupCD.weight' to make unit length */
+ float weight_accum;
+
+ /* both arrays the size of the 'BM_vert_face_count(v)'
+ * each contiguous fan gets a slide of these arrays */
+ void **data_array;
+ int *data_index_array;
+ float *weight_array;
};
/* Store vars to pass into 'CustomData_bmesh_interp' */
struct LoopGroupCD {
- /* direct customdata pointer array */
- void **data;
- /* weights (aligned with 'data') */
- float *data_weights;
- /* index-in-face */
- int *data_index;
- /* number of loops in the fan */
- int data_len;
+ /* direct customdata pointer array */
+ void **data;
+ /* weights (aligned with 'data') */
+ float *data_weights;
+ /* index-in-face */
+ int *data_index;
+ /* number of loops in the fan */
+ int data_len;
};
static void bm_loop_walk_add(struct LoopWalkCtx *lwc, BMLoop *l)
{
- const int i = BM_elem_index_get(l);
- const float w = lwc->loop_weights[i];
- BM_elem_flag_disable(l, BM_ELEM_INTERNAL_TAG);
- lwc->data_array[lwc->data_len] = BM_ELEM_CD_GET_VOID_P(l, lwc->cd_layer_offset);
- lwc->data_index_array[lwc->data_len] = i;
- lwc->weight_array[lwc->data_len] = w;
- lwc->weight_accum += w;
-
- lwc->data_len += 1;
+ const int i = BM_elem_index_get(l);
+ const float w = lwc->loop_weights[i];
+ BM_elem_flag_disable(l, BM_ELEM_INTERNAL_TAG);
+ lwc->data_array[lwc->data_len] = BM_ELEM_CD_GET_VOID_P(l, lwc->cd_layer_offset);
+ lwc->data_index_array[lwc->data_len] = i;
+ lwc->weight_array[lwc->data_len] = w;
+ lwc->weight_accum += w;
+
+ lwc->data_len += 1;
}
/**
@@ -1038,146 +1089,145 @@ static void bm_loop_walk_add(struct LoopWalkCtx *lwc, BMLoop *l)
*/
static void bm_loop_walk_data(struct LoopWalkCtx *lwc, BMLoop *l_walk)
{
- int i;
-
- BLI_assert(CustomData_data_equals(lwc->type, lwc->data_ref, BM_ELEM_CD_GET_VOID_P(l_walk, lwc->cd_layer_offset)));
- BLI_assert(BM_elem_flag_test(l_walk, BM_ELEM_INTERNAL_TAG));
-
- bm_loop_walk_add(lwc, l_walk);
-
- /* recurse around this loop-fan (in both directions) */
- for (i = 0; i < 2; i++) {
- BMLoop *l_other = ((i == 0) ? l_walk : l_walk->prev)->radial_next;
- if (l_other->radial_next != l_other) {
- if (l_other->v != l_walk->v) {
- l_other = l_other->next;
- }
- BLI_assert(l_other->v == l_walk->v);
- if (BM_elem_flag_test(l_other, BM_ELEM_INTERNAL_TAG)) {
- if (CustomData_data_equals(lwc->type, lwc->data_ref, BM_ELEM_CD_GET_VOID_P(l_other, lwc->cd_layer_offset))) {
- bm_loop_walk_data(lwc, l_other);
- }
- }
- }
- }
+ int i;
+
+ BLI_assert(CustomData_data_equals(
+ lwc->type, lwc->data_ref, BM_ELEM_CD_GET_VOID_P(l_walk, lwc->cd_layer_offset)));
+ BLI_assert(BM_elem_flag_test(l_walk, BM_ELEM_INTERNAL_TAG));
+
+ bm_loop_walk_add(lwc, l_walk);
+
+ /* recurse around this loop-fan (in both directions) */
+ for (i = 0; i < 2; i++) {
+ BMLoop *l_other = ((i == 0) ? l_walk : l_walk->prev)->radial_next;
+ if (l_other->radial_next != l_other) {
+ if (l_other->v != l_walk->v) {
+ l_other = l_other->next;
+ }
+ BLI_assert(l_other->v == l_walk->v);
+ if (BM_elem_flag_test(l_other, BM_ELEM_INTERNAL_TAG)) {
+ if (CustomData_data_equals(
+ lwc->type, lwc->data_ref, BM_ELEM_CD_GET_VOID_P(l_other, lwc->cd_layer_offset))) {
+ bm_loop_walk_data(lwc, l_other);
+ }
+ }
+ }
+ }
}
LinkNode *BM_vert_loop_groups_data_layer_create(
- BMesh *bm, BMVert *v, const int layer_n, const float *loop_weights, MemArena *arena)
+ BMesh *bm, BMVert *v, const int layer_n, const float *loop_weights, MemArena *arena)
{
- struct LoopWalkCtx lwc;
- LinkNode *groups = NULL;
- BMLoop *l;
- BMIter liter;
- int loop_num;
-
-
- lwc.type = bm->ldata.layers[layer_n].type;
- lwc.cd_layer_offset = bm->ldata.layers[layer_n].offset;
- lwc.loop_weights = loop_weights;
- lwc.arena = arena;
-
- /* Enable 'BM_ELEM_INTERNAL_TAG', leaving the flag clean on completion. */
- loop_num = 0;
- BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
- BM_elem_flag_enable(l, BM_ELEM_INTERNAL_TAG);
- BM_elem_index_set(l, loop_num); /* set_dirty! */
- loop_num++;
- }
- bm->elem_index_dirty |= BM_LOOP;
-
- lwc.data_len = 0;
- lwc.data_array = BLI_memarena_alloc(lwc.arena, sizeof(void *) * loop_num);
- lwc.data_index_array = BLI_memarena_alloc(lwc.arena, sizeof(int) * loop_num);
- lwc.weight_array = BLI_memarena_alloc(lwc.arena, sizeof(float) * loop_num);
-
- BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
- if (BM_elem_flag_test(l, BM_ELEM_INTERNAL_TAG)) {
- struct LoopGroupCD *lf = BLI_memarena_alloc(lwc.arena, sizeof(*lf));
- int len_prev = lwc.data_len;
-
- lwc.data_ref = BM_ELEM_CD_GET_VOID_P(l, lwc.cd_layer_offset);
-
- /* assign len-last */
- lf->data = &lwc.data_array[lwc.data_len];
- lf->data_index = &lwc.data_index_array[lwc.data_len];
- lf->data_weights = &lwc.weight_array[lwc.data_len];
- lwc.weight_accum = 0.0f;
-
- /* new group */
- bm_loop_walk_data(&lwc, l);
- lf->data_len = lwc.data_len - len_prev;
-
- if (LIKELY(lwc.weight_accum != 0.0f)) {
- mul_vn_fl(lf->data_weights, lf->data_len, 1.0f / lwc.weight_accum);
- }
- else {
- copy_vn_fl(lf->data_weights, lf->data_len, 1.0f / (float)lf->data_len);
- }
-
- BLI_linklist_prepend_arena(&groups, lf, lwc.arena);
- }
- }
-
- BLI_assert(lwc.data_len == loop_num);
-
- return groups;
+ struct LoopWalkCtx lwc;
+ LinkNode *groups = NULL;
+ BMLoop *l;
+ BMIter liter;
+ int loop_num;
+
+ lwc.type = bm->ldata.layers[layer_n].type;
+ lwc.cd_layer_offset = bm->ldata.layers[layer_n].offset;
+ lwc.loop_weights = loop_weights;
+ lwc.arena = arena;
+
+ /* Enable 'BM_ELEM_INTERNAL_TAG', leaving the flag clean on completion. */
+ loop_num = 0;
+ BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
+ BM_elem_flag_enable(l, BM_ELEM_INTERNAL_TAG);
+ BM_elem_index_set(l, loop_num); /* set_dirty! */
+ loop_num++;
+ }
+ bm->elem_index_dirty |= BM_LOOP;
+
+ lwc.data_len = 0;
+ lwc.data_array = BLI_memarena_alloc(lwc.arena, sizeof(void *) * loop_num);
+ lwc.data_index_array = BLI_memarena_alloc(lwc.arena, sizeof(int) * loop_num);
+ lwc.weight_array = BLI_memarena_alloc(lwc.arena, sizeof(float) * loop_num);
+
+ BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
+ if (BM_elem_flag_test(l, BM_ELEM_INTERNAL_TAG)) {
+ struct LoopGroupCD *lf = BLI_memarena_alloc(lwc.arena, sizeof(*lf));
+ int len_prev = lwc.data_len;
+
+ lwc.data_ref = BM_ELEM_CD_GET_VOID_P(l, lwc.cd_layer_offset);
+
+ /* assign len-last */
+ lf->data = &lwc.data_array[lwc.data_len];
+ lf->data_index = &lwc.data_index_array[lwc.data_len];
+ lf->data_weights = &lwc.weight_array[lwc.data_len];
+ lwc.weight_accum = 0.0f;
+
+ /* new group */
+ bm_loop_walk_data(&lwc, l);
+ lf->data_len = lwc.data_len - len_prev;
+
+ if (LIKELY(lwc.weight_accum != 0.0f)) {
+ mul_vn_fl(lf->data_weights, lf->data_len, 1.0f / lwc.weight_accum);
+ }
+ else {
+ copy_vn_fl(lf->data_weights, lf->data_len, 1.0f / (float)lf->data_len);
+ }
+
+ BLI_linklist_prepend_arena(&groups, lf, lwc.arena);
+ }
+ }
+
+ BLI_assert(lwc.data_len == loop_num);
+
+ return groups;
}
-static void bm_vert_loop_groups_data_layer_merge__single(
- BMesh *bm, void *lf_p, int layer_n,
- void *data_tmp)
+static void bm_vert_loop_groups_data_layer_merge__single(BMesh *bm,
+ void *lf_p,
+ int layer_n,
+ void *data_tmp)
{
- struct LoopGroupCD *lf = lf_p;
- const int type = bm->ldata.layers[layer_n].type;
- int i;
- const float *data_weights;
+ struct LoopGroupCD *lf = lf_p;
+ const int type = bm->ldata.layers[layer_n].type;
+ int i;
+ const float *data_weights;
- data_weights = lf->data_weights;
+ data_weights = lf->data_weights;
- CustomData_bmesh_interp_n(
- &bm->ldata, (const void **)lf->data,
- data_weights, NULL, lf->data_len, data_tmp, layer_n);
+ CustomData_bmesh_interp_n(
+ &bm->ldata, (const void **)lf->data, data_weights, NULL, lf->data_len, data_tmp, layer_n);
- for (i = 0; i < lf->data_len; i++) {
- CustomData_copy_elements(type, data_tmp, lf->data[i], 1);
- }
+ for (i = 0; i < lf->data_len; i++) {
+ CustomData_copy_elements(type, data_tmp, lf->data[i], 1);
+ }
}
static void bm_vert_loop_groups_data_layer_merge_weights__single(
- BMesh *bm, void *lf_p, const int layer_n, void *data_tmp,
- const float *loop_weights)
+ BMesh *bm, void *lf_p, const int layer_n, void *data_tmp, const float *loop_weights)
{
- struct LoopGroupCD *lf = lf_p;
- const int type = bm->ldata.layers[layer_n].type;
- int i;
- const float *data_weights;
-
- /* re-weight */
- float *temp_weights = BLI_array_alloca(temp_weights, lf->data_len);
- float weight_accum = 0.0f;
-
- for (i = 0; i < lf->data_len; i++) {
- float w = loop_weights[lf->data_index[i]] * lf->data_weights[i];
- temp_weights[i] = w;
- weight_accum += w;
- }
-
- if (LIKELY(weight_accum != 0.0f)) {
- mul_vn_fl(temp_weights, lf->data_len, 1.0f / weight_accum);
- data_weights = temp_weights;
- }
- else {
- data_weights = lf->data_weights;
- }
-
- CustomData_bmesh_interp_n(
- &bm->ldata, (const void **)lf->data,
- data_weights, NULL, lf->data_len, data_tmp, layer_n);
-
- for (i = 0; i < lf->data_len; i++) {
- CustomData_copy_elements(type, data_tmp, lf->data[i], 1);
- }
+ struct LoopGroupCD *lf = lf_p;
+ const int type = bm->ldata.layers[layer_n].type;
+ int i;
+ const float *data_weights;
+
+ /* re-weight */
+ float *temp_weights = BLI_array_alloca(temp_weights, lf->data_len);
+ float weight_accum = 0.0f;
+
+ for (i = 0; i < lf->data_len; i++) {
+ float w = loop_weights[lf->data_index[i]] * lf->data_weights[i];
+ temp_weights[i] = w;
+ weight_accum += w;
+ }
+
+ if (LIKELY(weight_accum != 0.0f)) {
+ mul_vn_fl(temp_weights, lf->data_len, 1.0f / weight_accum);
+ data_weights = temp_weights;
+ }
+ else {
+ data_weights = lf->data_weights;
+ }
+
+ CustomData_bmesh_interp_n(
+ &bm->ldata, (const void **)lf->data, data_weights, NULL, lf->data_len, data_tmp, layer_n);
+
+ for (i = 0; i < lf->data_len; i++) {
+ CustomData_copy_elements(type, data_tmp, lf->data[i], 1);
+ }
}
/**
@@ -1185,29 +1235,32 @@ static void bm_vert_loop_groups_data_layer_merge_weights__single(
*/
void BM_vert_loop_groups_data_layer_merge(BMesh *bm, LinkNode *groups, const int layer_n)
{
- const int type = bm->ldata.layers[layer_n].type;
- const int size = CustomData_sizeof(type);
- void *data_tmp = alloca(size);
+ const int type = bm->ldata.layers[layer_n].type;
+ const int size = CustomData_sizeof(type);
+ void *data_tmp = alloca(size);
- do {
- bm_vert_loop_groups_data_layer_merge__single(bm, groups->link, layer_n, data_tmp);
- } while ((groups = groups->next));
+ do {
+ bm_vert_loop_groups_data_layer_merge__single(bm, groups->link, layer_n, data_tmp);
+ } while ((groups = groups->next));
}
/**
* A version of #BM_vert_loop_groups_data_layer_merge
* that takes an array of loop-weights (aligned with #BM_LOOPS_OF_VERT iterator)
*/
-void BM_vert_loop_groups_data_layer_merge_weights(
- BMesh *bm, LinkNode *groups, const int layer_n, const float *loop_weights)
+void BM_vert_loop_groups_data_layer_merge_weights(BMesh *bm,
+ LinkNode *groups,
+ const int layer_n,
+ const float *loop_weights)
{
- const int type = bm->ldata.layers[layer_n].type;
- const int size = CustomData_sizeof(type);
- void *data_tmp = alloca(size);
-
- do {
- bm_vert_loop_groups_data_layer_merge_weights__single(bm, groups->link, layer_n, data_tmp, loop_weights);
- } while ((groups = groups->next));
+ const int type = bm->ldata.layers[layer_n].type;
+ const int size = CustomData_sizeof(type);
+ void *data_tmp = alloca(size);
+
+ do {
+ bm_vert_loop_groups_data_layer_merge_weights__single(
+ bm, groups->link, layer_n, data_tmp, loop_weights);
+ } while ((groups = groups->next));
}
/** \} */
diff --git a/source/blender/bmesh/intern/bmesh_interp.h b/source/blender/bmesh/intern/bmesh_interp.h
index ce6eb2186c5..bd3824ed3fd 100644
--- a/source/blender/bmesh/intern/bmesh_interp.h
+++ b/source/blender/bmesh/intern/bmesh_interp.h
@@ -24,51 +24,63 @@
struct LinkNode;
struct MemArena;
-void BM_loop_interp_multires_ex(
- BMesh *bm, BMLoop *l_dst, const BMFace *f_src,
- const float f_dst_center[3], const float f_src_center[3], const int cd_loop_mdisp_offset);
-void BM_loop_interp_multires(
- BMesh *bm, BMLoop *l_dst, const BMFace *f_src);
+void BM_loop_interp_multires_ex(BMesh *bm,
+ BMLoop *l_dst,
+ const BMFace *f_src,
+ const float f_dst_center[3],
+ const float f_src_center[3],
+ const int cd_loop_mdisp_offset);
+void BM_loop_interp_multires(BMesh *bm, BMLoop *l_dst, const BMFace *f_src);
-void BM_face_interp_multires_ex(
- BMesh *UNUSED(bm), BMFace *f_dst, const BMFace *f_src,
- const float f_dst_center[3], const float f_src_center[3], const int cd_loop_mdisp_offset);
+void BM_face_interp_multires_ex(BMesh *UNUSED(bm),
+ BMFace *f_dst,
+ const BMFace *f_src,
+ const float f_dst_center[3],
+ const float f_src_center[3],
+ const int cd_loop_mdisp_offset);
void BM_face_interp_multires(BMesh *bm, BMFace *f_dst, const BMFace *f_src);
-void BM_vert_interp_from_face(BMesh *bm, BMVert *v_dst, const BMFace *f_src);
+void BM_vert_interp_from_face(BMesh *bm, BMVert *v_dst, const BMFace *f_src);
-void BM_data_interp_from_verts(BMesh *bm, const BMVert *v_src_1, const BMVert *v_src_2, BMVert *v_dst, const float fac);
-void BM_data_interp_from_edges(BMesh *bm, const BMEdge *e_src_1, const BMEdge *e_src_2, BMEdge *e_dst, const float fac);
-void BM_data_interp_face_vert_edge(BMesh *bm, const BMVert *v_src_1, const BMVert *v_src_2, BMVert *v, BMEdge *e, const float fac);
-void BM_data_layer_add(BMesh *bm, CustomData *data, int type);
-void BM_data_layer_add_named(BMesh *bm, CustomData *data, int type, const char *name);
-void BM_data_layer_free(BMesh *bm, CustomData *data, int type);
-void BM_data_layer_free_n(BMesh *bm, CustomData *data, int type, int n);
-void BM_data_layer_copy(BMesh *bm, CustomData *data, int type, int src_n, int dst_n);
+void BM_data_interp_from_verts(
+ BMesh *bm, const BMVert *v_src_1, const BMVert *v_src_2, BMVert *v_dst, const float fac);
+void BM_data_interp_from_edges(
+ BMesh *bm, const BMEdge *e_src_1, const BMEdge *e_src_2, BMEdge *e_dst, const float fac);
+void BM_data_interp_face_vert_edge(BMesh *bm,
+ const BMVert *v_src_1,
+ const BMVert *v_src_2,
+ BMVert *v,
+ BMEdge *e,
+ const float fac);
+void BM_data_layer_add(BMesh *bm, CustomData *data, int type);
+void BM_data_layer_add_named(BMesh *bm, CustomData *data, int type, const char *name);
+void BM_data_layer_free(BMesh *bm, CustomData *data, int type);
+void BM_data_layer_free_n(BMesh *bm, CustomData *data, int type, int n);
+void BM_data_layer_copy(BMesh *bm, CustomData *data, int type, int src_n, int dst_n);
float BM_elem_float_data_get(CustomData *cd, void *element, int type);
-void BM_elem_float_data_set(CustomData *cd, void *element, int type, const float val);
+void BM_elem_float_data_set(CustomData *cd, void *element, int type, const float val);
-void BM_face_interp_from_face_ex(
- BMesh *bm, BMFace *f_dst, const BMFace *f_src, const bool do_vertex,
- const void **blocks, const void **blocks_v,
- float (*cos_2d)[2], float axis_mat[3][3]);
-void BM_face_interp_from_face(
- BMesh *bm, BMFace *f_dst, const BMFace *f_src,
- const bool do_vertex);
-void BM_loop_interp_from_face(
- BMesh *bm, BMLoop *l_dst, const BMFace *f_src,
- const bool do_vertex, const bool do_multires);
+void BM_face_interp_from_face_ex(BMesh *bm,
+ BMFace *f_dst,
+ const BMFace *f_src,
+ const bool do_vertex,
+ const void **blocks,
+ const void **blocks_v,
+ float (*cos_2d)[2],
+ float axis_mat[3][3]);
+void BM_face_interp_from_face(BMesh *bm, BMFace *f_dst, const BMFace *f_src, const bool do_vertex);
+void BM_loop_interp_from_face(
+ BMesh *bm, BMLoop *l_dst, const BMFace *f_src, const bool do_vertex, const bool do_multires);
-void BM_face_multires_bounds_smooth(BMesh *bm, BMFace *f);
+void BM_face_multires_bounds_smooth(BMesh *bm, BMFace *f);
struct LinkNode *BM_vert_loop_groups_data_layer_create(
- BMesh *bm, BMVert *v, const int layer_n,
- const float *loop_weights, struct MemArena *arena);
-void BM_vert_loop_groups_data_layer_merge(
- BMesh *bm, struct LinkNode *groups, const int layer_n);
-void BM_vert_loop_groups_data_layer_merge_weights(
- BMesh *bm, struct LinkNode *groups, const int layer_n,
- const float *loop_weights);
+ BMesh *bm, BMVert *v, const int layer_n, const float *loop_weights, struct MemArena *arena);
+void BM_vert_loop_groups_data_layer_merge(BMesh *bm, struct LinkNode *groups, const int layer_n);
+void BM_vert_loop_groups_data_layer_merge_weights(BMesh *bm,
+ struct LinkNode *groups,
+ const int layer_n,
+ const float *loop_weights);
#endif /* __BMESH_INTERP_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_iterators.c b/source/blender/bmesh/intern/bmesh_iterators.c
index 31e0fc00f59..b1e20dd6058 100644
--- a/source/blender/bmesh/intern/bmesh_iterators.c
+++ b/source/blender/bmesh/intern/bmesh_iterators.c
@@ -31,20 +31,20 @@
#include "intern/bmesh_private.h"
const char bm_iter_itype_htype_map[BM_ITYPE_MAX] = {
- '\0',
- BM_VERT, /* BM_VERTS_OF_MESH */
- BM_EDGE, /* BM_EDGES_OF_MESH */
- BM_FACE, /* BM_FACES_OF_MESH */
- BM_EDGE, /* BM_EDGES_OF_VERT */
- BM_FACE, /* BM_FACES_OF_VERT */
- BM_LOOP, /* BM_LOOPS_OF_VERT */
- BM_VERT, /* BM_VERTS_OF_EDGE */
- BM_FACE, /* BM_FACES_OF_EDGE */
- BM_VERT, /* BM_VERTS_OF_FACE */
- BM_EDGE, /* BM_EDGES_OF_FACE */
- BM_LOOP, /* BM_LOOPS_OF_FACE */
- BM_LOOP, /* BM_LOOPS_OF_LOOP */
- BM_LOOP, /* BM_LOOPS_OF_EDGE */
+ '\0',
+ BM_VERT, /* BM_VERTS_OF_MESH */
+ BM_EDGE, /* BM_EDGES_OF_MESH */
+ BM_FACE, /* BM_FACES_OF_MESH */
+ BM_EDGE, /* BM_EDGES_OF_VERT */
+ BM_FACE, /* BM_FACES_OF_VERT */
+ BM_LOOP, /* BM_LOOPS_OF_VERT */
+ BM_VERT, /* BM_VERTS_OF_EDGE */
+ BM_FACE, /* BM_FACES_OF_EDGE */
+ BM_VERT, /* BM_VERTS_OF_FACE */
+ BM_EDGE, /* BM_EDGES_OF_FACE */
+ BM_LOOP, /* BM_LOOPS_OF_FACE */
+ BM_LOOP, /* BM_LOOPS_OF_LOOP */
+ BM_LOOP, /* BM_LOOPS_OF_EDGE */
};
/**
@@ -52,25 +52,25 @@ const char bm_iter_itype_htype_map[BM_ITYPE_MAX] = {
*/
int BM_iter_mesh_count(const char itype, BMesh *bm)
{
- int count;
+ int count;
- switch (itype) {
- case BM_VERTS_OF_MESH:
- count = bm->totvert;
- break;
- case BM_EDGES_OF_MESH:
- count = bm->totedge;
- break;
- case BM_FACES_OF_MESH:
- count = bm->totface;
- break;
- default:
- count = 0;
- BLI_assert(0);
- break;
- }
+ switch (itype) {
+ case BM_VERTS_OF_MESH:
+ count = bm->totvert;
+ break;
+ case BM_EDGES_OF_MESH:
+ count = bm->totedge;
+ break;
+ case BM_FACES_OF_MESH:
+ count = bm->totface;
+ break;
+ default:
+ count = 0;
+ BLI_assert(0);
+ break;
+ }
- return count;
+ return count;
}
/**
@@ -78,27 +78,26 @@ int BM_iter_mesh_count(const char itype, BMesh *bm)
*/
void *BM_iter_at_index(BMesh *bm, const char itype, void *data, int index)
{
- BMIter iter;
- void *val;
- int i;
+ BMIter iter;
+ void *val;
+ int i;
- /* sanity check */
- if (index < 0) {
- return NULL;
- }
+ /* sanity check */
+ if (index < 0) {
+ return NULL;
+ }
- val = BM_iter_new(&iter, bm, itype, data);
+ val = BM_iter_new(&iter, bm, itype, data);
- i = 0;
- while (i < index) {
- val = BM_iter_step(&iter);
- i++;
- }
+ i = 0;
+ while (i < index) {
+ val = BM_iter_step(&iter);
+ i++;
+ }
- return val;
+ return val;
}
-
/**
* \brief Iterator as Array
*
@@ -107,53 +106,55 @@ void *BM_iter_at_index(BMesh *bm, const char itype, void *data, int index)
*/
int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, const int len)
{
- int i = 0;
+ int i = 0;
- /* sanity check */
- if (len > 0) {
- BMIter iter;
- void *ele;
+ /* sanity check */
+ if (len > 0) {
+ BMIter iter;
+ void *ele;
- for (ele = BM_iter_new(&iter, bm, itype, data); ele; ele = BM_iter_step(&iter)) {
- array[i] = ele;
- i++;
- if (i == len) {
- return len;
- }
- }
- }
+ for (ele = BM_iter_new(&iter, bm, itype, data); ele; ele = BM_iter_step(&iter)) {
+ array[i] = ele;
+ i++;
+ if (i == len) {
+ return len;
+ }
+ }
+ }
- return i;
+ return i;
}
/**
* \brief Operator Iterator as Array
*
* Sometimes its convenient to get the iterator as an array.
*/
-int BMO_iter_as_array(
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask,
- void **array, const int len)
+int BMO_iter_as_array(BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ const char restrictmask,
+ void **array,
+ const int len)
{
- int i = 0;
+ int i = 0;
- /* sanity check */
- if (len > 0) {
- BMOIter oiter;
- void *ele;
+ /* sanity check */
+ if (len > 0) {
+ BMOIter oiter;
+ void *ele;
- for (ele = BMO_iter_new(&oiter, slot_args, slot_name, restrictmask); ele; ele = BMO_iter_step(&oiter)) {
- array[i] = ele;
- i++;
- if (i == len) {
- return len;
- }
- }
- }
+ for (ele = BMO_iter_new(&oiter, slot_args, slot_name, restrictmask); ele;
+ ele = BMO_iter_step(&oiter)) {
+ array[i] = ele;
+ i++;
+ if (i == len) {
+ return len;
+ }
+ }
+ }
- return i;
+ return i;
}
-
/**
* \brief Iterator as Array
*
@@ -164,143 +165,146 @@ int BMO_iter_as_array(
*
* Caller needs to free the array.
*/
-void *BM_iter_as_arrayN(
- BMesh *bm, const char itype, void *data, int *r_len,
- /* optional args to avoid an alloc (normally stack array) */
- void **stack_array, int stack_array_size)
-{
- BMIter iter;
-
- BLI_assert(stack_array_size == 0 || (stack_array_size && stack_array));
-
- /* we can't rely on coun't being set */
- switch (itype) {
- case BM_VERTS_OF_MESH:
- iter.count = bm->totvert;
- break;
- case BM_EDGES_OF_MESH:
- iter.count = bm->totedge;
- break;
- case BM_FACES_OF_MESH:
- iter.count = bm->totface;
- break;
- default:
- break;
- }
-
- if (BM_iter_init(&iter, bm, itype, data) && iter.count > 0) {
- BMElem *ele;
- BMElem **array = iter.count > stack_array_size ?
- MEM_mallocN(sizeof(ele) * iter.count, __func__) :
- stack_array;
- int i = 0;
-
- *r_len = iter.count; /* set before iterating */
-
- while ((ele = BM_iter_step(&iter))) {
- array[i++] = ele;
- }
- return array;
- }
- else {
- *r_len = 0;
- return NULL;
- }
-}
-
-void *BMO_iter_as_arrayN(
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask,
- int *r_len,
- /* optional args to avoid an alloc (normally stack array) */
- void **stack_array, int stack_array_size)
-{
- BMOIter iter;
- BMElem *ele;
- int count = BMO_slot_buffer_count(slot_args, slot_name);
-
- BLI_assert(stack_array_size == 0 || (stack_array_size && stack_array));
-
- if ((ele = BMO_iter_new(&iter, slot_args, slot_name, restrictmask)) && count > 0) {
- BMElem **array = count > stack_array_size ?
- MEM_mallocN(sizeof(ele) * count, __func__) :
- stack_array;
- int i = 0;
-
- do {
- array[i++] = ele;
- } while ((ele = BMO_iter_step(&iter)));
- BLI_assert(i <= count);
-
- if (i != count) {
- if ((void **)array != stack_array) {
- array = MEM_reallocN(array, sizeof(ele) * i);
- }
- }
- *r_len = i;
- return array;
- }
- else {
- *r_len = 0;
- return NULL;
- }
-}
-
-int BM_iter_mesh_bitmap_from_filter(
- const char itype, BMesh *bm,
- BLI_bitmap *bitmap,
- bool (*test_fn)(BMElem *, void *user_data),
- void *user_data)
-{
- BMIter iter;
- BMElem *ele;
- int i;
- int bitmap_enabled = 0;
-
- BM_ITER_MESH_INDEX (ele, &iter, bm, itype, i) {
- if (test_fn(ele, user_data)) {
- BLI_BITMAP_ENABLE(bitmap, i);
- bitmap_enabled++;
- }
- else {
- BLI_BITMAP_DISABLE(bitmap, i);
- }
- }
-
- return bitmap_enabled;
+void *BM_iter_as_arrayN(BMesh *bm,
+ const char itype,
+ void *data,
+ int *r_len,
+ /* optional args to avoid an alloc (normally stack array) */
+ void **stack_array,
+ int stack_array_size)
+{
+ BMIter iter;
+
+ BLI_assert(stack_array_size == 0 || (stack_array_size && stack_array));
+
+ /* we can't rely on coun't being set */
+ switch (itype) {
+ case BM_VERTS_OF_MESH:
+ iter.count = bm->totvert;
+ break;
+ case BM_EDGES_OF_MESH:
+ iter.count = bm->totedge;
+ break;
+ case BM_FACES_OF_MESH:
+ iter.count = bm->totface;
+ break;
+ default:
+ break;
+ }
+
+ if (BM_iter_init(&iter, bm, itype, data) && iter.count > 0) {
+ BMElem *ele;
+ BMElem **array = iter.count > stack_array_size ?
+ MEM_mallocN(sizeof(ele) * iter.count, __func__) :
+ stack_array;
+ int i = 0;
+
+ *r_len = iter.count; /* set before iterating */
+
+ while ((ele = BM_iter_step(&iter))) {
+ array[i++] = ele;
+ }
+ return array;
+ }
+ else {
+ *r_len = 0;
+ return NULL;
+ }
+}
+
+void *BMO_iter_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ const char restrictmask,
+ int *r_len,
+ /* optional args to avoid an alloc (normally stack array) */
+ void **stack_array,
+ int stack_array_size)
+{
+ BMOIter iter;
+ BMElem *ele;
+ int count = BMO_slot_buffer_count(slot_args, slot_name);
+
+ BLI_assert(stack_array_size == 0 || (stack_array_size && stack_array));
+
+ if ((ele = BMO_iter_new(&iter, slot_args, slot_name, restrictmask)) && count > 0) {
+ BMElem **array = count > stack_array_size ? MEM_mallocN(sizeof(ele) * count, __func__) :
+ stack_array;
+ int i = 0;
+
+ do {
+ array[i++] = ele;
+ } while ((ele = BMO_iter_step(&iter)));
+ BLI_assert(i <= count);
+
+ if (i != count) {
+ if ((void **)array != stack_array) {
+ array = MEM_reallocN(array, sizeof(ele) * i);
+ }
+ }
+ *r_len = i;
+ return array;
+ }
+ else {
+ *r_len = 0;
+ return NULL;
+ }
+}
+
+int BM_iter_mesh_bitmap_from_filter(const char itype,
+ BMesh *bm,
+ BLI_bitmap *bitmap,
+ bool (*test_fn)(BMElem *, void *user_data),
+ void *user_data)
+{
+ BMIter iter;
+ BMElem *ele;
+ int i;
+ int bitmap_enabled = 0;
+
+ BM_ITER_MESH_INDEX (ele, &iter, bm, itype, i) {
+ if (test_fn(ele, user_data)) {
+ BLI_BITMAP_ENABLE(bitmap, i);
+ bitmap_enabled++;
+ }
+ else {
+ BLI_BITMAP_DISABLE(bitmap, i);
+ }
+ }
+
+ return bitmap_enabled;
}
/**
* Needed when we want to check faces, but return a loop aligned array.
*/
-int BM_iter_mesh_bitmap_from_filter_tessface(
- BMesh *bm,
- BLI_bitmap *bitmap,
- bool (*test_fn)(BMFace *, void *user_data),
- void *user_data)
-{
- BMIter iter;
- BMFace *f;
- int i;
- int j = 0;
- int bitmap_enabled = 0;
-
- BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) {
- if (test_fn(f, user_data)) {
- for (int tri = 2; tri < f->len; tri++) {
- BLI_BITMAP_ENABLE(bitmap, j);
- bitmap_enabled++;
- j++;
- }
- }
- else {
- for (int tri = 2; tri < f->len; tri++) {
- BLI_BITMAP_DISABLE(bitmap, j);
- j++;
- }
- }
- }
-
- return bitmap_enabled;
+int BM_iter_mesh_bitmap_from_filter_tessface(BMesh *bm,
+ BLI_bitmap *bitmap,
+ bool (*test_fn)(BMFace *, void *user_data),
+ void *user_data)
+{
+ BMIter iter;
+ BMFace *f;
+ int i;
+ int j = 0;
+ int bitmap_enabled = 0;
+
+ BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) {
+ if (test_fn(f, user_data)) {
+ for (int tri = 2; tri < f->len; tri++) {
+ BLI_BITMAP_ENABLE(bitmap, j);
+ bitmap_enabled++;
+ j++;
+ }
+ }
+ else {
+ for (int tri = 2; tri < f->len; tri++) {
+ BLI_BITMAP_DISABLE(bitmap, j);
+ j++;
+ }
+ }
+ }
+
+ return bitmap_enabled;
}
/**
@@ -310,17 +314,17 @@ int BM_iter_mesh_bitmap_from_filter_tessface(
*/
int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, const bool value)
{
- BMIter iter;
- BMElem *ele;
- int count = 0;
+ BMIter iter;
+ BMElem *ele;
+ int count = 0;
- BM_ITER_ELEM (ele, &iter, data, itype) {
- if (BM_elem_flag_test_bool(ele, hflag) == value) {
- count++;
- }
- }
+ BM_ITER_ELEM (ele, &iter, data, itype) {
+ if (BM_elem_flag_test_bool(ele, hflag) == value) {
+ count++;
+ }
+ }
- return count;
+ return count;
}
/**
@@ -329,52 +333,46 @@ int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, cons
* Counts how many flagged / unflagged items are found in this element.
*/
int BMO_iter_elem_count_flag(
- BMesh *bm, const char itype, void *data,
- const short oflag, const bool value)
-{
- BMIter iter;
- int count = 0;
-
- /* loops have no header flags */
- BLI_assert(bm_iter_itype_htype_map[itype] != BM_LOOP);
-
- switch (bm_iter_itype_htype_map[itype]) {
- case BM_VERT:
- {
- BMVert *ele;
- BM_ITER_ELEM (ele, &iter, data, itype) {
- if (BMO_vert_flag_test_bool(bm, ele, oflag) == value) {
- count++;
- }
- }
- break;
- }
- case BM_EDGE:
- {
- BMEdge *ele;
- BM_ITER_ELEM (ele, &iter, data, itype) {
- if (BMO_edge_flag_test_bool(bm, ele, oflag) == value) {
- count++;
- }
- }
- break;
- }
- case BM_FACE:
- {
- BMFace *ele;
- BM_ITER_ELEM (ele, &iter, data, itype) {
- if (BMO_face_flag_test_bool(bm, ele, oflag) == value) {
- count++;
- }
- }
- break;
- }
-
- }
- return count;
+ BMesh *bm, const char itype, void *data, const short oflag, const bool value)
+{
+ BMIter iter;
+ int count = 0;
+
+ /* loops have no header flags */
+ BLI_assert(bm_iter_itype_htype_map[itype] != BM_LOOP);
+
+ switch (bm_iter_itype_htype_map[itype]) {
+ case BM_VERT: {
+ BMVert *ele;
+ BM_ITER_ELEM (ele, &iter, data, itype) {
+ if (BMO_vert_flag_test_bool(bm, ele, oflag) == value) {
+ count++;
+ }
+ }
+ break;
+ }
+ case BM_EDGE: {
+ BMEdge *ele;
+ BM_ITER_ELEM (ele, &iter, data, itype) {
+ if (BMO_edge_flag_test_bool(bm, ele, oflag) == value) {
+ count++;
+ }
+ }
+ break;
+ }
+ case BM_FACE: {
+ BMFace *ele;
+ BM_ITER_ELEM (ele, &iter, data, itype) {
+ if (BMO_face_flag_test_bool(bm, ele, oflag) == value) {
+ count++;
+ }
+ }
+ break;
+ }
+ }
+ return count;
}
-
/**
* \brief Mesh Iter Flag Count
*
@@ -382,17 +380,17 @@ int BMO_iter_elem_count_flag(
*/
int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const bool value)
{
- BMIter iter;
- BMElem *ele;
- int count = 0;
+ BMIter iter;
+ BMElem *ele;
+ int count = 0;
- BM_ITER_MESH (ele, &iter, bm, itype) {
- if (BM_elem_flag_test_bool(ele, hflag) == value) {
- count++;
- }
- }
+ BM_ITER_MESH (ele, &iter, bm, itype) {
+ if (BM_elem_flag_test_bool(ele, hflag) == value) {
+ count++;
+ }
+ }
- return count;
+ return count;
}
/**
@@ -424,17 +422,17 @@ int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const
void bmiter__elem_of_mesh_begin(struct BMIter__elem_of_mesh *iter)
{
#ifdef USE_IMMUTABLE_ASSERT
- ((BMIter *)iter)->count = BLI_mempool_len(iter->pooliter.pool);
+ ((BMIter *)iter)->count = BLI_mempool_len(iter->pooliter.pool);
#endif
- BLI_mempool_iternew(iter->pooliter.pool, &iter->pooliter);
+ BLI_mempool_iternew(iter->pooliter.pool, &iter->pooliter);
}
void *bmiter__elem_of_mesh_step(struct BMIter__elem_of_mesh *iter)
{
#ifdef USE_IMMUTABLE_ASSERT
- BLI_assert(((BMIter *)iter)->count <= BLI_mempool_len(iter->pooliter.pool));
+ BLI_assert(((BMIter *)iter)->count <= BLI_mempool_len(iter->pooliter.pool));
#endif
- return BLI_mempool_iterstep(&iter->pooliter);
+ return BLI_mempool_iterstep(&iter->pooliter);
}
#ifdef USE_IMMUTABLE_ASSERT
@@ -445,274 +443,273 @@ void *bmiter__elem_of_mesh_step(struct BMIter__elem_of_mesh *iter)
* EDGE OF VERT CALLBACKS
*/
-void bmiter__edge_of_vert_begin(struct BMIter__edge_of_vert *iter)
+void bmiter__edge_of_vert_begin(struct BMIter__edge_of_vert *iter)
{
- if (iter->vdata->e) {
- iter->e_first = iter->vdata->e;
- iter->e_next = iter->vdata->e;
- }
- else {
- iter->e_first = NULL;
- iter->e_next = NULL;
- }
+ if (iter->vdata->e) {
+ iter->e_first = iter->vdata->e;
+ iter->e_next = iter->vdata->e;
+ }
+ else {
+ iter->e_first = NULL;
+ iter->e_next = NULL;
+ }
}
-void *bmiter__edge_of_vert_step(struct BMIter__edge_of_vert *iter)
+void *bmiter__edge_of_vert_step(struct BMIter__edge_of_vert *iter)
{
- BMEdge *e_curr = iter->e_next;
+ BMEdge *e_curr = iter->e_next;
- if (iter->e_next) {
- iter->e_next = bmesh_disk_edge_next(iter->e_next, iter->vdata);
- if (iter->e_next == iter->e_first) {
- iter->e_next = NULL;
- }
- }
+ if (iter->e_next) {
+ iter->e_next = bmesh_disk_edge_next(iter->e_next, iter->vdata);
+ if (iter->e_next == iter->e_first) {
+ iter->e_next = NULL;
+ }
+ }
- return e_curr;
+ return e_curr;
}
/*
* FACE OF VERT CALLBACKS
*/
-void bmiter__face_of_vert_begin(struct BMIter__face_of_vert *iter)
+void bmiter__face_of_vert_begin(struct BMIter__face_of_vert *iter)
{
- ((BMIter *)iter)->count = bmesh_disk_facevert_count(iter->vdata);
- if (((BMIter *)iter)->count) {
- iter->l_first = bmesh_disk_faceloop_find_first(iter->vdata->e, iter->vdata);
- iter->e_first = iter->l_first->e;
- iter->e_next = iter->e_first;
- iter->l_next = iter->l_first;
- }
- else {
- iter->l_first = iter->l_next = NULL;
- iter->e_first = iter->e_next = NULL;
- }
+ ((BMIter *)iter)->count = bmesh_disk_facevert_count(iter->vdata);
+ if (((BMIter *)iter)->count) {
+ iter->l_first = bmesh_disk_faceloop_find_first(iter->vdata->e, iter->vdata);
+ iter->e_first = iter->l_first->e;
+ iter->e_next = iter->e_first;
+ iter->l_next = iter->l_first;
+ }
+ else {
+ iter->l_first = iter->l_next = NULL;
+ iter->e_first = iter->e_next = NULL;
+ }
}
-void *bmiter__face_of_vert_step(struct BMIter__face_of_vert *iter)
+void *bmiter__face_of_vert_step(struct BMIter__face_of_vert *iter)
{
- BMLoop *l_curr = iter->l_next;
+ BMLoop *l_curr = iter->l_next;
- if (((BMIter *)iter)->count && iter->l_next) {
- ((BMIter *)iter)->count--;
- iter->l_next = bmesh_radial_faceloop_find_next(iter->l_next, iter->vdata);
- if (iter->l_next == iter->l_first) {
- iter->e_next = bmesh_disk_faceedge_find_next(iter->e_next, iter->vdata);
- iter->l_first = bmesh_radial_faceloop_find_first(iter->e_next->l, iter->vdata);
- iter->l_next = iter->l_first;
- }
- }
+ if (((BMIter *)iter)->count && iter->l_next) {
+ ((BMIter *)iter)->count--;
+ iter->l_next = bmesh_radial_faceloop_find_next(iter->l_next, iter->vdata);
+ if (iter->l_next == iter->l_first) {
+ iter->e_next = bmesh_disk_faceedge_find_next(iter->e_next, iter->vdata);
+ iter->l_first = bmesh_radial_faceloop_find_first(iter->e_next->l, iter->vdata);
+ iter->l_next = iter->l_first;
+ }
+ }
- if (!((BMIter *)iter)->count) {
- iter->l_next = NULL;
- }
+ if (!((BMIter *)iter)->count) {
+ iter->l_next = NULL;
+ }
- return l_curr ? l_curr->f : NULL;
+ return l_curr ? l_curr->f : NULL;
}
-
/*
* LOOP OF VERT CALLBACKS
*/
-void bmiter__loop_of_vert_begin(struct BMIter__loop_of_vert *iter)
+void bmiter__loop_of_vert_begin(struct BMIter__loop_of_vert *iter)
{
- ((BMIter *)iter)->count = bmesh_disk_facevert_count(iter->vdata);
- if (((BMIter *)iter)->count) {
- iter->l_first = bmesh_disk_faceloop_find_first(iter->vdata->e, iter->vdata);
- iter->e_first = iter->l_first->e;
- iter->e_next = iter->e_first;
- iter->l_next = iter->l_first;
- }
- else {
- iter->l_first = iter->l_next = NULL;
- iter->e_first = iter->e_next = NULL;
- }
+ ((BMIter *)iter)->count = bmesh_disk_facevert_count(iter->vdata);
+ if (((BMIter *)iter)->count) {
+ iter->l_first = bmesh_disk_faceloop_find_first(iter->vdata->e, iter->vdata);
+ iter->e_first = iter->l_first->e;
+ iter->e_next = iter->e_first;
+ iter->l_next = iter->l_first;
+ }
+ else {
+ iter->l_first = iter->l_next = NULL;
+ iter->e_first = iter->e_next = NULL;
+ }
}
-void *bmiter__loop_of_vert_step(struct BMIter__loop_of_vert *iter)
+void *bmiter__loop_of_vert_step(struct BMIter__loop_of_vert *iter)
{
- BMLoop *l_curr = iter->l_next;
+ BMLoop *l_curr = iter->l_next;
- if (((BMIter *)iter)->count) {
- ((BMIter *)iter)->count--;
- iter->l_next = bmesh_radial_faceloop_find_next(iter->l_next, iter->vdata);
- if (iter->l_next == iter->l_first) {
- iter->e_next = bmesh_disk_faceedge_find_next(iter->e_next, iter->vdata);
- iter->l_first = bmesh_radial_faceloop_find_first(iter->e_next->l, iter->vdata);
- iter->l_next = iter->l_first;
- }
- }
+ if (((BMIter *)iter)->count) {
+ ((BMIter *)iter)->count--;
+ iter->l_next = bmesh_radial_faceloop_find_next(iter->l_next, iter->vdata);
+ if (iter->l_next == iter->l_first) {
+ iter->e_next = bmesh_disk_faceedge_find_next(iter->e_next, iter->vdata);
+ iter->l_first = bmesh_radial_faceloop_find_first(iter->e_next->l, iter->vdata);
+ iter->l_next = iter->l_first;
+ }
+ }
- if (!((BMIter *)iter)->count) {
- iter->l_next = NULL;
- }
+ if (!((BMIter *)iter)->count) {
+ iter->l_next = NULL;
+ }
- /* NULL on finish */
- return l_curr;
+ /* NULL on finish */
+ return l_curr;
}
/*
* LOOP OF EDGE CALLBACKS
*/
-void bmiter__loop_of_edge_begin(struct BMIter__loop_of_edge *iter)
+void bmiter__loop_of_edge_begin(struct BMIter__loop_of_edge *iter)
{
- iter->l_first = iter->l_next = iter->edata->l;
+ iter->l_first = iter->l_next = iter->edata->l;
}
-void *bmiter__loop_of_edge_step(struct BMIter__loop_of_edge *iter)
+void *bmiter__loop_of_edge_step(struct BMIter__loop_of_edge *iter)
{
- BMLoop *l_curr = iter->l_next;
+ BMLoop *l_curr = iter->l_next;
- if (iter->l_next) {
- iter->l_next = iter->l_next->radial_next;
- if (iter->l_next == iter->l_first) {
- iter->l_next = NULL;
- }
- }
+ if (iter->l_next) {
+ iter->l_next = iter->l_next->radial_next;
+ if (iter->l_next == iter->l_first) {
+ iter->l_next = NULL;
+ }
+ }
- /* NULL on finish */
- return l_curr;
+ /* NULL on finish */
+ return l_curr;
}
/*
* LOOP OF LOOP CALLBACKS
*/
-void bmiter__loop_of_loop_begin(struct BMIter__loop_of_loop *iter)
+void bmiter__loop_of_loop_begin(struct BMIter__loop_of_loop *iter)
{
- iter->l_first = iter->ldata;
- iter->l_next = iter->l_first->radial_next;
+ iter->l_first = iter->ldata;
+ iter->l_next = iter->l_first->radial_next;
- if (iter->l_next == iter->l_first) {
- iter->l_next = NULL;
- }
+ if (iter->l_next == iter->l_first) {
+ iter->l_next = NULL;
+ }
}
-void *bmiter__loop_of_loop_step(struct BMIter__loop_of_loop *iter)
+void *bmiter__loop_of_loop_step(struct BMIter__loop_of_loop *iter)
{
- BMLoop *l_curr = iter->l_next;
+ BMLoop *l_curr = iter->l_next;
- if (iter->l_next) {
- iter->l_next = iter->l_next->radial_next;
- if (iter->l_next == iter->l_first) {
- iter->l_next = NULL;
- }
- }
+ if (iter->l_next) {
+ iter->l_next = iter->l_next->radial_next;
+ if (iter->l_next == iter->l_first) {
+ iter->l_next = NULL;
+ }
+ }
- /* NULL on finish */
- return l_curr;
+ /* NULL on finish */
+ return l_curr;
}
/*
* FACE OF EDGE CALLBACKS
*/
-void bmiter__face_of_edge_begin(struct BMIter__face_of_edge *iter)
+void bmiter__face_of_edge_begin(struct BMIter__face_of_edge *iter)
{
- iter->l_first = iter->l_next = iter->edata->l;
+ iter->l_first = iter->l_next = iter->edata->l;
}
-void *bmiter__face_of_edge_step(struct BMIter__face_of_edge *iter)
+void *bmiter__face_of_edge_step(struct BMIter__face_of_edge *iter)
{
- BMLoop *current = iter->l_next;
+ BMLoop *current = iter->l_next;
- if (iter->l_next) {
- iter->l_next = iter->l_next->radial_next;
- if (iter->l_next == iter->l_first) {
- iter->l_next = NULL;
- }
- }
+ if (iter->l_next) {
+ iter->l_next = iter->l_next->radial_next;
+ if (iter->l_next == iter->l_first) {
+ iter->l_next = NULL;
+ }
+ }
- return current ? current->f : NULL;
+ return current ? current->f : NULL;
}
/*
* VERTS OF EDGE CALLBACKS
*/
-void bmiter__vert_of_edge_begin(struct BMIter__vert_of_edge *iter)
+void bmiter__vert_of_edge_begin(struct BMIter__vert_of_edge *iter)
{
- ((BMIter *)iter)->count = 0;
+ ((BMIter *)iter)->count = 0;
}
-void *bmiter__vert_of_edge_step(struct BMIter__vert_of_edge *iter)
+void *bmiter__vert_of_edge_step(struct BMIter__vert_of_edge *iter)
{
- switch (((BMIter *)iter)->count++) {
- case 0:
- return iter->edata->v1;
- case 1:
- return iter->edata->v2;
- default:
- return NULL;
- }
+ switch (((BMIter *)iter)->count++) {
+ case 0:
+ return iter->edata->v1;
+ case 1:
+ return iter->edata->v2;
+ default:
+ return NULL;
+ }
}
/*
* VERT OF FACE CALLBACKS
*/
-void bmiter__vert_of_face_begin(struct BMIter__vert_of_face *iter)
+void bmiter__vert_of_face_begin(struct BMIter__vert_of_face *iter)
{
- iter->l_first = iter->l_next = BM_FACE_FIRST_LOOP(iter->pdata);
+ iter->l_first = iter->l_next = BM_FACE_FIRST_LOOP(iter->pdata);
}
-void *bmiter__vert_of_face_step(struct BMIter__vert_of_face *iter)
+void *bmiter__vert_of_face_step(struct BMIter__vert_of_face *iter)
{
- BMLoop *l_curr = iter->l_next;
+ BMLoop *l_curr = iter->l_next;
- if (iter->l_next) {
- iter->l_next = iter->l_next->next;
- if (iter->l_next == iter->l_first) {
- iter->l_next = NULL;
- }
- }
+ if (iter->l_next) {
+ iter->l_next = iter->l_next->next;
+ if (iter->l_next == iter->l_first) {
+ iter->l_next = NULL;
+ }
+ }
- return l_curr ? l_curr->v : NULL;
+ return l_curr ? l_curr->v : NULL;
}
/*
* EDGE OF FACE CALLBACKS
*/
-void bmiter__edge_of_face_begin(struct BMIter__edge_of_face *iter)
+void bmiter__edge_of_face_begin(struct BMIter__edge_of_face *iter)
{
- iter->l_first = iter->l_next = BM_FACE_FIRST_LOOP(iter->pdata);
+ iter->l_first = iter->l_next = BM_FACE_FIRST_LOOP(iter->pdata);
}
-void *bmiter__edge_of_face_step(struct BMIter__edge_of_face *iter)
+void *bmiter__edge_of_face_step(struct BMIter__edge_of_face *iter)
{
- BMLoop *l_curr = iter->l_next;
+ BMLoop *l_curr = iter->l_next;
- if (iter->l_next) {
- iter->l_next = iter->l_next->next;
- if (iter->l_next == iter->l_first) {
- iter->l_next = NULL;
- }
- }
+ if (iter->l_next) {
+ iter->l_next = iter->l_next->next;
+ if (iter->l_next == iter->l_first) {
+ iter->l_next = NULL;
+ }
+ }
- return l_curr ? l_curr->e : NULL;
+ return l_curr ? l_curr->e : NULL;
}
/*
* LOOP OF FACE CALLBACKS
*/
-void bmiter__loop_of_face_begin(struct BMIter__loop_of_face *iter)
+void bmiter__loop_of_face_begin(struct BMIter__loop_of_face *iter)
{
- iter->l_first = iter->l_next = BM_FACE_FIRST_LOOP(iter->pdata);
+ iter->l_first = iter->l_next = BM_FACE_FIRST_LOOP(iter->pdata);
}
-void *bmiter__loop_of_face_step(struct BMIter__loop_of_face *iter)
+void *bmiter__loop_of_face_step(struct BMIter__loop_of_face *iter)
{
- BMLoop *l_curr = iter->l_next;
+ BMLoop *l_curr = iter->l_next;
- if (iter->l_next) {
- iter->l_next = iter->l_next->next;
- if (iter->l_next == iter->l_first) {
- iter->l_next = NULL;
- }
- }
+ if (iter->l_next) {
+ iter->l_next = iter->l_next->next;
+ if (iter->l_next == iter->l_first) {
+ iter->l_next = NULL;
+ }
+ }
- return l_curr;
+ return l_curr;
}
diff --git a/source/blender/bmesh/intern/bmesh_iterators.h b/source/blender/bmesh/intern/bmesh_iterators.h
index 73784dabea8..a809c9a3d32 100644
--- a/source/blender/bmesh/intern/bmesh_iterators.h
+++ b/source/blender/bmesh/intern/bmesh_iterators.h
@@ -48,27 +48,27 @@
* be sure to keep 'bm_iter_itype_htype_map' in sync with any changes
*/
typedef enum BMIterType {
- BM_VERTS_OF_MESH = 1,
- BM_EDGES_OF_MESH = 2,
- BM_FACES_OF_MESH = 3,
- /* these are topological iterators. */
- BM_EDGES_OF_VERT = 4,
- BM_FACES_OF_VERT = 5,
- BM_LOOPS_OF_VERT = 6,
- BM_VERTS_OF_EDGE = 7, /* just v1, v2: added so py can use generalized sequencer wrapper */
- BM_FACES_OF_EDGE = 8,
- BM_VERTS_OF_FACE = 9,
- BM_EDGES_OF_FACE = 10,
- BM_LOOPS_OF_FACE = 11,
- /* returns elements from all boundaries, and returns
- * the first element at the end to flag that we're entering
- * a different face hole boundary*/
- // BM_ALL_LOOPS_OF_FACE = 12,
- /* iterate through loops around this loop, which are fetched
- * from the other faces in the radial cycle surrounding the
- * input loop's edge.*/
- BM_LOOPS_OF_LOOP = 12,
- BM_LOOPS_OF_EDGE = 13,
+ BM_VERTS_OF_MESH = 1,
+ BM_EDGES_OF_MESH = 2,
+ BM_FACES_OF_MESH = 3,
+ /* these are topological iterators. */
+ BM_EDGES_OF_VERT = 4,
+ BM_FACES_OF_VERT = 5,
+ BM_LOOPS_OF_VERT = 6,
+ BM_VERTS_OF_EDGE = 7, /* just v1, v2: added so py can use generalized sequencer wrapper */
+ BM_FACES_OF_EDGE = 8,
+ BM_VERTS_OF_FACE = 9,
+ BM_EDGES_OF_FACE = 10,
+ BM_LOOPS_OF_FACE = 11,
+ /* returns elements from all boundaries, and returns
+ * the first element at the end to flag that we're entering
+ * a different face hole boundary*/
+ // BM_ALL_LOOPS_OF_FACE = 12,
+ /* iterate through loops around this loop, which are fetched
+ * from the other faces in the radial cycle surrounding the
+ * input loop's edge.*/
+ BM_LOOPS_OF_LOOP = 12,
+ BM_LOOPS_OF_EDGE = 13,
} BMIterType;
#define BM_ITYPE_MAX 14
@@ -77,153 +77,157 @@ typedef enum BMIterType {
extern const char bm_iter_itype_htype_map[BM_ITYPE_MAX];
#define BM_ITER_MESH(ele, iter, bm, itype) \
- for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, bm, itype, NULL); \
- ele; \
- BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_step(iter))
+ for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, bm, itype, NULL); ele; \
+ BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_step(iter))
#define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar) \
- for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, bm, itype, NULL), indexvar = 0; \
- ele; \
- BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_step(iter), (indexvar)++)
+ for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, bm, itype, NULL), indexvar = 0; ele; \
+ BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_step(iter), (indexvar)++)
/* a version of BM_ITER_MESH which keeps the next item in storage
* so we can delete the current item, see bug [#36923] */
#ifdef DEBUG
# define BM_ITER_MESH_MUTABLE(ele, ele_next, iter, bm, itype) \
- for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, bm, itype, NULL); \
- ele ? ((void)((iter)->count = BM_iter_mesh_count(itype, bm)), \
- (void)(ele_next = BM_iter_step(iter)), 1) : 0; \
- BM_CHECK_TYPE_ELEM_ASSIGN(ele) = ele_next)
+ for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, bm, itype, NULL); \
+ ele ? ((void)((iter)->count = BM_iter_mesh_count(itype, bm)), \
+ (void)(ele_next = BM_iter_step(iter)), \
+ 1) : \
+ 0; \
+ BM_CHECK_TYPE_ELEM_ASSIGN(ele) = ele_next)
#else
# define BM_ITER_MESH_MUTABLE(ele, ele_next, iter, bm, itype) \
- for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, bm, itype, NULL); \
- ele ? ((BM_CHECK_TYPE_ELEM_ASSIGN(ele_next) = BM_iter_step(iter)), 1) : 0; \
- ele = ele_next)
+ for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, bm, itype, NULL); \
+ ele ? ((BM_CHECK_TYPE_ELEM_ASSIGN(ele_next) = BM_iter_step(iter)), 1) : 0; \
+ ele = ele_next)
#endif
-
#define BM_ITER_ELEM(ele, iter, data, itype) \
- for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, NULL, itype, data); \
- ele; \
- BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_step(iter))
+ for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, NULL, itype, data); ele; \
+ BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_step(iter))
#define BM_ITER_ELEM_INDEX(ele, iter, data, itype, indexvar) \
- for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, NULL, itype, data), indexvar = 0; \
- ele; \
- BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_step(iter), (indexvar)++)
+ for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, NULL, itype, data), indexvar = 0; ele; \
+ BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_step(iter), (indexvar)++)
/* iterator type structs */
struct BMIter__elem_of_mesh {
- BLI_mempool_iter pooliter;
+ BLI_mempool_iter pooliter;
};
struct BMIter__edge_of_vert {
- BMVert *vdata;
- BMEdge *e_first, *e_next;
+ BMVert *vdata;
+ BMEdge *e_first, *e_next;
};
struct BMIter__face_of_vert {
- BMVert *vdata;
- BMLoop *l_first, *l_next;
- BMEdge *e_first, *e_next;
+ BMVert *vdata;
+ BMLoop *l_first, *l_next;
+ BMEdge *e_first, *e_next;
};
struct BMIter__loop_of_vert {
- BMVert *vdata;
- BMLoop *l_first, *l_next;
- BMEdge *e_first, *e_next;
+ BMVert *vdata;
+ BMLoop *l_first, *l_next;
+ BMEdge *e_first, *e_next;
};
struct BMIter__loop_of_edge {
- BMEdge *edata;
- BMLoop *l_first, *l_next;
+ BMEdge *edata;
+ BMLoop *l_first, *l_next;
};
struct BMIter__loop_of_loop {
- BMLoop *ldata;
- BMLoop *l_first, *l_next;
+ BMLoop *ldata;
+ BMLoop *l_first, *l_next;
};
struct BMIter__face_of_edge {
- BMEdge *edata;
- BMLoop *l_first, *l_next;
+ BMEdge *edata;
+ BMLoop *l_first, *l_next;
};
struct BMIter__vert_of_edge {
- BMEdge *edata;
+ BMEdge *edata;
};
struct BMIter__vert_of_face {
- BMFace *pdata;
- BMLoop *l_first, *l_next;
+ BMFace *pdata;
+ BMLoop *l_first, *l_next;
};
struct BMIter__edge_of_face {
- BMFace *pdata;
- BMLoop *l_first, *l_next;
+ BMFace *pdata;
+ BMLoop *l_first, *l_next;
};
struct BMIter__loop_of_face {
- BMFace *pdata;
- BMLoop *l_first, *l_next;
+ BMFace *pdata;
+ BMLoop *l_first, *l_next;
};
-typedef void (*BMIter__begin_cb) (void *);
-typedef void *(*BMIter__step_cb) (void *);
+typedef void (*BMIter__begin_cb)(void *);
+typedef void *(*BMIter__step_cb)(void *);
/* Iterator Structure */
/* note: some of these vars are not used,
* so they have been commented to save stack space since this struct is used all over */
typedef struct BMIter {
- /* keep union first */
- union {
- struct BMIter__elem_of_mesh elem_of_mesh;
-
- struct BMIter__edge_of_vert edge_of_vert;
- struct BMIter__face_of_vert face_of_vert;
- struct BMIter__loop_of_vert loop_of_vert;
- struct BMIter__loop_of_edge loop_of_edge;
- struct BMIter__loop_of_loop loop_of_loop;
- struct BMIter__face_of_edge face_of_edge;
- struct BMIter__vert_of_edge vert_of_edge;
- struct BMIter__vert_of_face vert_of_face;
- struct BMIter__edge_of_face edge_of_face;
- struct BMIter__loop_of_face loop_of_face;
- } data;
-
- BMIter__begin_cb begin;
- BMIter__step_cb step;
-
- int count; /* note, only some iterators set this, don't rely on it */
- char itype;
+ /* keep union first */
+ union {
+ struct BMIter__elem_of_mesh elem_of_mesh;
+
+ struct BMIter__edge_of_vert edge_of_vert;
+ struct BMIter__face_of_vert face_of_vert;
+ struct BMIter__loop_of_vert loop_of_vert;
+ struct BMIter__loop_of_edge loop_of_edge;
+ struct BMIter__loop_of_loop loop_of_loop;
+ struct BMIter__face_of_edge face_of_edge;
+ struct BMIter__vert_of_edge vert_of_edge;
+ struct BMIter__vert_of_face vert_of_face;
+ struct BMIter__edge_of_face edge_of_face;
+ struct BMIter__loop_of_face loop_of_face;
+ } data;
+
+ BMIter__begin_cb begin;
+ BMIter__step_cb step;
+
+ int count; /* note, only some iterators set this, don't rely on it */
+ char itype;
} BMIter;
-void *BM_iter_at_index(BMesh *bm, const char itype, void *data, int index) ATTR_WARN_UNUSED_RESULT;
-int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, const int len);
-void *BM_iter_as_arrayN(
- BMesh *bm, const char itype, void *data, int *r_len,
- void **stack_array, int stack_array_size) ATTR_WARN_UNUSED_RESULT;
-int BMO_iter_as_array(
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask,
- void **array, const int len);
-void *BMO_iter_as_arrayN(
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask,
- int *r_len,
- /* optional args to avoid an alloc (normally stack array) */
- void **stack_array, int stack_array_size);
-
-int BM_iter_mesh_bitmap_from_filter(
- const char itype, BMesh *bm,
- uint *bitmap,
- bool (*test_fn)(BMElem *, void *user_data),
- void *user_data);
-int BM_iter_mesh_bitmap_from_filter_tessface(
- BMesh *bm,
- uint *bitmap,
- bool (*test_fn)(BMFace *, void *user_data),
- void *user_data);
-
-int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, const bool value);
-int BMO_iter_elem_count_flag(BMesh *bm, const char itype, void *data, const short oflag, const bool value);
-int BM_iter_mesh_count(const char itype, BMesh *bm);
-int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const bool value);
+void *BM_iter_at_index(BMesh *bm, const char itype, void *data, int index) ATTR_WARN_UNUSED_RESULT;
+int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, const int len);
+void *BM_iter_as_arrayN(BMesh *bm,
+ const char itype,
+ void *data,
+ int *r_len,
+ void **stack_array,
+ int stack_array_size) ATTR_WARN_UNUSED_RESULT;
+int BMO_iter_as_array(BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ const char restrictmask,
+ void **array,
+ const int len);
+void *BMO_iter_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ const char restrictmask,
+ int *r_len,
+ /* optional args to avoid an alloc (normally stack array) */
+ void **stack_array,
+ int stack_array_size);
+
+int BM_iter_mesh_bitmap_from_filter(const char itype,
+ BMesh *bm,
+ uint *bitmap,
+ bool (*test_fn)(BMElem *, void *user_data),
+ void *user_data);
+int BM_iter_mesh_bitmap_from_filter_tessface(BMesh *bm,
+ uint *bitmap,
+ bool (*test_fn)(BMFace *, void *user_data),
+ void *user_data);
+
+int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, const bool value);
+int BMO_iter_elem_count_flag(
+ BMesh *bm, const char itype, void *data, const short oflag, const bool value);
+int BM_iter_mesh_count(const char itype, BMesh *bm);
+int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const bool value);
/* private for bmesh_iterators_inline.c */
#define BMITER_CB_DEF(name) \
- struct BMIter__##name; \
- void bmiter__##name##_begin(struct BMIter__##name *iter); \
- void *bmiter__##name##_step(struct BMIter__##name *iter)
+ struct BMIter__##name; \
+ void bmiter__##name##_begin(struct BMIter__##name *iter); \
+ void *bmiter__##name##_step(struct BMIter__##name *iter)
BMITER_CB_DEF(elem_of_mesh);
BMITER_CB_DEF(edge_of_vert);
@@ -242,11 +246,11 @@ BMITER_CB_DEF(loop_of_face);
#include "intern/bmesh_iterators_inline.h"
#define BM_ITER_CHECK_TYPE_DATA(data) \
- CHECK_TYPE_ANY(data, void *, BMFace *, BMEdge *, BMVert *, BMLoop *, BMElem *)
+ CHECK_TYPE_ANY(data, void *, BMFace *, BMEdge *, BMVert *, BMLoop *, BMElem *)
#define BM_iter_new(iter, bm, itype, data) \
- (BM_ITER_CHECK_TYPE_DATA(data), BM_iter_new(iter, bm, itype, data))
+ (BM_ITER_CHECK_TYPE_DATA(data), BM_iter_new(iter, bm, itype, data))
#define BM_iter_init(iter, bm, itype, data) \
- (BM_ITER_CHECK_TYPE_DATA(data), BM_iter_init(iter, bm, itype, data))
+ (BM_ITER_CHECK_TYPE_DATA(data), BM_iter_init(iter, bm, itype, data))
#endif /* __BMESH_ITERATORS_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_iterators_inline.h b/source/blender/bmesh/intern/bmesh_iterators_inline.h
index 30740a1bc90..ed3a9a5be09 100644
--- a/source/blender/bmesh/intern/bmesh_iterators_inline.h
+++ b/source/blender/bmesh/intern/bmesh_iterators_inline.h
@@ -31,13 +31,11 @@
*
* Calls an iterators step function to return the next element.
*/
-ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
-BLI_INLINE void *BM_iter_step(BMIter *iter)
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE void *BM_iter_step(BMIter *iter)
{
- return iter->step(iter);
+ return iter->step(iter);
}
-
/**
* \brief Iterator Init
*
@@ -48,112 +46,112 @@ BLI_INLINE void *BM_iter_step(BMIter *iter)
ATTR_NONNULL(1)
BLI_INLINE bool BM_iter_init(BMIter *iter, BMesh *bm, const char itype, void *data)
{
- /* int argtype; */
- iter->itype = itype;
+ /* int argtype; */
+ iter->itype = itype;
- /* inlining optimizes out this switch when called with the defined type */
- switch ((BMIterType)itype) {
- case BM_VERTS_OF_MESH:
- BLI_assert(bm != NULL);
- BLI_assert(data == NULL);
- iter->begin = (BMIter__begin_cb)bmiter__elem_of_mesh_begin;
- iter->step = (BMIter__step_cb)bmiter__elem_of_mesh_step;
- iter->data.elem_of_mesh.pooliter.pool = bm->vpool;
- break;
- case BM_EDGES_OF_MESH:
- BLI_assert(bm != NULL);
- BLI_assert(data == NULL);
- iter->begin = (BMIter__begin_cb)bmiter__elem_of_mesh_begin;
- iter->step = (BMIter__step_cb)bmiter__elem_of_mesh_step;
- iter->data.elem_of_mesh.pooliter.pool = bm->epool;
- break;
- case BM_FACES_OF_MESH:
- BLI_assert(bm != NULL);
- BLI_assert(data == NULL);
- iter->begin = (BMIter__begin_cb)bmiter__elem_of_mesh_begin;
- iter->step = (BMIter__step_cb)bmiter__elem_of_mesh_step;
- iter->data.elem_of_mesh.pooliter.pool = bm->fpool;
- break;
- case BM_EDGES_OF_VERT:
- BLI_assert(data != NULL);
- BLI_assert(((BMElem *)data)->head.htype == BM_VERT);
- iter->begin = (BMIter__begin_cb)bmiter__edge_of_vert_begin;
- iter->step = (BMIter__step_cb)bmiter__edge_of_vert_step;
- iter->data.edge_of_vert.vdata = (BMVert *)data;
- break;
- case BM_FACES_OF_VERT:
- BLI_assert(data != NULL);
- BLI_assert(((BMElem *)data)->head.htype == BM_VERT);
- iter->begin = (BMIter__begin_cb)bmiter__face_of_vert_begin;
- iter->step = (BMIter__step_cb)bmiter__face_of_vert_step;
- iter->data.face_of_vert.vdata = (BMVert *)data;
- break;
- case BM_LOOPS_OF_VERT:
- BLI_assert(data != NULL);
- BLI_assert(((BMElem *)data)->head.htype == BM_VERT);
- iter->begin = (BMIter__begin_cb)bmiter__loop_of_vert_begin;
- iter->step = (BMIter__step_cb)bmiter__loop_of_vert_step;
- iter->data.loop_of_vert.vdata = (BMVert *)data;
- break;
- case BM_VERTS_OF_EDGE:
- BLI_assert(data != NULL);
- BLI_assert(((BMElem *)data)->head.htype == BM_EDGE);
- iter->begin = (BMIter__begin_cb)bmiter__vert_of_edge_begin;
- iter->step = (BMIter__step_cb)bmiter__vert_of_edge_step;
- iter->data.vert_of_edge.edata = (BMEdge *)data;
- break;
- case BM_FACES_OF_EDGE:
- BLI_assert(data != NULL);
- BLI_assert(((BMElem *)data)->head.htype == BM_EDGE);
- iter->begin = (BMIter__begin_cb)bmiter__face_of_edge_begin;
- iter->step = (BMIter__step_cb)bmiter__face_of_edge_step;
- iter->data.face_of_edge.edata = (BMEdge *)data;
- break;
- case BM_VERTS_OF_FACE:
- BLI_assert(data != NULL);
- BLI_assert(((BMElem *)data)->head.htype == BM_FACE);
- iter->begin = (BMIter__begin_cb)bmiter__vert_of_face_begin;
- iter->step = (BMIter__step_cb)bmiter__vert_of_face_step;
- iter->data.vert_of_face.pdata = (BMFace *)data;
- break;
- case BM_EDGES_OF_FACE:
- BLI_assert(data != NULL);
- BLI_assert(((BMElem *)data)->head.htype == BM_FACE);
- iter->begin = (BMIter__begin_cb)bmiter__edge_of_face_begin;
- iter->step = (BMIter__step_cb)bmiter__edge_of_face_step;
- iter->data.edge_of_face.pdata = (BMFace *)data;
- break;
- case BM_LOOPS_OF_FACE:
- BLI_assert(data != NULL);
- BLI_assert(((BMElem *)data)->head.htype == BM_FACE);
- iter->begin = (BMIter__begin_cb)bmiter__loop_of_face_begin;
- iter->step = (BMIter__step_cb)bmiter__loop_of_face_step;
- iter->data.loop_of_face.pdata = (BMFace *)data;
- break;
- case BM_LOOPS_OF_LOOP:
- BLI_assert(data != NULL);
- BLI_assert(((BMElem *)data)->head.htype == BM_LOOP);
- iter->begin = (BMIter__begin_cb)bmiter__loop_of_loop_begin;
- iter->step = (BMIter__step_cb)bmiter__loop_of_loop_step;
- iter->data.loop_of_loop.ldata = (BMLoop *)data;
- break;
- case BM_LOOPS_OF_EDGE:
- BLI_assert(data != NULL);
- BLI_assert(((BMElem *)data)->head.htype == BM_EDGE);
- iter->begin = (BMIter__begin_cb)bmiter__loop_of_edge_begin;
- iter->step = (BMIter__step_cb)bmiter__loop_of_edge_step;
- iter->data.loop_of_edge.edata = (BMEdge *)data;
- break;
- default:
- /* should never happen */
- BLI_assert(0);
- return false;
- break;
- }
+ /* inlining optimizes out this switch when called with the defined type */
+ switch ((BMIterType)itype) {
+ case BM_VERTS_OF_MESH:
+ BLI_assert(bm != NULL);
+ BLI_assert(data == NULL);
+ iter->begin = (BMIter__begin_cb)bmiter__elem_of_mesh_begin;
+ iter->step = (BMIter__step_cb)bmiter__elem_of_mesh_step;
+ iter->data.elem_of_mesh.pooliter.pool = bm->vpool;
+ break;
+ case BM_EDGES_OF_MESH:
+ BLI_assert(bm != NULL);
+ BLI_assert(data == NULL);
+ iter->begin = (BMIter__begin_cb)bmiter__elem_of_mesh_begin;
+ iter->step = (BMIter__step_cb)bmiter__elem_of_mesh_step;
+ iter->data.elem_of_mesh.pooliter.pool = bm->epool;
+ break;
+ case BM_FACES_OF_MESH:
+ BLI_assert(bm != NULL);
+ BLI_assert(data == NULL);
+ iter->begin = (BMIter__begin_cb)bmiter__elem_of_mesh_begin;
+ iter->step = (BMIter__step_cb)bmiter__elem_of_mesh_step;
+ iter->data.elem_of_mesh.pooliter.pool = bm->fpool;
+ break;
+ case BM_EDGES_OF_VERT:
+ BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_VERT);
+ iter->begin = (BMIter__begin_cb)bmiter__edge_of_vert_begin;
+ iter->step = (BMIter__step_cb)bmiter__edge_of_vert_step;
+ iter->data.edge_of_vert.vdata = (BMVert *)data;
+ break;
+ case BM_FACES_OF_VERT:
+ BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_VERT);
+ iter->begin = (BMIter__begin_cb)bmiter__face_of_vert_begin;
+ iter->step = (BMIter__step_cb)bmiter__face_of_vert_step;
+ iter->data.face_of_vert.vdata = (BMVert *)data;
+ break;
+ case BM_LOOPS_OF_VERT:
+ BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_VERT);
+ iter->begin = (BMIter__begin_cb)bmiter__loop_of_vert_begin;
+ iter->step = (BMIter__step_cb)bmiter__loop_of_vert_step;
+ iter->data.loop_of_vert.vdata = (BMVert *)data;
+ break;
+ case BM_VERTS_OF_EDGE:
+ BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_EDGE);
+ iter->begin = (BMIter__begin_cb)bmiter__vert_of_edge_begin;
+ iter->step = (BMIter__step_cb)bmiter__vert_of_edge_step;
+ iter->data.vert_of_edge.edata = (BMEdge *)data;
+ break;
+ case BM_FACES_OF_EDGE:
+ BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_EDGE);
+ iter->begin = (BMIter__begin_cb)bmiter__face_of_edge_begin;
+ iter->step = (BMIter__step_cb)bmiter__face_of_edge_step;
+ iter->data.face_of_edge.edata = (BMEdge *)data;
+ break;
+ case BM_VERTS_OF_FACE:
+ BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_FACE);
+ iter->begin = (BMIter__begin_cb)bmiter__vert_of_face_begin;
+ iter->step = (BMIter__step_cb)bmiter__vert_of_face_step;
+ iter->data.vert_of_face.pdata = (BMFace *)data;
+ break;
+ case BM_EDGES_OF_FACE:
+ BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_FACE);
+ iter->begin = (BMIter__begin_cb)bmiter__edge_of_face_begin;
+ iter->step = (BMIter__step_cb)bmiter__edge_of_face_step;
+ iter->data.edge_of_face.pdata = (BMFace *)data;
+ break;
+ case BM_LOOPS_OF_FACE:
+ BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_FACE);
+ iter->begin = (BMIter__begin_cb)bmiter__loop_of_face_begin;
+ iter->step = (BMIter__step_cb)bmiter__loop_of_face_step;
+ iter->data.loop_of_face.pdata = (BMFace *)data;
+ break;
+ case BM_LOOPS_OF_LOOP:
+ BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_LOOP);
+ iter->begin = (BMIter__begin_cb)bmiter__loop_of_loop_begin;
+ iter->step = (BMIter__step_cb)bmiter__loop_of_loop_step;
+ iter->data.loop_of_loop.ldata = (BMLoop *)data;
+ break;
+ case BM_LOOPS_OF_EDGE:
+ BLI_assert(data != NULL);
+ BLI_assert(((BMElem *)data)->head.htype == BM_EDGE);
+ iter->begin = (BMIter__begin_cb)bmiter__loop_of_edge_begin;
+ iter->step = (BMIter__step_cb)bmiter__loop_of_edge_step;
+ iter->data.loop_of_edge.edata = (BMEdge *)data;
+ break;
+ default:
+ /* should never happen */
+ BLI_assert(0);
+ return false;
+ break;
+ }
- iter->begin(iter);
+ iter->begin(iter);
- return true;
+ return true;
}
/**
@@ -164,15 +162,15 @@ BLI_INLINE bool BM_iter_init(BMIter *iter, BMesh *bm, const char itype, void *da
* upon its type and then calls BMeshIter_step()
* to return the first element of the iterator.
*/
-ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
-BLI_INLINE void *BM_iter_new(BMIter *iter, BMesh *bm, const char itype, void *data)
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE
+ void *BM_iter_new(BMIter *iter, BMesh *bm, const char itype, void *data)
{
- if (LIKELY(BM_iter_init(iter, bm, itype, data))) {
- return BM_iter_step(iter);
- }
- else {
- return NULL;
- }
+ if (LIKELY(BM_iter_init(iter, bm, itype, data))) {
+ return BM_iter_step(iter);
+ }
+ else {
+ return NULL;
+ }
}
/**
@@ -186,27 +184,30 @@ BLI_INLINE void *BM_iter_new(BMIter *iter, BMesh *bm, const char itype, void *da
#ifdef __BLI_TASK_H__
ATTR_NONNULL(1)
-BLI_INLINE void BM_iter_parallel(
- BMesh *bm, const char itype, TaskParallelMempoolFunc func, void *userdata, const bool use_threading)
+BLI_INLINE void BM_iter_parallel(BMesh *bm,
+ const char itype,
+ TaskParallelMempoolFunc func,
+ void *userdata,
+ const bool use_threading)
{
- /* inlining optimizes out this switch when called with the defined type */
- switch ((BMIterType)itype) {
- case BM_VERTS_OF_MESH:
- BLI_task_parallel_mempool(bm->vpool, userdata, func, use_threading);
- break;
- case BM_EDGES_OF_MESH:
- BLI_task_parallel_mempool(bm->epool, userdata, func, use_threading);
- break;
- case BM_FACES_OF_MESH:
- BLI_task_parallel_mempool(bm->fpool, userdata, func, use_threading);
- break;
- default:
- /* should never happen */
- BLI_assert(0);
- break;
- }
+ /* inlining optimizes out this switch when called with the defined type */
+ switch ((BMIterType)itype) {
+ case BM_VERTS_OF_MESH:
+ BLI_task_parallel_mempool(bm->vpool, userdata, func, use_threading);
+ break;
+ case BM_EDGES_OF_MESH:
+ BLI_task_parallel_mempool(bm->epool, userdata, func, use_threading);
+ break;
+ case BM_FACES_OF_MESH:
+ BLI_task_parallel_mempool(bm->fpool, userdata, func, use_threading);
+ break;
+ default:
+ /* should never happen */
+ BLI_assert(0);
+ break;
+ }
}
-#endif /* __BLI_TASK_H__ */
+#endif /* __BLI_TASK_H__ */
#endif /* __BMESH_ITERATORS_INLINE_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_log.c b/source/blender/bmesh/intern/bmesh_log.c
index 3b2e43b89ad..16a534b5e56 100644
--- a/source/blender/bmesh/intern/bmesh_log.c
+++ b/source/blender/bmesh/intern/bmesh_log.c
@@ -45,79 +45,78 @@
#include "BLI_strict_flags.h"
-
struct BMLogEntry {
- struct BMLogEntry *next, *prev;
-
- /* The following GHashes map from an element ID to one of the log
- * types above */
-
- /* Elements that were in the previous entry, but have been
- * deleted */
- GHash *deleted_verts;
- GHash *deleted_faces;
- /* Elements that were not in the previous entry, but are in the
- * result of this entry */
- GHash *added_verts;
- GHash *added_faces;
-
- /* Vertices whose coordinates, mask value, or hflag have changed */
- GHash *modified_verts;
- GHash *modified_faces;
-
- BLI_mempool *pool_verts;
- BLI_mempool *pool_faces;
-
- /* This is only needed for dropping BMLogEntries while still in
- * dynamic-topology mode, as that should release vert/face IDs
- * back to the BMLog but no BMLog pointer is available at that
- * time.
- *
- * This field is not guaranteed to be valid, any use of it should
- * check for NULL. */
- BMLog *log;
+ struct BMLogEntry *next, *prev;
+
+ /* The following GHashes map from an element ID to one of the log
+ * types above */
+
+ /* Elements that were in the previous entry, but have been
+ * deleted */
+ GHash *deleted_verts;
+ GHash *deleted_faces;
+ /* Elements that were not in the previous entry, but are in the
+ * result of this entry */
+ GHash *added_verts;
+ GHash *added_faces;
+
+ /* Vertices whose coordinates, mask value, or hflag have changed */
+ GHash *modified_verts;
+ GHash *modified_faces;
+
+ BLI_mempool *pool_verts;
+ BLI_mempool *pool_faces;
+
+ /* This is only needed for dropping BMLogEntries while still in
+ * dynamic-topology mode, as that should release vert/face IDs
+ * back to the BMLog but no BMLog pointer is available at that
+ * time.
+ *
+ * This field is not guaranteed to be valid, any use of it should
+ * check for NULL. */
+ BMLog *log;
};
struct BMLog {
- /* Tree of free IDs */
- struct RangeTreeUInt *unused_ids;
-
- /* Mapping from unique IDs to vertices and faces
- *
- * Each vertex and face in the log gets a unique uinteger
- * assigned. That ID is taken from the set managed by the
- * unused_ids range tree.
- *
- * The ID is needed because element pointers will change as they
- * are created and deleted.
- */
- GHash *id_to_elem;
- GHash *elem_to_id;
-
- /* All BMLogEntrys, ordered from earliest to most recent */
- ListBase entries;
-
- /* The current log entry from entries list
- *
- * If null, then the original mesh from before any of the log
- * entries is current (i.e. there is nothing left to undo.)
- *
- * If equal to the last entry in the entries list, then all log
- * entries have been applied (i.e. there is nothing left to redo.)
- */
- BMLogEntry *current_entry;
+ /* Tree of free IDs */
+ struct RangeTreeUInt *unused_ids;
+
+ /* Mapping from unique IDs to vertices and faces
+ *
+ * Each vertex and face in the log gets a unique uinteger
+ * assigned. That ID is taken from the set managed by the
+ * unused_ids range tree.
+ *
+ * The ID is needed because element pointers will change as they
+ * are created and deleted.
+ */
+ GHash *id_to_elem;
+ GHash *elem_to_id;
+
+ /* All BMLogEntrys, ordered from earliest to most recent */
+ ListBase entries;
+
+ /* The current log entry from entries list
+ *
+ * If null, then the original mesh from before any of the log
+ * entries is current (i.e. there is nothing left to undo.)
+ *
+ * If equal to the last entry in the entries list, then all log
+ * entries have been applied (i.e. there is nothing left to redo.)
+ */
+ BMLogEntry *current_entry;
};
typedef struct {
- float co[3];
- short no[3];
- char hflag;
- float mask;
+ float co[3];
+ short no[3];
+ char hflag;
+ float mask;
} BMLogVert;
typedef struct {
- uint v_ids[3];
- char hflag;
+ uint v_ids[3];
+ char hflag;
} BMLogFace;
/************************* Get/set element IDs ************************/
@@ -129,52 +128,51 @@ typedef struct {
/* Get the vertex's unique ID from the log */
static uint bm_log_vert_id_get(BMLog *log, BMVert *v)
{
- BLI_assert(BLI_ghash_haskey(log->elem_to_id, v));
- return POINTER_AS_UINT(BLI_ghash_lookup(log->elem_to_id, v));
+ BLI_assert(BLI_ghash_haskey(log->elem_to_id, v));
+ return POINTER_AS_UINT(BLI_ghash_lookup(log->elem_to_id, v));
}
/* Set the vertex's unique ID in the log */
static void bm_log_vert_id_set(BMLog *log, BMVert *v, uint id)
{
- void *vid = POINTER_FROM_UINT(id);
+ void *vid = POINTER_FROM_UINT(id);
- BLI_ghash_reinsert(log->id_to_elem, vid, v, NULL, NULL);
- BLI_ghash_reinsert(log->elem_to_id, v, vid, NULL, NULL);
+ BLI_ghash_reinsert(log->id_to_elem, vid, v, NULL, NULL);
+ BLI_ghash_reinsert(log->elem_to_id, v, vid, NULL, NULL);
}
/* Get a vertex from its unique ID */
static BMVert *bm_log_vert_from_id(BMLog *log, uint id)
{
- void *key = POINTER_FROM_UINT(id);
- BLI_assert(BLI_ghash_haskey(log->id_to_elem, key));
- return BLI_ghash_lookup(log->id_to_elem, key);
+ void *key = POINTER_FROM_UINT(id);
+ BLI_assert(BLI_ghash_haskey(log->id_to_elem, key));
+ return BLI_ghash_lookup(log->id_to_elem, key);
}
/* Get the face's unique ID from the log */
static uint bm_log_face_id_get(BMLog *log, BMFace *f)
{
- BLI_assert(BLI_ghash_haskey(log->elem_to_id, f));
- return POINTER_AS_UINT(BLI_ghash_lookup(log->elem_to_id, f));
+ BLI_assert(BLI_ghash_haskey(log->elem_to_id, f));
+ return POINTER_AS_UINT(BLI_ghash_lookup(log->elem_to_id, f));
}
/* Set the face's unique ID in the log */
static void bm_log_face_id_set(BMLog *log, BMFace *f, uint id)
{
- void *fid = POINTER_FROM_UINT(id);
+ void *fid = POINTER_FROM_UINT(id);
- BLI_ghash_reinsert(log->id_to_elem, fid, f, NULL, NULL);
- BLI_ghash_reinsert(log->elem_to_id, f, fid, NULL, NULL);
+ BLI_ghash_reinsert(log->id_to_elem, fid, f, NULL, NULL);
+ BLI_ghash_reinsert(log->elem_to_id, f, fid, NULL, NULL);
}
/* Get a face from its unique ID */
static BMFace *bm_log_face_from_id(BMLog *log, uint id)
{
- void *key = POINTER_FROM_UINT(id);
- BLI_assert(BLI_ghash_haskey(log->id_to_elem, key));
- return BLI_ghash_lookup(log->id_to_elem, key);
+ void *key = POINTER_FROM_UINT(id);
+ BLI_assert(BLI_ghash_haskey(log->id_to_elem, key));
+ return BLI_ghash_lookup(log->id_to_elem, key);
}
-
/************************ BMLogVert / BMLogFace ***********************/
/* Get a vertex's paint-mask value
@@ -182,12 +180,12 @@ static BMFace *bm_log_face_from_id(BMLog *log, uint id)
* Returns zero if no paint-mask layer is present */
static float vert_mask_get(BMVert *v, const int cd_vert_mask_offset)
{
- if (cd_vert_mask_offset != -1) {
- return BM_ELEM_CD_GET_FLOAT(v, cd_vert_mask_offset);
- }
- else {
- return 0.0f;
- }
+ if (cd_vert_mask_offset != -1) {
+ return BM_ELEM_CD_GET_FLOAT(v, cd_vert_mask_offset);
+ }
+ else {
+ return 0.0f;
+ }
}
/* Set a vertex's paint-mask value
@@ -195,208 +193,206 @@ static float vert_mask_get(BMVert *v, const int cd_vert_mask_offset)
* Has no effect is no paint-mask layer is present */
static void vert_mask_set(BMVert *v, const float new_mask, const int cd_vert_mask_offset)
{
- if (cd_vert_mask_offset != -1) {
- BM_ELEM_CD_SET_FLOAT(v, cd_vert_mask_offset, new_mask);
- }
+ if (cd_vert_mask_offset != -1) {
+ BM_ELEM_CD_SET_FLOAT(v, cd_vert_mask_offset, new_mask);
+ }
}
/* Update a BMLogVert with data from a BMVert */
static void bm_log_vert_bmvert_copy(BMLogVert *lv, BMVert *v, const int cd_vert_mask_offset)
{
- copy_v3_v3(lv->co, v->co);
- normal_float_to_short_v3(lv->no, v->no);
- lv->mask = vert_mask_get(v, cd_vert_mask_offset);
- lv->hflag = v->head.hflag;
+ copy_v3_v3(lv->co, v->co);
+ normal_float_to_short_v3(lv->no, v->no);
+ lv->mask = vert_mask_get(v, cd_vert_mask_offset);
+ lv->hflag = v->head.hflag;
}
/* Allocate and initialize a BMLogVert */
static BMLogVert *bm_log_vert_alloc(BMLog *log, BMVert *v, const int cd_vert_mask_offset)
{
- BMLogEntry *entry = log->current_entry;
- BMLogVert *lv = BLI_mempool_alloc(entry->pool_verts);
+ BMLogEntry *entry = log->current_entry;
+ BMLogVert *lv = BLI_mempool_alloc(entry->pool_verts);
- bm_log_vert_bmvert_copy(lv, v, cd_vert_mask_offset);
+ bm_log_vert_bmvert_copy(lv, v, cd_vert_mask_offset);
- return lv;
+ return lv;
}
/* Allocate and initialize a BMLogFace */
static BMLogFace *bm_log_face_alloc(BMLog *log, BMFace *f)
{
- BMLogEntry *entry = log->current_entry;
- BMLogFace *lf = BLI_mempool_alloc(entry->pool_faces);
- BMVert *v[3];
+ BMLogEntry *entry = log->current_entry;
+ BMLogFace *lf = BLI_mempool_alloc(entry->pool_faces);
+ BMVert *v[3];
- BLI_assert(f->len == 3);
+ BLI_assert(f->len == 3);
- // BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v, 3);
- BM_face_as_array_vert_tri(f, v);
+ // BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v, 3);
+ BM_face_as_array_vert_tri(f, v);
- lf->v_ids[0] = bm_log_vert_id_get(log, v[0]);
- lf->v_ids[1] = bm_log_vert_id_get(log, v[1]);
- lf->v_ids[2] = bm_log_vert_id_get(log, v[2]);
+ lf->v_ids[0] = bm_log_vert_id_get(log, v[0]);
+ lf->v_ids[1] = bm_log_vert_id_get(log, v[1]);
+ lf->v_ids[2] = bm_log_vert_id_get(log, v[2]);
- lf->hflag = f->head.hflag;
- return lf;
+ lf->hflag = f->head.hflag;
+ return lf;
}
-
/************************ Helpers for undo/redo ***********************/
static void bm_log_verts_unmake(BMesh *bm, BMLog *log, GHash *verts)
{
- const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK);
+ const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK);
- GHashIterator gh_iter;
- GHASH_ITER (gh_iter, verts) {
- void *key = BLI_ghashIterator_getKey(&gh_iter);
- BMLogVert *lv = BLI_ghashIterator_getValue(&gh_iter);
- uint id = POINTER_AS_UINT(key);
- BMVert *v = bm_log_vert_from_id(log, id);
+ GHashIterator gh_iter;
+ GHASH_ITER (gh_iter, verts) {
+ void *key = BLI_ghashIterator_getKey(&gh_iter);
+ BMLogVert *lv = BLI_ghashIterator_getValue(&gh_iter);
+ uint id = POINTER_AS_UINT(key);
+ BMVert *v = bm_log_vert_from_id(log, id);
- /* Ensure the log has the final values of the vertex before
- * deleting it */
- bm_log_vert_bmvert_copy(lv, v, cd_vert_mask_offset);
+ /* Ensure the log has the final values of the vertex before
+ * deleting it */
+ bm_log_vert_bmvert_copy(lv, v, cd_vert_mask_offset);
- BM_vert_kill(bm, v);
- }
+ BM_vert_kill(bm, v);
+ }
}
static void bm_log_faces_unmake(BMesh *bm, BMLog *log, GHash *faces)
{
- GHashIterator gh_iter;
- GHASH_ITER (gh_iter, faces) {
- void *key = BLI_ghashIterator_getKey(&gh_iter);
- uint id = POINTER_AS_UINT(key);
- BMFace *f = bm_log_face_from_id(log, id);
- BMEdge *e_tri[3];
- BMLoop *l_iter;
- int i;
-
- l_iter = BM_FACE_FIRST_LOOP(f);
- for (i = 0; i < 3; i++, l_iter = l_iter->next) {
- e_tri[i] = l_iter->e;
- }
-
- /* Remove any unused edges */
- BM_face_kill(bm, f);
- for (i = 0; i < 3; i++) {
- if (BM_edge_is_wire(e_tri[i])) {
- BM_edge_kill(bm, e_tri[i]);
- }
- }
- }
+ GHashIterator gh_iter;
+ GHASH_ITER (gh_iter, faces) {
+ void *key = BLI_ghashIterator_getKey(&gh_iter);
+ uint id = POINTER_AS_UINT(key);
+ BMFace *f = bm_log_face_from_id(log, id);
+ BMEdge *e_tri[3];
+ BMLoop *l_iter;
+ int i;
+
+ l_iter = BM_FACE_FIRST_LOOP(f);
+ for (i = 0; i < 3; i++, l_iter = l_iter->next) {
+ e_tri[i] = l_iter->e;
+ }
+
+ /* Remove any unused edges */
+ BM_face_kill(bm, f);
+ for (i = 0; i < 3; i++) {
+ if (BM_edge_is_wire(e_tri[i])) {
+ BM_edge_kill(bm, e_tri[i]);
+ }
+ }
+ }
}
static void bm_log_verts_restore(BMesh *bm, BMLog *log, GHash *verts)
{
- const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK);
-
- GHashIterator gh_iter;
- GHASH_ITER (gh_iter, verts) {
- void *key = BLI_ghashIterator_getKey(&gh_iter);
- BMLogVert *lv = BLI_ghashIterator_getValue(&gh_iter);
- BMVert *v = BM_vert_create(bm, lv->co, NULL, BM_CREATE_NOP);
- vert_mask_set(v, lv->mask, cd_vert_mask_offset);
- v->head.hflag = lv->hflag;
- normal_short_to_float_v3(v->no, lv->no);
- bm_log_vert_id_set(log, v, POINTER_AS_UINT(key));
- }
+ const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK);
+
+ GHashIterator gh_iter;
+ GHASH_ITER (gh_iter, verts) {
+ void *key = BLI_ghashIterator_getKey(&gh_iter);
+ BMLogVert *lv = BLI_ghashIterator_getValue(&gh_iter);
+ BMVert *v = BM_vert_create(bm, lv->co, NULL, BM_CREATE_NOP);
+ vert_mask_set(v, lv->mask, cd_vert_mask_offset);
+ v->head.hflag = lv->hflag;
+ normal_short_to_float_v3(v->no, lv->no);
+ bm_log_vert_id_set(log, v, POINTER_AS_UINT(key));
+ }
}
static void bm_log_faces_restore(BMesh *bm, BMLog *log, GHash *faces)
{
- GHashIterator gh_iter;
- GHASH_ITER (gh_iter, faces) {
- void *key = BLI_ghashIterator_getKey(&gh_iter);
- BMLogFace *lf = BLI_ghashIterator_getValue(&gh_iter);
- BMVert *v[3] = {bm_log_vert_from_id(log, lf->v_ids[0]),
- bm_log_vert_from_id(log, lf->v_ids[1]),
- bm_log_vert_from_id(log, lf->v_ids[2])};
- BMFace *f;
-
- f = BM_face_create_verts(bm, v, 3, NULL, BM_CREATE_NOP, true);
- f->head.hflag = lf->hflag;
- bm_log_face_id_set(log, f, POINTER_AS_UINT(key));
- }
+ GHashIterator gh_iter;
+ GHASH_ITER (gh_iter, faces) {
+ void *key = BLI_ghashIterator_getKey(&gh_iter);
+ BMLogFace *lf = BLI_ghashIterator_getValue(&gh_iter);
+ BMVert *v[3] = {bm_log_vert_from_id(log, lf->v_ids[0]),
+ bm_log_vert_from_id(log, lf->v_ids[1]),
+ bm_log_vert_from_id(log, lf->v_ids[2])};
+ BMFace *f;
+
+ f = BM_face_create_verts(bm, v, 3, NULL, BM_CREATE_NOP, true);
+ f->head.hflag = lf->hflag;
+ bm_log_face_id_set(log, f, POINTER_AS_UINT(key));
+ }
}
static void bm_log_vert_values_swap(BMesh *bm, BMLog *log, GHash *verts)
{
- const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK);
-
- GHashIterator gh_iter;
- GHASH_ITER (gh_iter, verts) {
- void *key = BLI_ghashIterator_getKey(&gh_iter);
- BMLogVert *lv = BLI_ghashIterator_getValue(&gh_iter);
- uint id = POINTER_AS_UINT(key);
- BMVert *v = bm_log_vert_from_id(log, id);
- float mask;
- short normal[3];
-
- swap_v3_v3(v->co, lv->co);
- copy_v3_v3_short(normal, lv->no);
- normal_float_to_short_v3(lv->no, v->no);
- normal_short_to_float_v3(v->no, normal);
- SWAP(char, v->head.hflag, lv->hflag);
- mask = lv->mask;
- lv->mask = vert_mask_get(v, cd_vert_mask_offset);
- vert_mask_set(v, mask, cd_vert_mask_offset);
- }
+ const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK);
+
+ GHashIterator gh_iter;
+ GHASH_ITER (gh_iter, verts) {
+ void *key = BLI_ghashIterator_getKey(&gh_iter);
+ BMLogVert *lv = BLI_ghashIterator_getValue(&gh_iter);
+ uint id = POINTER_AS_UINT(key);
+ BMVert *v = bm_log_vert_from_id(log, id);
+ float mask;
+ short normal[3];
+
+ swap_v3_v3(v->co, lv->co);
+ copy_v3_v3_short(normal, lv->no);
+ normal_float_to_short_v3(lv->no, v->no);
+ normal_short_to_float_v3(v->no, normal);
+ SWAP(char, v->head.hflag, lv->hflag);
+ mask = lv->mask;
+ lv->mask = vert_mask_get(v, cd_vert_mask_offset);
+ vert_mask_set(v, mask, cd_vert_mask_offset);
+ }
}
static void bm_log_face_values_swap(BMLog *log, GHash *faces)
{
- GHashIterator gh_iter;
- GHASH_ITER (gh_iter, faces) {
- void *key = BLI_ghashIterator_getKey(&gh_iter);
- BMLogFace *lf = BLI_ghashIterator_getValue(&gh_iter);
- uint id = POINTER_AS_UINT(key);
- BMFace *f = bm_log_face_from_id(log, id);
-
- SWAP(char, f->head.hflag, lf->hflag);
- }
+ GHashIterator gh_iter;
+ GHASH_ITER (gh_iter, faces) {
+ void *key = BLI_ghashIterator_getKey(&gh_iter);
+ BMLogFace *lf = BLI_ghashIterator_getValue(&gh_iter);
+ uint id = POINTER_AS_UINT(key);
+ BMFace *f = bm_log_face_from_id(log, id);
+
+ SWAP(char, f->head.hflag, lf->hflag);
+ }
}
-
/**********************************************************************/
/* Assign unique IDs to all vertices and faces already in the BMesh */
static void bm_log_assign_ids(BMesh *bm, BMLog *log)
{
- BMIter iter;
- BMVert *v;
- BMFace *f;
-
- /* Generate vertex IDs */
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- uint id = range_tree_uint_take_any(log->unused_ids);
- bm_log_vert_id_set(log, v, id);
- }
-
- /* Generate face IDs */
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- uint id = range_tree_uint_take_any(log->unused_ids);
- bm_log_face_id_set(log, f, id);
- }
+ BMIter iter;
+ BMVert *v;
+ BMFace *f;
+
+ /* Generate vertex IDs */
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ uint id = range_tree_uint_take_any(log->unused_ids);
+ bm_log_vert_id_set(log, v, id);
+ }
+
+ /* Generate face IDs */
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ uint id = range_tree_uint_take_any(log->unused_ids);
+ bm_log_face_id_set(log, f, id);
+ }
}
/* Allocate an empty log entry */
static BMLogEntry *bm_log_entry_create(void)
{
- BMLogEntry *entry = MEM_callocN(sizeof(BMLogEntry), __func__);
+ BMLogEntry *entry = MEM_callocN(sizeof(BMLogEntry), __func__);
- entry->deleted_verts = BLI_ghash_new(logkey_hash, logkey_cmp, __func__);
- entry->deleted_faces = BLI_ghash_new(logkey_hash, logkey_cmp, __func__);
- entry->added_verts = BLI_ghash_new(logkey_hash, logkey_cmp, __func__);
- entry->added_faces = BLI_ghash_new(logkey_hash, logkey_cmp, __func__);
- entry->modified_verts = BLI_ghash_new(logkey_hash, logkey_cmp, __func__);
- entry->modified_faces = BLI_ghash_new(logkey_hash, logkey_cmp, __func__);
+ entry->deleted_verts = BLI_ghash_new(logkey_hash, logkey_cmp, __func__);
+ entry->deleted_faces = BLI_ghash_new(logkey_hash, logkey_cmp, __func__);
+ entry->added_verts = BLI_ghash_new(logkey_hash, logkey_cmp, __func__);
+ entry->added_faces = BLI_ghash_new(logkey_hash, logkey_cmp, __func__);
+ entry->modified_verts = BLI_ghash_new(logkey_hash, logkey_cmp, __func__);
+ entry->modified_faces = BLI_ghash_new(logkey_hash, logkey_cmp, __func__);
- entry->pool_verts = BLI_mempool_create(sizeof(BMLogVert), 0, 64, BLI_MEMPOOL_NOP);
- entry->pool_faces = BLI_mempool_create(sizeof(BMLogFace), 0, 64, BLI_MEMPOOL_NOP);
+ entry->pool_verts = BLI_mempool_create(sizeof(BMLogVert), 0, 64, BLI_MEMPOOL_NOP);
+ entry->pool_faces = BLI_mempool_create(sizeof(BMLogFace), 0, 64, BLI_MEMPOOL_NOP);
- return entry;
+ return entry;
}
/* Free the data in a log entry
@@ -404,34 +400,34 @@ static BMLogEntry *bm_log_entry_create(void)
* Note: does not free the log entry itself */
static void bm_log_entry_free(BMLogEntry *entry)
{
- BLI_ghash_free(entry->deleted_verts, NULL, NULL);
- BLI_ghash_free(entry->deleted_faces, NULL, NULL);
- BLI_ghash_free(entry->added_verts, NULL, NULL);
- BLI_ghash_free(entry->added_faces, NULL, NULL);
- BLI_ghash_free(entry->modified_verts, NULL, NULL);
- BLI_ghash_free(entry->modified_faces, NULL, NULL);
-
- BLI_mempool_destroy(entry->pool_verts);
- BLI_mempool_destroy(entry->pool_faces);
+ BLI_ghash_free(entry->deleted_verts, NULL, NULL);
+ BLI_ghash_free(entry->deleted_faces, NULL, NULL);
+ BLI_ghash_free(entry->added_verts, NULL, NULL);
+ BLI_ghash_free(entry->added_faces, NULL, NULL);
+ BLI_ghash_free(entry->modified_verts, NULL, NULL);
+ BLI_ghash_free(entry->modified_faces, NULL, NULL);
+
+ BLI_mempool_destroy(entry->pool_verts);
+ BLI_mempool_destroy(entry->pool_faces);
}
static void bm_log_id_ghash_retake(RangeTreeUInt *unused_ids, GHash *id_ghash)
{
- GHashIterator gh_iter;
+ GHashIterator gh_iter;
- GHASH_ITER (gh_iter, id_ghash) {
- void *key = BLI_ghashIterator_getKey(&gh_iter);
- uint id = POINTER_AS_UINT(key);
+ GHASH_ITER (gh_iter, id_ghash) {
+ void *key = BLI_ghashIterator_getKey(&gh_iter);
+ uint id = POINTER_AS_UINT(key);
- range_tree_uint_retake(unused_ids, id);
- }
+ range_tree_uint_retake(unused_ids, id);
+ }
}
static int uint_compare(const void *a_v, const void *b_v)
{
- const uint *a = a_v;
- const uint *b = b_v;
- return (*a) < (*b);
+ const uint *a = a_v;
+ const uint *b = b_v;
+ return (*a) < (*b);
}
/* Remap IDs to contiguous indices
@@ -444,30 +440,30 @@ static int uint_compare(const void *a_v, const void *b_v)
*/
static GHash *bm_log_compress_ids_to_indices(uint *ids, uint totid)
{
- GHash *map = BLI_ghash_int_new_ex(__func__, totid);
- uint i;
+ GHash *map = BLI_ghash_int_new_ex(__func__, totid);
+ uint i;
- qsort(ids, totid, sizeof(*ids), uint_compare);
+ qsort(ids, totid, sizeof(*ids), uint_compare);
- for (i = 0; i < totid; i++) {
- void *key = POINTER_FROM_UINT(ids[i]);
- void *val = POINTER_FROM_UINT(i);
- BLI_ghash_insert(map, key, val);
- }
+ for (i = 0; i < totid; i++) {
+ void *key = POINTER_FROM_UINT(ids[i]);
+ void *val = POINTER_FROM_UINT(i);
+ BLI_ghash_insert(map, key, val);
+ }
- return map;
+ return map;
}
/* Release all ID keys in id_ghash */
static void bm_log_id_ghash_release(BMLog *log, GHash *id_ghash)
{
- GHashIterator gh_iter;
+ GHashIterator gh_iter;
- GHASH_ITER (gh_iter, id_ghash) {
- void *key = BLI_ghashIterator_getKey(&gh_iter);
- uint id = POINTER_AS_UINT(key);
- range_tree_uint_release(log->unused_ids, id);
- }
+ GHASH_ITER (gh_iter, id_ghash) {
+ void *key = BLI_ghashIterator_getKey(&gh_iter);
+ uint id = POINTER_AS_UINT(key);
+ range_tree_uint_release(log->unused_ids, id);
+ }
}
/***************************** Public API *****************************/
@@ -475,42 +471,41 @@ static void bm_log_id_ghash_release(BMLog *log, GHash *id_ghash)
/* Allocate, initialize, and assign a new BMLog */
BMLog *BM_log_create(BMesh *bm)
{
- BMLog *log = MEM_callocN(sizeof(*log), __func__);
- const uint reserve_num = (uint)(bm->totvert + bm->totface);
+ BMLog *log = MEM_callocN(sizeof(*log), __func__);
+ const uint reserve_num = (uint)(bm->totvert + bm->totface);
- log->unused_ids = range_tree_uint_alloc(0, (unsigned)-1);
- log->id_to_elem = BLI_ghash_new_ex(logkey_hash, logkey_cmp, __func__, reserve_num);
- log->elem_to_id = BLI_ghash_ptr_new_ex(__func__, reserve_num);
+ log->unused_ids = range_tree_uint_alloc(0, (unsigned)-1);
+ log->id_to_elem = BLI_ghash_new_ex(logkey_hash, logkey_cmp, __func__, reserve_num);
+ log->elem_to_id = BLI_ghash_ptr_new_ex(__func__, reserve_num);
- /* Assign IDs to all existing vertices and faces */
- bm_log_assign_ids(bm, log);
+ /* Assign IDs to all existing vertices and faces */
+ bm_log_assign_ids(bm, log);
- return log;
+ return log;
}
void BM_log_cleanup_entry(BMLogEntry *entry)
{
- BMLog *log = entry->log;
-
- if (log) {
- /* Take all used IDs */
- bm_log_id_ghash_retake(log->unused_ids, entry->deleted_verts);
- bm_log_id_ghash_retake(log->unused_ids, entry->deleted_faces);
- bm_log_id_ghash_retake(log->unused_ids, entry->added_verts);
- bm_log_id_ghash_retake(log->unused_ids, entry->added_faces);
- bm_log_id_ghash_retake(log->unused_ids, entry->modified_verts);
- bm_log_id_ghash_retake(log->unused_ids, entry->modified_faces);
-
- /* delete entries to avoid releasing ids in node cleanup */
- BLI_ghash_clear(entry->deleted_verts, NULL, NULL);
- BLI_ghash_clear(entry->deleted_faces, NULL, NULL);
- BLI_ghash_clear(entry->added_verts, NULL, NULL);
- BLI_ghash_clear(entry->added_faces, NULL, NULL);
- BLI_ghash_clear(entry->modified_verts, NULL, NULL);
- }
+ BMLog *log = entry->log;
+
+ if (log) {
+ /* Take all used IDs */
+ bm_log_id_ghash_retake(log->unused_ids, entry->deleted_verts);
+ bm_log_id_ghash_retake(log->unused_ids, entry->deleted_faces);
+ bm_log_id_ghash_retake(log->unused_ids, entry->added_verts);
+ bm_log_id_ghash_retake(log->unused_ids, entry->added_faces);
+ bm_log_id_ghash_retake(log->unused_ids, entry->modified_verts);
+ bm_log_id_ghash_retake(log->unused_ids, entry->modified_faces);
+
+ /* delete entries to avoid releasing ids in node cleanup */
+ BLI_ghash_clear(entry->deleted_verts, NULL, NULL);
+ BLI_ghash_clear(entry->deleted_faces, NULL, NULL);
+ BLI_ghash_clear(entry->added_verts, NULL, NULL);
+ BLI_ghash_clear(entry->added_faces, NULL, NULL);
+ BLI_ghash_clear(entry->modified_verts, NULL, NULL);
+ }
}
-
/* Allocate and initialize a new BMLog using existing BMLogEntries
*
* The 'entry' should be the last entry in the BMLog. Its prev pointer
@@ -521,127 +516,127 @@ void BM_log_cleanup_entry(BMLogEntry *entry)
*/
BMLog *BM_log_from_existing_entries_create(BMesh *bm, BMLogEntry *entry)
{
- BMLog *log = BM_log_create(bm);
-
- if (entry->prev) {
- log->current_entry = entry;
- }
- else {
- log->current_entry = NULL;
- }
-
- /* Let BMLog manage the entry list again */
- log->entries.first = log->entries.last = entry;
-
- {
- while (entry->prev) {
- entry = entry->prev;
- log->entries.first = entry;
- }
- entry = log->entries.last;
- while (entry->next) {
- entry = entry->next;
- log->entries.last = entry;
- }
- }
-
- for (entry = log->entries.first; entry; entry = entry->next) {
- entry->log = log;
-
- /* Take all used IDs */
- bm_log_id_ghash_retake(log->unused_ids, entry->deleted_verts);
- bm_log_id_ghash_retake(log->unused_ids, entry->deleted_faces);
- bm_log_id_ghash_retake(log->unused_ids, entry->added_verts);
- bm_log_id_ghash_retake(log->unused_ids, entry->added_faces);
- bm_log_id_ghash_retake(log->unused_ids, entry->modified_verts);
- bm_log_id_ghash_retake(log->unused_ids, entry->modified_faces);
- }
-
- return log;
+ BMLog *log = BM_log_create(bm);
+
+ if (entry->prev) {
+ log->current_entry = entry;
+ }
+ else {
+ log->current_entry = NULL;
+ }
+
+ /* Let BMLog manage the entry list again */
+ log->entries.first = log->entries.last = entry;
+
+ {
+ while (entry->prev) {
+ entry = entry->prev;
+ log->entries.first = entry;
+ }
+ entry = log->entries.last;
+ while (entry->next) {
+ entry = entry->next;
+ log->entries.last = entry;
+ }
+ }
+
+ for (entry = log->entries.first; entry; entry = entry->next) {
+ entry->log = log;
+
+ /* Take all used IDs */
+ bm_log_id_ghash_retake(log->unused_ids, entry->deleted_verts);
+ bm_log_id_ghash_retake(log->unused_ids, entry->deleted_faces);
+ bm_log_id_ghash_retake(log->unused_ids, entry->added_verts);
+ bm_log_id_ghash_retake(log->unused_ids, entry->added_faces);
+ bm_log_id_ghash_retake(log->unused_ids, entry->modified_verts);
+ bm_log_id_ghash_retake(log->unused_ids, entry->modified_faces);
+ }
+
+ return log;
}
/* Free all the data in a BMLog including the log itself */
void BM_log_free(BMLog *log)
{
- BMLogEntry *entry;
+ BMLogEntry *entry;
- if (log->unused_ids) {
- range_tree_uint_free(log->unused_ids);
- }
+ if (log->unused_ids) {
+ range_tree_uint_free(log->unused_ids);
+ }
- if (log->id_to_elem) {
- BLI_ghash_free(log->id_to_elem, NULL, NULL);
- }
+ if (log->id_to_elem) {
+ BLI_ghash_free(log->id_to_elem, NULL, NULL);
+ }
- if (log->elem_to_id) {
- BLI_ghash_free(log->elem_to_id, NULL, NULL);
- }
+ if (log->elem_to_id) {
+ BLI_ghash_free(log->elem_to_id, NULL, NULL);
+ }
- /* Clear the BMLog references within each entry, but do not free
- * the entries themselves */
- for (entry = log->entries.first; entry; entry = entry->next) {
- entry->log = NULL;
- }
+ /* Clear the BMLog references within each entry, but do not free
+ * the entries themselves */
+ for (entry = log->entries.first; entry; entry = entry->next) {
+ entry->log = NULL;
+ }
- MEM_freeN(log);
+ MEM_freeN(log);
}
/* Get the number of log entries */
int BM_log_length(const BMLog *log)
{
- return BLI_listbase_count(&log->entries);
+ return BLI_listbase_count(&log->entries);
}
/* Apply a consistent ordering to BMesh vertices */
void BM_log_mesh_elems_reorder(BMesh *bm, BMLog *log)
{
- uint *varr;
- uint *farr;
-
- GHash *id_to_idx;
-
- BMIter bm_iter;
- BMVert *v;
- BMFace *f;
-
- uint i;
-
- /* Put all vertex IDs into an array */
- varr = MEM_mallocN(sizeof(int) * (size_t)bm->totvert, __func__);
- BM_ITER_MESH_INDEX (v, &bm_iter, bm, BM_VERTS_OF_MESH, i) {
- varr[i] = bm_log_vert_id_get(log, v);
- }
-
- /* Put all face IDs into an array */
- farr = MEM_mallocN(sizeof(int) * (size_t)bm->totface, __func__);
- BM_ITER_MESH_INDEX (f, &bm_iter, bm, BM_FACES_OF_MESH, i) {
- farr[i] = bm_log_face_id_get(log, f);
- }
-
- /* Create BMVert index remap array */
- id_to_idx = bm_log_compress_ids_to_indices(varr, (uint)bm->totvert);
- BM_ITER_MESH_INDEX (v, &bm_iter, bm, BM_VERTS_OF_MESH, i) {
- const unsigned id = bm_log_vert_id_get(log, v);
- const void *key = POINTER_FROM_UINT(id);
- const void *val = BLI_ghash_lookup(id_to_idx, key);
- varr[i] = POINTER_AS_UINT(val);
- }
- BLI_ghash_free(id_to_idx, NULL, NULL);
-
- /* Create BMFace index remap array */
- id_to_idx = bm_log_compress_ids_to_indices(farr, (uint)bm->totface);
- BM_ITER_MESH_INDEX (f, &bm_iter, bm, BM_FACES_OF_MESH, i) {
- const unsigned id = bm_log_face_id_get(log, f);
- const void *key = POINTER_FROM_UINT(id);
- const void *val = BLI_ghash_lookup(id_to_idx, key);
- farr[i] = POINTER_AS_UINT(val);
- }
- BLI_ghash_free(id_to_idx, NULL, NULL);
-
- BM_mesh_remap(bm, varr, NULL, farr);
-
- MEM_freeN(varr);
- MEM_freeN(farr);
+ uint *varr;
+ uint *farr;
+
+ GHash *id_to_idx;
+
+ BMIter bm_iter;
+ BMVert *v;
+ BMFace *f;
+
+ uint i;
+
+ /* Put all vertex IDs into an array */
+ varr = MEM_mallocN(sizeof(int) * (size_t)bm->totvert, __func__);
+ BM_ITER_MESH_INDEX (v, &bm_iter, bm, BM_VERTS_OF_MESH, i) {
+ varr[i] = bm_log_vert_id_get(log, v);
+ }
+
+ /* Put all face IDs into an array */
+ farr = MEM_mallocN(sizeof(int) * (size_t)bm->totface, __func__);
+ BM_ITER_MESH_INDEX (f, &bm_iter, bm, BM_FACES_OF_MESH, i) {
+ farr[i] = bm_log_face_id_get(log, f);
+ }
+
+ /* Create BMVert index remap array */
+ id_to_idx = bm_log_compress_ids_to_indices(varr, (uint)bm->totvert);
+ BM_ITER_MESH_INDEX (v, &bm_iter, bm, BM_VERTS_OF_MESH, i) {
+ const unsigned id = bm_log_vert_id_get(log, v);
+ const void *key = POINTER_FROM_UINT(id);
+ const void *val = BLI_ghash_lookup(id_to_idx, key);
+ varr[i] = POINTER_AS_UINT(val);
+ }
+ BLI_ghash_free(id_to_idx, NULL, NULL);
+
+ /* Create BMFace index remap array */
+ id_to_idx = bm_log_compress_ids_to_indices(farr, (uint)bm->totface);
+ BM_ITER_MESH_INDEX (f, &bm_iter, bm, BM_FACES_OF_MESH, i) {
+ const unsigned id = bm_log_face_id_get(log, f);
+ const void *key = POINTER_FROM_UINT(id);
+ const void *val = BLI_ghash_lookup(id_to_idx, key);
+ farr[i] = POINTER_AS_UINT(val);
+ }
+ BLI_ghash_free(id_to_idx, NULL, NULL);
+
+ BM_mesh_remap(bm, varr, NULL, farr);
+
+ MEM_freeN(varr);
+ MEM_freeN(farr);
}
/* Start a new log entry and update the log entry list
@@ -656,29 +651,29 @@ void BM_log_mesh_elems_reorder(BMesh *bm, BMLog *log)
*/
BMLogEntry *BM_log_entry_add(BMLog *log)
{
- /* WARNING: this is now handled by the UndoSystem: BKE_UNDOSYS_TYPE_SCULPT
- * freeing here causes unnecessary complications. */
- BMLogEntry *entry;
+ /* WARNING: this is now handled by the UndoSystem: BKE_UNDOSYS_TYPE_SCULPT
+ * freeing here causes unnecessary complications. */
+ BMLogEntry *entry;
#if 0
- /* Delete any entries after the current one */
- entry = log->current_entry;
- if (entry) {
- BMLogEntry *next;
- for (entry = entry->next; entry; entry = next) {
- next = entry->next;
- bm_log_entry_free(entry);
- BLI_freelinkN(&log->entries, entry);
- }
- }
+ /* Delete any entries after the current one */
+ entry = log->current_entry;
+ if (entry) {
+ BMLogEntry *next;
+ for (entry = entry->next; entry; entry = next) {
+ next = entry->next;
+ bm_log_entry_free(entry);
+ BLI_freelinkN(&log->entries, entry);
+ }
+ }
#endif
- /* Create and append the new entry */
- entry = bm_log_entry_create();
- BLI_addtail(&log->entries, entry);
- entry->log = log;
- log->current_entry = entry;
+ /* Create and append the new entry */
+ entry = bm_log_entry_create();
+ BLI_addtail(&log->entries, entry);
+ entry->log = log;
+ log->current_entry = entry;
- return entry;
+ return entry;
}
/* Remove an entry from the log
@@ -692,68 +687,68 @@ BMLogEntry *BM_log_entry_add(BMLog *log)
*/
void BM_log_entry_drop(BMLogEntry *entry)
{
- BMLog *log = entry->log;
-
- if (!log) {
- /* Unlink */
- BLI_assert(!(entry->prev && entry->next));
- if (entry->prev) {
- entry->prev->next = NULL;
- }
- else if (entry->next) {
- entry->next->prev = NULL;
- }
-
- bm_log_entry_free(entry);
- MEM_freeN(entry);
- return;
- }
-
- if (!entry->prev) {
- /* Release IDs of elements that are deleted by this
- * entry. Since the entry is at the beginning of the undo
- * stack, and it's being deleted, those elements can never be
- * restored. Their IDs can go back into the pool. */
-
- /* This would never happen usually since first entry of log is
- * usually dyntopo enable, which, when reverted will free the log
- * completely. However, it is possible have a stroke instead of
- * dyntopo enable as first entry if nodes have been cleaned up
- * after sculpting on a different object than A, B.
- *
- * The steps are:
- * A dyntopo enable - sculpt
- * B dyntopo enable - sculpt - undo (A objects operators get cleaned up)
- * A sculpt (now A's log has a sculpt operator as first entry)
- *
- * Causing a cleanup at this point will call the code below, however
- * this will invalidate the state of the log since the deleted vertices
- * have been reclaimed already on step 2 (see BM_log_cleanup_entry)
- *
- * Also, design wise, a first entry should not have any deleted vertices since it
- * should not have anything to delete them -from-
- */
- //bm_log_id_ghash_release(log, entry->deleted_faces);
- //bm_log_id_ghash_release(log, entry->deleted_verts);
- }
- else if (!entry->next) {
- /* Release IDs of elements that are added by this entry. Since
- * the entry is at the end of the undo stack, and it's being
- * deleted, those elements can never be restored. Their IDs
- * can go back into the pool. */
- bm_log_id_ghash_release(log, entry->added_faces);
- bm_log_id_ghash_release(log, entry->added_verts);
- }
- else {
- BLI_assert(!"Cannot drop BMLogEntry from middle");
- }
-
- if (log->current_entry == entry) {
- log->current_entry = entry->prev;
- }
-
- bm_log_entry_free(entry);
- BLI_freelinkN(&log->entries, entry);
+ BMLog *log = entry->log;
+
+ if (!log) {
+ /* Unlink */
+ BLI_assert(!(entry->prev && entry->next));
+ if (entry->prev) {
+ entry->prev->next = NULL;
+ }
+ else if (entry->next) {
+ entry->next->prev = NULL;
+ }
+
+ bm_log_entry_free(entry);
+ MEM_freeN(entry);
+ return;
+ }
+
+ if (!entry->prev) {
+ /* Release IDs of elements that are deleted by this
+ * entry. Since the entry is at the beginning of the undo
+ * stack, and it's being deleted, those elements can never be
+ * restored. Their IDs can go back into the pool. */
+
+ /* This would never happen usually since first entry of log is
+ * usually dyntopo enable, which, when reverted will free the log
+ * completely. However, it is possible have a stroke instead of
+ * dyntopo enable as first entry if nodes have been cleaned up
+ * after sculpting on a different object than A, B.
+ *
+ * The steps are:
+ * A dyntopo enable - sculpt
+ * B dyntopo enable - sculpt - undo (A objects operators get cleaned up)
+ * A sculpt (now A's log has a sculpt operator as first entry)
+ *
+ * Causing a cleanup at this point will call the code below, however
+ * this will invalidate the state of the log since the deleted vertices
+ * have been reclaimed already on step 2 (see BM_log_cleanup_entry)
+ *
+ * Also, design wise, a first entry should not have any deleted vertices since it
+ * should not have anything to delete them -from-
+ */
+ //bm_log_id_ghash_release(log, entry->deleted_faces);
+ //bm_log_id_ghash_release(log, entry->deleted_verts);
+ }
+ else if (!entry->next) {
+ /* Release IDs of elements that are added by this entry. Since
+ * the entry is at the end of the undo stack, and it's being
+ * deleted, those elements can never be restored. Their IDs
+ * can go back into the pool. */
+ bm_log_id_ghash_release(log, entry->added_faces);
+ bm_log_id_ghash_release(log, entry->added_verts);
+ }
+ else {
+ BLI_assert(!"Cannot drop BMLogEntry from middle");
+ }
+
+ if (log->current_entry == entry) {
+ log->current_entry = entry->prev;
+ }
+
+ bm_log_entry_free(entry);
+ BLI_freelinkN(&log->entries, entry);
}
/* Undo one BMLogEntry
@@ -761,23 +756,23 @@ void BM_log_entry_drop(BMLogEntry *entry)
* Has no effect if there's nothing left to undo */
void BM_log_undo(BMesh *bm, BMLog *log)
{
- BMLogEntry *entry = log->current_entry;
+ BMLogEntry *entry = log->current_entry;
- if (entry) {
- log->current_entry = entry->prev;
+ if (entry) {
+ log->current_entry = entry->prev;
- /* Delete added faces and verts */
- bm_log_faces_unmake(bm, log, entry->added_faces);
- bm_log_verts_unmake(bm, log, entry->added_verts);
+ /* Delete added faces and verts */
+ bm_log_faces_unmake(bm, log, entry->added_faces);
+ bm_log_verts_unmake(bm, log, entry->added_verts);
- /* Restore deleted verts and faces */
- bm_log_verts_restore(bm, log, entry->deleted_verts);
- bm_log_faces_restore(bm, log, entry->deleted_faces);
+ /* Restore deleted verts and faces */
+ bm_log_verts_restore(bm, log, entry->deleted_verts);
+ bm_log_faces_restore(bm, log, entry->deleted_faces);
- /* Restore vertex coordinates, mask, and hflag */
- bm_log_vert_values_swap(bm, log, entry->modified_verts);
- bm_log_face_values_swap(log, entry->modified_faces);
- }
+ /* Restore vertex coordinates, mask, and hflag */
+ bm_log_vert_values_swap(bm, log, entry->modified_verts);
+ bm_log_face_values_swap(log, entry->modified_faces);
+ }
}
/* Redo one BMLogEntry
@@ -785,36 +780,36 @@ void BM_log_undo(BMesh *bm, BMLog *log)
* Has no effect if there's nothing left to redo */
void BM_log_redo(BMesh *bm, BMLog *log)
{
- BMLogEntry *entry = log->current_entry;
-
- if (!entry) {
- /* Currently at the beginning of the undo stack, move to first entry */
- entry = log->entries.first;
- }
- else if (entry && entry->next) {
- /* Move to next undo entry */
- entry = entry->next;
- }
- else {
- /* Currently at the end of the undo stack, nothing left to redo */
- return;
- }
-
- log->current_entry = entry;
-
- if (entry) {
- /* Re-delete previously deleted faces and verts */
- bm_log_faces_unmake(bm, log, entry->deleted_faces);
- bm_log_verts_unmake(bm, log, entry->deleted_verts);
-
- /* Restore previously added verts and faces */
- bm_log_verts_restore(bm, log, entry->added_verts);
- bm_log_faces_restore(bm, log, entry->added_faces);
-
- /* Restore vertex coordinates, mask, and hflag */
- bm_log_vert_values_swap(bm, log, entry->modified_verts);
- bm_log_face_values_swap(log, entry->modified_faces);
- }
+ BMLogEntry *entry = log->current_entry;
+
+ if (!entry) {
+ /* Currently at the beginning of the undo stack, move to first entry */
+ entry = log->entries.first;
+ }
+ else if (entry && entry->next) {
+ /* Move to next undo entry */
+ entry = entry->next;
+ }
+ else {
+ /* Currently at the end of the undo stack, nothing left to redo */
+ return;
+ }
+
+ log->current_entry = entry;
+
+ if (entry) {
+ /* Re-delete previously deleted faces and verts */
+ bm_log_faces_unmake(bm, log, entry->deleted_faces);
+ bm_log_verts_unmake(bm, log, entry->deleted_verts);
+
+ /* Restore previously added verts and faces */
+ bm_log_verts_restore(bm, log, entry->added_verts);
+ bm_log_faces_restore(bm, log, entry->added_faces);
+
+ /* Restore vertex coordinates, mask, and hflag */
+ bm_log_vert_values_swap(bm, log, entry->modified_verts);
+ bm_log_face_values_swap(log, entry->modified_faces);
+ }
}
/* Log a vertex before it is modified
@@ -842,23 +837,22 @@ void BM_log_redo(BMesh *bm, BMLog *log)
*/
void BM_log_vert_before_modified(BMLog *log, BMVert *v, const int cd_vert_mask_offset)
{
- BMLogEntry *entry = log->current_entry;
- BMLogVert *lv;
- uint v_id = bm_log_vert_id_get(log, v);
- void *key = POINTER_FROM_UINT(v_id);
- void **val_p;
-
- /* Find or create the BMLogVert entry */
- if ((lv = BLI_ghash_lookup(entry->added_verts, key))) {
- bm_log_vert_bmvert_copy(lv, v, cd_vert_mask_offset);
- }
- else if (!BLI_ghash_ensure_p(entry->modified_verts, key, &val_p)) {
- lv = bm_log_vert_alloc(log, v, cd_vert_mask_offset);
- *val_p = lv;
- }
+ BMLogEntry *entry = log->current_entry;
+ BMLogVert *lv;
+ uint v_id = bm_log_vert_id_get(log, v);
+ void *key = POINTER_FROM_UINT(v_id);
+ void **val_p;
+
+ /* Find or create the BMLogVert entry */
+ if ((lv = BLI_ghash_lookup(entry->added_verts, key))) {
+ bm_log_vert_bmvert_copy(lv, v, cd_vert_mask_offset);
+ }
+ else if (!BLI_ghash_ensure_p(entry->modified_verts, key, &val_p)) {
+ lv = bm_log_vert_alloc(log, v, cd_vert_mask_offset);
+ *val_p = lv;
+ }
}
-
/* Log a new vertex as added to the BMesh
*
* The new vertex gets a unique ID assigned. It is then added to a map
@@ -867,16 +861,15 @@ void BM_log_vert_before_modified(BMLog *log, BMVert *v, const int cd_vert_mask_o
*/
void BM_log_vert_added(BMLog *log, BMVert *v, const int cd_vert_mask_offset)
{
- BMLogVert *lv;
- uint v_id = range_tree_uint_take_any(log->unused_ids);
- void *key = POINTER_FROM_UINT(v_id);
+ BMLogVert *lv;
+ uint v_id = range_tree_uint_take_any(log->unused_ids);
+ void *key = POINTER_FROM_UINT(v_id);
- bm_log_vert_id_set(log, v, v_id);
- lv = bm_log_vert_alloc(log, v, cd_vert_mask_offset);
- BLI_ghash_insert(log->current_entry->added_verts, key, lv);
+ bm_log_vert_id_set(log, v, v_id);
+ lv = bm_log_vert_alloc(log, v, cd_vert_mask_offset);
+ BLI_ghash_insert(log->current_entry->added_verts, key, lv);
}
-
/* Log a face before it is modified
*
* This is intended to handle only header flags and we always
@@ -884,12 +877,12 @@ void BM_log_vert_added(BMLog *log, BMVert *v, const int cd_vert_mask_offset)
*/
void BM_log_face_modified(BMLog *log, BMFace *f)
{
- BMLogFace *lf;
- uint f_id = bm_log_face_id_get(log, f);
- void *key = POINTER_FROM_UINT(f_id);
+ BMLogFace *lf;
+ uint f_id = bm_log_face_id_get(log, f);
+ void *key = POINTER_FROM_UINT(f_id);
- lf = bm_log_face_alloc(log, f);
- BLI_ghash_insert(log->current_entry->modified_faces, key, lf);
+ lf = bm_log_face_alloc(log, f);
+ BLI_ghash_insert(log->current_entry->modified_faces, key, lf);
}
/* Log a new face as added to the BMesh
@@ -900,16 +893,16 @@ void BM_log_face_modified(BMLog *log, BMFace *f)
*/
void BM_log_face_added(BMLog *log, BMFace *f)
{
- BMLogFace *lf;
- uint f_id = range_tree_uint_take_any(log->unused_ids);
- void *key = POINTER_FROM_UINT(f_id);
+ BMLogFace *lf;
+ uint f_id = range_tree_uint_take_any(log->unused_ids);
+ void *key = POINTER_FROM_UINT(f_id);
- /* Only triangles are supported for now */
- BLI_assert(f->len == 3);
+ /* Only triangles are supported for now */
+ BLI_assert(f->len == 3);
- bm_log_face_id_set(log, f, f_id);
- lf = bm_log_face_alloc(log, f);
- BLI_ghash_insert(log->current_entry->added_faces, key, lf);
+ bm_log_face_id_set(log, f, f_id);
+ lf = bm_log_face_alloc(log, f);
+ BLI_ghash_insert(log->current_entry->added_faces, key, lf);
}
/* Log a vertex as removed from the BMesh
@@ -930,30 +923,30 @@ void BM_log_face_added(BMLog *log, BMFace *f)
*/
void BM_log_vert_removed(BMLog *log, BMVert *v, const int cd_vert_mask_offset)
{
- BMLogEntry *entry = log->current_entry;
- uint v_id = bm_log_vert_id_get(log, v);
- void *key = POINTER_FROM_UINT(v_id);
-
- /* if it has a key, it shouldn't be NULL */
- BLI_assert(!!BLI_ghash_lookup(entry->added_verts, key) ==
- !!BLI_ghash_haskey(entry->added_verts, key));
-
- if (BLI_ghash_remove(entry->added_verts, key, NULL, NULL)) {
- range_tree_uint_release(log->unused_ids, v_id);
- }
- else {
- BMLogVert *lv, *lv_mod;
-
- lv = bm_log_vert_alloc(log, v, cd_vert_mask_offset);
- BLI_ghash_insert(entry->deleted_verts, key, lv);
-
- /* If the vertex was modified before deletion, ensure that the
- * original vertex values are stored */
- if ((lv_mod = BLI_ghash_lookup(entry->modified_verts, key))) {
- (*lv) = (*lv_mod);
- BLI_ghash_remove(entry->modified_verts, key, NULL, NULL);
- }
- }
+ BMLogEntry *entry = log->current_entry;
+ uint v_id = bm_log_vert_id_get(log, v);
+ void *key = POINTER_FROM_UINT(v_id);
+
+ /* if it has a key, it shouldn't be NULL */
+ BLI_assert(!!BLI_ghash_lookup(entry->added_verts, key) ==
+ !!BLI_ghash_haskey(entry->added_verts, key));
+
+ if (BLI_ghash_remove(entry->added_verts, key, NULL, NULL)) {
+ range_tree_uint_release(log->unused_ids, v_id);
+ }
+ else {
+ BMLogVert *lv, *lv_mod;
+
+ lv = bm_log_vert_alloc(log, v, cd_vert_mask_offset);
+ BLI_ghash_insert(entry->deleted_verts, key, lv);
+
+ /* If the vertex was modified before deletion, ensure that the
+ * original vertex values are stored */
+ if ((lv_mod = BLI_ghash_lookup(entry->modified_verts, key))) {
+ (*lv) = (*lv_mod);
+ BLI_ghash_remove(entry->modified_verts, key, NULL, NULL);
+ }
+ }
}
/* Log a face as removed from the BMesh
@@ -971,70 +964,70 @@ void BM_log_vert_removed(BMLog *log, BMVert *v, const int cd_vert_mask_offset)
*/
void BM_log_face_removed(BMLog *log, BMFace *f)
{
- BMLogEntry *entry = log->current_entry;
- uint f_id = bm_log_face_id_get(log, f);
- void *key = POINTER_FROM_UINT(f_id);
-
- /* if it has a key, it shouldn't be NULL */
- BLI_assert(!!BLI_ghash_lookup(entry->added_faces, key) ==
- !!BLI_ghash_haskey(entry->added_faces, key));
-
- if (BLI_ghash_remove(entry->added_faces, key, NULL, NULL)) {
- range_tree_uint_release(log->unused_ids, f_id);
- }
- else {
- BMLogFace *lf;
-
- lf = bm_log_face_alloc(log, f);
- BLI_ghash_insert(entry->deleted_faces, key, lf);
- }
+ BMLogEntry *entry = log->current_entry;
+ uint f_id = bm_log_face_id_get(log, f);
+ void *key = POINTER_FROM_UINT(f_id);
+
+ /* if it has a key, it shouldn't be NULL */
+ BLI_assert(!!BLI_ghash_lookup(entry->added_faces, key) ==
+ !!BLI_ghash_haskey(entry->added_faces, key));
+
+ if (BLI_ghash_remove(entry->added_faces, key, NULL, NULL)) {
+ range_tree_uint_release(log->unused_ids, f_id);
+ }
+ else {
+ BMLogFace *lf;
+
+ lf = bm_log_face_alloc(log, f);
+ BLI_ghash_insert(entry->deleted_faces, key, lf);
+ }
}
/* Log all vertices/faces in the BMesh as added */
void BM_log_all_added(BMesh *bm, BMLog *log)
{
- const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK);
- BMIter bm_iter;
- BMVert *v;
- BMFace *f;
-
- /* avoid unnecessary resizing on initialization */
- if (BLI_ghash_len(log->current_entry->added_verts) == 0) {
- BLI_ghash_reserve(log->current_entry->added_verts, (uint)bm->totvert);
- }
-
- if (BLI_ghash_len(log->current_entry->added_faces) == 0) {
- BLI_ghash_reserve(log->current_entry->added_faces, (uint)bm->totface);
- }
-
- /* Log all vertices as newly created */
- BM_ITER_MESH (v, &bm_iter, bm, BM_VERTS_OF_MESH) {
- BM_log_vert_added(log, v, cd_vert_mask_offset);
- }
-
- /* Log all faces as newly created */
- BM_ITER_MESH (f, &bm_iter, bm, BM_FACES_OF_MESH) {
- BM_log_face_added(log, f);
- }
+ const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK);
+ BMIter bm_iter;
+ BMVert *v;
+ BMFace *f;
+
+ /* avoid unnecessary resizing on initialization */
+ if (BLI_ghash_len(log->current_entry->added_verts) == 0) {
+ BLI_ghash_reserve(log->current_entry->added_verts, (uint)bm->totvert);
+ }
+
+ if (BLI_ghash_len(log->current_entry->added_faces) == 0) {
+ BLI_ghash_reserve(log->current_entry->added_faces, (uint)bm->totface);
+ }
+
+ /* Log all vertices as newly created */
+ BM_ITER_MESH (v, &bm_iter, bm, BM_VERTS_OF_MESH) {
+ BM_log_vert_added(log, v, cd_vert_mask_offset);
+ }
+
+ /* Log all faces as newly created */
+ BM_ITER_MESH (f, &bm_iter, bm, BM_FACES_OF_MESH) {
+ BM_log_face_added(log, f);
+ }
}
/* Log all vertices/faces in the BMesh as removed */
void BM_log_before_all_removed(BMesh *bm, BMLog *log)
{
- const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK);
- BMIter bm_iter;
- BMVert *v;
- BMFace *f;
-
- /* Log deletion of all faces */
- BM_ITER_MESH (f, &bm_iter, bm, BM_FACES_OF_MESH) {
- BM_log_face_removed(log, f);
- }
-
- /* Log deletion of all vertices */
- BM_ITER_MESH (v, &bm_iter, bm, BM_VERTS_OF_MESH) {
- BM_log_vert_removed(log, v, cd_vert_mask_offset);
- }
+ const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK);
+ BMIter bm_iter;
+ BMVert *v;
+ BMFace *f;
+
+ /* Log deletion of all faces */
+ BM_ITER_MESH (f, &bm_iter, bm, BM_FACES_OF_MESH) {
+ BM_log_face_removed(log, f);
+ }
+
+ /* Log deletion of all vertices */
+ BM_ITER_MESH (v, &bm_iter, bm, BM_VERTS_OF_MESH) {
+ BM_log_vert_removed(log, v, cd_vert_mask_offset);
+ }
}
/* Get the logged coordinates of a vertex
@@ -1042,17 +1035,17 @@ void BM_log_before_all_removed(BMesh *bm, BMLog *log)
* Does not modify the log or the vertex */
const float *BM_log_original_vert_co(BMLog *log, BMVert *v)
{
- BMLogEntry *entry = log->current_entry;
- const BMLogVert *lv;
- unsigned v_id = bm_log_vert_id_get(log, v);
- void *key = POINTER_FROM_UINT(v_id);
+ BMLogEntry *entry = log->current_entry;
+ const BMLogVert *lv;
+ unsigned v_id = bm_log_vert_id_get(log, v);
+ void *key = POINTER_FROM_UINT(v_id);
- BLI_assert(entry);
+ BLI_assert(entry);
- BLI_assert(BLI_ghash_haskey(entry->modified_verts, key));
+ BLI_assert(BLI_ghash_haskey(entry->modified_verts, key));
- lv = BLI_ghash_lookup(entry->modified_verts, key);
- return lv->co;
+ lv = BLI_ghash_lookup(entry->modified_verts, key);
+ return lv->co;
}
/* Get the logged normal of a vertex
@@ -1060,17 +1053,17 @@ const float *BM_log_original_vert_co(BMLog *log, BMVert *v)
* Does not modify the log or the vertex */
const short *BM_log_original_vert_no(BMLog *log, BMVert *v)
{
- BMLogEntry *entry = log->current_entry;
- const BMLogVert *lv;
- unsigned v_id = bm_log_vert_id_get(log, v);
- void *key = POINTER_FROM_UINT(v_id);
+ BMLogEntry *entry = log->current_entry;
+ const BMLogVert *lv;
+ unsigned v_id = bm_log_vert_id_get(log, v);
+ void *key = POINTER_FROM_UINT(v_id);
- BLI_assert(entry);
+ BLI_assert(entry);
- BLI_assert(BLI_ghash_haskey(entry->modified_verts, key));
+ BLI_assert(BLI_ghash_haskey(entry->modified_verts, key));
- lv = BLI_ghash_lookup(entry->modified_verts, key);
- return lv->no;
+ lv = BLI_ghash_lookup(entry->modified_verts, key);
+ return lv->no;
}
/* Get the logged mask of a vertex
@@ -1078,35 +1071,33 @@ const short *BM_log_original_vert_no(BMLog *log, BMVert *v)
* Does not modify the log or the vertex */
float BM_log_original_mask(BMLog *log, BMVert *v)
{
- BMLogEntry *entry = log->current_entry;
- const BMLogVert *lv;
- unsigned v_id = bm_log_vert_id_get(log, v);
- void *key = POINTER_FROM_UINT(v_id);
+ BMLogEntry *entry = log->current_entry;
+ const BMLogVert *lv;
+ unsigned v_id = bm_log_vert_id_get(log, v);
+ void *key = POINTER_FROM_UINT(v_id);
- BLI_assert(entry);
+ BLI_assert(entry);
- BLI_assert(BLI_ghash_haskey(entry->modified_verts, key));
+ BLI_assert(BLI_ghash_haskey(entry->modified_verts, key));
- lv = BLI_ghash_lookup(entry->modified_verts, key);
- return lv->mask;
+ lv = BLI_ghash_lookup(entry->modified_verts, key);
+ return lv->mask;
}
-void BM_log_original_vert_data(
- BMLog *log, BMVert *v,
- const float **r_co, const short **r_no)
+void BM_log_original_vert_data(BMLog *log, BMVert *v, const float **r_co, const short **r_no)
{
- BMLogEntry *entry = log->current_entry;
- const BMLogVert *lv;
- unsigned v_id = bm_log_vert_id_get(log, v);
- void *key = POINTER_FROM_UINT(v_id);
+ BMLogEntry *entry = log->current_entry;
+ const BMLogVert *lv;
+ unsigned v_id = bm_log_vert_id_get(log, v);
+ void *key = POINTER_FROM_UINT(v_id);
- BLI_assert(entry);
+ BLI_assert(entry);
- BLI_assert(BLI_ghash_haskey(entry->modified_verts, key));
+ BLI_assert(BLI_ghash_haskey(entry->modified_verts, key));
- lv = BLI_ghash_lookup(entry->modified_verts, key);
- *r_co = lv->co;
- *r_no = lv->no;
+ lv = BLI_ghash_lookup(entry->modified_verts, key);
+ *r_co = lv->co;
+ *r_no = lv->no;
}
/************************ Debugging and Testing ***********************/
@@ -1114,13 +1105,13 @@ void BM_log_original_vert_data(
/* For internal use only (unit testing) */
BMLogEntry *BM_log_current_entry(BMLog *log)
{
- return log->current_entry;
+ return log->current_entry;
}
/* For internal use only (unit testing) */
RangeTreeUInt *BM_log_unused_ids(BMLog *log)
{
- return log->unused_ids;
+ return log->unused_ids;
}
#if 0
@@ -1129,16 +1120,16 @@ RangeTreeUInt *BM_log_unused_ids(BMLog *log)
* Keep around for debugging */
void bm_log_print(const BMLog *log, const char *description)
{
- const BMLogEntry *entry;
- const char *current = " <-- current";
- int i;
-
- printf("%s:\n", description);
- printf(" % 2d: [ initial ]%s\n", 0,
- (!log->current_entry) ? current : "");
- for (entry = log->entries.first, i = 1; entry; entry = entry->next, i++) {
- printf(" % 2d: [%p]%s\n", i, entry,
- (entry == log->current_entry) ? current : "");
- }
+ const BMLogEntry *entry;
+ const char *current = " <-- current";
+ int i;
+
+ printf("%s:\n", description);
+ printf(" % 2d: [ initial ]%s\n", 0,
+ (!log->current_entry) ? current : "");
+ for (entry = log->entries.first, i = 1; entry; entry = entry->next, i++) {
+ printf(" % 2d: [%p]%s\n", i, entry,
+ (entry == log->current_entry) ? current : "");
+ }
}
#endif
diff --git a/source/blender/bmesh/intern/bmesh_log.h b/source/blender/bmesh/intern/bmesh_log.h
index 8643e07c622..25c58132802 100644
--- a/source/blender/bmesh/intern/bmesh_log.h
+++ b/source/blender/bmesh/intern/bmesh_log.h
@@ -93,9 +93,7 @@ const short *BM_log_original_vert_no(BMLog *log, BMVert *v);
float BM_log_original_mask(BMLog *log, BMVert *v);
/* Get the logged data of a vertex (avoid multiple lookups) */
-void BM_log_original_vert_data(
- BMLog *log, BMVert *v,
- const float **r_co, const short **r_no);
+void BM_log_original_vert_data(BMLog *log, BMVert *v, const float **r_co, const short **r_no);
/* For internal use only (unit testing) */
BMLogEntry *BM_log_current_entry(BMLog *log);
diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c
index 53d9b4b1b56..f8ec69b6fe9 100644
--- a/source/blender/bmesh/intern/bmesh_marking.c
+++ b/source/blender/bmesh/intern/bmesh_marking.c
@@ -42,30 +42,28 @@
static void recount_totsels(BMesh *bm)
{
- const char iter_types[3] = {BM_VERTS_OF_MESH,
- BM_EDGES_OF_MESH,
- BM_FACES_OF_MESH};
- int *tots[3];
- int i;
-
- /* recount (tot * sel) variables */
- bm->totvertsel = bm->totedgesel = bm->totfacesel = 0;
- tots[0] = &bm->totvertsel;
- tots[1] = &bm->totedgesel;
- tots[2] = &bm->totfacesel;
-
- for (i = 0; i < 3; i++) {
- BMIter iter;
- BMElem *ele;
- int count = 0;
-
- BM_ITER_MESH (ele, &iter, bm, iter_types[i]) {
- if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
- count += 1;
- }
- }
- *tots[i] = count;
- }
+ const char iter_types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH};
+ int *tots[3];
+ int i;
+
+ /* recount (tot * sel) variables */
+ bm->totvertsel = bm->totedgesel = bm->totfacesel = 0;
+ tots[0] = &bm->totvertsel;
+ tots[1] = &bm->totedgesel;
+ tots[2] = &bm->totfacesel;
+
+ for (i = 0; i < 3; i++) {
+ BMIter iter;
+ BMElem *ele;
+ int count = 0;
+
+ BM_ITER_MESH (ele, &iter, bm, iter_types[i]) {
+ if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
+ count += 1;
+ }
+ }
+ *tots[i] = count;
+ }
}
/** \name BMesh helper functions for selection & hide flushing.
@@ -73,88 +71,88 @@ static void recount_totsels(BMesh *bm)
static bool bm_vert_is_edge_select_any_other(const BMVert *v, const BMEdge *e_first)
{
- const BMEdge *e_iter = e_first;
-
- /* start by stepping over the current edge */
- while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first) {
- if (BM_elem_flag_test(e_iter, BM_ELEM_SELECT)) {
- return true;
- }
- }
- return false;
+ const BMEdge *e_iter = e_first;
+
+ /* start by stepping over the current edge */
+ while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first) {
+ if (BM_elem_flag_test(e_iter, BM_ELEM_SELECT)) {
+ return true;
+ }
+ }
+ return false;
}
#if 0
static bool bm_vert_is_edge_select_any(const BMVert *v)
{
- if (v->e) {
- const BMEdge *e_iter, *e_first;
- e_iter = e_first = v->e;
- do {
- if (BM_elem_flag_test(e_iter, BM_ELEM_SELECT)) {
- return true;
- }
- } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
- }
- return false;
+ if (v->e) {
+ const BMEdge *e_iter, *e_first;
+ e_iter = e_first = v->e;
+ do {
+ if (BM_elem_flag_test(e_iter, BM_ELEM_SELECT)) {
+ return true;
+ }
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
+ }
+ return false;
}
#endif
static bool bm_vert_is_edge_visible_any(const BMVert *v)
{
- if (v->e) {
- const BMEdge *e_iter, *e_first;
- e_iter = e_first = v->e;
- do {
- if (!BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN)) {
- return true;
- }
- } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
- }
- return false;
+ if (v->e) {
+ const BMEdge *e_iter, *e_first;
+ e_iter = e_first = v->e;
+ do {
+ if (!BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN)) {
+ return true;
+ }
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
+ }
+ return false;
}
static bool bm_edge_is_face_select_any_other(BMLoop *l_first)
{
- const BMLoop *l_iter = l_first;
-
- /* start by stepping over the current face */
- while ((l_iter = l_iter->radial_next) != l_first) {
- if (BM_elem_flag_test(l_iter->f, BM_ELEM_SELECT)) {
- return true;
- }
- }
- return false;
+ const BMLoop *l_iter = l_first;
+
+ /* start by stepping over the current face */
+ while ((l_iter = l_iter->radial_next) != l_first) {
+ if (BM_elem_flag_test(l_iter->f, BM_ELEM_SELECT)) {
+ return true;
+ }
+ }
+ return false;
}
#if 0
static bool bm_edge_is_face_select_any(const BMEdge *e)
{
- if (e->l) {
- const BMLoop *l_iter, *l_first;
- l_iter = l_first = e->l;
- do {
- if (BM_elem_flag_test(l_iter->f, BM_ELEM_SELECT)) {
- return true;
- }
- } while ((l_iter = l_iter->radial_next) != l_first);
- }
- return false;
+ if (e->l) {
+ const BMLoop *l_iter, *l_first;
+ l_iter = l_first = e->l;
+ do {
+ if (BM_elem_flag_test(l_iter->f, BM_ELEM_SELECT)) {
+ return true;
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+ return false;
}
#endif
static bool bm_edge_is_face_visible_any(const BMEdge *e)
{
- if (e->l) {
- const BMLoop *l_iter, *l_first;
- l_iter = l_first = e->l;
- do {
- if (!BM_elem_flag_test(l_iter->f, BM_ELEM_HIDDEN)) {
- return true;
- }
- } while ((l_iter = l_iter->radial_next) != l_first);
- }
- return false;
+ if (e->l) {
+ const BMLoop *l_iter, *l_first;
+ l_iter = l_first = e->l;
+ do {
+ if (!BM_elem_flag_test(l_iter->f, BM_ELEM_HIDDEN)) {
+ return true;
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+ return false;
}
/** \} */
@@ -169,67 +167,67 @@ static bool bm_edge_is_face_visible_any(const BMEdge *e)
*/
void BM_mesh_select_mode_clean_ex(BMesh *bm, const short selectmode)
{
- if (selectmode & SCE_SELECT_VERTEX) {
- /* pass */
- }
- else if (selectmode & SCE_SELECT_EDGE) {
- BMIter iter;
-
- if (bm->totvertsel) {
- BMVert *v;
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- BM_elem_flag_disable(v, BM_ELEM_SELECT);
- }
- bm->totvertsel = 0;
- }
-
- if (bm->totedgesel) {
- BMEdge *e;
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
- BM_vert_select_set(bm, e->v1, true);
- BM_vert_select_set(bm, e->v2, true);
- }
- }
- }
- }
- else if (selectmode & SCE_SELECT_FACE) {
- BMIter iter;
-
- if (bm->totvertsel) {
- BMVert *v;
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- BM_elem_flag_disable(v, BM_ELEM_SELECT);
- }
- bm->totvertsel = 0;
- }
-
- if (bm->totedgesel) {
- BMEdge *e;
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- BM_elem_flag_disable(e, BM_ELEM_SELECT);
- }
- bm->totedgesel = 0;
- }
-
- if (bm->totfacesel) {
- BMFace *f;
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- BM_edge_select_set(bm, l_iter->e, true);
- } while ((l_iter = l_iter->next) != l_first);
- }
- }
- }
- }
+ if (selectmode & SCE_SELECT_VERTEX) {
+ /* pass */
+ }
+ else if (selectmode & SCE_SELECT_EDGE) {
+ BMIter iter;
+
+ if (bm->totvertsel) {
+ BMVert *v;
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_elem_flag_disable(v, BM_ELEM_SELECT);
+ }
+ bm->totvertsel = 0;
+ }
+
+ if (bm->totedgesel) {
+ BMEdge *e;
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ BM_vert_select_set(bm, e->v1, true);
+ BM_vert_select_set(bm, e->v2, true);
+ }
+ }
+ }
+ }
+ else if (selectmode & SCE_SELECT_FACE) {
+ BMIter iter;
+
+ if (bm->totvertsel) {
+ BMVert *v;
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_elem_flag_disable(v, BM_ELEM_SELECT);
+ }
+ bm->totvertsel = 0;
+ }
+
+ if (bm->totedgesel) {
+ BMEdge *e;
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ BM_elem_flag_disable(e, BM_ELEM_SELECT);
+ }
+ bm->totedgesel = 0;
+ }
+
+ if (bm->totfacesel) {
+ BMFace *f;
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BM_edge_select_set(bm, l_iter->e, true);
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ }
+ }
+ }
}
void BM_mesh_select_mode_clean(BMesh *bm)
{
- BM_mesh_select_mode_clean_ex(bm, bm->selectmode);
+ BM_mesh_select_mode_clean_ex(bm, bm->selectmode);
}
/**
@@ -241,74 +239,72 @@ void BM_mesh_select_mode_clean(BMesh *bm)
*/
void BM_mesh_select_mode_flush_ex(BMesh *bm, const short selectmode)
{
- BMEdge *e;
- BMLoop *l_iter;
- BMLoop *l_first;
- BMFace *f;
-
- BMIter eiter;
- BMIter fiter;
-
- if (selectmode & SCE_SELECT_VERTEX) {
- /* both loops only set edge/face flags and read off verts */
- BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e->v1, BM_ELEM_SELECT) &&
- BM_elem_flag_test(e->v2, BM_ELEM_SELECT) &&
- !BM_elem_flag_test(e, BM_ELEM_HIDDEN))
- {
- BM_elem_flag_enable(e, BM_ELEM_SELECT);
- }
- else {
- BM_elem_flag_disable(e, BM_ELEM_SELECT);
- }
- }
- BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
- bool ok = true;
- if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) {
- ok = false;
- break;
- }
- } while ((l_iter = l_iter->next) != l_first);
- }
- else {
- ok = false;
- }
-
- BM_elem_flag_set(f, BM_ELEM_SELECT, ok);
- }
- }
- else if (selectmode & SCE_SELECT_EDGE) {
- BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
- bool ok = true;
- if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if (!BM_elem_flag_test(l_iter->e, BM_ELEM_SELECT)) {
- ok = false;
- break;
- }
- } while ((l_iter = l_iter->next) != l_first);
- }
- else {
- ok = false;
- }
-
- BM_elem_flag_set(f, BM_ELEM_SELECT, ok);
- }
- }
-
- /* Remove any deselected elements from the BMEditSelection */
- BM_select_history_validate(bm);
-
- recount_totsels(bm);
+ BMEdge *e;
+ BMLoop *l_iter;
+ BMLoop *l_first;
+ BMFace *f;
+
+ BMIter eiter;
+ BMIter fiter;
+
+ if (selectmode & SCE_SELECT_VERTEX) {
+ /* both loops only set edge/face flags and read off verts */
+ BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e->v1, BM_ELEM_SELECT) && BM_elem_flag_test(e->v2, BM_ELEM_SELECT) &&
+ !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
+ BM_elem_flag_enable(e, BM_ELEM_SELECT);
+ }
+ else {
+ BM_elem_flag_disable(e, BM_ELEM_SELECT);
+ }
+ }
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ bool ok = true;
+ if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) {
+ ok = false;
+ break;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ else {
+ ok = false;
+ }
+
+ BM_elem_flag_set(f, BM_ELEM_SELECT, ok);
+ }
+ }
+ else if (selectmode & SCE_SELECT_EDGE) {
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ bool ok = true;
+ if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (!BM_elem_flag_test(l_iter->e, BM_ELEM_SELECT)) {
+ ok = false;
+ break;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ else {
+ ok = false;
+ }
+
+ BM_elem_flag_set(f, BM_ELEM_SELECT, ok);
+ }
+ }
+
+ /* Remove any deselected elements from the BMEditSelection */
+ BM_select_history_validate(bm);
+
+ recount_totsels(bm);
}
void BM_mesh_select_mode_flush(BMesh *bm)
{
- BM_mesh_select_mode_flush_ex(bm, bm->selectmode);
+ BM_mesh_select_mode_flush_ex(bm, bm->selectmode);
}
/**
@@ -316,82 +312,78 @@ void BM_mesh_select_mode_flush(BMesh *bm)
*/
void BM_mesh_deselect_flush(BMesh *bm)
{
- BMIter eiter;
- BMEdge *e;
-
- BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
- if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
- if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
- if (!BM_elem_flag_test(e->v1, BM_ELEM_SELECT) ||
- !BM_elem_flag_test(e->v2, BM_ELEM_SELECT))
- {
- BM_elem_flag_disable(e, BM_ELEM_SELECT);
- }
- }
-
- if (e->l && !BM_elem_flag_test(e, BM_ELEM_SELECT)) {
- BMLoop *l_iter;
- BMLoop *l_first;
-
- l_iter = l_first = e->l;
- do {
- BM_elem_flag_disable(l_iter->f, BM_ELEM_SELECT);
- } while ((l_iter = l_iter->radial_next) != l_first);
- }
- }
- }
-
- /* Remove any deselected elements from the BMEditSelection */
- BM_select_history_validate(bm);
-
- recount_totsels(bm);
+ BMIter eiter;
+ BMEdge *e;
+
+ BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
+ if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ if (!BM_elem_flag_test(e->v1, BM_ELEM_SELECT) ||
+ !BM_elem_flag_test(e->v2, BM_ELEM_SELECT)) {
+ BM_elem_flag_disable(e, BM_ELEM_SELECT);
+ }
+ }
+
+ if (e->l && !BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ BMLoop *l_iter;
+ BMLoop *l_first;
+
+ l_iter = l_first = e->l;
+ do {
+ BM_elem_flag_disable(l_iter->f, BM_ELEM_SELECT);
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+ }
+ }
+
+ /* Remove any deselected elements from the BMEditSelection */
+ BM_select_history_validate(bm);
+
+ recount_totsels(bm);
}
-
/**
* mode independent flushing up/down
*/
void BM_mesh_select_flush(BMesh *bm)
{
- BMEdge *e;
- BMLoop *l_iter;
- BMLoop *l_first;
- BMFace *f;
-
- BMIter eiter;
- BMIter fiter;
-
- bool ok;
-
- BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e->v1, BM_ELEM_SELECT) &&
- BM_elem_flag_test(e->v2, BM_ELEM_SELECT) &&
- !BM_elem_flag_test(e, BM_ELEM_HIDDEN))
- {
- BM_elem_flag_enable(e, BM_ELEM_SELECT);
- }
- }
- BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
- ok = true;
- if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) {
- ok = false;
- break;
- }
- } while ((l_iter = l_iter->next) != l_first);
- }
- else {
- ok = false;
- }
-
- if (ok) {
- BM_elem_flag_enable(f, BM_ELEM_SELECT);
- }
- }
-
- recount_totsels(bm);
+ BMEdge *e;
+ BMLoop *l_iter;
+ BMLoop *l_first;
+ BMFace *f;
+
+ BMIter eiter;
+ BMIter fiter;
+
+ bool ok;
+
+ BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e->v1, BM_ELEM_SELECT) && BM_elem_flag_test(e->v2, BM_ELEM_SELECT) &&
+ !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
+ BM_elem_flag_enable(e, BM_ELEM_SELECT);
+ }
+ }
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ ok = true;
+ if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) {
+ ok = false;
+ break;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ else {
+ ok = false;
+ }
+
+ if (ok) {
+ BM_elem_flag_enable(f, BM_ELEM_SELECT);
+ }
+ }
+
+ recount_totsels(bm);
}
/**
@@ -402,24 +394,24 @@ void BM_mesh_select_flush(BMesh *bm)
*/
void BM_vert_select_set(BMesh *bm, BMVert *v, const bool select)
{
- BLI_assert(v->head.htype == BM_VERT);
-
- if (BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
- return;
- }
-
- if (select) {
- if (!BM_elem_flag_test(v, BM_ELEM_SELECT)) {
- BM_elem_flag_enable(v, BM_ELEM_SELECT);
- bm->totvertsel += 1;
- }
- }
- else {
- if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
- bm->totvertsel -= 1;
- BM_elem_flag_disable(v, BM_ELEM_SELECT);
- }
- }
+ BLI_assert(v->head.htype == BM_VERT);
+
+ if (BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
+ return;
+ }
+
+ if (select) {
+ if (!BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+ BM_elem_flag_enable(v, BM_ELEM_SELECT);
+ bm->totvertsel += 1;
+ }
+ }
+ else {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+ bm->totvertsel -= 1;
+ BM_elem_flag_disable(v, BM_ELEM_SELECT);
+ }
+ }
}
/**
@@ -429,43 +421,42 @@ void BM_vert_select_set(BMesh *bm, BMVert *v, const bool select)
*/
void BM_edge_select_set(BMesh *bm, BMEdge *e, const bool select)
{
- BLI_assert(e->head.htype == BM_EDGE);
-
- if (BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
- return;
- }
-
- if (select) {
- if (!BM_elem_flag_test(e, BM_ELEM_SELECT)) {
- BM_elem_flag_enable(e, BM_ELEM_SELECT);
- bm->totedgesel += 1;
- }
- BM_vert_select_set(bm, e->v1, true);
- BM_vert_select_set(bm, e->v2, true);
- }
- else {
- if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
- BM_elem_flag_disable(e, BM_ELEM_SELECT);
- bm->totedgesel -= 1;
- }
-
- if ((bm->selectmode & SCE_SELECT_VERTEX) == 0) {
- int i;
-
- /* check if the vert is used by a selected edge */
- for (i = 0; i < 2; i++) {
- BMVert *v = *((&e->v1) + i);
- if (bm_vert_is_edge_select_any_other(v, e) == false) {
- BM_vert_select_set(bm, v, false);
- }
- }
- }
- else {
- BM_vert_select_set(bm, e->v1, false);
- BM_vert_select_set(bm, e->v2, false);
- }
-
- }
+ BLI_assert(e->head.htype == BM_EDGE);
+
+ if (BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
+ return;
+ }
+
+ if (select) {
+ if (!BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ BM_elem_flag_enable(e, BM_ELEM_SELECT);
+ bm->totedgesel += 1;
+ }
+ BM_vert_select_set(bm, e->v1, true);
+ BM_vert_select_set(bm, e->v2, true);
+ }
+ else {
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ BM_elem_flag_disable(e, BM_ELEM_SELECT);
+ bm->totedgesel -= 1;
+ }
+
+ if ((bm->selectmode & SCE_SELECT_VERTEX) == 0) {
+ int i;
+
+ /* check if the vert is used by a selected edge */
+ for (i = 0; i < 2; i++) {
+ BMVert *v = *((&e->v1) + i);
+ if (bm_vert_is_edge_select_any_other(v, e) == false) {
+ BM_vert_select_set(bm, v, false);
+ }
+ }
+ }
+ else {
+ BM_vert_select_set(bm, e->v1, false);
+ BM_vert_select_set(bm, e->v2, false);
+ }
+ }
}
/**
@@ -476,77 +467,77 @@ void BM_edge_select_set(BMesh *bm, BMEdge *e, const bool select)
*/
void BM_face_select_set(BMesh *bm, BMFace *f, const bool select)
{
- BMLoop *l_iter;
- BMLoop *l_first;
-
- BLI_assert(f->head.htype == BM_FACE);
-
- if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
- return;
- }
-
- if (select) {
- if (!BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- BM_elem_flag_enable(f, BM_ELEM_SELECT);
- bm->totfacesel += 1;
- }
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- BM_vert_select_set(bm, l_iter->v, true);
- BM_edge_select_set(bm, l_iter->e, true);
- } while ((l_iter = l_iter->next) != l_first);
- }
- else {
-
- if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- BM_elem_flag_disable(f, BM_ELEM_SELECT);
- bm->totfacesel -= 1;
- }
- /**
- * \note This allows a temporarily invalid state - where for eg
- * an edge bay be de-selected, but an adjacent face remains selected.
- *
- * Rely on #BM_mesh_select_mode_flush to correct these cases.
- *
- * \note flushing based on mode, see T46494
- */
- if (bm->selectmode & SCE_SELECT_VERTEX) {
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- BM_vert_select_set(bm, l_iter->v, false);
- BM_edge_select_set_noflush(bm, l_iter->e, false);
- } while ((l_iter = l_iter->next) != l_first);
- }
- else {
- /**
- * \note use #BM_edge_select_set_noflush,
- * vertex flushing is handled last.
- */
- if (bm->selectmode & SCE_SELECT_EDGE) {
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- BM_edge_select_set_noflush(bm, l_iter->e, false);
- } while ((l_iter = l_iter->next) != l_first);
- }
- else {
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if (bm_edge_is_face_select_any_other(l_iter) == false) {
- BM_edge_select_set_noflush(bm, l_iter->e, false);
- }
- } while ((l_iter = l_iter->next) != l_first);
- }
-
- /* flush down to verts */
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if (bm_vert_is_edge_select_any_other(l_iter->v, l_iter->e) == false) {
- BM_vert_select_set(bm, l_iter->v, false);
- }
- } while ((l_iter = l_iter->next) != l_first);
- }
- }
+ BMLoop *l_iter;
+ BMLoop *l_first;
+
+ BLI_assert(f->head.htype == BM_FACE);
+
+ if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+ return;
+ }
+
+ if (select) {
+ if (!BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ BM_elem_flag_enable(f, BM_ELEM_SELECT);
+ bm->totfacesel += 1;
+ }
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BM_vert_select_set(bm, l_iter->v, true);
+ BM_edge_select_set(bm, l_iter->e, true);
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ else {
+
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ BM_elem_flag_disable(f, BM_ELEM_SELECT);
+ bm->totfacesel -= 1;
+ }
+ /**
+ * \note This allows a temporarily invalid state - where for eg
+ * an edge bay be de-selected, but an adjacent face remains selected.
+ *
+ * Rely on #BM_mesh_select_mode_flush to correct these cases.
+ *
+ * \note flushing based on mode, see T46494
+ */
+ if (bm->selectmode & SCE_SELECT_VERTEX) {
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BM_vert_select_set(bm, l_iter->v, false);
+ BM_edge_select_set_noflush(bm, l_iter->e, false);
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ else {
+ /**
+ * \note use #BM_edge_select_set_noflush,
+ * vertex flushing is handled last.
+ */
+ if (bm->selectmode & SCE_SELECT_EDGE) {
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BM_edge_select_set_noflush(bm, l_iter->e, false);
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ else {
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (bm_edge_is_face_select_any_other(l_iter) == false) {
+ BM_edge_select_set_noflush(bm, l_iter->e, false);
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+
+ /* flush down to verts */
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (bm_vert_is_edge_select_any_other(l_iter->v, l_iter->e) == false) {
+ BM_vert_select_set(bm, l_iter->v, false);
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ }
}
/** \name Non flushing versions element selection.
@@ -554,46 +545,46 @@ void BM_face_select_set(BMesh *bm, BMFace *f, const bool select)
void BM_edge_select_set_noflush(BMesh *bm, BMEdge *e, const bool select)
{
- BLI_assert(e->head.htype == BM_EDGE);
-
- if (BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
- return;
- }
-
- if (select) {
- if (!BM_elem_flag_test(e, BM_ELEM_SELECT)) {
- BM_elem_flag_enable(e, BM_ELEM_SELECT);
- bm->totedgesel += 1;
- }
- }
- else {
- if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
- BM_elem_flag_disable(e, BM_ELEM_SELECT);
- bm->totedgesel -= 1;
- }
- }
+ BLI_assert(e->head.htype == BM_EDGE);
+
+ if (BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
+ return;
+ }
+
+ if (select) {
+ if (!BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ BM_elem_flag_enable(e, BM_ELEM_SELECT);
+ bm->totedgesel += 1;
+ }
+ }
+ else {
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ BM_elem_flag_disable(e, BM_ELEM_SELECT);
+ bm->totedgesel -= 1;
+ }
+ }
}
void BM_face_select_set_noflush(BMesh *bm, BMFace *f, const bool select)
{
- BLI_assert(f->head.htype == BM_FACE);
-
- if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
- return;
- }
-
- if (select) {
- if (!BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- BM_elem_flag_enable(f, BM_ELEM_SELECT);
- bm->totfacesel += 1;
- }
- }
- else {
- if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- BM_elem_flag_disable(f, BM_ELEM_SELECT);
- bm->totfacesel -= 1;
- }
- }
+ BLI_assert(f->head.htype == BM_FACE);
+
+ if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+ return;
+ }
+
+ if (select) {
+ if (!BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ BM_elem_flag_enable(f, BM_ELEM_SELECT);
+ bm->totfacesel += 1;
+ }
+ }
+ else {
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ BM_elem_flag_disable(f, BM_ELEM_SELECT);
+ bm->totfacesel -= 1;
+ }
+ }
}
/** \} */
@@ -606,109 +597,117 @@ void BM_face_select_set_noflush(BMesh *bm, BMFace *f, const bool select)
*/
void BM_mesh_select_mode_set(BMesh *bm, int selectmode)
{
- BMIter iter;
- BMElem *ele;
+ BMIter iter;
+ BMElem *ele;
- bm->selectmode = selectmode;
+ bm->selectmode = selectmode;
- if (bm->selectmode & SCE_SELECT_VERTEX) {
- /* disabled because selection flushing handles these */
+ if (bm->selectmode & SCE_SELECT_VERTEX) {
+ /* disabled because selection flushing handles these */
#if 0
- BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
- BM_elem_flag_disable(ele, BM_ELEM_SELECT);
- }
- BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
- BM_elem_flag_disable(ele, BM_ELEM_SELECT);
- }
+ BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
+ BM_elem_flag_disable(ele, BM_ELEM_SELECT);
+ }
+ BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
+ BM_elem_flag_disable(ele, BM_ELEM_SELECT);
+ }
#endif
- BM_mesh_select_mode_flush(bm);
- }
- else if (bm->selectmode & SCE_SELECT_EDGE) {
- /* disabled because selection flushing handles these */
+ BM_mesh_select_mode_flush(bm);
+ }
+ else if (bm->selectmode & SCE_SELECT_EDGE) {
+ /* disabled because selection flushing handles these */
#if 0
- BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
- BM_elem_flag_disable(ele, BM_ELEM_SELECT);
- }
+ BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_elem_flag_disable(ele, BM_ELEM_SELECT);
+ }
#endif
- BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
- BM_edge_select_set(bm, (BMEdge *)ele, true);
- }
- }
- BM_mesh_select_mode_flush(bm);
- }
- else if (bm->selectmode & SCE_SELECT_FACE) {
- /* disabled because selection flushing handles these */
+ BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
+ BM_edge_select_set(bm, (BMEdge *)ele, true);
+ }
+ }
+ BM_mesh_select_mode_flush(bm);
+ }
+ else if (bm->selectmode & SCE_SELECT_FACE) {
+ /* disabled because selection flushing handles these */
#if 0
- BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
- BM_elem_flag_disable(ele, BM_ELEM_SELECT);
- }
+ BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
+ BM_elem_flag_disable(ele, BM_ELEM_SELECT);
+ }
#endif
- BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
- BM_face_select_set(bm, (BMFace *)ele, true);
- }
- }
- BM_mesh_select_mode_flush(bm);
- }
+ BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
+ BM_face_select_set(bm, (BMFace *)ele, true);
+ }
+ }
+ BM_mesh_select_mode_flush(bm);
+ }
}
/**
* counts number of elements with flag enabled/disabled
*/
-static int bm_mesh_flag_count(
- BMesh *bm, const char htype, const char hflag,
- const bool respecthide, const bool test_for_enabled)
+static int bm_mesh_flag_count(BMesh *bm,
+ const char htype,
+ const char hflag,
+ const bool respecthide,
+ const bool test_for_enabled)
{
- BMElem *ele;
- BMIter iter;
- int tot = 0;
-
- BLI_assert((htype & ~BM_ALL_NOLOOP) == 0);
-
- if (htype & BM_VERT) {
- BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
- if (respecthide && BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) {
- continue;
- }
- if (BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) {
- tot++;
- }
- }
- }
- if (htype & BM_EDGE) {
- BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
- if (respecthide && BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) {
- continue;
- }
- if (BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) {
- tot++;
- }
- }
- }
- if (htype & BM_FACE) {
- BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
- if (respecthide && BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) {
- continue;
- }
- if (BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) {
- tot++;
- }
- }
- }
-
- return tot;
+ BMElem *ele;
+ BMIter iter;
+ int tot = 0;
+
+ BLI_assert((htype & ~BM_ALL_NOLOOP) == 0);
+
+ if (htype & BM_VERT) {
+ BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
+ if (respecthide && BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) {
+ continue;
+ }
+ if (BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) {
+ tot++;
+ }
+ }
+ }
+ if (htype & BM_EDGE) {
+ BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
+ if (respecthide && BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) {
+ continue;
+ }
+ if (BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) {
+ tot++;
+ }
+ }
+ }
+ if (htype & BM_FACE) {
+ BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
+ if (respecthide && BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) {
+ continue;
+ }
+ if (BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) {
+ tot++;
+ }
+ }
+ }
+
+ return tot;
}
-int BM_mesh_elem_hflag_count_enabled(BMesh *bm, const char htype, const char hflag, const bool respecthide)
+int BM_mesh_elem_hflag_count_enabled(BMesh *bm,
+ const char htype,
+ const char hflag,
+ const bool respecthide)
{
- return bm_mesh_flag_count(bm, htype, hflag, respecthide, true);
+ return bm_mesh_flag_count(bm, htype, hflag, respecthide, true);
}
-int BM_mesh_elem_hflag_count_disabled(BMesh *bm, const char htype, const char hflag, const bool respecthide)
+int BM_mesh_elem_hflag_count_disabled(BMesh *bm,
+ const char htype,
+ const char hflag,
+ const bool respecthide)
{
- return bm_mesh_flag_count(bm, htype, hflag, respecthide, false);
+ return bm_mesh_flag_count(bm, htype, hflag, respecthide, false);
}
/**
@@ -717,105 +716,105 @@ int BM_mesh_elem_hflag_count_disabled(BMesh *bm, const char htype, const char hf
*/
void BM_elem_select_set(BMesh *bm, BMElem *ele, const bool select)
{
- switch (ele->head.htype) {
- case BM_VERT:
- BM_vert_select_set(bm, (BMVert *)ele, select);
- break;
- case BM_EDGE:
- BM_edge_select_set(bm, (BMEdge *)ele, select);
- break;
- case BM_FACE:
- BM_face_select_set(bm, (BMFace *)ele, select);
- break;
- default:
- BLI_assert(0);
- break;
- }
+ switch (ele->head.htype) {
+ case BM_VERT:
+ BM_vert_select_set(bm, (BMVert *)ele, select);
+ break;
+ case BM_EDGE:
+ BM_edge_select_set(bm, (BMEdge *)ele, select);
+ break;
+ case BM_FACE:
+ BM_face_select_set(bm, (BMFace *)ele, select);
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
}
/* this replaces the active flag used in uv/face mode */
void BM_mesh_active_face_set(BMesh *bm, BMFace *efa)
{
- bm->act_face = efa;
+ bm->act_face = efa;
}
BMFace *BM_mesh_active_face_get(BMesh *bm, const bool is_sloppy, const bool is_selected)
{
- if (bm->act_face && (!is_selected || BM_elem_flag_test(bm->act_face, BM_ELEM_SELECT))) {
- return bm->act_face;
- }
- else if (is_sloppy) {
- BMIter iter;
- BMFace *f = NULL;
- BMEditSelection *ese;
-
- /* Find the latest non-hidden face from the BMEditSelection */
- ese = bm->selected.last;
- for ( ; ese; ese = ese->prev) {
- if (ese->htype == BM_FACE) {
- f = (BMFace *)ese->ele;
-
- if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
- f = NULL;
- }
- else if (is_selected && !BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- f = NULL;
- }
- else {
- break;
- }
- }
- }
- /* Last attempt: try to find any selected face */
- if (f == NULL) {
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- break;
- }
- }
- }
- return f; /* can still be null */
- }
- return NULL;
+ if (bm->act_face && (!is_selected || BM_elem_flag_test(bm->act_face, BM_ELEM_SELECT))) {
+ return bm->act_face;
+ }
+ else if (is_sloppy) {
+ BMIter iter;
+ BMFace *f = NULL;
+ BMEditSelection *ese;
+
+ /* Find the latest non-hidden face from the BMEditSelection */
+ ese = bm->selected.last;
+ for (; ese; ese = ese->prev) {
+ if (ese->htype == BM_FACE) {
+ f = (BMFace *)ese->ele;
+
+ if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+ f = NULL;
+ }
+ else if (is_selected && !BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ f = NULL;
+ }
+ else {
+ break;
+ }
+ }
+ }
+ /* Last attempt: try to find any selected face */
+ if (f == NULL) {
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ break;
+ }
+ }
+ }
+ return f; /* can still be null */
+ }
+ return NULL;
}
BMEdge *BM_mesh_active_edge_get(BMesh *bm)
{
- if (bm->selected.last) {
- BMEditSelection *ese = bm->selected.last;
+ if (bm->selected.last) {
+ BMEditSelection *ese = bm->selected.last;
- if (ese && ese->htype == BM_EDGE) {
- return (BMEdge *)ese->ele;
- }
- }
+ if (ese && ese->htype == BM_EDGE) {
+ return (BMEdge *)ese->ele;
+ }
+ }
- return NULL;
+ return NULL;
}
BMVert *BM_mesh_active_vert_get(BMesh *bm)
{
- if (bm->selected.last) {
- BMEditSelection *ese = bm->selected.last;
+ if (bm->selected.last) {
+ BMEditSelection *ese = bm->selected.last;
- if (ese && ese->htype == BM_VERT) {
- return (BMVert *)ese->ele;
- }
- }
+ if (ese && ese->htype == BM_VERT) {
+ return (BMVert *)ese->ele;
+ }
+ }
- return NULL;
+ return NULL;
}
BMElem *BM_mesh_active_elem_get(BMesh *bm)
{
- if (bm->selected.last) {
- BMEditSelection *ese = bm->selected.last;
+ if (bm->selected.last) {
+ BMEditSelection *ese = bm->selected.last;
- if (ese) {
- return ese->ele;
- }
- }
+ if (ese) {
+ return ese->ele;
+ }
+ }
- return NULL;
+ return NULL;
}
/**
@@ -829,47 +828,46 @@ BMElem *BM_mesh_active_elem_get(BMesh *bm)
*/
void BM_editselection_center(BMEditSelection *ese, float r_center[3])
{
- if (ese->htype == BM_VERT) {
- BMVert *eve = (BMVert *)ese->ele;
- copy_v3_v3(r_center, eve->co);
- }
- else if (ese->htype == BM_EDGE) {
- BMEdge *eed = (BMEdge *)ese->ele;
- mid_v3_v3v3(r_center, eed->v1->co, eed->v2->co);
- }
- else if (ese->htype == BM_FACE) {
- BMFace *efa = (BMFace *)ese->ele;
- BM_face_calc_center_median(efa, r_center);
- }
+ if (ese->htype == BM_VERT) {
+ BMVert *eve = (BMVert *)ese->ele;
+ copy_v3_v3(r_center, eve->co);
+ }
+ else if (ese->htype == BM_EDGE) {
+ BMEdge *eed = (BMEdge *)ese->ele;
+ mid_v3_v3v3(r_center, eed->v1->co, eed->v2->co);
+ }
+ else if (ese->htype == BM_FACE) {
+ BMFace *efa = (BMFace *)ese->ele;
+ BM_face_calc_center_median(efa, r_center);
+ }
}
void BM_editselection_normal(BMEditSelection *ese, float r_normal[3])
{
- if (ese->htype == BM_VERT) {
- BMVert *eve = (BMVert *)ese->ele;
- copy_v3_v3(r_normal, eve->no);
- }
- else if (ese->htype == BM_EDGE) {
- BMEdge *eed = (BMEdge *)ese->ele;
- float plane[3]; /* need a plane to correct the normal */
- float vec[3]; /* temp vec storage */
-
- add_v3_v3v3(r_normal, eed->v1->no, eed->v2->no);
- sub_v3_v3v3(plane, eed->v2->co, eed->v1->co);
-
- /* the 2 vertex normals will be close but not at rightangles to the edge
- * for rotate about edge we want them to be at right angles, so we need to
- * do some extra calculation to correct the vert normals,
- * we need the plane for this */
- cross_v3_v3v3(vec, r_normal, plane);
- cross_v3_v3v3(r_normal, plane, vec);
- normalize_v3(r_normal);
-
- }
- else if (ese->htype == BM_FACE) {
- BMFace *efa = (BMFace *)ese->ele;
- copy_v3_v3(r_normal, efa->no);
- }
+ if (ese->htype == BM_VERT) {
+ BMVert *eve = (BMVert *)ese->ele;
+ copy_v3_v3(r_normal, eve->no);
+ }
+ else if (ese->htype == BM_EDGE) {
+ BMEdge *eed = (BMEdge *)ese->ele;
+ float plane[3]; /* need a plane to correct the normal */
+ float vec[3]; /* temp vec storage */
+
+ add_v3_v3v3(r_normal, eed->v1->no, eed->v2->no);
+ sub_v3_v3v3(plane, eed->v2->co, eed->v1->co);
+
+ /* the 2 vertex normals will be close but not at rightangles to the edge
+ * for rotate about edge we want them to be at right angles, so we need to
+ * do some extra calculation to correct the vert normals,
+ * we need the plane for this */
+ cross_v3_v3v3(vec, r_normal, plane);
+ cross_v3_v3v3(r_normal, plane, vec);
+ normalize_v3(r_normal);
+ }
+ else if (ese->htype == BM_FACE) {
+ BMFace *efa = (BMFace *)ese->ele;
+ copy_v3_v3(r_normal, efa->no);
+ }
}
/* Calculate a plane that is rightangles to the edge/vert/faces normal
@@ -877,137 +875,142 @@ void BM_editselection_normal(BMEditSelection *ese, float r_normal[3])
* because this is used for the gizmos Y axis. */
void BM_editselection_plane(BMEditSelection *ese, float r_plane[3])
{
- if (ese->htype == BM_VERT) {
- BMVert *eve = (BMVert *)ese->ele;
- float vec[3] = {0.0f, 0.0f, 0.0f};
-
- if (ese->prev) { /* use previously selected data to make a useful vertex plane */
- BM_editselection_center(ese->prev, vec);
- sub_v3_v3v3(r_plane, vec, eve->co);
- }
- else {
- /* make a fake plane thats at rightangles to the normal
- * we cant make a crossvec from a vec thats the same as the vec
- * unlikely but possible, so make sure if the normal is (0, 0, 1)
- * that vec isn't the same or in the same direction even. */
- if (eve->no[0] < 0.5f) { vec[0] = 1.0f; }
- else if (eve->no[1] < 0.5f) { vec[1] = 1.0f; }
- else { vec[2] = 1.0f; }
- cross_v3_v3v3(r_plane, eve->no, vec);
- }
- normalize_v3(r_plane);
- }
- else if (ese->htype == BM_EDGE) {
- BMEdge *eed = (BMEdge *)ese->ele;
-
- if (BM_edge_is_boundary(eed)) {
- sub_v3_v3v3(r_plane, eed->l->v->co, eed->l->next->v->co);
- }
- else {
- /* the plane is simple, it runs along the edge
- * however selecting different edges can swap the direction of the y axis.
- * this makes it less likely for the y axis of the gizmo
- * (running along the edge).. to flip less often.
- * at least its more predictable */
- if (eed->v2->co[1] > eed->v1->co[1]) { /* check which to do first */
- sub_v3_v3v3(r_plane, eed->v2->co, eed->v1->co);
- }
- else {
- sub_v3_v3v3(r_plane, eed->v1->co, eed->v2->co);
- }
- }
-
- normalize_v3(r_plane);
- }
- else if (ese->htype == BM_FACE) {
- BMFace *efa = (BMFace *)ese->ele;
- BM_face_calc_tangent_auto(efa, r_plane);
- }
+ if (ese->htype == BM_VERT) {
+ BMVert *eve = (BMVert *)ese->ele;
+ float vec[3] = {0.0f, 0.0f, 0.0f};
+
+ if (ese->prev) { /* use previously selected data to make a useful vertex plane */
+ BM_editselection_center(ese->prev, vec);
+ sub_v3_v3v3(r_plane, vec, eve->co);
+ }
+ else {
+ /* make a fake plane thats at rightangles to the normal
+ * we cant make a crossvec from a vec thats the same as the vec
+ * unlikely but possible, so make sure if the normal is (0, 0, 1)
+ * that vec isn't the same or in the same direction even. */
+ if (eve->no[0] < 0.5f) {
+ vec[0] = 1.0f;
+ }
+ else if (eve->no[1] < 0.5f) {
+ vec[1] = 1.0f;
+ }
+ else {
+ vec[2] = 1.0f;
+ }
+ cross_v3_v3v3(r_plane, eve->no, vec);
+ }
+ normalize_v3(r_plane);
+ }
+ else if (ese->htype == BM_EDGE) {
+ BMEdge *eed = (BMEdge *)ese->ele;
+
+ if (BM_edge_is_boundary(eed)) {
+ sub_v3_v3v3(r_plane, eed->l->v->co, eed->l->next->v->co);
+ }
+ else {
+ /* the plane is simple, it runs along the edge
+ * however selecting different edges can swap the direction of the y axis.
+ * this makes it less likely for the y axis of the gizmo
+ * (running along the edge).. to flip less often.
+ * at least its more predictable */
+ if (eed->v2->co[1] > eed->v1->co[1]) { /* check which to do first */
+ sub_v3_v3v3(r_plane, eed->v2->co, eed->v1->co);
+ }
+ else {
+ sub_v3_v3v3(r_plane, eed->v1->co, eed->v2->co);
+ }
+ }
+
+ normalize_v3(r_plane);
+ }
+ else if (ese->htype == BM_FACE) {
+ BMFace *efa = (BMFace *)ese->ele;
+ BM_face_calc_tangent_auto(efa, r_plane);
+ }
}
static BMEditSelection *bm_select_history_create(BMHeader *ele)
{
- BMEditSelection *ese = (BMEditSelection *) MEM_callocN(sizeof(BMEditSelection), "BMEdit Selection");
- ese->htype = ele->htype;
- ese->ele = (BMElem *)ele;
- return ese;
+ BMEditSelection *ese = (BMEditSelection *)MEM_callocN(sizeof(BMEditSelection),
+ "BMEdit Selection");
+ ese->htype = ele->htype;
+ ese->ele = (BMElem *)ele;
+ return ese;
}
/* --- macro wrapped funcs --- */
bool _bm_select_history_check(BMesh *bm, const BMHeader *ele)
{
- return (BLI_findptr(&bm->selected, ele, offsetof(BMEditSelection, ele)) != NULL);
+ return (BLI_findptr(&bm->selected, ele, offsetof(BMEditSelection, ele)) != NULL);
}
bool _bm_select_history_remove(BMesh *bm, BMHeader *ele)
{
- BMEditSelection *ese = BLI_findptr(&bm->selected, ele, offsetof(BMEditSelection, ele));
- if (ese) {
- BLI_freelinkN(&bm->selected, ese);
- return true;
- }
- else {
- return false;
- }
+ BMEditSelection *ese = BLI_findptr(&bm->selected, ele, offsetof(BMEditSelection, ele));
+ if (ese) {
+ BLI_freelinkN(&bm->selected, ese);
+ return true;
+ }
+ else {
+ return false;
+ }
}
void _bm_select_history_store_notest(BMesh *bm, BMHeader *ele)
{
- BMEditSelection *ese = bm_select_history_create(ele);
- BLI_addtail(&(bm->selected), ese);
+ BMEditSelection *ese = bm_select_history_create(ele);
+ BLI_addtail(&(bm->selected), ese);
}
void _bm_select_history_store_head_notest(BMesh *bm, BMHeader *ele)
{
- BMEditSelection *ese = bm_select_history_create(ele);
- BLI_addhead(&(bm->selected), ese);
+ BMEditSelection *ese = bm_select_history_create(ele);
+ BLI_addhead(&(bm->selected), ese);
}
void _bm_select_history_store(BMesh *bm, BMHeader *ele)
{
- if (!BM_select_history_check(bm, (BMElem *)ele)) {
- BM_select_history_store_notest(bm, (BMElem *)ele);
- }
+ if (!BM_select_history_check(bm, (BMElem *)ele)) {
+ BM_select_history_store_notest(bm, (BMElem *)ele);
+ }
}
void _bm_select_history_store_head(BMesh *bm, BMHeader *ele)
{
- if (!BM_select_history_check(bm, (BMElem *)ele)) {
- BM_select_history_store_head_notest(bm, (BMElem *)ele);
- }
+ if (!BM_select_history_check(bm, (BMElem *)ele)) {
+ BM_select_history_store_head_notest(bm, (BMElem *)ele);
+ }
}
void _bm_select_history_store_after_notest(BMesh *bm, BMEditSelection *ese_ref, BMHeader *ele)
{
- BMEditSelection *ese = bm_select_history_create(ele);
- BLI_insertlinkafter(&(bm->selected), ese_ref, ese);
+ BMEditSelection *ese = bm_select_history_create(ele);
+ BLI_insertlinkafter(&(bm->selected), ese_ref, ese);
}
void _bm_select_history_store_after(BMesh *bm, BMEditSelection *ese_ref, BMHeader *ele)
{
- if (!BM_select_history_check(bm, (BMElem *)ele)) {
- BM_select_history_store_after_notest(bm, ese_ref, (BMElem *)ele);
- }
+ if (!BM_select_history_check(bm, (BMElem *)ele)) {
+ BM_select_history_store_after_notest(bm, ese_ref, (BMElem *)ele);
+ }
}
/* --- end macro wrapped funcs --- */
-
void BM_select_history_clear(BMesh *bm)
{
- BLI_freelistN(&bm->selected);
+ BLI_freelistN(&bm->selected);
}
-
void BM_select_history_validate(BMesh *bm)
{
- BMEditSelection *ese, *ese_next;
-
- for (ese = bm->selected.first; ese; ese = ese_next) {
- ese_next = ese->next;
- if (!BM_elem_flag_test(ese->ele, BM_ELEM_SELECT)) {
- BLI_freelinkN(&(bm->selected), ese);
- }
- }
+ BMEditSelection *ese, *ese_next;
+
+ for (ese = bm->selected.first; ese; ese = ese_next) {
+ ese_next = ese->next;
+ if (!BM_elem_flag_test(ese->ele, BM_ELEM_SELECT)) {
+ BLI_freelinkN(&(bm->selected), ese);
+ }
+ }
}
/**
@@ -1015,37 +1018,38 @@ void BM_select_history_validate(BMesh *bm)
*/
bool BM_select_history_active_get(BMesh *bm, BMEditSelection *ese)
{
- BMEditSelection *ese_last = bm->selected.last;
- BMFace *efa = BM_mesh_active_face_get(bm, false, false);
-
- ese->next = ese->prev = NULL;
-
- if (ese_last) {
- if (ese_last->htype == BM_FACE) { /* if there is an active face, use it over the last selected face */
- if (efa) {
- ese->ele = (BMElem *)efa;
- }
- else {
- ese->ele = ese_last->ele;
- }
- ese->htype = BM_FACE;
- }
- else {
- ese->ele = ese_last->ele;
- ese->htype = ese_last->htype;
- }
- }
- else if (efa) {
- /* no edit-selection, fallback to active face */
- ese->ele = (BMElem *)efa;
- ese->htype = BM_FACE;
- }
- else {
- ese->ele = NULL;
- return false;
- }
-
- return true;
+ BMEditSelection *ese_last = bm->selected.last;
+ BMFace *efa = BM_mesh_active_face_get(bm, false, false);
+
+ ese->next = ese->prev = NULL;
+
+ if (ese_last) {
+ if (ese_last->htype ==
+ BM_FACE) { /* if there is an active face, use it over the last selected face */
+ if (efa) {
+ ese->ele = (BMElem *)efa;
+ }
+ else {
+ ese->ele = ese_last->ele;
+ }
+ ese->htype = BM_FACE;
+ }
+ else {
+ ese->ele = ese_last->ele;
+ ese->htype = ese_last->htype;
+ }
+ }
+ else if (efa) {
+ /* no edit-selection, fallback to active face */
+ ese->ele = (BMElem *)efa;
+ ese->htype = BM_FACE;
+ }
+ else {
+ ese->ele = NULL;
+ return false;
+ }
+
+ return true;
}
/**
@@ -1053,220 +1057,225 @@ bool BM_select_history_active_get(BMesh *bm, BMEditSelection *ese)
*/
GHash *BM_select_history_map_create(BMesh *bm)
{
- BMEditSelection *ese;
- GHash *map;
+ BMEditSelection *ese;
+ GHash *map;
- if (BLI_listbase_is_empty(&bm->selected)) {
- return NULL;
- }
+ if (BLI_listbase_is_empty(&bm->selected)) {
+ return NULL;
+ }
- map = BLI_ghash_ptr_new(__func__);
+ map = BLI_ghash_ptr_new(__func__);
- for (ese = bm->selected.first; ese; ese = ese->next) {
- BLI_ghash_insert(map, ese->ele, ese);
- }
+ for (ese = bm->selected.first; ese; ese = ese->next) {
+ BLI_ghash_insert(map, ese->ele, ese);
+ }
- return map;
+ return map;
}
/**
* Map arguments may all be the same pointer.
*/
void BM_select_history_merge_from_targetmap(
- BMesh *bm,
- GHash *vert_map,
- GHash *edge_map,
- GHash *face_map,
- const bool use_chain)
+ BMesh *bm, GHash *vert_map, GHash *edge_map, GHash *face_map, const bool use_chain)
{
#ifdef DEBUG
- for (BMEditSelection *ese = bm->selected.first; ese; ese = ese->next) {
- BLI_assert(BM_ELEM_API_FLAG_TEST(ese->ele, _FLAG_OVERLAP) == 0);
- }
+ for (BMEditSelection *ese = bm->selected.first; ese; ese = ese->next) {
+ BLI_assert(BM_ELEM_API_FLAG_TEST(ese->ele, _FLAG_OVERLAP) == 0);
+ }
#endif
- for (BMEditSelection *ese = bm->selected.first; ese; ese = ese->next) {
- BM_ELEM_API_FLAG_ENABLE(ese->ele, _FLAG_OVERLAP);
-
- /* Only loop when (use_chain == true). */
- GHash *map = NULL;
- switch (ese->ele->head.htype) {
- case BM_VERT: map = vert_map; break;
- case BM_EDGE: map = edge_map; break;
- case BM_FACE: map = face_map; break;
- default: BMESH_ASSERT(0); break;
- }
- if (map != NULL) {
- BMElem *ele_dst = ese->ele;
- while (true) {
- BMElem *ele_dst_next = BLI_ghash_lookup(map, ele_dst);
- BLI_assert(ele_dst != ele_dst_next);
- if (ele_dst_next == NULL) {
- break;
- }
- ele_dst = ele_dst_next;
- /* Break loop on circular reference (should never happen). */
- if (UNLIKELY(ele_dst == ese->ele)) {
- BLI_assert(0);
- break;
- }
- if (use_chain == false) {
- break;
- }
- }
- ese->ele = ele_dst;
- }
- }
-
- /* Remove overlapping duplicates. */
- for (BMEditSelection *ese = bm->selected.first, *ese_next; ese; ese = ese_next) {
- ese_next = ese->next;
- if (BM_ELEM_API_FLAG_TEST(ese->ele, _FLAG_OVERLAP)) {
- BM_ELEM_API_FLAG_DISABLE(ese->ele, _FLAG_OVERLAP);
- }
- else {
- BLI_freelinkN(&bm->selected, ese);
- }
- }
+ for (BMEditSelection *ese = bm->selected.first; ese; ese = ese->next) {
+ BM_ELEM_API_FLAG_ENABLE(ese->ele, _FLAG_OVERLAP);
+
+ /* Only loop when (use_chain == true). */
+ GHash *map = NULL;
+ switch (ese->ele->head.htype) {
+ case BM_VERT:
+ map = vert_map;
+ break;
+ case BM_EDGE:
+ map = edge_map;
+ break;
+ case BM_FACE:
+ map = face_map;
+ break;
+ default:
+ BMESH_ASSERT(0);
+ break;
+ }
+ if (map != NULL) {
+ BMElem *ele_dst = ese->ele;
+ while (true) {
+ BMElem *ele_dst_next = BLI_ghash_lookup(map, ele_dst);
+ BLI_assert(ele_dst != ele_dst_next);
+ if (ele_dst_next == NULL) {
+ break;
+ }
+ ele_dst = ele_dst_next;
+ /* Break loop on circular reference (should never happen). */
+ if (UNLIKELY(ele_dst == ese->ele)) {
+ BLI_assert(0);
+ break;
+ }
+ if (use_chain == false) {
+ break;
+ }
+ }
+ ese->ele = ele_dst;
+ }
+ }
+
+ /* Remove overlapping duplicates. */
+ for (BMEditSelection *ese = bm->selected.first, *ese_next; ese; ese = ese_next) {
+ ese_next = ese->next;
+ if (BM_ELEM_API_FLAG_TEST(ese->ele, _FLAG_OVERLAP)) {
+ BM_ELEM_API_FLAG_DISABLE(ese->ele, _FLAG_OVERLAP);
+ }
+ else {
+ BLI_freelinkN(&bm->selected, ese);
+ }
+ }
}
-void BM_mesh_elem_hflag_disable_test(
- BMesh *bm, const char htype, const char hflag,
- const bool respecthide, const bool overwrite, const char hflag_test)
+void BM_mesh_elem_hflag_disable_test(BMesh *bm,
+ const char htype,
+ const char hflag,
+ const bool respecthide,
+ const bool overwrite,
+ const char hflag_test)
{
- const char iter_types[3] = {BM_VERTS_OF_MESH,
- BM_EDGES_OF_MESH,
- BM_FACES_OF_MESH};
-
- const char flag_types[3] = {BM_VERT, BM_EDGE, BM_FACE};
-
- const char hflag_nosel = hflag & ~BM_ELEM_SELECT;
-
- int i;
-
- BLI_assert((htype & ~BM_ALL_NOLOOP) == 0);
-
- if (hflag & BM_ELEM_SELECT) {
- BM_select_history_clear(bm);
- }
-
- if ((htype == (BM_VERT | BM_EDGE | BM_FACE)) &&
- (hflag == BM_ELEM_SELECT) &&
- (respecthide == false) &&
- (hflag_test == 0))
- {
- /* fast path for deselect all, avoid topology loops
- * since we know all will be de-selected anyway. */
- for (i = 0; i < 3; i++) {
- BMIter iter;
- BMElem *ele;
-
- ele = BM_iter_new(&iter, bm, iter_types[i], NULL);
- for ( ; ele; ele = BM_iter_step(&iter)) {
- BM_elem_flag_disable(ele, BM_ELEM_SELECT);
- }
- }
-
- bm->totvertsel = bm->totedgesel = bm->totfacesel = 0;
- }
- else {
- for (i = 0; i < 3; i++) {
- BMIter iter;
- BMElem *ele;
-
- if (htype & flag_types[i]) {
- ele = BM_iter_new(&iter, bm, iter_types[i], NULL);
- for ( ; ele; ele = BM_iter_step(&iter)) {
-
- if (UNLIKELY(respecthide && BM_elem_flag_test(ele, BM_ELEM_HIDDEN))) {
- /* pass */
- }
- else if (!hflag_test || BM_elem_flag_test(ele, hflag_test)) {
- if (hflag & BM_ELEM_SELECT) {
- BM_elem_select_set(bm, ele, false);
- }
- BM_elem_flag_disable(ele, hflag);
- }
- else if (overwrite) {
- /* no match! */
- if (hflag & BM_ELEM_SELECT) {
- BM_elem_select_set(bm, ele, true);
- }
- BM_elem_flag_enable(ele, hflag_nosel);
- }
- }
- }
- }
- }
+ const char iter_types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH};
+
+ const char flag_types[3] = {BM_VERT, BM_EDGE, BM_FACE};
+
+ const char hflag_nosel = hflag & ~BM_ELEM_SELECT;
+
+ int i;
+
+ BLI_assert((htype & ~BM_ALL_NOLOOP) == 0);
+
+ if (hflag & BM_ELEM_SELECT) {
+ BM_select_history_clear(bm);
+ }
+
+ if ((htype == (BM_VERT | BM_EDGE | BM_FACE)) && (hflag == BM_ELEM_SELECT) &&
+ (respecthide == false) && (hflag_test == 0)) {
+ /* fast path for deselect all, avoid topology loops
+ * since we know all will be de-selected anyway. */
+ for (i = 0; i < 3; i++) {
+ BMIter iter;
+ BMElem *ele;
+
+ ele = BM_iter_new(&iter, bm, iter_types[i], NULL);
+ for (; ele; ele = BM_iter_step(&iter)) {
+ BM_elem_flag_disable(ele, BM_ELEM_SELECT);
+ }
+ }
+
+ bm->totvertsel = bm->totedgesel = bm->totfacesel = 0;
+ }
+ else {
+ for (i = 0; i < 3; i++) {
+ BMIter iter;
+ BMElem *ele;
+
+ if (htype & flag_types[i]) {
+ ele = BM_iter_new(&iter, bm, iter_types[i], NULL);
+ for (; ele; ele = BM_iter_step(&iter)) {
+
+ if (UNLIKELY(respecthide && BM_elem_flag_test(ele, BM_ELEM_HIDDEN))) {
+ /* pass */
+ }
+ else if (!hflag_test || BM_elem_flag_test(ele, hflag_test)) {
+ if (hflag & BM_ELEM_SELECT) {
+ BM_elem_select_set(bm, ele, false);
+ }
+ BM_elem_flag_disable(ele, hflag);
+ }
+ else if (overwrite) {
+ /* no match! */
+ if (hflag & BM_ELEM_SELECT) {
+ BM_elem_select_set(bm, ele, true);
+ }
+ BM_elem_flag_enable(ele, hflag_nosel);
+ }
+ }
+ }
+ }
+ }
}
-void BM_mesh_elem_hflag_enable_test(
- BMesh *bm, const char htype, const char hflag,
- const bool respecthide, const bool overwrite, const char hflag_test)
+void BM_mesh_elem_hflag_enable_test(BMesh *bm,
+ const char htype,
+ const char hflag,
+ const bool respecthide,
+ const bool overwrite,
+ const char hflag_test)
{
- const char iter_types[3] = {BM_VERTS_OF_MESH,
- BM_EDGES_OF_MESH,
- BM_FACES_OF_MESH};
-
- const char flag_types[3] = {BM_VERT, BM_EDGE, BM_FACE};
-
- /* use the nosel version when setting so under no
- * condition may a hidden face become selected.
- * Applying other flags to hidden faces is OK. */
- const char hflag_nosel = hflag & ~BM_ELEM_SELECT;
-
- BMIter iter;
- BMElem *ele;
- int i;
-
- BLI_assert((htype & ~BM_ALL_NOLOOP) == 0);
-
- /* note, better not attempt a fast path for selection as done with de-select
- * because hidden geometry and different selection modes can give different results,
- * we could of course check for no hidden faces and then use quicker method but its not worth it. */
-
- for (i = 0; i < 3; i++) {
- if (htype & flag_types[i]) {
- ele = BM_iter_new(&iter, bm, iter_types[i], NULL);
- for ( ; ele; ele = BM_iter_step(&iter)) {
-
- if (UNLIKELY(respecthide && BM_elem_flag_test(ele, BM_ELEM_HIDDEN))) {
- /* pass */
- }
- else if (!hflag_test || BM_elem_flag_test(ele, hflag_test)) {
- /* match! */
- if (hflag & BM_ELEM_SELECT) {
- BM_elem_select_set(bm, ele, true);
- }
- BM_elem_flag_enable(ele, hflag_nosel);
- }
- else if (overwrite) {
- /* no match! */
- if (hflag & BM_ELEM_SELECT) {
- BM_elem_select_set(bm, ele, false);
- }
- BM_elem_flag_disable(ele, hflag);
- }
- }
- }
- }
+ const char iter_types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH};
+
+ const char flag_types[3] = {BM_VERT, BM_EDGE, BM_FACE};
+
+ /* use the nosel version when setting so under no
+ * condition may a hidden face become selected.
+ * Applying other flags to hidden faces is OK. */
+ const char hflag_nosel = hflag & ~BM_ELEM_SELECT;
+
+ BMIter iter;
+ BMElem *ele;
+ int i;
+
+ BLI_assert((htype & ~BM_ALL_NOLOOP) == 0);
+
+ /* note, better not attempt a fast path for selection as done with de-select
+ * because hidden geometry and different selection modes can give different results,
+ * we could of course check for no hidden faces and then use quicker method but its not worth it. */
+
+ for (i = 0; i < 3; i++) {
+ if (htype & flag_types[i]) {
+ ele = BM_iter_new(&iter, bm, iter_types[i], NULL);
+ for (; ele; ele = BM_iter_step(&iter)) {
+
+ if (UNLIKELY(respecthide && BM_elem_flag_test(ele, BM_ELEM_HIDDEN))) {
+ /* pass */
+ }
+ else if (!hflag_test || BM_elem_flag_test(ele, hflag_test)) {
+ /* match! */
+ if (hflag & BM_ELEM_SELECT) {
+ BM_elem_select_set(bm, ele, true);
+ }
+ BM_elem_flag_enable(ele, hflag_nosel);
+ }
+ else if (overwrite) {
+ /* no match! */
+ if (hflag & BM_ELEM_SELECT) {
+ BM_elem_select_set(bm, ele, false);
+ }
+ BM_elem_flag_disable(ele, hflag);
+ }
+ }
+ }
+ }
}
-void BM_mesh_elem_hflag_disable_all(
- BMesh *bm, const char htype, const char hflag,
- const bool respecthide)
+void BM_mesh_elem_hflag_disable_all(BMesh *bm,
+ const char htype,
+ const char hflag,
+ const bool respecthide)
{
- /* call with 0 hflag_test */
- BM_mesh_elem_hflag_disable_test(bm, htype, hflag, respecthide, false, 0);
+ /* call with 0 hflag_test */
+ BM_mesh_elem_hflag_disable_test(bm, htype, hflag, respecthide, false, 0);
}
-void BM_mesh_elem_hflag_enable_all(
- BMesh *bm, const char htype, const char hflag,
- const bool respecthide)
+void BM_mesh_elem_hflag_enable_all(BMesh *bm,
+ const char htype,
+ const char hflag,
+ const bool respecthide)
{
- /* call with 0 hflag_test */
- BM_mesh_elem_hflag_enable_test(bm, htype, hflag, respecthide, false, 0);
+ /* call with 0 hflag_test */
+ BM_mesh_elem_hflag_enable_test(bm, htype, hflag, respecthide, false, 0);
}
/***************** Mesh Hiding stuff *********** */
@@ -1277,7 +1286,7 @@ void BM_mesh_elem_hflag_enable_all(
*/
static void vert_flush_hide_set(BMVert *v)
{
- BM_elem_flag_set(v, BM_ELEM_HIDDEN, !bm_vert_is_edge_visible_any(v));
+ BM_elem_flag_set(v, BM_ELEM_HIDDEN, !bm_vert_is_edge_visible_any(v));
}
/**
@@ -1286,124 +1295,124 @@ static void vert_flush_hide_set(BMVert *v)
*/
static void edge_flush_hide_set(BMEdge *e)
{
- BM_elem_flag_set(e, BM_ELEM_HIDDEN, !bm_edge_is_face_visible_any(e));
+ BM_elem_flag_set(e, BM_ELEM_HIDDEN, !bm_edge_is_face_visible_any(e));
}
void BM_vert_hide_set(BMVert *v, const bool hide)
{
- /* vert hiding: vert + surrounding edges and faces */
- BLI_assert(v->head.htype == BM_VERT);
- if (hide) {
- BLI_assert(!BM_elem_flag_test(v, BM_ELEM_SELECT));
- }
-
- BM_elem_flag_set(v, BM_ELEM_HIDDEN, hide);
-
- if (v->e) {
- BMEdge *e_iter, *e_first;
- e_iter = e_first = v->e;
- do {
- BM_elem_flag_set(e_iter, BM_ELEM_HIDDEN, hide);
- if (e_iter->l) {
- const BMLoop *l_radial_iter, *l_radial_first;
- l_radial_iter = l_radial_first = e_iter->l;
- do {
- BM_elem_flag_set(l_radial_iter->f, BM_ELEM_HIDDEN, hide);
- } while ((l_radial_iter = l_radial_iter->radial_next) != l_radial_first);
- }
- } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
- }
+ /* vert hiding: vert + surrounding edges and faces */
+ BLI_assert(v->head.htype == BM_VERT);
+ if (hide) {
+ BLI_assert(!BM_elem_flag_test(v, BM_ELEM_SELECT));
+ }
+
+ BM_elem_flag_set(v, BM_ELEM_HIDDEN, hide);
+
+ if (v->e) {
+ BMEdge *e_iter, *e_first;
+ e_iter = e_first = v->e;
+ do {
+ BM_elem_flag_set(e_iter, BM_ELEM_HIDDEN, hide);
+ if (e_iter->l) {
+ const BMLoop *l_radial_iter, *l_radial_first;
+ l_radial_iter = l_radial_first = e_iter->l;
+ do {
+ BM_elem_flag_set(l_radial_iter->f, BM_ELEM_HIDDEN, hide);
+ } while ((l_radial_iter = l_radial_iter->radial_next) != l_radial_first);
+ }
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
+ }
}
void BM_edge_hide_set(BMEdge *e, const bool hide)
{
- BLI_assert(e->head.htype == BM_EDGE);
- if (hide) {
- BLI_assert(!BM_elem_flag_test(e, BM_ELEM_SELECT));
- }
-
- /* edge hiding: faces around the edge */
- if (e->l) {
- const BMLoop *l_iter, *l_first;
- l_iter = l_first = e->l;
- do {
- BM_elem_flag_set(l_iter->f, BM_ELEM_HIDDEN, hide);
- } while ((l_iter = l_iter->radial_next) != l_first);
- }
-
- BM_elem_flag_set(e, BM_ELEM_HIDDEN, hide);
-
- /* hide vertices if necessary */
- if (hide) {
- vert_flush_hide_set(e->v1);
- vert_flush_hide_set(e->v2);
- }
- else {
- BM_elem_flag_disable(e->v1, BM_ELEM_HIDDEN);
- BM_elem_flag_disable(e->v2, BM_ELEM_HIDDEN);
- }
+ BLI_assert(e->head.htype == BM_EDGE);
+ if (hide) {
+ BLI_assert(!BM_elem_flag_test(e, BM_ELEM_SELECT));
+ }
+
+ /* edge hiding: faces around the edge */
+ if (e->l) {
+ const BMLoop *l_iter, *l_first;
+ l_iter = l_first = e->l;
+ do {
+ BM_elem_flag_set(l_iter->f, BM_ELEM_HIDDEN, hide);
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+
+ BM_elem_flag_set(e, BM_ELEM_HIDDEN, hide);
+
+ /* hide vertices if necessary */
+ if (hide) {
+ vert_flush_hide_set(e->v1);
+ vert_flush_hide_set(e->v2);
+ }
+ else {
+ BM_elem_flag_disable(e->v1, BM_ELEM_HIDDEN);
+ BM_elem_flag_disable(e->v2, BM_ELEM_HIDDEN);
+ }
}
void BM_face_hide_set(BMFace *f, const bool hide)
{
- BLI_assert(f->head.htype == BM_FACE);
- if (hide) {
- BLI_assert(!BM_elem_flag_test(f, BM_ELEM_SELECT));
- }
-
- BM_elem_flag_set(f, BM_ELEM_HIDDEN, hide);
-
- if (hide) {
- BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
- BMLoop *l_iter;
-
- l_iter = l_first;
- do {
- edge_flush_hide_set(l_iter->e);
- } while ((l_iter = l_iter->next) != l_first);
-
- l_iter = l_first;
- do {
- vert_flush_hide_set(l_iter->v);
- } while ((l_iter = l_iter->next) != l_first);
- }
- else {
- BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
- BMLoop *l_iter;
-
- l_iter = l_first;
- do {
- BM_elem_flag_disable(l_iter->e, BM_ELEM_HIDDEN);
- BM_elem_flag_disable(l_iter->v, BM_ELEM_HIDDEN);
- } while ((l_iter = l_iter->next) != l_first);
- }
+ BLI_assert(f->head.htype == BM_FACE);
+ if (hide) {
+ BLI_assert(!BM_elem_flag_test(f, BM_ELEM_SELECT));
+ }
+
+ BM_elem_flag_set(f, BM_ELEM_HIDDEN, hide);
+
+ if (hide) {
+ BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
+ BMLoop *l_iter;
+
+ l_iter = l_first;
+ do {
+ edge_flush_hide_set(l_iter->e);
+ } while ((l_iter = l_iter->next) != l_first);
+
+ l_iter = l_first;
+ do {
+ vert_flush_hide_set(l_iter->v);
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ else {
+ BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
+ BMLoop *l_iter;
+
+ l_iter = l_first;
+ do {
+ BM_elem_flag_disable(l_iter->e, BM_ELEM_HIDDEN);
+ BM_elem_flag_disable(l_iter->v, BM_ELEM_HIDDEN);
+ } while ((l_iter = l_iter->next) != l_first);
+ }
}
void _bm_elem_hide_set(BMesh *bm, BMHeader *head, const bool hide)
{
- /* Follow convention of always deselecting before
- * hiding an element */
- switch (head->htype) {
- case BM_VERT:
- if (hide) {
- BM_vert_select_set(bm, (BMVert *)head, false);
- }
- BM_vert_hide_set((BMVert *)head, hide);
- break;
- case BM_EDGE:
- if (hide) {
- BM_edge_select_set(bm, (BMEdge *)head, false);
- }
- BM_edge_hide_set((BMEdge *)head, hide);
- break;
- case BM_FACE:
- if (hide) {
- BM_face_select_set(bm, (BMFace *)head, false);
- }
- BM_face_hide_set((BMFace *)head, hide);
- break;
- default:
- BMESH_ASSERT(0);
- break;
- }
+ /* Follow convention of always deselecting before
+ * hiding an element */
+ switch (head->htype) {
+ case BM_VERT:
+ if (hide) {
+ BM_vert_select_set(bm, (BMVert *)head, false);
+ }
+ BM_vert_hide_set((BMVert *)head, hide);
+ break;
+ case BM_EDGE:
+ if (hide) {
+ BM_edge_select_set(bm, (BMEdge *)head, false);
+ }
+ BM_edge_hide_set((BMEdge *)head, hide);
+ break;
+ case BM_FACE:
+ if (hide) {
+ BM_face_select_set(bm, (BMFace *)head, false);
+ }
+ BM_face_hide_set((BMFace *)head, hide);
+ break;
+ default:
+ BMESH_ASSERT(0);
+ break;
+ }
}
diff --git a/source/blender/bmesh/intern/bmesh_marking.h b/source/blender/bmesh/intern/bmesh_marking.h
index a7416b484d7..06314a7a388 100644
--- a/source/blender/bmesh/intern/bmesh_marking.h
+++ b/source/blender/bmesh/intern/bmesh_marking.h
@@ -22,9 +22,9 @@
*/
typedef struct BMEditSelection {
- struct BMEditSelection *next, *prev;
- BMElem *ele;
- char htype;
+ struct BMEditSelection *next, *prev;
+ BMElem *ele;
+ char htype;
} BMEditSelection;
/* geometry hiding code */
@@ -37,19 +37,27 @@ void BM_face_hide_set(BMFace *f, const bool hide);
/* Selection code */
void BM_elem_select_set(BMesh *bm, BMElem *ele, const bool select);
-void BM_mesh_elem_hflag_enable_test(
- BMesh *bm, const char htype, const char hflag,
- const bool respecthide, const bool overwrite, const char hflag_test);
-void BM_mesh_elem_hflag_disable_test(
- BMesh *bm, const char htype, const char hflag,
- const bool respecthide, const bool overwrite, const char hflag_test);
-
-void BM_mesh_elem_hflag_enable_all(
- BMesh *bm, const char htype, const char hflag,
- const bool respecthide);
-void BM_mesh_elem_hflag_disable_all(
- BMesh *bm, const char htype, const char hflag,
- const bool respecthide);
+void BM_mesh_elem_hflag_enable_test(BMesh *bm,
+ const char htype,
+ const char hflag,
+ const bool respecthide,
+ const bool overwrite,
+ const char hflag_test);
+void BM_mesh_elem_hflag_disable_test(BMesh *bm,
+ const char htype,
+ const char hflag,
+ const bool respecthide,
+ const bool overwrite,
+ const char hflag_test);
+
+void BM_mesh_elem_hflag_enable_all(BMesh *bm,
+ const char htype,
+ const char hflag,
+ const bool respecthide);
+void BM_mesh_elem_hflag_disable_all(BMesh *bm,
+ const char htype,
+ const char hflag,
+ const bool respecthide);
/* individual element select functions, BM_elem_select_set is a shortcut for these
* that automatically detects which one to use*/
@@ -71,37 +79,46 @@ void BM_mesh_select_mode_flush(BMesh *bm);
void BM_mesh_deselect_flush(BMesh *bm);
void BM_mesh_select_flush(BMesh *bm);
-int BM_mesh_elem_hflag_count_enabled(BMesh *bm, const char htype, const char hflag, const bool respecthide);
-int BM_mesh_elem_hflag_count_disabled(BMesh *bm, const char htype, const char hflag, const bool respecthide);
+int BM_mesh_elem_hflag_count_enabled(BMesh *bm,
+ const char htype,
+ const char hflag,
+ const bool respecthide);
+int BM_mesh_elem_hflag_count_disabled(BMesh *bm,
+ const char htype,
+ const char hflag,
+ const bool respecthide);
/* edit selection stuff */
-void BM_mesh_active_face_set(BMesh *bm, BMFace *f);
+void BM_mesh_active_face_set(BMesh *bm, BMFace *f);
BMFace *BM_mesh_active_face_get(BMesh *bm, const bool is_sloppy, const bool is_selected);
BMEdge *BM_mesh_active_edge_get(BMesh *bm);
BMVert *BM_mesh_active_vert_get(BMesh *bm);
BMElem *BM_mesh_active_elem_get(BMesh *bm);
-void BM_editselection_center(BMEditSelection *ese, float r_center[3]);
-void BM_editselection_normal(BMEditSelection *ese, float r_normal[3]);
-void BM_editselection_plane(BMEditSelection *ese, float r_plane[3]);
+void BM_editselection_center(BMEditSelection *ese, float r_center[3]);
+void BM_editselection_normal(BMEditSelection *ese, float r_normal[3]);
+void BM_editselection_plane(BMEditSelection *ese, float r_plane[3]);
-#define BM_select_history_check(bm, ele) _bm_select_history_check(bm, &(ele)->head)
-#define BM_select_history_remove(bm, ele) _bm_select_history_remove(bm, &(ele)->head)
+#define BM_select_history_check(bm, ele) _bm_select_history_check(bm, &(ele)->head)
+#define BM_select_history_remove(bm, ele) _bm_select_history_remove(bm, &(ele)->head)
#define BM_select_history_store_notest(bm, ele) _bm_select_history_store_notest(bm, &(ele)->head)
-#define BM_select_history_store(bm, ele) _bm_select_history_store(bm, &(ele)->head)
-#define BM_select_history_store_head_notest(bm, ele) _bm_select_history_store_head_notest(bm, &(ele)->head)
-#define BM_select_history_store_head(bm, ele) _bm_select_history_store_head(bm, &(ele)->head)
-#define BM_select_history_store_after_notest(bm, ese_ref, ele) _bm_select_history_store_after_notest(bm, ese_ref, &(ele)->head)
-#define BM_select_history_store_after(bm, ese, ese_ref) _bm_select_history_store_after(bm, ese_ref, &(ele)->head)
-
-bool _bm_select_history_check(BMesh *bm, const BMHeader *ele);
-bool _bm_select_history_remove(BMesh *bm, BMHeader *ele);
+#define BM_select_history_store(bm, ele) _bm_select_history_store(bm, &(ele)->head)
+#define BM_select_history_store_head_notest(bm, ele) \
+ _bm_select_history_store_head_notest(bm, &(ele)->head)
+#define BM_select_history_store_head(bm, ele) _bm_select_history_store_head(bm, &(ele)->head)
+#define BM_select_history_store_after_notest(bm, ese_ref, ele) \
+ _bm_select_history_store_after_notest(bm, ese_ref, &(ele)->head)
+#define BM_select_history_store_after(bm, ese, ese_ref) \
+ _bm_select_history_store_after(bm, ese_ref, &(ele)->head)
+
+bool _bm_select_history_check(BMesh *bm, const BMHeader *ele);
+bool _bm_select_history_remove(BMesh *bm, BMHeader *ele);
void _bm_select_history_store_notest(BMesh *bm, BMHeader *ele);
-void _bm_select_history_store(BMesh *bm, BMHeader *ele);
+void _bm_select_history_store(BMesh *bm, BMHeader *ele);
void _bm_select_history_store_head_notest(BMesh *bm, BMHeader *ele);
-void _bm_select_history_store_head(BMesh *bm, BMHeader *ele);
-void _bm_select_history_store_after(BMesh *bm, BMEditSelection *ese_ref, BMHeader *ele);
-void _bm_select_history_store_after_notest(BMesh *bm, BMEditSelection *ese_ref, BMHeader *ele);
+void _bm_select_history_store_head(BMesh *bm, BMHeader *ele);
+void _bm_select_history_store_after(BMesh *bm, BMEditSelection *ese_ref, BMHeader *ele);
+void _bm_select_history_store_after_notest(BMesh *bm, BMEditSelection *ese_ref, BMHeader *ele);
void BM_select_history_validate(BMesh *bm);
void BM_select_history_clear(BMesh *bm);
@@ -109,12 +126,16 @@ bool BM_select_history_active_get(BMesh *bm, struct BMEditSelection *ese);
struct GHash *BM_select_history_map_create(BMesh *bm);
void BM_select_history_merge_from_targetmap(
- BMesh *bm, GHash *vert_map, GHash *edge_map, GHash *face_map, const bool use_chain);
+ BMesh *bm, GHash *vert_map, GHash *edge_map, GHash *face_map, const bool use_chain);
-#define BM_SELECT_HISTORY_BACKUP(bm) { \
- ListBase _bm_prev_selected = (bm)->selected; BLI_listbase_clear(&(bm)->selected)
+#define BM_SELECT_HISTORY_BACKUP(bm) \
+ { \
+ ListBase _bm_prev_selected = (bm)->selected; \
+ BLI_listbase_clear(&(bm)->selected)
#define BM_SELECT_HISTORY_RESTORE(bm) \
- (bm)->selected = _bm_prev_selected; } (void)0
+ (bm)->selected = _bm_prev_selected; \
+ } \
+ (void)0
#endif /* __BMESH_MARKING_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c
index 460b7ce8dae..8d445d428b2 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.c
+++ b/source/blender/bmesh/intern/bmesh_mesh.c
@@ -45,106 +45,103 @@
const BMAllocTemplate bm_mesh_allocsize_default = {512, 1024, 2048, 512};
const BMAllocTemplate bm_mesh_chunksize_default = {512, 1024, 2048, 512};
-static void bm_mempool_init_ex(
- const BMAllocTemplate *allocsize, const bool use_toolflags,
- BLI_mempool **r_vpool, BLI_mempool **r_epool, BLI_mempool **r_lpool, BLI_mempool **r_fpool)
+static void bm_mempool_init_ex(const BMAllocTemplate *allocsize,
+ const bool use_toolflags,
+ BLI_mempool **r_vpool,
+ BLI_mempool **r_epool,
+ BLI_mempool **r_lpool,
+ BLI_mempool **r_fpool)
{
- size_t vert_size, edge_size, loop_size, face_size;
-
- if (use_toolflags == true) {
- vert_size = sizeof(BMVert_OFlag);
- edge_size = sizeof(BMEdge_OFlag);
- loop_size = sizeof(BMLoop);
- face_size = sizeof(BMFace_OFlag);
- }
- else {
- vert_size = sizeof(BMVert);
- edge_size = sizeof(BMEdge);
- loop_size = sizeof(BMLoop);
- face_size = sizeof(BMFace);
- }
-
- if (r_vpool) {
- *r_vpool = BLI_mempool_create(
- vert_size, allocsize->totvert,
- bm_mesh_chunksize_default.totvert, BLI_MEMPOOL_ALLOW_ITER);
- }
- if (r_epool) {
- *r_epool = BLI_mempool_create(
- edge_size, allocsize->totedge,
- bm_mesh_chunksize_default.totedge, BLI_MEMPOOL_ALLOW_ITER);
- }
- if (r_lpool) {
- *r_lpool = BLI_mempool_create(
- loop_size, allocsize->totloop,
- bm_mesh_chunksize_default.totloop, BLI_MEMPOOL_NOP);
- }
- if (r_fpool) {
- *r_fpool = BLI_mempool_create(
- face_size, allocsize->totface,
- bm_mesh_chunksize_default.totface, BLI_MEMPOOL_ALLOW_ITER);
- }
+ size_t vert_size, edge_size, loop_size, face_size;
+
+ if (use_toolflags == true) {
+ vert_size = sizeof(BMVert_OFlag);
+ edge_size = sizeof(BMEdge_OFlag);
+ loop_size = sizeof(BMLoop);
+ face_size = sizeof(BMFace_OFlag);
+ }
+ else {
+ vert_size = sizeof(BMVert);
+ edge_size = sizeof(BMEdge);
+ loop_size = sizeof(BMLoop);
+ face_size = sizeof(BMFace);
+ }
+
+ if (r_vpool) {
+ *r_vpool = BLI_mempool_create(
+ vert_size, allocsize->totvert, bm_mesh_chunksize_default.totvert, BLI_MEMPOOL_ALLOW_ITER);
+ }
+ if (r_epool) {
+ *r_epool = BLI_mempool_create(
+ edge_size, allocsize->totedge, bm_mesh_chunksize_default.totedge, BLI_MEMPOOL_ALLOW_ITER);
+ }
+ if (r_lpool) {
+ *r_lpool = BLI_mempool_create(
+ loop_size, allocsize->totloop, bm_mesh_chunksize_default.totloop, BLI_MEMPOOL_NOP);
+ }
+ if (r_fpool) {
+ *r_fpool = BLI_mempool_create(
+ face_size, allocsize->totface, bm_mesh_chunksize_default.totface, BLI_MEMPOOL_ALLOW_ITER);
+ }
}
static void bm_mempool_init(BMesh *bm, const BMAllocTemplate *allocsize, const bool use_toolflags)
{
- bm_mempool_init_ex(
- allocsize, use_toolflags,
- &bm->vpool, &bm->epool, &bm->lpool, &bm->fpool);
+ bm_mempool_init_ex(allocsize, use_toolflags, &bm->vpool, &bm->epool, &bm->lpool, &bm->fpool);
#ifdef USE_BMESH_HOLES
- bm->looplistpool = BLI_mempool_create(sizeof(BMLoopList), 512, 512, BLI_MEMPOOL_NOP);
+ bm->looplistpool = BLI_mempool_create(sizeof(BMLoopList), 512, 512, BLI_MEMPOOL_NOP);
#endif
}
void BM_mesh_elem_toolflags_ensure(BMesh *bm)
{
- BLI_assert(bm->use_toolflags);
-
- if (bm->vtoolflagpool && bm->etoolflagpool && bm->ftoolflagpool) {
- return;
- }
-
- bm->vtoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), bm->totvert, 512, BLI_MEMPOOL_NOP);
- bm->etoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), bm->totedge, 512, BLI_MEMPOOL_NOP);
- bm->ftoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), bm->totface, 512, BLI_MEMPOOL_NOP);
-
- BMIter iter;
- BMVert_OFlag *v_olfag;
- BLI_mempool *toolflagpool = bm->vtoolflagpool;
- BM_ITER_MESH (v_olfag, &iter, bm, BM_VERTS_OF_MESH) {
- v_olfag->oflags = BLI_mempool_calloc(toolflagpool);
- }
-
- BMEdge_OFlag *e_olfag;
- toolflagpool = bm->etoolflagpool;
- BM_ITER_MESH (e_olfag, &iter, bm, BM_EDGES_OF_MESH) {
- e_olfag->oflags = BLI_mempool_calloc(toolflagpool);
- }
-
- BMFace_OFlag *f_olfag;
- toolflagpool = bm->ftoolflagpool;
- BM_ITER_MESH (f_olfag, &iter, bm, BM_FACES_OF_MESH) {
- f_olfag->oflags = BLI_mempool_calloc(toolflagpool);
- }
-
- bm->totflags = 1;
+ BLI_assert(bm->use_toolflags);
+
+ if (bm->vtoolflagpool && bm->etoolflagpool && bm->ftoolflagpool) {
+ return;
+ }
+
+ bm->vtoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), bm->totvert, 512, BLI_MEMPOOL_NOP);
+ bm->etoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), bm->totedge, 512, BLI_MEMPOOL_NOP);
+ bm->ftoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), bm->totface, 512, BLI_MEMPOOL_NOP);
+
+ BMIter iter;
+ BMVert_OFlag *v_olfag;
+ BLI_mempool *toolflagpool = bm->vtoolflagpool;
+ BM_ITER_MESH (v_olfag, &iter, bm, BM_VERTS_OF_MESH) {
+ v_olfag->oflags = BLI_mempool_calloc(toolflagpool);
+ }
+
+ BMEdge_OFlag *e_olfag;
+ toolflagpool = bm->etoolflagpool;
+ BM_ITER_MESH (e_olfag, &iter, bm, BM_EDGES_OF_MESH) {
+ e_olfag->oflags = BLI_mempool_calloc(toolflagpool);
+ }
+
+ BMFace_OFlag *f_olfag;
+ toolflagpool = bm->ftoolflagpool;
+ BM_ITER_MESH (f_olfag, &iter, bm, BM_FACES_OF_MESH) {
+ f_olfag->oflags = BLI_mempool_calloc(toolflagpool);
+ }
+
+ bm->totflags = 1;
}
void BM_mesh_elem_toolflags_clear(BMesh *bm)
{
- if (bm->vtoolflagpool) {
- BLI_mempool_destroy(bm->vtoolflagpool);
- bm->vtoolflagpool = NULL;
- }
- if (bm->etoolflagpool) {
- BLI_mempool_destroy(bm->etoolflagpool);
- bm->etoolflagpool = NULL;
- }
- if (bm->ftoolflagpool) {
- BLI_mempool_destroy(bm->ftoolflagpool);
- bm->ftoolflagpool = NULL;
- }
+ if (bm->vtoolflagpool) {
+ BLI_mempool_destroy(bm->vtoolflagpool);
+ bm->vtoolflagpool = NULL;
+ }
+ if (bm->etoolflagpool) {
+ BLI_mempool_destroy(bm->etoolflagpool);
+ bm->etoolflagpool = NULL;
+ }
+ if (bm->ftoolflagpool) {
+ BLI_mempool_destroy(bm->ftoolflagpool);
+ bm->ftoolflagpool = NULL;
+ }
}
/**
@@ -156,27 +153,25 @@ void BM_mesh_elem_toolflags_clear(BMesh *bm)
*
* \note ob is needed by multires
*/
-BMesh *BM_mesh_create(
- const BMAllocTemplate *allocsize,
- const struct BMeshCreateParams *params)
+BMesh *BM_mesh_create(const BMAllocTemplate *allocsize, const struct BMeshCreateParams *params)
{
- /* allocate the structure */
- BMesh *bm = MEM_callocN(sizeof(BMesh), __func__);
+ /* allocate the structure */
+ BMesh *bm = MEM_callocN(sizeof(BMesh), __func__);
- /* allocate the memory pools for the mesh elements */
- bm_mempool_init(bm, allocsize, params->use_toolflags);
+ /* allocate the memory pools for the mesh elements */
+ bm_mempool_init(bm, allocsize, params->use_toolflags);
- /* allocate one flag pool that we don't get rid of. */
- bm->use_toolflags = params->use_toolflags;
- bm->toolflag_index = 0;
- bm->totflags = 0;
+ /* allocate one flag pool that we don't get rid of. */
+ bm->use_toolflags = params->use_toolflags;
+ bm->toolflag_index = 0;
+ bm->totflags = 0;
- CustomData_reset(&bm->vdata);
- CustomData_reset(&bm->edata);
- CustomData_reset(&bm->ldata);
- CustomData_reset(&bm->pdata);
+ CustomData_reset(&bm->vdata);
+ CustomData_reset(&bm->edata);
+ CustomData_reset(&bm->ldata);
+ CustomData_reset(&bm->pdata);
- return bm;
+ return bm;
}
/**
@@ -188,79 +183,93 @@ BMesh *BM_mesh_create(
*/
void BM_mesh_data_free(BMesh *bm)
{
- BMVert *v;
- BMEdge *e;
- BMLoop *l;
- BMFace *f;
-
- BMIter iter;
- BMIter itersub;
-
- const bool is_ldata_free = CustomData_bmesh_has_free(&bm->ldata);
- const bool is_pdata_free = CustomData_bmesh_has_free(&bm->pdata);
-
- /* Check if we have to call free, if not we can avoid a lot of looping */
- if (CustomData_bmesh_has_free(&(bm->vdata))) {
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- CustomData_bmesh_free_block(&(bm->vdata), &(v->head.data));
- }
- }
- if (CustomData_bmesh_has_free(&(bm->edata))) {
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- CustomData_bmesh_free_block(&(bm->edata), &(e->head.data));
- }
- }
-
- if (is_ldata_free || is_pdata_free) {
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- if (is_pdata_free) {
- CustomData_bmesh_free_block(&(bm->pdata), &(f->head.data));
- }
- if (is_ldata_free) {
- BM_ITER_ELEM (l, &itersub, f, BM_LOOPS_OF_FACE) {
- CustomData_bmesh_free_block(&(bm->ldata), &(l->head.data));
- }
- }
- }
- }
-
- /* Free custom data pools, This should probably go in CustomData_free? */
- if (bm->vdata.totlayer) { BLI_mempool_destroy(bm->vdata.pool); }
- if (bm->edata.totlayer) { BLI_mempool_destroy(bm->edata.pool); }
- if (bm->ldata.totlayer) { BLI_mempool_destroy(bm->ldata.pool); }
- if (bm->pdata.totlayer) { BLI_mempool_destroy(bm->pdata.pool); }
-
- /* free custom data */
- CustomData_free(&bm->vdata, 0);
- CustomData_free(&bm->edata, 0);
- CustomData_free(&bm->ldata, 0);
- CustomData_free(&bm->pdata, 0);
-
- /* destroy element pools */
- BLI_mempool_destroy(bm->vpool);
- BLI_mempool_destroy(bm->epool);
- BLI_mempool_destroy(bm->lpool);
- BLI_mempool_destroy(bm->fpool);
-
- if (bm->vtable) { MEM_freeN(bm->vtable); }
- if (bm->etable) { MEM_freeN(bm->etable); }
- if (bm->ftable) { MEM_freeN(bm->ftable); }
-
- /* destroy flag pool */
- BM_mesh_elem_toolflags_clear(bm);
+ BMVert *v;
+ BMEdge *e;
+ BMLoop *l;
+ BMFace *f;
+
+ BMIter iter;
+ BMIter itersub;
+
+ const bool is_ldata_free = CustomData_bmesh_has_free(&bm->ldata);
+ const bool is_pdata_free = CustomData_bmesh_has_free(&bm->pdata);
+
+ /* Check if we have to call free, if not we can avoid a lot of looping */
+ if (CustomData_bmesh_has_free(&(bm->vdata))) {
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ CustomData_bmesh_free_block(&(bm->vdata), &(v->head.data));
+ }
+ }
+ if (CustomData_bmesh_has_free(&(bm->edata))) {
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ CustomData_bmesh_free_block(&(bm->edata), &(e->head.data));
+ }
+ }
+
+ if (is_ldata_free || is_pdata_free) {
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if (is_pdata_free) {
+ CustomData_bmesh_free_block(&(bm->pdata), &(f->head.data));
+ }
+ if (is_ldata_free) {
+ BM_ITER_ELEM (l, &itersub, f, BM_LOOPS_OF_FACE) {
+ CustomData_bmesh_free_block(&(bm->ldata), &(l->head.data));
+ }
+ }
+ }
+ }
+
+ /* Free custom data pools, This should probably go in CustomData_free? */
+ if (bm->vdata.totlayer) {
+ BLI_mempool_destroy(bm->vdata.pool);
+ }
+ if (bm->edata.totlayer) {
+ BLI_mempool_destroy(bm->edata.pool);
+ }
+ if (bm->ldata.totlayer) {
+ BLI_mempool_destroy(bm->ldata.pool);
+ }
+ if (bm->pdata.totlayer) {
+ BLI_mempool_destroy(bm->pdata.pool);
+ }
+
+ /* free custom data */
+ CustomData_free(&bm->vdata, 0);
+ CustomData_free(&bm->edata, 0);
+ CustomData_free(&bm->ldata, 0);
+ CustomData_free(&bm->pdata, 0);
+
+ /* destroy element pools */
+ BLI_mempool_destroy(bm->vpool);
+ BLI_mempool_destroy(bm->epool);
+ BLI_mempool_destroy(bm->lpool);
+ BLI_mempool_destroy(bm->fpool);
+
+ if (bm->vtable) {
+ MEM_freeN(bm->vtable);
+ }
+ if (bm->etable) {
+ MEM_freeN(bm->etable);
+ }
+ if (bm->ftable) {
+ MEM_freeN(bm->ftable);
+ }
+
+ /* destroy flag pool */
+ BM_mesh_elem_toolflags_clear(bm);
#ifdef USE_BMESH_HOLES
- BLI_mempool_destroy(bm->looplistpool);
+ BLI_mempool_destroy(bm->looplistpool);
#endif
- BLI_freelistN(&bm->selected);
+ BLI_freelistN(&bm->selected);
- if (bm->lnor_spacearr) {
- BKE_lnor_spacearr_free(bm->lnor_spacearr);
- MEM_freeN(bm->lnor_spacearr);
- }
+ if (bm->lnor_spacearr) {
+ BKE_lnor_spacearr_free(bm->lnor_spacearr);
+ MEM_freeN(bm->lnor_spacearr);
+ }
- BMO_error_clear(bm);
+ BMO_error_clear(bm);
}
/**
@@ -270,23 +279,23 @@ void BM_mesh_data_free(BMesh *bm)
*/
void BM_mesh_clear(BMesh *bm)
{
- const bool use_toolflags = bm->use_toolflags;
+ const bool use_toolflags = bm->use_toolflags;
- /* free old mesh */
- BM_mesh_data_free(bm);
- memset(bm, 0, sizeof(BMesh));
+ /* free old mesh */
+ BM_mesh_data_free(bm);
+ memset(bm, 0, sizeof(BMesh));
- /* allocate the memory pools for the mesh elements */
- bm_mempool_init(bm, &bm_mesh_allocsize_default, use_toolflags);
+ /* allocate the memory pools for the mesh elements */
+ bm_mempool_init(bm, &bm_mesh_allocsize_default, use_toolflags);
- bm->use_toolflags = use_toolflags;
- bm->toolflag_index = 0;
- bm->totflags = 0;
+ bm->use_toolflags = use_toolflags;
+ bm->toolflag_index = 0;
+ bm->totflags = 0;
- CustomData_reset(&bm->vdata);
- CustomData_reset(&bm->edata);
- CustomData_reset(&bm->ldata);
- CustomData_reset(&bm->pdata);
+ CustomData_reset(&bm->vdata);
+ CustomData_reset(&bm->edata);
+ CustomData_reset(&bm->ldata);
+ CustomData_reset(&bm->pdata);
}
/**
@@ -296,19 +305,18 @@ void BM_mesh_clear(BMesh *bm)
*/
void BM_mesh_free(BMesh *bm)
{
- BM_mesh_data_free(bm);
+ BM_mesh_data_free(bm);
- if (bm->py_handle) {
- /* keep this out of 'BM_mesh_data_free' because we want python
- * to be able to clear the mesh and maintain access. */
- bpy_bm_generic_invalidate(bm->py_handle);
- bm->py_handle = NULL;
- }
+ if (bm->py_handle) {
+ /* keep this out of 'BM_mesh_data_free' because we want python
+ * to be able to clear the mesh and maintain access. */
+ bpy_bm_generic_invalidate(bm->py_handle);
+ bm->py_handle = NULL;
+ }
- MEM_freeN(bm);
+ MEM_freeN(bm);
}
-
/**
* Helpers for #BM_mesh_normals_update and #BM_verts_calc_normal_vcos
*/
@@ -317,166 +325,170 @@ void BM_mesh_free(BMesh *bm)
#define BM_LNORSPACE_UPDATE _FLAG_MF
typedef struct BMEdgesCalcVectorsData {
- /* Read-only data. */
- const float (*vcos)[3];
+ /* Read-only data. */
+ const float (*vcos)[3];
- /* Read-write data, but no need to protect it, no concurrency to fear here. */
- float (*edgevec)[3];
+ /* Read-write data, but no need to protect it, no concurrency to fear here. */
+ float (*edgevec)[3];
} BMEdgesCalcVectorsData;
-
static void mesh_edges_calc_vectors_cb(void *userdata, MempoolIterData *mp_e)
{
- BMEdgesCalcVectorsData *data = userdata;
- BMEdge *e = (BMEdge *)mp_e;
-
- if (e->l) {
- const float *v1_co = data->vcos ? data->vcos[BM_elem_index_get(e->v1)] : e->v1->co;
- const float *v2_co = data->vcos ? data->vcos[BM_elem_index_get(e->v2)] : e->v2->co;
- sub_v3_v3v3(data->edgevec[BM_elem_index_get(e)], v2_co, v1_co);
- normalize_v3(data->edgevec[BM_elem_index_get(e)]);
- }
- else {
- /* the edge vector will not be needed when the edge has no radial */
- }
+ BMEdgesCalcVectorsData *data = userdata;
+ BMEdge *e = (BMEdge *)mp_e;
+
+ if (e->l) {
+ const float *v1_co = data->vcos ? data->vcos[BM_elem_index_get(e->v1)] : e->v1->co;
+ const float *v2_co = data->vcos ? data->vcos[BM_elem_index_get(e->v2)] : e->v2->co;
+ sub_v3_v3v3(data->edgevec[BM_elem_index_get(e)], v2_co, v1_co);
+ normalize_v3(data->edgevec[BM_elem_index_get(e)]);
+ }
+ else {
+ /* the edge vector will not be needed when the edge has no radial */
+ }
}
static void bm_mesh_edges_calc_vectors(BMesh *bm, float (*edgevec)[3], const float (*vcos)[3])
{
- BM_mesh_elem_index_ensure(bm, BM_EDGE | (vcos ? BM_VERT : 0));
+ BM_mesh_elem_index_ensure(bm, BM_EDGE | (vcos ? BM_VERT : 0));
- BMEdgesCalcVectorsData data = {
- .vcos = vcos,
- .edgevec = edgevec,
- };
+ BMEdgesCalcVectorsData data = {
+ .vcos = vcos,
+ .edgevec = edgevec,
+ };
- BM_iter_parallel(bm, BM_EDGES_OF_MESH, mesh_edges_calc_vectors_cb, &data, bm->totedge >= BM_OMP_LIMIT);
+ BM_iter_parallel(
+ bm, BM_EDGES_OF_MESH, mesh_edges_calc_vectors_cb, &data, bm->totedge >= BM_OMP_LIMIT);
}
-
typedef struct BMVertsCalcNormalsData {
- /* Read-only data. */
- const float (*fnos)[3];
- const float (*edgevec)[3];
- const float (*vcos)[3];
+ /* Read-only data. */
+ const float (*fnos)[3];
+ const float (*edgevec)[3];
+ const float (*vcos)[3];
- /* Read-write data, protected by an atomic-based fake spinlock-like system... */
- float (*vnos)[3];
+ /* Read-write data, protected by an atomic-based fake spinlock-like system... */
+ float (*vnos)[3];
} BMVertsCalcNormalsData;
static void mesh_verts_calc_normals_accum_cb(void *userdata, MempoolIterData *mp_f)
{
#define FLT_EQ_NONAN(_fa, _fb) (*((const uint32_t *)&_fa) == *((const uint32_t *)&_fb))
- BMVertsCalcNormalsData *data = userdata;
- BMFace *f = (BMFace *)mp_f;
-
- const float *f_no = data->fnos ? data->fnos[BM_elem_index_get(f)] : f->no;
-
- BMLoop *l_first, *l_iter;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- const float *e1diff, *e2diff;
- float dotprod;
- float fac;
-
- /* calculate the dot product of the two edges that
- * meet at the loop's vertex */
- e1diff = data->edgevec[BM_elem_index_get(l_iter->prev->e)];
- e2diff = data->edgevec[BM_elem_index_get(l_iter->e)];
- dotprod = dot_v3v3(e1diff, e2diff);
-
- /* edge vectors are calculated from e->v1 to e->v2, so
- * adjust the dot product if one but not both loops
- * actually runs from from e->v2 to e->v1 */
- if ((l_iter->prev->e->v1 == l_iter->prev->v) ^ (l_iter->e->v1 == l_iter->v)) {
- dotprod = -dotprod;
- }
-
- fac = saacos(-dotprod);
-
- if (fac != fac) { /* NAN detection. */
- /* Degenerated case, nothing to do here, just ignore that vertex. */
- continue;
- }
-
- /* accumulate weighted face normal into the vertex's normal */
- float *v_no = data->vnos ? data->vnos[BM_elem_index_get(l_iter->v)] : l_iter->v->no;
-
- /* This block is a lockless threadsafe madd_v3_v3fl.
- * It uses the first float of the vector as a sort of cheap spinlock,
- * assuming FLT_MAX is a safe 'illegal' value that cannot be set here otherwise.
- * It also assumes that collisions between threads are highly unlikely,
- * else performances would be quite bad here. */
- float virtual_lock = v_no[0];
- while (true) {
- /* This loops until following conditions are met:
- * - v_no[0] has same value as virtual_lock (i.e. it did not change since last try).
- * - v_no[0] was not FLT_MAX, i.e. it was not locked by another thread.
- */
- const float vl = atomic_cas_float(&v_no[0], virtual_lock, FLT_MAX);
- if (FLT_EQ_NONAN(vl, virtual_lock) && vl != FLT_MAX) {
- break;
- }
- virtual_lock = vl;
- }
- BLI_assert(v_no[0] == FLT_MAX);
- /* Now we own that normal value, and can change it.
- * But first scalar of the vector must not be changed yet, it's our lock! */
- virtual_lock += f_no[0] * fac;
- v_no[1] += f_no[1] * fac;
- v_no[2] += f_no[2] * fac;
- /* Second atomic operation to 'release' our lock on that vector and set its first scalar value. */
- /* Note that we do not need to loop here, since we 'locked' v_no[0],
- * nobody should have changed it in the mean time. */
- virtual_lock = atomic_cas_float(&v_no[0], FLT_MAX, virtual_lock);
- BLI_assert(virtual_lock == FLT_MAX);
-
- } while ((l_iter = l_iter->next) != l_first);
+ BMVertsCalcNormalsData *data = userdata;
+ BMFace *f = (BMFace *)mp_f;
+
+ const float *f_no = data->fnos ? data->fnos[BM_elem_index_get(f)] : f->no;
+
+ BMLoop *l_first, *l_iter;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ const float *e1diff, *e2diff;
+ float dotprod;
+ float fac;
+
+ /* calculate the dot product of the two edges that
+ * meet at the loop's vertex */
+ e1diff = data->edgevec[BM_elem_index_get(l_iter->prev->e)];
+ e2diff = data->edgevec[BM_elem_index_get(l_iter->e)];
+ dotprod = dot_v3v3(e1diff, e2diff);
+
+ /* edge vectors are calculated from e->v1 to e->v2, so
+ * adjust the dot product if one but not both loops
+ * actually runs from from e->v2 to e->v1 */
+ if ((l_iter->prev->e->v1 == l_iter->prev->v) ^ (l_iter->e->v1 == l_iter->v)) {
+ dotprod = -dotprod;
+ }
+
+ fac = saacos(-dotprod);
+
+ if (fac != fac) { /* NAN detection. */
+ /* Degenerated case, nothing to do here, just ignore that vertex. */
+ continue;
+ }
+
+ /* accumulate weighted face normal into the vertex's normal */
+ float *v_no = data->vnos ? data->vnos[BM_elem_index_get(l_iter->v)] : l_iter->v->no;
+
+ /* This block is a lockless threadsafe madd_v3_v3fl.
+ * It uses the first float of the vector as a sort of cheap spinlock,
+ * assuming FLT_MAX is a safe 'illegal' value that cannot be set here otherwise.
+ * It also assumes that collisions between threads are highly unlikely,
+ * else performances would be quite bad here. */
+ float virtual_lock = v_no[0];
+ while (true) {
+ /* This loops until following conditions are met:
+ * - v_no[0] has same value as virtual_lock (i.e. it did not change since last try).
+ * - v_no[0] was not FLT_MAX, i.e. it was not locked by another thread.
+ */
+ const float vl = atomic_cas_float(&v_no[0], virtual_lock, FLT_MAX);
+ if (FLT_EQ_NONAN(vl, virtual_lock) && vl != FLT_MAX) {
+ break;
+ }
+ virtual_lock = vl;
+ }
+ BLI_assert(v_no[0] == FLT_MAX);
+ /* Now we own that normal value, and can change it.
+ * But first scalar of the vector must not be changed yet, it's our lock! */
+ virtual_lock += f_no[0] * fac;
+ v_no[1] += f_no[1] * fac;
+ v_no[2] += f_no[2] * fac;
+ /* Second atomic operation to 'release' our lock on that vector and set its first scalar value. */
+ /* Note that we do not need to loop here, since we 'locked' v_no[0],
+ * nobody should have changed it in the mean time. */
+ virtual_lock = atomic_cas_float(&v_no[0], FLT_MAX, virtual_lock);
+ BLI_assert(virtual_lock == FLT_MAX);
+
+ } while ((l_iter = l_iter->next) != l_first);
#undef FLT_EQ_NONAN
}
static void mesh_verts_calc_normals_normalize_cb(void *userdata, MempoolIterData *mp_v)
{
- BMVertsCalcNormalsData *data = userdata;
- BMVert *v = (BMVert *)mp_v;
-
- float *v_no = data->vnos ? data->vnos[BM_elem_index_get(v)] : v->no;
- if (UNLIKELY(normalize_v3(v_no) == 0.0f)) {
- const float *v_co = data->vcos ? data->vcos[BM_elem_index_get(v)] : v->co;
- normalize_v3_v3(v_no, v_co);
- }
+ BMVertsCalcNormalsData *data = userdata;
+ BMVert *v = (BMVert *)mp_v;
+
+ float *v_no = data->vnos ? data->vnos[BM_elem_index_get(v)] : v->no;
+ if (UNLIKELY(normalize_v3(v_no) == 0.0f)) {
+ const float *v_co = data->vcos ? data->vcos[BM_elem_index_get(v)] : v->co;
+ normalize_v3_v3(v_no, v_co);
+ }
}
-static void bm_mesh_verts_calc_normals(
- BMesh *bm, const float (*edgevec)[3], const float (*fnos)[3],
- const float (*vcos)[3], float (*vnos)[3])
+static void bm_mesh_verts_calc_normals(BMesh *bm,
+ const float (*edgevec)[3],
+ const float (*fnos)[3],
+ const float (*vcos)[3],
+ float (*vnos)[3])
{
- BM_mesh_elem_index_ensure(bm, (BM_EDGE | BM_FACE) | ((vnos || vcos) ? BM_VERT : 0));
-
- BMVertsCalcNormalsData data = {
- .fnos = fnos,
- .edgevec = edgevec,
- .vcos = vcos,
- .vnos = vnos,
- };
-
- BM_iter_parallel(bm, BM_FACES_OF_MESH, mesh_verts_calc_normals_accum_cb, &data, bm->totface >= BM_OMP_LIMIT);
-
- /* normalize the accumulated vertex normals */
- BM_iter_parallel(bm, BM_VERTS_OF_MESH, mesh_verts_calc_normals_normalize_cb, &data, bm->totvert >= BM_OMP_LIMIT);
+ BM_mesh_elem_index_ensure(bm, (BM_EDGE | BM_FACE) | ((vnos || vcos) ? BM_VERT : 0));
+
+ BMVertsCalcNormalsData data = {
+ .fnos = fnos,
+ .edgevec = edgevec,
+ .vcos = vcos,
+ .vnos = vnos,
+ };
+
+ BM_iter_parallel(
+ bm, BM_FACES_OF_MESH, mesh_verts_calc_normals_accum_cb, &data, bm->totface >= BM_OMP_LIMIT);
+
+ /* normalize the accumulated vertex normals */
+ BM_iter_parallel(bm,
+ BM_VERTS_OF_MESH,
+ mesh_verts_calc_normals_normalize_cb,
+ &data,
+ bm->totvert >= BM_OMP_LIMIT);
}
-
static void mesh_faces_calc_normals_cb(void *UNUSED(userdata), MempoolIterData *mp_f)
{
- BMFace *f = (BMFace *)mp_f;
+ BMFace *f = (BMFace *)mp_f;
- BM_face_normal_update(f);
+ BM_face_normal_update(f);
}
-
/**
* \brief BMesh Compute Normals
*
@@ -484,33 +496,34 @@ static void mesh_faces_calc_normals_cb(void *UNUSED(userdata), MempoolIterData *
*/
void BM_mesh_normals_update(BMesh *bm)
{
- float (*edgevec)[3] = MEM_mallocN(sizeof(*edgevec) * bm->totedge, __func__);
-
- /* Parallel mempool iteration does not allow to generate indices inline anymore... */
- BM_mesh_elem_index_ensure(bm, (BM_EDGE | BM_FACE));
-
- /* calculate all face normals */
- BM_iter_parallel(bm, BM_FACES_OF_MESH, mesh_faces_calc_normals_cb, NULL, bm->totface >= BM_OMP_LIMIT);
-
- /* Zero out vertex normals */
- BMIter viter;
- BMVert *v;
- int i;
-
- BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
- BM_elem_index_set(v, i); /* set_inline */
- zero_v3(v->no);
- }
- bm->elem_index_dirty &= ~BM_VERT;
-
- /* Compute normalized direction vectors for each edge.
- * Directions will be used for calculating the weights of the face normals on the vertex normals.
- */
- bm_mesh_edges_calc_vectors(bm, edgevec, NULL);
-
- /* Add weighted face normals to vertices, and normalize vert normals. */
- bm_mesh_verts_calc_normals(bm, (const float(*)[3])edgevec, NULL, NULL, NULL);
- MEM_freeN(edgevec);
+ float(*edgevec)[3] = MEM_mallocN(sizeof(*edgevec) * bm->totedge, __func__);
+
+ /* Parallel mempool iteration does not allow to generate indices inline anymore... */
+ BM_mesh_elem_index_ensure(bm, (BM_EDGE | BM_FACE));
+
+ /* calculate all face normals */
+ BM_iter_parallel(
+ bm, BM_FACES_OF_MESH, mesh_faces_calc_normals_cb, NULL, bm->totface >= BM_OMP_LIMIT);
+
+ /* Zero out vertex normals */
+ BMIter viter;
+ BMVert *v;
+ int i;
+
+ BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
+ BM_elem_index_set(v, i); /* set_inline */
+ zero_v3(v->no);
+ }
+ bm->elem_index_dirty &= ~BM_VERT;
+
+ /* Compute normalized direction vectors for each edge.
+ * Directions will be used for calculating the weights of the face normals on the vertex normals.
+ */
+ bm_mesh_edges_calc_vectors(bm, edgevec, NULL);
+
+ /* Add weighted face normals to vertices, and normalize vert normals. */
+ bm_mesh_verts_calc_normals(bm, (const float(*)[3])edgevec, NULL, NULL, NULL);
+ MEM_freeN(edgevec);
}
/**
@@ -518,95 +531,97 @@ void BM_mesh_normals_update(BMesh *bm)
*
* Computes the vertex normals of a mesh into vnos, using given vertex coordinates (vcos) and polygon normals (fnos).
*/
-void BM_verts_calc_normal_vcos(BMesh *bm, const float (*fnos)[3], const float (*vcos)[3], float (*vnos)[3])
+void BM_verts_calc_normal_vcos(BMesh *bm,
+ const float (*fnos)[3],
+ const float (*vcos)[3],
+ float (*vnos)[3])
{
- float (*edgevec)[3] = MEM_mallocN(sizeof(*edgevec) * bm->totedge, __func__);
+ float(*edgevec)[3] = MEM_mallocN(sizeof(*edgevec) * bm->totedge, __func__);
- /* Compute normalized direction vectors for each edge.
- * Directions will be used for calculating the weights of the face normals on the vertex normals.
- */
- bm_mesh_edges_calc_vectors(bm, edgevec, vcos);
+ /* Compute normalized direction vectors for each edge.
+ * Directions will be used for calculating the weights of the face normals on the vertex normals.
+ */
+ bm_mesh_edges_calc_vectors(bm, edgevec, vcos);
- /* Add weighted face normals to vertices, and normalize vert normals. */
- bm_mesh_verts_calc_normals(bm, (const float(*)[3])edgevec, fnos, vcos, vnos);
- MEM_freeN(edgevec);
+ /* Add weighted face normals to vertices, and normalize vert normals. */
+ bm_mesh_verts_calc_normals(bm, (const float(*)[3])edgevec, fnos, vcos, vnos);
+ MEM_freeN(edgevec);
}
/**
* Helpers for #BM_mesh_loop_normals_update and #BM_loops_calc_normal_vcos
*/
-static void bm_mesh_edges_sharp_tag(
- BMesh *bm,
- const float (*vnos)[3], const float (*fnos)[3], float (*r_lnos)[3],
- const float split_angle, const bool do_sharp_edges_tag)
+static void bm_mesh_edges_sharp_tag(BMesh *bm,
+ const float (*vnos)[3],
+ const float (*fnos)[3],
+ float (*r_lnos)[3],
+ const float split_angle,
+ const bool do_sharp_edges_tag)
{
- BMIter eiter;
- BMEdge *e;
- int i;
-
- const bool check_angle = (split_angle < (float)M_PI);
- const float split_angle_cos = check_angle ? cosf(split_angle) : -1.0f;
-
- {
- char htype = BM_VERT | BM_LOOP;
- if (fnos) {
- htype |= BM_FACE;
- }
- BM_mesh_elem_index_ensure(bm, htype);
- }
-
- /* This first loop checks which edges are actually smooth, and pre-populate lnos with vnos (as if they were
- * all smooth).
- */
- BM_ITER_MESH_INDEX (e, &eiter, bm, BM_EDGES_OF_MESH, i) {
- BMLoop *l_a, *l_b;
-
- BM_elem_index_set(e, i); /* set_inline */
- BM_elem_flag_disable(e, BM_ELEM_TAG); /* Clear tag (means edge is sharp). */
-
- /* An edge with only two loops, might be smooth... */
- if (BM_edge_loop_pair(e, &l_a, &l_b)) {
- bool is_angle_smooth = true;
- if (check_angle) {
- const float *no_a = fnos ? fnos[BM_elem_index_get(l_a->f)] : l_a->f->no;
- const float *no_b = fnos ? fnos[BM_elem_index_get(l_b->f)] : l_b->f->no;
- is_angle_smooth = (dot_v3v3(no_a, no_b) >= split_angle_cos);
- }
-
- /* We only tag edges that are *really* smooth:
- * If the angle between both its polys' normals is below split_angle value,
- * and it is tagged as such,
- * and both its faces are smooth,
- * and both its faces have compatible (non-flipped) normals,
- * i.e. both loops on the same edge do not share the same vertex.
- */
- if (BM_elem_flag_test(e, BM_ELEM_SMOOTH) &&
- BM_elem_flag_test(l_a->f, BM_ELEM_SMOOTH) &&
- BM_elem_flag_test(l_b->f, BM_ELEM_SMOOTH) &&
- l_a->v != l_b->v)
- {
- if (is_angle_smooth) {
- const float *no;
- BM_elem_flag_enable(e, BM_ELEM_TAG);
-
- /* linked vertices might be fully smooth, copy their normals to loop ones. */
- if (r_lnos) {
- no = vnos ? vnos[BM_elem_index_get(l_a->v)] : l_a->v->no;
- copy_v3_v3(r_lnos[BM_elem_index_get(l_a)], no);
- no = vnos ? vnos[BM_elem_index_get(l_b->v)] : l_b->v->no;
- copy_v3_v3(r_lnos[BM_elem_index_get(l_b)], no);
- }
- }
- else if (do_sharp_edges_tag) {
- /* Note that we do not care about the other sharp-edge cases (sharp poly, non-manifold edge, etc.),
- * only tag edge as sharp when it is due to angle threashold. */
- BM_elem_flag_disable(e, BM_ELEM_SMOOTH);
- }
- }
- }
- }
-
- bm->elem_index_dirty &= ~BM_EDGE;
+ BMIter eiter;
+ BMEdge *e;
+ int i;
+
+ const bool check_angle = (split_angle < (float)M_PI);
+ const float split_angle_cos = check_angle ? cosf(split_angle) : -1.0f;
+
+ {
+ char htype = BM_VERT | BM_LOOP;
+ if (fnos) {
+ htype |= BM_FACE;
+ }
+ BM_mesh_elem_index_ensure(bm, htype);
+ }
+
+ /* This first loop checks which edges are actually smooth, and pre-populate lnos with vnos (as if they were
+ * all smooth).
+ */
+ BM_ITER_MESH_INDEX (e, &eiter, bm, BM_EDGES_OF_MESH, i) {
+ BMLoop *l_a, *l_b;
+
+ BM_elem_index_set(e, i); /* set_inline */
+ BM_elem_flag_disable(e, BM_ELEM_TAG); /* Clear tag (means edge is sharp). */
+
+ /* An edge with only two loops, might be smooth... */
+ if (BM_edge_loop_pair(e, &l_a, &l_b)) {
+ bool is_angle_smooth = true;
+ if (check_angle) {
+ const float *no_a = fnos ? fnos[BM_elem_index_get(l_a->f)] : l_a->f->no;
+ const float *no_b = fnos ? fnos[BM_elem_index_get(l_b->f)] : l_b->f->no;
+ is_angle_smooth = (dot_v3v3(no_a, no_b) >= split_angle_cos);
+ }
+
+ /* We only tag edges that are *really* smooth:
+ * If the angle between both its polys' normals is below split_angle value,
+ * and it is tagged as such,
+ * and both its faces are smooth,
+ * and both its faces have compatible (non-flipped) normals,
+ * i.e. both loops on the same edge do not share the same vertex.
+ */
+ if (BM_elem_flag_test(e, BM_ELEM_SMOOTH) && BM_elem_flag_test(l_a->f, BM_ELEM_SMOOTH) &&
+ BM_elem_flag_test(l_b->f, BM_ELEM_SMOOTH) && l_a->v != l_b->v) {
+ if (is_angle_smooth) {
+ const float *no;
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
+
+ /* linked vertices might be fully smooth, copy their normals to loop ones. */
+ if (r_lnos) {
+ no = vnos ? vnos[BM_elem_index_get(l_a->v)] : l_a->v->no;
+ copy_v3_v3(r_lnos[BM_elem_index_get(l_a)], no);
+ no = vnos ? vnos[BM_elem_index_get(l_b->v)] : l_b->v->no;
+ copy_v3_v3(r_lnos[BM_elem_index_get(l_b)], no);
+ }
+ }
+ else if (do_sharp_edges_tag) {
+ /* Note that we do not care about the other sharp-edge cases (sharp poly, non-manifold edge, etc.),
+ * only tag edge as sharp when it is due to angle threashold. */
+ BM_elem_flag_disable(e, BM_ELEM_SMOOTH);
+ }
+ }
+ }
+ }
+
+ bm->elem_index_dirty &= ~BM_EDGE;
}
/**
@@ -615,389 +630,396 @@ static void bm_mesh_edges_sharp_tag(
*/
bool BM_loop_check_cyclic_smooth_fan(BMLoop *l_curr)
{
- BMLoop *lfan_pivot_next = l_curr;
- BMEdge *e_next = l_curr->e;
-
- BLI_assert(!BM_elem_flag_test(lfan_pivot_next, BM_ELEM_TAG));
- BM_elem_flag_enable(lfan_pivot_next, BM_ELEM_TAG);
-
- while (true) {
- /* Much simpler than in sibling code with basic Mesh data! */
- lfan_pivot_next = BM_vert_step_fan_loop(lfan_pivot_next, &e_next);
-
- if (!lfan_pivot_next || !BM_elem_flag_test(e_next, BM_ELEM_TAG)) {
- /* Sharp loop/edge, so not a cyclic smooth fan... */
- return false;
- }
- /* Smooth loop/edge... */
- else if (BM_elem_flag_test(lfan_pivot_next, BM_ELEM_TAG)) {
- if (lfan_pivot_next == l_curr) {
- /* We walked around a whole cyclic smooth fan without finding any already-processed loop, means we can
- * use initial l_curr/l_prev edge as start for this smooth fan. */
- return true;
- }
- /* ... already checked in some previous looping, we can abort. */
- return false;
- }
- else {
- /* ... we can skip it in future, and keep checking the smooth fan. */
- BM_elem_flag_enable(lfan_pivot_next, BM_ELEM_TAG);
- }
- }
+ BMLoop *lfan_pivot_next = l_curr;
+ BMEdge *e_next = l_curr->e;
+
+ BLI_assert(!BM_elem_flag_test(lfan_pivot_next, BM_ELEM_TAG));
+ BM_elem_flag_enable(lfan_pivot_next, BM_ELEM_TAG);
+
+ while (true) {
+ /* Much simpler than in sibling code with basic Mesh data! */
+ lfan_pivot_next = BM_vert_step_fan_loop(lfan_pivot_next, &e_next);
+
+ if (!lfan_pivot_next || !BM_elem_flag_test(e_next, BM_ELEM_TAG)) {
+ /* Sharp loop/edge, so not a cyclic smooth fan... */
+ return false;
+ }
+ /* Smooth loop/edge... */
+ else if (BM_elem_flag_test(lfan_pivot_next, BM_ELEM_TAG)) {
+ if (lfan_pivot_next == l_curr) {
+ /* We walked around a whole cyclic smooth fan without finding any already-processed loop, means we can
+ * use initial l_curr/l_prev edge as start for this smooth fan. */
+ return true;
+ }
+ /* ... already checked in some previous looping, we can abort. */
+ return false;
+ }
+ else {
+ /* ... we can skip it in future, and keep checking the smooth fan. */
+ BM_elem_flag_enable(lfan_pivot_next, BM_ELEM_TAG);
+ }
+ }
}
/* BMesh version of BKE_mesh_normals_loop_split() in mesh_evaluate.c
* Will use first clnors_data array, and fallback to cd_loop_clnors_offset (use NULL and -1 to not use clnors). */
-static void bm_mesh_loops_calc_normals(
- BMesh *bm, const float (*vcos)[3], const float (*fnos)[3], float (*r_lnos)[3],
- MLoopNorSpaceArray *r_lnors_spacearr, short (*clnors_data)[2],
- const int cd_loop_clnors_offset, const bool do_rebuild)
+static void bm_mesh_loops_calc_normals(BMesh *bm,
+ const float (*vcos)[3],
+ const float (*fnos)[3],
+ float (*r_lnos)[3],
+ MLoopNorSpaceArray *r_lnors_spacearr,
+ short (*clnors_data)[2],
+ const int cd_loop_clnors_offset,
+ const bool do_rebuild)
{
- BMIter fiter;
- BMFace *f_curr;
- const bool has_clnors = clnors_data || (cd_loop_clnors_offset != -1);
-
- MLoopNorSpaceArray _lnors_spacearr = {NULL};
-
- /* Temp normal stack. */
- BLI_SMALLSTACK_DECLARE(normal, float *);
- /* Temp clnors stack. */
- BLI_SMALLSTACK_DECLARE(clnors, short *);
- /* Temp edge vectors stack, only used when computing lnor spacearr. */
- BLI_Stack *edge_vectors = NULL;
-
- {
- char htype = 0;
- if (vcos) {
- htype |= BM_VERT;
- }
- /* Face/Loop indices are set inline below. */
- BM_mesh_elem_index_ensure(bm, htype);
- }
-
- if (!r_lnors_spacearr && has_clnors) {
- /* We need to compute lnor spacearr if some custom lnor data are given to us! */
- r_lnors_spacearr = &_lnors_spacearr;
- }
- if (r_lnors_spacearr) {
- BKE_lnor_spacearr_init(r_lnors_spacearr, bm->totloop, MLNOR_SPACEARR_BMLOOP_PTR);
- edge_vectors = BLI_stack_new(sizeof(float[3]), __func__);
- }
-
- /* Clear all loops' tags (means none are to be skipped for now). */
- int index_face, index_loop = 0;
- BM_ITER_MESH_INDEX (f_curr, &fiter, bm, BM_FACES_OF_MESH, index_face) {
- BMLoop *l_curr, *l_first;
-
- BM_elem_index_set(f_curr, index_face); /* set_inline */
-
- l_curr = l_first = BM_FACE_FIRST_LOOP(f_curr);
- do {
- BM_elem_index_set(l_curr, index_loop++); /* set_inline */
- BM_elem_flag_disable(l_curr, BM_ELEM_TAG);
- } while ((l_curr = l_curr->next) != l_first);
- }
- bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP);
-
- /* We now know edges that can be smoothed (they are tagged), and edges that will be hard (they aren't).
- * Now, time to generate the normals.
- */
- BM_ITER_MESH (f_curr, &fiter, bm, BM_FACES_OF_MESH) {
- BMLoop *l_curr, *l_first;
-
- l_curr = l_first = BM_FACE_FIRST_LOOP(f_curr);
- do {
- if (do_rebuild && !BM_ELEM_API_FLAG_TEST(l_curr, BM_LNORSPACE_UPDATE) &&
- !(bm->spacearr_dirty & BM_SPACEARR_DIRTY_ALL))
- {
- continue;
- }
- /* A smooth edge, we have to check for cyclic smooth fan case.
- * If we find a new, never-processed cyclic smooth fan, we can do it now using that loop/edge as
- * 'entry point', otherwise we can skip it. */
- /* Note: In theory, we could make bm_mesh_loop_check_cyclic_smooth_fan() store mlfan_pivot's in a stack,
- * to avoid having to fan again around the vert during actual computation of clnor & clnorspace.
- * However, this would complicate the code, add more memory usage, and BM_vert_step_fan_loop()
- * is quite cheap in term of CPU cycles, so really think it's not worth it. */
- if (BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) &&
- (BM_elem_flag_test(l_curr, BM_ELEM_TAG) || !BM_loop_check_cyclic_smooth_fan(l_curr)))
- {
- }
- else if (!BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) &&
- !BM_elem_flag_test(l_curr->prev->e, BM_ELEM_TAG))
- {
- /* Simple case (both edges around that vertex are sharp in related polygon),
- * this vertex just takes its poly normal.
- */
- const int l_curr_index = BM_elem_index_get(l_curr);
- const float *no = fnos ? fnos[BM_elem_index_get(f_curr)] : f_curr->no;
- copy_v3_v3(r_lnos[l_curr_index], no);
-
- /* If needed, generate this (simple!) lnor space. */
- if (r_lnors_spacearr) {
- float vec_curr[3], vec_prev[3];
- MLoopNorSpace *lnor_space = BKE_lnor_space_create(r_lnors_spacearr);
-
- {
- const BMVert *v_pivot = l_curr->v;
- const float *co_pivot = vcos ? vcos[BM_elem_index_get(v_pivot)] : v_pivot->co;
- const BMVert *v_1 = BM_edge_other_vert(l_curr->e, v_pivot);
- const float *co_1 = vcos ? vcos[BM_elem_index_get(v_1)] : v_1->co;
- const BMVert *v_2 = BM_edge_other_vert(l_curr->prev->e, v_pivot);
- const float *co_2 = vcos ? vcos[BM_elem_index_get(v_2)] : v_2->co;
-
- sub_v3_v3v3(vec_curr, co_1, co_pivot);
- normalize_v3(vec_curr);
- sub_v3_v3v3(vec_prev, co_2, co_pivot);
- normalize_v3(vec_prev);
- }
-
- BKE_lnor_space_define(lnor_space, r_lnos[l_curr_index], vec_curr, vec_prev, NULL);
- /* We know there is only one loop in this space, no need to create a linklist in this case... */
- BKE_lnor_space_add_loop(r_lnors_spacearr, lnor_space, l_curr_index, l_curr, true);
-
- if (has_clnors) {
- short (*clnor)[2] = clnors_data ? &clnors_data[l_curr_index] :
- BM_ELEM_CD_GET_VOID_P(l_curr, cd_loop_clnors_offset);
- BKE_lnor_space_custom_data_to_normal(lnor_space, *clnor, r_lnos[l_curr_index]);
- }
- }
- }
- /* We *do not need* to check/tag loops as already computed!
- * Due to the fact a loop only links to one of its two edges, a same fan *will never be walked more than
- * once!*
- * Since we consider edges having neighbor faces with inverted (flipped) normals as sharp, we are sure that
- * no fan will be skipped, even only considering the case (sharp curr_edge, smooth prev_edge), and not the
- * alternative (smooth curr_edge, sharp prev_edge).
- * All this due/thanks to link between normals and loop ordering.
- */
- else {
- /* We have to fan around current vertex, until we find the other non-smooth edge,
- * and accumulate face normals into the vertex!
- * Note in case this vertex has only one sharp edge, this is a waste because the normal is the same as
- * the vertex normal, but I do not see any easy way to detect that (would need to count number
- * of sharp edges per vertex, I doubt the additional memory usage would be worth it, especially as
- * it should not be a common case in real-life meshes anyway).
- */
- BMVert *v_pivot = l_curr->v;
- BMEdge *e_next;
- const BMEdge *e_org = l_curr->e;
- BMLoop *lfan_pivot, *lfan_pivot_next;
- int lfan_pivot_index;
- float lnor[3] = {0.0f, 0.0f, 0.0f};
- float vec_curr[3], vec_next[3], vec_org[3];
-
- /* We validate clnors data on the fly - cheapest way to do! */
- int clnors_avg[2] = {0, 0};
- short (*clnor_ref)[2] = NULL;
- int clnors_nbr = 0;
- bool clnors_invalid = false;
-
- const float *co_pivot = vcos ? vcos[BM_elem_index_get(v_pivot)] : v_pivot->co;
-
- MLoopNorSpace *lnor_space = r_lnors_spacearr ? BKE_lnor_space_create(r_lnors_spacearr) : NULL;
-
- BLI_assert((edge_vectors == NULL) || BLI_stack_is_empty(edge_vectors));
-
- lfan_pivot = l_curr;
- lfan_pivot_index = BM_elem_index_get(lfan_pivot);
- e_next = lfan_pivot->e; /* Current edge here, actually! */
-
- /* Only need to compute previous edge's vector once, then we can just reuse old current one! */
- {
- const BMVert *v_2 = BM_edge_other_vert(e_next, v_pivot);
- const float *co_2 = vcos ? vcos[BM_elem_index_get(v_2)] : v_2->co;
-
- sub_v3_v3v3(vec_org, co_2, co_pivot);
- normalize_v3(vec_org);
- copy_v3_v3(vec_curr, vec_org);
-
- if (r_lnors_spacearr) {
- BLI_stack_push(edge_vectors, vec_org);
- }
- }
-
- while (true) {
- /* Much simpler than in sibling code with basic Mesh data! */
- lfan_pivot_next = BM_vert_step_fan_loop(lfan_pivot, &e_next);
- if (lfan_pivot_next) {
- BLI_assert(lfan_pivot_next->v == v_pivot);
- }
- else {
- /* next edge is non-manifold, we have to find it ourselves! */
- e_next = (lfan_pivot->e == e_next) ? lfan_pivot->prev->e : lfan_pivot->e;
- }
-
- /* Compute edge vector.
- * NOTE: We could pre-compute those into an array, in the first iteration, instead of computing them
- * twice (or more) here. However, time gained is not worth memory and time lost,
- * given the fact that this code should not be called that much in real-life meshes...
- */
- {
- const BMVert *v_2 = BM_edge_other_vert(e_next, v_pivot);
- const float *co_2 = vcos ? vcos[BM_elem_index_get(v_2)] : v_2->co;
-
- sub_v3_v3v3(vec_next, co_2, co_pivot);
- normalize_v3(vec_next);
- }
-
- {
- /* Code similar to accumulate_vertex_normals_poly_v3. */
- /* Calculate angle between the two poly edges incident on this vertex. */
- const BMFace *f = lfan_pivot->f;
- const float fac = saacos(dot_v3v3(vec_next, vec_curr));
- const float *no = fnos ? fnos[BM_elem_index_get(f)] : f->no;
- /* Accumulate */
- madd_v3_v3fl(lnor, no, fac);
-
- if (has_clnors) {
- /* Accumulate all clnors, if they are not all equal we have to fix that! */
- short (*clnor)[2] = clnors_data ? &clnors_data[lfan_pivot_index] :
- BM_ELEM_CD_GET_VOID_P(lfan_pivot, cd_loop_clnors_offset);
- if (clnors_nbr) {
- clnors_invalid |= ((*clnor_ref)[0] != (*clnor)[0] || (*clnor_ref)[1] != (*clnor)[1]);
- }
- else {
- clnor_ref = clnor;
- }
- clnors_avg[0] += (*clnor)[0];
- clnors_avg[1] += (*clnor)[1];
- clnors_nbr++;
- /* We store here a pointer to all custom lnors processed. */
- BLI_SMALLSTACK_PUSH(clnors, (short *)*clnor);
- }
- }
-
- /* We store here a pointer to all loop-normals processed. */
- BLI_SMALLSTACK_PUSH(normal, (float *)r_lnos[lfan_pivot_index]);
-
- if (r_lnors_spacearr) {
- /* Assign current lnor space to current 'vertex' loop. */
- BKE_lnor_space_add_loop(r_lnors_spacearr, lnor_space, lfan_pivot_index, lfan_pivot, false);
- if (e_next != e_org) {
- /* We store here all edges-normalized vectors processed. */
- BLI_stack_push(edge_vectors, vec_next);
- }
- }
-
- if (!BM_elem_flag_test(e_next, BM_ELEM_TAG) || (e_next == e_org)) {
- /* Next edge is sharp, we have finished with this fan of faces around this vert! */
- break;
- }
-
- /* Copy next edge vector to current one. */
- copy_v3_v3(vec_curr, vec_next);
- /* Next pivot loop to current one. */
- lfan_pivot = lfan_pivot_next;
- lfan_pivot_index = BM_elem_index_get(lfan_pivot);
- }
-
- {
- float lnor_len = normalize_v3(lnor);
-
- /* If we are generating lnor spacearr, we can now define the one for this fan. */
- if (r_lnors_spacearr) {
- if (UNLIKELY(lnor_len == 0.0f)) {
- /* Use vertex normal as fallback! */
- copy_v3_v3(lnor, r_lnos[lfan_pivot_index]);
- lnor_len = 1.0f;
- }
-
- BKE_lnor_space_define(lnor_space, lnor, vec_org, vec_next, edge_vectors);
-
- if (has_clnors) {
- if (clnors_invalid) {
- short *clnor;
-
- clnors_avg[0] /= clnors_nbr;
- clnors_avg[1] /= clnors_nbr;
- /* Fix/update all clnors of this fan with computed average value. */
-
- /* Prints continuously when merge custom normals, so commenting. */
- /* printf("Invalid clnors in this fan!\n"); */
-
- while ((clnor = BLI_SMALLSTACK_POP(clnors))) {
- //print_v2("org clnor", clnor);
- clnor[0] = (short)clnors_avg[0];
- clnor[1] = (short)clnors_avg[1];
- }
- //print_v2("new clnors", clnors_avg);
- }
- else {
- /* We still have to consume the stack! */
- while (BLI_SMALLSTACK_POP(clnors)) {
- /* pass */
- }
- }
- BKE_lnor_space_custom_data_to_normal(lnor_space, *clnor_ref, lnor);
- }
- }
-
- /* In case we get a zero normal here, just use vertex normal already set! */
- if (LIKELY(lnor_len != 0.0f)) {
- /* Copy back the final computed normal into all related loop-normals. */
- float *nor;
-
- while ((nor = BLI_SMALLSTACK_POP(normal))) {
- copy_v3_v3(nor, lnor);
- }
- }
- else {
- /* We still have to consume the stack! */
- while (BLI_SMALLSTACK_POP(normal)) {
- /* pass */
- }
- }
- }
-
- /* Tag related vertex as sharp, to avoid fanning around it again (in case it was a smooth one). */
- if (r_lnors_spacearr) {
- BM_elem_flag_enable(l_curr->v, BM_ELEM_TAG);
- }
- }
- } while ((l_curr = l_curr->next) != l_first);
- }
-
- if (r_lnors_spacearr) {
- BLI_stack_free(edge_vectors);
- if (r_lnors_spacearr == &_lnors_spacearr) {
- BKE_lnor_spacearr_free(r_lnors_spacearr);
- }
- }
+ BMIter fiter;
+ BMFace *f_curr;
+ const bool has_clnors = clnors_data || (cd_loop_clnors_offset != -1);
+
+ MLoopNorSpaceArray _lnors_spacearr = {NULL};
+
+ /* Temp normal stack. */
+ BLI_SMALLSTACK_DECLARE(normal, float *);
+ /* Temp clnors stack. */
+ BLI_SMALLSTACK_DECLARE(clnors, short *);
+ /* Temp edge vectors stack, only used when computing lnor spacearr. */
+ BLI_Stack *edge_vectors = NULL;
+
+ {
+ char htype = 0;
+ if (vcos) {
+ htype |= BM_VERT;
+ }
+ /* Face/Loop indices are set inline below. */
+ BM_mesh_elem_index_ensure(bm, htype);
+ }
+
+ if (!r_lnors_spacearr && has_clnors) {
+ /* We need to compute lnor spacearr if some custom lnor data are given to us! */
+ r_lnors_spacearr = &_lnors_spacearr;
+ }
+ if (r_lnors_spacearr) {
+ BKE_lnor_spacearr_init(r_lnors_spacearr, bm->totloop, MLNOR_SPACEARR_BMLOOP_PTR);
+ edge_vectors = BLI_stack_new(sizeof(float[3]), __func__);
+ }
+
+ /* Clear all loops' tags (means none are to be skipped for now). */
+ int index_face, index_loop = 0;
+ BM_ITER_MESH_INDEX (f_curr, &fiter, bm, BM_FACES_OF_MESH, index_face) {
+ BMLoop *l_curr, *l_first;
+
+ BM_elem_index_set(f_curr, index_face); /* set_inline */
+
+ l_curr = l_first = BM_FACE_FIRST_LOOP(f_curr);
+ do {
+ BM_elem_index_set(l_curr, index_loop++); /* set_inline */
+ BM_elem_flag_disable(l_curr, BM_ELEM_TAG);
+ } while ((l_curr = l_curr->next) != l_first);
+ }
+ bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP);
+
+ /* We now know edges that can be smoothed (they are tagged), and edges that will be hard (they aren't).
+ * Now, time to generate the normals.
+ */
+ BM_ITER_MESH (f_curr, &fiter, bm, BM_FACES_OF_MESH) {
+ BMLoop *l_curr, *l_first;
+
+ l_curr = l_first = BM_FACE_FIRST_LOOP(f_curr);
+ do {
+ if (do_rebuild && !BM_ELEM_API_FLAG_TEST(l_curr, BM_LNORSPACE_UPDATE) &&
+ !(bm->spacearr_dirty & BM_SPACEARR_DIRTY_ALL)) {
+ continue;
+ }
+ /* A smooth edge, we have to check for cyclic smooth fan case.
+ * If we find a new, never-processed cyclic smooth fan, we can do it now using that loop/edge as
+ * 'entry point', otherwise we can skip it. */
+ /* Note: In theory, we could make bm_mesh_loop_check_cyclic_smooth_fan() store mlfan_pivot's in a stack,
+ * to avoid having to fan again around the vert during actual computation of clnor & clnorspace.
+ * However, this would complicate the code, add more memory usage, and BM_vert_step_fan_loop()
+ * is quite cheap in term of CPU cycles, so really think it's not worth it. */
+ if (BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) &&
+ (BM_elem_flag_test(l_curr, BM_ELEM_TAG) || !BM_loop_check_cyclic_smooth_fan(l_curr))) {
+ }
+ else if (!BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) &&
+ !BM_elem_flag_test(l_curr->prev->e, BM_ELEM_TAG)) {
+ /* Simple case (both edges around that vertex are sharp in related polygon),
+ * this vertex just takes its poly normal.
+ */
+ const int l_curr_index = BM_elem_index_get(l_curr);
+ const float *no = fnos ? fnos[BM_elem_index_get(f_curr)] : f_curr->no;
+ copy_v3_v3(r_lnos[l_curr_index], no);
+
+ /* If needed, generate this (simple!) lnor space. */
+ if (r_lnors_spacearr) {
+ float vec_curr[3], vec_prev[3];
+ MLoopNorSpace *lnor_space = BKE_lnor_space_create(r_lnors_spacearr);
+
+ {
+ const BMVert *v_pivot = l_curr->v;
+ const float *co_pivot = vcos ? vcos[BM_elem_index_get(v_pivot)] : v_pivot->co;
+ const BMVert *v_1 = BM_edge_other_vert(l_curr->e, v_pivot);
+ const float *co_1 = vcos ? vcos[BM_elem_index_get(v_1)] : v_1->co;
+ const BMVert *v_2 = BM_edge_other_vert(l_curr->prev->e, v_pivot);
+ const float *co_2 = vcos ? vcos[BM_elem_index_get(v_2)] : v_2->co;
+
+ sub_v3_v3v3(vec_curr, co_1, co_pivot);
+ normalize_v3(vec_curr);
+ sub_v3_v3v3(vec_prev, co_2, co_pivot);
+ normalize_v3(vec_prev);
+ }
+
+ BKE_lnor_space_define(lnor_space, r_lnos[l_curr_index], vec_curr, vec_prev, NULL);
+ /* We know there is only one loop in this space, no need to create a linklist in this case... */
+ BKE_lnor_space_add_loop(r_lnors_spacearr, lnor_space, l_curr_index, l_curr, true);
+
+ if (has_clnors) {
+ short(*clnor)[2] = clnors_data ? &clnors_data[l_curr_index] :
+ BM_ELEM_CD_GET_VOID_P(l_curr, cd_loop_clnors_offset);
+ BKE_lnor_space_custom_data_to_normal(lnor_space, *clnor, r_lnos[l_curr_index]);
+ }
+ }
+ }
+ /* We *do not need* to check/tag loops as already computed!
+ * Due to the fact a loop only links to one of its two edges, a same fan *will never be walked more than
+ * once!*
+ * Since we consider edges having neighbor faces with inverted (flipped) normals as sharp, we are sure that
+ * no fan will be skipped, even only considering the case (sharp curr_edge, smooth prev_edge), and not the
+ * alternative (smooth curr_edge, sharp prev_edge).
+ * All this due/thanks to link between normals and loop ordering.
+ */
+ else {
+ /* We have to fan around current vertex, until we find the other non-smooth edge,
+ * and accumulate face normals into the vertex!
+ * Note in case this vertex has only one sharp edge, this is a waste because the normal is the same as
+ * the vertex normal, but I do not see any easy way to detect that (would need to count number
+ * of sharp edges per vertex, I doubt the additional memory usage would be worth it, especially as
+ * it should not be a common case in real-life meshes anyway).
+ */
+ BMVert *v_pivot = l_curr->v;
+ BMEdge *e_next;
+ const BMEdge *e_org = l_curr->e;
+ BMLoop *lfan_pivot, *lfan_pivot_next;
+ int lfan_pivot_index;
+ float lnor[3] = {0.0f, 0.0f, 0.0f};
+ float vec_curr[3], vec_next[3], vec_org[3];
+
+ /* We validate clnors data on the fly - cheapest way to do! */
+ int clnors_avg[2] = {0, 0};
+ short(*clnor_ref)[2] = NULL;
+ int clnors_nbr = 0;
+ bool clnors_invalid = false;
+
+ const float *co_pivot = vcos ? vcos[BM_elem_index_get(v_pivot)] : v_pivot->co;
+
+ MLoopNorSpace *lnor_space = r_lnors_spacearr ? BKE_lnor_space_create(r_lnors_spacearr) :
+ NULL;
+
+ BLI_assert((edge_vectors == NULL) || BLI_stack_is_empty(edge_vectors));
+
+ lfan_pivot = l_curr;
+ lfan_pivot_index = BM_elem_index_get(lfan_pivot);
+ e_next = lfan_pivot->e; /* Current edge here, actually! */
+
+ /* Only need to compute previous edge's vector once, then we can just reuse old current one! */
+ {
+ const BMVert *v_2 = BM_edge_other_vert(e_next, v_pivot);
+ const float *co_2 = vcos ? vcos[BM_elem_index_get(v_2)] : v_2->co;
+
+ sub_v3_v3v3(vec_org, co_2, co_pivot);
+ normalize_v3(vec_org);
+ copy_v3_v3(vec_curr, vec_org);
+
+ if (r_lnors_spacearr) {
+ BLI_stack_push(edge_vectors, vec_org);
+ }
+ }
+
+ while (true) {
+ /* Much simpler than in sibling code with basic Mesh data! */
+ lfan_pivot_next = BM_vert_step_fan_loop(lfan_pivot, &e_next);
+ if (lfan_pivot_next) {
+ BLI_assert(lfan_pivot_next->v == v_pivot);
+ }
+ else {
+ /* next edge is non-manifold, we have to find it ourselves! */
+ e_next = (lfan_pivot->e == e_next) ? lfan_pivot->prev->e : lfan_pivot->e;
+ }
+
+ /* Compute edge vector.
+ * NOTE: We could pre-compute those into an array, in the first iteration, instead of computing them
+ * twice (or more) here. However, time gained is not worth memory and time lost,
+ * given the fact that this code should not be called that much in real-life meshes...
+ */
+ {
+ const BMVert *v_2 = BM_edge_other_vert(e_next, v_pivot);
+ const float *co_2 = vcos ? vcos[BM_elem_index_get(v_2)] : v_2->co;
+
+ sub_v3_v3v3(vec_next, co_2, co_pivot);
+ normalize_v3(vec_next);
+ }
+
+ {
+ /* Code similar to accumulate_vertex_normals_poly_v3. */
+ /* Calculate angle between the two poly edges incident on this vertex. */
+ const BMFace *f = lfan_pivot->f;
+ const float fac = saacos(dot_v3v3(vec_next, vec_curr));
+ const float *no = fnos ? fnos[BM_elem_index_get(f)] : f->no;
+ /* Accumulate */
+ madd_v3_v3fl(lnor, no, fac);
+
+ if (has_clnors) {
+ /* Accumulate all clnors, if they are not all equal we have to fix that! */
+ short(*clnor)[2] = clnors_data ?
+ &clnors_data[lfan_pivot_index] :
+ BM_ELEM_CD_GET_VOID_P(lfan_pivot, cd_loop_clnors_offset);
+ if (clnors_nbr) {
+ clnors_invalid |= ((*clnor_ref)[0] != (*clnor)[0] ||
+ (*clnor_ref)[1] != (*clnor)[1]);
+ }
+ else {
+ clnor_ref = clnor;
+ }
+ clnors_avg[0] += (*clnor)[0];
+ clnors_avg[1] += (*clnor)[1];
+ clnors_nbr++;
+ /* We store here a pointer to all custom lnors processed. */
+ BLI_SMALLSTACK_PUSH(clnors, (short *)*clnor);
+ }
+ }
+
+ /* We store here a pointer to all loop-normals processed. */
+ BLI_SMALLSTACK_PUSH(normal, (float *)r_lnos[lfan_pivot_index]);
+
+ if (r_lnors_spacearr) {
+ /* Assign current lnor space to current 'vertex' loop. */
+ BKE_lnor_space_add_loop(
+ r_lnors_spacearr, lnor_space, lfan_pivot_index, lfan_pivot, false);
+ if (e_next != e_org) {
+ /* We store here all edges-normalized vectors processed. */
+ BLI_stack_push(edge_vectors, vec_next);
+ }
+ }
+
+ if (!BM_elem_flag_test(e_next, BM_ELEM_TAG) || (e_next == e_org)) {
+ /* Next edge is sharp, we have finished with this fan of faces around this vert! */
+ break;
+ }
+
+ /* Copy next edge vector to current one. */
+ copy_v3_v3(vec_curr, vec_next);
+ /* Next pivot loop to current one. */
+ lfan_pivot = lfan_pivot_next;
+ lfan_pivot_index = BM_elem_index_get(lfan_pivot);
+ }
+
+ {
+ float lnor_len = normalize_v3(lnor);
+
+ /* If we are generating lnor spacearr, we can now define the one for this fan. */
+ if (r_lnors_spacearr) {
+ if (UNLIKELY(lnor_len == 0.0f)) {
+ /* Use vertex normal as fallback! */
+ copy_v3_v3(lnor, r_lnos[lfan_pivot_index]);
+ lnor_len = 1.0f;
+ }
+
+ BKE_lnor_space_define(lnor_space, lnor, vec_org, vec_next, edge_vectors);
+
+ if (has_clnors) {
+ if (clnors_invalid) {
+ short *clnor;
+
+ clnors_avg[0] /= clnors_nbr;
+ clnors_avg[1] /= clnors_nbr;
+ /* Fix/update all clnors of this fan with computed average value. */
+
+ /* Prints continuously when merge custom normals, so commenting. */
+ /* printf("Invalid clnors in this fan!\n"); */
+
+ while ((clnor = BLI_SMALLSTACK_POP(clnors))) {
+ //print_v2("org clnor", clnor);
+ clnor[0] = (short)clnors_avg[0];
+ clnor[1] = (short)clnors_avg[1];
+ }
+ //print_v2("new clnors", clnors_avg);
+ }
+ else {
+ /* We still have to consume the stack! */
+ while (BLI_SMALLSTACK_POP(clnors)) {
+ /* pass */
+ }
+ }
+ BKE_lnor_space_custom_data_to_normal(lnor_space, *clnor_ref, lnor);
+ }
+ }
+
+ /* In case we get a zero normal here, just use vertex normal already set! */
+ if (LIKELY(lnor_len != 0.0f)) {
+ /* Copy back the final computed normal into all related loop-normals. */
+ float *nor;
+
+ while ((nor = BLI_SMALLSTACK_POP(normal))) {
+ copy_v3_v3(nor, lnor);
+ }
+ }
+ else {
+ /* We still have to consume the stack! */
+ while (BLI_SMALLSTACK_POP(normal)) {
+ /* pass */
+ }
+ }
+ }
+
+ /* Tag related vertex as sharp, to avoid fanning around it again (in case it was a smooth one). */
+ if (r_lnors_spacearr) {
+ BM_elem_flag_enable(l_curr->v, BM_ELEM_TAG);
+ }
+ }
+ } while ((l_curr = l_curr->next) != l_first);
+ }
+
+ if (r_lnors_spacearr) {
+ BLI_stack_free(edge_vectors);
+ if (r_lnors_spacearr == &_lnors_spacearr) {
+ BKE_lnor_spacearr_free(r_lnors_spacearr);
+ }
+ }
}
-static void bm_mesh_loops_calc_normals_no_autosmooth(
- BMesh *bm, const float (*vnos)[3], const float (*fnos)[3], float (*r_lnos)[3])
+static void bm_mesh_loops_calc_normals_no_autosmooth(BMesh *bm,
+ const float (*vnos)[3],
+ const float (*fnos)[3],
+ float (*r_lnos)[3])
{
- BMIter fiter;
- BMFace *f_curr;
-
- {
- char htype = BM_LOOP;
- if (vnos) {
- htype |= BM_VERT;
- }
- if (fnos) {
- htype |= BM_FACE;
- }
- BM_mesh_elem_index_ensure(bm, htype);
- }
-
- BM_ITER_MESH (f_curr, &fiter, bm, BM_FACES_OF_MESH) {
- BMLoop *l_curr, *l_first;
- const bool is_face_flat = !BM_elem_flag_test(f_curr, BM_ELEM_SMOOTH);
-
- l_curr = l_first = BM_FACE_FIRST_LOOP(f_curr);
- do {
- const float *no = is_face_flat ? (fnos ? fnos[BM_elem_index_get(f_curr)] : f_curr->no) :
- (vnos ? vnos[BM_elem_index_get(l_curr->v)] : l_curr->v->no);
- copy_v3_v3(r_lnos[BM_elem_index_get(l_curr)], no);
-
- } while ((l_curr = l_curr->next) != l_first);
- }
+ BMIter fiter;
+ BMFace *f_curr;
+
+ {
+ char htype = BM_LOOP;
+ if (vnos) {
+ htype |= BM_VERT;
+ }
+ if (fnos) {
+ htype |= BM_FACE;
+ }
+ BM_mesh_elem_index_ensure(bm, htype);
+ }
+
+ BM_ITER_MESH (f_curr, &fiter, bm, BM_FACES_OF_MESH) {
+ BMLoop *l_curr, *l_first;
+ const bool is_face_flat = !BM_elem_flag_test(f_curr, BM_ELEM_SMOOTH);
+
+ l_curr = l_first = BM_FACE_FIRST_LOOP(f_curr);
+ do {
+ const float *no = is_face_flat ? (fnos ? fnos[BM_elem_index_get(f_curr)] : f_curr->no) :
+ (vnos ? vnos[BM_elem_index_get(l_curr->v)] : l_curr->v->no);
+ copy_v3_v3(r_lnos[BM_elem_index_get(l_curr)], no);
+
+ } while ((l_curr = l_curr->next) != l_first);
+ }
}
-#if 0 /* Unused currently */
+#if 0 /* Unused currently */
/**
* \brief BMesh Compute Loop Normals
*
@@ -1008,20 +1030,20 @@ void BM_mesh_loop_normals_update(
BMesh *bm, const bool use_split_normals, const float split_angle, float (*r_lnos)[3],
MLoopNorSpaceArray *r_lnors_spacearr, short (*clnors_data)[2], const int cd_loop_clnors_offset)
{
- const bool has_clnors = clnors_data || (cd_loop_clnors_offset != -1);
-
- if (use_split_normals) {
- /* Tag smooth edges and set lnos from vnos when they might be completely smooth...
- * When using custom loop normals, disable the angle feature! */
- bm_mesh_edges_sharp_tag(bm, NULL, NULL, has_clnors ? (float)M_PI : split_angle, r_lnos);
-
- /* Finish computing lnos by accumulating face normals in each fan of faces defined by sharp edges. */
- bm_mesh_loops_calc_normals(bm, NULL, NULL, r_lnos, r_lnors_spacearr, clnors_data, cd_loop_clnors_offset);
- }
- else {
- BLI_assert(!r_lnors_spacearr);
- bm_mesh_loops_calc_normals_no_autosmooth(bm, NULL, NULL, r_lnos);
- }
+ const bool has_clnors = clnors_data || (cd_loop_clnors_offset != -1);
+
+ if (use_split_normals) {
+ /* Tag smooth edges and set lnos from vnos when they might be completely smooth...
+ * When using custom loop normals, disable the angle feature! */
+ bm_mesh_edges_sharp_tag(bm, NULL, NULL, has_clnors ? (float)M_PI : split_angle, r_lnos);
+
+ /* Finish computing lnos by accumulating face normals in each fan of faces defined by sharp edges. */
+ bm_mesh_loops_calc_normals(bm, NULL, NULL, r_lnos, r_lnors_spacearr, clnors_data, cd_loop_clnors_offset);
+ }
+ else {
+ BLI_assert(!r_lnors_spacearr);
+ bm_mesh_loops_calc_normals_no_autosmooth(bm, NULL, NULL, r_lnos);
+ }
}
#endif
@@ -1031,27 +1053,33 @@ void BM_mesh_loop_normals_update(
* Compute split normals, i.e. vertex normals associated with each poly (hence 'loop normals').
* Useful to materialize sharp edges (or non-smooth faces) without actually modifying the geometry (splitting edges).
*/
-void BM_loops_calc_normal_vcos(
- BMesh *bm, const float (*vcos)[3], const float (*vnos)[3], const float (*fnos)[3],
- const bool use_split_normals, const float split_angle, float (*r_lnos)[3],
- MLoopNorSpaceArray *r_lnors_spacearr, short (*clnors_data)[2],
- const int cd_loop_clnors_offset, const bool do_rebuild)
+void BM_loops_calc_normal_vcos(BMesh *bm,
+ const float (*vcos)[3],
+ const float (*vnos)[3],
+ const float (*fnos)[3],
+ const bool use_split_normals,
+ const float split_angle,
+ float (*r_lnos)[3],
+ MLoopNorSpaceArray *r_lnors_spacearr,
+ short (*clnors_data)[2],
+ const int cd_loop_clnors_offset,
+ const bool do_rebuild)
{
- const bool has_clnors = clnors_data || (cd_loop_clnors_offset != -1);
-
- if (use_split_normals) {
- /* Tag smooth edges and set lnos from vnos when they might be completely smooth...
- * When using custom loop normals, disable the angle feature! */
- bm_mesh_edges_sharp_tag(bm, vnos, fnos, r_lnos, has_clnors ? (float)M_PI : split_angle, false);
-
- /* Finish computing lnos by accumulating face normals in each fan of faces defined by sharp edges. */
- bm_mesh_loops_calc_normals(
- bm, vcos, fnos, r_lnos, r_lnors_spacearr, clnors_data, cd_loop_clnors_offset, do_rebuild);
- }
- else {
- BLI_assert(!r_lnors_spacearr);
- bm_mesh_loops_calc_normals_no_autosmooth(bm, vnos, fnos, r_lnos);
- }
+ const bool has_clnors = clnors_data || (cd_loop_clnors_offset != -1);
+
+ if (use_split_normals) {
+ /* Tag smooth edges and set lnos from vnos when they might be completely smooth...
+ * When using custom loop normals, disable the angle feature! */
+ bm_mesh_edges_sharp_tag(bm, vnos, fnos, r_lnos, has_clnors ? (float)M_PI : split_angle, false);
+
+ /* Finish computing lnos by accumulating face normals in each fan of faces defined by sharp edges. */
+ bm_mesh_loops_calc_normals(
+ bm, vcos, fnos, r_lnos, r_lnors_spacearr, clnors_data, cd_loop_clnors_offset, do_rebuild);
+ }
+ else {
+ BLI_assert(!r_lnors_spacearr);
+ bm_mesh_loops_calc_normals_no_autosmooth(bm, vnos, fnos, r_lnos);
+ }
}
/** Define sharp edges as needed to mimic 'autosmooth' from angle threshold.
@@ -1060,215 +1088,232 @@ void BM_loops_calc_normal_vcos(
*/
void BM_edges_sharp_from_angle_set(BMesh *bm, const float split_angle)
{
- if (split_angle >= (float)M_PI) {
- /* Nothing to do! */
- return;
- }
+ if (split_angle >= (float)M_PI) {
+ /* Nothing to do! */
+ return;
+ }
- bm_mesh_edges_sharp_tag(bm, NULL, NULL, NULL, split_angle, true);
+ bm_mesh_edges_sharp_tag(bm, NULL, NULL, NULL, split_angle, true);
}
-void BM_lnorspacearr_store(BMesh *bm, float(*r_lnors)[3])
+void BM_lnorspacearr_store(BMesh *bm, float (*r_lnors)[3])
{
- BLI_assert(bm->lnor_spacearr != NULL);
-
- if (!CustomData_has_layer(&bm->ldata, CD_CUSTOMLOOPNORMAL)) {
- BM_data_layer_add(bm, &bm->ldata, CD_CUSTOMLOOPNORMAL);
- }
-
- int cd_loop_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
-
- BM_loops_calc_normal_vcos(
- bm, NULL, NULL, NULL, true, M_PI, r_lnors, bm->lnor_spacearr, NULL, cd_loop_clnors_offset, false);
- bm->spacearr_dirty &= ~(BM_SPACEARR_DIRTY | BM_SPACEARR_DIRTY_ALL);
+ BLI_assert(bm->lnor_spacearr != NULL);
+
+ if (!CustomData_has_layer(&bm->ldata, CD_CUSTOMLOOPNORMAL)) {
+ BM_data_layer_add(bm, &bm->ldata, CD_CUSTOMLOOPNORMAL);
+ }
+
+ int cd_loop_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
+
+ BM_loops_calc_normal_vcos(bm,
+ NULL,
+ NULL,
+ NULL,
+ true,
+ M_PI,
+ r_lnors,
+ bm->lnor_spacearr,
+ NULL,
+ cd_loop_clnors_offset,
+ false);
+ bm->spacearr_dirty &= ~(BM_SPACEARR_DIRTY | BM_SPACEARR_DIRTY_ALL);
}
#define CLEAR_SPACEARRAY_THRESHOLD(x) ((x) / 2)
void BM_lnorspace_invalidate(BMesh *bm, const bool do_invalidate_all)
{
- if (bm->spacearr_dirty & BM_SPACEARR_DIRTY_ALL) {
- return;
- }
- if (do_invalidate_all || bm->totvertsel > CLEAR_SPACEARRAY_THRESHOLD(bm->totvert)) {
- bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL;
- return;
- }
- if (bm->lnor_spacearr == NULL) {
- bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL;
- return;
- }
-
- BMVert *v;
- BMLoop *l;
- BMIter viter, liter;
- /* Note: we could use temp tag of BMItem for that, but probably better not use it in such a low-level func?
- * --mont29 */
- BLI_bitmap *done_verts = BLI_BITMAP_NEW(bm->totvert, __func__);
-
- BM_mesh_elem_index_ensure(bm, BM_VERT);
-
- /* When we affect a given vertex, we may affect following smooth fans:
- * - all smooth fans of said vertex;
- * - all smooth fans of all immediate loop-neighbors vertices;
- * This can be simplified as 'all loops of selected vertices and their immediate neighbors'
- * need to be tagged for update.
- */
- BM_ITER_MESH(v, &viter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
- BM_ITER_ELEM(l, &liter, v, BM_LOOPS_OF_VERT) {
- BM_ELEM_API_FLAG_ENABLE(l, BM_LNORSPACE_UPDATE);
-
- /* Note that we only handle unselected neighbor vertices here, main loop will take care of
- * selected ones. */
- if ((!BM_elem_flag_test(l->prev->v, BM_ELEM_SELECT)) &&
- !BLI_BITMAP_TEST(done_verts, BM_elem_index_get(l->prev->v)))
- {
-
- BMLoop *l_prev;
- BMIter liter_prev;
- BM_ITER_ELEM(l_prev, &liter_prev, l->prev->v, BM_LOOPS_OF_VERT) {
- BM_ELEM_API_FLAG_ENABLE(l_prev, BM_LNORSPACE_UPDATE);
- }
- BLI_BITMAP_ENABLE(done_verts, BM_elem_index_get(l_prev->v));
- }
-
- if ((!BM_elem_flag_test(l->next->v, BM_ELEM_SELECT)) &&
- !BLI_BITMAP_TEST(done_verts, BM_elem_index_get(l->next->v)))
- {
-
- BMLoop *l_next;
- BMIter liter_next;
- BM_ITER_ELEM(l_next, &liter_next, l->next->v, BM_LOOPS_OF_VERT) {
- BM_ELEM_API_FLAG_ENABLE(l_next, BM_LNORSPACE_UPDATE);
- }
- BLI_BITMAP_ENABLE(done_verts, BM_elem_index_get(l_next->v));
- }
- }
-
- BLI_BITMAP_ENABLE(done_verts, BM_elem_index_get(v));
- }
- }
-
- MEM_freeN(done_verts);
- bm->spacearr_dirty |= BM_SPACEARR_DIRTY;
+ if (bm->spacearr_dirty & BM_SPACEARR_DIRTY_ALL) {
+ return;
+ }
+ if (do_invalidate_all || bm->totvertsel > CLEAR_SPACEARRAY_THRESHOLD(bm->totvert)) {
+ bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL;
+ return;
+ }
+ if (bm->lnor_spacearr == NULL) {
+ bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL;
+ return;
+ }
+
+ BMVert *v;
+ BMLoop *l;
+ BMIter viter, liter;
+ /* Note: we could use temp tag of BMItem for that, but probably better not use it in such a low-level func?
+ * --mont29 */
+ BLI_bitmap *done_verts = BLI_BITMAP_NEW(bm->totvert, __func__);
+
+ BM_mesh_elem_index_ensure(bm, BM_VERT);
+
+ /* When we affect a given vertex, we may affect following smooth fans:
+ * - all smooth fans of said vertex;
+ * - all smooth fans of all immediate loop-neighbors vertices;
+ * This can be simplified as 'all loops of selected vertices and their immediate neighbors'
+ * need to be tagged for update.
+ */
+ BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+ BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
+ BM_ELEM_API_FLAG_ENABLE(l, BM_LNORSPACE_UPDATE);
+
+ /* Note that we only handle unselected neighbor vertices here, main loop will take care of
+ * selected ones. */
+ if ((!BM_elem_flag_test(l->prev->v, BM_ELEM_SELECT)) &&
+ !BLI_BITMAP_TEST(done_verts, BM_elem_index_get(l->prev->v))) {
+
+ BMLoop *l_prev;
+ BMIter liter_prev;
+ BM_ITER_ELEM (l_prev, &liter_prev, l->prev->v, BM_LOOPS_OF_VERT) {
+ BM_ELEM_API_FLAG_ENABLE(l_prev, BM_LNORSPACE_UPDATE);
+ }
+ BLI_BITMAP_ENABLE(done_verts, BM_elem_index_get(l_prev->v));
+ }
+
+ if ((!BM_elem_flag_test(l->next->v, BM_ELEM_SELECT)) &&
+ !BLI_BITMAP_TEST(done_verts, BM_elem_index_get(l->next->v))) {
+
+ BMLoop *l_next;
+ BMIter liter_next;
+ BM_ITER_ELEM (l_next, &liter_next, l->next->v, BM_LOOPS_OF_VERT) {
+ BM_ELEM_API_FLAG_ENABLE(l_next, BM_LNORSPACE_UPDATE);
+ }
+ BLI_BITMAP_ENABLE(done_verts, BM_elem_index_get(l_next->v));
+ }
+ }
+
+ BLI_BITMAP_ENABLE(done_verts, BM_elem_index_get(v));
+ }
+ }
+
+ MEM_freeN(done_verts);
+ bm->spacearr_dirty |= BM_SPACEARR_DIRTY;
}
void BM_lnorspace_rebuild(BMesh *bm, bool preserve_clnor)
{
- BLI_assert(bm->lnor_spacearr != NULL);
-
- if (!(bm->spacearr_dirty & (BM_SPACEARR_DIRTY | BM_SPACEARR_DIRTY_ALL))) {
- return;
- }
- BMFace *f;
- BMLoop *l;
- BMIter fiter, liter;
-
- float(*r_lnors)[3] = MEM_callocN(sizeof(*r_lnors) * bm->totloop, __func__);
- float(*oldnors)[3] = preserve_clnor ? MEM_mallocN(sizeof(*oldnors) * bm->totloop, __func__) : NULL;
-
- int cd_loop_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
-
- BM_mesh_elem_index_ensure(bm, BM_LOOP);
-
- if (preserve_clnor) {
- BLI_assert(bm->lnor_spacearr->lspacearr != NULL);
-
- BM_ITER_MESH(f, &fiter, bm, BM_FACES_OF_MESH) {
- BM_ITER_ELEM(l, &liter, f, BM_LOOPS_OF_FACE) {
- if (BM_ELEM_API_FLAG_TEST(l, BM_LNORSPACE_UPDATE) || bm->spacearr_dirty & BM_SPACEARR_DIRTY_ALL) {
- short(*clnor)[2] = BM_ELEM_CD_GET_VOID_P(l, cd_loop_clnors_offset);
- int l_index = BM_elem_index_get(l);
-
- BKE_lnor_space_custom_data_to_normal(
- bm->lnor_spacearr->lspacearr[l_index], *clnor,
- oldnors[l_index]);
- }
- }
- }
- }
-
- if (bm->spacearr_dirty & BM_SPACEARR_DIRTY_ALL) {
- BKE_lnor_spacearr_clear(bm->lnor_spacearr);
- }
- BM_loops_calc_normal_vcos(
- bm, NULL, NULL, NULL, true, M_PI, r_lnors, bm->lnor_spacearr, NULL, cd_loop_clnors_offset, true);
- MEM_freeN(r_lnors);
-
- BM_ITER_MESH(f, &fiter, bm, BM_FACES_OF_MESH) {
- BM_ITER_ELEM(l, &liter, f, BM_LOOPS_OF_FACE) {
- if (BM_ELEM_API_FLAG_TEST(l, BM_LNORSPACE_UPDATE) || bm->spacearr_dirty & BM_SPACEARR_DIRTY_ALL) {
- if (preserve_clnor) {
- short(*clnor)[2] = BM_ELEM_CD_GET_VOID_P(l, cd_loop_clnors_offset);
- int l_index = BM_elem_index_get(l);
- BKE_lnor_space_custom_normal_to_data(
- bm->lnor_spacearr->lspacearr[l_index], oldnors[l_index],
- *clnor);
- }
- BM_ELEM_API_FLAG_DISABLE(l, BM_LNORSPACE_UPDATE);
- }
- }
- }
-
- MEM_SAFE_FREE(oldnors);
- bm->spacearr_dirty &= ~(BM_SPACEARR_DIRTY | BM_SPACEARR_DIRTY_ALL);
+ BLI_assert(bm->lnor_spacearr != NULL);
+
+ if (!(bm->spacearr_dirty & (BM_SPACEARR_DIRTY | BM_SPACEARR_DIRTY_ALL))) {
+ return;
+ }
+ BMFace *f;
+ BMLoop *l;
+ BMIter fiter, liter;
+
+ float(*r_lnors)[3] = MEM_callocN(sizeof(*r_lnors) * bm->totloop, __func__);
+ float(*oldnors)[3] = preserve_clnor ? MEM_mallocN(sizeof(*oldnors) * bm->totloop, __func__) :
+ NULL;
+
+ int cd_loop_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
+
+ BM_mesh_elem_index_ensure(bm, BM_LOOP);
+
+ if (preserve_clnor) {
+ BLI_assert(bm->lnor_spacearr->lspacearr != NULL);
+
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ if (BM_ELEM_API_FLAG_TEST(l, BM_LNORSPACE_UPDATE) ||
+ bm->spacearr_dirty & BM_SPACEARR_DIRTY_ALL) {
+ short(*clnor)[2] = BM_ELEM_CD_GET_VOID_P(l, cd_loop_clnors_offset);
+ int l_index = BM_elem_index_get(l);
+
+ BKE_lnor_space_custom_data_to_normal(
+ bm->lnor_spacearr->lspacearr[l_index], *clnor, oldnors[l_index]);
+ }
+ }
+ }
+ }
+
+ if (bm->spacearr_dirty & BM_SPACEARR_DIRTY_ALL) {
+ BKE_lnor_spacearr_clear(bm->lnor_spacearr);
+ }
+ BM_loops_calc_normal_vcos(bm,
+ NULL,
+ NULL,
+ NULL,
+ true,
+ M_PI,
+ r_lnors,
+ bm->lnor_spacearr,
+ NULL,
+ cd_loop_clnors_offset,
+ true);
+ MEM_freeN(r_lnors);
+
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ if (BM_ELEM_API_FLAG_TEST(l, BM_LNORSPACE_UPDATE) ||
+ bm->spacearr_dirty & BM_SPACEARR_DIRTY_ALL) {
+ if (preserve_clnor) {
+ short(*clnor)[2] = BM_ELEM_CD_GET_VOID_P(l, cd_loop_clnors_offset);
+ int l_index = BM_elem_index_get(l);
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[l_index], oldnors[l_index], *clnor);
+ }
+ BM_ELEM_API_FLAG_DISABLE(l, BM_LNORSPACE_UPDATE);
+ }
+ }
+ }
+
+ MEM_SAFE_FREE(oldnors);
+ bm->spacearr_dirty &= ~(BM_SPACEARR_DIRTY | BM_SPACEARR_DIRTY_ALL);
#ifndef NDEBUG
- BM_lnorspace_err(bm);
+ BM_lnorspace_err(bm);
#endif
}
void BM_lnorspace_update(BMesh *bm)
{
- if (bm->lnor_spacearr == NULL) {
- bm->lnor_spacearr = MEM_callocN(sizeof(*bm->lnor_spacearr), __func__);
- }
- if (bm->lnor_spacearr->lspacearr == NULL) {
- float(*lnors)[3] = MEM_callocN(sizeof(*lnors) * bm->totloop, __func__);
-
- BM_lnorspacearr_store(bm, lnors);
-
- MEM_freeN(lnors);
- }
- else if (bm->spacearr_dirty & (BM_SPACEARR_DIRTY | BM_SPACEARR_DIRTY_ALL)) {
- BM_lnorspace_rebuild(bm, false);
- }
+ if (bm->lnor_spacearr == NULL) {
+ bm->lnor_spacearr = MEM_callocN(sizeof(*bm->lnor_spacearr), __func__);
+ }
+ if (bm->lnor_spacearr->lspacearr == NULL) {
+ float(*lnors)[3] = MEM_callocN(sizeof(*lnors) * bm->totloop, __func__);
+
+ BM_lnorspacearr_store(bm, lnors);
+
+ MEM_freeN(lnors);
+ }
+ else if (bm->spacearr_dirty & (BM_SPACEARR_DIRTY | BM_SPACEARR_DIRTY_ALL)) {
+ BM_lnorspace_rebuild(bm, false);
+ }
}
void BM_normals_loops_edges_tag(BMesh *bm, const bool do_edges)
{
- BMFace *f;
- BMEdge *e;
- BMIter fiter, eiter;
- BMLoop *l_curr, *l_first;
-
- if (do_edges) {
- int index_edge;
- BM_ITER_MESH_INDEX(e, &eiter, bm, BM_EDGES_OF_MESH, index_edge) {
- BMLoop *l_a, *l_b;
-
- BM_elem_index_set(e, index_edge); /* set_inline */
- BM_elem_flag_disable(e, BM_ELEM_TAG);
- if (BM_edge_loop_pair(e, &l_a, &l_b)) {
- if (BM_elem_flag_test(e, BM_ELEM_SMOOTH) && l_a->v != l_b->v) {
- BM_elem_flag_enable(e, BM_ELEM_TAG);
- }
- }
- }
- bm->elem_index_dirty &= ~BM_EDGE;
- }
-
- int index_face, index_loop = 0;
- BM_ITER_MESH_INDEX(f, &fiter, bm, BM_FACES_OF_MESH, index_face) {
- BM_elem_index_set(f, index_face); /* set_inline */
- l_curr = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- BM_elem_index_set(l_curr, index_loop++); /* set_inline */
- BM_elem_flag_disable(l_curr, BM_ELEM_TAG);
- } while ((l_curr = l_curr->next) != l_first);
- }
- bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP);
+ BMFace *f;
+ BMEdge *e;
+ BMIter fiter, eiter;
+ BMLoop *l_curr, *l_first;
+
+ if (do_edges) {
+ int index_edge;
+ BM_ITER_MESH_INDEX (e, &eiter, bm, BM_EDGES_OF_MESH, index_edge) {
+ BMLoop *l_a, *l_b;
+
+ BM_elem_index_set(e, index_edge); /* set_inline */
+ BM_elem_flag_disable(e, BM_ELEM_TAG);
+ if (BM_edge_loop_pair(e, &l_a, &l_b)) {
+ if (BM_elem_flag_test(e, BM_ELEM_SMOOTH) && l_a->v != l_b->v) {
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
+ }
+ }
+ }
+ bm->elem_index_dirty &= ~BM_EDGE;
+ }
+
+ int index_face, index_loop = 0;
+ BM_ITER_MESH_INDEX (f, &fiter, bm, BM_FACES_OF_MESH, index_face) {
+ BM_elem_index_set(f, index_face); /* set_inline */
+ l_curr = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BM_elem_index_set(l_curr, index_loop++); /* set_inline */
+ BM_elem_flag_disable(l_curr, BM_ELEM_TAG);
+ } while ((l_curr = l_curr->next) != l_first);
+ }
+ bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP);
}
/**
@@ -1279,253 +1324,268 @@ void BM_normals_loops_edges_tag(BMesh *bm, const bool do_edges)
#ifndef NDEBUG
void BM_lnorspace_err(BMesh *bm)
{
- bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL;
- bool clear = true;
-
- MLoopNorSpaceArray *temp = MEM_callocN(sizeof(*temp), __func__);
- temp->lspacearr = NULL;
-
- BKE_lnor_spacearr_init(temp, bm->totloop, MLNOR_SPACEARR_BMLOOP_PTR);
-
- int cd_loop_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
- float(*lnors)[3] = MEM_callocN(sizeof(*lnors) * bm->totloop, __func__);
- BM_loops_calc_normal_vcos(bm, NULL, NULL, NULL, true, M_PI, lnors, temp, NULL, cd_loop_clnors_offset, true);
-
- for (int i = 0; i < bm->totloop; i++) {
- int j = 0;
- j += compare_ff(temp->lspacearr[i]->ref_alpha, bm->lnor_spacearr->lspacearr[i]->ref_alpha, 1e-4f);
- j += compare_ff(temp->lspacearr[i]->ref_beta, bm->lnor_spacearr->lspacearr[i]->ref_beta, 1e-4f);
- j += compare_v3v3(temp->lspacearr[i]->vec_lnor, bm->lnor_spacearr->lspacearr[i]->vec_lnor, 1e-4f);
- j += compare_v3v3(temp->lspacearr[i]->vec_ortho, bm->lnor_spacearr->lspacearr[i]->vec_ortho, 1e-4f);
- j += compare_v3v3(temp->lspacearr[i]->vec_ref, bm->lnor_spacearr->lspacearr[i]->vec_ref, 1e-4f);
-
- if (j != 5) {
- clear = false;
- break;
- }
- }
- BKE_lnor_spacearr_free(temp);
- MEM_freeN(temp);
- MEM_freeN(lnors);
- BLI_assert(clear);
-
- bm->spacearr_dirty &= ~BM_SPACEARR_DIRTY_ALL;
+ bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL;
+ bool clear = true;
+
+ MLoopNorSpaceArray *temp = MEM_callocN(sizeof(*temp), __func__);
+ temp->lspacearr = NULL;
+
+ BKE_lnor_spacearr_init(temp, bm->totloop, MLNOR_SPACEARR_BMLOOP_PTR);
+
+ int cd_loop_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
+ float(*lnors)[3] = MEM_callocN(sizeof(*lnors) * bm->totloop, __func__);
+ BM_loops_calc_normal_vcos(
+ bm, NULL, NULL, NULL, true, M_PI, lnors, temp, NULL, cd_loop_clnors_offset, true);
+
+ for (int i = 0; i < bm->totloop; i++) {
+ int j = 0;
+ j += compare_ff(
+ temp->lspacearr[i]->ref_alpha, bm->lnor_spacearr->lspacearr[i]->ref_alpha, 1e-4f);
+ j += compare_ff(
+ temp->lspacearr[i]->ref_beta, bm->lnor_spacearr->lspacearr[i]->ref_beta, 1e-4f);
+ j += compare_v3v3(
+ temp->lspacearr[i]->vec_lnor, bm->lnor_spacearr->lspacearr[i]->vec_lnor, 1e-4f);
+ j += compare_v3v3(
+ temp->lspacearr[i]->vec_ortho, bm->lnor_spacearr->lspacearr[i]->vec_ortho, 1e-4f);
+ j += compare_v3v3(
+ temp->lspacearr[i]->vec_ref, bm->lnor_spacearr->lspacearr[i]->vec_ref, 1e-4f);
+
+ if (j != 5) {
+ clear = false;
+ break;
+ }
+ }
+ BKE_lnor_spacearr_free(temp);
+ MEM_freeN(temp);
+ MEM_freeN(lnors);
+ BLI_assert(clear);
+
+ bm->spacearr_dirty &= ~BM_SPACEARR_DIRTY_ALL;
}
#endif
-static void bm_loop_normal_mark_indiv_do_loop(
- BMLoop *l, BLI_bitmap *loops, MLoopNorSpaceArray *lnor_spacearr, int *totloopsel)
+static void bm_loop_normal_mark_indiv_do_loop(BMLoop *l,
+ BLI_bitmap *loops,
+ MLoopNorSpaceArray *lnor_spacearr,
+ int *totloopsel)
{
- if (l != NULL) {
- const int l_idx = BM_elem_index_get(l);
-
- if (!BLI_BITMAP_TEST(loops, BM_elem_index_get(l))) {
- /* If vert and face selected share a loop, mark it for editing. */
- BLI_BITMAP_ENABLE(loops, l_idx);
- (*totloopsel)++;
-
- /* Mark all loops in same loop normal space (aka smooth fan). */
- if ((lnor_spacearr->lspacearr[l_idx]->flags & MLNOR_SPACE_IS_SINGLE) == 0) {
- for (LinkNode *node = lnor_spacearr->lspacearr[l_idx]->loops; node; node = node->next) {
- const int lfan_idx = BM_elem_index_get((BMLoop *)node->link);
- if (!BLI_BITMAP_TEST(loops, lfan_idx)) {
- BLI_BITMAP_ENABLE(loops, lfan_idx);
- (*totloopsel)++;
- }
- }
- }
- }
- }
+ if (l != NULL) {
+ const int l_idx = BM_elem_index_get(l);
+
+ if (!BLI_BITMAP_TEST(loops, BM_elem_index_get(l))) {
+ /* If vert and face selected share a loop, mark it for editing. */
+ BLI_BITMAP_ENABLE(loops, l_idx);
+ (*totloopsel)++;
+
+ /* Mark all loops in same loop normal space (aka smooth fan). */
+ if ((lnor_spacearr->lspacearr[l_idx]->flags & MLNOR_SPACE_IS_SINGLE) == 0) {
+ for (LinkNode *node = lnor_spacearr->lspacearr[l_idx]->loops; node; node = node->next) {
+ const int lfan_idx = BM_elem_index_get((BMLoop *)node->link);
+ if (!BLI_BITMAP_TEST(loops, lfan_idx)) {
+ BLI_BITMAP_ENABLE(loops, lfan_idx);
+ (*totloopsel)++;
+ }
+ }
+ }
+ }
+ }
}
/* Mark the individual clnors to be edited, if multiple selection methods are used. */
static int bm_loop_normal_mark_indiv(BMesh *bm, BLI_bitmap *loops)
{
- BMEditSelection *ese, *ese_prev;
- int totloopsel = 0;
-
- const bool sel_verts = (bm->selectmode & SCE_SELECT_VERTEX) != 0;
- const bool sel_edges = (bm->selectmode & SCE_SELECT_EDGE) != 0;
- const bool sel_faces = (bm->selectmode & SCE_SELECT_FACE) != 0;
- const bool use_sel_face_history = sel_faces && (sel_edges || sel_verts);
-
- BM_mesh_elem_index_ensure(bm, BM_LOOP);
-
- BLI_assert(bm->lnor_spacearr != NULL);
- BLI_assert(bm->lnor_spacearr->data_type == MLNOR_SPACEARR_BMLOOP_PTR);
-
- if (use_sel_face_history) {
- /* Using face history allows to select a single loop from a single face...
- * Note that this is On² piece of code, but it is not designed to be used with huge selection sets,
- * rather with only a few items selected at most.*/
- printf("using face history selection\n");
- /* Goes from last selected to the first selected element. */
- for (ese = bm->selected.last; ese; ese = ese->prev) {
- if (ese->htype == BM_FACE) {
- /* If current face is selected, then any verts to be edited must have been selected before it. */
- for (ese_prev = ese->prev; ese_prev; ese_prev = ese_prev->prev) {
- if (ese_prev->htype == BM_VERT) {
- bm_loop_normal_mark_indiv_do_loop(
- BM_face_vert_share_loop((BMFace *)ese->ele, (BMVert *)ese_prev->ele),
- loops, bm->lnor_spacearr, &totloopsel);
- }
- else if (ese_prev->htype == BM_EDGE) {
- BMEdge *e = (BMEdge *)ese_prev->ele;
- bm_loop_normal_mark_indiv_do_loop(
- BM_face_vert_share_loop((BMFace *)ese->ele, e->v1),
- loops, bm->lnor_spacearr, &totloopsel);
-
- bm_loop_normal_mark_indiv_do_loop(
- BM_face_vert_share_loop((BMFace *)ese->ele, e->v2),
- loops, bm->lnor_spacearr, &totloopsel);
- }
- }
- }
- }
- }
- else {
- if (sel_faces) {
- /* Only select all loops of selected faces. */
- printf("using face selection\n");
- BMLoop *l;
- BMFace *f;
- BMIter liter, fiter;
- BM_ITER_MESH(f, &fiter, bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- BM_ITER_ELEM(l, &liter, f, BM_LOOPS_OF_FACE) {
- bm_loop_normal_mark_indiv_do_loop(l, loops, bm->lnor_spacearr, &totloopsel);
- }
- }
- }
- }
- if (sel_edges) {
- /* Only select all loops of selected edges. */
- printf("using edge selection\n");
- BMLoop *l;
- BMEdge *e;
- BMIter liter, eiter;
- BM_ITER_MESH(e, &eiter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
- BM_ITER_ELEM(l, &liter, e, BM_LOOPS_OF_EDGE) {
- bm_loop_normal_mark_indiv_do_loop(l, loops, bm->lnor_spacearr, &totloopsel);
- /* Loops actually 'have' two edges, or said otherwise, a selected edge actually selects
- * *two* loops in each of its faces. We have to find the other one too. */
- if (BM_vert_in_edge(e, l->next->v)) {
- bm_loop_normal_mark_indiv_do_loop(l->next, loops, bm->lnor_spacearr, &totloopsel);
- }
- else {
- BLI_assert(BM_vert_in_edge(e, l->prev->v));
- bm_loop_normal_mark_indiv_do_loop(l->prev, loops, bm->lnor_spacearr, &totloopsel);
- }
- }
- }
- }
- }
- if (sel_verts) {
- /* Select all loops of selected verts. */
- printf("using vert selection\n");
- BMLoop *l;
- BMVert *v;
- BMIter liter, viter;
- BM_ITER_MESH(v, &viter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
- BM_ITER_ELEM(l, &liter, v, BM_LOOPS_OF_VERT) {
- bm_loop_normal_mark_indiv_do_loop(l, loops, bm->lnor_spacearr, &totloopsel);
- }
- }
- }
- }
- }
-
- return totloopsel;
+ BMEditSelection *ese, *ese_prev;
+ int totloopsel = 0;
+
+ const bool sel_verts = (bm->selectmode & SCE_SELECT_VERTEX) != 0;
+ const bool sel_edges = (bm->selectmode & SCE_SELECT_EDGE) != 0;
+ const bool sel_faces = (bm->selectmode & SCE_SELECT_FACE) != 0;
+ const bool use_sel_face_history = sel_faces && (sel_edges || sel_verts);
+
+ BM_mesh_elem_index_ensure(bm, BM_LOOP);
+
+ BLI_assert(bm->lnor_spacearr != NULL);
+ BLI_assert(bm->lnor_spacearr->data_type == MLNOR_SPACEARR_BMLOOP_PTR);
+
+ if (use_sel_face_history) {
+ /* Using face history allows to select a single loop from a single face...
+ * Note that this is On² piece of code, but it is not designed to be used with huge selection sets,
+ * rather with only a few items selected at most.*/
+ printf("using face history selection\n");
+ /* Goes from last selected to the first selected element. */
+ for (ese = bm->selected.last; ese; ese = ese->prev) {
+ if (ese->htype == BM_FACE) {
+ /* If current face is selected, then any verts to be edited must have been selected before it. */
+ for (ese_prev = ese->prev; ese_prev; ese_prev = ese_prev->prev) {
+ if (ese_prev->htype == BM_VERT) {
+ bm_loop_normal_mark_indiv_do_loop(
+ BM_face_vert_share_loop((BMFace *)ese->ele, (BMVert *)ese_prev->ele),
+ loops,
+ bm->lnor_spacearr,
+ &totloopsel);
+ }
+ else if (ese_prev->htype == BM_EDGE) {
+ BMEdge *e = (BMEdge *)ese_prev->ele;
+ bm_loop_normal_mark_indiv_do_loop(BM_face_vert_share_loop((BMFace *)ese->ele, e->v1),
+ loops,
+ bm->lnor_spacearr,
+ &totloopsel);
+
+ bm_loop_normal_mark_indiv_do_loop(BM_face_vert_share_loop((BMFace *)ese->ele, e->v2),
+ loops,
+ bm->lnor_spacearr,
+ &totloopsel);
+ }
+ }
+ }
+ }
+ }
+ else {
+ if (sel_faces) {
+ /* Only select all loops of selected faces. */
+ printf("using face selection\n");
+ BMLoop *l;
+ BMFace *f;
+ BMIter liter, fiter;
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ bm_loop_normal_mark_indiv_do_loop(l, loops, bm->lnor_spacearr, &totloopsel);
+ }
+ }
+ }
+ }
+ if (sel_edges) {
+ /* Only select all loops of selected edges. */
+ printf("using edge selection\n");
+ BMLoop *l;
+ BMEdge *e;
+ BMIter liter, eiter;
+ BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ BM_ITER_ELEM (l, &liter, e, BM_LOOPS_OF_EDGE) {
+ bm_loop_normal_mark_indiv_do_loop(l, loops, bm->lnor_spacearr, &totloopsel);
+ /* Loops actually 'have' two edges, or said otherwise, a selected edge actually selects
+ * *two* loops in each of its faces. We have to find the other one too. */
+ if (BM_vert_in_edge(e, l->next->v)) {
+ bm_loop_normal_mark_indiv_do_loop(l->next, loops, bm->lnor_spacearr, &totloopsel);
+ }
+ else {
+ BLI_assert(BM_vert_in_edge(e, l->prev->v));
+ bm_loop_normal_mark_indiv_do_loop(l->prev, loops, bm->lnor_spacearr, &totloopsel);
+ }
+ }
+ }
+ }
+ }
+ if (sel_verts) {
+ /* Select all loops of selected verts. */
+ printf("using vert selection\n");
+ BMLoop *l;
+ BMVert *v;
+ BMIter liter, viter;
+ BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+ BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
+ bm_loop_normal_mark_indiv_do_loop(l, loops, bm->lnor_spacearr, &totloopsel);
+ }
+ }
+ }
+ }
+ }
+
+ return totloopsel;
}
-static void loop_normal_editdata_init(BMesh *bm, BMLoopNorEditData *lnor_ed, BMVert *v, BMLoop *l, const int offset)
+static void loop_normal_editdata_init(
+ BMesh *bm, BMLoopNorEditData *lnor_ed, BMVert *v, BMLoop *l, const int offset)
{
- BLI_assert(bm->lnor_spacearr != NULL);
- BLI_assert(bm->lnor_spacearr->lspacearr != NULL);
+ BLI_assert(bm->lnor_spacearr != NULL);
+ BLI_assert(bm->lnor_spacearr->lspacearr != NULL);
- const int l_index = BM_elem_index_get(l);
- short *clnors_data = BM_ELEM_CD_GET_VOID_P(l, offset);
+ const int l_index = BM_elem_index_get(l);
+ short *clnors_data = BM_ELEM_CD_GET_VOID_P(l, offset);
- lnor_ed->loop_index = l_index;
- lnor_ed->loop = l;
+ lnor_ed->loop_index = l_index;
+ lnor_ed->loop = l;
- float custom_normal[3];
- BKE_lnor_space_custom_data_to_normal(bm->lnor_spacearr->lspacearr[l_index], clnors_data, custom_normal);
+ float custom_normal[3];
+ BKE_lnor_space_custom_data_to_normal(
+ bm->lnor_spacearr->lspacearr[l_index], clnors_data, custom_normal);
- lnor_ed->clnors_data = clnors_data;
- copy_v3_v3(lnor_ed->nloc, custom_normal);
- copy_v3_v3(lnor_ed->niloc, custom_normal);
+ lnor_ed->clnors_data = clnors_data;
+ copy_v3_v3(lnor_ed->nloc, custom_normal);
+ copy_v3_v3(lnor_ed->niloc, custom_normal);
- lnor_ed->loc = v->co;
+ lnor_ed->loc = v->co;
}
BMLoopNorEditDataArray *BM_loop_normal_editdata_array_init(BMesh *bm)
{
- BMLoop *l;
- BMVert *v;
- BMIter liter, viter;
+ BMLoop *l;
+ BMVert *v;
+ BMIter liter, viter;
- int totloopsel = 0;
+ int totloopsel = 0;
- BLI_assert(bm->spacearr_dirty == 0);
+ BLI_assert(bm->spacearr_dirty == 0);
- BMLoopNorEditDataArray *lnors_ed_arr = MEM_mallocN(sizeof(*lnors_ed_arr), __func__);
- lnors_ed_arr->lidx_to_lnor_editdata = MEM_callocN(
- sizeof(*lnors_ed_arr->lidx_to_lnor_editdata) * bm->totloop, __func__);
+ BMLoopNorEditDataArray *lnors_ed_arr = MEM_mallocN(sizeof(*lnors_ed_arr), __func__);
+ lnors_ed_arr->lidx_to_lnor_editdata = MEM_callocN(
+ sizeof(*lnors_ed_arr->lidx_to_lnor_editdata) * bm->totloop, __func__);
- if (!CustomData_has_layer(&bm->ldata, CD_CUSTOMLOOPNORMAL)) {
- BM_data_layer_add(bm, &bm->ldata, CD_CUSTOMLOOPNORMAL);
- }
- const int cd_custom_normal_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
+ if (!CustomData_has_layer(&bm->ldata, CD_CUSTOMLOOPNORMAL)) {
+ BM_data_layer_add(bm, &bm->ldata, CD_CUSTOMLOOPNORMAL);
+ }
+ const int cd_custom_normal_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
- BM_mesh_elem_index_ensure(bm, BM_LOOP);
+ BM_mesh_elem_index_ensure(bm, BM_LOOP);
- BLI_bitmap *loops = BLI_BITMAP_NEW(bm->totloop, __func__);
+ BLI_bitmap *loops = BLI_BITMAP_NEW(bm->totloop, __func__);
- /* This function define loop normals to edit, based on selection modes and history. */
- totloopsel = bm_loop_normal_mark_indiv(bm, loops);
+ /* This function define loop normals to edit, based on selection modes and history. */
+ totloopsel = bm_loop_normal_mark_indiv(bm, loops);
- if (totloopsel) {
- BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata = MEM_mallocN(sizeof(*lnor_ed) * totloopsel, __func__);
+ if (totloopsel) {
+ BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata = MEM_mallocN(
+ sizeof(*lnor_ed) * totloopsel, __func__);
- BM_ITER_MESH(v, &viter, bm, BM_VERTS_OF_MESH) {
- BM_ITER_ELEM(l, &liter, v, BM_LOOPS_OF_VERT) {
- if (BLI_BITMAP_TEST(loops, BM_elem_index_get(l))) {
- loop_normal_editdata_init(bm, lnor_ed, v, l, cd_custom_normal_offset);
- lnors_ed_arr->lidx_to_lnor_editdata[BM_elem_index_get(l)] = lnor_ed;
- lnor_ed++;
- }
- }
- }
- lnors_ed_arr->totloop = totloopsel;
- }
+ BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
+ BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
+ if (BLI_BITMAP_TEST(loops, BM_elem_index_get(l))) {
+ loop_normal_editdata_init(bm, lnor_ed, v, l, cd_custom_normal_offset);
+ lnors_ed_arr->lidx_to_lnor_editdata[BM_elem_index_get(l)] = lnor_ed;
+ lnor_ed++;
+ }
+ }
+ }
+ lnors_ed_arr->totloop = totloopsel;
+ }
- MEM_freeN(loops);
- lnors_ed_arr->cd_custom_normal_offset = cd_custom_normal_offset;
- return lnors_ed_arr;
+ MEM_freeN(loops);
+ lnors_ed_arr->cd_custom_normal_offset = cd_custom_normal_offset;
+ return lnors_ed_arr;
}
void BM_loop_normal_editdata_array_free(BMLoopNorEditDataArray *lnors_ed_arr)
{
- MEM_SAFE_FREE(lnors_ed_arr->lnor_editdata);
- MEM_SAFE_FREE(lnors_ed_arr->lidx_to_lnor_editdata);
- MEM_freeN(lnors_ed_arr);
+ MEM_SAFE_FREE(lnors_ed_arr->lnor_editdata);
+ MEM_SAFE_FREE(lnors_ed_arr->lidx_to_lnor_editdata);
+ MEM_freeN(lnors_ed_arr);
}
int BM_total_loop_select(BMesh *bm)
{
- int r_sel = 0;
- BMVert *v;
- BMIter viter;
-
- BM_ITER_MESH(v, &viter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
- r_sel += BM_vert_face_count(v);
- }
- }
- return r_sel;
+ int r_sel = 0;
+ BMVert *v;
+ BMIter viter;
+
+ BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT)) {
+ r_sel += BM_vert_face_count(v);
+ }
+ }
+ return r_sel;
}
/**
@@ -1537,20 +1597,21 @@ int BM_total_loop_select(BMesh *bm)
*/
void bmesh_edit_begin(BMesh *UNUSED(bm), BMOpTypeFlag UNUSED(type_flag))
{
- /* Most operators seem to be using BMO_OPTYPE_FLAG_UNTAN_MULTIRES to change the MDisps to
- * absolute space during mesh edits. With this enabled, changes to the topology
- * (loop cuts, edge subdivides, etc) are not reflected in the higher levels of
- * the mesh at all, which doesn't seem right. Turning off completely for now,
- * until this is shown to be better for certain types of mesh edits. */
+ /* Most operators seem to be using BMO_OPTYPE_FLAG_UNTAN_MULTIRES to change the MDisps to
+ * absolute space during mesh edits. With this enabled, changes to the topology
+ * (loop cuts, edge subdivides, etc) are not reflected in the higher levels of
+ * the mesh at all, which doesn't seem right. Turning off completely for now,
+ * until this is shown to be better for certain types of mesh edits. */
#ifdef BMOP_UNTAN_MULTIRES_ENABLED
- /* switch multires data out of tangent space */
- if ((type_flag & BMO_OPTYPE_FLAG_UNTAN_MULTIRES) && CustomData_has_layer(&bm->ldata, CD_MDISPS)) {
- bmesh_mdisps_space_set(bm, MULTIRES_SPACE_TANGENT, MULTIRES_SPACE_ABSOLUTE);
-
- /* ensure correct normals, if possible */
- bmesh_rationalize_normals(bm, 0);
- BM_mesh_normals_update(bm);
- }
+ /* switch multires data out of tangent space */
+ if ((type_flag & BMO_OPTYPE_FLAG_UNTAN_MULTIRES) &&
+ CustomData_has_layer(&bm->ldata, CD_MDISPS)) {
+ bmesh_mdisps_space_set(bm, MULTIRES_SPACE_TANGENT, MULTIRES_SPACE_ABSOLUTE);
+
+ /* ensure correct normals, if possible */
+ bmesh_rationalize_normals(bm, 0);
+ BM_mesh_normals_update(bm);
+ }
#endif
}
@@ -1559,164 +1620,163 @@ void bmesh_edit_begin(BMesh *UNUSED(bm), BMOpTypeFlag UNUSED(type_flag))
*/
void bmesh_edit_end(BMesh *bm, BMOpTypeFlag type_flag)
{
- ListBase select_history;
+ ListBase select_history;
- /* BMO_OPTYPE_FLAG_UNTAN_MULTIRES disabled for now, see comment above in bmesh_edit_begin. */
+ /* BMO_OPTYPE_FLAG_UNTAN_MULTIRES disabled for now, see comment above in bmesh_edit_begin. */
#ifdef BMOP_UNTAN_MULTIRES_ENABLED
- /* switch multires data into tangent space */
- if ((flag & BMO_OPTYPE_FLAG_UNTAN_MULTIRES) && CustomData_has_layer(&bm->ldata, CD_MDISPS)) {
- /* set normals to their previous winding */
- bmesh_rationalize_normals(bm, 1);
- bmesh_mdisps_space_set(bm, MULTIRES_SPACE_ABSOLUTE, MULTIRES_SPACE_TANGENT);
- }
- else if (flag & BMO_OP_FLAG_RATIONALIZE_NORMALS) {
- bmesh_rationalize_normals(bm, 1);
- }
+ /* switch multires data into tangent space */
+ if ((flag & BMO_OPTYPE_FLAG_UNTAN_MULTIRES) && CustomData_has_layer(&bm->ldata, CD_MDISPS)) {
+ /* set normals to their previous winding */
+ bmesh_rationalize_normals(bm, 1);
+ bmesh_mdisps_space_set(bm, MULTIRES_SPACE_ABSOLUTE, MULTIRES_SPACE_TANGENT);
+ }
+ else if (flag & BMO_OP_FLAG_RATIONALIZE_NORMALS) {
+ bmesh_rationalize_normals(bm, 1);
+ }
#endif
- /* compute normals, clear temp flags and flush selections */
- if (type_flag & BMO_OPTYPE_FLAG_NORMALS_CALC) {
- bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL;
- BM_mesh_normals_update(bm);
- }
-
-
- if ((type_flag & BMO_OPTYPE_FLAG_SELECT_VALIDATE) == 0) {
- select_history = bm->selected;
- BLI_listbase_clear(&bm->selected);
- }
-
- if (type_flag & BMO_OPTYPE_FLAG_SELECT_FLUSH) {
- BM_mesh_select_mode_flush(bm);
- }
-
- if ((type_flag & BMO_OPTYPE_FLAG_SELECT_VALIDATE) == 0) {
- bm->selected = select_history;
- }
- if (type_flag & BMO_OPTYPE_FLAG_INVALIDATE_CLNOR_ALL) {
- bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL;
- }
+ /* compute normals, clear temp flags and flush selections */
+ if (type_flag & BMO_OPTYPE_FLAG_NORMALS_CALC) {
+ bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL;
+ BM_mesh_normals_update(bm);
+ }
+
+ if ((type_flag & BMO_OPTYPE_FLAG_SELECT_VALIDATE) == 0) {
+ select_history = bm->selected;
+ BLI_listbase_clear(&bm->selected);
+ }
+
+ if (type_flag & BMO_OPTYPE_FLAG_SELECT_FLUSH) {
+ BM_mesh_select_mode_flush(bm);
+ }
+
+ if ((type_flag & BMO_OPTYPE_FLAG_SELECT_VALIDATE) == 0) {
+ bm->selected = select_history;
+ }
+ if (type_flag & BMO_OPTYPE_FLAG_INVALIDATE_CLNOR_ALL) {
+ bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL;
+ }
}
void BM_mesh_elem_index_ensure_ex(BMesh *bm, const char htype, int elem_offset[4])
{
#ifdef DEBUG
- BM_ELEM_INDEX_VALIDATE(bm, "Should Never Fail!", __func__);
+ BM_ELEM_INDEX_VALIDATE(bm, "Should Never Fail!", __func__);
#endif
- if (elem_offset == NULL) {
- /* Simple case. */
- const char htype_needed = bm->elem_index_dirty & htype;
- if (htype_needed == 0) {
- goto finally;
- }
- }
-
- if (htype & BM_VERT) {
- if ((bm->elem_index_dirty & BM_VERT) || (elem_offset && elem_offset[0])) {
- BMIter iter;
- BMElem *ele;
-
- int index = elem_offset ? elem_offset[0] : 0;
- BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
- BM_elem_index_set(ele, index++); /* set_ok */
- }
- BLI_assert(elem_offset || index == bm->totvert);
- }
- else {
- // printf("%s: skipping vert index calc!\n", __func__);
- }
- }
-
- if (htype & BM_EDGE) {
- if ((bm->elem_index_dirty & BM_EDGE) || (elem_offset && elem_offset[1])) {
- BMIter iter;
- BMElem *ele;
-
- int index = elem_offset ? elem_offset[1] : 0;
- BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
- BM_elem_index_set(ele, index++); /* set_ok */
- }
- BLI_assert(elem_offset || index == bm->totedge);
- }
- else {
- // printf("%s: skipping edge index calc!\n", __func__);
- }
- }
-
- if (htype & (BM_FACE | BM_LOOP)) {
- if ((bm->elem_index_dirty & (BM_FACE | BM_LOOP)) || (elem_offset && (elem_offset[2] || elem_offset[3]))) {
- BMIter iter;
- BMElem *ele;
-
- const bool update_face = (htype & BM_FACE) && (bm->elem_index_dirty & BM_FACE);
- const bool update_loop = (htype & BM_LOOP) && (bm->elem_index_dirty & BM_LOOP);
-
- int index_loop = elem_offset ? elem_offset[2] : 0;
- int index = elem_offset ? elem_offset[3] : 0;
-
- BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
- if (update_face) {
- BM_elem_index_set(ele, index++); /* set_ok */
- }
-
- if (update_loop) {
- BMLoop *l_iter, *l_first;
-
- l_iter = l_first = BM_FACE_FIRST_LOOP((BMFace *)ele);
- do {
- BM_elem_index_set(l_iter, index_loop++); /* set_ok */
- } while ((l_iter = l_iter->next) != l_first);
- }
- }
-
- BLI_assert(elem_offset || !update_face || index == bm->totface);
- if (update_loop) {
- BLI_assert(elem_offset || !update_loop || index_loop == bm->totloop);
- }
- }
- else {
- // printf("%s: skipping face/loop index calc!\n", __func__);
- }
- }
+ if (elem_offset == NULL) {
+ /* Simple case. */
+ const char htype_needed = bm->elem_index_dirty & htype;
+ if (htype_needed == 0) {
+ goto finally;
+ }
+ }
+
+ if (htype & BM_VERT) {
+ if ((bm->elem_index_dirty & BM_VERT) || (elem_offset && elem_offset[0])) {
+ BMIter iter;
+ BMElem *ele;
+
+ int index = elem_offset ? elem_offset[0] : 0;
+ BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_elem_index_set(ele, index++); /* set_ok */
+ }
+ BLI_assert(elem_offset || index == bm->totvert);
+ }
+ else {
+ // printf("%s: skipping vert index calc!\n", __func__);
+ }
+ }
+
+ if (htype & BM_EDGE) {
+ if ((bm->elem_index_dirty & BM_EDGE) || (elem_offset && elem_offset[1])) {
+ BMIter iter;
+ BMElem *ele;
+
+ int index = elem_offset ? elem_offset[1] : 0;
+ BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
+ BM_elem_index_set(ele, index++); /* set_ok */
+ }
+ BLI_assert(elem_offset || index == bm->totedge);
+ }
+ else {
+ // printf("%s: skipping edge index calc!\n", __func__);
+ }
+ }
+
+ if (htype & (BM_FACE | BM_LOOP)) {
+ if ((bm->elem_index_dirty & (BM_FACE | BM_LOOP)) ||
+ (elem_offset && (elem_offset[2] || elem_offset[3]))) {
+ BMIter iter;
+ BMElem *ele;
+
+ const bool update_face = (htype & BM_FACE) && (bm->elem_index_dirty & BM_FACE);
+ const bool update_loop = (htype & BM_LOOP) && (bm->elem_index_dirty & BM_LOOP);
+
+ int index_loop = elem_offset ? elem_offset[2] : 0;
+ int index = elem_offset ? elem_offset[3] : 0;
+
+ BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
+ if (update_face) {
+ BM_elem_index_set(ele, index++); /* set_ok */
+ }
+
+ if (update_loop) {
+ BMLoop *l_iter, *l_first;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP((BMFace *)ele);
+ do {
+ BM_elem_index_set(l_iter, index_loop++); /* set_ok */
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ }
+
+ BLI_assert(elem_offset || !update_face || index == bm->totface);
+ if (update_loop) {
+ BLI_assert(elem_offset || !update_loop || index_loop == bm->totloop);
+ }
+ }
+ else {
+ // printf("%s: skipping face/loop index calc!\n", __func__);
+ }
+ }
finally:
- bm->elem_index_dirty &= ~htype;
- if (elem_offset) {
- if (htype & BM_VERT) {
- elem_offset[0] += bm->totvert;
- if (elem_offset[0] != bm->totvert) {
- bm->elem_index_dirty |= BM_VERT;
- }
- }
- if (htype & BM_EDGE) {
- elem_offset[1] += bm->totedge;
- if (elem_offset[1] != bm->totedge) {
- bm->elem_index_dirty |= BM_EDGE;
- }
- }
- if (htype & BM_LOOP) {
- elem_offset[2] += bm->totloop;
- if (elem_offset[2] != bm->totloop) {
- bm->elem_index_dirty |= BM_LOOP;
- }
- }
- if (htype & BM_FACE) {
- elem_offset[3] += bm->totface;
- if (elem_offset[3] != bm->totface) {
- bm->elem_index_dirty |= BM_FACE;
- }
- }
- }
+ bm->elem_index_dirty &= ~htype;
+ if (elem_offset) {
+ if (htype & BM_VERT) {
+ elem_offset[0] += bm->totvert;
+ if (elem_offset[0] != bm->totvert) {
+ bm->elem_index_dirty |= BM_VERT;
+ }
+ }
+ if (htype & BM_EDGE) {
+ elem_offset[1] += bm->totedge;
+ if (elem_offset[1] != bm->totedge) {
+ bm->elem_index_dirty |= BM_EDGE;
+ }
+ }
+ if (htype & BM_LOOP) {
+ elem_offset[2] += bm->totloop;
+ if (elem_offset[2] != bm->totloop) {
+ bm->elem_index_dirty |= BM_LOOP;
+ }
+ }
+ if (htype & BM_FACE) {
+ elem_offset[3] += bm->totface;
+ if (elem_offset[3] != bm->totface) {
+ bm->elem_index_dirty |= BM_FACE;
+ }
+ }
+ }
}
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
{
- BM_mesh_elem_index_ensure_ex(bm, htype, NULL);
+ BM_mesh_elem_index_ensure_ex(bm, htype, NULL);
}
-
/**
* Array checking/setting macros
*
@@ -1729,221 +1789,223 @@ void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
*/
void BM_mesh_elem_index_validate(
- BMesh *bm, const char *location, const char *func,
- const char *msg_a, const char *msg_b)
+ BMesh *bm, const char *location, const char *func, const char *msg_a, const char *msg_b)
{
- const char iter_types[3] = {BM_VERTS_OF_MESH,
- BM_EDGES_OF_MESH,
- BM_FACES_OF_MESH};
-
- const char flag_types[3] = {BM_VERT, BM_EDGE, BM_FACE};
- const char *type_names[3] = {"vert", "edge", "face"};
-
- BMIter iter;
- BMElem *ele;
- int i;
- bool is_any_error = 0;
-
- for (i = 0; i < 3; i++) {
- const bool is_dirty = (flag_types[i] & bm->elem_index_dirty) != 0;
- int index = 0;
- bool is_error = false;
- int err_val = 0;
- int err_idx = 0;
-
- BM_ITER_MESH (ele, &iter, bm, iter_types[i]) {
- if (!is_dirty) {
- if (BM_elem_index_get(ele) != index) {
- err_val = BM_elem_index_get(ele);
- err_idx = index;
- is_error = true;
- }
- }
-
- BM_elem_index_set(ele, index); /* set_ok */
- index++;
- }
-
- if ((is_error == true) && (is_dirty == false)) {
- is_any_error = true;
- fprintf(stderr,
- "Invalid Index: at %s, %s, %s[%d] invalid index %d, '%s', '%s'\n",
- location, func, type_names[i], err_idx, err_val, msg_a, msg_b);
- }
- else if ((is_error == false) && (is_dirty == true)) {
-
-#if 0 /* mostly annoying */
-
- /* dirty may have been incorrectly set */
- fprintf(stderr,
- "Invalid Dirty: at %s, %s (%s), dirty flag was set but all index values are correct, '%s', '%s'\n",
- location, func, type_names[i], msg_a, msg_b);
+ const char iter_types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH};
+
+ const char flag_types[3] = {BM_VERT, BM_EDGE, BM_FACE};
+ const char *type_names[3] = {"vert", "edge", "face"};
+
+ BMIter iter;
+ BMElem *ele;
+ int i;
+ bool is_any_error = 0;
+
+ for (i = 0; i < 3; i++) {
+ const bool is_dirty = (flag_types[i] & bm->elem_index_dirty) != 0;
+ int index = 0;
+ bool is_error = false;
+ int err_val = 0;
+ int err_idx = 0;
+
+ BM_ITER_MESH (ele, &iter, bm, iter_types[i]) {
+ if (!is_dirty) {
+ if (BM_elem_index_get(ele) != index) {
+ err_val = BM_elem_index_get(ele);
+ err_idx = index;
+ is_error = true;
+ }
+ }
+
+ BM_elem_index_set(ele, index); /* set_ok */
+ index++;
+ }
+
+ if ((is_error == true) && (is_dirty == false)) {
+ is_any_error = true;
+ fprintf(stderr,
+ "Invalid Index: at %s, %s, %s[%d] invalid index %d, '%s', '%s'\n",
+ location,
+ func,
+ type_names[i],
+ err_idx,
+ err_val,
+ msg_a,
+ msg_b);
+ }
+ else if ((is_error == false) && (is_dirty == true)) {
+
+#if 0 /* mostly annoying */
+
+ /* dirty may have been incorrectly set */
+ fprintf(stderr,
+ "Invalid Dirty: at %s, %s (%s), dirty flag was set but all index values are correct, '%s', '%s'\n",
+ location, func, type_names[i], msg_a, msg_b);
#endif
- }
- }
+ }
+ }
#if 0 /* mostly annoying, even in debug mode */
-#ifdef DEBUG
- if (is_any_error == 0) {
- fprintf(stderr,
- "Valid Index Success: at %s, %s, '%s', '%s'\n",
- location, func, msg_a, msg_b);
- }
+# ifdef DEBUG
+ if (is_any_error == 0) {
+ fprintf(stderr,
+ "Valid Index Success: at %s, %s, '%s', '%s'\n",
+ location, func, msg_a, msg_b);
+ }
+# endif
#endif
-#endif
- (void) is_any_error; /* shut up the compiler */
-
+ (void)is_any_error; /* shut up the compiler */
}
/* debug check only - no need to optimize */
#ifndef NDEBUG
bool BM_mesh_elem_table_check(BMesh *bm)
{
- BMIter iter;
- BMElem *ele;
- int i;
-
- if (bm->vtable && ((bm->elem_table_dirty & BM_VERT) == 0)) {
- BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, i) {
- if (ele != (BMElem *)bm->vtable[i]) {
- return false;
- }
- }
- }
-
- if (bm->etable && ((bm->elem_table_dirty & BM_EDGE) == 0)) {
- BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) {
- if (ele != (BMElem *)bm->etable[i]) {
- return false;
- }
- }
- }
-
- if (bm->ftable && ((bm->elem_table_dirty & BM_FACE) == 0)) {
- BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) {
- if (ele != (BMElem *)bm->ftable[i]) {
- return false;
- }
- }
- }
-
- return true;
+ BMIter iter;
+ BMElem *ele;
+ int i;
+
+ if (bm->vtable && ((bm->elem_table_dirty & BM_VERT) == 0)) {
+ BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, i) {
+ if (ele != (BMElem *)bm->vtable[i]) {
+ return false;
+ }
+ }
+ }
+
+ if (bm->etable && ((bm->elem_table_dirty & BM_EDGE) == 0)) {
+ BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) {
+ if (ele != (BMElem *)bm->etable[i]) {
+ return false;
+ }
+ }
+ }
+
+ if (bm->ftable && ((bm->elem_table_dirty & BM_FACE) == 0)) {
+ BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) {
+ if (ele != (BMElem *)bm->ftable[i]) {
+ return false;
+ }
+ }
+ }
+
+ return true;
}
#endif
-
-
void BM_mesh_elem_table_ensure(BMesh *bm, const char htype)
{
- /* assume if the array is non-null then its valid and no need to recalc */
- const char htype_needed = (((bm->vtable && ((bm->elem_table_dirty & BM_VERT) == 0)) ? 0 : BM_VERT) |
- ((bm->etable && ((bm->elem_table_dirty & BM_EDGE) == 0)) ? 0 : BM_EDGE) |
- ((bm->ftable && ((bm->elem_table_dirty & BM_FACE) == 0)) ? 0 : BM_FACE)) & htype;
-
- BLI_assert((htype & ~BM_ALL_NOLOOP) == 0);
-
- /* in debug mode double check we didn't need to recalculate */
- BLI_assert(BM_mesh_elem_table_check(bm) == true);
-
- if (htype_needed == 0) {
- goto finally;
- }
-
- if (htype_needed & BM_VERT) {
- if (bm->vtable && bm->totvert <= bm->vtable_tot && bm->totvert * 2 >= bm->vtable_tot) {
- /* pass (re-use the array) */
- }
- else {
- if (bm->vtable) {
- MEM_freeN(bm->vtable);
- }
- bm->vtable = MEM_mallocN(sizeof(void **) * bm->totvert, "bm->vtable");
- bm->vtable_tot = bm->totvert;
- }
- }
- if (htype_needed & BM_EDGE) {
- if (bm->etable && bm->totedge <= bm->etable_tot && bm->totedge * 2 >= bm->etable_tot) {
- /* pass (re-use the array) */
- }
- else {
- if (bm->etable) {
- MEM_freeN(bm->etable);
- }
- bm->etable = MEM_mallocN(sizeof(void **) * bm->totedge, "bm->etable");
- bm->etable_tot = bm->totedge;
- }
- }
- if (htype_needed & BM_FACE) {
- if (bm->ftable && bm->totface <= bm->ftable_tot && bm->totface * 2 >= bm->ftable_tot) {
- /* pass (re-use the array) */
- }
- else {
- if (bm->ftable) {
- MEM_freeN(bm->ftable);
- }
- bm->ftable = MEM_mallocN(sizeof(void **) * bm->totface, "bm->ftable");
- bm->ftable_tot = bm->totface;
- }
- }
-
- if (htype_needed & BM_VERT) {
- BM_iter_as_array(bm, BM_VERTS_OF_MESH, NULL, (void **)bm->vtable, bm->totvert);
- }
-
- if (htype_needed & BM_EDGE) {
- BM_iter_as_array(bm, BM_EDGES_OF_MESH, NULL, (void **)bm->etable, bm->totedge);
- }
-
- if (htype_needed & BM_FACE) {
- BM_iter_as_array(bm, BM_FACES_OF_MESH, NULL, (void **)bm->ftable, bm->totface);
- }
+ /* assume if the array is non-null then its valid and no need to recalc */
+ const char htype_needed =
+ (((bm->vtable && ((bm->elem_table_dirty & BM_VERT) == 0)) ? 0 : BM_VERT) |
+ ((bm->etable && ((bm->elem_table_dirty & BM_EDGE) == 0)) ? 0 : BM_EDGE) |
+ ((bm->ftable && ((bm->elem_table_dirty & BM_FACE) == 0)) ? 0 : BM_FACE)) &
+ htype;
+
+ BLI_assert((htype & ~BM_ALL_NOLOOP) == 0);
+
+ /* in debug mode double check we didn't need to recalculate */
+ BLI_assert(BM_mesh_elem_table_check(bm) == true);
+
+ if (htype_needed == 0) {
+ goto finally;
+ }
+
+ if (htype_needed & BM_VERT) {
+ if (bm->vtable && bm->totvert <= bm->vtable_tot && bm->totvert * 2 >= bm->vtable_tot) {
+ /* pass (re-use the array) */
+ }
+ else {
+ if (bm->vtable) {
+ MEM_freeN(bm->vtable);
+ }
+ bm->vtable = MEM_mallocN(sizeof(void **) * bm->totvert, "bm->vtable");
+ bm->vtable_tot = bm->totvert;
+ }
+ }
+ if (htype_needed & BM_EDGE) {
+ if (bm->etable && bm->totedge <= bm->etable_tot && bm->totedge * 2 >= bm->etable_tot) {
+ /* pass (re-use the array) */
+ }
+ else {
+ if (bm->etable) {
+ MEM_freeN(bm->etable);
+ }
+ bm->etable = MEM_mallocN(sizeof(void **) * bm->totedge, "bm->etable");
+ bm->etable_tot = bm->totedge;
+ }
+ }
+ if (htype_needed & BM_FACE) {
+ if (bm->ftable && bm->totface <= bm->ftable_tot && bm->totface * 2 >= bm->ftable_tot) {
+ /* pass (re-use the array) */
+ }
+ else {
+ if (bm->ftable) {
+ MEM_freeN(bm->ftable);
+ }
+ bm->ftable = MEM_mallocN(sizeof(void **) * bm->totface, "bm->ftable");
+ bm->ftable_tot = bm->totface;
+ }
+ }
+
+ if (htype_needed & BM_VERT) {
+ BM_iter_as_array(bm, BM_VERTS_OF_MESH, NULL, (void **)bm->vtable, bm->totvert);
+ }
+
+ if (htype_needed & BM_EDGE) {
+ BM_iter_as_array(bm, BM_EDGES_OF_MESH, NULL, (void **)bm->etable, bm->totedge);
+ }
+
+ if (htype_needed & BM_FACE) {
+ BM_iter_as_array(bm, BM_FACES_OF_MESH, NULL, (void **)bm->ftable, bm->totface);
+ }
finally:
- /* Only clear dirty flags when all the pointers and data are actually valid.
- * This prevents possible threading issues when dirty flag check failed but
- * data wasn't ready still.
- */
- bm->elem_table_dirty &= ~htype_needed;
+ /* Only clear dirty flags when all the pointers and data are actually valid.
+ * This prevents possible threading issues when dirty flag check failed but
+ * data wasn't ready still.
+ */
+ bm->elem_table_dirty &= ~htype_needed;
}
/* use BM_mesh_elem_table_ensure where possible to avoid full rebuild */
void BM_mesh_elem_table_init(BMesh *bm, const char htype)
{
- BLI_assert((htype & ~BM_ALL_NOLOOP) == 0);
+ BLI_assert((htype & ~BM_ALL_NOLOOP) == 0);
- /* force recalc */
- BM_mesh_elem_table_free(bm, BM_ALL_NOLOOP);
- BM_mesh_elem_table_ensure(bm, htype);
+ /* force recalc */
+ BM_mesh_elem_table_free(bm, BM_ALL_NOLOOP);
+ BM_mesh_elem_table_ensure(bm, htype);
}
void BM_mesh_elem_table_free(BMesh *bm, const char htype)
{
- if (htype & BM_VERT) {
- MEM_SAFE_FREE(bm->vtable);
- }
+ if (htype & BM_VERT) {
+ MEM_SAFE_FREE(bm->vtable);
+ }
- if (htype & BM_EDGE) {
- MEM_SAFE_FREE(bm->etable);
- }
+ if (htype & BM_EDGE) {
+ MEM_SAFE_FREE(bm->etable);
+ }
- if (htype & BM_FACE) {
- MEM_SAFE_FREE(bm->ftable);
- }
+ if (htype & BM_FACE) {
+ MEM_SAFE_FREE(bm->ftable);
+ }
}
BMVert *BM_vert_at_index_find(BMesh *bm, const int index)
{
- return BLI_mempool_findelem(bm->vpool, index);
+ return BLI_mempool_findelem(bm->vpool, index);
}
BMEdge *BM_edge_at_index_find(BMesh *bm, const int index)
{
- return BLI_mempool_findelem(bm->epool, index);
+ return BLI_mempool_findelem(bm->epool, index);
}
BMFace *BM_face_at_index_find(BMesh *bm, const int index)
{
- return BLI_mempool_findelem(bm->fpool, index);
+ return BLI_mempool_findelem(bm->fpool, index);
}
/**
@@ -1953,55 +2015,55 @@ BMFace *BM_face_at_index_find(BMesh *bm, const int index)
*/
BMVert *BM_vert_at_index_find_or_table(BMesh *bm, const int index)
{
- if ((bm->elem_table_dirty & BM_VERT) == 0) {
- return (index < bm->totvert) ? bm->vtable[index] : NULL;
- }
- else {
- return BM_vert_at_index_find(bm, index);
- }
+ if ((bm->elem_table_dirty & BM_VERT) == 0) {
+ return (index < bm->totvert) ? bm->vtable[index] : NULL;
+ }
+ else {
+ return BM_vert_at_index_find(bm, index);
+ }
}
BMEdge *BM_edge_at_index_find_or_table(BMesh *bm, const int index)
{
- if ((bm->elem_table_dirty & BM_EDGE) == 0) {
- return (index < bm->totedge) ? bm->etable[index] : NULL;
- }
- else {
- return BM_edge_at_index_find(bm, index);
- }
+ if ((bm->elem_table_dirty & BM_EDGE) == 0) {
+ return (index < bm->totedge) ? bm->etable[index] : NULL;
+ }
+ else {
+ return BM_edge_at_index_find(bm, index);
+ }
}
BMFace *BM_face_at_index_find_or_table(BMesh *bm, const int index)
{
- if ((bm->elem_table_dirty & BM_FACE) == 0) {
- return (index < bm->totface) ? bm->ftable[index] : NULL;
- }
- else {
- return BM_face_at_index_find(bm, index);
- }
+ if ((bm->elem_table_dirty & BM_FACE) == 0) {
+ return (index < bm->totface) ? bm->ftable[index] : NULL;
+ }
+ else {
+ return BM_face_at_index_find(bm, index);
+ }
}
-
/**
* Return the amount of element of type 'type' in a given bmesh.
*/
int BM_mesh_elem_count(BMesh *bm, const char htype)
{
- BLI_assert((htype & ~BM_ALL_NOLOOP) == 0);
-
- switch (htype) {
- case BM_VERT: return bm->totvert;
- case BM_EDGE: return bm->totedge;
- case BM_FACE: return bm->totface;
- default:
- {
- BLI_assert(0);
- return 0;
- }
- }
+ BLI_assert((htype & ~BM_ALL_NOLOOP) == 0);
+
+ switch (htype) {
+ case BM_VERT:
+ return bm->totvert;
+ case BM_EDGE:
+ return bm->totedge;
+ case BM_FACE:
+ return bm->totface;
+ default: {
+ BLI_assert(0);
+ return 0;
+ }
+ }
}
-
/**
* Remaps the vertices, edges and/or faces of the bmesh as indicated by vert/edge/face_idx arrays
* (xxx_idx[org_index] = new_index).
@@ -2014,281 +2076,277 @@ int BM_mesh_elem_count(BMesh *bm, const char htype)
*
* WARNING: Be careful if you keep pointers to affected BM elements, or arrays, when using this func!
*/
-void BM_mesh_remap(
- BMesh *bm,
- const uint *vert_idx,
- const uint *edge_idx,
- const uint *face_idx)
+void BM_mesh_remap(BMesh *bm, const uint *vert_idx, const uint *edge_idx, const uint *face_idx)
{
- /* Mapping old to new pointers. */
- GHash *vptr_map = NULL, *eptr_map = NULL, *fptr_map = NULL;
- BMIter iter, iterl;
- BMVert *ve;
- BMEdge *ed;
- BMFace *fa;
- BMLoop *lo;
-
- if (!(vert_idx || edge_idx || face_idx)) {
- return;
- }
-
- BM_mesh_elem_table_ensure(
- bm,
- (vert_idx ? BM_VERT : 0) |
- (edge_idx ? BM_EDGE : 0) |
- (face_idx ? BM_FACE : 0));
-
- /* Remap Verts */
- if (vert_idx) {
- BMVert **verts_pool, *verts_copy, **vep;
- int i, totvert = bm->totvert;
- const uint *new_idx;
- /* Special case: Python uses custom - data layers to hold PyObject references.
- * These have to be kept in - place, else the PyObject's we point to, wont point back to us. */
- const int cd_vert_pyptr = CustomData_get_offset(&bm->vdata, CD_BM_ELEM_PYPTR);
-
- /* Init the old-to-new vert pointers mapping */
- vptr_map = BLI_ghash_ptr_new_ex("BM_mesh_remap vert pointers mapping", bm->totvert);
-
- /* Make a copy of all vertices. */
- verts_pool = bm->vtable;
- verts_copy = MEM_mallocN(sizeof(BMVert) * totvert, "BM_mesh_remap verts copy");
- void **pyptrs = (cd_vert_pyptr != -1) ? MEM_mallocN(sizeof(void *) * totvert, __func__) : NULL;
- for (i = totvert, ve = verts_copy + totvert - 1, vep = verts_pool + totvert - 1; i--; ve--, vep--) {
- *ve = **vep;
-/* printf("*vep: %p, verts_pool[%d]: %p\n", *vep, i, verts_pool[i]);*/
- if (cd_vert_pyptr != -1) {
- void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)ve), cd_vert_pyptr);
- pyptrs[i] = *pyptr;
- }
- }
-
- /* Copy back verts to their new place, and update old2new pointers mapping. */
- new_idx = vert_idx + totvert - 1;
- ve = verts_copy + totvert - 1;
- vep = verts_pool + totvert - 1; /* old, org pointer */
- for (i = totvert; i--; new_idx--, ve--, vep--) {
- BMVert *new_vep = verts_pool[*new_idx];
- *new_vep = *ve;
-/* printf("mapping vert from %d to %d (%p/%p to %p)\n", i, *new_idx, *vep, verts_pool[i], new_vep);*/
- BLI_ghash_insert(vptr_map, *vep, new_vep);
- if (cd_vert_pyptr != -1) {
- void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)new_vep), cd_vert_pyptr);
- *pyptr = pyptrs[*new_idx];
- }
- }
- bm->elem_index_dirty |= BM_VERT;
- bm->elem_table_dirty |= BM_VERT;
-
- MEM_freeN(verts_copy);
- if (pyptrs) {
- MEM_freeN(pyptrs);
- }
- }
-
- /* Remap Edges */
- if (edge_idx) {
- BMEdge **edges_pool, *edges_copy, **edp;
- int i, totedge = bm->totedge;
- const uint *new_idx;
- /* Special case: Python uses custom - data layers to hold PyObject references.
- * These have to be kept in - place, else the PyObject's we point to, wont point back to us. */
- const int cd_edge_pyptr = CustomData_get_offset(&bm->edata, CD_BM_ELEM_PYPTR);
-
- /* Init the old-to-new vert pointers mapping */
- eptr_map = BLI_ghash_ptr_new_ex("BM_mesh_remap edge pointers mapping", bm->totedge);
-
- /* Make a copy of all vertices. */
- edges_pool = bm->etable;
- edges_copy = MEM_mallocN(sizeof(BMEdge) * totedge, "BM_mesh_remap edges copy");
- void **pyptrs = (cd_edge_pyptr != -1) ? MEM_mallocN(sizeof(void *) * totedge, __func__) : NULL;
- for (i = totedge, ed = edges_copy + totedge - 1, edp = edges_pool + totedge - 1; i--; ed--, edp--) {
- *ed = **edp;
- if (cd_edge_pyptr != -1) {
- void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)ed), cd_edge_pyptr);
- pyptrs[i] = *pyptr;
- }
- }
-
- /* Copy back verts to their new place, and update old2new pointers mapping. */
- new_idx = edge_idx + totedge - 1;
- ed = edges_copy + totedge - 1;
- edp = edges_pool + totedge - 1; /* old, org pointer */
- for (i = totedge; i--; new_idx--, ed--, edp--) {
- BMEdge *new_edp = edges_pool[*new_idx];
- *new_edp = *ed;
- BLI_ghash_insert(eptr_map, *edp, new_edp);
-/* printf("mapping edge from %d to %d (%p/%p to %p)\n", i, *new_idx, *edp, edges_pool[i], new_edp);*/
- if (cd_edge_pyptr != -1) {
- void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)new_edp), cd_edge_pyptr);
- *pyptr = pyptrs[*new_idx];
- }
- }
- bm->elem_index_dirty |= BM_EDGE;
- bm->elem_table_dirty |= BM_EDGE;
-
- MEM_freeN(edges_copy);
- if (pyptrs) {
- MEM_freeN(pyptrs);
- }
- }
-
- /* Remap Faces */
- if (face_idx) {
- BMFace **faces_pool, *faces_copy, **fap;
- int i, totface = bm->totface;
- const uint *new_idx;
- /* Special case: Python uses custom - data layers to hold PyObject references.
- * These have to be kept in - place, else the PyObject's we point to, wont point back to us. */
- const int cd_poly_pyptr = CustomData_get_offset(&bm->pdata, CD_BM_ELEM_PYPTR);
-
- /* Init the old-to-new vert pointers mapping */
- fptr_map = BLI_ghash_ptr_new_ex("BM_mesh_remap face pointers mapping", bm->totface);
-
- /* Make a copy of all vertices. */
- faces_pool = bm->ftable;
- faces_copy = MEM_mallocN(sizeof(BMFace) * totface, "BM_mesh_remap faces copy");
- void **pyptrs = (cd_poly_pyptr != -1) ? MEM_mallocN(sizeof(void *) * totface, __func__) : NULL;
- for (i = totface, fa = faces_copy + totface - 1, fap = faces_pool + totface - 1; i--; fa--, fap--) {
- *fa = **fap;
- if (cd_poly_pyptr != -1) {
- void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)fa), cd_poly_pyptr);
- pyptrs[i] = *pyptr;
- }
- }
-
- /* Copy back verts to their new place, and update old2new pointers mapping. */
- new_idx = face_idx + totface - 1;
- fa = faces_copy + totface - 1;
- fap = faces_pool + totface - 1; /* old, org pointer */
- for (i = totface; i--; new_idx--, fa--, fap--) {
- BMFace *new_fap = faces_pool[*new_idx];
- *new_fap = *fa;
- BLI_ghash_insert(fptr_map, *fap, new_fap);
- if (cd_poly_pyptr != -1) {
- void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)new_fap), cd_poly_pyptr);
- *pyptr = pyptrs[*new_idx];
- }
- }
-
- bm->elem_index_dirty |= BM_FACE | BM_LOOP;
- bm->elem_table_dirty |= BM_FACE;
-
- MEM_freeN(faces_copy);
- if (pyptrs) {
- MEM_freeN(pyptrs);
- }
- }
-
- /* And now, fix all vertices/edges/faces/loops pointers! */
- /* Verts' pointers, only edge pointers... */
- if (eptr_map) {
- BM_ITER_MESH (ve, &iter, bm, BM_VERTS_OF_MESH) {
-/* printf("Vert e: %p -> %p\n", ve->e, BLI_ghash_lookup(eptr_map, ve->e));*/
- if (ve->e) {
- ve->e = BLI_ghash_lookup(eptr_map, ve->e);
- BLI_assert(ve->e);
- }
- }
- }
-
- /* Edges' pointers, only vert pointers (as we don't mess with loops!), and - ack! - edge pointers,
- * as we have to handle disklinks... */
- if (vptr_map || eptr_map) {
- BM_ITER_MESH (ed, &iter, bm, BM_EDGES_OF_MESH) {
- if (vptr_map) {
-/* printf("Edge v1: %p -> %p\n", ed->v1, BLI_ghash_lookup(vptr_map, ed->v1));*/
-/* printf("Edge v2: %p -> %p\n", ed->v2, BLI_ghash_lookup(vptr_map, ed->v2));*/
- ed->v1 = BLI_ghash_lookup(vptr_map, ed->v1);
- ed->v2 = BLI_ghash_lookup(vptr_map, ed->v2);
- BLI_assert(ed->v1);
- BLI_assert(ed->v2);
- }
- if (eptr_map) {
-/* printf("Edge v1_disk_link prev: %p -> %p\n", ed->v1_disk_link.prev,*/
-/* BLI_ghash_lookup(eptr_map, ed->v1_disk_link.prev));*/
-/* printf("Edge v1_disk_link next: %p -> %p\n", ed->v1_disk_link.next,*/
-/* BLI_ghash_lookup(eptr_map, ed->v1_disk_link.next));*/
-/* printf("Edge v2_disk_link prev: %p -> %p\n", ed->v2_disk_link.prev,*/
-/* BLI_ghash_lookup(eptr_map, ed->v2_disk_link.prev));*/
-/* printf("Edge v2_disk_link next: %p -> %p\n", ed->v2_disk_link.next,*/
-/* BLI_ghash_lookup(eptr_map, ed->v2_disk_link.next));*/
- ed->v1_disk_link.prev = BLI_ghash_lookup(eptr_map, ed->v1_disk_link.prev);
- ed->v1_disk_link.next = BLI_ghash_lookup(eptr_map, ed->v1_disk_link.next);
- ed->v2_disk_link.prev = BLI_ghash_lookup(eptr_map, ed->v2_disk_link.prev);
- ed->v2_disk_link.next = BLI_ghash_lookup(eptr_map, ed->v2_disk_link.next);
- BLI_assert(ed->v1_disk_link.prev);
- BLI_assert(ed->v1_disk_link.next);
- BLI_assert(ed->v2_disk_link.prev);
- BLI_assert(ed->v2_disk_link.next);
- }
- }
- }
-
- /* Faces' pointers (loops, in fact), always needed... */
- BM_ITER_MESH (fa, &iter, bm, BM_FACES_OF_MESH) {
- BM_ITER_ELEM (lo, &iterl, fa, BM_LOOPS_OF_FACE) {
- if (vptr_map) {
-/* printf("Loop v: %p -> %p\n", lo->v, BLI_ghash_lookup(vptr_map, lo->v));*/
- lo->v = BLI_ghash_lookup(vptr_map, lo->v);
- BLI_assert(lo->v);
- }
- if (eptr_map) {
-/* printf("Loop e: %p -> %p\n", lo->e, BLI_ghash_lookup(eptr_map, lo->e));*/
- lo->e = BLI_ghash_lookup(eptr_map, lo->e);
- BLI_assert(lo->e);
- }
- if (fptr_map) {
-/* printf("Loop f: %p -> %p\n", lo->f, BLI_ghash_lookup(fptr_map, lo->f));*/
- lo->f = BLI_ghash_lookup(fptr_map, lo->f);
- BLI_assert(lo->f);
- }
- }
- }
-
- /* Selection history */
- {
- BMEditSelection *ese;
- for (ese = bm->selected.first; ese; ese = ese->next) {
- switch (ese->htype) {
- case BM_VERT:
- if (vptr_map) {
- ese->ele = BLI_ghash_lookup(vptr_map, ese->ele);
- BLI_assert(ese->ele);
- }
- break;
- case BM_EDGE:
- if (eptr_map) {
- ese->ele = BLI_ghash_lookup(eptr_map, ese->ele);
- BLI_assert(ese->ele);
- }
- break;
- case BM_FACE:
- if (fptr_map) {
- ese->ele = BLI_ghash_lookup(fptr_map, ese->ele);
- BLI_assert(ese->ele);
- }
- break;
- }
- }
- }
-
- if (fptr_map) {
- if (bm->act_face) {
- bm->act_face = BLI_ghash_lookup(fptr_map, bm->act_face);
- BLI_assert(bm->act_face);
- }
- }
-
- if (vptr_map) {
- BLI_ghash_free(vptr_map, NULL, NULL);
- }
- if (eptr_map) {
- BLI_ghash_free(eptr_map, NULL, NULL);
- }
- if (fptr_map) {
- BLI_ghash_free(fptr_map, NULL, NULL);
- }
+ /* Mapping old to new pointers. */
+ GHash *vptr_map = NULL, *eptr_map = NULL, *fptr_map = NULL;
+ BMIter iter, iterl;
+ BMVert *ve;
+ BMEdge *ed;
+ BMFace *fa;
+ BMLoop *lo;
+
+ if (!(vert_idx || edge_idx || face_idx)) {
+ return;
+ }
+
+ BM_mesh_elem_table_ensure(
+ bm, (vert_idx ? BM_VERT : 0) | (edge_idx ? BM_EDGE : 0) | (face_idx ? BM_FACE : 0));
+
+ /* Remap Verts */
+ if (vert_idx) {
+ BMVert **verts_pool, *verts_copy, **vep;
+ int i, totvert = bm->totvert;
+ const uint *new_idx;
+ /* Special case: Python uses custom - data layers to hold PyObject references.
+ * These have to be kept in - place, else the PyObject's we point to, wont point back to us. */
+ const int cd_vert_pyptr = CustomData_get_offset(&bm->vdata, CD_BM_ELEM_PYPTR);
+
+ /* Init the old-to-new vert pointers mapping */
+ vptr_map = BLI_ghash_ptr_new_ex("BM_mesh_remap vert pointers mapping", bm->totvert);
+
+ /* Make a copy of all vertices. */
+ verts_pool = bm->vtable;
+ verts_copy = MEM_mallocN(sizeof(BMVert) * totvert, "BM_mesh_remap verts copy");
+ void **pyptrs = (cd_vert_pyptr != -1) ? MEM_mallocN(sizeof(void *) * totvert, __func__) : NULL;
+ for (i = totvert, ve = verts_copy + totvert - 1, vep = verts_pool + totvert - 1; i--;
+ ve--, vep--) {
+ *ve = **vep;
+ /* printf("*vep: %p, verts_pool[%d]: %p\n", *vep, i, verts_pool[i]);*/
+ if (cd_vert_pyptr != -1) {
+ void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)ve), cd_vert_pyptr);
+ pyptrs[i] = *pyptr;
+ }
+ }
+
+ /* Copy back verts to their new place, and update old2new pointers mapping. */
+ new_idx = vert_idx + totvert - 1;
+ ve = verts_copy + totvert - 1;
+ vep = verts_pool + totvert - 1; /* old, org pointer */
+ for (i = totvert; i--; new_idx--, ve--, vep--) {
+ BMVert *new_vep = verts_pool[*new_idx];
+ *new_vep = *ve;
+ /* printf("mapping vert from %d to %d (%p/%p to %p)\n", i, *new_idx, *vep, verts_pool[i], new_vep);*/
+ BLI_ghash_insert(vptr_map, *vep, new_vep);
+ if (cd_vert_pyptr != -1) {
+ void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)new_vep), cd_vert_pyptr);
+ *pyptr = pyptrs[*new_idx];
+ }
+ }
+ bm->elem_index_dirty |= BM_VERT;
+ bm->elem_table_dirty |= BM_VERT;
+
+ MEM_freeN(verts_copy);
+ if (pyptrs) {
+ MEM_freeN(pyptrs);
+ }
+ }
+
+ /* Remap Edges */
+ if (edge_idx) {
+ BMEdge **edges_pool, *edges_copy, **edp;
+ int i, totedge = bm->totedge;
+ const uint *new_idx;
+ /* Special case: Python uses custom - data layers to hold PyObject references.
+ * These have to be kept in - place, else the PyObject's we point to, wont point back to us. */
+ const int cd_edge_pyptr = CustomData_get_offset(&bm->edata, CD_BM_ELEM_PYPTR);
+
+ /* Init the old-to-new vert pointers mapping */
+ eptr_map = BLI_ghash_ptr_new_ex("BM_mesh_remap edge pointers mapping", bm->totedge);
+
+ /* Make a copy of all vertices. */
+ edges_pool = bm->etable;
+ edges_copy = MEM_mallocN(sizeof(BMEdge) * totedge, "BM_mesh_remap edges copy");
+ void **pyptrs = (cd_edge_pyptr != -1) ? MEM_mallocN(sizeof(void *) * totedge, __func__) : NULL;
+ for (i = totedge, ed = edges_copy + totedge - 1, edp = edges_pool + totedge - 1; i--;
+ ed--, edp--) {
+ *ed = **edp;
+ if (cd_edge_pyptr != -1) {
+ void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)ed), cd_edge_pyptr);
+ pyptrs[i] = *pyptr;
+ }
+ }
+
+ /* Copy back verts to their new place, and update old2new pointers mapping. */
+ new_idx = edge_idx + totedge - 1;
+ ed = edges_copy + totedge - 1;
+ edp = edges_pool + totedge - 1; /* old, org pointer */
+ for (i = totedge; i--; new_idx--, ed--, edp--) {
+ BMEdge *new_edp = edges_pool[*new_idx];
+ *new_edp = *ed;
+ BLI_ghash_insert(eptr_map, *edp, new_edp);
+ /* printf("mapping edge from %d to %d (%p/%p to %p)\n", i, *new_idx, *edp, edges_pool[i], new_edp);*/
+ if (cd_edge_pyptr != -1) {
+ void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)new_edp), cd_edge_pyptr);
+ *pyptr = pyptrs[*new_idx];
+ }
+ }
+ bm->elem_index_dirty |= BM_EDGE;
+ bm->elem_table_dirty |= BM_EDGE;
+
+ MEM_freeN(edges_copy);
+ if (pyptrs) {
+ MEM_freeN(pyptrs);
+ }
+ }
+
+ /* Remap Faces */
+ if (face_idx) {
+ BMFace **faces_pool, *faces_copy, **fap;
+ int i, totface = bm->totface;
+ const uint *new_idx;
+ /* Special case: Python uses custom - data layers to hold PyObject references.
+ * These have to be kept in - place, else the PyObject's we point to, wont point back to us. */
+ const int cd_poly_pyptr = CustomData_get_offset(&bm->pdata, CD_BM_ELEM_PYPTR);
+
+ /* Init the old-to-new vert pointers mapping */
+ fptr_map = BLI_ghash_ptr_new_ex("BM_mesh_remap face pointers mapping", bm->totface);
+
+ /* Make a copy of all vertices. */
+ faces_pool = bm->ftable;
+ faces_copy = MEM_mallocN(sizeof(BMFace) * totface, "BM_mesh_remap faces copy");
+ void **pyptrs = (cd_poly_pyptr != -1) ? MEM_mallocN(sizeof(void *) * totface, __func__) : NULL;
+ for (i = totface, fa = faces_copy + totface - 1, fap = faces_pool + totface - 1; i--;
+ fa--, fap--) {
+ *fa = **fap;
+ if (cd_poly_pyptr != -1) {
+ void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)fa), cd_poly_pyptr);
+ pyptrs[i] = *pyptr;
+ }
+ }
+
+ /* Copy back verts to their new place, and update old2new pointers mapping. */
+ new_idx = face_idx + totface - 1;
+ fa = faces_copy + totface - 1;
+ fap = faces_pool + totface - 1; /* old, org pointer */
+ for (i = totface; i--; new_idx--, fa--, fap--) {
+ BMFace *new_fap = faces_pool[*new_idx];
+ *new_fap = *fa;
+ BLI_ghash_insert(fptr_map, *fap, new_fap);
+ if (cd_poly_pyptr != -1) {
+ void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)new_fap), cd_poly_pyptr);
+ *pyptr = pyptrs[*new_idx];
+ }
+ }
+
+ bm->elem_index_dirty |= BM_FACE | BM_LOOP;
+ bm->elem_table_dirty |= BM_FACE;
+
+ MEM_freeN(faces_copy);
+ if (pyptrs) {
+ MEM_freeN(pyptrs);
+ }
+ }
+
+ /* And now, fix all vertices/edges/faces/loops pointers! */
+ /* Verts' pointers, only edge pointers... */
+ if (eptr_map) {
+ BM_ITER_MESH (ve, &iter, bm, BM_VERTS_OF_MESH) {
+ /* printf("Vert e: %p -> %p\n", ve->e, BLI_ghash_lookup(eptr_map, ve->e));*/
+ if (ve->e) {
+ ve->e = BLI_ghash_lookup(eptr_map, ve->e);
+ BLI_assert(ve->e);
+ }
+ }
+ }
+
+ /* Edges' pointers, only vert pointers (as we don't mess with loops!), and - ack! - edge pointers,
+ * as we have to handle disklinks... */
+ if (vptr_map || eptr_map) {
+ BM_ITER_MESH (ed, &iter, bm, BM_EDGES_OF_MESH) {
+ if (vptr_map) {
+ /* printf("Edge v1: %p -> %p\n", ed->v1, BLI_ghash_lookup(vptr_map, ed->v1));*/
+ /* printf("Edge v2: %p -> %p\n", ed->v2, BLI_ghash_lookup(vptr_map, ed->v2));*/
+ ed->v1 = BLI_ghash_lookup(vptr_map, ed->v1);
+ ed->v2 = BLI_ghash_lookup(vptr_map, ed->v2);
+ BLI_assert(ed->v1);
+ BLI_assert(ed->v2);
+ }
+ if (eptr_map) {
+ /* printf("Edge v1_disk_link prev: %p -> %p\n", ed->v1_disk_link.prev,*/
+ /* BLI_ghash_lookup(eptr_map, ed->v1_disk_link.prev));*/
+ /* printf("Edge v1_disk_link next: %p -> %p\n", ed->v1_disk_link.next,*/
+ /* BLI_ghash_lookup(eptr_map, ed->v1_disk_link.next));*/
+ /* printf("Edge v2_disk_link prev: %p -> %p\n", ed->v2_disk_link.prev,*/
+ /* BLI_ghash_lookup(eptr_map, ed->v2_disk_link.prev));*/
+ /* printf("Edge v2_disk_link next: %p -> %p\n", ed->v2_disk_link.next,*/
+ /* BLI_ghash_lookup(eptr_map, ed->v2_disk_link.next));*/
+ ed->v1_disk_link.prev = BLI_ghash_lookup(eptr_map, ed->v1_disk_link.prev);
+ ed->v1_disk_link.next = BLI_ghash_lookup(eptr_map, ed->v1_disk_link.next);
+ ed->v2_disk_link.prev = BLI_ghash_lookup(eptr_map, ed->v2_disk_link.prev);
+ ed->v2_disk_link.next = BLI_ghash_lookup(eptr_map, ed->v2_disk_link.next);
+ BLI_assert(ed->v1_disk_link.prev);
+ BLI_assert(ed->v1_disk_link.next);
+ BLI_assert(ed->v2_disk_link.prev);
+ BLI_assert(ed->v2_disk_link.next);
+ }
+ }
+ }
+
+ /* Faces' pointers (loops, in fact), always needed... */
+ BM_ITER_MESH (fa, &iter, bm, BM_FACES_OF_MESH) {
+ BM_ITER_ELEM (lo, &iterl, fa, BM_LOOPS_OF_FACE) {
+ if (vptr_map) {
+ /* printf("Loop v: %p -> %p\n", lo->v, BLI_ghash_lookup(vptr_map, lo->v));*/
+ lo->v = BLI_ghash_lookup(vptr_map, lo->v);
+ BLI_assert(lo->v);
+ }
+ if (eptr_map) {
+ /* printf("Loop e: %p -> %p\n", lo->e, BLI_ghash_lookup(eptr_map, lo->e));*/
+ lo->e = BLI_ghash_lookup(eptr_map, lo->e);
+ BLI_assert(lo->e);
+ }
+ if (fptr_map) {
+ /* printf("Loop f: %p -> %p\n", lo->f, BLI_ghash_lookup(fptr_map, lo->f));*/
+ lo->f = BLI_ghash_lookup(fptr_map, lo->f);
+ BLI_assert(lo->f);
+ }
+ }
+ }
+
+ /* Selection history */
+ {
+ BMEditSelection *ese;
+ for (ese = bm->selected.first; ese; ese = ese->next) {
+ switch (ese->htype) {
+ case BM_VERT:
+ if (vptr_map) {
+ ese->ele = BLI_ghash_lookup(vptr_map, ese->ele);
+ BLI_assert(ese->ele);
+ }
+ break;
+ case BM_EDGE:
+ if (eptr_map) {
+ ese->ele = BLI_ghash_lookup(eptr_map, ese->ele);
+ BLI_assert(ese->ele);
+ }
+ break;
+ case BM_FACE:
+ if (fptr_map) {
+ ese->ele = BLI_ghash_lookup(fptr_map, ese->ele);
+ BLI_assert(ese->ele);
+ }
+ break;
+ }
+ }
+ }
+
+ if (fptr_map) {
+ if (bm->act_face) {
+ bm->act_face = BLI_ghash_lookup(fptr_map, bm->act_face);
+ BLI_assert(bm->act_face);
+ }
+ }
+
+ if (vptr_map) {
+ BLI_ghash_free(vptr_map, NULL, NULL);
+ }
+ if (eptr_map) {
+ BLI_ghash_free(eptr_map, NULL, NULL);
+ }
+ if (fptr_map) {
+ BLI_ghash_free(fptr_map, NULL, NULL);
+ }
}
/**
@@ -2297,168 +2355,202 @@ void BM_mesh_remap(
* \note needed for re-sizing elements (adding/removing tool flags)
* but could also be used for packing fragmented bmeshes.
*/
-void BM_mesh_rebuild(
- BMesh *bm, const struct BMeshCreateParams *params,
- BLI_mempool *vpool_dst, BLI_mempool *epool_dst, BLI_mempool *lpool_dst, BLI_mempool *fpool_dst)
+void BM_mesh_rebuild(BMesh *bm,
+ const struct BMeshCreateParams *params,
+ BLI_mempool *vpool_dst,
+ BLI_mempool *epool_dst,
+ BLI_mempool *lpool_dst,
+ BLI_mempool *fpool_dst)
{
- const char remap =
- (vpool_dst ? BM_VERT : 0) |
- (epool_dst ? BM_EDGE : 0) |
- (lpool_dst ? BM_LOOP : 0) |
- (fpool_dst ? BM_FACE : 0);
-
- BMVert **vtable_dst = (remap & BM_VERT) ? MEM_mallocN(bm->totvert * sizeof(BMVert *), __func__) : NULL;
- BMEdge **etable_dst = (remap & BM_EDGE) ? MEM_mallocN(bm->totedge * sizeof(BMEdge *), __func__) : NULL;
- BMLoop **ltable_dst = (remap & BM_LOOP) ? MEM_mallocN(bm->totloop * sizeof(BMLoop *), __func__) : NULL;
- BMFace **ftable_dst = (remap & BM_FACE) ? MEM_mallocN(bm->totface * sizeof(BMFace *), __func__) : NULL;
-
- const bool use_toolflags = params->use_toolflags;
-
- if (remap & BM_VERT) {
- BMIter iter;
- int index;
- BMVert *v_src;
- BM_ITER_MESH_INDEX (v_src, &iter, bm, BM_VERTS_OF_MESH, index) {
- BMVert *v_dst = BLI_mempool_alloc(vpool_dst);
- memcpy(v_dst, v_src, sizeof(BMVert));
- if (use_toolflags) {
- ((BMVert_OFlag *)v_dst)->oflags = bm->vtoolflagpool ? BLI_mempool_calloc(bm->vtoolflagpool) : NULL;
- }
-
- vtable_dst[index] = v_dst;
- BM_elem_index_set(v_src, index); /* set_ok */
- }
- }
-
- if (remap & BM_EDGE) {
- BMIter iter;
- int index;
- BMEdge *e_src;
- BM_ITER_MESH_INDEX (e_src, &iter, bm, BM_EDGES_OF_MESH, index) {
- BMEdge *e_dst = BLI_mempool_alloc(epool_dst);
- memcpy(e_dst, e_src, sizeof(BMEdge));
- if (use_toolflags) {
- ((BMEdge_OFlag *)e_dst)->oflags = bm->etoolflagpool ? BLI_mempool_calloc(bm->etoolflagpool) : NULL;
- }
-
- etable_dst[index] = e_dst;
- BM_elem_index_set(e_src, index); /* set_ok */
- }
- }
-
- if (remap & (BM_LOOP | BM_FACE)) {
- BMIter iter;
- int index, index_loop = 0;
- BMFace *f_src;
- BM_ITER_MESH_INDEX (f_src, &iter, bm, BM_FACES_OF_MESH, index) {
-
- if (remap & BM_FACE) {
- BMFace *f_dst = BLI_mempool_alloc(fpool_dst);
- memcpy(f_dst, f_src, sizeof(BMFace));
- if (use_toolflags) {
- ((BMFace_OFlag *)f_dst)->oflags = bm->ftoolflagpool ? BLI_mempool_calloc(bm->ftoolflagpool) : NULL;
- }
-
- ftable_dst[index] = f_dst;
- BM_elem_index_set(f_src, index); /* set_ok */
- }
-
- /* handle loops */
- if (remap & BM_LOOP) {
- BMLoop *l_iter_src, *l_first_src;
- l_iter_src = l_first_src = BM_FACE_FIRST_LOOP((BMFace *)f_src);
- do {
- BMLoop *l_dst = BLI_mempool_alloc(lpool_dst);
- memcpy(l_dst, l_iter_src, sizeof(BMLoop));
- ltable_dst[index_loop] = l_dst;
- BM_elem_index_set(l_iter_src, index_loop++); /* set_ok */
- } while ((l_iter_src = l_iter_src->next) != l_first_src);
- }
- }
- }
+ const char remap = (vpool_dst ? BM_VERT : 0) | (epool_dst ? BM_EDGE : 0) |
+ (lpool_dst ? BM_LOOP : 0) | (fpool_dst ? BM_FACE : 0);
+
+ BMVert **vtable_dst = (remap & BM_VERT) ? MEM_mallocN(bm->totvert * sizeof(BMVert *), __func__) :
+ NULL;
+ BMEdge **etable_dst = (remap & BM_EDGE) ? MEM_mallocN(bm->totedge * sizeof(BMEdge *), __func__) :
+ NULL;
+ BMLoop **ltable_dst = (remap & BM_LOOP) ? MEM_mallocN(bm->totloop * sizeof(BMLoop *), __func__) :
+ NULL;
+ BMFace **ftable_dst = (remap & BM_FACE) ? MEM_mallocN(bm->totface * sizeof(BMFace *), __func__) :
+ NULL;
+
+ const bool use_toolflags = params->use_toolflags;
+
+ if (remap & BM_VERT) {
+ BMIter iter;
+ int index;
+ BMVert *v_src;
+ BM_ITER_MESH_INDEX (v_src, &iter, bm, BM_VERTS_OF_MESH, index) {
+ BMVert *v_dst = BLI_mempool_alloc(vpool_dst);
+ memcpy(v_dst, v_src, sizeof(BMVert));
+ if (use_toolflags) {
+ ((BMVert_OFlag *)v_dst)->oflags = bm->vtoolflagpool ?
+ BLI_mempool_calloc(bm->vtoolflagpool) :
+ NULL;
+ }
+
+ vtable_dst[index] = v_dst;
+ BM_elem_index_set(v_src, index); /* set_ok */
+ }
+ }
+
+ if (remap & BM_EDGE) {
+ BMIter iter;
+ int index;
+ BMEdge *e_src;
+ BM_ITER_MESH_INDEX (e_src, &iter, bm, BM_EDGES_OF_MESH, index) {
+ BMEdge *e_dst = BLI_mempool_alloc(epool_dst);
+ memcpy(e_dst, e_src, sizeof(BMEdge));
+ if (use_toolflags) {
+ ((BMEdge_OFlag *)e_dst)->oflags = bm->etoolflagpool ?
+ BLI_mempool_calloc(bm->etoolflagpool) :
+ NULL;
+ }
+
+ etable_dst[index] = e_dst;
+ BM_elem_index_set(e_src, index); /* set_ok */
+ }
+ }
+
+ if (remap & (BM_LOOP | BM_FACE)) {
+ BMIter iter;
+ int index, index_loop = 0;
+ BMFace *f_src;
+ BM_ITER_MESH_INDEX (f_src, &iter, bm, BM_FACES_OF_MESH, index) {
+
+ if (remap & BM_FACE) {
+ BMFace *f_dst = BLI_mempool_alloc(fpool_dst);
+ memcpy(f_dst, f_src, sizeof(BMFace));
+ if (use_toolflags) {
+ ((BMFace_OFlag *)f_dst)->oflags = bm->ftoolflagpool ?
+ BLI_mempool_calloc(bm->ftoolflagpool) :
+ NULL;
+ }
+
+ ftable_dst[index] = f_dst;
+ BM_elem_index_set(f_src, index); /* set_ok */
+ }
+
+ /* handle loops */
+ if (remap & BM_LOOP) {
+ BMLoop *l_iter_src, *l_first_src;
+ l_iter_src = l_first_src = BM_FACE_FIRST_LOOP((BMFace *)f_src);
+ do {
+ BMLoop *l_dst = BLI_mempool_alloc(lpool_dst);
+ memcpy(l_dst, l_iter_src, sizeof(BMLoop));
+ ltable_dst[index_loop] = l_dst;
+ BM_elem_index_set(l_iter_src, index_loop++); /* set_ok */
+ } while ((l_iter_src = l_iter_src->next) != l_first_src);
+ }
+ }
+ }
#define MAP_VERT(ele) vtable_dst[BM_elem_index_get(ele)]
#define MAP_EDGE(ele) etable_dst[BM_elem_index_get(ele)]
#define MAP_LOOP(ele) ltable_dst[BM_elem_index_get(ele)]
#define MAP_FACE(ele) ftable_dst[BM_elem_index_get(ele)]
-#define REMAP_VERT(ele) { if (remap & BM_VERT) { ele = MAP_VERT(ele); }} ((void)0)
-#define REMAP_EDGE(ele) { if (remap & BM_EDGE) { ele = MAP_EDGE(ele); }} ((void)0)
-#define REMAP_LOOP(ele) { if (remap & BM_LOOP) { ele = MAP_LOOP(ele); }} ((void)0)
-#define REMAP_FACE(ele) { if (remap & BM_FACE) { ele = MAP_FACE(ele); }} ((void)0)
-
- /* verts */
- {
- for (int i = 0; i < bm->totvert; i++) {
- BMVert *v = vtable_dst[i];
- if (v->e) {
- REMAP_EDGE(v->e);
- }
- }
- }
-
- /* edges */
- {
- for (int i = 0; i < bm->totedge; i++) {
- BMEdge *e = etable_dst[i];
- REMAP_VERT(e->v1);
- REMAP_VERT(e->v2);
- REMAP_EDGE(e->v1_disk_link.next);
- REMAP_EDGE(e->v1_disk_link.prev);
- REMAP_EDGE(e->v2_disk_link.next);
- REMAP_EDGE(e->v2_disk_link.prev);
- if (e->l) {
- REMAP_LOOP(e->l);
- }
- }
- }
-
- /* faces */
- {
- for (int i = 0; i < bm->totface; i++) {
- BMFace *f = ftable_dst[i];
- REMAP_LOOP(f->l_first);
-
- {
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP((BMFace *)f);
- do {
- REMAP_VERT(l_iter->v);
- REMAP_EDGE(l_iter->e);
- REMAP_FACE(l_iter->f);
-
- REMAP_LOOP(l_iter->radial_next);
- REMAP_LOOP(l_iter->radial_prev);
- REMAP_LOOP(l_iter->next);
- REMAP_LOOP(l_iter->prev);
- } while ((l_iter = l_iter->next) != l_first);
- }
- }
- }
-
- for (BMEditSelection *ese = bm->selected.first; ese; ese = ese->next) {
- switch (ese->htype) {
- case BM_VERT:
- if (remap & BM_VERT) {
- ese->ele = (BMElem *)MAP_VERT(ese->ele);
- }
- break;
- case BM_EDGE:
- if (remap & BM_EDGE) {
- ese->ele = (BMElem *)MAP_EDGE(ese->ele);
- }
- break;
- case BM_FACE:
- if (remap & BM_FACE) {
- ese->ele = (BMElem *)MAP_FACE(ese->ele);
- }
- break;
- }
- }
-
- if (bm->act_face) {
- REMAP_FACE(bm->act_face);
- }
+#define REMAP_VERT(ele) \
+ { \
+ if (remap & BM_VERT) { \
+ ele = MAP_VERT(ele); \
+ } \
+ } \
+ ((void)0)
+#define REMAP_EDGE(ele) \
+ { \
+ if (remap & BM_EDGE) { \
+ ele = MAP_EDGE(ele); \
+ } \
+ } \
+ ((void)0)
+#define REMAP_LOOP(ele) \
+ { \
+ if (remap & BM_LOOP) { \
+ ele = MAP_LOOP(ele); \
+ } \
+ } \
+ ((void)0)
+#define REMAP_FACE(ele) \
+ { \
+ if (remap & BM_FACE) { \
+ ele = MAP_FACE(ele); \
+ } \
+ } \
+ ((void)0)
+
+ /* verts */
+ {
+ for (int i = 0; i < bm->totvert; i++) {
+ BMVert *v = vtable_dst[i];
+ if (v->e) {
+ REMAP_EDGE(v->e);
+ }
+ }
+ }
+
+ /* edges */
+ {
+ for (int i = 0; i < bm->totedge; i++) {
+ BMEdge *e = etable_dst[i];
+ REMAP_VERT(e->v1);
+ REMAP_VERT(e->v2);
+ REMAP_EDGE(e->v1_disk_link.next);
+ REMAP_EDGE(e->v1_disk_link.prev);
+ REMAP_EDGE(e->v2_disk_link.next);
+ REMAP_EDGE(e->v2_disk_link.prev);
+ if (e->l) {
+ REMAP_LOOP(e->l);
+ }
+ }
+ }
+
+ /* faces */
+ {
+ for (int i = 0; i < bm->totface; i++) {
+ BMFace *f = ftable_dst[i];
+ REMAP_LOOP(f->l_first);
+
+ {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP((BMFace *)f);
+ do {
+ REMAP_VERT(l_iter->v);
+ REMAP_EDGE(l_iter->e);
+ REMAP_FACE(l_iter->f);
+
+ REMAP_LOOP(l_iter->radial_next);
+ REMAP_LOOP(l_iter->radial_prev);
+ REMAP_LOOP(l_iter->next);
+ REMAP_LOOP(l_iter->prev);
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ }
+ }
+
+ for (BMEditSelection *ese = bm->selected.first; ese; ese = ese->next) {
+ switch (ese->htype) {
+ case BM_VERT:
+ if (remap & BM_VERT) {
+ ese->ele = (BMElem *)MAP_VERT(ese->ele);
+ }
+ break;
+ case BM_EDGE:
+ if (remap & BM_EDGE) {
+ ese->ele = (BMElem *)MAP_EDGE(ese->ele);
+ }
+ break;
+ case BM_FACE:
+ if (remap & BM_FACE) {
+ ese->ele = (BMElem *)MAP_FACE(ese->ele);
+ }
+ break;
+ }
+ }
+
+ if (bm->act_face) {
+ REMAP_FACE(bm->act_face);
+ }
#undef MAP_VERT
#undef MAP_EDGE
@@ -2470,47 +2562,47 @@ void BM_mesh_rebuild(
#undef REMAP_LOOP
#undef REMAP_EDGE
- /* Cleanup, re-use local tables if the current mesh had tables allocated.
- * could use irrespective but it may use more memory then the caller wants (and not be needed). */
- if (remap & BM_VERT) {
- if (bm->vtable) {
- SWAP(BMVert **, vtable_dst, bm->vtable);
- bm->vtable_tot = bm->totvert;
- bm->elem_table_dirty &= ~BM_VERT;
- }
- MEM_freeN(vtable_dst);
- BLI_mempool_destroy(bm->vpool);
- bm->vpool = vpool_dst;
- }
-
- if (remap & BM_EDGE) {
- if (bm->etable) {
- SWAP(BMEdge **, etable_dst, bm->etable);
- bm->etable_tot = bm->totedge;
- bm->elem_table_dirty &= ~BM_EDGE;
- }
- MEM_freeN(etable_dst);
- BLI_mempool_destroy(bm->epool);
- bm->epool = epool_dst;
- }
-
- if (remap & BM_LOOP) {
- /* no loop table */
- MEM_freeN(ltable_dst);
- BLI_mempool_destroy(bm->lpool);
- bm->lpool = lpool_dst;
- }
-
- if (remap & BM_FACE) {
- if (bm->ftable) {
- SWAP(BMFace **, ftable_dst, bm->ftable);
- bm->ftable_tot = bm->totface;
- bm->elem_table_dirty &= ~BM_FACE;
- }
- MEM_freeN(ftable_dst);
- BLI_mempool_destroy(bm->fpool);
- bm->fpool = fpool_dst;
- }
+ /* Cleanup, re-use local tables if the current mesh had tables allocated.
+ * could use irrespective but it may use more memory then the caller wants (and not be needed). */
+ if (remap & BM_VERT) {
+ if (bm->vtable) {
+ SWAP(BMVert **, vtable_dst, bm->vtable);
+ bm->vtable_tot = bm->totvert;
+ bm->elem_table_dirty &= ~BM_VERT;
+ }
+ MEM_freeN(vtable_dst);
+ BLI_mempool_destroy(bm->vpool);
+ bm->vpool = vpool_dst;
+ }
+
+ if (remap & BM_EDGE) {
+ if (bm->etable) {
+ SWAP(BMEdge **, etable_dst, bm->etable);
+ bm->etable_tot = bm->totedge;
+ bm->elem_table_dirty &= ~BM_EDGE;
+ }
+ MEM_freeN(etable_dst);
+ BLI_mempool_destroy(bm->epool);
+ bm->epool = epool_dst;
+ }
+
+ if (remap & BM_LOOP) {
+ /* no loop table */
+ MEM_freeN(ltable_dst);
+ BLI_mempool_destroy(bm->lpool);
+ bm->lpool = lpool_dst;
+ }
+
+ if (remap & BM_FACE) {
+ if (bm->ftable) {
+ SWAP(BMFace **, ftable_dst, bm->ftable);
+ bm->ftable_tot = bm->totface;
+ bm->elem_table_dirty &= ~BM_FACE;
+ }
+ MEM_freeN(ftable_dst);
+ BLI_mempool_destroy(bm->fpool);
+ bm->fpool = fpool_dst;
+ }
}
/**
@@ -2518,34 +2610,36 @@ void BM_mesh_rebuild(
*/
void BM_mesh_toolflags_set(BMesh *bm, bool use_toolflags)
{
- if (bm->use_toolflags == use_toolflags) {
- return;
- }
-
- const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_BM(bm);
-
- BLI_mempool *vpool_dst = NULL;
- BLI_mempool *epool_dst = NULL;
- BLI_mempool *fpool_dst = NULL;
-
- bm_mempool_init_ex(
- &allocsize, use_toolflags,
- &vpool_dst, &epool_dst, NULL, &fpool_dst);
-
- if (use_toolflags == false) {
- BLI_mempool_destroy(bm->vtoolflagpool);
- BLI_mempool_destroy(bm->etoolflagpool);
- BLI_mempool_destroy(bm->ftoolflagpool);
-
- bm->vtoolflagpool = NULL;
- bm->etoolflagpool = NULL;
- bm->ftoolflagpool = NULL;
- }
-
- BM_mesh_rebuild(
- bm,
- &((struct BMeshCreateParams){.use_toolflags = use_toolflags,}),
- vpool_dst, epool_dst, NULL, fpool_dst);
-
- bm->use_toolflags = use_toolflags;
+ if (bm->use_toolflags == use_toolflags) {
+ return;
+ }
+
+ const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_BM(bm);
+
+ BLI_mempool *vpool_dst = NULL;
+ BLI_mempool *epool_dst = NULL;
+ BLI_mempool *fpool_dst = NULL;
+
+ bm_mempool_init_ex(&allocsize, use_toolflags, &vpool_dst, &epool_dst, NULL, &fpool_dst);
+
+ if (use_toolflags == false) {
+ BLI_mempool_destroy(bm->vtoolflagpool);
+ BLI_mempool_destroy(bm->etoolflagpool);
+ BLI_mempool_destroy(bm->ftoolflagpool);
+
+ bm->vtoolflagpool = NULL;
+ bm->etoolflagpool = NULL;
+ bm->ftoolflagpool = NULL;
+ }
+
+ BM_mesh_rebuild(bm,
+ &((struct BMeshCreateParams){
+ .use_toolflags = use_toolflags,
+ }),
+ vpool_dst,
+ epool_dst,
+ NULL,
+ fpool_dst);
+
+ bm->use_toolflags = use_toolflags;
}
diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h
index 6f340411b00..d0cf50a7894 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.h
+++ b/source/blender/bmesh/intern/bmesh_mesh.h
@@ -25,31 +25,39 @@ struct BMAllocTemplate;
struct BMLoopNorEditDataArray;
struct MLoopNorSpaceArray;
-void BM_mesh_elem_toolflags_ensure(BMesh *bm);
-void BM_mesh_elem_toolflags_clear(BMesh *bm);
+void BM_mesh_elem_toolflags_ensure(BMesh *bm);
+void BM_mesh_elem_toolflags_clear(BMesh *bm);
struct BMeshCreateParams {
- uint use_toolflags : 1;
+ uint use_toolflags : 1;
};
-BMesh *BM_mesh_create(
- const struct BMAllocTemplate *allocsize,
- const struct BMeshCreateParams *params);
+BMesh *BM_mesh_create(const struct BMAllocTemplate *allocsize,
+ const struct BMeshCreateParams *params);
-void BM_mesh_free(BMesh *bm);
-void BM_mesh_data_free(BMesh *bm);
-void BM_mesh_clear(BMesh *bm);
+void BM_mesh_free(BMesh *bm);
+void BM_mesh_data_free(BMesh *bm);
+void BM_mesh_clear(BMesh *bm);
void BM_mesh_normals_update(BMesh *bm);
-void BM_verts_calc_normal_vcos(BMesh *bm, const float (*fnos)[3], const float (*vcos)[3], float (*vnos)[3]);
-void BM_loops_calc_normal_vcos(
- BMesh *bm, const float(*vcos)[3], const float(*vnos)[3], const float(*pnos)[3],
- const bool use_split_normals, const float split_angle, float(*r_lnos)[3],
- struct MLoopNorSpaceArray *r_lnors_spacearr, short(*clnors_data)[2],
- const int cd_loop_clnors_offset, const bool do_rebuild);
+void BM_verts_calc_normal_vcos(BMesh *bm,
+ const float (*fnos)[3],
+ const float (*vcos)[3],
+ float (*vnos)[3]);
+void BM_loops_calc_normal_vcos(BMesh *bm,
+ const float (*vcos)[3],
+ const float (*vnos)[3],
+ const float (*pnos)[3],
+ const bool use_split_normals,
+ const float split_angle,
+ float (*r_lnos)[3],
+ struct MLoopNorSpaceArray *r_lnors_spacearr,
+ short (*clnors_data)[2],
+ const int cd_loop_clnors_offset,
+ const bool do_rebuild);
bool BM_loop_check_cyclic_smooth_fan(BMLoop *l_curr);
-void BM_lnorspacearr_store(BMesh *bm, float(*r_lnors)[3]);
+void BM_lnorspacearr_store(BMesh *bm, float (*r_lnors)[3]);
void BM_lnorspace_invalidate(BMesh *bm, const bool do_invalidate_all);
void BM_lnorspace_rebuild(BMesh *bm, bool preserve_clnor);
void BM_lnorspace_update(BMesh *bm);
@@ -63,7 +71,6 @@ struct BMLoopNorEditDataArray *BM_loop_normal_editdata_array_init(BMesh *bm);
void BM_loop_normal_editdata_array_free(struct BMLoopNorEditDataArray *lnors_ed_arr);
int BM_total_loop_select(BMesh *bm);
-
void BM_edges_sharp_from_angle_set(BMesh *bm, const float split_angle);
void bmesh_edit_begin(BMesh *bm, const BMOpTypeFlag type_flag);
@@ -72,8 +79,7 @@ void bmesh_edit_end(BMesh *bm, const BMOpTypeFlag type_flag);
void BM_mesh_elem_index_ensure_ex(BMesh *bm, const char htype, int elem_offset[4]);
void BM_mesh_elem_index_ensure(BMesh *bm, const char hflag);
void BM_mesh_elem_index_validate(
- BMesh *bm, const char *location, const char *func,
- const char *msg_a, const char *msg_b);
+ BMesh *bm, const char *location, const char *func, const char *msg_a, const char *msg_b);
void BM_mesh_toolflags_set(BMesh *bm, bool use_toolflags);
@@ -81,27 +87,27 @@ void BM_mesh_toolflags_set(BMesh *bm, bool use_toolflags);
bool BM_mesh_elem_table_check(BMesh *bm);
#endif
-void BM_mesh_elem_table_ensure(BMesh *bm, const char htype);
-void BM_mesh_elem_table_init(BMesh *bm, const char htype);
-void BM_mesh_elem_table_free(BMesh *bm, const char htype);
+void BM_mesh_elem_table_ensure(BMesh *bm, const char htype);
+void BM_mesh_elem_table_init(BMesh *bm, const char htype);
+void BM_mesh_elem_table_free(BMesh *bm, const char htype);
BLI_INLINE BMVert *BM_vert_at_index(BMesh *bm, const int index)
{
- BLI_assert((index >= 0) && (index < bm->totvert));
- BLI_assert((bm->elem_table_dirty & BM_VERT) == 0);
- return bm->vtable[index];
+ BLI_assert((index >= 0) && (index < bm->totvert));
+ BLI_assert((bm->elem_table_dirty & BM_VERT) == 0);
+ return bm->vtable[index];
}
BLI_INLINE BMEdge *BM_edge_at_index(BMesh *bm, const int index)
{
- BLI_assert((index >= 0) && (index < bm->totedge));
- BLI_assert((bm->elem_table_dirty & BM_EDGE) == 0);
- return bm->etable[index];
+ BLI_assert((index >= 0) && (index < bm->totedge));
+ BLI_assert((bm->elem_table_dirty & BM_EDGE) == 0);
+ return bm->etable[index];
}
BLI_INLINE BMFace *BM_face_at_index(BMesh *bm, const int index)
{
- BLI_assert((index >= 0) && (index < bm->totface));
- BLI_assert((bm->elem_table_dirty & BM_FACE) == 0);
- return bm->ftable[index];
+ BLI_assert((index >= 0) && (index < bm->totface));
+ BLI_assert((bm->elem_table_dirty & BM_FACE) == 0);
+ return bm->ftable[index];
}
BMVert *BM_vert_at_index_find(BMesh *bm, const int index);
@@ -114,43 +120,42 @@ BMFace *BM_face_at_index_find_or_table(BMesh *bm, const int index);
// XXX
-int BM_mesh_elem_count(BMesh *bm, const char htype);
+int BM_mesh_elem_count(BMesh *bm, const char htype);
-void BM_mesh_remap(
- BMesh *bm,
- const uint *vert_idx,
- const uint *edge_idx,
- const uint *face_idx);
+void BM_mesh_remap(BMesh *bm, const uint *vert_idx, const uint *edge_idx, const uint *face_idx);
-void BM_mesh_rebuild(
- BMesh *bm, const struct BMeshCreateParams *params,
- struct BLI_mempool *vpool, struct BLI_mempool *epool, struct BLI_mempool *lpool, struct BLI_mempool *fpool);
+void BM_mesh_rebuild(BMesh *bm,
+ const struct BMeshCreateParams *params,
+ struct BLI_mempool *vpool,
+ struct BLI_mempool *epool,
+ struct BLI_mempool *lpool,
+ struct BLI_mempool *fpool);
typedef struct BMAllocTemplate {
- int totvert, totedge, totloop, totface;
+ int totvert, totedge, totloop, totface;
} BMAllocTemplate;
extern const BMAllocTemplate bm_mesh_allocsize_default;
extern const BMAllocTemplate bm_mesh_chunksize_default;
-#define BMALLOC_TEMPLATE_FROM_BM(bm) { (CHECK_TYPE_INLINE(bm, BMesh *), \
- (bm)->totvert), (bm)->totedge, (bm)->totloop, (bm)->totface}
-
-#define _VA_BMALLOC_TEMPLATE_FROM_ME_1(me) { \
- (CHECK_TYPE_INLINE(me, Mesh *), \
- (me)->totvert), \
- (me)->totedge, \
- (me)->totloop, \
- (me)->totpoly, \
-}
-#define _VA_BMALLOC_TEMPLATE_FROM_ME_2(me_a, me_b) { \
- (CHECK_TYPE_INLINE(me_a, Mesh *), \
- CHECK_TYPE_INLINE(me_b, Mesh *), \
- (me_a)->totvert + (me_b)->totvert), \
- (me_a)->totedge + (me_b)->totedge, \
- (me_a)->totloop + (me_b)->totloop, \
- (me_a)->totpoly + (me_b)->totpoly, \
-}
-#define BMALLOC_TEMPLATE_FROM_ME(...) VA_NARGS_CALL_OVERLOAD(_VA_BMALLOC_TEMPLATE_FROM_ME_, __VA_ARGS__)
+#define BMALLOC_TEMPLATE_FROM_BM(bm) \
+ { \
+ (CHECK_TYPE_INLINE(bm, BMesh *), (bm)->totvert), (bm)->totedge, (bm)->totloop, (bm)->totface \
+ }
+
+#define _VA_BMALLOC_TEMPLATE_FROM_ME_1(me) \
+ { \
+ (CHECK_TYPE_INLINE(me, Mesh *), (me)->totvert), (me)->totedge, (me)->totloop, (me)->totpoly, \
+ }
+#define _VA_BMALLOC_TEMPLATE_FROM_ME_2(me_a, me_b) \
+ { \
+ (CHECK_TYPE_INLINE(me_a, Mesh *), \
+ CHECK_TYPE_INLINE(me_b, Mesh *), \
+ (me_a)->totvert + (me_b)->totvert), \
+ (me_a)->totedge + (me_b)->totedge, (me_a)->totloop + (me_b)->totloop, \
+ (me_a)->totpoly + (me_b)->totpoly, \
+ }
+#define BMALLOC_TEMPLATE_FROM_ME(...) \
+ VA_NARGS_CALL_OVERLOAD(_VA_BMALLOC_TEMPLATE_FROM_ME_, __VA_ARGS__)
#endif /* __BMESH_MESH_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c
index 66cd3a0b30c..f2db451888a 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_conv.c
+++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c
@@ -87,87 +87,85 @@
void BM_mesh_cd_flag_ensure(BMesh *bm, Mesh *mesh, const char cd_flag)
{
- const char cd_flag_all = BM_mesh_cd_flag_from_bmesh(bm) | cd_flag;
- BM_mesh_cd_flag_apply(bm, cd_flag_all);
- if (mesh) {
- mesh->cd_flag = cd_flag_all;
- }
+ const char cd_flag_all = BM_mesh_cd_flag_from_bmesh(bm) | cd_flag;
+ BM_mesh_cd_flag_apply(bm, cd_flag_all);
+ if (mesh) {
+ mesh->cd_flag = cd_flag_all;
+ }
}
void BM_mesh_cd_flag_apply(BMesh *bm, const char cd_flag)
{
- /* CustomData_bmesh_init_pool() must run first */
- BLI_assert(bm->vdata.totlayer == 0 || bm->vdata.pool != NULL);
- BLI_assert(bm->edata.totlayer == 0 || bm->edata.pool != NULL);
- BLI_assert(bm->pdata.totlayer == 0 || bm->pdata.pool != NULL);
-
- if (cd_flag & ME_CDFLAG_VERT_BWEIGHT) {
- if (!CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) {
- BM_data_layer_add(bm, &bm->vdata, CD_BWEIGHT);
- }
- }
- else {
- if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) {
- BM_data_layer_free(bm, &bm->vdata, CD_BWEIGHT);
- }
- }
-
- if (cd_flag & ME_CDFLAG_EDGE_BWEIGHT) {
- if (!CustomData_has_layer(&bm->edata, CD_BWEIGHT)) {
- BM_data_layer_add(bm, &bm->edata, CD_BWEIGHT);
- }
- }
- else {
- if (CustomData_has_layer(&bm->edata, CD_BWEIGHT)) {
- BM_data_layer_free(bm, &bm->edata, CD_BWEIGHT);
- }
- }
-
- if (cd_flag & ME_CDFLAG_EDGE_CREASE) {
- if (!CustomData_has_layer(&bm->edata, CD_CREASE)) {
- BM_data_layer_add(bm, &bm->edata, CD_CREASE);
- }
- }
- else {
- if (CustomData_has_layer(&bm->edata, CD_CREASE)) {
- BM_data_layer_free(bm, &bm->edata, CD_CREASE);
- }
- }
+ /* CustomData_bmesh_init_pool() must run first */
+ BLI_assert(bm->vdata.totlayer == 0 || bm->vdata.pool != NULL);
+ BLI_assert(bm->edata.totlayer == 0 || bm->edata.pool != NULL);
+ BLI_assert(bm->pdata.totlayer == 0 || bm->pdata.pool != NULL);
+
+ if (cd_flag & ME_CDFLAG_VERT_BWEIGHT) {
+ if (!CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) {
+ BM_data_layer_add(bm, &bm->vdata, CD_BWEIGHT);
+ }
+ }
+ else {
+ if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) {
+ BM_data_layer_free(bm, &bm->vdata, CD_BWEIGHT);
+ }
+ }
+
+ if (cd_flag & ME_CDFLAG_EDGE_BWEIGHT) {
+ if (!CustomData_has_layer(&bm->edata, CD_BWEIGHT)) {
+ BM_data_layer_add(bm, &bm->edata, CD_BWEIGHT);
+ }
+ }
+ else {
+ if (CustomData_has_layer(&bm->edata, CD_BWEIGHT)) {
+ BM_data_layer_free(bm, &bm->edata, CD_BWEIGHT);
+ }
+ }
+
+ if (cd_flag & ME_CDFLAG_EDGE_CREASE) {
+ if (!CustomData_has_layer(&bm->edata, CD_CREASE)) {
+ BM_data_layer_add(bm, &bm->edata, CD_CREASE);
+ }
+ }
+ else {
+ if (CustomData_has_layer(&bm->edata, CD_CREASE)) {
+ BM_data_layer_free(bm, &bm->edata, CD_CREASE);
+ }
+ }
}
char BM_mesh_cd_flag_from_bmesh(BMesh *bm)
{
- char cd_flag = 0;
- if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) {
- cd_flag |= ME_CDFLAG_VERT_BWEIGHT;
- }
- if (CustomData_has_layer(&bm->edata, CD_BWEIGHT)) {
- cd_flag |= ME_CDFLAG_EDGE_BWEIGHT;
- }
- if (CustomData_has_layer(&bm->edata, CD_CREASE)) {
- cd_flag |= ME_CDFLAG_EDGE_CREASE;
- }
- return cd_flag;
+ char cd_flag = 0;
+ if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) {
+ cd_flag |= ME_CDFLAG_VERT_BWEIGHT;
+ }
+ if (CustomData_has_layer(&bm->edata, CD_BWEIGHT)) {
+ cd_flag |= ME_CDFLAG_EDGE_BWEIGHT;
+ }
+ if (CustomData_has_layer(&bm->edata, CD_CREASE)) {
+ cd_flag |= ME_CDFLAG_EDGE_CREASE;
+ }
+ return cd_flag;
}
/* Static function for alloc (duplicate in modifiers_bmesh.c) */
static BMFace *bm_face_create_from_mpoly(
- MPoly *mp, MLoop *ml,
- BMesh *bm, BMVert **vtable, BMEdge **etable)
+ MPoly *mp, MLoop *ml, BMesh *bm, BMVert **vtable, BMEdge **etable)
{
- BMVert **verts = BLI_array_alloca(verts, mp->totloop);
- BMEdge **edges = BLI_array_alloca(edges, mp->totloop);
- int j;
+ BMVert **verts = BLI_array_alloca(verts, mp->totloop);
+ BMEdge **edges = BLI_array_alloca(edges, mp->totloop);
+ int j;
- for (j = 0; j < mp->totloop; j++, ml++) {
- verts[j] = vtable[ml->v];
- edges[j] = etable[ml->e];
- }
+ for (j = 0; j < mp->totloop; j++, ml++) {
+ verts[j] = vtable[ml->v];
+ edges[j] = etable[ml->e];
+ }
- return BM_face_create(bm, verts, edges, mp->totloop, NULL, BM_CREATE_SKIP_CD);
+ return BM_face_create(bm, verts, edges, mp->totloop, NULL, BM_CREATE_SKIP_CD);
}
-
/**
* \brief Mesh -> BMesh
* \param bm: The mesh to write into, while this is typically a newly created BMesh,
@@ -178,340 +176,338 @@ static BMFace *bm_face_create_from_mpoly(
*
* \warning This function doesn't calculate face normals.
*/
-void BM_mesh_bm_from_me(
- BMesh *bm, const Mesh *me,
- const struct BMeshFromMeshParams *params)
+void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshParams *params)
{
- const bool is_new =
- !(bm->totvert ||
- (bm->vdata.totlayer || bm->edata.totlayer || bm->pdata.totlayer || bm->ldata.totlayer));
- MVert *mvert;
- MEdge *medge;
- MLoop *mloop;
- MPoly *mp;
- KeyBlock *actkey, *block;
- BMVert *v, **vtable = NULL;
- BMEdge *e, **etable = NULL;
- BMFace *f, **ftable = NULL;
- float (*keyco)[3] = NULL;
- int totloops, i;
- CustomData_MeshMasks mask = CD_MASK_BMESH;
- CustomData_MeshMasks_update(&mask, &params->cd_mask_extra);
-
- if (!me || !me->totvert) {
- if (me && is_new) { /*no verts? still copy customdata layout*/
- CustomData_copy(&me->vdata, &bm->vdata, mask.vmask, CD_ASSIGN, 0);
- CustomData_copy(&me->edata, &bm->edata, mask.emask, CD_ASSIGN, 0);
- CustomData_copy(&me->ldata, &bm->ldata, mask.lmask, CD_ASSIGN, 0);
- CustomData_copy(&me->pdata, &bm->pdata, mask.pmask, CD_ASSIGN, 0);
-
- CustomData_bmesh_init_pool(&bm->vdata, me->totvert, BM_VERT);
- CustomData_bmesh_init_pool(&bm->edata, me->totedge, BM_EDGE);
- CustomData_bmesh_init_pool(&bm->ldata, me->totloop, BM_LOOP);
- CustomData_bmesh_init_pool(&bm->pdata, me->totpoly, BM_FACE);
- }
- return; /* sanity check */
- }
-
- if (is_new) {
- CustomData_copy(&me->vdata, &bm->vdata, mask.vmask, CD_CALLOC, 0);
- CustomData_copy(&me->edata, &bm->edata, mask.emask, CD_CALLOC, 0);
- CustomData_copy(&me->ldata, &bm->ldata, mask.lmask, CD_CALLOC, 0);
- CustomData_copy(&me->pdata, &bm->pdata, mask.pmask, CD_CALLOC, 0);
- }
- else {
- CustomData_bmesh_merge(&me->vdata, &bm->vdata, mask.vmask, CD_CALLOC, bm, BM_VERT);
- CustomData_bmesh_merge(&me->edata, &bm->edata, mask.emask, CD_CALLOC, bm, BM_EDGE);
- CustomData_bmesh_merge(&me->ldata, &bm->ldata, mask.lmask, CD_CALLOC, bm, BM_LOOP);
- CustomData_bmesh_merge(&me->pdata, &bm->pdata, mask.pmask, CD_CALLOC, bm, BM_FACE);
- }
-
- /* -------------------------------------------------------------------- */
- /* Shape Key */
- int tot_shape_keys = me->key ? BLI_listbase_count(&me->key->block) : 0;
- if (is_new == false) {
- tot_shape_keys = min_ii(tot_shape_keys, CustomData_number_of_layers(&bm->vdata, CD_SHAPEKEY));
- }
- const float (**shape_key_table)[3] = tot_shape_keys ? BLI_array_alloca(shape_key_table, tot_shape_keys) : NULL;
-
- if ((params->active_shapekey != 0) && (me->key != NULL)) {
- actkey = BLI_findlink(&me->key->block, params->active_shapekey - 1);
- }
- else {
- actkey = NULL;
- }
-
- if (is_new) {
- if (tot_shape_keys || params->add_key_index) {
- CustomData_add_layer(&bm->vdata, CD_SHAPE_KEYINDEX, CD_ASSIGN, NULL, 0);
- }
- }
-
- if (tot_shape_keys) {
- if (is_new) {
- /* check if we need to generate unique ids for the shapekeys.
- * this also exists in the file reading code, but is here for
- * a sanity check */
- if (!me->key->uidgen) {
- fprintf(stderr,
- "%s had to generate shape key uid's in a situation we shouldn't need to! "
- "(bmesh internal error)\n",
- __func__);
-
- me->key->uidgen = 1;
- for (block = me->key->block.first; block; block = block->next) {
- block->uid = me->key->uidgen++;
- }
- }
- }
-
- if (actkey && actkey->totelem == me->totvert) {
- keyco = params->use_shapekey ? actkey->data : NULL;
- if (is_new) {
- bm->shapenr = params->active_shapekey;
- }
- }
-
- for (i = 0, block = me->key->block.first; i < tot_shape_keys; block = block->next, i++) {
- if (is_new) {
- CustomData_add_layer_named(&bm->vdata, CD_SHAPEKEY,
- CD_ASSIGN, NULL, 0, block->name);
- int j = CustomData_get_layer_index_n(&bm->vdata, CD_SHAPEKEY, i);
- bm->vdata.layers[j].uid = block->uid;
- }
- shape_key_table[i] = (const float (*)[3])block->data;
- }
- }
-
- if (is_new) {
- CustomData_bmesh_init_pool(&bm->vdata, me->totvert, BM_VERT);
- CustomData_bmesh_init_pool(&bm->edata, me->totedge, BM_EDGE);
- CustomData_bmesh_init_pool(&bm->ldata, me->totloop, BM_LOOP);
- CustomData_bmesh_init_pool(&bm->pdata, me->totpoly, BM_FACE);
-
- BM_mesh_cd_flag_apply(bm, me->cd_flag);
- }
-
- const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
- const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
- const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE);
- const int cd_shape_key_offset = me->key ? CustomData_get_offset(&bm->vdata, CD_SHAPEKEY) : -1;
- const int cd_shape_keyindex_offset = is_new && (tot_shape_keys || params->add_key_index) ?
- CustomData_get_offset(&bm->vdata, CD_SHAPE_KEYINDEX) : -1;
-
- vtable = MEM_mallocN(sizeof(BMVert **) * me->totvert, __func__);
-
- for (i = 0, mvert = me->mvert; i < me->totvert; i++, mvert++) {
- v = vtable[i] = BM_vert_create(bm, keyco ? keyco[i] : mvert->co, NULL, BM_CREATE_SKIP_CD);
- BM_elem_index_set(v, i); /* set_ok */
-
- /* transfer flag */
- v->head.hflag = BM_vert_flag_from_mflag(mvert->flag & ~SELECT);
-
- /* this is necessary for selection counts to work properly */
- if (mvert->flag & SELECT) {
- BM_vert_select_set(bm, v, true);
- }
-
- normal_short_to_float_v3(v->no, mvert->no);
-
- /* Copy Custom Data */
- CustomData_to_bmesh_block(&me->vdata, &bm->vdata, i, &v->head.data, true);
-
- if (cd_vert_bweight_offset != -1) {
- BM_ELEM_CD_SET_FLOAT(v, cd_vert_bweight_offset, (float)mvert->bweight / 255.0f);
- }
-
- /* set shape key original index */
- if (cd_shape_keyindex_offset != -1) {
- BM_ELEM_CD_SET_INT(v, cd_shape_keyindex_offset, i);
- }
-
- /* set shapekey data */
- if (tot_shape_keys) {
- float (*co_dst)[3] = BM_ELEM_CD_GET_VOID_P(v, cd_shape_key_offset);
- for (int j = 0; j < tot_shape_keys; j++, co_dst++) {
- copy_v3_v3(*co_dst, shape_key_table[j][i]);
- }
- }
- }
- if (is_new) {
- bm->elem_index_dirty &= ~BM_VERT; /* added in order, clear dirty flag */
- }
-
- etable = MEM_mallocN(sizeof(BMEdge **) * me->totedge, __func__);
-
- medge = me->medge;
- for (i = 0; i < me->totedge; i++, medge++) {
- e = etable[i] = BM_edge_create(bm, vtable[medge->v1], vtable[medge->v2], NULL, BM_CREATE_SKIP_CD);
- BM_elem_index_set(e, i); /* set_ok */
-
- /* transfer flags */
- e->head.hflag = BM_edge_flag_from_mflag(medge->flag & ~SELECT);
-
- /* this is necessary for selection counts to work properly */
- if (medge->flag & SELECT) {
- BM_edge_select_set(bm, e, true);
- }
-
- /* Copy Custom Data */
- CustomData_to_bmesh_block(&me->edata, &bm->edata, i, &e->head.data, true);
-
- if (cd_edge_bweight_offset != -1) {
- BM_ELEM_CD_SET_FLOAT(e, cd_edge_bweight_offset, (float)medge->bweight / 255.0f);
- }
- if (cd_edge_crease_offset != -1) {
- BM_ELEM_CD_SET_FLOAT(e, cd_edge_crease_offset, (float)medge->crease / 255.0f);
- }
-
- }
- if (is_new) {
- bm->elem_index_dirty &= ~BM_EDGE; /* added in order, clear dirty flag */
- }
-
- /* only needed for selection. */
- if (me->mselect && me->totselect != 0) {
- ftable = MEM_mallocN(sizeof(BMFace **) * me->totpoly, __func__);
- }
-
- mloop = me->mloop;
- mp = me->mpoly;
- for (i = 0, totloops = 0; i < me->totpoly; i++, mp++) {
- BMLoop *l_iter;
- BMLoop *l_first;
-
- f = bm_face_create_from_mpoly(mp, mloop + mp->loopstart,
- bm, vtable, etable);
- if (ftable != NULL) {
- ftable[i] = f;
- }
-
- if (UNLIKELY(f == NULL)) {
- printf("%s: Warning! Bad face in mesh"
- " \"%s\" at index %d!, skipping\n",
- __func__, me->id.name + 2, i);
- continue;
- }
-
- /* don't use 'i' since we may have skipped the face */
- BM_elem_index_set(f, bm->totface - 1); /* set_ok */
-
- /* transfer flag */
- f->head.hflag = BM_face_flag_from_mflag(mp->flag & ~ME_FACE_SEL);
-
- /* this is necessary for selection counts to work properly */
- if (mp->flag & ME_FACE_SEL) {
- BM_face_select_set(bm, f, true);
- }
-
- f->mat_nr = mp->mat_nr;
- if (i == me->act_face) {
- bm->act_face = f;
- }
-
- int j = mp->loopstart;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- /* don't use 'j' since we may have skipped some faces, hence some loops. */
- BM_elem_index_set(l_iter, totloops++); /* set_ok */
-
- /* Save index of correspsonding MLoop */
- CustomData_to_bmesh_block(&me->ldata, &bm->ldata, j++, &l_iter->head.data, true);
- } while ((l_iter = l_iter->next) != l_first);
-
- /* Copy Custom Data */
- CustomData_to_bmesh_block(&me->pdata, &bm->pdata, i, &f->head.data, true);
-
- if (params->calc_face_normal) {
- BM_face_normal_update(f);
- }
- }
- if (is_new) {
- bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP); /* added in order, clear dirty flag */
- }
-
- /* -------------------------------------------------------------------- */
- /* MSelect clears the array elements (avoid adding multiple times).
- *
- * Take care to keep this last and not use (v/e/ftable) after this.
- */
-
- if (me->mselect && me->totselect != 0) {
- MSelect *msel;
- for (i = 0, msel = me->mselect; i < me->totselect; i++, msel++) {
- BMElem **ele_p;
- switch (msel->type) {
- case ME_VSEL:
- ele_p = (BMElem **)&vtable[msel->index];
- break;
- case ME_ESEL:
- ele_p = (BMElem **)&etable[msel->index];
- break;
- case ME_FSEL:
- ele_p = (BMElem **)&ftable[msel->index];
- break;
- default:
- continue;
- }
-
- if (*ele_p != NULL) {
- BM_select_history_store_notest(bm, *ele_p);
- *ele_p = NULL;
- }
- }
- }
- else {
- BM_select_history_clear(bm);
- }
-
- MEM_freeN(vtable);
- MEM_freeN(etable);
- if (ftable) {
- MEM_freeN(ftable);
- }
+ const bool is_new = !(bm->totvert || (bm->vdata.totlayer || bm->edata.totlayer ||
+ bm->pdata.totlayer || bm->ldata.totlayer));
+ MVert *mvert;
+ MEdge *medge;
+ MLoop *mloop;
+ MPoly *mp;
+ KeyBlock *actkey, *block;
+ BMVert *v, **vtable = NULL;
+ BMEdge *e, **etable = NULL;
+ BMFace *f, **ftable = NULL;
+ float(*keyco)[3] = NULL;
+ int totloops, i;
+ CustomData_MeshMasks mask = CD_MASK_BMESH;
+ CustomData_MeshMasks_update(&mask, &params->cd_mask_extra);
+
+ if (!me || !me->totvert) {
+ if (me && is_new) { /*no verts? still copy customdata layout*/
+ CustomData_copy(&me->vdata, &bm->vdata, mask.vmask, CD_ASSIGN, 0);
+ CustomData_copy(&me->edata, &bm->edata, mask.emask, CD_ASSIGN, 0);
+ CustomData_copy(&me->ldata, &bm->ldata, mask.lmask, CD_ASSIGN, 0);
+ CustomData_copy(&me->pdata, &bm->pdata, mask.pmask, CD_ASSIGN, 0);
+
+ CustomData_bmesh_init_pool(&bm->vdata, me->totvert, BM_VERT);
+ CustomData_bmesh_init_pool(&bm->edata, me->totedge, BM_EDGE);
+ CustomData_bmesh_init_pool(&bm->ldata, me->totloop, BM_LOOP);
+ CustomData_bmesh_init_pool(&bm->pdata, me->totpoly, BM_FACE);
+ }
+ return; /* sanity check */
+ }
+
+ if (is_new) {
+ CustomData_copy(&me->vdata, &bm->vdata, mask.vmask, CD_CALLOC, 0);
+ CustomData_copy(&me->edata, &bm->edata, mask.emask, CD_CALLOC, 0);
+ CustomData_copy(&me->ldata, &bm->ldata, mask.lmask, CD_CALLOC, 0);
+ CustomData_copy(&me->pdata, &bm->pdata, mask.pmask, CD_CALLOC, 0);
+ }
+ else {
+ CustomData_bmesh_merge(&me->vdata, &bm->vdata, mask.vmask, CD_CALLOC, bm, BM_VERT);
+ CustomData_bmesh_merge(&me->edata, &bm->edata, mask.emask, CD_CALLOC, bm, BM_EDGE);
+ CustomData_bmesh_merge(&me->ldata, &bm->ldata, mask.lmask, CD_CALLOC, bm, BM_LOOP);
+ CustomData_bmesh_merge(&me->pdata, &bm->pdata, mask.pmask, CD_CALLOC, bm, BM_FACE);
+ }
+
+ /* -------------------------------------------------------------------- */
+ /* Shape Key */
+ int tot_shape_keys = me->key ? BLI_listbase_count(&me->key->block) : 0;
+ if (is_new == false) {
+ tot_shape_keys = min_ii(tot_shape_keys, CustomData_number_of_layers(&bm->vdata, CD_SHAPEKEY));
+ }
+ const float(**shape_key_table)[3] = tot_shape_keys ?
+ BLI_array_alloca(shape_key_table, tot_shape_keys) :
+ NULL;
+
+ if ((params->active_shapekey != 0) && (me->key != NULL)) {
+ actkey = BLI_findlink(&me->key->block, params->active_shapekey - 1);
+ }
+ else {
+ actkey = NULL;
+ }
+
+ if (is_new) {
+ if (tot_shape_keys || params->add_key_index) {
+ CustomData_add_layer(&bm->vdata, CD_SHAPE_KEYINDEX, CD_ASSIGN, NULL, 0);
+ }
+ }
+
+ if (tot_shape_keys) {
+ if (is_new) {
+ /* check if we need to generate unique ids for the shapekeys.
+ * this also exists in the file reading code, but is here for
+ * a sanity check */
+ if (!me->key->uidgen) {
+ fprintf(stderr,
+ "%s had to generate shape key uid's in a situation we shouldn't need to! "
+ "(bmesh internal error)\n",
+ __func__);
+
+ me->key->uidgen = 1;
+ for (block = me->key->block.first; block; block = block->next) {
+ block->uid = me->key->uidgen++;
+ }
+ }
+ }
+
+ if (actkey && actkey->totelem == me->totvert) {
+ keyco = params->use_shapekey ? actkey->data : NULL;
+ if (is_new) {
+ bm->shapenr = params->active_shapekey;
+ }
+ }
+
+ for (i = 0, block = me->key->block.first; i < tot_shape_keys; block = block->next, i++) {
+ if (is_new) {
+ CustomData_add_layer_named(&bm->vdata, CD_SHAPEKEY, CD_ASSIGN, NULL, 0, block->name);
+ int j = CustomData_get_layer_index_n(&bm->vdata, CD_SHAPEKEY, i);
+ bm->vdata.layers[j].uid = block->uid;
+ }
+ shape_key_table[i] = (const float(*)[3])block->data;
+ }
+ }
+
+ if (is_new) {
+ CustomData_bmesh_init_pool(&bm->vdata, me->totvert, BM_VERT);
+ CustomData_bmesh_init_pool(&bm->edata, me->totedge, BM_EDGE);
+ CustomData_bmesh_init_pool(&bm->ldata, me->totloop, BM_LOOP);
+ CustomData_bmesh_init_pool(&bm->pdata, me->totpoly, BM_FACE);
+
+ BM_mesh_cd_flag_apply(bm, me->cd_flag);
+ }
+
+ const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
+ const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
+ const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE);
+ const int cd_shape_key_offset = me->key ? CustomData_get_offset(&bm->vdata, CD_SHAPEKEY) : -1;
+ const int cd_shape_keyindex_offset = is_new && (tot_shape_keys || params->add_key_index) ?
+ CustomData_get_offset(&bm->vdata, CD_SHAPE_KEYINDEX) :
+ -1;
+
+ vtable = MEM_mallocN(sizeof(BMVert **) * me->totvert, __func__);
+
+ for (i = 0, mvert = me->mvert; i < me->totvert; i++, mvert++) {
+ v = vtable[i] = BM_vert_create(bm, keyco ? keyco[i] : mvert->co, NULL, BM_CREATE_SKIP_CD);
+ BM_elem_index_set(v, i); /* set_ok */
+
+ /* transfer flag */
+ v->head.hflag = BM_vert_flag_from_mflag(mvert->flag & ~SELECT);
+
+ /* this is necessary for selection counts to work properly */
+ if (mvert->flag & SELECT) {
+ BM_vert_select_set(bm, v, true);
+ }
+
+ normal_short_to_float_v3(v->no, mvert->no);
+
+ /* Copy Custom Data */
+ CustomData_to_bmesh_block(&me->vdata, &bm->vdata, i, &v->head.data, true);
+
+ if (cd_vert_bweight_offset != -1) {
+ BM_ELEM_CD_SET_FLOAT(v, cd_vert_bweight_offset, (float)mvert->bweight / 255.0f);
+ }
+
+ /* set shape key original index */
+ if (cd_shape_keyindex_offset != -1) {
+ BM_ELEM_CD_SET_INT(v, cd_shape_keyindex_offset, i);
+ }
+
+ /* set shapekey data */
+ if (tot_shape_keys) {
+ float(*co_dst)[3] = BM_ELEM_CD_GET_VOID_P(v, cd_shape_key_offset);
+ for (int j = 0; j < tot_shape_keys; j++, co_dst++) {
+ copy_v3_v3(*co_dst, shape_key_table[j][i]);
+ }
+ }
+ }
+ if (is_new) {
+ bm->elem_index_dirty &= ~BM_VERT; /* added in order, clear dirty flag */
+ }
+
+ etable = MEM_mallocN(sizeof(BMEdge **) * me->totedge, __func__);
+
+ medge = me->medge;
+ for (i = 0; i < me->totedge; i++, medge++) {
+ e = etable[i] = BM_edge_create(
+ bm, vtable[medge->v1], vtable[medge->v2], NULL, BM_CREATE_SKIP_CD);
+ BM_elem_index_set(e, i); /* set_ok */
+
+ /* transfer flags */
+ e->head.hflag = BM_edge_flag_from_mflag(medge->flag & ~SELECT);
+
+ /* this is necessary for selection counts to work properly */
+ if (medge->flag & SELECT) {
+ BM_edge_select_set(bm, e, true);
+ }
+
+ /* Copy Custom Data */
+ CustomData_to_bmesh_block(&me->edata, &bm->edata, i, &e->head.data, true);
+
+ if (cd_edge_bweight_offset != -1) {
+ BM_ELEM_CD_SET_FLOAT(e, cd_edge_bweight_offset, (float)medge->bweight / 255.0f);
+ }
+ if (cd_edge_crease_offset != -1) {
+ BM_ELEM_CD_SET_FLOAT(e, cd_edge_crease_offset, (float)medge->crease / 255.0f);
+ }
+ }
+ if (is_new) {
+ bm->elem_index_dirty &= ~BM_EDGE; /* added in order, clear dirty flag */
+ }
+
+ /* only needed for selection. */
+ if (me->mselect && me->totselect != 0) {
+ ftable = MEM_mallocN(sizeof(BMFace **) * me->totpoly, __func__);
+ }
+
+ mloop = me->mloop;
+ mp = me->mpoly;
+ for (i = 0, totloops = 0; i < me->totpoly; i++, mp++) {
+ BMLoop *l_iter;
+ BMLoop *l_first;
+
+ f = bm_face_create_from_mpoly(mp, mloop + mp->loopstart, bm, vtable, etable);
+ if (ftable != NULL) {
+ ftable[i] = f;
+ }
+
+ if (UNLIKELY(f == NULL)) {
+ printf(
+ "%s: Warning! Bad face in mesh"
+ " \"%s\" at index %d!, skipping\n",
+ __func__,
+ me->id.name + 2,
+ i);
+ continue;
+ }
+
+ /* don't use 'i' since we may have skipped the face */
+ BM_elem_index_set(f, bm->totface - 1); /* set_ok */
+
+ /* transfer flag */
+ f->head.hflag = BM_face_flag_from_mflag(mp->flag & ~ME_FACE_SEL);
+
+ /* this is necessary for selection counts to work properly */
+ if (mp->flag & ME_FACE_SEL) {
+ BM_face_select_set(bm, f, true);
+ }
+
+ f->mat_nr = mp->mat_nr;
+ if (i == me->act_face) {
+ bm->act_face = f;
+ }
+
+ int j = mp->loopstart;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ /* don't use 'j' since we may have skipped some faces, hence some loops. */
+ BM_elem_index_set(l_iter, totloops++); /* set_ok */
+
+ /* Save index of correspsonding MLoop */
+ CustomData_to_bmesh_block(&me->ldata, &bm->ldata, j++, &l_iter->head.data, true);
+ } while ((l_iter = l_iter->next) != l_first);
+
+ /* Copy Custom Data */
+ CustomData_to_bmesh_block(&me->pdata, &bm->pdata, i, &f->head.data, true);
+
+ if (params->calc_face_normal) {
+ BM_face_normal_update(f);
+ }
+ }
+ if (is_new) {
+ bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP); /* added in order, clear dirty flag */
+ }
+
+ /* -------------------------------------------------------------------- */
+ /* MSelect clears the array elements (avoid adding multiple times).
+ *
+ * Take care to keep this last and not use (v/e/ftable) after this.
+ */
+
+ if (me->mselect && me->totselect != 0) {
+ MSelect *msel;
+ for (i = 0, msel = me->mselect; i < me->totselect; i++, msel++) {
+ BMElem **ele_p;
+ switch (msel->type) {
+ case ME_VSEL:
+ ele_p = (BMElem **)&vtable[msel->index];
+ break;
+ case ME_ESEL:
+ ele_p = (BMElem **)&etable[msel->index];
+ break;
+ case ME_FSEL:
+ ele_p = (BMElem **)&ftable[msel->index];
+ break;
+ default:
+ continue;
+ }
+
+ if (*ele_p != NULL) {
+ BM_select_history_store_notest(bm, *ele_p);
+ *ele_p = NULL;
+ }
+ }
+ }
+ else {
+ BM_select_history_clear(bm);
+ }
+
+ MEM_freeN(vtable);
+ MEM_freeN(etable);
+ if (ftable) {
+ MEM_freeN(ftable);
+ }
}
-
/**
* \brief BMesh -> Mesh
*/
static BMVert **bm_to_mesh_vertex_map(BMesh *bm, int ototvert)
{
- const int cd_shape_keyindex_offset = CustomData_get_offset(&bm->vdata, CD_SHAPE_KEYINDEX);
- BMVert **vertMap = NULL;
- BMVert *eve;
- int i = 0;
- BMIter iter;
-
- /* caller needs to ensure this */
- BLI_assert(ototvert > 0);
-
- vertMap = MEM_callocN(sizeof(*vertMap) * ototvert, "vertMap");
- if (cd_shape_keyindex_offset != -1) {
- BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
- const int keyi = BM_ELEM_CD_GET_INT(eve, cd_shape_keyindex_offset);
- if ((keyi != ORIGINDEX_NONE) &&
- (keyi < ototvert) &&
- /* not fool-proof, but chances are if we have many verts with the same index,
- * we will want to use the first one, since the second is more likely to be a duplicate. */
- (vertMap[keyi] == NULL))
- {
- vertMap[keyi] = eve;
- }
- }
- }
- else {
- BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
- if (i < ototvert) {
- vertMap[i] = eve;
- }
- else {
- break;
- }
- }
- }
-
- return vertMap;
+ const int cd_shape_keyindex_offset = CustomData_get_offset(&bm->vdata, CD_SHAPE_KEYINDEX);
+ BMVert **vertMap = NULL;
+ BMVert *eve;
+ int i = 0;
+ BMIter iter;
+
+ /* caller needs to ensure this */
+ BLI_assert(ototvert > 0);
+
+ vertMap = MEM_callocN(sizeof(*vertMap) * ototvert, "vertMap");
+ if (cd_shape_keyindex_offset != -1) {
+ BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
+ const int keyi = BM_ELEM_CD_GET_INT(eve, cd_shape_keyindex_offset);
+ if ((keyi != ORIGINDEX_NONE) && (keyi < ototvert) &&
+ /* not fool-proof, but chances are if we have many verts with the same index,
+ * we will want to use the first one, since the second is more likely to be a duplicate. */
+ (vertMap[keyi] == NULL)) {
+ vertMap[keyi] = eve;
+ }
+ }
+ }
+ else {
+ BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
+ if (i < ototvert) {
+ vertMap[i] = eve;
+ }
+ else {
+ break;
+ }
+ }
+ }
+
+ return vertMap;
}
/**
@@ -519,475 +515,465 @@ static BMVert **bm_to_mesh_vertex_map(BMesh *bm, int ototvert)
* \note could split this out into a more generic function */
static int bm_to_mesh_shape_layer_index_from_kb(BMesh *bm, KeyBlock *currkey)
{
- int i;
- int j = 0;
-
- for (i = 0; i < bm->vdata.totlayer; i++) {
- if (bm->vdata.layers[i].type == CD_SHAPEKEY) {
- if (currkey->uid == bm->vdata.layers[i].uid) {
- return j;
- }
- j++;
- }
- }
- return -1;
+ int i;
+ int j = 0;
+
+ for (i = 0; i < bm->vdata.totlayer; i++) {
+ if (bm->vdata.layers[i].type == CD_SHAPEKEY) {
+ if (currkey->uid == bm->vdata.layers[i].uid) {
+ return j;
+ }
+ j++;
+ }
+ }
+ return -1;
}
BLI_INLINE void bmesh_quick_edgedraw_flag(MEdge *med, BMEdge *e)
{
- /* this is a cheap way to set the edge draw, its not precise and will
- * pick the first 2 faces an edge uses.
- * The dot comparison is a little arbitrary, but set so that a 5 subd
- * IcoSphere won't vanish but subd 6 will (as with pre-bmesh blender) */
-
-
- if ( /* (med->flag & ME_EDGEDRAW) && */ /* assume to be true */
- (e->l && (e->l != e->l->radial_next)) &&
- (dot_v3v3(e->l->f->no, e->l->radial_next->f->no) > 0.9995f))
- {
- med->flag &= ~ME_EDGEDRAW;
- }
- else {
- med->flag |= ME_EDGEDRAW;
- }
+ /* this is a cheap way to set the edge draw, its not precise and will
+ * pick the first 2 faces an edge uses.
+ * The dot comparison is a little arbitrary, but set so that a 5 subd
+ * IcoSphere won't vanish but subd 6 will (as with pre-bmesh blender) */
+
+ if (/* (med->flag & ME_EDGEDRAW) && */ /* assume to be true */
+ (e->l && (e->l != e->l->radial_next)) &&
+ (dot_v3v3(e->l->f->no, e->l->radial_next->f->no) > 0.9995f)) {
+ med->flag &= ~ME_EDGEDRAW;
+ }
+ else {
+ med->flag |= ME_EDGEDRAW;
+ }
}
/**
*
* \param bmain: May be NULL in case \a calc_object_remap parameter option is not set.
*/
-void BM_mesh_bm_to_me(
- Main *bmain, BMesh *bm, Mesh *me,
- const struct BMeshToMeshParams *params)
+void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMeshParams *params)
{
- MLoop *mloop;
- MPoly *mpoly;
- MVert *mvert, *oldverts;
- MEdge *med, *medge;
- BMVert *v, *eve;
- BMEdge *e;
- BMFace *f;
- BMIter iter;
- int i, j, ototvert;
-
- const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
- const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
- const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE);
-
- ototvert = me->totvert;
-
- /* new vertex block */
- if (bm->totvert == 0) {
- mvert = NULL;
- }
- else {
- mvert = MEM_callocN(bm->totvert * sizeof(MVert), "loadeditbMesh vert");
- }
-
- /* new edge block */
- if (bm->totedge == 0) {
- medge = NULL;
- }
- else {
- medge = MEM_callocN(bm->totedge * sizeof(MEdge), "loadeditbMesh edge");
- }
-
- /* new ngon face block */
- if (bm->totface == 0) {
- mpoly = NULL;
- }
- else {
- mpoly = MEM_callocN(bm->totface * sizeof(MPoly), "loadeditbMesh poly");
- }
-
- /* new loop block */
- if (bm->totloop == 0) {
- mloop = NULL;
- }
- else {
- mloop = MEM_callocN(bm->totloop * sizeof(MLoop), "loadeditbMesh loop");
- }
-
- /* lets save the old verts just in case we are actually working on
- * a key ... we now do processing of the keys at the end */
- oldverts = me->mvert;
-
- /* don't free this yet */
- if (oldverts) {
- CustomData_set_layer(&me->vdata, CD_MVERT, NULL);
- }
-
- /* free custom data */
- CustomData_free(&me->vdata, me->totvert);
- CustomData_free(&me->edata, me->totedge);
- CustomData_free(&me->fdata, me->totface);
- CustomData_free(&me->ldata, me->totloop);
- CustomData_free(&me->pdata, me->totpoly);
-
- /* add new custom data */
- me->totvert = bm->totvert;
- me->totedge = bm->totedge;
- me->totloop = bm->totloop;
- me->totpoly = bm->totface;
- /* will be overwritten with a valid value if 'dotess' is set, otherwise we
- * end up with 'me->totface' and me->mface == NULL which can crash [#28625]
- */
- me->totface = 0;
- me->act_face = -1;
-
- {
- CustomData_MeshMasks mask = CD_MASK_MESH;
- CustomData_MeshMasks_update(&mask, &params->cd_mask_extra);
- CustomData_copy(&bm->vdata, &me->vdata, mask.vmask, CD_CALLOC, me->totvert);
- CustomData_copy(&bm->edata, &me->edata, mask.emask, CD_CALLOC, me->totedge);
- CustomData_copy(&bm->ldata, &me->ldata, mask.lmask, CD_CALLOC, me->totloop);
- CustomData_copy(&bm->pdata, &me->pdata, mask.pmask, CD_CALLOC, me->totpoly);
- }
-
- CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, mvert, me->totvert);
- CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, medge, me->totedge);
- CustomData_add_layer(&me->ldata, CD_MLOOP, CD_ASSIGN, mloop, me->totloop);
- CustomData_add_layer(&me->pdata, CD_MPOLY, CD_ASSIGN, mpoly, me->totpoly);
-
- me->cd_flag = BM_mesh_cd_flag_from_bmesh(bm);
-
- /* this is called again, 'dotess' arg is used there */
- BKE_mesh_update_customdata_pointers(me, 0);
-
- i = 0;
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- copy_v3_v3(mvert->co, v->co);
- normal_float_to_short_v3(mvert->no, v->no);
-
- mvert->flag = BM_vert_flag_to_mflag(v);
-
- BM_elem_index_set(v, i); /* set_inline */
-
- /* copy over customdat */
- CustomData_from_bmesh_block(&bm->vdata, &me->vdata, v->head.data, i);
-
- if (cd_vert_bweight_offset != -1) {
- mvert->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(v, cd_vert_bweight_offset);
- }
-
- i++;
- mvert++;
-
- BM_CHECK_ELEMENT(v);
- }
- bm->elem_index_dirty &= ~BM_VERT;
-
- med = medge;
- i = 0;
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- med->v1 = BM_elem_index_get(e->v1);
- med->v2 = BM_elem_index_get(e->v2);
-
- med->flag = BM_edge_flag_to_mflag(e);
-
- BM_elem_index_set(e, i); /* set_inline */
-
- /* copy over customdata */
- CustomData_from_bmesh_block(&bm->edata, &me->edata, e->head.data, i);
-
- bmesh_quick_edgedraw_flag(med, e);
-
- if (cd_edge_crease_offset != -1) {
- med->crease = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(e, cd_edge_crease_offset);
- }
- if (cd_edge_bweight_offset != -1) {
- med->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(e, cd_edge_bweight_offset);
- }
-
- i++;
- med++;
- BM_CHECK_ELEMENT(e);
- }
- bm->elem_index_dirty &= ~BM_EDGE;
-
- i = 0;
- j = 0;
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- BMLoop *l_iter, *l_first;
- mpoly->loopstart = j;
- mpoly->totloop = f->len;
- mpoly->mat_nr = f->mat_nr;
- mpoly->flag = BM_face_flag_to_mflag(f);
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- mloop->e = BM_elem_index_get(l_iter->e);
- mloop->v = BM_elem_index_get(l_iter->v);
-
- /* copy over customdata */
- CustomData_from_bmesh_block(&bm->ldata, &me->ldata, l_iter->head.data, j);
-
- j++;
- mloop++;
- BM_CHECK_ELEMENT(l_iter);
- BM_CHECK_ELEMENT(l_iter->e);
- BM_CHECK_ELEMENT(l_iter->v);
- } while ((l_iter = l_iter->next) != l_first);
-
- if (f == bm->act_face) {
- me->act_face = i;
- }
-
- /* copy over customdata */
- CustomData_from_bmesh_block(&bm->pdata, &me->pdata, f->head.data, i);
-
- i++;
- mpoly++;
- BM_CHECK_ELEMENT(f);
- }
-
- /* patch hook indices and vertex parents */
- if (params->calc_object_remap && (ototvert > 0)) {
- BLI_assert(bmain != NULL);
- Object *ob;
- ModifierData *md;
- BMVert **vertMap = NULL;
-
- for (ob = bmain->objects.first; ob; ob = ob->id.next) {
- if ((ob->parent) && (ob->parent->data == me) && ELEM(ob->partype, PARVERT1, PARVERT3)) {
-
- if (vertMap == NULL) {
- vertMap = bm_to_mesh_vertex_map(bm, ototvert);
- }
-
- if (ob->par1 < ototvert) {
- eve = vertMap[ob->par1];
- if (eve) {
- ob->par1 = BM_elem_index_get(eve);
- }
- }
- if (ob->par2 < ototvert) {
- eve = vertMap[ob->par2];
- if (eve) {
- ob->par2 = BM_elem_index_get(eve);
- }
- }
- if (ob->par3 < ototvert) {
- eve = vertMap[ob->par3];
- if (eve) {
- ob->par3 = BM_elem_index_get(eve);
- }
- }
-
- }
- if (ob->data == me) {
- for (md = ob->modifiers.first; md; md = md->next) {
- if (md->type == eModifierType_Hook) {
- HookModifierData *hmd = (HookModifierData *) md;
-
- if (vertMap == NULL) {
- vertMap = bm_to_mesh_vertex_map(bm, ototvert);
- }
-
- for (i = j = 0; i < hmd->totindex; i++) {
- if (hmd->indexar[i] < ototvert) {
- eve = vertMap[hmd->indexar[i]];
-
- if (eve) {
- hmd->indexar[j++] = BM_elem_index_get(eve);
- }
- }
- else {
- j++;
- }
- }
-
- hmd->totindex = j;
- }
- }
- }
- }
-
- if (vertMap) {
- MEM_freeN(vertMap);
- }
- }
-
- BKE_mesh_update_customdata_pointers(me, false);
-
- {
- BMEditSelection *selected;
- me->totselect = BLI_listbase_count(&(bm->selected));
-
- MEM_SAFE_FREE(me->mselect);
- if (me->totselect != 0) {
- me->mselect = MEM_mallocN(sizeof(MSelect) * me->totselect, "Mesh selection history");
- }
-
- for (i = 0, selected = bm->selected.first; selected; i++, selected = selected->next) {
- if (selected->htype == BM_VERT) {
- me->mselect[i].type = ME_VSEL;
-
- }
- else if (selected->htype == BM_EDGE) {
- me->mselect[i].type = ME_ESEL;
-
- }
- else if (selected->htype == BM_FACE) {
- me->mselect[i].type = ME_FSEL;
- }
-
- me->mselect[i].index = BM_elem_index_get(selected->ele);
- }
- }
-
- /* see comment below, this logic is in twice */
-
- if (me->key) {
- const int cd_shape_keyindex_offset = CustomData_get_offset(&bm->vdata, CD_SHAPE_KEYINDEX);
-
- KeyBlock *currkey;
- KeyBlock *actkey = BLI_findlink(&me->key->block, bm->shapenr - 1);
-
- float (*ofs)[3] = NULL;
-
- /* go through and find any shapekey customdata layers
- * that might not have corresponding KeyBlocks, and add them if
- * necessary */
- j = 0;
- for (i = 0; i < bm->vdata.totlayer; i++) {
- if (bm->vdata.layers[i].type != CD_SHAPEKEY) {
- continue;
- }
-
- for (currkey = me->key->block.first; currkey; currkey = currkey->next) {
- if (currkey->uid == bm->vdata.layers[i].uid) {
- break;
- }
- }
-
- if (!currkey) {
- currkey = BKE_keyblock_add(me->key, bm->vdata.layers[i].name);
- currkey->uid = bm->vdata.layers[i].uid;
- }
-
- j++;
- }
-
-
- /* editing the base key should update others */
- if ((me->key->type == KEY_RELATIVE) && /* only need offsets for relative shape keys */
- (actkey != NULL) && /* unlikely, but the active key may not be valid if the
- * bmesh and the mesh are out of sync */
- (oldverts != NULL)) /* not used here, but 'oldverts' is used later for applying 'ofs' */
- {
- const bool act_is_basis = BKE_keyblock_is_basis(me->key, bm->shapenr - 1);
-
- /* active key is a base */
- if (act_is_basis && (cd_shape_keyindex_offset != -1)) {
- float (*fp)[3] = actkey->data;
-
- ofs = MEM_callocN(sizeof(float) * 3 * bm->totvert, "currkey->data");
- mvert = me->mvert;
- BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
- const int keyi = BM_ELEM_CD_GET_INT(eve, cd_shape_keyindex_offset);
-
- if (keyi != ORIGINDEX_NONE) {
- sub_v3_v3v3(ofs[i], mvert->co, fp[keyi]);
- }
- else {
- /* if there are new vertices in the mesh, we can't propagate the offset
- * because it will only work for the existing vertices and not the new
- * ones, creating a mess when doing e.g. subdivide + translate */
- MEM_freeN(ofs);
- ofs = NULL;
- break;
- }
-
- mvert++;
- }
- }
- }
-
- for (currkey = me->key->block.first; currkey; currkey = currkey->next) {
- const bool apply_offset = (ofs && (currkey != actkey) && (bm->shapenr - 1 == currkey->relative));
- int cd_shape_offset;
- int keyi;
- float (*ofs_pt)[3] = ofs;
- float *newkey, (*oldkey)[3], *fp;
-
- j = bm_to_mesh_shape_layer_index_from_kb(bm, currkey);
- cd_shape_offset = CustomData_get_n_offset(&bm->vdata, CD_SHAPEKEY, j);
-
-
- fp = newkey = MEM_callocN(me->key->elemsize * bm->totvert, "currkey->data");
- oldkey = currkey->data;
-
- mvert = me->mvert;
- BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
-
- if (currkey == actkey) {
- copy_v3_v3(fp, eve->co);
-
- if (actkey != me->key->refkey) { /* important see bug [#30771] */
- if (cd_shape_keyindex_offset != -1) {
- if (oldverts) {
- keyi = BM_ELEM_CD_GET_INT(eve, cd_shape_keyindex_offset);
- if (keyi != ORIGINDEX_NONE && keyi < currkey->totelem) { /* valid old vertex */
- copy_v3_v3(mvert->co, oldverts[keyi].co);
- }
- }
- }
- }
- }
- else if (j != -1) {
- /* in most cases this runs */
- copy_v3_v3(fp, BM_ELEM_CD_GET_VOID_P(eve, cd_shape_offset));
- }
- else if ((oldkey != NULL) &&
- (cd_shape_keyindex_offset != -1) &&
- ((keyi = BM_ELEM_CD_GET_INT(eve, cd_shape_keyindex_offset)) != ORIGINDEX_NONE) &&
- (keyi < currkey->totelem))
- {
- /* old method of reconstructing keys via vertice's original key indices,
- * currently used if the new method above fails (which is theoretically
- * possible in certain cases of undo) */
- copy_v3_v3(fp, oldkey[keyi]);
- }
- else {
- /* fail! fill in with dummy value */
- copy_v3_v3(fp, mvert->co);
- }
-
- /* propagate edited basis offsets to other shapes */
- if (apply_offset) {
- add_v3_v3(fp, *ofs_pt++);
- /* Apply back new coordinates of offsetted shapekeys into BMesh.
- * Otherwise, in case we call again BM_mesh_bm_to_me on same BMesh, we'll apply diff from previous
- * call to BM_mesh_bm_to_me, to shapekey values from *original creation of the BMesh*. See T50524. */
- copy_v3_v3(BM_ELEM_CD_GET_VOID_P(eve, cd_shape_offset), fp);
- }
-
- fp += 3;
- mvert++;
- }
-
- currkey->totelem = bm->totvert;
- if (currkey->data) {
- MEM_freeN(currkey->data);
- }
- currkey->data = newkey;
- }
-
- if (ofs) {
- MEM_freeN(ofs);
- }
- }
-
- if (oldverts) {
- MEM_freeN(oldverts);
- }
-
- /* topology could be changed, ensure mdisps are ok */
- multires_topology_changed(me);
-
- /* to be removed as soon as COW is enabled by default. */
- BKE_mesh_runtime_clear_geometry(me);
+ MLoop *mloop;
+ MPoly *mpoly;
+ MVert *mvert, *oldverts;
+ MEdge *med, *medge;
+ BMVert *v, *eve;
+ BMEdge *e;
+ BMFace *f;
+ BMIter iter;
+ int i, j, ototvert;
+
+ const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
+ const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
+ const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE);
+
+ ototvert = me->totvert;
+
+ /* new vertex block */
+ if (bm->totvert == 0) {
+ mvert = NULL;
+ }
+ else {
+ mvert = MEM_callocN(bm->totvert * sizeof(MVert), "loadeditbMesh vert");
+ }
+
+ /* new edge block */
+ if (bm->totedge == 0) {
+ medge = NULL;
+ }
+ else {
+ medge = MEM_callocN(bm->totedge * sizeof(MEdge), "loadeditbMesh edge");
+ }
+
+ /* new ngon face block */
+ if (bm->totface == 0) {
+ mpoly = NULL;
+ }
+ else {
+ mpoly = MEM_callocN(bm->totface * sizeof(MPoly), "loadeditbMesh poly");
+ }
+
+ /* new loop block */
+ if (bm->totloop == 0) {
+ mloop = NULL;
+ }
+ else {
+ mloop = MEM_callocN(bm->totloop * sizeof(MLoop), "loadeditbMesh loop");
+ }
+
+ /* lets save the old verts just in case we are actually working on
+ * a key ... we now do processing of the keys at the end */
+ oldverts = me->mvert;
+
+ /* don't free this yet */
+ if (oldverts) {
+ CustomData_set_layer(&me->vdata, CD_MVERT, NULL);
+ }
+
+ /* free custom data */
+ CustomData_free(&me->vdata, me->totvert);
+ CustomData_free(&me->edata, me->totedge);
+ CustomData_free(&me->fdata, me->totface);
+ CustomData_free(&me->ldata, me->totloop);
+ CustomData_free(&me->pdata, me->totpoly);
+
+ /* add new custom data */
+ me->totvert = bm->totvert;
+ me->totedge = bm->totedge;
+ me->totloop = bm->totloop;
+ me->totpoly = bm->totface;
+ /* will be overwritten with a valid value if 'dotess' is set, otherwise we
+ * end up with 'me->totface' and me->mface == NULL which can crash [#28625]
+ */
+ me->totface = 0;
+ me->act_face = -1;
+
+ {
+ CustomData_MeshMasks mask = CD_MASK_MESH;
+ CustomData_MeshMasks_update(&mask, &params->cd_mask_extra);
+ CustomData_copy(&bm->vdata, &me->vdata, mask.vmask, CD_CALLOC, me->totvert);
+ CustomData_copy(&bm->edata, &me->edata, mask.emask, CD_CALLOC, me->totedge);
+ CustomData_copy(&bm->ldata, &me->ldata, mask.lmask, CD_CALLOC, me->totloop);
+ CustomData_copy(&bm->pdata, &me->pdata, mask.pmask, CD_CALLOC, me->totpoly);
+ }
+
+ CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, mvert, me->totvert);
+ CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, medge, me->totedge);
+ CustomData_add_layer(&me->ldata, CD_MLOOP, CD_ASSIGN, mloop, me->totloop);
+ CustomData_add_layer(&me->pdata, CD_MPOLY, CD_ASSIGN, mpoly, me->totpoly);
+
+ me->cd_flag = BM_mesh_cd_flag_from_bmesh(bm);
+
+ /* this is called again, 'dotess' arg is used there */
+ BKE_mesh_update_customdata_pointers(me, 0);
+
+ i = 0;
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ copy_v3_v3(mvert->co, v->co);
+ normal_float_to_short_v3(mvert->no, v->no);
+
+ mvert->flag = BM_vert_flag_to_mflag(v);
+
+ BM_elem_index_set(v, i); /* set_inline */
+
+ /* copy over customdat */
+ CustomData_from_bmesh_block(&bm->vdata, &me->vdata, v->head.data, i);
+
+ if (cd_vert_bweight_offset != -1) {
+ mvert->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(v, cd_vert_bweight_offset);
+ }
+
+ i++;
+ mvert++;
+
+ BM_CHECK_ELEMENT(v);
+ }
+ bm->elem_index_dirty &= ~BM_VERT;
+
+ med = medge;
+ i = 0;
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ med->v1 = BM_elem_index_get(e->v1);
+ med->v2 = BM_elem_index_get(e->v2);
+
+ med->flag = BM_edge_flag_to_mflag(e);
+
+ BM_elem_index_set(e, i); /* set_inline */
+
+ /* copy over customdata */
+ CustomData_from_bmesh_block(&bm->edata, &me->edata, e->head.data, i);
+
+ bmesh_quick_edgedraw_flag(med, e);
+
+ if (cd_edge_crease_offset != -1) {
+ med->crease = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(e, cd_edge_crease_offset);
+ }
+ if (cd_edge_bweight_offset != -1) {
+ med->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(e, cd_edge_bweight_offset);
+ }
+
+ i++;
+ med++;
+ BM_CHECK_ELEMENT(e);
+ }
+ bm->elem_index_dirty &= ~BM_EDGE;
+
+ i = 0;
+ j = 0;
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ BMLoop *l_iter, *l_first;
+ mpoly->loopstart = j;
+ mpoly->totloop = f->len;
+ mpoly->mat_nr = f->mat_nr;
+ mpoly->flag = BM_face_flag_to_mflag(f);
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ mloop->e = BM_elem_index_get(l_iter->e);
+ mloop->v = BM_elem_index_get(l_iter->v);
+
+ /* copy over customdata */
+ CustomData_from_bmesh_block(&bm->ldata, &me->ldata, l_iter->head.data, j);
+
+ j++;
+ mloop++;
+ BM_CHECK_ELEMENT(l_iter);
+ BM_CHECK_ELEMENT(l_iter->e);
+ BM_CHECK_ELEMENT(l_iter->v);
+ } while ((l_iter = l_iter->next) != l_first);
+
+ if (f == bm->act_face) {
+ me->act_face = i;
+ }
+
+ /* copy over customdata */
+ CustomData_from_bmesh_block(&bm->pdata, &me->pdata, f->head.data, i);
+
+ i++;
+ mpoly++;
+ BM_CHECK_ELEMENT(f);
+ }
+
+ /* patch hook indices and vertex parents */
+ if (params->calc_object_remap && (ototvert > 0)) {
+ BLI_assert(bmain != NULL);
+ Object *ob;
+ ModifierData *md;
+ BMVert **vertMap = NULL;
+
+ for (ob = bmain->objects.first; ob; ob = ob->id.next) {
+ if ((ob->parent) && (ob->parent->data == me) && ELEM(ob->partype, PARVERT1, PARVERT3)) {
+
+ if (vertMap == NULL) {
+ vertMap = bm_to_mesh_vertex_map(bm, ototvert);
+ }
+
+ if (ob->par1 < ototvert) {
+ eve = vertMap[ob->par1];
+ if (eve) {
+ ob->par1 = BM_elem_index_get(eve);
+ }
+ }
+ if (ob->par2 < ototvert) {
+ eve = vertMap[ob->par2];
+ if (eve) {
+ ob->par2 = BM_elem_index_get(eve);
+ }
+ }
+ if (ob->par3 < ototvert) {
+ eve = vertMap[ob->par3];
+ if (eve) {
+ ob->par3 = BM_elem_index_get(eve);
+ }
+ }
+ }
+ if (ob->data == me) {
+ for (md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_Hook) {
+ HookModifierData *hmd = (HookModifierData *)md;
+
+ if (vertMap == NULL) {
+ vertMap = bm_to_mesh_vertex_map(bm, ototvert);
+ }
+
+ for (i = j = 0; i < hmd->totindex; i++) {
+ if (hmd->indexar[i] < ototvert) {
+ eve = vertMap[hmd->indexar[i]];
+
+ if (eve) {
+ hmd->indexar[j++] = BM_elem_index_get(eve);
+ }
+ }
+ else {
+ j++;
+ }
+ }
+
+ hmd->totindex = j;
+ }
+ }
+ }
+ }
+
+ if (vertMap) {
+ MEM_freeN(vertMap);
+ }
+ }
+
+ BKE_mesh_update_customdata_pointers(me, false);
+
+ {
+ BMEditSelection *selected;
+ me->totselect = BLI_listbase_count(&(bm->selected));
+
+ MEM_SAFE_FREE(me->mselect);
+ if (me->totselect != 0) {
+ me->mselect = MEM_mallocN(sizeof(MSelect) * me->totselect, "Mesh selection history");
+ }
+
+ for (i = 0, selected = bm->selected.first; selected; i++, selected = selected->next) {
+ if (selected->htype == BM_VERT) {
+ me->mselect[i].type = ME_VSEL;
+ }
+ else if (selected->htype == BM_EDGE) {
+ me->mselect[i].type = ME_ESEL;
+ }
+ else if (selected->htype == BM_FACE) {
+ me->mselect[i].type = ME_FSEL;
+ }
+
+ me->mselect[i].index = BM_elem_index_get(selected->ele);
+ }
+ }
+
+ /* see comment below, this logic is in twice */
+
+ if (me->key) {
+ const int cd_shape_keyindex_offset = CustomData_get_offset(&bm->vdata, CD_SHAPE_KEYINDEX);
+
+ KeyBlock *currkey;
+ KeyBlock *actkey = BLI_findlink(&me->key->block, bm->shapenr - 1);
+
+ float(*ofs)[3] = NULL;
+
+ /* go through and find any shapekey customdata layers
+ * that might not have corresponding KeyBlocks, and add them if
+ * necessary */
+ j = 0;
+ for (i = 0; i < bm->vdata.totlayer; i++) {
+ if (bm->vdata.layers[i].type != CD_SHAPEKEY) {
+ continue;
+ }
+
+ for (currkey = me->key->block.first; currkey; currkey = currkey->next) {
+ if (currkey->uid == bm->vdata.layers[i].uid) {
+ break;
+ }
+ }
+
+ if (!currkey) {
+ currkey = BKE_keyblock_add(me->key, bm->vdata.layers[i].name);
+ currkey->uid = bm->vdata.layers[i].uid;
+ }
+
+ j++;
+ }
+
+ /* editing the base key should update others */
+ if ((me->key->type == KEY_RELATIVE) && /* only need offsets for relative shape keys */
+ (actkey != NULL) && /* unlikely, but the active key may not be valid if the
+ * bmesh and the mesh are out of sync */
+ (oldverts != NULL)) /* not used here, but 'oldverts' is used later for applying 'ofs' */
+ {
+ const bool act_is_basis = BKE_keyblock_is_basis(me->key, bm->shapenr - 1);
+
+ /* active key is a base */
+ if (act_is_basis && (cd_shape_keyindex_offset != -1)) {
+ float(*fp)[3] = actkey->data;
+
+ ofs = MEM_callocN(sizeof(float) * 3 * bm->totvert, "currkey->data");
+ mvert = me->mvert;
+ BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
+ const int keyi = BM_ELEM_CD_GET_INT(eve, cd_shape_keyindex_offset);
+
+ if (keyi != ORIGINDEX_NONE) {
+ sub_v3_v3v3(ofs[i], mvert->co, fp[keyi]);
+ }
+ else {
+ /* if there are new vertices in the mesh, we can't propagate the offset
+ * because it will only work for the existing vertices and not the new
+ * ones, creating a mess when doing e.g. subdivide + translate */
+ MEM_freeN(ofs);
+ ofs = NULL;
+ break;
+ }
+
+ mvert++;
+ }
+ }
+ }
+
+ for (currkey = me->key->block.first; currkey; currkey = currkey->next) {
+ const bool apply_offset = (ofs && (currkey != actkey) &&
+ (bm->shapenr - 1 == currkey->relative));
+ int cd_shape_offset;
+ int keyi;
+ float(*ofs_pt)[3] = ofs;
+ float *newkey, (*oldkey)[3], *fp;
+
+ j = bm_to_mesh_shape_layer_index_from_kb(bm, currkey);
+ cd_shape_offset = CustomData_get_n_offset(&bm->vdata, CD_SHAPEKEY, j);
+
+ fp = newkey = MEM_callocN(me->key->elemsize * bm->totvert, "currkey->data");
+ oldkey = currkey->data;
+
+ mvert = me->mvert;
+ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+
+ if (currkey == actkey) {
+ copy_v3_v3(fp, eve->co);
+
+ if (actkey != me->key->refkey) { /* important see bug [#30771] */
+ if (cd_shape_keyindex_offset != -1) {
+ if (oldverts) {
+ keyi = BM_ELEM_CD_GET_INT(eve, cd_shape_keyindex_offset);
+ if (keyi != ORIGINDEX_NONE && keyi < currkey->totelem) { /* valid old vertex */
+ copy_v3_v3(mvert->co, oldverts[keyi].co);
+ }
+ }
+ }
+ }
+ }
+ else if (j != -1) {
+ /* in most cases this runs */
+ copy_v3_v3(fp, BM_ELEM_CD_GET_VOID_P(eve, cd_shape_offset));
+ }
+ else if ((oldkey != NULL) && (cd_shape_keyindex_offset != -1) &&
+ ((keyi = BM_ELEM_CD_GET_INT(eve, cd_shape_keyindex_offset)) != ORIGINDEX_NONE) &&
+ (keyi < currkey->totelem)) {
+ /* old method of reconstructing keys via vertice's original key indices,
+ * currently used if the new method above fails (which is theoretically
+ * possible in certain cases of undo) */
+ copy_v3_v3(fp, oldkey[keyi]);
+ }
+ else {
+ /* fail! fill in with dummy value */
+ copy_v3_v3(fp, mvert->co);
+ }
+
+ /* propagate edited basis offsets to other shapes */
+ if (apply_offset) {
+ add_v3_v3(fp, *ofs_pt++);
+ /* Apply back new coordinates of offsetted shapekeys into BMesh.
+ * Otherwise, in case we call again BM_mesh_bm_to_me on same BMesh, we'll apply diff from previous
+ * call to BM_mesh_bm_to_me, to shapekey values from *original creation of the BMesh*. See T50524. */
+ copy_v3_v3(BM_ELEM_CD_GET_VOID_P(eve, cd_shape_offset), fp);
+ }
+
+ fp += 3;
+ mvert++;
+ }
+
+ currkey->totelem = bm->totvert;
+ if (currkey->data) {
+ MEM_freeN(currkey->data);
+ }
+ currkey->data = newkey;
+ }
+
+ if (ofs) {
+ MEM_freeN(ofs);
+ }
+ }
+
+ if (oldverts) {
+ MEM_freeN(oldverts);
+ }
+
+ /* topology could be changed, ensure mdisps are ok */
+ multires_topology_changed(me);
+
+ /* to be removed as soon as COW is enabled by default. */
+ BKE_mesh_runtime_clear_geometry(me);
}
/**
@@ -1007,150 +993,150 @@ void BM_mesh_bm_to_me(
*/
void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *cd_mask_extra)
{
- /* must be an empty mesh. */
- BLI_assert(me->totvert == 0);
- BLI_assert(cd_mask_extra == NULL || (cd_mask_extra->vmask & CD_MASK_SHAPEKEY) == 0);
-
- me->totvert = bm->totvert;
- me->totedge = bm->totedge;
- me->totface = 0;
- me->totloop = bm->totloop;
- me->totpoly = bm->totface;
-
- CustomData_add_layer(&me->vdata, CD_ORIGINDEX, CD_CALLOC, NULL, bm->totvert);
- CustomData_add_layer(&me->edata, CD_ORIGINDEX, CD_CALLOC, NULL, bm->totedge);
- CustomData_add_layer(&me->pdata, CD_ORIGINDEX, CD_CALLOC, NULL, bm->totface);
-
- CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, bm->totvert);
- CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, bm->totedge);
- CustomData_add_layer(&me->ldata, CD_MLOOP, CD_CALLOC, NULL, bm->totloop);
- CustomData_add_layer(&me->pdata, CD_MPOLY, CD_CALLOC, NULL, bm->totface);
-
- /* don't process shapekeys, we only feed them through the modifier stack as needed,
- * e.g. for applying modifiers or the like*/
- CustomData_MeshMasks mask = CD_MASK_DERIVEDMESH;
- if (cd_mask_extra != NULL) {
- CustomData_MeshMasks_update(&mask, cd_mask_extra);
- }
- mask.vmask &= ~CD_MASK_SHAPEKEY;
- CustomData_merge(&bm->vdata, &me->vdata, mask.vmask, CD_CALLOC, me->totvert);
- CustomData_merge(&bm->edata, &me->edata, mask.emask, CD_CALLOC, me->totedge);
- CustomData_merge(&bm->ldata, &me->ldata, mask.lmask, CD_CALLOC, me->totloop);
- CustomData_merge(&bm->pdata, &me->pdata, mask.pmask, CD_CALLOC, me->totpoly);
-
- BKE_mesh_update_customdata_pointers(me, false);
-
- BMIter iter;
- BMVert *eve;
- BMEdge *eed;
- BMFace *efa;
- MVert *mvert = me->mvert;
- MEdge *medge = me->medge;
- MLoop *mloop = me->mloop;
- MPoly *mpoly = me->mpoly;
- int *index, add_orig;
- unsigned int i, j;
-
- const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
- const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
- const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE);
-
- me->runtime.deformed_only = true;
-
- /* don't add origindex layer if one already exists */
- add_orig = !CustomData_has_layer(&bm->pdata, CD_ORIGINDEX);
-
- index = CustomData_get_layer(&me->vdata, CD_ORIGINDEX);
-
- BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
- MVert *mv = &mvert[i];
-
- copy_v3_v3(mv->co, eve->co);
-
- BM_elem_index_set(eve, i); /* set_inline */
-
- normal_float_to_short_v3(mv->no, eve->no);
-
- mv->flag = BM_vert_flag_to_mflag(eve);
-
- if (cd_vert_bweight_offset != -1) {
- mv->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eve, cd_vert_bweight_offset);
- }
-
- if (add_orig) {
- *index++ = i;
- }
-
- CustomData_from_bmesh_block(&bm->vdata, &me->vdata, eve->head.data, i);
- }
- bm->elem_index_dirty &= ~BM_VERT;
-
- index = CustomData_get_layer(&me->edata, CD_ORIGINDEX);
- BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
- MEdge *med = &medge[i];
-
- BM_elem_index_set(eed, i); /* set_inline */
-
- med->v1 = BM_elem_index_get(eed->v1);
- med->v2 = BM_elem_index_get(eed->v2);
-
- med->flag = BM_edge_flag_to_mflag(eed);
-
- /* handle this differently to editmode switching,
- * only enable draw for single user edges rather then calculating angle */
- if ((med->flag & ME_EDGEDRAW) == 0) {
- if (eed->l && eed->l == eed->l->radial_next) {
- med->flag |= ME_EDGEDRAW;
- }
- }
-
- if (cd_edge_crease_offset != -1) {
- med->crease = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_crease_offset);
- }
- if (cd_edge_bweight_offset != -1) {
- med->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_bweight_offset);
- }
-
- CustomData_from_bmesh_block(&bm->edata, &me->edata, eed->head.data, i);
- if (add_orig) {
- *index++ = i;
- }
- }
- bm->elem_index_dirty &= ~BM_EDGE;
-
- index = CustomData_get_layer(&me->pdata, CD_ORIGINDEX);
- j = 0;
- BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) {
- BMLoop *l_iter;
- BMLoop *l_first;
- MPoly *mp = &mpoly[i];
-
- BM_elem_index_set(efa, i); /* set_inline */
-
- mp->totloop = efa->len;
- mp->flag = BM_face_flag_to_mflag(efa);
- mp->loopstart = j;
- mp->mat_nr = efa->mat_nr;
+ /* must be an empty mesh. */
+ BLI_assert(me->totvert == 0);
+ BLI_assert(cd_mask_extra == NULL || (cd_mask_extra->vmask & CD_MASK_SHAPEKEY) == 0);
+
+ me->totvert = bm->totvert;
+ me->totedge = bm->totedge;
+ me->totface = 0;
+ me->totloop = bm->totloop;
+ me->totpoly = bm->totface;
+
+ CustomData_add_layer(&me->vdata, CD_ORIGINDEX, CD_CALLOC, NULL, bm->totvert);
+ CustomData_add_layer(&me->edata, CD_ORIGINDEX, CD_CALLOC, NULL, bm->totedge);
+ CustomData_add_layer(&me->pdata, CD_ORIGINDEX, CD_CALLOC, NULL, bm->totface);
+
+ CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, bm->totvert);
+ CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, bm->totedge);
+ CustomData_add_layer(&me->ldata, CD_MLOOP, CD_CALLOC, NULL, bm->totloop);
+ CustomData_add_layer(&me->pdata, CD_MPOLY, CD_CALLOC, NULL, bm->totface);
+
+ /* don't process shapekeys, we only feed them through the modifier stack as needed,
+ * e.g. for applying modifiers or the like*/
+ CustomData_MeshMasks mask = CD_MASK_DERIVEDMESH;
+ if (cd_mask_extra != NULL) {
+ CustomData_MeshMasks_update(&mask, cd_mask_extra);
+ }
+ mask.vmask &= ~CD_MASK_SHAPEKEY;
+ CustomData_merge(&bm->vdata, &me->vdata, mask.vmask, CD_CALLOC, me->totvert);
+ CustomData_merge(&bm->edata, &me->edata, mask.emask, CD_CALLOC, me->totedge);
+ CustomData_merge(&bm->ldata, &me->ldata, mask.lmask, CD_CALLOC, me->totloop);
+ CustomData_merge(&bm->pdata, &me->pdata, mask.pmask, CD_CALLOC, me->totpoly);
+
+ BKE_mesh_update_customdata_pointers(me, false);
+
+ BMIter iter;
+ BMVert *eve;
+ BMEdge *eed;
+ BMFace *efa;
+ MVert *mvert = me->mvert;
+ MEdge *medge = me->medge;
+ MLoop *mloop = me->mloop;
+ MPoly *mpoly = me->mpoly;
+ int *index, add_orig;
+ unsigned int i, j;
+
+ const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
+ const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
+ const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE);
+
+ me->runtime.deformed_only = true;
+
+ /* don't add origindex layer if one already exists */
+ add_orig = !CustomData_has_layer(&bm->pdata, CD_ORIGINDEX);
+
+ index = CustomData_get_layer(&me->vdata, CD_ORIGINDEX);
+
+ BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
+ MVert *mv = &mvert[i];
+
+ copy_v3_v3(mv->co, eve->co);
+
+ BM_elem_index_set(eve, i); /* set_inline */
+
+ normal_float_to_short_v3(mv->no, eve->no);
+
+ mv->flag = BM_vert_flag_to_mflag(eve);
+
+ if (cd_vert_bweight_offset != -1) {
+ mv->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eve, cd_vert_bweight_offset);
+ }
+
+ if (add_orig) {
+ *index++ = i;
+ }
+
+ CustomData_from_bmesh_block(&bm->vdata, &me->vdata, eve->head.data, i);
+ }
+ bm->elem_index_dirty &= ~BM_VERT;
+
+ index = CustomData_get_layer(&me->edata, CD_ORIGINDEX);
+ BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
+ MEdge *med = &medge[i];
+
+ BM_elem_index_set(eed, i); /* set_inline */
+
+ med->v1 = BM_elem_index_get(eed->v1);
+ med->v2 = BM_elem_index_get(eed->v2);
+
+ med->flag = BM_edge_flag_to_mflag(eed);
+
+ /* handle this differently to editmode switching,
+ * only enable draw for single user edges rather then calculating angle */
+ if ((med->flag & ME_EDGEDRAW) == 0) {
+ if (eed->l && eed->l == eed->l->radial_next) {
+ med->flag |= ME_EDGEDRAW;
+ }
+ }
+
+ if (cd_edge_crease_offset != -1) {
+ med->crease = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_crease_offset);
+ }
+ if (cd_edge_bweight_offset != -1) {
+ med->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_bweight_offset);
+ }
+
+ CustomData_from_bmesh_block(&bm->edata, &me->edata, eed->head.data, i);
+ if (add_orig) {
+ *index++ = i;
+ }
+ }
+ bm->elem_index_dirty &= ~BM_EDGE;
+
+ index = CustomData_get_layer(&me->pdata, CD_ORIGINDEX);
+ j = 0;
+ BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) {
+ BMLoop *l_iter;
+ BMLoop *l_first;
+ MPoly *mp = &mpoly[i];
+
+ BM_elem_index_set(efa, i); /* set_inline */
+
+ mp->totloop = efa->len;
+ mp->flag = BM_face_flag_to_mflag(efa);
+ mp->loopstart = j;
+ mp->mat_nr = efa->mat_nr;
- l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
- do {
- mloop->v = BM_elem_index_get(l_iter->v);
- mloop->e = BM_elem_index_get(l_iter->e);
- CustomData_from_bmesh_block(&bm->ldata, &me->ldata, l_iter->head.data, j);
+ l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
+ do {
+ mloop->v = BM_elem_index_get(l_iter->v);
+ mloop->e = BM_elem_index_get(l_iter->e);
+ CustomData_from_bmesh_block(&bm->ldata, &me->ldata, l_iter->head.data, j);
- BM_elem_index_set(l_iter, j); /* set_inline */
+ BM_elem_index_set(l_iter, j); /* set_inline */
- j++;
- mloop++;
- } while ((l_iter = l_iter->next) != l_first);
+ j++;
+ mloop++;
+ } while ((l_iter = l_iter->next) != l_first);
- CustomData_from_bmesh_block(&bm->pdata, &me->pdata, efa->head.data, i);
+ CustomData_from_bmesh_block(&bm->pdata, &me->pdata, efa->head.data, i);
- if (add_orig) {
- *index++ = i;
- }
- }
- bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP);
+ if (add_orig) {
+ *index++ = i;
+ }
+ }
+ bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP);
- me->cd_flag = BM_mesh_cd_flag_from_bmesh(bm);
+ me->cd_flag = BM_mesh_cd_flag_from_bmesh(bm);
}
diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.h b/source/blender/bmesh/intern/bmesh_mesh_conv.h
index 30a1e8bffd5..f0302764a5f 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_conv.h
+++ b/source/blender/bmesh/intern/bmesh_mesh_conv.h
@@ -33,33 +33,31 @@ void BM_mesh_cd_flag_apply(BMesh *bm, const char cd_flag);
char BM_mesh_cd_flag_from_bmesh(BMesh *bm);
struct BMeshFromMeshParams {
- uint calc_face_normal : 1;
- /* add a vertex CD_SHAPE_KEYINDEX layer */
- uint add_key_index : 1;
- /* set vertex coordinates from the shapekey */
- uint use_shapekey : 1;
- /* define the active shape key (index + 1) */
- int active_shapekey;
- struct CustomData_MeshMasks cd_mask_extra;
+ uint calc_face_normal : 1;
+ /* add a vertex CD_SHAPE_KEYINDEX layer */
+ uint add_key_index : 1;
+ /* set vertex coordinates from the shapekey */
+ uint use_shapekey : 1;
+ /* define the active shape key (index + 1) */
+ int active_shapekey;
+ struct CustomData_MeshMasks cd_mask_extra;
};
-void BM_mesh_bm_from_me(
- BMesh *bm, const struct Mesh *me,
- const struct BMeshFromMeshParams *params)
-ATTR_NONNULL(1, 3);
+void BM_mesh_bm_from_me(BMesh *bm, const struct Mesh *me, const struct BMeshFromMeshParams *params)
+ ATTR_NONNULL(1, 3);
struct BMeshToMeshParams {
- /** Update object hook indices & vertex parents. */
- uint calc_object_remap : 1;
- struct CustomData_MeshMasks cd_mask_extra;
+ /** Update object hook indices & vertex parents. */
+ uint calc_object_remap : 1;
+ struct CustomData_MeshMasks cd_mask_extra;
};
-void BM_mesh_bm_to_me(
- struct Main *bmain, BMesh *bm, struct Mesh *me,
- const struct BMeshToMeshParams *params)
-ATTR_NONNULL(2, 3, 4);
-
-void BM_mesh_bm_to_me_for_eval(
- BMesh *bm, struct Mesh *me, const struct CustomData_MeshMasks *cd_mask_extra)
-ATTR_NONNULL(1, 2);
-
+void BM_mesh_bm_to_me(struct Main *bmain,
+ BMesh *bm,
+ struct Mesh *me,
+ const struct BMeshToMeshParams *params) ATTR_NONNULL(2, 3, 4);
+
+void BM_mesh_bm_to_me_for_eval(BMesh *bm,
+ struct Mesh *me,
+ const struct CustomData_MeshMasks *cd_mask_extra)
+ ATTR_NONNULL(1, 2);
#endif /* __BMESH_MESH_CONV_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_mesh_validate.c b/source/blender/bmesh/intern/bmesh_mesh_validate.c
index de0554c0cc2..3b6f63df089 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_validate.c
+++ b/source/blender/bmesh/intern/bmesh_mesh_validate.c
@@ -26,20 +26,29 @@
/* debug builds only */
#ifdef DEBUG
-#include "BLI_utildefines.h"
-#include "BLI_edgehash.h"
+# include "BLI_utildefines.h"
+# include "BLI_edgehash.h"
-#include "bmesh.h"
-
-#include "bmesh_mesh_validate.h"
+# include "bmesh.h"
+# include "bmesh_mesh_validate.h"
/* macro which inserts the function name */
-#if defined __GNUC__
-# define ERRMSG(format, args...) { fprintf(stderr, "%s: " format ", " AT "\n", __func__, ##args); errtot++; } (void)0
-#else
-# define ERRMSG(format, ...) { fprintf(stderr, "%s: " format ", " AT "\n", __func__, __VA_ARGS__); errtot++; } (void)0
-#endif
+# if defined __GNUC__
+# define ERRMSG(format, args...) \
+ { \
+ fprintf(stderr, "%s: " format ", " AT "\n", __func__, ##args); \
+ errtot++; \
+ } \
+ (void)0
+# else
+# define ERRMSG(format, ...) \
+ { \
+ fprintf(stderr, "%s: " format ", " AT "\n", __func__, __VA_ARGS__); \
+ errtot++; \
+ } \
+ (void)0
+# endif
/**
* Check of this BMesh is valid, this function can be slow since its intended to help with debugging.
@@ -48,156 +57,166 @@
*/
bool BM_mesh_validate(BMesh *bm)
{
- EdgeHash *edge_hash = BLI_edgehash_new_ex(__func__, bm->totedge);
- int errtot;
-
- BMIter iter;
- BMVert *v;
- BMEdge *e;
- BMFace *f;
-
- int i, j;
-
- errtot = -1; /* 'ERRMSG' next line will set at zero */
- fprintf(stderr, "\n");
- ERRMSG("This is a debugging function and not intended for general use, running slow test!");
-
- /* force recalc, even if tagged as valid, since this mesh is suspect! */
- bm->elem_index_dirty |= BM_ALL;
- BM_mesh_elem_index_ensure(bm, BM_ALL);
-
- BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
- if (BM_elem_flag_test(v, BM_ELEM_SELECT | BM_ELEM_HIDDEN) == (BM_ELEM_SELECT | BM_ELEM_HIDDEN)) {
- ERRMSG("vert %d: is hidden and selected", i);
- }
-
- if (v->e) {
- if (!BM_vert_in_edge(v->e, v)) {
- ERRMSG("vert %d: is not in its referenced edge: %d", i, BM_elem_index_get(v->e));
- }
- }
- }
-
- /* check edges */
- BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
- void **val_p;
-
- if (e->v1 == e->v2) {
- ERRMSG("edge %d: duplicate index: %d", i, BM_elem_index_get(e->v1));
- }
-
- /* build edgehash at the same time */
- if (BLI_edgehash_ensure_p(edge_hash, BM_elem_index_get(e->v1), BM_elem_index_get(e->v2), &val_p)) {
- BMEdge *e_other = *val_p;
- ERRMSG("edge %d, %d: are duplicates", i, BM_elem_index_get(e_other));
- }
- else {
- *val_p = e;
- }
- }
-
- /* edge radial structure */
- BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
- if (BM_elem_flag_test(e, BM_ELEM_SELECT | BM_ELEM_HIDDEN) == (BM_ELEM_SELECT | BM_ELEM_HIDDEN)) {
- ERRMSG("edge %d: is hidden and selected", i);
- }
-
- if (e->l) {
- BMLoop *l_iter;
- BMLoop *l_first;
-
- j = 0;
-
- l_iter = l_first = e->l;
- /* we could do more checks here, but save for face checks */
- do {
- if (l_iter->e != e) {
- ERRMSG("edge %d: has invalid loop, loop is of face %d", i, BM_elem_index_get(l_iter->f));
- }
- else if (BM_vert_in_edge(e, l_iter->v) == false) {
- ERRMSG("edge %d: has invalid loop with vert not in edge, loop is of face %d",
- i, BM_elem_index_get(l_iter->f));
- }
- else if (BM_vert_in_edge(e, l_iter->next->v) == false) {
- ERRMSG("edge %d: has invalid loop with next vert not in edge, loop is of face %d",
- i, BM_elem_index_get(l_iter->f));
- }
- } while ((l_iter = l_iter->radial_next) != l_first);
- }
- }
-
- /* face structure */
- BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) {
- BMLoop *l_iter;
- BMLoop *l_first;
-
- if (BM_elem_flag_test(f, BM_ELEM_SELECT | BM_ELEM_HIDDEN) == (BM_ELEM_SELECT | BM_ELEM_HIDDEN)) {
- ERRMSG("face %d: is hidden and selected", i);
- }
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
-
- do {
- BM_elem_flag_disable(l_iter, BM_ELEM_INTERNAL_TAG);
- BM_elem_flag_disable(l_iter->v, BM_ELEM_INTERNAL_TAG);
- BM_elem_flag_disable(l_iter->e, BM_ELEM_INTERNAL_TAG);
- } while ((l_iter = l_iter->next) != l_first);
-
- j = 0;
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if (BM_elem_flag_test(l_iter, BM_ELEM_INTERNAL_TAG)) {
- ERRMSG("face %d: has duplicate loop at corner: %d", i, j);
- }
- if (BM_elem_flag_test(l_iter->v, BM_ELEM_INTERNAL_TAG)) {
- ERRMSG("face %d: has duplicate vert: %d, at corner: %d", i, BM_elem_index_get(l_iter->v), j);
- }
- if (BM_elem_flag_test(l_iter->e, BM_ELEM_INTERNAL_TAG)) {
- ERRMSG("face %d: has duplicate edge: %d, at corner: %d", i, BM_elem_index_get(l_iter->e), j);
- }
-
- /* adjacent data checks */
- if (l_iter->f != f) {
- ERRMSG("face %d: has loop that points to face: %d at corner: %d", i, BM_elem_index_get(l_iter->f), j);
- }
- if (l_iter != l_iter->prev->next) {
- ERRMSG("face %d: has invalid 'prev/next' at corner: %d", i, j);
- }
- if (l_iter != l_iter->next->prev) {
- ERRMSG("face %d: has invalid 'next/prev' at corner: %d", i, j);
- }
- if (l_iter != l_iter->radial_prev->radial_next) {
- ERRMSG("face %d: has invalid 'radial_prev/radial_next' at corner: %d", i, j);
- }
- if (l_iter != l_iter->radial_next->radial_prev) {
- ERRMSG("face %d: has invalid 'radial_next/radial_prev' at corner: %d", i, j);
- }
-
- BM_elem_flag_enable(l_iter, BM_ELEM_INTERNAL_TAG);
- BM_elem_flag_enable(l_iter->v, BM_ELEM_INTERNAL_TAG);
- BM_elem_flag_enable(l_iter->e, BM_ELEM_INTERNAL_TAG);
- j++;
- } while ((l_iter = l_iter->next) != l_first);
-
- if (j != f->len) {
- ERRMSG("face %d: has length of %d but should be %d", i, f->len, j);
- }
-
- /* leave elements un-tagged, not essential but nice to avoid unintended dirty tag use later. */
- do {
- BM_elem_flag_disable(l_iter, BM_ELEM_INTERNAL_TAG);
- BM_elem_flag_disable(l_iter->v, BM_ELEM_INTERNAL_TAG);
- BM_elem_flag_disable(l_iter->e, BM_ELEM_INTERNAL_TAG);
- } while ((l_iter = l_iter->next) != l_first);
- }
-
- BLI_edgehash_free(edge_hash, NULL);
-
- const bool is_valid = (errtot == 0);
- ERRMSG("Finished - errors %d", errtot);
- return is_valid;
+ EdgeHash *edge_hash = BLI_edgehash_new_ex(__func__, bm->totedge);
+ int errtot;
+
+ BMIter iter;
+ BMVert *v;
+ BMEdge *e;
+ BMFace *f;
+
+ int i, j;
+
+ errtot = -1; /* 'ERRMSG' next line will set at zero */
+ fprintf(stderr, "\n");
+ ERRMSG("This is a debugging function and not intended for general use, running slow test!");
+
+ /* force recalc, even if tagged as valid, since this mesh is suspect! */
+ bm->elem_index_dirty |= BM_ALL;
+ BM_mesh_elem_index_ensure(bm, BM_ALL);
+
+ BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT | BM_ELEM_HIDDEN) ==
+ (BM_ELEM_SELECT | BM_ELEM_HIDDEN)) {
+ ERRMSG("vert %d: is hidden and selected", i);
+ }
+
+ if (v->e) {
+ if (!BM_vert_in_edge(v->e, v)) {
+ ERRMSG("vert %d: is not in its referenced edge: %d", i, BM_elem_index_get(v->e));
+ }
+ }
+ }
+
+ /* check edges */
+ BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
+ void **val_p;
+
+ if (e->v1 == e->v2) {
+ ERRMSG("edge %d: duplicate index: %d", i, BM_elem_index_get(e->v1));
+ }
+
+ /* build edgehash at the same time */
+ if (BLI_edgehash_ensure_p(
+ edge_hash, BM_elem_index_get(e->v1), BM_elem_index_get(e->v2), &val_p)) {
+ BMEdge *e_other = *val_p;
+ ERRMSG("edge %d, %d: are duplicates", i, BM_elem_index_get(e_other));
+ }
+ else {
+ *val_p = e;
+ }
+ }
+
+ /* edge radial structure */
+ BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT | BM_ELEM_HIDDEN) ==
+ (BM_ELEM_SELECT | BM_ELEM_HIDDEN)) {
+ ERRMSG("edge %d: is hidden and selected", i);
+ }
+
+ if (e->l) {
+ BMLoop *l_iter;
+ BMLoop *l_first;
+
+ j = 0;
+
+ l_iter = l_first = e->l;
+ /* we could do more checks here, but save for face checks */
+ do {
+ if (l_iter->e != e) {
+ ERRMSG("edge %d: has invalid loop, loop is of face %d", i, BM_elem_index_get(l_iter->f));
+ }
+ else if (BM_vert_in_edge(e, l_iter->v) == false) {
+ ERRMSG("edge %d: has invalid loop with vert not in edge, loop is of face %d",
+ i,
+ BM_elem_index_get(l_iter->f));
+ }
+ else if (BM_vert_in_edge(e, l_iter->next->v) == false) {
+ ERRMSG("edge %d: has invalid loop with next vert not in edge, loop is of face %d",
+ i,
+ BM_elem_index_get(l_iter->f));
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+ }
+
+ /* face structure */
+ BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) {
+ BMLoop *l_iter;
+ BMLoop *l_first;
+
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT | BM_ELEM_HIDDEN) ==
+ (BM_ELEM_SELECT | BM_ELEM_HIDDEN)) {
+ ERRMSG("face %d: is hidden and selected", i);
+ }
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+
+ do {
+ BM_elem_flag_disable(l_iter, BM_ELEM_INTERNAL_TAG);
+ BM_elem_flag_disable(l_iter->v, BM_ELEM_INTERNAL_TAG);
+ BM_elem_flag_disable(l_iter->e, BM_ELEM_INTERNAL_TAG);
+ } while ((l_iter = l_iter->next) != l_first);
+
+ j = 0;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (BM_elem_flag_test(l_iter, BM_ELEM_INTERNAL_TAG)) {
+ ERRMSG("face %d: has duplicate loop at corner: %d", i, j);
+ }
+ if (BM_elem_flag_test(l_iter->v, BM_ELEM_INTERNAL_TAG)) {
+ ERRMSG(
+ "face %d: has duplicate vert: %d, at corner: %d", i, BM_elem_index_get(l_iter->v), j);
+ }
+ if (BM_elem_flag_test(l_iter->e, BM_ELEM_INTERNAL_TAG)) {
+ ERRMSG(
+ "face %d: has duplicate edge: %d, at corner: %d", i, BM_elem_index_get(l_iter->e), j);
+ }
+
+ /* adjacent data checks */
+ if (l_iter->f != f) {
+ ERRMSG("face %d: has loop that points to face: %d at corner: %d",
+ i,
+ BM_elem_index_get(l_iter->f),
+ j);
+ }
+ if (l_iter != l_iter->prev->next) {
+ ERRMSG("face %d: has invalid 'prev/next' at corner: %d", i, j);
+ }
+ if (l_iter != l_iter->next->prev) {
+ ERRMSG("face %d: has invalid 'next/prev' at corner: %d", i, j);
+ }
+ if (l_iter != l_iter->radial_prev->radial_next) {
+ ERRMSG("face %d: has invalid 'radial_prev/radial_next' at corner: %d", i, j);
+ }
+ if (l_iter != l_iter->radial_next->radial_prev) {
+ ERRMSG("face %d: has invalid 'radial_next/radial_prev' at corner: %d", i, j);
+ }
+
+ BM_elem_flag_enable(l_iter, BM_ELEM_INTERNAL_TAG);
+ BM_elem_flag_enable(l_iter->v, BM_ELEM_INTERNAL_TAG);
+ BM_elem_flag_enable(l_iter->e, BM_ELEM_INTERNAL_TAG);
+ j++;
+ } while ((l_iter = l_iter->next) != l_first);
+
+ if (j != f->len) {
+ ERRMSG("face %d: has length of %d but should be %d", i, f->len, j);
+ }
+
+ /* leave elements un-tagged, not essential but nice to avoid unintended dirty tag use later. */
+ do {
+ BM_elem_flag_disable(l_iter, BM_ELEM_INTERNAL_TAG);
+ BM_elem_flag_disable(l_iter->v, BM_ELEM_INTERNAL_TAG);
+ BM_elem_flag_disable(l_iter->e, BM_ELEM_INTERNAL_TAG);
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+
+ BLI_edgehash_free(edge_hash, NULL);
+
+ const bool is_valid = (errtot == 0);
+ ERRMSG("Finished - errors %d", errtot);
+ return is_valid;
}
-
#endif
diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c
index e1aa5fcfee1..1075b3753da 100644
--- a/source/blender/bmesh/intern/bmesh_mods.c
+++ b/source/blender/bmesh/intern/bmesh_mods.c
@@ -58,39 +58,39 @@
*/
bool BM_vert_dissolve(BMesh *bm, BMVert *v)
{
- /* logic for 3 or more is identical */
- const int len = BM_vert_edge_count_at_most(v, 3);
-
- if (len == 1) {
- BM_vert_kill(bm, v); /* will kill edges too */
- return true;
- }
- else if (!BM_vert_is_manifold(v)) {
- if (!v->e) {
- BM_vert_kill(bm, v);
- return true;
- }
- else if (!v->e->l) {
- if (len == 2) {
- return (BM_vert_collapse_edge(bm, v->e, v, true, true) != NULL);
- }
- else {
- /* used to kill the vertex here, but it may be connected to faces.
- * so better do nothing */
- return false;
- }
- }
- else {
- return false;
- }
- }
- else if (len == 2 && BM_vert_face_count_is_equal(v, 1)) {
- /* boundary vertex on a face */
- return (BM_vert_collapse_edge(bm, v->e, v, true, true) != NULL);
- }
- else {
- return BM_disk_dissolve(bm, v);
- }
+ /* logic for 3 or more is identical */
+ const int len = BM_vert_edge_count_at_most(v, 3);
+
+ if (len == 1) {
+ BM_vert_kill(bm, v); /* will kill edges too */
+ return true;
+ }
+ else if (!BM_vert_is_manifold(v)) {
+ if (!v->e) {
+ BM_vert_kill(bm, v);
+ return true;
+ }
+ else if (!v->e->l) {
+ if (len == 2) {
+ return (BM_vert_collapse_edge(bm, v->e, v, true, true) != NULL);
+ }
+ else {
+ /* used to kill the vertex here, but it may be connected to faces.
+ * so better do nothing */
+ return false;
+ }
+ }
+ else {
+ return false;
+ }
+ }
+ else if (len == 2 && BM_vert_face_count_is_equal(v, 1)) {
+ /* boundary vertex on a face */
+ return (BM_vert_collapse_edge(bm, v->e, v, true, true) != NULL);
+ }
+ else {
+ return BM_disk_dissolve(bm, v);
+ }
}
/**
@@ -98,115 +98,115 @@ bool BM_vert_dissolve(BMesh *bm, BMVert *v)
*/
bool BM_disk_dissolve(BMesh *bm, BMVert *v)
{
- BMEdge *e, *keepedge = NULL, *baseedge = NULL;
- int len = 0;
-
- if (!BM_vert_is_manifold(v)) {
- return false;
- }
-
- if (v->e) {
- /* v->e we keep, what else */
- e = v->e;
- do {
- e = bmesh_disk_edge_next(e, v);
- if (!(BM_edge_share_face_check(e, v->e))) {
- keepedge = e;
- baseedge = v->e;
- break;
- }
- len++;
- } while (e != v->e);
- }
-
- /* this code for handling 2 and 3-valence verts
- * may be totally bad */
- if (keepedge == NULL && len == 3) {
+ BMEdge *e, *keepedge = NULL, *baseedge = NULL;
+ int len = 0;
+
+ if (!BM_vert_is_manifold(v)) {
+ return false;
+ }
+
+ if (v->e) {
+ /* v->e we keep, what else */
+ e = v->e;
+ do {
+ e = bmesh_disk_edge_next(e, v);
+ if (!(BM_edge_share_face_check(e, v->e))) {
+ keepedge = e;
+ baseedge = v->e;
+ break;
+ }
+ len++;
+ } while (e != v->e);
+ }
+
+ /* this code for handling 2 and 3-valence verts
+ * may be totally bad */
+ if (keepedge == NULL && len == 3) {
#if 0
- /* handle specific case for three-valence. solve it by
- * increasing valence to four. this may be hackish. . */
- BMLoop *l_a = BM_face_vert_share_loop(e->l->f, v);
- BMLoop *l_b = (e->l->v == v) ? e->l->next : e->l;
+ /* handle specific case for three-valence. solve it by
+ * increasing valence to four. this may be hackish. . */
+ BMLoop *l_a = BM_face_vert_share_loop(e->l->f, v);
+ BMLoop *l_b = (e->l->v == v) ? e->l->next : e->l;
- if (!BM_face_split(bm, e->l->f, l_a, l_b, NULL, NULL, false))
- return false;
+ if (!BM_face_split(bm, e->l->f, l_a, l_b, NULL, NULL, false))
+ return false;
- if (!BM_disk_dissolve(bm, v)) {
- return false;
- }
+ if (!BM_disk_dissolve(bm, v)) {
+ return false;
+ }
#else
- if (UNLIKELY(!BM_faces_join_pair(bm, e->l, e->l->radial_next, true))) {
- return false;
- }
- else if (UNLIKELY(!BM_vert_collapse_faces(bm, v->e, v, 1.0, true, false, true))) {
- return false;
- }
+ if (UNLIKELY(!BM_faces_join_pair(bm, e->l, e->l->radial_next, true))) {
+ return false;
+ }
+ else if (UNLIKELY(!BM_vert_collapse_faces(bm, v->e, v, 1.0, true, false, true))) {
+ return false;
+ }
#endif
- return true;
- }
- else if (keepedge == NULL && len == 2) {
- /* collapse the vertex */
- e = BM_vert_collapse_faces(bm, v->e, v, 1.0, true, true, true);
-
- if (!e) {
- return false;
- }
-
- /* handle two-valence */
- if (e->l != e->l->radial_next) {
- if (!BM_faces_join_pair(bm, e->l, e->l->radial_next, true)) {
- return false;
- }
- }
-
- return true;
- }
-
- if (keepedge) {
- bool done = false;
-
- while (!done) {
- done = true;
- e = v->e;
- do {
- BMFace *f = NULL;
- if (BM_edge_is_manifold(e) && (e != baseedge) && (e != keepedge)) {
- f = BM_faces_join_pair(bm, e->l, e->l->radial_next, true);
- /* return if couldn't join faces in manifold
- * conditions */
- /* !disabled for testing why bad things happen */
- if (!f) {
- return false;
- }
- }
-
- if (f) {
- done = false;
- break;
- }
- } while ((e = bmesh_disk_edge_next(e, v)) != v->e);
- }
-
- /* collapse the vertex */
- /* note, the baseedge can be a boundary of manifold, use this as join_faces arg */
- e = BM_vert_collapse_faces(bm, baseedge, v, 1.0, true, !BM_edge_is_boundary(baseedge), true);
-
- if (!e) {
- return false;
- }
-
- if (e->l) {
- /* get remaining two faces */
- if (e->l != e->l->radial_next) {
- /* join two remaining faces */
- if (!BM_faces_join_pair(bm, e->l, e->l->radial_next, true)) {
- return false;
- }
- }
- }
- }
-
- return true;
+ return true;
+ }
+ else if (keepedge == NULL && len == 2) {
+ /* collapse the vertex */
+ e = BM_vert_collapse_faces(bm, v->e, v, 1.0, true, true, true);
+
+ if (!e) {
+ return false;
+ }
+
+ /* handle two-valence */
+ if (e->l != e->l->radial_next) {
+ if (!BM_faces_join_pair(bm, e->l, e->l->radial_next, true)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ if (keepedge) {
+ bool done = false;
+
+ while (!done) {
+ done = true;
+ e = v->e;
+ do {
+ BMFace *f = NULL;
+ if (BM_edge_is_manifold(e) && (e != baseedge) && (e != keepedge)) {
+ f = BM_faces_join_pair(bm, e->l, e->l->radial_next, true);
+ /* return if couldn't join faces in manifold
+ * conditions */
+ /* !disabled for testing why bad things happen */
+ if (!f) {
+ return false;
+ }
+ }
+
+ if (f) {
+ done = false;
+ break;
+ }
+ } while ((e = bmesh_disk_edge_next(e, v)) != v->e);
+ }
+
+ /* collapse the vertex */
+ /* note, the baseedge can be a boundary of manifold, use this as join_faces arg */
+ e = BM_vert_collapse_faces(bm, baseedge, v, 1.0, true, !BM_edge_is_boundary(baseedge), true);
+
+ if (!e) {
+ return false;
+ }
+
+ if (e->l) {
+ /* get remaining two faces */
+ if (e->l != e->l->radial_next) {
+ /* join two remaining faces */
+ if (!BM_faces_join_pair(bm, e->l, e->l->radial_next, true)) {
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
}
/**
@@ -224,15 +224,15 @@ bool BM_disk_dissolve(BMesh *bm, BMVert *v)
*/
BMFace *BM_faces_join_pair(BMesh *bm, BMLoop *l_a, BMLoop *l_b, const bool do_del)
{
- BLI_assert((l_a != l_b) && (l_a->e == l_b->e));
+ BLI_assert((l_a != l_b) && (l_a->e == l_b->e));
- if (l_a->v == l_b->v) {
- const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
- bmesh_kernel_loop_reverse(bm, l_b->f, cd_loop_mdisp_offset, true);
- }
+ if (l_a->v == l_b->v) {
+ const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
+ bmesh_kernel_loop_reverse(bm, l_b->f, cd_loop_mdisp_offset, true);
+ }
- BMFace *faces[2] = {l_a->f, l_b->f};
- return BM_faces_join(bm, faces, 2, do_del);
+ BMFace *faces[2] = {l_a->f, l_b->f};
+ return BM_faces_join(bm, faces, 2, do_del);
}
/**
@@ -253,67 +253,68 @@ BMFace *BM_faces_join_pair(BMesh *bm, BMLoop *l_a, BMLoop *l_b, const bool do_de
* if the split is successful (and the original original face will be the
* other side). NULL if the split fails.
*/
-BMFace *BM_face_split(
- BMesh *bm, BMFace *f,
- BMLoop *l_a, BMLoop *l_b,
- BMLoop **r_l, BMEdge *example,
- const bool no_double)
+BMFace *BM_face_split(BMesh *bm,
+ BMFace *f,
+ BMLoop *l_a,
+ BMLoop *l_b,
+ BMLoop **r_l,
+ BMEdge *example,
+ const bool no_double)
{
- const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
- BMFace *f_new, *f_tmp;
-
- BLI_assert(l_a != l_b);
- BLI_assert(f == l_a->f && f == l_b->f);
- BLI_assert(!BM_loop_is_adjacent(l_a, l_b));
-
- /* could be an assert */
- if (UNLIKELY(BM_loop_is_adjacent(l_a, l_b)) ||
- UNLIKELY((f != l_a->f || f != l_b->f)))
- {
- if (r_l) {
- *r_l = NULL;
- }
- return NULL;
- }
-
- /* do we have a multires layer? */
- if (cd_loop_mdisp_offset != -1) {
- f_tmp = BM_face_copy(bm, bm, f, false, false);
- }
+ const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
+ BMFace *f_new, *f_tmp;
+
+ BLI_assert(l_a != l_b);
+ BLI_assert(f == l_a->f && f == l_b->f);
+ BLI_assert(!BM_loop_is_adjacent(l_a, l_b));
+
+ /* could be an assert */
+ if (UNLIKELY(BM_loop_is_adjacent(l_a, l_b)) || UNLIKELY((f != l_a->f || f != l_b->f))) {
+ if (r_l) {
+ *r_l = NULL;
+ }
+ return NULL;
+ }
+
+ /* do we have a multires layer? */
+ if (cd_loop_mdisp_offset != -1) {
+ f_tmp = BM_face_copy(bm, bm, f, false, false);
+ }
#ifdef USE_BMESH_HOLES
- f_new = bmesh_kernel_split_face_make_edge(bm, f, l_a, l_b, r_l, NULL, example, no_double);
+ f_new = bmesh_kernel_split_face_make_edge(bm, f, l_a, l_b, r_l, NULL, example, no_double);
#else
- f_new = bmesh_kernel_split_face_make_edge(bm, f, l_a, l_b, r_l, example, no_double);
+ f_new = bmesh_kernel_split_face_make_edge(bm, f, l_a, l_b, r_l, example, no_double);
#endif
- if (f_new) {
- /* handle multires update */
- if (cd_loop_mdisp_offset != -1) {
- float f_dst_center[3];
- float f_src_center[3];
+ if (f_new) {
+ /* handle multires update */
+ if (cd_loop_mdisp_offset != -1) {
+ float f_dst_center[3];
+ float f_src_center[3];
- BM_face_calc_center_median(f_tmp, f_src_center);
+ BM_face_calc_center_median(f_tmp, f_src_center);
- BM_face_calc_center_median(f, f_dst_center);
- BM_face_interp_multires_ex(bm, f, f_tmp, f_dst_center, f_src_center, cd_loop_mdisp_offset);
+ BM_face_calc_center_median(f, f_dst_center);
+ BM_face_interp_multires_ex(bm, f, f_tmp, f_dst_center, f_src_center, cd_loop_mdisp_offset);
- BM_face_calc_center_median(f_new, f_dst_center);
- BM_face_interp_multires_ex(bm, f_new, f_tmp, f_dst_center, f_src_center, cd_loop_mdisp_offset);
+ BM_face_calc_center_median(f_new, f_dst_center);
+ BM_face_interp_multires_ex(
+ bm, f_new, f_tmp, f_dst_center, f_src_center, cd_loop_mdisp_offset);
#if 0
- /* BM_face_multires_bounds_smooth doesn't flip displacement correct */
- BM_face_multires_bounds_smooth(bm, f);
- BM_face_multires_bounds_smooth(bm, f_new);
+ /* BM_face_multires_bounds_smooth doesn't flip displacement correct */
+ BM_face_multires_bounds_smooth(bm, f);
+ BM_face_multires_bounds_smooth(bm, f_new);
#endif
- }
- }
+ }
+ }
- if (cd_loop_mdisp_offset != -1) {
- BM_face_kill(bm, f_tmp);
- }
+ if (cd_loop_mdisp_offset != -1) {
+ BM_face_kill(bm, f_tmp);
+ }
- return f_new;
+ return f_new;
}
/**
@@ -333,74 +334,75 @@ BMFace *BM_face_split(
* if the split is successful (and the original original face will be the
* other side). NULL if the split fails.
*/
-BMFace *BM_face_split_n(
- BMesh *bm, BMFace *f,
- BMLoop *l_a, BMLoop *l_b,
- float cos[][3], int n,
- BMLoop **r_l, BMEdge *example)
+BMFace *BM_face_split_n(BMesh *bm,
+ BMFace *f,
+ BMLoop *l_a,
+ BMLoop *l_b,
+ float cos[][3],
+ int n,
+ BMLoop **r_l,
+ BMEdge *example)
{
- BMFace *f_new, *f_tmp;
- BMLoop *l_new;
- BMEdge *e, *e_new;
- BMVert *v_new;
- // BMVert *v_a = l_a->v; /* UNUSED */
- BMVert *v_b = l_b->v;
- int i, j;
-
- BLI_assert(l_a != l_b);
- BLI_assert(f == l_a->f && f == l_b->f);
- BLI_assert(!((n == 0) && BM_loop_is_adjacent(l_a, l_b)));
-
- /* could be an assert */
- if (UNLIKELY((n == 0) && BM_loop_is_adjacent(l_a, l_b)) ||
- UNLIKELY(l_a->f != l_b->f))
- {
- if (r_l) {
- *r_l = NULL;
- }
- return NULL;
- }
-
- f_tmp = BM_face_copy(bm, bm, f, true, true);
+ BMFace *f_new, *f_tmp;
+ BMLoop *l_new;
+ BMEdge *e, *e_new;
+ BMVert *v_new;
+ // BMVert *v_a = l_a->v; /* UNUSED */
+ BMVert *v_b = l_b->v;
+ int i, j;
+
+ BLI_assert(l_a != l_b);
+ BLI_assert(f == l_a->f && f == l_b->f);
+ BLI_assert(!((n == 0) && BM_loop_is_adjacent(l_a, l_b)));
+
+ /* could be an assert */
+ if (UNLIKELY((n == 0) && BM_loop_is_adjacent(l_a, l_b)) || UNLIKELY(l_a->f != l_b->f)) {
+ if (r_l) {
+ *r_l = NULL;
+ }
+ return NULL;
+ }
+
+ f_tmp = BM_face_copy(bm, bm, f, true, true);
#ifdef USE_BMESH_HOLES
- f_new = bmesh_kernel_split_face_make_edge(bm, f, l_a, l_b, &l_new, NULL, example, false);
+ f_new = bmesh_kernel_split_face_make_edge(bm, f, l_a, l_b, &l_new, NULL, example, false);
#else
- f_new = bmesh_kernel_split_face_make_edge(bm, f, l_a, l_b, &l_new, example, false);
+ f_new = bmesh_kernel_split_face_make_edge(bm, f, l_a, l_b, &l_new, example, false);
#endif
- /* bmesh_kernel_split_face_make_edge returns in 'l_new' a Loop for f_new going from 'v_a' to 'v_b'.
- * The radial_next is for 'f' and goes from 'v_b' to 'v_a' */
-
- if (f_new) {
- e = l_new->e;
- for (i = 0; i < n; i++) {
- v_new = bmesh_kernel_split_edge_make_vert(bm, v_b, e, &e_new);
- BLI_assert(v_new != NULL);
- /* bmesh_kernel_split_edge_make_vert returns in 'e_new' the edge going from 'v_new' to 'v_b' */
- copy_v3_v3(v_new->co, cos[i]);
-
- /* interpolate the loop data for the loops with (v == v_new), using orig face */
- for (j = 0; j < 2; j++) {
- BMEdge *e_iter = (j == 0) ? e : e_new;
- BMLoop *l_iter = e_iter->l;
- do {
- if (l_iter->v == v_new) {
- /* this interpolates both loop and vertex data */
- BM_loop_interp_from_face(bm, l_iter, f_tmp, true, true);
- }
- } while ((l_iter = l_iter->radial_next) != e_iter->l);
- }
- e = e_new;
- }
- }
-
- BM_face_verts_kill(bm, f_tmp);
-
- if (r_l) {
- *r_l = l_new;
- }
-
- return f_new;
+ /* bmesh_kernel_split_face_make_edge returns in 'l_new' a Loop for f_new going from 'v_a' to 'v_b'.
+ * The radial_next is for 'f' and goes from 'v_b' to 'v_a' */
+
+ if (f_new) {
+ e = l_new->e;
+ for (i = 0; i < n; i++) {
+ v_new = bmesh_kernel_split_edge_make_vert(bm, v_b, e, &e_new);
+ BLI_assert(v_new != NULL);
+ /* bmesh_kernel_split_edge_make_vert returns in 'e_new' the edge going from 'v_new' to 'v_b' */
+ copy_v3_v3(v_new->co, cos[i]);
+
+ /* interpolate the loop data for the loops with (v == v_new), using orig face */
+ for (j = 0; j < 2; j++) {
+ BMEdge *e_iter = (j == 0) ? e : e_new;
+ BMLoop *l_iter = e_iter->l;
+ do {
+ if (l_iter->v == v_new) {
+ /* this interpolates both loop and vertex data */
+ BM_loop_interp_from_face(bm, l_iter, f_tmp, true, true);
+ }
+ } while ((l_iter = l_iter->radial_next) != e_iter->l);
+ }
+ e = e_new;
+ }
+ }
+
+ BM_face_verts_kill(bm, f_tmp);
+
+ if (r_l) {
+ *r_l = l_new;
+ }
+
+ return f_new;
}
/**
@@ -426,89 +428,90 @@ BMFace *BM_face_split_n(
*
* \returns The New Edge
*/
-BMEdge *BM_vert_collapse_faces(
- BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float fac,
- const bool do_del, const bool join_faces, const bool kill_degenerate_faces)
+BMEdge *BM_vert_collapse_faces(BMesh *bm,
+ BMEdge *e_kill,
+ BMVert *v_kill,
+ float fac,
+ const bool do_del,
+ const bool join_faces,
+ const bool kill_degenerate_faces)
{
- BMEdge *e_new = NULL;
- BMVert *tv = BM_edge_other_vert(e_kill, v_kill);
-
- BMEdge *e2;
- BMVert *tv2;
-
- /* Only intended to be called for 2-valence vertices */
- BLI_assert(bmesh_disk_count(v_kill) <= 2);
-
-
- /* first modify the face loop data */
-
- if (e_kill->l) {
- BMLoop *l_iter;
- const float w[2] = {1.0f - fac, fac};
-
- l_iter = e_kill->l;
- do {
- if (l_iter->v == tv && l_iter->next->v == v_kill) {
- const void *src[2];
- BMLoop *tvloop = l_iter;
- BMLoop *kvloop = l_iter->next;
-
- src[0] = kvloop->head.data;
- src[1] = tvloop->head.data;
- CustomData_bmesh_interp(&bm->ldata, src, w, NULL, 2, kvloop->head.data);
- }
- } while ((l_iter = l_iter->radial_next) != e_kill->l);
- }
-
- /* now interpolate the vertex data */
- BM_data_interp_from_verts(bm, v_kill, tv, v_kill, fac);
-
- e2 = bmesh_disk_edge_next(e_kill, v_kill);
- tv2 = BM_edge_other_vert(e2, v_kill);
-
- if (join_faces) {
- BMIter fiter;
- BMFace **faces = NULL;
- BMFace *f;
- BLI_array_staticdeclare(faces, BM_DEFAULT_ITER_STACK_SIZE);
-
- BM_ITER_ELEM (f, &fiter, v_kill, BM_FACES_OF_VERT) {
- BLI_array_append(faces, f);
- }
-
- if (BLI_array_len(faces) >= 2) {
- BMFace *f2 = BM_faces_join(bm, faces, BLI_array_len(faces), true);
- if (f2) {
- BMLoop *l_a, *l_b;
-
- if ((l_a = BM_face_vert_share_loop(f2, tv)) &&
- (l_b = BM_face_vert_share_loop(f2, tv2)))
- {
- BMLoop *l_new;
-
- if (BM_face_split(bm, f2, l_a, l_b, &l_new, NULL, false)) {
- e_new = l_new->e;
- }
- }
- }
- }
-
- BLI_assert(BLI_array_len(faces) < 8);
-
- BLI_array_free(faces);
- }
- else {
- /* single face or no faces */
- /* same as BM_vert_collapse_edge() however we already
- * have vars to perform this operation so don't call. */
- e_new = bmesh_kernel_join_edge_kill_vert(bm, e_kill, v_kill, do_del, true, kill_degenerate_faces);
- /* e_new = BM_edge_exists(tv, tv2); */ /* same as return above */
- }
-
- return e_new;
+ BMEdge *e_new = NULL;
+ BMVert *tv = BM_edge_other_vert(e_kill, v_kill);
+
+ BMEdge *e2;
+ BMVert *tv2;
+
+ /* Only intended to be called for 2-valence vertices */
+ BLI_assert(bmesh_disk_count(v_kill) <= 2);
+
+ /* first modify the face loop data */
+
+ if (e_kill->l) {
+ BMLoop *l_iter;
+ const float w[2] = {1.0f - fac, fac};
+
+ l_iter = e_kill->l;
+ do {
+ if (l_iter->v == tv && l_iter->next->v == v_kill) {
+ const void *src[2];
+ BMLoop *tvloop = l_iter;
+ BMLoop *kvloop = l_iter->next;
+
+ src[0] = kvloop->head.data;
+ src[1] = tvloop->head.data;
+ CustomData_bmesh_interp(&bm->ldata, src, w, NULL, 2, kvloop->head.data);
+ }
+ } while ((l_iter = l_iter->radial_next) != e_kill->l);
+ }
+
+ /* now interpolate the vertex data */
+ BM_data_interp_from_verts(bm, v_kill, tv, v_kill, fac);
+
+ e2 = bmesh_disk_edge_next(e_kill, v_kill);
+ tv2 = BM_edge_other_vert(e2, v_kill);
+
+ if (join_faces) {
+ BMIter fiter;
+ BMFace **faces = NULL;
+ BMFace *f;
+ BLI_array_staticdeclare(faces, BM_DEFAULT_ITER_STACK_SIZE);
+
+ BM_ITER_ELEM (f, &fiter, v_kill, BM_FACES_OF_VERT) {
+ BLI_array_append(faces, f);
+ }
+
+ if (BLI_array_len(faces) >= 2) {
+ BMFace *f2 = BM_faces_join(bm, faces, BLI_array_len(faces), true);
+ if (f2) {
+ BMLoop *l_a, *l_b;
+
+ if ((l_a = BM_face_vert_share_loop(f2, tv)) && (l_b = BM_face_vert_share_loop(f2, tv2))) {
+ BMLoop *l_new;
+
+ if (BM_face_split(bm, f2, l_a, l_b, &l_new, NULL, false)) {
+ e_new = l_new->e;
+ }
+ }
+ }
+ }
+
+ BLI_assert(BLI_array_len(faces) < 8);
+
+ BLI_array_free(faces);
+ }
+ else {
+ /* single face or no faces */
+ /* same as BM_vert_collapse_edge() however we already
+ * have vars to perform this operation so don't call. */
+ e_new = bmesh_kernel_join_edge_kill_vert(
+ bm, e_kill, v_kill, do_del, true, kill_degenerate_faces);
+ /* e_new = BM_edge_exists(tv, tv2); */ /* same as return above */
+ }
+
+ return e_new;
}
-
/**
* \brief Vert Collapse Faces
*
@@ -517,35 +520,34 @@ BMEdge *BM_vert_collapse_faces(
* \return The New Edge
*/
BMEdge *BM_vert_collapse_edge(
- BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
- const bool do_del, const bool kill_degenerate_faces)
+ BMesh *bm, BMEdge *e_kill, BMVert *v_kill, const bool do_del, const bool kill_degenerate_faces)
{
- /* nice example implementation but we want loops to have their customdata
- * accounted for */
+ /* nice example implementation but we want loops to have their customdata
+ * accounted for */
#if 0
- BMEdge *e_new = NULL;
-
- /* Collapse between 2 edges */
-
- /* in this case we want to keep all faces and not join them,
- * rather just get rid of the vertex - see bug [#28645] */
- BMVert *tv = BM_edge_other_vert(e_kill, v_kill);
- if (tv) {
- BMEdge *e2 = bmesh_disk_edge_next(e_kill, v_kill);
- if (e2) {
- BMVert *tv2 = BM_edge_other_vert(e2, v_kill);
- if (tv2) {
- /* only action, other calls here only get the edge to return */
- e_new = bmesh_kernel_join_edge_kill_vert(bm, e_kill, v_kill, do_del, true, kill_degenerate_faces);
- }
- }
- }
-
- return e_new;
+ BMEdge *e_new = NULL;
+
+ /* Collapse between 2 edges */
+
+ /* in this case we want to keep all faces and not join them,
+ * rather just get rid of the vertex - see bug [#28645] */
+ BMVert *tv = BM_edge_other_vert(e_kill, v_kill);
+ if (tv) {
+ BMEdge *e2 = bmesh_disk_edge_next(e_kill, v_kill);
+ if (e2) {
+ BMVert *tv2 = BM_edge_other_vert(e2, v_kill);
+ if (tv2) {
+ /* only action, other calls here only get the edge to return */
+ e_new = bmesh_kernel_join_edge_kill_vert(bm, e_kill, v_kill, do_del, true, kill_degenerate_faces);
+ }
+ }
+ }
+
+ return e_new;
#else
- /* with these args faces are never joined, same as above
- * but account for loop customdata */
- return BM_vert_collapse_faces(bm, e_kill, v_kill, 1.0f, do_del, false, kill_degenerate_faces);
+ /* with these args faces are never joined, same as above
+ * but account for loop customdata */
+ return BM_vert_collapse_faces(bm, e_kill, v_kill, 1.0f, do_del, false, kill_degenerate_faces);
#endif
}
@@ -555,10 +557,9 @@ BMEdge *BM_vert_collapse_edge(
* Collapse and edge into a single vertex.
*/
BMVert *BM_edge_collapse(
- BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
- const bool do_del, const bool kill_degenerate_faces)
+ BMesh *bm, BMEdge *e_kill, BMVert *v_kill, const bool do_del, const bool kill_degenerate_faces)
{
- return bmesh_kernel_join_vert_kill_edge(bm, e_kill, v_kill, do_del, true, kill_degenerate_faces);
+ return bmesh_kernel_join_vert_kill_edge(bm, e_kill, v_kill, do_del, true, kill_degenerate_faces);
}
/**
@@ -582,116 +583,117 @@ BMVert *BM_edge_collapse(
*/
BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac)
{
- BMVert *v_new, *v_other;
- BMEdge *e_new;
- BMFace **oldfaces = NULL;
- BLI_array_staticdeclare(oldfaces, 32);
- const int cd_loop_mdisp_offset = BM_edge_is_wire(e) ? -1 : CustomData_get_offset(&bm->ldata, CD_MDISPS);
-
- BLI_assert(BM_vert_in_edge(e, v) == true);
-
- /* do we have a multi-res layer? */
- if (cd_loop_mdisp_offset != -1) {
- BMLoop *l;
- int i;
-
- l = e->l;
- do {
- BLI_array_append(oldfaces, l->f);
- l = l->radial_next;
- } while (l != e->l);
-
- /* flag existing faces so we can differentiate oldfaces from new faces */
- for (i = 0; i < BLI_array_len(oldfaces); i++) {
- BM_ELEM_API_FLAG_ENABLE(oldfaces[i], _FLAG_OVERLAP);
- oldfaces[i] = BM_face_copy(bm, bm, oldfaces[i], true, true);
- BM_ELEM_API_FLAG_DISABLE(oldfaces[i], _FLAG_OVERLAP);
- }
- }
-
- v_other = BM_edge_other_vert(e, v);
- v_new = bmesh_kernel_split_edge_make_vert(bm, v, e, &e_new);
- if (r_e != NULL) {
- *r_e = e_new;
- }
-
- BLI_assert(v_new != NULL);
- BLI_assert(BM_vert_in_edge(e_new, v) && BM_vert_in_edge(e_new, v_new));
- BLI_assert(BM_vert_in_edge(e, v_new) && BM_vert_in_edge(e, v_other));
-
- sub_v3_v3v3(v_new->co, v_other->co, v->co);
- madd_v3_v3v3fl(v_new->co, v->co, v_new->co, fac);
-
- e_new->head.hflag = e->head.hflag;
- BM_elem_attrs_copy(bm, bm, e, e_new);
-
- /* v->v_new->v2 */
- BM_data_interp_face_vert_edge(bm, v_other, v, v_new, e, fac);
- BM_data_interp_from_verts(bm, v, v_other, v_new, fac);
-
- if (cd_loop_mdisp_offset != -1) {
- int i, j;
-
- /* interpolate new/changed loop data from copied old faces */
- for (i = 0; i < BLI_array_len(oldfaces); i++) {
- float f_center_old[3];
-
- BM_face_calc_center_median(oldfaces[i], f_center_old);
-
- for (j = 0; j < 2; j++) {
- BMEdge *e1 = j ? e_new : e;
- BMLoop *l;
-
- l = e1->l;
-
- if (UNLIKELY(!l)) {
- BMESH_ASSERT(0);
- break;
- }
-
- do {
- /* check this is an old face */
- if (BM_ELEM_API_FLAG_TEST(l->f, _FLAG_OVERLAP)) {
- float f_center[3];
-
- BM_face_calc_center_median(l->f, f_center);
- BM_face_interp_multires_ex(
- bm, l->f, oldfaces[i],
- f_center, f_center_old, cd_loop_mdisp_offset);
- }
- l = l->radial_next;
- } while (l != e1->l);
- }
- }
-
- /* destroy the old faces */
- for (i = 0; i < BLI_array_len(oldfaces); i++) {
- BM_face_verts_kill(bm, oldfaces[i]);
- }
-
- /* fix boundaries a bit, doesn't work too well quite yet */
+ BMVert *v_new, *v_other;
+ BMEdge *e_new;
+ BMFace **oldfaces = NULL;
+ BLI_array_staticdeclare(oldfaces, 32);
+ const int cd_loop_mdisp_offset = BM_edge_is_wire(e) ?
+ -1 :
+ CustomData_get_offset(&bm->ldata, CD_MDISPS);
+
+ BLI_assert(BM_vert_in_edge(e, v) == true);
+
+ /* do we have a multi-res layer? */
+ if (cd_loop_mdisp_offset != -1) {
+ BMLoop *l;
+ int i;
+
+ l = e->l;
+ do {
+ BLI_array_append(oldfaces, l->f);
+ l = l->radial_next;
+ } while (l != e->l);
+
+ /* flag existing faces so we can differentiate oldfaces from new faces */
+ for (i = 0; i < BLI_array_len(oldfaces); i++) {
+ BM_ELEM_API_FLAG_ENABLE(oldfaces[i], _FLAG_OVERLAP);
+ oldfaces[i] = BM_face_copy(bm, bm, oldfaces[i], true, true);
+ BM_ELEM_API_FLAG_DISABLE(oldfaces[i], _FLAG_OVERLAP);
+ }
+ }
+
+ v_other = BM_edge_other_vert(e, v);
+ v_new = bmesh_kernel_split_edge_make_vert(bm, v, e, &e_new);
+ if (r_e != NULL) {
+ *r_e = e_new;
+ }
+
+ BLI_assert(v_new != NULL);
+ BLI_assert(BM_vert_in_edge(e_new, v) && BM_vert_in_edge(e_new, v_new));
+ BLI_assert(BM_vert_in_edge(e, v_new) && BM_vert_in_edge(e, v_other));
+
+ sub_v3_v3v3(v_new->co, v_other->co, v->co);
+ madd_v3_v3v3fl(v_new->co, v->co, v_new->co, fac);
+
+ e_new->head.hflag = e->head.hflag;
+ BM_elem_attrs_copy(bm, bm, e, e_new);
+
+ /* v->v_new->v2 */
+ BM_data_interp_face_vert_edge(bm, v_other, v, v_new, e, fac);
+ BM_data_interp_from_verts(bm, v, v_other, v_new, fac);
+
+ if (cd_loop_mdisp_offset != -1) {
+ int i, j;
+
+ /* interpolate new/changed loop data from copied old faces */
+ for (i = 0; i < BLI_array_len(oldfaces); i++) {
+ float f_center_old[3];
+
+ BM_face_calc_center_median(oldfaces[i], f_center_old);
+
+ for (j = 0; j < 2; j++) {
+ BMEdge *e1 = j ? e_new : e;
+ BMLoop *l;
+
+ l = e1->l;
+
+ if (UNLIKELY(!l)) {
+ BMESH_ASSERT(0);
+ break;
+ }
+
+ do {
+ /* check this is an old face */
+ if (BM_ELEM_API_FLAG_TEST(l->f, _FLAG_OVERLAP)) {
+ float f_center[3];
+
+ BM_face_calc_center_median(l->f, f_center);
+ BM_face_interp_multires_ex(
+ bm, l->f, oldfaces[i], f_center, f_center_old, cd_loop_mdisp_offset);
+ }
+ l = l->radial_next;
+ } while (l != e1->l);
+ }
+ }
+
+ /* destroy the old faces */
+ for (i = 0; i < BLI_array_len(oldfaces); i++) {
+ BM_face_verts_kill(bm, oldfaces[i]);
+ }
+
+ /* fix boundaries a bit, doesn't work too well quite yet */
#if 0
- for (j = 0; j < 2; j++) {
- BMEdge *e1 = j ? e_new : e;
- BMLoop *l, *l2;
-
- l = e1->l;
- if (UNLIKELY(!l)) {
- BMESH_ASSERT(0);
- break;
- }
-
- do {
- BM_face_multires_bounds_smooth(bm, l->f);
- l = l->radial_next;
- } while (l != e1->l);
- }
+ for (j = 0; j < 2; j++) {
+ BMEdge *e1 = j ? e_new : e;
+ BMLoop *l, *l2;
+
+ l = e1->l;
+ if (UNLIKELY(!l)) {
+ BMESH_ASSERT(0);
+ break;
+ }
+
+ do {
+ BM_face_multires_bounds_smooth(bm, l->f);
+ l = l->radial_next;
+ } while (l != e1->l);
+ }
#endif
- BLI_array_free(oldfaces);
- }
+ BLI_array_free(oldfaces);
+ }
- return v_new;
+ return v_new;
}
/**
@@ -699,21 +701,21 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac)
*
* \param r_varr: Optional array, verts in between (v1 -> v2)
*/
-BMVert *BM_edge_split_n(BMesh *bm, BMEdge *e, int numcuts, BMVert **r_varr)
+BMVert *BM_edge_split_n(BMesh *bm, BMEdge *e, int numcuts, BMVert **r_varr)
{
- int i;
- float percent;
- BMVert *v_new = NULL;
-
- for (i = 0; i < numcuts; i++) {
- percent = 1.0f / (float)(numcuts + 1 - i);
- v_new = BM_edge_split(bm, e, e->v2, NULL, percent);
- if (r_varr) {
- /* fill in reverse order (v1 -> v2) */
- r_varr[numcuts - i - 1] = v_new;
- }
- }
- return v_new;
+ int i;
+ float percent;
+ BMVert *v_new = NULL;
+
+ for (i = 0; i < numcuts; i++) {
+ percent = 1.0f / (float)(numcuts + 1 - i);
+ v_new = BM_edge_split(bm, e, e->v2, NULL, percent);
+ if (r_varr) {
+ /* fill in reverse order (v1 -> v2) */
+ r_varr[numcuts - i - 1] = v_new;
+ }
+ }
+ return v_new;
}
/**
@@ -723,8 +725,8 @@ BMVert *BM_edge_split_n(BMesh *bm, BMEdge *e, int numcuts, BMVert **r_varr)
*/
void BM_edge_verts_swap(BMEdge *e)
{
- SWAP(BMVert *, e->v1, e->v2);
- SWAP(BMDiskLink, e->v1_disk_link, e->v2_disk_link);
+ SWAP(BMVert *, e->v1, e->v2);
+ SWAP(BMDiskLink, e->v1_disk_link, e->v2_disk_link);
}
#if 0
@@ -733,46 +735,46 @@ void BM_edge_verts_swap(BMEdge *e)
*/
bool BM_face_validate(BMFace *face, FILE *err)
{
- BMIter iter;
- BLI_array_declare(verts);
- BMVert **verts = NULL;
- BMLoop *l;
- int i, j;
- bool ret = true;
-
- if (face->len == 2) {
- fprintf(err, "warning: found two-edged face. face ptr: %p\n", face);
- fflush(err);
- }
-
- BLI_array_grow_items(verts, face->len);
- BM_ITER_ELEM_INDEX (l, &iter, face, BM_LOOPS_OF_FACE, i) {
- verts[i] = l->v;
- if (l->e->v1 == l->e->v2) {
- fprintf(err, "Found bmesh edge with identical verts!\n");
- fprintf(err, " edge ptr: %p, vert: %p\n", l->e, l->e->v1);
- fflush(err);
- ret = false;
- }
- }
-
- for (i = 0; i < face->len; i++) {
- for (j = 0; j < face->len; j++) {
- if (j == i) {
- continue;
- }
-
- if (verts[i] == verts[j]) {
- fprintf(err, "Found duplicate verts in bmesh face!\n");
- fprintf(err, " face ptr: %p, vert: %p\n", face, verts[i]);
- fflush(err);
- ret = false;
- }
- }
- }
-
- BLI_array_free(verts);
- return ret;
+ BMIter iter;
+ BLI_array_declare(verts);
+ BMVert **verts = NULL;
+ BMLoop *l;
+ int i, j;
+ bool ret = true;
+
+ if (face->len == 2) {
+ fprintf(err, "warning: found two-edged face. face ptr: %p\n", face);
+ fflush(err);
+ }
+
+ BLI_array_grow_items(verts, face->len);
+ BM_ITER_ELEM_INDEX (l, &iter, face, BM_LOOPS_OF_FACE, i) {
+ verts[i] = l->v;
+ if (l->e->v1 == l->e->v2) {
+ fprintf(err, "Found bmesh edge with identical verts!\n");
+ fprintf(err, " edge ptr: %p, vert: %p\n", l->e, l->e->v1);
+ fflush(err);
+ ret = false;
+ }
+ }
+
+ for (i = 0; i < face->len; i++) {
+ for (j = 0; j < face->len; j++) {
+ if (j == i) {
+ continue;
+ }
+
+ if (verts[i] == verts[j]) {
+ fprintf(err, "Found duplicate verts in bmesh face!\n");
+ fprintf(err, " face ptr: %p, vert: %p\n", face, verts[i]);
+ fflush(err);
+ ret = false;
+ }
+ }
+ }
+
+ BLI_array_free(verts);
+ return ret;
}
#endif
@@ -790,32 +792,30 @@ bool BM_face_validate(BMFace *face, FILE *err)
*
* \note #BM_edge_rotate_check must have already run.
*/
-void BM_edge_calc_rotate(
- BMEdge *e, const bool ccw,
- BMLoop **r_l1, BMLoop **r_l2)
+void BM_edge_calc_rotate(BMEdge *e, const bool ccw, BMLoop **r_l1, BMLoop **r_l2)
{
- BMVert *v1, *v2;
- BMFace *fa, *fb;
+ BMVert *v1, *v2;
+ BMFace *fa, *fb;
- /* this should have already run */
- BLI_assert(BM_edge_rotate_check(e) == true);
+ /* this should have already run */
+ BLI_assert(BM_edge_rotate_check(e) == true);
- /* we know this will work */
- BM_edge_face_pair(e, &fa, &fb);
+ /* we know this will work */
+ BM_edge_face_pair(e, &fa, &fb);
- /* so we can use ccw variable correctly,
- * otherwise we could use the edges verts direct */
- BM_edge_ordered_verts(e, &v1, &v2);
+ /* so we can use ccw variable correctly,
+ * otherwise we could use the edges verts direct */
+ BM_edge_ordered_verts(e, &v1, &v2);
- /* we could swap the verts _or_ the faces, swapping faces
- * gives more predictable results since that way the next vert
- * just stitches from face fa / fb */
- if (!ccw) {
- SWAP(BMFace *, fa, fb);
- }
+ /* we could swap the verts _or_ the faces, swapping faces
+ * gives more predictable results since that way the next vert
+ * just stitches from face fa / fb */
+ if (!ccw) {
+ SWAP(BMFace *, fa, fb);
+ }
- *r_l1 = BM_face_other_vert_loop(fb, v2, v1);
- *r_l2 = BM_face_other_vert_loop(fa, v1, v2);
+ *r_l1 = BM_face_other_vert_loop(fb, v2, v1);
+ *r_l2 = BM_face_other_vert_loop(fa, v1, v2);
}
/**
@@ -826,33 +826,33 @@ void BM_edge_calc_rotate(
*/
bool BM_edge_rotate_check(BMEdge *e)
{
- BMFace *fa, *fb;
- if (BM_edge_face_pair(e, &fa, &fb)) {
- BMLoop *la, *lb;
-
- la = BM_face_other_vert_loop(fa, e->v2, e->v1);
- lb = BM_face_other_vert_loop(fb, e->v2, e->v1);
-
- /* check that the next vert in both faces isn't the same
- * (ie - the next edge doesn't share the same faces).
- * since we can't rotate usefully in this case. */
- if (la->v == lb->v) {
- return false;
- }
-
- /* mirror of the check above but in the opposite direction */
- la = BM_face_other_vert_loop(fa, e->v1, e->v2);
- lb = BM_face_other_vert_loop(fb, e->v1, e->v2);
-
- if (la->v == lb->v) {
- return false;
- }
-
- return true;
- }
- else {
- return false;
- }
+ BMFace *fa, *fb;
+ if (BM_edge_face_pair(e, &fa, &fb)) {
+ BMLoop *la, *lb;
+
+ la = BM_face_other_vert_loop(fa, e->v2, e->v1);
+ lb = BM_face_other_vert_loop(fb, e->v2, e->v1);
+
+ /* check that the next vert in both faces isn't the same
+ * (ie - the next edge doesn't share the same faces).
+ * since we can't rotate usefully in this case. */
+ if (la->v == lb->v) {
+ return false;
+ }
+
+ /* mirror of the check above but in the opposite direction */
+ la = BM_face_other_vert_loop(fa, e->v1, e->v2);
+ lb = BM_face_other_vert_loop(fb, e->v1, e->v2);
+
+ if (la->v == lb->v) {
+ return false;
+ }
+
+ return true;
+ }
+ else {
+ return false;
+ }
}
/**
@@ -868,101 +868,97 @@ bool BM_edge_rotate_check(BMEdge *e)
*/
bool BM_edge_rotate_check_degenerate(BMEdge *e, BMLoop *l1, BMLoop *l2)
{
- /* note: for these vars 'old' just means initial edge state. */
+ /* note: for these vars 'old' just means initial edge state. */
- float ed_dir_old[3]; /* edge vector */
- float ed_dir_new[3]; /* edge vector */
- float ed_dir_new_flip[3]; /* edge vector */
+ float ed_dir_old[3]; /* edge vector */
+ float ed_dir_new[3]; /* edge vector */
+ float ed_dir_new_flip[3]; /* edge vector */
- float ed_dir_v1_old[3];
- float ed_dir_v2_old[3];
+ float ed_dir_v1_old[3];
+ float ed_dir_v2_old[3];
- float ed_dir_v1_new[3];
- float ed_dir_v2_new[3];
+ float ed_dir_v1_new[3];
+ float ed_dir_v2_new[3];
- float cross_old[3];
- float cross_new[3];
+ float cross_old[3];
+ float cross_new[3];
- /* original verts - these will be in the edge 'e' */
- BMVert *v1_old, *v2_old;
+ /* original verts - these will be in the edge 'e' */
+ BMVert *v1_old, *v2_old;
- /* verts from the loops passed */
+ /* verts from the loops passed */
- BMVert *v1, *v2;
- /* these are the opposite verts - the verts that _would_ be used if 'ccw' was inverted*/
- BMVert *v1_alt, *v2_alt;
+ BMVert *v1, *v2;
+ /* these are the opposite verts - the verts that _would_ be used if 'ccw' was inverted*/
+ BMVert *v1_alt, *v2_alt;
- /* this should have already run */
- BLI_assert(BM_edge_rotate_check(e) == true);
+ /* this should have already run */
+ BLI_assert(BM_edge_rotate_check(e) == true);
- BM_edge_ordered_verts(e, &v1_old, &v2_old);
+ BM_edge_ordered_verts(e, &v1_old, &v2_old);
- v1 = l1->v;
- v2 = l2->v;
+ v1 = l1->v;
+ v2 = l2->v;
- /* get the next vert along */
- v1_alt = BM_face_other_vert_loop(l1->f, v1_old, v1)->v;
- v2_alt = BM_face_other_vert_loop(l2->f, v2_old, v2)->v;
+ /* get the next vert along */
+ v1_alt = BM_face_other_vert_loop(l1->f, v1_old, v1)->v;
+ v2_alt = BM_face_other_vert_loop(l2->f, v2_old, v2)->v;
- /* normalize all so comparisons are scale independent */
+ /* normalize all so comparisons are scale independent */
- BLI_assert(BM_edge_exists(v1_old, v1));
- BLI_assert(BM_edge_exists(v1, v1_alt));
+ BLI_assert(BM_edge_exists(v1_old, v1));
+ BLI_assert(BM_edge_exists(v1, v1_alt));
- BLI_assert(BM_edge_exists(v2_old, v2));
- BLI_assert(BM_edge_exists(v2, v2_alt));
+ BLI_assert(BM_edge_exists(v2_old, v2));
+ BLI_assert(BM_edge_exists(v2, v2_alt));
- /* old and new edge vecs */
- sub_v3_v3v3(ed_dir_old, v1_old->co, v2_old->co);
- sub_v3_v3v3(ed_dir_new, v1->co, v2->co);
- normalize_v3(ed_dir_old);
- normalize_v3(ed_dir_new);
+ /* old and new edge vecs */
+ sub_v3_v3v3(ed_dir_old, v1_old->co, v2_old->co);
+ sub_v3_v3v3(ed_dir_new, v1->co, v2->co);
+ normalize_v3(ed_dir_old);
+ normalize_v3(ed_dir_new);
- /* old edge corner vecs */
- sub_v3_v3v3(ed_dir_v1_old, v1_old->co, v1->co);
- sub_v3_v3v3(ed_dir_v2_old, v2_old->co, v2->co);
- normalize_v3(ed_dir_v1_old);
- normalize_v3(ed_dir_v2_old);
+ /* old edge corner vecs */
+ sub_v3_v3v3(ed_dir_v1_old, v1_old->co, v1->co);
+ sub_v3_v3v3(ed_dir_v2_old, v2_old->co, v2->co);
+ normalize_v3(ed_dir_v1_old);
+ normalize_v3(ed_dir_v2_old);
- /* old edge corner vecs */
- sub_v3_v3v3(ed_dir_v1_new, v1->co, v1_alt->co);
- sub_v3_v3v3(ed_dir_v2_new, v2->co, v2_alt->co);
- normalize_v3(ed_dir_v1_new);
- normalize_v3(ed_dir_v2_new);
+ /* old edge corner vecs */
+ sub_v3_v3v3(ed_dir_v1_new, v1->co, v1_alt->co);
+ sub_v3_v3v3(ed_dir_v2_new, v2->co, v2_alt->co);
+ normalize_v3(ed_dir_v1_new);
+ normalize_v3(ed_dir_v2_new);
- /* compare */
- cross_v3_v3v3(cross_old, ed_dir_old, ed_dir_v1_old);
- cross_v3_v3v3(cross_new, ed_dir_new, ed_dir_v1_new);
- if (dot_v3v3(cross_old, cross_new) < 0.0f) { /* does this flip? */
- return false;
- }
- cross_v3_v3v3(cross_old, ed_dir_old, ed_dir_v2_old);
- cross_v3_v3v3(cross_new, ed_dir_new, ed_dir_v2_new);
- if (dot_v3v3(cross_old, cross_new) < 0.0f) { /* does this flip? */
- return false;
- }
+ /* compare */
+ cross_v3_v3v3(cross_old, ed_dir_old, ed_dir_v1_old);
+ cross_v3_v3v3(cross_new, ed_dir_new, ed_dir_v1_new);
+ if (dot_v3v3(cross_old, cross_new) < 0.0f) { /* does this flip? */
+ return false;
+ }
+ cross_v3_v3v3(cross_old, ed_dir_old, ed_dir_v2_old);
+ cross_v3_v3v3(cross_new, ed_dir_new, ed_dir_v2_new);
+ if (dot_v3v3(cross_old, cross_new) < 0.0f) { /* does this flip? */
+ return false;
+ }
- negate_v3_v3(ed_dir_new_flip, ed_dir_new);
+ negate_v3_v3(ed_dir_new_flip, ed_dir_new);
- /* result is zero area corner */
- if ((dot_v3v3(ed_dir_new, ed_dir_v1_new) > 0.999f) ||
- (dot_v3v3(ed_dir_new_flip, ed_dir_v2_new) > 0.999f))
- {
- return false;
- }
+ /* result is zero area corner */
+ if ((dot_v3v3(ed_dir_new, ed_dir_v1_new) > 0.999f) ||
+ (dot_v3v3(ed_dir_new_flip, ed_dir_v2_new) > 0.999f)) {
+ return false;
+ }
- return true;
+ return true;
}
-bool BM_edge_rotate_check_beauty(
- BMEdge *e,
- BMLoop *l1, BMLoop *l2)
+bool BM_edge_rotate_check_beauty(BMEdge *e, BMLoop *l1, BMLoop *l2)
{
- /* Stupid check for now:
- * Could compare angles of surrounding edges
- * before & after, but this is OK.*/
- return (len_squared_v3v3(e->v1->co, e->v2->co) >
- len_squared_v3v3(l1->v->co, l2->v->co));
+ /* Stupid check for now:
+ * Could compare angles of surrounding edges
+ * before & after, but this is OK.*/
+ return (len_squared_v3v3(e->v1->co, e->v2->co) > len_squared_v3v3(l1->v->co, l2->v->co));
}
/**
@@ -981,115 +977,113 @@ bool BM_edge_rotate_check_beauty(
*/
BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const bool ccw, const short check_flag)
{
- BMVert *v1, *v2;
- BMLoop *l1, *l2;
- BMFace *f;
- BMEdge *e_new = NULL;
- char f_active_prev = 0;
- char f_hflag_prev_1;
- char f_hflag_prev_2;
-
- if (!BM_edge_rotate_check(e)) {
- return NULL;
- }
-
- BM_edge_calc_rotate(e, ccw, &l1, &l2);
-
- /* the loops will be freed so assign verts */
- v1 = l1->v;
- v2 = l2->v;
-
- /* --------------------------------------- */
- /* Checking Code - make sure we can rotate */
-
- if (check_flag & BM_EDGEROT_CHECK_BEAUTY) {
- if (!BM_edge_rotate_check_beauty(e, l1, l2)) {
- return NULL;
- }
- }
-
- /* check before applying */
- if (check_flag & BM_EDGEROT_CHECK_EXISTS) {
- if (BM_edge_exists(v1, v2)) {
- return NULL;
- }
- }
-
- /* slowest, check last */
- if (check_flag & BM_EDGEROT_CHECK_DEGENERATE) {
- if (!BM_edge_rotate_check_degenerate(e, l1, l2)) {
- return NULL;
- }
- }
- /* Done Checking */
- /* ------------- */
-
-
-
- /* --------------- */
- /* Rotate The Edge */
-
- /* first create the new edge, this is so we can copy the customdata from the old one
- * if splice if disabled, always add in a new edge even if theres one there. */
- e_new = BM_edge_create(bm, v1, v2, e, (check_flag & BM_EDGEROT_CHECK_SPLICE) ? BM_CREATE_NO_DOUBLE : BM_CREATE_NOP);
-
- f_hflag_prev_1 = l1->f->head.hflag;
- f_hflag_prev_2 = l2->f->head.hflag;
-
- /* maintain active face */
- if (bm->act_face == l1->f) {
- f_active_prev = 1;
- }
- else if (bm->act_face == l2->f) {
- f_active_prev = 2;
- }
-
- const bool is_flipped = !BM_edge_is_contiguous(e);
-
- /* don't delete the edge, manually remove the edge after so we can copy its attributes */
- f = BM_faces_join_pair(bm, BM_face_edge_share_loop(l1->f, e), BM_face_edge_share_loop(l2->f, e), true);
-
- if (f == NULL) {
- return NULL;
- }
-
- /* note, this assumes joining the faces _didnt_ also remove the verts.
- * the #BM_edge_rotate_check will ensure this, but its possibly corrupt state or future edits
- * break this */
- if ((l1 = BM_face_vert_share_loop(f, v1)) &&
- (l2 = BM_face_vert_share_loop(f, v2)) &&
- BM_face_split(bm, f, l1, l2, NULL, NULL, true))
- {
- /* we should really be able to know the faces some other way,
- * rather then fetching them back from the edge, but this is predictable
- * where using the return values from face split isn't. - campbell */
- BMFace *fa, *fb;
- if (BM_edge_face_pair(e_new, &fa, &fb)) {
- fa->head.hflag = f_hflag_prev_1;
- fb->head.hflag = f_hflag_prev_2;
-
- if (f_active_prev == 1) {
- bm->act_face = fa;
- }
- else if (f_active_prev == 2) {
- bm->act_face = fb;
- }
-
- if (is_flipped) {
- BM_face_normal_flip(bm, fb);
-
- if (ccw) {
- /* needed otherwise ccw toggles direction */
- e_new->l = e_new->l->radial_next;
- }
- }
- }
- }
- else {
- return NULL;
- }
-
- return e_new;
+ BMVert *v1, *v2;
+ BMLoop *l1, *l2;
+ BMFace *f;
+ BMEdge *e_new = NULL;
+ char f_active_prev = 0;
+ char f_hflag_prev_1;
+ char f_hflag_prev_2;
+
+ if (!BM_edge_rotate_check(e)) {
+ return NULL;
+ }
+
+ BM_edge_calc_rotate(e, ccw, &l1, &l2);
+
+ /* the loops will be freed so assign verts */
+ v1 = l1->v;
+ v2 = l2->v;
+
+ /* --------------------------------------- */
+ /* Checking Code - make sure we can rotate */
+
+ if (check_flag & BM_EDGEROT_CHECK_BEAUTY) {
+ if (!BM_edge_rotate_check_beauty(e, l1, l2)) {
+ return NULL;
+ }
+ }
+
+ /* check before applying */
+ if (check_flag & BM_EDGEROT_CHECK_EXISTS) {
+ if (BM_edge_exists(v1, v2)) {
+ return NULL;
+ }
+ }
+
+ /* slowest, check last */
+ if (check_flag & BM_EDGEROT_CHECK_DEGENERATE) {
+ if (!BM_edge_rotate_check_degenerate(e, l1, l2)) {
+ return NULL;
+ }
+ }
+ /* Done Checking */
+ /* ------------- */
+
+ /* --------------- */
+ /* Rotate The Edge */
+
+ /* first create the new edge, this is so we can copy the customdata from the old one
+ * if splice if disabled, always add in a new edge even if theres one there. */
+ e_new = BM_edge_create(
+ bm, v1, v2, e, (check_flag & BM_EDGEROT_CHECK_SPLICE) ? BM_CREATE_NO_DOUBLE : BM_CREATE_NOP);
+
+ f_hflag_prev_1 = l1->f->head.hflag;
+ f_hflag_prev_2 = l2->f->head.hflag;
+
+ /* maintain active face */
+ if (bm->act_face == l1->f) {
+ f_active_prev = 1;
+ }
+ else if (bm->act_face == l2->f) {
+ f_active_prev = 2;
+ }
+
+ const bool is_flipped = !BM_edge_is_contiguous(e);
+
+ /* don't delete the edge, manually remove the edge after so we can copy its attributes */
+ f = BM_faces_join_pair(
+ bm, BM_face_edge_share_loop(l1->f, e), BM_face_edge_share_loop(l2->f, e), true);
+
+ if (f == NULL) {
+ return NULL;
+ }
+
+ /* note, this assumes joining the faces _didnt_ also remove the verts.
+ * the #BM_edge_rotate_check will ensure this, but its possibly corrupt state or future edits
+ * break this */
+ if ((l1 = BM_face_vert_share_loop(f, v1)) && (l2 = BM_face_vert_share_loop(f, v2)) &&
+ BM_face_split(bm, f, l1, l2, NULL, NULL, true)) {
+ /* we should really be able to know the faces some other way,
+ * rather then fetching them back from the edge, but this is predictable
+ * where using the return values from face split isn't. - campbell */
+ BMFace *fa, *fb;
+ if (BM_edge_face_pair(e_new, &fa, &fb)) {
+ fa->head.hflag = f_hflag_prev_1;
+ fb->head.hflag = f_hflag_prev_2;
+
+ if (f_active_prev == 1) {
+ bm->act_face = fa;
+ }
+ else if (f_active_prev == 2) {
+ bm->act_face = fb;
+ }
+
+ if (is_flipped) {
+ BM_face_normal_flip(bm, fb);
+
+ if (ccw) {
+ /* needed otherwise ccw toggles direction */
+ e_new->l = e_new->l->radial_next;
+ }
+ }
+ }
+ }
+ else {
+ return NULL;
+ }
+
+ return e_new;
}
/**
@@ -1097,15 +1091,15 @@ BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const bool ccw, const short check_f
*/
BMVert *BM_face_loop_separate(BMesh *bm, BMLoop *l_sep)
{
- return bmesh_kernel_unglue_region_make_vert(bm, l_sep);
+ return bmesh_kernel_unglue_region_make_vert(bm, l_sep);
}
BMVert *BM_face_loop_separate_multi_isolated(BMesh *bm, BMLoop *l_sep)
{
- return bmesh_kernel_unglue_region_make_vert_multi_isolated(bm, l_sep);
+ return bmesh_kernel_unglue_region_make_vert_multi_isolated(bm, l_sep);
}
BMVert *BM_face_loop_separate_multi(BMesh *bm, BMLoop **larr, int larr_len)
{
- return bmesh_kernel_unglue_region_make_vert_multi(bm, larr, larr_len);
+ return bmesh_kernel_unglue_region_make_vert_multi(bm, larr, larr_len);
}
diff --git a/source/blender/bmesh/intern/bmesh_mods.h b/source/blender/bmesh/intern/bmesh_mods.h
index 425770a8c32..3d4eefbb598 100644
--- a/source/blender/bmesh/intern/bmesh_mods.h
+++ b/source/blender/bmesh/intern/bmesh_mods.h
@@ -27,31 +27,43 @@ bool BM_disk_dissolve(BMesh *bm, BMVert *v);
BMFace *BM_faces_join_pair(BMesh *bm, BMLoop *l_a, BMLoop *l_b, const bool do_del);
-
/** see: bmesh_polygon_edgenet.h for #BM_face_split_edgenet */
-BMFace *BM_face_split(
- BMesh *bm, BMFace *f,
- BMLoop *l_a, BMLoop *l_b,
- BMLoop **r_l,
- BMEdge *example, const bool no_double);
-
-BMFace *BM_face_split_n(
- BMesh *bm, BMFace *f,
- BMLoop *l_a, BMLoop *l_b,
- float cos[][3], int n,
-BMLoop **r_l, BMEdge *example);
-
-BMEdge *BM_vert_collapse_faces(
- BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float fac,
- const bool do_del, const bool join_faces, const bool kill_degenerate_faces);
-BMEdge *BM_vert_collapse_edge(
- BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
- const bool do_del, const bool kill_degenerate_faces);
-
-BMVert *BM_edge_collapse(
- BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
- const bool do_del, const bool kill_degenerate_faces);
+BMFace *BM_face_split(BMesh *bm,
+ BMFace *f,
+ BMLoop *l_a,
+ BMLoop *l_b,
+ BMLoop **r_l,
+ BMEdge *example,
+ const bool no_double);
+
+BMFace *BM_face_split_n(BMesh *bm,
+ BMFace *f,
+ BMLoop *l_a,
+ BMLoop *l_b,
+ float cos[][3],
+ int n,
+ BMLoop **r_l,
+ BMEdge *example);
+
+BMEdge *BM_vert_collapse_faces(BMesh *bm,
+ BMEdge *e_kill,
+ BMVert *v_kill,
+ float fac,
+ const bool do_del,
+ const bool join_faces,
+ const bool kill_degenerate_faces);
+BMEdge *BM_vert_collapse_edge(BMesh *bm,
+ BMEdge *e_kill,
+ BMVert *v_kill,
+ const bool do_del,
+ const bool kill_degenerate_faces);
+
+BMVert *BM_edge_collapse(BMesh *bm,
+ BMEdge *e_kill,
+ BMVert *v_kill,
+ const bool do_del,
+ const bool kill_degenerate_faces);
BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float percent);
@@ -59,29 +71,25 @@ BMVert *BM_edge_split_n(BMesh *bm, BMEdge *e, int numcuts, BMVert **r_varr);
void BM_edge_verts_swap(BMEdge *e);
-bool BM_face_validate(BMFace *face, FILE *err);
-
-void BM_edge_calc_rotate(
- BMEdge *e, const bool ccw,
- BMLoop **r_l1, BMLoop **r_l2);
-bool BM_edge_rotate_check(BMEdge *e);
-bool BM_edge_rotate_check_degenerate(
- BMEdge *e,
- BMLoop *l1, BMLoop *l2);
-bool BM_edge_rotate_check_beauty(
- BMEdge *e,
- BMLoop *l1, BMLoop *l2);
+bool BM_face_validate(BMFace *face, FILE *err);
+
+void BM_edge_calc_rotate(BMEdge *e, const bool ccw, BMLoop **r_l1, BMLoop **r_l2);
+bool BM_edge_rotate_check(BMEdge *e);
+bool BM_edge_rotate_check_degenerate(BMEdge *e, BMLoop *l1, BMLoop *l2);
+bool BM_edge_rotate_check_beauty(BMEdge *e, BMLoop *l1, BMLoop *l2);
BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const bool ccw, const short check_flag);
/* flags for BM_edge_rotate */
enum {
- BM_EDGEROT_CHECK_EXISTS = (1 << 0), /* disallow to rotate when the new edge matches an existing one */
- BM_EDGEROT_CHECK_SPLICE = (1 << 1), /* overrides existing check, if the edge already, rotate and merge them */
- BM_EDGEROT_CHECK_DEGENERATE = (1 << 2), /* disallow creating bow-tie, concave or zero area faces */
- BM_EDGEROT_CHECK_BEAUTY = (1 << 3), /* disallow to rotate into ugly topology */
+ BM_EDGEROT_CHECK_EXISTS =
+ (1 << 0), /* disallow to rotate when the new edge matches an existing one */
+ BM_EDGEROT_CHECK_SPLICE =
+ (1 << 1), /* overrides existing check, if the edge already, rotate and merge them */
+ BM_EDGEROT_CHECK_DEGENERATE = (1
+ << 2), /* disallow creating bow-tie, concave or zero area faces */
+ BM_EDGEROT_CHECK_BEAUTY = (1 << 3), /* disallow to rotate into ugly topology */
};
-
BMVert *BM_face_loop_separate(BMesh *bm, BMLoop *l_sep);
BMVert *BM_face_loop_separate_multi_isolated(BMesh *bm, BMLoop *l_sep);
BMVert *BM_face_loop_separate_multi(BMesh *bm, BMLoop **larr, int larr_len);
diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c
index 4ca8e02e94d..2114f9ebd3d 100644
--- a/source/blender/bmesh/intern/bmesh_opdefines.c
+++ b/source/blender/bmesh/intern/bmesh_opdefines.c
@@ -96,20 +96,20 @@
/* enums shared between multiple operators */
static BMO_FlagSet bmo_enum_axis_xyz[] = {
- {0, "X"},
- {1, "Y"},
- {2, "Z"},
- {0, NULL},
+ {0, "X"},
+ {1, "Y"},
+ {2, "Z"},
+ {0, NULL},
};
static BMO_FlagSet bmo_enum_falloff_type[] = {
- {SUBD_FALLOFF_SMOOTH, "SMOOTH"},
- {SUBD_FALLOFF_SPHERE, "SPHERE"},
- {SUBD_FALLOFF_ROOT, "ROOT"},
- {SUBD_FALLOFF_SHARP, "SHARP"},
- {SUBD_FALLOFF_LIN, "LINEAR"},
- {SUBD_FALLOFF_INVSQUARE, "INVERSE_SQUARE"},
- {0, NULL},
+ {SUBD_FALLOFF_SMOOTH, "SMOOTH"},
+ {SUBD_FALLOFF_SPHERE, "SPHERE"},
+ {SUBD_FALLOFF_ROOT, "ROOT"},
+ {SUBD_FALLOFF_SHARP, "SHARP"},
+ {SUBD_FALLOFF_LIN, "LINEAR"},
+ {SUBD_FALLOFF_INVSQUARE, "INVERSE_SQUARE"},
+ {0, NULL},
};
/*
@@ -118,22 +118,22 @@ static BMO_FlagSet bmo_enum_falloff_type[] = {
* Smooths vertices by using a basic vertex averaging scheme.
*/
static BMOpDefine bmo_smooth_vert_def = {
- "smooth_vert",
- /* slots_in */
- {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */
- {"factor", BMO_OP_SLOT_FLT}, /* smoothing factor */
- {"mirror_clip_x", BMO_OP_SLOT_BOOL}, /* set vertices close to the x axis before the operation to 0 */
- {"mirror_clip_y", BMO_OP_SLOT_BOOL}, /* set vertices close to the y axis before the operation to 0 */
- {"mirror_clip_z", BMO_OP_SLOT_BOOL}, /* set vertices close to the z axis before the operation to 0 */
- {"clip_dist", BMO_OP_SLOT_FLT}, /* clipping threshold for the above three slots */
- {"use_axis_x", BMO_OP_SLOT_BOOL}, /* smooth vertices along X axis */
- {"use_axis_y", BMO_OP_SLOT_BOOL}, /* smooth vertices along Y axis */
- {"use_axis_z", BMO_OP_SLOT_BOOL}, /* smooth vertices along Z axis */
- {{'\0'}},
- },
- {{{'\0'}}}, /* no output */
- bmo_smooth_vert_exec,
- (BMO_OPTYPE_FLAG_NORMALS_CALC),
+ "smooth_vert",
+ /* slots_in */
+ {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */
+ {"factor", BMO_OP_SLOT_FLT}, /* smoothing factor */
+ {"mirror_clip_x", BMO_OP_SLOT_BOOL}, /* set vertices close to the x axis before the operation to 0 */
+ {"mirror_clip_y", BMO_OP_SLOT_BOOL}, /* set vertices close to the y axis before the operation to 0 */
+ {"mirror_clip_z", BMO_OP_SLOT_BOOL}, /* set vertices close to the z axis before the operation to 0 */
+ {"clip_dist", BMO_OP_SLOT_FLT}, /* clipping threshold for the above three slots */
+ {"use_axis_x", BMO_OP_SLOT_BOOL}, /* smooth vertices along X axis */
+ {"use_axis_y", BMO_OP_SLOT_BOOL}, /* smooth vertices along Y axis */
+ {"use_axis_z", BMO_OP_SLOT_BOOL}, /* smooth vertices along Z axis */
+ {{'\0'}},
+ },
+ {{{'\0'}}}, /* no output */
+ bmo_smooth_vert_exec,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC),
};
/*
@@ -143,20 +143,20 @@ static BMOpDefine bmo_smooth_vert_def = {
* Desbrun, et al. Implicit Fairing of Irregular Meshes using Diffusion and Curvature Flow.
*/
static BMOpDefine bmo_smooth_laplacian_vert_def = {
- "smooth_laplacian_vert",
- /* slots_in */
- {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */
- {"lambda_factor", BMO_OP_SLOT_FLT}, /* lambda param */
- {"lambda_border", BMO_OP_SLOT_FLT}, /* lambda param in border */
- {"use_x", BMO_OP_SLOT_BOOL}, /* Smooth object along X axis */
- {"use_y", BMO_OP_SLOT_BOOL}, /* Smooth object along Y axis */
- {"use_z", BMO_OP_SLOT_BOOL}, /* Smooth object along Z axis */
- {"preserve_volume", BMO_OP_SLOT_BOOL}, /* Apply volume preservation after smooth */
- {{'\0'}},
- },
- {{{'\0'}}}, /* no output */
- bmo_smooth_laplacian_vert_exec,
- (BMO_OPTYPE_FLAG_NORMALS_CALC),
+ "smooth_laplacian_vert",
+ /* slots_in */
+ {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */
+ {"lambda_factor", BMO_OP_SLOT_FLT}, /* lambda param */
+ {"lambda_border", BMO_OP_SLOT_FLT}, /* lambda param in border */
+ {"use_x", BMO_OP_SLOT_BOOL}, /* Smooth object along X axis */
+ {"use_y", BMO_OP_SLOT_BOOL}, /* Smooth object along Y axis */
+ {"use_z", BMO_OP_SLOT_BOOL}, /* Smooth object along Z axis */
+ {"preserve_volume", BMO_OP_SLOT_BOOL}, /* Apply volume preservation after smooth */
+ {{'\0'}},
+ },
+ {{{'\0'}}}, /* no output */
+ bmo_smooth_laplacian_vert_exec,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC),
};
/*
@@ -165,15 +165,15 @@ static BMOpDefine bmo_smooth_laplacian_vert_def = {
* Computes an "outside" normal for the specified input faces.
*/
static BMOpDefine bmo_recalc_face_normals_def = {
- "recalc_face_normals",
- /* slots_in */
- {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
- {{'\0'}},
- },
- {{{'\0'}}}, /* no output */
- bmo_recalc_face_normals_exec,
- (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
- BMO_OPTYPE_FLAG_NORMALS_CALC),
+ "recalc_face_normals",
+ /* slots_in */
+ {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
+ {{'\0'}},
+ },
+ {{{'\0'}}}, /* no output */
+ bmo_recalc_face_normals_exec,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC),
};
/*
@@ -182,20 +182,20 @@ static BMOpDefine bmo_recalc_face_normals_def = {
* Iteratively flatten faces.
*/
static BMOpDefine bmo_planar_faces_def = {
- "planar_faces",
- /* slots_in */
- {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input geometry. */
- {"iterations", BMO_OP_SLOT_INT}, /* Number of times to flatten faces (for when connected faces are used) */
- {"factor", BMO_OP_SLOT_FLT}, /* Influence for making planar each iteration */
- {{'\0'}},
- },
- /* slots_out */
- {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* output slot, computed boundary geometry. */
- {{'\0'}},
- },
- bmo_planar_faces_exec,
- (BMO_OPTYPE_FLAG_SELECT_FLUSH |
- BMO_OPTYPE_FLAG_SELECT_VALIDATE),
+ "planar_faces",
+ /* slots_in */
+ {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input geometry. */
+ {"iterations", BMO_OP_SLOT_INT}, /* Number of times to flatten faces (for when connected faces are used) */
+ {"factor", BMO_OP_SLOT_FLT}, /* Influence for making planar each iteration */
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* output slot, computed boundary geometry. */
+ {{'\0'}},
+ },
+ bmo_planar_faces_exec,
+ (BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -209,21 +209,21 @@ static BMOpDefine bmo_planar_faces_def = {
* otherwise it spits out faces.
*/
static BMOpDefine bmo_region_extend_def = {
- "region_extend",
- /* slots_in */
- {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input geometry */
- {"use_contract", BMO_OP_SLOT_BOOL}, /* find boundary inside the regions, not outside. */
- {"use_faces", BMO_OP_SLOT_BOOL}, /* extend from faces instead of edges */
- {"use_face_step", BMO_OP_SLOT_BOOL}, /* step over connected faces */
- {{'\0'}},
- },
- /* slots_out */
- {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* output slot, computed boundary geometry. */
- {{'\0'}},
- },
- bmo_region_extend_exec,
- (BMO_OPTYPE_FLAG_SELECT_FLUSH |
- BMO_OPTYPE_FLAG_SELECT_VALIDATE),
+ "region_extend",
+ /* slots_in */
+ {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input geometry */
+ {"use_contract", BMO_OP_SLOT_BOOL}, /* find boundary inside the regions, not outside. */
+ {"use_faces", BMO_OP_SLOT_BOOL}, /* extend from faces instead of edges */
+ {"use_face_step", BMO_OP_SLOT_BOOL}, /* step over connected faces */
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* output slot, computed boundary geometry. */
+ {{'\0'}},
+ },
+ bmo_region_extend_exec,
+ (BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -233,21 +233,21 @@ static BMOpDefine bmo_region_extend_def = {
* Simple example: ``[/] becomes [|] then [\]``.
*/
static BMOpDefine bmo_rotate_edges_def = {
- "rotate_edges",
- /* slots_in */
- {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
- {"use_ccw", BMO_OP_SLOT_BOOL}, /* rotate edge counter-clockwise if true, otherwise clockwise */
- {{'\0'}},
- },
- /* slots_out */
- {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* newly spun edges */
- {{'\0'}},
- },
- bmo_rotate_edges_exec,
- (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
- BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH |
- BMO_OPTYPE_FLAG_SELECT_VALIDATE),
+ "rotate_edges",
+ /* slots_in */
+ {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
+ {"use_ccw", BMO_OP_SLOT_BOOL}, /* rotate edge counter-clockwise if true, otherwise clockwise */
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* newly spun edges */
+ {{'\0'}},
+ },
+ bmo_rotate_edges_exec,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -257,16 +257,16 @@ static BMOpDefine bmo_rotate_edges_def = {
* This has the effect of flipping the normal.
*/
static BMOpDefine bmo_reverse_faces_def = {
- "reverse_faces",
- /* slots_in */
- {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */
- {"flip_multires", BMO_OP_SLOT_BOOL}, /* maintain multi-res offset */
- {{'\0'}},
- },
- {{{'\0'}}}, /* no output */
- bmo_reverse_faces_exec,
- (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
- BMO_OPTYPE_FLAG_NORMALS_CALC),
+ "reverse_faces",
+ /* slots_in */
+ {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */
+ {"flip_multires", BMO_OP_SLOT_BOOL}, /* maintain multi-res offset */
+ {{'\0'}},
+ },
+ {{{'\0'}}}, /* no output */
+ bmo_reverse_faces_exec,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC),
};
/*
@@ -276,22 +276,22 @@ static BMOpDefine bmo_reverse_faces_def = {
* This creates a 2-valence vert.
*/
static BMOpDefine bmo_bisect_edges_def = {
- "bisect_edges",
- /* slots_in */
- {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
- {"cuts", BMO_OP_SLOT_INT}, /* number of cuts */
- {"edge_percents", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_FLT}},
- {{'\0'}},
- },
- /* slots_out */
- {{"geom_split.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* newly created vertices and edges */
- {{'\0'}},
- },
- bmo_bisect_edges_exec,
- (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
- BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH |
- BMO_OPTYPE_FLAG_SELECT_VALIDATE),
+ "bisect_edges",
+ /* slots_in */
+ {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
+ {"cuts", BMO_OP_SLOT_INT}, /* number of cuts */
+ {"edge_percents", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_FLT}},
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"geom_split.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* newly created vertices and edges */
+ {{'\0'}},
+ },
+ bmo_bisect_edges_exec,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -302,24 +302,24 @@ static BMOpDefine bmo_bisect_edges_def = {
* parameter (which defines the minimum distance for welding to happen).
*/
static BMOpDefine bmo_mirror_def = {
- "mirror",
- /* slots_in */
- {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input geometry */
- {"matrix", BMO_OP_SLOT_MAT}, /* matrix defining the mirror transformation */
- {"merge_dist", BMO_OP_SLOT_FLT}, /* maximum distance for merging. does no merging if 0. */
- {"axis", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_axis_xyz}, /* the axis to use. */
- {"mirror_u", BMO_OP_SLOT_BOOL}, /* mirror UVs across the u axis */
- {"mirror_v", BMO_OP_SLOT_BOOL}, /* mirror UVs across the v axis */
- {{'\0'}},
- },
- /* slots_out */
- {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* output geometry, mirrored */
- {{'\0'}},
- },
- bmo_mirror_exec,
- (BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH |
- BMO_OPTYPE_FLAG_SELECT_VALIDATE),
+ "mirror",
+ /* slots_in */
+ {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input geometry */
+ {"matrix", BMO_OP_SLOT_MAT}, /* matrix defining the mirror transformation */
+ {"merge_dist", BMO_OP_SLOT_FLT}, /* maximum distance for merging. does no merging if 0. */
+ {"axis", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_axis_xyz}, /* the axis to use. */
+ {"mirror_u", BMO_OP_SLOT_BOOL}, /* mirror UVs across the u axis */
+ {"mirror_v", BMO_OP_SLOT_BOOL}, /* mirror UVs across the v axis */
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* output geometry, mirrored */
+ {{'\0'}},
+ },
+ bmo_mirror_exec,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -332,19 +332,19 @@ static BMOpDefine bmo_mirror_def = {
* with vertices in that set.
*/
static BMOpDefine bmo_find_doubles_def = {
- "find_doubles",
- /* slots_in */
- {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */
- {"keep_verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* list of verts to keep */
- {"dist", BMO_OP_SLOT_FLT}, /* minimum distance */
- {{'\0'}},
- },
- /* slots_out */
- {{"targetmap.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
- {{'\0'}},
- },
- bmo_find_doubles_exec,
- (BMO_OPTYPE_FLAG_NOP),
+ "find_doubles",
+ /* slots_in */
+ {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */
+ {"keep_verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* list of verts to keep */
+ {"dist", BMO_OP_SLOT_FLT}, /* minimum distance */
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"targetmap.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
+ {{'\0'}},
+ },
+ bmo_find_doubles_exec,
+ (BMO_OPTYPE_FLAG_NOP),
};
/*
@@ -354,18 +354,18 @@ static BMOpDefine bmo_find_doubles_def = {
* using the weld verts bmop.
*/
static BMOpDefine bmo_remove_doubles_def = {
- "remove_doubles",
- /* slots_in */
- {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input verts */
- {"dist", BMO_OP_SLOT_FLT}, /* minimum distance */
- {{'\0'}},
- },
- {{{'\0'}}}, /* no output */
- bmo_remove_doubles_exec,
- (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
- BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH |
- BMO_OPTYPE_FLAG_SELECT_VALIDATE),
+ "remove_doubles",
+ /* slots_in */
+ {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input verts */
+ {"dist", BMO_OP_SLOT_FLT}, /* minimum distance */
+ {{'\0'}},
+ },
+ {{{'\0'}}}, /* no output */
+ bmo_remove_doubles_exec,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -376,18 +376,18 @@ static BMOpDefine bmo_remove_doubles_def = {
* **verts** to one in **verts**.
*/
static BMOpDefine bmo_automerge_def = {
- "automerge",
- /* slots_in */
- {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input verts */
- {"dist", BMO_OP_SLOT_FLT}, /* minimum distance */
- {{'\0'}},
- },
- {{{'\0'}}}, /* no output */
- bmo_automerge_exec,
- (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
- BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH |
- BMO_OPTYPE_FLAG_SELECT_VALIDATE),
+ "automerge",
+ /* slots_in */
+ {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input verts */
+ {"dist", BMO_OP_SLOT_FLT}, /* minimum distance */
+ {{'\0'}},
+ },
+ {{{'\0'}}}, /* no output */
+ bmo_automerge_exec,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -396,18 +396,18 @@ static BMOpDefine bmo_automerge_def = {
* Collapses connected vertices
*/
static BMOpDefine bmo_collapse_def = {
- "collapse",
- /* slots_in */
- {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
- {"uvs", BMO_OP_SLOT_BOOL}, /* also collapse UVs and such */
- {{'\0'}},
- },
- {{{'\0'}}}, /* no output */
- bmo_collapse_exec,
- (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
- BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH |
- BMO_OPTYPE_FLAG_SELECT_VALIDATE),
+ "collapse",
+ /* slots_in */
+ {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
+ {"uvs", BMO_OP_SLOT_BOOL}, /* also collapse UVs and such */
+ {{'\0'}},
+ },
+ {{{'\0'}}}, /* no output */
+ bmo_collapse_exec,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -416,15 +416,15 @@ static BMOpDefine bmo_collapse_def = {
* Merge uv/vcols at a specific vertex.
*/
static BMOpDefine bmo_pointmerge_facedata_def = {
- "pointmerge_facedata",
- /* slots_in */
- {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */
- {"vert_snap", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | (int)BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE}}, /* snap vertex */
- {{'\0'}},
- },
- {{{'\0'}}}, /* no output */
- bmo_pointmerge_facedata_exec,
- (BMO_OPTYPE_FLAG_NOP),
+ "pointmerge_facedata",
+ /* slots_in */
+ {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */
+ {"vert_snap", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | (int)BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE}}, /* snap vertex */
+ {{'\0'}},
+ },
+ {{{'\0'}}}, /* no output */
+ bmo_pointmerge_facedata_exec,
+ (BMO_OPTYPE_FLAG_NOP),
};
/*
@@ -435,14 +435,14 @@ static BMOpDefine bmo_pointmerge_facedata_def = {
* the vert_snap_to_bb_center is just too long).
*/
static BMOpDefine bmo_average_vert_facedata_def = {
- "average_vert_facedata",
- /* slots_in */
- {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */
- {{'\0'}},
- },
- {{{'\0'}}}, /* no output */
- bmo_average_vert_facedata_exec,
- (BMO_OPTYPE_FLAG_NOP),
+ "average_vert_facedata",
+ /* slots_in */
+ {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */
+ {{'\0'}},
+ },
+ {{{'\0'}}}, /* no output */
+ bmo_average_vert_facedata_exec,
+ (BMO_OPTYPE_FLAG_NOP),
};
/*
@@ -451,18 +451,18 @@ static BMOpDefine bmo_average_vert_facedata_def = {
* Merge verts together at a point.
*/
static BMOpDefine bmo_pointmerge_def = {
- "pointmerge",
- /* slots_in */
- {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices (all verts will be merged into the first). */
- {"merge_co", BMO_OP_SLOT_VEC}, /* Position to merge at. */
- {{'\0'}},
- },
- {{{'\0'}}}, /* no output */
- bmo_pointmerge_exec,
- (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
- BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH |
- BMO_OPTYPE_FLAG_SELECT_VALIDATE),
+ "pointmerge",
+ /* slots_in */
+ {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices (all verts will be merged into the first). */
+ {"merge_co", BMO_OP_SLOT_VEC}, /* Position to merge at. */
+ {{'\0'}},
+ },
+ {{{'\0'}}}, /* no output */
+ bmo_pointmerge_exec,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -471,14 +471,14 @@ static BMOpDefine bmo_pointmerge_def = {
* Collapses connected UV vertices.
*/
static BMOpDefine bmo_collapse_uvs_def = {
- "collapse_uvs",
- /* slots_in */
- {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
- {{'\0'}},
- },
- {{{'\0'}}}, /* no output */
- bmo_collapse_uvs_exec,
- (BMO_OPTYPE_FLAG_NOP),
+ "collapse_uvs",
+ /* slots_in */
+ {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
+ {{'\0'}},
+ },
+ {{{'\0'}}}, /* no output */
+ bmo_collapse_uvs_exec,
+ (BMO_OPTYPE_FLAG_NOP),
};
/*
@@ -489,18 +489,18 @@ static BMOpDefine bmo_collapse_uvs_def = {
* they weld with.
*/
static BMOpDefine bmo_weld_verts_def = {
- "weld_verts",
- /* slots_in */
- /* maps welded vertices to verts they should weld to */
- {{"targetmap", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
- {{'\0'}},
- },
- {{{'\0'}}}, /* no output */
- bmo_weld_verts_exec,
- (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
- BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH |
- BMO_OPTYPE_FLAG_SELECT_VALIDATE),
+ "weld_verts",
+ /* slots_in */
+ /* maps welded vertices to verts they should weld to */
+ {{"targetmap", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
+ {{'\0'}},
+ },
+ {{{'\0'}}}, /* no output */
+ bmo_weld_verts_exec,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -510,17 +510,17 @@ static BMOpDefine bmo_weld_verts_def = {
* for click-create-vertex.
*/
static BMOpDefine bmo_create_vert_def = {
- "create_vert",
- /* slots_in */
- {{"co", BMO_OP_SLOT_VEC}, /* the coordinate of the new vert */
- {{'\0'}},
- },
- /* slots_out */
- {{"vert.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* the new vert */
- {{'\0'}},
- },
- bmo_create_vert_exec,
- (BMO_OPTYPE_FLAG_NOP),
+ "create_vert",
+ /* slots_in */
+ {{"co", BMO_OP_SLOT_VEC}, /* the coordinate of the new vert */
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"vert.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* the new vert */
+ {{'\0'}},
+ },
+ bmo_create_vert_exec,
+ (BMO_OPTYPE_FLAG_NOP),
};
/*
@@ -530,27 +530,27 @@ static BMOpDefine bmo_create_vert_def = {
* to angle threshold and delimiters.
*/
static BMOpDefine bmo_join_triangles_def = {
- "join_triangles",
- /* slots_in */
- {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input geometry. */
- {"cmp_seam", BMO_OP_SLOT_BOOL},
- {"cmp_sharp", BMO_OP_SLOT_BOOL},
- {"cmp_uvs", BMO_OP_SLOT_BOOL},
- {"cmp_vcols", BMO_OP_SLOT_BOOL},
- {"cmp_materials", BMO_OP_SLOT_BOOL},
- {"angle_face_threshold", BMO_OP_SLOT_FLT},
- {"angle_shape_threshold", BMO_OP_SLOT_FLT},
- {{'\0'}},
- },
- /* slots_out */
- {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* joined faces */
- {{'\0'}},
- },
- bmo_join_triangles_exec,
- (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
- BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH |
- BMO_OPTYPE_FLAG_SELECT_VALIDATE),
+ "join_triangles",
+ /* slots_in */
+ {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input geometry. */
+ {"cmp_seam", BMO_OP_SLOT_BOOL},
+ {"cmp_sharp", BMO_OP_SLOT_BOOL},
+ {"cmp_uvs", BMO_OP_SLOT_BOOL},
+ {"cmp_vcols", BMO_OP_SLOT_BOOL},
+ {"cmp_materials", BMO_OP_SLOT_BOOL},
+ {"angle_face_threshold", BMO_OP_SLOT_FLT},
+ {"angle_shape_threshold", BMO_OP_SLOT_FLT},
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* joined faces */
+ {{'\0'}},
+ },
+ bmo_join_triangles_exec,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -564,49 +564,49 @@ static BMOpDefine bmo_join_triangles_def = {
* become a wire edge.
*/
static BMOpDefine bmo_contextual_create_def = {
- "contextual_create",
- /* slots_in */
- {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input geometry. */
- {"mat_nr", BMO_OP_SLOT_INT}, /* material to use */
- {"use_smooth", BMO_OP_SLOT_BOOL}, /* smooth to use */
- {{'\0'}},
- },
- /* slots_out */
- {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* newly-made face(s) */
- /* note, this is for stand-alone edges only, not edges which are apart of newly created faces */
- {"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* newly-made edge(s) */
- {{'\0'}},
- },
- bmo_contextual_create_exec,
- (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
- BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH |
- BMO_OPTYPE_FLAG_SELECT_VALIDATE),
+ "contextual_create",
+ /* slots_in */
+ {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input geometry. */
+ {"mat_nr", BMO_OP_SLOT_INT}, /* material to use */
+ {"use_smooth", BMO_OP_SLOT_BOOL}, /* smooth to use */
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* newly-made face(s) */
+ /* note, this is for stand-alone edges only, not edges which are apart of newly created faces */
+ {"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* newly-made edge(s) */
+ {{'\0'}},
+ },
+ bmo_contextual_create_exec,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
* Bridge edge loops with faces.
*/
static BMOpDefine bmo_bridge_loops_def = {
- "bridge_loops",
- /* slots_in */
- {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
- {"use_pairs", BMO_OP_SLOT_BOOL},
- {"use_cyclic", BMO_OP_SLOT_BOOL},
- {"use_merge", BMO_OP_SLOT_BOOL},
- {"merge_factor", BMO_OP_SLOT_FLT},
- {"twist_offset", BMO_OP_SLOT_INT},
- {{'\0'}},
- },
- /* slots_out */
- {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new faces */
- {"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* new edges */
- {{'\0'}},
- },
- bmo_bridge_loops_exec,
- (BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH |
- BMO_OPTYPE_FLAG_SELECT_VALIDATE),
+ "bridge_loops",
+ /* slots_in */
+ {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
+ {"use_pairs", BMO_OP_SLOT_BOOL},
+ {"use_cyclic", BMO_OP_SLOT_BOOL},
+ {"use_merge", BMO_OP_SLOT_BOOL},
+ {"merge_factor", BMO_OP_SLOT_FLT},
+ {"twist_offset", BMO_OP_SLOT_INT},
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new faces */
+ {"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* new edges */
+ {{'\0'}},
+ },
+ bmo_bridge_loops_exec,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -615,23 +615,23 @@ static BMOpDefine bmo_bridge_loops_def = {
* Create faces defined by 2 disconnected edge loops (which share edges).
*/
static BMOpDefine bmo_grid_fill_def = {
- "grid_fill",
- /* slots_in */
- {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
- /* restricts edges to groups. maps edges to integer */
- {"mat_nr", BMO_OP_SLOT_INT}, /* material to use */
- {"use_smooth", BMO_OP_SLOT_BOOL}, /* smooth state to use */
- {"use_interp_simple", BMO_OP_SLOT_BOOL}, /* use simple interpolation */
- {{'\0'}},
- },
- /* slots_out */
- /* maps new faces to the group numbers they came from */
- {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new faces */
- {{'\0'}},
- },
- bmo_grid_fill_exec,
- (BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH),
+ "grid_fill",
+ /* slots_in */
+ {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
+ /* restricts edges to groups. maps edges to integer */
+ {"mat_nr", BMO_OP_SLOT_INT}, /* material to use */
+ {"use_smooth", BMO_OP_SLOT_BOOL}, /* smooth state to use */
+ {"use_interp_simple", BMO_OP_SLOT_BOOL}, /* use simple interpolation */
+ {{'\0'}},
+ },
+ /* slots_out */
+ /* maps new faces to the group numbers they came from */
+ {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new faces */
+ {{'\0'}},
+ },
+ bmo_grid_fill_exec,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
@@ -641,20 +641,20 @@ static BMOpDefine bmo_grid_fill_def = {
* Fill boundary edges with faces, copying surrounding customdata.
*/
static BMOpDefine bmo_holes_fill_def = {
- "holes_fill",
- /* slots_in */
- {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
- {"sides", BMO_OP_SLOT_INT}, /* number of face sides to fill */
- {{'\0'}},
- },
- /* slots_out */
- /* maps new faces to the group numbers they came from */
- {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new faces */
- {{'\0'}},
- },
- bmo_holes_fill_exec,
- (BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH),
+ "holes_fill",
+ /* slots_in */
+ {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
+ {"sides", BMO_OP_SLOT_INT}, /* number of face sides to fill */
+ {{'\0'}},
+ },
+ /* slots_out */
+ /* maps new faces to the group numbers they came from */
+ {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new faces */
+ {{'\0'}},
+ },
+ bmo_holes_fill_exec,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
@@ -664,20 +664,20 @@ static BMOpDefine bmo_holes_fill_def = {
* Fill in faces with data from adjacent faces.
*/
static BMOpDefine bmo_face_attribute_fill_def = {
- "face_attribute_fill",
- /* slots_in */
- {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */
- {"use_normals", BMO_OP_SLOT_BOOL}, /* copy face winding */
- {"use_data", BMO_OP_SLOT_BOOL}, /* copy face data */
- {{'\0'}},
- },
- /* slots_out */
- /* maps new faces to the group numbers they came from */
- {{"faces_fail.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* faces that could not be handled */
- {{'\0'}},
- },
- bmo_face_attribute_fill_exec,
- (BMO_OPTYPE_FLAG_NORMALS_CALC),
+ "face_attribute_fill",
+ /* slots_in */
+ {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */
+ {"use_normals", BMO_OP_SLOT_BOOL}, /* copy face winding */
+ {"use_data", BMO_OP_SLOT_BOOL}, /* copy face data */
+ {{'\0'}},
+ },
+ /* slots_out */
+ /* maps new faces to the group numbers they came from */
+ {{"faces_fail.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* faces that could not be handled */
+ {{'\0'}},
+ },
+ bmo_face_attribute_fill_exec,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC),
};
/*
@@ -686,22 +686,22 @@ static BMOpDefine bmo_face_attribute_fill_def = {
* Create faces defined by one or more non overlapping edge loops.
*/
static BMOpDefine bmo_edgeloop_fill_def = {
- "edgeloop_fill",
- /* slots_in */
- {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
- /* restricts edges to groups. maps edges to integer */
- {"mat_nr", BMO_OP_SLOT_INT}, /* material to use */
- {"use_smooth", BMO_OP_SLOT_BOOL}, /* smooth state to use */
- {{'\0'}},
- },
- /* slots_out */
- /* maps new faces to the group numbers they came from */
- {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new faces */
- {{'\0'}},
- },
- bmo_edgeloop_fill_exec,
- (BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH),
+ "edgeloop_fill",
+ /* slots_in */
+ {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
+ /* restricts edges to groups. maps edges to integer */
+ {"mat_nr", BMO_OP_SLOT_INT}, /* material to use */
+ {"use_smooth", BMO_OP_SLOT_BOOL}, /* smooth state to use */
+ {{'\0'}},
+ },
+ /* slots_out */
+ /* maps new faces to the group numbers they came from */
+ {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new faces */
+ {{'\0'}},
+ },
+ bmo_edgeloop_fill_exec,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
@@ -711,22 +711,22 @@ static BMOpDefine bmo_edgeloop_fill_def = {
* Create faces defined by enclosed edges.
*/
static BMOpDefine bmo_edgenet_fill_def = {
- "edgenet_fill",
- /* slots_in */
- {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
- {"mat_nr", BMO_OP_SLOT_INT}, /* material to use */
- {"use_smooth", BMO_OP_SLOT_BOOL}, /* smooth state to use */
- {"sides", BMO_OP_SLOT_INT}, /* number of sides */
- {{'\0'}},
- },
- /* slots_out */
- /* maps new faces to the group numbers they came from */
- {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new faces */
- {{'\0'}},
- },
- bmo_edgenet_fill_exec,
- (BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH),
+ "edgenet_fill",
+ /* slots_in */
+ {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
+ {"mat_nr", BMO_OP_SLOT_INT}, /* material to use */
+ {"use_smooth", BMO_OP_SLOT_BOOL}, /* smooth state to use */
+ {"sides", BMO_OP_SLOT_INT}, /* number of sides */
+ {{'\0'}},
+ },
+ /* slots_out */
+ /* maps new faces to the group numbers they came from */
+ {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new faces */
+ {{'\0'}},
+ },
+ bmo_edgenet_fill_exec,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -740,17 +740,17 @@ static BMOpDefine bmo_edgenet_fill_def = {
* shortest distance between each endpont).
*/
static BMOpDefine bmo_edgenet_prepare_def = {
- "edgenet_prepare",
- /* slots_in */
- {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
- {{'\0'}},
- },
- /* slots_out */
- {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* new edges */
- {{'\0'}},
- },
- bmo_edgenet_prepare_exec,
- (BMO_OPTYPE_FLAG_NOP),
+ "edgenet_prepare",
+ /* slots_in */
+ {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* new edges */
+ {{'\0'}},
+ },
+ bmo_edgenet_prepare_exec,
+ (BMO_OPTYPE_FLAG_NOP),
};
/*
@@ -759,17 +759,17 @@ static BMOpDefine bmo_edgenet_prepare_def = {
* Rotate vertices around a center, using a 3x3 rotation matrix.
*/
static BMOpDefine bmo_rotate_def = {
- "rotate",
- /* slots_in */
- {{"cent", BMO_OP_SLOT_VEC}, /* center of rotation */
- {"matrix", BMO_OP_SLOT_MAT}, /* matrix defining rotation */
- {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */
- {"space", BMO_OP_SLOT_MAT}, /* matrix to define the space (typically object matrix) */
- {{'\0'}},
- },
- {{{'\0'}}}, /* no output */
- bmo_rotate_exec,
- (BMO_OPTYPE_FLAG_NORMALS_CALC),
+ "rotate",
+ /* slots_in */
+ {{"cent", BMO_OP_SLOT_VEC}, /* center of rotation */
+ {"matrix", BMO_OP_SLOT_MAT}, /* matrix defining rotation */
+ {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */
+ {"space", BMO_OP_SLOT_MAT}, /* matrix to define the space (typically object matrix) */
+ {{'\0'}},
+ },
+ {{{'\0'}}}, /* no output */
+ bmo_rotate_exec,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC),
};
/*
@@ -778,16 +778,16 @@ static BMOpDefine bmo_rotate_def = {
* Translate vertices by an offset.
*/
static BMOpDefine bmo_translate_def = {
- "translate",
- /* slots_in */
- {{"vec", BMO_OP_SLOT_VEC}, /* translation offset */
- {"space", BMO_OP_SLOT_MAT}, /* matrix to define the space (typically object matrix) */
- {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */
- {{'\0'}},
- },
- {{{'\0'}}}, /* no output */
- bmo_translate_exec,
- (BMO_OPTYPE_FLAG_NORMALS_CALC),
+ "translate",
+ /* slots_in */
+ {{"vec", BMO_OP_SLOT_VEC}, /* translation offset */
+ {"space", BMO_OP_SLOT_MAT}, /* matrix to define the space (typically object matrix) */
+ {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */
+ {{'\0'}},
+ },
+ {{{'\0'}}}, /* no output */
+ bmo_translate_exec,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC),
};
/*
@@ -796,16 +796,16 @@ static BMOpDefine bmo_translate_def = {
* Scales vertices by an offset.
*/
static BMOpDefine bmo_scale_def = {
- "scale",
- /* slots_in */
- {{"vec", BMO_OP_SLOT_VEC}, /* scale factor */
- {"space", BMO_OP_SLOT_MAT}, /* matrix to define the space (typically object matrix) */
- {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */
- {{'\0'}},
- },
- {{{'\0'}}}, /* no output */
- bmo_scale_exec,
- (BMO_OPTYPE_FLAG_NORMALS_CALC),
+ "scale",
+ /* slots_in */
+ {{"vec", BMO_OP_SLOT_VEC}, /* scale factor */
+ {"space", BMO_OP_SLOT_MAT}, /* matrix to define the space (typically object matrix) */
+ {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */
+ {{'\0'}},
+ },
+ {{{'\0'}}}, /* no output */
+ bmo_scale_exec,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC),
};
@@ -816,16 +816,16 @@ static BMOpDefine bmo_scale_def = {
* the vertex coordinates with the matrix.
*/
static BMOpDefine bmo_transform_def = {
- "transform",
- /* slots_in */
- {{"matrix", BMO_OP_SLOT_MAT}, /* transform matrix */
- {"space", BMO_OP_SLOT_MAT}, /* matrix to define the space (typically object matrix) */
- {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */
- {{'\0'}},
- },
- {{{'\0'}}}, /* no output */
- bmo_transform_exec,
- (BMO_OPTYPE_FLAG_NORMALS_CALC),
+ "transform",
+ /* slots_in */
+ {{"matrix", BMO_OP_SLOT_MAT}, /* transform matrix */
+ {"space", BMO_OP_SLOT_MAT}, /* matrix to define the space (typically object matrix) */
+ {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */
+ {{'\0'}},
+ },
+ {{{'\0'}}}, /* no output */
+ bmo_transform_exec,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC),
};
/*
@@ -835,15 +835,15 @@ static BMOpDefine bmo_transform_def = {
* bmop.
*/
static BMOpDefine bmo_object_load_bmesh_def = {
- "object_load_bmesh",
- /* slots_in */
- {{"scene", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_SCENE}},
- {"object", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}},
- {{'\0'}},
- },
- {{{'\0'}}}, /* no output */
- bmo_object_load_bmesh_exec,
- (BMO_OPTYPE_FLAG_NOP),
+ "object_load_bmesh",
+ /* slots_in */
+ {{"scene", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_SCENE}},
+ {"object", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}},
+ {{'\0'}},
+ },
+ {{{'\0'}}}, /* no output */
+ bmo_object_load_bmesh_exec,
+ (BMO_OPTYPE_FLAG_NOP),
};
@@ -853,18 +853,18 @@ static BMOpDefine bmo_object_load_bmesh_def = {
* Converts a bmesh to a Mesh. This is reserved for exiting editmode.
*/
static BMOpDefine bmo_bmesh_to_mesh_def = {
- "bmesh_to_mesh",
- /* slots_in */
- {
- /* pointer to a mesh structure to fill in */
- {"mesh", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_MESH}},
- /* pointer to an object structure */
- {"object", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}},
- {{'\0'}},
- },
- {{{'\0'}}}, /* no output */
- bmo_bmesh_to_mesh_exec,
- (BMO_OPTYPE_FLAG_NOP),
+ "bmesh_to_mesh",
+ /* slots_in */
+ {
+ /* pointer to a mesh structure to fill in */
+ {"mesh", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_MESH}},
+ /* pointer to an object structure */
+ {"object", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}},
+ {{'\0'}},
+ },
+ {{{'\0'}}}, /* no output */
+ bmo_bmesh_to_mesh_exec,
+ (BMO_OPTYPE_FLAG_NOP),
};
/*
@@ -874,19 +874,19 @@ static BMOpDefine bmo_bmesh_to_mesh_def = {
* reserved exclusively for entering editmode.
*/
static BMOpDefine bmo_mesh_to_bmesh_def = {
- "mesh_to_bmesh",
- /* slots_in */
- {
- /* pointer to a Mesh structure */
- {"mesh", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_MESH}},
- /* pointer to an Object structure */
- {"object", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}},
- {"use_shapekey", BMO_OP_SLOT_BOOL}, /* load active shapekey coordinates into verts */
- {{'\0'}},
- },
- {{{'\0'}}}, /* no output */
- bmo_mesh_to_bmesh_exec,
- (BMO_OPTYPE_FLAG_NOP),
+ "mesh_to_bmesh",
+ /* slots_in */
+ {
+ /* pointer to a Mesh structure */
+ {"mesh", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_MESH}},
+ /* pointer to an Object structure */
+ {"object", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_OBJECT}},
+ {"use_shapekey", BMO_OP_SLOT_BOOL}, /* load active shapekey coordinates into verts */
+ {{'\0'}},
+ },
+ {{{'\0'}}}, /* no output */
+ bmo_mesh_to_bmesh_exec,
+ (BMO_OPTYPE_FLAG_NOP),
};
/*
@@ -895,19 +895,19 @@ static BMOpDefine bmo_mesh_to_bmesh_def = {
* Extrudes faces individually.
*/
static BMOpDefine bmo_extrude_discrete_faces_def = {
- "extrude_discrete_faces",
- /* slots_in */
- {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */
- {"use_normal_flip", BMO_OP_SLOT_BOOL}, /* Create faces with reversed direction. */
- {"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */
- {{'\0'}},
- },
- /* slots_out */
- {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */
- {{'\0'}},
- },
- bmo_extrude_discrete_faces_exec,
- (BMO_OPTYPE_FLAG_NORMALS_CALC),
+ "extrude_discrete_faces",
+ /* slots_in */
+ {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */
+ {"use_normal_flip", BMO_OP_SLOT_BOOL}, /* Create faces with reversed direction. */
+ {"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */
+ {{'\0'}},
+ },
+ bmo_extrude_discrete_faces_exec,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC),
};
/*
@@ -917,19 +917,19 @@ static BMOpDefine bmo_extrude_discrete_faces_def = {
* winged extrusion.
*/
static BMOpDefine bmo_extrude_edge_only_def = {
- "extrude_edge_only",
- /* slots_in */
- {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input vertices */
- {"use_normal_flip", BMO_OP_SLOT_BOOL}, /* Create faces with reversed direction. */
- {"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */
- {{'\0'}},
- },
- /* slots_out */
- {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* output geometry */
- {{'\0'}},
- },
- bmo_extrude_edge_only_exec,
- (BMO_OPTYPE_FLAG_NORMALS_CALC),
+ "extrude_edge_only",
+ /* slots_in */
+ {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input vertices */
+ {"use_normal_flip", BMO_OP_SLOT_BOOL}, /* Create faces with reversed direction. */
+ {"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* output geometry */
+ {{'\0'}},
+ },
+ bmo_extrude_edge_only_exec,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC),
};
/*
@@ -938,19 +938,19 @@ static BMOpDefine bmo_extrude_edge_only_def = {
* Extrudes wire edges from vertices.
*/
static BMOpDefine bmo_extrude_vert_indiv_def = {
- "extrude_vert_indiv",
- /* slots_in */
- {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */
- {"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */
- {{'\0'}},
- },
- /* slots_out */
- {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* output wire edges */
- {"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output vertices */
- {{'\0'}},
- },
- bmo_extrude_vert_indiv_exec,
- (BMO_OPTYPE_FLAG_SELECT_FLUSH),
+ "extrude_vert_indiv",
+ /* slots_in */
+ {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */
+ {"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* output wire edges */
+ {"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output vertices */
+ {{'\0'}},
+ },
+ bmo_extrude_vert_indiv_exec,
+ (BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -959,21 +959,21 @@ static BMOpDefine bmo_extrude_vert_indiv_def = {
* Split faces by adding edges that connect **verts**.
*/
static BMOpDefine bmo_connect_verts_def = {
- "connect_verts",
- /* slots_in */
- {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},
- {"faces_exclude", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
- {"check_degenerate", BMO_OP_SLOT_BOOL}, /* prevent splits with overlaps & intersections */
- {{'\0'}},
- },
- /* slots_out */
- {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
- {{'\0'}},
- },
- bmo_connect_verts_exec,
- (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
- BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH),
+ "connect_verts",
+ /* slots_in */
+ {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},
+ {"faces_exclude", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
+ {"check_degenerate", BMO_OP_SLOT_BOOL}, /* prevent splits with overlaps & intersections */
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
+ {{'\0'}},
+ },
+ bmo_connect_verts_exec,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -982,20 +982,20 @@ static BMOpDefine bmo_connect_verts_def = {
* Ensures all faces are convex **faces**.
*/
static BMOpDefine bmo_connect_verts_concave_def = {
- "connect_verts_concave",
- /* slots_in */
- {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
- {{'\0'}},
- },
- /* slots_out */
- {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
- {"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
- {{'\0'}},
- },
- bmo_connect_verts_concave_exec,
- (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
- BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH),
+ "connect_verts_concave",
+ /* slots_in */
+ {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
+ {"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
+ {{'\0'}},
+ },
+ bmo_connect_verts_concave_exec,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1004,21 +1004,21 @@ static BMOpDefine bmo_connect_verts_concave_def = {
* Split faces by connecting edges along non planer **faces**.
*/
static BMOpDefine bmo_connect_verts_nonplanar_def = {
- "connect_verts_nonplanar",
- /* slots_in */
- {{"angle_limit", BMO_OP_SLOT_FLT}, /* total rotation angle (radians) */
- {"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
- {{'\0'}},
- },
- /* slots_out */
- {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
- {"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
- {{'\0'}},
- },
- bmo_connect_verts_nonplanar_exec,
- (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
- BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH),
+ "connect_verts_nonplanar",
+ /* slots_in */
+ {{"angle_limit", BMO_OP_SLOT_FLT}, /* total rotation angle (radians) */
+ {"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
+ {"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
+ {{'\0'}},
+ },
+ bmo_connect_verts_nonplanar_exec,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1027,21 +1027,21 @@ static BMOpDefine bmo_connect_verts_nonplanar_def = {
* Split faces by adding edges that connect **verts**.
*/
static BMOpDefine bmo_connect_vert_pair_def = {
- "connect_vert_pair",
- /* slots_in */
- {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},
- {"verts_exclude", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},
- {"faces_exclude", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
- {{'\0'}},
- },
- /* slots_out */
- {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
- {{'\0'}},
- },
- bmo_connect_vert_pair_exec,
- (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
- BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH),
+ "connect_vert_pair",
+ /* slots_in */
+ {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},
+ {"verts_exclude", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},
+ {"faces_exclude", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
+ {{'\0'}},
+ },
+ bmo_connect_vert_pair_exec,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
@@ -1051,93 +1051,93 @@ static BMOpDefine bmo_connect_vert_pair_def = {
* Extrude operator (does not transform)
*/
static BMOpDefine bmo_extrude_face_region_def = {
- "extrude_face_region",
- /* slots_in */
- {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* edges and faces */
- {"edges_exclude", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_EMPTY}},
- {"use_keep_orig", BMO_OP_SLOT_BOOL}, /* keep original geometry (requires ``geom`` to include edges). */
- {"use_normal_flip", BMO_OP_SLOT_BOOL}, /* Create faces with reversed direction. */
- {"use_normal_from_adjacent", BMO_OP_SLOT_BOOL}, /* Use winding from surrounding faces instead of this region. */
- {"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */
- {{'\0'}},
- },
- /* slots_out */
- {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
- {{'\0'}},
- },
- bmo_extrude_face_region_exec,
- (BMO_OPTYPE_FLAG_NORMALS_CALC),
+ "extrude_face_region",
+ /* slots_in */
+ {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* edges and faces */
+ {"edges_exclude", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_EMPTY}},
+ {"use_keep_orig", BMO_OP_SLOT_BOOL}, /* keep original geometry (requires ``geom`` to include edges). */
+ {"use_normal_flip", BMO_OP_SLOT_BOOL}, /* Create faces with reversed direction. */
+ {"use_normal_from_adjacent", BMO_OP_SLOT_BOOL}, /* Use winding from surrounding faces instead of this region. */
+ {"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
+ {{'\0'}},
+ },
+ bmo_extrude_face_region_exec,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC),
};
/*
* Dissolve Verts.
*/
static BMOpDefine bmo_dissolve_verts_def = {
- "dissolve_verts",
- /* slots_in */
- {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},
- {"use_face_split", BMO_OP_SLOT_BOOL},
- {"use_boundary_tear", BMO_OP_SLOT_BOOL},
- {{'\0'}},
- },
- {{{'\0'}}}, /* no output */
- bmo_dissolve_verts_exec,
- (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
- BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH |
- BMO_OPTYPE_FLAG_SELECT_VALIDATE),
+ "dissolve_verts",
+ /* slots_in */
+ {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},
+ {"use_face_split", BMO_OP_SLOT_BOOL},
+ {"use_boundary_tear", BMO_OP_SLOT_BOOL},
+ {{'\0'}},
+ },
+ {{{'\0'}}}, /* no output */
+ bmo_dissolve_verts_exec,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
* Dissolve Edges.
*/
static BMOpDefine bmo_dissolve_edges_def = {
- "dissolve_edges",
- /* slots_in */
- {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
- {"use_verts", BMO_OP_SLOT_BOOL}, /* dissolve verts left between only 2 edges. */
- {"use_face_split", BMO_OP_SLOT_BOOL},
- {{'\0'}},
- },
- /* slots_out */
- {{"region.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
- {{'\0'}},
- },
- bmo_dissolve_edges_exec,
- (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
- BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH |
- BMO_OPTYPE_FLAG_SELECT_VALIDATE),
+ "dissolve_edges",
+ /* slots_in */
+ {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
+ {"use_verts", BMO_OP_SLOT_BOOL}, /* dissolve verts left between only 2 edges. */
+ {"use_face_split", BMO_OP_SLOT_BOOL},
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"region.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
+ {{'\0'}},
+ },
+ bmo_dissolve_edges_exec,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
* Dissolve Faces.
*/
static BMOpDefine bmo_dissolve_faces_def = {
- "dissolve_faces",
- /* slots_in */
- {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
- {"use_verts", BMO_OP_SLOT_BOOL}, /* dissolve verts left between only 2 edges. */
- {{'\0'}},
- },
- /* slots_out */
- {{"region.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
- {{'\0'}},
- },
- bmo_dissolve_faces_exec,
- (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
- BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH |
- BMO_OPTYPE_FLAG_SELECT_VALIDATE),
+ "dissolve_faces",
+ /* slots_in */
+ {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
+ {"use_verts", BMO_OP_SLOT_BOOL}, /* dissolve verts left between only 2 edges. */
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"region.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
+ {{'\0'}},
+ },
+ bmo_dissolve_faces_exec,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
static BMO_FlagSet bmo_enum_dissolve_limit_flags[] = {
- {BMO_DELIM_NORMAL, "NORMAL"},
- {BMO_DELIM_MATERIAL, "MATERIAL"},
- {BMO_DELIM_SEAM, "SEAM"},
- {BMO_DELIM_SHARP, "SHARP"},
- {BMO_DELIM_UV, "UV"},
- {0, NULL},
+ {BMO_DELIM_NORMAL, "NORMAL"},
+ {BMO_DELIM_MATERIAL, "MATERIAL"},
+ {BMO_DELIM_SEAM, "SEAM"},
+ {BMO_DELIM_SHARP, "SHARP"},
+ {BMO_DELIM_UV, "UV"},
+ {0, NULL},
};
/*
@@ -1146,23 +1146,23 @@ static BMO_FlagSet bmo_enum_dissolve_limit_flags[] = {
* Dissolve planar faces and co-linear edges.
*/
static BMOpDefine bmo_dissolve_limit_def = {
- "dissolve_limit",
- /* slots_in */
- {{"angle_limit", BMO_OP_SLOT_FLT}, /* total rotation angle (radians) */
- {"use_dissolve_boundaries", BMO_OP_SLOT_BOOL},
- {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},
- {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
- {"delimit", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_FLAG}, bmo_enum_dissolve_limit_flags},
- {{'\0'}},
- },
- /* slots_out */
- {{"region.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
- {{'\0'}}},
- bmo_dissolve_limit_exec,
- (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
- BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH |
- BMO_OPTYPE_FLAG_SELECT_VALIDATE),
+ "dissolve_limit",
+ /* slots_in */
+ {{"angle_limit", BMO_OP_SLOT_FLT}, /* total rotation angle (radians) */
+ {"use_dissolve_boundaries", BMO_OP_SLOT_BOOL},
+ {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}},
+ {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
+ {"delimit", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_FLAG}, bmo_enum_dissolve_limit_flags},
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"region.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
+ {{'\0'}}},
+ bmo_dissolve_limit_exec,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -1171,57 +1171,57 @@ static BMOpDefine bmo_dissolve_limit_def = {
* Dissolve edges with no length, faces with no area.
*/
static BMOpDefine bmo_dissolve_degenerate_def = {
- "dissolve_degenerate",
- /* slots_in */
- {{"dist", BMO_OP_SLOT_FLT}, /* minimum distance to consider degenerate */
- {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
- {{'\0'}},
- },
- /* slots_out */
- {{{'\0'}}},
- bmo_dissolve_degenerate_exec,
- (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
- BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH |
- BMO_OPTYPE_FLAG_SELECT_VALIDATE),
+ "dissolve_degenerate",
+ /* slots_in */
+ {{"dist", BMO_OP_SLOT_FLT}, /* minimum distance to consider degenerate */
+ {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{{'\0'}}},
+ bmo_dissolve_degenerate_exec,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
static BMO_FlagSet bmo_enum_triangulate_quad_method[] = {
- {MOD_TRIANGULATE_QUAD_BEAUTY, "BEAUTY"},
- {MOD_TRIANGULATE_QUAD_FIXED, "FIXED"},
- {MOD_TRIANGULATE_QUAD_ALTERNATE, "ALTERNATE"},
- {MOD_TRIANGULATE_QUAD_SHORTEDGE, "SHORT_EDGE"},
- {0, NULL},
+ {MOD_TRIANGULATE_QUAD_BEAUTY, "BEAUTY"},
+ {MOD_TRIANGULATE_QUAD_FIXED, "FIXED"},
+ {MOD_TRIANGULATE_QUAD_ALTERNATE, "ALTERNATE"},
+ {MOD_TRIANGULATE_QUAD_SHORTEDGE, "SHORT_EDGE"},
+ {0, NULL},
};
static BMO_FlagSet bmo_enum_triangulate_ngon_method[] = {
- {MOD_TRIANGULATE_NGON_BEAUTY, "BEAUTY"},
- {MOD_TRIANGULATE_NGON_EARCLIP, "EAR_CLIP"},
- {0, NULL},
+ {MOD_TRIANGULATE_NGON_BEAUTY, "BEAUTY"},
+ {MOD_TRIANGULATE_NGON_EARCLIP, "EAR_CLIP"},
+ {0, NULL},
};
/*
* Triangulate.
*/
static BMOpDefine bmo_triangulate_def = {
- "triangulate",
- /* slots_in */
- {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
- {"quad_method", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_triangulate_quad_method},
- {"ngon_method", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_triangulate_ngon_method},
- {{'\0'}},
- },
- /* slots_out */
- {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
- {"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
- {"face_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
- {"face_map_double.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, /* duplicate faces */
- {{'\0'}},
- },
- bmo_triangulate_exec,
- (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
- BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH),
+ "triangulate",
+ /* slots_in */
+ {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
+ {"quad_method", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_triangulate_quad_method},
+ {"ngon_method", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_triangulate_ngon_method},
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
+ {"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
+ {"face_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
+ {"face_map_double.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, /* duplicate faces */
+ {{'\0'}},
+ },
+ bmo_triangulate_exec,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1230,26 +1230,26 @@ static BMOpDefine bmo_triangulate_def = {
* Reduce detail in geometry containing grids.
*/
static BMOpDefine bmo_unsubdivide_def = {
- "unsubdivide",
- /* slots_in */
- {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */
- {"iterations", BMO_OP_SLOT_INT},
- {{'\0'}},
- },
- {{{'\0'}}}, /* no output */
- bmo_unsubdivide_exec,
- (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
- BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH |
- BMO_OPTYPE_FLAG_SELECT_VALIDATE),
+ "unsubdivide",
+ /* slots_in */
+ {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */
+ {"iterations", BMO_OP_SLOT_INT},
+ {{'\0'}},
+ },
+ {{{'\0'}}}, /* no output */
+ bmo_unsubdivide_exec,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
static BMO_FlagSet bmo_enum_subdivide_edges_quad_corner_type[] = {
- {SUBD_CORNER_STRAIGHT_CUT, "STRAIGHT_CUT"},
- {SUBD_CORNER_INNERVERT, "INNER_VERT"},
- {SUBD_CORNER_PATH, "PATH"},
- {SUBD_CORNER_FAN, "FAN"},
- {0, NULL},
+ {SUBD_CORNER_STRAIGHT_CUT, "STRAIGHT_CUT"},
+ {SUBD_CORNER_INNERVERT, "INNER_VERT"},
+ {SUBD_CORNER_PATH, "PATH"},
+ {SUBD_CORNER_FAN, "FAN"},
+ {0, NULL},
};
/*
@@ -1259,44 +1259,44 @@ static BMO_FlagSet bmo_enum_subdivide_edges_quad_corner_type[] = {
* with options for face patterns, smoothing and randomization.
*/
static BMOpDefine bmo_subdivide_edges_def = {
- "subdivide_edges",
- /* slots_in */
- {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
- {"smooth", BMO_OP_SLOT_FLT},
- {"smooth_falloff", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_falloff_type}, /* smooth falloff type */
- {"fractal", BMO_OP_SLOT_FLT},
- {"along_normal", BMO_OP_SLOT_FLT},
- {"cuts", BMO_OP_SLOT_INT},
- {"seed", BMO_OP_SLOT_INT},
- {"custom_patterns", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL}}, /* uses custom pointers */
- {"edge_percents", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_FLT}},
- {"quad_corner_type", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_subdivide_edges_quad_corner_type}, /* quad corner type */
- {"use_grid_fill", BMO_OP_SLOT_BOOL}, /* fill in fully-selected faces with a grid */
- {"use_single_edge", BMO_OP_SLOT_BOOL}, /* tessellate the case of one edge selected in a quad or triangle */
- {"use_only_quads", BMO_OP_SLOT_BOOL}, /* only subdivide quads (for loopcut) */
- {"use_sphere", BMO_OP_SLOT_BOOL}, /* for making new primitives only */
- {"use_smooth_even", BMO_OP_SLOT_BOOL}, /* maintain even offset when smoothing */
- {{'\0'}},
- },
- /* slots_out */
- {/* these next three can have multiple types of elements in them */
- {"geom_inner.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
- {"geom_split.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
- {"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* contains all output geometry */
- {{'\0'}},
- },
- bmo_subdivide_edges_exec,
- (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
- BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH |
- BMO_OPTYPE_FLAG_SELECT_VALIDATE),
+ "subdivide_edges",
+ /* slots_in */
+ {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}},
+ {"smooth", BMO_OP_SLOT_FLT},
+ {"smooth_falloff", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_falloff_type}, /* smooth falloff type */
+ {"fractal", BMO_OP_SLOT_FLT},
+ {"along_normal", BMO_OP_SLOT_FLT},
+ {"cuts", BMO_OP_SLOT_INT},
+ {"seed", BMO_OP_SLOT_INT},
+ {"custom_patterns", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL}}, /* uses custom pointers */
+ {"edge_percents", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_FLT}},
+ {"quad_corner_type", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_subdivide_edges_quad_corner_type}, /* quad corner type */
+ {"use_grid_fill", BMO_OP_SLOT_BOOL}, /* fill in fully-selected faces with a grid */
+ {"use_single_edge", BMO_OP_SLOT_BOOL}, /* tessellate the case of one edge selected in a quad or triangle */
+ {"use_only_quads", BMO_OP_SLOT_BOOL}, /* only subdivide quads (for loopcut) */
+ {"use_sphere", BMO_OP_SLOT_BOOL}, /* for making new primitives only */
+ {"use_smooth_even", BMO_OP_SLOT_BOOL}, /* maintain even offset when smoothing */
+ {{'\0'}},
+ },
+ /* slots_out */
+ {/* these next three can have multiple types of elements in them */
+ {"geom_inner.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
+ {"geom_split.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
+ {"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* contains all output geometry */
+ {{'\0'}},
+ },
+ bmo_subdivide_edges_exec,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
static BMO_FlagSet bmo_enum_subdivide_edgering_interp_mode[] = {
- {SUBD_RING_INTERP_LINEAR, "LINEAR"},
- {SUBD_RING_INTERP_PATH, "PATH"},
- {SUBD_RING_INTERP_SURF, "SURFACE"},
- {0, NULL},
+ {SUBD_RING_INTERP_LINEAR, "LINEAR"},
+ {SUBD_RING_INTERP_PATH, "PATH"},
+ {SUBD_RING_INTERP_SURF, "SURFACE"},
+ {0, NULL},
};
/*
@@ -1305,23 +1305,23 @@ static BMO_FlagSet bmo_enum_subdivide_edgering_interp_mode[] = {
* Take an edge-ring, and subdivide with interpolation options.
*/
static BMOpDefine bmo_subdivide_edgering_def = {
- "subdivide_edgering",
- /* slots_in */
- {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input vertices */
- {"interp_mode", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_subdivide_edgering_interp_mode}, /* interpolation method */
- {"smooth", BMO_OP_SLOT_FLT},
- {"cuts", BMO_OP_SLOT_INT},
- {"profile_shape", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_falloff_type}, /* profile shape type */
- {"profile_shape_factor", BMO_OP_SLOT_FLT},
- {{'\0'}},
- },
- {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */
- {{'\0'}}},
- bmo_subdivide_edgering_exec,
- (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
- BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH |
- BMO_OPTYPE_FLAG_SELECT_VALIDATE),
+ "subdivide_edgering",
+ /* slots_in */
+ {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input vertices */
+ {"interp_mode", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_subdivide_edgering_interp_mode}, /* interpolation method */
+ {"smooth", BMO_OP_SLOT_FLT},
+ {"cuts", BMO_OP_SLOT_INT},
+ {"profile_shape", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_falloff_type}, /* profile shape type */
+ {"profile_shape_factor", BMO_OP_SLOT_FLT},
+ {{'\0'}},
+ },
+ {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */
+ {{'\0'}}},
+ bmo_subdivide_edgering_exec,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -1330,36 +1330,36 @@ static BMOpDefine bmo_subdivide_edgering_def = {
* Bisects the mesh by a plane (cut the mesh in half).
*/
static BMOpDefine bmo_bisect_plane_def = {
- "bisect_plane",
- /* slots_in */
- {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
- {"dist", BMO_OP_SLOT_FLT}, /* minimum distance when testing if a vert is exactly on the plane */
- {"plane_co", BMO_OP_SLOT_VEC}, /* point on the plane */
- {"plane_no", BMO_OP_SLOT_VEC}, /* direction of the plane */
- {"use_snap_center", BMO_OP_SLOT_BOOL}, /* snap axis aligned verts to the center */
- {"clear_outer", BMO_OP_SLOT_BOOL}, /* when enabled. remove all geometry on the positive side of the plane */
- {"clear_inner", BMO_OP_SLOT_BOOL}, /* when enabled. remove all geometry on the negative side of the plane */
- {{'\0'}},
- },
- {{"geom_cut.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE}}, /* output geometry aligned with the plane (new and existing) */
- {"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input and output geometry (result of cut) */
- {{'\0'}}},
- bmo_bisect_plane_exec,
- (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
- BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH |
- BMO_OPTYPE_FLAG_SELECT_VALIDATE),
+ "bisect_plane",
+ /* slots_in */
+ {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
+ {"dist", BMO_OP_SLOT_FLT}, /* minimum distance when testing if a vert is exactly on the plane */
+ {"plane_co", BMO_OP_SLOT_VEC}, /* point on the plane */
+ {"plane_no", BMO_OP_SLOT_VEC}, /* direction of the plane */
+ {"use_snap_center", BMO_OP_SLOT_BOOL}, /* snap axis aligned verts to the center */
+ {"clear_outer", BMO_OP_SLOT_BOOL}, /* when enabled. remove all geometry on the positive side of the plane */
+ {"clear_inner", BMO_OP_SLOT_BOOL}, /* when enabled. remove all geometry on the negative side of the plane */
+ {{'\0'}},
+ },
+ {{"geom_cut.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE}}, /* output geometry aligned with the plane (new and existing) */
+ {"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input and output geometry (result of cut) */
+ {{'\0'}}},
+ bmo_bisect_plane_exec,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
static BMO_FlagSet bmo_enum_delete_context[] = {
- {DEL_VERTS, "VERTS"},
- {DEL_EDGES, "EDGES"},
- {DEL_ONLYFACES, "FACES_ONLY"},
- {DEL_EDGESFACES, "EDGES_FACES"},
- {DEL_FACES, "FACES"},
- {DEL_FACES_KEEP_BOUNDARY, "FACES_KEEP_BOUNDARY"},
- {DEL_ONLYTAGGED, "TAGGED_ONLY"},
- {0, NULL},
+ {DEL_VERTS, "VERTS"},
+ {DEL_EDGES, "EDGES"},
+ {DEL_ONLYFACES, "FACES_ONLY"},
+ {DEL_EDGESFACES, "EDGES_FACES"},
+ {DEL_FACES, "FACES"},
+ {DEL_FACES_KEEP_BOUNDARY, "FACES_KEEP_BOUNDARY"},
+ {DEL_ONLYTAGGED, "TAGGED_ONLY"},
+ {0, NULL},
};
/*
@@ -1368,17 +1368,17 @@ static BMO_FlagSet bmo_enum_delete_context[] = {
* Utility operator to delete geometry.
*/
static BMOpDefine bmo_delete_def = {
- "delete",
- /* slots_in */
- {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
- {"context", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_delete_context}, /* geometry types to delete */
- {{'\0'}},
- },
- {{{'\0'}}}, /* no output */
- bmo_delete_exec,
- (BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH |
- BMO_OPTYPE_FLAG_SELECT_VALIDATE),
+ "delete",
+ /* slots_in */
+ {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
+ {"context", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_delete_context}, /* geometry types to delete */
+ {{'\0'}},
+ },
+ {{{'\0'}}}, /* no output */
+ bmo_delete_exec,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -1388,30 +1388,30 @@ static BMOpDefine bmo_delete_def = {
* optionally into a destination mesh.
*/
static BMOpDefine bmo_duplicate_def = {
- "duplicate",
- /* slots_in */
- {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
- /* destination bmesh, if NULL will use current on */
- {"dest", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_BMESH}},
- {"use_select_history", BMO_OP_SLOT_BOOL},
- {"use_edge_flip_from_face", BMO_OP_SLOT_BOOL},
- {{'\0'}},
- },
- /* slots_out */
- {{"geom_orig.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
- {"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
- /* facemap maps from source faces to dupe
- * faces, and from dupe faces to source faces */
- {"vert_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
- {"edge_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
- {"face_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
- {"boundary_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
- {"isovert_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
- {{'\0'}},
- },
- bmo_duplicate_exec,
- (BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH),
+ "duplicate",
+ /* slots_in */
+ {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
+ /* destination bmesh, if NULL will use current on */
+ {"dest", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_BMESH}},
+ {"use_select_history", BMO_OP_SLOT_BOOL},
+ {"use_edge_flip_from_face", BMO_OP_SLOT_BOOL},
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"geom_orig.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
+ {"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
+ /* facemap maps from source faces to dupe
+ * faces, and from dupe faces to source faces */
+ {"vert_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
+ {"edge_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
+ {"face_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
+ {"boundary_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
+ {"isovert_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
+ {{'\0'}},
+ },
+ bmo_duplicate_exec,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1421,23 +1421,23 @@ static BMOpDefine bmo_duplicate_def = {
* optionally into a destination mesh.
*/
static BMOpDefine bmo_split_def = {
- "split",
- /* slots_in */
- {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
- /* destination bmesh, if NULL will use current one */
- {"dest", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_BMESH}},
- {"use_only_faces", BMO_OP_SLOT_BOOL}, /* when enabled. don't duplicate loose verts/edges */
- {{'\0'}},
- },
- /* slots_out */
- {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
- {"boundary_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
- {"isovert_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
- {{'\0'}},
- },
- bmo_split_exec,
- (BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH),
+ "split",
+ /* slots_in */
+ {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
+ /* destination bmesh, if NULL will use current one */
+ {"dest", BMO_OP_SLOT_PTR, {(int)BMO_OP_SLOT_SUBTYPE_PTR_BMESH}},
+ {"use_only_faces", BMO_OP_SLOT_BOOL}, /* when enabled. don't duplicate loose verts/edges */
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
+ {"boundary_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
+ {"isovert_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}},
+ {{'\0'}},
+ },
+ bmo_split_exec,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1447,27 +1447,27 @@ static BMOpDefine bmo_split_def = {
* rotating and possibly translating after each step
*/
static BMOpDefine bmo_spin_def = {
- "spin",
- /* slots_in */
- {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
- {"cent", BMO_OP_SLOT_VEC}, /* rotation center */
- {"axis", BMO_OP_SLOT_VEC}, /* rotation axis */
- {"dvec", BMO_OP_SLOT_VEC}, /* translation delta per step */
- {"angle", BMO_OP_SLOT_FLT}, /* total rotation angle (radians) */
- {"space", BMO_OP_SLOT_MAT}, /* matrix to define the space (typically object matrix) */
- {"steps", BMO_OP_SLOT_INT}, /* number of steps */
- {"use_merge", BMO_OP_SLOT_BOOL}, /* Merge first/last when the angle is a full revolution. */
- {"use_normal_flip", BMO_OP_SLOT_BOOL}, /* Create faces with reversed direction. */
- {"use_duplicate", BMO_OP_SLOT_BOOL}, /* duplicate or extrude? */
- {{'\0'}},
- },
- /* slots_out */
- {{"geom_last.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* result of last step */
- {{'\0'}},
- },
- bmo_spin_exec,
- (BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH),
+ "spin",
+ /* slots_in */
+ {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
+ {"cent", BMO_OP_SLOT_VEC}, /* rotation center */
+ {"axis", BMO_OP_SLOT_VEC}, /* rotation axis */
+ {"dvec", BMO_OP_SLOT_VEC}, /* translation delta per step */
+ {"angle", BMO_OP_SLOT_FLT}, /* total rotation angle (radians) */
+ {"space", BMO_OP_SLOT_MAT}, /* matrix to define the space (typically object matrix) */
+ {"steps", BMO_OP_SLOT_INT}, /* number of steps */
+ {"use_merge", BMO_OP_SLOT_BOOL}, /* Merge first/last when the angle is a full revolution. */
+ {"use_normal_flip", BMO_OP_SLOT_BOOL}, /* Create faces with reversed direction. */
+ {"use_duplicate", BMO_OP_SLOT_BOOL}, /* duplicate or extrude? */
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"geom_last.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* result of last step */
+ {{'\0'}},
+ },
+ bmo_spin_exec,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1476,15 +1476,15 @@ static BMOpDefine bmo_spin_def = {
* Cycle the loop UV's
*/
static BMOpDefine bmo_rotate_uvs_def = {
- "rotate_uvs",
- /* slots_in */
- {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */
- {"use_ccw", BMO_OP_SLOT_BOOL}, /* rotate counter-clockwise if true, otherwise clockwise */
- {{'\0'}},
- },
- {{{'\0'}}}, /* no output */
- bmo_rotate_uvs_exec,
- (BMO_OPTYPE_FLAG_NOP),
+ "rotate_uvs",
+ /* slots_in */
+ {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */
+ {"use_ccw", BMO_OP_SLOT_BOOL}, /* rotate counter-clockwise if true, otherwise clockwise */
+ {{'\0'}},
+ },
+ {{{'\0'}}}, /* no output */
+ bmo_rotate_uvs_exec,
+ (BMO_OPTYPE_FLAG_NOP),
};
/*
@@ -1493,14 +1493,14 @@ static BMOpDefine bmo_rotate_uvs_def = {
* Reverse the UV's
*/
static BMOpDefine bmo_reverse_uvs_def = {
- "reverse_uvs",
- /* slots_in */
- {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */
- {{'\0'}},
- },
- {{{'\0'}}}, /* no output */
- bmo_reverse_uvs_exec,
- (BMO_OPTYPE_FLAG_NOP),
+ "reverse_uvs",
+ /* slots_in */
+ {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */
+ {{'\0'}},
+ },
+ {{{'\0'}}}, /* no output */
+ bmo_reverse_uvs_exec,
+ (BMO_OPTYPE_FLAG_NOP),
};
/*
@@ -1509,15 +1509,15 @@ static BMOpDefine bmo_reverse_uvs_def = {
* Cycle the loop colors
*/
static BMOpDefine bmo_rotate_colors_def = {
- "rotate_colors",
- /* slots_in */
- {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */
- {"use_ccw", BMO_OP_SLOT_BOOL}, /* rotate counter-clockwise if true, otherwise clockwise */
- {{'\0'}},
- },
- {{{'\0'}}}, /* no output */
- bmo_rotate_colors_exec,
- (BMO_OPTYPE_FLAG_NOP),
+ "rotate_colors",
+ /* slots_in */
+ {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */
+ {"use_ccw", BMO_OP_SLOT_BOOL}, /* rotate counter-clockwise if true, otherwise clockwise */
+ {{'\0'}},
+ },
+ {{{'\0'}}}, /* no output */
+ bmo_rotate_colors_exec,
+ (BMO_OPTYPE_FLAG_NOP),
};
/*
@@ -1526,14 +1526,14 @@ static BMOpDefine bmo_rotate_colors_def = {
* Reverse the loop colors.
*/
static BMOpDefine bmo_reverse_colors_def = {
- "reverse_colors",
- /* slots_in */
- {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */
- {{'\0'}},
- },
- {{{'\0'}}}, /* no output */
- bmo_reverse_colors_exec,
- (BMO_OPTYPE_FLAG_NOP),
+ "reverse_colors",
+ /* slots_in */
+ {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */
+ {{'\0'}},
+ },
+ {{{'\0'}}}, /* no output */
+ bmo_reverse_colors_exec,
+ (BMO_OPTYPE_FLAG_NOP),
};
/*
@@ -1542,22 +1542,22 @@ static BMOpDefine bmo_reverse_colors_def = {
* Disconnects faces along input edges.
*/
static BMOpDefine bmo_split_edges_def = {
- "split_edges",
- /* slots_in */
- {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
- /* needed for vertex rip so we can rip only half an edge at a boundary wich would otherwise split off */
- {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* optional tag verts, use to have greater control of splits */
- {"use_verts", BMO_OP_SLOT_BOOL}, /* use 'verts' for splitting, else just find verts to split from edges */
- {{'\0'}},
- },
- /* slots_out */
- {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* old output disconnected edges */
- {{'\0'}},
- },
- bmo_split_edges_exec,
- (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
- BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH),
+ "split_edges",
+ /* slots_in */
+ {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
+ /* needed for vertex rip so we can rip only half an edge at a boundary wich would otherwise split off */
+ {"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* optional tag verts, use to have greater control of splits */
+ {"use_verts", BMO_OP_SLOT_BOOL}, /* use 'verts' for splitting, else just find verts to split from edges */
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* old output disconnected edges */
+ {{'\0'}},
+ },
+ bmo_split_edges_exec,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1566,22 +1566,22 @@ static BMOpDefine bmo_split_edges_def = {
* Creates a grid with a variable number of subdivisions
*/
static BMOpDefine bmo_create_grid_def = {
- "create_grid",
- /* slots_in */
- {{"x_segments", BMO_OP_SLOT_INT}, /* number of x segments */
- {"y_segments", BMO_OP_SLOT_INT}, /* number of y segments */
- {"size", BMO_OP_SLOT_FLT}, /* size of the grid */
- {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */
- {"calc_uvs", BMO_OP_SLOT_BOOL}, /* calculate default UVs */
- {{'\0'}},
- },
- /* slots_out */
- {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
- {{'\0'}},
- },
- bmo_create_grid_exec,
- (BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH),
+ "create_grid",
+ /* slots_in */
+ {{"x_segments", BMO_OP_SLOT_INT}, /* number of x segments */
+ {"y_segments", BMO_OP_SLOT_INT}, /* number of y segments */
+ {"size", BMO_OP_SLOT_FLT}, /* size of the grid */
+ {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */
+ {"calc_uvs", BMO_OP_SLOT_BOOL}, /* calculate default UVs */
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
+ {{'\0'}},
+ },
+ bmo_create_grid_exec,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1590,22 +1590,22 @@ static BMOpDefine bmo_create_grid_def = {
* Creates a grid with a variable number of subdivisions
*/
static BMOpDefine bmo_create_uvsphere_def = {
- "create_uvsphere",
- /* slots_in */
- {{"u_segments", BMO_OP_SLOT_INT}, /* number of u segments */
- {"v_segments", BMO_OP_SLOT_INT}, /* number of v segment */
- {"diameter", BMO_OP_SLOT_FLT}, /* diameter */
- {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */
- {"calc_uvs", BMO_OP_SLOT_BOOL}, /* calculate default UVs */
- {{'\0'}},
- },
- /* slots_out */
- {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
- {{'\0'}},
- },
- bmo_create_uvsphere_exec,
- (BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH),
+ "create_uvsphere",
+ /* slots_in */
+ {{"u_segments", BMO_OP_SLOT_INT}, /* number of u segments */
+ {"v_segments", BMO_OP_SLOT_INT}, /* number of v segment */
+ {"diameter", BMO_OP_SLOT_FLT}, /* diameter */
+ {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */
+ {"calc_uvs", BMO_OP_SLOT_BOOL}, /* calculate default UVs */
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
+ {{'\0'}},
+ },
+ bmo_create_uvsphere_exec,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1614,21 +1614,21 @@ static BMOpDefine bmo_create_uvsphere_def = {
* Creates a grid with a variable number of subdivisions
*/
static BMOpDefine bmo_create_icosphere_def = {
- "create_icosphere",
- /* slots_in */
- {{"subdivisions", BMO_OP_SLOT_INT}, /* how many times to recursively subdivide the sphere */
- {"diameter", BMO_OP_SLOT_FLT}, /* diameter */
- {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */
- {"calc_uvs", BMO_OP_SLOT_BOOL}, /* calculate default UVs */
- {{'\0'}},
- },
- /* slots_out */
- {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
- {{'\0'}},
- },
- bmo_create_icosphere_exec,
- (BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH),
+ "create_icosphere",
+ /* slots_in */
+ {{"subdivisions", BMO_OP_SLOT_INT}, /* how many times to recursively subdivide the sphere */
+ {"diameter", BMO_OP_SLOT_FLT}, /* diameter */
+ {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */
+ {"calc_uvs", BMO_OP_SLOT_BOOL}, /* calculate default UVs */
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
+ {{'\0'}},
+ },
+ bmo_create_icosphere_exec,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1637,19 +1637,19 @@ static BMOpDefine bmo_create_icosphere_def = {
* Creates a monkey (standard blender primitive).
*/
static BMOpDefine bmo_create_monkey_def = {
- "create_monkey",
- /* slots_in */
- {{"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */
- {"calc_uvs", BMO_OP_SLOT_BOOL}, /* calculate default UVs */
- {{'\0'}},
- },
- /* slots_out */
- {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
- {{'\0'}},
- },
- bmo_create_monkey_exec,
- (BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH),
+ "create_monkey",
+ /* slots_in */
+ {{"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */
+ {"calc_uvs", BMO_OP_SLOT_BOOL}, /* calculate default UVs */
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
+ {{'\0'}},
+ },
+ bmo_create_monkey_exec,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1658,48 +1658,48 @@ static BMOpDefine bmo_create_monkey_def = {
* Creates a cone with variable depth at both ends
*/
static BMOpDefine bmo_create_cone_def = {
- "create_cone",
- /* slots_in */
- {{"cap_ends", BMO_OP_SLOT_BOOL}, /* whether or not to fill in the ends with faces */
- {"cap_tris", BMO_OP_SLOT_BOOL}, /* fill ends with triangles instead of ngons */
- {"segments", BMO_OP_SLOT_INT},
- {"diameter1", BMO_OP_SLOT_FLT}, /* diameter of one end */
- {"diameter2", BMO_OP_SLOT_FLT}, /* diameter of the opposite */
- {"depth", BMO_OP_SLOT_FLT}, /* distance between ends */
- {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */
- {"calc_uvs", BMO_OP_SLOT_BOOL}, /* calculate default UVs */
- {{'\0'}},
- },
- /* slots_out */
- {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
- {{'\0'}},
- },
- bmo_create_cone_exec,
- (BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH),
+ "create_cone",
+ /* slots_in */
+ {{"cap_ends", BMO_OP_SLOT_BOOL}, /* whether or not to fill in the ends with faces */
+ {"cap_tris", BMO_OP_SLOT_BOOL}, /* fill ends with triangles instead of ngons */
+ {"segments", BMO_OP_SLOT_INT},
+ {"diameter1", BMO_OP_SLOT_FLT}, /* diameter of one end */
+ {"diameter2", BMO_OP_SLOT_FLT}, /* diameter of the opposite */
+ {"depth", BMO_OP_SLOT_FLT}, /* distance between ends */
+ {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */
+ {"calc_uvs", BMO_OP_SLOT_BOOL}, /* calculate default UVs */
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
+ {{'\0'}},
+ },
+ bmo_create_cone_exec,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
* Creates a Circle.
*/
static BMOpDefine bmo_create_circle_def = {
- "create_circle",
- /* slots_in */
- {{"cap_ends", BMO_OP_SLOT_BOOL}, /* whether or not to fill in the ends with faces */
- {"cap_tris", BMO_OP_SLOT_BOOL}, /* fill ends with triangles instead of ngons */
- {"segments", BMO_OP_SLOT_INT},
- {"radius", BMO_OP_SLOT_FLT}, /* Radius of the circle. */
- {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */
- {"calc_uvs", BMO_OP_SLOT_BOOL}, /* calculate default UVs */
- {{'\0'}},
- },
- /* slots_out */
- {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
- {{'\0'}},
- },
- bmo_create_circle_exec,
- (BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH),
+ "create_circle",
+ /* slots_in */
+ {{"cap_ends", BMO_OP_SLOT_BOOL}, /* whether or not to fill in the ends with faces */
+ {"cap_tris", BMO_OP_SLOT_BOOL}, /* fill ends with triangles instead of ngons */
+ {"segments", BMO_OP_SLOT_INT},
+ {"radius", BMO_OP_SLOT_FLT}, /* Radius of the circle. */
+ {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */
+ {"calc_uvs", BMO_OP_SLOT_BOOL}, /* calculate default UVs */
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
+ {{'\0'}},
+ },
+ bmo_create_circle_exec,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1708,43 +1708,43 @@ static BMOpDefine bmo_create_circle_def = {
* Creates a cube.
*/
static BMOpDefine bmo_create_cube_def = {
- "create_cube",
- /* slots_in */
- {{"size", BMO_OP_SLOT_FLT}, /* size of the cube */
- {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */
- {"calc_uvs", BMO_OP_SLOT_BOOL}, /* calculate default UVs */
- {{'\0'}},
- },
- /* slots_out */
- {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
- {{'\0'}},
- },
- bmo_create_cube_exec,
- (BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH),
+ "create_cube",
+ /* slots_in */
+ {{"size", BMO_OP_SLOT_FLT}, /* size of the cube */
+ {"matrix", BMO_OP_SLOT_MAT}, /* matrix to multiply the new geometry with */
+ {"calc_uvs", BMO_OP_SLOT_BOOL}, /* calculate default UVs */
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
+ {{'\0'}},
+ },
+ bmo_create_cube_exec,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
static BMO_FlagSet bmo_enum_bevel_offset_type[] = {
- {BEVEL_AMT_OFFSET, "OFFSET"},
- {BEVEL_AMT_WIDTH, "WIDTH"},
- {BEVEL_AMT_DEPTH, "DEPTH"},
- {BEVEL_AMT_PERCENT, "PERCENT"},
- {0, NULL},
+ {BEVEL_AMT_OFFSET, "OFFSET"},
+ {BEVEL_AMT_WIDTH, "WIDTH"},
+ {BEVEL_AMT_DEPTH, "DEPTH"},
+ {BEVEL_AMT_PERCENT, "PERCENT"},
+ {0, NULL},
};
static BMO_FlagSet bmo_enum_bevel_face_strength_type[] = {
- {BEVEL_FACE_STRENGTH_NONE, "NONE"},
- {BEVEL_FACE_STRENGTH_NEW, "NEW"},
- {BEVEL_FACE_STRENGTH_AFFECTED, "AFFECTED"},
- {BEVEL_FACE_STRENGTH_ALL, "ALL"},
- {0, NULL},
+ {BEVEL_FACE_STRENGTH_NONE, "NONE"},
+ {BEVEL_FACE_STRENGTH_NEW, "NEW"},
+ {BEVEL_FACE_STRENGTH_AFFECTED, "AFFECTED"},
+ {BEVEL_FACE_STRENGTH_ALL, "ALL"},
+ {0, NULL},
};
static BMO_FlagSet bmo_enum_bevel_miter_type[] = {
- {BEVEL_MITER_SHARP, "SHARP"},
- {BEVEL_MITER_PATCH, "PATCH"},
- {BEVEL_MITER_ARC, "ARC"},
- {0, NULL},
+ {BEVEL_MITER_SHARP, "SHARP"},
+ {BEVEL_MITER_PATCH, "PATCH"},
+ {BEVEL_MITER_ARC, "ARC"},
+ {0, NULL},
};
/*
@@ -1753,49 +1753,49 @@ static BMO_FlagSet bmo_enum_bevel_miter_type[] = {
* Bevels edges and vertices
*/
static BMOpDefine bmo_bevel_def = {
- "bevel",
- /* slots_in */
- {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input edges and vertices */
- {"offset", BMO_OP_SLOT_FLT}, /* amount to offset beveled edge */
- {"offset_type", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_bevel_offset_type}, /* how to measure the offset */
- {"segments", BMO_OP_SLOT_INT}, /* number of segments in bevel */
- {"profile", BMO_OP_SLOT_FLT}, /* profile shape, 0->1 (.5=>round) */
- {"vertex_only", BMO_OP_SLOT_BOOL}, /* only bevel vertices, not edges */
- {"clamp_overlap", BMO_OP_SLOT_BOOL}, /* do not allow beveled edges/vertices to overlap each other */
- {"material", BMO_OP_SLOT_INT}, /* material for bevel faces, -1 means get from adjacent faces */
- {"loop_slide", BMO_OP_SLOT_BOOL}, /* prefer to slide along edges to having even widths */
- {"mark_seam", BMO_OP_SLOT_BOOL}, /* extend edge data to allow seams to run across bevels */
- {"mark_sharp", BMO_OP_SLOT_BOOL}, /* extend edge data to allow sharp edges to run across bevels */
- {"harden_normals", BMO_OP_SLOT_BOOL}, /* harden normals */
- {"face_strength_mode", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM},
- bmo_enum_bevel_face_strength_type}, /* whether to set face strength, and which faces to set if so */
- {"miter_outer", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM},
- bmo_enum_bevel_miter_type}, /* outer miter kind */
- {"miter_inner", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM},
- bmo_enum_bevel_miter_type}, /* outer miter kind */
- {"spread", BMO_OP_SLOT_FLT}, /* amount to offset beveled edge */
- {"smoothresh", BMO_OP_SLOT_FLT}, /* for passing mesh's smoothresh, used in hardening */
- {{'\0'}},
- },
- /* slots_out */
- {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */
- {"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* output edges */
- {"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
- {{'\0'}},
- },
-
- bmo_bevel_exec,
- (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
- BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH |
- BMO_OPTYPE_FLAG_SELECT_VALIDATE),
+ "bevel",
+ /* slots_in */
+ {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input edges and vertices */
+ {"offset", BMO_OP_SLOT_FLT}, /* amount to offset beveled edge */
+ {"offset_type", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_bevel_offset_type}, /* how to measure the offset */
+ {"segments", BMO_OP_SLOT_INT}, /* number of segments in bevel */
+ {"profile", BMO_OP_SLOT_FLT}, /* profile shape, 0->1 (.5=>round) */
+ {"vertex_only", BMO_OP_SLOT_BOOL}, /* only bevel vertices, not edges */
+ {"clamp_overlap", BMO_OP_SLOT_BOOL}, /* do not allow beveled edges/vertices to overlap each other */
+ {"material", BMO_OP_SLOT_INT}, /* material for bevel faces, -1 means get from adjacent faces */
+ {"loop_slide", BMO_OP_SLOT_BOOL}, /* prefer to slide along edges to having even widths */
+ {"mark_seam", BMO_OP_SLOT_BOOL}, /* extend edge data to allow seams to run across bevels */
+ {"mark_sharp", BMO_OP_SLOT_BOOL}, /* extend edge data to allow sharp edges to run across bevels */
+ {"harden_normals", BMO_OP_SLOT_BOOL}, /* harden normals */
+ {"face_strength_mode", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM},
+ bmo_enum_bevel_face_strength_type}, /* whether to set face strength, and which faces to set if so */
+ {"miter_outer", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM},
+ bmo_enum_bevel_miter_type}, /* outer miter kind */
+ {"miter_inner", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM},
+ bmo_enum_bevel_miter_type}, /* outer miter kind */
+ {"spread", BMO_OP_SLOT_FLT}, /* amount to offset beveled edge */
+ {"smoothresh", BMO_OP_SLOT_FLT}, /* for passing mesh's smoothresh, used in hardening */
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */
+ {"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* output edges */
+ {"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
+ {{'\0'}},
+ },
+
+ bmo_bevel_exec,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/* no enum is defined for this */
static BMO_FlagSet bmo_enum_beautify_fill_method[] = {
- {0, "AREA"},
- {1, "ANGLE"},
- {0, NULL},
+ {0, "AREA"},
+ {1, "ANGLE"},
+ {0, NULL},
};
/*
@@ -1804,23 +1804,23 @@ static BMO_FlagSet bmo_enum_beautify_fill_method[] = {
* Rotate edges to create more evenly spaced triangles.
*/
static BMOpDefine bmo_beautify_fill_def = {
- "beautify_fill",
- /* slots_in */
- {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */
- {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* edges that can be flipped */
- {"use_restrict_tag", BMO_OP_SLOT_BOOL}, /* restrict edge rotation to mixed tagged vertices */
- {"method", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_beautify_fill_method}, /* method to define what is beautiful */
- {{'\0'}},
- },
- /* slots_out */
- {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* new flipped faces and edges */
- {{'\0'}},
- },
- bmo_beautify_fill_exec,
- (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
- BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH |
- BMO_OPTYPE_FLAG_SELECT_VALIDATE),
+ "beautify_fill",
+ /* slots_in */
+ {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */
+ {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* edges that can be flipped */
+ {"use_restrict_tag", BMO_OP_SLOT_BOOL}, /* restrict edge rotation to mixed tagged vertices */
+ {"method", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_beautify_fill_method}, /* method to define what is beautiful */
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* new flipped faces and edges */
+ {{'\0'}},
+ },
+ bmo_beautify_fill_exec,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/*
@@ -1829,22 +1829,22 @@ static BMOpDefine bmo_beautify_fill_def = {
* Fill edges with triangles
*/
static BMOpDefine bmo_triangle_fill_def = {
- "triangle_fill",
- /* slots_in */
- {{"use_beauty", BMO_OP_SLOT_BOOL},
- {"use_dissolve", BMO_OP_SLOT_BOOL}, /* dissolve resulting faces */
- {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
- {"normal", BMO_OP_SLOT_VEC}, /* optionally pass the fill normal to use */
- {{'\0'}},
- },
- /* slots_out */
- {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* new faces and edges */
- {{'\0'}},
- },
- bmo_triangle_fill_exec,
- (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
- BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH),
+ "triangle_fill",
+ /* slots_in */
+ {{"use_beauty", BMO_OP_SLOT_BOOL},
+ {"use_dissolve", BMO_OP_SLOT_BOOL}, /* dissolve resulting faces */
+ {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */
+ {"normal", BMO_OP_SLOT_VEC}, /* optionally pass the fill normal to use */
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* new faces and edges */
+ {{'\0'}},
+ },
+ bmo_triangle_fill_exec,
+ (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
+ BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1853,19 +1853,19 @@ static BMOpDefine bmo_triangle_fill_def = {
* Turns a mesh into a shell with thickness
*/
static BMOpDefine bmo_solidify_def = {
- "solidify",
- /* slots_in */
- {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
- {"thickness", BMO_OP_SLOT_FLT},
- {{'\0'}},
- },
- /* slots_out */
- {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
- {{'\0'}},
- },
- bmo_solidify_face_region_exec,
- (BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH),
+ "solidify",
+ /* slots_in */
+ {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
+ {"thickness", BMO_OP_SLOT_FLT},
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
+ {{'\0'}},
+ },
+ bmo_solidify_face_region_exec,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1874,23 +1874,23 @@ static BMOpDefine bmo_solidify_def = {
* Insets individual faces.
*/
static BMOpDefine bmo_inset_individual_def = {
- "inset_individual",
- /* slots_in */
- {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */
- {"thickness", BMO_OP_SLOT_FLT},
- {"depth", BMO_OP_SLOT_FLT},
- {"use_even_offset", BMO_OP_SLOT_BOOL},
- {"use_interpolate", BMO_OP_SLOT_BOOL},
- {"use_relative_offset", BMO_OP_SLOT_BOOL},
- {{'\0'}},
- },
- /* slots_out */
- {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */
- {{'\0'}},
- },
- bmo_inset_individual_exec,
- /* caller needs to handle BMO_OPTYPE_FLAG_SELECT_FLUSH */
- (BMO_OPTYPE_FLAG_NORMALS_CALC),
+ "inset_individual",
+ /* slots_in */
+ {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */
+ {"thickness", BMO_OP_SLOT_FLT},
+ {"depth", BMO_OP_SLOT_FLT},
+ {"use_even_offset", BMO_OP_SLOT_BOOL},
+ {"use_interpolate", BMO_OP_SLOT_BOOL},
+ {"use_relative_offset", BMO_OP_SLOT_BOOL},
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */
+ {{'\0'}},
+ },
+ bmo_inset_individual_exec,
+ /* caller needs to handle BMO_OPTYPE_FLAG_SELECT_FLUSH */
+ (BMO_OPTYPE_FLAG_NORMALS_CALC),
};
/*
@@ -1899,27 +1899,27 @@ static BMOpDefine bmo_inset_individual_def = {
* Inset or outset face regions.
*/
static BMOpDefine bmo_inset_region_def = {
- "inset_region",
- /* slots_in */
- {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */
- {"faces_exclude", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
- {"use_boundary", BMO_OP_SLOT_BOOL},
- {"use_even_offset", BMO_OP_SLOT_BOOL},
- {"use_interpolate", BMO_OP_SLOT_BOOL},
- {"use_relative_offset", BMO_OP_SLOT_BOOL},
- {"use_edge_rail", BMO_OP_SLOT_BOOL},
- {"thickness", BMO_OP_SLOT_FLT},
- {"depth", BMO_OP_SLOT_FLT},
- {"use_outset", BMO_OP_SLOT_BOOL},
- {{'\0'}},
- },
- /* slots_out */
- {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */
- {{'\0'}},
- },
- bmo_inset_region_exec,
- (BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH),
+ "inset_region",
+ /* slots_in */
+ {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */
+ {"faces_exclude", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},
+ {"use_boundary", BMO_OP_SLOT_BOOL},
+ {"use_even_offset", BMO_OP_SLOT_BOOL},
+ {"use_interpolate", BMO_OP_SLOT_BOOL},
+ {"use_relative_offset", BMO_OP_SLOT_BOOL},
+ {"use_edge_rail", BMO_OP_SLOT_BOOL},
+ {"thickness", BMO_OP_SLOT_FLT},
+ {"depth", BMO_OP_SLOT_FLT},
+ {"use_outset", BMO_OP_SLOT_BOOL},
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */
+ {{'\0'}},
+ },
+ bmo_inset_region_exec,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1928,19 +1928,19 @@ static BMOpDefine bmo_inset_region_def = {
* Creates edge loops based on simple edge-outset method.
*/
static BMOpDefine bmo_offset_edgeloops_def = {
- "offset_edgeloops",
- /* slots_in */
- {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input faces */
- {"use_cap_endpoint", BMO_OP_SLOT_BOOL},
- {{'\0'}},
- },
- /* slots_out */
- {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* output faces */
- {{'\0'}},
- },
- bmo_offset_edgeloops_exec,
- (BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH),
+ "offset_edgeloops",
+ /* slots_in */
+ {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input faces */
+ {"use_cap_endpoint", BMO_OP_SLOT_BOOL},
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"edges.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* output faces */
+ {{'\0'}},
+ },
+ bmo_offset_edgeloops_exec,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH),
};
/*
@@ -1949,35 +1949,35 @@ static BMOpDefine bmo_offset_edgeloops_def = {
* Makes a wire-frame copy of faces.
*/
static BMOpDefine bmo_wireframe_def = {
- "wireframe",
- /* slots_in */
- {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */
- {"thickness", BMO_OP_SLOT_FLT},
- {"offset", BMO_OP_SLOT_FLT},
- {"use_replace", BMO_OP_SLOT_BOOL},
- {"use_boundary", BMO_OP_SLOT_BOOL},
- {"use_even_offset", BMO_OP_SLOT_BOOL},
- {"use_crease", BMO_OP_SLOT_BOOL},
- {"crease_weight", BMO_OP_SLOT_FLT},
- {"use_relative_offset", BMO_OP_SLOT_BOOL},
- {"material_offset", BMO_OP_SLOT_INT},
- {{'\0'}},
- },
- /* slots_out */
- {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */
- {{'\0'}},
- },
- bmo_wireframe_exec,
- (BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH |
- BMO_OPTYPE_FLAG_SELECT_VALIDATE),
+ "wireframe",
+ /* slots_in */
+ {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */
+ {"thickness", BMO_OP_SLOT_FLT},
+ {"offset", BMO_OP_SLOT_FLT},
+ {"use_replace", BMO_OP_SLOT_BOOL},
+ {"use_boundary", BMO_OP_SLOT_BOOL},
+ {"use_even_offset", BMO_OP_SLOT_BOOL},
+ {"use_crease", BMO_OP_SLOT_BOOL},
+ {"crease_weight", BMO_OP_SLOT_FLT},
+ {"use_relative_offset", BMO_OP_SLOT_BOOL},
+ {"material_offset", BMO_OP_SLOT_INT},
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */
+ {{'\0'}},
+ },
+ bmo_wireframe_exec,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
static BMO_FlagSet bmo_enum_poke_center_mode[] = {
- {BMOP_POKE_MEDIAN_WEIGHTED, "MEAN_WEIGHTED"},
- {BMOP_POKE_MEDIAN, "MEAN"},
- {BMOP_POKE_BOUNDS, "BOUNDS"},
- {0, NULL},
+ {BMOP_POKE_MEDIAN_WEIGHTED, "MEAN_WEIGHTED"},
+ {BMOP_POKE_MEDIAN, "MEAN"},
+ {BMOP_POKE_BOUNDS, "BOUNDS"},
+ {0, NULL},
};
/*
@@ -1986,23 +1986,23 @@ static BMO_FlagSet bmo_enum_poke_center_mode[] = {
* Splits a face into a triangle fan.
*/
static BMOpDefine bmo_poke_def = {
- "poke",
- /* slots_in */
- {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */
- {"offset", BMO_OP_SLOT_FLT}, /* center vertex offset along normal */
- {"center_mode", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_poke_center_mode}, /* calculation mode for center vertex */
- {"use_relative_offset", BMO_OP_SLOT_BOOL}, /* apply offset */
- {{'\0'}},
- },
- /* slots_out */
- {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
- {"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */
- {{'\0'}},
- },
- bmo_poke_exec,
- (BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH |
- BMO_OPTYPE_FLAG_SELECT_VALIDATE),
+ "poke",
+ /* slots_in */
+ {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */
+ {"offset", BMO_OP_SLOT_FLT}, /* center vertex offset along normal */
+ {"center_mode", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_poke_center_mode}, /* calculation mode for center vertex */
+ {"use_relative_offset", BMO_OP_SLOT_BOOL}, /* apply offset */
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* output verts */
+ {"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* output faces */
+ {{'\0'}},
+ },
+ bmo_poke_exec,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
#ifdef WITH_BULLET
@@ -2022,23 +2022,23 @@ static BMOpDefine bmo_poke_def = {
* that were in the input and are part of the hull.
*/
static BMOpDefine bmo_convex_hull_def = {
- "convex_hull",
- /* slots_in */
- {{"input", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
- {"use_existing_faces", BMO_OP_SLOT_BOOL},
- {{'\0'}},
- },
- /* slots_out */
- {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
- {"geom_interior.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
- {"geom_unused.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
- {"geom_holes.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
- {{'\0'}},
- },
- bmo_convex_hull_exec,
- (BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH |
- BMO_OPTYPE_FLAG_SELECT_VALIDATE),
+ "convex_hull",
+ /* slots_in */
+ {{"input", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
+ {"use_existing_faces", BMO_OP_SLOT_BOOL},
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
+ {"geom_interior.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
+ {"geom_unused.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
+ {"geom_holes.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
+ {{'\0'}},
+ },
+ bmo_convex_hull_exec,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
#endif
@@ -2053,108 +2053,108 @@ static BMOpDefine bmo_convex_hull_def = {
* All new vertices, edges, and faces are added to the "geom.out" slot.
*/
static BMOpDefine bmo_symmetrize_def = {
- "symmetrize",
- /* slots_in */
- {{"input", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
- {"direction", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_axis_xyz}, /* axis to use */
- {"dist", BMO_OP_SLOT_FLT}, /* minimum distance */
- {{'\0'}},
- },
- /* slots_out */
- {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
- {{'\0'}},
- },
- bmo_symmetrize_exec,
- (BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH |
- BMO_OPTYPE_FLAG_SELECT_VALIDATE),
+ "symmetrize",
+ /* slots_in */
+ {{"input", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
+ {"direction", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_axis_xyz}, /* axis to use */
+ {"dist", BMO_OP_SLOT_FLT}, /* minimum distance */
+ {{'\0'}},
+ },
+ /* slots_out */
+ {{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}},
+ {{'\0'}},
+ },
+ bmo_symmetrize_exec,
+ (BMO_OPTYPE_FLAG_NORMALS_CALC |
+ BMO_OPTYPE_FLAG_SELECT_FLUSH |
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE),
};
/* clang-format on */
const BMOpDefine *bmo_opdefines[] = {
- &bmo_automerge_def,
- &bmo_average_vert_facedata_def,
- &bmo_beautify_fill_def,
- &bmo_bevel_def,
- &bmo_bisect_edges_def,
- &bmo_bmesh_to_mesh_def,
- &bmo_bridge_loops_def,
- &bmo_collapse_def,
- &bmo_collapse_uvs_def,
- &bmo_connect_verts_def,
- &bmo_connect_verts_concave_def,
- &bmo_connect_verts_nonplanar_def,
- &bmo_connect_vert_pair_def,
- &bmo_contextual_create_def,
+ &bmo_automerge_def,
+ &bmo_average_vert_facedata_def,
+ &bmo_beautify_fill_def,
+ &bmo_bevel_def,
+ &bmo_bisect_edges_def,
+ &bmo_bmesh_to_mesh_def,
+ &bmo_bridge_loops_def,
+ &bmo_collapse_def,
+ &bmo_collapse_uvs_def,
+ &bmo_connect_verts_def,
+ &bmo_connect_verts_concave_def,
+ &bmo_connect_verts_nonplanar_def,
+ &bmo_connect_vert_pair_def,
+ &bmo_contextual_create_def,
#ifdef WITH_BULLET
- &bmo_convex_hull_def,
+ &bmo_convex_hull_def,
#endif
- &bmo_create_circle_def,
- &bmo_create_cone_def,
- &bmo_create_cube_def,
- &bmo_create_grid_def,
- &bmo_create_icosphere_def,
- &bmo_create_monkey_def,
- &bmo_create_uvsphere_def,
- &bmo_create_vert_def,
- &bmo_delete_def,
- &bmo_dissolve_edges_def,
- &bmo_dissolve_faces_def,
- &bmo_dissolve_verts_def,
- &bmo_dissolve_limit_def,
- &bmo_dissolve_degenerate_def,
- &bmo_duplicate_def,
- &bmo_holes_fill_def,
- &bmo_face_attribute_fill_def,
- &bmo_offset_edgeloops_def,
- &bmo_edgeloop_fill_def,
- &bmo_edgenet_fill_def,
- &bmo_edgenet_prepare_def,
- &bmo_extrude_discrete_faces_def,
- &bmo_extrude_edge_only_def,
- &bmo_extrude_face_region_def,
- &bmo_extrude_vert_indiv_def,
- &bmo_find_doubles_def,
- &bmo_grid_fill_def,
- &bmo_inset_individual_def,
- &bmo_inset_region_def,
- &bmo_join_triangles_def,
- &bmo_mesh_to_bmesh_def,
- &bmo_mirror_def,
- &bmo_object_load_bmesh_def,
- &bmo_pointmerge_def,
- &bmo_pointmerge_facedata_def,
- &bmo_poke_def,
- &bmo_recalc_face_normals_def,
- &bmo_planar_faces_def,
- &bmo_region_extend_def,
- &bmo_remove_doubles_def,
- &bmo_reverse_colors_def,
- &bmo_reverse_faces_def,
- &bmo_reverse_uvs_def,
- &bmo_rotate_colors_def,
- &bmo_rotate_def,
- &bmo_rotate_edges_def,
- &bmo_rotate_uvs_def,
- &bmo_scale_def,
- &bmo_smooth_vert_def,
- &bmo_smooth_laplacian_vert_def,
- &bmo_solidify_def,
- &bmo_spin_def,
- &bmo_split_def,
- &bmo_split_edges_def,
- &bmo_subdivide_edges_def,
- &bmo_subdivide_edgering_def,
- &bmo_bisect_plane_def,
- &bmo_symmetrize_def,
- &bmo_transform_def,
- &bmo_translate_def,
- &bmo_triangle_fill_def,
- &bmo_triangulate_def,
- &bmo_unsubdivide_def,
- &bmo_weld_verts_def,
- &bmo_wireframe_def,
+ &bmo_create_circle_def,
+ &bmo_create_cone_def,
+ &bmo_create_cube_def,
+ &bmo_create_grid_def,
+ &bmo_create_icosphere_def,
+ &bmo_create_monkey_def,
+ &bmo_create_uvsphere_def,
+ &bmo_create_vert_def,
+ &bmo_delete_def,
+ &bmo_dissolve_edges_def,
+ &bmo_dissolve_faces_def,
+ &bmo_dissolve_verts_def,
+ &bmo_dissolve_limit_def,
+ &bmo_dissolve_degenerate_def,
+ &bmo_duplicate_def,
+ &bmo_holes_fill_def,
+ &bmo_face_attribute_fill_def,
+ &bmo_offset_edgeloops_def,
+ &bmo_edgeloop_fill_def,
+ &bmo_edgenet_fill_def,
+ &bmo_edgenet_prepare_def,
+ &bmo_extrude_discrete_faces_def,
+ &bmo_extrude_edge_only_def,
+ &bmo_extrude_face_region_def,
+ &bmo_extrude_vert_indiv_def,
+ &bmo_find_doubles_def,
+ &bmo_grid_fill_def,
+ &bmo_inset_individual_def,
+ &bmo_inset_region_def,
+ &bmo_join_triangles_def,
+ &bmo_mesh_to_bmesh_def,
+ &bmo_mirror_def,
+ &bmo_object_load_bmesh_def,
+ &bmo_pointmerge_def,
+ &bmo_pointmerge_facedata_def,
+ &bmo_poke_def,
+ &bmo_recalc_face_normals_def,
+ &bmo_planar_faces_def,
+ &bmo_region_extend_def,
+ &bmo_remove_doubles_def,
+ &bmo_reverse_colors_def,
+ &bmo_reverse_faces_def,
+ &bmo_reverse_uvs_def,
+ &bmo_rotate_colors_def,
+ &bmo_rotate_def,
+ &bmo_rotate_edges_def,
+ &bmo_rotate_uvs_def,
+ &bmo_scale_def,
+ &bmo_smooth_vert_def,
+ &bmo_smooth_laplacian_vert_def,
+ &bmo_solidify_def,
+ &bmo_spin_def,
+ &bmo_split_def,
+ &bmo_split_edges_def,
+ &bmo_subdivide_edges_def,
+ &bmo_subdivide_edgering_def,
+ &bmo_bisect_plane_def,
+ &bmo_symmetrize_def,
+ &bmo_transform_def,
+ &bmo_translate_def,
+ &bmo_triangle_fill_def,
+ &bmo_triangulate_def,
+ &bmo_unsubdivide_def,
+ &bmo_weld_verts_def,
+ &bmo_wireframe_def,
};
const int bmo_opdefines_total = ARRAY_SIZE(bmo_opdefines);
diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h
index 9894252a53a..5085eb801ce 100644
--- a/source/blender/bmesh/intern/bmesh_operator_api.h
+++ b/source/blender/bmesh/intern/bmesh_operator_api.h
@@ -71,222 +71,274 @@ struct GHashIterator;
BLI_INLINE BMFlagLayer *BMO_elem_flag_from_header(BMHeader *ele_head)
{
- switch (ele_head->htype) {
- case BM_VERT: return ((BMVert_OFlag *)ele_head)->oflags;
- case BM_EDGE: return ((BMEdge_OFlag *)ele_head)->oflags;
- default: return ((BMFace_OFlag *)ele_head)->oflags;
- }
+ switch (ele_head->htype) {
+ case BM_VERT:
+ return ((BMVert_OFlag *)ele_head)->oflags;
+ case BM_EDGE:
+ return ((BMEdge_OFlag *)ele_head)->oflags;
+ default:
+ return ((BMFace_OFlag *)ele_head)->oflags;
+ }
}
#define BMO_elem_flag_test(bm, ele, oflag) \
- _bmo_elem_flag_test(bm, BMO_elem_flag_from_header(&(ele)->head), oflag)
+ _bmo_elem_flag_test(bm, BMO_elem_flag_from_header(&(ele)->head), oflag)
#define BMO_elem_flag_test_bool(bm, ele, oflag) \
- _bmo_elem_flag_test_bool(bm, BMO_elem_flag_from_header(&(ele)->head), oflag)
+ _bmo_elem_flag_test_bool(bm, BMO_elem_flag_from_header(&(ele)->head), oflag)
#define BMO_elem_flag_enable(bm, ele, oflag) \
- _bmo_elem_flag_enable(bm, (BM_CHECK_TYPE_ELEM_NONCONST(ele), BMO_elem_flag_from_header(&(ele)->head)), oflag)
+ _bmo_elem_flag_enable( \
+ bm, (BM_CHECK_TYPE_ELEM_NONCONST(ele), BMO_elem_flag_from_header(&(ele)->head)), oflag)
#define BMO_elem_flag_disable(bm, ele, oflag) \
- _bmo_elem_flag_disable(bm, (BM_CHECK_TYPE_ELEM_NONCONST(ele), BMO_elem_flag_from_header(&(ele)->head)), oflag)
+ _bmo_elem_flag_disable( \
+ bm, (BM_CHECK_TYPE_ELEM_NONCONST(ele), BMO_elem_flag_from_header(&(ele)->head)), oflag)
#define BMO_elem_flag_set(bm, ele, oflag, val) \
- _bmo_elem_flag_set(bm, (BM_CHECK_TYPE_ELEM_NONCONST(ele), BMO_elem_flag_from_header(&(ele)->head)), oflag, val)
+ _bmo_elem_flag_set(bm, \
+ (BM_CHECK_TYPE_ELEM_NONCONST(ele), BMO_elem_flag_from_header(&(ele)->head)), \
+ oflag, \
+ val)
#define BMO_elem_flag_toggle(bm, ele, oflag) \
- _bmo_elem_flag_toggle(bm, (BM_CHECK_TYPE_ELEM_NONCONST(ele), BMO_elem_flag_from_header(&(ele)->head)), oflag)
+ _bmo_elem_flag_toggle( \
+ bm, (BM_CHECK_TYPE_ELEM_NONCONST(ele), BMO_elem_flag_from_header(&(ele)->head)), oflag)
/* take care not to instansiate args multiple times */
#ifdef __GNUC___
-#define _BMO_CAST_V_CONST(e) ({ typeof(e) _e = e; \
- (BM_CHECK_TYPE_VERT(_e), BLI_assert(((const BMHeader *)_e)->htype == BM_VERT), (const BMVert_OFlag *)_e); })
-#define _BMO_CAST_E_CONST(e) ({ typeof(e) _e = e; \
- (BM_CHECK_TYPE_EDGE(_e), BLI_assert(((const BMHeader *)_e)->htype == BM_EDGE), (const BMEdge_OFlag *)_e); })
-#define _BMO_CAST_F_CONST(e) ({ typeof(e) _e = e; \
- (BM_CHECK_TYPE_FACE(_e), BLI_assert(((const BMHeader *)_e)->htype == BM_FACE), (const BMFace_OFlag *)_e); })
-#define _BMO_CAST_V(e) ({ typeof(e) _e = e; \
- (BM_CHECK_TYPE_VERT_NONCONST(_e), BLI_assert(((BMHeader *)_e)->htype == BM_VERT), (BMVert_OFlag *)_e); })
-#define _BMO_CAST_E(e) ({ typeof(e) _e = e; \
- (BM_CHECK_TYPE_EDGE_NONCONST(_e), BLI_assert(((BMHeader *)_e)->htype == BM_EDGE), (BMEdge_OFlag *)_e); })
-#define _BMO_CAST_F(e) ({ typeof(e) _e = e; \
- (BM_CHECK_TYPE_FACE_NONCONST(_e), BLI_assert(((BMHeader *)_e)->htype == BM_FACE), (BMFace_OFlag *)_e); })
+# define _BMO_CAST_V_CONST(e) \
+ ({ \
+ typeof(e) _e = e; \
+ (BM_CHECK_TYPE_VERT(_e), \
+ BLI_assert(((const BMHeader *)_e)->htype == BM_VERT), \
+ (const BMVert_OFlag *)_e); \
+ })
+# define _BMO_CAST_E_CONST(e) \
+ ({ \
+ typeof(e) _e = e; \
+ (BM_CHECK_TYPE_EDGE(_e), \
+ BLI_assert(((const BMHeader *)_e)->htype == BM_EDGE), \
+ (const BMEdge_OFlag *)_e); \
+ })
+# define _BMO_CAST_F_CONST(e) \
+ ({ \
+ typeof(e) _e = e; \
+ (BM_CHECK_TYPE_FACE(_e), \
+ BLI_assert(((const BMHeader *)_e)->htype == BM_FACE), \
+ (const BMFace_OFlag *)_e); \
+ })
+# define _BMO_CAST_V(e) \
+ ({ \
+ typeof(e) _e = e; \
+ (BM_CHECK_TYPE_VERT_NONCONST(_e), \
+ BLI_assert(((BMHeader *)_e)->htype == BM_VERT), \
+ (BMVert_OFlag *)_e); \
+ })
+# define _BMO_CAST_E(e) \
+ ({ \
+ typeof(e) _e = e; \
+ (BM_CHECK_TYPE_EDGE_NONCONST(_e), \
+ BLI_assert(((BMHeader *)_e)->htype == BM_EDGE), \
+ (BMEdge_OFlag *)_e); \
+ })
+# define _BMO_CAST_F(e) \
+ ({ \
+ typeof(e) _e = e; \
+ (BM_CHECK_TYPE_FACE_NONCONST(_e), \
+ BLI_assert(((BMHeader *)_e)->htype == BM_FACE), \
+ (BMFace_OFlag *)_e); \
+ })
#else
-#define _BMO_CAST_V_CONST(e) (BM_CHECK_TYPE_VERT(e), (const BMVert_OFlag *)e)
-#define _BMO_CAST_E_CONST(e) (BM_CHECK_TYPE_EDGE(e), (const BMEdge_OFlag *)e)
-#define _BMO_CAST_F_CONST(e) (BM_CHECK_TYPE_FACE(e), (const BMFace_OFlag *)e)
-#define _BMO_CAST_V(e) (BM_CHECK_TYPE_VERT_NONCONST(e), (BMVert_OFlag *)e)
-#define _BMO_CAST_E(e) (BM_CHECK_TYPE_EDGE_NONCONST(e), (BMEdge_OFlag *)e)
-#define _BMO_CAST_F(e) (BM_CHECK_TYPE_FACE_NONCONST(e), (BMFace_OFlag *)e)
+# define _BMO_CAST_V_CONST(e) (BM_CHECK_TYPE_VERT(e), (const BMVert_OFlag *)e)
+# define _BMO_CAST_E_CONST(e) (BM_CHECK_TYPE_EDGE(e), (const BMEdge_OFlag *)e)
+# define _BMO_CAST_F_CONST(e) (BM_CHECK_TYPE_FACE(e), (const BMFace_OFlag *)e)
+# define _BMO_CAST_V(e) (BM_CHECK_TYPE_VERT_NONCONST(e), (BMVert_OFlag *)e)
+# define _BMO_CAST_E(e) (BM_CHECK_TYPE_EDGE_NONCONST(e), (BMEdge_OFlag *)e)
+# define _BMO_CAST_F(e) (BM_CHECK_TYPE_FACE_NONCONST(e), (BMFace_OFlag *)e)
#endif
-#define BMO_vert_flag_test( bm, e, oflag) _bmo_elem_flag_test (bm, _BMO_CAST_V_CONST(e)->oflags, oflag)
-#define BMO_vert_flag_test_bool(bm, e, oflag) _bmo_elem_flag_test_bool(bm, _BMO_CAST_V_CONST(e)->oflags, oflag)
-#define BMO_vert_flag_enable( bm, e, oflag) _bmo_elem_flag_enable (bm, _BMO_CAST_V(e)->oflags, oflag)
-#define BMO_vert_flag_disable( bm, e, oflag) _bmo_elem_flag_disable (bm, _BMO_CAST_V(e)->oflags, oflag)
-#define BMO_vert_flag_set( bm, e, oflag, val) _bmo_elem_flag_set (bm, _BMO_CAST_V(e)->oflags, oflag, val)
-#define BMO_vert_flag_toggle( bm, e, oflag) _bmo_elem_flag_toggle (bm, _BMO_CAST_V(e)->oflags, oflag)
-
-#define BMO_edge_flag_test( bm, e, oflag) _bmo_elem_flag_test (bm, _BMO_CAST_E_CONST(e)->oflags, oflag)
-#define BMO_edge_flag_test_bool(bm, e, oflag) _bmo_elem_flag_test_bool(bm, _BMO_CAST_E_CONST(e)->oflags, oflag)
-#define BMO_edge_flag_enable( bm, e, oflag) _bmo_elem_flag_enable (bm, _BMO_CAST_E(e)->oflags, oflag)
-#define BMO_edge_flag_disable( bm, e, oflag) _bmo_elem_flag_disable (bm, _BMO_CAST_E(e)->oflags, oflag)
-#define BMO_edge_flag_set( bm, e, oflag, val) _bmo_elem_flag_set (bm, _BMO_CAST_E(e)->oflags, oflag, val)
-#define BMO_edge_flag_toggle( bm, e, oflag) _bmo_elem_flag_toggle (bm, _BMO_CAST_E(e)->oflags, oflag)
-
-#define BMO_face_flag_test( bm, e, oflag) _bmo_elem_flag_test (bm, _BMO_CAST_F_CONST(e)->oflags, oflag)
-#define BMO_face_flag_test_bool(bm, e, oflag) _bmo_elem_flag_test_bool(bm, _BMO_CAST_F_CONST(e)->oflags, oflag)
-#define BMO_face_flag_enable( bm, e, oflag) _bmo_elem_flag_enable (bm, _BMO_CAST_F(e)->oflags, oflag)
-#define BMO_face_flag_disable( bm, e, oflag) _bmo_elem_flag_disable (bm, _BMO_CAST_F(e)->oflags, oflag)
-#define BMO_face_flag_set( bm, e, oflag, val) _bmo_elem_flag_set (bm, _BMO_CAST_F(e)->oflags, oflag, val)
-#define BMO_face_flag_toggle( bm, e, oflag) _bmo_elem_flag_toggle (bm, _BMO_CAST_F(e)->oflags, oflag)
-
-BLI_INLINE short _bmo_elem_flag_test( BMesh *bm, const BMFlagLayer *oflags, const short oflag);
-BLI_INLINE bool _bmo_elem_flag_test_bool(BMesh *bm, const BMFlagLayer *oflags, const short oflag);
-BLI_INLINE void _bmo_elem_flag_enable( BMesh *bm, BMFlagLayer *oflags, const short oflag);
-BLI_INLINE void _bmo_elem_flag_disable( BMesh *bm, BMFlagLayer *oflags, const short oflag);
-BLI_INLINE void _bmo_elem_flag_set( BMesh *bm, BMFlagLayer *oflags, const short oflag, int val);
-BLI_INLINE void _bmo_elem_flag_toggle( BMesh *bm, BMFlagLayer *oflags, const short oflag);
+#define BMO_vert_flag_test(bm, e, oflag) \
+ _bmo_elem_flag_test(bm, _BMO_CAST_V_CONST(e)->oflags, oflag)
+#define BMO_vert_flag_test_bool(bm, e, oflag) \
+ _bmo_elem_flag_test_bool(bm, _BMO_CAST_V_CONST(e)->oflags, oflag)
+#define BMO_vert_flag_enable(bm, e, oflag) _bmo_elem_flag_enable(bm, _BMO_CAST_V(e)->oflags, oflag)
+#define BMO_vert_flag_disable(bm, e, oflag) \
+ _bmo_elem_flag_disable(bm, _BMO_CAST_V(e)->oflags, oflag)
+#define BMO_vert_flag_set(bm, e, oflag, val) \
+ _bmo_elem_flag_set(bm, _BMO_CAST_V(e)->oflags, oflag, val)
+#define BMO_vert_flag_toggle(bm, e, oflag) _bmo_elem_flag_toggle(bm, _BMO_CAST_V(e)->oflags, oflag)
+
+#define BMO_edge_flag_test(bm, e, oflag) \
+ _bmo_elem_flag_test(bm, _BMO_CAST_E_CONST(e)->oflags, oflag)
+#define BMO_edge_flag_test_bool(bm, e, oflag) \
+ _bmo_elem_flag_test_bool(bm, _BMO_CAST_E_CONST(e)->oflags, oflag)
+#define BMO_edge_flag_enable(bm, e, oflag) _bmo_elem_flag_enable(bm, _BMO_CAST_E(e)->oflags, oflag)
+#define BMO_edge_flag_disable(bm, e, oflag) \
+ _bmo_elem_flag_disable(bm, _BMO_CAST_E(e)->oflags, oflag)
+#define BMO_edge_flag_set(bm, e, oflag, val) \
+ _bmo_elem_flag_set(bm, _BMO_CAST_E(e)->oflags, oflag, val)
+#define BMO_edge_flag_toggle(bm, e, oflag) _bmo_elem_flag_toggle(bm, _BMO_CAST_E(e)->oflags, oflag)
+
+#define BMO_face_flag_test(bm, e, oflag) \
+ _bmo_elem_flag_test(bm, _BMO_CAST_F_CONST(e)->oflags, oflag)
+#define BMO_face_flag_test_bool(bm, e, oflag) \
+ _bmo_elem_flag_test_bool(bm, _BMO_CAST_F_CONST(e)->oflags, oflag)
+#define BMO_face_flag_enable(bm, e, oflag) _bmo_elem_flag_enable(bm, _BMO_CAST_F(e)->oflags, oflag)
+#define BMO_face_flag_disable(bm, e, oflag) \
+ _bmo_elem_flag_disable(bm, _BMO_CAST_F(e)->oflags, oflag)
+#define BMO_face_flag_set(bm, e, oflag, val) \
+ _bmo_elem_flag_set(bm, _BMO_CAST_F(e)->oflags, oflag, val)
+#define BMO_face_flag_toggle(bm, e, oflag) _bmo_elem_flag_toggle(bm, _BMO_CAST_F(e)->oflags, oflag)
+
+BLI_INLINE short _bmo_elem_flag_test(BMesh *bm, const BMFlagLayer *oflags, const short oflag);
+BLI_INLINE bool _bmo_elem_flag_test_bool(BMesh *bm, const BMFlagLayer *oflags, const short oflag);
+BLI_INLINE void _bmo_elem_flag_enable(BMesh *bm, BMFlagLayer *oflags, const short oflag);
+BLI_INLINE void _bmo_elem_flag_disable(BMesh *bm, BMFlagLayer *oflags, const short oflag);
+BLI_INLINE void _bmo_elem_flag_set(BMesh *bm, BMFlagLayer *oflags, const short oflag, int val);
+BLI_INLINE void _bmo_elem_flag_toggle(BMesh *bm, BMFlagLayer *oflags, const short oflag);
/* slot type arrays are terminated by the last member
* having a slot type of 0 */
typedef enum eBMOpSlotType {
- /* BMO_OP_SLOT_SENTINEL = 0, */
- BMO_OP_SLOT_BOOL = 1,
- BMO_OP_SLOT_INT = 2,
- BMO_OP_SLOT_FLT = 3,
-
- /* normally store pointers to object, scene,
- * _never_ store arrays corresponding to mesh elements with this */
- BMO_OP_SLOT_PTR = 4, /* requres subtype BMO_OP_SLOT_SUBTYPE_PTR_xxx */
- BMO_OP_SLOT_MAT = 5,
- BMO_OP_SLOT_VEC = 8,
-
- /* after BMO_OP_SLOT_VEC, everything is dynamically allocated arrays.
- * We leave a space in the identifiers for future growth.
- *
- * it's very important this remain a power of two */
- BMO_OP_SLOT_ELEMENT_BUF = 9, /* list of verts/edges/faces */
- BMO_OP_SLOT_MAPPING = 10 /* simple hash map, requres subtype BMO_OP_SLOT_SUBTYPE_MAP_xxx */
+ /* BMO_OP_SLOT_SENTINEL = 0, */
+ BMO_OP_SLOT_BOOL = 1,
+ BMO_OP_SLOT_INT = 2,
+ BMO_OP_SLOT_FLT = 3,
+
+ /* normally store pointers to object, scene,
+ * _never_ store arrays corresponding to mesh elements with this */
+ BMO_OP_SLOT_PTR = 4, /* requres subtype BMO_OP_SLOT_SUBTYPE_PTR_xxx */
+ BMO_OP_SLOT_MAT = 5,
+ BMO_OP_SLOT_VEC = 8,
+
+ /* after BMO_OP_SLOT_VEC, everything is dynamically allocated arrays.
+ * We leave a space in the identifiers for future growth.
+ *
+ * it's very important this remain a power of two */
+ BMO_OP_SLOT_ELEMENT_BUF = 9, /* list of verts/edges/faces */
+ BMO_OP_SLOT_MAPPING = 10 /* simple hash map, requres subtype BMO_OP_SLOT_SUBTYPE_MAP_xxx */
} eBMOpSlotType;
#define BMO_OP_SLOT_TOTAL_TYPES 11
/* don't overlap values to avoid confusion */
typedef enum eBMOpSlotSubType_Elem {
- /* use as flags */
- BMO_OP_SLOT_SUBTYPE_ELEM_VERT = BM_VERT,
- BMO_OP_SLOT_SUBTYPE_ELEM_EDGE = BM_EDGE,
- BMO_OP_SLOT_SUBTYPE_ELEM_FACE = BM_FACE,
- BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE = (BM_FACE << 1),
+ /* use as flags */
+ BMO_OP_SLOT_SUBTYPE_ELEM_VERT = BM_VERT,
+ BMO_OP_SLOT_SUBTYPE_ELEM_EDGE = BM_EDGE,
+ BMO_OP_SLOT_SUBTYPE_ELEM_FACE = BM_FACE,
+ BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE = (BM_FACE << 1),
} eBMOpSlotSubType_Elem;
typedef enum eBMOpSlotSubType_Map {
- BMO_OP_SLOT_SUBTYPE_MAP_EMPTY = 64, /* use as a set(), unused value */
- BMO_OP_SLOT_SUBTYPE_MAP_ELEM = 65,
- BMO_OP_SLOT_SUBTYPE_MAP_FLT = 66,
- BMO_OP_SLOT_SUBTYPE_MAP_INT = 67,
- BMO_OP_SLOT_SUBTYPE_MAP_BOOL = 68,
- BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL = 69, /* python can't convert these */
+ BMO_OP_SLOT_SUBTYPE_MAP_EMPTY = 64, /* use as a set(), unused value */
+ BMO_OP_SLOT_SUBTYPE_MAP_ELEM = 65,
+ BMO_OP_SLOT_SUBTYPE_MAP_FLT = 66,
+ BMO_OP_SLOT_SUBTYPE_MAP_INT = 67,
+ BMO_OP_SLOT_SUBTYPE_MAP_BOOL = 68,
+ BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL = 69, /* python can't convert these */
} eBMOpSlotSubType_Map;
typedef enum eBMOpSlotSubType_Ptr {
- BMO_OP_SLOT_SUBTYPE_PTR_BMESH = 100,
- BMO_OP_SLOT_SUBTYPE_PTR_SCENE = 101,
- BMO_OP_SLOT_SUBTYPE_PTR_OBJECT = 102,
- BMO_OP_SLOT_SUBTYPE_PTR_MESH = 103,
+ BMO_OP_SLOT_SUBTYPE_PTR_BMESH = 100,
+ BMO_OP_SLOT_SUBTYPE_PTR_SCENE = 101,
+ BMO_OP_SLOT_SUBTYPE_PTR_OBJECT = 102,
+ BMO_OP_SLOT_SUBTYPE_PTR_MESH = 103,
} eBMOpSlotSubType_Ptr;
typedef enum eBMOpSlotSubType_Int {
- BMO_OP_SLOT_SUBTYPE_INT_ENUM = 200,
- BMO_OP_SLOT_SUBTYPE_INT_FLAG = 201,
+ BMO_OP_SLOT_SUBTYPE_INT_ENUM = 200,
+ BMO_OP_SLOT_SUBTYPE_INT_FLAG = 201,
} eBMOpSlotSubType_Int;
typedef union eBMOpSlotSubType_Union {
- eBMOpSlotSubType_Elem elem;
- eBMOpSlotSubType_Ptr ptr;
- eBMOpSlotSubType_Map map;
- eBMOpSlotSubType_Int intg;
+ eBMOpSlotSubType_Elem elem;
+ eBMOpSlotSubType_Ptr ptr;
+ eBMOpSlotSubType_Map map;
+ eBMOpSlotSubType_Int intg;
} eBMOpSlotSubType_Union;
typedef struct BMO_FlagSet {
- int value;
- const char *identifier;
+ int value;
+ const char *identifier;
} BMO_FlagSet;
/* please ignore all these structures, don't touch them in tool code, except
* for when your defining an operator with BMOpDefine.*/
typedef struct BMOpSlot {
- const char *slot_name; /* pointer to BMOpDefine.slot_args */
- eBMOpSlotType slot_type;
- eBMOpSlotSubType_Union slot_subtype;
-
- int len;
-// int flag; /* UNUSED */
-// int index; /* index within slot array */ /* UNUSED */
- union {
- int i;
- float f;
- void *p;
- float vec[3];
- void **buf;
- GHash *ghash;
- struct {
- /** Don't clobber (i) when assigning flags, see #eBMOpSlotSubType_Int. */
- int _i;
- BMO_FlagSet *flags;
- } enum_data;
- } data;
+ const char *slot_name; /* pointer to BMOpDefine.slot_args */
+ eBMOpSlotType slot_type;
+ eBMOpSlotSubType_Union slot_subtype;
+
+ int len;
+ // int flag; /* UNUSED */
+ // int index; /* index within slot array */ /* UNUSED */
+ union {
+ int i;
+ float f;
+ void *p;
+ float vec[3];
+ void **buf;
+ GHash *ghash;
+ struct {
+ /** Don't clobber (i) when assigning flags, see #eBMOpSlotSubType_Int. */
+ int _i;
+ BMO_FlagSet *flags;
+ } enum_data;
+ } data;
} BMOpSlot;
/* mainly for use outside bmesh internal code */
-#define BMO_SLOT_AS_BOOL(slot) ((slot)->data.i)
-#define BMO_SLOT_AS_INT(slot) ((slot)->data.i)
-#define BMO_SLOT_AS_FLOAT(slot) ((slot)->data.f)
-#define BMO_SLOT_AS_VECTOR(slot) ((slot)->data.vec)
-#define BMO_SLOT_AS_MATRIX(slot ) ((float (*)[4])((slot)->data.p))
-#define BMO_SLOT_AS_BUFFER(slot ) ((slot)->data.buf)
-#define BMO_SLOT_AS_GHASH(slot ) ((slot)->data.ghash)
+#define BMO_SLOT_AS_BOOL(slot) ((slot)->data.i)
+#define BMO_SLOT_AS_INT(slot) ((slot)->data.i)
+#define BMO_SLOT_AS_FLOAT(slot) ((slot)->data.f)
+#define BMO_SLOT_AS_VECTOR(slot) ((slot)->data.vec)
+#define BMO_SLOT_AS_MATRIX(slot) ((float(*)[4])((slot)->data.p))
+#define BMO_SLOT_AS_BUFFER(slot) ((slot)->data.buf)
+#define BMO_SLOT_AS_GHASH(slot) ((slot)->data.ghash)
#define BMO_ASSERT_SLOT_IN_OP(slot, op) \
- BLI_assert(((slot >= (op)->slots_in) && (slot < &(op)->slots_in[BMO_OP_MAX_SLOTS])) || \
- ((slot >= (op)->slots_out) && (slot < &(op)->slots_out[BMO_OP_MAX_SLOTS])))
+ BLI_assert(((slot >= (op)->slots_in) && (slot < &(op)->slots_in[BMO_OP_MAX_SLOTS])) || \
+ ((slot >= (op)->slots_out) && (slot < &(op)->slots_out[BMO_OP_MAX_SLOTS])))
/* way more than probably needed, compiler complains if limit hit */
#define BMO_OP_MAX_SLOTS 20
/* BMOpDefine->type_flag */
typedef enum {
- BMO_OPTYPE_FLAG_NOP = 0,
- BMO_OPTYPE_FLAG_UNTAN_MULTIRES = (1 << 0), /* switch from multires tangent space to absolute coordinates */
- BMO_OPTYPE_FLAG_NORMALS_CALC = (1 << 1),
- BMO_OPTYPE_FLAG_SELECT_FLUSH = (1 << 2),
- BMO_OPTYPE_FLAG_SELECT_VALIDATE = (1 << 3),
- BMO_OPTYPE_FLAG_INVALIDATE_CLNOR_ALL = (1 << 4),
+ BMO_OPTYPE_FLAG_NOP = 0,
+ BMO_OPTYPE_FLAG_UNTAN_MULTIRES =
+ (1 << 0), /* switch from multires tangent space to absolute coordinates */
+ BMO_OPTYPE_FLAG_NORMALS_CALC = (1 << 1),
+ BMO_OPTYPE_FLAG_SELECT_FLUSH = (1 << 2),
+ BMO_OPTYPE_FLAG_SELECT_VALIDATE = (1 << 3),
+ BMO_OPTYPE_FLAG_INVALIDATE_CLNOR_ALL = (1 << 4),
} BMOpTypeFlag;
typedef struct BMOperator {
- struct BMOpSlot slots_in[BMO_OP_MAX_SLOTS];
- struct BMOpSlot slots_out[BMO_OP_MAX_SLOTS];
- void (*exec)(BMesh *bm, struct BMOperator *op);
- struct MemArena *arena;
- int type;
- BMOpTypeFlag type_flag;
- int flag; /* runtime options */
+ struct BMOpSlot slots_in[BMO_OP_MAX_SLOTS];
+ struct BMOpSlot slots_out[BMO_OP_MAX_SLOTS];
+ void (*exec)(BMesh *bm, struct BMOperator *op);
+ struct MemArena *arena;
+ int type;
+ BMOpTypeFlag type_flag;
+ int flag; /* runtime options */
} BMOperator;
enum {
- BMO_FLAG_RESPECT_HIDE = 1,
+ BMO_FLAG_RESPECT_HIDE = 1,
};
-#define BMO_FLAG_DEFAULTS BMO_FLAG_RESPECT_HIDE
+#define BMO_FLAG_DEFAULTS BMO_FLAG_RESPECT_HIDE
-#define MAX_SLOTNAME 32
+#define MAX_SLOTNAME 32
typedef struct BMOSlotType {
- char name[MAX_SLOTNAME];
- eBMOpSlotType type;
- eBMOpSlotSubType_Union subtype;
- BMO_FlagSet *enum_flags;
+ char name[MAX_SLOTNAME];
+ eBMOpSlotType type;
+ eBMOpSlotSubType_Union subtype;
+ BMO_FlagSet *enum_flags;
} BMOSlotType;
typedef struct BMOpDefine {
- const char *opname;
- BMOSlotType slot_types_in[BMO_OP_MAX_SLOTS];
- BMOSlotType slot_types_out[BMO_OP_MAX_SLOTS];
- void (*exec)(BMesh *bm, BMOperator *op);
- BMOpTypeFlag type_flag;
+ const char *opname;
+ BMOSlotType slot_types_in[BMO_OP_MAX_SLOTS];
+ BMOSlotType slot_types_out[BMO_OP_MAX_SLOTS];
+ void (*exec)(BMesh *bm, BMOperator *op);
+ BMOpTypeFlag type_flag;
} BMOpDefine;
/*------------- Operator API --------------*/
@@ -337,177 +389,205 @@ BMOpSlot *BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identif
/* copies the data of a slot from one operator to another. src and dst are the
* source/destination slot codes, respectively. */
-#define BMO_slot_copy(op_src, slots_src, slot_name_src, \
- op_dst, slots_dst, slot_name_dst) \
- _bmo_slot_copy((op_src)->slots_src, slot_name_src, \
- (op_dst)->slots_dst, slot_name_dst, \
- (op_dst)->arena)
+#define BMO_slot_copy(op_src, slots_src, slot_name_src, op_dst, slots_dst, slot_name_dst) \
+ _bmo_slot_copy( \
+ (op_src)->slots_src, slot_name_src, (op_dst)->slots_dst, slot_name_dst, (op_dst)->arena)
-void _bmo_slot_copy(
- BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src,
- BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst,
- struct MemArena *arena_dst);
+void _bmo_slot_copy(BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS],
+ const char *slot_name_src,
+ BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS],
+ const char *slot_name_dst,
+ struct MemArena *arena_dst);
/* del "context" slot values, used for operator too */
enum {
- DEL_VERTS = 1,
- DEL_EDGES,
- DEL_ONLYFACES,
- DEL_EDGESFACES,
- DEL_FACES,
- /* A version of 'DEL_FACES' that keeps edges on face boundaries,
- * allowing the surrounding edge-loop to be kept from removed face regions. */
- DEL_FACES_KEEP_BOUNDARY,
- DEL_ONLYTAGGED,
+ DEL_VERTS = 1,
+ DEL_EDGES,
+ DEL_ONLYFACES,
+ DEL_EDGESFACES,
+ DEL_FACES,
+ /* A version of 'DEL_FACES' that keeps edges on face boundaries,
+ * allowing the surrounding edge-loop to be kept from removed face regions. */
+ DEL_FACES_KEEP_BOUNDARY,
+ DEL_ONLYTAGGED,
};
typedef enum {
- BMO_SYMMETRIZE_NEGATIVE_X,
- BMO_SYMMETRIZE_NEGATIVE_Y,
- BMO_SYMMETRIZE_NEGATIVE_Z,
+ BMO_SYMMETRIZE_NEGATIVE_X,
+ BMO_SYMMETRIZE_NEGATIVE_Y,
+ BMO_SYMMETRIZE_NEGATIVE_Z,
- BMO_SYMMETRIZE_POSITIVE_X,
- BMO_SYMMETRIZE_POSITIVE_Y,
- BMO_SYMMETRIZE_POSITIVE_Z,
+ BMO_SYMMETRIZE_POSITIVE_X,
+ BMO_SYMMETRIZE_POSITIVE_Y,
+ BMO_SYMMETRIZE_POSITIVE_Z,
} BMO_SymmDirection;
typedef enum {
- BMO_DELIM_NORMAL = 1 << 0,
- BMO_DELIM_MATERIAL = 1 << 1,
- BMO_DELIM_SEAM = 1 << 2,
- BMO_DELIM_SHARP = 1 << 3,
- BMO_DELIM_UV = 1 << 4,
+ BMO_DELIM_NORMAL = 1 << 0,
+ BMO_DELIM_MATERIAL = 1 << 1,
+ BMO_DELIM_SEAM = 1 << 2,
+ BMO_DELIM_SHARP = 1 << 3,
+ BMO_DELIM_UV = 1 << 4,
} BMO_Delimit;
void BMO_op_flag_enable(BMesh *bm, BMOperator *op, const int op_flag);
void BMO_op_flag_disable(BMesh *bm, BMOperator *op, const int op_flag);
-void BMO_slot_float_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float f);
+void BMO_slot_float_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ const float f);
float BMO_slot_float_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
-void BMO_slot_int_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int i);
-int BMO_slot_int_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
-void BMO_slot_bool_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const bool i);
-bool BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
+void BMO_slot_int_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int i);
+int BMO_slot_int_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
+void BMO_slot_bool_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const bool i);
+bool BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
void *BMO_slot_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, int *len);
-
/* don't pass in arrays that are supposed to map to elements this way.
*
* so, e.g. passing in list of floats per element in another slot is bad.
* passing in, e.g. pointer to an editmesh for the conversion operator is fine
* though. */
-void BMO_slot_ptr_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, void *p);
+void BMO_slot_ptr_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, void *p);
void *BMO_slot_ptr_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
-void BMO_slot_vec_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float vec[3]);
-void BMO_slot_vec_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_vec[3]);
+void BMO_slot_vec_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ const float vec[3]);
+void BMO_slot_vec_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_vec[3]);
/* only supports square mats */
/* size must be 3 or 4; this api is meant only for transformation matrices.
* note that internally the matrix is stored in 4x4 form, and it's safe to
* call whichever BMO_Get_MatXXX function you want. */
-void BMO_slot_mat_set(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float *mat, int size);
-void BMO_slot_mat4_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_mat[4][4]);
-void BMO_slot_mat3_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_mat[3][3]);
+void BMO_slot_mat_set(BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ const float *mat,
+ int size);
+void BMO_slot_mat4_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ float r_mat[4][4]);
+void BMO_slot_mat3_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ float r_mat[3][3]);
void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *op, const char htype, const short oflag);
-void BMO_mesh_selected_remap(
- BMesh *bm,
- BMOpSlot *slot_vert_map,
- BMOpSlot *slot_edge_map,
- BMOpSlot *slot_face_map,
- const bool check_select);
+void BMO_mesh_selected_remap(BMesh *bm,
+ BMOpSlot *slot_vert_map,
+ BMOpSlot *slot_edge_map,
+ BMOpSlot *slot_face_map,
+ const bool check_select);
/* copies the values from another slot to the end of the output slot */
-#define BMO_slot_buffer_append(op_src, slots_src, slot_name_src, \
- op_dst, slots_dst, slot_name_dst) \
- _bmo_slot_buffer_append((op_src)->slots_src, slot_name_src, \
- (op_dst)->slots_dst, slot_name_dst, \
- (op_dst)->arena)
-void _bmo_slot_buffer_append(
- BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst,
- BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src,
- struct MemArena *arena_dst);
+#define BMO_slot_buffer_append( \
+ op_src, slots_src, slot_name_src, op_dst, slots_dst, slot_name_dst) \
+ _bmo_slot_buffer_append( \
+ (op_src)->slots_src, slot_name_src, (op_dst)->slots_dst, slot_name_dst, (op_dst)->arena)
+void _bmo_slot_buffer_append(BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS],
+ const char *slot_name_dst,
+ BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS],
+ const char *slot_name_src,
+ struct MemArena *arena_dst);
/* puts every element of type 'type' (which is a bitmask) with tool
* flag 'flag', into a slot. */
-void BMO_slot_buffer_from_enabled_flag(
- BMesh *bm, BMOperator *op,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const short oflag);
+void BMO_slot_buffer_from_enabled_flag(BMesh *bm,
+ BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ const char htype,
+ const short oflag);
/* puts every element of type 'type' (which is a bitmask) without tool
* flag 'flag', into a slot. */
-void BMO_slot_buffer_from_disabled_flag(
- BMesh *bm, BMOperator *op,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const short oflag);
+void BMO_slot_buffer_from_disabled_flag(BMesh *bm,
+ BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ const char htype,
+ const short oflag);
/* tool-flags all elements inside an element slot array with flag flag. */
-void BMO_slot_buffer_flag_enable(
- BMesh *bm,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const short oflag);
+void BMO_slot_buffer_flag_enable(BMesh *bm,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ const char htype,
+ const short oflag);
/* clears tool-flag flag from all elements inside a slot array. */
-void BMO_slot_buffer_flag_disable(
- BMesh *bm,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const short oflag);
+void BMO_slot_buffer_flag_disable(BMesh *bm,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ const char htype,
+ const short oflag);
/* tool-flags all elements inside an element slot array with flag flag. */
-void BMO_slot_buffer_hflag_enable(
- BMesh *bm,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const char hflag, const bool do_flush);
+void BMO_slot_buffer_hflag_enable(BMesh *bm,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ const char htype,
+ const char hflag,
+ const bool do_flush);
/* clears tool-flag flag from all elements inside a slot array. */
-void BMO_slot_buffer_hflag_disable(
- BMesh *bm,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const char hflag, const bool do_flush);
+void BMO_slot_buffer_hflag_disable(BMesh *bm,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ const char htype,
+ const char hflag,
+ const bool do_flush);
/* puts every element of type 'type' (which is a bitmask) with header
* flag 'flag', into a slot. note: ignores hidden elements
* (e.g. elements with header flag BM_ELEM_HIDDEN set).*/
-void BMO_slot_buffer_from_enabled_hflag(
- BMesh *bm, BMOperator *op,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const char hflag);
+void BMO_slot_buffer_from_enabled_hflag(BMesh *bm,
+ BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ const char htype,
+ const char hflag);
/* puts every element of type 'type' (which is a bitmask) without
* header flag 'flag', into a slot. note: ignores hidden elements
* (e.g. elements with header flag BM_ELEM_HIDDEN set).*/
-void BMO_slot_buffer_from_disabled_hflag(
- BMesh *bm, BMOperator *op,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const char hflag);
-
-void BMO_slot_buffer_from_array(BMOperator *op, BMOpSlot *slot, BMHeader **ele_buffer, int ele_buffer_len);
-
-void BMO_slot_buffer_from_single(BMOperator *op, BMOpSlot *slot, BMHeader *ele);
+void BMO_slot_buffer_from_disabled_hflag(BMesh *bm,
+ BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ const char htype,
+ const char hflag);
+
+void BMO_slot_buffer_from_array(BMOperator *op,
+ BMOpSlot *slot,
+ BMHeader **ele_buffer,
+ int ele_buffer_len);
+
+void BMO_slot_buffer_from_single(BMOperator *op, BMOpSlot *slot, BMHeader *ele);
void *BMO_slot_buffer_get_single(BMOpSlot *slot);
-
/* counts number of elements inside a slot array. */
int BMO_slot_buffer_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
-void BMO_slot_map_insert(
- BMOperator *op, BMOpSlot *slot,
- const void *element, const void *data);
+void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot, const void *element, const void *data);
/* flags all elements in a mapping. note that the mapping must only have
* bmesh elements in it.*/
-void BMO_slot_map_to_flag(
- BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
- const char *slot_name, const char hflag, const short oflag);
-
-void *BMO_slot_buffer_alloc(
- BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
- const char *slot_name, const int len);
-
-void BMO_slot_buffer_from_all(
- BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
- const char *slot_name, const char htype);
+void BMO_slot_map_to_flag(BMesh *bm,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ const char hflag,
+ const short oflag);
+
+void *BMO_slot_buffer_alloc(BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ const int len);
+
+void BMO_slot_buffer_from_all(BMesh *bm,
+ BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ const char htype);
/**
* This part of the API is used to iterate over element buffer or
@@ -547,37 +627,38 @@ void BMO_slot_buffer_from_all(
/* contents of this structure are private,
* don't directly access. */
typedef struct BMOIter {
- BMOpSlot *slot;
- int cur; //for arrays
- GHashIterator giter;
- void **val;
- char restrictmask; /* bitwise '&' with BMHeader.htype */
+ BMOpSlot *slot;
+ int cur; //for arrays
+ GHashIterator giter;
+ void **val;
+ char restrictmask; /* bitwise '&' with BMHeader.htype */
} BMOIter;
void *BMO_slot_buffer_get_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
-void *BMO_iter_new(
- BMOIter *iter,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char restrictmask);
+void *BMO_iter_new(BMOIter *iter,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ const char restrictmask);
void *BMO_iter_step(BMOIter *iter);
void **BMO_iter_map_value_p(BMOIter *iter);
-void *BMO_iter_map_value_ptr(BMOIter *iter);
+void *BMO_iter_map_value_ptr(BMOIter *iter);
float BMO_iter_map_value_float(BMOIter *iter);
-int BMO_iter_map_value_int(BMOIter *iter);
-bool BMO_iter_map_value_bool(BMOIter *iter);
-
-#define BMO_ITER(ele, iter, slot_args, slot_name, restrict_flag) \
- for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMO_iter_new(iter, slot_args, slot_name, restrict_flag); \
- ele; \
- BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMO_iter_step(iter))
-
-#define BMO_ITER_INDEX(ele, iter, slot_args, slot_name, restrict_flag, i_) \
- for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMO_iter_new(iter, slot_args, slot_name, restrict_flag), i_ = 0; \
- ele; \
- BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMO_iter_step(iter), i_++)
+int BMO_iter_map_value_int(BMOIter *iter);
+bool BMO_iter_map_value_bool(BMOIter *iter);
+
+#define BMO_ITER(ele, iter, slot_args, slot_name, restrict_flag) \
+ for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMO_iter_new(iter, slot_args, slot_name, restrict_flag); \
+ ele; \
+ BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMO_iter_step(iter))
+
+#define BMO_ITER_INDEX(ele, iter, slot_args, slot_name, restrict_flag, i_) \
+ for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMO_iter_new(iter, slot_args, slot_name, restrict_flag), \
+ i_ = 0; \
+ ele; \
+ BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMO_iter_step(iter), i_++)
extern const int BMO_OPSLOT_TYPEINFO[BMO_OP_SLOT_TOTAL_TYPES];
diff --git a/source/blender/bmesh/intern/bmesh_operator_api_inline.h b/source/blender/bmesh/intern/bmesh_operator_api_inline.h
index 78e75cf3d30..2bda2d121c2 100644
--- a/source/blender/bmesh/intern/bmesh_operator_api_inline.h
+++ b/source/blender/bmesh/intern/bmesh_operator_api_inline.h
@@ -32,195 +32,209 @@
* ghash or a mapping slot to do it. */
/* flags 15 and 16 (1 << 14 and 1 << 15) are reserved for bmesh api use */
-ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2)
-BLI_INLINE short _bmo_elem_flag_test(BMesh *bm, const BMFlagLayer *oflags, const short oflag)
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) BLI_INLINE
+ short _bmo_elem_flag_test(BMesh *bm, const BMFlagLayer *oflags, const short oflag)
{
- BLI_assert(bm->use_toolflags);
- return oflags[bm->toolflag_index].f & oflag;
+ BLI_assert(bm->use_toolflags);
+ return oflags[bm->toolflag_index].f & oflag;
}
-ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2)
-BLI_INLINE bool _bmo_elem_flag_test_bool(BMesh *bm, const BMFlagLayer *oflags, const short oflag)
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) BLI_INLINE
+ bool _bmo_elem_flag_test_bool(BMesh *bm, const BMFlagLayer *oflags, const short oflag)
{
- BLI_assert(bm->use_toolflags);
- return (oflags[bm->toolflag_index].f & oflag) != 0;
+ BLI_assert(bm->use_toolflags);
+ return (oflags[bm->toolflag_index].f & oflag) != 0;
}
ATTR_NONNULL(1, 2)
BLI_INLINE void _bmo_elem_flag_enable(BMesh *bm, BMFlagLayer *oflags, const short oflag)
{
- BLI_assert(bm->use_toolflags);
- oflags[bm->toolflag_index].f |= oflag;
+ BLI_assert(bm->use_toolflags);
+ oflags[bm->toolflag_index].f |= oflag;
}
ATTR_NONNULL(1, 2)
BLI_INLINE void _bmo_elem_flag_disable(BMesh *bm, BMFlagLayer *oflags, const short oflag)
{
- BLI_assert(bm->use_toolflags);
- oflags[bm->toolflag_index].f &= (short)~oflag;
+ BLI_assert(bm->use_toolflags);
+ oflags[bm->toolflag_index].f &= (short)~oflag;
}
ATTR_NONNULL(1, 2)
BLI_INLINE void _bmo_elem_flag_set(BMesh *bm, BMFlagLayer *oflags, const short oflag, int val)
{
- BLI_assert(bm->use_toolflags);
- if (val) { oflags[bm->toolflag_index].f |= oflag; }
- else { oflags[bm->toolflag_index].f &= (short)~oflag; }
+ BLI_assert(bm->use_toolflags);
+ if (val) {
+ oflags[bm->toolflag_index].f |= oflag;
+ }
+ else {
+ oflags[bm->toolflag_index].f &= (short)~oflag;
+ }
}
ATTR_NONNULL(1, 2)
BLI_INLINE void _bmo_elem_flag_toggle(BMesh *bm, BMFlagLayer *oflags, const short oflag)
{
- BLI_assert(bm->use_toolflags);
- oflags[bm->toolflag_index].f ^= oflag;
+ BLI_assert(bm->use_toolflags);
+ oflags[bm->toolflag_index].f ^= oflag;
}
ATTR_NONNULL(1, 2)
-BLI_INLINE void BMO_slot_map_int_insert(
- BMOperator *op, BMOpSlot *slot,
- void *element, const int val)
+BLI_INLINE void BMO_slot_map_int_insert(BMOperator *op,
+ BMOpSlot *slot,
+ void *element,
+ const int val)
{
- union { void *ptr; int val; } t = {NULL};
- BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INT);
- BMO_slot_map_insert(op, slot, element, ((void)(t.val = val), t.ptr));
+ union {
+ void *ptr;
+ int val;
+ } t = {NULL};
+ BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INT);
+ BMO_slot_map_insert(op, slot, element, ((void)(t.val = val), t.ptr));
}
ATTR_NONNULL(1, 2)
-BLI_INLINE void BMO_slot_map_bool_insert(
- BMOperator *op, BMOpSlot *slot,
- void *element, const bool val)
+BLI_INLINE void BMO_slot_map_bool_insert(BMOperator *op,
+ BMOpSlot *slot,
+ void *element,
+ const bool val)
{
- union { void *ptr; bool val; } t = {NULL};
- BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_BOOL);
- BMO_slot_map_insert(op, slot, element, ((void)(t.val = val), t.ptr));
+ union {
+ void *ptr;
+ bool val;
+ } t = {NULL};
+ BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_BOOL);
+ BMO_slot_map_insert(op, slot, element, ((void)(t.val = val), t.ptr));
}
ATTR_NONNULL(1, 2)
-BLI_INLINE void BMO_slot_map_float_insert(
- BMOperator *op, BMOpSlot *slot,
- void *element, const float val)
+BLI_INLINE void BMO_slot_map_float_insert(BMOperator *op,
+ BMOpSlot *slot,
+ void *element,
+ const float val)
{
- union { void *ptr; float val; } t = {NULL};
- BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_FLT);
- BMO_slot_map_insert(op, slot, element, ((void)(t.val = val), t.ptr));
+ union {
+ void *ptr;
+ float val;
+ } t = {NULL};
+ BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_FLT);
+ BMO_slot_map_insert(op, slot, element, ((void)(t.val = val), t.ptr));
}
-
/* pointer versions of BMO_slot_map_float_get and BMO_slot_map_float_insert.
*
* do NOT use these for non-operator-api-allocated memory! instead
* use BMO_slot_map_data_get and BMO_slot_map_insert, which copies the data. */
ATTR_NONNULL(1, 2)
-BLI_INLINE void BMO_slot_map_ptr_insert(
- BMOperator *op, BMOpSlot *slot,
- const void *element, void *val)
+BLI_INLINE void BMO_slot_map_ptr_insert(BMOperator *op,
+ BMOpSlot *slot,
+ const void *element,
+ void *val)
{
- BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL);
- BMO_slot_map_insert(op, slot, element, val);
+ BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL);
+ BMO_slot_map_insert(op, slot, element, val);
}
ATTR_NONNULL(1, 2)
-BLI_INLINE void BMO_slot_map_elem_insert(
- BMOperator *op, BMOpSlot *slot,
- const void *element, void *val)
+BLI_INLINE void BMO_slot_map_elem_insert(BMOperator *op,
+ BMOpSlot *slot,
+ const void *element,
+ void *val)
{
- BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_ELEM);
- BMO_slot_map_insert(op, slot, element, val);
+ BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_ELEM);
+ BMO_slot_map_insert(op, slot, element, val);
}
-
/* no values */
ATTR_NONNULL(1, 2)
-BLI_INLINE void BMO_slot_map_empty_insert(
- BMOperator *op, BMOpSlot *slot,
- const void *element)
+BLI_INLINE void BMO_slot_map_empty_insert(BMOperator *op, BMOpSlot *slot, const void *element)
{
- BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_EMPTY);
- BMO_slot_map_insert(op, slot, element, NULL);
+ BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_EMPTY);
+ BMO_slot_map_insert(op, slot, element, NULL);
}
-ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
-BLI_INLINE bool BMO_slot_map_contains(BMOpSlot *slot, const void *element)
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE
+ bool BMO_slot_map_contains(BMOpSlot *slot, const void *element)
{
- BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING);
- return BLI_ghash_haskey(slot->data.ghash, element);
+ BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING);
+ return BLI_ghash_haskey(slot->data.ghash, element);
}
-ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
-BLI_INLINE void **BMO_slot_map_data_get(BMOpSlot *slot, const void *element)
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE
+ void **BMO_slot_map_data_get(BMOpSlot *slot, const void *element)
{
- return BLI_ghash_lookup_p(slot->data.ghash, element);
+ return BLI_ghash_lookup_p(slot->data.ghash, element);
}
-ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
-BLI_INLINE float BMO_slot_map_float_get(BMOpSlot *slot, const void *element)
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE
+ float BMO_slot_map_float_get(BMOpSlot *slot, const void *element)
{
- void **data;
- BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_FLT);
+ void **data;
+ BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_FLT);
- data = BMO_slot_map_data_get(slot, element);
- if (data) {
- return *(float *)data;
- }
- else {
- return 0.0f;
- }
+ data = BMO_slot_map_data_get(slot, element);
+ if (data) {
+ return *(float *)data;
+ }
+ else {
+ return 0.0f;
+ }
}
-ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
-BLI_INLINE int BMO_slot_map_int_get(BMOpSlot *slot, const void *element)
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE
+ int BMO_slot_map_int_get(BMOpSlot *slot, const void *element)
{
- void **data;
- BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INT);
+ void **data;
+ BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INT);
- data = BMO_slot_map_data_get(slot, element);
- if (data) {
- return *(int *)data;
- }
- else {
- return 0;
- }
+ data = BMO_slot_map_data_get(slot, element);
+ if (data) {
+ return *(int *)data;
+ }
+ else {
+ return 0;
+ }
}
-ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
-BLI_INLINE bool BMO_slot_map_bool_get(BMOpSlot *slot, const void *element)
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE
+ bool BMO_slot_map_bool_get(BMOpSlot *slot, const void *element)
{
- void **data;
- BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_BOOL);
+ void **data;
+ BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_BOOL);
- data = BMO_slot_map_data_get(slot, element);
- if (data) {
- return *(bool *)data;
- }
- else {
- return false;
- }
+ data = BMO_slot_map_data_get(slot, element);
+ if (data) {
+ return *(bool *)data;
+ }
+ else {
+ return false;
+ }
}
-ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
-BLI_INLINE void *BMO_slot_map_ptr_get(BMOpSlot *slot, const void *element)
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE
+ void *BMO_slot_map_ptr_get(BMOpSlot *slot, const void *element)
{
- void **val = BMO_slot_map_data_get(slot, element);
- BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL);
- if (val) {
- return *val;
- }
+ void **val = BMO_slot_map_data_get(slot, element);
+ BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL);
+ if (val) {
+ return *val;
+ }
- return NULL;
+ return NULL;
}
-ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
-BLI_INLINE void *BMO_slot_map_elem_get(BMOpSlot *slot, const void *element)
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE
+ void *BMO_slot_map_elem_get(BMOpSlot *slot, const void *element)
{
- void **val = (void **) BMO_slot_map_data_get(slot, element);
- BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_ELEM);
- if (val) {
- return *val;
- }
+ void **val = (void **)BMO_slot_map_data_get(slot, element);
+ BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_ELEM);
+ if (val) {
+ return *val;
+ }
- return NULL;
+ return NULL;
}
#endif /* __BMESH_OPERATOR_API_INLINE_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c
index fb6edbecaed..a7783084c01 100644
--- a/source/blender/bmesh/intern/bmesh_operators.c
+++ b/source/blender/bmesh/intern/bmesh_operators.c
@@ -39,36 +39,37 @@ static void bmo_flag_layer_alloc(BMesh *bm);
static void bmo_flag_layer_free(BMesh *bm);
static void bmo_flag_layer_clear(BMesh *bm);
static int bmo_name_to_slotcode(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier);
-static int bmo_name_to_slotcode_check(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier);
+static int bmo_name_to_slotcode_check(BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *identifier);
static const char *bmo_error_messages[] = {
- NULL,
- N_("Self intersection error"),
- N_("Could not dissolve vert"),
- N_("Could not connect vertices"),
- N_("Could not traverse mesh"),
- N_("Could not dissolve faces"),
- N_("Tessellation error"),
- N_("Cannot deal with non-manifold geometry"),
- N_("Invalid selection"),
- N_("Internal mesh error"),
+ NULL,
+ N_("Self intersection error"),
+ N_("Could not dissolve vert"),
+ N_("Could not connect vertices"),
+ N_("Could not traverse mesh"),
+ N_("Could not dissolve faces"),
+ N_("Tessellation error"),
+ N_("Cannot deal with non-manifold geometry"),
+ N_("Invalid selection"),
+ N_("Internal mesh error"),
};
BLI_STATIC_ASSERT(ARRAY_SIZE(bmo_error_messages) + 1 == BMERR_TOTAL, "message mismatch");
/* operator slot type information - size of one element of the type given. */
const int BMO_OPSLOT_TYPEINFO[BMO_OP_SLOT_TOTAL_TYPES] = {
- 0, /* 0: BMO_OP_SLOT_SENTINEL */
- sizeof(int), /* 1: BMO_OP_SLOT_BOOL */
- sizeof(int), /* 2: BMO_OP_SLOT_INT */
- sizeof(float), /* 3: BMO_OP_SLOT_FLT */
- sizeof(void *), /* 4: BMO_OP_SLOT_PNT */
- sizeof(void *), /* 5: BMO_OP_SLOT_PNT */
- 0, /* 6: unused */
- 0, /* 7: unused */
- sizeof(float) * 3, /* 8: BMO_OP_SLOT_VEC */
- sizeof(void *), /* 9: BMO_OP_SLOT_ELEMENT_BUF */
- sizeof(void *), /* 10: BMO_OP_SLOT_MAPPING */
+ 0, /* 0: BMO_OP_SLOT_SENTINEL */
+ sizeof(int), /* 1: BMO_OP_SLOT_BOOL */
+ sizeof(int), /* 2: BMO_OP_SLOT_INT */
+ sizeof(float), /* 3: BMO_OP_SLOT_FLT */
+ sizeof(void *), /* 4: BMO_OP_SLOT_PNT */
+ sizeof(void *), /* 5: BMO_OP_SLOT_PNT */
+ 0, /* 6: unused */
+ 0, /* 7: unused */
+ sizeof(float) * 3, /* 8: BMO_OP_SLOT_VEC */
+ sizeof(void *), /* 9: BMO_OP_SLOT_ELEMENT_BUF */
+ sizeof(void *), /* 10: BMO_OP_SLOT_MAPPING */
};
/* Dummy slot so there is something to return when slot name lookup fails */
@@ -76,12 +77,12 @@ const int BMO_OPSLOT_TYPEINFO[BMO_OP_SLOT_TOTAL_TYPES] = {
void BMO_op_flag_enable(BMesh *UNUSED(bm), BMOperator *op, const int op_flag)
{
- op->flag |= op_flag;
+ op->flag |= op_flag;
}
void BMO_op_flag_disable(BMesh *UNUSED(bm), BMOperator *op, const int op_flag)
{
- op->flag &= ~op_flag;
+ op->flag &= ~op_flag;
}
/**
@@ -91,17 +92,17 @@ void BMO_op_flag_disable(BMesh *UNUSED(bm), BMOperator *op, const int op_flag)
*/
void BMO_push(BMesh *bm, BMOperator *UNUSED(op))
{
- bm->toolflag_index++;
+ bm->toolflag_index++;
- BLI_assert(bm->totflags > 0);
+ BLI_assert(bm->totflags > 0);
- /* add flag layer, if appropriate */
- if (bm->toolflag_index > 0) {
- bmo_flag_layer_alloc(bm);
- }
- else {
- bmo_flag_layer_clear(bm);
- }
+ /* add flag layer, if appropriate */
+ if (bm->toolflag_index > 0) {
+ bmo_flag_layer_alloc(bm);
+ }
+ else {
+ bmo_flag_layer_clear(bm);
+ }
}
/**
@@ -113,54 +114,55 @@ void BMO_push(BMesh *bm, BMOperator *UNUSED(op))
*/
void BMO_pop(BMesh *bm)
{
- if (bm->toolflag_index > 0) {
- bmo_flag_layer_free(bm);
- }
+ if (bm->toolflag_index > 0) {
+ bmo_flag_layer_free(bm);
+ }
- bm->toolflag_index--;
+ bm->toolflag_index--;
}
-
/* use for both slot_types_in and slot_types_out */
static void bmo_op_slots_init(const BMOSlotType *slot_types, BMOpSlot *slot_args)
{
- BMOpSlot *slot;
- uint i;
- for (i = 0; slot_types[i].type; i++) {
- slot = &slot_args[i];
- slot->slot_name = slot_types[i].name;
- slot->slot_type = slot_types[i].type;
- slot->slot_subtype = slot_types[i].subtype;
- // slot->index = i; // UNUSED
-
- switch (slot->slot_type) {
- case BMO_OP_SLOT_MAPPING:
- slot->data.ghash = BLI_ghash_ptr_new("bmesh slot map hash");
- break;
- case BMO_OP_SLOT_INT:
- if (ELEM(slot->slot_subtype.intg, BMO_OP_SLOT_SUBTYPE_INT_ENUM, BMO_OP_SLOT_SUBTYPE_INT_FLAG)) {
- slot->data.enum_data.flags = slot_types[i].enum_flags;
- }
- default:
- break;
- }
- }
+ BMOpSlot *slot;
+ uint i;
+ for (i = 0; slot_types[i].type; i++) {
+ slot = &slot_args[i];
+ slot->slot_name = slot_types[i].name;
+ slot->slot_type = slot_types[i].type;
+ slot->slot_subtype = slot_types[i].subtype;
+ // slot->index = i; // UNUSED
+
+ switch (slot->slot_type) {
+ case BMO_OP_SLOT_MAPPING:
+ slot->data.ghash = BLI_ghash_ptr_new("bmesh slot map hash");
+ break;
+ case BMO_OP_SLOT_INT:
+ if (ELEM(slot->slot_subtype.intg,
+ BMO_OP_SLOT_SUBTYPE_INT_ENUM,
+ BMO_OP_SLOT_SUBTYPE_INT_FLAG)) {
+ slot->data.enum_data.flags = slot_types[i].enum_flags;
+ }
+ default:
+ break;
+ }
+ }
}
static void bmo_op_slots_free(const BMOSlotType *slot_types, BMOpSlot *slot_args)
{
- BMOpSlot *slot;
- uint i;
- for (i = 0; slot_types[i].type; i++) {
- slot = &slot_args[i];
- switch (slot->slot_type) {
- case BMO_OP_SLOT_MAPPING:
- BLI_ghash_free(slot->data.ghash, NULL, NULL);
- break;
- default:
- break;
- }
- }
+ BMOpSlot *slot;
+ uint i;
+ for (i = 0; slot_types[i].type; i++) {
+ slot = &slot_args[i];
+ switch (slot->slot_type) {
+ case BMO_OP_SLOT_MAPPING:
+ BLI_ghash_free(slot->data.ghash, NULL, NULL);
+ break;
+ default:
+ break;
+ }
+ }
}
/**
@@ -170,33 +172,33 @@ static void bmo_op_slots_free(const BMOSlotType *slot_types, BMOpSlot *slot_args
*/
void BMO_op_init(BMesh *bm, BMOperator *op, const int flag, const char *opname)
{
- int opcode = BMO_opcode_from_opname(opname);
+ int opcode = BMO_opcode_from_opname(opname);
#ifdef DEBUG
- BM_ELEM_INDEX_VALIDATE(bm, "pre bmo", opname);
+ BM_ELEM_INDEX_VALIDATE(bm, "pre bmo", opname);
#else
- (void)bm;
+ (void)bm;
#endif
- if (opcode == -1) {
- opcode = 0; /* error!, already printed, have a better way to handle this? */
- }
+ if (opcode == -1) {
+ opcode = 0; /* error!, already printed, have a better way to handle this? */
+ }
- memset(op, 0, sizeof(BMOperator));
- op->type = opcode;
- op->type_flag = bmo_opdefines[opcode]->type_flag;
- op->flag = flag;
+ memset(op, 0, sizeof(BMOperator));
+ op->type = opcode;
+ op->type_flag = bmo_opdefines[opcode]->type_flag;
+ op->flag = flag;
- /* initialize the operator slot types */
- bmo_op_slots_init(bmo_opdefines[opcode]->slot_types_in, op->slots_in);
- bmo_op_slots_init(bmo_opdefines[opcode]->slot_types_out, op->slots_out);
+ /* initialize the operator slot types */
+ bmo_op_slots_init(bmo_opdefines[opcode]->slot_types_in, op->slots_in);
+ bmo_op_slots_init(bmo_opdefines[opcode]->slot_types_out, op->slots_out);
- /* callback */
- op->exec = bmo_opdefines[opcode]->exec;
+ /* callback */
+ op->exec = bmo_opdefines[opcode]->exec;
- /* memarena, used for operator's slot buffers */
- op->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
- BLI_memarena_use_calloc(op->arena);
+ /* memarena, used for operator's slot buffers */
+ op->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+ BLI_memarena_use_calloc(op->arena);
}
/**
@@ -210,21 +212,21 @@ void BMO_op_init(BMesh *bm, BMOperator *op, const int flag, const char *opname)
*/
void BMO_op_exec(BMesh *bm, BMOperator *op)
{
- /* allocate tool flags on demand */
- BM_mesh_elem_toolflags_ensure(bm);
+ /* allocate tool flags on demand */
+ BM_mesh_elem_toolflags_ensure(bm);
- BMO_push(bm, op);
+ BMO_push(bm, op);
- if (bm->toolflag_index == 1) {
- bmesh_edit_begin(bm, op->type_flag);
- }
- op->exec(bm, op);
+ if (bm->toolflag_index == 1) {
+ bmesh_edit_begin(bm, op->type_flag);
+ }
+ op->exec(bm, op);
- if (bm->toolflag_index == 1) {
- bmesh_edit_end(bm, op->type_flag);
- }
+ if (bm->toolflag_index == 1) {
+ bmesh_edit_end(bm, op->type_flag);
+ }
- BMO_pop(bm);
+ BMO_pop(bm);
}
/**
@@ -234,18 +236,18 @@ void BMO_op_exec(BMesh *bm, BMOperator *op)
*/
void BMO_op_finish(BMesh *bm, BMOperator *op)
{
- bmo_op_slots_free(bmo_opdefines[op->type]->slot_types_in, op->slots_in);
- bmo_op_slots_free(bmo_opdefines[op->type]->slot_types_out, op->slots_out);
+ bmo_op_slots_free(bmo_opdefines[op->type]->slot_types_in, op->slots_in);
+ bmo_op_slots_free(bmo_opdefines[op->type]->slot_types_out, op->slots_out);
- BLI_memarena_free(op->arena);
+ BLI_memarena_free(op->arena);
#ifdef DEBUG
- BM_ELEM_INDEX_VALIDATE(bm, "post bmo", bmo_opdefines[op->type]->opname);
+ BM_ELEM_INDEX_VALIDATE(bm, "post bmo", bmo_opdefines[op->type]->opname);
- /* avoid accidental re-use */
- memset(op, 0xff, sizeof(*op));
+ /* avoid accidental re-use */
+ memset(op, 0xff, sizeof(*op));
#else
- (void)bm;
+ (void)bm;
#endif
}
@@ -256,8 +258,8 @@ void BMO_op_finish(BMesh *bm, BMOperator *op)
*/
bool BMO_slot_exists(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier)
{
- int slot_code = bmo_name_to_slotcode(slot_args, identifier);
- return (slot_code >= 0);
+ int slot_code = bmo_name_to_slotcode(slot_args, identifier);
+ return (slot_code >= 0);
}
/**
@@ -267,15 +269,15 @@ bool BMO_slot_exists(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifie
*/
BMOpSlot *BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier)
{
- int slot_code = bmo_name_to_slotcode_check(slot_args, identifier);
+ int slot_code = bmo_name_to_slotcode_check(slot_args, identifier);
- if (UNLIKELY(slot_code < 0)) {
- //return &BMOpEmptySlot;
- BLI_assert(0);
- return NULL; /* better crash */
- }
+ if (UNLIKELY(slot_code < 0)) {
+ //return &BMOpEmptySlot;
+ BLI_assert(0);
+ return NULL; /* better crash */
+ }
- return &slot_args[slot_code];
+ return &slot_args[slot_code];
}
/**
@@ -284,84 +286,85 @@ BMOpSlot *BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identif
* define used.
* Copies data from one slot to another.
*/
-void _bmo_slot_copy(
- BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src,
- BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst,
- struct MemArena *arena_dst)
-{
- BMOpSlot *slot_src = BMO_slot_get(slot_args_src, slot_name_src);
- BMOpSlot *slot_dst = BMO_slot_get(slot_args_dst, slot_name_dst);
-
- if (slot_src == slot_dst) {
- return;
- }
-
- BLI_assert(slot_src->slot_type == slot_dst->slot_type);
- if (slot_src->slot_type != slot_dst->slot_type) {
- return;
- }
-
- if (slot_dst->slot_type == BMO_OP_SLOT_ELEMENT_BUF) {
- /* do buffer copy */
- slot_dst->data.buf = NULL;
- slot_dst->len = slot_src->len;
- if (slot_dst->len) {
- /* check dest has all flags enabled that the source has */
- const eBMOpSlotSubType_Elem src_elem_flag = (slot_src->slot_subtype.elem & BM_ALL_NOLOOP);
- const eBMOpSlotSubType_Elem dst_elem_flag = (slot_dst->slot_subtype.elem & BM_ALL_NOLOOP);
-
- if ((src_elem_flag | dst_elem_flag) == dst_elem_flag) {
- /* pass */
- }
- else {
- /* check types */
- const uint tot = slot_src->len;
- uint i;
- uint out = 0;
- BMElem **ele_src = (BMElem **)slot_src->data.buf;
- for (i = 0; i < tot; i++, ele_src++) {
- if ((*ele_src)->head.htype & dst_elem_flag) {
- out++;
- }
- }
- if (out != tot) {
- slot_dst->len = out;
- }
- }
-
- if (slot_dst->len) {
- const int slot_alloc_size = BMO_OPSLOT_TYPEINFO[slot_dst->slot_type] * slot_dst->len;
- slot_dst->data.buf = BLI_memarena_alloc(arena_dst, slot_alloc_size);
- if (slot_src->len == slot_dst->len) {
- memcpy(slot_dst->data.buf, slot_src->data.buf, slot_alloc_size);
- }
- else {
- /* only copy compatible elements */
- const uint tot = slot_src->len;
- uint i;
- BMElem **ele_src = (BMElem **)slot_src->data.buf;
- BMElem **ele_dst = (BMElem **)slot_dst->data.buf;
- for (i = 0; i < tot; i++, ele_src++) {
- if ((*ele_src)->head.htype & dst_elem_flag) {
- *ele_dst = *ele_src;
- ele_dst++;
- }
- }
- }
- }
- }
- }
- else if (slot_dst->slot_type == BMO_OP_SLOT_MAPPING) {
- GHashIterator gh_iter;
- GHASH_ITER (gh_iter, slot_src->data.ghash) {
- void *key = BLI_ghashIterator_getKey(&gh_iter);
- void *val = BLI_ghashIterator_getValue(&gh_iter);
- BLI_ghash_insert(slot_dst->data.ghash, key, val);
- }
- }
- else {
- slot_dst->data = slot_src->data;
- }
+void _bmo_slot_copy(BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS],
+ const char *slot_name_src,
+ BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS],
+ const char *slot_name_dst,
+ struct MemArena *arena_dst)
+{
+ BMOpSlot *slot_src = BMO_slot_get(slot_args_src, slot_name_src);
+ BMOpSlot *slot_dst = BMO_slot_get(slot_args_dst, slot_name_dst);
+
+ if (slot_src == slot_dst) {
+ return;
+ }
+
+ BLI_assert(slot_src->slot_type == slot_dst->slot_type);
+ if (slot_src->slot_type != slot_dst->slot_type) {
+ return;
+ }
+
+ if (slot_dst->slot_type == BMO_OP_SLOT_ELEMENT_BUF) {
+ /* do buffer copy */
+ slot_dst->data.buf = NULL;
+ slot_dst->len = slot_src->len;
+ if (slot_dst->len) {
+ /* check dest has all flags enabled that the source has */
+ const eBMOpSlotSubType_Elem src_elem_flag = (slot_src->slot_subtype.elem & BM_ALL_NOLOOP);
+ const eBMOpSlotSubType_Elem dst_elem_flag = (slot_dst->slot_subtype.elem & BM_ALL_NOLOOP);
+
+ if ((src_elem_flag | dst_elem_flag) == dst_elem_flag) {
+ /* pass */
+ }
+ else {
+ /* check types */
+ const uint tot = slot_src->len;
+ uint i;
+ uint out = 0;
+ BMElem **ele_src = (BMElem **)slot_src->data.buf;
+ for (i = 0; i < tot; i++, ele_src++) {
+ if ((*ele_src)->head.htype & dst_elem_flag) {
+ out++;
+ }
+ }
+ if (out != tot) {
+ slot_dst->len = out;
+ }
+ }
+
+ if (slot_dst->len) {
+ const int slot_alloc_size = BMO_OPSLOT_TYPEINFO[slot_dst->slot_type] * slot_dst->len;
+ slot_dst->data.buf = BLI_memarena_alloc(arena_dst, slot_alloc_size);
+ if (slot_src->len == slot_dst->len) {
+ memcpy(slot_dst->data.buf, slot_src->data.buf, slot_alloc_size);
+ }
+ else {
+ /* only copy compatible elements */
+ const uint tot = slot_src->len;
+ uint i;
+ BMElem **ele_src = (BMElem **)slot_src->data.buf;
+ BMElem **ele_dst = (BMElem **)slot_dst->data.buf;
+ for (i = 0; i < tot; i++, ele_src++) {
+ if ((*ele_src)->head.htype & dst_elem_flag) {
+ *ele_dst = *ele_src;
+ ele_dst++;
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (slot_dst->slot_type == BMO_OP_SLOT_MAPPING) {
+ GHashIterator gh_iter;
+ GHASH_ITER (gh_iter, slot_src->data.ghash) {
+ void *key = BLI_ghashIterator_getKey(&gh_iter);
+ void *val = BLI_ghashIterator_getValue(&gh_iter);
+ BLI_ghash_insert(slot_dst->data.ghash, key, val);
+ }
+ }
+ else {
+ slot_dst->data = slot_src->data;
+ }
}
/*
@@ -372,185 +375,194 @@ void _bmo_slot_copy(
void BMO_slot_float_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float f)
{
- BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
- BLI_assert(slot->slot_type == BMO_OP_SLOT_FLT);
- if (!(slot->slot_type == BMO_OP_SLOT_FLT)) {
- return;
- }
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
+ BLI_assert(slot->slot_type == BMO_OP_SLOT_FLT);
+ if (!(slot->slot_type == BMO_OP_SLOT_FLT)) {
+ return;
+ }
- slot->data.f = f;
+ slot->data.f = f;
}
void BMO_slot_int_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int i)
{
- BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
- BLI_assert(slot->slot_type == BMO_OP_SLOT_INT);
- if (!(slot->slot_type == BMO_OP_SLOT_INT)) {
- return;
- }
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
+ BLI_assert(slot->slot_type == BMO_OP_SLOT_INT);
+ if (!(slot->slot_type == BMO_OP_SLOT_INT)) {
+ return;
+ }
- slot->data.i = i;
+ slot->data.i = i;
}
void BMO_slot_bool_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const bool i)
{
- BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
- BLI_assert(slot->slot_type == BMO_OP_SLOT_BOOL);
- if (!(slot->slot_type == BMO_OP_SLOT_BOOL)) {
- return;
- }
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
+ BLI_assert(slot->slot_type == BMO_OP_SLOT_BOOL);
+ if (!(slot->slot_type == BMO_OP_SLOT_BOOL)) {
+ return;
+ }
- slot->data.i = i;
+ slot->data.i = i;
}
/* only supports square mats */
-void BMO_slot_mat_set(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float *mat, int size)
-{
- BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
- BLI_assert(slot->slot_type == BMO_OP_SLOT_MAT);
- if (!(slot->slot_type == BMO_OP_SLOT_MAT)) {
- return;
- }
-
- slot->len = 4;
- slot->data.p = BLI_memarena_alloc(op->arena, sizeof(float) * 4 * 4);
-
- if (size == 4) {
- copy_m4_m4(slot->data.p, (float (*)[4])mat);
- }
- else if (size == 3) {
- copy_m4_m3(slot->data.p, (float (*)[3])mat);
- }
- else {
- fprintf(stderr, "%s: invalid size argument %d (bmesh internal error)\n", __func__, size);
-
- zero_m4(slot->data.p);
- }
-}
-
-void BMO_slot_mat4_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_mat[4][4])
-{
- BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
- BLI_assert(slot->slot_type == BMO_OP_SLOT_MAT);
- if (!(slot->slot_type == BMO_OP_SLOT_MAT)) {
- return;
- }
-
- if (slot->data.p) {
- copy_m4_m4(r_mat, BMO_SLOT_AS_MATRIX(slot));
- }
- else {
- unit_m4(r_mat);
- }
-}
-
-void BMO_slot_mat3_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_mat[3][3])
-{
- BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
- BLI_assert(slot->slot_type == BMO_OP_SLOT_MAT);
- if (!(slot->slot_type == BMO_OP_SLOT_MAT)) {
- return;
- }
-
- if (slot->data.p) {
- copy_m3_m4(r_mat, BMO_SLOT_AS_MATRIX(slot));
- }
- else {
- unit_m3(r_mat);
- }
+void BMO_slot_mat_set(BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ const float *mat,
+ int size)
+{
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
+ BLI_assert(slot->slot_type == BMO_OP_SLOT_MAT);
+ if (!(slot->slot_type == BMO_OP_SLOT_MAT)) {
+ return;
+ }
+
+ slot->len = 4;
+ slot->data.p = BLI_memarena_alloc(op->arena, sizeof(float) * 4 * 4);
+
+ if (size == 4) {
+ copy_m4_m4(slot->data.p, (float(*)[4])mat);
+ }
+ else if (size == 3) {
+ copy_m4_m3(slot->data.p, (float(*)[3])mat);
+ }
+ else {
+ fprintf(stderr, "%s: invalid size argument %d (bmesh internal error)\n", __func__, size);
+
+ zero_m4(slot->data.p);
+ }
+}
+
+void BMO_slot_mat4_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ float r_mat[4][4])
+{
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
+ BLI_assert(slot->slot_type == BMO_OP_SLOT_MAT);
+ if (!(slot->slot_type == BMO_OP_SLOT_MAT)) {
+ return;
+ }
+
+ if (slot->data.p) {
+ copy_m4_m4(r_mat, BMO_SLOT_AS_MATRIX(slot));
+ }
+ else {
+ unit_m4(r_mat);
+ }
+}
+
+void BMO_slot_mat3_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ float r_mat[3][3])
+{
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
+ BLI_assert(slot->slot_type == BMO_OP_SLOT_MAT);
+ if (!(slot->slot_type == BMO_OP_SLOT_MAT)) {
+ return;
+ }
+
+ if (slot->data.p) {
+ copy_m3_m4(r_mat, BMO_SLOT_AS_MATRIX(slot));
+ }
+ else {
+ unit_m3(r_mat);
+ }
}
void BMO_slot_ptr_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, void *p)
{
- BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
- BLI_assert(slot->slot_type == BMO_OP_SLOT_PTR);
- if (!(slot->slot_type == BMO_OP_SLOT_PTR)) {
- return;
- }
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
+ BLI_assert(slot->slot_type == BMO_OP_SLOT_PTR);
+ if (!(slot->slot_type == BMO_OP_SLOT_PTR)) {
+ return;
+ }
- slot->data.p = p;
+ slot->data.p = p;
}
-void BMO_slot_vec_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float vec[3])
+void BMO_slot_vec_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ const float vec[3])
{
- BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
- BLI_assert(slot->slot_type == BMO_OP_SLOT_VEC);
- if (!(slot->slot_type == BMO_OP_SLOT_VEC)) {
- return;
- }
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
+ BLI_assert(slot->slot_type == BMO_OP_SLOT_VEC);
+ if (!(slot->slot_type == BMO_OP_SLOT_VEC)) {
+ return;
+ }
- copy_v3_v3(slot->data.vec, vec);
+ copy_v3_v3(slot->data.vec, vec);
}
-
float BMO_slot_float_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
{
- BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
- BLI_assert(slot->slot_type == BMO_OP_SLOT_FLT);
- if (!(slot->slot_type == BMO_OP_SLOT_FLT)) {
- return 0.0f;
- }
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
+ BLI_assert(slot->slot_type == BMO_OP_SLOT_FLT);
+ if (!(slot->slot_type == BMO_OP_SLOT_FLT)) {
+ return 0.0f;
+ }
- return slot->data.f;
+ return slot->data.f;
}
int BMO_slot_int_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
{
- BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
- BLI_assert(slot->slot_type == BMO_OP_SLOT_INT);
- if (!(slot->slot_type == BMO_OP_SLOT_INT)) {
- return 0;
- }
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
+ BLI_assert(slot->slot_type == BMO_OP_SLOT_INT);
+ if (!(slot->slot_type == BMO_OP_SLOT_INT)) {
+ return 0;
+ }
- return slot->data.i;
+ return slot->data.i;
}
bool BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
{
- BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
- BLI_assert(slot->slot_type == BMO_OP_SLOT_BOOL);
- if (!(slot->slot_type == BMO_OP_SLOT_BOOL)) {
- return 0;
- }
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
+ BLI_assert(slot->slot_type == BMO_OP_SLOT_BOOL);
+ if (!(slot->slot_type == BMO_OP_SLOT_BOOL)) {
+ return 0;
+ }
- return slot->data.i;
+ return slot->data.i;
}
/* if you want a copy of the elem buffer */
void *BMO_slot_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, int *len)
{
- BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
- void **ret;
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
+ void **ret;
- /* could add support for mapping type */
- BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
+ /* could add support for mapping type */
+ BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
- ret = MEM_mallocN(sizeof(void *) * slot->len, __func__);
- memcpy(ret, slot->data.buf, sizeof(void *) * slot->len);
- *len = slot->len;
- return ret;
+ ret = MEM_mallocN(sizeof(void *) * slot->len, __func__);
+ memcpy(ret, slot->data.buf, sizeof(void *) * slot->len);
+ *len = slot->len;
+ return ret;
}
void *BMO_slot_ptr_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
{
- BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
- BLI_assert(slot->slot_type == BMO_OP_SLOT_PTR);
- if (!(slot->slot_type == BMO_OP_SLOT_PTR)) {
- return NULL;
- }
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
+ BLI_assert(slot->slot_type == BMO_OP_SLOT_PTR);
+ if (!(slot->slot_type == BMO_OP_SLOT_PTR)) {
+ return NULL;
+ }
- return slot->data.p;
+ return slot->data.p;
}
void BMO_slot_vec_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_vec[3])
{
- BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
- BLI_assert(slot->slot_type == BMO_OP_SLOT_VEC);
- if (!(slot->slot_type == BMO_OP_SLOT_VEC)) {
- return;
- }
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
+ BLI_assert(slot->slot_type == BMO_OP_SLOT_VEC);
+ if (!(slot->slot_type == BMO_OP_SLOT_VEC)) {
+ return;
+ }
- copy_v3_v3(r_vec, slot->data.vec);
+ copy_v3_v3(r_vec, slot->data.vec);
}
/*
@@ -560,234 +572,242 @@ void BMO_slot_vec_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_nam
* specific flag enabled (or disabled if test_for_enabled is false).
*/
-static int bmo_mesh_flag_count(
- BMesh *bm, const char htype, const short oflag,
- const bool test_for_enabled)
-{
- int count_vert = 0, count_edge = 0, count_face = 0;
-
- if (htype & BM_VERT) {
- BMIter iter;
- BMVert *ele;
- BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
- if (BMO_vert_flag_test_bool(bm, ele, oflag) == test_for_enabled) {
- count_vert++;
- }
- }
- }
- if (htype & BM_EDGE) {
- BMIter iter;
- BMEdge *ele;
- BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
- if (BMO_edge_flag_test_bool(bm, ele, oflag) == test_for_enabled) {
- count_edge++;
- }
- }
- }
- if (htype & BM_FACE) {
- BMIter iter;
- BMFace *ele;
- BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
- if (BMO_face_flag_test_bool(bm, ele, oflag) == test_for_enabled) {
- count_face++;
- }
- }
- }
-
- return (count_vert + count_edge + count_face);
+static int bmo_mesh_flag_count(BMesh *bm,
+ const char htype,
+ const short oflag,
+ const bool test_for_enabled)
+{
+ int count_vert = 0, count_edge = 0, count_face = 0;
+
+ if (htype & BM_VERT) {
+ BMIter iter;
+ BMVert *ele;
+ BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BMO_vert_flag_test_bool(bm, ele, oflag) == test_for_enabled) {
+ count_vert++;
+ }
+ }
+ }
+ if (htype & BM_EDGE) {
+ BMIter iter;
+ BMEdge *ele;
+ BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BMO_edge_flag_test_bool(bm, ele, oflag) == test_for_enabled) {
+ count_edge++;
+ }
+ }
+ }
+ if (htype & BM_FACE) {
+ BMIter iter;
+ BMFace *ele;
+ BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
+ if (BMO_face_flag_test_bool(bm, ele, oflag) == test_for_enabled) {
+ count_face++;
+ }
+ }
+ }
+
+ return (count_vert + count_edge + count_face);
}
-
int BMO_mesh_enabled_flag_count(BMesh *bm, const char htype, const short oflag)
{
- return bmo_mesh_flag_count(bm, htype, oflag, true);
+ return bmo_mesh_flag_count(bm, htype, oflag, true);
}
int BMO_mesh_disabled_flag_count(BMesh *bm, const char htype, const short oflag)
{
- return bmo_mesh_flag_count(bm, htype, oflag, false);
-}
-
-void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *UNUSED(op), const char htype, const short oflag)
-{
- if (htype & BM_VERT) {
- BMIter iter;
- BMVert *ele;
- BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
- BMO_vert_flag_disable(bm, ele, oflag);
- }
- }
- if (htype & BM_EDGE) {
- BMIter iter;
- BMEdge *ele;
- BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
- BMO_edge_flag_disable(bm, ele, oflag);
- }
- }
- if (htype & BM_FACE) {
- BMIter iter;
- BMFace *ele;
- BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
- BMO_face_flag_disable(bm, ele, oflag);
- }
- }
-}
-
-void BMO_mesh_selected_remap(
- BMesh *bm,
- BMOpSlot *slot_vert_map,
- BMOpSlot *slot_edge_map,
- BMOpSlot *slot_face_map,
- const bool check_select)
-{
- if (bm->selected.first) {
- BMEditSelection *ese, *ese_next;
- BMOpSlot *slot_elem_map;
-
- for (ese = bm->selected.first; ese; ese = ese_next) {
- ese_next = ese->next;
-
- switch (ese->htype) {
- case BM_VERT: slot_elem_map = slot_vert_map; break;
- case BM_EDGE: slot_elem_map = slot_edge_map; break;
- default: slot_elem_map = slot_face_map; break;
- }
-
- ese->ele = BMO_slot_map_elem_get(slot_elem_map, ese->ele);
-
- if (UNLIKELY((ese->ele == NULL) ||
- (check_select && (BM_elem_flag_test(ese->ele, BM_ELEM_SELECT) == false))))
- {
- BLI_remlink(&bm->selected, ese);
- MEM_freeN(ese);
- }
- }
- }
-
- if (bm->act_face) {
- BMFace *f = BMO_slot_map_elem_get(slot_face_map, bm->act_face);
- if (f) {
- bm->act_face = f;
- }
- }
+ return bmo_mesh_flag_count(bm, htype, oflag, false);
+}
+
+void BMO_mesh_flag_disable_all(BMesh *bm,
+ BMOperator *UNUSED(op),
+ const char htype,
+ const short oflag)
+{
+ if (htype & BM_VERT) {
+ BMIter iter;
+ BMVert *ele;
+ BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
+ BMO_vert_flag_disable(bm, ele, oflag);
+ }
+ }
+ if (htype & BM_EDGE) {
+ BMIter iter;
+ BMEdge *ele;
+ BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
+ BMO_edge_flag_disable(bm, ele, oflag);
+ }
+ }
+ if (htype & BM_FACE) {
+ BMIter iter;
+ BMFace *ele;
+ BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
+ BMO_face_flag_disable(bm, ele, oflag);
+ }
+ }
+}
+
+void BMO_mesh_selected_remap(BMesh *bm,
+ BMOpSlot *slot_vert_map,
+ BMOpSlot *slot_edge_map,
+ BMOpSlot *slot_face_map,
+ const bool check_select)
+{
+ if (bm->selected.first) {
+ BMEditSelection *ese, *ese_next;
+ BMOpSlot *slot_elem_map;
+
+ for (ese = bm->selected.first; ese; ese = ese_next) {
+ ese_next = ese->next;
+
+ switch (ese->htype) {
+ case BM_VERT:
+ slot_elem_map = slot_vert_map;
+ break;
+ case BM_EDGE:
+ slot_elem_map = slot_edge_map;
+ break;
+ default:
+ slot_elem_map = slot_face_map;
+ break;
+ }
+
+ ese->ele = BMO_slot_map_elem_get(slot_elem_map, ese->ele);
+
+ if (UNLIKELY((ese->ele == NULL) ||
+ (check_select && (BM_elem_flag_test(ese->ele, BM_ELEM_SELECT) == false)))) {
+ BLI_remlink(&bm->selected, ese);
+ MEM_freeN(ese);
+ }
+ }
+ }
+
+ if (bm->act_face) {
+ BMFace *f = BMO_slot_map_elem_get(slot_face_map, bm->act_face);
+ if (f) {
+ bm->act_face = f;
+ }
+ }
}
-
int BMO_slot_buffer_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
{
- BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
- BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
+ BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
- /* check if its actually a buffer */
- if (slot->slot_type != BMO_OP_SLOT_ELEMENT_BUF) {
- return 0;
- }
+ /* check if its actually a buffer */
+ if (slot->slot_type != BMO_OP_SLOT_ELEMENT_BUF) {
+ return 0;
+ }
- return slot->len;
+ return slot->len;
}
int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
{
- BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
- BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING);
- return BLI_ghash_len(slot->data.ghash);
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
+ BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING);
+ return BLI_ghash_len(slot->data.ghash);
}
/* inserts a key/value mapping into a mapping slot. note that it copies the
* value, it doesn't store a reference to it. */
-void BMO_slot_map_insert(
- BMOperator *op, BMOpSlot *slot,
- const void *element, const void *data)
+void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot, const void *element, const void *data)
{
- (void) op; /* Ignored in release builds. */
+ (void)op; /* Ignored in release builds. */
- BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING);
- BMO_ASSERT_SLOT_IN_OP(slot, op);
+ BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING);
+ BMO_ASSERT_SLOT_IN_OP(slot, op);
- BLI_ghash_insert(slot->data.ghash, (void *)element, (void *)data);
+ BLI_ghash_insert(slot->data.ghash, (void *)element, (void *)data);
}
#if 0
void *bmo_slot_buffer_grow(BMesh *bm, BMOperator *op, int slot_code, int totadd)
{
- BMOpSlot *slot = &op->slots[slot_code];
- void *tmp;
- ssize_t allocsize;
+ BMOpSlot *slot = &op->slots[slot_code];
+ void *tmp;
+ ssize_t allocsize;
- BLI_assert(slot->slottype == BMO_OP_SLOT_ELEMENT_BUF);
+ BLI_assert(slot->slottype == BMO_OP_SLOT_ELEMENT_BUF);
- /* check if its actually a buffer */
- if (slot->slottype != BMO_OP_SLOT_ELEMENT_BUF)
- return NULL;
+ /* check if its actually a buffer */
+ if (slot->slottype != BMO_OP_SLOT_ELEMENT_BUF)
+ return NULL;
- if (slot->flag & BMOS_DYNAMIC_ARRAY) {
- if (slot->len >= slot->size) {
- slot->size = (slot->size + 1 + totadd) * 2;
+ if (slot->flag & BMOS_DYNAMIC_ARRAY) {
+ if (slot->len >= slot->size) {
+ slot->size = (slot->size + 1 + totadd) * 2;
- allocsize = BMO_OPSLOT_TYPEINFO[bmo_opdefines[op->type]->slot_types[slot_code].type] * slot->size;
+ allocsize = BMO_OPSLOT_TYPEINFO[bmo_opdefines[op->type]->slot_types[slot_code].type] * slot->size;
- tmp = slot->data.buf;
- slot->data.buf = MEM_callocN(allocsize, "opslot dynamic array");
- memcpy(slot->data.buf, tmp, allocsize);
- MEM_freeN(tmp);
- }
+ tmp = slot->data.buf;
+ slot->data.buf = MEM_callocN(allocsize, "opslot dynamic array");
+ memcpy(slot->data.buf, tmp, allocsize);
+ MEM_freeN(tmp);
+ }
- slot->len += totadd;
- }
- else {
- slot->flag |= BMOS_DYNAMIC_ARRAY;
- slot->len += totadd;
- slot->size = slot->len + 2;
+ slot->len += totadd;
+ }
+ else {
+ slot->flag |= BMOS_DYNAMIC_ARRAY;
+ slot->len += totadd;
+ slot->size = slot->len + 2;
- allocsize = BMO_OPSLOT_TYPEINFO[bmo_opdefines[op->type]->slot_types[slot_code].type] * slot->len;
+ allocsize = BMO_OPSLOT_TYPEINFO[bmo_opdefines[op->type]->slot_types[slot_code].type] * slot->len;
- tmp = slot->data.buf;
- slot->data.buf = MEM_callocN(allocsize, "opslot dynamic array");
- memcpy(slot->data.buf, tmp, allocsize);
- }
+ tmp = slot->data.buf;
+ slot->data.buf = MEM_callocN(allocsize, "opslot dynamic array");
+ memcpy(slot->data.buf, tmp, allocsize);
+ }
- return slot->data.buf;
+ return slot->data.buf;
}
#endif
-void BMO_slot_map_to_flag(
- BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const short oflag)
+void BMO_slot_map_to_flag(BMesh *bm,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ const char htype,
+ const short oflag)
{
- GHashIterator gh_iter;
- BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
- BMElemF *ele_f;
-
- BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING);
+ GHashIterator gh_iter;
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
+ BMElemF *ele_f;
+ BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING);
- GHASH_ITER (gh_iter, slot->data.ghash) {
- ele_f = BLI_ghashIterator_getKey(&gh_iter);
- if (ele_f->head.htype & htype) {
- BMO_elem_flag_enable(bm, ele_f, oflag);
- }
- }
+ GHASH_ITER (gh_iter, slot->data.ghash) {
+ ele_f = BLI_ghashIterator_getKey(&gh_iter);
+ if (ele_f->head.htype & htype) {
+ BMO_elem_flag_enable(bm, ele_f, oflag);
+ }
+ }
}
-void *BMO_slot_buffer_alloc(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int len)
+void *BMO_slot_buffer_alloc(BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ const int len)
{
- BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
- /* check if its actually a buffer */
- if (slot->slot_type != BMO_OP_SLOT_ELEMENT_BUF) {
- return NULL;
- }
+ /* check if its actually a buffer */
+ if (slot->slot_type != BMO_OP_SLOT_ELEMENT_BUF) {
+ return NULL;
+ }
- slot->len = len;
- if (len) {
- slot->data.buf = BLI_memarena_alloc(op->arena, BMO_OPSLOT_TYPEINFO[slot->slot_type] * len);
- }
- else {
- slot->data.buf = NULL;
- }
+ slot->len = len;
+ if (len) {
+ slot->data.buf = BLI_memarena_alloc(op->arena, BMO_OPSLOT_TYPEINFO[slot->slot_type] * len);
+ }
+ else {
+ slot->data.buf = NULL;
+ }
- return slot->data.buf;
+ return slot->data.buf;
}
/**
@@ -795,49 +815,57 @@ void *BMO_slot_buffer_alloc(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS]
*
* Copies all elements of a certain type into an operator slot.
*/
-void BMO_slot_buffer_from_all(
- BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
- const char *slot_name, const char htype)
-{
- BMOpSlot *output = BMO_slot_get(slot_args, slot_name);
- int totelement = 0, i = 0;
-
- BLI_assert(output->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
- BLI_assert(((output->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
-
- if (htype & BM_VERT) { totelement += bm->totvert; }
- if (htype & BM_EDGE) { totelement += bm->totedge; }
- if (htype & BM_FACE) { totelement += bm->totface; }
-
- if (totelement) {
- BMIter iter;
- BMHeader *ele;
-
- BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement);
-
- /* TODO - collapse these loops into one */
-
- if (htype & BM_VERT) {
- BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
- output->data.buf[i] = ele;
- i++;
- }
- }
-
- if (htype & BM_EDGE) {
- BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
- output->data.buf[i] = ele;
- i++;
- }
- }
-
- if (htype & BM_FACE) {
- BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
- output->data.buf[i] = ele;
- i++;
- }
- }
- }
+void BMO_slot_buffer_from_all(BMesh *bm,
+ BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ const char htype)
+{
+ BMOpSlot *output = BMO_slot_get(slot_args, slot_name);
+ int totelement = 0, i = 0;
+
+ BLI_assert(output->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
+ BLI_assert(((output->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
+
+ if (htype & BM_VERT) {
+ totelement += bm->totvert;
+ }
+ if (htype & BM_EDGE) {
+ totelement += bm->totedge;
+ }
+ if (htype & BM_FACE) {
+ totelement += bm->totface;
+ }
+
+ if (totelement) {
+ BMIter iter;
+ BMHeader *ele;
+
+ BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement);
+
+ /* TODO - collapse these loops into one */
+
+ if (htype & BM_VERT) {
+ BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
+ output->data.buf[i] = ele;
+ i++;
+ }
+ }
+
+ if (htype & BM_EDGE) {
+ BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
+ output->data.buf[i] = ele;
+ i++;
+ }
+ }
+
+ if (htype & BM_FACE) {
+ BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
+ output->data.buf[i] = ele;
+ i++;
+ }
+ }
+ }
}
/**
@@ -846,159 +874,166 @@ void BMO_slot_buffer_from_all(
* Copies elements of a certain type, which have a certain header flag
* enabled/disabled into a slot for an operator.
*/
-static void bmo_slot_buffer_from_hflag(
- BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const char hflag,
- const bool test_for_enabled)
-{
- BMOpSlot *output = BMO_slot_get(slot_args, slot_name);
- int totelement = 0, i = 0;
- const bool respecthide = ((op->flag & BMO_FLAG_RESPECT_HIDE) != 0) && ((hflag & BM_ELEM_HIDDEN) == 0);
-
- BLI_assert(output->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
- BLI_assert(((output->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
- BLI_assert((output->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE) == 0);
-
- if (test_for_enabled) {
- totelement = BM_mesh_elem_hflag_count_enabled(bm, htype, hflag, respecthide);
- }
- else {
- totelement = BM_mesh_elem_hflag_count_disabled(bm, htype, hflag, respecthide);
- }
-
- if (totelement) {
- BMIter iter;
- BMElem *ele;
-
- BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement);
-
- /* TODO - collapse these loops into one */
-
- if (htype & BM_VERT) {
- BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
- if ((!respecthide || !BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) &&
- BM_elem_flag_test_bool(ele, hflag) == test_for_enabled)
- {
- output->data.buf[i] = ele;
- i++;
- }
- }
- }
-
- if (htype & BM_EDGE) {
- BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
- if ((!respecthide || !BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) &&
- BM_elem_flag_test_bool(ele, hflag) == test_for_enabled)
- {
- output->data.buf[i] = ele;
- i++;
- }
- }
- }
-
- if (htype & BM_FACE) {
- BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
- if ((!respecthide || !BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) &&
- BM_elem_flag_test_bool(ele, hflag) == test_for_enabled)
- {
- output->data.buf[i] = ele;
- i++;
- }
- }
- }
- }
- else {
- output->len = 0;
- }
-}
-
-void BMO_slot_buffer_from_enabled_hflag(
- BMesh *bm, BMOperator *op,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const char hflag)
-{
- bmo_slot_buffer_from_hflag(bm, op, slot_args, slot_name, htype, hflag, true);
-}
-
-void BMO_slot_buffer_from_disabled_hflag(
- BMesh *bm, BMOperator *op,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const char hflag)
-{
- bmo_slot_buffer_from_hflag(bm, op, slot_args, slot_name, htype, hflag, false);
+static void bmo_slot_buffer_from_hflag(BMesh *bm,
+ BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ const char htype,
+ const char hflag,
+ const bool test_for_enabled)
+{
+ BMOpSlot *output = BMO_slot_get(slot_args, slot_name);
+ int totelement = 0, i = 0;
+ const bool respecthide = ((op->flag & BMO_FLAG_RESPECT_HIDE) != 0) &&
+ ((hflag & BM_ELEM_HIDDEN) == 0);
+
+ BLI_assert(output->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
+ BLI_assert(((output->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
+ BLI_assert((output->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE) == 0);
+
+ if (test_for_enabled) {
+ totelement = BM_mesh_elem_hflag_count_enabled(bm, htype, hflag, respecthide);
+ }
+ else {
+ totelement = BM_mesh_elem_hflag_count_disabled(bm, htype, hflag, respecthide);
+ }
+
+ if (totelement) {
+ BMIter iter;
+ BMElem *ele;
+
+ BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement);
+
+ /* TODO - collapse these loops into one */
+
+ if (htype & BM_VERT) {
+ BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
+ if ((!respecthide || !BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) &&
+ BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) {
+ output->data.buf[i] = ele;
+ i++;
+ }
+ }
+ }
+
+ if (htype & BM_EDGE) {
+ BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
+ if ((!respecthide || !BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) &&
+ BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) {
+ output->data.buf[i] = ele;
+ i++;
+ }
+ }
+ }
+
+ if (htype & BM_FACE) {
+ BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
+ if ((!respecthide || !BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) &&
+ BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) {
+ output->data.buf[i] = ele;
+ i++;
+ }
+ }
+ }
+ }
+ else {
+ output->len = 0;
+ }
+}
+
+void BMO_slot_buffer_from_enabled_hflag(BMesh *bm,
+ BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ const char htype,
+ const char hflag)
+{
+ bmo_slot_buffer_from_hflag(bm, op, slot_args, slot_name, htype, hflag, true);
+}
+
+void BMO_slot_buffer_from_disabled_hflag(BMesh *bm,
+ BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ const char htype,
+ const char hflag)
+{
+ bmo_slot_buffer_from_hflag(bm, op, slot_args, slot_name, htype, hflag, false);
}
void BMO_slot_buffer_from_single(BMOperator *op, BMOpSlot *slot, BMHeader *ele)
{
- BMO_ASSERT_SLOT_IN_OP(slot, op);
- BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
- BLI_assert(slot->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE);
- BLI_assert(slot->len == 0 || slot->len == 1);
+ BMO_ASSERT_SLOT_IN_OP(slot, op);
+ BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
+ BLI_assert(slot->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE);
+ BLI_assert(slot->len == 0 || slot->len == 1);
- BLI_assert(slot->slot_subtype.elem & ele->htype);
+ BLI_assert(slot->slot_subtype.elem & ele->htype);
- slot->data.buf = BLI_memarena_alloc(op->arena, sizeof(void *) * 4); /* XXX, why 'x4' ? */
- slot->len = 1;
- *slot->data.buf = ele;
+ slot->data.buf = BLI_memarena_alloc(op->arena, sizeof(void *) * 4); /* XXX, why 'x4' ? */
+ slot->len = 1;
+ *slot->data.buf = ele;
}
-void BMO_slot_buffer_from_array(BMOperator *op, BMOpSlot *slot, BMHeader **ele_buffer, int ele_buffer_len)
+void BMO_slot_buffer_from_array(BMOperator *op,
+ BMOpSlot *slot,
+ BMHeader **ele_buffer,
+ int ele_buffer_len)
{
- BMO_ASSERT_SLOT_IN_OP(slot, op);
- BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
- BLI_assert(slot->len == 0 || slot->len == ele_buffer_len);
+ BMO_ASSERT_SLOT_IN_OP(slot, op);
+ BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
+ BLI_assert(slot->len == 0 || slot->len == ele_buffer_len);
- if (slot->data.buf == NULL) {
- slot->data.buf = BLI_memarena_alloc(op->arena, sizeof(*slot->data.buf) * ele_buffer_len);
- }
+ if (slot->data.buf == NULL) {
+ slot->data.buf = BLI_memarena_alloc(op->arena, sizeof(*slot->data.buf) * ele_buffer_len);
+ }
- slot->len = ele_buffer_len;
- memcpy(slot->data.buf, ele_buffer, ele_buffer_len * sizeof(*slot->data.buf));
+ slot->len = ele_buffer_len;
+ memcpy(slot->data.buf, ele_buffer, ele_buffer_len * sizeof(*slot->data.buf));
}
-
void *BMO_slot_buffer_get_single(BMOpSlot *slot)
{
- BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
- BLI_assert(slot->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE);
- BLI_assert(slot->len == 0 || slot->len == 1);
+ BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
+ BLI_assert(slot->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE);
+ BLI_assert(slot->len == 0 || slot->len == 1);
- return slot->len ? (BMHeader *)slot->data.buf[0] : NULL;
+ return slot->len ? (BMHeader *)slot->data.buf[0] : NULL;
}
/**
* Copies the values from another slot to the end of the output slot.
*/
-void _bmo_slot_buffer_append(
- BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst,
- BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src,
- struct MemArena *arena_dst)
-{
- BMOpSlot *slot_dst = BMO_slot_get(slot_args_dst, slot_name_dst);
- BMOpSlot *slot_src = BMO_slot_get(slot_args_src, slot_name_src);
-
- BLI_assert(slot_dst->slot_type == BMO_OP_SLOT_ELEMENT_BUF &&
- slot_src->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
-
- if (slot_dst->len == 0) {
- /* output slot is empty, copy rather than append */
- _bmo_slot_copy(slot_args_src, slot_name_src,
- slot_args_dst, slot_name_dst,
- arena_dst);
- }
- else if (slot_src->len != 0) {
- int elem_size = BMO_OPSLOT_TYPEINFO[slot_dst->slot_type];
- int alloc_size = elem_size * (slot_dst->len + slot_src->len);
- /* allocate new buffer */
- void *buf = BLI_memarena_alloc(arena_dst, alloc_size);
-
- /* copy slot data */
- memcpy(buf, slot_dst->data.buf, elem_size * slot_dst->len);
- memcpy(((char *)buf) + elem_size * slot_dst->len, slot_src->data.buf, elem_size * slot_src->len);
-
- slot_dst->data.buf = buf;
- slot_dst->len += slot_src->len;
- }
+void _bmo_slot_buffer_append(BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS],
+ const char *slot_name_dst,
+ BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS],
+ const char *slot_name_src,
+ struct MemArena *arena_dst)
+{
+ BMOpSlot *slot_dst = BMO_slot_get(slot_args_dst, slot_name_dst);
+ BMOpSlot *slot_src = BMO_slot_get(slot_args_src, slot_name_src);
+
+ BLI_assert(slot_dst->slot_type == BMO_OP_SLOT_ELEMENT_BUF &&
+ slot_src->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
+
+ if (slot_dst->len == 0) {
+ /* output slot is empty, copy rather than append */
+ _bmo_slot_copy(slot_args_src, slot_name_src, slot_args_dst, slot_name_dst, arena_dst);
+ }
+ else if (slot_src->len != 0) {
+ int elem_size = BMO_OPSLOT_TYPEINFO[slot_dst->slot_type];
+ int alloc_size = elem_size * (slot_dst->len + slot_src->len);
+ /* allocate new buffer */
+ void *buf = BLI_memarena_alloc(arena_dst, alloc_size);
+
+ /* copy slot data */
+ memcpy(buf, slot_dst->data.buf, elem_size * slot_dst->len);
+ memcpy(
+ ((char *)buf) + elem_size * slot_dst->len, slot_src->data.buf, elem_size * slot_src->len);
+
+ slot_dst->data.buf = buf;
+ slot_dst->len += slot_src->len;
+ }
}
/**
@@ -1007,85 +1042,91 @@ void _bmo_slot_buffer_append(
* Copies elements of a certain type, which have a certain flag set
* into an output slot for an operator.
*/
-static void bmo_slot_buffer_from_flag(
- BMesh *bm, BMOperator *op,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const short oflag,
- const bool test_for_enabled)
-{
- BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
- int totelement, i = 0;
-
- BLI_assert(op->slots_in == slot_args || op->slots_out == slot_args);
-
- BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
- BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
- BLI_assert((slot->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE) == 0);
-
- if (test_for_enabled) {
- totelement = BMO_mesh_enabled_flag_count(bm, htype, oflag);
- }
- else {
- totelement = BMO_mesh_disabled_flag_count(bm, htype, oflag);
- }
-
- if (totelement) {
- BMIter iter;
- BMHeader *ele;
- BMHeader **ele_array;
-
- BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement);
-
- ele_array = (BMHeader **)slot->data.buf;
-
- /* TODO - collapse these loops into one */
-
- if (htype & BM_VERT) {
- BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
- if (BMO_vert_flag_test_bool(bm, (BMVert *)ele, oflag) == test_for_enabled) {
- ele_array[i] = ele;
- i++;
- }
- }
- }
-
- if (htype & BM_EDGE) {
- BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
- if (BMO_edge_flag_test_bool(bm, (BMEdge *)ele, oflag) == test_for_enabled) {
- ele_array[i] = ele;
- i++;
- }
- }
- }
-
- if (htype & BM_FACE) {
- BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
- if (BMO_face_flag_test_bool(bm, (BMFace *)ele, oflag) == test_for_enabled) {
- ele_array[i] = ele;
- i++;
- }
- }
- }
- }
- else {
- slot->len = 0;
- }
-}
-
-void BMO_slot_buffer_from_enabled_flag(
- BMesh *bm, BMOperator *op,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const short oflag)
-{
- bmo_slot_buffer_from_flag(bm, op, slot_args, slot_name, htype, oflag, true);
-}
-
-void BMO_slot_buffer_from_disabled_flag(
- BMesh *bm, BMOperator *op,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const short oflag)
-{
- bmo_slot_buffer_from_flag(bm, op, slot_args, slot_name, htype, oflag, false);
+static void bmo_slot_buffer_from_flag(BMesh *bm,
+ BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ const char htype,
+ const short oflag,
+ const bool test_for_enabled)
+{
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
+ int totelement, i = 0;
+
+ BLI_assert(op->slots_in == slot_args || op->slots_out == slot_args);
+
+ BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
+ BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
+ BLI_assert((slot->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE) == 0);
+
+ if (test_for_enabled) {
+ totelement = BMO_mesh_enabled_flag_count(bm, htype, oflag);
+ }
+ else {
+ totelement = BMO_mesh_disabled_flag_count(bm, htype, oflag);
+ }
+
+ if (totelement) {
+ BMIter iter;
+ BMHeader *ele;
+ BMHeader **ele_array;
+
+ BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement);
+
+ ele_array = (BMHeader **)slot->data.buf;
+
+ /* TODO - collapse these loops into one */
+
+ if (htype & BM_VERT) {
+ BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BMO_vert_flag_test_bool(bm, (BMVert *)ele, oflag) == test_for_enabled) {
+ ele_array[i] = ele;
+ i++;
+ }
+ }
+ }
+
+ if (htype & BM_EDGE) {
+ BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BMO_edge_flag_test_bool(bm, (BMEdge *)ele, oflag) == test_for_enabled) {
+ ele_array[i] = ele;
+ i++;
+ }
+ }
+ }
+
+ if (htype & BM_FACE) {
+ BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
+ if (BMO_face_flag_test_bool(bm, (BMFace *)ele, oflag) == test_for_enabled) {
+ ele_array[i] = ele;
+ i++;
+ }
+ }
+ }
+ }
+ else {
+ slot->len = 0;
+ }
+}
+
+void BMO_slot_buffer_from_enabled_flag(BMesh *bm,
+ BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ const char htype,
+ const short oflag)
+{
+ bmo_slot_buffer_from_flag(bm, op, slot_args, slot_name, htype, oflag, true);
+}
+
+void BMO_slot_buffer_from_disabled_flag(BMesh *bm,
+ BMOperator *op,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ const char htype,
+ const short oflag)
+{
+ bmo_slot_buffer_from_flag(bm, op, slot_args, slot_name, htype, oflag, false);
}
/**
@@ -1094,36 +1135,38 @@ void BMO_slot_buffer_from_disabled_flag(
* Header Flags elements in a slots buffer, automatically
* using the selection API where appropriate.
*/
-void BMO_slot_buffer_hflag_enable(
- BMesh *bm,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const char hflag, const bool do_flush)
+void BMO_slot_buffer_hflag_enable(BMesh *bm,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ const char htype,
+ const char hflag,
+ const bool do_flush)
{
- BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
- BMElem **data = (BMElem **)slot->data.buf;
- int i;
- const bool do_flush_select = (do_flush && (hflag & BM_ELEM_SELECT));
- const bool do_flush_hide = (do_flush && (hflag & BM_ELEM_HIDDEN));
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
+ BMElem **data = (BMElem **)slot->data.buf;
+ int i;
+ const bool do_flush_select = (do_flush && (hflag & BM_ELEM_SELECT));
+ const bool do_flush_hide = (do_flush && (hflag & BM_ELEM_HIDDEN));
- BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
- BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
- BLI_assert((slot->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE) == 0);
+ BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
+ BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
+ BLI_assert((slot->slot_subtype.elem & BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE) == 0);
- for (i = 0; i < slot->len; i++, data++) {
- if (!(htype & (*data)->head.htype)) {
- continue;
- }
+ for (i = 0; i < slot->len; i++, data++) {
+ if (!(htype & (*data)->head.htype)) {
+ continue;
+ }
- if (do_flush_select) {
- BM_elem_select_set(bm, *data, true);
- }
+ if (do_flush_select) {
+ BM_elem_select_set(bm, *data, true);
+ }
- if (do_flush_hide) {
- BM_elem_hide_set(bm, *data, false);
- }
+ if (do_flush_hide) {
+ BM_elem_hide_set(bm, *data, false);
+ }
- BM_elem_flag_enable(*data, hflag);
- }
+ BM_elem_flag_enable(*data, hflag);
+ }
}
/**
@@ -1132,35 +1175,37 @@ void BMO_slot_buffer_hflag_enable(
* Removes flags from elements in a slots buffer, automatically
* using the selection API where appropriate.
*/
-void BMO_slot_buffer_hflag_disable(
- BMesh *bm,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const char hflag, const bool do_flush)
+void BMO_slot_buffer_hflag_disable(BMesh *bm,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ const char htype,
+ const char hflag,
+ const bool do_flush)
{
- BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
- BMElem **data = (BMElem **)slot->data.buf;
- int i;
- const bool do_flush_select = (do_flush && (hflag & BM_ELEM_SELECT));
- const bool do_flush_hide = (do_flush && (hflag & BM_ELEM_HIDDEN));
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
+ BMElem **data = (BMElem **)slot->data.buf;
+ int i;
+ const bool do_flush_select = (do_flush && (hflag & BM_ELEM_SELECT));
+ const bool do_flush_hide = (do_flush && (hflag & BM_ELEM_HIDDEN));
- BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
- BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
+ BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
+ BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
- for (i = 0; i < slot->len; i++, data++) {
- if (!(htype & (*data)->head.htype)) {
- continue;
- }
+ for (i = 0; i < slot->len; i++, data++) {
+ if (!(htype & (*data)->head.htype)) {
+ continue;
+ }
- if (do_flush_select) {
- BM_elem_select_set(bm, *data, false);
- }
+ if (do_flush_select) {
+ BM_elem_select_set(bm, *data, false);
+ }
- if (do_flush_hide) {
- BM_elem_hide_set(bm, *data, false);
- }
+ if (do_flush_hide) {
+ BM_elem_hide_set(bm, *data, false);
+ }
- BM_elem_flag_disable(*data, hflag);
- }
+ BM_elem_flag_disable(*data, hflag);
+ }
}
/**
@@ -1168,25 +1213,26 @@ void BMO_slot_buffer_hflag_disable(
*
* Flags elements in a slots buffer
*/
-void BMO_slot_buffer_flag_enable(
- BMesh *bm,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const short oflag)
+void BMO_slot_buffer_flag_enable(BMesh *bm,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ const char htype,
+ const short oflag)
{
- BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
- BMHeader **data = slot->data.p;
- int i;
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
+ BMHeader **data = slot->data.p;
+ int i;
- BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
- BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
+ BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
+ BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
- for (i = 0; i < slot->len; i++) {
- if (!(htype & data[i]->htype)) {
- continue;
- }
+ for (i = 0; i < slot->len; i++) {
+ if (!(htype & data[i]->htype)) {
+ continue;
+ }
- BMO_elem_flag_enable(bm, (BMElemF *)data[i], oflag);
- }
+ BMO_elem_flag_enable(bm, (BMElemF *)data[i], oflag);
+ }
}
/**
@@ -1194,28 +1240,28 @@ void BMO_slot_buffer_flag_enable(
*
* Removes flags from elements in a slots buffer
*/
-void BMO_slot_buffer_flag_disable(
- BMesh *bm,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char htype, const short oflag)
+void BMO_slot_buffer_flag_disable(BMesh *bm,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ const char htype,
+ const short oflag)
{
- BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
- BMHeader **data = (BMHeader **)slot->data.buf;
- int i;
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
+ BMHeader **data = (BMHeader **)slot->data.buf;
+ int i;
- BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
- BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
+ BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF);
+ BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype);
- for (i = 0; i < slot->len; i++) {
- if (!(htype & data[i]->htype)) {
- continue;
- }
+ for (i = 0; i < slot->len; i++) {
+ if (!(htype & data[i]->htype)) {
+ continue;
+ }
- BMO_elem_flag_disable(bm, (BMElemF *)data[i], oflag);
- }
+ BMO_elem_flag_disable(bm, (BMElemF *)data[i], oflag);
+ }
}
-
/**
* \brief ALLOC/FREE FLAG LAYER
*
@@ -1231,172 +1277,175 @@ void BMO_slot_buffer_flag_disable(
*/
static void bmo_flag_layer_alloc(BMesh *bm)
{
- /* set the index values since we are looping over all data anyway,
- * may save time later on */
-
- BLI_mempool *voldpool = bm->vtoolflagpool; /* old flag pool */
- BLI_mempool *eoldpool = bm->etoolflagpool; /* old flag pool */
- BLI_mempool *foldpool = bm->ftoolflagpool; /* old flag pool */
-
- /* store memcpy size for reuse */
- const size_t old_totflags_size = (bm->totflags * sizeof(BMFlagLayer));
-
- bm->totflags++;
-
- bm->vtoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer) * bm->totflags, bm->totvert, 512, BLI_MEMPOOL_NOP);
- bm->etoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer) * bm->totflags, bm->totedge, 512, BLI_MEMPOOL_NOP);
- bm->ftoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer) * bm->totflags, bm->totface, 512, BLI_MEMPOOL_NOP);
-
- /* now go through and memcpy all the flags. Loops don't get a flag layer at this time.. */
- BMIter iter;
- int i;
-
- BMVert_OFlag *v_oflag;
- BLI_mempool *newpool = bm->vtoolflagpool;
- BM_ITER_MESH_INDEX (v_oflag, &iter, bm, BM_VERTS_OF_MESH, i) {
- void *oldflags = v_oflag->oflags;
- v_oflag->oflags = BLI_mempool_calloc(newpool);
- memcpy(v_oflag->oflags, oldflags, old_totflags_size);
- BM_elem_index_set(&v_oflag->base, i); /* set_inline */
- BM_ELEM_API_FLAG_CLEAR((BMElemF *)v_oflag);
- }
-
- BMEdge_OFlag *e_oflag;
- newpool = bm->etoolflagpool;
- BM_ITER_MESH_INDEX (e_oflag, &iter, bm, BM_EDGES_OF_MESH, i) {
- void *oldflags = e_oflag->oflags;
- e_oflag->oflags = BLI_mempool_calloc(newpool);
- memcpy(e_oflag->oflags, oldflags, old_totflags_size);
- BM_elem_index_set(&e_oflag->base, i); /* set_inline */
- BM_ELEM_API_FLAG_CLEAR((BMElemF *)e_oflag);
- }
-
- BMFace_OFlag *f_oflag;
- newpool = bm->ftoolflagpool;
- BM_ITER_MESH_INDEX (f_oflag, &iter, bm, BM_FACES_OF_MESH, i) {
- void *oldflags = f_oflag->oflags;
- f_oflag->oflags = BLI_mempool_calloc(newpool);
- memcpy(f_oflag->oflags, oldflags, old_totflags_size);
- BM_elem_index_set(&f_oflag->base, i); /* set_inline */
- BM_ELEM_API_FLAG_CLEAR((BMElemF *)f_oflag);
- }
-
- BLI_mempool_destroy(voldpool);
- BLI_mempool_destroy(eoldpool);
- BLI_mempool_destroy(foldpool);
-
- bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE);
+ /* set the index values since we are looping over all data anyway,
+ * may save time later on */
+
+ BLI_mempool *voldpool = bm->vtoolflagpool; /* old flag pool */
+ BLI_mempool *eoldpool = bm->etoolflagpool; /* old flag pool */
+ BLI_mempool *foldpool = bm->ftoolflagpool; /* old flag pool */
+
+ /* store memcpy size for reuse */
+ const size_t old_totflags_size = (bm->totflags * sizeof(BMFlagLayer));
+
+ bm->totflags++;
+
+ bm->vtoolflagpool = BLI_mempool_create(
+ sizeof(BMFlagLayer) * bm->totflags, bm->totvert, 512, BLI_MEMPOOL_NOP);
+ bm->etoolflagpool = BLI_mempool_create(
+ sizeof(BMFlagLayer) * bm->totflags, bm->totedge, 512, BLI_MEMPOOL_NOP);
+ bm->ftoolflagpool = BLI_mempool_create(
+ sizeof(BMFlagLayer) * bm->totflags, bm->totface, 512, BLI_MEMPOOL_NOP);
+
+ /* now go through and memcpy all the flags. Loops don't get a flag layer at this time.. */
+ BMIter iter;
+ int i;
+
+ BMVert_OFlag *v_oflag;
+ BLI_mempool *newpool = bm->vtoolflagpool;
+ BM_ITER_MESH_INDEX (v_oflag, &iter, bm, BM_VERTS_OF_MESH, i) {
+ void *oldflags = v_oflag->oflags;
+ v_oflag->oflags = BLI_mempool_calloc(newpool);
+ memcpy(v_oflag->oflags, oldflags, old_totflags_size);
+ BM_elem_index_set(&v_oflag->base, i); /* set_inline */
+ BM_ELEM_API_FLAG_CLEAR((BMElemF *)v_oflag);
+ }
+
+ BMEdge_OFlag *e_oflag;
+ newpool = bm->etoolflagpool;
+ BM_ITER_MESH_INDEX (e_oflag, &iter, bm, BM_EDGES_OF_MESH, i) {
+ void *oldflags = e_oflag->oflags;
+ e_oflag->oflags = BLI_mempool_calloc(newpool);
+ memcpy(e_oflag->oflags, oldflags, old_totflags_size);
+ BM_elem_index_set(&e_oflag->base, i); /* set_inline */
+ BM_ELEM_API_FLAG_CLEAR((BMElemF *)e_oflag);
+ }
+
+ BMFace_OFlag *f_oflag;
+ newpool = bm->ftoolflagpool;
+ BM_ITER_MESH_INDEX (f_oflag, &iter, bm, BM_FACES_OF_MESH, i) {
+ void *oldflags = f_oflag->oflags;
+ f_oflag->oflags = BLI_mempool_calloc(newpool);
+ memcpy(f_oflag->oflags, oldflags, old_totflags_size);
+ BM_elem_index_set(&f_oflag->base, i); /* set_inline */
+ BM_ELEM_API_FLAG_CLEAR((BMElemF *)f_oflag);
+ }
+
+ BLI_mempool_destroy(voldpool);
+ BLI_mempool_destroy(eoldpool);
+ BLI_mempool_destroy(foldpool);
+
+ bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE);
}
static void bmo_flag_layer_free(BMesh *bm)
{
- /* set the index values since we are looping over all data anyway,
- * may save time later on */
-
- BLI_mempool *voldpool = bm->vtoolflagpool;
- BLI_mempool *eoldpool = bm->etoolflagpool;
- BLI_mempool *foldpool = bm->ftoolflagpool;
-
- /* store memcpy size for reuse */
- const size_t new_totflags_size = ((bm->totflags - 1) * sizeof(BMFlagLayer));
-
- /* de-increment the totflags first.. */
- bm->totflags--;
-
- bm->vtoolflagpool = BLI_mempool_create(new_totflags_size, bm->totvert, 512, BLI_MEMPOOL_NOP);
- bm->etoolflagpool = BLI_mempool_create(new_totflags_size, bm->totedge, 512, BLI_MEMPOOL_NOP);
- bm->ftoolflagpool = BLI_mempool_create(new_totflags_size, bm->totface, 512, BLI_MEMPOOL_NOP);
-
- /* now go through and memcpy all the flag */
- BMIter iter;
- int i;
-
- BMVert_OFlag *v_oflag;
- BLI_mempool *newpool = bm->vtoolflagpool;
- BM_ITER_MESH_INDEX (v_oflag, &iter, bm, BM_VERTS_OF_MESH, i) {
- void *oldflags = v_oflag->oflags;
- v_oflag->oflags = BLI_mempool_alloc(newpool);
- memcpy(v_oflag->oflags, oldflags, new_totflags_size);
- BM_elem_index_set(&v_oflag->base, i); /* set_inline */
- BM_ELEM_API_FLAG_CLEAR((BMElemF *)v_oflag);
- }
-
- BMEdge_OFlag *e_oflag;
- newpool = bm->etoolflagpool;
- BM_ITER_MESH_INDEX (e_oflag, &iter, bm, BM_EDGES_OF_MESH, i) {
- void *oldflags = e_oflag->oflags;
- e_oflag->oflags = BLI_mempool_alloc(newpool);
- memcpy(e_oflag->oflags, oldflags, new_totflags_size);
- BM_elem_index_set(&e_oflag->base, i); /* set_inline */
- BM_ELEM_API_FLAG_CLEAR((BMElemF *)e_oflag);
- }
-
- BMFace_OFlag *f_oflag;
- newpool = bm->ftoolflagpool;
- BM_ITER_MESH_INDEX (f_oflag, &iter, bm, BM_FACES_OF_MESH, i) {
- void *oldflags = f_oflag->oflags;
- f_oflag->oflags = BLI_mempool_alloc(newpool);
- memcpy(f_oflag->oflags, oldflags, new_totflags_size);
- BM_elem_index_set(&f_oflag->base, i); /* set_inline */
- BM_ELEM_API_FLAG_CLEAR((BMElemF *)f_oflag);
- }
-
- BLI_mempool_destroy(voldpool);
- BLI_mempool_destroy(eoldpool);
- BLI_mempool_destroy(foldpool);
-
- bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE);
+ /* set the index values since we are looping over all data anyway,
+ * may save time later on */
+
+ BLI_mempool *voldpool = bm->vtoolflagpool;
+ BLI_mempool *eoldpool = bm->etoolflagpool;
+ BLI_mempool *foldpool = bm->ftoolflagpool;
+
+ /* store memcpy size for reuse */
+ const size_t new_totflags_size = ((bm->totflags - 1) * sizeof(BMFlagLayer));
+
+ /* de-increment the totflags first.. */
+ bm->totflags--;
+
+ bm->vtoolflagpool = BLI_mempool_create(new_totflags_size, bm->totvert, 512, BLI_MEMPOOL_NOP);
+ bm->etoolflagpool = BLI_mempool_create(new_totflags_size, bm->totedge, 512, BLI_MEMPOOL_NOP);
+ bm->ftoolflagpool = BLI_mempool_create(new_totflags_size, bm->totface, 512, BLI_MEMPOOL_NOP);
+
+ /* now go through and memcpy all the flag */
+ BMIter iter;
+ int i;
+
+ BMVert_OFlag *v_oflag;
+ BLI_mempool *newpool = bm->vtoolflagpool;
+ BM_ITER_MESH_INDEX (v_oflag, &iter, bm, BM_VERTS_OF_MESH, i) {
+ void *oldflags = v_oflag->oflags;
+ v_oflag->oflags = BLI_mempool_alloc(newpool);
+ memcpy(v_oflag->oflags, oldflags, new_totflags_size);
+ BM_elem_index_set(&v_oflag->base, i); /* set_inline */
+ BM_ELEM_API_FLAG_CLEAR((BMElemF *)v_oflag);
+ }
+
+ BMEdge_OFlag *e_oflag;
+ newpool = bm->etoolflagpool;
+ BM_ITER_MESH_INDEX (e_oflag, &iter, bm, BM_EDGES_OF_MESH, i) {
+ void *oldflags = e_oflag->oflags;
+ e_oflag->oflags = BLI_mempool_alloc(newpool);
+ memcpy(e_oflag->oflags, oldflags, new_totflags_size);
+ BM_elem_index_set(&e_oflag->base, i); /* set_inline */
+ BM_ELEM_API_FLAG_CLEAR((BMElemF *)e_oflag);
+ }
+
+ BMFace_OFlag *f_oflag;
+ newpool = bm->ftoolflagpool;
+ BM_ITER_MESH_INDEX (f_oflag, &iter, bm, BM_FACES_OF_MESH, i) {
+ void *oldflags = f_oflag->oflags;
+ f_oflag->oflags = BLI_mempool_alloc(newpool);
+ memcpy(f_oflag->oflags, oldflags, new_totflags_size);
+ BM_elem_index_set(&f_oflag->base, i); /* set_inline */
+ BM_ELEM_API_FLAG_CLEAR((BMElemF *)f_oflag);
+ }
+
+ BLI_mempool_destroy(voldpool);
+ BLI_mempool_destroy(eoldpool);
+ BLI_mempool_destroy(foldpool);
+
+ bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE);
}
static void bmo_flag_layer_clear(BMesh *bm)
{
- /* set the index values since we are looping over all data anyway,
- * may save time later on */
- const BMFlagLayer zero_flag = {0};
-
- const int totflags_offset = bm->totflags - 1;
-
- /* now go through and memcpy all the flag */
- {
- BMIter iter;
- BMVert_OFlag *ele;
- int i;
- BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, i) {
- ele->oflags[totflags_offset] = zero_flag;
- BM_elem_index_set(&ele->base, i); /* set_inline */
- }
- }
- {
- BMIter iter;
- BMEdge_OFlag *ele;
- int i;
- BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) {
- ele->oflags[totflags_offset] = zero_flag;
- BM_elem_index_set(&ele->base, i); /* set_inline */
- }
- }
- {
- BMIter iter;
- BMFace_OFlag *ele;
- int i;
- BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) {
- ele->oflags[totflags_offset] = zero_flag;
- BM_elem_index_set(&ele->base, i); /* set_inline */
- }
- }
-
- bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE);
+ /* set the index values since we are looping over all data anyway,
+ * may save time later on */
+ const BMFlagLayer zero_flag = {0};
+
+ const int totflags_offset = bm->totflags - 1;
+
+ /* now go through and memcpy all the flag */
+ {
+ BMIter iter;
+ BMVert_OFlag *ele;
+ int i;
+ BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, i) {
+ ele->oflags[totflags_offset] = zero_flag;
+ BM_elem_index_set(&ele->base, i); /* set_inline */
+ }
+ }
+ {
+ BMIter iter;
+ BMEdge_OFlag *ele;
+ int i;
+ BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) {
+ ele->oflags[totflags_offset] = zero_flag;
+ BM_elem_index_set(&ele->base, i); /* set_inline */
+ }
+ }
+ {
+ BMIter iter;
+ BMFace_OFlag *ele;
+ int i;
+ BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) {
+ ele->oflags[totflags_offset] = zero_flag;
+ BM_elem_index_set(&ele->base, i); /* set_inline */
+ }
+ }
+
+ bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE);
}
void *BMO_slot_buffer_get_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
{
- BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
- if (slot->slot_type != BMO_OP_SLOT_ELEMENT_BUF) {
- return NULL;
- }
+ if (slot->slot_type != BMO_OP_SLOT_ELEMENT_BUF) {
+ return NULL;
+ }
- return slot->data.buf ? *slot->data.buf : NULL;
+ return slot->data.buf ? *slot->data.buf : NULL;
}
/**
@@ -1405,78 +1454,77 @@ void *BMO_slot_buffer_get_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char
* \param restrictmask: restricts the iteration to certain element types
* (e.g. combination of BM_VERT, BM_EDGE, BM_FACE), if iterating
* over an element buffer (not a mapping). */
-void *BMO_iter_new(
- BMOIter *iter,
- BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name,
- const char restrictmask)
+void *BMO_iter_new(BMOIter *iter,
+ BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
+ const char *slot_name,
+ const char restrictmask)
{
- BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
+ BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
- memset(iter, 0, sizeof(BMOIter));
+ memset(iter, 0, sizeof(BMOIter));
- iter->slot = slot;
- iter->cur = 0;
- iter->restrictmask = restrictmask;
+ iter->slot = slot;
+ iter->cur = 0;
+ iter->restrictmask = restrictmask;
- if (iter->slot->slot_type == BMO_OP_SLOT_MAPPING) {
- BLI_ghashIterator_init(&iter->giter, slot->data.ghash);
- }
- else if (iter->slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF) {
- BLI_assert(restrictmask & slot->slot_subtype.elem);
- }
- else {
- BLI_assert(0);
- }
+ if (iter->slot->slot_type == BMO_OP_SLOT_MAPPING) {
+ BLI_ghashIterator_init(&iter->giter, slot->data.ghash);
+ }
+ else if (iter->slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF) {
+ BLI_assert(restrictmask & slot->slot_subtype.elem);
+ }
+ else {
+ BLI_assert(0);
+ }
- return BMO_iter_step(iter);
+ return BMO_iter_step(iter);
}
void *BMO_iter_step(BMOIter *iter)
{
- BMOpSlot *slot = iter->slot;
- if (slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF) {
- BMHeader *ele;
+ BMOpSlot *slot = iter->slot;
+ if (slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF) {
+ BMHeader *ele;
- if (iter->cur >= slot->len) {
- return NULL;
- }
+ if (iter->cur >= slot->len) {
+ return NULL;
+ }
- ele = slot->data.buf[iter->cur++];
- while (!(iter->restrictmask & ele->htype)) {
- if (iter->cur >= slot->len) {
- return NULL;
- }
+ ele = slot->data.buf[iter->cur++];
+ while (!(iter->restrictmask & ele->htype)) {
+ if (iter->cur >= slot->len) {
+ return NULL;
+ }
- ele = slot->data.buf[iter->cur++];
- BLI_assert((ele == NULL) || (slot->slot_subtype.elem & ele->htype));
- }
+ ele = slot->data.buf[iter->cur++];
+ BLI_assert((ele == NULL) || (slot->slot_subtype.elem & ele->htype));
+ }
- BLI_assert((ele == NULL) || (slot->slot_subtype.elem & ele->htype));
+ BLI_assert((ele == NULL) || (slot->slot_subtype.elem & ele->htype));
- return ele;
- }
- else if (slot->slot_type == BMO_OP_SLOT_MAPPING) {
- void *ret;
+ return ele;
+ }
+ else if (slot->slot_type == BMO_OP_SLOT_MAPPING) {
+ void *ret;
+ if (BLI_ghashIterator_done(&iter->giter) == false) {
+ ret = BLI_ghashIterator_getKey(&iter->giter);
+ iter->val = BLI_ghashIterator_getValue_p(&iter->giter);
- if (BLI_ghashIterator_done(&iter->giter) == false) {
- ret = BLI_ghashIterator_getKey(&iter->giter);
- iter->val = BLI_ghashIterator_getValue_p(&iter->giter);
+ BLI_ghashIterator_step(&iter->giter);
+ }
+ else {
+ ret = NULL;
+ iter->val = NULL;
+ }
- BLI_ghashIterator_step(&iter->giter);
- }
- else {
- ret = NULL;
- iter->val = NULL;
- }
+ return ret;
+ }
+ else {
+ BLI_assert(0);
+ }
- return ret;
- }
- else {
- BLI_assert(0);
- }
-
- return NULL;
+ return NULL;
}
/* used for iterating over mappings */
@@ -1487,149 +1535,154 @@ void *BMO_iter_step(BMOIter *iter)
*/
void **BMO_iter_map_value_p(BMOIter *iter)
{
- return iter->val;
+ return iter->val;
}
void *BMO_iter_map_value_ptr(BMOIter *iter)
{
- BLI_assert(ELEM(iter->slot->slot_subtype.map,
- BMO_OP_SLOT_SUBTYPE_MAP_ELEM, BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL));
- return iter->val ? *iter->val : NULL;
+ BLI_assert(ELEM(iter->slot->slot_subtype.map,
+ BMO_OP_SLOT_SUBTYPE_MAP_ELEM,
+ BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL));
+ return iter->val ? *iter->val : NULL;
}
-
float BMO_iter_map_value_float(BMOIter *iter)
{
- BLI_assert(iter->slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_FLT);
- return **((float **)iter->val);
+ BLI_assert(iter->slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_FLT);
+ return **((float **)iter->val);
}
int BMO_iter_map_value_int(BMOIter *iter)
{
- BLI_assert(iter->slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INT);
- return **((int **)iter->val);
+ BLI_assert(iter->slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INT);
+ return **((int **)iter->val);
}
bool BMO_iter_map_value_bool(BMOIter *iter)
{
- BLI_assert(iter->slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_BOOL);
- return **((bool **)iter->val);
+ BLI_assert(iter->slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_BOOL);
+ return **((bool **)iter->val);
}
/* error system */
typedef struct BMOpError {
- struct BMOpError *next, *prev;
- int errorcode;
- BMOperator *op;
- const char *msg;
+ struct BMOpError *next, *prev;
+ int errorcode;
+ BMOperator *op;
+ const char *msg;
} BMOpError;
void BMO_error_clear(BMesh *bm)
{
- while (BMO_error_pop(bm, NULL, NULL)) {
- /* pass */
- }
+ while (BMO_error_pop(bm, NULL, NULL)) {
+ /* pass */
+ }
}
void BMO_error_raise(BMesh *bm, BMOperator *owner, int errcode, const char *msg)
{
- BMOpError *err = MEM_callocN(sizeof(BMOpError), "bmop_error");
+ BMOpError *err = MEM_callocN(sizeof(BMOpError), "bmop_error");
- err->errorcode = errcode;
- if (!msg) {
- msg = bmo_error_messages[errcode];
- }
- err->msg = msg;
- err->op = owner;
+ err->errorcode = errcode;
+ if (!msg) {
+ msg = bmo_error_messages[errcode];
+ }
+ err->msg = msg;
+ err->op = owner;
- BLI_addhead(&bm->errorstack, err);
+ BLI_addhead(&bm->errorstack, err);
}
bool BMO_error_occurred(BMesh *bm)
{
- return (BLI_listbase_is_empty(&bm->errorstack) == false);
+ return (BLI_listbase_is_empty(&bm->errorstack) == false);
}
/* returns error code or 0 if no error */
int BMO_error_get(BMesh *bm, const char **msg, BMOperator **op)
{
- BMOpError *err = bm->errorstack.first;
- if (!err) {
- return 0;
- }
+ BMOpError *err = bm->errorstack.first;
+ if (!err) {
+ return 0;
+ }
- if (msg) {
- *msg = err->msg;
- }
- if (op) {
- *op = err->op;
- }
+ if (msg) {
+ *msg = err->msg;
+ }
+ if (op) {
+ *op = err->op;
+ }
- return err->errorcode;
+ return err->errorcode;
}
int BMO_error_pop(BMesh *bm, const char **msg, BMOperator **op)
{
- int errorcode = BMO_error_get(bm, msg, op);
+ int errorcode = BMO_error_get(bm, msg, op);
- if (errorcode) {
- BMOpError *err = bm->errorstack.first;
+ if (errorcode) {
+ BMOpError *err = bm->errorstack.first;
- BLI_remlink(&bm->errorstack, bm->errorstack.first);
- MEM_freeN(err);
- }
+ BLI_remlink(&bm->errorstack, bm->errorstack.first);
+ MEM_freeN(err);
+ }
- return errorcode;
+ return errorcode;
}
-
#define NEXT_CHAR(fmt) ((fmt)[0] != 0 ? (fmt)[1] : 0)
static int bmo_name_to_slotcode(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier)
{
- int i = 0;
+ int i = 0;
- while (slot_args->slot_name) {
- if (STREQLEN(identifier, slot_args->slot_name, MAX_SLOTNAME)) {
- return i;
- }
- slot_args++;
- i++;
- }
+ while (slot_args->slot_name) {
+ if (STREQLEN(identifier, slot_args->slot_name, MAX_SLOTNAME)) {
+ return i;
+ }
+ slot_args++;
+ i++;
+ }
- return -1;
+ return -1;
}
static int bmo_name_to_slotcode_check(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier)
{
- int i = bmo_name_to_slotcode(slot_args, identifier);
- if (i < 0) {
- fprintf(stderr, "%s: ! could not find bmesh slot for name %s! (bmesh internal error)\n", __func__, identifier);
- }
+ int i = bmo_name_to_slotcode(slot_args, identifier);
+ if (i < 0) {
+ fprintf(stderr,
+ "%s: ! could not find bmesh slot for name %s! (bmesh internal error)\n",
+ __func__,
+ identifier);
+ }
- return i;
+ return i;
}
int BMO_opcode_from_opname(const char *opname)
{
- const uint tot = bmo_opdefines_total;
- uint i;
- for (i = 0; i < tot; i++) {
- if (STREQ(bmo_opdefines[i]->opname, opname)) {
- return i;
- }
- }
- return -1;
+ const uint tot = bmo_opdefines_total;
+ uint i;
+ for (i = 0; i < tot; i++) {
+ if (STREQ(bmo_opdefines[i]->opname, opname)) {
+ return i;
+ }
+ }
+ return -1;
}
static int BMO_opcode_from_opname_check(const char *opname)
{
- int i = BMO_opcode_from_opname(opname);
- if (i == -1) {
- fprintf(stderr, "%s: could not find bmesh slot for name %s! (bmesh internal error)\n", __func__, opname);
- }
- return i;
+ int i = BMO_opcode_from_opname(opname);
+ if (i == -1) {
+ fprintf(stderr,
+ "%s: could not find bmesh slot for name %s! (bmesh internal error)\n",
+ __func__,
+ opname);
+ }
+ return i;
}
/**
@@ -1688,283 +1741,294 @@ static int BMO_opcode_from_opname_check(const char *opname)
bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, va_list vlist)
{
-// BMOpDefine *def;
- char *opname, *ofmt, *fmt;
- char slot_name[64] = {0};
- int i, type;
- bool noslot, state;
-
-
- /* basic useful info to help find where bmop formatting strings fail */
- const char *err_reason = "Unknown";
- int lineno = -1;
-
-#define GOTO_ERROR(reason) \
- { \
- err_reason = reason; \
- lineno = __LINE__; \
- goto error; \
- } (void)0
-
- /* we muck around in here, so dup it */
- fmt = ofmt = BLI_strdup(_fmt);
-
- /* find operator name */
- i = strcspn(fmt, " ");
-
- opname = fmt;
- noslot = (opname[i] == '\0');
- opname[i] = '\0';
-
- fmt += i + (noslot ? 0 : 1);
-
- i = BMO_opcode_from_opname_check(opname);
-
- if (i == -1) {
- MEM_freeN(ofmt);
- BLI_assert(0);
- return false;
- }
-
- BMO_op_init(bm, op, flag, opname);
-// def = bmo_opdefines[i];
-
- i = 0;
- state = true; /* false: not inside slot_code name, true: inside slot_code name */
-
- while (*fmt) {
- if (state) {
- /* jump past leading whitespace */
- i = strspn(fmt, " ");
- fmt += i;
-
- /* ignore trailing whitespace */
- if (!fmt[i]) {
- break;
- }
-
- /* find end of slot name, only "slot=%f", can be used */
- i = strcspn(fmt, "=");
- if (!fmt[i]) {
- GOTO_ERROR("could not match end of slot name");
- }
-
- fmt[i] = 0;
-
- if (bmo_name_to_slotcode_check(op->slots_in, fmt) < 0) {
- GOTO_ERROR("name to slot code check failed");
- }
-
- BLI_strncpy(slot_name, fmt, sizeof(slot_name));
-
- state = false;
- fmt += i;
- }
- else {
- switch (*fmt) {
- case ' ':
- case '=':
- case '%':
- break;
- case 'm':
- {
- int size;
- const char c = NEXT_CHAR(fmt);
- fmt++;
-
- if (c == '3') { size = 3; }
- else if (c == '4') { size = 4; }
- else { GOTO_ERROR("matrix size was not 3 or 4"); }
-
- BMO_slot_mat_set(op, op->slots_in, slot_name, va_arg(vlist, void *), size);
- state = true;
- break;
- }
- case 'v':
- {
- BMO_slot_vec_set(op->slots_in, slot_name, va_arg(vlist, float *));
- state = true;
- break;
- }
- case 'e':
- {
- BMOpSlot *slot = BMO_slot_get(op->slots_in, slot_name);
-
- if (NEXT_CHAR(fmt) == 'b') {
- BMHeader **ele_buffer = va_arg(vlist, void *);
- int ele_buffer_len = va_arg(vlist, int);
-
- BMO_slot_buffer_from_array(op, slot, ele_buffer, ele_buffer_len);
- fmt++;
- }
- else {
- /* single vert/edge/face */
- BMHeader *ele = va_arg(vlist, void *);
-
- BMO_slot_buffer_from_single(op, slot, ele);
- }
-
- state = true;
- break;
- }
- case 's':
- case 'S':
- {
- BMOperator *op_other = va_arg(vlist, void *);
- const char *slot_name_other = va_arg(vlist, char *);
-
- if (*fmt == 's') {
- BLI_assert(bmo_name_to_slotcode_check(op_other->slots_in, slot_name_other) != -1);
- BMO_slot_copy(op_other, slots_in, slot_name_other,
- op, slots_in, slot_name);
- }
- else {
- BLI_assert(bmo_name_to_slotcode_check(op_other->slots_out, slot_name_other) != -1);
- BMO_slot_copy(op_other, slots_out, slot_name_other,
- op, slots_in, slot_name);
- }
- state = true;
- break;
- }
- case 'i':
- BMO_slot_int_set(op->slots_in, slot_name, va_arg(vlist, int));
- state = true;
- break;
- case 'b':
- BMO_slot_bool_set(op->slots_in, slot_name, va_arg(vlist, int));
- state = true;
- break;
- case 'p':
- BMO_slot_ptr_set(op->slots_in, slot_name, va_arg(vlist, void *));
- state = true;
- break;
- case 'f':
- case 'F':
- case 'h':
- case 'H':
- case 'a':
- type = *fmt;
-
- if (NEXT_CHAR(fmt) == ' ' || NEXT_CHAR(fmt) == '\0') {
- BMO_slot_float_set(op->slots_in, slot_name, va_arg(vlist, double));
- }
- else {
- char htype = 0;
-
- while (1) {
- char htype_set;
- const char c = NEXT_CHAR(fmt);
- if (c == 'f') { htype_set = BM_FACE; }
- else if (c == 'e') { htype_set = BM_EDGE; }
- else if (c == 'v') { htype_set = BM_VERT; }
- else {
- break;
- }
-
- if (UNLIKELY(htype & htype_set)) {
- GOTO_ERROR("htype duplicated");
- }
-
- htype |= htype_set;
- fmt++;
- }
-
- if (type == 'h') {
- BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int));
- }
- else if (type == 'H') {
- BMO_slot_buffer_from_disabled_hflag(bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int));
- }
- else if (type == 'a') {
- if ((op->flag & BMO_FLAG_RESPECT_HIDE) == 0) {
- BMO_slot_buffer_from_all(bm, op, op->slots_in, slot_name, htype);
- }
- else {
- BMO_slot_buffer_from_disabled_hflag(bm, op, op->slots_in, slot_name, htype, BM_ELEM_HIDDEN);
- }
- }
- else if (type == 'f') {
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int));
- }
- else if (type == 'F') {
- BMO_slot_buffer_from_disabled_flag(bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int));
- }
- }
-
- state = true;
- break;
- default:
- fprintf(stderr,
- "%s: unrecognized bmop format char: '%c', %d in '%s'\n",
- __func__, *fmt, (int)(fmt - ofmt), ofmt);
- break;
- }
- }
- fmt++;
- }
-
- MEM_freeN(ofmt);
- return true;
+ // BMOpDefine *def;
+ char *opname, *ofmt, *fmt;
+ char slot_name[64] = {0};
+ int i, type;
+ bool noslot, state;
+
+ /* basic useful info to help find where bmop formatting strings fail */
+ const char *err_reason = "Unknown";
+ int lineno = -1;
+
+#define GOTO_ERROR(reason) \
+ { \
+ err_reason = reason; \
+ lineno = __LINE__; \
+ goto error; \
+ } \
+ (void)0
+
+ /* we muck around in here, so dup it */
+ fmt = ofmt = BLI_strdup(_fmt);
+
+ /* find operator name */
+ i = strcspn(fmt, " ");
+
+ opname = fmt;
+ noslot = (opname[i] == '\0');
+ opname[i] = '\0';
+
+ fmt += i + (noslot ? 0 : 1);
+
+ i = BMO_opcode_from_opname_check(opname);
+
+ if (i == -1) {
+ MEM_freeN(ofmt);
+ BLI_assert(0);
+ return false;
+ }
+
+ BMO_op_init(bm, op, flag, opname);
+ // def = bmo_opdefines[i];
+
+ i = 0;
+ state = true; /* false: not inside slot_code name, true: inside slot_code name */
+
+ while (*fmt) {
+ if (state) {
+ /* jump past leading whitespace */
+ i = strspn(fmt, " ");
+ fmt += i;
+
+ /* ignore trailing whitespace */
+ if (!fmt[i]) {
+ break;
+ }
+
+ /* find end of slot name, only "slot=%f", can be used */
+ i = strcspn(fmt, "=");
+ if (!fmt[i]) {
+ GOTO_ERROR("could not match end of slot name");
+ }
+
+ fmt[i] = 0;
+
+ if (bmo_name_to_slotcode_check(op->slots_in, fmt) < 0) {
+ GOTO_ERROR("name to slot code check failed");
+ }
+
+ BLI_strncpy(slot_name, fmt, sizeof(slot_name));
+
+ state = false;
+ fmt += i;
+ }
+ else {
+ switch (*fmt) {
+ case ' ':
+ case '=':
+ case '%':
+ break;
+ case 'm': {
+ int size;
+ const char c = NEXT_CHAR(fmt);
+ fmt++;
+
+ if (c == '3') {
+ size = 3;
+ }
+ else if (c == '4') {
+ size = 4;
+ }
+ else {
+ GOTO_ERROR("matrix size was not 3 or 4");
+ }
+
+ BMO_slot_mat_set(op, op->slots_in, slot_name, va_arg(vlist, void *), size);
+ state = true;
+ break;
+ }
+ case 'v': {
+ BMO_slot_vec_set(op->slots_in, slot_name, va_arg(vlist, float *));
+ state = true;
+ break;
+ }
+ case 'e': {
+ BMOpSlot *slot = BMO_slot_get(op->slots_in, slot_name);
+
+ if (NEXT_CHAR(fmt) == 'b') {
+ BMHeader **ele_buffer = va_arg(vlist, void *);
+ int ele_buffer_len = va_arg(vlist, int);
+
+ BMO_slot_buffer_from_array(op, slot, ele_buffer, ele_buffer_len);
+ fmt++;
+ }
+ else {
+ /* single vert/edge/face */
+ BMHeader *ele = va_arg(vlist, void *);
+
+ BMO_slot_buffer_from_single(op, slot, ele);
+ }
+
+ state = true;
+ break;
+ }
+ case 's':
+ case 'S': {
+ BMOperator *op_other = va_arg(vlist, void *);
+ const char *slot_name_other = va_arg(vlist, char *);
+
+ if (*fmt == 's') {
+ BLI_assert(bmo_name_to_slotcode_check(op_other->slots_in, slot_name_other) != -1);
+ BMO_slot_copy(op_other, slots_in, slot_name_other, op, slots_in, slot_name);
+ }
+ else {
+ BLI_assert(bmo_name_to_slotcode_check(op_other->slots_out, slot_name_other) != -1);
+ BMO_slot_copy(op_other, slots_out, slot_name_other, op, slots_in, slot_name);
+ }
+ state = true;
+ break;
+ }
+ case 'i':
+ BMO_slot_int_set(op->slots_in, slot_name, va_arg(vlist, int));
+ state = true;
+ break;
+ case 'b':
+ BMO_slot_bool_set(op->slots_in, slot_name, va_arg(vlist, int));
+ state = true;
+ break;
+ case 'p':
+ BMO_slot_ptr_set(op->slots_in, slot_name, va_arg(vlist, void *));
+ state = true;
+ break;
+ case 'f':
+ case 'F':
+ case 'h':
+ case 'H':
+ case 'a':
+ type = *fmt;
+
+ if (NEXT_CHAR(fmt) == ' ' || NEXT_CHAR(fmt) == '\0') {
+ BMO_slot_float_set(op->slots_in, slot_name, va_arg(vlist, double));
+ }
+ else {
+ char htype = 0;
+
+ while (1) {
+ char htype_set;
+ const char c = NEXT_CHAR(fmt);
+ if (c == 'f') {
+ htype_set = BM_FACE;
+ }
+ else if (c == 'e') {
+ htype_set = BM_EDGE;
+ }
+ else if (c == 'v') {
+ htype_set = BM_VERT;
+ }
+ else {
+ break;
+ }
+
+ if (UNLIKELY(htype & htype_set)) {
+ GOTO_ERROR("htype duplicated");
+ }
+
+ htype |= htype_set;
+ fmt++;
+ }
+
+ if (type == 'h') {
+ BMO_slot_buffer_from_enabled_hflag(
+ bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int));
+ }
+ else if (type == 'H') {
+ BMO_slot_buffer_from_disabled_hflag(
+ bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int));
+ }
+ else if (type == 'a') {
+ if ((op->flag & BMO_FLAG_RESPECT_HIDE) == 0) {
+ BMO_slot_buffer_from_all(bm, op, op->slots_in, slot_name, htype);
+ }
+ else {
+ BMO_slot_buffer_from_disabled_hflag(
+ bm, op, op->slots_in, slot_name, htype, BM_ELEM_HIDDEN);
+ }
+ }
+ else if (type == 'f') {
+ BMO_slot_buffer_from_enabled_flag(
+ bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int));
+ }
+ else if (type == 'F') {
+ BMO_slot_buffer_from_disabled_flag(
+ bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int));
+ }
+ }
+
+ state = true;
+ break;
+ default:
+ fprintf(stderr,
+ "%s: unrecognized bmop format char: '%c', %d in '%s'\n",
+ __func__,
+ *fmt,
+ (int)(fmt - ofmt),
+ ofmt);
+ break;
+ }
+ }
+ fmt++;
+ }
+
+ MEM_freeN(ofmt);
+ return true;
error:
- /* non urgent todo - explain exactly what is failing */
- fprintf(stderr, "%s: error parsing formatting string\n", __func__);
-
- fprintf(stderr, "string: '%s', position %d\n", _fmt, (int)(fmt - ofmt));
- fprintf(stderr, " ");
- {
- int pos = (int)(fmt - ofmt);
- for (i = 0; i < pos; i++) {
- fprintf(stderr, " ");
- }
- fprintf(stderr, "^\n");
- }
+ /* non urgent todo - explain exactly what is failing */
+ fprintf(stderr, "%s: error parsing formatting string\n", __func__);
- fprintf(stderr, "source code: %s:%d\n", __FILE__, lineno);
+ fprintf(stderr, "string: '%s', position %d\n", _fmt, (int)(fmt - ofmt));
+ fprintf(stderr, " ");
+ {
+ int pos = (int)(fmt - ofmt);
+ for (i = 0; i < pos; i++) {
+ fprintf(stderr, " ");
+ }
+ fprintf(stderr, "^\n");
+ }
- fprintf(stderr, "reason: %s\n", err_reason);
+ fprintf(stderr, "source code: %s:%d\n", __FILE__, lineno);
+ fprintf(stderr, "reason: %s\n", err_reason);
- MEM_freeN(ofmt);
+ MEM_freeN(ofmt);
- BMO_op_finish(bm, op);
- return false;
+ BMO_op_finish(bm, op);
+ return false;
#undef GOTO_ERROR
-
}
-
bool BMO_op_initf(BMesh *bm, BMOperator *op, const int flag, const char *fmt, ...)
{
- va_list list;
+ va_list list;
- va_start(list, fmt);
- if (!BMO_op_vinitf(bm, op, flag, fmt, list)) {
- printf("%s: failed\n", __func__);
- va_end(list);
- return false;
- }
- va_end(list);
+ va_start(list, fmt);
+ if (!BMO_op_vinitf(bm, op, flag, fmt, list)) {
+ printf("%s: failed\n", __func__);
+ va_end(list);
+ return false;
+ }
+ va_end(list);
- return true;
+ return true;
}
bool BMO_op_callf(BMesh *bm, const int flag, const char *fmt, ...)
{
- va_list list;
- BMOperator op;
+ va_list list;
+ BMOperator op;
- va_start(list, fmt);
- if (!BMO_op_vinitf(bm, &op, flag, fmt, list)) {
- printf("%s: failed, format is:\n \"%s\"\n", __func__, fmt);
- va_end(list);
- return false;
- }
+ va_start(list, fmt);
+ if (!BMO_op_vinitf(bm, &op, flag, fmt, list)) {
+ printf("%s: failed, format is:\n \"%s\"\n", __func__, fmt);
+ va_end(list);
+ return false;
+ }
- BMO_op_exec(bm, &op);
- BMO_op_finish(bm, &op);
+ BMO_op_exec(bm, &op);
+ BMO_op_finish(bm, &op);
- va_end(list);
- return true;
+ va_end(list);
+ return true;
}
diff --git a/source/blender/bmesh/intern/bmesh_operators.h b/source/blender/bmesh/intern/bmesh_operators.h
index 6c0a6854d8e..0279e4dd23e 100644
--- a/source/blender/bmesh/intern/bmesh_operators.h
+++ b/source/blender/bmesh/intern/bmesh_operators.h
@@ -27,132 +27,143 @@
/*quad innervert values*/
enum {
- SUBD_CORNER_INNERVERT,
- SUBD_CORNER_PATH,
- SUBD_CORNER_FAN,
- SUBD_CORNER_STRAIGHT_CUT,
+ SUBD_CORNER_INNERVERT,
+ SUBD_CORNER_PATH,
+ SUBD_CORNER_FAN,
+ SUBD_CORNER_STRAIGHT_CUT,
};
/* aligned with PROP_SMOOTH and friends */
enum {
- SUBD_FALLOFF_SMOOTH = 0,
- SUBD_FALLOFF_SPHERE,
- SUBD_FALLOFF_ROOT,
- SUBD_FALLOFF_SHARP,
- SUBD_FALLOFF_LIN,
- SUBD_FALLOFF_INVSQUARE = 7, /* matching PROP_INVSQUARE */
+ SUBD_FALLOFF_SMOOTH = 0,
+ SUBD_FALLOFF_SPHERE,
+ SUBD_FALLOFF_ROOT,
+ SUBD_FALLOFF_SHARP,
+ SUBD_FALLOFF_LIN,
+ SUBD_FALLOFF_INVSQUARE = 7, /* matching PROP_INVSQUARE */
};
enum {
- SUBDIV_SELECT_NONE,
- SUBDIV_SELECT_ORIG,
- SUBDIV_SELECT_INNER,
- SUBDIV_SELECT_LOOPCUT,
+ SUBDIV_SELECT_NONE,
+ SUBDIV_SELECT_ORIG,
+ SUBDIV_SELECT_INNER,
+ SUBDIV_SELECT_LOOPCUT,
};
/* subdivide_edgering */
enum {
- /* just subdiv */
- SUBD_RING_INTERP_LINEAR,
+ /* just subdiv */
+ SUBD_RING_INTERP_LINEAR,
- /* single bezier spline - curve follows bezier rotation */
- SUBD_RING_INTERP_PATH,
+ /* single bezier spline - curve follows bezier rotation */
+ SUBD_RING_INTERP_PATH,
- /* beziers based on adjacent faces (fallback to tangent) */
- SUBD_RING_INTERP_SURF,
+ /* beziers based on adjacent faces (fallback to tangent) */
+ SUBD_RING_INTERP_SURF,
};
/* similar face selection slot values */
enum {
- SIMFACE_MATERIAL = 201,
- SIMFACE_AREA,
- SIMFACE_SIDES,
- SIMFACE_PERIMETER,
- SIMFACE_NORMAL,
- SIMFACE_COPLANAR,
- SIMFACE_SMOOTH,
- SIMFACE_FACEMAP,
- SIMFACE_FREESTYLE,
+ SIMFACE_MATERIAL = 201,
+ SIMFACE_AREA,
+ SIMFACE_SIDES,
+ SIMFACE_PERIMETER,
+ SIMFACE_NORMAL,
+ SIMFACE_COPLANAR,
+ SIMFACE_SMOOTH,
+ SIMFACE_FACEMAP,
+ SIMFACE_FREESTYLE,
};
/* similar edge selection slot values */
enum {
- SIMEDGE_LENGTH = 101,
- SIMEDGE_DIR,
- SIMEDGE_FACE,
- SIMEDGE_FACE_ANGLE,
- SIMEDGE_CREASE,
- SIMEDGE_BEVEL,
- SIMEDGE_SEAM,
- SIMEDGE_SHARP,
- SIMEDGE_FREESTYLE,
+ SIMEDGE_LENGTH = 101,
+ SIMEDGE_DIR,
+ SIMEDGE_FACE,
+ SIMEDGE_FACE_ANGLE,
+ SIMEDGE_CREASE,
+ SIMEDGE_BEVEL,
+ SIMEDGE_SEAM,
+ SIMEDGE_SHARP,
+ SIMEDGE_FREESTYLE,
};
/* similar vertex selection slot values */
enum {
- SIMVERT_NORMAL = 0,
- SIMVERT_FACE,
- SIMVERT_VGROUP,
- SIMVERT_EDGE,
+ SIMVERT_NORMAL = 0,
+ SIMVERT_FACE,
+ SIMVERT_VGROUP,
+ SIMVERT_EDGE,
};
/* Poke face center calculation */
enum {
- BMOP_POKE_MEDIAN_WEIGHTED = 0,
- BMOP_POKE_MEDIAN,
- BMOP_POKE_BOUNDS,
+ BMOP_POKE_MEDIAN_WEIGHTED = 0,
+ BMOP_POKE_MEDIAN,
+ BMOP_POKE_BOUNDS,
};
/* Bevel offset_type slot values */
enum {
- BEVEL_AMT_OFFSET,
- BEVEL_AMT_WIDTH,
- BEVEL_AMT_DEPTH,
- BEVEL_AMT_PERCENT,
+ BEVEL_AMT_OFFSET,
+ BEVEL_AMT_WIDTH,
+ BEVEL_AMT_DEPTH,
+ BEVEL_AMT_PERCENT,
};
/* Bevel face_strength_mode values: should match face_str mode enum in DNA_modifer_types.h */
enum {
- BEVEL_FACE_STRENGTH_NONE,
- BEVEL_FACE_STRENGTH_NEW,
- BEVEL_FACE_STRENGTH_AFFECTED,
- BEVEL_FACE_STRENGTH_ALL,
+ BEVEL_FACE_STRENGTH_NONE,
+ BEVEL_FACE_STRENGTH_NEW,
+ BEVEL_FACE_STRENGTH_AFFECTED,
+ BEVEL_FACE_STRENGTH_ALL,
};
/* Bevel miter slot values */
enum {
- BEVEL_MITER_SHARP,
- BEVEL_MITER_PATCH,
- BEVEL_MITER_ARC,
+ BEVEL_MITER_SHARP,
+ BEVEL_MITER_PATCH,
+ BEVEL_MITER_ARC,
};
extern const BMOpDefine *bmo_opdefines[];
-extern const int bmo_opdefines_total;
+extern const int bmo_opdefines_total;
/*------specific operator helper functions-------*/
-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_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_sphere(
- BMesh *bm,
- const short oflag, const int cd_loop_uv_offset);
-void BM_mesh_calc_uvs_circle(
- BMesh *bm, float mat[4][4], const float radius,
- 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);
+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_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_sphere(BMesh *bm, const short oflag, const int cd_loop_uv_offset);
+void BM_mesh_calc_uvs_circle(BMesh *bm,
+ float mat[4][4],
+ const float radius,
+ 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);
void BM_mesh_calc_uvs_cube(BMesh *bm, const short oflag);
#include "intern/bmesh_operator_api_inline.h"
diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c
index 4cc3cf3e4c1..2a734c242ba 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.c
+++ b/source/blender/bmesh/intern/bmesh_polygon.c
@@ -50,24 +50,24 @@
*/
static float bm_face_calc_poly_normal(const BMFace *f, float n[3])
{
- BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
- BMLoop *l_iter = l_first;
- const float *v_prev = l_first->prev->v->co;
- const float *v_curr = l_first->v->co;
+ BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
+ BMLoop *l_iter = l_first;
+ const float *v_prev = l_first->prev->v->co;
+ const float *v_curr = l_first->v->co;
- zero_v3(n);
+ zero_v3(n);
- /* Newell's Method */
- do {
- add_newell_cross_v3_v3v3(n, v_prev, v_curr);
+ /* Newell's Method */
+ do {
+ add_newell_cross_v3_v3v3(n, v_prev, v_curr);
- l_iter = l_iter->next;
- v_prev = v_curr;
- v_curr = l_iter->v->co;
+ l_iter = l_iter->next;
+ v_prev = v_curr;
+ v_curr = l_iter->v->co;
- } while (l_iter != l_first);
+ } while (l_iter != l_first);
- return normalize_v3(n);
+ return normalize_v3(n);
}
/**
@@ -76,46 +76,46 @@ static float bm_face_calc_poly_normal(const BMFace *f, float n[3])
* Same as #bm_face_calc_poly_normal
* but takes an array of vertex locations.
*/
-static float bm_face_calc_poly_normal_vertex_cos(
- const BMFace *f, float r_no[3],
- float const (*vertexCos)[3])
+static float bm_face_calc_poly_normal_vertex_cos(const BMFace *f,
+ float r_no[3],
+ float const (*vertexCos)[3])
{
- BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
- BMLoop *l_iter = l_first;
- const float *v_prev = vertexCos[BM_elem_index_get(l_first->prev->v)];
- const float *v_curr = vertexCos[BM_elem_index_get(l_first->v)];
+ BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
+ BMLoop *l_iter = l_first;
+ const float *v_prev = vertexCos[BM_elem_index_get(l_first->prev->v)];
+ const float *v_curr = vertexCos[BM_elem_index_get(l_first->v)];
- zero_v3(r_no);
+ zero_v3(r_no);
- /* Newell's Method */
- do {
- add_newell_cross_v3_v3v3(r_no, v_prev, v_curr);
+ /* Newell's Method */
+ do {
+ add_newell_cross_v3_v3v3(r_no, v_prev, v_curr);
- l_iter = l_iter->next;
- v_prev = v_curr;
- v_curr = vertexCos[BM_elem_index_get(l_iter->v)];
- } while (l_iter != l_first);
+ l_iter = l_iter->next;
+ v_prev = v_curr;
+ v_curr = vertexCos[BM_elem_index_get(l_iter->v)];
+ } while (l_iter != l_first);
- return normalize_v3(r_no);
+ return normalize_v3(r_no);
}
/**
* \brief COMPUTE POLY CENTER (BMFace)
*/
-static void bm_face_calc_poly_center_median_vertex_cos(
- const BMFace *f, float r_cent[3],
- float const (*vertexCos)[3])
+static void bm_face_calc_poly_center_median_vertex_cos(const BMFace *f,
+ float r_cent[3],
+ float const (*vertexCos)[3])
{
- const BMLoop *l_first, *l_iter;
+ const BMLoop *l_first, *l_iter;
- zero_v3(r_cent);
+ zero_v3(r_cent);
- /* Newell's Method */
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- add_v3_v3(r_cent, vertexCos[BM_elem_index_get(l_iter->v)]);
- } while ((l_iter = l_iter->next) != l_first);
- mul_v3_fl(r_cent, 1.0f / f->len);
+ /* Newell's Method */
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ add_v3_v3(r_cent, vertexCos[BM_elem_index_get(l_iter->v)]);
+ } while ((l_iter = l_iter->next) != l_first);
+ mul_v3_fl(r_cent, 1.0f / f->len);
}
/**
@@ -126,54 +126,55 @@ static void bm_face_calc_poly_center_median_vertex_cos(
* \param r_loops: Store face loop pointers, (f->len)
* \param r_index: Store triangle triples, indices into \a r_loops, `((f->len - 2) * 3)`
*/
-void BM_face_calc_tessellation(
- const BMFace *f, const bool use_fixed_quad,
- BMLoop **r_loops, uint (*r_index)[3])
+void BM_face_calc_tessellation(const BMFace *f,
+ const bool use_fixed_quad,
+ BMLoop **r_loops,
+ uint (*r_index)[3])
{
- BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
- BMLoop *l_iter;
-
- if (f->len == 3) {
- *r_loops++ = (l_iter = l_first);
- *r_loops++ = (l_iter = l_iter->next);
- *r_loops++ = ( l_iter->next);
-
- r_index[0][0] = 0;
- r_index[0][1] = 1;
- r_index[0][2] = 2;
- }
- else if (f->len == 4 && use_fixed_quad) {
- *r_loops++ = (l_iter = l_first);
- *r_loops++ = (l_iter = l_iter->next);
- *r_loops++ = (l_iter = l_iter->next);
- *r_loops++ = ( l_iter->next);
-
- r_index[0][0] = 0;
- r_index[0][1] = 1;
- r_index[0][2] = 2;
-
- r_index[1][0] = 0;
- r_index[1][1] = 2;
- r_index[1][2] = 3;
- }
- else {
- float axis_mat[3][3];
- float (*projverts)[2] = BLI_array_alloca(projverts, f->len);
- int j;
-
- axis_dominant_v3_to_m3(axis_mat, f->no);
-
- j = 0;
- l_iter = l_first;
- do {
- mul_v2_m3v3(projverts[j], axis_mat, l_iter->v->co);
- r_loops[j] = l_iter;
- j++;
- } while ((l_iter = l_iter->next) != l_first);
-
- /* complete the loop */
- BLI_polyfill_calc(projverts, f->len, -1, r_index);
- }
+ BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
+ BMLoop *l_iter;
+
+ if (f->len == 3) {
+ *r_loops++ = (l_iter = l_first);
+ *r_loops++ = (l_iter = l_iter->next);
+ *r_loops++ = (l_iter->next);
+
+ r_index[0][0] = 0;
+ r_index[0][1] = 1;
+ r_index[0][2] = 2;
+ }
+ else if (f->len == 4 && use_fixed_quad) {
+ *r_loops++ = (l_iter = l_first);
+ *r_loops++ = (l_iter = l_iter->next);
+ *r_loops++ = (l_iter = l_iter->next);
+ *r_loops++ = (l_iter->next);
+
+ r_index[0][0] = 0;
+ r_index[0][1] = 1;
+ r_index[0][2] = 2;
+
+ r_index[1][0] = 0;
+ r_index[1][1] = 2;
+ r_index[1][2] = 3;
+ }
+ else {
+ float axis_mat[3][3];
+ float(*projverts)[2] = BLI_array_alloca(projverts, f->len);
+ int j;
+
+ axis_dominant_v3_to_m3(axis_mat, f->no);
+
+ j = 0;
+ l_iter = l_first;
+ do {
+ mul_v2_m3v3(projverts[j], axis_mat, l_iter->v->co);
+ r_loops[j] = l_iter;
+ j++;
+ } while ((l_iter = l_iter->next) != l_first);
+
+ /* complete the loop */
+ BLI_polyfill_calc(projverts, f->len, -1, r_index);
+ }
}
/**
@@ -181,39 +182,40 @@ void BM_face_calc_tessellation(
*/
void BM_face_calc_point_in_face(const BMFace *f, float r_co[3])
{
- const BMLoop *l_tri[3];
-
- if (f->len == 3) {
- const BMLoop *l = BM_FACE_FIRST_LOOP(f);
- ARRAY_SET_ITEMS(l_tri, l, l->next, l->prev);
- }
- else {
- /* tessellation here seems overkill when in many cases this will be the center,
- * but without this we can't be sure the point is inside a concave face. */
- const int tottri = f->len - 2;
- BMLoop **loops = BLI_array_alloca(loops, f->len);
- uint (*index)[3] = BLI_array_alloca(index, tottri);
- int j;
- int j_best = 0; /* use as fallback when unset */
- float area_best = -1.0f;
-
- BM_face_calc_tessellation(f, false, loops, index);
-
- for (j = 0; j < tottri; j++) {
- const float *p1 = loops[index[j][0]]->v->co;
- const float *p2 = loops[index[j][1]]->v->co;
- const float *p3 = loops[index[j][2]]->v->co;
- const float area = area_squared_tri_v3(p1, p2, p3);
- if (area > area_best) {
- j_best = j;
- area_best = area;
- }
- }
-
- ARRAY_SET_ITEMS(l_tri, loops[index[j_best][0]], loops[index[j_best][1]], loops[index[j_best][2]]);
- }
-
- mid_v3_v3v3v3(r_co, l_tri[0]->v->co, l_tri[1]->v->co, l_tri[2]->v->co);
+ const BMLoop *l_tri[3];
+
+ if (f->len == 3) {
+ const BMLoop *l = BM_FACE_FIRST_LOOP(f);
+ ARRAY_SET_ITEMS(l_tri, l, l->next, l->prev);
+ }
+ else {
+ /* tessellation here seems overkill when in many cases this will be the center,
+ * but without this we can't be sure the point is inside a concave face. */
+ const int tottri = f->len - 2;
+ BMLoop **loops = BLI_array_alloca(loops, f->len);
+ uint(*index)[3] = BLI_array_alloca(index, tottri);
+ int j;
+ int j_best = 0; /* use as fallback when unset */
+ float area_best = -1.0f;
+
+ BM_face_calc_tessellation(f, false, loops, index);
+
+ for (j = 0; j < tottri; j++) {
+ const float *p1 = loops[index[j][0]]->v->co;
+ const float *p2 = loops[index[j][1]]->v->co;
+ const float *p3 = loops[index[j][2]]->v->co;
+ const float area = area_squared_tri_v3(p1, p2, p3);
+ if (area > area_best) {
+ j_best = j;
+ area_best = area;
+ }
+ }
+
+ ARRAY_SET_ITEMS(
+ l_tri, loops[index[j_best][0]], loops[index[j_best][1]], loops[index[j_best][2]]);
+ }
+
+ mid_v3_v3v3v3(r_co, l_tri[0]->v->co, l_tri[1]->v->co, l_tri[2]->v->co);
}
/**
@@ -221,16 +223,16 @@ void BM_face_calc_point_in_face(const BMFace *f, float r_co[3])
*/
float BM_face_calc_area(const BMFace *f)
{
- /* inline 'area_poly_v3' logic, avoid creating a temp array */
- const BMLoop *l_iter, *l_first;
- float n[3];
-
- zero_v3(n);
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- add_newell_cross_v3_v3v3(n, l_iter->v->co, l_iter->next->v->co);
- } while ((l_iter = l_iter->next) != l_first);
- return len_v3(n) * 0.5f;
+ /* inline 'area_poly_v3' logic, avoid creating a temp array */
+ const BMLoop *l_iter, *l_first;
+ float n[3];
+
+ zero_v3(n);
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ add_newell_cross_v3_v3v3(n, l_iter->v->co, l_iter->next->v->co);
+ } while ((l_iter = l_iter->next) != l_first);
+ return len_v3(n) * 0.5f;
}
/**
@@ -238,21 +240,21 @@ float BM_face_calc_area(const BMFace *f)
*/
float BM_face_calc_area_with_mat3(const BMFace *f, const float mat3[3][3])
{
- /* inline 'area_poly_v3' logic, avoid creating a temp array */
- const BMLoop *l_iter, *l_first;
- float co[3];
- float n[3];
-
- zero_v3(n);
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- mul_v3_m3v3(co, mat3, l_iter->v->co);
- do {
- float co_next[3];
- mul_v3_m3v3(co_next, mat3, l_iter->next->v->co);
- add_newell_cross_v3_v3v3(n, co, co_next);
- copy_v3_v3(co, co_next);
- } while ((l_iter = l_iter->next) != l_first);
- return len_v3(n) * 0.5f;
+ /* inline 'area_poly_v3' logic, avoid creating a temp array */
+ const BMLoop *l_iter, *l_first;
+ float co[3];
+ float n[3];
+
+ zero_v3(n);
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ mul_v3_m3v3(co, mat3, l_iter->v->co);
+ do {
+ float co_next[3];
+ mul_v3_m3v3(co_next, mat3, l_iter->next->v->co);
+ add_newell_cross_v3_v3v3(n, co, co_next);
+ copy_v3_v3(co, co_next);
+ } while ((l_iter = l_iter->next) != l_first);
+ return len_v3(n) * 0.5f;
}
/**
@@ -260,18 +262,18 @@ float BM_face_calc_area_with_mat3(const BMFace *f, const float mat3[3][3])
*/
float BM_face_calc_area_uv(const BMFace *f, int cd_loop_uv_offset)
{
- /* inline 'area_poly_v2' logic, avoid creating a temp array */
- const BMLoop *l_iter, *l_first;
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- /* The Trapezium Area Rule */
- float cross = 0.0f;
- do {
- const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset);
- const MLoopUV *luv_next = BM_ELEM_CD_GET_VOID_P(l_iter->next, cd_loop_uv_offset);
- cross += (luv_next->uv[0] - luv->uv[0]) * (luv_next->uv[1] + luv->uv[1]);
- } while ((l_iter = l_iter->next) != l_first);
- return fabsf(cross * 0.5f);
+ /* inline 'area_poly_v2' logic, avoid creating a temp array */
+ const BMLoop *l_iter, *l_first;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ /* The Trapezium Area Rule */
+ float cross = 0.0f;
+ do {
+ const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset);
+ const MLoopUV *luv_next = BM_ELEM_CD_GET_VOID_P(l_iter->next, cd_loop_uv_offset);
+ cross += (luv_next->uv[0] - luv->uv[0]) * (luv_next->uv[1] + luv->uv[1]);
+ } while ((l_iter = l_iter->next) != l_first);
+ return fabsf(cross * 0.5f);
}
/**
@@ -279,15 +281,15 @@ float BM_face_calc_area_uv(const BMFace *f, int cd_loop_uv_offset)
*/
float BM_face_calc_perimeter(const BMFace *f)
{
- const BMLoop *l_iter, *l_first;
- float perimeter = 0.0f;
+ const BMLoop *l_iter, *l_first;
+ float perimeter = 0.0f;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- perimeter += len_v3v3(l_iter->v->co, l_iter->next->v->co);
- } while ((l_iter = l_iter->next) != l_first);
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ perimeter += len_v3v3(l_iter->v->co, l_iter->next->v->co);
+ } while ((l_iter = l_iter->next) != l_first);
- return perimeter;
+ return perimeter;
}
/**
@@ -295,20 +297,20 @@ float BM_face_calc_perimeter(const BMFace *f)
*/
float BM_face_calc_perimeter_with_mat3(const BMFace *f, const float mat3[3][3])
{
- const BMLoop *l_iter, *l_first;
- float co[3];
- float perimeter = 0.0f;
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- mul_v3_m3v3(co, mat3, l_iter->v->co);
- do {
- float co_next[3];
- mul_v3_m3v3(co_next, mat3, l_iter->next->v->co);
- perimeter += len_v3v3(co, co_next);
- copy_v3_v3(co, co_next);
- } while ((l_iter = l_iter->next) != l_first);
-
- return perimeter;
+ const BMLoop *l_iter, *l_first;
+ float co[3];
+ float perimeter = 0.0f;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ mul_v3_m3v3(co, mat3, l_iter->v->co);
+ do {
+ float co_next[3];
+ mul_v3_m3v3(co_next, mat3, l_iter->next->v->co);
+ perimeter += len_v3v3(co, co_next);
+ copy_v3_v3(co, co_next);
+ } while ((l_iter = l_iter->next) != l_first);
+
+ return perimeter;
}
/**
@@ -318,42 +320,39 @@ float BM_face_calc_perimeter_with_mat3(const BMFace *f, const float mat3[3][3])
*/
static int bm_vert_tri_find_unique_edge(BMVert *verts[3])
{
- /* find the most 'unique' loop, (greatest difference to others) */
+ /* find the most 'unique' loop, (greatest difference to others) */
#if 1
- /* optimized version that avoids sqrt */
- float difs[3];
- for (int i_prev = 1, i_curr = 2, i_next = 0;
- i_next < 3;
- i_prev = i_curr, i_curr = i_next++)
- {
- const float *co = verts[i_curr]->co;
- const float *co_other[2] = {verts[i_prev]->co, verts[i_next]->co};
- float proj_dir[3];
- mid_v3_v3v3(proj_dir, co_other[0], co_other[1]);
- sub_v3_v3(proj_dir, co);
-
- float proj_pair[2][3];
- project_v3_v3v3(proj_pair[0], co_other[0], proj_dir);
- project_v3_v3v3(proj_pair[1], co_other[1], proj_dir);
- difs[i_next] = len_squared_v3v3(proj_pair[0], proj_pair[1]);
- }
+ /* optimized version that avoids sqrt */
+ float difs[3];
+ for (int i_prev = 1, i_curr = 2, i_next = 0; i_next < 3; i_prev = i_curr, i_curr = i_next++) {
+ const float *co = verts[i_curr]->co;
+ const float *co_other[2] = {verts[i_prev]->co, verts[i_next]->co};
+ float proj_dir[3];
+ mid_v3_v3v3(proj_dir, co_other[0], co_other[1]);
+ sub_v3_v3(proj_dir, co);
+
+ float proj_pair[2][3];
+ project_v3_v3v3(proj_pair[0], co_other[0], proj_dir);
+ project_v3_v3v3(proj_pair[1], co_other[1], proj_dir);
+ difs[i_next] = len_squared_v3v3(proj_pair[0], proj_pair[1]);
+ }
#else
- const float lens[3] = {
- len_v3v3(verts[0]->co, verts[1]->co),
- len_v3v3(verts[1]->co, verts[2]->co),
- len_v3v3(verts[2]->co, verts[0]->co),
- };
- const float difs[3] = {
- fabsf(lens[1] - lens[2]),
- fabsf(lens[2] - lens[0]),
- fabsf(lens[0] - lens[1]),
- };
+ const float lens[3] = {
+ len_v3v3(verts[0]->co, verts[1]->co),
+ len_v3v3(verts[1]->co, verts[2]->co),
+ len_v3v3(verts[2]->co, verts[0]->co),
+ };
+ const float difs[3] = {
+ fabsf(lens[1] - lens[2]),
+ fabsf(lens[2] - lens[0]),
+ fabsf(lens[0] - lens[1]),
+ };
#endif
- int order[3] = {0, 1, 2};
- axis_sort_v3(difs, order);
+ int order[3] = {0, 1, 2};
+ axis_sort_v3(difs, order);
- return order[0];
+ return order[0];
}
/**
@@ -366,11 +365,11 @@ static int bm_vert_tri_find_unique_edge(BMVert *verts[3])
*/
void BM_vert_tri_calc_tangent_edge(BMVert *verts[3], float r_tangent[3])
{
- const int index = bm_vert_tri_find_unique_edge(verts);
+ const int index = bm_vert_tri_find_unique_edge(verts);
- sub_v3_v3v3(r_tangent, verts[index]->co, verts[(index + 1) % 3]->co);
+ sub_v3_v3v3(r_tangent, verts[index]->co, verts[(index + 1) % 3]->co);
- normalize_v3(r_tangent);
+ normalize_v3(r_tangent);
}
/**
@@ -383,29 +382,28 @@ void BM_vert_tri_calc_tangent_edge(BMVert *verts[3], float r_tangent[3])
*/
void BM_vert_tri_calc_tangent_edge_pair(BMVert *verts[3], float r_tangent[3])
{
- const int index = bm_vert_tri_find_unique_edge(verts);
+ const int index = bm_vert_tri_find_unique_edge(verts);
- const float *v_a = verts[index]->co;
- const float *v_b = verts[(index + 1) % 3]->co;
- const float *v_other = verts[(index + 2) % 3]->co;
+ const float *v_a = verts[index]->co;
+ const float *v_b = verts[(index + 1) % 3]->co;
+ const float *v_other = verts[(index + 2) % 3]->co;
- mid_v3_v3v3(r_tangent, v_a, v_b);
- sub_v3_v3v3(r_tangent, v_other, r_tangent);
+ mid_v3_v3v3(r_tangent, v_a, v_b);
+ sub_v3_v3v3(r_tangent, v_other, r_tangent);
- normalize_v3(r_tangent);
+ normalize_v3(r_tangent);
}
/**
* Compute the tangent of the face, using the longest edge.
*/
-void BM_face_calc_tangent_edge(const BMFace *f, float r_tangent[3])
+void BM_face_calc_tangent_edge(const BMFace *f, float r_tangent[3])
{
- const BMLoop *l_long = BM_face_find_longest_loop((BMFace *)f);
+ const BMLoop *l_long = BM_face_find_longest_loop((BMFace *)f);
- sub_v3_v3v3(r_tangent, l_long->v->co, l_long->next->v->co);
-
- normalize_v3(r_tangent);
+ sub_v3_v3v3(r_tangent, l_long->v->co, l_long->next->v->co);
+ normalize_v3(r_tangent);
}
/**
@@ -413,64 +411,64 @@ void BM_face_calc_tangent_edge(const BMFace *f, float r_tangent[3])
*
* \param r_tangent: Calculated unit length tangent (return value).
*/
-void BM_face_calc_tangent_edge_pair(const BMFace *f, float r_tangent[3])
+void BM_face_calc_tangent_edge_pair(const BMFace *f, float r_tangent[3])
{
- if (f->len == 3) {
- BMVert *verts[3];
-
- BM_face_as_array_vert_tri((BMFace *)f, verts);
-
- BM_vert_tri_calc_tangent_edge_pair(verts, r_tangent);
- }
- else if (f->len == 4) {
- /* Use longest edge pair */
- BMVert *verts[4];
- float vec[3], vec_a[3], vec_b[3];
-
- BM_face_as_array_vert_quad((BMFace *)f, verts);
-
- sub_v3_v3v3(vec_a, verts[3]->co, verts[2]->co);
- sub_v3_v3v3(vec_b, verts[0]->co, verts[1]->co);
- add_v3_v3v3(r_tangent, vec_a, vec_b);
-
- sub_v3_v3v3(vec_a, verts[0]->co, verts[3]->co);
- sub_v3_v3v3(vec_b, verts[1]->co, verts[2]->co);
- add_v3_v3v3(vec, vec_a, vec_b);
- /* use the longest edge length */
- if (len_squared_v3(r_tangent) < len_squared_v3(vec)) {
- copy_v3_v3(r_tangent, vec);
- }
- }
- else {
- /* For ngons use two longest disconnected edges */
- BMLoop *l_long = BM_face_find_longest_loop((BMFace *)f);
- BMLoop *l_long_other = NULL;
-
- float len_max_sq = 0.0f;
- float vec_a[3], vec_b[3];
-
- BMLoop *l_iter = l_long->prev->prev;
- BMLoop *l_last = l_long->next;
-
- do {
- const float len_sq = len_squared_v3v3(l_iter->v->co, l_iter->next->v->co);
- if (len_sq >= len_max_sq) {
- l_long_other = l_iter;
- len_max_sq = len_sq;
- }
- } while ((l_iter = l_iter->prev) != l_last);
-
- sub_v3_v3v3(vec_a, l_long->next->v->co, l_long->v->co);
- sub_v3_v3v3(vec_b, l_long_other->v->co, l_long_other->next->v->co);
- add_v3_v3v3(r_tangent, vec_a, vec_b);
-
- /* Edges may not be opposite side of the ngon,
- * this could cause problems for ngons with multiple-aligned edges of the same length.
- * Fallback to longest edge. */
- if (UNLIKELY(normalize_v3(r_tangent) == 0.0f)) {
- normalize_v3_v3(r_tangent, vec_a);
- }
- }
+ if (f->len == 3) {
+ BMVert *verts[3];
+
+ BM_face_as_array_vert_tri((BMFace *)f, verts);
+
+ BM_vert_tri_calc_tangent_edge_pair(verts, r_tangent);
+ }
+ else if (f->len == 4) {
+ /* Use longest edge pair */
+ BMVert *verts[4];
+ float vec[3], vec_a[3], vec_b[3];
+
+ BM_face_as_array_vert_quad((BMFace *)f, verts);
+
+ sub_v3_v3v3(vec_a, verts[3]->co, verts[2]->co);
+ sub_v3_v3v3(vec_b, verts[0]->co, verts[1]->co);
+ add_v3_v3v3(r_tangent, vec_a, vec_b);
+
+ sub_v3_v3v3(vec_a, verts[0]->co, verts[3]->co);
+ sub_v3_v3v3(vec_b, verts[1]->co, verts[2]->co);
+ add_v3_v3v3(vec, vec_a, vec_b);
+ /* use the longest edge length */
+ if (len_squared_v3(r_tangent) < len_squared_v3(vec)) {
+ copy_v3_v3(r_tangent, vec);
+ }
+ }
+ else {
+ /* For ngons use two longest disconnected edges */
+ BMLoop *l_long = BM_face_find_longest_loop((BMFace *)f);
+ BMLoop *l_long_other = NULL;
+
+ float len_max_sq = 0.0f;
+ float vec_a[3], vec_b[3];
+
+ BMLoop *l_iter = l_long->prev->prev;
+ BMLoop *l_last = l_long->next;
+
+ do {
+ const float len_sq = len_squared_v3v3(l_iter->v->co, l_iter->next->v->co);
+ if (len_sq >= len_max_sq) {
+ l_long_other = l_iter;
+ len_max_sq = len_sq;
+ }
+ } while ((l_iter = l_iter->prev) != l_last);
+
+ sub_v3_v3v3(vec_a, l_long->next->v->co, l_long->v->co);
+ sub_v3_v3v3(vec_b, l_long_other->v->co, l_long_other->next->v->co);
+ add_v3_v3v3(r_tangent, vec_a, vec_b);
+
+ /* Edges may not be opposite side of the ngon,
+ * this could cause problems for ngons with multiple-aligned edges of the same length.
+ * Fallback to longest edge. */
+ if (UNLIKELY(normalize_v3(r_tangent) == 0.0f)) {
+ normalize_v3_v3(r_tangent, vec_a);
+ }
+ }
}
/**
@@ -478,35 +476,36 @@ void BM_face_calc_tangent_edge_pair(const BMFace *f, float r_tangent[3])
*
* \param r_tangent: Calculated unit length tangent (return value).
*/
-void BM_face_calc_tangent_edge_diagonal(const BMFace *f, float r_tangent[3])
+void BM_face_calc_tangent_edge_diagonal(const BMFace *f, float r_tangent[3])
{
- BMLoop *l_iter, *l_first;
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
-
- /* incase of degenerate faces */
- zero_v3(r_tangent);
-
- /* warning: O(n^2) loop here, take care! */
- float dist_max_sq = 0.0f;
- do {
- BMLoop *l_iter_other = l_iter->next;
- BMLoop *l_iter_last = l_iter->prev;
- do {
- BLI_assert(!ELEM(l_iter->v->co, l_iter_other->v->co, l_iter_other->next->v->co));
- float co_other[3], vec[3];
- closest_to_line_segment_v3(co_other, l_iter->v->co, l_iter_other->v->co, l_iter_other->next->v->co);
- sub_v3_v3v3(vec, l_iter->v->co, co_other);
-
- const float dist_sq = len_squared_v3(vec);
- if (dist_sq > dist_max_sq) {
- dist_max_sq = dist_sq;
- copy_v3_v3(r_tangent, vec);
- }
- } while ((l_iter_other = l_iter_other->next) != l_iter_last);
- } while ((l_iter = l_iter->next) != l_first);
-
- normalize_v3(r_tangent);
+ BMLoop *l_iter, *l_first;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+
+ /* incase of degenerate faces */
+ zero_v3(r_tangent);
+
+ /* warning: O(n^2) loop here, take care! */
+ float dist_max_sq = 0.0f;
+ do {
+ BMLoop *l_iter_other = l_iter->next;
+ BMLoop *l_iter_last = l_iter->prev;
+ do {
+ BLI_assert(!ELEM(l_iter->v->co, l_iter_other->v->co, l_iter_other->next->v->co));
+ float co_other[3], vec[3];
+ closest_to_line_segment_v3(
+ co_other, l_iter->v->co, l_iter_other->v->co, l_iter_other->next->v->co);
+ sub_v3_v3v3(vec, l_iter->v->co, co_other);
+
+ const float dist_sq = len_squared_v3(vec);
+ if (dist_sq > dist_max_sq) {
+ dist_max_sq = dist_sq;
+ copy_v3_v3(r_tangent, vec);
+ }
+ } while ((l_iter_other = l_iter_other->next) != l_iter_last);
+ } while ((l_iter = l_iter->next) != l_first);
+
+ normalize_v3(r_tangent);
}
/**
@@ -514,32 +513,32 @@ void BM_face_calc_tangent_edge_diagonal(const BMFace *f, float r_tangent[3])
*
* \note The logic is almost identical to #BM_face_calc_tangent_edge_diagonal
*/
-void BM_face_calc_tangent_vert_diagonal(const BMFace *f, float r_tangent[3])
+void BM_face_calc_tangent_vert_diagonal(const BMFace *f, float r_tangent[3])
{
- BMLoop *l_iter, *l_first;
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
-
- /* incase of degenerate faces */
- zero_v3(r_tangent);
-
- /* warning: O(n^2) loop here, take care! */
- float dist_max_sq = 0.0f;
- do {
- BMLoop *l_iter_other = l_iter->next;
- do {
- float vec[3];
- sub_v3_v3v3(vec, l_iter->v->co, l_iter_other->v->co);
-
- const float dist_sq = len_squared_v3(vec);
- if (dist_sq > dist_max_sq) {
- dist_max_sq = dist_sq;
- copy_v3_v3(r_tangent, vec);
- }
- } while ((l_iter_other = l_iter_other->next) != l_iter);
- } while ((l_iter = l_iter->next) != l_first);
-
- normalize_v3(r_tangent);
+ BMLoop *l_iter, *l_first;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+
+ /* incase of degenerate faces */
+ zero_v3(r_tangent);
+
+ /* warning: O(n^2) loop here, take care! */
+ float dist_max_sq = 0.0f;
+ do {
+ BMLoop *l_iter_other = l_iter->next;
+ do {
+ float vec[3];
+ sub_v3_v3v3(vec, l_iter->v->co, l_iter_other->v->co);
+
+ const float dist_sq = len_squared_v3(vec);
+ if (dist_sq > dist_max_sq) {
+ dist_max_sq = dist_sq;
+ copy_v3_v3(r_tangent, vec);
+ }
+ } while ((l_iter_other = l_iter_other->next) != l_iter);
+ } while ((l_iter = l_iter->next) != l_first);
+
+ normalize_v3(r_tangent);
}
/**
@@ -549,20 +548,20 @@ void BM_face_calc_tangent_vert_diagonal(const BMFace *f, float r_tangent[3])
*/
void BM_face_calc_tangent_auto(const BMFace *f, float r_tangent[3])
{
- if (f->len == 3) {
- /* most 'unique' edge of a triangle */
- BMVert *verts[3];
- BM_face_as_array_vert_tri((BMFace *)f, verts);
- BM_vert_tri_calc_tangent_edge(verts, r_tangent);
- }
- else if (f->len == 4) {
- /* longest edge pair of a quad */
- BM_face_calc_tangent_edge_pair((BMFace *)f, r_tangent);
- }
- else {
- /* longest edge of an ngon */
- BM_face_calc_tangent_edge((BMFace *)f, r_tangent);
- }
+ if (f->len == 3) {
+ /* most 'unique' edge of a triangle */
+ BMVert *verts[3];
+ BM_face_as_array_vert_tri((BMFace *)f, verts);
+ BM_vert_tri_calc_tangent_edge(verts, r_tangent);
+ }
+ else if (f->len == 4) {
+ /* longest edge pair of a quad */
+ BM_face_calc_tangent_edge_pair((BMFace *)f, r_tangent);
+ }
+ else {
+ /* longest edge of an ngon */
+ BM_face_calc_tangent_edge((BMFace *)f, r_tangent);
+ }
}
/**
@@ -570,11 +569,11 @@ void BM_face_calc_tangent_auto(const BMFace *f, float r_tangent[3])
*/
void BM_face_calc_bounds_expand(const BMFace *f, float min[3], float max[3])
{
- const BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- minmax_v3v3_v3(min, max, l_iter->v->co);
- } while ((l_iter = l_iter->next) != l_first);
+ const BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ minmax_v3v3_v3(min, max, l_iter->v->co);
+ } while ((l_iter = l_iter->next) != l_first);
}
/**
@@ -582,17 +581,17 @@ void BM_face_calc_bounds_expand(const BMFace *f, float min[3], float max[3])
*/
void BM_face_calc_center_bounds(const BMFace *f, float r_cent[3])
{
- const BMLoop *l_iter, *l_first;
- float min[3], max[3];
+ const BMLoop *l_iter, *l_first;
+ float min[3], max[3];
- INIT_MINMAX(min, max);
+ INIT_MINMAX(min, max);
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- minmax_v3v3_v3(min, max, l_iter->v->co);
- } while ((l_iter = l_iter->next) != l_first);
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ minmax_v3v3_v3(min, max, l_iter->v->co);
+ } while ((l_iter = l_iter->next) != l_first);
- mid_v3_v3v3(r_cent, min, max);
+ mid_v3_v3v3(r_cent, min, max);
}
/**
@@ -600,15 +599,15 @@ void BM_face_calc_center_bounds(const BMFace *f, float r_cent[3])
*/
void BM_face_calc_center_median(const BMFace *f, float r_cent[3])
{
- const BMLoop *l_iter, *l_first;
+ const BMLoop *l_iter, *l_first;
- zero_v3(r_cent);
+ zero_v3(r_cent);
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- add_v3_v3(r_cent, l_iter->v->co);
- } while ((l_iter = l_iter->next) != l_first);
- mul_v3_fl(r_cent, 1.0f / (float) f->len);
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ add_v3_v3(r_cent, l_iter->v->co);
+ } while ((l_iter = l_iter->next) != l_first);
+ mul_v3_fl(r_cent, 1.0f / (float)f->len);
}
/**
@@ -617,27 +616,26 @@ void BM_face_calc_center_median(const BMFace *f, float r_cent[3])
*/
void BM_face_calc_center_median_weighted(const BMFace *f, float r_cent[3])
{
- const BMLoop *l_iter;
- const BMLoop *l_first;
- float totw = 0.0f;
- float w_prev;
-
- zero_v3(r_cent);
-
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- w_prev = BM_edge_calc_length(l_iter->prev->e);
- do {
- const float w_curr = BM_edge_calc_length(l_iter->e);
- const float w = (w_curr + w_prev);
- madd_v3_v3fl(r_cent, l_iter->v->co, w);
- totw += w;
- w_prev = w_curr;
- } while ((l_iter = l_iter->next) != l_first);
-
- if (totw != 0.0f) {
- mul_v3_fl(r_cent, 1.0f / (float) totw);
- }
+ const BMLoop *l_iter;
+ const BMLoop *l_first;
+ float totw = 0.0f;
+ float w_prev;
+
+ zero_v3(r_cent);
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ w_prev = BM_edge_calc_length(l_iter->prev->e);
+ do {
+ const float w_curr = BM_edge_calc_length(l_iter->e);
+ const float w = (w_curr + w_prev);
+ madd_v3_v3fl(r_cent, l_iter->v->co, w);
+ totw += w;
+ w_prev = w_curr;
+ } while ((l_iter = l_iter->next) != l_first);
+
+ if (totw != 0.0f) {
+ mul_v3_fl(r_cent, 1.0f / (float)totw);
+ }
}
/**
@@ -648,17 +646,17 @@ void BM_face_calc_center_median_weighted(const BMFace *f, float r_cent[3])
*/
void poly_rotate_plane(const float normal[3], float (*verts)[3], const uint nverts)
{
- float mat[3][3];
- float co[3];
- uint i;
+ float mat[3][3];
+ float co[3];
+ uint i;
- co[2] = 0.0f;
+ co[2] = 0.0f;
- axis_dominant_v3_to_m3(mat, normal);
- for (i = 0; i < nverts; i++) {
- mul_v2_m3v3(co, mat, verts[i]);
- copy_v3_v3(verts[i], co);
- }
+ axis_dominant_v3_to_m3(mat, normal);
+ for (i = 0; i < nverts; i++) {
+ mul_v2_m3v3(co, mat, verts[i]);
+ copy_v3_v3(verts[i], co);
+ }
}
/**
@@ -666,119 +664,119 @@ void poly_rotate_plane(const float normal[3], float (*verts)[3], const uint nver
*/
void BM_edge_normals_update(BMEdge *e)
{
- BMIter iter;
- BMFace *f;
+ BMIter iter;
+ BMFace *f;
- BM_ITER_ELEM (f, &iter, e, BM_FACES_OF_EDGE) {
- BM_face_normal_update(f);
- }
+ BM_ITER_ELEM (f, &iter, e, BM_FACES_OF_EDGE) {
+ BM_face_normal_update(f);
+ }
- BM_vert_normal_update(e->v1);
- BM_vert_normal_update(e->v2);
+ BM_vert_normal_update(e->v1);
+ BM_vert_normal_update(e->v2);
}
static void bm_loop_normal_accum(const BMLoop *l, float no[3])
{
- float vec1[3], vec2[3], fac;
+ float vec1[3], vec2[3], fac;
- /* Same calculation used in BM_mesh_normals_update */
- sub_v3_v3v3(vec1, l->v->co, l->prev->v->co);
- sub_v3_v3v3(vec2, l->next->v->co, l->v->co);
- normalize_v3(vec1);
- normalize_v3(vec2);
+ /* Same calculation used in BM_mesh_normals_update */
+ sub_v3_v3v3(vec1, l->v->co, l->prev->v->co);
+ sub_v3_v3v3(vec2, l->next->v->co, l->v->co);
+ normalize_v3(vec1);
+ normalize_v3(vec2);
- fac = saacos(-dot_v3v3(vec1, vec2));
+ fac = saacos(-dot_v3v3(vec1, vec2));
- madd_v3_v3fl(no, l->f->no, fac);
+ madd_v3_v3fl(no, l->f->no, fac);
}
bool BM_vert_calc_normal_ex(const BMVert *v, const char hflag, float r_no[3])
{
- int len = 0;
-
- zero_v3(r_no);
-
- if (v->e) {
- const BMEdge *e = v->e;
- do {
- if (e->l) {
- const BMLoop *l = e->l;
- do {
- if (l->v == v) {
- if (BM_elem_flag_test(l->f, hflag)) {
- bm_loop_normal_accum(l, r_no);
- len++;
- }
- }
- } while ((l = l->radial_next) != e->l);
- }
- } while ((e = bmesh_disk_edge_next(e, v)) != v->e);
- }
-
- if (len) {
- normalize_v3(r_no);
- return true;
- }
- else {
- return false;
- }
+ int len = 0;
+
+ zero_v3(r_no);
+
+ if (v->e) {
+ const BMEdge *e = v->e;
+ do {
+ if (e->l) {
+ const BMLoop *l = e->l;
+ do {
+ if (l->v == v) {
+ if (BM_elem_flag_test(l->f, hflag)) {
+ bm_loop_normal_accum(l, r_no);
+ len++;
+ }
+ }
+ } while ((l = l->radial_next) != e->l);
+ }
+ } while ((e = bmesh_disk_edge_next(e, v)) != v->e);
+ }
+
+ if (len) {
+ normalize_v3(r_no);
+ return true;
+ }
+ else {
+ return false;
+ }
}
bool BM_vert_calc_normal(const BMVert *v, float r_no[3])
{
- int len = 0;
-
- zero_v3(r_no);
-
- if (v->e) {
- const BMEdge *e = v->e;
- do {
- if (e->l) {
- const BMLoop *l = e->l;
- do {
- if (l->v == v) {
- bm_loop_normal_accum(l, r_no);
- len++;
- }
- } while ((l = l->radial_next) != e->l);
- }
- } while ((e = bmesh_disk_edge_next(e, v)) != v->e);
- }
-
- if (len) {
- normalize_v3(r_no);
- return true;
- }
- else {
- return false;
- }
+ int len = 0;
+
+ zero_v3(r_no);
+
+ if (v->e) {
+ const BMEdge *e = v->e;
+ do {
+ if (e->l) {
+ const BMLoop *l = e->l;
+ do {
+ if (l->v == v) {
+ bm_loop_normal_accum(l, r_no);
+ len++;
+ }
+ } while ((l = l->radial_next) != e->l);
+ }
+ } while ((e = bmesh_disk_edge_next(e, v)) != v->e);
+ }
+
+ if (len) {
+ normalize_v3(r_no);
+ return true;
+ }
+ else {
+ return false;
+ }
}
void BM_vert_normal_update_all(BMVert *v)
{
- int len = 0;
-
- zero_v3(v->no);
-
- if (v->e) {
- const BMEdge *e = v->e;
- do {
- if (e->l) {
- const BMLoop *l = e->l;
- do {
- if (l->v == v) {
- BM_face_normal_update(l->f);
- bm_loop_normal_accum(l, v->no);
- len++;
- }
- } while ((l = l->radial_next) != e->l);
- }
- } while ((e = bmesh_disk_edge_next(e, v)) != v->e);
- }
-
- if (len) {
- normalize_v3(v->no);
- }
+ int len = 0;
+
+ zero_v3(v->no);
+
+ if (v->e) {
+ const BMEdge *e = v->e;
+ do {
+ if (e->l) {
+ const BMLoop *l = e->l;
+ do {
+ if (l->v == v) {
+ BM_face_normal_update(l->f);
+ bm_loop_normal_accum(l, v->no);
+ len++;
+ }
+ } while ((l = l->radial_next) != e->l);
+ }
+ } while ((e = bmesh_disk_edge_next(e, v)) != v->e);
+ }
+
+ if (len) {
+ normalize_v3(v->no);
+ }
}
/**
@@ -786,7 +784,7 @@ void BM_vert_normal_update_all(BMVert *v)
*/
void BM_vert_normal_update(BMVert *v)
{
- BM_vert_calc_normal(v, v->no);
+ BM_vert_calc_normal(v, v->no);
}
/**
@@ -801,73 +799,68 @@ void BM_vert_normal_update(BMVert *v)
float BM_face_calc_normal(const BMFace *f, float r_no[3])
{
- BMLoop *l;
-
- /* common cases first */
- switch (f->len) {
- case 4:
- {
- const float *co1 = (l = BM_FACE_FIRST_LOOP(f))->v->co;
- const float *co2 = (l = l->next)->v->co;
- const float *co3 = (l = l->next)->v->co;
- const float *co4 = (l->next)->v->co;
-
- return normal_quad_v3(r_no, co1, co2, co3, co4);
- }
- case 3:
- {
- const float *co1 = (l = BM_FACE_FIRST_LOOP(f))->v->co;
- const float *co2 = (l = l->next)->v->co;
- const float *co3 = (l->next)->v->co;
-
- return normal_tri_v3(r_no, co1, co2, co3);
- }
- default:
- {
- return bm_face_calc_poly_normal(f, r_no);
- }
- }
+ BMLoop *l;
+
+ /* common cases first */
+ switch (f->len) {
+ case 4: {
+ const float *co1 = (l = BM_FACE_FIRST_LOOP(f))->v->co;
+ const float *co2 = (l = l->next)->v->co;
+ const float *co3 = (l = l->next)->v->co;
+ const float *co4 = (l->next)->v->co;
+
+ return normal_quad_v3(r_no, co1, co2, co3, co4);
+ }
+ case 3: {
+ const float *co1 = (l = BM_FACE_FIRST_LOOP(f))->v->co;
+ const float *co2 = (l = l->next)->v->co;
+ const float *co3 = (l->next)->v->co;
+
+ return normal_tri_v3(r_no, co1, co2, co3);
+ }
+ default: {
+ return bm_face_calc_poly_normal(f, r_no);
+ }
+ }
}
void BM_face_normal_update(BMFace *f)
{
- BM_face_calc_normal(f, f->no);
+ BM_face_calc_normal(f, f->no);
}
/* exact same as 'BM_face_calc_normal' but accepts vertex coords */
-float BM_face_calc_normal_vcos(
- const BMesh *bm, const BMFace *f, float r_no[3],
- float const (*vertexCos)[3])
+float BM_face_calc_normal_vcos(const BMesh *bm,
+ const BMFace *f,
+ float r_no[3],
+ float const (*vertexCos)[3])
{
- BMLoop *l;
-
- /* must have valid index data */
- BLI_assert((bm->elem_index_dirty & BM_VERT) == 0);
- (void)bm;
-
- /* common cases first */
- switch (f->len) {
- case 4:
- {
- const float *co1 = vertexCos[BM_elem_index_get((l = BM_FACE_FIRST_LOOP(f))->v)];
- const float *co2 = vertexCos[BM_elem_index_get((l = l->next)->v)];
- const float *co3 = vertexCos[BM_elem_index_get((l = l->next)->v)];
- const float *co4 = vertexCos[BM_elem_index_get((l->next)->v)];
-
- return normal_quad_v3(r_no, co1, co2, co3, co4);
- }
- case 3:
- {
- const float *co1 = vertexCos[BM_elem_index_get((l = BM_FACE_FIRST_LOOP(f))->v)];
- const float *co2 = vertexCos[BM_elem_index_get((l = l->next)->v)];
- const float *co3 = vertexCos[BM_elem_index_get((l->next)->v)];
-
- return normal_tri_v3(r_no, co1, co2, co3);
- }
- default:
- {
- return bm_face_calc_poly_normal_vertex_cos(f, r_no, vertexCos);
- }
- }
+ BMLoop *l;
+
+ /* must have valid index data */
+ BLI_assert((bm->elem_index_dirty & BM_VERT) == 0);
+ (void)bm;
+
+ /* common cases first */
+ switch (f->len) {
+ case 4: {
+ const float *co1 = vertexCos[BM_elem_index_get((l = BM_FACE_FIRST_LOOP(f))->v)];
+ const float *co2 = vertexCos[BM_elem_index_get((l = l->next)->v)];
+ const float *co3 = vertexCos[BM_elem_index_get((l = l->next)->v)];
+ const float *co4 = vertexCos[BM_elem_index_get((l->next)->v)];
+
+ return normal_quad_v3(r_no, co1, co2, co3, co4);
+ }
+ case 3: {
+ const float *co1 = vertexCos[BM_elem_index_get((l = BM_FACE_FIRST_LOOP(f))->v)];
+ const float *co2 = vertexCos[BM_elem_index_get((l = l->next)->v)];
+ const float *co3 = vertexCos[BM_elem_index_get((l->next)->v)];
+
+ return normal_tri_v3(r_no, co1, co2, co3);
+ }
+ default: {
+ return bm_face_calc_poly_normal_vertex_cos(f, r_no, vertexCos);
+ }
+ }
}
/**
@@ -875,34 +868,35 @@ float BM_face_calc_normal_vcos(
*/
float BM_face_calc_normal_subset(const BMLoop *l_first, const BMLoop *l_last, float r_no[3])
{
- const float *v_prev, *v_curr;
+ const float *v_prev, *v_curr;
- /* Newell's Method */
- const BMLoop *l_iter = l_first;
- const BMLoop *l_term = l_last->next;
+ /* Newell's Method */
+ const BMLoop *l_iter = l_first;
+ const BMLoop *l_term = l_last->next;
- zero_v3(r_no);
+ zero_v3(r_no);
- v_prev = l_last->v->co;
- do {
- v_curr = l_iter->v->co;
- add_newell_cross_v3_v3v3(r_no, v_prev, v_curr);
- v_prev = v_curr;
- } while ((l_iter = l_iter->next) != l_term);
+ v_prev = l_last->v->co;
+ do {
+ v_curr = l_iter->v->co;
+ add_newell_cross_v3_v3v3(r_no, v_prev, v_curr);
+ v_prev = v_curr;
+ } while ((l_iter = l_iter->next) != l_term);
- return normalize_v3(r_no);
+ return normalize_v3(r_no);
}
/* exact same as 'BM_face_calc_normal' but accepts vertex coords */
-void BM_face_calc_center_median_vcos(
- const BMesh *bm, const BMFace *f, float r_cent[3],
- float const (*vertexCos)[3])
+void BM_face_calc_center_median_vcos(const BMesh *bm,
+ const BMFace *f,
+ float r_cent[3],
+ float const (*vertexCos)[3])
{
- /* must have valid index data */
- BLI_assert((bm->elem_index_dirty & BM_VERT) == 0);
- (void)bm;
+ /* must have valid index data */
+ BLI_assert((bm->elem_index_dirty & BM_VERT) == 0);
+ (void)bm;
- bm_face_calc_poly_center_median_vertex_cos(f, r_cent, vertexCos);
+ bm_face_calc_poly_center_median_vertex_cos(f, r_cent, vertexCos);
}
/**
@@ -911,18 +905,19 @@ void BM_face_calc_center_median_vcos(
* Reverses the winding of a face.
* \note This updates the calculated normal.
*/
-void BM_face_normal_flip_ex(
- BMesh *bm, BMFace *f,
- const int cd_loop_mdisp_offset, const bool use_loop_mdisp_flip)
+void BM_face_normal_flip_ex(BMesh *bm,
+ BMFace *f,
+ const int cd_loop_mdisp_offset,
+ const bool use_loop_mdisp_flip)
{
- bmesh_kernel_loop_reverse(bm, f, cd_loop_mdisp_offset, use_loop_mdisp_flip);
- negate_v3(f->no);
+ bmesh_kernel_loop_reverse(bm, f, cd_loop_mdisp_offset, use_loop_mdisp_flip);
+ negate_v3(f->no);
}
void BM_face_normal_flip(BMesh *bm, BMFace *f)
{
- const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
- BM_face_normal_flip_ex(bm, f, cd_loop_mdisp_offset, true);
+ const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
+ BM_face_normal_flip_ex(bm, f, cd_loop_mdisp_offset, true);
}
/**
@@ -937,24 +932,24 @@ void BM_face_normal_flip(BMesh *bm, BMFace *f)
*/
bool BM_face_point_inside_test(const BMFace *f, const float co[3])
{
- float axis_mat[3][3];
- float (*projverts)[2] = BLI_array_alloca(projverts, f->len);
+ float axis_mat[3][3];
+ float(*projverts)[2] = BLI_array_alloca(projverts, f->len);
- float co_2d[2];
- BMLoop *l_iter;
- int i;
+ float co_2d[2];
+ BMLoop *l_iter;
+ int i;
- BLI_assert(BM_face_is_normal_valid(f));
+ BLI_assert(BM_face_is_normal_valid(f));
- axis_dominant_v3_to_m3(axis_mat, f->no);
+ axis_dominant_v3_to_m3(axis_mat, f->no);
- mul_v2_m3v3(co_2d, axis_mat, co);
+ mul_v2_m3v3(co_2d, axis_mat, co);
- for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l_iter = l_iter->next) {
- mul_v2_m3v3(projverts[i], axis_mat, l_iter->v->co);
- }
+ for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l_iter = l_iter->next) {
+ mul_v2_m3v3(projverts[i], axis_mat, l_iter->v->co);
+ }
- return isect_point_poly_v2(co_2d, projverts, f->len, false);
+ return isect_point_poly_v2(co_2d, projverts, f->len, false);
}
/**
@@ -980,236 +975,226 @@ bool BM_face_point_inside_test(const BMFace *f, const float co[3])
*
* \note use_tag tags new flags and edges.
*/
-void BM_face_triangulate(
- BMesh *bm, BMFace *f,
- BMFace **r_faces_new,
- int *r_faces_new_tot,
- BMEdge **r_edges_new,
- int *r_edges_new_tot,
- LinkNode **r_faces_double,
- const int quad_method,
- const int ngon_method,
- const bool use_tag,
- /* use for ngons only! */
- MemArena *pf_arena,
-
- /* use for MOD_TRIANGULATE_NGON_BEAUTY only! */
- struct Heap *pf_heap)
+void BM_face_triangulate(BMesh *bm,
+ BMFace *f,
+ BMFace **r_faces_new,
+ int *r_faces_new_tot,
+ BMEdge **r_edges_new,
+ int *r_edges_new_tot,
+ LinkNode **r_faces_double,
+ const int quad_method,
+ const int ngon_method,
+ const bool use_tag,
+ /* use for ngons only! */
+ MemArena *pf_arena,
+
+ /* use for MOD_TRIANGULATE_NGON_BEAUTY only! */
+ struct Heap *pf_heap)
{
- const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
- const bool use_beauty = (ngon_method == MOD_TRIANGULATE_NGON_BEAUTY);
- BMLoop *l_first, *l_new;
- BMFace *f_new;
- int nf_i = 0;
- int ne_i = 0;
-
- BLI_assert(BM_face_is_normal_valid(f));
-
- /* ensure both are valid or NULL */
- BLI_assert((r_faces_new == NULL) == (r_faces_new_tot == NULL));
-
- BLI_assert(f->len > 3);
-
- {
- BMLoop **loops = BLI_array_alloca(loops, f->len);
- uint (*tris)[3] = BLI_array_alloca(tris, f->len);
- const int totfilltri = f->len - 2;
- const int last_tri = f->len - 3;
- int i;
- /* for mdisps */
- float f_center[3];
-
- if (f->len == 4) {
- /* even though we're not using BLI_polyfill, fill in 'tris' and 'loops'
- * so we can share code to handle face creation afterwards. */
- BMLoop *l_v1, *l_v2;
-
- l_first = BM_FACE_FIRST_LOOP(f);
-
- switch (quad_method) {
- case MOD_TRIANGULATE_QUAD_FIXED:
- {
- l_v1 = l_first;
- l_v2 = l_first->next->next;
- break;
- }
- case MOD_TRIANGULATE_QUAD_ALTERNATE:
- {
- l_v1 = l_first->next;
- l_v2 = l_first->prev;
- break;
- }
- case MOD_TRIANGULATE_QUAD_SHORTEDGE:
- case MOD_TRIANGULATE_QUAD_BEAUTY:
- default:
- {
- BMLoop *l_v3, *l_v4;
- bool split_24;
-
- l_v1 = l_first->next;
- l_v2 = l_first->next->next;
- l_v3 = l_first->prev;
- l_v4 = l_first;
-
- if (quad_method == MOD_TRIANGULATE_QUAD_SHORTEDGE) {
- float d1, d2;
- d1 = len_squared_v3v3(l_v4->v->co, l_v2->v->co);
- d2 = len_squared_v3v3(l_v1->v->co, l_v3->v->co);
- split_24 = ((d2 - d1) > 0.0f);
- }
- else {
- /* first check if the quad is concave on either diagonal */
- const int flip_flag = is_quad_flip_v3(l_v1->v->co, l_v2->v->co, l_v3->v->co, l_v4->v->co);
- if (UNLIKELY(flip_flag & (1 << 0))) {
- split_24 = true;
- }
- else if (UNLIKELY(flip_flag & (1 << 1))) {
- split_24 = false;
- }
- else {
- split_24 = (BM_verts_calc_rotate_beauty(l_v1->v, l_v2->v, l_v3->v, l_v4->v, 0, 0) > 0.0f);
- }
- }
-
- /* named confusingly, l_v1 is in fact the second vertex */
- if (split_24) {
- l_v1 = l_v4;
- //l_v2 = l_v2;
- }
- else {
- //l_v1 = l_v1;
- l_v2 = l_v3;
- }
- break;
- }
- }
-
- loops[0] = l_v1;
- loops[1] = l_v1->next;
- loops[2] = l_v2;
- loops[3] = l_v2->next;
-
- ARRAY_SET_ITEMS(tris[0], 0, 1, 2);
- ARRAY_SET_ITEMS(tris[1], 0, 2, 3);
- }
- else {
- BMLoop *l_iter;
- float axis_mat[3][3];
- float (*projverts)[2] = BLI_array_alloca(projverts, f->len);
-
- axis_dominant_v3_to_m3_negate(axis_mat, f->no);
-
- for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l_iter = l_iter->next) {
- loops[i] = l_iter;
- mul_v2_m3v3(projverts[i], axis_mat, l_iter->v->co);
- }
-
- BLI_polyfill_calc_arena(projverts, f->len, 1, tris,
- pf_arena);
-
- if (use_beauty) {
- BLI_polyfill_beautify(
- projverts, f->len, tris,
- pf_arena, pf_heap);
- }
-
- BLI_memarena_clear(pf_arena);
- }
-
- if (cd_loop_mdisp_offset != -1) {
- BM_face_calc_center_median(f, f_center);
- }
-
- /* loop over calculated triangles and create new geometry */
- for (i = 0; i < totfilltri; i++) {
- BMLoop *l_tri[3] = {
- loops[tris[i][0]],
- loops[tris[i][1]],
- loops[tris[i][2]]};
-
- BMVert *v_tri[3] = {
- l_tri[0]->v,
- l_tri[1]->v,
- l_tri[2]->v};
-
- f_new = BM_face_create_verts(bm, v_tri, 3, f, BM_CREATE_NOP, true);
- l_new = BM_FACE_FIRST_LOOP(f_new);
-
- BLI_assert(v_tri[0] == l_new->v);
-
- /* check for duplicate */
- if (l_new->radial_next != l_new) {
- BMLoop *l_iter = l_new->radial_next;
- do {
- if (UNLIKELY((l_iter->f->len == 3) && (l_new->prev->v == l_iter->prev->v))) {
- /* Check the last tri because we swap last f_new with f at the end... */
- BLI_linklist_prepend(r_faces_double, (i != last_tri) ? f_new : f);
- break;
- }
- } while ((l_iter = l_iter->radial_next) != l_new);
- }
-
- /* copy CD data */
- BM_elem_attrs_copy(bm, bm, l_tri[0], l_new);
- BM_elem_attrs_copy(bm, bm, l_tri[1], l_new->next);
- BM_elem_attrs_copy(bm, bm, l_tri[2], l_new->prev);
-
- /* add all but the last face which is swapped and removed (below) */
- if (i != last_tri) {
- if (use_tag) {
- BM_elem_flag_enable(f_new, BM_ELEM_TAG);
- }
- if (r_faces_new) {
- r_faces_new[nf_i++] = f_new;
- }
- }
-
- if (use_tag || r_edges_new) {
- /* new faces loops */
- BMLoop *l_iter;
-
- l_iter = l_first = l_new;
- do {
- BMEdge *e = l_iter->e;
- /* confusing! if its not a boundary now, we know it will be later
- * since this will be an edge of one of the new faces which we're in the middle of creating */
- bool is_new_edge = (l_iter == l_iter->radial_next);
-
- if (is_new_edge) {
- if (use_tag) {
- BM_elem_flag_enable(e, BM_ELEM_TAG);
- }
- if (r_edges_new) {
- r_edges_new[ne_i++] = e;
- }
- }
- /* note, never disable tag's */
- } while ((l_iter = l_iter->next) != l_first);
- }
-
- 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);
- }
- }
-
- {
- /* we can't delete the real face, because some of the callers expect it to remain valid.
- * so swap data and delete the last created tri */
- bmesh_face_swap_data(f, f_new);
- BM_face_kill(bm, f_new);
- }
- }
- bm->elem_index_dirty |= BM_FACE;
-
- if (r_faces_new_tot) {
- *r_faces_new_tot = nf_i;
- }
-
- if (r_edges_new_tot) {
- *r_edges_new_tot = ne_i;
- }
+ const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
+ const bool use_beauty = (ngon_method == MOD_TRIANGULATE_NGON_BEAUTY);
+ BMLoop *l_first, *l_new;
+ BMFace *f_new;
+ int nf_i = 0;
+ int ne_i = 0;
+
+ BLI_assert(BM_face_is_normal_valid(f));
+
+ /* ensure both are valid or NULL */
+ BLI_assert((r_faces_new == NULL) == (r_faces_new_tot == NULL));
+
+ BLI_assert(f->len > 3);
+
+ {
+ BMLoop **loops = BLI_array_alloca(loops, f->len);
+ uint(*tris)[3] = BLI_array_alloca(tris, f->len);
+ const int totfilltri = f->len - 2;
+ const int last_tri = f->len - 3;
+ int i;
+ /* for mdisps */
+ float f_center[3];
+
+ if (f->len == 4) {
+ /* even though we're not using BLI_polyfill, fill in 'tris' and 'loops'
+ * so we can share code to handle face creation afterwards. */
+ BMLoop *l_v1, *l_v2;
+
+ l_first = BM_FACE_FIRST_LOOP(f);
+
+ switch (quad_method) {
+ case MOD_TRIANGULATE_QUAD_FIXED: {
+ l_v1 = l_first;
+ l_v2 = l_first->next->next;
+ break;
+ }
+ case MOD_TRIANGULATE_QUAD_ALTERNATE: {
+ l_v1 = l_first->next;
+ l_v2 = l_first->prev;
+ break;
+ }
+ case MOD_TRIANGULATE_QUAD_SHORTEDGE:
+ case MOD_TRIANGULATE_QUAD_BEAUTY:
+ default: {
+ BMLoop *l_v3, *l_v4;
+ bool split_24;
+
+ l_v1 = l_first->next;
+ l_v2 = l_first->next->next;
+ l_v3 = l_first->prev;
+ l_v4 = l_first;
+
+ if (quad_method == MOD_TRIANGULATE_QUAD_SHORTEDGE) {
+ float d1, d2;
+ d1 = len_squared_v3v3(l_v4->v->co, l_v2->v->co);
+ d2 = len_squared_v3v3(l_v1->v->co, l_v3->v->co);
+ split_24 = ((d2 - d1) > 0.0f);
+ }
+ else {
+ /* first check if the quad is concave on either diagonal */
+ const int flip_flag = is_quad_flip_v3(
+ l_v1->v->co, l_v2->v->co, l_v3->v->co, l_v4->v->co);
+ if (UNLIKELY(flip_flag & (1 << 0))) {
+ split_24 = true;
+ }
+ else if (UNLIKELY(flip_flag & (1 << 1))) {
+ split_24 = false;
+ }
+ else {
+ split_24 = (BM_verts_calc_rotate_beauty(l_v1->v, l_v2->v, l_v3->v, l_v4->v, 0, 0) >
+ 0.0f);
+ }
+ }
+
+ /* named confusingly, l_v1 is in fact the second vertex */
+ if (split_24) {
+ l_v1 = l_v4;
+ //l_v2 = l_v2;
+ }
+ else {
+ //l_v1 = l_v1;
+ l_v2 = l_v3;
+ }
+ break;
+ }
+ }
+
+ loops[0] = l_v1;
+ loops[1] = l_v1->next;
+ loops[2] = l_v2;
+ loops[3] = l_v2->next;
+
+ ARRAY_SET_ITEMS(tris[0], 0, 1, 2);
+ ARRAY_SET_ITEMS(tris[1], 0, 2, 3);
+ }
+ else {
+ BMLoop *l_iter;
+ float axis_mat[3][3];
+ float(*projverts)[2] = BLI_array_alloca(projverts, f->len);
+
+ axis_dominant_v3_to_m3_negate(axis_mat, f->no);
+
+ for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l_iter = l_iter->next) {
+ loops[i] = l_iter;
+ mul_v2_m3v3(projverts[i], axis_mat, l_iter->v->co);
+ }
+
+ BLI_polyfill_calc_arena(projverts, f->len, 1, tris, pf_arena);
+
+ if (use_beauty) {
+ BLI_polyfill_beautify(projverts, f->len, tris, pf_arena, pf_heap);
+ }
+
+ BLI_memarena_clear(pf_arena);
+ }
+
+ if (cd_loop_mdisp_offset != -1) {
+ BM_face_calc_center_median(f, f_center);
+ }
+
+ /* loop over calculated triangles and create new geometry */
+ for (i = 0; i < totfilltri; i++) {
+ BMLoop *l_tri[3] = {loops[tris[i][0]], loops[tris[i][1]], loops[tris[i][2]]};
+
+ BMVert *v_tri[3] = {l_tri[0]->v, l_tri[1]->v, l_tri[2]->v};
+
+ f_new = BM_face_create_verts(bm, v_tri, 3, f, BM_CREATE_NOP, true);
+ l_new = BM_FACE_FIRST_LOOP(f_new);
+
+ BLI_assert(v_tri[0] == l_new->v);
+
+ /* check for duplicate */
+ if (l_new->radial_next != l_new) {
+ BMLoop *l_iter = l_new->radial_next;
+ do {
+ if (UNLIKELY((l_iter->f->len == 3) && (l_new->prev->v == l_iter->prev->v))) {
+ /* Check the last tri because we swap last f_new with f at the end... */
+ BLI_linklist_prepend(r_faces_double, (i != last_tri) ? f_new : f);
+ break;
+ }
+ } while ((l_iter = l_iter->radial_next) != l_new);
+ }
+
+ /* copy CD data */
+ BM_elem_attrs_copy(bm, bm, l_tri[0], l_new);
+ BM_elem_attrs_copy(bm, bm, l_tri[1], l_new->next);
+ BM_elem_attrs_copy(bm, bm, l_tri[2], l_new->prev);
+
+ /* add all but the last face which is swapped and removed (below) */
+ if (i != last_tri) {
+ if (use_tag) {
+ BM_elem_flag_enable(f_new, BM_ELEM_TAG);
+ }
+ if (r_faces_new) {
+ r_faces_new[nf_i++] = f_new;
+ }
+ }
+
+ if (use_tag || r_edges_new) {
+ /* new faces loops */
+ BMLoop *l_iter;
+
+ l_iter = l_first = l_new;
+ do {
+ BMEdge *e = l_iter->e;
+ /* confusing! if its not a boundary now, we know it will be later
+ * since this will be an edge of one of the new faces which we're in the middle of creating */
+ bool is_new_edge = (l_iter == l_iter->radial_next);
+
+ if (is_new_edge) {
+ if (use_tag) {
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
+ }
+ if (r_edges_new) {
+ r_edges_new[ne_i++] = e;
+ }
+ }
+ /* note, never disable tag's */
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+
+ 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);
+ }
+ }
+
+ {
+ /* we can't delete the real face, because some of the callers expect it to remain valid.
+ * so swap data and delete the last created tri */
+ bmesh_face_swap_data(f, f_new);
+ BM_face_kill(bm, f_new);
+ }
+ }
+ bm->elem_index_dirty |= BM_FACE;
+
+ if (r_faces_new_tot) {
+ *r_faces_new_tot = nf_i;
+ }
+
+ if (r_edges_new_tot) {
+ *r_edges_new_tot = ne_i;
+ }
}
/**
@@ -1222,101 +1207,97 @@ void BM_face_triangulate(
*/
void BM_face_splits_check_legal(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len)
{
- float out[2] = {-FLT_MAX, -FLT_MAX};
- float center[2] = {0.0f, 0.0f};
- float axis_mat[3][3];
- float (*projverts)[2] = BLI_array_alloca(projverts, f->len);
- const float *(*edgeverts)[2] = BLI_array_alloca(edgeverts, len);
- BMLoop *l;
- int i, i_prev, j;
-
- BLI_assert(BM_face_is_normal_valid(f));
-
- axis_dominant_v3_to_m3(axis_mat, f->no);
-
- for (i = 0, l = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l = l->next) {
- mul_v2_m3v3(projverts[i], axis_mat, l->v->co);
- add_v2_v2(center, projverts[i]);
- }
-
- /* first test for completely convex face */
- if (is_poly_convex_v2(projverts, f->len)) {
- return;
- }
-
- mul_v2_fl(center, 1.0f / f->len);
-
- for (i = 0, l = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l = l->next) {
- BM_elem_index_set(l, i); /* set_dirty */
-
- /* center the projection for maximum accuracy */
- sub_v2_v2(projverts[i], center);
-
- out[0] = max_ff(out[0], projverts[i][0]);
- out[1] = max_ff(out[1], projverts[i][1]);
- }
- bm->elem_index_dirty |= BM_LOOP;
-
- /* ensure we are well outside the face bounds (value is arbitrary) */
- add_v2_fl(out, 1.0f);
-
- for (i = 0; i < len; i++) {
- edgeverts[i][0] = projverts[BM_elem_index_get(loops[i][0])];
- edgeverts[i][1] = projverts[BM_elem_index_get(loops[i][1])];
- }
-
- /* do convexity test */
- for (i = 0; i < len; i++) {
- float mid[2];
- mid_v2_v2v2(mid, edgeverts[i][0], edgeverts[i][1]);
-
- int isect = 0;
- int j_prev;
- for (j = 0, j_prev = f->len - 1; j < f->len; j_prev = j++) {
- const float *f_edge[2] = {projverts[j_prev], projverts[j]};
- if (isect_seg_seg_v2(UNPACK2(f_edge), mid, out) == ISECT_LINE_LINE_CROSS) {
- isect++;
- }
- }
-
- if (isect % 2 == 0) {
- loops[i][0] = NULL;
- }
- }
+ float out[2] = {-FLT_MAX, -FLT_MAX};
+ float center[2] = {0.0f, 0.0f};
+ float axis_mat[3][3];
+ float(*projverts)[2] = BLI_array_alloca(projverts, f->len);
+ const float *(*edgeverts)[2] = BLI_array_alloca(edgeverts, len);
+ BMLoop *l;
+ int i, i_prev, j;
+
+ BLI_assert(BM_face_is_normal_valid(f));
+
+ axis_dominant_v3_to_m3(axis_mat, f->no);
+
+ for (i = 0, l = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l = l->next) {
+ mul_v2_m3v3(projverts[i], axis_mat, l->v->co);
+ add_v2_v2(center, projverts[i]);
+ }
+
+ /* first test for completely convex face */
+ if (is_poly_convex_v2(projverts, f->len)) {
+ return;
+ }
+
+ mul_v2_fl(center, 1.0f / f->len);
+
+ for (i = 0, l = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l = l->next) {
+ BM_elem_index_set(l, i); /* set_dirty */
+
+ /* center the projection for maximum accuracy */
+ sub_v2_v2(projverts[i], center);
+
+ out[0] = max_ff(out[0], projverts[i][0]);
+ out[1] = max_ff(out[1], projverts[i][1]);
+ }
+ bm->elem_index_dirty |= BM_LOOP;
+
+ /* ensure we are well outside the face bounds (value is arbitrary) */
+ add_v2_fl(out, 1.0f);
+
+ for (i = 0; i < len; i++) {
+ edgeverts[i][0] = projverts[BM_elem_index_get(loops[i][0])];
+ edgeverts[i][1] = projverts[BM_elem_index_get(loops[i][1])];
+ }
+
+ /* do convexity test */
+ for (i = 0; i < len; i++) {
+ float mid[2];
+ mid_v2_v2v2(mid, edgeverts[i][0], edgeverts[i][1]);
+
+ int isect = 0;
+ int j_prev;
+ for (j = 0, j_prev = f->len - 1; j < f->len; j_prev = j++) {
+ const float *f_edge[2] = {projverts[j_prev], projverts[j]};
+ if (isect_seg_seg_v2(UNPACK2(f_edge), mid, out) == ISECT_LINE_LINE_CROSS) {
+ isect++;
+ }
+ }
+
+ if (isect % 2 == 0) {
+ loops[i][0] = NULL;
+ }
+ }
#define EDGE_SHARE_VERT(e1, e2) \
- ((ELEM((e1)[0], (e2)[0], (e2)[1])) || \
- (ELEM((e1)[1], (e2)[0], (e2)[1])))
-
- /* do line crossing tests */
- for (i = 0, i_prev = f->len - 1; i < f->len; i_prev = i++) {
- const float *f_edge[2] = {projverts[i_prev], projverts[i]};
- for (j = 0; j < len; j++) {
- if ((loops[j][0] != NULL) &&
- !EDGE_SHARE_VERT(f_edge, edgeverts[j]))
- {
- if (isect_seg_seg_v2(UNPACK2(f_edge), UNPACK2(edgeverts[j])) == ISECT_LINE_LINE_CROSS) {
- loops[j][0] = NULL;
- }
- }
- }
- }
-
- /* self intersect tests */
- for (i = 0; i < len; i++) {
- if (loops[i][0]) {
- for (j = i + 1; j < len; j++) {
- if ((loops[j][0] != NULL) &&
- !EDGE_SHARE_VERT(edgeverts[i], edgeverts[j]))
- {
- if (isect_seg_seg_v2(UNPACK2(edgeverts[i]), UNPACK2(edgeverts[j])) == ISECT_LINE_LINE_CROSS) {
- loops[i][0] = NULL;
- break;
- }
- }
- }
- }
- }
+ ((ELEM((e1)[0], (e2)[0], (e2)[1])) || (ELEM((e1)[1], (e2)[0], (e2)[1])))
+
+ /* do line crossing tests */
+ for (i = 0, i_prev = f->len - 1; i < f->len; i_prev = i++) {
+ const float *f_edge[2] = {projverts[i_prev], projverts[i]};
+ for (j = 0; j < len; j++) {
+ if ((loops[j][0] != NULL) && !EDGE_SHARE_VERT(f_edge, edgeverts[j])) {
+ if (isect_seg_seg_v2(UNPACK2(f_edge), UNPACK2(edgeverts[j])) == ISECT_LINE_LINE_CROSS) {
+ loops[j][0] = NULL;
+ }
+ }
+ }
+ }
+
+ /* self intersect tests */
+ for (i = 0; i < len; i++) {
+ if (loops[i][0]) {
+ for (j = i + 1; j < len; j++) {
+ if ((loops[j][0] != NULL) && !EDGE_SHARE_VERT(edgeverts[i], edgeverts[j])) {
+ if (isect_seg_seg_v2(UNPACK2(edgeverts[i]), UNPACK2(edgeverts[j])) ==
+ ISECT_LINE_LINE_CROSS) {
+ loops[i][0] = NULL;
+ break;
+ }
+ }
+ }
+ }
+ }
#undef EDGE_SHARE_VERT
}
@@ -1327,14 +1308,15 @@ void BM_face_splits_check_legal(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int l
*/
void BM_face_splits_check_optimal(BMFace *f, BMLoop *(*loops)[2], int len)
{
- int i;
-
- for (i = 0; i < len; i++) {
- BMLoop *l_a_dummy, *l_b_dummy;
- if (f != BM_vert_pair_share_face_by_angle(loops[i][0]->v, loops[i][1]->v, &l_a_dummy, &l_b_dummy, false)) {
- loops[i][0] = NULL;
- }
- }
+ int i;
+
+ for (i = 0; i < len; i++) {
+ BMLoop *l_a_dummy, *l_b_dummy;
+ if (f != BM_vert_pair_share_face_by_angle(
+ loops[i][0]->v, loops[i][1]->v, &l_a_dummy, &l_b_dummy, false)) {
+ loops[i][0] = NULL;
+ }
+ }
}
/**
@@ -1345,13 +1327,15 @@ void BM_face_splits_check_optimal(BMFace *f, BMLoop *(*loops)[2], int len)
*/
void BM_face_as_array_vert_tri(BMFace *f, BMVert *r_verts[3])
{
- BMLoop *l = BM_FACE_FIRST_LOOP(f);
+ BMLoop *l = BM_FACE_FIRST_LOOP(f);
- BLI_assert(f->len == 3);
+ BLI_assert(f->len == 3);
- r_verts[0] = l->v; l = l->next;
- r_verts[1] = l->v; l = l->next;
- r_verts[2] = l->v;
+ r_verts[0] = l->v;
+ l = l->next;
+ r_verts[1] = l->v;
+ l = l->next;
+ r_verts[2] = l->v;
}
/**
@@ -1360,17 +1344,19 @@ void BM_face_as_array_vert_tri(BMFace *f, BMVert *r_verts[3])
*/
void BM_face_as_array_vert_quad(BMFace *f, BMVert *r_verts[4])
{
- BMLoop *l = BM_FACE_FIRST_LOOP(f);
+ BMLoop *l = BM_FACE_FIRST_LOOP(f);
- BLI_assert(f->len == 4);
+ BLI_assert(f->len == 4);
- r_verts[0] = l->v; l = l->next;
- r_verts[1] = l->v; l = l->next;
- r_verts[2] = l->v; l = l->next;
- r_verts[3] = l->v;
+ r_verts[0] = l->v;
+ l = l->next;
+ r_verts[1] = l->v;
+ l = l->next;
+ r_verts[2] = l->v;
+ l = l->next;
+ r_verts[3] = l->v;
}
-
/**
* Small utility functions for fast access
*
@@ -1379,13 +1365,15 @@ void BM_face_as_array_vert_quad(BMFace *f, BMVert *r_verts[4])
*/
void BM_face_as_array_loop_tri(BMFace *f, BMLoop *r_loops[3])
{
- BMLoop *l = BM_FACE_FIRST_LOOP(f);
+ BMLoop *l = BM_FACE_FIRST_LOOP(f);
- BLI_assert(f->len == 3);
+ BLI_assert(f->len == 3);
- r_loops[0] = l; l = l->next;
- r_loops[1] = l; l = l->next;
- r_loops[2] = l;
+ r_loops[0] = l;
+ l = l->next;
+ r_loops[1] = l;
+ l = l->next;
+ r_loops[2] = l;
}
/**
@@ -1394,17 +1382,19 @@ void BM_face_as_array_loop_tri(BMFace *f, BMLoop *r_loops[3])
*/
void BM_face_as_array_loop_quad(BMFace *f, BMLoop *r_loops[4])
{
- BMLoop *l = BM_FACE_FIRST_LOOP(f);
+ BMLoop *l = BM_FACE_FIRST_LOOP(f);
- BLI_assert(f->len == 4);
+ BLI_assert(f->len == 4);
- r_loops[0] = l; l = l->next;
- r_loops[1] = l; l = l->next;
- r_loops[2] = l; l = l->next;
- r_loops[3] = l;
+ r_loops[0] = l;
+ l = l->next;
+ r_loops[1] = l;
+ l = l->next;
+ r_loops[2] = l;
+ l = l->next;
+ r_loops[3] = l;
}
-
/**
* \brief BM_mesh_calc_tessellation get the looptris and its number from a certain bmesh
* \param looptris:
@@ -1413,287 +1403,280 @@ void BM_face_as_array_loop_quad(BMFace *f, BMLoop *r_loops[4])
*/
void BM_mesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptris_tot)
{
- /* use this to avoid locking pthread for _every_ polygon
- * and calling the fill function */
+ /* use this to avoid locking pthread for _every_ polygon
+ * and calling the fill function */
#define USE_TESSFACE_SPEEDUP
- /* this assumes all faces can be scan-filled, which isn't always true,
- * worst case we over alloc a little which is acceptable */
+ /* this assumes all faces can be scan-filled, which isn't always true,
+ * worst case we over alloc a little which is acceptable */
#ifndef NDEBUG
- const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop);
+ const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop);
#endif
- BMIter iter;
- BMFace *efa;
- int i = 0;
+ BMIter iter;
+ BMFace *efa;
+ int i = 0;
- MemArena *arena = NULL;
+ MemArena *arena = NULL;
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- /* don't consider two-edged faces */
- if (UNLIKELY(efa->len < 3)) {
- /* do nothing */
- }
+ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
+ /* don't consider two-edged faces */
+ if (UNLIKELY(efa->len < 3)) {
+ /* do nothing */
+ }
#ifdef USE_TESSFACE_SPEEDUP
- /* no need to ensure the loop order, we know its ok */
-
- else if (efa->len == 3) {
-#if 0
- int j;
- BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, j) {
- looptris[i][j] = l;
- }
- i += 1;
-#else
- /* more cryptic but faster */
- BMLoop *l;
- BMLoop **l_ptr = looptris[i++];
- l_ptr[0] = l = BM_FACE_FIRST_LOOP(efa);
- l_ptr[1] = l = l->next;
- l_ptr[2] = l->next;
-#endif
- }
- else if (efa->len == 4) {
-#if 0
- BMLoop *ltmp[4];
- int j;
- BLI_array_grow_items(looptris, 2);
- BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, j) {
- ltmp[j] = l;
- }
-
- looptris[i][0] = ltmp[0];
- looptris[i][1] = ltmp[1];
- looptris[i][2] = ltmp[2];
- i += 1;
-
- looptris[i][0] = ltmp[0];
- looptris[i][1] = ltmp[2];
- looptris[i][2] = ltmp[3];
- i += 1;
-#else
- /* more cryptic but faster */
- BMLoop *l;
- BMLoop **l_ptr_a = looptris[i++];
- BMLoop **l_ptr_b = looptris[i++];
- (l_ptr_a[0] = l_ptr_b[0] = l = BM_FACE_FIRST_LOOP(efa));
- (l_ptr_a[1] = l = l->next);
- (l_ptr_a[2] = l_ptr_b[1] = l = l->next);
- ( l_ptr_b[2] = l->next);
-#endif
-
- if (UNLIKELY(is_quad_flip_v3_first_third_fast(
- l_ptr_a[0]->v->co,
- l_ptr_a[1]->v->co,
- l_ptr_a[2]->v->co,
- l_ptr_b[2]->v->co)))
- {
- /* flip out of degenerate 0-2 state. */
- l_ptr_a[2] = l_ptr_b[2];
- l_ptr_b[0] = l_ptr_a[1];
- }
- }
+ /* no need to ensure the loop order, we know its ok */
+
+ else if (efa->len == 3) {
+# if 0
+ int j;
+ BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, j) {
+ looptris[i][j] = l;
+ }
+ i += 1;
+# else
+ /* more cryptic but faster */
+ BMLoop *l;
+ BMLoop **l_ptr = looptris[i++];
+ l_ptr[0] = l = BM_FACE_FIRST_LOOP(efa);
+ l_ptr[1] = l = l->next;
+ l_ptr[2] = l->next;
+# endif
+ }
+ else if (efa->len == 4) {
+# if 0
+ BMLoop *ltmp[4];
+ int j;
+ BLI_array_grow_items(looptris, 2);
+ BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, j) {
+ ltmp[j] = l;
+ }
+
+ looptris[i][0] = ltmp[0];
+ looptris[i][1] = ltmp[1];
+ looptris[i][2] = ltmp[2];
+ i += 1;
+
+ looptris[i][0] = ltmp[0];
+ looptris[i][1] = ltmp[2];
+ looptris[i][2] = ltmp[3];
+ i += 1;
+# else
+ /* more cryptic but faster */
+ BMLoop *l;
+ BMLoop **l_ptr_a = looptris[i++];
+ BMLoop **l_ptr_b = looptris[i++];
+ (l_ptr_a[0] = l_ptr_b[0] = l = BM_FACE_FIRST_LOOP(efa));
+ (l_ptr_a[1] = l = l->next);
+ (l_ptr_a[2] = l_ptr_b[1] = l = l->next);
+ (l_ptr_b[2] = l->next);
+# endif
+
+ if (UNLIKELY(is_quad_flip_v3_first_third_fast(
+ l_ptr_a[0]->v->co, l_ptr_a[1]->v->co, l_ptr_a[2]->v->co, l_ptr_b[2]->v->co))) {
+ /* flip out of degenerate 0-2 state. */
+ l_ptr_a[2] = l_ptr_b[2];
+ l_ptr_b[0] = l_ptr_a[1];
+ }
+ }
#endif /* USE_TESSFACE_SPEEDUP */
- else {
- int j;
+ else {
+ int j;
- BMLoop *l_iter;
- BMLoop *l_first;
- BMLoop **l_arr;
+ BMLoop *l_iter;
+ BMLoop *l_first;
+ BMLoop **l_arr;
- float axis_mat[3][3];
- float (*projverts)[2];
- uint (*tris)[3];
+ float axis_mat[3][3];
+ float(*projverts)[2];
+ uint(*tris)[3];
- const int totfilltri = efa->len - 2;
+ const int totfilltri = efa->len - 2;
- if (UNLIKELY(arena == NULL)) {
- arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
- }
+ if (UNLIKELY(arena == NULL)) {
+ arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+ }
- tris = BLI_memarena_alloc(arena, sizeof(*tris) * totfilltri);
- l_arr = BLI_memarena_alloc(arena, sizeof(*l_arr) * efa->len);
- projverts = BLI_memarena_alloc(arena, sizeof(*projverts) * efa->len);
+ tris = BLI_memarena_alloc(arena, sizeof(*tris) * totfilltri);
+ l_arr = BLI_memarena_alloc(arena, sizeof(*l_arr) * efa->len);
+ projverts = BLI_memarena_alloc(arena, sizeof(*projverts) * efa->len);
- axis_dominant_v3_to_m3_negate(axis_mat, efa->no);
+ axis_dominant_v3_to_m3_negate(axis_mat, efa->no);
- j = 0;
- l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
- do {
- l_arr[j] = l_iter;
- mul_v2_m3v3(projverts[j], axis_mat, l_iter->v->co);
- j++;
- } while ((l_iter = l_iter->next) != l_first);
+ j = 0;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
+ do {
+ l_arr[j] = l_iter;
+ mul_v2_m3v3(projverts[j], axis_mat, l_iter->v->co);
+ j++;
+ } while ((l_iter = l_iter->next) != l_first);
- BLI_polyfill_calc_arena(projverts, efa->len, 1, tris, arena);
+ BLI_polyfill_calc_arena(projverts, efa->len, 1, tris, arena);
- for (j = 0; j < totfilltri; j++) {
- BMLoop **l_ptr = looptris[i++];
- uint *tri = tris[j];
+ for (j = 0; j < totfilltri; j++) {
+ BMLoop **l_ptr = looptris[i++];
+ uint *tri = tris[j];
- l_ptr[0] = l_arr[tri[0]];
- l_ptr[1] = l_arr[tri[1]];
- l_ptr[2] = l_arr[tri[2]];
- }
+ l_ptr[0] = l_arr[tri[0]];
+ l_ptr[1] = l_arr[tri[1]];
+ l_ptr[2] = l_arr[tri[2]];
+ }
- BLI_memarena_clear(arena);
- }
- }
+ BLI_memarena_clear(arena);
+ }
+ }
- if (arena) {
- BLI_memarena_free(arena);
- arena = NULL;
- }
+ if (arena) {
+ BLI_memarena_free(arena);
+ arena = NULL;
+ }
- *r_looptris_tot = i;
+ *r_looptris_tot = i;
- BLI_assert(i <= looptris_tot);
+ BLI_assert(i <= looptris_tot);
#undef USE_TESSFACE_SPEEDUP
-
}
-
/**
* A version of #BM_mesh_calc_tessellation that avoids degenerate triangles.
*/
void BM_mesh_calc_tessellation_beauty(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptris_tot)
{
- /* this assumes all faces can be scan-filled, which isn't always true,
- * worst case we over alloc a little which is acceptable */
+ /* this assumes all faces can be scan-filled, which isn't always true,
+ * worst case we over alloc a little which is acceptable */
#ifndef NDEBUG
- const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop);
+ const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop);
#endif
- BMIter iter;
- BMFace *efa;
- int i = 0;
-
- MemArena *pf_arena = NULL;
-
- /* use_beauty */
- Heap *pf_heap = NULL;
-
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- /* don't consider two-edged faces */
- if (UNLIKELY(efa->len < 3)) {
- /* do nothing */
- }
- else if (efa->len == 3) {
- BMLoop *l;
- BMLoop **l_ptr = looptris[i++];
- l_ptr[0] = l = BM_FACE_FIRST_LOOP(efa);
- l_ptr[1] = l = l->next;
- l_ptr[2] = l->next;
- }
- else if (efa->len == 4) {
- BMLoop *l_v1 = BM_FACE_FIRST_LOOP(efa);
- BMLoop *l_v2 = l_v1->next;
- BMLoop *l_v3 = l_v2->next;
- BMLoop *l_v4 = l_v1->prev;
-
- /* #BM_verts_calc_rotate_beauty performs excessive checks we don't need!
- * It's meant for rotating edges, it also calculates a new normal.
- *
- * Use #BLI_polyfill_beautify_quad_rotate_calc since we have the normal.
- */
+ BMIter iter;
+ BMFace *efa;
+ int i = 0;
+
+ MemArena *pf_arena = NULL;
+
+ /* use_beauty */
+ Heap *pf_heap = NULL;
+
+ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
+ /* don't consider two-edged faces */
+ if (UNLIKELY(efa->len < 3)) {
+ /* do nothing */
+ }
+ else if (efa->len == 3) {
+ BMLoop *l;
+ BMLoop **l_ptr = looptris[i++];
+ l_ptr[0] = l = BM_FACE_FIRST_LOOP(efa);
+ l_ptr[1] = l = l->next;
+ l_ptr[2] = l->next;
+ }
+ else if (efa->len == 4) {
+ BMLoop *l_v1 = BM_FACE_FIRST_LOOP(efa);
+ BMLoop *l_v2 = l_v1->next;
+ BMLoop *l_v3 = l_v2->next;
+ BMLoop *l_v4 = l_v1->prev;
+
+ /* #BM_verts_calc_rotate_beauty performs excessive checks we don't need!
+ * It's meant for rotating edges, it also calculates a new normal.
+ *
+ * Use #BLI_polyfill_beautify_quad_rotate_calc since we have the normal.
+ */
#if 0
- const bool split_13 = (BM_verts_calc_rotate_beauty(
- l_v1->v, l_v2->v, l_v3->v, l_v4->v, 0, 0) < 0.0f);
+ const bool split_13 = (BM_verts_calc_rotate_beauty(
+ l_v1->v, l_v2->v, l_v3->v, l_v4->v, 0, 0) < 0.0f);
#else
- float axis_mat[3][3], v_quad[4][2];
- axis_dominant_v3_to_m3(axis_mat, efa->no);
- mul_v2_m3v3(v_quad[0], axis_mat, l_v1->v->co);
- mul_v2_m3v3(v_quad[1], axis_mat, l_v2->v->co);
- mul_v2_m3v3(v_quad[2], axis_mat, l_v3->v->co);
- mul_v2_m3v3(v_quad[3], axis_mat, l_v4->v->co);
-
- const bool split_13 = BLI_polyfill_beautify_quad_rotate_calc(
- v_quad[0], v_quad[1], v_quad[2], v_quad[3]) < 0.0f;
+ float axis_mat[3][3], v_quad[4][2];
+ axis_dominant_v3_to_m3(axis_mat, efa->no);
+ mul_v2_m3v3(v_quad[0], axis_mat, l_v1->v->co);
+ mul_v2_m3v3(v_quad[1], axis_mat, l_v2->v->co);
+ mul_v2_m3v3(v_quad[2], axis_mat, l_v3->v->co);
+ mul_v2_m3v3(v_quad[3], axis_mat, l_v4->v->co);
+
+ const bool split_13 = BLI_polyfill_beautify_quad_rotate_calc(
+ v_quad[0], v_quad[1], v_quad[2], v_quad[3]) < 0.0f;
#endif
- BMLoop **l_ptr_a = looptris[i++];
- BMLoop **l_ptr_b = looptris[i++];
- if (split_13) {
- l_ptr_a[0] = l_v1;
- l_ptr_a[1] = l_v2;
- l_ptr_a[2] = l_v3;
-
- l_ptr_b[0] = l_v1;
- l_ptr_b[1] = l_v3;
- l_ptr_b[2] = l_v4;
- }
- else {
- l_ptr_a[0] = l_v1;
- l_ptr_a[1] = l_v2;
- l_ptr_a[2] = l_v4;
-
- l_ptr_b[0] = l_v2;
- l_ptr_b[1] = l_v3;
- l_ptr_b[2] = l_v4;
- }
- }
- else {
- int j;
-
- BMLoop *l_iter;
- BMLoop *l_first;
- BMLoop **l_arr;
-
- float axis_mat[3][3];
- float (*projverts)[2];
- unsigned int (*tris)[3];
-
- const int totfilltri = efa->len - 2;
-
- if (UNLIKELY(pf_arena == NULL)) {
- pf_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
- pf_heap = BLI_heap_new_ex(BLI_POLYFILL_ALLOC_NGON_RESERVE);
- }
-
- tris = BLI_memarena_alloc(pf_arena, sizeof(*tris) * totfilltri);
- l_arr = BLI_memarena_alloc(pf_arena, sizeof(*l_arr) * efa->len);
- projverts = BLI_memarena_alloc(pf_arena, sizeof(*projverts) * efa->len);
-
- axis_dominant_v3_to_m3_negate(axis_mat, efa->no);
-
- j = 0;
- l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
- do {
- l_arr[j] = l_iter;
- mul_v2_m3v3(projverts[j], axis_mat, l_iter->v->co);
- j++;
- } while ((l_iter = l_iter->next) != l_first);
-
- BLI_polyfill_calc_arena(projverts, efa->len, 1, tris, pf_arena);
-
- BLI_polyfill_beautify(projverts, efa->len, tris, pf_arena, pf_heap);
-
- for (j = 0; j < totfilltri; j++) {
- BMLoop **l_ptr = looptris[i++];
- unsigned int *tri = tris[j];
-
- l_ptr[0] = l_arr[tri[0]];
- l_ptr[1] = l_arr[tri[1]];
- l_ptr[2] = l_arr[tri[2]];
- }
-
- BLI_memarena_clear(pf_arena);
- }
- }
-
- if (pf_arena) {
- BLI_memarena_free(pf_arena);
-
- BLI_heap_free(pf_heap, NULL);
- }
-
- *r_looptris_tot = i;
-
- BLI_assert(i <= looptris_tot);
-
+ BMLoop **l_ptr_a = looptris[i++];
+ BMLoop **l_ptr_b = looptris[i++];
+ if (split_13) {
+ l_ptr_a[0] = l_v1;
+ l_ptr_a[1] = l_v2;
+ l_ptr_a[2] = l_v3;
+
+ l_ptr_b[0] = l_v1;
+ l_ptr_b[1] = l_v3;
+ l_ptr_b[2] = l_v4;
+ }
+ else {
+ l_ptr_a[0] = l_v1;
+ l_ptr_a[1] = l_v2;
+ l_ptr_a[2] = l_v4;
+
+ l_ptr_b[0] = l_v2;
+ l_ptr_b[1] = l_v3;
+ l_ptr_b[2] = l_v4;
+ }
+ }
+ else {
+ int j;
+
+ BMLoop *l_iter;
+ BMLoop *l_first;
+ BMLoop **l_arr;
+
+ float axis_mat[3][3];
+ float(*projverts)[2];
+ unsigned int(*tris)[3];
+
+ const int totfilltri = efa->len - 2;
+
+ if (UNLIKELY(pf_arena == NULL)) {
+ pf_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+ pf_heap = BLI_heap_new_ex(BLI_POLYFILL_ALLOC_NGON_RESERVE);
+ }
+
+ tris = BLI_memarena_alloc(pf_arena, sizeof(*tris) * totfilltri);
+ l_arr = BLI_memarena_alloc(pf_arena, sizeof(*l_arr) * efa->len);
+ projverts = BLI_memarena_alloc(pf_arena, sizeof(*projverts) * efa->len);
+
+ axis_dominant_v3_to_m3_negate(axis_mat, efa->no);
+
+ j = 0;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
+ do {
+ l_arr[j] = l_iter;
+ mul_v2_m3v3(projverts[j], axis_mat, l_iter->v->co);
+ j++;
+ } while ((l_iter = l_iter->next) != l_first);
+
+ BLI_polyfill_calc_arena(projverts, efa->len, 1, tris, pf_arena);
+
+ BLI_polyfill_beautify(projverts, efa->len, tris, pf_arena, pf_heap);
+
+ for (j = 0; j < totfilltri; j++) {
+ BMLoop **l_ptr = looptris[i++];
+ unsigned int *tri = tris[j];
+
+ l_ptr[0] = l_arr[tri[0]];
+ l_ptr[1] = l_arr[tri[1]];
+ l_ptr[2] = l_arr[tri[2]];
+ }
+
+ BLI_memarena_clear(pf_arena);
+ }
+ }
+
+ if (pf_arena) {
+ BLI_memarena_free(pf_arena);
+
+ BLI_heap_free(pf_heap, NULL);
+ }
+
+ *r_looptris_tot = i;
+
+ BLI_assert(i <= looptris_tot);
}
diff --git a/source/blender/bmesh/intern/bmesh_polygon.h b/source/blender/bmesh/intern/bmesh_polygon.h
index ff93ce94c77..191ebd86f4a 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.h
+++ b/source/blender/bmesh/intern/bmesh_polygon.h
@@ -25,67 +25,77 @@ struct Heap;
#include "BLI_compiler_attrs.h"
-void BM_mesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptris_tot);
-void BM_mesh_calc_tessellation_beauty(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptris_tot);
-
-void BM_face_calc_tessellation(
- const BMFace *f, const bool use_fixed_quad,
- BMLoop **r_loops, uint (*r_index)[3]);
-void BM_face_calc_point_in_face(const BMFace *f, float r_co[3]);
+void BM_mesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptris_tot);
+void BM_mesh_calc_tessellation_beauty(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptris_tot);
+
+void BM_face_calc_tessellation(const BMFace *f,
+ const bool use_fixed_quad,
+ BMLoop **r_loops,
+ uint (*r_index)[3]);
+void BM_face_calc_point_in_face(const BMFace *f, float r_co[3]);
float BM_face_calc_normal(const BMFace *f, float r_no[3]) ATTR_NONNULL();
-float BM_face_calc_normal_vcos(
- const BMesh *bm, const BMFace *f, float r_no[3],
- float const (*vertexCos)[3]) ATTR_NONNULL();
-float BM_face_calc_normal_subset(const BMLoop *l_first, const BMLoop *l_last, float r_no[3]) ATTR_NONNULL();
+float BM_face_calc_normal_vcos(const BMesh *bm,
+ const BMFace *f,
+ float r_no[3],
+ float const (*vertexCos)[3]) ATTR_NONNULL();
+float BM_face_calc_normal_subset(const BMLoop *l_first, const BMLoop *l_last, float r_no[3])
+ ATTR_NONNULL();
float BM_face_calc_area(const BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-float BM_face_calc_area_with_mat3(const BMFace *f, const float mat3[3][3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-float BM_face_calc_area_uv(const BMFace *f, int cd_loop_uv_offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_face_calc_area_with_mat3(const BMFace *f, const float mat3[3][3]) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+float BM_face_calc_area_uv(const BMFace *f, int cd_loop_uv_offset) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
float BM_face_calc_perimeter(const BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-float BM_face_calc_perimeter_with_mat3(const BMFace *f, const float mat3[3][3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-void BM_face_calc_tangent_edge(const BMFace *f, float r_plane[3]) ATTR_NONNULL();
-void BM_face_calc_tangent_edge_pair(const BMFace *f, float r_plane[3]) ATTR_NONNULL();
-void BM_face_calc_tangent_edge_diagonal(const BMFace *f, float r_plane[3]) ATTR_NONNULL();
-void BM_face_calc_tangent_vert_diagonal(const BMFace *f, float r_plane[3]) ATTR_NONNULL();
-void BM_face_calc_tangent_auto(const BMFace *f, float r_plane[3]) ATTR_NONNULL();
-void BM_face_calc_center_bounds(const BMFace *f, float center[3]) ATTR_NONNULL();
-void BM_face_calc_center_median(const BMFace *f, float center[3]) ATTR_NONNULL();
-void BM_face_calc_center_median_vcos(
- const BMesh *bm, const BMFace *f, float r_cent[3],
- float const (*vertexCos)[3]) ATTR_NONNULL();
-void BM_face_calc_center_median_weighted(const BMFace *f, float center[3]) ATTR_NONNULL();
+float BM_face_calc_perimeter_with_mat3(const BMFace *f,
+ const float mat3[3][3]) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+void BM_face_calc_tangent_edge(const BMFace *f, float r_plane[3]) ATTR_NONNULL();
+void BM_face_calc_tangent_edge_pair(const BMFace *f, float r_plane[3]) ATTR_NONNULL();
+void BM_face_calc_tangent_edge_diagonal(const BMFace *f, float r_plane[3]) ATTR_NONNULL();
+void BM_face_calc_tangent_vert_diagonal(const BMFace *f, float r_plane[3]) ATTR_NONNULL();
+void BM_face_calc_tangent_auto(const BMFace *f, float r_plane[3]) ATTR_NONNULL();
+void BM_face_calc_center_bounds(const BMFace *f, float center[3]) ATTR_NONNULL();
+void BM_face_calc_center_median(const BMFace *f, float center[3]) ATTR_NONNULL();
+void BM_face_calc_center_median_vcos(const BMesh *bm,
+ const BMFace *f,
+ float r_cent[3],
+ float const (*vertexCos)[3]) ATTR_NONNULL();
+void BM_face_calc_center_median_weighted(const BMFace *f, float center[3]) ATTR_NONNULL();
void BM_face_calc_bounds_expand(const BMFace *f, float min[3], float max[3]);
-void BM_face_normal_update(BMFace *f) ATTR_NONNULL();
-
-void BM_edge_normals_update(BMEdge *e) ATTR_NONNULL();
-
-bool BM_vert_calc_normal_ex(const BMVert *v, const char hflag, float r_no[3]);
-bool BM_vert_calc_normal(const BMVert *v, float r_no[3]);
-void BM_vert_normal_update(BMVert *v) ATTR_NONNULL();
-void BM_vert_normal_update_all(BMVert *v) ATTR_NONNULL();
-
-void BM_face_normal_flip_ex(
- BMesh *bm, BMFace *f,
- const int cd_loop_mdisp_offset, const bool use_loop_mdisp_flip) ATTR_NONNULL();
-void BM_face_normal_flip(BMesh *bm, BMFace *f) ATTR_NONNULL();
-bool BM_face_point_inside_test(const BMFace *f, const float co[3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-
-void BM_face_triangulate(
- BMesh *bm, BMFace *f,
- BMFace **r_faces_new,
- int *r_faces_new_tot,
- BMEdge **r_edges_new,
- int *r_edges_new_tot,
- struct LinkNode **r_faces_double,
- const int quad_method, const int ngon_method,
- const bool use_tag,
- struct MemArena *pf_arena,
- struct Heap *pf_heap
- ) ATTR_NONNULL(1, 2);
-
-void BM_face_splits_check_legal(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len) ATTR_NONNULL();
-void BM_face_splits_check_optimal(BMFace *f, BMLoop *(*loops)[2], int len) ATTR_NONNULL();
+void BM_face_normal_update(BMFace *f) ATTR_NONNULL();
+
+void BM_edge_normals_update(BMEdge *e) ATTR_NONNULL();
+
+bool BM_vert_calc_normal_ex(const BMVert *v, const char hflag, float r_no[3]);
+bool BM_vert_calc_normal(const BMVert *v, float r_no[3]);
+void BM_vert_normal_update(BMVert *v) ATTR_NONNULL();
+void BM_vert_normal_update_all(BMVert *v) ATTR_NONNULL();
+
+void BM_face_normal_flip_ex(BMesh *bm,
+ BMFace *f,
+ const int cd_loop_mdisp_offset,
+ const bool use_loop_mdisp_flip) ATTR_NONNULL();
+void BM_face_normal_flip(BMesh *bm, BMFace *f) ATTR_NONNULL();
+bool BM_face_point_inside_test(const BMFace *f, const float co[3]) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+
+void BM_face_triangulate(BMesh *bm,
+ BMFace *f,
+ BMFace **r_faces_new,
+ int *r_faces_new_tot,
+ BMEdge **r_edges_new,
+ int *r_edges_new_tot,
+ struct LinkNode **r_faces_double,
+ const int quad_method,
+ const int ngon_method,
+ const bool use_tag,
+ struct MemArena *pf_arena,
+ struct Heap *pf_heap) ATTR_NONNULL(1, 2);
+
+void BM_face_splits_check_legal(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len) ATTR_NONNULL();
+void BM_face_splits_check_optimal(BMFace *f, BMLoop *(*loops)[2], int len) ATTR_NONNULL();
void BM_face_as_array_vert_tri(BMFace *f, BMVert *r_verts[3]) ATTR_NONNULL();
void BM_face_as_array_vert_quad(BMFace *f, BMVert *r_verts[4]) ATTR_NONNULL();
diff --git a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c
index 76c0dcc1dfa..e2b117536f3 100644
--- a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c
+++ b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c
@@ -52,167 +52,169 @@
/* Note: All these flags _must_ be cleared on exit */
/* face is apart of the edge-net (including the original face we're splitting) */
-#define FACE_NET _FLAG_WALK
+#define FACE_NET _FLAG_WALK
/* edge is apart of the edge-net we're filling */
-#define EDGE_NET _FLAG_WALK
+#define EDGE_NET _FLAG_WALK
/* tag verts we've visit */
#define VERT_VISIT _FLAG_WALK
#define VERT_IN_QUEUE _FLAG_WALK_ALT
struct VertOrder {
- float angle;
- BMVert *v;
+ float angle;
+ BMVert *v;
};
static uint bm_edge_flagged_radial_count(BMEdge *e)
{
- uint count = 0;
- BMLoop *l;
-
- if ((l = e->l)) {
- do {
- if (BM_ELEM_API_FLAG_TEST(l->f, FACE_NET)) {
- count++;
- }
- } while ((l = l->radial_next) != e->l);
- }
- return count;
+ uint count = 0;
+ BMLoop *l;
+
+ if ((l = e->l)) {
+ do {
+ if (BM_ELEM_API_FLAG_TEST(l->f, FACE_NET)) {
+ count++;
+ }
+ } while ((l = l->radial_next) != e->l);
+ }
+ return count;
}
static BMLoop *bm_edge_flagged_radial_first(BMEdge *e)
{
- BMLoop *l;
-
- if ((l = e->l)) {
- do {
- if (BM_ELEM_API_FLAG_TEST(l->f, FACE_NET)) {
- return l;
- }
- } while ((l = l->radial_next) != e->l);
- }
- return NULL;
+ BMLoop *l;
+
+ if ((l = e->l)) {
+ do {
+ if (BM_ELEM_API_FLAG_TEST(l->f, FACE_NET)) {
+ return l;
+ }
+ } while ((l = l->radial_next) != e->l);
+ }
+ return NULL;
}
-static void normalize_v2_m3_v3v3(float out[2], float axis_mat[3][3], const float v1[3], const float v2[3])
+static void normalize_v2_m3_v3v3(float out[2],
+ float axis_mat[3][3],
+ const float v1[3],
+ const float v2[3])
{
- float dir[3];
- sub_v3_v3v3(dir, v1, v2);
- mul_v2_m3v3(out, axis_mat, dir);
- normalize_v2(out);
+ float dir[3];
+ sub_v3_v3v3(dir, v1, v2);
+ mul_v2_m3v3(out, axis_mat, dir);
+ normalize_v2(out);
}
-
/**
* \note Be sure to update #bm_face_split_edgenet_find_loop_pair_exists
* when making changed to edge picking logic.
*/
-static bool bm_face_split_edgenet_find_loop_pair(
- BMVert *v_init,
- const float face_normal[3], float face_normal_matrix[3][3],
- BMEdge *e_pair[2])
+static bool bm_face_split_edgenet_find_loop_pair(BMVert *v_init,
+ const float face_normal[3],
+ float face_normal_matrix[3][3],
+ BMEdge *e_pair[2])
{
- /* Always find one boundary edge (to determine winding)
- * and one wire (if available), otherwise another boundary.
- */
-
- /* detect winding */
- BMLoop *l_walk;
- bool swap;
-
- BLI_SMALLSTACK_DECLARE(edges_boundary, BMEdge *);
- BLI_SMALLSTACK_DECLARE(edges_wire, BMEdge *);
- int edges_boundary_len = 0;
- int edges_wire_len = 0;
-
- {
- BMEdge *e, *e_first;
- e = e_first = v_init->e;
- do {
- if (BM_ELEM_API_FLAG_TEST(e, EDGE_NET)) {
- const uint count = bm_edge_flagged_radial_count(e);
- if (count == 1) {
- BLI_SMALLSTACK_PUSH(edges_boundary, e);
- edges_boundary_len++;
- }
- else if (count == 0) {
- BLI_SMALLSTACK_PUSH(edges_wire, e);
- edges_wire_len++;
- }
- }
- } while ((e = BM_DISK_EDGE_NEXT(e, v_init)) != e_first);
- }
-
- /* first edge should always be boundary */
- if (edges_boundary_len == 0) {
- return false;
- }
- e_pair[0] = BLI_SMALLSTACK_POP(edges_boundary);
-
- /* use to hold boundary OR wire edges */
- BLI_SMALLSTACK_DECLARE(edges_search, BMEdge *);
-
- /* attempt one boundary and one wire, or 2 boundary */
- if (edges_wire_len == 0) {
- if (edges_boundary_len > 1) {
- e_pair[1] = BLI_SMALLSTACK_POP(edges_boundary);
-
- if (edges_boundary_len > 2) {
- BLI_SMALLSTACK_SWAP(edges_search, edges_boundary);
- }
- }
- else {
- /* one boundary and no wire */
- return false;
- }
- }
- else {
- e_pair[1] = BLI_SMALLSTACK_POP(edges_wire);
- if (edges_wire_len > 1) {
- BLI_SMALLSTACK_SWAP(edges_search, edges_wire);
- }
- }
-
- /* if we swapped above, search this list for the best edge */
- if (!BLI_SMALLSTACK_IS_EMPTY(edges_search)) {
- /* find the best edge in 'edge_list' to use for 'e_pair[1]' */
- const BMVert *v_prev = BM_edge_other_vert(e_pair[0], v_init);
- const BMVert *v_next = BM_edge_other_vert(e_pair[1], v_init);
-
- float dir_prev[2], dir_next[2];
-
- normalize_v2_m3_v3v3(dir_prev, face_normal_matrix, v_prev->co, v_init->co);
- normalize_v2_m3_v3v3(dir_next, face_normal_matrix, v_next->co, v_init->co);
- float angle_best_cos = dot_v2v2(dir_next, dir_prev);
-
- BMEdge *e;
- while ((e = BLI_SMALLSTACK_POP(edges_search))) {
- v_next = BM_edge_other_vert(e, v_init);
- float dir_test[2];
-
- normalize_v2_m3_v3v3(dir_test, face_normal_matrix, v_next->co, v_init->co);
- const float angle_test_cos = dot_v2v2(dir_prev, dir_test);
-
- if (angle_test_cos > angle_best_cos) {
- angle_best_cos = angle_test_cos;
- e_pair[1] = e;
- }
- }
- }
-
- /* flip based on winding */
- l_walk = bm_edge_flagged_radial_first(e_pair[0]);
- swap = false;
- if (face_normal == l_walk->f->no) {
- swap = !swap;
- }
- if (l_walk->v != v_init) {
- swap = !swap;
- }
- if (swap) {
- SWAP(BMEdge *, e_pair[0], e_pair[1]);
- }
-
- return true;
+ /* Always find one boundary edge (to determine winding)
+ * and one wire (if available), otherwise another boundary.
+ */
+
+ /* detect winding */
+ BMLoop *l_walk;
+ bool swap;
+
+ BLI_SMALLSTACK_DECLARE(edges_boundary, BMEdge *);
+ BLI_SMALLSTACK_DECLARE(edges_wire, BMEdge *);
+ int edges_boundary_len = 0;
+ int edges_wire_len = 0;
+
+ {
+ BMEdge *e, *e_first;
+ e = e_first = v_init->e;
+ do {
+ if (BM_ELEM_API_FLAG_TEST(e, EDGE_NET)) {
+ const uint count = bm_edge_flagged_radial_count(e);
+ if (count == 1) {
+ BLI_SMALLSTACK_PUSH(edges_boundary, e);
+ edges_boundary_len++;
+ }
+ else if (count == 0) {
+ BLI_SMALLSTACK_PUSH(edges_wire, e);
+ edges_wire_len++;
+ }
+ }
+ } while ((e = BM_DISK_EDGE_NEXT(e, v_init)) != e_first);
+ }
+
+ /* first edge should always be boundary */
+ if (edges_boundary_len == 0) {
+ return false;
+ }
+ e_pair[0] = BLI_SMALLSTACK_POP(edges_boundary);
+
+ /* use to hold boundary OR wire edges */
+ BLI_SMALLSTACK_DECLARE(edges_search, BMEdge *);
+
+ /* attempt one boundary and one wire, or 2 boundary */
+ if (edges_wire_len == 0) {
+ if (edges_boundary_len > 1) {
+ e_pair[1] = BLI_SMALLSTACK_POP(edges_boundary);
+
+ if (edges_boundary_len > 2) {
+ BLI_SMALLSTACK_SWAP(edges_search, edges_boundary);
+ }
+ }
+ else {
+ /* one boundary and no wire */
+ return false;
+ }
+ }
+ else {
+ e_pair[1] = BLI_SMALLSTACK_POP(edges_wire);
+ if (edges_wire_len > 1) {
+ BLI_SMALLSTACK_SWAP(edges_search, edges_wire);
+ }
+ }
+
+ /* if we swapped above, search this list for the best edge */
+ if (!BLI_SMALLSTACK_IS_EMPTY(edges_search)) {
+ /* find the best edge in 'edge_list' to use for 'e_pair[1]' */
+ const BMVert *v_prev = BM_edge_other_vert(e_pair[0], v_init);
+ const BMVert *v_next = BM_edge_other_vert(e_pair[1], v_init);
+
+ float dir_prev[2], dir_next[2];
+
+ normalize_v2_m3_v3v3(dir_prev, face_normal_matrix, v_prev->co, v_init->co);
+ normalize_v2_m3_v3v3(dir_next, face_normal_matrix, v_next->co, v_init->co);
+ float angle_best_cos = dot_v2v2(dir_next, dir_prev);
+
+ BMEdge *e;
+ while ((e = BLI_SMALLSTACK_POP(edges_search))) {
+ v_next = BM_edge_other_vert(e, v_init);
+ float dir_test[2];
+
+ normalize_v2_m3_v3v3(dir_test, face_normal_matrix, v_next->co, v_init->co);
+ const float angle_test_cos = dot_v2v2(dir_prev, dir_test);
+
+ if (angle_test_cos > angle_best_cos) {
+ angle_best_cos = angle_test_cos;
+ e_pair[1] = e;
+ }
+ }
+ }
+
+ /* flip based on winding */
+ l_walk = bm_edge_flagged_radial_first(e_pair[0]);
+ swap = false;
+ if (face_normal == l_walk->f->no) {
+ swap = !swap;
+ }
+ if (l_walk->v != v_init) {
+ swap = !swap;
+ }
+ if (swap) {
+ SWAP(BMEdge *, e_pair[0], e_pair[1]);
+ }
+
+ return true;
}
/**
@@ -223,226 +225,233 @@ static bool bm_face_split_edgenet_find_loop_pair(
* since between this check and running #bm_face_split_edgenet_find_loop,
* the selected edges may have had faces attached.
*/
-static bool bm_face_split_edgenet_find_loop_pair_exists(
- BMVert *v_init)
+static bool bm_face_split_edgenet_find_loop_pair_exists(BMVert *v_init)
{
- int edges_boundary_len = 0;
- int edges_wire_len = 0;
-
- {
- BMEdge *e, *e_first;
- e = e_first = v_init->e;
- do {
- if (BM_ELEM_API_FLAG_TEST(e, EDGE_NET)) {
- const uint count = bm_edge_flagged_radial_count(e);
- if (count == 1) {
- edges_boundary_len++;
- }
- else if (count == 0) {
- edges_wire_len++;
- }
- }
- } while ((e = BM_DISK_EDGE_NEXT(e, v_init)) != e_first);
- }
-
- /* first edge should always be boundary */
- if (edges_boundary_len == 0) {
- return false;
- }
-
- /* attempt one boundary and one wire, or 2 boundary */
- if (edges_wire_len == 0) {
- if (edges_boundary_len >= 2) {
- /* pass */
- }
- else {
- /* one boundary and no wire */
- return false;
- }
- }
- else {
- /* pass */
- }
-
- return true;
+ int edges_boundary_len = 0;
+ int edges_wire_len = 0;
+
+ {
+ BMEdge *e, *e_first;
+ e = e_first = v_init->e;
+ do {
+ if (BM_ELEM_API_FLAG_TEST(e, EDGE_NET)) {
+ const uint count = bm_edge_flagged_radial_count(e);
+ if (count == 1) {
+ edges_boundary_len++;
+ }
+ else if (count == 0) {
+ edges_wire_len++;
+ }
+ }
+ } while ((e = BM_DISK_EDGE_NEXT(e, v_init)) != e_first);
+ }
+
+ /* first edge should always be boundary */
+ if (edges_boundary_len == 0) {
+ return false;
+ }
+
+ /* attempt one boundary and one wire, or 2 boundary */
+ if (edges_wire_len == 0) {
+ if (edges_boundary_len >= 2) {
+ /* pass */
+ }
+ else {
+ /* one boundary and no wire */
+ return false;
+ }
+ }
+ else {
+ /* pass */
+ }
+
+ return true;
}
-static bool bm_face_split_edgenet_find_loop_walk(
- BMVert *v_init, const float face_normal[3],
- /* cache to avoid realloc every time */
- struct VertOrder *edge_order, const uint edge_order_len,
- BMEdge *e_pair[2])
+static bool bm_face_split_edgenet_find_loop_walk(BMVert *v_init,
+ const float face_normal[3],
+ /* cache to avoid realloc every time */
+ struct VertOrder *edge_order,
+ const uint edge_order_len,
+ BMEdge *e_pair[2])
{
- /* fast-path for the common case (avoid push-pop).
- * Also avoids tagging as visited since we know we
- * can't reach these verts some other way */
+ /* fast-path for the common case (avoid push-pop).
+ * Also avoids tagging as visited since we know we
+ * can't reach these verts some other way */
#define USE_FASTPATH_NOFORK
- BMVert *v;
- BMVert *v_dst;
- bool found = false;
+ BMVert *v;
+ BMVert *v_dst;
+ bool found = false;
- struct VertOrder *eo;
- STACK_DECLARE(edge_order);
+ struct VertOrder *eo;
+ STACK_DECLARE(edge_order);
- /* store visited verts so we can clear the visit flag after execution */
- BLI_SMALLSTACK_DECLARE(vert_visit, BMVert *);
+ /* store visited verts so we can clear the visit flag after execution */
+ BLI_SMALLSTACK_DECLARE(vert_visit, BMVert *);
- /* likely this will stay very small
- * all verts pushed into this stack _must_ have their previous edges set! */
- BLI_SMALLSTACK_DECLARE(vert_stack, BMVert *);
- BLI_SMALLSTACK_DECLARE(vert_stack_next, BMVert *);
+ /* likely this will stay very small
+ * all verts pushed into this stack _must_ have their previous edges set! */
+ BLI_SMALLSTACK_DECLARE(vert_stack, BMVert *);
+ BLI_SMALLSTACK_DECLARE(vert_stack_next, BMVert *);
- STACK_INIT(edge_order, edge_order_len);
+ STACK_INIT(edge_order, edge_order_len);
- /* start stepping */
- v = BM_edge_other_vert(e_pair[0], v_init);
- v->e = e_pair[0];
- BLI_SMALLSTACK_PUSH(vert_stack, v);
+ /* start stepping */
+ v = BM_edge_other_vert(e_pair[0], v_init);
+ v->e = e_pair[0];
+ BLI_SMALLSTACK_PUSH(vert_stack, v);
- v_dst = BM_edge_other_vert(e_pair[1], v_init);
+ v_dst = BM_edge_other_vert(e_pair[1], v_init);
#ifdef DEBUG_PRINT
- printf("%s: vert (search) %d\n", __func__, BM_elem_index_get(v_init));
+ printf("%s: vert (search) %d\n", __func__, BM_elem_index_get(v_init));
#endif
- /* This loop will keep stepping over the best possible edge,
- * in most cases it finds the direct route to close the face.
- *
- * In cases where paths can't be closed,
- * alternatives are stored in the 'vert_stack'.
- */
- while ((v = BLI_SMALLSTACK_POP_EX(vert_stack, vert_stack_next))) {
+ /* This loop will keep stepping over the best possible edge,
+ * in most cases it finds the direct route to close the face.
+ *
+ * In cases where paths can't be closed,
+ * alternatives are stored in the 'vert_stack'.
+ */
+ while ((v = BLI_SMALLSTACK_POP_EX(vert_stack, vert_stack_next))) {
#ifdef USE_FASTPATH_NOFORK
-walk_nofork:
+ walk_nofork:
#else
- BLI_SMALLSTACK_PUSH(vert_visit, v);
- BM_ELEM_API_FLAG_ENABLE(v, VERT_VISIT);
+ BLI_SMALLSTACK_PUSH(vert_visit, v);
+ BM_ELEM_API_FLAG_ENABLE(v, VERT_VISIT);
#endif
- BLI_assert(STACK_SIZE(edge_order) == 0);
+ BLI_assert(STACK_SIZE(edge_order) == 0);
- /* check if we're done! */
- if (v == v_dst) {
- found = true;
- goto finally;
- }
+ /* check if we're done! */
+ if (v == v_dst) {
+ found = true;
+ goto finally;
+ }
- BMEdge *e_next, *e_first;
- e_first = v->e;
- e_next = BM_DISK_EDGE_NEXT(e_first, v); /* always skip this verts edge */
+ BMEdge *e_next, *e_first;
+ e_first = v->e;
+ e_next = BM_DISK_EDGE_NEXT(e_first, v); /* always skip this verts edge */
- /* in rare cases there may be edges with a single connecting vertex */
- if (e_next != e_first) {
- do {
- if ((BM_ELEM_API_FLAG_TEST(e_next, EDGE_NET)) &&
- (bm_edge_flagged_radial_count(e_next) < 2))
- {
- BMVert *v_next;
+ /* in rare cases there may be edges with a single connecting vertex */
+ if (e_next != e_first) {
+ do {
+ if ((BM_ELEM_API_FLAG_TEST(e_next, EDGE_NET)) &&
+ (bm_edge_flagged_radial_count(e_next) < 2)) {
+ BMVert *v_next;
- v_next = BM_edge_other_vert(e_next, v);
- BLI_assert(v->e != e_next);
+ v_next = BM_edge_other_vert(e_next, v);
+ BLI_assert(v->e != e_next);
#ifdef DEBUG_PRINT
- /* indent and print */
- {
- BMVert *_v = v;
- do {
- printf(" ");
- } while ((_v = BM_edge_other_vert(_v->e, _v)) != v_init);
- printf("vert %d -> %d (add=%d)\n",
- BM_elem_index_get(v), BM_elem_index_get(v_next),
- BM_ELEM_API_FLAG_TEST(v_next, VERT_VISIT) == 0);
- }
+ /* indent and print */
+ {
+ BMVert *_v = v;
+ do {
+ printf(" ");
+ } while ((_v = BM_edge_other_vert(_v->e, _v)) != v_init);
+ printf("vert %d -> %d (add=%d)\n",
+ BM_elem_index_get(v),
+ BM_elem_index_get(v_next),
+ BM_ELEM_API_FLAG_TEST(v_next, VERT_VISIT) == 0);
+ }
#endif
- if (!BM_ELEM_API_FLAG_TEST(v_next, VERT_VISIT)) {
- eo = STACK_PUSH_RET_PTR(edge_order);
- eo->v = v_next;
+ if (!BM_ELEM_API_FLAG_TEST(v_next, VERT_VISIT)) {
+ eo = STACK_PUSH_RET_PTR(edge_order);
+ eo->v = v_next;
- v_next->e = e_next;
- }
- }
- } while ((e_next = BM_DISK_EDGE_NEXT(e_next, v)) != e_first);
- }
+ v_next->e = e_next;
+ }
+ }
+ } while ((e_next = BM_DISK_EDGE_NEXT(e_next, v)) != e_first);
+ }
#ifdef USE_FASTPATH_NOFORK
- if (STACK_SIZE(edge_order) == 1) {
- eo = STACK_POP_PTR(edge_order);
- v = eo->v;
+ if (STACK_SIZE(edge_order) == 1) {
+ eo = STACK_POP_PTR(edge_order);
+ v = eo->v;
- goto walk_nofork;
- }
+ goto walk_nofork;
+ }
#endif
- /* sort by angle if needed */
- if (STACK_SIZE(edge_order) > 1) {
- uint j;
- BMVert *v_prev = BM_edge_other_vert(v->e, v);
+ /* sort by angle if needed */
+ if (STACK_SIZE(edge_order) > 1) {
+ uint j;
+ BMVert *v_prev = BM_edge_other_vert(v->e, v);
- for (j = 0; j < STACK_SIZE(edge_order); j++) {
- edge_order[j].angle = angle_signed_on_axis_v3v3v3_v3(v_prev->co, v->co, edge_order[j].v->co, face_normal);
- }
- qsort(edge_order, STACK_SIZE(edge_order), sizeof(struct VertOrder), BLI_sortutil_cmp_float_reverse);
+ for (j = 0; j < STACK_SIZE(edge_order); j++) {
+ edge_order[j].angle = angle_signed_on_axis_v3v3v3_v3(
+ v_prev->co, v->co, edge_order[j].v->co, face_normal);
+ }
+ qsort(edge_order,
+ STACK_SIZE(edge_order),
+ sizeof(struct VertOrder),
+ BLI_sortutil_cmp_float_reverse);
#ifdef USE_FASTPATH_NOFORK
- /* only tag forks */
- BLI_SMALLSTACK_PUSH(vert_visit, v);
- BM_ELEM_API_FLAG_ENABLE(v, VERT_VISIT);
+ /* only tag forks */
+ BLI_SMALLSTACK_PUSH(vert_visit, v);
+ BM_ELEM_API_FLAG_ENABLE(v, VERT_VISIT);
#endif
- }
-
- while ((eo = STACK_POP_PTR(edge_order))) {
- BLI_SMALLSTACK_PUSH(vert_stack_next, eo->v);
- }
+ }
- if (!BLI_SMALLSTACK_IS_EMPTY(vert_stack_next)) {
- BLI_SMALLSTACK_SWAP(vert_stack, vert_stack_next);
- }
- }
+ while ((eo = STACK_POP_PTR(edge_order))) {
+ BLI_SMALLSTACK_PUSH(vert_stack_next, eo->v);
+ }
+ if (!BLI_SMALLSTACK_IS_EMPTY(vert_stack_next)) {
+ BLI_SMALLSTACK_SWAP(vert_stack, vert_stack_next);
+ }
+ }
finally:
- /* clear flag for next execution */
- while ((v = BLI_SMALLSTACK_POP(vert_visit))) {
- BM_ELEM_API_FLAG_DISABLE(v, VERT_VISIT);
- }
+ /* clear flag for next execution */
+ while ((v = BLI_SMALLSTACK_POP(vert_visit))) {
+ BM_ELEM_API_FLAG_DISABLE(v, VERT_VISIT);
+ }
- return found;
+ return found;
#undef USE_FASTPATH_NOFORK
}
-static bool bm_face_split_edgenet_find_loop(
- BMVert *v_init, const float face_normal[3], float face_normal_matrix[3][3],
- /* cache to avoid realloc every time */
- struct VertOrder *edge_order, const uint edge_order_len,
- BMVert **r_face_verts, int *r_face_verts_len)
+static bool bm_face_split_edgenet_find_loop(BMVert *v_init,
+ const float face_normal[3],
+ float face_normal_matrix[3][3],
+ /* cache to avoid realloc every time */
+ struct VertOrder *edge_order,
+ const uint edge_order_len,
+ BMVert **r_face_verts,
+ int *r_face_verts_len)
{
- BMEdge *e_pair[2];
- BMVert *v;
-
- if (!bm_face_split_edgenet_find_loop_pair(v_init, face_normal, face_normal_matrix, e_pair)) {
- return false;
- }
-
- BLI_assert((bm_edge_flagged_radial_count(e_pair[0]) == 1) ||
- (bm_edge_flagged_radial_count(e_pair[1]) == 1));
-
- if (bm_face_split_edgenet_find_loop_walk(v_init, face_normal, edge_order, edge_order_len, e_pair)) {
- uint i = 0;
-
- r_face_verts[i++] = v_init;
- v = BM_edge_other_vert(e_pair[1], v_init);
- do {
- r_face_verts[i++] = v;
- } while ((v = BM_edge_other_vert(v->e, v)) != v_init);
- *r_face_verts_len = i;
- return (i > 2) ? true : false;
- }
- else {
- return false;
- }
+ BMEdge *e_pair[2];
+ BMVert *v;
+
+ if (!bm_face_split_edgenet_find_loop_pair(v_init, face_normal, face_normal_matrix, e_pair)) {
+ return false;
+ }
+
+ BLI_assert((bm_edge_flagged_radial_count(e_pair[0]) == 1) ||
+ (bm_edge_flagged_radial_count(e_pair[1]) == 1));
+
+ if (bm_face_split_edgenet_find_loop_walk(
+ v_init, face_normal, edge_order, edge_order_len, e_pair)) {
+ uint i = 0;
+
+ r_face_verts[i++] = v_init;
+ v = BM_edge_other_vert(e_pair[1], v_init);
+ do {
+ r_face_verts[i++] = v;
+ } while ((v = BM_edge_other_vert(v->e, v)) != v_init);
+ *r_face_verts_len = i;
+ return (i > 2) ? true : false;
+ }
+ else {
+ return false;
+ }
}
/**
@@ -453,237 +462,232 @@ static bool bm_face_split_edgenet_find_loop(
* - customdata calculations aren't efficient
* (need to calculate weights for each vert).
*/
-bool BM_face_split_edgenet(
- BMesh *bm,
- BMFace *f, BMEdge **edge_net, const int edge_net_len,
- BMFace ***r_face_arr, int *r_face_arr_len)
+bool BM_face_split_edgenet(BMesh *bm,
+ BMFace *f,
+ BMEdge **edge_net,
+ const int edge_net_len,
+ BMFace ***r_face_arr,
+ int *r_face_arr_len)
{
- /* re-use for new face verts */
- BMVert **face_verts;
- int face_verts_len;
-
- BMFace **face_arr = NULL;
- BLI_array_declare(face_arr);
+ /* re-use for new face verts */
+ BMVert **face_verts;
+ int face_verts_len;
- BMVert **vert_queue;
- STACK_DECLARE(vert_queue);
- int i;
+ BMFace **face_arr = NULL;
+ BLI_array_declare(face_arr);
- struct VertOrder *edge_order;
- const uint edge_order_len = edge_net_len + 2;
+ BMVert **vert_queue;
+ STACK_DECLARE(vert_queue);
+ int i;
- BMVert *v;
+ struct VertOrder *edge_order;
+ const uint edge_order_len = edge_net_len + 2;
- BMLoop *l_iter, *l_first;
+ BMVert *v;
+ BMLoop *l_iter, *l_first;
- if (!edge_net_len) {
- if (r_face_arr) {
- *r_face_arr = NULL;
- *r_face_arr_len = 0;
- }
- return false;
- }
+ if (!edge_net_len) {
+ if (r_face_arr) {
+ *r_face_arr = NULL;
+ *r_face_arr_len = 0;
+ }
+ return false;
+ }
- /* over-alloc (probably 2-4 is only used in most cases), for the biggest-fan */
- edge_order = BLI_array_alloca(edge_order, edge_order_len);
+ /* over-alloc (probably 2-4 is only used in most cases), for the biggest-fan */
+ edge_order = BLI_array_alloca(edge_order, edge_order_len);
- /* use later */
- face_verts = BLI_array_alloca(face_verts, edge_net_len + f->len);
+ /* use later */
+ face_verts = BLI_array_alloca(face_verts, edge_net_len + f->len);
- vert_queue = BLI_array_alloca(vert_queue, edge_net_len + f->len);
- STACK_INIT(vert_queue, f->len + edge_net_len);
+ vert_queue = BLI_array_alloca(vert_queue, edge_net_len + f->len);
+ STACK_INIT(vert_queue, f->len + edge_net_len);
- BLI_assert(BM_ELEM_API_FLAG_TEST(f, FACE_NET) == 0);
- BM_ELEM_API_FLAG_ENABLE(f, FACE_NET);
+ BLI_assert(BM_ELEM_API_FLAG_TEST(f, FACE_NET) == 0);
+ BM_ELEM_API_FLAG_ENABLE(f, FACE_NET);
#ifdef DEBUG
- for (i = 0; i < edge_net_len; i++) {
- BLI_assert(BM_ELEM_API_FLAG_TEST(edge_net[i], EDGE_NET) == 0);
- BLI_assert(BM_edge_in_face(edge_net[i], f) == false);
- }
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- BLI_assert(BM_ELEM_API_FLAG_TEST(l_iter->e, EDGE_NET) == 0);
- } while ((l_iter = l_iter->next) != l_first);
+ for (i = 0; i < edge_net_len; i++) {
+ BLI_assert(BM_ELEM_API_FLAG_TEST(edge_net[i], EDGE_NET) == 0);
+ BLI_assert(BM_edge_in_face(edge_net[i], f) == false);
+ }
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BLI_assert(BM_ELEM_API_FLAG_TEST(l_iter->e, EDGE_NET) == 0);
+ } while ((l_iter = l_iter->next) != l_first);
#endif
- /* Note: 'VERT_IN_QUEUE' is often not needed at all,
- * however in rare cases verts are added multiple times to the queue,
- * that on it's own is harmless but in _very_ rare cases,
- * the queue will overflow its maximum size,
- * so we better be strict about this! see: T51539 */
-
- for (i = 0; i < edge_net_len; i++) {
- BM_ELEM_API_FLAG_ENABLE(edge_net[i], EDGE_NET);
- BM_ELEM_API_FLAG_DISABLE(edge_net[i]->v1, VERT_IN_QUEUE);
- BM_ELEM_API_FLAG_DISABLE(edge_net[i]->v2, VERT_IN_QUEUE);
- }
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- BM_ELEM_API_FLAG_ENABLE(l_iter->e, EDGE_NET);
- BM_ELEM_API_FLAG_DISABLE(l_iter->v, VERT_IN_QUEUE);
- } while ((l_iter = l_iter->next) != l_first);
-
- float face_normal_matrix[3][3];
- axis_dominant_v3_to_m3(face_normal_matrix, f->no);
-
-
- /* any vert can be used to begin with */
- STACK_PUSH(vert_queue, l_first->v);
- BM_ELEM_API_FLAG_ENABLE(l_first->v, VERT_IN_QUEUE);
-
- while ((v = STACK_POP(vert_queue))) {
- BM_ELEM_API_FLAG_DISABLE(v, VERT_IN_QUEUE);
- if (bm_face_split_edgenet_find_loop(
- v, f->no, face_normal_matrix,
- edge_order, edge_order_len, face_verts, &face_verts_len))
- {
- BMFace *f_new;
-
- f_new = BM_face_create_verts(bm, face_verts, face_verts_len, f, BM_CREATE_NOP, false);
-
- for (i = 0; i < edge_net_len; i++) {
- BLI_assert(BM_ELEM_API_FLAG_TEST(edge_net[i], EDGE_NET));
- }
-
- if (f_new) {
- BLI_array_append(face_arr, f_new);
- copy_v3_v3(f_new->no, f->no);
-
- /* warning, normally don't do this,
- * its needed for mesh intersection - which tracks face-sides based on selection */
- f_new->head.hflag = f->head.hflag;
- if (f->head.hflag & BM_ELEM_SELECT) {
- bm->totfacesel++;
- }
-
- BM_ELEM_API_FLAG_ENABLE(f_new, FACE_NET);
-
- /* add new verts to keep finding loops for
- * (verts between boundary and manifold edges) */
- l_iter = l_first = BM_FACE_FIRST_LOOP(f_new);
- do {
- /* Avoid adding to queue multiple times (not common but happens). */
- if (!BM_ELEM_API_FLAG_TEST(l_iter->v, VERT_IN_QUEUE) &&
- bm_face_split_edgenet_find_loop_pair_exists(l_iter->v))
- {
- STACK_PUSH(vert_queue, l_iter->v);
- BM_ELEM_API_FLAG_ENABLE(l_iter->v, VERT_IN_QUEUE);
- }
- } while ((l_iter = l_iter->next) != l_first);
- }
- }
- }
-
-
- if (CustomData_has_math(&bm->ldata)) {
- /* reuse VERT_VISIT here to tag vert's already interpolated */
- BMIter iter;
- BMLoop *l_other;
-
- /* see: #BM_loop_interp_from_face for similar logic */
- void **blocks = BLI_array_alloca(blocks, f->len);
- float (*cos_2d)[2] = BLI_array_alloca(cos_2d, f->len);
- float *w = BLI_array_alloca(w, f->len);
- float axis_mat[3][3];
- float co[2];
-
- /* interior loops */
- axis_dominant_v3_to_m3(axis_mat, f->no);
-
-
- /* first simply copy from existing face */
- i = 0;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- BM_ITER_ELEM (l_other, &iter, l_iter->v, BM_LOOPS_OF_VERT) {
- if ((l_other->f != f) && BM_ELEM_API_FLAG_TEST(l_other->f, FACE_NET)) {
- CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata,
- l_iter->head.data, &l_other->head.data);
- }
- }
- /* tag not to interpolate */
- BM_ELEM_API_FLAG_ENABLE(l_iter->v, VERT_VISIT);
-
-
- mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co);
- blocks[i] = l_iter->head.data;
-
- } while ((void)i++, (l_iter = l_iter->next) != l_first);
-
-
- for (i = 0; i < edge_net_len; i++) {
- BM_ITER_ELEM (v, &iter, edge_net[i], BM_VERTS_OF_EDGE) {
- if (!BM_ELEM_API_FLAG_TEST(v, VERT_VISIT)) {
- BMIter liter;
-
- BM_ELEM_API_FLAG_ENABLE(v, VERT_VISIT);
-
- /* interpolate this loop, then copy to the rest */
- l_first = NULL;
-
- BM_ITER_ELEM (l_iter, &liter, v, BM_LOOPS_OF_VERT) {
- if (BM_ELEM_API_FLAG_TEST(l_iter->f, FACE_NET)) {
- if (l_first == NULL) {
- mul_v2_m3v3(co, axis_mat, v->co);
- interp_weights_poly_v2(w, cos_2d, f->len, co);
- CustomData_bmesh_interp(
- &bm->ldata, (const void **)blocks,
- w, NULL, f->len, l_iter->head.data);
- l_first = l_iter;
- }
- else {
- CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata,
- l_first->head.data, &l_iter->head.data);
- }
- }
- }
- }
- }
- }
- }
-
-
-
- /* cleanup */
- for (i = 0; i < edge_net_len; i++) {
- BM_ELEM_API_FLAG_DISABLE(edge_net[i], EDGE_NET);
- /* from interp only */
- BM_ELEM_API_FLAG_DISABLE(edge_net[i]->v1, VERT_VISIT);
- BM_ELEM_API_FLAG_DISABLE(edge_net[i]->v2, VERT_VISIT);
- }
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- BM_ELEM_API_FLAG_DISABLE(l_iter->e, EDGE_NET);
- /* from interp only */
- BM_ELEM_API_FLAG_DISABLE(l_iter->v, VERT_VISIT);
- } while ((l_iter = l_iter->next) != l_first);
-
- if (BLI_array_len(face_arr)) {
- bmesh_face_swap_data(f, face_arr[0]);
- BM_face_kill(bm, face_arr[0]);
- face_arr[0] = f;
- }
- else {
- BM_ELEM_API_FLAG_DISABLE(f, FACE_NET);
- }
-
- for (i = 0; i < BLI_array_len(face_arr); i++) {
- BM_ELEM_API_FLAG_DISABLE(face_arr[i], FACE_NET);
- }
-
- if (r_face_arr) {
- *r_face_arr = face_arr;
- *r_face_arr_len = BLI_array_len(face_arr);
- }
- else {
- if (face_arr) {
- MEM_freeN(face_arr);
- }
- }
-
- return true;
+ /* Note: 'VERT_IN_QUEUE' is often not needed at all,
+ * however in rare cases verts are added multiple times to the queue,
+ * that on it's own is harmless but in _very_ rare cases,
+ * the queue will overflow its maximum size,
+ * so we better be strict about this! see: T51539 */
+
+ for (i = 0; i < edge_net_len; i++) {
+ BM_ELEM_API_FLAG_ENABLE(edge_net[i], EDGE_NET);
+ BM_ELEM_API_FLAG_DISABLE(edge_net[i]->v1, VERT_IN_QUEUE);
+ BM_ELEM_API_FLAG_DISABLE(edge_net[i]->v2, VERT_IN_QUEUE);
+ }
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BM_ELEM_API_FLAG_ENABLE(l_iter->e, EDGE_NET);
+ BM_ELEM_API_FLAG_DISABLE(l_iter->v, VERT_IN_QUEUE);
+ } while ((l_iter = l_iter->next) != l_first);
+
+ float face_normal_matrix[3][3];
+ axis_dominant_v3_to_m3(face_normal_matrix, f->no);
+
+ /* any vert can be used to begin with */
+ STACK_PUSH(vert_queue, l_first->v);
+ BM_ELEM_API_FLAG_ENABLE(l_first->v, VERT_IN_QUEUE);
+
+ while ((v = STACK_POP(vert_queue))) {
+ BM_ELEM_API_FLAG_DISABLE(v, VERT_IN_QUEUE);
+ if (bm_face_split_edgenet_find_loop(v,
+ f->no,
+ face_normal_matrix,
+ edge_order,
+ edge_order_len,
+ face_verts,
+ &face_verts_len)) {
+ BMFace *f_new;
+
+ f_new = BM_face_create_verts(bm, face_verts, face_verts_len, f, BM_CREATE_NOP, false);
+
+ for (i = 0; i < edge_net_len; i++) {
+ BLI_assert(BM_ELEM_API_FLAG_TEST(edge_net[i], EDGE_NET));
+ }
+
+ if (f_new) {
+ BLI_array_append(face_arr, f_new);
+ copy_v3_v3(f_new->no, f->no);
+
+ /* warning, normally don't do this,
+ * its needed for mesh intersection - which tracks face-sides based on selection */
+ f_new->head.hflag = f->head.hflag;
+ if (f->head.hflag & BM_ELEM_SELECT) {
+ bm->totfacesel++;
+ }
+
+ BM_ELEM_API_FLAG_ENABLE(f_new, FACE_NET);
+
+ /* add new verts to keep finding loops for
+ * (verts between boundary and manifold edges) */
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_new);
+ do {
+ /* Avoid adding to queue multiple times (not common but happens). */
+ if (!BM_ELEM_API_FLAG_TEST(l_iter->v, VERT_IN_QUEUE) &&
+ bm_face_split_edgenet_find_loop_pair_exists(l_iter->v)) {
+ STACK_PUSH(vert_queue, l_iter->v);
+ BM_ELEM_API_FLAG_ENABLE(l_iter->v, VERT_IN_QUEUE);
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ }
+ }
+
+ if (CustomData_has_math(&bm->ldata)) {
+ /* reuse VERT_VISIT here to tag vert's already interpolated */
+ BMIter iter;
+ BMLoop *l_other;
+
+ /* see: #BM_loop_interp_from_face for similar logic */
+ void **blocks = BLI_array_alloca(blocks, f->len);
+ float(*cos_2d)[2] = BLI_array_alloca(cos_2d, f->len);
+ float *w = BLI_array_alloca(w, f->len);
+ float axis_mat[3][3];
+ float co[2];
+
+ /* interior loops */
+ axis_dominant_v3_to_m3(axis_mat, f->no);
+
+ /* first simply copy from existing face */
+ i = 0;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BM_ITER_ELEM (l_other, &iter, l_iter->v, BM_LOOPS_OF_VERT) {
+ if ((l_other->f != f) && BM_ELEM_API_FLAG_TEST(l_other->f, FACE_NET)) {
+ CustomData_bmesh_copy_data(
+ &bm->ldata, &bm->ldata, l_iter->head.data, &l_other->head.data);
+ }
+ }
+ /* tag not to interpolate */
+ BM_ELEM_API_FLAG_ENABLE(l_iter->v, VERT_VISIT);
+
+ mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co);
+ blocks[i] = l_iter->head.data;
+
+ } while ((void)i++, (l_iter = l_iter->next) != l_first);
+
+ for (i = 0; i < edge_net_len; i++) {
+ BM_ITER_ELEM (v, &iter, edge_net[i], BM_VERTS_OF_EDGE) {
+ if (!BM_ELEM_API_FLAG_TEST(v, VERT_VISIT)) {
+ BMIter liter;
+
+ BM_ELEM_API_FLAG_ENABLE(v, VERT_VISIT);
+
+ /* interpolate this loop, then copy to the rest */
+ l_first = NULL;
+
+ BM_ITER_ELEM (l_iter, &liter, v, BM_LOOPS_OF_VERT) {
+ if (BM_ELEM_API_FLAG_TEST(l_iter->f, FACE_NET)) {
+ if (l_first == NULL) {
+ mul_v2_m3v3(co, axis_mat, v->co);
+ interp_weights_poly_v2(w, cos_2d, f->len, co);
+ CustomData_bmesh_interp(
+ &bm->ldata, (const void **)blocks, w, NULL, f->len, l_iter->head.data);
+ l_first = l_iter;
+ }
+ else {
+ CustomData_bmesh_copy_data(
+ &bm->ldata, &bm->ldata, l_first->head.data, &l_iter->head.data);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* cleanup */
+ for (i = 0; i < edge_net_len; i++) {
+ BM_ELEM_API_FLAG_DISABLE(edge_net[i], EDGE_NET);
+ /* from interp only */
+ BM_ELEM_API_FLAG_DISABLE(edge_net[i]->v1, VERT_VISIT);
+ BM_ELEM_API_FLAG_DISABLE(edge_net[i]->v2, VERT_VISIT);
+ }
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BM_ELEM_API_FLAG_DISABLE(l_iter->e, EDGE_NET);
+ /* from interp only */
+ BM_ELEM_API_FLAG_DISABLE(l_iter->v, VERT_VISIT);
+ } while ((l_iter = l_iter->next) != l_first);
+
+ if (BLI_array_len(face_arr)) {
+ bmesh_face_swap_data(f, face_arr[0]);
+ BM_face_kill(bm, face_arr[0]);
+ face_arr[0] = f;
+ }
+ else {
+ BM_ELEM_API_FLAG_DISABLE(f, FACE_NET);
+ }
+
+ for (i = 0; i < BLI_array_len(face_arr); i++) {
+ BM_ELEM_API_FLAG_DISABLE(face_arr[i], FACE_NET);
+ }
+
+ if (r_face_arr) {
+ *r_face_arr = face_arr;
+ *r_face_arr_len = BLI_array_len(face_arr);
+ }
+ else {
+ if (face_arr) {
+ MEM_freeN(face_arr);
+ }
+ }
+
+ return true;
}
#undef FACE_NET
@@ -692,7 +696,6 @@ bool BM_face_split_edgenet(
/** \} */
-
/* -------------------------------------------------------------------- */
/* Face Split Edge-Net Connect Islands */
@@ -707,41 +710,41 @@ bool BM_face_split_edgenet(
*
* \{ */
-
#define USE_PARTIAL_CONNECT
-
#define VERT_IS_VALID BM_ELEM_INTERNAL_TAG
/* can be X or Y */
#define SORT_AXIS 0
-BLI_INLINE bool edge_isect_verts_point_2d(
- const BMEdge *e, const BMVert *v_a, const BMVert *v_b,
- float r_isect[2])
+BLI_INLINE bool edge_isect_verts_point_2d(const BMEdge *e,
+ const BMVert *v_a,
+ const BMVert *v_b,
+ float r_isect[2])
{
- /* This bias seems like it could be too large,
- * mostly its not needed, see T52329 for example where it is. */
- const float endpoint_bias = 1e-4f;
- return ((isect_seg_seg_v2_point_ex(v_a->co, v_b->co, e->v1->co, e->v2->co, endpoint_bias, r_isect) == 1) &&
- ((e->v1 != v_a) && (e->v2 != v_a) && (e->v1 != v_b) && (e->v2 != v_b)));
+ /* This bias seems like it could be too large,
+ * mostly its not needed, see T52329 for example where it is. */
+ const float endpoint_bias = 1e-4f;
+ return ((isect_seg_seg_v2_point_ex(
+ v_a->co, v_b->co, e->v1->co, e->v2->co, endpoint_bias, r_isect) == 1) &&
+ ((e->v1 != v_a) && (e->v2 != v_a) && (e->v1 != v_b) && (e->v2 != v_b)));
}
BLI_INLINE int axis_pt_cmp(const float pt_a[2], const float pt_b[2])
{
- if (pt_a[0] < pt_b[0]) {
- return -1;
- }
- if (pt_a[0] > pt_b[0]) {
- return 1;
- }
- if (pt_a[1] < pt_b[1]) {
- return -1;
- }
- if (pt_a[1] > pt_b[1]) {
- return 1;
- }
- return 0;
+ if (pt_a[0] < pt_b[0]) {
+ return -1;
+ }
+ if (pt_a[0] > pt_b[0]) {
+ return 1;
+ }
+ if (pt_a[1] < pt_b[1]) {
+ return -1;
+ }
+ if (pt_a[1] > pt_b[1]) {
+ return 1;
+ }
+ return 0;
}
/**
@@ -750,106 +753,107 @@ BLI_INLINE int axis_pt_cmp(const float pt_a[2], const float pt_b[2])
* (edges remain in `edge_links`).
*/
struct EdgeGroupIsland {
- LinkNode edge_links; /* keep first */
- uint vert_len, edge_len;
-
- /* Set the following vars once we have >1 groups */
-
- /* when when an edge in a previous group connects to this one,
- * so theres no need to create one pointing back. */
- uint has_prev_edge : 1;
-
- /* verts in the group which has the lowest & highest values,
- * the lower vertex is connected to the first edge */
- struct {
- BMVert *min, *max;
- /* used for sorting only */
- float min_axis[2];
- float max_axis[2];
- } vert_span;
+ LinkNode edge_links; /* keep first */
+ uint vert_len, edge_len;
+
+ /* Set the following vars once we have >1 groups */
+
+ /* when when an edge in a previous group connects to this one,
+ * so theres no need to create one pointing back. */
+ uint has_prev_edge : 1;
+
+ /* verts in the group which has the lowest & highest values,
+ * the lower vertex is connected to the first edge */
+ struct {
+ BMVert *min, *max;
+ /* used for sorting only */
+ float min_axis[2];
+ float max_axis[2];
+ } vert_span;
};
static int group_min_cmp_fn(const void *p1, const void *p2)
{
- const struct EdgeGroupIsland *g1 = *(struct EdgeGroupIsland **)p1;
- const struct EdgeGroupIsland *g2 = *(struct EdgeGroupIsland **)p2;
- /* min->co[SORT_AXIS] hasn't been applied yet */
- int test = axis_pt_cmp(g1->vert_span.min_axis, g2->vert_span.min_axis);
- if (UNLIKELY(test == 0)) {
- test = axis_pt_cmp(g1->vert_span.max_axis, g2->vert_span.max_axis);
- }
- return test;
+ const struct EdgeGroupIsland *g1 = *(struct EdgeGroupIsland **)p1;
+ const struct EdgeGroupIsland *g2 = *(struct EdgeGroupIsland **)p2;
+ /* min->co[SORT_AXIS] hasn't been applied yet */
+ int test = axis_pt_cmp(g1->vert_span.min_axis, g2->vert_span.min_axis);
+ if (UNLIKELY(test == 0)) {
+ test = axis_pt_cmp(g1->vert_span.max_axis, g2->vert_span.max_axis);
+ }
+ return test;
}
struct Edges_VertVert_BVHTreeTest {
- float dist_orig;
- BMEdge **edge_arr;
+ float dist_orig;
+ BMEdge **edge_arr;
- BMVert *v_origin;
- BMVert *v_other;
+ BMVert *v_origin;
+ BMVert *v_other;
- const uint *vert_range;
+ const uint *vert_range;
};
struct Edges_VertRay_BVHTreeTest {
- BMEdge **edge_arr;
+ BMEdge **edge_arr;
- BMVert *v_origin;
+ BMVert *v_origin;
- const uint *vert_range;
+ const uint *vert_range;
};
-static void bvhtree_test_edges_isect_2d_vert_cb(
- void *user_data, int index, const BVHTreeRay *UNUSED(ray), BVHTreeRayHit *hit)
+static void bvhtree_test_edges_isect_2d_vert_cb(void *user_data,
+ int index,
+ const BVHTreeRay *UNUSED(ray),
+ BVHTreeRayHit *hit)
{
- struct Edges_VertVert_BVHTreeTest *data = user_data;
- const BMEdge *e = data->edge_arr[index];
- const int v1_index = BM_elem_index_get(e->v1);
- float co_isect[2];
-
- if (edge_isect_verts_point_2d(e, data->v_origin, data->v_other, co_isect)) {
- const float t = line_point_factor_v2(co_isect, data->v_origin->co, data->v_other->co);
- const float dist_new = data->dist_orig * t;
- /* avoid float precision issues, possible this is greater,
- * check above zero to allow some overlap
- * (and needed for partial-connect which will overlap vertices) */
- if (LIKELY((dist_new < hit->dist) && (dist_new > 0.0f))) {
- /* v1/v2 will both be in the same group */
- if (v1_index < (int)data->vert_range[0] ||
- v1_index >= (int)data->vert_range[1])
- {
- hit->dist = dist_new;
- hit->index = index;
- }
- }
- }
+ struct Edges_VertVert_BVHTreeTest *data = user_data;
+ const BMEdge *e = data->edge_arr[index];
+ const int v1_index = BM_elem_index_get(e->v1);
+ float co_isect[2];
+
+ if (edge_isect_verts_point_2d(e, data->v_origin, data->v_other, co_isect)) {
+ const float t = line_point_factor_v2(co_isect, data->v_origin->co, data->v_other->co);
+ const float dist_new = data->dist_orig * t;
+ /* avoid float precision issues, possible this is greater,
+ * check above zero to allow some overlap
+ * (and needed for partial-connect which will overlap vertices) */
+ if (LIKELY((dist_new < hit->dist) && (dist_new > 0.0f))) {
+ /* v1/v2 will both be in the same group */
+ if (v1_index < (int)data->vert_range[0] || v1_index >= (int)data->vert_range[1]) {
+ hit->dist = dist_new;
+ hit->index = index;
+ }
+ }
+ }
}
-static void bvhtree_test_edges_isect_2d_ray_cb(
- void *user_data, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
+static void bvhtree_test_edges_isect_2d_ray_cb(void *user_data,
+ int index,
+ const BVHTreeRay *ray,
+ BVHTreeRayHit *hit)
{
- struct Edges_VertRay_BVHTreeTest *data = user_data;
- const BMEdge *e = data->edge_arr[index];
-
- /* direction is normalized, so this will be the distance */
- float dist_new;
- if (isect_ray_seg_v2(data->v_origin->co, ray->direction, e->v1->co, e->v2->co, &dist_new, NULL)) {
- /* avoid float precision issues, possible this is greater,
- * check above zero to allow some overlap
- * (and needed for partial-connect which will overlap vertices) */
- if (LIKELY(dist_new < hit->dist && (dist_new > 0.0f))) {
- if (e->v1 != data->v_origin && e->v2 != data->v_origin) {
- const int v1_index = BM_elem_index_get(e->v1);
- /* v1/v2 will both be in the same group */
- if (v1_index < (int)data->vert_range[0] ||
- v1_index >= (int)data->vert_range[1])
- {
- hit->dist = dist_new;
- hit->index = index;
- }
- }
- }
- }
+ struct Edges_VertRay_BVHTreeTest *data = user_data;
+ const BMEdge *e = data->edge_arr[index];
+
+ /* direction is normalized, so this will be the distance */
+ float dist_new;
+ if (isect_ray_seg_v2(
+ data->v_origin->co, ray->direction, e->v1->co, e->v2->co, &dist_new, NULL)) {
+ /* avoid float precision issues, possible this is greater,
+ * check above zero to allow some overlap
+ * (and needed for partial-connect which will overlap vertices) */
+ if (LIKELY(dist_new < hit->dist && (dist_new > 0.0f))) {
+ if (e->v1 != data->v_origin && e->v2 != data->v_origin) {
+ const int v1_index = BM_elem_index_get(e->v1);
+ /* v1/v2 will both be in the same group */
+ if (v1_index < (int)data->vert_range[0] || v1_index >= (int)data->vert_range[1]) {
+ hit->dist = dist_new;
+ hit->index = index;
+ }
+ }
+ }
+ }
}
/**
@@ -859,186 +863,193 @@ static void bvhtree_test_edges_isect_2d_ray_cb(
* ... which don't change each call.
*/
struct EdgeGroup_FindConnection_Args {
- BVHTree *bvhtree;
- BMEdge **edge_arr;
- uint edge_arr_len;
+ BVHTree *bvhtree;
+ BMEdge **edge_arr;
+ uint edge_arr_len;
- BMEdge **edge_arr_new;
- uint edge_arr_new_len;
+ BMEdge **edge_arr_new;
+ uint edge_arr_new_len;
- const uint *vert_range;
+ const uint *vert_range;
};
-static BMEdge *test_edges_isect_2d_vert(
- const struct EdgeGroup_FindConnection_Args *args,
- BMVert *v_origin, BMVert *v_other)
+static BMEdge *test_edges_isect_2d_vert(const struct EdgeGroup_FindConnection_Args *args,
+ BMVert *v_origin,
+ BMVert *v_other)
{
- int index;
-
- BVHTreeRayHit hit = {0};
- float dir[3];
-
- sub_v2_v2v2(dir, v_other->co, v_origin->co);
- dir[2] = 0.0f;
- hit.index = -1;
- hit.dist = normalize_v2(dir);
-
- struct Edges_VertVert_BVHTreeTest user_data = {0};
- user_data.dist_orig = hit.dist;
- user_data.edge_arr = args->edge_arr;
- user_data.v_origin = v_origin;
- user_data.v_other = v_other;
- user_data.vert_range = args->vert_range;
-
- index = BLI_bvhtree_ray_cast_ex(
- args->bvhtree, v_origin->co, dir, 0.0f, &hit,
- bvhtree_test_edges_isect_2d_vert_cb, &user_data, 0);
-
- BMEdge *e_hit = (index != -1) ? args->edge_arr[index] : NULL;
-
- /* check existing connections (no spatial optimization here since we're continually adding). */
- if (LIKELY(index == -1)) {
- float t_best = 1.0f;
- for (uint i = 0; i < args->edge_arr_new_len; i++) {
- float co_isect[2];
- if (UNLIKELY(edge_isect_verts_point_2d(args->edge_arr_new[i], v_origin, v_other, co_isect))) {
- const float t_test = line_point_factor_v2(co_isect, v_origin->co, v_other->co);
- if (t_test < t_best) {
- t_best = t_test;
-
- e_hit = args->edge_arr_new[i];
- }
- }
- }
- }
-
- return e_hit;
+ int index;
+
+ BVHTreeRayHit hit = {0};
+ float dir[3];
+
+ sub_v2_v2v2(dir, v_other->co, v_origin->co);
+ dir[2] = 0.0f;
+ hit.index = -1;
+ hit.dist = normalize_v2(dir);
+
+ struct Edges_VertVert_BVHTreeTest user_data = {0};
+ user_data.dist_orig = hit.dist;
+ user_data.edge_arr = args->edge_arr;
+ user_data.v_origin = v_origin;
+ user_data.v_other = v_other;
+ user_data.vert_range = args->vert_range;
+
+ index = BLI_bvhtree_ray_cast_ex(args->bvhtree,
+ v_origin->co,
+ dir,
+ 0.0f,
+ &hit,
+ bvhtree_test_edges_isect_2d_vert_cb,
+ &user_data,
+ 0);
+
+ BMEdge *e_hit = (index != -1) ? args->edge_arr[index] : NULL;
+
+ /* check existing connections (no spatial optimization here since we're continually adding). */
+ if (LIKELY(index == -1)) {
+ float t_best = 1.0f;
+ for (uint i = 0; i < args->edge_arr_new_len; i++) {
+ float co_isect[2];
+ if (UNLIKELY(
+ edge_isect_verts_point_2d(args->edge_arr_new[i], v_origin, v_other, co_isect))) {
+ const float t_test = line_point_factor_v2(co_isect, v_origin->co, v_other->co);
+ if (t_test < t_best) {
+ t_best = t_test;
+
+ e_hit = args->edge_arr_new[i];
+ }
+ }
+ }
+ }
+
+ return e_hit;
}
/**
* Similar to #test_edges_isect_2d_vert but we're casting into a direction,
* (not to a vertex)
*/
-static BMEdge *test_edges_isect_2d_ray(
- const struct EdgeGroup_FindConnection_Args *args,
- BMVert *v_origin, const float dir[3])
+static BMEdge *test_edges_isect_2d_ray(const struct EdgeGroup_FindConnection_Args *args,
+ BMVert *v_origin,
+ const float dir[3])
{
- int index;
- BVHTreeRayHit hit = {0};
-
- BLI_ASSERT_UNIT_V2(dir);
-
- hit.index = -1;
- hit.dist = BVH_RAYCAST_DIST_MAX;
-
- struct Edges_VertRay_BVHTreeTest user_data = {0};
- user_data.edge_arr = args->edge_arr;
- user_data.v_origin = v_origin;
- user_data.vert_range = args->vert_range;
-
- index = BLI_bvhtree_ray_cast_ex(
- args->bvhtree, v_origin->co, dir, 0.0f, &hit,
- bvhtree_test_edges_isect_2d_ray_cb, &user_data, 0);
-
- BMEdge *e_hit = (index != -1) ? args->edge_arr[index] : NULL;
-
- /* check existing connections (no spatial optimization here since we're continually adding). */
- if (LIKELY(index != -1)) {
- for (uint i = 0; i < args->edge_arr_new_len; i++) {
- BMEdge *e = args->edge_arr_new[i];
- float dist_new;
- if (isect_ray_seg_v2(v_origin->co, dir, e->v1->co, e->v2->co, &dist_new, NULL)) {
- if (e->v1 != v_origin && e->v2 != v_origin) {
- /* avoid float precision issues, possible this is greater */
- if (LIKELY(dist_new < hit.dist)) {
- hit.dist = dist_new;
-
- e_hit = args->edge_arr_new[i];
- }
- }
- }
- }
- }
-
- return e_hit;
+ int index;
+ BVHTreeRayHit hit = {0};
+
+ BLI_ASSERT_UNIT_V2(dir);
+
+ hit.index = -1;
+ hit.dist = BVH_RAYCAST_DIST_MAX;
+
+ struct Edges_VertRay_BVHTreeTest user_data = {0};
+ user_data.edge_arr = args->edge_arr;
+ user_data.v_origin = v_origin;
+ user_data.vert_range = args->vert_range;
+
+ index = BLI_bvhtree_ray_cast_ex(args->bvhtree,
+ v_origin->co,
+ dir,
+ 0.0f,
+ &hit,
+ bvhtree_test_edges_isect_2d_ray_cb,
+ &user_data,
+ 0);
+
+ BMEdge *e_hit = (index != -1) ? args->edge_arr[index] : NULL;
+
+ /* check existing connections (no spatial optimization here since we're continually adding). */
+ if (LIKELY(index != -1)) {
+ for (uint i = 0; i < args->edge_arr_new_len; i++) {
+ BMEdge *e = args->edge_arr_new[i];
+ float dist_new;
+ if (isect_ray_seg_v2(v_origin->co, dir, e->v1->co, e->v2->co, &dist_new, NULL)) {
+ if (e->v1 != v_origin && e->v2 != v_origin) {
+ /* avoid float precision issues, possible this is greater */
+ if (LIKELY(dist_new < hit.dist)) {
+ hit.dist = dist_new;
+
+ e_hit = args->edge_arr_new[i];
+ }
+ }
+ }
+ }
+ }
+
+ return e_hit;
}
-static int bm_face_split_edgenet_find_connection(
- const struct EdgeGroup_FindConnection_Args *args,
- BMVert *v_origin,
- /* false = negative, true = positive */
- bool direction_sign)
+static int bm_face_split_edgenet_find_connection(const struct EdgeGroup_FindConnection_Args *args,
+ BMVert *v_origin,
+ /* false = negative, true = positive */
+ bool direction_sign)
{
- /**
- * Method for finding connection is as follows:
- *
- * - Cast a ray along either the positive or negative directions.
- * - Take the hit-edge, and cast rays to their vertices checking those rays don't intersect a closer edge.
- * - Keep taking the hit-edge and testing its verts until a vertex is found which isn't blocked by an edge.
- *
- * \note It's possible none of the verts can be accessed (with self-intersecting lines).
- * In that case theres no right answer (without subdividing edges),
- * so return a fall-back vertex in that case.
- */
-
- const float dir[3] = {[SORT_AXIS] = direction_sign ? 1.0f : -1.0f};
- BMEdge *e_hit = test_edges_isect_2d_ray(args, v_origin, dir);
- BMVert *v_other = NULL;
-
- if (e_hit) {
- BMVert *v_other_fallback = NULL;
-
- BLI_SMALLSTACK_DECLARE(vert_search, BMVert *);
-
- /* ensure we never add verts multiple times (not all that likely - but possible) */
- BLI_SMALLSTACK_DECLARE(vert_blacklist, BMVert *);
-
- do {
- BMVert *v_pair[2];
- /* ensure the closest vertex is popped back off the stack first */
- if (len_squared_v2v2(v_origin->co, e_hit->v1->co) >
- len_squared_v2v2(v_origin->co, e_hit->v2->co))
- {
- ARRAY_SET_ITEMS(v_pair, e_hit->v1, e_hit->v2);
- }
- else {
- ARRAY_SET_ITEMS(v_pair, e_hit->v2, e_hit->v1);
- }
-
- for (int j = 0; j < 2; j++) {
- BMVert *v_iter = v_pair[j];
- if (BM_elem_flag_test(v_iter, VERT_IS_VALID)) {
- if (direction_sign ? (v_iter->co[SORT_AXIS] > v_origin->co[SORT_AXIS]) :
- (v_iter->co[SORT_AXIS] < v_origin->co[SORT_AXIS]))
- {
- BLI_SMALLSTACK_PUSH(vert_search, v_iter);
- BLI_SMALLSTACK_PUSH(vert_blacklist, v_iter);
- BM_elem_flag_disable(v_iter, VERT_IS_VALID);
- }
- }
- }
- v_other_fallback = v_other;
-
- } while ((v_other = BLI_SMALLSTACK_POP(vert_search)) &&
- (e_hit = test_edges_isect_2d_vert(args, v_origin, v_other)));
-
- if (v_other == NULL) {
- printf("Using fallback\n");
- v_other = v_other_fallback;
- }
-
- /* reset the blacklist flag, for future use */
- BMVert *v;
- while ((v = BLI_SMALLSTACK_POP(vert_blacklist))) {
- BM_elem_flag_enable(v, VERT_IS_VALID);
- }
- }
-
- /* if we reach this line, v_other is either the best vertex or its NULL */
- return v_other ? BM_elem_index_get(v_other) : -1;
+ /**
+ * Method for finding connection is as follows:
+ *
+ * - Cast a ray along either the positive or negative directions.
+ * - Take the hit-edge, and cast rays to their vertices checking those rays don't intersect a closer edge.
+ * - Keep taking the hit-edge and testing its verts until a vertex is found which isn't blocked by an edge.
+ *
+ * \note It's possible none of the verts can be accessed (with self-intersecting lines).
+ * In that case theres no right answer (without subdividing edges),
+ * so return a fall-back vertex in that case.
+ */
+
+ const float dir[3] = {[SORT_AXIS] = direction_sign ? 1.0f : -1.0f};
+ BMEdge *e_hit = test_edges_isect_2d_ray(args, v_origin, dir);
+ BMVert *v_other = NULL;
+
+ if (e_hit) {
+ BMVert *v_other_fallback = NULL;
+
+ BLI_SMALLSTACK_DECLARE(vert_search, BMVert *);
+
+ /* ensure we never add verts multiple times (not all that likely - but possible) */
+ BLI_SMALLSTACK_DECLARE(vert_blacklist, BMVert *);
+
+ do {
+ BMVert *v_pair[2];
+ /* ensure the closest vertex is popped back off the stack first */
+ if (len_squared_v2v2(v_origin->co, e_hit->v1->co) >
+ len_squared_v2v2(v_origin->co, e_hit->v2->co)) {
+ ARRAY_SET_ITEMS(v_pair, e_hit->v1, e_hit->v2);
+ }
+ else {
+ ARRAY_SET_ITEMS(v_pair, e_hit->v2, e_hit->v1);
+ }
+
+ for (int j = 0; j < 2; j++) {
+ BMVert *v_iter = v_pair[j];
+ if (BM_elem_flag_test(v_iter, VERT_IS_VALID)) {
+ if (direction_sign ? (v_iter->co[SORT_AXIS] > v_origin->co[SORT_AXIS]) :
+ (v_iter->co[SORT_AXIS] < v_origin->co[SORT_AXIS])) {
+ BLI_SMALLSTACK_PUSH(vert_search, v_iter);
+ BLI_SMALLSTACK_PUSH(vert_blacklist, v_iter);
+ BM_elem_flag_disable(v_iter, VERT_IS_VALID);
+ }
+ }
+ }
+ v_other_fallback = v_other;
+
+ } while ((v_other = BLI_SMALLSTACK_POP(vert_search)) &&
+ (e_hit = test_edges_isect_2d_vert(args, v_origin, v_other)));
+
+ if (v_other == NULL) {
+ printf("Using fallback\n");
+ v_other = v_other_fallback;
+ }
+
+ /* reset the blacklist flag, for future use */
+ BMVert *v;
+ while ((v = BLI_SMALLSTACK_POP(vert_blacklist))) {
+ BM_elem_flag_enable(v, VERT_IS_VALID);
+ }
+ }
+
+ /* if we reach this line, v_other is either the best vertex or its NULL */
+ return v_other ? BM_elem_index_get(v_other) : -1;
}
-
/**
* Support for connecting islands that have single-edge connections.
* This options is not very optimal (however its not needed for booleans either).
@@ -1051,8 +1062,8 @@ static int bm_face_split_edgenet_find_connection(
*/
static bool test_tagged_and_notface(BMEdge *e, void *fptr)
{
- BMFace *f = (BMFace *)fptr;
- return BM_elem_flag_test(e, BM_ELEM_INTERNAL_TAG) && !BM_edge_in_face(e, f);
+ BMFace *f = (BMFace *)fptr;
+ return BM_elem_flag_test(e, BM_ELEM_INTERNAL_TAG) && !BM_edge_in_face(e, f);
}
/**
@@ -1064,148 +1075,144 @@ static bool test_tagged_and_notface(BMEdge *e, void *fptr)
*/
static BMVert *bm_face_split_edgenet_partial_connect(BMesh *bm, BMVert *v_delimit, BMFace *f)
{
- /* -------------------------------------------------------------------- */
- /* Initial check that we may be a delimiting vert (keep this fast) */
-
- /* initial check - see if we have 3+ flagged edges attached to 'v_delimit'
- * if not, we can early exit */
- LinkNode *e_delimit_list = NULL;
- uint e_delimit_list_len = 0;
-
-#define EDGE_NOT_IN_STACK BM_ELEM_INTERNAL_TAG
-#define VERT_NOT_IN_STACK BM_ELEM_INTERNAL_TAG
-
-#define FOREACH_VERT_EDGE(v_, e_, body_) { \
- BMEdge *e_ = v_->e; \
- do { body_ } while ((e_ = BM_DISK_EDGE_NEXT(e_, v_)) != v_->e); \
-} ((void)0)
-
- /* start with face edges, since we need to split away wire-only edges */
- BMEdge *e_face_init = NULL;
-
- FOREACH_VERT_EDGE(v_delimit, e_iter, {
- if (BM_elem_flag_test(e_iter, EDGE_NOT_IN_STACK)) {
- BLI_assert(BM_elem_flag_test(BM_edge_other_vert(e_iter, v_delimit), VERT_NOT_IN_STACK));
- BLI_linklist_prepend_alloca(&e_delimit_list, e_iter);
- e_delimit_list_len++;
- if (e_iter->l != NULL && BM_edge_in_face(e_iter, f)) {
- e_face_init = e_iter;
- }
- }
- });
-
- /* skip typical edge-chain verts */
- if (LIKELY(e_delimit_list_len <= 2)) {
- return NULL;
- }
-
-
- /* -------------------------------------------------------------------- */
- /* Complicated stuff starts now! */
-
-
- /* Store connected vertices for restoring the flag */
- LinkNode *vert_stack = NULL;
- BLI_linklist_prepend_alloca(&vert_stack, v_delimit);
- BM_elem_flag_disable(v_delimit, VERT_NOT_IN_STACK);
-
- /* Walk the net... */
- {
- BLI_SMALLSTACK_DECLARE(search, BMVert *);
- BMVert *v_other = BM_edge_other_vert(e_face_init ? e_face_init : v_delimit->e, v_delimit);
-
- BLI_SMALLSTACK_PUSH(search, v_other);
- BM_elem_flag_disable(v_other, VERT_NOT_IN_STACK);
-
- while ((v_other = BLI_SMALLSTACK_POP(search))) {
- BLI_assert(BM_elem_flag_test(v_other, VERT_NOT_IN_STACK) == false);
- BLI_linklist_prepend_alloca(&vert_stack, v_other);
- BMEdge *e_iter = v_other->e;
- do {
- BMVert *v_step = BM_edge_other_vert(e_iter, v_other);
- if (BM_elem_flag_test(e_iter, EDGE_NOT_IN_STACK)) {
- if (BM_elem_flag_test(v_step, VERT_NOT_IN_STACK)) {
- BM_elem_flag_disable(v_step, VERT_NOT_IN_STACK);
- BLI_SMALLSTACK_PUSH(search, v_step);
- }
- }
- } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v_other)) != v_other->e);
- }
- }
-
- /* Detect if this is a delimiter by checking if we didn't walk any of edges connected to 'v_delimit' */
- bool is_delimit = false;
- FOREACH_VERT_EDGE(v_delimit, e_iter, {
- BMVert *v_step = BM_edge_other_vert(e_iter, v_delimit);
- if (BM_elem_flag_test(v_step, VERT_NOT_IN_STACK) && !BM_edge_in_face(e_iter, f)) {
- is_delimit = true; /* if one vertex is valid - we have a mix */
- }
- else {
- /* match the vertex flag (only for edges around 'v_delimit') */
- BM_elem_flag_disable(e_iter, EDGE_NOT_IN_STACK);
- }
- });
-
-#undef FOREACH_VERT_EDGE
-
- /* Execute the split */
- BMVert *v_split = NULL;
- if (is_delimit) {
- v_split = BM_vert_create(bm, v_delimit->co, NULL, 0);
- BM_vert_separate_tested_edges(bm, v_split, v_delimit, test_tagged_and_notface, f);
- BM_elem_flag_enable(v_split, VERT_NOT_IN_STACK);
-
- BLI_assert(v_delimit->e != NULL);
-
- /* Degenerate, avoid eternal loop, see: T59074. */
-#if 0
- BLI_assert(v_split->e != NULL);
-#else
- if (UNLIKELY(v_split->e == NULL)) {
- BM_vert_kill(bm, v_split);
- v_split = NULL;
- }
-#endif
- }
-
- /* Restore flags */
- do {
- BM_elem_flag_enable((BMVert *)vert_stack->link, VERT_NOT_IN_STACK);
- } while ((vert_stack = vert_stack->next));
-
- do {
- BM_elem_flag_enable((BMEdge *)e_delimit_list->link, EDGE_NOT_IN_STACK);
- } while ((e_delimit_list = e_delimit_list->next));
-
-#undef EDGE_NOT_IN_STACK
-#undef VERT_NOT_IN_STACK
-
- return v_split;
+ /* -------------------------------------------------------------------- */
+ /* Initial check that we may be a delimiting vert (keep this fast) */
+
+ /* initial check - see if we have 3+ flagged edges attached to 'v_delimit'
+ * if not, we can early exit */
+ LinkNode *e_delimit_list = NULL;
+ uint e_delimit_list_len = 0;
+
+# define EDGE_NOT_IN_STACK BM_ELEM_INTERNAL_TAG
+# define VERT_NOT_IN_STACK BM_ELEM_INTERNAL_TAG
+
+# define FOREACH_VERT_EDGE(v_, e_, body_) \
+ { \
+ BMEdge *e_ = v_->e; \
+ do { \
+ body_ \
+ } while ((e_ = BM_DISK_EDGE_NEXT(e_, v_)) != v_->e); \
+ } \
+ ((void)0)
+
+ /* start with face edges, since we need to split away wire-only edges */
+ BMEdge *e_face_init = NULL;
+
+ FOREACH_VERT_EDGE(v_delimit, e_iter, {
+ if (BM_elem_flag_test(e_iter, EDGE_NOT_IN_STACK)) {
+ BLI_assert(BM_elem_flag_test(BM_edge_other_vert(e_iter, v_delimit), VERT_NOT_IN_STACK));
+ BLI_linklist_prepend_alloca(&e_delimit_list, e_iter);
+ e_delimit_list_len++;
+ if (e_iter->l != NULL && BM_edge_in_face(e_iter, f)) {
+ e_face_init = e_iter;
+ }
+ }
+ });
+
+ /* skip typical edge-chain verts */
+ if (LIKELY(e_delimit_list_len <= 2)) {
+ return NULL;
+ }
+
+ /* -------------------------------------------------------------------- */
+ /* Complicated stuff starts now! */
+
+ /* Store connected vertices for restoring the flag */
+ LinkNode *vert_stack = NULL;
+ BLI_linklist_prepend_alloca(&vert_stack, v_delimit);
+ BM_elem_flag_disable(v_delimit, VERT_NOT_IN_STACK);
+
+ /* Walk the net... */
+ {
+ BLI_SMALLSTACK_DECLARE(search, BMVert *);
+ BMVert *v_other = BM_edge_other_vert(e_face_init ? e_face_init : v_delimit->e, v_delimit);
+
+ BLI_SMALLSTACK_PUSH(search, v_other);
+ BM_elem_flag_disable(v_other, VERT_NOT_IN_STACK);
+
+ while ((v_other = BLI_SMALLSTACK_POP(search))) {
+ BLI_assert(BM_elem_flag_test(v_other, VERT_NOT_IN_STACK) == false);
+ BLI_linklist_prepend_alloca(&vert_stack, v_other);
+ BMEdge *e_iter = v_other->e;
+ do {
+ BMVert *v_step = BM_edge_other_vert(e_iter, v_other);
+ if (BM_elem_flag_test(e_iter, EDGE_NOT_IN_STACK)) {
+ if (BM_elem_flag_test(v_step, VERT_NOT_IN_STACK)) {
+ BM_elem_flag_disable(v_step, VERT_NOT_IN_STACK);
+ BLI_SMALLSTACK_PUSH(search, v_step);
+ }
+ }
+ } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v_other)) != v_other->e);
+ }
+ }
+
+ /* Detect if this is a delimiter by checking if we didn't walk any of edges connected to 'v_delimit' */
+ bool is_delimit = false;
+ FOREACH_VERT_EDGE(v_delimit, e_iter, {
+ BMVert *v_step = BM_edge_other_vert(e_iter, v_delimit);
+ if (BM_elem_flag_test(v_step, VERT_NOT_IN_STACK) && !BM_edge_in_face(e_iter, f)) {
+ is_delimit = true; /* if one vertex is valid - we have a mix */
+ }
+ else {
+ /* match the vertex flag (only for edges around 'v_delimit') */
+ BM_elem_flag_disable(e_iter, EDGE_NOT_IN_STACK);
+ }
+ });
+
+# undef FOREACH_VERT_EDGE
+
+ /* Execute the split */
+ BMVert *v_split = NULL;
+ if (is_delimit) {
+ v_split = BM_vert_create(bm, v_delimit->co, NULL, 0);
+ BM_vert_separate_tested_edges(bm, v_split, v_delimit, test_tagged_and_notface, f);
+ BM_elem_flag_enable(v_split, VERT_NOT_IN_STACK);
+
+ BLI_assert(v_delimit->e != NULL);
+
+ /* Degenerate, avoid eternal loop, see: T59074. */
+# if 0
+ BLI_assert(v_split->e != NULL);
+# else
+ if (UNLIKELY(v_split->e == NULL)) {
+ BM_vert_kill(bm, v_split);
+ v_split = NULL;
+ }
+# endif
+ }
+
+ /* Restore flags */
+ do {
+ BM_elem_flag_enable((BMVert *)vert_stack->link, VERT_NOT_IN_STACK);
+ } while ((vert_stack = vert_stack->next));
+
+ do {
+ BM_elem_flag_enable((BMEdge *)e_delimit_list->link, EDGE_NOT_IN_STACK);
+ } while ((e_delimit_list = e_delimit_list->next));
+
+# undef EDGE_NOT_IN_STACK
+# undef VERT_NOT_IN_STACK
+
+ return v_split;
}
-
/**
* Check if connecting vertices would cause an edge with duplicate verts.
*/
-static bool bm_vert_partial_connect_check_overlap(
- const int *remap,
- const int v_a_index, const int v_b_index)
+static bool bm_vert_partial_connect_check_overlap(const int *remap,
+ const int v_a_index,
+ const int v_b_index)
{
- /* connected to eachother */
- if (UNLIKELY((remap[v_a_index] == v_b_index) ||
- (remap[v_b_index] == v_a_index)))
- {
- return true;
- }
- else {
- return false;
- }
+ /* connected to eachother */
+ if (UNLIKELY((remap[v_a_index] == v_b_index) || (remap[v_b_index] == v_a_index))) {
+ return true;
+ }
+ else {
+ return false;
+ }
}
-
-#endif /* USE_PARTIAL_CONNECT */
-
-
+#endif /* USE_PARTIAL_CONNECT */
/**
* For when the edge-net has holes in it-this connects them.
@@ -1215,476 +1222,470 @@ static bool bm_vert_partial_connect_check_overlap(
* \param mem_arena: Avoids many small allocs & should be cleared after each use.
* take care since \a r_edge_net_new is stored in \a r_edge_net_new.
*/
-bool BM_face_split_edgenet_connect_islands(
- BMesh *bm,
- BMFace *f, BMEdge **edge_net_init, const uint edge_net_init_len,
- bool use_partial_connect,
- MemArena *mem_arena,
- BMEdge ***r_edge_net_new, uint *r_edge_net_new_len)
+bool BM_face_split_edgenet_connect_islands(BMesh *bm,
+ BMFace *f,
+ BMEdge **edge_net_init,
+ const uint edge_net_init_len,
+ bool use_partial_connect,
+ MemArena *mem_arena,
+ BMEdge ***r_edge_net_new,
+ uint *r_edge_net_new_len)
{
- /* -------------------------------------------------------------------- */
- /* This function has 2 main parts.
- *
- * - Check if there are any holes.
- * - Connect the holes with edges (if any are found).
- *
- * Keep the first part fast since it will run very often for edge-nets that have no holes.
- *
- * \note Don't use the mem_arena unless he have holes to fill.
- * (avoid thrashing the area when the initial check isn't so intensive on the stack).
- */
-
- const uint edge_arr_len = (uint)edge_net_init_len + (uint)f->len;
- BMEdge **edge_arr = BLI_array_alloca(edge_arr, edge_arr_len);
- bool ok = false;
- uint edge_net_new_len = (uint)edge_net_init_len;
-
- memcpy(edge_arr, edge_net_init, sizeof(*edge_arr) * (size_t)edge_net_init_len);
-
- /* _must_ clear on exit */
-#define EDGE_NOT_IN_STACK BM_ELEM_INTERNAL_TAG
-#define VERT_NOT_IN_STACK BM_ELEM_INTERNAL_TAG
-
- {
- uint i = edge_net_init_len;
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- BLI_assert(!BM_elem_flag_test(l_iter->v, VERT_NOT_IN_STACK));
- BLI_assert(!BM_elem_flag_test(l_iter->e, EDGE_NOT_IN_STACK));
- edge_arr[i++] = l_iter->e;
- } while ((l_iter = l_iter->next) != l_first);
- BLI_assert(i == edge_arr_len);
- }
-
- for (uint i = 0; i < edge_arr_len; i++) {
- BM_elem_flag_enable(edge_arr[i], EDGE_NOT_IN_STACK);
- BM_elem_flag_enable(edge_arr[i]->v1, VERT_NOT_IN_STACK);
- BM_elem_flag_enable(edge_arr[i]->v2, VERT_NOT_IN_STACK);
- }
-
-
+ /* -------------------------------------------------------------------- */
+ /* This function has 2 main parts.
+ *
+ * - Check if there are any holes.
+ * - Connect the holes with edges (if any are found).
+ *
+ * Keep the first part fast since it will run very often for edge-nets that have no holes.
+ *
+ * \note Don't use the mem_arena unless he have holes to fill.
+ * (avoid thrashing the area when the initial check isn't so intensive on the stack).
+ */
+
+ const uint edge_arr_len = (uint)edge_net_init_len + (uint)f->len;
+ BMEdge **edge_arr = BLI_array_alloca(edge_arr, edge_arr_len);
+ bool ok = false;
+ uint edge_net_new_len = (uint)edge_net_init_len;
+
+ memcpy(edge_arr, edge_net_init, sizeof(*edge_arr) * (size_t)edge_net_init_len);
+
+ /* _must_ clear on exit */
+#define EDGE_NOT_IN_STACK BM_ELEM_INTERNAL_TAG
+#define VERT_NOT_IN_STACK BM_ELEM_INTERNAL_TAG
+
+ {
+ uint i = edge_net_init_len;
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BLI_assert(!BM_elem_flag_test(l_iter->v, VERT_NOT_IN_STACK));
+ BLI_assert(!BM_elem_flag_test(l_iter->e, EDGE_NOT_IN_STACK));
+ edge_arr[i++] = l_iter->e;
+ } while ((l_iter = l_iter->next) != l_first);
+ BLI_assert(i == edge_arr_len);
+ }
+
+ for (uint i = 0; i < edge_arr_len; i++) {
+ BM_elem_flag_enable(edge_arr[i], EDGE_NOT_IN_STACK);
+ BM_elem_flag_enable(edge_arr[i]->v1, VERT_NOT_IN_STACK);
+ BM_elem_flag_enable(edge_arr[i]->v2, VERT_NOT_IN_STACK);
+ }
#ifdef USE_PARTIAL_CONNECT
- /* Split-out delimiting vertices */
- struct TempVertPair {
- struct TempVertPair *next;
- BMVert *v_temp;
- BMVert *v_orig;
- };
-
- struct {
- struct TempVertPair *list;
- uint len;
- int *remap; /* temp -> orig mapping */
- } temp_vert_pairs = {NULL};
-
- if (use_partial_connect) {
- for (uint i = 0; i < edge_net_init_len; i++) {
- for (unsigned j = 0; j < 2; j++) {
- BMVert *v_delimit = (&edge_arr[i]->v1)[j];
- BMVert *v_other;
-
- /* note, remapping will _never_ map a vertex to an already mapped vertex */
- while (UNLIKELY((v_other = bm_face_split_edgenet_partial_connect(bm, v_delimit, f)))) {
- struct TempVertPair *tvp = BLI_memarena_alloc(mem_arena, sizeof(*tvp));
- tvp->next = temp_vert_pairs.list;
- tvp->v_orig = v_delimit;
- tvp->v_temp = v_other;
- temp_vert_pairs.list = tvp;
- temp_vert_pairs.len++;
- }
- }
- }
-
- if (temp_vert_pairs.len == 0) {
- use_partial_connect = false;
- }
- }
-#endif /* USE_PARTIAL_CONNECT */
-
-
-
- uint group_arr_len = 0;
- LinkNode *group_head = NULL;
- {
- /* scan 'edge_arr' backwards so the outer face boundary is handled first
- * (since its likely to be the largest) */
- uint edge_index = (edge_arr_len - 1);
- uint edge_in_group_tot = 0;
-
- BLI_SMALLSTACK_DECLARE(vstack, BMVert *);
-
- while (true) {
- LinkNode *edge_links = NULL;
- uint unique_verts_in_group = 0, unique_edges_in_group = 0;
-
- /* list of groups */
- BLI_assert(BM_elem_flag_test(edge_arr[edge_index]->v1, VERT_NOT_IN_STACK));
- BLI_SMALLSTACK_PUSH(vstack, edge_arr[edge_index]->v1);
- BM_elem_flag_disable(edge_arr[edge_index]->v1, VERT_NOT_IN_STACK);
-
- BMVert *v_iter;
- while ((v_iter = BLI_SMALLSTACK_POP(vstack))) {
- unique_verts_in_group++;
-
- BMEdge *e_iter = v_iter->e;
- do {
- if (BM_elem_flag_test(e_iter, EDGE_NOT_IN_STACK)) {
- BM_elem_flag_disable(e_iter, EDGE_NOT_IN_STACK);
- unique_edges_in_group++;
-
- BLI_linklist_prepend_alloca(&edge_links, e_iter);
-
- BMVert *v_other = BM_edge_other_vert(e_iter, v_iter);
- if (BM_elem_flag_test(v_other, VERT_NOT_IN_STACK)) {
- BLI_SMALLSTACK_PUSH(vstack, v_other);
- BM_elem_flag_disable(v_other, VERT_NOT_IN_STACK);
- }
- }
- } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v_iter)) != v_iter->e);
- }
-
- struct EdgeGroupIsland *g = alloca(sizeof(*g));
- g->vert_len = unique_verts_in_group;
- g->edge_len = unique_edges_in_group;
- edge_in_group_tot += unique_edges_in_group;
-
- BLI_linklist_prepend_nlink(&group_head, edge_links, (LinkNode *)g);
-
- group_arr_len++;
-
- if (edge_in_group_tot == edge_arr_len) {
- break;
- }
-
- /* skip edges in the stack */
- while (BM_elem_flag_test(edge_arr[edge_index], EDGE_NOT_IN_STACK) == false) {
- BLI_assert(edge_index != 0);
- edge_index--;
- }
- }
- }
-
- /* single group - no holes */
- if (group_arr_len == 1) {
- goto finally;
- }
-
-
- /* -------------------------------------------------------------------- */
- /* Previous checks need to be kept fast, since they will run very often,
- * now we know there are holes, so calculate a spatial lookup info and
- * other per-group data.
- */
-
- float axis_mat[3][3];
- axis_dominant_v3_to_m3(axis_mat, f->no);
+ /* Split-out delimiting vertices */
+ struct TempVertPair {
+ struct TempVertPair *next;
+ BMVert *v_temp;
+ BMVert *v_orig;
+ };
+
+ struct {
+ struct TempVertPair *list;
+ uint len;
+ int *remap; /* temp -> orig mapping */
+ } temp_vert_pairs = {NULL};
+
+ if (use_partial_connect) {
+ for (uint i = 0; i < edge_net_init_len; i++) {
+ for (unsigned j = 0; j < 2; j++) {
+ BMVert *v_delimit = (&edge_arr[i]->v1)[j];
+ BMVert *v_other;
+
+ /* note, remapping will _never_ map a vertex to an already mapped vertex */
+ while (UNLIKELY((v_other = bm_face_split_edgenet_partial_connect(bm, v_delimit, f)))) {
+ struct TempVertPair *tvp = BLI_memarena_alloc(mem_arena, sizeof(*tvp));
+ tvp->next = temp_vert_pairs.list;
+ tvp->v_orig = v_delimit;
+ tvp->v_temp = v_other;
+ temp_vert_pairs.list = tvp;
+ temp_vert_pairs.len++;
+ }
+ }
+ }
+
+ if (temp_vert_pairs.len == 0) {
+ use_partial_connect = false;
+ }
+ }
+#endif /* USE_PARTIAL_CONNECT */
+
+ uint group_arr_len = 0;
+ LinkNode *group_head = NULL;
+ {
+ /* scan 'edge_arr' backwards so the outer face boundary is handled first
+ * (since its likely to be the largest) */
+ uint edge_index = (edge_arr_len - 1);
+ uint edge_in_group_tot = 0;
+
+ BLI_SMALLSTACK_DECLARE(vstack, BMVert *);
+
+ while (true) {
+ LinkNode *edge_links = NULL;
+ uint unique_verts_in_group = 0, unique_edges_in_group = 0;
+
+ /* list of groups */
+ BLI_assert(BM_elem_flag_test(edge_arr[edge_index]->v1, VERT_NOT_IN_STACK));
+ BLI_SMALLSTACK_PUSH(vstack, edge_arr[edge_index]->v1);
+ BM_elem_flag_disable(edge_arr[edge_index]->v1, VERT_NOT_IN_STACK);
+
+ BMVert *v_iter;
+ while ((v_iter = BLI_SMALLSTACK_POP(vstack))) {
+ unique_verts_in_group++;
+
+ BMEdge *e_iter = v_iter->e;
+ do {
+ if (BM_elem_flag_test(e_iter, EDGE_NOT_IN_STACK)) {
+ BM_elem_flag_disable(e_iter, EDGE_NOT_IN_STACK);
+ unique_edges_in_group++;
+
+ BLI_linklist_prepend_alloca(&edge_links, e_iter);
+
+ BMVert *v_other = BM_edge_other_vert(e_iter, v_iter);
+ if (BM_elem_flag_test(v_other, VERT_NOT_IN_STACK)) {
+ BLI_SMALLSTACK_PUSH(vstack, v_other);
+ BM_elem_flag_disable(v_other, VERT_NOT_IN_STACK);
+ }
+ }
+ } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v_iter)) != v_iter->e);
+ }
+
+ struct EdgeGroupIsland *g = alloca(sizeof(*g));
+ g->vert_len = unique_verts_in_group;
+ g->edge_len = unique_edges_in_group;
+ edge_in_group_tot += unique_edges_in_group;
+
+ BLI_linklist_prepend_nlink(&group_head, edge_links, (LinkNode *)g);
+
+ group_arr_len++;
+
+ if (edge_in_group_tot == edge_arr_len) {
+ break;
+ }
+
+ /* skip edges in the stack */
+ while (BM_elem_flag_test(edge_arr[edge_index], EDGE_NOT_IN_STACK) == false) {
+ BLI_assert(edge_index != 0);
+ edge_index--;
+ }
+ }
+ }
+
+ /* single group - no holes */
+ if (group_arr_len == 1) {
+ goto finally;
+ }
+
+ /* -------------------------------------------------------------------- */
+ /* Previous checks need to be kept fast, since they will run very often,
+ * now we know there are holes, so calculate a spatial lookup info and
+ * other per-group data.
+ */
+
+ float axis_mat[3][3];
+ axis_dominant_v3_to_m3(axis_mat, f->no);
#define VERT_IN_ARRAY BM_ELEM_INTERNAL_TAG
- struct EdgeGroupIsland **group_arr = BLI_memarena_alloc(mem_arena, sizeof(*group_arr) * group_arr_len);
- uint vert_arr_len = 0;
- /* sort groups by lowest value vertex */
- {
- /* fill 'groups_arr' in reverse order so the boundary face is first */
- struct EdgeGroupIsland **group_arr_p = &group_arr[group_arr_len];
-
- for (struct EdgeGroupIsland *g = (void *)group_head; g; g = (struct EdgeGroupIsland *)g->edge_links.next) {
- LinkNode *edge_links = g->edge_links.link;
-
- /* init with *any* different verts */
- g->vert_span.min = ((BMEdge *)edge_links->link)->v1;
- g->vert_span.max = ((BMEdge *)edge_links->link)->v2;
- float min_axis[2] = {FLT_MAX, FLT_MAX};
- float max_axis[2] = {-FLT_MAX, -FLT_MAX};
-
- do {
- BMEdge *e = edge_links->link;
- BLI_assert(e->head.htype == BM_EDGE);
-
- for (int j = 0; j < 2; j++) {
- BMVert *v_iter = (&e->v1)[j];
- BLI_assert(v_iter->head.htype == BM_VERT);
- /* ideally we could use 'v_iter->co[SORT_AXIS]' here,
- * but we need to sort the groups before setting the vertex array order */
- const float axis_value[2] = {
+ struct EdgeGroupIsland **group_arr = BLI_memarena_alloc(mem_arena,
+ sizeof(*group_arr) * group_arr_len);
+ uint vert_arr_len = 0;
+ /* sort groups by lowest value vertex */
+ {
+ /* fill 'groups_arr' in reverse order so the boundary face is first */
+ struct EdgeGroupIsland **group_arr_p = &group_arr[group_arr_len];
+
+ for (struct EdgeGroupIsland *g = (void *)group_head; g;
+ g = (struct EdgeGroupIsland *)g->edge_links.next) {
+ LinkNode *edge_links = g->edge_links.link;
+
+ /* init with *any* different verts */
+ g->vert_span.min = ((BMEdge *)edge_links->link)->v1;
+ g->vert_span.max = ((BMEdge *)edge_links->link)->v2;
+ float min_axis[2] = {FLT_MAX, FLT_MAX};
+ float max_axis[2] = {-FLT_MAX, -FLT_MAX};
+
+ do {
+ BMEdge *e = edge_links->link;
+ BLI_assert(e->head.htype == BM_EDGE);
+
+ for (int j = 0; j < 2; j++) {
+ BMVert *v_iter = (&e->v1)[j];
+ BLI_assert(v_iter->head.htype == BM_VERT);
+ /* ideally we could use 'v_iter->co[SORT_AXIS]' here,
+ * but we need to sort the groups before setting the vertex array order */
+ const float axis_value[2] = {
#if SORT_AXIS == 0
- dot_m3_v3_row_x(axis_mat, v_iter->co),
- dot_m3_v3_row_y(axis_mat, v_iter->co),
+ dot_m3_v3_row_x(axis_mat, v_iter->co),
+ dot_m3_v3_row_y(axis_mat, v_iter->co),
#else
- dot_m3_v3_row_y(axis_mat, v_iter->co),
- dot_m3_v3_row_x(axis_mat, v_iter->co),
+ dot_m3_v3_row_y(axis_mat, v_iter->co),
+ dot_m3_v3_row_x(axis_mat, v_iter->co),
#endif
- };
-
- if (axis_pt_cmp(axis_value, min_axis) == -1) {
- g->vert_span.min = v_iter;
- copy_v2_v2(min_axis, axis_value);
- }
- if (axis_pt_cmp(axis_value, max_axis) == 1) {
- g->vert_span.max = v_iter;
- copy_v2_v2(max_axis, axis_value);
- }
- }
- } while ((edge_links = edge_links->next));
-
- copy_v2_v2(g->vert_span.min_axis, min_axis);
- copy_v2_v2(g->vert_span.max_axis, max_axis);
-
- g->has_prev_edge = false;
-
- vert_arr_len += g->vert_len;
-
- *(--group_arr_p) = g;
- }
- }
-
- qsort(group_arr, group_arr_len, sizeof(*group_arr), group_min_cmp_fn);
-
- /* we don't know how many unique verts there are connecting the edges, so over-alloc */
- BMVert **vert_arr = BLI_memarena_alloc(mem_arena, sizeof(*vert_arr) * vert_arr_len);
- /* map vertex -> group index */
- uint *verts_group_table = BLI_memarena_alloc(mem_arena, sizeof(*verts_group_table) * vert_arr_len);
-
- float (*vert_coords_backup)[3] = BLI_memarena_alloc(mem_arena, sizeof(*vert_coords_backup) * vert_arr_len);
-
- {
- /* relative location, for higher precision calculations */
- const float f_co_ref[3] = {UNPACK3(BM_FACE_FIRST_LOOP(f)->v->co)};
-
- int v_index = 0; /* global vert index */
- for (uint g_index = 0; g_index < group_arr_len; g_index++) {
- LinkNode *edge_links = group_arr[g_index]->edge_links.link;
- do {
- BMEdge *e = edge_links->link;
- for (int j = 0; j < 2; j++) {
- BMVert *v_iter = (&e->v1)[j];
- if (!BM_elem_flag_test(v_iter, VERT_IN_ARRAY)) {
- BM_elem_flag_enable(v_iter, VERT_IN_ARRAY);
-
- /* not nice, but alternatives arent much better :S */
- {
- copy_v3_v3(vert_coords_backup[v_index], v_iter->co);
-
- /* for higher precision */
- sub_v3_v3(v_iter->co, f_co_ref);
-
- float co_2d[2];
- mul_v2_m3v3(co_2d, axis_mat, v_iter->co);
- v_iter->co[0] = co_2d[0];
- v_iter->co[1] = co_2d[1];
- v_iter->co[2] = 0.0f;
- }
-
- BM_elem_index_set(v_iter, v_index); /* set_dirty */
-
- vert_arr[v_index] = v_iter;
- verts_group_table[v_index] = g_index;
- v_index++;
- }
- }
- } while ((edge_links = edge_links->next));
- }
- }
-
- bm->elem_index_dirty |= BM_VERT;
-
- /* Now create bvh tree
- *
- * Note that a large epsilon is used because meshes with dimensions of around 100+ need it. see T52329. */
- BVHTree *bvhtree = BLI_bvhtree_new(edge_arr_len, 1e-4f, 8, 8);
- for (uint i = 0; i < edge_arr_len; i++) {
- const float e_cos[2][3] = {
- {UNPACK2(edge_arr[i]->v1->co), 0.0f},
- {UNPACK2(edge_arr[i]->v2->co), 0.0f},
- };
- BLI_bvhtree_insert(bvhtree, i, (const float *)e_cos, 2);
- }
- BLI_bvhtree_balance(bvhtree);
-
-
+ };
+
+ if (axis_pt_cmp(axis_value, min_axis) == -1) {
+ g->vert_span.min = v_iter;
+ copy_v2_v2(min_axis, axis_value);
+ }
+ if (axis_pt_cmp(axis_value, max_axis) == 1) {
+ g->vert_span.max = v_iter;
+ copy_v2_v2(max_axis, axis_value);
+ }
+ }
+ } while ((edge_links = edge_links->next));
+
+ copy_v2_v2(g->vert_span.min_axis, min_axis);
+ copy_v2_v2(g->vert_span.max_axis, max_axis);
+
+ g->has_prev_edge = false;
+
+ vert_arr_len += g->vert_len;
+
+ *(--group_arr_p) = g;
+ }
+ }
+
+ qsort(group_arr, group_arr_len, sizeof(*group_arr), group_min_cmp_fn);
+
+ /* we don't know how many unique verts there are connecting the edges, so over-alloc */
+ BMVert **vert_arr = BLI_memarena_alloc(mem_arena, sizeof(*vert_arr) * vert_arr_len);
+ /* map vertex -> group index */
+ uint *verts_group_table = BLI_memarena_alloc(mem_arena,
+ sizeof(*verts_group_table) * vert_arr_len);
+
+ float(*vert_coords_backup)[3] = BLI_memarena_alloc(mem_arena,
+ sizeof(*vert_coords_backup) * vert_arr_len);
+
+ {
+ /* relative location, for higher precision calculations */
+ const float f_co_ref[3] = {UNPACK3(BM_FACE_FIRST_LOOP(f)->v->co)};
+
+ int v_index = 0; /* global vert index */
+ for (uint g_index = 0; g_index < group_arr_len; g_index++) {
+ LinkNode *edge_links = group_arr[g_index]->edge_links.link;
+ do {
+ BMEdge *e = edge_links->link;
+ for (int j = 0; j < 2; j++) {
+ BMVert *v_iter = (&e->v1)[j];
+ if (!BM_elem_flag_test(v_iter, VERT_IN_ARRAY)) {
+ BM_elem_flag_enable(v_iter, VERT_IN_ARRAY);
+
+ /* not nice, but alternatives arent much better :S */
+ {
+ copy_v3_v3(vert_coords_backup[v_index], v_iter->co);
+
+ /* for higher precision */
+ sub_v3_v3(v_iter->co, f_co_ref);
+
+ float co_2d[2];
+ mul_v2_m3v3(co_2d, axis_mat, v_iter->co);
+ v_iter->co[0] = co_2d[0];
+ v_iter->co[1] = co_2d[1];
+ v_iter->co[2] = 0.0f;
+ }
+
+ BM_elem_index_set(v_iter, v_index); /* set_dirty */
+
+ vert_arr[v_index] = v_iter;
+ verts_group_table[v_index] = g_index;
+ v_index++;
+ }
+ }
+ } while ((edge_links = edge_links->next));
+ }
+ }
+
+ bm->elem_index_dirty |= BM_VERT;
+
+ /* Now create bvh tree
+ *
+ * Note that a large epsilon is used because meshes with dimensions of around 100+ need it. see T52329. */
+ BVHTree *bvhtree = BLI_bvhtree_new(edge_arr_len, 1e-4f, 8, 8);
+ for (uint i = 0; i < edge_arr_len; i++) {
+ const float e_cos[2][3] = {
+ {UNPACK2(edge_arr[i]->v1->co), 0.0f},
+ {UNPACK2(edge_arr[i]->v2->co), 0.0f},
+ };
+ BLI_bvhtree_insert(bvhtree, i, (const float *)e_cos, 2);
+ }
+ BLI_bvhtree_balance(bvhtree);
#ifdef USE_PARTIAL_CONNECT
- if (use_partial_connect) {
- /* needs to be done once the vertex indices have been written into */
- temp_vert_pairs.remap = BLI_memarena_alloc(mem_arena, sizeof(*temp_vert_pairs.remap) * vert_arr_len);
- copy_vn_i(temp_vert_pairs.remap, vert_arr_len, -1);
+ if (use_partial_connect) {
+ /* needs to be done once the vertex indices have been written into */
+ temp_vert_pairs.remap = BLI_memarena_alloc(mem_arena,
+ sizeof(*temp_vert_pairs.remap) * vert_arr_len);
+ copy_vn_i(temp_vert_pairs.remap, vert_arr_len, -1);
- struct TempVertPair *tvp = temp_vert_pairs.list;
- do {
- temp_vert_pairs.remap[BM_elem_index_get(tvp->v_temp)] = BM_elem_index_get(tvp->v_orig);
- } while ((tvp = tvp->next));
- }
-#endif /* USE_PARTIAL_CONNECT */
+ struct TempVertPair *tvp = temp_vert_pairs.list;
+ do {
+ temp_vert_pairs.remap[BM_elem_index_get(tvp->v_temp)] = BM_elem_index_get(tvp->v_orig);
+ } while ((tvp = tvp->next));
+ }
+#endif /* USE_PARTIAL_CONNECT */
+ /* Create connections between groups */
+ /* may be an over-alloc, but not by much */
+ edge_net_new_len = (uint)edge_net_init_len + ((group_arr_len - 1) * 2);
+ BMEdge **edge_net_new = BLI_memarena_alloc(mem_arena, sizeof(*edge_net_new) * edge_net_new_len);
+ memcpy(edge_net_new, edge_net_init, sizeof(*edge_net_new) * (size_t)edge_net_init_len);
- /* Create connections between groups */
+ {
+ uint edge_net_new_index = edge_net_init_len;
+ /* start-end of the verts in the current group */
- /* may be an over-alloc, but not by much */
- edge_net_new_len = (uint)edge_net_init_len + ((group_arr_len - 1) * 2);
- BMEdge **edge_net_new = BLI_memarena_alloc(mem_arena, sizeof(*edge_net_new) * edge_net_new_len);
- memcpy(edge_net_new, edge_net_init, sizeof(*edge_net_new) * (size_t)edge_net_init_len);
+ uint vert_range[2];
- {
- uint edge_net_new_index = edge_net_init_len;
- /* start-end of the verts in the current group */
+ vert_range[0] = 0;
+ vert_range[1] = group_arr[0]->vert_len;
- uint vert_range[2];
+ struct EdgeGroup_FindConnection_Args args = {
+ .bvhtree = bvhtree,
- vert_range[0] = 0;
- vert_range[1] = group_arr[0]->vert_len;
+ /* use the new edge array so we can scan edges which have been added */
+ .edge_arr = edge_arr,
+ .edge_arr_len = edge_arr_len,
- struct EdgeGroup_FindConnection_Args args = {
- .bvhtree = bvhtree,
+ /* we only want to check newly created edges */
+ .edge_arr_new = edge_net_new + edge_net_init_len,
+ .edge_arr_new_len = 0,
- /* use the new edge array so we can scan edges which have been added */
- .edge_arr = edge_arr,
- .edge_arr_len = edge_arr_len,
+ .vert_range = vert_range,
+ };
- /* we only want to check newly created edges */
- .edge_arr_new = edge_net_new + edge_net_init_len,
- .edge_arr_new_len = 0,
+ for (uint g_index = 1; g_index < group_arr_len; g_index++) {
+ struct EdgeGroupIsland *g = group_arr[g_index];
- .vert_range = vert_range,
- };
+ /* the range of verts this group uses in 'verts_arr' (not uncluding the last index) */
+ vert_range[0] = vert_range[1];
+ vert_range[1] += g->vert_len;
- for (uint g_index = 1; g_index < group_arr_len; g_index++) {
- struct EdgeGroupIsland *g = group_arr[g_index];
+ if (g->has_prev_edge == false) {
+ BMVert *v_origin = g->vert_span.min;
- /* the range of verts this group uses in 'verts_arr' (not uncluding the last index) */
- vert_range[0] = vert_range[1];
- vert_range[1] += g->vert_len;
+ const int index_other = bm_face_split_edgenet_find_connection(&args, v_origin, false);
+ // BLI_assert(index_other >= 0 && index_other < (int)vert_arr_len);
- if (g->has_prev_edge == false) {
- BMVert *v_origin = g->vert_span.min;
-
- const int index_other = bm_face_split_edgenet_find_connection(&args, v_origin, false);
- // BLI_assert(index_other >= 0 && index_other < (int)vert_arr_len);
-
- /* only for degenerate geometry */
- if (index_other != -1) {
+ /* only for degenerate geometry */
+ if (index_other != -1) {
#ifdef USE_PARTIAL_CONNECT
- if ((use_partial_connect == false) ||
- (bm_vert_partial_connect_check_overlap(
- temp_vert_pairs.remap,
- BM_elem_index_get(v_origin), index_other) == false))
+ if ((use_partial_connect == false) ||
+ (bm_vert_partial_connect_check_overlap(
+ temp_vert_pairs.remap, BM_elem_index_get(v_origin), index_other) == false))
#endif
- {
- BMVert *v_end = vert_arr[index_other];
+ {
+ BMVert *v_end = vert_arr[index_other];
- edge_net_new[edge_net_new_index] = BM_edge_create(bm, v_origin, v_end, NULL, 0);
+ edge_net_new[edge_net_new_index] = BM_edge_create(bm, v_origin, v_end, NULL, 0);
#ifdef USE_PARTIAL_CONNECT
- BM_elem_index_set(edge_net_new[edge_net_new_index], edge_net_new_index);
+ BM_elem_index_set(edge_net_new[edge_net_new_index], edge_net_new_index);
#endif
- edge_net_new_index++;
- args.edge_arr_new_len++;
- }
- }
- }
+ edge_net_new_index++;
+ args.edge_arr_new_len++;
+ }
+ }
+ }
- {
- BMVert *v_origin = g->vert_span.max;
+ {
+ BMVert *v_origin = g->vert_span.max;
- const int index_other = bm_face_split_edgenet_find_connection(&args, v_origin, true);
- // BLI_assert(index_other >= 0 && index_other < (int)vert_arr_len);
+ const int index_other = bm_face_split_edgenet_find_connection(&args, v_origin, true);
+ // BLI_assert(index_other >= 0 && index_other < (int)vert_arr_len);
- /* only for degenerate geometry */
- if (index_other != -1) {
+ /* only for degenerate geometry */
+ if (index_other != -1) {
#ifdef USE_PARTIAL_CONNECT
- if ((use_partial_connect == false) ||
- (bm_vert_partial_connect_check_overlap(
- temp_vert_pairs.remap,
- BM_elem_index_get(v_origin), index_other) == false))
+ if ((use_partial_connect == false) ||
+ (bm_vert_partial_connect_check_overlap(
+ temp_vert_pairs.remap, BM_elem_index_get(v_origin), index_other) == false))
#endif
- {
- BMVert *v_end = vert_arr[index_other];
- edge_net_new[edge_net_new_index] = BM_edge_create(bm, v_origin, v_end, NULL, 0);
+ {
+ BMVert *v_end = vert_arr[index_other];
+ edge_net_new[edge_net_new_index] = BM_edge_create(bm, v_origin, v_end, NULL, 0);
#ifdef USE_PARTIAL_CONNECT
- BM_elem_index_set(edge_net_new[edge_net_new_index], edge_net_new_index);
+ BM_elem_index_set(edge_net_new[edge_net_new_index], edge_net_new_index);
#endif
- edge_net_new_index++;
- args.edge_arr_new_len++;
- }
-
- /* tell the 'next' group it doesn't need to create its own back-link */
- uint g_index_other = verts_group_table[index_other];
- group_arr[g_index_other]->has_prev_edge = true;
- }
- }
-
- }
- BLI_assert(edge_net_new_len >= edge_net_new_index);
- edge_net_new_len = edge_net_new_index;
- }
-
- BLI_bvhtree_free(bvhtree);
-
- *r_edge_net_new = edge_net_new;
- *r_edge_net_new_len = edge_net_new_len;
- ok = true;
-
- for (uint i = 0; i < vert_arr_len; i++) {
- copy_v3_v3(vert_arr[i]->co, vert_coords_backup[i]);
- }
+ edge_net_new_index++;
+ args.edge_arr_new_len++;
+ }
+
+ /* tell the 'next' group it doesn't need to create its own back-link */
+ uint g_index_other = verts_group_table[index_other];
+ group_arr[g_index_other]->has_prev_edge = true;
+ }
+ }
+ }
+ BLI_assert(edge_net_new_len >= edge_net_new_index);
+ edge_net_new_len = edge_net_new_index;
+ }
+
+ BLI_bvhtree_free(bvhtree);
+
+ *r_edge_net_new = edge_net_new;
+ *r_edge_net_new_len = edge_net_new_len;
+ ok = true;
+
+ for (uint i = 0; i < vert_arr_len; i++) {
+ copy_v3_v3(vert_arr[i]->co, vert_coords_backup[i]);
+ }
finally:
#ifdef USE_PARTIAL_CONNECT
- /* don't free 'vert_temp_pair_list', its part of the arena */
- if (use_partial_connect) {
-
- /* Sanity check: ensure we don't have connecting edges before splicing begins. */
-#ifdef DEBUG
- {
- struct TempVertPair *tvp = temp_vert_pairs.list;
- do {
- /* we must _never_ create connections here
- * (inface the islands can't have a connection at all) */
- BLI_assert(BM_edge_exists(tvp->v_orig, tvp->v_temp) == NULL);
- } while ((tvp = tvp->next));
- }
-#endif
-
- struct TempVertPair *tvp = temp_vert_pairs.list;
- do {
- /* its _very_ unlikely the edge exists,
- * however splicing may case this. see: T48012 */
- if (!BM_edge_exists(tvp->v_orig, tvp->v_temp)) {
- BM_vert_splice(bm, tvp->v_orig, tvp->v_temp);
- }
- } while ((tvp = tvp->next));
-
- /* Remove edges which have become doubles since splicing vertices together,
- * its less trouble then detecting future-doubles on edge-creation. */
- for (uint i = edge_net_init_len; i < edge_net_new_len; i++) {
- while (BM_edge_find_double(edge_net_new[i])) {
- BM_edge_kill(bm, edge_net_new[i]);
- edge_net_new_len--;
- if (i == edge_net_new_len) {
- break;
- }
- edge_net_new[i] = edge_net_new[edge_net_new_len];
- }
- }
-
- *r_edge_net_new_len = edge_net_new_len;
- }
+ /* don't free 'vert_temp_pair_list', its part of the arena */
+ if (use_partial_connect) {
+
+ /* Sanity check: ensure we don't have connecting edges before splicing begins. */
+# ifdef DEBUG
+ {
+ struct TempVertPair *tvp = temp_vert_pairs.list;
+ do {
+ /* we must _never_ create connections here
+ * (inface the islands can't have a connection at all) */
+ BLI_assert(BM_edge_exists(tvp->v_orig, tvp->v_temp) == NULL);
+ } while ((tvp = tvp->next));
+ }
+# endif
+
+ struct TempVertPair *tvp = temp_vert_pairs.list;
+ do {
+ /* its _very_ unlikely the edge exists,
+ * however splicing may case this. see: T48012 */
+ if (!BM_edge_exists(tvp->v_orig, tvp->v_temp)) {
+ BM_vert_splice(bm, tvp->v_orig, tvp->v_temp);
+ }
+ } while ((tvp = tvp->next));
+
+ /* Remove edges which have become doubles since splicing vertices together,
+ * its less trouble then detecting future-doubles on edge-creation. */
+ for (uint i = edge_net_init_len; i < edge_net_new_len; i++) {
+ while (BM_edge_find_double(edge_net_new[i])) {
+ BM_edge_kill(bm, edge_net_new[i]);
+ edge_net_new_len--;
+ if (i == edge_net_new_len) {
+ break;
+ }
+ edge_net_new[i] = edge_net_new[edge_net_new_len];
+ }
+ }
+
+ *r_edge_net_new_len = edge_net_new_len;
+ }
#endif
-
- for (uint i = 0; i < edge_arr_len; i++) {
- BM_elem_flag_disable(edge_arr[i], EDGE_NOT_IN_STACK);
- BM_elem_flag_disable(edge_arr[i]->v1, VERT_NOT_IN_STACK);
- BM_elem_flag_disable(edge_arr[i]->v2, VERT_NOT_IN_STACK);
- }
+ for (uint i = 0; i < edge_arr_len; i++) {
+ BM_elem_flag_disable(edge_arr[i], EDGE_NOT_IN_STACK);
+ BM_elem_flag_disable(edge_arr[i]->v1, VERT_NOT_IN_STACK);
+ BM_elem_flag_disable(edge_arr[i]->v2, VERT_NOT_IN_STACK);
+ }
#undef VERT_IN_ARRAY
#undef VERT_NOT_IN_STACK
#undef EDGE_NOT_IN_STACK
- return ok;
+ return ok;
}
#undef SORT_AXIS
diff --git a/source/blender/bmesh/intern/bmesh_polygon_edgenet.h b/source/blender/bmesh/intern/bmesh_polygon_edgenet.h
index 7e57f648704..38af944d0cd 100644
--- a/source/blender/bmesh/intern/bmesh_polygon_edgenet.h
+++ b/source/blender/bmesh/intern/bmesh_polygon_edgenet.h
@@ -21,17 +21,21 @@
* \ingroup bmesh
*/
-bool BM_face_split_edgenet(
- BMesh *bm, BMFace *f,
- BMEdge **edge_net, const int edge_net_len,
- BMFace ***r_face_arr, int *r_face_arr_len);
+bool BM_face_split_edgenet(BMesh *bm,
+ BMFace *f,
+ BMEdge **edge_net,
+ const int edge_net_len,
+ BMFace ***r_face_arr,
+ int *r_face_arr_len);
-bool BM_face_split_edgenet_connect_islands(
- BMesh *bm,
- BMFace *f, BMEdge **edge_net_init, const uint edge_net_init_len,
- bool use_partial_connect,
- struct MemArena *arena,
- BMEdge ***r_edge_net_new, uint *r_edge_net_new_len)
-ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3, 6, 7, 8);
+bool BM_face_split_edgenet_connect_islands(BMesh *bm,
+ BMFace *f,
+ BMEdge **edge_net_init,
+ const uint edge_net_init_len,
+ bool use_partial_connect,
+ struct MemArena *arena,
+ BMEdge ***r_edge_net_new,
+ uint *r_edge_net_new_len) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL(1, 2, 3, 6, 7, 8);
-#endif /* __BMESH_POLYGON_EDGENET_H__ */
+#endif /* __BMESH_POLYGON_EDGENET_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_private.h b/source/blender/bmesh/intern/bmesh_private.h
index c0f74c50a3a..b77243f7b26 100644
--- a/source/blender/bmesh/intern/bmesh_private.h
+++ b/source/blender/bmesh/intern/bmesh_private.h
@@ -31,19 +31,23 @@
/* returns positive nonzero on error */
#ifdef NDEBUG
- /* no error checking for release,
+/* no error checking for release,
* it can take most of the CPU time when running some tools */
-# define BM_CHECK_ELEMENT(el) (void)(el)
+# define BM_CHECK_ELEMENT(el) (void)(el)
#else
int bmesh_elem_check(void *element, const char htype);
-# define BM_CHECK_ELEMENT(el) { \
- if (bmesh_elem_check(el, ((BMHeader *)el)->htype)) { \
- printf("check_element failure, with code %i on line %i in file\n" \
- " \"%s\"\n\n", \
- bmesh_elem_check(el, ((BMHeader *)el)->htype), \
- __LINE__, __FILE__); \
- } \
-} ((void)0)
+# define BM_CHECK_ELEMENT(el) \
+ { \
+ if (bmesh_elem_check(el, ((BMHeader *)el)->htype)) { \
+ printf( \
+ "check_element failure, with code %i on line %i in file\n" \
+ " \"%s\"\n\n", \
+ bmesh_elem_check(el, ((BMHeader *)el)->htype), \
+ __LINE__, \
+ __FILE__); \
+ } \
+ } \
+ ((void)0)
#endif
int bmesh_radial_length(const BMLoop *l);
@@ -55,20 +59,32 @@ int bmesh_disk_count(const BMVert *v);
* \note Ensure different parts of the API do not conflict
* on using these internal flags!*/
enum {
- _FLAG_JF = (1 << 0), /* join faces */
- _FLAG_MF = (1 << 1), /* make face */
- _FLAG_MV = (1 << 1), /* make face, vertex */
- _FLAG_OVERLAP = (1 << 2), /* general overlap flag */
- _FLAG_WALK = (1 << 3), /* general walk flag (keep clean) */
- _FLAG_WALK_ALT = (1 << 4), /* same as _FLAG_WALK, for when a second tag is needed */
+ _FLAG_JF = (1 << 0), /* join faces */
+ _FLAG_MF = (1 << 1), /* make face */
+ _FLAG_MV = (1 << 1), /* make face, vertex */
+ _FLAG_OVERLAP = (1 << 2), /* general overlap flag */
+ _FLAG_WALK = (1 << 3), /* general walk flag (keep clean) */
+ _FLAG_WALK_ALT = (1 << 4), /* same as _FLAG_WALK, for when a second tag is needed */
- _FLAG_ELEM_CHECK = (1 << 7), /* reserved for bmesh_elem_check */
+ _FLAG_ELEM_CHECK = (1 << 7), /* reserved for bmesh_elem_check */
};
-#define BM_ELEM_API_FLAG_ENABLE(element, f) { ((element)->head.api_flag |= (f)); } (void)0
-#define BM_ELEM_API_FLAG_DISABLE(element, f) { ((element)->head.api_flag &= (uchar)~(f)); } (void)0
-#define BM_ELEM_API_FLAG_TEST(element, f) ((element)->head.api_flag & (f))
-#define BM_ELEM_API_FLAG_CLEAR(element) { ((element)->head.api_flag = 0); } (void)0
+#define BM_ELEM_API_FLAG_ENABLE(element, f) \
+ { \
+ ((element)->head.api_flag |= (f)); \
+ } \
+ (void)0
+#define BM_ELEM_API_FLAG_DISABLE(element, f) \
+ { \
+ ((element)->head.api_flag &= (uchar) ~(f)); \
+ } \
+ (void)0
+#define BM_ELEM_API_FLAG_TEST(element, f) ((element)->head.api_flag & (f))
+#define BM_ELEM_API_FLAG_CLEAR(element) \
+ { \
+ ((element)->head.api_flag = 0); \
+ } \
+ (void)0
void poly_rotate_plane(const float normal[3], float (*verts)[3], unsigned const int nverts);
diff --git a/source/blender/bmesh/intern/bmesh_query.c b/source/blender/bmesh/intern/bmesh_query.c
index 4b34e1fe07d..98ad30b6a28 100644
--- a/source/blender/bmesh/intern/bmesh_query.c
+++ b/source/blender/bmesh/intern/bmesh_query.c
@@ -57,9 +57,9 @@
*/
BMLoop *BM_face_other_edge_loop(BMFace *f, BMEdge *e, BMVert *v)
{
- BMLoop *l = BM_face_edge_share_loop(f, e);
- BLI_assert(l != NULL);
- return BM_loop_other_edge_loop(l, v);
+ BMLoop *l = BM_face_edge_share_loop(f, e);
+ BLI_assert(l != NULL);
+ return BM_loop_other_edge_loop(l, v);
}
/**
@@ -68,8 +68,8 @@ BMLoop *BM_face_other_edge_loop(BMFace *f, BMEdge *e, BMVert *v)
*/
BMLoop *BM_loop_other_edge_loop(BMLoop *l, BMVert *v)
{
- BLI_assert(BM_vert_in_edge(l->e, v));
- return l->v == v ? l->prev : l->next;
+ BLI_assert(BM_vert_in_edge(l->e, v));
+ return l->v == v ? l->prev : l->next;
}
/**
@@ -96,28 +96,28 @@ BMLoop *BM_loop_other_edge_loop(BMLoop *l, BMVert *v)
*/
BMLoop *BM_face_other_vert_loop(BMFace *f, BMVert *v_prev, BMVert *v)
{
- BMLoop *l_iter = BM_face_vert_share_loop(f, v);
+ BMLoop *l_iter = BM_face_vert_share_loop(f, v);
- BLI_assert(BM_edge_exists(v_prev, v) != NULL);
+ BLI_assert(BM_edge_exists(v_prev, v) != NULL);
- if (l_iter) {
- if (l_iter->prev->v == v_prev) {
- return l_iter->next;
- }
- else if (l_iter->next->v == v_prev) {
- return l_iter->prev;
- }
- else {
- /* invalid args */
- BLI_assert(0);
- return NULL;
- }
- }
- else {
- /* invalid args */
- BLI_assert(0);
- return NULL;
- }
+ if (l_iter) {
+ if (l_iter->prev->v == v_prev) {
+ return l_iter->next;
+ }
+ else if (l_iter->next->v == v_prev) {
+ return l_iter->prev;
+ }
+ else {
+ /* invalid args */
+ BLI_assert(0);
+ return NULL;
+ }
+ }
+ else {
+ /* invalid args */
+ BLI_assert(0);
+ return NULL;
+ }
}
/**
@@ -139,149 +139,144 @@ BMLoop *BM_face_other_vert_loop(BMFace *f, BMVert *v_prev, BMVert *v)
BMLoop *BM_loop_other_vert_loop(BMLoop *l, BMVert *v)
{
#if 0 /* works but slow */
- return BM_face_other_vert_loop(l->f, BM_edge_other_vert(l->e, v), v);
+ return BM_face_other_vert_loop(l->f, BM_edge_other_vert(l->e, v), v);
#else
- BMEdge *e = l->e;
- BMVert *v_prev = BM_edge_other_vert(e, v);
- if (l->v == v) {
- if (l->prev->v == v_prev) {
- return l->next;
- }
- else {
- BLI_assert(l->next->v == v_prev);
-
- return l->prev;
- }
- }
- else {
- BLI_assert(l->v == v_prev);
-
- if (l->prev->v == v) {
- return l->prev->prev;
- }
- else {
- BLI_assert(l->next->v == v);
- return l->next->next;
- }
- }
+ BMEdge *e = l->e;
+ BMVert *v_prev = BM_edge_other_vert(e, v);
+ if (l->v == v) {
+ if (l->prev->v == v_prev) {
+ return l->next;
+ }
+ else {
+ BLI_assert(l->next->v == v_prev);
+
+ return l->prev;
+ }
+ }
+ else {
+ BLI_assert(l->v == v_prev);
+
+ if (l->prev->v == v) {
+ return l->prev->prev;
+ }
+ else {
+ BLI_assert(l->next->v == v);
+ return l->next->next;
+ }
+ }
#endif
}
/**
* Check if verts share a face.
*/
-bool BM_vert_pair_share_face_check(
- BMVert *v_a, BMVert *v_b)
+bool BM_vert_pair_share_face_check(BMVert *v_a, BMVert *v_b)
{
- if (v_a->e && v_b->e) {
- BMIter iter;
- BMFace *f;
+ if (v_a->e && v_b->e) {
+ BMIter iter;
+ BMFace *f;
- BM_ITER_ELEM (f, &iter, v_a, BM_FACES_OF_VERT) {
- if (BM_vert_in_face(v_b, f)) {
- return true;
- }
- }
- }
+ BM_ITER_ELEM (f, &iter, v_a, BM_FACES_OF_VERT) {
+ if (BM_vert_in_face(v_b, f)) {
+ return true;
+ }
+ }
+ }
- return false;
+ return false;
}
-bool BM_vert_pair_share_face_check_cb(
- BMVert *v_a, BMVert *v_b,
- bool (*test_fn)(BMFace *, void *user_data), void *user_data)
+bool BM_vert_pair_share_face_check_cb(BMVert *v_a,
+ BMVert *v_b,
+ bool (*test_fn)(BMFace *, void *user_data),
+ void *user_data)
{
- if (v_a->e && v_b->e) {
- BMIter iter;
- BMFace *f;
+ if (v_a->e && v_b->e) {
+ BMIter iter;
+ BMFace *f;
- BM_ITER_ELEM (f, &iter, v_a, BM_FACES_OF_VERT) {
- if (test_fn(f, user_data)) {
- if (BM_vert_in_face(v_b, f)) {
- return true;
- }
- }
- }
- }
+ BM_ITER_ELEM (f, &iter, v_a, BM_FACES_OF_VERT) {
+ if (test_fn(f, user_data)) {
+ if (BM_vert_in_face(v_b, f)) {
+ return true;
+ }
+ }
+ }
+ }
- return false;
+ return false;
}
/**
* Given 2 verts, find the smallest face they share and give back both loops.
*/
BMFace *BM_vert_pair_share_face_by_len(
- BMVert *v_a, BMVert *v_b,
- BMLoop **r_l_a, BMLoop **r_l_b,
- const bool allow_adjacent)
+ BMVert *v_a, BMVert *v_b, BMLoop **r_l_a, BMLoop **r_l_b, const bool allow_adjacent)
{
- BMLoop *l_cur_a = NULL, *l_cur_b = NULL;
- BMFace *f_cur = NULL;
+ BMLoop *l_cur_a = NULL, *l_cur_b = NULL;
+ BMFace *f_cur = NULL;
- if (v_a->e && v_b->e) {
- BMIter iter;
- BMLoop *l_a, *l_b;
+ if (v_a->e && v_b->e) {
+ BMIter iter;
+ BMLoop *l_a, *l_b;
- BM_ITER_ELEM (l_a, &iter, v_a, BM_LOOPS_OF_VERT) {
- if ((f_cur == NULL) || (l_a->f->len < f_cur->len)) {
- l_b = BM_face_vert_share_loop(l_a->f, v_b);
- if (l_b && (allow_adjacent || !BM_loop_is_adjacent(l_a, l_b))) {
- f_cur = l_a->f;
- l_cur_a = l_a;
- l_cur_b = l_b;
- }
- }
- }
- }
+ BM_ITER_ELEM (l_a, &iter, v_a, BM_LOOPS_OF_VERT) {
+ if ((f_cur == NULL) || (l_a->f->len < f_cur->len)) {
+ l_b = BM_face_vert_share_loop(l_a->f, v_b);
+ if (l_b && (allow_adjacent || !BM_loop_is_adjacent(l_a, l_b))) {
+ f_cur = l_a->f;
+ l_cur_a = l_a;
+ l_cur_b = l_b;
+ }
+ }
+ }
+ }
- *r_l_a = l_cur_a;
- *r_l_b = l_cur_b;
+ *r_l_a = l_cur_a;
+ *r_l_b = l_cur_b;
- return f_cur;
+ return f_cur;
}
BMFace *BM_edge_pair_share_face_by_len(
- BMEdge *e_a, BMEdge *e_b,
- BMLoop **r_l_a, BMLoop **r_l_b,
- const bool allow_adjacent)
+ BMEdge *e_a, BMEdge *e_b, BMLoop **r_l_a, BMLoop **r_l_b, const bool allow_adjacent)
{
- BMLoop *l_cur_a = NULL, *l_cur_b = NULL;
- BMFace *f_cur = NULL;
+ BMLoop *l_cur_a = NULL, *l_cur_b = NULL;
+ BMFace *f_cur = NULL;
- if (e_a->l && e_b->l) {
- BMIter iter;
- BMLoop *l_a, *l_b;
+ if (e_a->l && e_b->l) {
+ BMIter iter;
+ BMLoop *l_a, *l_b;
- BM_ITER_ELEM (l_a, &iter, e_a, BM_LOOPS_OF_EDGE) {
- if ((f_cur == NULL) || (l_a->f->len < f_cur->len)) {
- l_b = BM_face_edge_share_loop(l_a->f, e_b);
- if (l_b && (allow_adjacent || !BM_loop_is_adjacent(l_a, l_b))) {
- f_cur = l_a->f;
- l_cur_a = l_a;
- l_cur_b = l_b;
- }
- }
- }
- }
+ BM_ITER_ELEM (l_a, &iter, e_a, BM_LOOPS_OF_EDGE) {
+ if ((f_cur == NULL) || (l_a->f->len < f_cur->len)) {
+ l_b = BM_face_edge_share_loop(l_a->f, e_b);
+ if (l_b && (allow_adjacent || !BM_loop_is_adjacent(l_a, l_b))) {
+ f_cur = l_a->f;
+ l_cur_a = l_a;
+ l_cur_b = l_b;
+ }
+ }
+ }
+ }
- *r_l_a = l_cur_a;
- *r_l_b = l_cur_b;
+ *r_l_a = l_cur_a;
+ *r_l_b = l_cur_b;
- return f_cur;
+ return f_cur;
}
static float bm_face_calc_split_dot(BMLoop *l_a, BMLoop *l_b)
{
- float no[2][3];
+ float no[2][3];
- if ((BM_face_calc_normal_subset(l_a, l_b, no[0]) != 0.0f) &&
- (BM_face_calc_normal_subset(l_b, l_a, no[1]) != 0.0f))
- {
- return dot_v3v3(no[0], no[1]);
- }
- else {
- return -1.0f;
- }
+ if ((BM_face_calc_normal_subset(l_a, l_b, no[0]) != 0.0f) &&
+ (BM_face_calc_normal_subset(l_b, l_a, no[1]) != 0.0f)) {
+ return dot_v3v3(no[0], no[1]);
+ }
+ else {
+ return -1.0f;
+ }
}
/**
@@ -292,8 +287,8 @@ static float bm_face_calc_split_dot(BMLoop *l_a, BMLoop *l_b)
*/
float BM_loop_point_side_of_loop_test(const BMLoop *l, const float co[3])
{
- const float *axis = l->f->no;
- return dist_signed_squared_to_corner_v3v3v3(co, l->prev->v->co, l->v->co, l->next->v->co, axis);
+ const float *axis = l->f->no;
+ return dist_signed_squared_to_corner_v3v3v3(co, l->prev->v->co, l->v->co, l->next->v->co, axis);
}
/**
@@ -304,15 +299,15 @@ float BM_loop_point_side_of_loop_test(const BMLoop *l, const float co[3])
*/
float BM_loop_point_side_of_edge_test(const BMLoop *l, const float co[3])
{
- const float *axis = l->f->no;
- float dir[3];
- float plane[4];
+ const float *axis = l->f->no;
+ float dir[3];
+ float plane[4];
- sub_v3_v3v3(dir, l->next->v->co, l->v->co);
- cross_v3_v3v3(plane, axis, dir);
+ sub_v3_v3v3(dir, l->next->v->co, l->v->co);
+ cross_v3_v3v3(plane, axis, dir);
- plane[3] = -dot_v3v3(plane, l->v->co);
- return dist_signed_squared_to_plane_v3(co, plane);
+ plane[3] = -dot_v3v3(plane, l->v->co);
+ return dist_signed_squared_to_plane_v3(co, plane);
}
/**
@@ -321,68 +316,65 @@ float BM_loop_point_side_of_edge_test(const BMLoop *l, const float co[3])
* This can be better then #BM_vert_pair_share_face_by_len because concave splits are ranked lowest.
*/
BMFace *BM_vert_pair_share_face_by_angle(
- BMVert *v_a, BMVert *v_b,
- BMLoop **r_l_a, BMLoop **r_l_b,
- const bool allow_adjacent)
+ BMVert *v_a, BMVert *v_b, BMLoop **r_l_a, BMLoop **r_l_b, const bool allow_adjacent)
{
- BMLoop *l_cur_a = NULL, *l_cur_b = NULL;
- BMFace *f_cur = NULL;
+ BMLoop *l_cur_a = NULL, *l_cur_b = NULL;
+ BMFace *f_cur = NULL;
- if (v_a->e && v_b->e) {
- BMIter iter;
- BMLoop *l_a, *l_b;
- float dot_best = -1.0f;
+ if (v_a->e && v_b->e) {
+ BMIter iter;
+ BMLoop *l_a, *l_b;
+ float dot_best = -1.0f;
- BM_ITER_ELEM (l_a, &iter, v_a, BM_LOOPS_OF_VERT) {
- l_b = BM_face_vert_share_loop(l_a->f, v_b);
- if (l_b && (allow_adjacent || !BM_loop_is_adjacent(l_a, l_b))) {
+ BM_ITER_ELEM (l_a, &iter, v_a, BM_LOOPS_OF_VERT) {
+ l_b = BM_face_vert_share_loop(l_a->f, v_b);
+ if (l_b && (allow_adjacent || !BM_loop_is_adjacent(l_a, l_b))) {
- if (f_cur == NULL) {
- f_cur = l_a->f;
- l_cur_a = l_a;
- l_cur_b = l_b;
- }
- else {
- /* avoid expensive calculations if we only ever find one face */
- float dot;
- if (dot_best == -1.0f) {
- dot_best = bm_face_calc_split_dot(l_cur_a, l_cur_b);
- }
+ if (f_cur == NULL) {
+ f_cur = l_a->f;
+ l_cur_a = l_a;
+ l_cur_b = l_b;
+ }
+ else {
+ /* avoid expensive calculations if we only ever find one face */
+ float dot;
+ if (dot_best == -1.0f) {
+ dot_best = bm_face_calc_split_dot(l_cur_a, l_cur_b);
+ }
- dot = bm_face_calc_split_dot(l_a, l_b);
- if (dot > dot_best) {
- dot_best = dot;
+ dot = bm_face_calc_split_dot(l_a, l_b);
+ if (dot > dot_best) {
+ dot_best = dot;
- f_cur = l_a->f;
- l_cur_a = l_a;
- l_cur_b = l_b;
- }
- }
- }
- }
- }
+ f_cur = l_a->f;
+ l_cur_a = l_a;
+ l_cur_b = l_b;
+ }
+ }
+ }
+ }
+ }
- *r_l_a = l_cur_a;
- *r_l_b = l_cur_b;
+ *r_l_a = l_cur_a;
+ *r_l_b = l_cur_b;
- return f_cur;
+ return f_cur;
}
-
/**
* Get the first loop of a vert. Uses the same initialization code for the first loop of the
* iterator API
*/
BMLoop *BM_vert_find_first_loop(BMVert *v)
{
- return v->e ? bmesh_disk_faceloop_find_first(v->e, v) : NULL;
+ return v->e ? bmesh_disk_faceloop_find_first(v->e, v) : NULL;
}
/**
* A version of #BM_vert_find_first_loop that ignores hidden loops.
*/
BMLoop *BM_vert_find_first_loop_visible(BMVert *v)
{
- return v->e ? bmesh_disk_faceloop_find_first_visible(v->e, v) : NULL;
+ return v->e ? bmesh_disk_faceloop_find_first_visible(v->e, v) : NULL;
}
/**
@@ -390,26 +382,26 @@ BMLoop *BM_vert_find_first_loop_visible(BMVert *v)
*/
bool BM_vert_in_face(BMVert *v, BMFace *f)
{
- BMLoop *l_iter, *l_first;
+ BMLoop *l_iter, *l_first;
#ifdef USE_BMESH_HOLES
- BMLoopList *lst;
- for (lst = f->loops.first; lst; lst = lst->next)
+ BMLoopList *lst;
+ for (lst = f->loops.first; lst; lst = lst->next)
#endif
- {
+ {
#ifdef USE_BMESH_HOLES
- l_iter = l_first = lst->first;
+ l_iter = l_first = lst->first;
#else
- l_iter = l_first = f->l_first;
+ l_iter = l_first = f->l_first;
#endif
- do {
- if (l_iter->v == v) {
- return true;
- }
- } while ((l_iter = l_iter->next) != l_first);
- }
+ do {
+ if (l_iter->v == v) {
+ return true;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
- return false;
+ return false;
}
/**
@@ -418,96 +410,95 @@ bool BM_vert_in_face(BMVert *v, BMFace *f)
*/
int BM_verts_in_face_count(BMVert **varr, int len, BMFace *f)
{
- BMLoop *l_iter, *l_first;
+ BMLoop *l_iter, *l_first;
#ifdef USE_BMESH_HOLES
- BMLoopList *lst;
+ BMLoopList *lst;
#endif
- int i, count = 0;
+ int i, count = 0;
- for (i = 0; i < len; i++) {
- BM_ELEM_API_FLAG_ENABLE(varr[i], _FLAG_OVERLAP);
- }
+ for (i = 0; i < len; i++) {
+ BM_ELEM_API_FLAG_ENABLE(varr[i], _FLAG_OVERLAP);
+ }
#ifdef USE_BMESH_HOLES
- for (lst = f->loops.first; lst; lst = lst->next)
+ for (lst = f->loops.first; lst; lst = lst->next)
#endif
- {
+ {
#ifdef USE_BMESH_HOLES
- l_iter = l_first = lst->first;
+ l_iter = l_first = lst->first;
#else
- l_iter = l_first = f->l_first;
+ l_iter = l_first = f->l_first;
#endif
- do {
- if (BM_ELEM_API_FLAG_TEST(l_iter->v, _FLAG_OVERLAP)) {
- count++;
- }
+ do {
+ if (BM_ELEM_API_FLAG_TEST(l_iter->v, _FLAG_OVERLAP)) {
+ count++;
+ }
- } while ((l_iter = l_iter->next) != l_first);
- }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
- for (i = 0; i < len; i++) {
- BM_ELEM_API_FLAG_DISABLE(varr[i], _FLAG_OVERLAP);
- }
+ for (i = 0; i < len; i++) {
+ BM_ELEM_API_FLAG_DISABLE(varr[i], _FLAG_OVERLAP);
+ }
- return count;
+ return count;
}
-
/**
* Return true if all verts are in the face.
*/
bool BM_verts_in_face(BMVert **varr, int len, BMFace *f)
{
- BMLoop *l_iter, *l_first;
+ BMLoop *l_iter, *l_first;
#ifdef USE_BMESH_HOLES
- BMLoopList *lst;
+ BMLoopList *lst;
#endif
- int i;
- bool ok = true;
+ int i;
+ bool ok = true;
- /* simple check, we know can't succeed */
- if (f->len < len) {
- return false;
- }
+ /* simple check, we know can't succeed */
+ if (f->len < len) {
+ return false;
+ }
- for (i = 0; i < len; i++) {
- BM_ELEM_API_FLAG_ENABLE(varr[i], _FLAG_OVERLAP);
- }
+ for (i = 0; i < len; i++) {
+ BM_ELEM_API_FLAG_ENABLE(varr[i], _FLAG_OVERLAP);
+ }
#ifdef USE_BMESH_HOLES
- for (lst = f->loops.first; lst; lst = lst->next)
+ for (lst = f->loops.first; lst; lst = lst->next)
#endif
- {
+ {
#ifdef USE_BMESH_HOLES
- l_iter = l_first = lst->first;
+ l_iter = l_first = lst->first;
#else
- l_iter = l_first = f->l_first;
+ l_iter = l_first = f->l_first;
#endif
- do {
- if (BM_ELEM_API_FLAG_TEST(l_iter->v, _FLAG_OVERLAP)) {
- /* pass */
- }
- else {
- ok = false;
- break;
- }
+ do {
+ if (BM_ELEM_API_FLAG_TEST(l_iter->v, _FLAG_OVERLAP)) {
+ /* pass */
+ }
+ else {
+ ok = false;
+ break;
+ }
- } while ((l_iter = l_iter->next) != l_first);
- }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
- for (i = 0; i < len; i++) {
- BM_ELEM_API_FLAG_DISABLE(varr[i], _FLAG_OVERLAP);
- }
+ for (i = 0; i < len; i++) {
+ BM_ELEM_API_FLAG_DISABLE(varr[i], _FLAG_OVERLAP);
+ }
- return ok;
+ return ok;
}
/**
@@ -515,18 +506,18 @@ bool BM_verts_in_face(BMVert **varr, int len, BMFace *f)
*/
bool BM_edge_in_face(const BMEdge *e, const BMFace *f)
{
- if (e->l) {
- const BMLoop *l_iter, *l_first;
+ if (e->l) {
+ const BMLoop *l_iter, *l_first;
- l_iter = l_first = e->l;
- do {
- if (l_iter->f == f) {
- return true;
- }
- } while ((l_iter = l_iter->radial_next) != l_first);
- }
+ l_iter = l_first = e->l;
+ do {
+ if (l_iter->f == f) {
+ return true;
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
- return false;
+ return false;
}
/**
@@ -547,27 +538,27 @@ bool BM_edge_in_face(const BMEdge *e, const BMFace *f)
*/
BMLoop *BM_edge_other_loop(BMEdge *e, BMLoop *l)
{
- BMLoop *l_other;
+ BMLoop *l_other;
- // BLI_assert(BM_edge_is_manifold(e)); // TOO strict, just check if we have another radial face
- BLI_assert(e->l && e->l->radial_next != e->l);
- BLI_assert(BM_vert_in_edge(e, l->v));
+ // BLI_assert(BM_edge_is_manifold(e)); // TOO strict, just check if we have another radial face
+ BLI_assert(e->l && e->l->radial_next != e->l);
+ BLI_assert(BM_vert_in_edge(e, l->v));
- l_other = (l->e == e) ? l : l->prev;
- l_other = l_other->radial_next;
- BLI_assert(l_other->e == e);
+ l_other = (l->e == e) ? l : l->prev;
+ l_other = l_other->radial_next;
+ BLI_assert(l_other->e == e);
- if (l_other->v == l->v) {
- /* pass */
- }
- else if (l_other->next->v == l->v) {
- l_other = l_other->next;
- }
- else {
- BLI_assert(0);
- }
+ if (l_other->v == l->v) {
+ /* pass */
+ }
+ else if (l_other->next->v == l->v) {
+ l_other = l_other->next;
+ }
+ else {
+ BLI_assert(0);
+ }
- return l_other;
+ return l_other;
}
/**
@@ -597,29 +588,27 @@ BMLoop *BM_edge_other_loop(BMEdge *e, BMLoop *l)
BMLoop *BM_vert_step_fan_loop(BMLoop *l, BMEdge **e_step)
{
- BMEdge *e_prev = *e_step;
- BMEdge *e_next;
- if (l->e == e_prev) {
- e_next = l->prev->e;
- }
- else if (l->prev->e == e_prev) {
- e_next = l->e;
- }
- else {
- BLI_assert(0);
- return NULL;
- }
+ BMEdge *e_prev = *e_step;
+ BMEdge *e_next;
+ if (l->e == e_prev) {
+ e_next = l->prev->e;
+ }
+ else if (l->prev->e == e_prev) {
+ e_next = l->e;
+ }
+ else {
+ BLI_assert(0);
+ return NULL;
+ }
- if (BM_edge_is_manifold(e_next)) {
- return BM_edge_other_loop((*e_step = e_next), l);
- }
- else {
- return NULL;
- }
+ if (BM_edge_is_manifold(e_next)) {
+ return BM_edge_other_loop((*e_step = e_next), l);
+ }
+ else {
+ return NULL;
+ }
}
-
-
/**
* The function takes a vertex at the center of a fan and returns the opposite edge in the fan.
* All edges in the fan must be manifold, otherwise return NULL.
@@ -628,49 +617,48 @@ BMLoop *BM_vert_step_fan_loop(BMLoop *l, BMEdge **e_step)
*/
BMEdge *BM_vert_other_disk_edge(BMVert *v, BMEdge *e_first)
{
- BMLoop *l_a;
- int tot = 0;
- int i;
+ BMLoop *l_a;
+ int tot = 0;
+ int i;
- BLI_assert(BM_vert_in_edge(e_first, v));
+ BLI_assert(BM_vert_in_edge(e_first, v));
- l_a = e_first->l;
- do {
- l_a = BM_loop_other_vert_loop(l_a, v);
- l_a = BM_vert_in_edge(l_a->e, v) ? l_a : l_a->prev;
- if (BM_edge_is_manifold(l_a->e)) {
- l_a = l_a->radial_next;
- }
- else {
- return NULL;
- }
+ l_a = e_first->l;
+ do {
+ l_a = BM_loop_other_vert_loop(l_a, v);
+ l_a = BM_vert_in_edge(l_a->e, v) ? l_a : l_a->prev;
+ if (BM_edge_is_manifold(l_a->e)) {
+ l_a = l_a->radial_next;
+ }
+ else {
+ return NULL;
+ }
- tot++;
- } while (l_a != e_first->l);
+ tot++;
+ } while (l_a != e_first->l);
- /* we know the total, now loop half way */
- tot /= 2;
- i = 0;
+ /* we know the total, now loop half way */
+ tot /= 2;
+ i = 0;
- l_a = e_first->l;
- do {
- if (i == tot) {
- l_a = BM_vert_in_edge(l_a->e, v) ? l_a : l_a->prev;
- return l_a->e;
- }
+ l_a = e_first->l;
+ do {
+ if (i == tot) {
+ l_a = BM_vert_in_edge(l_a->e, v) ? l_a : l_a->prev;
+ return l_a->e;
+ }
- l_a = BM_loop_other_vert_loop(l_a, v);
- l_a = BM_vert_in_edge(l_a->e, v) ? l_a : l_a->prev;
- if (BM_edge_is_manifold(l_a->e)) {
- l_a = l_a->radial_next;
- }
- /* this wont have changed from the previous loop */
+ l_a = BM_loop_other_vert_loop(l_a, v);
+ l_a = BM_vert_in_edge(l_a->e, v) ? l_a : l_a->prev;
+ if (BM_edge_is_manifold(l_a->e)) {
+ l_a = l_a->radial_next;
+ }
+ /* this wont have changed from the previous loop */
+ i++;
+ } while (l_a != e_first->l);
- i++;
- } while (l_a != e_first->l);
-
- return NULL;
+ return NULL;
}
/**
@@ -678,7 +666,7 @@ BMEdge *BM_vert_other_disk_edge(BMVert *v, BMEdge *e_first)
*/
float BM_edge_calc_length(const BMEdge *e)
{
- return len_v3v3(e->v1->co, e->v2->co);
+ return len_v3v3(e->v1->co, e->v2->co);
}
/**
@@ -686,7 +674,7 @@ float BM_edge_calc_length(const BMEdge *e)
*/
float BM_edge_calc_length_squared(const BMEdge *e)
{
- return len_squared_v3v3(e->v1->co, e->v2->co);
+ return len_squared_v3v3(e->v1->co, e->v2->co);
}
/**
@@ -697,22 +685,18 @@ float BM_edge_calc_length_squared(const BMEdge *e)
*/
bool BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb)
{
- BMLoop *la, *lb;
+ BMLoop *la, *lb;
- if ((la = e->l) &&
- (lb = la->radial_next) &&
- (la != lb) &&
- (lb->radial_next == la))
- {
- *r_fa = la->f;
- *r_fb = lb->f;
- return true;
- }
- else {
- *r_fa = NULL;
- *r_fb = NULL;
- return false;
- }
+ if ((la = e->l) && (lb = la->radial_next) && (la != lb) && (lb->radial_next == la)) {
+ *r_fa = la->f;
+ *r_fb = lb->f;
+ return true;
+ }
+ else {
+ *r_fa = NULL;
+ *r_fb = NULL;
+ return false;
+ }
}
/**
@@ -723,22 +707,18 @@ bool BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb)
*/
bool BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb)
{
- BMLoop *la, *lb;
+ BMLoop *la, *lb;
- if ((la = e->l) &&
- (lb = la->radial_next) &&
- (la != lb) &&
- (lb->radial_next == la))
- {
- *r_la = la;
- *r_lb = lb;
- return true;
- }
- else {
- *r_la = NULL;
- *r_lb = NULL;
- return false;
- }
+ if ((la = e->l) && (lb = la->radial_next) && (la != lb) && (lb->radial_next == la)) {
+ *r_la = la;
+ *r_lb = lb;
+ return true;
+ }
+ else {
+ *r_la = NULL;
+ *r_lb = NULL;
+ return false;
+ }
}
/**
@@ -746,12 +726,12 @@ bool BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb)
*/
bool BM_vert_is_edge_pair(const BMVert *v)
{
- const BMEdge *e = v->e;
- if (e) {
- BMEdge *e_other = BM_DISK_EDGE_NEXT(e, v);
- return ((e_other != e) && (BM_DISK_EDGE_NEXT(e_other, v) == e));
- }
- return false;
+ const BMEdge *e = v->e;
+ if (e) {
+ BMEdge *e_other = BM_DISK_EDGE_NEXT(e, v);
+ return ((e_other != e) && (BM_DISK_EDGE_NEXT(e_other, v) == e));
+ }
+ return false;
}
/**
@@ -760,14 +740,14 @@ bool BM_vert_is_edge_pair(const BMVert *v)
*/
bool BM_vert_is_edge_pair_manifold(const BMVert *v)
{
- const BMEdge *e = v->e;
- if (e) {
- BMEdge *e_other = BM_DISK_EDGE_NEXT(e, v);
- if (((e_other != e) && (BM_DISK_EDGE_NEXT(e_other, v) == e))) {
- return BM_edge_is_manifold(e) && BM_edge_is_manifold(e_other);
- }
- }
- return false;
+ const BMEdge *e = v->e;
+ if (e) {
+ BMEdge *e_other = BM_DISK_EDGE_NEXT(e, v);
+ if (((e_other != e) && (BM_DISK_EDGE_NEXT(e_other, v) == e))) {
+ return BM_edge_is_manifold(e) && BM_edge_is_manifold(e_other);
+ }
+ }
+ return false;
}
/**
@@ -777,19 +757,19 @@ bool BM_vert_is_edge_pair_manifold(const BMVert *v)
*/
bool BM_vert_edge_pair(BMVert *v, BMEdge **r_e_a, BMEdge **r_e_b)
{
- BMEdge *e_a = v->e;
- if (e_a) {
- BMEdge *e_b = BM_DISK_EDGE_NEXT(e_a, v);
- if ((e_b != e_a) && (BM_DISK_EDGE_NEXT(e_b, v) == e_a)) {
- *r_e_a = e_a;
- *r_e_b = e_b;
- return true;
- }
- }
+ BMEdge *e_a = v->e;
+ if (e_a) {
+ BMEdge *e_b = BM_DISK_EDGE_NEXT(e_a, v);
+ if ((e_b != e_a) && (BM_DISK_EDGE_NEXT(e_b, v) == e_a)) {
+ *r_e_a = e_a;
+ *r_e_b = e_b;
+ return true;
+ }
+ }
- *r_e_a = NULL;
- *r_e_b = NULL;
- return false;
+ *r_e_a = NULL;
+ *r_e_b = NULL;
+ return false;
}
/**
@@ -797,62 +777,62 @@ bool BM_vert_edge_pair(BMVert *v, BMEdge **r_e_a, BMEdge **r_e_b)
*/
int BM_vert_edge_count(const BMVert *v)
{
- return bmesh_disk_count(v);
+ return bmesh_disk_count(v);
}
int BM_vert_edge_count_at_most(const BMVert *v, const int count_max)
{
- return bmesh_disk_count_at_most(v, count_max);
+ return bmesh_disk_count_at_most(v, count_max);
}
int BM_vert_edge_count_nonwire(const BMVert *v)
{
- int count = 0;
- BMIter eiter;
- BMEdge *edge;
- BM_ITER_ELEM (edge, &eiter, (BMVert *)v, BM_EDGES_OF_VERT) {
- if (edge->l) {
- count++;
- }
- }
- return count;
+ int count = 0;
+ BMIter eiter;
+ BMEdge *edge;
+ BM_ITER_ELEM (edge, &eiter, (BMVert *)v, BM_EDGES_OF_VERT) {
+ if (edge->l) {
+ count++;
+ }
+ }
+ return count;
}
/**
* Returns the number of faces around this edge
*/
int BM_edge_face_count(const BMEdge *e)
{
- int count = 0;
+ int count = 0;
- if (e->l) {
- BMLoop *l_iter, *l_first;
+ if (e->l) {
+ BMLoop *l_iter, *l_first;
- l_iter = l_first = e->l;
- do {
- count++;
- } while ((l_iter = l_iter->radial_next) != l_first);
- }
+ l_iter = l_first = e->l;
+ do {
+ count++;
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
- return count;
+ return count;
}
int BM_edge_face_count_at_most(const BMEdge *e, const int count_max)
{
- int count = 0;
+ int count = 0;
- if (e->l) {
- BMLoop *l_iter, *l_first;
+ if (e->l) {
+ BMLoop *l_iter, *l_first;
- l_iter = l_first = e->l;
- do {
- count++;
- if (count == count_max) {
- break;
- }
- } while ((l_iter = l_iter->radial_next) != l_first);
- }
+ l_iter = l_first = e->l;
+ do {
+ count++;
+ if (count == count_max) {
+ break;
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
- return count;
+ return count;
}
/**
@@ -861,12 +841,12 @@ int BM_edge_face_count_at_most(const BMEdge *e, const int count_max)
*/
int BM_vert_face_count(const BMVert *v)
{
- return bmesh_disk_facevert_count(v);
+ return bmesh_disk_facevert_count(v);
}
int BM_vert_face_count_at_most(const BMVert *v, int count_max)
{
- return bmesh_disk_facevert_count_at_most(v, count_max);
+ return bmesh_disk_facevert_count_at_most(v, count_max);
}
/**
@@ -876,16 +856,16 @@ int BM_vert_face_count_at_most(const BMVert *v, int count_max)
*/
bool BM_vert_face_check(const BMVert *v)
{
- if (v->e != NULL) {
- const BMEdge *e_iter, *e_first;
- e_first = e_iter = v->e;
- do {
- if (e_iter->l != NULL) {
- return true;
- }
- } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
- }
- return false;
+ if (v->e != NULL) {
+ const BMEdge *e_iter, *e_first;
+ e_first = e_iter = v->e;
+ do {
+ if (e_iter->l != NULL) {
+ return true;
+ }
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
+ }
+ return false;
}
/**
@@ -894,21 +874,21 @@ bool BM_vert_face_check(const BMVert *v)
*/
bool BM_vert_is_wire(const BMVert *v)
{
- if (v->e) {
- BMEdge *e_first, *e_iter;
+ if (v->e) {
+ BMEdge *e_first, *e_iter;
- e_first = e_iter = v->e;
- do {
- if (e_iter->l) {
- return false;
- }
- } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
+ e_first = e_iter = v->e;
+ do {
+ if (e_iter->l) {
+ return false;
+ }
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
- return true;
- }
- else {
- return false;
- }
+ return true;
+ }
+ else {
+ return false;
+ }
}
/**
@@ -920,61 +900,61 @@ bool BM_vert_is_wire(const BMVert *v)
*/
bool BM_vert_is_manifold(const BMVert *v)
{
- BMEdge *e_iter, *e_first, *e_prev;
- BMLoop *l_iter, *l_first;
- int loop_num = 0, loop_num_region = 0, boundary_num = 0;
-
- if (v->e == NULL) {
- /* loose vert */
- return false;
- }
-
- /* count edges while looking for non-manifold edges */
- e_first = e_iter = v->e;
- /* may be null */
- l_first = e_iter->l;
- do {
- /* loose edge or edge shared by more than two faces,
- * edges with 1 face user are OK, otherwise we could
- * use BM_edge_is_manifold() here */
- if (e_iter->l == NULL || (e_iter->l != e_iter->l->radial_next->radial_next)) {
- return false;
- }
-
- /* count radial loops */
- if (e_iter->l->v == v) {
- loop_num += 1;
- }
-
- if (!BM_edge_is_boundary(e_iter)) {
- /* non boundary check opposite loop */
- if (e_iter->l->radial_next->v == v) {
- loop_num += 1;
- }
- }
- else {
- /* start at the boundary */
- l_first = e_iter->l;
- boundary_num += 1;
- /* >2 boundaries cant be manifold */
- if (boundary_num == 3) {
- return false;
- }
- }
- } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
-
- e_first = l_first->e;
- l_first = (l_first->v == v) ? l_first : l_first->next;
- BLI_assert(l_first->v == v);
-
- l_iter = l_first;
- e_prev = e_first;
-
- do {
- loop_num_region += 1;
- } while (((l_iter = BM_vert_step_fan_loop(l_iter, &e_prev)) != l_first) && (l_iter != NULL));
-
- return (loop_num == loop_num_region);
+ BMEdge *e_iter, *e_first, *e_prev;
+ BMLoop *l_iter, *l_first;
+ int loop_num = 0, loop_num_region = 0, boundary_num = 0;
+
+ if (v->e == NULL) {
+ /* loose vert */
+ return false;
+ }
+
+ /* count edges while looking for non-manifold edges */
+ e_first = e_iter = v->e;
+ /* may be null */
+ l_first = e_iter->l;
+ do {
+ /* loose edge or edge shared by more than two faces,
+ * edges with 1 face user are OK, otherwise we could
+ * use BM_edge_is_manifold() here */
+ if (e_iter->l == NULL || (e_iter->l != e_iter->l->radial_next->radial_next)) {
+ return false;
+ }
+
+ /* count radial loops */
+ if (e_iter->l->v == v) {
+ loop_num += 1;
+ }
+
+ if (!BM_edge_is_boundary(e_iter)) {
+ /* non boundary check opposite loop */
+ if (e_iter->l->radial_next->v == v) {
+ loop_num += 1;
+ }
+ }
+ else {
+ /* start at the boundary */
+ l_first = e_iter->l;
+ boundary_num += 1;
+ /* >2 boundaries cant be manifold */
+ if (boundary_num == 3) {
+ return false;
+ }
+ }
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
+
+ e_first = l_first->e;
+ l_first = (l_first->v == v) ? l_first : l_first->next;
+ BLI_assert(l_first->v == v);
+
+ l_iter = l_first;
+ e_prev = e_first;
+
+ do {
+ loop_num_region += 1;
+ } while (((l_iter = BM_vert_step_fan_loop(l_iter, &e_prev)) != l_first) && (l_iter != NULL));
+
+ return (loop_num == loop_num_region);
}
#define LOOP_VISIT _FLAG_WALK
@@ -982,64 +962,64 @@ bool BM_vert_is_manifold(const BMVert *v)
static int bm_loop_region_count__recursive(BMEdge *e, BMVert *v)
{
- BMLoop *l_iter, *l_first;
- int count = 0;
-
- BLI_assert(!BM_ELEM_API_FLAG_TEST(e, EDGE_VISIT));
- BM_ELEM_API_FLAG_ENABLE(e, EDGE_VISIT);
-
- l_iter = l_first = e->l;
- do {
- if (l_iter->v == v) {
- BMEdge *e_other = l_iter->prev->e;
- if (!BM_ELEM_API_FLAG_TEST(l_iter, LOOP_VISIT)) {
- BM_ELEM_API_FLAG_ENABLE(l_iter, LOOP_VISIT);
- count += 1;
- }
- if (!BM_ELEM_API_FLAG_TEST(e_other, EDGE_VISIT)) {
- count += bm_loop_region_count__recursive(e_other, v);
- }
- }
- else if (l_iter->next->v == v) {
- BMEdge *e_other = l_iter->next->e;
- if (!BM_ELEM_API_FLAG_TEST(l_iter->next, LOOP_VISIT)) {
- BM_ELEM_API_FLAG_ENABLE(l_iter->next, LOOP_VISIT);
- count += 1;
- }
- if (!BM_ELEM_API_FLAG_TEST(e_other, EDGE_VISIT)) {
- count += bm_loop_region_count__recursive(e_other, v);
- }
- }
- else {
- BLI_assert(0);
- }
- } while ((l_iter = l_iter->radial_next) != l_first);
-
- return count;
+ BMLoop *l_iter, *l_first;
+ int count = 0;
+
+ BLI_assert(!BM_ELEM_API_FLAG_TEST(e, EDGE_VISIT));
+ BM_ELEM_API_FLAG_ENABLE(e, EDGE_VISIT);
+
+ l_iter = l_first = e->l;
+ do {
+ if (l_iter->v == v) {
+ BMEdge *e_other = l_iter->prev->e;
+ if (!BM_ELEM_API_FLAG_TEST(l_iter, LOOP_VISIT)) {
+ BM_ELEM_API_FLAG_ENABLE(l_iter, LOOP_VISIT);
+ count += 1;
+ }
+ if (!BM_ELEM_API_FLAG_TEST(e_other, EDGE_VISIT)) {
+ count += bm_loop_region_count__recursive(e_other, v);
+ }
+ }
+ else if (l_iter->next->v == v) {
+ BMEdge *e_other = l_iter->next->e;
+ if (!BM_ELEM_API_FLAG_TEST(l_iter->next, LOOP_VISIT)) {
+ BM_ELEM_API_FLAG_ENABLE(l_iter->next, LOOP_VISIT);
+ count += 1;
+ }
+ if (!BM_ELEM_API_FLAG_TEST(e_other, EDGE_VISIT)) {
+ count += bm_loop_region_count__recursive(e_other, v);
+ }
+ }
+ else {
+ BLI_assert(0);
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
+
+ return count;
}
static int bm_loop_region_count__clear(BMLoop *l)
{
- int count = 0;
- BMEdge *e_iter, *e_first;
+ int count = 0;
+ BMEdge *e_iter, *e_first;
- /* clear flags */
- e_iter = e_first = l->e;
- do {
- BM_ELEM_API_FLAG_DISABLE(e_iter, EDGE_VISIT);
- if (e_iter->l) {
- BMLoop *l_iter, *l_first;
- l_iter = l_first = e_iter->l;
- do {
- if (l_iter->v == l->v) {
- BM_ELEM_API_FLAG_DISABLE(l_iter, LOOP_VISIT);
- count += 1;
- }
- } while ((l_iter = l_iter->radial_next) != l_first);
- }
- } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, l->v)) != e_first);
+ /* clear flags */
+ e_iter = e_first = l->e;
+ do {
+ BM_ELEM_API_FLAG_DISABLE(e_iter, EDGE_VISIT);
+ if (e_iter->l) {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = e_iter->l;
+ do {
+ if (l_iter->v == l->v) {
+ BM_ELEM_API_FLAG_DISABLE(l_iter, LOOP_VISIT);
+ count += 1;
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+ } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, l->v)) != e_first);
- return count;
+ return count;
}
/**
@@ -1047,12 +1027,12 @@ static int bm_loop_region_count__clear(BMLoop *l)
*/
int BM_loop_region_loops_count_at_most(BMLoop *l, int *r_loop_total)
{
- const int count = bm_loop_region_count__recursive(l->e, l->v);
- const int count_total = bm_loop_region_count__clear(l);
- if (r_loop_total) {
- *r_loop_total = count_total;
- }
- return count;
+ const int count = bm_loop_region_count__recursive(l->e, l->v);
+ const int count_total = bm_loop_region_count__clear(l);
+ if (r_loop_total) {
+ *r_loop_total = count_total;
+ }
+ return count;
}
#undef LOOP_VISIT
@@ -1060,7 +1040,7 @@ int BM_loop_region_loops_count_at_most(BMLoop *l, int *r_loop_total)
int BM_loop_region_loops_count(BMLoop *l)
{
- return BM_loop_region_loops_count_at_most(l, NULL);
+ return BM_loop_region_loops_count_at_most(l, NULL);
}
/**
@@ -1069,13 +1049,13 @@ int BM_loop_region_loops_count(BMLoop *l)
*/
bool BM_vert_is_manifold_region(const BMVert *v)
{
- BMLoop *l_first = BM_vert_find_first_loop((BMVert *)v);
- if (l_first) {
- int count, count_total;
- count = BM_loop_region_loops_count_at_most(l_first, &count_total);
- return (count == count_total);
- }
- return true;
+ BMLoop *l_first = BM_vert_find_first_loop((BMVert *)v);
+ if (l_first) {
+ int count, count_total;
+ count = BM_loop_region_loops_count_at_most(l_first, &count_total);
+ return (count == count_total);
+ }
+ return true;
}
/**
@@ -1084,85 +1064,82 @@ bool BM_vert_is_manifold_region(const BMVert *v)
*/
bool BM_edge_is_convex(const BMEdge *e)
{
- if (BM_edge_is_manifold(e)) {
- BMLoop *l1 = e->l;
- BMLoop *l2 = e->l->radial_next;
- if (!equals_v3v3(l1->f->no, l2->f->no)) {
- float cross[3];
- float l_dir[3];
- cross_v3_v3v3(cross, l1->f->no, l2->f->no);
- /* we assume contiguous normals, otherwise the result isn't meaningful */
- sub_v3_v3v3(l_dir, l1->next->v->co, l1->v->co);
- return (dot_v3v3(l_dir, cross) > 0.0f);
- }
- }
- return true;
+ if (BM_edge_is_manifold(e)) {
+ BMLoop *l1 = e->l;
+ BMLoop *l2 = e->l->radial_next;
+ if (!equals_v3v3(l1->f->no, l2->f->no)) {
+ float cross[3];
+ float l_dir[3];
+ cross_v3_v3v3(cross, l1->f->no, l2->f->no);
+ /* we assume contiguous normals, otherwise the result isn't meaningful */
+ sub_v3_v3v3(l_dir, l1->next->v->co, l1->v->co);
+ return (dot_v3v3(l_dir, cross) > 0.0f);
+ }
+ }
+ return true;
}
/**
* \return true when loop customdata is contiguous.
*/
-bool BM_edge_is_contiguous_loop_cd(
- const BMEdge *e,
- const int cd_loop_type, const int cd_loop_offset)
-{
- BLI_assert(cd_loop_offset != -1);
-
- if (e->l && e->l->radial_next != e->l) {
- const BMLoop *l_base_v1 = e->l;
- const BMLoop *l_base_v2 = e->l->next;
- const void *l_base_cd_v1 = BM_ELEM_CD_GET_VOID_P(l_base_v1, cd_loop_offset);
- const void *l_base_cd_v2 = BM_ELEM_CD_GET_VOID_P(l_base_v2, cd_loop_offset);
- const BMLoop *l_iter = e->l->radial_next;
- do {
- const BMLoop *l_iter_v1;
- const BMLoop *l_iter_v2;
- const void *l_iter_cd_v1;
- const void *l_iter_cd_v2;
-
- if (l_iter->v == l_base_v1->v) {
- l_iter_v1 = l_iter;
- l_iter_v2 = l_iter->next;
- }
- else {
- l_iter_v1 = l_iter->next;
- l_iter_v2 = l_iter;
- }
- BLI_assert((l_iter_v1->v == l_base_v1->v) &&
- (l_iter_v2->v == l_base_v2->v));
-
- l_iter_cd_v1 = BM_ELEM_CD_GET_VOID_P(l_iter_v1, cd_loop_offset);
- l_iter_cd_v2 = BM_ELEM_CD_GET_VOID_P(l_iter_v2, cd_loop_offset);
-
-
- if ((CustomData_data_equals(cd_loop_type, l_base_cd_v1, l_iter_cd_v1) == 0) ||
- (CustomData_data_equals(cd_loop_type, l_base_cd_v2, l_iter_cd_v2) == 0))
- {
- return false;
- }
-
- } while ((l_iter = l_iter->radial_next) != e->l);
- }
- return true;
+bool BM_edge_is_contiguous_loop_cd(const BMEdge *e,
+ const int cd_loop_type,
+ const int cd_loop_offset)
+{
+ BLI_assert(cd_loop_offset != -1);
+
+ if (e->l && e->l->radial_next != e->l) {
+ const BMLoop *l_base_v1 = e->l;
+ const BMLoop *l_base_v2 = e->l->next;
+ const void *l_base_cd_v1 = BM_ELEM_CD_GET_VOID_P(l_base_v1, cd_loop_offset);
+ const void *l_base_cd_v2 = BM_ELEM_CD_GET_VOID_P(l_base_v2, cd_loop_offset);
+ const BMLoop *l_iter = e->l->radial_next;
+ do {
+ const BMLoop *l_iter_v1;
+ const BMLoop *l_iter_v2;
+ const void *l_iter_cd_v1;
+ const void *l_iter_cd_v2;
+
+ if (l_iter->v == l_base_v1->v) {
+ l_iter_v1 = l_iter;
+ l_iter_v2 = l_iter->next;
+ }
+ else {
+ l_iter_v1 = l_iter->next;
+ l_iter_v2 = l_iter;
+ }
+ BLI_assert((l_iter_v1->v == l_base_v1->v) && (l_iter_v2->v == l_base_v2->v));
+
+ l_iter_cd_v1 = BM_ELEM_CD_GET_VOID_P(l_iter_v1, cd_loop_offset);
+ l_iter_cd_v2 = BM_ELEM_CD_GET_VOID_P(l_iter_v2, cd_loop_offset);
+
+ if ((CustomData_data_equals(cd_loop_type, l_base_cd_v1, l_iter_cd_v1) == 0) ||
+ (CustomData_data_equals(cd_loop_type, l_base_cd_v2, l_iter_cd_v2) == 0)) {
+ return false;
+ }
+
+ } while ((l_iter = l_iter->radial_next) != e->l);
+ }
+ return true;
}
bool BM_vert_is_boundary(const BMVert *v)
{
- if (v->e) {
- BMEdge *e_first, *e_iter;
+ if (v->e) {
+ BMEdge *e_first, *e_iter;
- e_first = e_iter = v->e;
- do {
- if (BM_edge_is_boundary(e_iter)) {
- return true;
- }
- } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
+ e_first = e_iter = v->e;
+ do {
+ if (BM_edge_is_boundary(e_iter)) {
+ return true;
+ }
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
- return false;
- }
- else {
- return false;
- }
+ return false;
+ }
+ else {
+ return false;
+ }
}
/**
@@ -1172,20 +1149,20 @@ bool BM_vert_is_boundary(const BMVert *v)
*/
int BM_face_share_face_count(BMFace *f1, BMFace *f2)
{
- BMIter iter1, iter2;
- BMEdge *e;
- BMFace *f;
- int count = 0;
+ BMIter iter1, iter2;
+ BMEdge *e;
+ BMFace *f;
+ int count = 0;
- BM_ITER_ELEM (e, &iter1, f1, BM_EDGES_OF_FACE) {
- BM_ITER_ELEM (f, &iter2, e, BM_FACES_OF_EDGE) {
- if (f != f1 && f != f2 && BM_face_share_edge_check(f, f2)) {
- count++;
- }
- }
- }
+ BM_ITER_ELEM (e, &iter1, f1, BM_EDGES_OF_FACE) {
+ BM_ITER_ELEM (f, &iter2, e, BM_FACES_OF_EDGE) {
+ if (f != f1 && f != f2 && BM_face_share_edge_check(f, f2)) {
+ count++;
+ }
+ }
+ }
- return count;
+ return count;
}
/**
@@ -1193,19 +1170,19 @@ int BM_face_share_face_count(BMFace *f1, BMFace *f2)
*/
bool BM_face_share_face_check(BMFace *f1, BMFace *f2)
{
- BMIter iter1, iter2;
- BMEdge *e;
- BMFace *f;
+ BMIter iter1, iter2;
+ BMEdge *e;
+ BMFace *f;
- BM_ITER_ELEM (e, &iter1, f1, BM_EDGES_OF_FACE) {
- BM_ITER_ELEM (f, &iter2, e, BM_FACES_OF_EDGE) {
- if (f != f1 && f != f2 && BM_face_share_edge_check(f, f2)) {
- return true;
- }
- }
- }
+ BM_ITER_ELEM (e, &iter1, f1, BM_EDGES_OF_FACE) {
+ BM_ITER_ELEM (f, &iter2, e, BM_FACES_OF_EDGE) {
+ if (f != f1 && f != f2 && BM_face_share_edge_check(f, f2)) {
+ return true;
+ }
+ }
+ }
- return false;
+ return false;
}
/**
@@ -1213,18 +1190,18 @@ bool BM_face_share_face_check(BMFace *f1, BMFace *f2)
*/
int BM_face_share_edge_count(BMFace *f_a, BMFace *f_b)
{
- BMLoop *l_iter;
- BMLoop *l_first;
- int count = 0;
+ BMLoop *l_iter;
+ BMLoop *l_first;
+ int count = 0;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f_a);
- do {
- if (BM_edge_in_face(l_iter->e, f_b)) {
- count++;
- }
- } while ((l_iter = l_iter->next) != l_first);
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_a);
+ do {
+ if (BM_edge_in_face(l_iter->e, f_b)) {
+ count++;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
- return count;
+ return count;
}
/**
@@ -1232,17 +1209,17 @@ int BM_face_share_edge_count(BMFace *f_a, BMFace *f_b)
*/
bool BM_face_share_edge_check(BMFace *f1, BMFace *f2)
{
- BMLoop *l_iter;
- BMLoop *l_first;
+ BMLoop *l_iter;
+ BMLoop *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f1);
- do {
- if (BM_edge_in_face(l_iter->e, f2)) {
- return true;
- }
- } while ((l_iter = l_iter->next) != l_first);
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f1);
+ do {
+ if (BM_edge_in_face(l_iter->e, f2)) {
+ return true;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
- return false;
+ return false;
}
/**
@@ -1250,18 +1227,18 @@ bool BM_face_share_edge_check(BMFace *f1, BMFace *f2)
*/
int BM_face_share_vert_count(BMFace *f_a, BMFace *f_b)
{
- BMLoop *l_iter;
- BMLoop *l_first;
- int count = 0;
+ BMLoop *l_iter;
+ BMLoop *l_first;
+ int count = 0;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f_a);
- do {
- if (BM_vert_in_face(l_iter->v, f_b)) {
- count++;
- }
- } while ((l_iter = l_iter->next) != l_first);
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_a);
+ do {
+ if (BM_vert_in_face(l_iter->v, f_b)) {
+ count++;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
- return count;
+ return count;
}
/**
@@ -1269,17 +1246,17 @@ int BM_face_share_vert_count(BMFace *f_a, BMFace *f_b)
*/
bool BM_face_share_vert_check(BMFace *f_a, BMFace *f_b)
{
- BMLoop *l_iter;
- BMLoop *l_first;
+ BMLoop *l_iter;
+ BMLoop *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f_a);
- do {
- if (BM_vert_in_face(l_iter->v, f_b)) {
- return true;
- }
- } while ((l_iter = l_iter->next) != l_first);
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_a);
+ do {
+ if (BM_vert_in_face(l_iter->v, f_b)) {
+ return true;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
- return false;
+ return false;
}
/**
@@ -1287,9 +1264,8 @@ bool BM_face_share_vert_check(BMFace *f_a, BMFace *f_b)
*/
bool BM_loop_share_edge_check(BMLoop *l_a, BMLoop *l_b)
{
- BLI_assert(l_a->v == l_b->v);
- return (ELEM(l_a->e, l_b->e, l_b->prev->e) ||
- ELEM(l_b->e, l_a->e, l_a->prev->e));
+ BLI_assert(l_a->v == l_b->v);
+ return (ELEM(l_a->e, l_b->e, l_b->prev->e) || ELEM(l_b->e, l_a->e, l_a->prev->e));
}
/**
@@ -1297,20 +1273,20 @@ bool BM_loop_share_edge_check(BMLoop *l_a, BMLoop *l_b)
*/
bool BM_edge_share_face_check(BMEdge *e1, BMEdge *e2)
{
- BMLoop *l;
- BMFace *f;
+ BMLoop *l;
+ BMFace *f;
- if (e1->l && e2->l) {
- l = e1->l;
- do {
- f = l->f;
- if (BM_edge_in_face(e2, f)) {
- return true;
- }
- l = l->radial_next;
- } while (l != e1->l);
- }
- return false;
+ if (e1->l && e2->l) {
+ l = e1->l;
+ do {
+ f = l->f;
+ if (BM_edge_in_face(e2, f)) {
+ return true;
+ }
+ l = l->radial_next;
+ } while (l != e1->l);
+ }
+ return false;
}
/**
@@ -1318,22 +1294,22 @@ bool BM_edge_share_face_check(BMEdge *e1, BMEdge *e2)
*/
bool BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2)
{
- BMLoop *l;
- BMFace *f;
+ BMLoop *l;
+ BMFace *f;
- if (e1->l && e2->l) {
- l = e1->l;
- do {
- f = l->f;
- if (f->len == 4) {
- if (BM_edge_in_face(e2, f)) {
- return true;
- }
- }
- l = l->radial_next;
- } while (l != e1->l);
- }
- return false;
+ if (e1->l && e2->l) {
+ l = e1->l;
+ do {
+ f = l->f;
+ if (f->len == 4) {
+ if (BM_edge_in_face(e2, f)) {
+ return true;
+ }
+ }
+ l = l->radial_next;
+ } while (l != e1->l);
+ }
+ return false;
}
/**
@@ -1341,10 +1317,7 @@ bool BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2)
*/
bool BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2)
{
- return (e1->v1 == e2->v1 ||
- e1->v1 == e2->v2 ||
- e1->v2 == e2->v1 ||
- e1->v2 == e2->v2);
+ return (e1->v1 == e2->v1 || e1->v1 == e2->v2 || e1->v2 == e2->v1 || e1->v2 == e2->v2);
}
/**
@@ -1352,16 +1325,16 @@ bool BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2)
*/
BMVert *BM_edge_share_vert(BMEdge *e1, BMEdge *e2)
{
- BLI_assert(e1 != e2);
- if (BM_vert_in_edge(e2, e1->v1)) {
- return e1->v1;
- }
- else if (BM_vert_in_edge(e2, e1->v2)) {
- return e1->v2;
- }
- else {
- return NULL;
- }
+ BLI_assert(e1 != e2);
+ if (BM_vert_in_edge(e2, e1->v1)) {
+ return e1->v1;
+ }
+ else if (BM_vert_in_edge(e2, e1->v2)) {
+ return e1->v2;
+ }
+ else {
+ return NULL;
+ }
}
/**
@@ -1374,13 +1347,13 @@ BMVert *BM_edge_share_vert(BMEdge *e1, BMEdge *e2)
*/
BMLoop *BM_edge_vert_share_loop(BMLoop *l, BMVert *v)
{
- BLI_assert(BM_vert_in_edge(l->e, v));
- if (l->v == v) {
- return l;
- }
- else {
- return l->next;
- }
+ BLI_assert(BM_vert_in_edge(l->e, v));
+ if (l->v == v) {
+ return l;
+ }
+ else {
+ return l->next;
+ }
}
/**
@@ -1393,17 +1366,17 @@ BMLoop *BM_edge_vert_share_loop(BMLoop *l, BMVert *v)
*/
BMLoop *BM_face_vert_share_loop(BMFace *f, BMVert *v)
{
- BMLoop *l_first;
- BMLoop *l_iter;
+ BMLoop *l_first;
+ BMLoop *l_iter;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if (l_iter->v == v) {
- return l_iter;
- }
- } while ((l_iter = l_iter->next) != l_first);
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (l_iter->v == v) {
+ return l_iter;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
- return NULL;
+ return NULL;
}
/**
@@ -1416,17 +1389,17 @@ BMLoop *BM_face_vert_share_loop(BMFace *f, BMVert *v)
*/
BMLoop *BM_face_edge_share_loop(BMFace *f, BMEdge *e)
{
- BMLoop *l_first;
- BMLoop *l_iter;
+ BMLoop *l_first;
+ BMLoop *l_iter;
- l_iter = l_first = e->l;
- do {
- if (l_iter->f == f) {
- return l_iter;
- }
- } while ((l_iter = l_iter->radial_next) != l_first);
+ l_iter = l_first = e->l;
+ do {
+ if (l_iter->f == f) {
+ return l_iter;
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
- return NULL;
+ return NULL;
}
/**
@@ -1440,19 +1413,20 @@ BMLoop *BM_face_edge_share_loop(BMFace *f, BMEdge *e)
* \note This is in fact quite a simple check, mainly include this function so the intent is more obvious.
* We know these 2 verts will _always_ make up the loops edge
*/
-void BM_edge_ordered_verts_ex(
- const BMEdge *edge, BMVert **r_v1, BMVert **r_v2,
- const BMLoop *edge_loop)
+void BM_edge_ordered_verts_ex(const BMEdge *edge,
+ BMVert **r_v1,
+ BMVert **r_v2,
+ const BMLoop *edge_loop)
{
- BLI_assert(edge_loop->e == edge);
- (void)edge; /* quiet warning in release build */
- *r_v1 = edge_loop->v;
- *r_v2 = edge_loop->next->v;
+ BLI_assert(edge_loop->e == edge);
+ (void)edge; /* quiet warning in release build */
+ *r_v1 = edge_loop->v;
+ *r_v2 = edge_loop->next->v;
}
void BM_edge_ordered_verts(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2)
{
- BM_edge_ordered_verts_ex(edge, r_v1, r_v2, edge->l);
+ BM_edge_ordered_verts_ex(edge, r_v1, r_v2, edge->l);
}
/**
@@ -1460,19 +1434,19 @@ void BM_edge_ordered_verts(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2)
*/
BMLoop *BM_loop_find_prev_nodouble(BMLoop *l, BMLoop *l_stop, const float eps_sq)
{
- BMLoop *l_step = l->prev;
+ BMLoop *l_step = l->prev;
- BLI_assert(!ELEM(l_stop, NULL, l));
+ BLI_assert(!ELEM(l_stop, NULL, l));
- while (UNLIKELY(len_squared_v3v3(l->v->co, l_step->v->co) < eps_sq)) {
- l_step = l_step->prev;
- BLI_assert(l_step != l);
- if (UNLIKELY(l_step == l_stop)) {
- return NULL;
- }
- }
+ while (UNLIKELY(len_squared_v3v3(l->v->co, l_step->v->co) < eps_sq)) {
+ l_step = l_step->prev;
+ BLI_assert(l_step != l);
+ if (UNLIKELY(l_step == l_stop)) {
+ return NULL;
+ }
+ }
- return l_step;
+ return l_step;
}
/**
@@ -1480,19 +1454,19 @@ BMLoop *BM_loop_find_prev_nodouble(BMLoop *l, BMLoop *l_stop, const float eps_sq
*/
BMLoop *BM_loop_find_next_nodouble(BMLoop *l, BMLoop *l_stop, const float eps_sq)
{
- BMLoop *l_step = l->next;
+ BMLoop *l_step = l->next;
- BLI_assert(!ELEM(l_stop, NULL, l));
+ BLI_assert(!ELEM(l_stop, NULL, l));
- while (UNLIKELY(len_squared_v3v3(l->v->co, l_step->v->co) < eps_sq)) {
- l_step = l_step->next;
- BLI_assert(l_step != l);
- if (UNLIKELY(l_step == l_stop)) {
- return NULL;
- }
- }
+ while (UNLIKELY(len_squared_v3v3(l->v->co, l_step->v->co) < eps_sq)) {
+ l_step = l_step->next;
+ BLI_assert(l_step != l);
+ if (UNLIKELY(l_step == l_stop)) {
+ return NULL;
+ }
+ }
- return l_step;
+ return l_step;
}
/**
@@ -1501,14 +1475,14 @@ BMLoop *BM_loop_find_next_nodouble(BMLoop *l, BMLoop *l_stop, const float eps_sq
*/
bool BM_loop_is_convex(const BMLoop *l)
{
- float e_dir_prev[3];
- float e_dir_next[3];
- float l_no[3];
+ float e_dir_prev[3];
+ float e_dir_next[3];
+ float l_no[3];
- sub_v3_v3v3(e_dir_prev, l->prev->v->co, l->v->co);
- sub_v3_v3v3(e_dir_next, l->next->v->co, l->v->co);
- cross_v3_v3v3(l_no, e_dir_next, e_dir_prev);
- return dot_v3v3(l_no, l->f->no) > 0.0f;
+ sub_v3_v3v3(e_dir_prev, l->prev->v->co, l->v->co);
+ sub_v3_v3v3(e_dir_next, l->next->v->co, l->v->co);
+ cross_v3_v3v3(l_no, e_dir_next, e_dir_prev);
+ return dot_v3v3(l_no, l->f->no) > 0.0f;
}
/**
@@ -1519,9 +1493,7 @@ bool BM_loop_is_convex(const BMLoop *l)
*/
float BM_loop_calc_face_angle(const BMLoop *l)
{
- return angle_v3v3v3(l->prev->v->co,
- l->v->co,
- l->next->v->co);
+ return angle_v3v3v3(l->prev->v->co, l->v->co, l->next->v->co);
}
/**
@@ -1535,30 +1507,30 @@ float BM_loop_calc_face_angle(const BMLoop *l)
*/
float BM_loop_calc_face_normal_safe_ex(const BMLoop *l, const float epsilon_sq, float r_normal[3])
{
- /* Note: we cannot use result of normal_tri_v3 here to detect colinear vectors (vertex on a straight line)
- * from zero value, because it does not normalize both vectors before making crossproduct.
- * Instead of adding two costly normalize computations, just check ourselves for colinear case. */
- /* Note: FEPSILON might need some finer tweaking at some point? Seems to be working OK for now though. */
- float v1[3], v2[3], v_tmp[3];
- sub_v3_v3v3(v1, l->prev->v->co, l->v->co);
- sub_v3_v3v3(v2, l->next->v->co, l->v->co);
-
- const float fac =
- ((v2[0] == 0.0f) ?
- ((v2[1] == 0.0f) ?
- ((v2[2] == 0.0f) ? 0.0f : v1[2] / v2[2]) : v1[1] / v2[1]) : v1[0] / v2[0]);
-
- mul_v3_v3fl(v_tmp, v2, fac);
- sub_v3_v3(v_tmp, v1);
- if (fac != 0.0f && !is_zero_v3(v1) && len_squared_v3(v_tmp) > epsilon_sq) {
- /* Not co-linear, we can compute crossproduct and normalize it into normal. */
- cross_v3_v3v3(r_normal, v1, v2);
- return normalize_v3(r_normal);
- }
- else {
- copy_v3_v3(r_normal, l->f->no);
- return 0.0f;
- }
+ /* Note: we cannot use result of normal_tri_v3 here to detect colinear vectors (vertex on a straight line)
+ * from zero value, because it does not normalize both vectors before making crossproduct.
+ * Instead of adding two costly normalize computations, just check ourselves for colinear case. */
+ /* Note: FEPSILON might need some finer tweaking at some point? Seems to be working OK for now though. */
+ float v1[3], v2[3], v_tmp[3];
+ sub_v3_v3v3(v1, l->prev->v->co, l->v->co);
+ sub_v3_v3v3(v2, l->next->v->co, l->v->co);
+
+ const float fac = ((v2[0] == 0.0f) ?
+ ((v2[1] == 0.0f) ? ((v2[2] == 0.0f) ? 0.0f : v1[2] / v2[2]) :
+ v1[1] / v2[1]) :
+ v1[0] / v2[0]);
+
+ mul_v3_v3fl(v_tmp, v2, fac);
+ sub_v3_v3(v_tmp, v1);
+ if (fac != 0.0f && !is_zero_v3(v1) && len_squared_v3(v_tmp) > epsilon_sq) {
+ /* Not co-linear, we can compute crossproduct and normalize it into normal. */
+ cross_v3_v3v3(r_normal, v1, v2);
+ return normalize_v3(r_normal);
+ }
+ else {
+ copy_v3_v3(r_normal, l->f->no);
+ return 0.0f;
+ }
}
/**
@@ -1568,7 +1540,7 @@ float BM_loop_calc_face_normal_safe_ex(const BMLoop *l, const float epsilon_sq,
*/
float BM_loop_calc_face_normal_safe(const BMLoop *l, float r_normal[3])
{
- return BM_loop_calc_face_normal_safe_ex(l, 1e-5f, r_normal);
+ return BM_loop_calc_face_normal_safe_ex(l, 1e-5f, r_normal);
}
/**
@@ -1582,16 +1554,16 @@ float BM_loop_calc_face_normal_safe(const BMLoop *l, float r_normal[3])
*/
float BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3])
{
- float v1[3], v2[3];
- sub_v3_v3v3(v1, l->prev->v->co, l->v->co);
- sub_v3_v3v3(v2, l->next->v->co, l->v->co);
+ float v1[3], v2[3];
+ sub_v3_v3v3(v1, l->prev->v->co, l->v->co);
+ sub_v3_v3v3(v2, l->next->v->co, l->v->co);
- cross_v3_v3v3(r_normal, v1, v2);
- const float len = normalize_v3(r_normal);
- if (UNLIKELY(len == 0.0f)) {
- copy_v3_v3(r_normal, l->f->no);
- }
- return len;
+ cross_v3_v3v3(r_normal, v1, v2);
+ const float len = normalize_v3(r_normal);
+ if (UNLIKELY(len == 0.0f)) {
+ copy_v3_v3(r_normal, l->f->no);
+ }
+ return len;
}
/**
@@ -1604,17 +1576,17 @@ float BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3])
*/
void BM_loop_calc_face_direction(const BMLoop *l, float r_dir[3])
{
- float v_prev[3];
- float v_next[3];
+ float v_prev[3];
+ float v_next[3];
- sub_v3_v3v3(v_prev, l->v->co, l->prev->v->co);
- sub_v3_v3v3(v_next, l->next->v->co, l->v->co);
+ sub_v3_v3v3(v_prev, l->v->co, l->prev->v->co);
+ sub_v3_v3v3(v_next, l->next->v->co, l->v->co);
- normalize_v3(v_prev);
- normalize_v3(v_next);
+ normalize_v3(v_prev);
+ normalize_v3(v_next);
- add_v3_v3v3(r_dir, v_prev, v_next);
- normalize_v3(r_dir);
+ add_v3_v3v3(r_dir, v_prev, v_next);
+ normalize_v3(r_dir);
}
/**
@@ -1628,32 +1600,32 @@ void BM_loop_calc_face_direction(const BMLoop *l, float r_dir[3])
*/
void BM_loop_calc_face_tangent(const BMLoop *l, float r_tangent[3])
{
- float v_prev[3];
- float v_next[3];
- float dir[3];
+ float v_prev[3];
+ float v_next[3];
+ float dir[3];
- sub_v3_v3v3(v_prev, l->prev->v->co, l->v->co);
- sub_v3_v3v3(v_next, l->v->co, l->next->v->co);
+ sub_v3_v3v3(v_prev, l->prev->v->co, l->v->co);
+ sub_v3_v3v3(v_next, l->v->co, l->next->v->co);
- normalize_v3(v_prev);
- normalize_v3(v_next);
- add_v3_v3v3(dir, v_prev, v_next);
+ normalize_v3(v_prev);
+ normalize_v3(v_next);
+ add_v3_v3v3(dir, v_prev, v_next);
- if (compare_v3v3(v_prev, v_next, FLT_EPSILON * 10.0f) == false) {
- float nor[3]; /* for this purpose doesn't need to be normalized */
- cross_v3_v3v3(nor, v_prev, v_next);
- /* concave face check */
- if (UNLIKELY(dot_v3v3(nor, l->f->no) < 0.0f)) {
- negate_v3(nor);
- }
- cross_v3_v3v3(r_tangent, dir, nor);
- }
- else {
- /* prev/next are the same - compare with face normal since we don't have one */
- cross_v3_v3v3(r_tangent, dir, l->f->no);
- }
+ if (compare_v3v3(v_prev, v_next, FLT_EPSILON * 10.0f) == false) {
+ float nor[3]; /* for this purpose doesn't need to be normalized */
+ cross_v3_v3v3(nor, v_prev, v_next);
+ /* concave face check */
+ if (UNLIKELY(dot_v3v3(nor, l->f->no) < 0.0f)) {
+ negate_v3(nor);
+ }
+ cross_v3_v3v3(r_tangent, dir, nor);
+ }
+ else {
+ /* prev/next are the same - compare with face normal since we don't have one */
+ cross_v3_v3v3(r_tangent, dir, l->f->no);
+ }
- normalize_v3(r_tangent);
+ normalize_v3(r_tangent);
}
/**
@@ -1666,18 +1638,18 @@ void BM_loop_calc_face_tangent(const BMLoop *l, float r_tangent[3])
*/
float BM_edge_calc_face_angle_ex(const BMEdge *e, const float fallback)
{
- if (BM_edge_is_manifold(e)) {
- const BMLoop *l1 = e->l;
- const BMLoop *l2 = e->l->radial_next;
- return angle_normalized_v3v3(l1->f->no, l2->f->no);
- }
- else {
- return fallback;
- }
+ if (BM_edge_is_manifold(e)) {
+ const BMLoop *l1 = e->l;
+ const BMLoop *l2 = e->l->radial_next;
+ return angle_normalized_v3v3(l1->f->no, l2->f->no);
+ }
+ else {
+ return fallback;
+ }
}
float BM_edge_calc_face_angle(const BMEdge *e)
{
- return BM_edge_calc_face_angle_ex(e, DEG2RADF(90.0f));
+ return BM_edge_calc_face_angle_ex(e, DEG2RADF(90.0f));
}
/**
@@ -1688,30 +1660,32 @@ float BM_edge_calc_face_angle(const BMEdge *e)
*
* \return angle in radians
*/
-float BM_edge_calc_face_angle_with_imat3_ex(const BMEdge *e, const float imat3[3][3], const float fallback)
+float BM_edge_calc_face_angle_with_imat3_ex(const BMEdge *e,
+ const float imat3[3][3],
+ const float fallback)
{
- if (BM_edge_is_manifold(e)) {
- const BMLoop *l1 = e->l;
- const BMLoop *l2 = e->l->radial_next;
- float no1[3], no2[3];
- copy_v3_v3(no1, l1->f->no);
- copy_v3_v3(no2, l2->f->no);
+ if (BM_edge_is_manifold(e)) {
+ const BMLoop *l1 = e->l;
+ const BMLoop *l2 = e->l->radial_next;
+ float no1[3], no2[3];
+ copy_v3_v3(no1, l1->f->no);
+ copy_v3_v3(no2, l2->f->no);
- mul_transposed_m3_v3(imat3, no1);
- mul_transposed_m3_v3(imat3, no2);
+ mul_transposed_m3_v3(imat3, no1);
+ mul_transposed_m3_v3(imat3, no2);
- normalize_v3(no1);
- normalize_v3(no2);
+ normalize_v3(no1);
+ normalize_v3(no2);
- return angle_normalized_v3v3(no1, no2);
- }
- else {
- return fallback;
- }
+ return angle_normalized_v3v3(no1, no2);
+ }
+ else {
+ return fallback;
+ }
}
float BM_edge_calc_face_angle_with_imat3(const BMEdge *e, const float imat3[3][3])
{
- return BM_edge_calc_face_angle_with_imat3_ex(e, imat3, DEG2RADF(90.0f));
+ return BM_edge_calc_face_angle_with_imat3_ex(e, imat3, DEG2RADF(90.0f));
}
/**
@@ -1724,19 +1698,19 @@ float BM_edge_calc_face_angle_with_imat3(const BMEdge *e, const float imat3[3][3
*/
float BM_edge_calc_face_angle_signed_ex(const BMEdge *e, const float fallback)
{
- if (BM_edge_is_manifold(e)) {
- BMLoop *l1 = e->l;
- BMLoop *l2 = e->l->radial_next;
- const float angle = angle_normalized_v3v3(l1->f->no, l2->f->no);
- return BM_edge_is_convex(e) ? angle : -angle;
- }
- else {
- return fallback;
- }
+ if (BM_edge_is_manifold(e)) {
+ BMLoop *l1 = e->l;
+ BMLoop *l2 = e->l->radial_next;
+ const float angle = angle_normalized_v3v3(l1->f->no, l2->f->no);
+ return BM_edge_is_convex(e) ? angle : -angle;
+ }
+ else {
+ return fallback;
+ }
}
float BM_edge_calc_face_angle_signed(const BMEdge *e)
{
- return BM_edge_calc_face_angle_signed_ex(e, DEG2RADF(90.0f));
+ return BM_edge_calc_face_angle_signed_ex(e, DEG2RADF(90.0f));
}
/**
@@ -1754,15 +1728,15 @@ float BM_edge_calc_face_angle_signed(const BMEdge *e)
void BM_edge_calc_face_tangent(const BMEdge *e, const BMLoop *e_loop, float r_tangent[3])
{
- float tvec[3];
- BMVert *v1, *v2;
- BM_edge_ordered_verts_ex(e, &v1, &v2, e_loop);
+ float tvec[3];
+ BMVert *v1, *v2;
+ BM_edge_ordered_verts_ex(e, &v1, &v2, e_loop);
- sub_v3_v3v3(tvec, v1->co, v2->co); /* use for temp storage */
- /* note, we could average the tangents of both loops,
- * for non flat ngons it will give a better direction */
- cross_v3_v3v3(r_tangent, tvec, e_loop->f->no);
- normalize_v3(r_tangent);
+ sub_v3_v3v3(tvec, v1->co, v2->co); /* use for temp storage */
+ /* note, we could average the tangents of both loops,
+ * for non flat ngons it will give a better direction */
+ cross_v3_v3v3(r_tangent, tvec, e_loop->f->no);
+ normalize_v3(r_tangent);
}
/**
@@ -1774,30 +1748,27 @@ void BM_edge_calc_face_tangent(const BMEdge *e, const BMLoop *e_loop, float r_ta
*/
float BM_vert_calc_edge_angle_ex(const BMVert *v, const float fallback)
{
- BMEdge *e1, *e2;
+ BMEdge *e1, *e2;
- /* saves BM_vert_edge_count(v) and and edge iterator,
- * get the edges and count them both at once */
+ /* saves BM_vert_edge_count(v) and and edge iterator,
+ * get the edges and count them both at once */
- if ((e1 = v->e) &&
- (e2 = bmesh_disk_edge_next(e1, v)) &&
- (e1 != e2) &&
- /* make sure we come full circle and only have 2 connected edges */
- (e1 == bmesh_disk_edge_next(e2, v)))
- {
- BMVert *v1 = BM_edge_other_vert(e1, v);
- BMVert *v2 = BM_edge_other_vert(e2, v);
+ if ((e1 = v->e) && (e2 = bmesh_disk_edge_next(e1, v)) && (e1 != e2) &&
+ /* make sure we come full circle and only have 2 connected edges */
+ (e1 == bmesh_disk_edge_next(e2, v))) {
+ BMVert *v1 = BM_edge_other_vert(e1, v);
+ BMVert *v2 = BM_edge_other_vert(e2, v);
- return (float)M_PI - angle_v3v3v3(v1->co, v->co, v2->co);
- }
- else {
- return fallback;
- }
+ return (float)M_PI - angle_v3v3v3(v1->co, v->co, v2->co);
+ }
+ else {
+ return fallback;
+ }
}
float BM_vert_calc_edge_angle(const BMVert *v)
{
- return BM_vert_calc_edge_angle_ex(v, DEG2RADF(90.0f));
+ return BM_vert_calc_edge_angle_ex(v, DEG2RADF(90.0f));
}
/**
@@ -1806,57 +1777,57 @@ float BM_vert_calc_edge_angle(const BMVert *v)
*/
float BM_vert_calc_shell_factor(const BMVert *v)
{
- BMIter iter;
- BMLoop *l;
- float accum_shell = 0.0f;
- float accum_angle = 0.0f;
+ BMIter iter;
+ BMLoop *l;
+ float accum_shell = 0.0f;
+ float accum_angle = 0.0f;
- BM_ITER_ELEM (l, &iter, (BMVert *)v, BM_LOOPS_OF_VERT) {
- const float face_angle = BM_loop_calc_face_angle(l);
- accum_shell += shell_v3v3_normalized_to_dist(v->no, l->f->no) * face_angle;
- accum_angle += face_angle;
- }
+ BM_ITER_ELEM (l, &iter, (BMVert *)v, BM_LOOPS_OF_VERT) {
+ const float face_angle = BM_loop_calc_face_angle(l);
+ accum_shell += shell_v3v3_normalized_to_dist(v->no, l->f->no) * face_angle;
+ accum_angle += face_angle;
+ }
- if (accum_angle != 0.0f) {
- return accum_shell / accum_angle;
- }
- else {
- return 1.0f;
- }
+ if (accum_angle != 0.0f) {
+ return accum_shell / accum_angle;
+ }
+ else {
+ return 1.0f;
+ }
}
/* alternate version of #BM_vert_calc_shell_factor which only
* uses 'hflag' faces, but falls back to all if none found. */
float BM_vert_calc_shell_factor_ex(const BMVert *v, const float no[3], const char hflag)
{
- BMIter iter;
- const BMLoop *l;
- float accum_shell = 0.0f;
- float accum_angle = 0.0f;
- int tot_sel = 0, tot = 0;
-
- BM_ITER_ELEM (l, &iter, (BMVert *)v, BM_LOOPS_OF_VERT) {
- if (BM_elem_flag_test(l->f, hflag)) { /* <-- main difference to BM_vert_calc_shell_factor! */
- const float face_angle = BM_loop_calc_face_angle(l);
- accum_shell += shell_v3v3_normalized_to_dist(no, l->f->no) * face_angle;
- accum_angle += face_angle;
- tot_sel++;
- }
- tot++;
- }
-
- if (accum_angle != 0.0f) {
- return accum_shell / accum_angle;
- }
- else {
- /* other main difference from BM_vert_calc_shell_factor! */
- if (tot != 0 && tot_sel == 0) {
- /* none selected, so use all */
- return BM_vert_calc_shell_factor(v);
- }
- else {
- return 1.0f;
- }
- }
+ BMIter iter;
+ const BMLoop *l;
+ float accum_shell = 0.0f;
+ float accum_angle = 0.0f;
+ int tot_sel = 0, tot = 0;
+
+ BM_ITER_ELEM (l, &iter, (BMVert *)v, BM_LOOPS_OF_VERT) {
+ if (BM_elem_flag_test(l->f, hflag)) { /* <-- main difference to BM_vert_calc_shell_factor! */
+ const float face_angle = BM_loop_calc_face_angle(l);
+ accum_shell += shell_v3v3_normalized_to_dist(no, l->f->no) * face_angle;
+ accum_angle += face_angle;
+ tot_sel++;
+ }
+ tot++;
+ }
+
+ if (accum_angle != 0.0f) {
+ return accum_shell / accum_angle;
+ }
+ else {
+ /* other main difference from BM_vert_calc_shell_factor! */
+ if (tot != 0 && tot_sel == 0) {
+ /* none selected, so use all */
+ return BM_vert_calc_shell_factor(v);
+ }
+ else {
+ return 1.0f;
+ }
+ }
}
/**
@@ -1865,49 +1836,49 @@ float BM_vert_calc_shell_factor_ex(const BMVert *v, const float no[3], const cha
*/
float BM_vert_calc_median_tagged_edge_length(const BMVert *v)
{
- BMIter iter;
- BMEdge *e;
- int tot;
- float length = 0.0f;
+ BMIter iter;
+ BMEdge *e;
+ int tot;
+ float length = 0.0f;
- BM_ITER_ELEM_INDEX (e, &iter, (BMVert *)v, BM_EDGES_OF_VERT, tot) {
- const BMVert *v_other = BM_edge_other_vert(e, v);
- if (BM_elem_flag_test(v_other, BM_ELEM_TAG)) {
- length += BM_edge_calc_length(e);
- }
- }
+ BM_ITER_ELEM_INDEX(e, &iter, (BMVert *)v, BM_EDGES_OF_VERT, tot)
+ {
+ const BMVert *v_other = BM_edge_other_vert(e, v);
+ if (BM_elem_flag_test(v_other, BM_ELEM_TAG)) {
+ length += BM_edge_calc_length(e);
+ }
+ }
- if (tot) {
- return length / (float)tot;
- }
- else {
- return 0.0f;
- }
+ if (tot) {
+ return length / (float)tot;
+ }
+ else {
+ return 0.0f;
+ }
}
-
/**
* Returns the loop of the shortest edge in f.
*/
BMLoop *BM_face_find_shortest_loop(BMFace *f)
{
- BMLoop *shortest_loop = NULL;
- float shortest_len = FLT_MAX;
+ BMLoop *shortest_loop = NULL;
+ float shortest_len = FLT_MAX;
- BMLoop *l_iter;
- BMLoop *l_first;
+ BMLoop *l_iter;
+ BMLoop *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- const float len_sq = len_squared_v3v3(l_iter->v->co, l_iter->next->v->co);
- if (len_sq <= shortest_len) {
- shortest_loop = l_iter;
- shortest_len = len_sq;
- }
- } while ((l_iter = l_iter->next) != l_first);
+ do {
+ const float len_sq = len_squared_v3v3(l_iter->v->co, l_iter->next->v->co);
+ if (len_sq <= shortest_len) {
+ shortest_loop = l_iter;
+ shortest_len = len_sq;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
- return shortest_loop;
+ return shortest_loop;
}
/**
@@ -1915,23 +1886,23 @@ BMLoop *BM_face_find_shortest_loop(BMFace *f)
*/
BMLoop *BM_face_find_longest_loop(BMFace *f)
{
- BMLoop *longest_loop = NULL;
- float len_max_sq = 0.0f;
+ BMLoop *longest_loop = NULL;
+ float len_max_sq = 0.0f;
- BMLoop *l_iter;
- BMLoop *l_first;
+ BMLoop *l_iter;
+ BMLoop *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- const float len_sq = len_squared_v3v3(l_iter->v->co, l_iter->next->v->co);
- if (len_sq >= len_max_sq) {
- longest_loop = l_iter;
- len_max_sq = len_sq;
- }
- } while ((l_iter = l_iter->next) != l_first);
+ do {
+ const float len_sq = len_squared_v3v3(l_iter->v->co, l_iter->next->v->co);
+ if (len_sq >= len_max_sq) {
+ longest_loop = l_iter;
+ len_max_sq = len_sq;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
- return longest_loop;
+ return longest_loop;
}
/**
@@ -1943,46 +1914,46 @@ BMLoop *BM_face_find_longest_loop(BMFace *f)
#if 0
BMEdge *BM_edge_exists(BMVert *v_a, BMVert *v_b)
{
- BMIter iter;
- BMEdge *e;
+ BMIter iter;
+ BMEdge *e;
- BLI_assert(v_a != v_b);
- BLI_assert(v_a->head.htype == BM_VERT && v_b->head.htype == BM_VERT);
+ BLI_assert(v_a != v_b);
+ BLI_assert(v_a->head.htype == BM_VERT && v_b->head.htype == BM_VERT);
- BM_ITER_ELEM (e, &iter, v_a, BM_EDGES_OF_VERT) {
- if (e->v1 == v_b || e->v2 == v_b)
- return e;
- }
+ BM_ITER_ELEM (e, &iter, v_a, BM_EDGES_OF_VERT) {
+ if (e->v1 == v_b || e->v2 == v_b)
+ return e;
+ }
- return NULL;
+ return NULL;
}
#else
BMEdge *BM_edge_exists(BMVert *v_a, BMVert *v_b)
{
- /* speedup by looping over both edges verts
- * where one vert may connect to many edges but not the other. */
+ /* speedup by looping over both edges verts
+ * where one vert may connect to many edges but not the other. */
- BMEdge *e_a, *e_b;
+ BMEdge *e_a, *e_b;
- BLI_assert(v_a != v_b);
- BLI_assert(v_a->head.htype == BM_VERT && v_b->head.htype == BM_VERT);
+ BLI_assert(v_a != v_b);
+ BLI_assert(v_a->head.htype == BM_VERT && v_b->head.htype == BM_VERT);
- if ((e_a = v_a->e) && (e_b = v_b->e)) {
- BMEdge *e_a_iter = e_a, *e_b_iter = e_b;
+ if ((e_a = v_a->e) && (e_b = v_b->e)) {
+ BMEdge *e_a_iter = e_a, *e_b_iter = e_b;
- do {
- if (BM_vert_in_edge(e_a_iter, v_b)) {
- return e_a_iter;
- }
- if (BM_vert_in_edge(e_b_iter, v_a)) {
- return e_b_iter;
- }
- } while (((e_a_iter = bmesh_disk_edge_next(e_a_iter, v_a)) != e_a) &&
- ((e_b_iter = bmesh_disk_edge_next(e_b_iter, v_b)) != e_b));
- }
+ do {
+ if (BM_vert_in_edge(e_a_iter, v_b)) {
+ return e_a_iter;
+ }
+ if (BM_vert_in_edge(e_b_iter, v_a)) {
+ return e_b_iter;
+ }
+ } while (((e_a_iter = bmesh_disk_edge_next(e_a_iter, v_a)) != e_a) &&
+ ((e_b_iter = bmesh_disk_edge_next(e_b_iter, v_b)) != e_b));
+ }
- return NULL;
+ return NULL;
}
#endif
@@ -1993,19 +1964,19 @@ BMEdge *BM_edge_exists(BMVert *v_a, BMVert *v_b)
*/
BMEdge *BM_edge_find_double(BMEdge *e)
{
- BMVert *v = e->v1;
- BMVert *v_other = e->v2;
+ BMVert *v = e->v1;
+ BMVert *v_other = e->v2;
- BMEdge *e_iter;
+ BMEdge *e_iter;
- e_iter = e;
- while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e) {
- if (UNLIKELY(BM_vert_in_edge(e_iter, v_other))) {
- return e_iter;
- }
- }
+ e_iter = e;
+ while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e) {
+ if (UNLIKELY(BM_vert_in_edge(e_iter, v_other))) {
+ return e_iter;
+ }
+ }
- return NULL;
+ return NULL;
}
/**
@@ -2014,16 +1985,16 @@ BMEdge *BM_edge_find_double(BMEdge *e)
*/
BMLoop *BM_edge_find_first_loop_visible(BMEdge *e)
{
- if (e->l != NULL) {
- BMLoop *l_iter, *l_first;
- l_iter = l_first = e->l;
- do {
- if (!BM_elem_flag_test(l_iter->f, BM_ELEM_HIDDEN)) {
- return l_iter;
- }
- } while ((l_iter = l_iter->radial_next) != l_first);
- }
- return NULL;
+ if (e->l != NULL) {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = e->l;
+ do {
+ if (!BM_elem_flag_test(l_iter->f, BM_ELEM_HIDDEN)) {
+ return l_iter;
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+ return NULL;
}
/**
@@ -2035,53 +2006,50 @@ BMLoop *BM_edge_find_first_loop_visible(BMEdge *e)
*/
BMFace *BM_face_exists(BMVert **varr, int len)
{
- if (varr[0]->e) {
- BMEdge *e_iter, *e_first;
- e_iter = e_first = varr[0]->e;
-
- /* would normally use BM_LOOPS_OF_VERT, but this runs so often,
- * its faster to iterate on the data directly */
- do {
- if (e_iter->l) {
- BMLoop *l_iter_radial, *l_first_radial;
- l_iter_radial = l_first_radial = e_iter->l;
-
- do {
- if ((l_iter_radial->v == varr[0]) &&
- (l_iter_radial->f->len == len))
- {
- /* the fist 2 verts match, now check the remaining (len - 2) faces do too
- * winding isn't known, so check in both directions */
- int i_walk = 2;
-
- if (l_iter_radial->next->v == varr[1]) {
- BMLoop *l_walk = l_iter_radial->next->next;
- do {
- if (l_walk->v != varr[i_walk]) {
- break;
- }
- } while ((void)(l_walk = l_walk->next), ++i_walk != len);
- }
- else if (l_iter_radial->prev->v == varr[1]) {
- BMLoop *l_walk = l_iter_radial->prev->prev;
- do {
- if (l_walk->v != varr[i_walk]) {
- break;
- }
- } while ((void)(l_walk = l_walk->prev), ++i_walk != len);
- }
-
- if (i_walk == len) {
- return l_iter_radial->f;
- }
- }
- } while ((l_iter_radial = l_iter_radial->radial_next) != l_first_radial);
-
- }
- } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, varr[0])) != e_first);
- }
-
- return NULL;
+ if (varr[0]->e) {
+ BMEdge *e_iter, *e_first;
+ e_iter = e_first = varr[0]->e;
+
+ /* would normally use BM_LOOPS_OF_VERT, but this runs so often,
+ * its faster to iterate on the data directly */
+ do {
+ if (e_iter->l) {
+ BMLoop *l_iter_radial, *l_first_radial;
+ l_iter_radial = l_first_radial = e_iter->l;
+
+ do {
+ if ((l_iter_radial->v == varr[0]) && (l_iter_radial->f->len == len)) {
+ /* the fist 2 verts match, now check the remaining (len - 2) faces do too
+ * winding isn't known, so check in both directions */
+ int i_walk = 2;
+
+ if (l_iter_radial->next->v == varr[1]) {
+ BMLoop *l_walk = l_iter_radial->next->next;
+ do {
+ if (l_walk->v != varr[i_walk]) {
+ break;
+ }
+ } while ((void)(l_walk = l_walk->next), ++i_walk != len);
+ }
+ else if (l_iter_radial->prev->v == varr[1]) {
+ BMLoop *l_walk = l_iter_radial->prev->prev;
+ do {
+ if (l_walk->v != varr[i_walk]) {
+ break;
+ }
+ } while ((void)(l_walk = l_walk->prev), ++i_walk != len);
+ }
+
+ if (i_walk == len) {
+ return l_iter_radial->f;
+ }
+ }
+ } while ((l_iter_radial = l_iter_radial->radial_next) != l_first_radial);
+ }
+ } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, varr[0])) != e_first);
+ }
+
+ return NULL;
}
/**
@@ -2089,34 +2057,34 @@ BMFace *BM_face_exists(BMVert **varr, int len)
*/
BMFace *BM_face_find_double(BMFace *f)
{
- BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
- for (BMLoop *l_iter = l_first->radial_next; l_first != l_iter; l_iter = l_iter->radial_next) {
- if (l_iter->f->len == l_first->f->len) {
- if (l_iter->v == l_first->v) {
- BMLoop *l_a = l_first, *l_b = l_iter, *l_b_init = l_iter;
- do {
- if (l_a->e != l_b->e) {
- break;
- }
- } while (((void)(l_a = l_a->next), (l_b = l_b->next)) != l_b_init);
- if (l_b == l_b_init) {
- return l_iter->f;
- }
- }
- else {
- BMLoop *l_a = l_first, *l_b = l_iter, *l_b_init = l_iter;
- do {
- if (l_a->e != l_b->e) {
- break;
- }
- } while (((void)(l_a = l_a->prev), (l_b = l_b->next)) != l_b_init);
- if (l_b == l_b_init) {
- return l_iter->f;
- }
- }
- }
- }
- return NULL;
+ BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
+ for (BMLoop *l_iter = l_first->radial_next; l_first != l_iter; l_iter = l_iter->radial_next) {
+ if (l_iter->f->len == l_first->f->len) {
+ if (l_iter->v == l_first->v) {
+ BMLoop *l_a = l_first, *l_b = l_iter, *l_b_init = l_iter;
+ do {
+ if (l_a->e != l_b->e) {
+ break;
+ }
+ } while (((void)(l_a = l_a->next), (l_b = l_b->next)) != l_b_init);
+ if (l_b == l_b_init) {
+ return l_iter->f;
+ }
+ }
+ else {
+ BMLoop *l_a = l_first, *l_b = l_iter, *l_b_init = l_iter;
+ do {
+ if (l_a->e != l_b->e) {
+ break;
+ }
+ } while (((void)(l_a = l_a->prev), (l_b = l_b->next)) != l_b_init);
+ if (l_b == l_b_init) {
+ return l_iter->f;
+ }
+ }
+ }
+ }
+ return NULL;
}
/**
@@ -2133,131 +2101,126 @@ BMFace *BM_face_find_double(BMFace *f)
*/
bool BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len)
{
- BMFace *f;
- BMEdge *e;
- BMVert *v;
- bool ok;
- int tot_tag;
-
- BMIter fiter;
- BMIter viter;
-
- int i;
-
- for (i = 0; i < len; i++) {
- /* save some time by looping over edge faces rather then vert faces
- * will still loop over some faces twice but not as many */
- BM_ITER_ELEM (f, &fiter, earr[i], BM_FACES_OF_EDGE) {
- BM_elem_flag_disable(f, BM_ELEM_INTERNAL_TAG);
- BM_ITER_ELEM (v, &viter, f, BM_VERTS_OF_FACE) {
- BM_elem_flag_disable(v, BM_ELEM_INTERNAL_TAG);
- }
- }
-
- /* clear all edge tags */
- BM_ITER_ELEM (e, &fiter, varr[i], BM_EDGES_OF_VERT) {
- BM_elem_flag_disable(e, BM_ELEM_INTERNAL_TAG);
- }
- }
-
- /* now tag all verts and edges in the boundary array as true so
- * we can know if a face-vert is from our array */
- for (i = 0; i < len; i++) {
- BM_elem_flag_enable(varr[i], BM_ELEM_INTERNAL_TAG);
- BM_elem_flag_enable(earr[i], BM_ELEM_INTERNAL_TAG);
- }
-
-
- /* so! boundary is tagged, everything else cleared */
-
-
- /* 1) tag all faces connected to edges - if all their verts are boundary */
- tot_tag = 0;
- for (i = 0; i < len; i++) {
- BM_ITER_ELEM (f, &fiter, earr[i], BM_FACES_OF_EDGE) {
- if (!BM_elem_flag_test(f, BM_ELEM_INTERNAL_TAG)) {
- ok = true;
- BM_ITER_ELEM (v, &viter, f, BM_VERTS_OF_FACE) {
- if (!BM_elem_flag_test(v, BM_ELEM_INTERNAL_TAG)) {
- ok = false;
- break;
- }
- }
-
- if (ok) {
- /* we only use boundary verts */
- BM_elem_flag_enable(f, BM_ELEM_INTERNAL_TAG);
- tot_tag++;
- }
- }
- else {
- /* we already found! */
- }
- }
- }
-
- if (tot_tag == 0) {
- /* no faces use only boundary verts, quit early */
- ok = false;
- goto finally;
- }
-
- /* 2) loop over non-boundary edges that use boundary verts,
- * check each have 2 tagged faces connected (faces that only use 'varr' verts) */
- ok = true;
- for (i = 0; i < len; i++) {
- BM_ITER_ELEM (e, &fiter, varr[i], BM_EDGES_OF_VERT) {
-
- if (/* non-boundary edge */
- BM_elem_flag_test(e, BM_ELEM_INTERNAL_TAG) == false &&
- /* ...using boundary verts */
- BM_elem_flag_test(e->v1, BM_ELEM_INTERNAL_TAG) &&
- BM_elem_flag_test(e->v2, BM_ELEM_INTERNAL_TAG))
- {
- int tot_face_tag = 0;
- BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) {
- if (BM_elem_flag_test(f, BM_ELEM_INTERNAL_TAG)) {
- tot_face_tag++;
- }
- }
-
- if (tot_face_tag != 2) {
- ok = false;
- break;
- }
-
- }
- }
-
- if (ok == false) {
- break;
- }
- }
+ BMFace *f;
+ BMEdge *e;
+ BMVert *v;
+ bool ok;
+ int tot_tag;
+
+ BMIter fiter;
+ BMIter viter;
+
+ int i;
+
+ for (i = 0; i < len; i++) {
+ /* save some time by looping over edge faces rather then vert faces
+ * will still loop over some faces twice but not as many */
+ BM_ITER_ELEM (f, &fiter, earr[i], BM_FACES_OF_EDGE) {
+ BM_elem_flag_disable(f, BM_ELEM_INTERNAL_TAG);
+ BM_ITER_ELEM (v, &viter, f, BM_VERTS_OF_FACE) {
+ BM_elem_flag_disable(v, BM_ELEM_INTERNAL_TAG);
+ }
+ }
+
+ /* clear all edge tags */
+ BM_ITER_ELEM (e, &fiter, varr[i], BM_EDGES_OF_VERT) {
+ BM_elem_flag_disable(e, BM_ELEM_INTERNAL_TAG);
+ }
+ }
+
+ /* now tag all verts and edges in the boundary array as true so
+ * we can know if a face-vert is from our array */
+ for (i = 0; i < len; i++) {
+ BM_elem_flag_enable(varr[i], BM_ELEM_INTERNAL_TAG);
+ BM_elem_flag_enable(earr[i], BM_ELEM_INTERNAL_TAG);
+ }
+
+ /* so! boundary is tagged, everything else cleared */
+
+ /* 1) tag all faces connected to edges - if all their verts are boundary */
+ tot_tag = 0;
+ for (i = 0; i < len; i++) {
+ BM_ITER_ELEM (f, &fiter, earr[i], BM_FACES_OF_EDGE) {
+ if (!BM_elem_flag_test(f, BM_ELEM_INTERNAL_TAG)) {
+ ok = true;
+ BM_ITER_ELEM (v, &viter, f, BM_VERTS_OF_FACE) {
+ if (!BM_elem_flag_test(v, BM_ELEM_INTERNAL_TAG)) {
+ ok = false;
+ break;
+ }
+ }
+
+ if (ok) {
+ /* we only use boundary verts */
+ BM_elem_flag_enable(f, BM_ELEM_INTERNAL_TAG);
+ tot_tag++;
+ }
+ }
+ else {
+ /* we already found! */
+ }
+ }
+ }
+
+ if (tot_tag == 0) {
+ /* no faces use only boundary verts, quit early */
+ ok = false;
+ goto finally;
+ }
+
+ /* 2) loop over non-boundary edges that use boundary verts,
+ * check each have 2 tagged faces connected (faces that only use 'varr' verts) */
+ ok = true;
+ for (i = 0; i < len; i++) {
+ BM_ITER_ELEM (e, &fiter, varr[i], BM_EDGES_OF_VERT) {
+
+ if (/* non-boundary edge */
+ BM_elem_flag_test(e, BM_ELEM_INTERNAL_TAG) == false &&
+ /* ...using boundary verts */
+ BM_elem_flag_test(e->v1, BM_ELEM_INTERNAL_TAG) &&
+ BM_elem_flag_test(e->v2, BM_ELEM_INTERNAL_TAG)) {
+ int tot_face_tag = 0;
+ BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) {
+ if (BM_elem_flag_test(f, BM_ELEM_INTERNAL_TAG)) {
+ tot_face_tag++;
+ }
+ }
+
+ if (tot_face_tag != 2) {
+ ok = false;
+ break;
+ }
+ }
+ }
+
+ if (ok == false) {
+ break;
+ }
+ }
finally:
- /* Cleanup */
- for (i = 0; i < len; i++) {
- BM_elem_flag_disable(varr[i], BM_ELEM_INTERNAL_TAG);
- BM_elem_flag_disable(earr[i], BM_ELEM_INTERNAL_TAG);
- }
- return ok;
+ /* Cleanup */
+ for (i = 0; i < len; i++) {
+ BM_elem_flag_disable(varr[i], BM_ELEM_INTERNAL_TAG);
+ BM_elem_flag_disable(earr[i], BM_ELEM_INTERNAL_TAG);
+ }
+ return ok;
}
/* same as 'BM_face_exists_multi' but built vert array from edges */
bool BM_face_exists_multi_edge(BMEdge **earr, int len)
{
- BMVert **varr = BLI_array_alloca(varr, len);
+ BMVert **varr = BLI_array_alloca(varr, len);
- /* first check if verts have edges, if not we can bail out early */
- if (!BM_verts_from_edges(varr, earr, len)) {
- BMESH_ASSERT(0);
- return false;
- }
+ /* first check if verts have edges, if not we can bail out early */
+ if (!BM_verts_from_edges(varr, earr, len)) {
+ BMESH_ASSERT(0);
+ return false;
+ }
- return BM_face_exists_multi(varr, earr, len);
+ return BM_face_exists_multi(varr, earr, len);
}
-
/**
* Given a set of vertices (varr), find out if
* all those vertices overlap an existing face.
@@ -2274,40 +2237,40 @@ bool BM_face_exists_multi_edge(BMEdge **earr, int len)
BMFace *BM_face_exists_overlap(BMVert **varr, const int len)
{
- BMIter viter;
- BMFace *f;
- int i;
- BMFace *f_overlap = NULL;
- LinkNode *f_lnk = NULL;
+ BMIter viter;
+ BMFace *f;
+ int i;
+ BMFace *f_overlap = NULL;
+ LinkNode *f_lnk = NULL;
#ifdef DEBUG
- /* check flag isn't already set */
- for (i = 0; i < len; i++) {
- BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) {
- BLI_assert(BM_ELEM_API_FLAG_TEST(f, _FLAG_OVERLAP) == 0);
- }
- }
+ /* check flag isn't already set */
+ for (i = 0; i < len; i++) {
+ BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) {
+ BLI_assert(BM_ELEM_API_FLAG_TEST(f, _FLAG_OVERLAP) == 0);
+ }
+ }
#endif
- for (i = 0; i < len; i++) {
- BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) {
- if (BM_ELEM_API_FLAG_TEST(f, _FLAG_OVERLAP) == 0) {
- if (len <= BM_verts_in_face_count(varr, len, f)) {
- f_overlap = f;
- break;
- }
+ for (i = 0; i < len; i++) {
+ BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) {
+ if (BM_ELEM_API_FLAG_TEST(f, _FLAG_OVERLAP) == 0) {
+ if (len <= BM_verts_in_face_count(varr, len, f)) {
+ f_overlap = f;
+ break;
+ }
- BM_ELEM_API_FLAG_ENABLE(f, _FLAG_OVERLAP);
- BLI_linklist_prepend_alloca(&f_lnk, f);
- }
- }
- }
+ BM_ELEM_API_FLAG_ENABLE(f, _FLAG_OVERLAP);
+ BLI_linklist_prepend_alloca(&f_lnk, f);
+ }
+ }
+ }
- for (; f_lnk; f_lnk = f_lnk->next) {
- BM_ELEM_API_FLAG_DISABLE((BMFace *)f_lnk->link, _FLAG_OVERLAP);
- }
+ for (; f_lnk; f_lnk = f_lnk->next) {
+ BM_ELEM_API_FLAG_DISABLE((BMFace *)f_lnk->link, _FLAG_OVERLAP);
+ }
- return f_overlap;
+ return f_overlap;
}
/**
@@ -2320,155 +2283,153 @@ BMFace *BM_face_exists_overlap(BMVert **varr, const int len)
*/
bool BM_face_exists_overlap_subset(BMVert **varr, const int len)
{
- BMIter viter;
- BMFace *f;
- bool is_init = false;
- bool is_overlap = false;
- LinkNode *f_lnk = NULL;
+ BMIter viter;
+ BMFace *f;
+ bool is_init = false;
+ bool is_overlap = false;
+ LinkNode *f_lnk = NULL;
#ifdef DEBUG
- /* check flag isn't already set */
- for (int i = 0; i < len; i++) {
- BLI_assert(BM_ELEM_API_FLAG_TEST(varr[i], _FLAG_OVERLAP) == 0);
- BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) {
- BLI_assert(BM_ELEM_API_FLAG_TEST(f, _FLAG_OVERLAP) == 0);
- }
- }
+ /* check flag isn't already set */
+ for (int i = 0; i < len; i++) {
+ BLI_assert(BM_ELEM_API_FLAG_TEST(varr[i], _FLAG_OVERLAP) == 0);
+ BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) {
+ BLI_assert(BM_ELEM_API_FLAG_TEST(f, _FLAG_OVERLAP) == 0);
+ }
+ }
#endif
- for (int i = 0; i < len; i++) {
- BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) {
- if ((f->len <= len) && (BM_ELEM_API_FLAG_TEST(f, _FLAG_OVERLAP) == 0)) {
- /* check if all vers in this face are flagged*/
- BMLoop *l_iter, *l_first;
-
- if (is_init == false) {
- is_init = true;
- for (int j = 0; j < len; j++) {
- BM_ELEM_API_FLAG_ENABLE(varr[j], _FLAG_OVERLAP);
- }
- }
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- is_overlap = true;
- do {
- if (BM_ELEM_API_FLAG_TEST(l_iter->v, _FLAG_OVERLAP) == 0) {
- is_overlap = false;
- break;
- }
- } while ((l_iter = l_iter->next) != l_first);
-
- if (is_overlap) {
- break;
- }
-
- BM_ELEM_API_FLAG_ENABLE(f, _FLAG_OVERLAP);
- BLI_linklist_prepend_alloca(&f_lnk, f);
- }
- }
- }
-
- if (is_init == true) {
- for (int i = 0; i < len; i++) {
- BM_ELEM_API_FLAG_DISABLE(varr[i], _FLAG_OVERLAP);
- }
- }
-
- for (; f_lnk; f_lnk = f_lnk->next) {
- BM_ELEM_API_FLAG_DISABLE((BMFace *)f_lnk->link, _FLAG_OVERLAP);
- }
-
- return is_overlap;
+ for (int i = 0; i < len; i++) {
+ BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) {
+ if ((f->len <= len) && (BM_ELEM_API_FLAG_TEST(f, _FLAG_OVERLAP) == 0)) {
+ /* check if all vers in this face are flagged*/
+ BMLoop *l_iter, *l_first;
+
+ if (is_init == false) {
+ is_init = true;
+ for (int j = 0; j < len; j++) {
+ BM_ELEM_API_FLAG_ENABLE(varr[j], _FLAG_OVERLAP);
+ }
+ }
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ is_overlap = true;
+ do {
+ if (BM_ELEM_API_FLAG_TEST(l_iter->v, _FLAG_OVERLAP) == 0) {
+ is_overlap = false;
+ break;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+
+ if (is_overlap) {
+ break;
+ }
+
+ BM_ELEM_API_FLAG_ENABLE(f, _FLAG_OVERLAP);
+ BLI_linklist_prepend_alloca(&f_lnk, f);
+ }
+ }
+ }
+
+ if (is_init == true) {
+ for (int i = 0; i < len; i++) {
+ BM_ELEM_API_FLAG_DISABLE(varr[i], _FLAG_OVERLAP);
+ }
+ }
+
+ for (; f_lnk; f_lnk = f_lnk->next) {
+ BM_ELEM_API_FLAG_DISABLE((BMFace *)f_lnk->link, _FLAG_OVERLAP);
+ }
+
+ return is_overlap;
}
bool BM_vert_is_all_edge_flag_test(const BMVert *v, const char hflag, const bool respect_hide)
{
- if (v->e) {
- BMEdge *e_other;
- BMIter eiter;
+ if (v->e) {
+ BMEdge *e_other;
+ BMIter eiter;
- BM_ITER_ELEM (e_other, &eiter, (BMVert *)v, BM_EDGES_OF_VERT) {
- if (!respect_hide || !BM_elem_flag_test(e_other, BM_ELEM_HIDDEN)) {
- if (!BM_elem_flag_test(e_other, hflag)) {
- return false;
- }
- }
- }
- }
+ BM_ITER_ELEM (e_other, &eiter, (BMVert *)v, BM_EDGES_OF_VERT) {
+ if (!respect_hide || !BM_elem_flag_test(e_other, BM_ELEM_HIDDEN)) {
+ if (!BM_elem_flag_test(e_other, hflag)) {
+ return false;
+ }
+ }
+ }
+ }
- return true;
+ return true;
}
bool BM_vert_is_all_face_flag_test(const BMVert *v, const char hflag, const bool respect_hide)
{
- if (v->e) {
- BMEdge *f_other;
- BMIter fiter;
+ if (v->e) {
+ BMEdge *f_other;
+ BMIter fiter;
- BM_ITER_ELEM (f_other, &fiter, (BMVert *)v, BM_FACES_OF_VERT) {
- if (!respect_hide || !BM_elem_flag_test(f_other, BM_ELEM_HIDDEN)) {
- if (!BM_elem_flag_test(f_other, hflag)) {
- return false;
- }
- }
- }
- }
+ BM_ITER_ELEM (f_other, &fiter, (BMVert *)v, BM_FACES_OF_VERT) {
+ if (!respect_hide || !BM_elem_flag_test(f_other, BM_ELEM_HIDDEN)) {
+ if (!BM_elem_flag_test(f_other, hflag)) {
+ return false;
+ }
+ }
+ }
+ }
- return true;
+ return true;
}
-
bool BM_edge_is_all_face_flag_test(const BMEdge *e, const char hflag, const bool respect_hide)
{
- if (e->l) {
- BMLoop *l_iter, *l_first;
+ if (e->l) {
+ BMLoop *l_iter, *l_first;
- l_iter = l_first = e->l;
- do {
- if (!respect_hide || !BM_elem_flag_test(l_iter->f, BM_ELEM_HIDDEN)) {
- if (!BM_elem_flag_test(l_iter->f, hflag)) {
- return false;
- }
- }
- } while ((l_iter = l_iter->radial_next) != l_first);
- }
+ l_iter = l_first = e->l;
+ do {
+ if (!respect_hide || !BM_elem_flag_test(l_iter->f, BM_ELEM_HIDDEN)) {
+ if (!BM_elem_flag_test(l_iter->f, hflag)) {
+ return false;
+ }
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
- return true;
+ return true;
}
/* convenience functions for checking flags */
bool BM_edge_is_any_vert_flag_test(const BMEdge *e, const char hflag)
{
- return (BM_elem_flag_test(e->v1, hflag) ||
- BM_elem_flag_test(e->v2, hflag));
+ return (BM_elem_flag_test(e->v1, hflag) || BM_elem_flag_test(e->v2, hflag));
}
bool BM_face_is_any_vert_flag_test(const BMFace *f, const char hflag)
{
- BMLoop *l_iter;
- BMLoop *l_first;
+ BMLoop *l_iter;
+ BMLoop *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if (BM_elem_flag_test(l_iter->v, hflag)) {
- return true;
- }
- } while ((l_iter = l_iter->next) != l_first);
- return false;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (BM_elem_flag_test(l_iter->v, hflag)) {
+ return true;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ return false;
}
bool BM_face_is_any_edge_flag_test(const BMFace *f, const char hflag)
{
- BMLoop *l_iter;
- BMLoop *l_first;
+ BMLoop *l_iter;
+ BMLoop *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if (BM_elem_flag_test(l_iter->e, hflag)) {
- return true;
- }
- } while ((l_iter = l_iter->next) != l_first);
- return false;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (BM_elem_flag_test(l_iter->e, hflag)) {
+ return true;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ return false;
}
/**
@@ -2476,49 +2437,49 @@ bool BM_face_is_any_edge_flag_test(const BMFace *f, const char hflag)
*/
bool BM_face_is_normal_valid(const BMFace *f)
{
- const float eps = 0.0001f;
- float no[3];
+ const float eps = 0.0001f;
+ float no[3];
- BM_face_calc_normal(f, no);
- return len_squared_v3v3(no, f->no) < (eps * eps);
+ BM_face_calc_normal(f, no);
+ return len_squared_v3v3(no, f->no) < (eps * eps);
}
static void bm_mesh_calc_volume_face(const BMFace *f, float *r_vol)
{
- const int tottri = f->len - 2;
- BMLoop **loops = BLI_array_alloca(loops, f->len);
- uint (*index)[3] = BLI_array_alloca(index, tottri);
- int j;
+ const int tottri = f->len - 2;
+ BMLoop **loops = BLI_array_alloca(loops, f->len);
+ uint(*index)[3] = BLI_array_alloca(index, tottri);
+ int j;
- BM_face_calc_tessellation(f, false, loops, index);
+ BM_face_calc_tessellation(f, false, loops, index);
- for (j = 0; j < tottri; j++) {
- const float *p1 = loops[index[j][0]]->v->co;
- const float *p2 = loops[index[j][1]]->v->co;
- const float *p3 = loops[index[j][2]]->v->co;
+ for (j = 0; j < tottri; j++) {
+ const float *p1 = loops[index[j][0]]->v->co;
+ const float *p2 = loops[index[j][1]]->v->co;
+ const float *p3 = loops[index[j][2]]->v->co;
- /* co1.dot(co2.cross(co3)) / 6.0 */
- float cross[3];
- cross_v3_v3v3(cross, p2, p3);
- *r_vol += (1.0f / 6.0f) * dot_v3v3(p1, cross);
- }
+ /* co1.dot(co2.cross(co3)) / 6.0 */
+ float cross[3];
+ cross_v3_v3v3(cross, p2, p3);
+ *r_vol += (1.0f / 6.0f) * dot_v3v3(p1, cross);
+ }
}
float BM_mesh_calc_volume(BMesh *bm, bool is_signed)
{
- /* warning, calls own tessellation function, may be slow */
- float vol = 0.0f;
- BMFace *f;
- BMIter fiter;
+ /* warning, calls own tessellation function, may be slow */
+ float vol = 0.0f;
+ BMFace *f;
+ BMIter fiter;
- BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
- bm_mesh_calc_volume_face(f, &vol);
- }
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ bm_mesh_calc_volume_face(f, &vol);
+ }
- if (is_signed == false) {
- vol = fabsf(vol);
- }
+ if (is_signed == false) {
+ vol = fabsf(vol);
+ }
- return vol;
+ return vol;
}
/* note, almost duplicate of BM_mesh_calc_edge_groups, keep in sync */
@@ -2538,143 +2499,144 @@ float BM_mesh_calc_volume(BMesh *bm, bool is_signed)
* (having both set is supported too).
* \return The number of groups found.
*/
-int BM_mesh_calc_face_groups(
- BMesh *bm, int *r_groups_array, int (**r_group_index)[2],
- BMLoopFilterFunc filter_fn, void *user_data,
- const char hflag_test, const char htype_step)
+int BM_mesh_calc_face_groups(BMesh *bm,
+ int *r_groups_array,
+ int (**r_group_index)[2],
+ BMLoopFilterFunc filter_fn,
+ void *user_data,
+ const char hflag_test,
+ const char htype_step)
{
#ifdef DEBUG
- int group_index_len = 1;
+ int group_index_len = 1;
#else
- int group_index_len = 32;
+ int group_index_len = 32;
#endif
- int (*group_index)[2] = MEM_mallocN(sizeof(*group_index) * group_index_len, __func__);
-
- int *group_array = r_groups_array;
- STACK_DECLARE(group_array);
-
- int group_curr = 0;
-
- uint tot_faces = 0;
- uint tot_touch = 0;
-
- BMFace **stack;
- STACK_DECLARE(stack);
-
- BMIter iter;
- BMFace *f;
- int i;
-
- STACK_INIT(group_array, bm->totface);
-
- BLI_assert(((htype_step & ~(BM_VERT | BM_EDGE)) == 0) && (htype_step != 0));
-
- /* init the array */
- BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) {
- if ((hflag_test == 0) || BM_elem_flag_test(f, hflag_test)) {
- tot_faces++;
- BM_elem_flag_disable(f, BM_ELEM_TAG);
- }
- else {
- /* never walk over tagged */
- BM_elem_flag_enable(f, BM_ELEM_TAG);
- }
-
- BM_elem_index_set(f, i); /* set_inline */
- }
- bm->elem_index_dirty &= ~BM_FACE;
-
- /* detect groups */
- stack = MEM_mallocN(sizeof(*stack) * tot_faces, __func__);
-
- while (tot_touch != tot_faces) {
- int *group_item;
- bool ok = false;
-
- BLI_assert(tot_touch < tot_faces);
-
- STACK_INIT(stack, tot_faces);
-
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(f, BM_ELEM_TAG) == false) {
- BM_elem_flag_enable(f, BM_ELEM_TAG);
- STACK_PUSH(stack, f);
- ok = true;
- break;
- }
- }
-
- BLI_assert(ok == true);
- UNUSED_VARS_NDEBUG(ok);
-
- /* manage arrays */
- if (group_index_len == group_curr) {
- group_index_len *= 2;
- group_index = MEM_reallocN(group_index, sizeof(*group_index) * group_index_len);
- }
-
- group_item = group_index[group_curr];
- group_item[0] = STACK_SIZE(group_array);
- group_item[1] = 0;
-
- while ((f = STACK_POP(stack))) {
- BMLoop *l_iter, *l_first;
-
- /* add face */
- STACK_PUSH(group_array, BM_elem_index_get(f));
- tot_touch++;
- group_item[1]++;
- /* done */
-
- if (htype_step & BM_EDGE) {
- /* search for other faces */
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- BMLoop *l_radial_iter = l_iter->radial_next;
- if ((l_radial_iter != l_iter) &&
- ((filter_fn == NULL) || filter_fn(l_iter, user_data)))
- {
- do {
- BMFace *f_other = l_radial_iter->f;
- if (BM_elem_flag_test(f_other, BM_ELEM_TAG) == false) {
- BM_elem_flag_enable(f_other, BM_ELEM_TAG);
- STACK_PUSH(stack, f_other);
- }
- } while ((l_radial_iter = l_radial_iter->radial_next) != l_iter);
- }
- } while ((l_iter = l_iter->next) != l_first);
- }
-
- if (htype_step & BM_VERT) {
- BMIter liter;
- /* search for other faces */
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if ((filter_fn == NULL) || filter_fn(l_iter, user_data)) {
- BMLoop *l_other;
- BM_ITER_ELEM (l_other, &liter, l_iter, BM_LOOPS_OF_LOOP) {
- BMFace *f_other = l_other->f;
- if (BM_elem_flag_test(f_other, BM_ELEM_TAG) == false) {
- BM_elem_flag_enable(f_other, BM_ELEM_TAG);
- STACK_PUSH(stack, f_other);
- }
- }
- }
- } while ((l_iter = l_iter->next) != l_first);
- }
- }
-
- group_curr++;
- }
-
- MEM_freeN(stack);
-
- /* reduce alloc to required size */
- group_index = MEM_reallocN(group_index, sizeof(*group_index) * group_curr);
- *r_group_index = group_index;
-
- return group_curr;
+ int(*group_index)[2] = MEM_mallocN(sizeof(*group_index) * group_index_len, __func__);
+
+ int *group_array = r_groups_array;
+ STACK_DECLARE(group_array);
+
+ int group_curr = 0;
+
+ uint tot_faces = 0;
+ uint tot_touch = 0;
+
+ BMFace **stack;
+ STACK_DECLARE(stack);
+
+ BMIter iter;
+ BMFace *f;
+ int i;
+
+ STACK_INIT(group_array, bm->totface);
+
+ BLI_assert(((htype_step & ~(BM_VERT | BM_EDGE)) == 0) && (htype_step != 0));
+
+ /* init the array */
+ BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) {
+ if ((hflag_test == 0) || BM_elem_flag_test(f, hflag_test)) {
+ tot_faces++;
+ BM_elem_flag_disable(f, BM_ELEM_TAG);
+ }
+ else {
+ /* never walk over tagged */
+ BM_elem_flag_enable(f, BM_ELEM_TAG);
+ }
+
+ BM_elem_index_set(f, i); /* set_inline */
+ }
+ bm->elem_index_dirty &= ~BM_FACE;
+
+ /* detect groups */
+ stack = MEM_mallocN(sizeof(*stack) * tot_faces, __func__);
+
+ while (tot_touch != tot_faces) {
+ int *group_item;
+ bool ok = false;
+
+ BLI_assert(tot_touch < tot_faces);
+
+ STACK_INIT(stack, tot_faces);
+
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_TAG) == false) {
+ BM_elem_flag_enable(f, BM_ELEM_TAG);
+ STACK_PUSH(stack, f);
+ ok = true;
+ break;
+ }
+ }
+
+ BLI_assert(ok == true);
+ UNUSED_VARS_NDEBUG(ok);
+
+ /* manage arrays */
+ if (group_index_len == group_curr) {
+ group_index_len *= 2;
+ group_index = MEM_reallocN(group_index, sizeof(*group_index) * group_index_len);
+ }
+
+ group_item = group_index[group_curr];
+ group_item[0] = STACK_SIZE(group_array);
+ group_item[1] = 0;
+
+ while ((f = STACK_POP(stack))) {
+ BMLoop *l_iter, *l_first;
+
+ /* add face */
+ STACK_PUSH(group_array, BM_elem_index_get(f));
+ tot_touch++;
+ group_item[1]++;
+ /* done */
+
+ if (htype_step & BM_EDGE) {
+ /* search for other faces */
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BMLoop *l_radial_iter = l_iter->radial_next;
+ if ((l_radial_iter != l_iter) && ((filter_fn == NULL) || filter_fn(l_iter, user_data))) {
+ do {
+ BMFace *f_other = l_radial_iter->f;
+ if (BM_elem_flag_test(f_other, BM_ELEM_TAG) == false) {
+ BM_elem_flag_enable(f_other, BM_ELEM_TAG);
+ STACK_PUSH(stack, f_other);
+ }
+ } while ((l_radial_iter = l_radial_iter->radial_next) != l_iter);
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+
+ if (htype_step & BM_VERT) {
+ BMIter liter;
+ /* search for other faces */
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if ((filter_fn == NULL) || filter_fn(l_iter, user_data)) {
+ BMLoop *l_other;
+ BM_ITER_ELEM (l_other, &liter, l_iter, BM_LOOPS_OF_LOOP) {
+ BMFace *f_other = l_other->f;
+ if (BM_elem_flag_test(f_other, BM_ELEM_TAG) == false) {
+ BM_elem_flag_enable(f_other, BM_ELEM_TAG);
+ STACK_PUSH(stack, f_other);
+ }
+ }
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ }
+
+ group_curr++;
+ }
+
+ MEM_freeN(stack);
+
+ /* reduce alloc to required size */
+ group_index = MEM_reallocN(group_index, sizeof(*group_index) * group_curr);
+ *r_group_index = group_index;
+
+ return group_curr;
}
/* note, almost duplicate of BM_mesh_calc_face_groups, keep in sync */
@@ -2696,145 +2658,147 @@ int BM_mesh_calc_face_groups(
* \note Unlike #BM_mesh_calc_face_groups there is no 'htype_step' argument,
* since we always walk over verts.
*/
-int BM_mesh_calc_edge_groups(
- BMesh *bm, int *r_groups_array, int (**r_group_index)[2],
- BMVertFilterFunc filter_fn, void *user_data,
- const char hflag_test)
+int BM_mesh_calc_edge_groups(BMesh *bm,
+ int *r_groups_array,
+ int (**r_group_index)[2],
+ BMVertFilterFunc filter_fn,
+ void *user_data,
+ const char hflag_test)
{
#ifdef DEBUG
- int group_index_len = 1;
+ int group_index_len = 1;
#else
- int group_index_len = 32;
+ int group_index_len = 32;
#endif
- int (*group_index)[2] = MEM_mallocN(sizeof(*group_index) * group_index_len, __func__);
-
- int *group_array = r_groups_array;
- STACK_DECLARE(group_array);
+ int(*group_index)[2] = MEM_mallocN(sizeof(*group_index) * group_index_len, __func__);
+
+ int *group_array = r_groups_array;
+ STACK_DECLARE(group_array);
- int group_curr = 0;
+ int group_curr = 0;
- uint tot_edges = 0;
- uint tot_touch = 0;
+ uint tot_edges = 0;
+ uint tot_touch = 0;
- BMEdge **stack;
- STACK_DECLARE(stack);
+ BMEdge **stack;
+ STACK_DECLARE(stack);
- BMIter iter;
- BMEdge *e;
- int i;
+ BMIter iter;
+ BMEdge *e;
+ int i;
- STACK_INIT(group_array, bm->totedge);
+ STACK_INIT(group_array, bm->totedge);
- /* init the array */
- BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
- if ((hflag_test == 0) || BM_elem_flag_test(e, hflag_test)) {
- tot_edges++;
- BM_elem_flag_disable(e, BM_ELEM_TAG);
- }
- else {
- /* never walk over tagged */
- BM_elem_flag_enable(e, BM_ELEM_TAG);
- }
+ /* init the array */
+ BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
+ if ((hflag_test == 0) || BM_elem_flag_test(e, hflag_test)) {
+ tot_edges++;
+ BM_elem_flag_disable(e, BM_ELEM_TAG);
+ }
+ else {
+ /* never walk over tagged */
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
+ }
- BM_elem_index_set(e, i); /* set_inline */
- }
- bm->elem_index_dirty &= ~BM_EDGE;
+ BM_elem_index_set(e, i); /* set_inline */
+ }
+ bm->elem_index_dirty &= ~BM_EDGE;
- /* detect groups */
- stack = MEM_mallocN(sizeof(*stack) * tot_edges, __func__);
+ /* detect groups */
+ stack = MEM_mallocN(sizeof(*stack) * tot_edges, __func__);
- while (tot_touch != tot_edges) {
- int *group_item;
- bool ok = false;
+ while (tot_touch != tot_edges) {
+ int *group_item;
+ bool ok = false;
- BLI_assert(tot_touch < tot_edges);
+ BLI_assert(tot_touch < tot_edges);
- STACK_INIT(stack, tot_edges);
+ STACK_INIT(stack, tot_edges);
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_TAG) == false) {
- BM_elem_flag_enable(e, BM_ELEM_TAG);
- STACK_PUSH(stack, e);
- ok = true;
- break;
- }
- }
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_TAG) == false) {
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
+ STACK_PUSH(stack, e);
+ ok = true;
+ break;
+ }
+ }
- BLI_assert(ok == true);
- UNUSED_VARS_NDEBUG(ok);
+ BLI_assert(ok == true);
+ UNUSED_VARS_NDEBUG(ok);
- /* manage arrays */
- if (group_index_len == group_curr) {
- group_index_len *= 2;
- group_index = MEM_reallocN(group_index, sizeof(*group_index) * group_index_len);
- }
+ /* manage arrays */
+ if (group_index_len == group_curr) {
+ group_index_len *= 2;
+ group_index = MEM_reallocN(group_index, sizeof(*group_index) * group_index_len);
+ }
- group_item = group_index[group_curr];
- group_item[0] = STACK_SIZE(group_array);
- group_item[1] = 0;
+ group_item = group_index[group_curr];
+ group_item[0] = STACK_SIZE(group_array);
+ group_item[1] = 0;
- while ((e = STACK_POP(stack))) {
- BMIter viter;
- BMIter eiter;
- BMVert *v;
+ while ((e = STACK_POP(stack))) {
+ BMIter viter;
+ BMIter eiter;
+ BMVert *v;
- /* add edge */
- STACK_PUSH(group_array, BM_elem_index_get(e));
- tot_touch++;
- group_item[1]++;
- /* done */
+ /* add edge */
+ STACK_PUSH(group_array, BM_elem_index_get(e));
+ tot_touch++;
+ group_item[1]++;
+ /* done */
- /* search for other edges */
- BM_ITER_ELEM (v, &viter, e, BM_VERTS_OF_EDGE) {
- if ((filter_fn == NULL) || filter_fn(v, user_data)) {
- BMEdge *e_other;
- BM_ITER_ELEM (e_other, &eiter, v, BM_EDGES_OF_VERT) {
- if (BM_elem_flag_test(e_other, BM_ELEM_TAG) == false) {
- BM_elem_flag_enable(e_other, BM_ELEM_TAG);
- STACK_PUSH(stack, e_other);
- }
- }
- }
- }
- }
+ /* search for other edges */
+ BM_ITER_ELEM (v, &viter, e, BM_VERTS_OF_EDGE) {
+ if ((filter_fn == NULL) || filter_fn(v, user_data)) {
+ BMEdge *e_other;
+ BM_ITER_ELEM (e_other, &eiter, v, BM_EDGES_OF_VERT) {
+ if (BM_elem_flag_test(e_other, BM_ELEM_TAG) == false) {
+ BM_elem_flag_enable(e_other, BM_ELEM_TAG);
+ STACK_PUSH(stack, e_other);
+ }
+ }
+ }
+ }
+ }
- group_curr++;
- }
+ group_curr++;
+ }
- MEM_freeN(stack);
+ MEM_freeN(stack);
- /* reduce alloc to required size */
- group_index = MEM_reallocN(group_index, sizeof(*group_index) * group_curr);
- *r_group_index = group_index;
-
- return group_curr;
+ /* reduce alloc to required size */
+ group_index = MEM_reallocN(group_index, sizeof(*group_index) * group_curr);
+ *r_group_index = group_index;
+
+ return group_curr;
}
float bmesh_subd_falloff_calc(const int falloff, float val)
{
- switch (falloff) {
- case SUBD_FALLOFF_SMOOTH:
- val = 3.0f * val * val - 2.0f * val * val * val;
- break;
- case SUBD_FALLOFF_SPHERE:
- val = sqrtf(2.0f * val - val * val);
- break;
- case SUBD_FALLOFF_ROOT:
- val = sqrtf(val);
- break;
- case SUBD_FALLOFF_SHARP:
- val = val * val;
- break;
- case SUBD_FALLOFF_LIN:
- break;
- case SUBD_FALLOFF_INVSQUARE:
- val = val * (2.0f - val);
- break;
- default:
- BLI_assert(0);
- break;
- }
-
- return val;
+ switch (falloff) {
+ case SUBD_FALLOFF_SMOOTH:
+ val = 3.0f * val * val - 2.0f * val * val * val;
+ break;
+ case SUBD_FALLOFF_SPHERE:
+ val = sqrtf(2.0f * val - val * val);
+ break;
+ case SUBD_FALLOFF_ROOT:
+ val = sqrtf(val);
+ break;
+ case SUBD_FALLOFF_SHARP:
+ val = val * val;
+ break;
+ case SUBD_FALLOFF_LIN:
+ break;
+ case SUBD_FALLOFF_INVSQUARE:
+ val = val * (2.0f - val);
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
+
+ return val;
}
diff --git a/source/blender/bmesh/intern/bmesh_query.h b/source/blender/bmesh/intern/bmesh_query.h
index c04c7f5e97d..e96984490c0 100644
--- a/source/blender/bmesh/intern/bmesh_query.h
+++ b/source/blender/bmesh/intern/bmesh_query.h
@@ -21,25 +21,33 @@
* \ingroup bmesh
*/
-bool BM_vert_in_face(BMVert *v, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-int BM_verts_in_face_count(BMVert **varr, int len, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_verts_in_face(BMVert **varr, int len, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-
-bool BM_edge_in_face(const BMEdge *e, const BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-BLI_INLINE bool BM_edge_in_loop(const BMEdge *e, const BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-
-BLI_INLINE bool BM_vert_in_edge(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-BLI_INLINE bool BM_verts_in_edge(const BMVert *v1, const BMVert *v2, const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-
-float BM_edge_calc_length(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-float BM_edge_calc_length_squared(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb) ATTR_NONNULL();
-bool BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb) ATTR_NONNULL();
-BLI_INLINE BMVert *BM_edge_other_vert(BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_vert_in_face(BMVert *v, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int BM_verts_in_face_count(BMVert **varr, int len, BMFace *f) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+bool BM_verts_in_face(BMVert **varr, int len, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+
+bool BM_edge_in_face(const BMEdge *e, const BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BLI_INLINE bool BM_edge_in_loop(const BMEdge *e, const BMLoop *l) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+
+BLI_INLINE bool BM_vert_in_edge(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+BLI_INLINE bool BM_verts_in_edge(const BMVert *v1,
+ const BMVert *v2,
+ const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+
+float BM_edge_calc_length(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_edge_calc_length_squared(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb) ATTR_NONNULL();
+bool BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb) ATTR_NONNULL();
+BLI_INLINE BMVert *BM_edge_other_vert(BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
BMLoop *BM_edge_other_loop(BMEdge *e, BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-BMLoop *BM_face_other_edge_loop(BMFace *f, BMEdge *e, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMLoop *BM_face_other_edge_loop(BMFace *f, BMEdge *e, BMVert *v) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
BMLoop *BM_loop_other_edge_loop(BMLoop *l, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-BMLoop *BM_face_other_vert_loop(BMFace *f, BMVert *v_prev, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMLoop *BM_face_other_vert_loop(BMFace *f, BMVert *v_prev, BMVert *v) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
BMLoop *BM_loop_other_vert_loop(BMLoop *l, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BMLoop *BM_vert_step_fan_loop(BMLoop *l, BMEdge **e_step) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
@@ -47,89 +55,115 @@ BMLoop *BM_vert_find_first_loop(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(
BMLoop *BM_vert_find_first_loop_visible(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BMLoop *BM_edge_find_first_loop_visible(BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_vert_pair_share_face_check(
- BMVert *v_a, BMVert *v_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_vert_pair_share_face_check_cb(
- BMVert *v_a, BMVert *v_b,
- bool (*test_fn)(BMFace *f, void *user_data), void *user_data) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3);
-BMFace *BM_vert_pair_share_face_by_len(
- BMVert *v_a, BMVert *v_b,
- BMLoop **r_l_a, BMLoop **r_l_b,
- const bool allow_adjacent) ATTR_NONNULL();
-BMFace *BM_vert_pair_share_face_by_angle(
- BMVert *v_a, BMVert *v_b,
- BMLoop **r_l_a, BMLoop **r_l_b,
- const bool allow_adjacent) ATTR_NONNULL();
-
-BMFace *BM_edge_pair_share_face_by_len(
- BMEdge *e_a, BMEdge *e_b,
- BMLoop **r_l_a, BMLoop **r_l_b,
- const bool allow_adjacent) ATTR_NONNULL();
-
-int BM_vert_edge_count_nonwire(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_vert_pair_share_face_check(BMVert *v_a, BMVert *v_b) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+bool BM_vert_pair_share_face_check_cb(BMVert *v_a,
+ BMVert *v_b,
+ bool (*test_fn)(BMFace *f, void *user_data),
+ void *user_data) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL(1, 2, 3);
+BMFace *BM_vert_pair_share_face_by_len(BMVert *v_a,
+ BMVert *v_b,
+ BMLoop **r_l_a,
+ BMLoop **r_l_b,
+ const bool allow_adjacent) ATTR_NONNULL();
+BMFace *BM_vert_pair_share_face_by_angle(BMVert *v_a,
+ BMVert *v_b,
+ BMLoop **r_l_a,
+ BMLoop **r_l_b,
+ const bool allow_adjacent) ATTR_NONNULL();
+
+BMFace *BM_edge_pair_share_face_by_len(BMEdge *e_a,
+ BMEdge *e_b,
+ BMLoop **r_l_a,
+ BMLoop **r_l_b,
+ const bool allow_adjacent) ATTR_NONNULL();
+
+int BM_vert_edge_count_nonwire(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
#define BM_vert_edge_count_is_equal(v, n) (BM_vert_edge_count_at_most(v, (n) + 1) == n)
#define BM_vert_edge_count_is_over(v, n) (BM_vert_edge_count_at_most(v, (n) + 1) == (n) + 1)
-int BM_vert_edge_count_at_most(const BMVert *v, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-int BM_vert_edge_count(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int BM_vert_edge_count_at_most(const BMVert *v, const int count_max) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+int BM_vert_edge_count(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
#define BM_edge_face_count_is_equal(e, n) (BM_edge_face_count_at_most(e, (n) + 1) == n)
#define BM_edge_face_count_is_over(e, n) (BM_edge_face_count_at_most(e, (n) + 1) == (n) + 1)
-int BM_edge_face_count_at_most(const BMEdge *e, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-int BM_edge_face_count(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int BM_edge_face_count_at_most(const BMEdge *e, const int count_max) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+int BM_edge_face_count(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
#define BM_vert_face_count_is_equal(v, n) (BM_vert_face_count_at_most(v, (n) + 1) == n)
#define BM_vert_face_count_is_over(v, n) (BM_vert_face_count_at_most(v, (n) + 1) == (n) + 1)
-int BM_vert_face_count_at_most(const BMVert *v, int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-int BM_vert_face_count(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int BM_vert_face_count_at_most(const BMVert *v, int count_max) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+int BM_vert_face_count(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BMEdge *BM_vert_other_disk_edge(BMVert *v, BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_vert_is_edge_pair(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_vert_is_edge_pair_manifold(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_vert_edge_pair(BMVert *v, BMEdge **r_e_a, BMEdge **r_e_b);
-bool BM_vert_face_check(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_vert_is_wire(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-BLI_INLINE bool BM_edge_is_wire(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-
-bool BM_vert_is_manifold(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_vert_is_manifold_region(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-BLI_INLINE bool BM_edge_is_manifold(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_vert_is_boundary(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-BLI_INLINE bool BM_edge_is_boundary(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-BLI_INLINE bool BM_edge_is_contiguous(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_edge_is_convex(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_edge_is_contiguous_loop_cd(
- const BMEdge *e,
- const int cd_loop_type, const int cd_loop_offset)
- ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-
-int BM_loop_region_loops_count_at_most(BMLoop *l, int *r_loop_total) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
-int BM_loop_region_loops_count(BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
-bool BM_loop_is_convex(const BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-BLI_INLINE bool BM_loop_is_adjacent(const BMLoop *l_a, const BMLoop *l_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-float BM_loop_point_side_of_loop_test(const BMLoop *l, const float co[3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-float BM_loop_point_side_of_edge_test(const BMLoop *l, const float co[3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_vert_is_edge_pair(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_vert_is_edge_pair_manifold(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_vert_edge_pair(BMVert *v, BMEdge **r_e_a, BMEdge **r_e_b);
+bool BM_vert_face_check(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_vert_is_wire(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BLI_INLINE bool BM_edge_is_wire(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+
+bool BM_vert_is_manifold(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_vert_is_manifold_region(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BLI_INLINE bool BM_edge_is_manifold(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_vert_is_boundary(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BLI_INLINE bool BM_edge_is_boundary(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BLI_INLINE bool BM_edge_is_contiguous(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_edge_is_convex(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_edge_is_contiguous_loop_cd(const BMEdge *e,
+ const int cd_loop_type,
+ const int cd_loop_offset) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+
+int BM_loop_region_loops_count_at_most(BMLoop *l, int *r_loop_total) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL(1);
+int BM_loop_region_loops_count(BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+bool BM_loop_is_convex(const BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BLI_INLINE bool BM_loop_is_adjacent(const BMLoop *l_a, const BMLoop *l_b) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+float BM_loop_point_side_of_loop_test(const BMLoop *l, const float co[3]) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+float BM_loop_point_side_of_edge_test(const BMLoop *l, const float co[3]) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
BMLoop *BM_loop_find_prev_nodouble(BMLoop *l, BMLoop *l_stop, const float eps_sq);
BMLoop *BM_loop_find_next_nodouble(BMLoop *l, BMLoop *l_stop, const float eps_sq);
-float BM_loop_calc_face_angle(const BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-float BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3]) ATTR_NONNULL();
-float BM_loop_calc_face_normal_safe(const BMLoop *l, float r_normal[3]) ATTR_NONNULL();
-float BM_loop_calc_face_normal_safe_ex(const BMLoop *l, const float epsilon, float r_normal[3]) ATTR_NONNULL();
-void BM_loop_calc_face_direction(const BMLoop *l, float r_normal[3]);
-void BM_loop_calc_face_tangent(const BMLoop *l, float r_tangent[3]);
-
-float BM_edge_calc_face_angle_ex(const BMEdge *e, const float fallback) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-float BM_edge_calc_face_angle(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-float BM_edge_calc_face_angle_signed_ex(const BMEdge *e, const float fallback) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-float BM_edge_calc_face_angle_with_imat3_ex(const BMEdge *e, const float imat3[3][3], const float fallback) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-float BM_edge_calc_face_angle_with_imat3(const BMEdge *e, const float imat3[3][3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-float BM_edge_calc_face_angle_signed(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-void BM_edge_calc_face_tangent(const BMEdge *e, const BMLoop *e_loop, float r_tangent[3]) ATTR_NONNULL();
-
-float BM_vert_calc_edge_angle(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-float BM_vert_calc_edge_angle_ex(const BMVert *v, const float fallback) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-float BM_vert_calc_shell_factor(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-float BM_vert_calc_shell_factor_ex(const BMVert *v, const float no[3], const char hflag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-float BM_vert_calc_median_tagged_edge_length(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_loop_calc_face_angle(const BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3]) ATTR_NONNULL();
+float BM_loop_calc_face_normal_safe(const BMLoop *l, float r_normal[3]) ATTR_NONNULL();
+float BM_loop_calc_face_normal_safe_ex(const BMLoop *l, const float epsilon, float r_normal[3])
+ ATTR_NONNULL();
+void BM_loop_calc_face_direction(const BMLoop *l, float r_normal[3]);
+void BM_loop_calc_face_tangent(const BMLoop *l, float r_tangent[3]);
+
+float BM_edge_calc_face_angle_ex(const BMEdge *e, const float fallback) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+float BM_edge_calc_face_angle(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_edge_calc_face_angle_signed_ex(const BMEdge *e,
+ const float fallback) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+float BM_edge_calc_face_angle_with_imat3_ex(const BMEdge *e,
+ const float imat3[3][3],
+ const float fallback) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+float BM_edge_calc_face_angle_with_imat3(const BMEdge *e,
+ const float imat3[3][3]) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+float BM_edge_calc_face_angle_signed(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+void BM_edge_calc_face_tangent(const BMEdge *e, const BMLoop *e_loop, float r_tangent[3])
+ ATTR_NONNULL();
+
+float BM_vert_calc_edge_angle(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_vert_calc_edge_angle_ex(const BMVert *v, const float fallback) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+float BM_vert_calc_shell_factor(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_vert_calc_shell_factor_ex(const BMVert *v,
+ const float no[3],
+ const char hflag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+float BM_vert_calc_median_tagged_edge_length(const BMVert *v) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
BMLoop *BM_face_find_shortest_loop(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BMLoop *BM_face_find_longest_loop(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
@@ -140,58 +174,73 @@ BMEdge *BM_edge_find_double(BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BMFace *BM_face_exists(BMVert **varr, int len) ATTR_NONNULL(1);
BMFace *BM_face_find_double(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_face_exists_multi_edge(BMEdge **earr, int len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+bool BM_face_exists_multi_edge(BMEdge **earr, int len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BMFace *BM_face_exists_overlap(BMVert **varr, const int len) ATTR_WARN_UNUSED_RESULT;
-bool BM_face_exists_overlap_subset(BMVert **varr, const int len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_face_exists_overlap_subset(BMVert **varr, const int len) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
-int BM_face_share_face_count(BMFace *f_a, BMFace *f_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-int BM_face_share_edge_count(BMFace *f_a, BMFace *f_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-int BM_face_share_vert_count(BMFace *f_a, BMFace *f_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int BM_face_share_face_count(BMFace *f_a, BMFace *f_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int BM_face_share_edge_count(BMFace *f_a, BMFace *f_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int BM_face_share_vert_count(BMFace *f_a, BMFace *f_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_face_share_face_check(BMFace *f_a, BMFace *f_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_face_share_edge_check(BMFace *f_a, BMFace *f_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_face_share_vert_check(BMFace *f_a, BMFace *f_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_face_share_face_check(BMFace *f_a, BMFace *f_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_face_share_edge_check(BMFace *f_a, BMFace *f_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_face_share_vert_check(BMFace *f_a, BMFace *f_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_loop_share_edge_check(BMLoop *l_a, BMLoop *l_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_loop_share_edge_check(BMLoop *l_a, BMLoop *l_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_edge_share_face_check(BMEdge *e1, BMEdge *e2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_edge_share_face_check(BMEdge *e1, BMEdge *e2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BMVert *BM_edge_share_vert(BMEdge *e1, BMEdge *e2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BMLoop *BM_edge_vert_share_loop(BMLoop *l, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BMLoop *BM_face_vert_share_loop(BMFace *f, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BMLoop *BM_face_edge_share_loop(BMFace *f, BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-void BM_edge_ordered_verts(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2) ATTR_NONNULL();
-void BM_edge_ordered_verts_ex(
- const BMEdge *edge, BMVert **r_v1, BMVert **r_v2,
- const BMLoop *edge_loop) ATTR_NONNULL();
-
-bool BM_vert_is_all_edge_flag_test(const BMVert *v, const char hflag, const bool respect_hide) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_vert_is_all_face_flag_test(const BMVert *v, const char hflag, const bool respect_hide) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_edge_is_all_face_flag_test(const BMEdge *e, const char hflag, const bool respect_hide) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-
-bool BM_edge_is_any_vert_flag_test(const BMEdge *e, const char hflag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_face_is_any_vert_flag_test(const BMFace *f, const char hflag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool BM_face_is_any_edge_flag_test(const BMFace *f, const char hflag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+void BM_edge_ordered_verts(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2) ATTR_NONNULL();
+void BM_edge_ordered_verts_ex(const BMEdge *edge,
+ BMVert **r_v1,
+ BMVert **r_v2,
+ const BMLoop *edge_loop) ATTR_NONNULL();
+
+bool BM_vert_is_all_edge_flag_test(const BMVert *v,
+ const char hflag,
+ const bool respect_hide) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_vert_is_all_face_flag_test(const BMVert *v,
+ const char hflag,
+ const bool respect_hide) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BM_edge_is_all_face_flag_test(const BMEdge *e,
+ const char hflag,
+ const bool respect_hide) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+
+bool BM_edge_is_any_vert_flag_test(const BMEdge *e, const char hflag) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+bool BM_face_is_any_vert_flag_test(const BMFace *f, const char hflag) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+bool BM_face_is_any_edge_flag_test(const BMFace *f, const char hflag) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
bool BM_face_is_normal_valid(const BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
float BM_mesh_calc_volume(BMesh *bm, bool is_signed) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-int BM_mesh_calc_face_groups(
- BMesh *bm, int *r_groups_array, int (**r_group_index)[2],
- BMLoopFilterFunc filter_fn, void *user_data,
- const char hflag_test, const char htype_step)
- ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3);
-int BM_mesh_calc_edge_groups(
- BMesh *bm, int *r_groups_array, int (**r_group_index)[2],
- BMVertFilterFunc filter_fn, void *user_data,
- const char hflag_test)
- ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3);
+int BM_mesh_calc_face_groups(BMesh *bm,
+ int *r_groups_array,
+ int (**r_group_index)[2],
+ BMLoopFilterFunc filter_fn,
+ void *user_data,
+ const char hflag_test,
+ const char htype_step) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3);
+int BM_mesh_calc_edge_groups(BMesh *bm,
+ int *r_groups_array,
+ int (**r_group_index)[2],
+ BMVertFilterFunc filter_fn,
+ void *user_data,
+ const char hflag_test) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3);
/* not really any good place to put this */
float bmesh_subd_falloff_calc(const int falloff, float val) ATTR_WARN_UNUSED_RESULT;
diff --git a/source/blender/bmesh/intern/bmesh_query_inline.h b/source/blender/bmesh/intern/bmesh_query_inline.h
index 582aa55b600..90919cc361b 100644
--- a/source/blender/bmesh/intern/bmesh_query_inline.h
+++ b/source/blender/bmesh/intern/bmesh_query_inline.h
@@ -18,7 +18,6 @@
* \ingroup bmesh
*/
-
#ifndef __BMESH_QUERY_INLINE_H__
#define __BMESH_QUERY_INLINE_H__
@@ -26,56 +25,54 @@
* Returns whether or not a given vertex is
* is part of a given edge.
*/
-ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
-BLI_INLINE bool BM_vert_in_edge(const BMEdge *e, const BMVert *v)
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE
+ bool BM_vert_in_edge(const BMEdge *e, const BMVert *v)
{
- return (ELEM(v, e->v1, e->v2));
+ return (ELEM(v, e->v1, e->v2));
}
/**
* Returns whether or not a given edge is part of a given loop.
*/
-ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2)
-BLI_INLINE bool BM_edge_in_loop(const BMEdge *e, const BMLoop *l)
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) BLI_INLINE
+ bool BM_edge_in_loop(const BMEdge *e, const BMLoop *l)
{
- return (l->e == e || l->prev->e == e);
+ return (l->e == e || l->prev->e == e);
}
/**
* Returns whether or not two vertices are in
* a given edge
*/
-ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3)
-BLI_INLINE bool BM_verts_in_edge(const BMVert *v1, const BMVert *v2, const BMEdge *e)
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3) BLI_INLINE
+ bool BM_verts_in_edge(const BMVert *v1, const BMVert *v2, const BMEdge *e)
{
- return ((e->v1 == v1 && e->v2 == v2) ||
- (e->v1 == v2 && e->v2 == v1));
+ return ((e->v1 == v1 && e->v2 == v2) || (e->v1 == v2 && e->v2 == v1));
}
/**
* Given a edge and one of its vertices, returns
* the other vertex.
*/
-ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2)
-BLI_INLINE BMVert *BM_edge_other_vert(BMEdge *e, const BMVert *v)
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) BLI_INLINE BMVert *BM_edge_other_vert(BMEdge *e,
+ const BMVert *v)
{
- if (e->v1 == v) {
- return e->v2;
- }
- else if (e->v2 == v) {
- return e->v1;
- }
- return NULL;
+ if (e->v1 == v) {
+ return e->v2;
+ }
+ else if (e->v2 == v) {
+ return e->v1;
+ }
+ return NULL;
}
/**
* Tests whether or not the edge is part of a wire.
* (ie: has no faces attached to it)
*/
-ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
-BLI_INLINE bool BM_edge_is_wire(const BMEdge *e)
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE bool BM_edge_is_wire(const BMEdge *e)
{
- return (e->l == NULL);
+ return (e->l == NULL);
}
/**
@@ -84,17 +81,16 @@ BLI_INLINE bool BM_edge_is_wire(const BMEdge *e)
*/
#if 1 /* fast path for checking manifold */
-ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
-BLI_INLINE bool BM_edge_is_manifold(const BMEdge *e)
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE bool BM_edge_is_manifold(const BMEdge *e)
{
- const BMLoop *l = e->l;
- return (l && (l->radial_next != l) && /* not 0 or 1 face users */
- (l->radial_next->radial_next == l)); /* 2 face users */
+ const BMLoop *l = e->l;
+ return (l && (l->radial_next != l) && /* not 0 or 1 face users */
+ (l->radial_next->radial_next == l)); /* 2 face users */
}
#else
BLI_INLINE int BM_edge_is_manifold(BMEdge *e)
{
- return (BM_edge_face_count(e) == 2);
+ return (BM_edge_face_count(e) == 2);
}
#endif
@@ -102,14 +98,13 @@ BLI_INLINE int BM_edge_is_manifold(BMEdge *e)
* Tests that the edge is manifold and
* that both its faces point the same way.
*/
-ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
-BLI_INLINE bool BM_edge_is_contiguous(const BMEdge *e)
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE bool BM_edge_is_contiguous(const BMEdge *e)
{
- const BMLoop *l = e->l;
- const BMLoop *l_other;
- return (l && ((l_other = l->radial_next) != l) && /* not 0 or 1 face users */
- (l_other->radial_next == l) && /* 2 face users */
- (l_other->v != l->v));
+ const BMLoop *l = e->l;
+ const BMLoop *l_other;
+ return (l && ((l_other = l->radial_next) != l) && /* not 0 or 1 face users */
+ (l_other->radial_next == l) && /* 2 face users */
+ (l_other->v != l->v));
}
/**
@@ -118,48 +113,44 @@ BLI_INLINE bool BM_edge_is_contiguous(const BMEdge *e)
*/
#if 1 /* fast path for checking boundary */
-ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
-BLI_INLINE bool BM_edge_is_boundary(const BMEdge *e)
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE bool BM_edge_is_boundary(const BMEdge *e)
{
- const BMLoop *l = e->l;
- return (l && (l->radial_next == l));
+ const BMLoop *l = e->l;
+ return (l && (l->radial_next == l));
}
#else
BLI_INLINE int BM_edge_is_boundary(BMEdge *e)
{
- return (BM_edge_face_count(e) == 1);
+ return (BM_edge_face_count(e) == 1);
}
#endif
/**
* Tests whether one loop is next to another within the same face.
*/
-ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2)
-BLI_INLINE bool BM_loop_is_adjacent(const BMLoop *l_a, const BMLoop *l_b)
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) BLI_INLINE
+ bool BM_loop_is_adjacent(const BMLoop *l_a, const BMLoop *l_b)
{
- BLI_assert(l_a->f == l_b->f);
- BLI_assert(l_a != l_b);
- return (ELEM(l_b, l_a->next, l_a->prev));
+ BLI_assert(l_a->f == l_b->f);
+ BLI_assert(l_a != l_b);
+ return (ELEM(l_b, l_a->next, l_a->prev));
}
-ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
-BLI_INLINE bool BM_loop_is_manifold(const BMLoop *l)
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE bool BM_loop_is_manifold(const BMLoop *l)
{
- return ((l != l->radial_next) &&
- (l == l->radial_next->radial_next));
+ return ((l != l->radial_next) && (l == l->radial_next->radial_next));
}
/**
* Check if we have a single wire edge user.
*/
-ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
-BLI_INLINE bool BM_vert_is_wire_endpoint(const BMVert *v)
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE bool BM_vert_is_wire_endpoint(const BMVert *v)
{
- const BMEdge *e = v->e;
- if (e && e->l == NULL) {
- return (BM_DISK_EDGE_NEXT(e, v) == e);
- }
- return false;
+ const BMEdge *e = v->e;
+ if (e && e->l == NULL) {
+ return (BM_DISK_EDGE_NEXT(e, v) == e);
+ }
+ return false;
}
#endif /* __BMESH_QUERY_INLINE_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_structure.c b/source/blender/bmesh/intern/bmesh_structure.c
index a90d0d245d0..d9f68f8aa62 100644
--- a/source/blender/bmesh/intern/bmesh_structure.c
+++ b/source/blender/bmesh/intern/bmesh_structure.c
@@ -34,17 +34,17 @@
void bmesh_disk_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src)
{
- if (e->v1 == v_src) {
- e->v1 = v_dst;
- e->v1_disk_link.next = e->v1_disk_link.prev = NULL;
- }
- else if (e->v2 == v_src) {
- e->v2 = v_dst;
- e->v2_disk_link.next = e->v2_disk_link.prev = NULL;
- }
- else {
- BLI_assert(0);
- }
+ if (e->v1 == v_src) {
+ e->v1 = v_dst;
+ e->v1_disk_link.next = e->v1_disk_link.prev = NULL;
+ }
+ else if (e->v2 == v_src) {
+ e->v2 = v_dst;
+ e->v2_disk_link.next = e->v2_disk_link.prev = NULL;
+ }
+ else {
+ BLI_assert(0);
+ }
}
/**
@@ -54,34 +54,34 @@ void bmesh_disk_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src)
*/
void bmesh_edge_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src)
{
- /* swap out loops */
- if (e->l) {
- BMLoop *l_iter, *l_first;
- l_iter = l_first = e->l;
- do {
- if (l_iter->v == v_src) {
- l_iter->v = v_dst;
- }
- else if (l_iter->next->v == v_src) {
- l_iter->next->v = v_dst;
- }
- else {
- BLI_assert(l_iter->prev->v != v_src);
- }
- } while ((l_iter = l_iter->radial_next) != l_first);
- }
-
- /* swap out edges */
- bmesh_disk_vert_replace(e, v_dst, v_src);
+ /* swap out loops */
+ if (e->l) {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = e->l;
+ do {
+ if (l_iter->v == v_src) {
+ l_iter->v = v_dst;
+ }
+ else if (l_iter->next->v == v_src) {
+ l_iter->next->v = v_dst;
+ }
+ else {
+ BLI_assert(l_iter->prev->v != v_src);
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+
+ /* swap out edges */
+ bmesh_disk_vert_replace(e, v_dst, v_src);
}
void bmesh_disk_vert_replace(BMEdge *e, BMVert *v_dst, BMVert *v_src)
{
- BLI_assert(e->v1 == v_src || e->v2 == v_src);
- bmesh_disk_edge_remove(e, v_src); /* remove e from tv's disk cycle */
- bmesh_disk_vert_swap(e, v_dst, v_src); /* swap out tv for v_new in e */
- bmesh_disk_edge_append(e, v_dst); /* add e to v_dst's disk cycle */
- BLI_assert(e->v1 != e->v2);
+ BLI_assert(e->v1 == v_src || e->v2 == v_src);
+ bmesh_disk_edge_remove(e, v_src); /* remove e from tv's disk cycle */
+ bmesh_disk_vert_swap(e, v_dst, v_src); /* swap out tv for v_new in e */
+ bmesh_disk_edge_append(e, v_dst); /* add e to v_dst's disk cycle */
+ BLI_assert(e->v1 != e->v2);
}
/**
@@ -155,116 +155,116 @@ void bmesh_disk_vert_replace(BMEdge *e, BMVert *v_dst, BMVert *v_src)
void bmesh_disk_edge_append(BMEdge *e, BMVert *v)
{
- if (!v->e) {
- BMDiskLink *dl1 = bmesh_disk_edge_link_from_vert(e, v);
-
- v->e = e;
- dl1->next = dl1->prev = e;
- }
- else {
- BMDiskLink *dl1, *dl2, *dl3;
-
- dl1 = bmesh_disk_edge_link_from_vert(e, v);
- dl2 = bmesh_disk_edge_link_from_vert(v->e, v);
- dl3 = dl2->prev ? bmesh_disk_edge_link_from_vert(dl2->prev, v) : NULL;
-
- dl1->next = v->e;
- dl1->prev = dl2->prev;
-
- dl2->prev = e;
- if (dl3) {
- dl3->next = e;
- }
- }
+ if (!v->e) {
+ BMDiskLink *dl1 = bmesh_disk_edge_link_from_vert(e, v);
+
+ v->e = e;
+ dl1->next = dl1->prev = e;
+ }
+ else {
+ BMDiskLink *dl1, *dl2, *dl3;
+
+ dl1 = bmesh_disk_edge_link_from_vert(e, v);
+ dl2 = bmesh_disk_edge_link_from_vert(v->e, v);
+ dl3 = dl2->prev ? bmesh_disk_edge_link_from_vert(dl2->prev, v) : NULL;
+
+ dl1->next = v->e;
+ dl1->prev = dl2->prev;
+
+ dl2->prev = e;
+ if (dl3) {
+ dl3->next = e;
+ }
+ }
}
void bmesh_disk_edge_remove(BMEdge *e, BMVert *v)
{
- BMDiskLink *dl1, *dl2;
+ BMDiskLink *dl1, *dl2;
- dl1 = bmesh_disk_edge_link_from_vert(e, v);
- if (dl1->prev) {
- dl2 = bmesh_disk_edge_link_from_vert(dl1->prev, v);
- dl2->next = dl1->next;
- }
+ dl1 = bmesh_disk_edge_link_from_vert(e, v);
+ if (dl1->prev) {
+ dl2 = bmesh_disk_edge_link_from_vert(dl1->prev, v);
+ dl2->next = dl1->next;
+ }
- if (dl1->next) {
- dl2 = bmesh_disk_edge_link_from_vert(dl1->next, v);
- dl2->prev = dl1->prev;
- }
+ if (dl1->next) {
+ dl2 = bmesh_disk_edge_link_from_vert(dl1->next, v);
+ dl2->prev = dl1->prev;
+ }
- if (v->e == e) {
- v->e = (e != dl1->next) ? dl1->next : NULL;
- }
+ if (v->e == e) {
+ v->e = (e != dl1->next) ? dl1->next : NULL;
+ }
- dl1->next = dl1->prev = NULL;
+ dl1->next = dl1->prev = NULL;
}
BMEdge *bmesh_disk_edge_exists(const BMVert *v1, const BMVert *v2)
{
- BMEdge *e_iter, *e_first;
+ BMEdge *e_iter, *e_first;
- if (v1->e) {
- e_first = e_iter = v1->e;
+ if (v1->e) {
+ e_first = e_iter = v1->e;
- do {
- if (BM_verts_in_edge(v1, v2, e_iter)) {
- return e_iter;
- }
- } while ((e_iter = bmesh_disk_edge_next(e_iter, v1)) != e_first);
- }
+ do {
+ if (BM_verts_in_edge(v1, v2, e_iter)) {
+ return e_iter;
+ }
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v1)) != e_first);
+ }
- return NULL;
+ return NULL;
}
int bmesh_disk_count(const BMVert *v)
{
- int count = 0;
- if (v->e) {
- BMEdge *e_first, *e_iter;
- e_iter = e_first = v->e;
- do {
- count++;
- } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
- }
- return count;
+ int count = 0;
+ if (v->e) {
+ BMEdge *e_first, *e_iter;
+ e_iter = e_first = v->e;
+ do {
+ count++;
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
+ }
+ return count;
}
int bmesh_disk_count_at_most(const BMVert *v, const int count_max)
{
- int count = 0;
- if (v->e) {
- BMEdge *e_first, *e_iter;
- e_iter = e_first = v->e;
- do {
- count++;
- if (count == count_max) {
- break;
- }
- } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
- }
- return count;
+ int count = 0;
+ if (v->e) {
+ BMEdge *e_first, *e_iter;
+ e_iter = e_first = v->e;
+ do {
+ count++;
+ if (count == count_max) {
+ break;
+ }
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
+ }
+ return count;
}
bool bmesh_disk_validate(int len, BMEdge *e, BMVert *v)
{
- BMEdge *e_iter;
-
- if (!BM_vert_in_edge(e, v)) {
- return false;
- }
- if (len == 0 || bmesh_disk_count_at_most(v, len + 1) != len) {
- return false;
- }
-
- e_iter = e;
- do {
- if (len != 1 && bmesh_disk_edge_prev(e_iter, v) == e_iter) {
- return false;
- }
- } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e);
-
- return true;
+ BMEdge *e_iter;
+
+ if (!BM_vert_in_edge(e, v)) {
+ return false;
+ }
+ if (len == 0 || bmesh_disk_count_at_most(v, len + 1) != len) {
+ return false;
+ }
+
+ e_iter = e;
+ do {
+ if (len != 1 && bmesh_disk_edge_prev(e_iter, v) == e_iter) {
+ return false;
+ }
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e);
+
+ return true;
}
/**
@@ -277,41 +277,41 @@ bool bmesh_disk_validate(int len, BMEdge *e, BMVert *v)
*/
int bmesh_disk_facevert_count(const BMVert *v)
{
- /* is there an edge on this vert at all */
- int count = 0;
- if (v->e) {
- BMEdge *e_first, *e_iter;
-
- /* first, loop around edge */
- e_first = e_iter = v->e;
- do {
- if (e_iter->l) {
- count += bmesh_radial_facevert_count(e_iter->l, v);
- }
- } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
- }
- return count;
+ /* is there an edge on this vert at all */
+ int count = 0;
+ if (v->e) {
+ BMEdge *e_first, *e_iter;
+
+ /* first, loop around edge */
+ e_first = e_iter = v->e;
+ do {
+ if (e_iter->l) {
+ count += bmesh_radial_facevert_count(e_iter->l, v);
+ }
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
+ }
+ return count;
}
int bmesh_disk_facevert_count_at_most(const BMVert *v, const int count_max)
{
- /* is there an edge on this vert at all */
- int count = 0;
- if (v->e) {
- BMEdge *e_first, *e_iter;
-
- /* first, loop around edge */
- e_first = e_iter = v->e;
- do {
- if (e_iter->l) {
- count += bmesh_radial_facevert_count_at_most(e_iter->l, v, count_max - count);
- if (count == count_max) {
- break;
- }
- }
- } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
- }
- return count;
+ /* is there an edge on this vert at all */
+ int count = 0;
+ if (v->e) {
+ BMEdge *e_first, *e_iter;
+
+ /* first, loop around edge */
+ e_first = e_iter = v->e;
+ do {
+ if (e_iter->l) {
+ count += bmesh_radial_facevert_count_at_most(e_iter->l, v, count_max - count);
+ if (count == count_max) {
+ break;
+ }
+ }
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
+ }
+ return count;
}
/**
@@ -324,13 +324,13 @@ int bmesh_disk_facevert_count_at_most(const BMVert *v, const int count_max)
*/
BMEdge *bmesh_disk_faceedge_find_first(const BMEdge *e, const BMVert *v)
{
- const BMEdge *e_iter = e;
- do {
- if (e_iter->l != NULL) {
- return (BMEdge *)((e_iter->l->v == v) ? e_iter : e_iter->l->next->e);
- }
- } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e);
- return NULL;
+ const BMEdge *e_iter = e;
+ do {
+ if (e_iter->l != NULL) {
+ return (BMEdge *)((e_iter->l->v == v) ? e_iter : e_iter->l->next->e);
+ }
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e);
+ return NULL;
}
/**
@@ -340,13 +340,13 @@ BMEdge *bmesh_disk_faceedge_find_first(const BMEdge *e, const BMVert *v)
*/
BMLoop *bmesh_disk_faceloop_find_first(const BMEdge *e, const BMVert *v)
{
- const BMEdge *e_iter = e;
- do {
- if (e_iter->l != NULL) {
- return (e_iter->l->v == v) ? e_iter->l : e_iter->l->next;
- }
- } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e);
- return NULL;
+ const BMEdge *e_iter = e;
+ do {
+ if (e_iter->l != NULL) {
+ return (e_iter->l->v == v) ? e_iter->l : e_iter->l->next;
+ }
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e);
+ return NULL;
}
/**
@@ -354,91 +354,91 @@ BMLoop *bmesh_disk_faceloop_find_first(const BMEdge *e, const BMVert *v)
*/
BMLoop *bmesh_disk_faceloop_find_first_visible(const BMEdge *e, const BMVert *v)
{
- const BMEdge *e_iter = e;
- do {
- if (!BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN)) {
- if (e_iter->l != NULL) {
- BMLoop *l_iter, *l_first;
- l_iter = l_first = e_iter->l;
- do {
- if (!BM_elem_flag_test(l_iter->f, BM_ELEM_HIDDEN)) {
- return (l_iter->v == v) ? l_iter : l_iter->next;
- }
- } while ((l_iter = l_iter->radial_next) != l_first);
- }
- }
- } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e);
- return NULL;
+ const BMEdge *e_iter = e;
+ do {
+ if (!BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN)) {
+ if (e_iter->l != NULL) {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = e_iter->l;
+ do {
+ if (!BM_elem_flag_test(l_iter->f, BM_ELEM_HIDDEN)) {
+ return (l_iter->v == v) ? l_iter : l_iter->next;
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+ }
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e);
+ return NULL;
}
BMEdge *bmesh_disk_faceedge_find_next(const BMEdge *e, const BMVert *v)
{
- BMEdge *e_find;
- e_find = bmesh_disk_edge_next(e, v);
- do {
- if (e_find->l && bmesh_radial_facevert_check(e_find->l, v)) {
- return e_find;
- }
- } while ((e_find = bmesh_disk_edge_next(e_find, v)) != e);
- return (BMEdge *)e;
+ BMEdge *e_find;
+ e_find = bmesh_disk_edge_next(e, v);
+ do {
+ if (e_find->l && bmesh_radial_facevert_check(e_find->l, v)) {
+ return e_find;
+ }
+ } while ((e_find = bmesh_disk_edge_next(e_find, v)) != e);
+ return (BMEdge *)e;
}
/*****radial cycle functions, e.g. loops surrounding edges**** */
bool bmesh_radial_validate(int radlen, BMLoop *l)
{
- BMLoop *l_iter = l;
- int i = 0;
-
- if (bmesh_radial_length(l) != radlen) {
- return false;
- }
-
- do {
- if (UNLIKELY(!l_iter)) {
- BMESH_ASSERT(0);
- return false;
- }
-
- if (l_iter->e != l->e) {
- return false;
- }
- if (l_iter->v != l->e->v1 && l_iter->v != l->e->v2) {
- return false;
- }
-
- if (UNLIKELY(i > BM_LOOP_RADIAL_MAX)) {
- BMESH_ASSERT(0);
- return false;
- }
-
- i++;
- } while ((l_iter = l_iter->radial_next) != l);
-
- return true;
+ BMLoop *l_iter = l;
+ int i = 0;
+
+ if (bmesh_radial_length(l) != radlen) {
+ return false;
+ }
+
+ do {
+ if (UNLIKELY(!l_iter)) {
+ BMESH_ASSERT(0);
+ return false;
+ }
+
+ if (l_iter->e != l->e) {
+ return false;
+ }
+ if (l_iter->v != l->e->v1 && l_iter->v != l->e->v2) {
+ return false;
+ }
+
+ if (UNLIKELY(i > BM_LOOP_RADIAL_MAX)) {
+ BMESH_ASSERT(0);
+ return false;
+ }
+
+ i++;
+ } while ((l_iter = l_iter->radial_next) != l);
+
+ return true;
}
void bmesh_radial_loop_append(BMEdge *e, BMLoop *l)
{
- if (e->l == NULL) {
- e->l = l;
- l->radial_next = l->radial_prev = l;
- }
- else {
- l->radial_prev = e->l;
- l->radial_next = e->l->radial_next;
-
- e->l->radial_next->radial_prev = l;
- e->l->radial_next = l;
-
- e->l = l;
- }
-
- if (UNLIKELY(l->e && l->e != e)) {
- /* l is already in a radial cycle for a different edge */
- BMESH_ASSERT(0);
- }
-
- l->e = e;
+ if (e->l == NULL) {
+ e->l = l;
+ l->radial_next = l->radial_prev = l;
+ }
+ else {
+ l->radial_prev = e->l;
+ l->radial_next = e->l->radial_next;
+
+ e->l->radial_next->radial_prev = l;
+ e->l->radial_next = l;
+
+ e->l = l;
+ }
+
+ if (UNLIKELY(l->e && l->e != e)) {
+ /* l is already in a radial cycle for a different edge */
+ BMESH_ASSERT(0);
+ }
+
+ l->e = e;
}
/**
@@ -451,32 +451,32 @@ void bmesh_radial_loop_append(BMEdge *e, BMLoop *l)
*/
void bmesh_radial_loop_remove(BMEdge *e, BMLoop *l)
{
- /* if e is non-NULL, l must be in the radial cycle of e */
- if (UNLIKELY(e != l->e)) {
- BMESH_ASSERT(0);
- }
-
- if (l->radial_next != l) {
- if (l == e->l) {
- e->l = l->radial_next;
- }
-
- l->radial_next->radial_prev = l->radial_prev;
- l->radial_prev->radial_next = l->radial_next;
- }
- else {
- if (l == e->l) {
- e->l = NULL;
- }
- else {
- BMESH_ASSERT(0);
- }
- }
-
- /* l is no longer in a radial cycle; empty the links
- * to the cycle and the link back to an edge */
- l->radial_next = l->radial_prev = NULL;
- l->e = NULL;
+ /* if e is non-NULL, l must be in the radial cycle of e */
+ if (UNLIKELY(e != l->e)) {
+ BMESH_ASSERT(0);
+ }
+
+ if (l->radial_next != l) {
+ if (l == e->l) {
+ e->l = l->radial_next;
+ }
+
+ l->radial_next->radial_prev = l->radial_prev;
+ l->radial_prev->radial_next = l->radial_next;
+ }
+ else {
+ if (l == e->l) {
+ e->l = NULL;
+ }
+ else {
+ BMESH_ASSERT(0);
+ }
+ }
+
+ /* l is no longer in a radial cycle; empty the links
+ * to the cycle and the link back to an edge */
+ l->radial_next = l->radial_prev = NULL;
+ l->e = NULL;
}
/**
@@ -485,15 +485,15 @@ void bmesh_radial_loop_remove(BMEdge *e, BMLoop *l)
*/
void bmesh_radial_loop_unlink(BMLoop *l)
{
- if (l->radial_next != l) {
- l->radial_next->radial_prev = l->radial_prev;
- l->radial_prev->radial_next = l->radial_next;
- }
-
- /* l is no longer in a radial cycle; empty the links
- * to the cycle and the link back to an edge */
- l->radial_next = l->radial_prev = NULL;
- l->e = NULL;
+ if (l->radial_next != l) {
+ l->radial_next->radial_prev = l->radial_prev;
+ l->radial_prev->radial_next = l->radial_next;
+ }
+
+ /* l is no longer in a radial cycle; empty the links
+ * to the cycle and the link back to an edge */
+ l->radial_next = l->radial_prev = NULL;
+ l->e = NULL;
}
/**
@@ -504,52 +504,52 @@ void bmesh_radial_loop_unlink(BMLoop *l)
*/
BMLoop *bmesh_radial_faceloop_find_first(const BMLoop *l, const BMVert *v)
{
- const BMLoop *l_iter;
- l_iter = l;
- do {
- if (l_iter->v == v) {
- return (BMLoop *)l_iter;
- }
- } while ((l_iter = l_iter->radial_next) != l);
- return NULL;
+ const BMLoop *l_iter;
+ l_iter = l;
+ do {
+ if (l_iter->v == v) {
+ return (BMLoop *)l_iter;
+ }
+ } while ((l_iter = l_iter->radial_next) != l);
+ return NULL;
}
BMLoop *bmesh_radial_faceloop_find_next(const BMLoop *l, const BMVert *v)
{
- BMLoop *l_iter;
- l_iter = l->radial_next;
- do {
- if (l_iter->v == v) {
- return l_iter;
- }
- } while ((l_iter = l_iter->radial_next) != l);
- return (BMLoop *)l;
+ BMLoop *l_iter;
+ l_iter = l->radial_next;
+ do {
+ if (l_iter->v == v) {
+ return l_iter;
+ }
+ } while ((l_iter = l_iter->radial_next) != l);
+ return (BMLoop *)l;
}
int bmesh_radial_length(const BMLoop *l)
{
- const BMLoop *l_iter = l;
- int i = 0;
-
- if (!l) {
- return 0;
- }
-
- do {
- if (UNLIKELY(!l_iter)) {
- /* radial cycle is broken (not a circulat loop) */
- BMESH_ASSERT(0);
- return 0;
- }
-
- i++;
- if (UNLIKELY(i >= BM_LOOP_RADIAL_MAX)) {
- BMESH_ASSERT(0);
- return -1;
- }
- } while ((l_iter = l_iter->radial_next) != l);
-
- return i;
+ const BMLoop *l_iter = l;
+ int i = 0;
+
+ if (!l) {
+ return 0;
+ }
+
+ do {
+ if (UNLIKELY(!l_iter)) {
+ /* radial cycle is broken (not a circulat loop) */
+ BMESH_ASSERT(0);
+ return 0;
+ }
+
+ i++;
+ if (UNLIKELY(i >= BM_LOOP_RADIAL_MAX)) {
+ BMESH_ASSERT(0);
+ return -1;
+ }
+ } while ((l_iter = l_iter->radial_next) != l);
+
+ return i;
}
/**
@@ -560,33 +560,33 @@ int bmesh_radial_length(const BMLoop *l)
*/
int bmesh_radial_facevert_count(const BMLoop *l, const BMVert *v)
{
- const BMLoop *l_iter;
- int count = 0;
- l_iter = l;
- do {
- if (l_iter->v == v) {
- count++;
- }
- } while ((l_iter = l_iter->radial_next) != l);
-
- return count;
+ const BMLoop *l_iter;
+ int count = 0;
+ l_iter = l;
+ do {
+ if (l_iter->v == v) {
+ count++;
+ }
+ } while ((l_iter = l_iter->radial_next) != l);
+
+ return count;
}
int bmesh_radial_facevert_count_at_most(const BMLoop *l, const BMVert *v, const int count_max)
{
- const BMLoop *l_iter;
- int count = 0;
- l_iter = l;
- do {
- if (l_iter->v == v) {
- count++;
- if (count == count_max) {
- break;
- }
- }
- } while ((l_iter = l_iter->radial_next) != l);
-
- return count;
+ const BMLoop *l_iter;
+ int count = 0;
+ l_iter = l;
+ do {
+ if (l_iter->v == v) {
+ count++;
+ if (count == count_max) {
+ break;
+ }
+ }
+ } while ((l_iter = l_iter->radial_next) != l);
+
+ return count;
}
/**
@@ -596,51 +596,49 @@ int bmesh_radial_facevert_count_at_most(const BMLoop *l, const BMVert *v, const
*/
bool bmesh_radial_facevert_check(const BMLoop *l, const BMVert *v)
{
- const BMLoop *l_iter;
- l_iter = l;
- do {
- if (l_iter->v == v) {
- return true;
- }
- } while ((l_iter = l_iter->radial_next) != l);
-
- return false;
+ const BMLoop *l_iter;
+ l_iter = l;
+ do {
+ if (l_iter->v == v) {
+ return true;
+ }
+ } while ((l_iter = l_iter->radial_next) != l);
+
+ return false;
}
/*****loop cycle functions, e.g. loops surrounding a face**** */
bool bmesh_loop_validate(BMFace *f)
{
- int i;
- int len = f->len;
- BMLoop *l_iter, *l_first;
-
- l_first = BM_FACE_FIRST_LOOP(f);
-
- if (l_first == NULL) {
- return false;
- }
-
- /* Validate that the face loop cycle is the length specified by f->len */
- for (i = 1, l_iter = l_first->next; i < len; i++, l_iter = l_iter->next) {
- if ((l_iter->f != f) ||
- (l_iter == l_first))
- {
- return false;
- }
- }
- if (l_iter != l_first) {
- return false;
- }
-
- /* Validate the loop->prev links also form a cycle of length f->len */
- for (i = 1, l_iter = l_first->prev; i < len; i++, l_iter = l_iter->prev) {
- if (l_iter == l_first) {
- return false;
- }
- }
- if (l_iter != l_first) {
- return false;
- }
-
- return true;
+ int i;
+ int len = f->len;
+ BMLoop *l_iter, *l_first;
+
+ l_first = BM_FACE_FIRST_LOOP(f);
+
+ if (l_first == NULL) {
+ return false;
+ }
+
+ /* Validate that the face loop cycle is the length specified by f->len */
+ for (i = 1, l_iter = l_first->next; i < len; i++, l_iter = l_iter->next) {
+ if ((l_iter->f != f) || (l_iter == l_first)) {
+ return false;
+ }
+ }
+ if (l_iter != l_first) {
+ return false;
+ }
+
+ /* Validate the loop->prev links also form a cycle of length f->len */
+ for (i = 1, l_iter = l_first->prev; i < len; i++, l_iter = l_iter->prev) {
+ if (l_iter == l_first) {
+ return false;
+ }
+ }
+ if (l_iter != l_first) {
+ return false;
+ }
+
+ return true;
}
diff --git a/source/blender/bmesh/intern/bmesh_structure.h b/source/blender/bmesh/intern/bmesh_structure.h
index 8e3ba7b46c0..7ae55a5fa6f 100644
--- a/source/blender/bmesh/intern/bmesh_structure.h
+++ b/source/blender/bmesh/intern/bmesh_structure.h
@@ -32,44 +32,65 @@
*/
/* LOOP CYCLE MANAGEMENT */
-bool bmesh_loop_validate(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool bmesh_loop_validate(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
/* DISK CYCLE MANAGMENT */
-void bmesh_disk_edge_append(BMEdge *e, BMVert *v) ATTR_NONNULL();
-void bmesh_disk_edge_remove(BMEdge *e, BMVert *v) ATTR_NONNULL();
-BLI_INLINE BMEdge *bmesh_disk_edge_next_safe(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-BLI_INLINE BMEdge *bmesh_disk_edge_prev_safe(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-BLI_INLINE BMEdge *bmesh_disk_edge_next(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-BLI_INLINE BMEdge *bmesh_disk_edge_prev(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-int bmesh_disk_facevert_count_at_most(const BMVert *v, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-int bmesh_disk_facevert_count(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-BMEdge *bmesh_disk_faceedge_find_first(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-BMLoop *bmesh_disk_faceloop_find_first(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-BMLoop *bmesh_disk_faceloop_find_first_visible(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-BMEdge *bmesh_disk_faceedge_find_next(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+void bmesh_disk_edge_append(BMEdge *e, BMVert *v) ATTR_NONNULL();
+void bmesh_disk_edge_remove(BMEdge *e, BMVert *v) ATTR_NONNULL();
+BLI_INLINE BMEdge *bmesh_disk_edge_next_safe(const BMEdge *e,
+ const BMVert *v) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+BLI_INLINE BMEdge *bmesh_disk_edge_prev_safe(const BMEdge *e,
+ const BMVert *v) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+BLI_INLINE BMEdge *bmesh_disk_edge_next(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+BLI_INLINE BMEdge *bmesh_disk_edge_prev(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+int bmesh_disk_facevert_count_at_most(const BMVert *v, const int count_max) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+int bmesh_disk_facevert_count(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+BMEdge *bmesh_disk_faceedge_find_first(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+BMLoop *bmesh_disk_faceloop_find_first(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+BMLoop *bmesh_disk_faceloop_find_first_visible(const BMEdge *e,
+ const BMVert *v) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+BMEdge *bmesh_disk_faceedge_find_next(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
/* RADIAL CYCLE MANAGMENT */
-void bmesh_radial_loop_append(BMEdge *e, BMLoop *l) ATTR_NONNULL();
-void bmesh_radial_loop_remove(BMEdge *e, BMLoop *l) ATTR_NONNULL();
-void bmesh_radial_loop_unlink(BMLoop *l) ATTR_NONNULL();
+void bmesh_radial_loop_append(BMEdge *e, BMLoop *l) ATTR_NONNULL();
+void bmesh_radial_loop_remove(BMEdge *e, BMLoop *l) ATTR_NONNULL();
+void bmesh_radial_loop_unlink(BMLoop *l) ATTR_NONNULL();
/* note:
* bmesh_radial_loop_next(BMLoop *l) / prev.
* just use member access l->radial_next, l->radial_prev now */
-int bmesh_radial_facevert_count_at_most(const BMLoop *l, const BMVert *v, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-int bmesh_radial_facevert_count(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool bmesh_radial_facevert_check(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-BMLoop *bmesh_radial_faceloop_find_first(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-BMLoop *bmesh_radial_faceloop_find_next(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-BMLoop *bmesh_radial_faceloop_find_vert(const BMFace *f, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool bmesh_radial_validate(int radlen, BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int bmesh_radial_facevert_count_at_most(const BMLoop *l,
+ const BMVert *v,
+ const int count_max) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+int bmesh_radial_facevert_count(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+bool bmesh_radial_facevert_check(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+BMLoop *bmesh_radial_faceloop_find_first(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+BMLoop *bmesh_radial_faceloop_find_next(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+BMLoop *bmesh_radial_faceloop_find_vert(const BMFace *f, const BMVert *v) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+bool bmesh_radial_validate(int radlen, BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
/* EDGE UTILITIES */
-void bmesh_disk_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src) ATTR_NONNULL();
-void bmesh_edge_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src) ATTR_NONNULL();
-void bmesh_disk_vert_replace(BMEdge *e, BMVert *v_dst, BMVert *v_src) ATTR_NONNULL();
-BMEdge *bmesh_disk_edge_exists(const BMVert *v1, const BMVert *v2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-bool bmesh_disk_validate(int len, BMEdge *e, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+void bmesh_disk_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src) ATTR_NONNULL();
+void bmesh_edge_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src) ATTR_NONNULL();
+void bmesh_disk_vert_replace(BMEdge *e, BMVert *v_dst, BMVert *v_src) ATTR_NONNULL();
+BMEdge *bmesh_disk_edge_exists(const BMVert *v1, const BMVert *v2) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+bool bmesh_disk_validate(int len, BMEdge *e, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
#include "intern/bmesh_structure_inline.h"
diff --git a/source/blender/bmesh/intern/bmesh_structure_inline.h b/source/blender/bmesh/intern/bmesh_structure_inline.h
index 0998d9bd907..26d161693af 100644
--- a/source/blender/bmesh/intern/bmesh_structure_inline.h
+++ b/source/blender/bmesh/intern/bmesh_structure_inline.h
@@ -24,10 +24,10 @@
#define __BMESH_STRUCTURE_INLINE_H__
ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2)
-BLI_INLINE BMDiskLink *bmesh_disk_edge_link_from_vert(const BMEdge *e, const BMVert *v)
+ BLI_INLINE BMDiskLink *bmesh_disk_edge_link_from_vert(const BMEdge *e, const BMVert *v)
{
- BLI_assert(BM_vert_in_edge(e, v));
- return (BMDiskLink *)&(&e->v1_disk_link)[v == e->v2];
+ BLI_assert(BM_vert_in_edge(e, v));
+ return (BMDiskLink *)&(&e->v1_disk_link)[v == e->v2];
}
/**
@@ -38,39 +38,39 @@ BLI_INLINE BMDiskLink *bmesh_disk_edge_link_from_vert(const BMEdge *e, const BMV
* \return Pointer to the next edge in the disk cycle for the vertex v.
*/
ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
-BLI_INLINE BMEdge *bmesh_disk_edge_next_safe(const BMEdge *e, const BMVert *v)
+ BLI_INLINE BMEdge *bmesh_disk_edge_next_safe(const BMEdge *e, const BMVert *v)
{
- if (v == e->v1) {
- return e->v1_disk_link.next;
- }
- if (v == e->v2) {
- return e->v2_disk_link.next;
- }
- return NULL;
+ if (v == e->v1) {
+ return e->v1_disk_link.next;
+ }
+ if (v == e->v2) {
+ return e->v2_disk_link.next;
+ }
+ return NULL;
}
ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
-BLI_INLINE BMEdge *bmesh_disk_edge_prev_safe(const BMEdge *e, const BMVert *v)
+ BLI_INLINE BMEdge *bmesh_disk_edge_prev_safe(const BMEdge *e, const BMVert *v)
{
- if (v == e->v1) {
- return e->v1_disk_link.prev;
- }
- if (v == e->v2) {
- return e->v2_disk_link.prev;
- }
- return NULL;
+ if (v == e->v1) {
+ return e->v1_disk_link.prev;
+ }
+ if (v == e->v2) {
+ return e->v2_disk_link.prev;
+ }
+ return NULL;
}
-ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2)
-BLI_INLINE BMEdge *bmesh_disk_edge_next(const BMEdge *e, const BMVert *v)
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) BLI_INLINE BMEdge *bmesh_disk_edge_next(const BMEdge *e,
+ const BMVert *v)
{
- return BM_DISK_EDGE_NEXT(e, v);
+ return BM_DISK_EDGE_NEXT(e, v);
}
-ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2)
-BLI_INLINE BMEdge *bmesh_disk_edge_prev(const BMEdge *e, const BMVert *v)
+ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) BLI_INLINE BMEdge *bmesh_disk_edge_prev(const BMEdge *e,
+ const BMVert *v)
{
- return BM_DISK_EDGE_PREV(e, v);
+ return BM_DISK_EDGE_PREV(e, v);
}
#endif /* __BMESH_STRUCTURE_INLINE_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_walkers.c b/source/blender/bmesh/intern/bmesh_walkers.c
index 011addc9220..b850c87d5aa 100644
--- a/source/blender/bmesh/intern/bmesh_walkers.c
+++ b/source/blender/bmesh/intern/bmesh_walkers.c
@@ -54,11 +54,11 @@
void *BMW_begin(BMWalker *walker, void *start)
{
- BLI_assert(((BMHeader *)start)->htype & walker->begin_htype);
+ BLI_assert(((BMHeader *)start)->htype & walker->begin_htype);
- walker->begin(walker, start);
+ walker->begin(walker, start);
- return BMW_current_state(walker) ? walker->step(walker) : NULL;
+ return BMW_current_state(walker) ? walker->step(walker) : NULL;
}
/**
@@ -68,53 +68,62 @@ void *BMW_begin(BMWalker *walker, void *start)
* a given type. The elements visited are filtered
* by the bitmask 'searchmask'.
*/
-void BMW_init(
- BMWalker *walker, BMesh *bm, int type,
- short mask_vert, short mask_edge, short mask_face,
- BMWFlag flag,
- int layer)
+void BMW_init(BMWalker *walker,
+ BMesh *bm,
+ int type,
+ short mask_vert,
+ short mask_edge,
+ short mask_face,
+ BMWFlag flag,
+ int layer)
{
- memset(walker, 0, sizeof(BMWalker));
+ memset(walker, 0, sizeof(BMWalker));
- walker->layer = layer;
- walker->flag = flag;
- walker->bm = bm;
+ walker->layer = layer;
+ walker->flag = flag;
+ walker->bm = bm;
- walker->mask_vert = mask_vert;
- walker->mask_edge = mask_edge;
- walker->mask_face = mask_face;
+ walker->mask_vert = mask_vert;
+ walker->mask_edge = mask_edge;
+ walker->mask_face = mask_face;
- walker->visit_set = BLI_gset_ptr_new("bmesh walkers");
- walker->visit_set_alt = BLI_gset_ptr_new("bmesh walkers sec");
+ walker->visit_set = BLI_gset_ptr_new("bmesh walkers");
+ walker->visit_set_alt = BLI_gset_ptr_new("bmesh walkers sec");
- if (UNLIKELY(type >= BMW_MAXWALKERS || type < 0)) {
- fprintf(stderr,
- "%s: Invalid walker type in BMW_init; type: %d, "
- "searchmask: (v:%d, e:%d, f:%d), flag: %u, layer: %d\n",
- __func__, type, mask_vert, mask_edge, mask_face, flag, layer);
- BLI_assert(0);
- return;
- }
+ if (UNLIKELY(type >= BMW_MAXWALKERS || type < 0)) {
+ fprintf(stderr,
+ "%s: Invalid walker type in BMW_init; type: %d, "
+ "searchmask: (v:%d, e:%d, f:%d), flag: %u, layer: %d\n",
+ __func__,
+ type,
+ mask_vert,
+ mask_edge,
+ mask_face,
+ flag,
+ layer);
+ BLI_assert(0);
+ return;
+ }
- if (type != BMW_CUSTOM) {
- walker->begin_htype = bm_walker_types[type]->begin_htype;
- walker->begin = bm_walker_types[type]->begin;
- walker->yield = bm_walker_types[type]->yield;
- walker->step = bm_walker_types[type]->step;
- walker->structsize = bm_walker_types[type]->structsize;
- walker->order = bm_walker_types[type]->order;
- walker->valid_mask = bm_walker_types[type]->valid_mask;
+ if (type != BMW_CUSTOM) {
+ walker->begin_htype = bm_walker_types[type]->begin_htype;
+ walker->begin = bm_walker_types[type]->begin;
+ walker->yield = bm_walker_types[type]->yield;
+ walker->step = bm_walker_types[type]->step;
+ walker->structsize = bm_walker_types[type]->structsize;
+ walker->order = bm_walker_types[type]->order;
+ walker->valid_mask = bm_walker_types[type]->valid_mask;
- /* safety checks */
- /* if this raises an error either the caller is wrong or
- * 'bm_walker_types' needs updating */
- BLI_assert(mask_vert == 0 || (walker->valid_mask & BM_VERT));
- BLI_assert(mask_edge == 0 || (walker->valid_mask & BM_EDGE));
- BLI_assert(mask_face == 0 || (walker->valid_mask & BM_FACE));
- }
+ /* safety checks */
+ /* if this raises an error either the caller is wrong or
+ * 'bm_walker_types' needs updating */
+ BLI_assert(mask_vert == 0 || (walker->valid_mask & BM_VERT));
+ BLI_assert(mask_edge == 0 || (walker->valid_mask & BM_EDGE));
+ BLI_assert(mask_face == 0 || (walker->valid_mask & BM_FACE));
+ }
- walker->worklist = BLI_mempool_create(walker->structsize, 0, 128, BLI_MEMPOOL_NOP);
- BLI_listbase_clear(&walker->states);
+ walker->worklist = BLI_mempool_create(walker->structsize, 0, 128, BLI_MEMPOOL_NOP);
+ BLI_listbase_clear(&walker->states);
}
/**
@@ -124,22 +133,21 @@ void BMW_init(
*/
void BMW_end(BMWalker *walker)
{
- BLI_mempool_destroy(walker->worklist);
- BLI_gset_free(walker->visit_set, NULL);
- BLI_gset_free(walker->visit_set_alt, NULL);
+ BLI_mempool_destroy(walker->worklist);
+ BLI_gset_free(walker->visit_set, NULL);
+ BLI_gset_free(walker->visit_set_alt, NULL);
}
-
/**
* \brief Step Walker
*/
void *BMW_step(BMWalker *walker)
{
- BMHeader *head;
+ BMHeader *head;
- head = BMW_walk(walker);
+ head = BMW_walk(walker);
- return head;
+ return head;
}
/**
@@ -150,7 +158,7 @@ void *BMW_step(BMWalker *walker)
int BMW_current_depth(BMWalker *walker)
{
- return walker->depth;
+ return walker->depth;
}
/**
@@ -160,15 +168,15 @@ int BMW_current_depth(BMWalker *walker)
*/
void *BMW_walk(BMWalker *walker)
{
- void *current = NULL;
+ void *current = NULL;
- while (BMW_current_state(walker)) {
- current = walker->step(walker);
- if (current) {
- return current;
- }
- }
- return NULL;
+ while (BMW_current_state(walker)) {
+ current = walker->step(walker);
+ if (current) {
+ return current;
+ }
+ }
+ return NULL;
}
/**
@@ -180,21 +188,21 @@ void *BMW_walk(BMWalker *walker)
*/
void *BMW_current_state(BMWalker *walker)
{
- BMwGenericWalker *currentstate = walker->states.first;
- if (currentstate) {
- /* Automatic update of depth. For most walkers that
- * follow the standard "Step" pattern of:
- * - read current state
- * - remove current state
- * - push new states
- * - return walk result from just-removed current state
- * this simple automatic update should keep track of depth
- * just fine. Walkers that deviate from that pattern may
- * need to manually update the depth if they care about
- * keeping it correct. */
- walker->depth = currentstate->depth + 1;
- }
- return currentstate;
+ BMwGenericWalker *currentstate = walker->states.first;
+ if (currentstate) {
+ /* Automatic update of depth. For most walkers that
+ * follow the standard "Step" pattern of:
+ * - read current state
+ * - remove current state
+ * - push new states
+ * - return walk result from just-removed current state
+ * this simple automatic update should keep track of depth
+ * just fine. Walkers that deviate from that pattern may
+ * need to manually update the depth if they care about
+ * keeping it correct. */
+ walker->depth = currentstate->depth + 1;
+ }
+ return currentstate;
}
/**
@@ -205,10 +213,10 @@ void *BMW_current_state(BMWalker *walker)
*/
void BMW_state_remove(BMWalker *walker)
{
- void *oldstate;
- oldstate = BMW_current_state(walker);
- BLI_remlink(&walker->states, oldstate);
- BLI_mempool_free(walker->worklist, oldstate);
+ void *oldstate;
+ oldstate = BMW_current_state(walker);
+ BLI_remlink(&walker->states, oldstate);
+ BLI_mempool_free(walker->worklist, oldstate);
}
/**
@@ -222,21 +230,21 @@ void BMW_state_remove(BMWalker *walker)
*/
void *BMW_state_add(BMWalker *walker)
{
- BMwGenericWalker *newstate;
- newstate = BLI_mempool_alloc(walker->worklist);
- newstate->depth = walker->depth;
- switch (walker->order) {
- case BMW_DEPTH_FIRST:
- BLI_addhead(&walker->states, newstate);
- break;
- case BMW_BREADTH_FIRST:
- BLI_addtail(&walker->states, newstate);
- break;
- default:
- BLI_assert(0);
- break;
- }
- return newstate;
+ BMwGenericWalker *newstate;
+ newstate = BLI_mempool_alloc(walker->worklist);
+ newstate->depth = walker->depth;
+ switch (walker->order) {
+ case BMW_DEPTH_FIRST:
+ BLI_addhead(&walker->states, newstate);
+ break;
+ case BMW_BREADTH_FIRST:
+ BLI_addtail(&walker->states, newstate);
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
+ return newstate;
}
/**
@@ -247,10 +255,10 @@ void *BMW_state_add(BMWalker *walker)
*/
void BMW_reset(BMWalker *walker)
{
- while (BMW_current_state(walker)) {
- BMW_state_remove(walker);
- }
- walker->depth = 0;
- BLI_gset_clear(walker->visit_set, NULL);
- BLI_gset_clear(walker->visit_set_alt, NULL);
+ while (BMW_current_state(walker)) {
+ BMW_state_remove(walker);
+ }
+ walker->depth = 0;
+ BLI_gset_clear(walker->visit_set, NULL);
+ BLI_gset_clear(walker->visit_set_alt, NULL);
}
diff --git a/source/blender/bmesh/intern/bmesh_walkers.h b/source/blender/bmesh/intern/bmesh_walkers.h
index 3de7d6d2c90..54cfccb9ed8 100644
--- a/source/blender/bmesh/intern/bmesh_walkers.h
+++ b/source/blender/bmesh/intern/bmesh_walkers.h
@@ -26,43 +26,43 @@
*/
typedef enum {
- BMW_DEPTH_FIRST,
- BMW_BREADTH_FIRST,
+ BMW_DEPTH_FIRST,
+ BMW_BREADTH_FIRST,
} BMWOrder;
typedef enum {
- BMW_FLAG_NOP = 0,
- BMW_FLAG_TEST_HIDDEN = (1 << 0),
+ BMW_FLAG_NOP = 0,
+ BMW_FLAG_TEST_HIDDEN = (1 << 0),
} BMWFlag;
/*Walkers*/
typedef struct BMWalker {
- char begin_htype; /* only for validating input */
- void (*begin) (struct BMWalker *walker, void *start);
- void *(*step) (struct BMWalker *walker);
- void *(*yield) (struct BMWalker *walker);
- int structsize;
- BMWOrder order;
- int valid_mask;
-
- /* runtime */
- int layer;
-
- BMesh *bm;
- BLI_mempool *worklist;
- ListBase states;
-
- /* these masks are to be tested against elements BMO_elem_flag_test(),
- * should never be accessed directly only through BMW_init() and bmw_mask_check_*() functions */
- short mask_vert;
- short mask_edge;
- short mask_face;
-
- BMWFlag flag;
-
- struct GSet *visit_set;
- struct GSet *visit_set_alt;
- int depth;
+ char begin_htype; /* only for validating input */
+ void (*begin)(struct BMWalker *walker, void *start);
+ void *(*step)(struct BMWalker *walker);
+ void *(*yield)(struct BMWalker *walker);
+ int structsize;
+ BMWOrder order;
+ int valid_mask;
+
+ /* runtime */
+ int layer;
+
+ BMesh *bm;
+ BLI_mempool *worklist;
+ ListBase states;
+
+ /* these masks are to be tested against elements BMO_elem_flag_test(),
+ * should never be accessed directly only through BMW_init() and bmw_mask_check_*() functions */
+ short mask_vert;
+ short mask_edge;
+ short mask_face;
+
+ BMWFlag flag;
+
+ struct GSet *visit_set;
+ struct GSet *visit_set_alt;
+ int depth;
} BMWalker;
/* define to make BMW_init more clear */
@@ -70,27 +70,29 @@ typedef struct BMWalker {
/* initialize a walker. searchmask restricts some (not all) walkers to
* elements with a specific tool flag set. flags is specific to each walker.*/
-void BMW_init(
- struct BMWalker *walker, BMesh *bm, int type,
- short mask_vert, short mask_edge, short mask_face,
- BMWFlag flag,
- int layer);
+void BMW_init(struct BMWalker *walker,
+ BMesh *bm,
+ int type,
+ short mask_vert,
+ short mask_edge,
+ short mask_face,
+ BMWFlag flag,
+ int layer);
void *BMW_begin(BMWalker *walker, void *start);
void *BMW_step(struct BMWalker *walker);
-void BMW_end(struct BMWalker *walker);
-int BMW_current_depth(BMWalker *walker);
+void BMW_end(struct BMWalker *walker);
+int BMW_current_depth(BMWalker *walker);
/*these are used by custom walkers*/
void *BMW_current_state(BMWalker *walker);
void *BMW_state_add(BMWalker *walker);
-void BMW_state_remove(BMWalker *walker);
+void BMW_state_remove(BMWalker *walker);
void *BMW_walk(BMWalker *walker);
-void BMW_reset(BMWalker *walker);
+void BMW_reset(BMWalker *walker);
#define BMW_ITER(ele, walker, data) \
- for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMW_begin(walker, (BM_CHECK_TYPE_ELEM(data), data)); \
- ele; \
- BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMW_step(walker))
+ for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMW_begin(walker, (BM_CHECK_TYPE_ELEM(data), data)); ele; \
+ BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMW_step(walker))
/*
* example of usage, walking over an island of tool flagged faces:
@@ -107,28 +109,28 @@ void BMW_reset(BMWalker *walker);
*/
enum {
- BMW_VERT_SHELL,
- BMW_LOOP_SHELL,
- BMW_LOOP_SHELL_WIRE,
- BMW_FACE_SHELL,
- BMW_EDGELOOP,
- BMW_FACELOOP,
- BMW_EDGERING,
- BMW_EDGEBOUNDARY,
- /* BMW_RING, */
- BMW_LOOPDATA_ISLAND,
- BMW_ISLANDBOUND,
- BMW_ISLAND,
- BMW_ISLAND_MANIFOLD,
- BMW_CONNECTED_VERTEX,
- /* end of array index enum vals */
-
- /* do not intitialze function pointers and struct size in BMW_init */
- BMW_CUSTOM,
- BMW_MAXWALKERS,
+ BMW_VERT_SHELL,
+ BMW_LOOP_SHELL,
+ BMW_LOOP_SHELL_WIRE,
+ BMW_FACE_SHELL,
+ BMW_EDGELOOP,
+ BMW_FACELOOP,
+ BMW_EDGERING,
+ BMW_EDGEBOUNDARY,
+ /* BMW_RING, */
+ BMW_LOOPDATA_ISLAND,
+ BMW_ISLANDBOUND,
+ BMW_ISLAND,
+ BMW_ISLAND_MANIFOLD,
+ BMW_CONNECTED_VERTEX,
+ /* end of array index enum vals */
+
+ /* do not intitialze function pointers and struct size in BMW_init */
+ BMW_CUSTOM,
+ BMW_MAXWALKERS,
};
/* use with BMW_init, so as not to confuse with restrict flags */
-#define BMW_NIL_LAY 0
+#define BMW_NIL_LAY 0
#endif /* __BMESH_WALKERS_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_walkers_impl.c b/source/blender/bmesh/intern/bmesh_walkers_impl.c
index 0ac9b958c11..c327c10226f 100644
--- a/source/blender/bmesh/intern/bmesh_walkers_impl.c
+++ b/source/blender/bmesh/intern/bmesh_walkers_impl.c
@@ -30,56 +30,57 @@
#include "intern/bmesh_walkers_private.h"
/* pop into stack memory (common operation) */
-#define BMW_state_remove_r(walker, owalk) { \
- memcpy(owalk, BMW_current_state(walker), sizeof(*(owalk))); \
- BMW_state_remove(walker); \
-} (void)0
+#define BMW_state_remove_r(walker, owalk) \
+ { \
+ memcpy(owalk, BMW_current_state(walker), sizeof(*(owalk))); \
+ BMW_state_remove(walker); \
+ } \
+ (void)0
/** \name Mask Flag Checks
* \{ */
static bool bmw_mask_check_vert(BMWalker *walker, BMVert *v)
{
- if ((walker->flag & BMW_FLAG_TEST_HIDDEN) && BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
- return false;
- }
- else if (walker->mask_vert && !BMO_vert_flag_test(walker->bm, v, walker->mask_vert)) {
- return false;
- }
- else {
- return true;
- }
+ if ((walker->flag & BMW_FLAG_TEST_HIDDEN) && BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
+ return false;
+ }
+ else if (walker->mask_vert && !BMO_vert_flag_test(walker->bm, v, walker->mask_vert)) {
+ return false;
+ }
+ else {
+ return true;
+ }
}
static bool bmw_mask_check_edge(BMWalker *walker, BMEdge *e)
{
- if ((walker->flag & BMW_FLAG_TEST_HIDDEN) && BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
- return false;
- }
- else if (walker->mask_edge && !BMO_edge_flag_test(walker->bm, e, walker->mask_edge)) {
- return false;
- }
- else {
- return true;
- }
+ if ((walker->flag & BMW_FLAG_TEST_HIDDEN) && BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
+ return false;
+ }
+ else if (walker->mask_edge && !BMO_edge_flag_test(walker->bm, e, walker->mask_edge)) {
+ return false;
+ }
+ else {
+ return true;
+ }
}
static bool bmw_mask_check_face(BMWalker *walker, BMFace *f)
{
- if ((walker->flag & BMW_FLAG_TEST_HIDDEN) && BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
- return false;
- }
- else if (walker->mask_face && !BMO_face_flag_test(walker->bm, f, walker->mask_face)) {
- return false;
- }
- else {
- return true;
- }
+ if ((walker->flag & BMW_FLAG_TEST_HIDDEN) && BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+ return false;
+ }
+ else if (walker->mask_face && !BMO_face_flag_test(walker->bm, f, walker->mask_face)) {
+ return false;
+ }
+ else {
+ return true;
+ }
}
/** \} */
-
/** \name BMesh Queries (modified to check walker flags)
* \{ */
@@ -88,22 +89,21 @@ static bool bmw_mask_check_face(BMWalker *walker, BMFace *f)
*/
static bool bmw_edge_is_wire(const BMWalker *walker, const BMEdge *e)
{
- if (walker->flag & BMW_FLAG_TEST_HIDDEN) {
- /* check if this is a wire edge, ignoring hidden faces */
- if (BM_edge_is_wire(e)) {
- return true;
- }
- else {
- return BM_edge_is_all_face_flag_test(e, BM_ELEM_HIDDEN, false);
- }
- }
- else {
- return BM_edge_is_wire(e);
- }
+ if (walker->flag & BMW_FLAG_TEST_HIDDEN) {
+ /* check if this is a wire edge, ignoring hidden faces */
+ if (BM_edge_is_wire(e)) {
+ return true;
+ }
+ else {
+ return BM_edge_is_all_face_flag_test(e, BM_ELEM_HIDDEN, false);
+ }
+ }
+ else {
+ return BM_edge_is_wire(e);
+ }
}
/** \} */
-
/** \name Shell Walker
* \{
*
@@ -117,125 +117,123 @@ static bool bmw_edge_is_wire(const BMWalker *walker, const BMEdge *e)
*/
static void bmw_VertShellWalker_visitEdge(BMWalker *walker, BMEdge *e)
{
- BMwShellWalker *shellWalk = NULL;
+ BMwShellWalker *shellWalk = NULL;
- if (BLI_gset_haskey(walker->visit_set, e)) {
- return;
- }
+ if (BLI_gset_haskey(walker->visit_set, e)) {
+ return;
+ }
- if (!bmw_mask_check_edge(walker, e)) {
- return;
- }
+ if (!bmw_mask_check_edge(walker, e)) {
+ return;
+ }
- shellWalk = BMW_state_add(walker);
- shellWalk->curedge = e;
- BLI_gset_insert(walker->visit_set, e);
+ shellWalk = BMW_state_add(walker);
+ shellWalk->curedge = e;
+ BLI_gset_insert(walker->visit_set, e);
}
static void bmw_VertShellWalker_begin(BMWalker *walker, void *data)
{
- BMIter eiter;
- BMHeader *h = data;
- BMEdge *e;
- BMVert *v;
-
- if (UNLIKELY(h == NULL)) {
- return;
- }
-
- switch (h->htype) {
- case BM_VERT:
- {
- /* starting the walk at a vert, add all the edges
- * to the worklist */
- v = (BMVert *)h;
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- bmw_VertShellWalker_visitEdge(walker, e);
- }
- break;
- }
-
- case BM_EDGE:
- {
- /* starting the walk at an edge, add the single edge
- * to the worklist */
- e = (BMEdge *)h;
- bmw_VertShellWalker_visitEdge(walker, e);
- break;
- }
- default:
- BLI_assert(0);
- }
+ BMIter eiter;
+ BMHeader *h = data;
+ BMEdge *e;
+ BMVert *v;
+
+ if (UNLIKELY(h == NULL)) {
+ return;
+ }
+
+ switch (h->htype) {
+ case BM_VERT: {
+ /* starting the walk at a vert, add all the edges
+ * to the worklist */
+ v = (BMVert *)h;
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ bmw_VertShellWalker_visitEdge(walker, e);
+ }
+ break;
+ }
+
+ case BM_EDGE: {
+ /* starting the walk at an edge, add the single edge
+ * to the worklist */
+ e = (BMEdge *)h;
+ bmw_VertShellWalker_visitEdge(walker, e);
+ break;
+ }
+ default:
+ BLI_assert(0);
+ }
}
static void *bmw_VertShellWalker_yield(BMWalker *walker)
{
- BMwShellWalker *shellWalk = BMW_current_state(walker);
- return shellWalk->curedge;
+ BMwShellWalker *shellWalk = BMW_current_state(walker);
+ return shellWalk->curedge;
}
static void *bmw_VertShellWalker_step(BMWalker *walker)
{
- BMwShellWalker *swalk, owalk;
- BMEdge *e, *e2;
- BMVert *v;
- BMIter iter;
- int i;
+ BMwShellWalker *swalk, owalk;
+ BMEdge *e, *e2;
+ BMVert *v;
+ BMIter iter;
+ int i;
- BMW_state_remove_r(walker, &owalk);
- swalk = &owalk;
+ BMW_state_remove_r(walker, &owalk);
+ swalk = &owalk;
- e = swalk->curedge;
+ e = swalk->curedge;
- for (i = 0; i < 2; i++) {
- v = i ? e->v2 : e->v1;
- BM_ITER_ELEM (e2, &iter, v, BM_EDGES_OF_VERT) {
- bmw_VertShellWalker_visitEdge(walker, e2);
- }
- }
+ for (i = 0; i < 2; i++) {
+ v = i ? e->v2 : e->v1;
+ BM_ITER_ELEM (e2, &iter, v, BM_EDGES_OF_VERT) {
+ bmw_VertShellWalker_visitEdge(walker, e2);
+ }
+ }
- return e;
+ return e;
}
#if 0
static void *bmw_VertShellWalker_step(BMWalker *walker)
{
- BMEdge *curedge, *next = NULL;
- BMVert *v_old = NULL;
- bool restrictpass = true;
- BMwShellWalker shellWalk = *((BMwShellWalker *)BMW_current_state(walker));
+ BMEdge *curedge, *next = NULL;
+ BMVert *v_old = NULL;
+ bool restrictpass = true;
+ BMwShellWalker shellWalk = *((BMwShellWalker *)BMW_current_state(walker));
- if (!BLI_gset_haskey(walker->visit_set, shellWalk.base)) {
- BLI_gset_insert(walker->visit_set, shellWalk.base);
- }
+ if (!BLI_gset_haskey(walker->visit_set, shellWalk.base)) {
+ BLI_gset_insert(walker->visit_set, shellWalk.base);
+ }
- BMW_state_remove(walker);
+ BMW_state_remove(walker);
- /* find the next edge whose other vertex has not been visite */
- curedge = shellWalk.curedge;
- do {
- if (!BLI_gset_haskey(walker->visit_set, curedge)) {
- if (!walker->restrictflag ||
- (walker->restrictflag && BMO_edge_flag_test(walker->bm, curedge, walker->restrictflag)))
- {
- BMwShellWalker *newstate;
+ /* find the next edge whose other vertex has not been visite */
+ curedge = shellWalk.curedge;
+ do {
+ if (!BLI_gset_haskey(walker->visit_set, curedge)) {
+ if (!walker->restrictflag ||
+ (walker->restrictflag && BMO_edge_flag_test(walker->bm, curedge, walker->restrictflag)))
+ {
+ BMwShellWalker *newstate;
- v_old = BM_edge_other_vert(curedge, shellWalk.base);
+ v_old = BM_edge_other_vert(curedge, shellWalk.base);
- /* push a new state onto the stac */
- newState = BMW_state_add(walker);
- BLI_gset_insert(walker->visit_set, curedge);
+ /* push a new state onto the stac */
+ newState = BMW_state_add(walker);
+ BLI_gset_insert(walker->visit_set, curedge);
- /* populate the new stat */
+ /* populate the new stat */
- newState->base = v_old;
- newState->curedge = curedge;
- }
- }
- } while ((curedge = bmesh_disk_edge_next(curedge, shellWalk.base)) != shellWalk.curedge);
+ newState->base = v_old;
+ newState->curedge = curedge;
+ }
+ }
+ } while ((curedge = bmesh_disk_edge_next(curedge, shellWalk.base)) != shellWalk.curedge);
- return shellWalk.curedge;
+ return shellWalk.curedge;
}
#endif
@@ -251,120 +249,116 @@ static void *bmw_VertShellWalker_step(BMWalker *walker)
*/
static void bmw_LoopShellWalker_visitLoop(BMWalker *walker, BMLoop *l)
{
- BMwLoopShellWalker *shellWalk = NULL;
+ BMwLoopShellWalker *shellWalk = NULL;
- if (BLI_gset_haskey(walker->visit_set, l)) {
- return;
- }
+ if (BLI_gset_haskey(walker->visit_set, l)) {
+ return;
+ }
- if (!bmw_mask_check_face(walker, l->f)) {
- return;
- }
+ if (!bmw_mask_check_face(walker, l->f)) {
+ return;
+ }
- shellWalk = BMW_state_add(walker);
- shellWalk->curloop = l;
- BLI_gset_insert(walker->visit_set, l);
+ shellWalk = BMW_state_add(walker);
+ shellWalk->curloop = l;
+ BLI_gset_insert(walker->visit_set, l);
}
static void bmw_LoopShellWalker_begin(BMWalker *walker, void *data)
{
- BMIter iter;
- BMHeader *h = data;
-
- if (UNLIKELY(h == NULL)) {
- return;
- }
-
- switch (h->htype) {
- case BM_LOOP:
- {
- /* starting the walk at a vert, add all the edges
- * to the worklist */
- BMLoop *l = (BMLoop *)h;
- bmw_LoopShellWalker_visitLoop(walker, l);
- break;
- }
-
- case BM_VERT:
- {
- BMVert *v = (BMVert *)h;
- BMLoop *l;
- BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
- bmw_LoopShellWalker_visitLoop(walker, l);
- }
- break;
- }
- case BM_EDGE:
- {
- BMEdge *e = (BMEdge *)h;
- BMLoop *l;
- BM_ITER_ELEM (l, &iter, e, BM_LOOPS_OF_EDGE) {
- bmw_LoopShellWalker_visitLoop(walker, l);
- }
- break;
- }
- case BM_FACE:
- {
- BMFace *f = (BMFace *)h;
- BMLoop *l = BM_FACE_FIRST_LOOP(f);
- /* walker will handle other loops within the face */
- bmw_LoopShellWalker_visitLoop(walker, l);
- break;
- }
- default:
- BLI_assert(0);
- }
+ BMIter iter;
+ BMHeader *h = data;
+
+ if (UNLIKELY(h == NULL)) {
+ return;
+ }
+
+ switch (h->htype) {
+ case BM_LOOP: {
+ /* starting the walk at a vert, add all the edges
+ * to the worklist */
+ BMLoop *l = (BMLoop *)h;
+ bmw_LoopShellWalker_visitLoop(walker, l);
+ break;
+ }
+
+ case BM_VERT: {
+ BMVert *v = (BMVert *)h;
+ BMLoop *l;
+ BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
+ bmw_LoopShellWalker_visitLoop(walker, l);
+ }
+ break;
+ }
+ case BM_EDGE: {
+ BMEdge *e = (BMEdge *)h;
+ BMLoop *l;
+ BM_ITER_ELEM (l, &iter, e, BM_LOOPS_OF_EDGE) {
+ bmw_LoopShellWalker_visitLoop(walker, l);
+ }
+ break;
+ }
+ case BM_FACE: {
+ BMFace *f = (BMFace *)h;
+ BMLoop *l = BM_FACE_FIRST_LOOP(f);
+ /* walker will handle other loops within the face */
+ bmw_LoopShellWalker_visitLoop(walker, l);
+ break;
+ }
+ default:
+ BLI_assert(0);
+ }
}
static void *bmw_LoopShellWalker_yield(BMWalker *walker)
{
- BMwLoopShellWalker *shellWalk = BMW_current_state(walker);
- return shellWalk->curloop;
+ BMwLoopShellWalker *shellWalk = BMW_current_state(walker);
+ return shellWalk->curloop;
}
static void bmw_LoopShellWalker_step_impl(BMWalker *walker, BMLoop *l)
{
- BMEdge *e_edj_pair[2];
- int i;
-
- /* seems paranoid, but one caller also walks edges */
- BLI_assert(l->head.htype == BM_LOOP);
-
- bmw_LoopShellWalker_visitLoop(walker, l->next);
- bmw_LoopShellWalker_visitLoop(walker, l->prev);
-
- e_edj_pair[0] = l->e;
- e_edj_pair[1] = l->prev->e;
-
- for (i = 0; i < 2; i++) {
- BMEdge *e = e_edj_pair[i];
- if (bmw_mask_check_edge(walker, e)) {
- BMLoop *l_iter, *l_first;
-
- l_iter = l_first = e->l;
- do {
- BMLoop *l_radial = (l_iter->v == l->v) ? l_iter : l_iter->next;
- BLI_assert(l_radial->v == l->v);
- if (l != l_radial) {
- bmw_LoopShellWalker_visitLoop(walker, l_radial);
- }
- } while ((l_iter = l_iter->radial_next) != l_first);
- }
- }
+ BMEdge *e_edj_pair[2];
+ int i;
+
+ /* seems paranoid, but one caller also walks edges */
+ BLI_assert(l->head.htype == BM_LOOP);
+
+ bmw_LoopShellWalker_visitLoop(walker, l->next);
+ bmw_LoopShellWalker_visitLoop(walker, l->prev);
+
+ e_edj_pair[0] = l->e;
+ e_edj_pair[1] = l->prev->e;
+
+ for (i = 0; i < 2; i++) {
+ BMEdge *e = e_edj_pair[i];
+ if (bmw_mask_check_edge(walker, e)) {
+ BMLoop *l_iter, *l_first;
+
+ l_iter = l_first = e->l;
+ do {
+ BMLoop *l_radial = (l_iter->v == l->v) ? l_iter : l_iter->next;
+ BLI_assert(l_radial->v == l->v);
+ if (l != l_radial) {
+ bmw_LoopShellWalker_visitLoop(walker, l_radial);
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+ }
}
static void *bmw_LoopShellWalker_step(BMWalker *walker)
{
- BMwLoopShellWalker *swalk, owalk;
- BMLoop *l;
+ BMwLoopShellWalker *swalk, owalk;
+ BMLoop *l;
- BMW_state_remove_r(walker, &owalk);
- swalk = &owalk;
+ BMW_state_remove_r(walker, &owalk);
+ swalk = &owalk;
- l = swalk->curloop;
- bmw_LoopShellWalker_step_impl(walker, l);
+ l = swalk->curloop;
+ bmw_LoopShellWalker_step_impl(walker, l);
- return l;
+ return l;
}
/** \} */
@@ -384,149 +378,144 @@ static void *bmw_LoopShellWalker_step(BMWalker *walker)
static void bmw_LoopShellWalker_visitEdgeWire(BMWalker *walker, BMEdge *e)
{
- BMwLoopShellWireWalker *shellWalk = NULL;
+ BMwLoopShellWireWalker *shellWalk = NULL;
- BLI_assert(bmw_edge_is_wire(walker, e));
+ BLI_assert(bmw_edge_is_wire(walker, e));
- if (BLI_gset_haskey(walker->visit_set_alt, e)) {
- return;
- }
+ if (BLI_gset_haskey(walker->visit_set_alt, e)) {
+ return;
+ }
- if (!bmw_mask_check_edge(walker, e)) {
- return;
- }
+ if (!bmw_mask_check_edge(walker, e)) {
+ return;
+ }
- shellWalk = BMW_state_add(walker);
- shellWalk->curelem = (BMElem *)e;
- BLI_gset_insert(walker->visit_set_alt, e);
+ shellWalk = BMW_state_add(walker);
+ shellWalk->curelem = (BMElem *)e;
+ BLI_gset_insert(walker->visit_set_alt, e);
}
static void bmw_LoopShellWireWalker_visitVert(BMWalker *walker, BMVert *v, const BMEdge *e_from)
{
- BMEdge *e;
+ BMEdge *e;
- BLI_assert(v->head.htype == BM_VERT);
+ BLI_assert(v->head.htype == BM_VERT);
- if (BLI_gset_haskey(walker->visit_set_alt, v)) {
- return;
- }
+ if (BLI_gset_haskey(walker->visit_set_alt, v)) {
+ return;
+ }
- if (!bmw_mask_check_vert(walker, v)) {
- return;
- }
+ if (!bmw_mask_check_vert(walker, v)) {
+ return;
+ }
- e = v->e;
- do {
- if (bmw_edge_is_wire(walker, e) && (e != e_from)) {
- BMVert *v_other;
- BMIter iter;
- BMLoop *l;
+ e = v->e;
+ do {
+ if (bmw_edge_is_wire(walker, e) && (e != e_from)) {
+ BMVert *v_other;
+ BMIter iter;
+ BMLoop *l;
- bmw_LoopShellWalker_visitEdgeWire(walker, e);
+ bmw_LoopShellWalker_visitEdgeWire(walker, e);
- /* check if we step onto a non-wire vertex */
- v_other = BM_edge_other_vert(e, v);
- BM_ITER_ELEM (l, &iter, v_other, BM_LOOPS_OF_VERT) {
+ /* check if we step onto a non-wire vertex */
+ v_other = BM_edge_other_vert(e, v);
+ BM_ITER_ELEM (l, &iter, v_other, BM_LOOPS_OF_VERT) {
- bmw_LoopShellWalker_visitLoop(walker, l);
- }
- }
- } while ((e = BM_DISK_EDGE_NEXT(e, v)) != v->e);
+ bmw_LoopShellWalker_visitLoop(walker, l);
+ }
+ }
+ } while ((e = BM_DISK_EDGE_NEXT(e, v)) != v->e);
- BLI_gset_insert(walker->visit_set_alt, v);
+ BLI_gset_insert(walker->visit_set_alt, v);
}
static void bmw_LoopShellWireWalker_begin(BMWalker *walker, void *data)
{
- BMHeader *h = data;
-
- if (UNLIKELY(h == NULL)) {
- return;
- }
-
- bmw_LoopShellWalker_begin(walker, data);
-
- switch (h->htype) {
- case BM_LOOP:
- {
- BMLoop *l = (BMLoop *)h;
- bmw_LoopShellWireWalker_visitVert(walker, l->v, NULL);
- break;
- }
-
- case BM_VERT:
- {
- BMVert *v = (BMVert *)h;
- if (v->e) {
- bmw_LoopShellWireWalker_visitVert(walker, v, NULL);
- }
- break;
- }
- case BM_EDGE:
- {
- BMEdge *e = (BMEdge *)h;
- if (bmw_mask_check_edge(walker, e)) {
- bmw_LoopShellWireWalker_visitVert(walker, e->v1, NULL);
- bmw_LoopShellWireWalker_visitVert(walker, e->v2, NULL);
- }
- else if (e->l) {
- BMLoop *l_iter, *l_first;
-
- l_iter = l_first = e->l;
- do {
- bmw_LoopShellWalker_visitLoop(walker, l_iter);
- bmw_LoopShellWalker_visitLoop(walker, l_iter->next);
- } while ((l_iter = l_iter->radial_next) != l_first);
- }
- break;
- }
- case BM_FACE:
- {
- /* wire verts will be walked over */
- break;
- }
- default:
- BLI_assert(0);
- }
+ BMHeader *h = data;
+
+ if (UNLIKELY(h == NULL)) {
+ return;
+ }
+
+ bmw_LoopShellWalker_begin(walker, data);
+
+ switch (h->htype) {
+ case BM_LOOP: {
+ BMLoop *l = (BMLoop *)h;
+ bmw_LoopShellWireWalker_visitVert(walker, l->v, NULL);
+ break;
+ }
+
+ case BM_VERT: {
+ BMVert *v = (BMVert *)h;
+ if (v->e) {
+ bmw_LoopShellWireWalker_visitVert(walker, v, NULL);
+ }
+ break;
+ }
+ case BM_EDGE: {
+ BMEdge *e = (BMEdge *)h;
+ if (bmw_mask_check_edge(walker, e)) {
+ bmw_LoopShellWireWalker_visitVert(walker, e->v1, NULL);
+ bmw_LoopShellWireWalker_visitVert(walker, e->v2, NULL);
+ }
+ else if (e->l) {
+ BMLoop *l_iter, *l_first;
+
+ l_iter = l_first = e->l;
+ do {
+ bmw_LoopShellWalker_visitLoop(walker, l_iter);
+ bmw_LoopShellWalker_visitLoop(walker, l_iter->next);
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+ break;
+ }
+ case BM_FACE: {
+ /* wire verts will be walked over */
+ break;
+ }
+ default:
+ BLI_assert(0);
+ }
}
static void *bmw_LoopShellWireWalker_yield(BMWalker *walker)
{
- BMwLoopShellWireWalker *shellWalk = BMW_current_state(walker);
- return shellWalk->curelem;
+ BMwLoopShellWireWalker *shellWalk = BMW_current_state(walker);
+ return shellWalk->curelem;
}
static void *bmw_LoopShellWireWalker_step(BMWalker *walker)
{
- BMwLoopShellWireWalker *swalk, owalk;
+ BMwLoopShellWireWalker *swalk, owalk;
- BMW_state_remove_r(walker, &owalk);
- swalk = &owalk;
+ BMW_state_remove_r(walker, &owalk);
+ swalk = &owalk;
- if (swalk->curelem->head.htype == BM_LOOP) {
- BMLoop *l = (BMLoop *)swalk->curelem;
+ if (swalk->curelem->head.htype == BM_LOOP) {
+ BMLoop *l = (BMLoop *)swalk->curelem;
- bmw_LoopShellWalker_step_impl(walker, l);
+ bmw_LoopShellWalker_step_impl(walker, l);
- bmw_LoopShellWireWalker_visitVert(walker, l->v, NULL);
+ bmw_LoopShellWireWalker_visitVert(walker, l->v, NULL);
- return l;
- }
- else {
- BMEdge *e = (BMEdge *)swalk->curelem;
+ return l;
+ }
+ else {
+ BMEdge *e = (BMEdge *)swalk->curelem;
- BLI_assert(e->head.htype == BM_EDGE);
+ BLI_assert(e->head.htype == BM_EDGE);
- bmw_LoopShellWireWalker_visitVert(walker, e->v1, e);
- bmw_LoopShellWireWalker_visitVert(walker, e->v2, e);
+ bmw_LoopShellWireWalker_visitVert(walker, e->v1, e);
+ bmw_LoopShellWireWalker_visitVert(walker, e->v2, e);
- return e;
- }
+ return e;
+ }
}
/** \} */
-
/** \name FaceShell Walker
* \{
*
@@ -535,62 +524,61 @@ static void *bmw_LoopShellWireWalker_step(BMWalker *walker)
*/
static void bmw_FaceShellWalker_visitEdge(BMWalker *walker, BMEdge *e)
{
- BMwShellWalker *shellWalk = NULL;
+ BMwShellWalker *shellWalk = NULL;
- if (BLI_gset_haskey(walker->visit_set, e)) {
- return;
- }
+ if (BLI_gset_haskey(walker->visit_set, e)) {
+ return;
+ }
- if (!bmw_mask_check_edge(walker, e)) {
- return;
- }
+ if (!bmw_mask_check_edge(walker, e)) {
+ return;
+ }
- shellWalk = BMW_state_add(walker);
- shellWalk->curedge = e;
- BLI_gset_insert(walker->visit_set, e);
+ shellWalk = BMW_state_add(walker);
+ shellWalk->curedge = e;
+ BLI_gset_insert(walker->visit_set, e);
}
static void bmw_FaceShellWalker_begin(BMWalker *walker, void *data)
{
- BMEdge *e = data;
- bmw_FaceShellWalker_visitEdge(walker, e);
+ BMEdge *e = data;
+ bmw_FaceShellWalker_visitEdge(walker, e);
}
static void *bmw_FaceShellWalker_yield(BMWalker *walker)
{
- BMwShellWalker *shellWalk = BMW_current_state(walker);
- return shellWalk->curedge;
+ BMwShellWalker *shellWalk = BMW_current_state(walker);
+ return shellWalk->curedge;
}
static void *bmw_FaceShellWalker_step(BMWalker *walker)
{
- BMwShellWalker *swalk, owalk;
- BMEdge *e, *e2;
- BMIter iter;
+ BMwShellWalker *swalk, owalk;
+ BMEdge *e, *e2;
+ BMIter iter;
- BMW_state_remove_r(walker, &owalk);
- swalk = &owalk;
+ BMW_state_remove_r(walker, &owalk);
+ swalk = &owalk;
- e = swalk->curedge;
+ e = swalk->curedge;
- if (e->l) {
- BMLoop *l_iter, *l_first;
+ if (e->l) {
+ BMLoop *l_iter, *l_first;
- l_iter = l_first = e->l;
- do {
- BM_ITER_ELEM (e2, &iter, l_iter->f, BM_EDGES_OF_FACE) {
- if (e2 != e) {
- bmw_FaceShellWalker_visitEdge(walker, e2);
- }
- }
- } while ((l_iter = l_iter->radial_next) != l_first);
- }
+ l_iter = l_first = e->l;
+ do {
+ BM_ITER_ELEM (e2, &iter, l_iter->f, BM_EDGES_OF_FACE) {
+ if (e2 != e) {
+ bmw_FaceShellWalker_visitEdge(walker, e2);
+ }
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
- return e;
+ return e;
}
/** \} */
-
/** \name Connected Vertex Walker
* \{
*
@@ -600,60 +588,59 @@ static void *bmw_FaceShellWalker_step(BMWalker *walker)
*/
static void bmw_ConnectedVertexWalker_visitVertex(BMWalker *walker, BMVert *v)
{
- BMwConnectedVertexWalker *vwalk;
+ BMwConnectedVertexWalker *vwalk;
- if (BLI_gset_haskey(walker->visit_set, v)) {
- /* already visited */
- return;
- }
+ if (BLI_gset_haskey(walker->visit_set, v)) {
+ /* already visited */
+ return;
+ }
- if (!bmw_mask_check_vert(walker, v)) {
- /* not flagged for walk */
- return;
- }
+ if (!bmw_mask_check_vert(walker, v)) {
+ /* not flagged for walk */
+ return;
+ }
- vwalk = BMW_state_add(walker);
- vwalk->curvert = v;
- BLI_gset_insert(walker->visit_set, v);
+ vwalk = BMW_state_add(walker);
+ vwalk->curvert = v;
+ BLI_gset_insert(walker->visit_set, v);
}
static void bmw_ConnectedVertexWalker_begin(BMWalker *walker, void *data)
{
- BMVert *v = data;
- bmw_ConnectedVertexWalker_visitVertex(walker, v);
+ BMVert *v = data;
+ bmw_ConnectedVertexWalker_visitVertex(walker, v);
}
static void *bmw_ConnectedVertexWalker_yield(BMWalker *walker)
{
- BMwConnectedVertexWalker *vwalk = BMW_current_state(walker);
- return vwalk->curvert;
+ BMwConnectedVertexWalker *vwalk = BMW_current_state(walker);
+ return vwalk->curvert;
}
static void *bmw_ConnectedVertexWalker_step(BMWalker *walker)
{
- BMwConnectedVertexWalker *vwalk, owalk;
- BMVert *v, *v2;
- BMEdge *e;
- BMIter iter;
+ BMwConnectedVertexWalker *vwalk, owalk;
+ BMVert *v, *v2;
+ BMEdge *e;
+ BMIter iter;
- BMW_state_remove_r(walker, &owalk);
- vwalk = &owalk;
+ BMW_state_remove_r(walker, &owalk);
+ vwalk = &owalk;
- v = vwalk->curvert;
+ v = vwalk->curvert;
- BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
- v2 = BM_edge_other_vert(e, v);
- if (!BLI_gset_haskey(walker->visit_set, v2)) {
- bmw_ConnectedVertexWalker_visitVertex(walker, v2);
- }
- }
+ BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
+ v2 = BM_edge_other_vert(e, v);
+ if (!BLI_gset_haskey(walker->visit_set, v2)) {
+ bmw_ConnectedVertexWalker_visitVertex(walker, v2);
+ }
+ }
- return v;
+ return v;
}
/** \} */
-
/** \name Island Boundary Walker
* \{
*
@@ -668,88 +655,86 @@ static void *bmw_ConnectedVertexWalker_step(BMWalker *walker)
*/
static void bmw_IslandboundWalker_begin(BMWalker *walker, void *data)
{
- BMLoop *l = data;
- BMwIslandboundWalker *iwalk = NULL;
-
- iwalk = BMW_state_add(walker);
+ BMLoop *l = data;
+ BMwIslandboundWalker *iwalk = NULL;
- iwalk->base = iwalk->curloop = l;
- iwalk->lastv = l->v;
+ iwalk = BMW_state_add(walker);
- BLI_gset_insert(walker->visit_set, data);
+ iwalk->base = iwalk->curloop = l;
+ iwalk->lastv = l->v;
+ BLI_gset_insert(walker->visit_set, data);
}
static void *bmw_IslandboundWalker_yield(BMWalker *walker)
{
- BMwIslandboundWalker *iwalk = BMW_current_state(walker);
+ BMwIslandboundWalker *iwalk = BMW_current_state(walker);
- return iwalk->curloop;
+ return iwalk->curloop;
}
static void *bmw_IslandboundWalker_step(BMWalker *walker)
{
- BMwIslandboundWalker *iwalk, owalk;
- BMVert *v;
- BMEdge *e;
- BMFace *f;
- BMLoop *l;
- /* int found = 0; */
-
- memcpy(&owalk, BMW_current_state(walker), sizeof(owalk));
- /* normally we'd remove here, but delay until after error checking */
- iwalk = &owalk;
-
- l = iwalk->curloop;
- e = l->e;
-
- v = BM_edge_other_vert(e, iwalk->lastv);
-
- /* pop off current state */
- BMW_state_remove(walker);
-
- f = l->f;
-
- while (1) {
- l = BM_loop_other_edge_loop(l, v);
- if (BM_loop_is_manifold(l)) {
- l = l->radial_next;
- f = l->f;
- e = l->e;
-
- if (!bmw_mask_check_face(walker, f)) {
- l = l->radial_next;
- break;
- }
- }
- else {
- /* treat non-manifold edges as boundaries */
- f = l->f;
- e = l->e;
- break;
- }
- }
-
- if (l == owalk.curloop) {
- return NULL;
- }
- else if (BLI_gset_haskey(walker->visit_set, l)) {
- return owalk.curloop;
- }
-
- BLI_gset_insert(walker->visit_set, l);
- iwalk = BMW_state_add(walker);
- iwalk->base = owalk.base;
-
- //if (!BMO_face_flag_test(walker->bm, l->f, walker->restrictflag))
- // iwalk->curloop = l->radial_next;
- iwalk->curloop = l; //else iwalk->curloop = l;
- iwalk->lastv = v;
-
- return owalk.curloop;
+ BMwIslandboundWalker *iwalk, owalk;
+ BMVert *v;
+ BMEdge *e;
+ BMFace *f;
+ BMLoop *l;
+ /* int found = 0; */
+
+ memcpy(&owalk, BMW_current_state(walker), sizeof(owalk));
+ /* normally we'd remove here, but delay until after error checking */
+ iwalk = &owalk;
+
+ l = iwalk->curloop;
+ e = l->e;
+
+ v = BM_edge_other_vert(e, iwalk->lastv);
+
+ /* pop off current state */
+ BMW_state_remove(walker);
+
+ f = l->f;
+
+ while (1) {
+ l = BM_loop_other_edge_loop(l, v);
+ if (BM_loop_is_manifold(l)) {
+ l = l->radial_next;
+ f = l->f;
+ e = l->e;
+
+ if (!bmw_mask_check_face(walker, f)) {
+ l = l->radial_next;
+ break;
+ }
+ }
+ else {
+ /* treat non-manifold edges as boundaries */
+ f = l->f;
+ e = l->e;
+ break;
+ }
+ }
+
+ if (l == owalk.curloop) {
+ return NULL;
+ }
+ else if (BLI_gset_haskey(walker->visit_set, l)) {
+ return owalk.curloop;
+ }
+
+ BLI_gset_insert(walker->visit_set, l);
+ iwalk = BMW_state_add(walker);
+ iwalk->base = owalk.base;
+
+ //if (!BMO_face_flag_test(walker->bm, l->f, walker->restrictflag))
+ // iwalk->curloop = l->radial_next;
+ iwalk->curloop = l; //else iwalk->curloop = l;
+ iwalk->lastv = v;
+
+ return owalk.curloop;
}
-
/** \name Island Walker
* \{
*
@@ -759,90 +744,90 @@ static void *bmw_IslandboundWalker_step(BMWalker *walker)
*/
static void bmw_IslandWalker_begin(BMWalker *walker, void *data)
{
- BMwIslandWalker *iwalk = NULL;
+ BMwIslandWalker *iwalk = NULL;
- if (!bmw_mask_check_face(walker, data)) {
- return;
- }
+ if (!bmw_mask_check_face(walker, data)) {
+ return;
+ }
- iwalk = BMW_state_add(walker);
- BLI_gset_insert(walker->visit_set, data);
+ iwalk = BMW_state_add(walker);
+ BLI_gset_insert(walker->visit_set, data);
- iwalk->cur = data;
+ iwalk->cur = data;
}
static void *bmw_IslandWalker_yield(BMWalker *walker)
{
- BMwIslandWalker *iwalk = BMW_current_state(walker);
+ BMwIslandWalker *iwalk = BMW_current_state(walker);
- return iwalk->cur;
+ return iwalk->cur;
}
static void *bmw_IslandWalker_step_ex(BMWalker *walker, bool only_manifold)
{
- BMwIslandWalker *iwalk, owalk;
- BMLoop *l_iter, *l_first;
-
- BMW_state_remove_r(walker, &owalk);
- iwalk = &owalk;
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(iwalk->cur);
- do {
- /* could skip loop here too, but don't add unless we need it */
- if (!bmw_mask_check_edge(walker, l_iter->e)) {
- continue;
- }
-
- BMLoop *l_radial_iter;
-
- if (only_manifold && (l_iter->radial_next != l_iter)) {
- int face_count = 1;
- /* check other faces (not this one), ensure only one other can be walked onto. */
- l_radial_iter = l_iter->radial_next;
- do {
- if (bmw_mask_check_face(walker, l_radial_iter->f)) {
- face_count++;
- if (face_count == 3) {
- break;
- }
- }
- } while ((l_radial_iter = l_radial_iter->radial_next) != l_iter);
-
- if (face_count != 2) {
- continue;
- }
- }
-
- l_radial_iter = l_iter;
- while ((l_radial_iter = l_radial_iter->radial_next) != l_iter) {
- BMFace *f = l_radial_iter->f;
-
- if (!bmw_mask_check_face(walker, f)) {
- continue;
- }
-
- /* saves checking BLI_gset_haskey below (manifold edges theres a 50% chance) */
- if (f == iwalk->cur) {
- continue;
- }
-
- if (BLI_gset_haskey(walker->visit_set, f)) {
- continue;
- }
-
- iwalk = BMW_state_add(walker);
- iwalk->cur = f;
- BLI_gset_insert(walker->visit_set, f);
- break;
- }
- } while ((l_iter = l_iter->next) != l_first);
-
- return owalk.cur;
+ BMwIslandWalker *iwalk, owalk;
+ BMLoop *l_iter, *l_first;
+
+ BMW_state_remove_r(walker, &owalk);
+ iwalk = &owalk;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(iwalk->cur);
+ do {
+ /* could skip loop here too, but don't add unless we need it */
+ if (!bmw_mask_check_edge(walker, l_iter->e)) {
+ continue;
+ }
+
+ BMLoop *l_radial_iter;
+
+ if (only_manifold && (l_iter->radial_next != l_iter)) {
+ int face_count = 1;
+ /* check other faces (not this one), ensure only one other can be walked onto. */
+ l_radial_iter = l_iter->radial_next;
+ do {
+ if (bmw_mask_check_face(walker, l_radial_iter->f)) {
+ face_count++;
+ if (face_count == 3) {
+ break;
+ }
+ }
+ } while ((l_radial_iter = l_radial_iter->radial_next) != l_iter);
+
+ if (face_count != 2) {
+ continue;
+ }
+ }
+
+ l_radial_iter = l_iter;
+ while ((l_radial_iter = l_radial_iter->radial_next) != l_iter) {
+ BMFace *f = l_radial_iter->f;
+
+ if (!bmw_mask_check_face(walker, f)) {
+ continue;
+ }
+
+ /* saves checking BLI_gset_haskey below (manifold edges theres a 50% chance) */
+ if (f == iwalk->cur) {
+ continue;
+ }
+
+ if (BLI_gset_haskey(walker->visit_set, f)) {
+ continue;
+ }
+
+ iwalk = BMW_state_add(walker);
+ iwalk->cur = f;
+ BLI_gset_insert(walker->visit_set, f);
+ break;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+
+ return owalk.cur;
}
static void *bmw_IslandWalker_step(BMWalker *walker)
{
- return bmw_IslandWalker_step_ex(walker, false);
+ return bmw_IslandWalker_step_ex(walker, false);
}
/**
@@ -850,12 +835,11 @@ static void *bmw_IslandWalker_step(BMWalker *walker)
*/
static void *bmw_IslandManifoldWalker_step(BMWalker *walker)
{
- return bmw_IslandWalker_step_ex(walker, true);
+ return bmw_IslandWalker_step_ex(walker, true);
}
/** \} */
-
/** \name Edge Loop Walker
* \{
*
@@ -865,251 +849,238 @@ static void *bmw_IslandManifoldWalker_step(BMWalker *walker)
/* utility function to see if an edge is apart of an ngon boundary */
static bool bm_edge_is_single(BMEdge *e)
{
- return ((BM_edge_is_boundary(e)) &&
- (e->l->f->len > 4) &&
- (BM_edge_is_boundary(e->l->next->e) || BM_edge_is_boundary(e->l->prev->e)));
+ return ((BM_edge_is_boundary(e)) && (e->l->f->len > 4) &&
+ (BM_edge_is_boundary(e->l->next->e) || BM_edge_is_boundary(e->l->prev->e)));
}
static void bmw_EdgeLoopWalker_begin(BMWalker *walker, void *data)
{
- BMwEdgeLoopWalker *lwalk = NULL, owalk, *owalk_pt;
- BMEdge *e = data;
- BMVert *v;
- const int vert_edge_count[2] = {
- BM_vert_edge_count_nonwire(e->v1),
- BM_vert_edge_count_nonwire(e->v2),
- };
-
- v = e->v1;
-
- lwalk = BMW_state_add(walker);
- BLI_gset_insert(walker->visit_set, e);
-
- lwalk->cur = lwalk->start = e;
- lwalk->lastv = lwalk->startv = v;
- lwalk->is_boundary = BM_edge_is_boundary(e);
- lwalk->is_single = (lwalk->is_boundary && bm_edge_is_single(e));
-
- /* could also check that vertex*/
- if ((lwalk->is_boundary == false) &&
- (vert_edge_count[0] == 3 || vert_edge_count[1] == 3))
- {
- BMIter iter;
- BMFace *f_iter;
- BMFace *f_best = NULL;
-
- BM_ITER_ELEM (f_iter, &iter, e, BM_FACES_OF_EDGE) {
- if (f_best == NULL || f_best->len < f_iter->len) {
- f_best = f_iter;
- }
- }
-
- if (f_best) {
- /* only use hub selection for 5+ sides else this could
- * conflict with normal edge loop selection. */
- lwalk->f_hub = f_best->len > 4 ? f_best : NULL;
- }
- else {
- /* edge doesn't have any faces connected to it */
- lwalk->f_hub = NULL;
- }
- }
- else {
- lwalk->f_hub = NULL;
- }
-
- /* rewind */
- while ((owalk_pt = BMW_current_state(walker))) {
- owalk = *((BMwEdgeLoopWalker *)owalk_pt);
- BMW_walk(walker);
- }
-
- lwalk = BMW_state_add(walker);
- *lwalk = owalk;
-
- lwalk->lastv = lwalk->startv = BM_edge_other_vert(owalk.cur, lwalk->lastv);
-
- BLI_gset_clear(walker->visit_set, NULL);
- BLI_gset_insert(walker->visit_set, owalk.cur);
+ BMwEdgeLoopWalker *lwalk = NULL, owalk, *owalk_pt;
+ BMEdge *e = data;
+ BMVert *v;
+ const int vert_edge_count[2] = {
+ BM_vert_edge_count_nonwire(e->v1),
+ BM_vert_edge_count_nonwire(e->v2),
+ };
+
+ v = e->v1;
+
+ lwalk = BMW_state_add(walker);
+ BLI_gset_insert(walker->visit_set, e);
+
+ lwalk->cur = lwalk->start = e;
+ lwalk->lastv = lwalk->startv = v;
+ lwalk->is_boundary = BM_edge_is_boundary(e);
+ lwalk->is_single = (lwalk->is_boundary && bm_edge_is_single(e));
+
+ /* could also check that vertex*/
+ if ((lwalk->is_boundary == false) && (vert_edge_count[0] == 3 || vert_edge_count[1] == 3)) {
+ BMIter iter;
+ BMFace *f_iter;
+ BMFace *f_best = NULL;
+
+ BM_ITER_ELEM (f_iter, &iter, e, BM_FACES_OF_EDGE) {
+ if (f_best == NULL || f_best->len < f_iter->len) {
+ f_best = f_iter;
+ }
+ }
+
+ if (f_best) {
+ /* only use hub selection for 5+ sides else this could
+ * conflict with normal edge loop selection. */
+ lwalk->f_hub = f_best->len > 4 ? f_best : NULL;
+ }
+ else {
+ /* edge doesn't have any faces connected to it */
+ lwalk->f_hub = NULL;
+ }
+ }
+ else {
+ lwalk->f_hub = NULL;
+ }
+
+ /* rewind */
+ while ((owalk_pt = BMW_current_state(walker))) {
+ owalk = *((BMwEdgeLoopWalker *)owalk_pt);
+ BMW_walk(walker);
+ }
+
+ lwalk = BMW_state_add(walker);
+ *lwalk = owalk;
+
+ lwalk->lastv = lwalk->startv = BM_edge_other_vert(owalk.cur, lwalk->lastv);
+
+ BLI_gset_clear(walker->visit_set, NULL);
+ BLI_gset_insert(walker->visit_set, owalk.cur);
}
static void *bmw_EdgeLoopWalker_yield(BMWalker *walker)
{
- BMwEdgeLoopWalker *lwalk = BMW_current_state(walker);
+ BMwEdgeLoopWalker *lwalk = BMW_current_state(walker);
- return lwalk->cur;
+ return lwalk->cur;
}
static void *bmw_EdgeLoopWalker_step(BMWalker *walker)
{
- BMwEdgeLoopWalker *lwalk, owalk;
- BMEdge *e, *nexte = NULL;
- BMLoop *l;
- BMVert *v;
-
- BMW_state_remove_r(walker, &owalk);
- lwalk = &owalk;
-
- e = lwalk->cur;
- l = e->l;
-
- if (owalk.f_hub) { /* NGON EDGE */
- int vert_edge_tot;
-
- v = BM_edge_other_vert(e, lwalk->lastv);
-
- vert_edge_tot = BM_vert_edge_count_nonwire(v);
-
- if (vert_edge_tot == 3) {
- l = BM_face_other_vert_loop(owalk.f_hub, lwalk->lastv, v);
- nexte = BM_edge_exists(v, l->v);
-
- if (bmw_mask_check_edge(walker, nexte) &&
- !BLI_gset_haskey(walker->visit_set, nexte) &&
- /* never step onto a boundary edge, this gives odd-results */
- (BM_edge_is_boundary(nexte) == false))
- {
- lwalk = BMW_state_add(walker);
- lwalk->cur = nexte;
- lwalk->lastv = v;
-
- lwalk->is_boundary = owalk.is_boundary;
- lwalk->is_single = owalk.is_single;
- lwalk->f_hub = owalk.f_hub;
-
- BLI_gset_insert(walker->visit_set, nexte);
- }
- }
- }
- else if (l == NULL) { /* WIRE EDGE */
- BMIter eiter;
-
- /* match trunk: mark all connected wire edges */
- for (int i = 0; i < 2; i++) {
- v = i ? e->v2 : e->v1;
-
- BM_ITER_ELEM (nexte, &eiter, v, BM_EDGES_OF_VERT) {
- if ((nexte->l == NULL) &&
- bmw_mask_check_edge(walker, nexte) &&
- !BLI_gset_haskey(walker->visit_set, nexte))
- {
- lwalk = BMW_state_add(walker);
- lwalk->cur = nexte;
- lwalk->lastv = v;
-
- lwalk->is_boundary = owalk.is_boundary;
- lwalk->is_single = owalk.is_single;
- lwalk->f_hub = owalk.f_hub;
-
- BLI_gset_insert(walker->visit_set, nexte);
- }
- }
- }
- }
- else if (owalk.is_boundary == false) { /* NORMAL EDGE WITH FACES */
- int vert_edge_tot;
-
- v = BM_edge_other_vert(e, lwalk->lastv);
-
- vert_edge_tot = BM_vert_edge_count_nonwire(v);
-
- /* typical loopiong over edges in the middle of a mesh */
- /* however, why use 2 here at all? I guess for internal ngon loops it can be useful. Antony R. */
- if (vert_edge_tot == 4 || vert_edge_tot == 2) {
- int i_opposite = vert_edge_tot / 2;
- int i = 0;
- do {
- l = BM_loop_other_edge_loop(l, v);
- if (BM_edge_is_manifold(l->e)) {
- l = l->radial_next;
- }
- else {
- l = NULL;
- break;
- }
- } while ((++i != i_opposite));
- }
- else {
- l = NULL;
- }
-
- if (l != NULL) {
- if (l != e->l &&
- bmw_mask_check_edge(walker, l->e) &&
- !BLI_gset_haskey(walker->visit_set, l->e))
- {
- lwalk = BMW_state_add(walker);
- lwalk->cur = l->e;
- lwalk->lastv = v;
-
- lwalk->is_boundary = owalk.is_boundary;
- lwalk->is_single = owalk.is_single;
- lwalk->f_hub = owalk.f_hub;
-
- BLI_gset_insert(walker->visit_set, l->e);
- }
- }
- }
- else if (owalk.is_boundary == true) { /* BOUNDARY EDGE WITH FACES */
- int vert_edge_tot;
-
- v = BM_edge_other_vert(e, lwalk->lastv);
-
- vert_edge_tot = BM_vert_edge_count_nonwire(v);
-
- /* check if we should step, this is fairly involved */
- if (
- /* walk over boundary of faces but stop at corners */
- (owalk.is_single == false && vert_edge_tot > 2) ||
-
- /* initial edge was a boundary, so is this edge and vertex is only apart of this face
- * this lets us walk over the boundary of an ngon which is handy */
- (owalk.is_single == true && vert_edge_tot == 2 && BM_edge_is_boundary(e)))
- {
- /* find next boundary edge in the fan */
- do {
- l = BM_loop_other_edge_loop(l, v);
- if (BM_edge_is_manifold(l->e)) {
- l = l->radial_next;
- }
- else if (BM_edge_is_boundary(l->e)) {
- break;
- }
- else {
- l = NULL;
- break;
- }
- } while (true);
- }
-
- if (owalk.is_single == false && l && bm_edge_is_single(l->e)) {
- l = NULL;
- }
-
- if (l != NULL) {
- if (l != e->l &&
- bmw_mask_check_edge(walker, l->e) &&
- !BLI_gset_haskey(walker->visit_set, l->e))
- {
- lwalk = BMW_state_add(walker);
- lwalk->cur = l->e;
- lwalk->lastv = v;
-
- lwalk->is_boundary = owalk.is_boundary;
- lwalk->is_single = owalk.is_single;
- lwalk->f_hub = owalk.f_hub;
-
- BLI_gset_insert(walker->visit_set, l->e);
- }
- }
- }
-
- return owalk.cur;
+ BMwEdgeLoopWalker *lwalk, owalk;
+ BMEdge *e, *nexte = NULL;
+ BMLoop *l;
+ BMVert *v;
+
+ BMW_state_remove_r(walker, &owalk);
+ lwalk = &owalk;
+
+ e = lwalk->cur;
+ l = e->l;
+
+ if (owalk.f_hub) { /* NGON EDGE */
+ int vert_edge_tot;
+
+ v = BM_edge_other_vert(e, lwalk->lastv);
+
+ vert_edge_tot = BM_vert_edge_count_nonwire(v);
+
+ if (vert_edge_tot == 3) {
+ l = BM_face_other_vert_loop(owalk.f_hub, lwalk->lastv, v);
+ nexte = BM_edge_exists(v, l->v);
+
+ if (bmw_mask_check_edge(walker, nexte) && !BLI_gset_haskey(walker->visit_set, nexte) &&
+ /* never step onto a boundary edge, this gives odd-results */
+ (BM_edge_is_boundary(nexte) == false)) {
+ lwalk = BMW_state_add(walker);
+ lwalk->cur = nexte;
+ lwalk->lastv = v;
+
+ lwalk->is_boundary = owalk.is_boundary;
+ lwalk->is_single = owalk.is_single;
+ lwalk->f_hub = owalk.f_hub;
+
+ BLI_gset_insert(walker->visit_set, nexte);
+ }
+ }
+ }
+ else if (l == NULL) { /* WIRE EDGE */
+ BMIter eiter;
+
+ /* match trunk: mark all connected wire edges */
+ for (int i = 0; i < 2; i++) {
+ v = i ? e->v2 : e->v1;
+
+ BM_ITER_ELEM (nexte, &eiter, v, BM_EDGES_OF_VERT) {
+ if ((nexte->l == NULL) && bmw_mask_check_edge(walker, nexte) &&
+ !BLI_gset_haskey(walker->visit_set, nexte)) {
+ lwalk = BMW_state_add(walker);
+ lwalk->cur = nexte;
+ lwalk->lastv = v;
+
+ lwalk->is_boundary = owalk.is_boundary;
+ lwalk->is_single = owalk.is_single;
+ lwalk->f_hub = owalk.f_hub;
+
+ BLI_gset_insert(walker->visit_set, nexte);
+ }
+ }
+ }
+ }
+ else if (owalk.is_boundary == false) { /* NORMAL EDGE WITH FACES */
+ int vert_edge_tot;
+
+ v = BM_edge_other_vert(e, lwalk->lastv);
+
+ vert_edge_tot = BM_vert_edge_count_nonwire(v);
+
+ /* typical loopiong over edges in the middle of a mesh */
+ /* however, why use 2 here at all? I guess for internal ngon loops it can be useful. Antony R. */
+ if (vert_edge_tot == 4 || vert_edge_tot == 2) {
+ int i_opposite = vert_edge_tot / 2;
+ int i = 0;
+ do {
+ l = BM_loop_other_edge_loop(l, v);
+ if (BM_edge_is_manifold(l->e)) {
+ l = l->radial_next;
+ }
+ else {
+ l = NULL;
+ break;
+ }
+ } while ((++i != i_opposite));
+ }
+ else {
+ l = NULL;
+ }
+
+ if (l != NULL) {
+ if (l != e->l && bmw_mask_check_edge(walker, l->e) &&
+ !BLI_gset_haskey(walker->visit_set, l->e)) {
+ lwalk = BMW_state_add(walker);
+ lwalk->cur = l->e;
+ lwalk->lastv = v;
+
+ lwalk->is_boundary = owalk.is_boundary;
+ lwalk->is_single = owalk.is_single;
+ lwalk->f_hub = owalk.f_hub;
+
+ BLI_gset_insert(walker->visit_set, l->e);
+ }
+ }
+ }
+ else if (owalk.is_boundary == true) { /* BOUNDARY EDGE WITH FACES */
+ int vert_edge_tot;
+
+ v = BM_edge_other_vert(e, lwalk->lastv);
+
+ vert_edge_tot = BM_vert_edge_count_nonwire(v);
+
+ /* check if we should step, this is fairly involved */
+ if (
+ /* walk over boundary of faces but stop at corners */
+ (owalk.is_single == false && vert_edge_tot > 2) ||
+
+ /* initial edge was a boundary, so is this edge and vertex is only apart of this face
+ * this lets us walk over the boundary of an ngon which is handy */
+ (owalk.is_single == true && vert_edge_tot == 2 && BM_edge_is_boundary(e))) {
+ /* find next boundary edge in the fan */
+ do {
+ l = BM_loop_other_edge_loop(l, v);
+ if (BM_edge_is_manifold(l->e)) {
+ l = l->radial_next;
+ }
+ else if (BM_edge_is_boundary(l->e)) {
+ break;
+ }
+ else {
+ l = NULL;
+ break;
+ }
+ } while (true);
+ }
+
+ if (owalk.is_single == false && l && bm_edge_is_single(l->e)) {
+ l = NULL;
+ }
+
+ if (l != NULL) {
+ if (l != e->l && bmw_mask_check_edge(walker, l->e) &&
+ !BLI_gset_haskey(walker->visit_set, l->e)) {
+ lwalk = BMW_state_add(walker);
+ lwalk->cur = l->e;
+ lwalk->lastv = v;
+
+ lwalk->is_boundary = owalk.is_boundary;
+ lwalk->is_single = owalk.is_single;
+ lwalk->f_hub = owalk.f_hub;
+
+ BLI_gset_insert(walker->visit_set, l->e);
+ }
+ }
+ }
+
+ return owalk.cur;
}
/** \} */
-
/** \name Face Loop Walker
* \{
*
@@ -1122,139 +1093,138 @@ static void *bmw_EdgeLoopWalker_step(BMWalker *walker)
* by the given BMLoop */
static bool bmw_FaceLoopWalker_include_face(BMWalker *walker, BMLoop *l)
{
- /* face must have degree 4 */
- if (l->f->len != 4) {
- return false;
- }
+ /* face must have degree 4 */
+ if (l->f->len != 4) {
+ return false;
+ }
- if (!bmw_mask_check_face(walker, l->f)) {
- return false;
- }
+ if (!bmw_mask_check_face(walker, l->f)) {
+ return false;
+ }
- /* the face must not have been already visited */
- if (BLI_gset_haskey(walker->visit_set, l->f) && BLI_gset_haskey(walker->visit_set_alt, l->e)) {
- return false;
- }
+ /* the face must not have been already visited */
+ if (BLI_gset_haskey(walker->visit_set, l->f) && BLI_gset_haskey(walker->visit_set_alt, l->e)) {
+ return false;
+ }
- return true;
+ return true;
}
/* Check whether the face loop can start from the given edge */
static bool bmw_FaceLoopWalker_edge_begins_loop(BMWalker *walker, BMEdge *e)
{
- /* There is no face loop starting from a wire edge */
- if (BM_edge_is_wire(e)) {
- return false;
- }
-
- /* Don't start a loop from a boundary edge if it cannot
- * be extended to cover any faces */
- if (BM_edge_is_boundary(e)) {
- if (!bmw_FaceLoopWalker_include_face(walker, e->l)) {
- return false;
- }
- }
-
- /* Don't start a face loop from non-manifold edges */
- if (!BM_edge_is_manifold(e)) {
- return false;
- }
-
- return true;
+ /* There is no face loop starting from a wire edge */
+ if (BM_edge_is_wire(e)) {
+ return false;
+ }
+
+ /* Don't start a loop from a boundary edge if it cannot
+ * be extended to cover any faces */
+ if (BM_edge_is_boundary(e)) {
+ if (!bmw_FaceLoopWalker_include_face(walker, e->l)) {
+ return false;
+ }
+ }
+
+ /* Don't start a face loop from non-manifold edges */
+ if (!BM_edge_is_manifold(e)) {
+ return false;
+ }
+
+ return true;
}
static void bmw_FaceLoopWalker_begin(BMWalker *walker, void *data)
{
- BMwFaceLoopWalker *lwalk, owalk, *owalk_pt;
- BMEdge *e = data;
- /* BMesh *bm = walker->bm; */ /* UNUSED */
- /* int fcount = BM_edge_face_count(e); */ /* UNUSED */
-
- if (!bmw_FaceLoopWalker_edge_begins_loop(walker, e)) {
- return;
- }
-
- lwalk = BMW_state_add(walker);
- lwalk->l = e->l;
- lwalk->no_calc = false;
- BLI_gset_insert(walker->visit_set, lwalk->l->f);
-
- /* rewind */
- while ((owalk_pt = BMW_current_state(walker))) {
- owalk = *((BMwFaceLoopWalker *)owalk_pt);
- BMW_walk(walker);
- }
-
- lwalk = BMW_state_add(walker);
- *lwalk = owalk;
- lwalk->no_calc = false;
-
- BLI_gset_clear(walker->visit_set_alt, NULL);
- BLI_gset_insert(walker->visit_set_alt, lwalk->l->e);
-
- BLI_gset_clear(walker->visit_set, NULL);
- BLI_gset_insert(walker->visit_set, lwalk->l->f);
+ BMwFaceLoopWalker *lwalk, owalk, *owalk_pt;
+ BMEdge *e = data;
+ /* BMesh *bm = walker->bm; */ /* UNUSED */
+ /* int fcount = BM_edge_face_count(e); */ /* UNUSED */
+
+ if (!bmw_FaceLoopWalker_edge_begins_loop(walker, e)) {
+ return;
+ }
+
+ lwalk = BMW_state_add(walker);
+ lwalk->l = e->l;
+ lwalk->no_calc = false;
+ BLI_gset_insert(walker->visit_set, lwalk->l->f);
+
+ /* rewind */
+ while ((owalk_pt = BMW_current_state(walker))) {
+ owalk = *((BMwFaceLoopWalker *)owalk_pt);
+ BMW_walk(walker);
+ }
+
+ lwalk = BMW_state_add(walker);
+ *lwalk = owalk;
+ lwalk->no_calc = false;
+
+ BLI_gset_clear(walker->visit_set_alt, NULL);
+ BLI_gset_insert(walker->visit_set_alt, lwalk->l->e);
+
+ BLI_gset_clear(walker->visit_set, NULL);
+ BLI_gset_insert(walker->visit_set, lwalk->l->f);
}
static void *bmw_FaceLoopWalker_yield(BMWalker *walker)
{
- BMwFaceLoopWalker *lwalk = BMW_current_state(walker);
+ BMwFaceLoopWalker *lwalk = BMW_current_state(walker);
- if (!lwalk) {
- return NULL;
- }
+ if (!lwalk) {
+ return NULL;
+ }
- return lwalk->l->f;
+ return lwalk->l->f;
}
static void *bmw_FaceLoopWalker_step(BMWalker *walker)
{
- BMwFaceLoopWalker *lwalk, owalk;
- BMFace *f;
- BMLoop *l;
-
- BMW_state_remove_r(walker, &owalk);
- lwalk = &owalk;
-
- f = lwalk->l->f;
- l = lwalk->l->radial_next;
-
- if (lwalk->no_calc) {
- return f;
- }
-
- if (!bmw_FaceLoopWalker_include_face(walker, l)) {
- l = lwalk->l;
- l = l->next->next;
- if (!BM_edge_is_manifold(l->e)) {
- l = l->prev->prev;
- }
- l = l->radial_next;
- }
-
- if (bmw_FaceLoopWalker_include_face(walker, l)) {
- lwalk = BMW_state_add(walker);
- lwalk->l = l;
-
- if (l->f->len != 4) {
- lwalk->no_calc = true;
- lwalk->l = owalk.l;
- }
- else {
- lwalk->no_calc = false;
- }
-
- /* both may already exist */
- BLI_gset_add(walker->visit_set_alt, l->e);
- BLI_gset_add(walker->visit_set, l->f);
- }
-
- return f;
+ BMwFaceLoopWalker *lwalk, owalk;
+ BMFace *f;
+ BMLoop *l;
+
+ BMW_state_remove_r(walker, &owalk);
+ lwalk = &owalk;
+
+ f = lwalk->l->f;
+ l = lwalk->l->radial_next;
+
+ if (lwalk->no_calc) {
+ return f;
+ }
+
+ if (!bmw_FaceLoopWalker_include_face(walker, l)) {
+ l = lwalk->l;
+ l = l->next->next;
+ if (!BM_edge_is_manifold(l->e)) {
+ l = l->prev->prev;
+ }
+ l = l->radial_next;
+ }
+
+ if (bmw_FaceLoopWalker_include_face(walker, l)) {
+ lwalk = BMW_state_add(walker);
+ lwalk->l = l;
+
+ if (l->f->len != 4) {
+ lwalk->no_calc = true;
+ lwalk->l = owalk.l;
+ }
+ else {
+ lwalk->no_calc = false;
+ }
+
+ /* both may already exist */
+ BLI_gset_add(walker->visit_set_alt, l->e);
+ BLI_gset_add(walker->visit_set, l->f);
+ }
+
+ return f;
}
/** \} */
-
// #define BMW_EDGERING_NGON
/** \name Edge Ring Walker
@@ -1266,210 +1236,205 @@ static void *bmw_FaceLoopWalker_step(BMWalker *walker)
*/
static void bmw_EdgeringWalker_begin(BMWalker *walker, void *data)
{
- BMwEdgeringWalker *lwalk, owalk, *owalk_pt;
- BMEdge *e = data;
+ BMwEdgeringWalker *lwalk, owalk, *owalk_pt;
+ BMEdge *e = data;
- lwalk = BMW_state_add(walker);
- lwalk->l = e->l;
+ lwalk = BMW_state_add(walker);
+ lwalk->l = e->l;
- if (!lwalk->l) {
- lwalk->wireedge = e;
- return;
- }
- else {
- lwalk->wireedge = NULL;
- }
+ if (!lwalk->l) {
+ lwalk->wireedge = e;
+ return;
+ }
+ else {
+ lwalk->wireedge = NULL;
+ }
- BLI_gset_insert(walker->visit_set, lwalk->l->e);
+ BLI_gset_insert(walker->visit_set, lwalk->l->e);
- /* rewind */
- while ((owalk_pt = BMW_current_state(walker))) {
- owalk = *((BMwEdgeringWalker *)owalk_pt);
- BMW_walk(walker);
- }
+ /* rewind */
+ while ((owalk_pt = BMW_current_state(walker))) {
+ owalk = *((BMwEdgeringWalker *)owalk_pt);
+ BMW_walk(walker);
+ }
- lwalk = BMW_state_add(walker);
- *lwalk = owalk;
+ lwalk = BMW_state_add(walker);
+ *lwalk = owalk;
#ifdef BMW_EDGERING_NGON
- if (lwalk->l->f->len % 2 != 0)
+ if (lwalk->l->f->len % 2 != 0)
#else
- if (lwalk->l->f->len != 4)
+ if (lwalk->l->f->len != 4)
#endif
- {
- lwalk->l = lwalk->l->radial_next;
- }
+ {
+ lwalk->l = lwalk->l->radial_next;
+ }
- BLI_gset_clear(walker->visit_set, NULL);
- BLI_gset_insert(walker->visit_set, lwalk->l->e);
+ BLI_gset_clear(walker->visit_set, NULL);
+ BLI_gset_insert(walker->visit_set, lwalk->l->e);
}
static void *bmw_EdgeringWalker_yield(BMWalker *walker)
{
- BMwEdgeringWalker *lwalk = BMW_current_state(walker);
-
- if (!lwalk) {
- return NULL;
- }
-
- if (lwalk->l) {
- return lwalk->l->e;
- }
- else {
- return lwalk->wireedge;
- }
+ BMwEdgeringWalker *lwalk = BMW_current_state(walker);
+
+ if (!lwalk) {
+ return NULL;
+ }
+
+ if (lwalk->l) {
+ return lwalk->l->e;
+ }
+ else {
+ return lwalk->wireedge;
+ }
}
static void *bmw_EdgeringWalker_step(BMWalker *walker)
{
- BMwEdgeringWalker *lwalk, owalk;
- BMEdge *e;
- BMLoop *l;
+ BMwEdgeringWalker *lwalk, owalk;
+ BMEdge *e;
+ BMLoop *l;
#ifdef BMW_EDGERING_NGON
- int i, len;
+ int i, len;
#endif
-#define EDGE_CHECK(e) (bmw_mask_check_edge(walker, e) && (BM_edge_is_boundary(e) || BM_edge_is_manifold(e)))
+#define EDGE_CHECK(e) \
+ (bmw_mask_check_edge(walker, e) && (BM_edge_is_boundary(e) || BM_edge_is_manifold(e)))
- BMW_state_remove_r(walker, &owalk);
- lwalk = &owalk;
+ BMW_state_remove_r(walker, &owalk);
+ lwalk = &owalk;
- l = lwalk->l;
- if (!l) {
- return lwalk->wireedge;
- }
+ l = lwalk->l;
+ if (!l) {
+ return lwalk->wireedge;
+ }
- e = l->e;
- if (!EDGE_CHECK(e)) {
- /* walker won't traverse to a non-manifold edge, but may
- * be started on one, and should not traverse *away* from
- * a non-manifold edge (non-manifold edges are never in an
- * edge ring with manifold edges */
- return e;
- }
+ e = l->e;
+ if (!EDGE_CHECK(e)) {
+ /* walker won't traverse to a non-manifold edge, but may
+ * be started on one, and should not traverse *away* from
+ * a non-manifold edge (non-manifold edges are never in an
+ * edge ring with manifold edges */
+ return e;
+ }
#ifdef BMW_EDGERING_NGON
- l = l->radial_next;
-
- i = len = l->f->len;
- while (i > 0) {
- l = l->next;
- i -= 2;
- }
-
- if ((len <= 0) || (len % 2 != 0) || !EDGE_CHECK(l->e) ||
- !bmw_mask_check_face(walker, l->f))
- {
- l = owalk.l;
- i = len;
- while (i > 0) {
- l = l->next;
- i -= 2;
- }
- }
- /* only walk to manifold edge */
- if ((l->f->len % 2 == 0) && EDGE_CHECK(l->e) &&
- !BLI_gset_haskey(walker->visit_set, l->e))
+ l = l->radial_next;
+
+ i = len = l->f->len;
+ while (i > 0) {
+ l = l->next;
+ i -= 2;
+ }
+
+ if ((len <= 0) || (len % 2 != 0) || !EDGE_CHECK(l->e) || !bmw_mask_check_face(walker, l->f)) {
+ l = owalk.l;
+ i = len;
+ while (i > 0) {
+ l = l->next;
+ i -= 2;
+ }
+ }
+ /* only walk to manifold edge */
+ if ((l->f->len % 2 == 0) && EDGE_CHECK(l->e) && !BLI_gset_haskey(walker->visit_set, l->e))
#else
- l = l->radial_next;
- l = l->next->next;
+ l = l->radial_next;
+ l = l->next->next;
- if ((l->f->len != 4) || !EDGE_CHECK(l->e) || !bmw_mask_check_face(walker, l->f)) {
- l = owalk.l->next->next;
- }
- /* only walk to manifold edge */
- if ((l->f->len == 4) && EDGE_CHECK(l->e) &&
- !BLI_gset_haskey(walker->visit_set, l->e))
+ if ((l->f->len != 4) || !EDGE_CHECK(l->e) || !bmw_mask_check_face(walker, l->f)) {
+ l = owalk.l->next->next;
+ }
+ /* only walk to manifold edge */
+ if ((l->f->len == 4) && EDGE_CHECK(l->e) && !BLI_gset_haskey(walker->visit_set, l->e))
#endif
- {
- lwalk = BMW_state_add(walker);
- lwalk->l = l;
- lwalk->wireedge = NULL;
+ {
+ lwalk = BMW_state_add(walker);
+ lwalk->l = l;
+ lwalk->wireedge = NULL;
- BLI_gset_insert(walker->visit_set, l->e);
- }
+ BLI_gset_insert(walker->visit_set, l->e);
+ }
- return e;
+ return e;
#undef EDGE_CHECK
}
/** \} */
-
/** \name Boundary Edge Walker
* \{ */
static void bmw_EdgeboundaryWalker_begin(BMWalker *walker, void *data)
{
- BMwEdgeboundaryWalker *lwalk;
- BMEdge *e = data;
+ BMwEdgeboundaryWalker *lwalk;
+ BMEdge *e = data;
- BLI_assert(BM_edge_is_boundary(e));
+ BLI_assert(BM_edge_is_boundary(e));
- if (BLI_gset_haskey(walker->visit_set, e)) {
- return;
- }
+ if (BLI_gset_haskey(walker->visit_set, e)) {
+ return;
+ }
- lwalk = BMW_state_add(walker);
- lwalk->e = e;
- BLI_gset_insert(walker->visit_set, e);
+ lwalk = BMW_state_add(walker);
+ lwalk->e = e;
+ BLI_gset_insert(walker->visit_set, e);
}
static void *bmw_EdgeboundaryWalker_yield(BMWalker *walker)
{
- BMwEdgeboundaryWalker *lwalk = BMW_current_state(walker);
+ BMwEdgeboundaryWalker *lwalk = BMW_current_state(walker);
- if (!lwalk) {
- return NULL;
- }
+ if (!lwalk) {
+ return NULL;
+ }
- return lwalk->e;
+ return lwalk->e;
}
static void *bmw_EdgeboundaryWalker_step(BMWalker *walker)
{
- BMwEdgeboundaryWalker *lwalk, owalk;
- BMEdge *e, *e_other;
- BMVert *v;
- BMIter eiter;
- BMIter viter;
+ BMwEdgeboundaryWalker *lwalk, owalk;
+ BMEdge *e, *e_other;
+ BMVert *v;
+ BMIter eiter;
+ BMIter viter;
- BMW_state_remove_r(walker, &owalk);
- lwalk = &owalk;
+ BMW_state_remove_r(walker, &owalk);
+ lwalk = &owalk;
- e = lwalk->e;
+ e = lwalk->e;
- if (!bmw_mask_check_edge(walker, e)) {
- return e;
- }
+ if (!bmw_mask_check_edge(walker, e)) {
+ return e;
+ }
- BM_ITER_ELEM (v, &viter, e, BM_VERTS_OF_EDGE) {
- BM_ITER_ELEM (e_other, &eiter, v, BM_EDGES_OF_VERT) {
- if (e != e_other && BM_edge_is_boundary(e_other)) {
- if (BLI_gset_haskey(walker->visit_set, e_other)) {
- continue;
- }
+ BM_ITER_ELEM (v, &viter, e, BM_VERTS_OF_EDGE) {
+ BM_ITER_ELEM (e_other, &eiter, v, BM_EDGES_OF_VERT) {
+ if (e != e_other && BM_edge_is_boundary(e_other)) {
+ if (BLI_gset_haskey(walker->visit_set, e_other)) {
+ continue;
+ }
- if (!bmw_mask_check_edge(walker, e_other)) {
- continue;
- }
+ if (!bmw_mask_check_edge(walker, e_other)) {
+ continue;
+ }
- lwalk = BMW_state_add(walker);
- BLI_gset_insert(walker->visit_set, e_other);
+ lwalk = BMW_state_add(walker);
+ BLI_gset_insert(walker->visit_set, e_other);
- lwalk->e = e_other;
- }
- }
- }
+ lwalk->e = e_other;
+ }
+ }
+ }
- return e;
+ return e;
}
/** \} */
-
/** \name UV Edge Walker
*
* walk over uv islands; takes a loop as input. restrict flag
@@ -1482,238 +1447,239 @@ static void *bmw_EdgeboundaryWalker_step(BMWalker *walker)
static void bmw_UVEdgeWalker_begin(BMWalker *walker, void *data)
{
- BMwUVEdgeWalker *lwalk;
- BMLoop *l = data;
+ BMwUVEdgeWalker *lwalk;
+ BMLoop *l = data;
- if (BLI_gset_haskey(walker->visit_set, l)) {
- return;
- }
+ if (BLI_gset_haskey(walker->visit_set, l)) {
+ return;
+ }
- lwalk = BMW_state_add(walker);
- lwalk->l = l;
- BLI_gset_insert(walker->visit_set, l);
+ lwalk = BMW_state_add(walker);
+ lwalk->l = l;
+ BLI_gset_insert(walker->visit_set, l);
}
static void *bmw_UVEdgeWalker_yield(BMWalker *walker)
{
- BMwUVEdgeWalker *lwalk = BMW_current_state(walker);
+ BMwUVEdgeWalker *lwalk = BMW_current_state(walker);
- if (!lwalk) {
- return NULL;
- }
+ if (!lwalk) {
+ return NULL;
+ }
- return lwalk->l;
+ return lwalk->l;
}
static void *bmw_UVEdgeWalker_step(BMWalker *walker)
{
- const int type = walker->bm->ldata.layers[walker->layer].type;
- const int offset = walker->bm->ldata.layers[walker->layer].offset;
+ const int type = walker->bm->ldata.layers[walker->layer].type;
+ const int offset = walker->bm->ldata.layers[walker->layer].offset;
- BMwUVEdgeWalker *lwalk, owalk;
- BMLoop *l;
- int i;
+ BMwUVEdgeWalker *lwalk, owalk;
+ BMLoop *l;
+ int i;
- BMW_state_remove_r(walker, &owalk);
- lwalk = &owalk;
+ BMW_state_remove_r(walker, &owalk);
+ lwalk = &owalk;
- l = lwalk->l;
+ l = lwalk->l;
- if (!bmw_mask_check_edge(walker, l->e)) {
- return l;
- }
+ if (!bmw_mask_check_edge(walker, l->e)) {
+ return l;
+ }
- /* go over loops around l->v and nl->v and see which ones share l and nl's
- * mloopuv's coordinates. in addition, push on l->next if necessary */
- for (i = 0; i < 2; i++) {
- BMIter liter;
- BMLoop *l_pivot, *l_radial;
+ /* go over loops around l->v and nl->v and see which ones share l and nl's
+ * mloopuv's coordinates. in addition, push on l->next if necessary */
+ for (i = 0; i < 2; i++) {
+ BMIter liter;
+ BMLoop *l_pivot, *l_radial;
- l_pivot = i ? l->next : l;
- BM_ITER_ELEM (l_radial, &liter, l_pivot->v, BM_LOOPS_OF_VERT) {
- BMLoop *l_radial_first = l_radial;
- void *data_pivot = BM_ELEM_CD_GET_VOID_P(l_pivot, offset);
+ l_pivot = i ? l->next : l;
+ BM_ITER_ELEM (l_radial, &liter, l_pivot->v, BM_LOOPS_OF_VERT) {
+ BMLoop *l_radial_first = l_radial;
+ void *data_pivot = BM_ELEM_CD_GET_VOID_P(l_pivot, offset);
- do {
- BMLoop *l_other;
- void *data_other;
+ do {
+ BMLoop *l_other;
+ void *data_other;
- if (BLI_gset_haskey(walker->visit_set, l_radial)) {
- continue;
- }
+ if (BLI_gset_haskey(walker->visit_set, l_radial)) {
+ continue;
+ }
- if (l_radial->v != l_pivot->v) {
- if (!bmw_mask_check_edge(walker, l_radial->e)) {
- continue;
- }
- }
+ if (l_radial->v != l_pivot->v) {
+ if (!bmw_mask_check_edge(walker, l_radial->e)) {
+ continue;
+ }
+ }
- l_other = (l_radial->v != l_pivot->v) ? l_radial->next : l_radial;
- data_other = BM_ELEM_CD_GET_VOID_P(l_other, offset);
+ l_other = (l_radial->v != l_pivot->v) ? l_radial->next : l_radial;
+ data_other = BM_ELEM_CD_GET_VOID_P(l_other, offset);
- if (!CustomData_data_equals(type, data_pivot, data_other)) {
- continue;
- }
+ if (!CustomData_data_equals(type, data_pivot, data_other)) {
+ continue;
+ }
- lwalk = BMW_state_add(walker);
- BLI_gset_insert(walker->visit_set, l_radial);
+ lwalk = BMW_state_add(walker);
+ BLI_gset_insert(walker->visit_set, l_radial);
- lwalk->l = l_radial;
+ lwalk->l = l_radial;
- } while ((l_radial = l_radial->radial_next) != l_radial_first);
- }
- }
+ } while ((l_radial = l_radial->radial_next) != l_radial_first);
+ }
+ }
- return l;
+ return l;
}
/** \} */
-
static BMWalker bmw_VertShellWalker_Type = {
- BM_VERT | BM_EDGE,
- bmw_VertShellWalker_begin,
- bmw_VertShellWalker_step,
- bmw_VertShellWalker_yield,
- sizeof(BMwShellWalker),
- BMW_BREADTH_FIRST,
- BM_EDGE, /* valid restrict masks */
+ BM_VERT | BM_EDGE,
+ bmw_VertShellWalker_begin,
+ bmw_VertShellWalker_step,
+ bmw_VertShellWalker_yield,
+ sizeof(BMwShellWalker),
+ BMW_BREADTH_FIRST,
+ BM_EDGE, /* valid restrict masks */
};
static BMWalker bmw_LoopShellWalker_Type = {
- BM_FACE | BM_LOOP | BM_EDGE | BM_VERT,
- bmw_LoopShellWalker_begin,
- bmw_LoopShellWalker_step,
- bmw_LoopShellWalker_yield,
- sizeof(BMwLoopShellWalker),
- BMW_BREADTH_FIRST,
- BM_EDGE, /* valid restrict masks */
+ BM_FACE | BM_LOOP | BM_EDGE | BM_VERT,
+ bmw_LoopShellWalker_begin,
+ bmw_LoopShellWalker_step,
+ bmw_LoopShellWalker_yield,
+ sizeof(BMwLoopShellWalker),
+ BMW_BREADTH_FIRST,
+ BM_EDGE, /* valid restrict masks */
};
static BMWalker bmw_LoopShellWireWalker_Type = {
- BM_FACE | BM_LOOP | BM_EDGE | BM_VERT,
- bmw_LoopShellWireWalker_begin,
- bmw_LoopShellWireWalker_step,
- bmw_LoopShellWireWalker_yield,
- sizeof(BMwLoopShellWireWalker),
- BMW_BREADTH_FIRST,
- BM_EDGE, /* valid restrict masks */
+ BM_FACE | BM_LOOP | BM_EDGE | BM_VERT,
+ bmw_LoopShellWireWalker_begin,
+ bmw_LoopShellWireWalker_step,
+ bmw_LoopShellWireWalker_yield,
+ sizeof(BMwLoopShellWireWalker),
+ BMW_BREADTH_FIRST,
+ BM_EDGE, /* valid restrict masks */
};
static BMWalker bmw_FaceShellWalker_Type = {
- BM_EDGE,
- bmw_FaceShellWalker_begin,
- bmw_FaceShellWalker_step,
- bmw_FaceShellWalker_yield,
- sizeof(BMwShellWalker),
- BMW_BREADTH_FIRST,
- BM_EDGE, /* valid restrict masks */
+ BM_EDGE,
+ bmw_FaceShellWalker_begin,
+ bmw_FaceShellWalker_step,
+ bmw_FaceShellWalker_yield,
+ sizeof(BMwShellWalker),
+ BMW_BREADTH_FIRST,
+ BM_EDGE, /* valid restrict masks */
};
static BMWalker bmw_IslandboundWalker_Type = {
- BM_LOOP,
- bmw_IslandboundWalker_begin,
- bmw_IslandboundWalker_step,
- bmw_IslandboundWalker_yield,
- sizeof(BMwIslandboundWalker),
- BMW_DEPTH_FIRST,
- BM_FACE, /* valid restrict masks */
+ BM_LOOP,
+ bmw_IslandboundWalker_begin,
+ bmw_IslandboundWalker_step,
+ bmw_IslandboundWalker_yield,
+ sizeof(BMwIslandboundWalker),
+ BMW_DEPTH_FIRST,
+ BM_FACE, /* valid restrict masks */
};
static BMWalker bmw_IslandWalker_Type = {
- BM_FACE,
- bmw_IslandWalker_begin,
- bmw_IslandWalker_step,
- bmw_IslandWalker_yield,
- sizeof(BMwIslandWalker),
- BMW_BREADTH_FIRST,
- BM_EDGE | BM_FACE, /* valid restrict masks */
+ BM_FACE,
+ bmw_IslandWalker_begin,
+ bmw_IslandWalker_step,
+ bmw_IslandWalker_yield,
+ sizeof(BMwIslandWalker),
+ BMW_BREADTH_FIRST,
+ BM_EDGE | BM_FACE, /* valid restrict masks */
};
static BMWalker bmw_IslandManifoldWalker_Type = {
- BM_FACE,
- bmw_IslandWalker_begin,
- bmw_IslandManifoldWalker_step, /* only difference with BMW_ISLAND */
- bmw_IslandWalker_yield,
- sizeof(BMwIslandWalker),
- BMW_BREADTH_FIRST,
- BM_EDGE | BM_FACE, /* valid restrict masks */
+ BM_FACE,
+ bmw_IslandWalker_begin,
+ bmw_IslandManifoldWalker_step, /* only difference with BMW_ISLAND */
+ bmw_IslandWalker_yield,
+ sizeof(BMwIslandWalker),
+ BMW_BREADTH_FIRST,
+ BM_EDGE | BM_FACE, /* valid restrict masks */
};
static BMWalker bmw_EdgeLoopWalker_Type = {
- BM_EDGE,
- bmw_EdgeLoopWalker_begin,
- bmw_EdgeLoopWalker_step,
- bmw_EdgeLoopWalker_yield,
- sizeof(BMwEdgeLoopWalker),
- BMW_DEPTH_FIRST,
- 0, /* valid restrict masks */ /* could add flags here but so far none are used */
+ BM_EDGE,
+ bmw_EdgeLoopWalker_begin,
+ bmw_EdgeLoopWalker_step,
+ bmw_EdgeLoopWalker_yield,
+ sizeof(BMwEdgeLoopWalker),
+ BMW_DEPTH_FIRST,
+ 0,
+ /* valid restrict masks */ /* could add flags here but so far none are used */
};
static BMWalker bmw_FaceLoopWalker_Type = {
- BM_EDGE,
- bmw_FaceLoopWalker_begin,
- bmw_FaceLoopWalker_step,
- bmw_FaceLoopWalker_yield,
- sizeof(BMwFaceLoopWalker),
- BMW_DEPTH_FIRST,
- 0, /* valid restrict masks */ /* could add flags here but so far none are used */
+ BM_EDGE,
+ bmw_FaceLoopWalker_begin,
+ bmw_FaceLoopWalker_step,
+ bmw_FaceLoopWalker_yield,
+ sizeof(BMwFaceLoopWalker),
+ BMW_DEPTH_FIRST,
+ 0,
+ /* valid restrict masks */ /* could add flags here but so far none are used */
};
static BMWalker bmw_EdgeringWalker_Type = {
- BM_EDGE,
- bmw_EdgeringWalker_begin,
- bmw_EdgeringWalker_step,
- bmw_EdgeringWalker_yield,
- sizeof(BMwEdgeringWalker),
- BMW_DEPTH_FIRST,
- BM_EDGE, /* valid restrict masks */
+ BM_EDGE,
+ bmw_EdgeringWalker_begin,
+ bmw_EdgeringWalker_step,
+ bmw_EdgeringWalker_yield,
+ sizeof(BMwEdgeringWalker),
+ BMW_DEPTH_FIRST,
+ BM_EDGE, /* valid restrict masks */
};
static BMWalker bmw_EdgeboundaryWalker_Type = {
- BM_EDGE,
- bmw_EdgeboundaryWalker_begin,
- bmw_EdgeboundaryWalker_step,
- bmw_EdgeboundaryWalker_yield,
- sizeof(BMwEdgeboundaryWalker),
- BMW_DEPTH_FIRST,
- 0,
+ BM_EDGE,
+ bmw_EdgeboundaryWalker_begin,
+ bmw_EdgeboundaryWalker_step,
+ bmw_EdgeboundaryWalker_yield,
+ sizeof(BMwEdgeboundaryWalker),
+ BMW_DEPTH_FIRST,
+ 0,
};
static BMWalker bmw_UVEdgeWalker_Type = {
- BM_LOOP,
- bmw_UVEdgeWalker_begin,
- bmw_UVEdgeWalker_step,
- bmw_UVEdgeWalker_yield,
- sizeof(BMwUVEdgeWalker),
- BMW_DEPTH_FIRST,
- BM_EDGE, /* valid restrict masks */
+ BM_LOOP,
+ bmw_UVEdgeWalker_begin,
+ bmw_UVEdgeWalker_step,
+ bmw_UVEdgeWalker_yield,
+ sizeof(BMwUVEdgeWalker),
+ BMW_DEPTH_FIRST,
+ BM_EDGE, /* valid restrict masks */
};
static BMWalker bmw_ConnectedVertexWalker_Type = {
- BM_VERT,
- bmw_ConnectedVertexWalker_begin,
- bmw_ConnectedVertexWalker_step,
- bmw_ConnectedVertexWalker_yield,
- sizeof(BMwConnectedVertexWalker),
- BMW_BREADTH_FIRST,
- BM_VERT, /* valid restrict masks */
+ BM_VERT,
+ bmw_ConnectedVertexWalker_begin,
+ bmw_ConnectedVertexWalker_step,
+ bmw_ConnectedVertexWalker_yield,
+ sizeof(BMwConnectedVertexWalker),
+ BMW_BREADTH_FIRST,
+ BM_VERT, /* valid restrict masks */
};
BMWalker *bm_walker_types[] = {
- &bmw_VertShellWalker_Type, /* BMW_VERT_SHELL */
- &bmw_LoopShellWalker_Type, /* BMW_LOOP_SHELL */
- &bmw_LoopShellWireWalker_Type, /* BMW_LOOP_SHELL_WIRE */
- &bmw_FaceShellWalker_Type, /* BMW_FACE_SHELL */
- &bmw_EdgeLoopWalker_Type, /* BMW_EDGELOOP */
- &bmw_FaceLoopWalker_Type, /* BMW_FACELOOP */
- &bmw_EdgeringWalker_Type, /* BMW_EDGERING */
- &bmw_EdgeboundaryWalker_Type, /* BMW_EDGEBOUNDARY */
- &bmw_UVEdgeWalker_Type, /* BMW_LOOPDATA_ISLAND */
- &bmw_IslandboundWalker_Type, /* BMW_ISLANDBOUND */
- &bmw_IslandWalker_Type, /* BMW_ISLAND */
- &bmw_IslandManifoldWalker_Type, /* BMW_ISLAND_MANIFOLD */
- &bmw_ConnectedVertexWalker_Type, /* BMW_CONNECTED_VERTEX */
+ &bmw_VertShellWalker_Type, /* BMW_VERT_SHELL */
+ &bmw_LoopShellWalker_Type, /* BMW_LOOP_SHELL */
+ &bmw_LoopShellWireWalker_Type, /* BMW_LOOP_SHELL_WIRE */
+ &bmw_FaceShellWalker_Type, /* BMW_FACE_SHELL */
+ &bmw_EdgeLoopWalker_Type, /* BMW_EDGELOOP */
+ &bmw_FaceLoopWalker_Type, /* BMW_FACELOOP */
+ &bmw_EdgeringWalker_Type, /* BMW_EDGERING */
+ &bmw_EdgeboundaryWalker_Type, /* BMW_EDGEBOUNDARY */
+ &bmw_UVEdgeWalker_Type, /* BMW_LOOPDATA_ISLAND */
+ &bmw_IslandboundWalker_Type, /* BMW_ISLANDBOUND */
+ &bmw_IslandWalker_Type, /* BMW_ISLAND */
+ &bmw_IslandManifoldWalker_Type, /* BMW_ISLAND_MANIFOLD */
+ &bmw_ConnectedVertexWalker_Type, /* BMW_CONNECTED_VERTEX */
};
const int bm_totwalkers = ARRAY_SIZE(bm_walker_types);
diff --git a/source/blender/bmesh/intern/bmesh_walkers_private.h b/source/blender/bmesh/intern/bmesh_walkers_private.h
index 185c18d6777..3457a2b9187 100644
--- a/source/blender/bmesh/intern/bmesh_walkers_private.h
+++ b/source/blender/bmesh/intern/bmesh_walkers_private.h
@@ -26,75 +26,73 @@
extern BMWalker *bm_walker_types[];
extern const int bm_totwalkers;
-
/* Pointer hiding */
typedef struct BMwGenericWalker {
- Link link;
- int depth;
+ Link link;
+ int depth;
} BMwGenericWalker;
-
typedef struct BMwShellWalker {
- BMwGenericWalker header;
- BMEdge *curedge;
+ BMwGenericWalker header;
+ BMEdge *curedge;
} BMwShellWalker;
typedef struct BMwLoopShellWalker {
- BMwGenericWalker header;
- BMLoop *curloop;
+ BMwGenericWalker header;
+ BMLoop *curloop;
} BMwLoopShellWalker;
typedef struct BMwLoopShellWireWalker {
- BMwGenericWalker header;
- BMElem *curelem;
+ BMwGenericWalker header;
+ BMElem *curelem;
} BMwLoopShellWireWalker;
typedef struct BMwIslandboundWalker {
- BMwGenericWalker header;
- BMLoop *base;
- BMVert *lastv;
- BMLoop *curloop;
+ BMwGenericWalker header;
+ BMLoop *base;
+ BMVert *lastv;
+ BMLoop *curloop;
} BMwIslandboundWalker;
typedef struct BMwIslandWalker {
- BMwGenericWalker header;
- BMFace *cur;
+ BMwGenericWalker header;
+ BMFace *cur;
} BMwIslandWalker;
typedef struct BMwEdgeLoopWalker {
- BMwGenericWalker header;
- BMEdge *cur, *start;
- BMVert *lastv, *startv;
- BMFace *f_hub;
- bool is_boundary; /* boundary looping changes behavior */
- bool is_single; /* single means the edge verts are only connected to 1 face */
+ BMwGenericWalker header;
+ BMEdge *cur, *start;
+ BMVert *lastv, *startv;
+ BMFace *f_hub;
+ bool is_boundary; /* boundary looping changes behavior */
+ bool is_single; /* single means the edge verts are only connected to 1 face */
} BMwEdgeLoopWalker;
typedef struct BMwFaceLoopWalker {
- BMwGenericWalker header;
- BMLoop *l;
- bool no_calc;
+ BMwGenericWalker header;
+ BMLoop *l;
+ bool no_calc;
} BMwFaceLoopWalker;
typedef struct BMwEdgeringWalker {
- BMwGenericWalker header;
- BMLoop *l;
- BMEdge *wireedge;
+ BMwGenericWalker header;
+ BMLoop *l;
+ BMEdge *wireedge;
} BMwEdgeringWalker;
typedef struct BMwEdgeboundaryWalker {
- BMwGenericWalker header;
- BMEdge *e;
+ BMwGenericWalker header;
+ BMEdge *e;
} BMwEdgeboundaryWalker;
typedef struct BMwUVEdgeWalker {
- BMwGenericWalker header;
- BMLoop *l;
+ BMwGenericWalker header;
+ BMLoop *l;
} BMwUVEdgeWalker;
typedef struct BMwConnectedVertexWalker {
- BMwGenericWalker header;
- BMVert *curvert;
+ BMwGenericWalker header;
+ BMVert *curvert;
} BMwConnectedVertexWalker;
#endif /* __BMESH_WALKERS_PRIVATE_H__ */
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);
}
diff --git a/source/blender/bmesh/tools/bmesh_beautify.c b/source/blender/bmesh/tools/bmesh_beautify.c
index aa484a2ef8b..e8a49c895ab 100644
--- a/source/blender/bmesh/tools/bmesh_beautify.c
+++ b/source/blender/bmesh/tools/bmesh_beautify.c
@@ -36,8 +36,7 @@
#include "MEM_guardedalloc.h"
#include "bmesh.h"
-#include "bmesh_beautify.h" /* own include */
-
+#include "bmesh_beautify.h" /* own include */
// #define DEBUG_TIME
@@ -50,169 +49,169 @@
/* GSet for edge rotation */
typedef struct EdRotState {
- int v1, v2; /* edge vert, small -> large */
- int f1, f2; /* face vert, small -> large */
+ int v1, v2; /* edge vert, small -> large */
+ int f1, f2; /* face vert, small -> large */
} EdRotState;
#if 0
/* use BLI_ghashutil_inthash_v4 direct */
static uint erot_gsetutil_hash(const void *ptr)
{
- const EdRotState *e_state = (const EdRotState *)ptr;
- return BLI_ghashutil_inthash_v4(&e_state->v1);
+ const EdRotState *e_state = (const EdRotState *)ptr;
+ return BLI_ghashutil_inthash_v4(&e_state->v1);
}
#endif
#if 0
static int erot_gsetutil_cmp(const void *a, const void *b)
{
- const EdRotState *e_state_a = (const EdRotState *)a;
- const EdRotState *e_state_b = (const EdRotState *)b;
- if (e_state_a->v1 < e_state_b->v1) return -1;
- else if (e_state_a->v1 > e_state_b->v1) return 1;
- else if (e_state_a->v2 < e_state_b->v2) return -1;
- else if (e_state_a->v2 > e_state_b->v2) return 1;
- else if (e_state_a->f1 < e_state_b->f1) return -1;
- else if (e_state_a->f1 > e_state_b->f1) return 1;
- else if (e_state_a->f2 < e_state_b->f2) return -1;
- else if (e_state_a->f2 > e_state_b->f2) return 1;
- else return 0;
+ const EdRotState *e_state_a = (const EdRotState *)a;
+ const EdRotState *e_state_b = (const EdRotState *)b;
+ if (e_state_a->v1 < e_state_b->v1) return -1;
+ else if (e_state_a->v1 > e_state_b->v1) return 1;
+ else if (e_state_a->v2 < e_state_b->v2) return -1;
+ else if (e_state_a->v2 > e_state_b->v2) return 1;
+ else if (e_state_a->f1 < e_state_b->f1) return -1;
+ else if (e_state_a->f1 > e_state_b->f1) return 1;
+ else if (e_state_a->f2 < e_state_b->f2) return -1;
+ else if (e_state_a->f2 > e_state_b->f2) return 1;
+ else return 0;
}
#endif
static GSet *erot_gset_new(void)
{
- return BLI_gset_new(BLI_ghashutil_inthash_v4_p, BLI_ghashutil_inthash_v4_cmp, __func__);
+ return BLI_gset_new(BLI_ghashutil_inthash_v4_p, BLI_ghashutil_inthash_v4_cmp, __func__);
}
/* ensure v0 is smaller */
-#define EDGE_ORD(v0, v1) \
- if (v0 > v1) { \
- SWAP(int, v0, v1); \
- } (void)0
+#define EDGE_ORD(v0, v1) \
+ if (v0 > v1) { \
+ SWAP(int, v0, v1); \
+ } \
+ (void)0
static void erot_state_ex(const BMEdge *e, int v_index[2], int f_index[2])
{
- BLI_assert(BM_edge_is_manifold(e));
- BLI_assert(BM_vert_in_edge(e, e->l->prev->v) == false);
- BLI_assert(BM_vert_in_edge(e, e->l->radial_next->prev->v) == false);
-
- /* verts of the edge */
- v_index[0] = BM_elem_index_get(e->v1);
- v_index[1] = BM_elem_index_get(e->v2);
- EDGE_ORD(v_index[0], v_index[1]);
-
- /* verts of each of the 2 faces attached to this edge
- * (that are not apart of this edge) */
- f_index[0] = BM_elem_index_get(e->l->prev->v);
- f_index[1] = BM_elem_index_get(e->l->radial_next->prev->v);
- EDGE_ORD(f_index[0], f_index[1]);
+ BLI_assert(BM_edge_is_manifold(e));
+ BLI_assert(BM_vert_in_edge(e, e->l->prev->v) == false);
+ BLI_assert(BM_vert_in_edge(e, e->l->radial_next->prev->v) == false);
+
+ /* verts of the edge */
+ v_index[0] = BM_elem_index_get(e->v1);
+ v_index[1] = BM_elem_index_get(e->v2);
+ EDGE_ORD(v_index[0], v_index[1]);
+
+ /* verts of each of the 2 faces attached to this edge
+ * (that are not apart of this edge) */
+ f_index[0] = BM_elem_index_get(e->l->prev->v);
+ f_index[1] = BM_elem_index_get(e->l->radial_next->prev->v);
+ EDGE_ORD(f_index[0], f_index[1]);
}
static void erot_state_current(const BMEdge *e, EdRotState *e_state)
{
- erot_state_ex(e, &e_state->v1, &e_state->f1);
+ erot_state_ex(e, &e_state->v1, &e_state->f1);
}
static void erot_state_alternate(const BMEdge *e, EdRotState *e_state)
{
- erot_state_ex(e, &e_state->f1, &e_state->v1);
+ erot_state_ex(e, &e_state->f1, &e_state->v1);
}
/* -------------------------------------------------------------------- */
/* Calculate the improvement of rotating the edge */
-static float bm_edge_calc_rotate_beauty__area(
- const float v1[3], const float v2[3], const float v3[3], const float v4[3])
+static float bm_edge_calc_rotate_beauty__area(const float v1[3],
+ const float v2[3],
+ const float v3[3],
+ const float v4[3])
{
- /* not a loop (only to be able to break out) */
- do {
- float v1_xy[2], v2_xy[2], v3_xy[2], v4_xy[2];
-
- /* first get the 2d values */
- {
- const float eps = 1e-5;
- float no_a[3], no_b[3];
- float no[3];
- float axis_mat[3][3];
- float no_scale;
- cross_tri_v3(no_a, v2, v3, v4);
- cross_tri_v3(no_b, v2, v4, v1);
-
- // printf("%p %p %p %p - %p %p\n", v1, v2, v3, v4, e->l->f, e->l->radial_next->f);
- BLI_assert((ELEM(v1, v2, v3, v4) == false) &&
- (ELEM(v2, v1, v3, v4) == false) &&
- (ELEM(v3, v1, v2, v4) == false) &&
- (ELEM(v4, v1, v2, v3) == false));
-
- add_v3_v3v3(no, no_a, no_b);
- if (UNLIKELY((no_scale = normalize_v3(no)) == 0.0f)) {
- break;
- }
-
- axis_dominant_v3_to_m3(axis_mat, no);
- mul_v2_m3v3(v1_xy, axis_mat, v1);
- mul_v2_m3v3(v2_xy, axis_mat, v2);
- mul_v2_m3v3(v3_xy, axis_mat, v3);
- mul_v2_m3v3(v4_xy, axis_mat, v4);
-
- /**
- * Check if input faces are already flipped.
- * Logic for 'signum_i' addition is:
- *
- * Accept:
- * - (1, 1) or (-1, -1): same side (common case).
- * - (-1/1, 0): one degenerate, OK since we may rotate into a valid state.
- *
- * Ignore:
- * - (-1, 1): opposite winding, ignore.
- * - ( 0, 0): both degenerate, ignore.
- *
- * \note The cross product is divided by 'no_scale'
- * so the rotation calculation is scale independent.
- */
- if (!(signum_i_ex(cross_tri_v2(v2_xy, v3_xy, v4_xy) / no_scale, eps) +
- signum_i_ex(cross_tri_v2(v2_xy, v4_xy, v1_xy) / no_scale, eps)))
- {
- break;
- }
- }
-
- /**
- * Important to lock degenerate here,
- * since the triangle pars will be projected into different 2D spaces.
- * Allowing to rotate out of a degenerate state can flip the faces (when performed iteratively).
- */
- return BLI_polyfill_beautify_quad_rotate_calc_ex(v1_xy, v2_xy, v3_xy, v4_xy, true);
- } while (false);
-
- return FLT_MAX;
+ /* not a loop (only to be able to break out) */
+ do {
+ float v1_xy[2], v2_xy[2], v3_xy[2], v4_xy[2];
+
+ /* first get the 2d values */
+ {
+ const float eps = 1e-5;
+ float no_a[3], no_b[3];
+ float no[3];
+ float axis_mat[3][3];
+ float no_scale;
+ cross_tri_v3(no_a, v2, v3, v4);
+ cross_tri_v3(no_b, v2, v4, v1);
+
+ // printf("%p %p %p %p - %p %p\n", v1, v2, v3, v4, e->l->f, e->l->radial_next->f);
+ BLI_assert((ELEM(v1, v2, v3, v4) == false) && (ELEM(v2, v1, v3, v4) == false) &&
+ (ELEM(v3, v1, v2, v4) == false) && (ELEM(v4, v1, v2, v3) == false));
+
+ add_v3_v3v3(no, no_a, no_b);
+ if (UNLIKELY((no_scale = normalize_v3(no)) == 0.0f)) {
+ break;
+ }
+
+ axis_dominant_v3_to_m3(axis_mat, no);
+ mul_v2_m3v3(v1_xy, axis_mat, v1);
+ mul_v2_m3v3(v2_xy, axis_mat, v2);
+ mul_v2_m3v3(v3_xy, axis_mat, v3);
+ mul_v2_m3v3(v4_xy, axis_mat, v4);
+
+ /**
+ * Check if input faces are already flipped.
+ * Logic for 'signum_i' addition is:
+ *
+ * Accept:
+ * - (1, 1) or (-1, -1): same side (common case).
+ * - (-1/1, 0): one degenerate, OK since we may rotate into a valid state.
+ *
+ * Ignore:
+ * - (-1, 1): opposite winding, ignore.
+ * - ( 0, 0): both degenerate, ignore.
+ *
+ * \note The cross product is divided by 'no_scale'
+ * so the rotation calculation is scale independent.
+ */
+ if (!(signum_i_ex(cross_tri_v2(v2_xy, v3_xy, v4_xy) / no_scale, eps) +
+ signum_i_ex(cross_tri_v2(v2_xy, v4_xy, v1_xy) / no_scale, eps))) {
+ break;
+ }
+ }
+
+ /**
+ * Important to lock degenerate here,
+ * since the triangle pars will be projected into different 2D spaces.
+ * Allowing to rotate out of a degenerate state can flip the faces (when performed iteratively).
+ */
+ return BLI_polyfill_beautify_quad_rotate_calc_ex(v1_xy, v2_xy, v3_xy, v4_xy, true);
+ } while (false);
+
+ return FLT_MAX;
}
-static float bm_edge_calc_rotate_beauty__angle(
- const float v1[3], const float v2[3], const float v3[3], const float v4[3])
+static float bm_edge_calc_rotate_beauty__angle(const float v1[3],
+ const float v2[3],
+ const float v3[3],
+ const float v4[3])
{
- /* not a loop (only to be able to break out) */
- do {
- float no_a[3], no_b[3];
- float angle_24, angle_13;
-
- /* edge (2-4), current state */
- normal_tri_v3(no_a, v2, v3, v4);
- normal_tri_v3(no_b, v2, v4, v1);
- angle_24 = angle_normalized_v3v3(no_a, no_b);
-
- /* edge (1-3), new state */
- /* only check new state for degenerate outcome */
- if ((normal_tri_v3(no_a, v1, v2, v3) == 0.0f) ||
- (normal_tri_v3(no_b, v1, v3, v4) == 0.0f))
- {
- break;
- }
- angle_13 = angle_normalized_v3v3(no_a, no_b);
-
- return angle_13 - angle_24;
- } while (false);
-
- return FLT_MAX;
+ /* not a loop (only to be able to break out) */
+ do {
+ float no_a[3], no_b[3];
+ float angle_24, angle_13;
+
+ /* edge (2-4), current state */
+ normal_tri_v3(no_a, v2, v3, v4);
+ normal_tri_v3(no_b, v2, v4, v1);
+ angle_24 = angle_normalized_v3v3(no_a, no_b);
+
+ /* edge (1-3), new state */
+ /* only check new state for degenerate outcome */
+ if ((normal_tri_v3(no_a, v1, v2, v3) == 0.0f) || (normal_tri_v3(no_b, v1, v3, v4) == 0.0f)) {
+ break;
+ }
+ angle_13 = angle_normalized_v3v3(no_a, no_b);
+
+ return angle_13 - angle_24;
+ } while (false);
+
+ return FLT_MAX;
}
/**
@@ -221,44 +220,47 @@ static float bm_edge_calc_rotate_beauty__angle(
*
* \return (negative number means the edge can be rotated, lager == better).
*/
-float BM_verts_calc_rotate_beauty(
- const BMVert *v1, const BMVert *v2, const BMVert *v3, const BMVert *v4,
- const short flag, const short method)
+float BM_verts_calc_rotate_beauty(const BMVert *v1,
+ const BMVert *v2,
+ const BMVert *v3,
+ const BMVert *v4,
+ const short flag,
+ const short method)
{
- /* not a loop (only to be able to break out) */
- do {
- if (flag & VERT_RESTRICT_TAG) {
- const BMVert *v_a = v1, *v_b = v3;
- if (BM_elem_flag_test(v_a, BM_ELEM_TAG) == BM_elem_flag_test(v_b, BM_ELEM_TAG)) {
- break;
- }
- }
-
- if (UNLIKELY(v1 == v3)) {
- // printf("This should never happen, but does sometimes!\n");
- break;
- }
-
- switch (method) {
- case 0:
- return bm_edge_calc_rotate_beauty__area(v1->co, v2->co, v3->co, v4->co);
- default:
- return bm_edge_calc_rotate_beauty__angle(v1->co, v2->co, v3->co, v4->co);
- }
- } while (false);
-
- return FLT_MAX;
+ /* not a loop (only to be able to break out) */
+ do {
+ if (flag & VERT_RESTRICT_TAG) {
+ const BMVert *v_a = v1, *v_b = v3;
+ if (BM_elem_flag_test(v_a, BM_ELEM_TAG) == BM_elem_flag_test(v_b, BM_ELEM_TAG)) {
+ break;
+ }
+ }
+
+ if (UNLIKELY(v1 == v3)) {
+ // printf("This should never happen, but does sometimes!\n");
+ break;
+ }
+
+ switch (method) {
+ case 0:
+ return bm_edge_calc_rotate_beauty__area(v1->co, v2->co, v3->co, v4->co);
+ default:
+ return bm_edge_calc_rotate_beauty__angle(v1->co, v2->co, v3->co, v4->co);
+ }
+ } while (false);
+
+ return FLT_MAX;
}
static float bm_edge_calc_rotate_beauty(const BMEdge *e, const short flag, const short method)
{
- const BMVert *v1, *v2, *v3, *v4;
- v1 = e->l->prev->v; /* first vert co */
- v2 = e->l->v; /* e->v1 or e->v2*/
- v3 = e->l->radial_next->prev->v; /* second vert co */
- v4 = e->l->next->v; /* e->v1 or e->v2*/
+ const BMVert *v1, *v2, *v3, *v4;
+ v1 = e->l->prev->v; /* first vert co */
+ v2 = e->l->v; /* e->v1 or e->v2*/
+ v3 = e->l->radial_next->prev->v; /* second vert co */
+ v4 = e->l->next->v; /* e->v1 or e->v2*/
- return BM_verts_calc_rotate_beauty(v1, v2, v3, v4, flag, method);
+ return BM_verts_calc_rotate_beauty(v1, v2, v3, v4, flag, method);
}
/* -------------------------------------------------------------------- */
@@ -266,83 +268,85 @@ static float bm_edge_calc_rotate_beauty(const BMEdge *e, const short flag, const
BLI_INLINE bool edge_in_array(const BMEdge *e, const BMEdge **edge_array, const int edge_array_len)
{
- const int index = BM_elem_index_get(e);
- return ((index >= 0) &&
- (index < edge_array_len) &&
- (e == edge_array[index]));
+ const int index = BM_elem_index_get(e);
+ return ((index >= 0) && (index < edge_array_len) && (e == edge_array[index]));
}
/* recalc an edge in the heap (surrounding geometry has changed) */
-static void bm_edge_update_beauty_cost_single(
- BMEdge *e, Heap *eheap, HeapNode **eheap_table, GSet **edge_state_arr,
- /* only for testing the edge is in the array */
- const BMEdge **edge_array, const int edge_array_len,
-
- const short flag, const short method)
+static void bm_edge_update_beauty_cost_single(BMEdge *e,
+ Heap *eheap,
+ HeapNode **eheap_table,
+ GSet **edge_state_arr,
+ /* only for testing the edge is in the array */
+ const BMEdge **edge_array,
+ const int edge_array_len,
+
+ const short flag,
+ const short method)
{
- if (edge_in_array(e, edge_array, edge_array_len)) {
- const int i = BM_elem_index_get(e);
- GSet *e_state_set = edge_state_arr[i];
-
- if (eheap_table[i]) {
- BLI_heap_remove(eheap, eheap_table[i]);
- eheap_table[i] = NULL;
- }
-
- /* check if we can add it back */
- BLI_assert(BM_edge_is_manifold(e) == true);
-
- /* check we're not moving back into a state we have been in before */
- if (e_state_set != NULL) {
- EdRotState e_state_alt;
- erot_state_alternate(e, &e_state_alt);
- if (BLI_gset_haskey(e_state_set, (void *)&e_state_alt)) {
- // printf(" skipping, we already have this state\n");
- return;
- }
- }
-
- {
- /* recalculate edge */
- const float cost = bm_edge_calc_rotate_beauty(e, flag, method);
- if (cost < 0.0f) {
- eheap_table[i] = BLI_heap_insert(eheap, cost, e);
- }
- else {
- eheap_table[i] = NULL;
- }
- }
- }
+ if (edge_in_array(e, edge_array, edge_array_len)) {
+ const int i = BM_elem_index_get(e);
+ GSet *e_state_set = edge_state_arr[i];
+
+ if (eheap_table[i]) {
+ BLI_heap_remove(eheap, eheap_table[i]);
+ eheap_table[i] = NULL;
+ }
+
+ /* check if we can add it back */
+ BLI_assert(BM_edge_is_manifold(e) == true);
+
+ /* check we're not moving back into a state we have been in before */
+ if (e_state_set != NULL) {
+ EdRotState e_state_alt;
+ erot_state_alternate(e, &e_state_alt);
+ if (BLI_gset_haskey(e_state_set, (void *)&e_state_alt)) {
+ // printf(" skipping, we already have this state\n");
+ return;
+ }
+ }
+
+ {
+ /* recalculate edge */
+ const float cost = bm_edge_calc_rotate_beauty(e, flag, method);
+ if (cost < 0.0f) {
+ eheap_table[i] = BLI_heap_insert(eheap, cost, e);
+ }
+ else {
+ eheap_table[i] = NULL;
+ }
+ }
+ }
}
/* we have rotated an edge, tag other edges and clear this one */
-static void bm_edge_update_beauty_cost(
- BMEdge *e, Heap *eheap, HeapNode **eheap_table, GSet **edge_state_arr,
- const BMEdge **edge_array, const int edge_array_len,
- /* only for testing the edge is in the array */
- const short flag, const short method)
+static void bm_edge_update_beauty_cost(BMEdge *e,
+ Heap *eheap,
+ HeapNode **eheap_table,
+ GSet **edge_state_arr,
+ const BMEdge **edge_array,
+ const int edge_array_len,
+ /* only for testing the edge is in the array */
+ const short flag,
+ const short method)
{
- int i;
-
- BMEdge *e_arr[4] = {
- e->l->next->e,
- e->l->prev->e,
- e->l->radial_next->next->e,
- e->l->radial_next->prev->e,
- };
-
- BLI_assert(e->l->f->len == 3 &&
- e->l->radial_next->f->len == 3);
-
- BLI_assert(BM_edge_face_count_is_equal(e, 2));
-
- for (i = 0; i < 4; i++) {
- bm_edge_update_beauty_cost_single(
- e_arr[i],
- eheap, eheap_table, edge_state_arr,
- edge_array, edge_array_len,
- flag, method);
- }
+ int i;
+
+ BMEdge *e_arr[4] = {
+ e->l->next->e,
+ e->l->prev->e,
+ e->l->radial_next->next->e,
+ e->l->radial_next->prev->e,
+ };
+
+ BLI_assert(e->l->f->len == 3 && e->l->radial_next->f->len == 3);
+
+ BLI_assert(BM_edge_face_count_is_equal(e, 2));
+
+ for (i = 0; i < 4; i++) {
+ bm_edge_update_beauty_cost_single(
+ e_arr[i], eheap, eheap_table, edge_state_arr, edge_array, edge_array_len, flag, method);
+ }
}
/* -------------------------------------------------------------------- */
@@ -351,102 +355,109 @@ static void bm_edge_update_beauty_cost(
/**
* \note This function sets the edge indices to invalid values.
*/
-void BM_mesh_beautify_fill(
- BMesh *bm, BMEdge **edge_array, const int edge_array_len,
- const short flag, const short method,
- const short oflag_edge, const short oflag_face)
+void BM_mesh_beautify_fill(BMesh *bm,
+ BMEdge **edge_array,
+ const int edge_array_len,
+ const short flag,
+ const short method,
+ const short oflag_edge,
+ const short oflag_face)
{
- Heap *eheap; /* edge heap */
- HeapNode **eheap_table; /* edge index aligned table pointing to the eheap */
+ Heap *eheap; /* edge heap */
+ HeapNode **eheap_table; /* edge index aligned table pointing to the eheap */
- GSet **edge_state_arr = MEM_callocN((size_t)edge_array_len * sizeof(GSet *), __func__);
- BLI_mempool *edge_state_pool = BLI_mempool_create(sizeof(EdRotState), 0, 512, BLI_MEMPOOL_NOP);
- int i;
+ GSet **edge_state_arr = MEM_callocN((size_t)edge_array_len * sizeof(GSet *), __func__);
+ BLI_mempool *edge_state_pool = BLI_mempool_create(sizeof(EdRotState), 0, 512, BLI_MEMPOOL_NOP);
+ int i;
#ifdef DEBUG_TIME
- TIMEIT_START(beautify_fill);
+ TIMEIT_START(beautify_fill);
#endif
- eheap = BLI_heap_new_ex((uint)edge_array_len);
- eheap_table = MEM_mallocN(sizeof(HeapNode *) * (size_t)edge_array_len, __func__);
-
- /* build heap */
- for (i = 0; i < edge_array_len; i++) {
- BMEdge *e = edge_array[i];
- const float cost = bm_edge_calc_rotate_beauty(e, flag, method);
- if (cost < 0.0f) {
- eheap_table[i] = BLI_heap_insert(eheap, cost, e);
- }
- else {
- eheap_table[i] = NULL;
- }
-
- BM_elem_index_set(e, i); /* set_dirty */
- }
- bm->elem_index_dirty |= BM_EDGE;
-
- while (BLI_heap_is_empty(eheap) == false) {
- BMEdge *e = BLI_heap_pop_min(eheap);
- i = BM_elem_index_get(e);
- eheap_table[i] = NULL;
-
- BLI_assert(BM_edge_face_count_is_equal(e, 2));
-
- e = BM_edge_rotate(bm, e, false, BM_EDGEROT_CHECK_EXISTS);
-
- BLI_assert(e == NULL || BM_edge_face_count_is_equal(e, 2));
-
- if (LIKELY(e)) {
- GSet *e_state_set = edge_state_arr[i];
-
- /* add the new state into the set so we don't move into this state again
- * note: we could add the previous state too but this isn't essential)
- * for avoiding eternal loops */
- EdRotState *e_state = BLI_mempool_alloc(edge_state_pool);
- erot_state_current(e, e_state);
- if (UNLIKELY(e_state_set == NULL)) {
- edge_state_arr[i] = e_state_set = erot_gset_new(); /* store previous state */
- }
- BLI_assert(BLI_gset_haskey(e_state_set, (void *)e_state) == false);
- BLI_gset_insert(e_state_set, e_state);
-
-
- // printf(" %d -> %d, %d\n", i, BM_elem_index_get(e->v1), BM_elem_index_get(e->v2));
-
- /* maintain the index array */
- edge_array[i] = e;
- BM_elem_index_set(e, i);
-
- /* recalculate faces connected on the heap */
- bm_edge_update_beauty_cost(e, eheap, eheap_table, edge_state_arr,
- (const BMEdge **)edge_array, edge_array_len,
- flag, method);
-
- /* update flags */
- if (oflag_edge) {
- BMO_edge_flag_enable(bm, e, oflag_edge);
- }
-
- if (oflag_face) {
- BMO_face_flag_enable(bm, e->l->f, oflag_face);
- BMO_face_flag_enable(bm, e->l->radial_next->f, oflag_face);
- }
- }
- }
-
- BLI_heap_free(eheap, NULL);
- MEM_freeN(eheap_table);
-
- for (i = 0; i < edge_array_len; i++) {
- if (edge_state_arr[i]) {
- BLI_gset_free(edge_state_arr[i], NULL);
- }
- }
-
- MEM_freeN(edge_state_arr);
- BLI_mempool_destroy(edge_state_pool);
+ eheap = BLI_heap_new_ex((uint)edge_array_len);
+ eheap_table = MEM_mallocN(sizeof(HeapNode *) * (size_t)edge_array_len, __func__);
+
+ /* build heap */
+ for (i = 0; i < edge_array_len; i++) {
+ BMEdge *e = edge_array[i];
+ const float cost = bm_edge_calc_rotate_beauty(e, flag, method);
+ if (cost < 0.0f) {
+ eheap_table[i] = BLI_heap_insert(eheap, cost, e);
+ }
+ else {
+ eheap_table[i] = NULL;
+ }
+
+ BM_elem_index_set(e, i); /* set_dirty */
+ }
+ bm->elem_index_dirty |= BM_EDGE;
+
+ while (BLI_heap_is_empty(eheap) == false) {
+ BMEdge *e = BLI_heap_pop_min(eheap);
+ i = BM_elem_index_get(e);
+ eheap_table[i] = NULL;
+
+ BLI_assert(BM_edge_face_count_is_equal(e, 2));
+
+ e = BM_edge_rotate(bm, e, false, BM_EDGEROT_CHECK_EXISTS);
+
+ BLI_assert(e == NULL || BM_edge_face_count_is_equal(e, 2));
+
+ if (LIKELY(e)) {
+ GSet *e_state_set = edge_state_arr[i];
+
+ /* add the new state into the set so we don't move into this state again
+ * note: we could add the previous state too but this isn't essential)
+ * for avoiding eternal loops */
+ EdRotState *e_state = BLI_mempool_alloc(edge_state_pool);
+ erot_state_current(e, e_state);
+ if (UNLIKELY(e_state_set == NULL)) {
+ edge_state_arr[i] = e_state_set = erot_gset_new(); /* store previous state */
+ }
+ BLI_assert(BLI_gset_haskey(e_state_set, (void *)e_state) == false);
+ BLI_gset_insert(e_state_set, e_state);
+
+ // printf(" %d -> %d, %d\n", i, BM_elem_index_get(e->v1), BM_elem_index_get(e->v2));
+
+ /* maintain the index array */
+ edge_array[i] = e;
+ BM_elem_index_set(e, i);
+
+ /* recalculate faces connected on the heap */
+ bm_edge_update_beauty_cost(e,
+ eheap,
+ eheap_table,
+ edge_state_arr,
+ (const BMEdge **)edge_array,
+ edge_array_len,
+ flag,
+ method);
+
+ /* update flags */
+ if (oflag_edge) {
+ BMO_edge_flag_enable(bm, e, oflag_edge);
+ }
+
+ if (oflag_face) {
+ BMO_face_flag_enable(bm, e->l->f, oflag_face);
+ BMO_face_flag_enable(bm, e->l->radial_next->f, oflag_face);
+ }
+ }
+ }
+
+ BLI_heap_free(eheap, NULL);
+ MEM_freeN(eheap_table);
+
+ for (i = 0; i < edge_array_len; i++) {
+ if (edge_state_arr[i]) {
+ BLI_gset_free(edge_state_arr[i], NULL);
+ }
+ }
+
+ MEM_freeN(edge_state_arr);
+ BLI_mempool_destroy(edge_state_pool);
#ifdef DEBUG_TIME
- TIMEIT_END(beautify_fill);
+ TIMEIT_END(beautify_fill);
#endif
}
diff --git a/source/blender/bmesh/tools/bmesh_beautify.h b/source/blender/bmesh/tools/bmesh_beautify.h
index f967af2bfe7..f957f0d3560 100644
--- a/source/blender/bmesh/tools/bmesh_beautify.h
+++ b/source/blender/bmesh/tools/bmesh_beautify.h
@@ -22,17 +22,22 @@
*/
enum {
- VERT_RESTRICT_TAG = (1 << 0),
+ VERT_RESTRICT_TAG = (1 << 0),
};
-void BM_mesh_beautify_fill(
- BMesh *bm, BMEdge **edge_array, const int edge_array_len,
- const short flag, const short method,
- const short oflag_edge, const short oflag_face);
+void BM_mesh_beautify_fill(BMesh *bm,
+ BMEdge **edge_array,
+ const int edge_array_len,
+ const short flag,
+ const short method,
+ const short oflag_edge,
+ const short oflag_face);
-float BM_verts_calc_rotate_beauty(
- const BMVert *v1, const BMVert *v2,
- const BMVert *v3, const BMVert *v4,
- const short flag, const short method);
+float BM_verts_calc_rotate_beauty(const BMVert *v1,
+ const BMVert *v2,
+ const BMVert *v3,
+ const BMVert *v4,
+ const short flag,
+ const short method);
#endif /* __BMESH_BEAUTIFY_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index 1c77220c03c..2c304d790df 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -39,12 +39,12 @@
#include "eigen_capi.h"
#include "bmesh.h"
-#include "bmesh_bevel.h" /* own include */
+#include "bmesh_bevel.h" /* own include */
#include "./intern/bmesh_private.h"
-#define BEVEL_EPSILON_D 1e-6
-#define BEVEL_EPSILON 1e-6f
+#define BEVEL_EPSILON_D 1e-6
+#define BEVEL_EPSILON 1e-6f
#define BEVEL_EPSILON_SQ 1e-12f
#define BEVEL_EPSILON_BIG 1e-4f
#define BEVEL_EPSILON_BIG_SQ 1e-8f
@@ -62,31 +62,31 @@
/* Constructed vertex, sometimes later instantiated as BMVert */
typedef struct NewVert {
- BMVert *v;
- float co[3];
-// int _pad;
+ BMVert *v;
+ float co[3];
+ // int _pad;
} NewVert;
struct BoundVert;
/* Data for one end of an edge involved in a bevel */
typedef struct EdgeHalf {
- struct EdgeHalf *next, *prev; /* in CCW order */
- BMEdge *e; /* original mesh edge */
- BMFace *fprev; /* face between this edge and previous, if any */
- BMFace *fnext; /* face between this edge and next, if any */
- struct BoundVert *leftv; /* left boundary vert (looking along edge to end) */
- struct BoundVert *rightv; /* right boundary vert, if beveled */
- int profile_index; /* offset into profile to attach non-beveled edge */
- int seg; /* how many segments for the bevel */
- float offset_l; /* offset for this edge, on left side */
- float offset_r; /* offset for this edge, on right side */
- float offset_l_spec; /* user specification for offset_l */
- float offset_r_spec; /* user specification for offset_r */
- bool is_bev; /* is this edge beveled? */
- bool is_rev; /* is e->v2 the vertex at this end? */
- bool is_seam; /* is e a seam for custom loopdata (e.g., UVs)? */
-// int _pad;
+ struct EdgeHalf *next, *prev; /* in CCW order */
+ BMEdge *e; /* original mesh edge */
+ BMFace *fprev; /* face between this edge and previous, if any */
+ BMFace *fnext; /* face between this edge and next, if any */
+ struct BoundVert *leftv; /* left boundary vert (looking along edge to end) */
+ struct BoundVert *rightv; /* right boundary vert, if beveled */
+ int profile_index; /* offset into profile to attach non-beveled edge */
+ int seg; /* how many segments for the bevel */
+ float offset_l; /* offset for this edge, on left side */
+ float offset_r; /* offset for this edge, on right side */
+ float offset_l_spec; /* user specification for offset_l */
+ float offset_r_spec; /* user specification for offset_r */
+ bool is_bev; /* is this edge beveled? */
+ bool is_rev; /* is e->v2 the vertex at this end? */
+ bool is_seam; /* is e a seam for custom loopdata (e.g., UVs)? */
+ // int _pad;
} EdgeHalf;
/* Profile specification.
@@ -103,15 +103,15 @@ typedef struct EdgeHalf {
* in prof_co_2.
*/
typedef struct Profile {
- float super_r; /* superellipse r parameter */
- float coa[3]; /* start control point for profile */
- float midco[3]; /* mid control point for profile */
- float cob[3]; /* end control point for profile */
- float plane_no[3]; /* normal of plane to project to */
- float plane_co[3]; /* coordinate on plane to project to */
- float proj_dir[3]; /* direction of projection line */
- float *prof_co; /* seg+1 profile coordinates (triples of floats) */
- float *prof_co_2; /* like prof_co, but for seg power of 2 >= seg */
+ float super_r; /* superellipse r parameter */
+ float coa[3]; /* start control point for profile */
+ float midco[3]; /* mid control point for profile */
+ float cob[3]; /* end control point for profile */
+ float plane_no[3]; /* normal of plane to project to */
+ float plane_co[3]; /* coordinate on plane to project to */
+ float proj_dir[3]; /* direction of projection line */
+ float *prof_co; /* seg+1 profile coordinates (triples of floats) */
+ float *prof_co_2; /* like prof_co, but for seg power of 2 >= seg */
} Profile;
#define PRO_SQUARE_R 1e4f
#define PRO_CIRCLE_R 2.0f
@@ -122,102 +122,103 @@ typedef struct Profile {
* get even spacing on superellipse for current BevelParams seg
* and pro_super_r. */
typedef struct ProfileSpacing {
- double *xvals; /* seg+1 x values */
- double *xvals_2; /* seg_2+1 x values, seg_2 = power of 2 >= seg */
- double *yvals; /* seg+1 y values */
- double *yvals_2; /* seg_2+1 y values, seg_2 = power of 2 >= seg */
- int seg_2; /* the seg_2 value */
+ double *xvals; /* seg+1 x values */
+ double *xvals_2; /* seg_2+1 x values, seg_2 = power of 2 >= seg */
+ double *yvals; /* seg+1 y values */
+ double *yvals_2; /* seg_2+1 y values, seg_2 = power of 2 >= seg */
+ int seg_2; /* the seg_2 value */
} ProfileSpacing;
/* An element in a cyclic boundary of a Vertex Mesh (VMesh) */
typedef struct BoundVert {
- struct BoundVert *next, *prev; /* in CCW order */
- NewVert nv;
- EdgeHalf *efirst; /* first of edges attached here: in CCW order */
- EdgeHalf *elast;
- EdgeHalf *eon; /* the "edge between" that this is on, in offset_on_edge_between case */
- EdgeHalf *ebev; /* beveled edge whose left side is attached here, if any */
- int index; /* used for vmesh indexing */
- float sinratio; /* when eon set, ratio of sines of angles to eon edge */
- struct BoundVert *adjchain; /* adjustment chain or cycle link pointer */
- Profile profile; /* edge profile between this and next BoundVert */
- bool any_seam; /* are any of the edges attached here seams? */
- bool visited; /* used during delta adjust pass */
- bool is_arc_start; /* this boundvert begins an arc profile */
- bool is_patch_start; /* this boundvert begins a patch profile */
- int seam_len; /* length of seam starting from current boundvert to next boundvert with ccw ordering */
- int sharp_len; /* Same as seam_len but defines length of sharp edges */
-// int _pad;
+ struct BoundVert *next, *prev; /* in CCW order */
+ NewVert nv;
+ EdgeHalf *efirst; /* first of edges attached here: in CCW order */
+ EdgeHalf *elast;
+ EdgeHalf *eon; /* the "edge between" that this is on, in offset_on_edge_between case */
+ EdgeHalf *ebev; /* beveled edge whose left side is attached here, if any */
+ int index; /* used for vmesh indexing */
+ float sinratio; /* when eon set, ratio of sines of angles to eon edge */
+ struct BoundVert *adjchain; /* adjustment chain or cycle link pointer */
+ Profile profile; /* edge profile between this and next BoundVert */
+ bool any_seam; /* are any of the edges attached here seams? */
+ bool visited; /* used during delta adjust pass */
+ bool is_arc_start; /* this boundvert begins an arc profile */
+ bool is_patch_start; /* this boundvert begins a patch profile */
+ int seam_len; /* length of seam starting from current boundvert to next boundvert with ccw ordering */
+ int sharp_len; /* Same as seam_len but defines length of sharp edges */
+ // int _pad;
} BoundVert;
/* Mesh structure replacing a vertex */
typedef struct VMesh {
- NewVert *mesh; /* allocated array - size and structure depends on kind */
- BoundVert *boundstart; /* start of boundary double-linked list */
- int count; /* number of vertices in the boundary */
- int seg; /* common # of segments for segmented edges */
- enum {
- M_NONE, /* no polygon mesh needed */
- M_POLY, /* a simple polygon */
- M_ADJ, /* "adjacent edges" mesh pattern */
- M_TRI_FAN, /* a simple polygon - fan filled */
- } mesh_kind;
-// int _pad;
+ NewVert *mesh; /* allocated array - size and structure depends on kind */
+ BoundVert *boundstart; /* start of boundary double-linked list */
+ int count; /* number of vertices in the boundary */
+ int seg; /* common # of segments for segmented edges */
+ enum {
+ M_NONE, /* no polygon mesh needed */
+ M_POLY, /* a simple polygon */
+ M_ADJ, /* "adjacent edges" mesh pattern */
+ M_TRI_FAN, /* a simple polygon - fan filled */
+ } mesh_kind;
+ // int _pad;
} VMesh;
/* Data for a vertex involved in a bevel */
typedef struct BevVert {
- BMVert *v; /* original mesh vertex */
- int edgecount; /* total number of edges around the vertex (excluding wire edges if edge beveling) */
- int selcount; /* number of selected edges around the vertex */
- int wirecount; /* count of wire edges */
- float offset; /* offset for this vertex, if vertex_only bevel */
- bool any_seam; /* any seams on attached edges? */
- bool visited; /* used in graph traversal */
- EdgeHalf *edges; /* array of size edgecount; CCW order from vertex normal side */
- BMEdge **wire_edges; /* array of size wirecount of wire edges */
- VMesh *vmesh; /* mesh structure for replacing vertex */
+ BMVert *v; /* original mesh vertex */
+ int edgecount; /* total number of edges around the vertex (excluding wire edges if edge beveling) */
+ int selcount; /* number of selected edges around the vertex */
+ int wirecount; /* count of wire edges */
+ float offset; /* offset for this vertex, if vertex_only bevel */
+ bool any_seam; /* any seams on attached edges? */
+ bool visited; /* used in graph traversal */
+ EdgeHalf *edges; /* array of size edgecount; CCW order from vertex normal side */
+ BMEdge **wire_edges; /* array of size wirecount of wire edges */
+ VMesh *vmesh; /* mesh structure for replacing vertex */
} BevVert;
/* face classification: note depend on F_RECON > F_EDGE > F_VERT */
typedef enum {
- F_NONE, /* used when there is no face at all */
- F_ORIG, /* original face, not touched */
- F_VERT, /* face for construction aroun a vert */
- F_EDGE, /* face for a beveled edge */
- F_RECON, /* reconstructed original face with some new verts */
+ F_NONE, /* used when there is no face at all */
+ F_ORIG, /* original face, not touched */
+ F_VERT, /* face for construction aroun a vert */
+ F_EDGE, /* face for a beveled edge */
+ F_RECON, /* reconstructed original face with some new verts */
} FKind;
// static const char* fkind_names[] = {"F_NONE", "F_ORIG", "F_VERT", "F_EDGE", "F_RECON"}; /* DEBUG */
/* Bevel parameters and state */
typedef struct BevelParams {
- GHash *vert_hash; /* records BevVerts made: key BMVert*, value BevVert* */
- GHash *face_hash; /* records new faces: key BMFace*, value one of {VERT/EDGE/RECON}_POLY */
- MemArena *mem_arena; /* use for all allocs while bevel runs, if we need to free we can switch to mempool */
- ProfileSpacing pro_spacing; /* parameter values for evenly spaced profiles */
-
- float offset; /* blender units to offset each side of a beveled edge */
- int offset_type; /* how offset is measured; enum defined in bmesh_operators.h */
- int seg; /* number of segments in beveled edge profile */
- float profile; /* user profile setting */
- float pro_super_r; /* superellipse parameter for edge profile */
- bool vertex_only; /* bevel vertices only */
- bool use_weights; /* bevel amount affected by weights on edges or verts */
- bool loop_slide; /* should bevel prefer to slide along edges rather than keep widths spec? */
- bool limit_offset; /* should offsets be limited by collisions? */
- bool offset_adjust; /* should offsets be adjusted to try to get even widths? */
- bool mark_seam; /* should we propagate seam edge markings? */
- bool mark_sharp; /* should we propagate sharp edge markings? */
- bool harden_normals; /* should we harden normals? */
- const struct MDeformVert *dvert; /* vertex group array, maybe set if vertex_only */
- int vertex_group; /* vertex group index, maybe set if vertex_only */
- int mat_nr; /* if >= 0, material number for bevel; else material comes from adjacent faces */
- int face_strength_mode; /* setting face strength if > 0 */
- int miter_outer; /* what kind of miter pattern to use on reflex angles */
- int miter_inner; /* what kind of miter pattern to use on non-reflex angles */
- float spread; /* amount to spread when doing inside miter */
- float smoothresh; /* mesh's smoothresh, used if hardening */
+ GHash *vert_hash; /* records BevVerts made: key BMVert*, value BevVert* */
+ GHash *face_hash; /* records new faces: key BMFace*, value one of {VERT/EDGE/RECON}_POLY */
+ MemArena *
+ mem_arena; /* use for all allocs while bevel runs, if we need to free we can switch to mempool */
+ ProfileSpacing pro_spacing; /* parameter values for evenly spaced profiles */
+
+ float offset; /* blender units to offset each side of a beveled edge */
+ int offset_type; /* how offset is measured; enum defined in bmesh_operators.h */
+ int seg; /* number of segments in beveled edge profile */
+ float profile; /* user profile setting */
+ float pro_super_r; /* superellipse parameter for edge profile */
+ bool vertex_only; /* bevel vertices only */
+ bool use_weights; /* bevel amount affected by weights on edges or verts */
+ bool loop_slide; /* should bevel prefer to slide along edges rather than keep widths spec? */
+ bool limit_offset; /* should offsets be limited by collisions? */
+ bool offset_adjust; /* should offsets be adjusted to try to get even widths? */
+ bool mark_seam; /* should we propagate seam edge markings? */
+ bool mark_sharp; /* should we propagate sharp edge markings? */
+ bool harden_normals; /* should we harden normals? */
+ const struct MDeformVert *dvert; /* vertex group array, maybe set if vertex_only */
+ int vertex_group; /* vertex group index, maybe set if vertex_only */
+ int mat_nr; /* if >= 0, material number for bevel; else material comes from adjacent faces */
+ int face_strength_mode; /* setting face strength if > 0 */
+ int miter_outer; /* what kind of miter pattern to use on reflex angles */
+ int miter_inner; /* what kind of miter pattern to use on non-reflex angles */
+ float spread; /* amount to spread when doing inside miter */
+ float smoothresh; /* mesh's smoothresh, used if hardening */
} BevelParams;
// #pragma GCC diagnostic ignored "-Wpadded"
@@ -231,7 +232,7 @@ static int bev_debug_flags = 0;
#define DEBUG_OLD_FLAT_MID (bev_debug_flags & 4)
/* use the unused _BM_ELEM_TAG_ALT flag to flag the 'long' loops (parallel to beveled edge) of edge-polygons */
-#define BM_ELEM_LONG_TAG (1<<6)
+#define BM_ELEM_LONG_TAG (1 << 6)
/* these flag values will get set on geom we want to return in 'out' slots for edges and verts */
#define EDGE_OUT 4
@@ -240,81 +241,81 @@ static int bev_debug_flags = 0;
/* If we're called from the modifier, tool flags aren't available, but don't need output geometry */
static void flag_out_edge(BMesh *bm, BMEdge *bme)
{
- if (bm->use_toolflags) {
- BMO_edge_flag_enable(bm, bme, EDGE_OUT);
- }
+ if (bm->use_toolflags) {
+ BMO_edge_flag_enable(bm, bme, EDGE_OUT);
+ }
}
static void flag_out_vert(BMesh *bm, BMVert *bmv)
{
- if (bm->use_toolflags) {
- BMO_vert_flag_enable(bm, bmv, VERT_OUT);
- }
+ if (bm->use_toolflags) {
+ BMO_vert_flag_enable(bm, bmv, VERT_OUT);
+ }
}
static void disable_flag_out_edge(BMesh *bm, BMEdge *bme)
{
- if (bm->use_toolflags) {
- BMO_edge_flag_disable(bm, bme, EDGE_OUT);
- }
+ if (bm->use_toolflags) {
+ BMO_edge_flag_disable(bm, bme, EDGE_OUT);
+ }
}
static void record_face_kind(BevelParams *bp, BMFace *f, FKind fkind)
{
- if (bp->face_hash) {
- BLI_ghash_insert(bp->face_hash, f, POINTER_FROM_INT(fkind));
- }
+ if (bp->face_hash) {
+ BLI_ghash_insert(bp->face_hash, f, POINTER_FROM_INT(fkind));
+ }
}
static FKind get_face_kind(BevelParams *bp, BMFace *f)
{
- void *val = BLI_ghash_lookup(bp->face_hash, f);
- return val ? (FKind)POINTER_AS_INT(val) : F_ORIG;
+ void *val = BLI_ghash_lookup(bp->face_hash, f);
+ return val ? (FKind)POINTER_AS_INT(val) : F_ORIG;
}
/* Are d1 and d2 parallel or nearly so? */
static bool nearly_parallel(const float d1[3], const float d2[3])
{
- float ang;
+ float ang;
- ang = angle_v3v3(d1, d2);
- return (fabsf(ang) < BEVEL_EPSILON_ANG) || (fabsf(ang - (float)M_PI) < BEVEL_EPSILON_ANG);
+ ang = angle_v3v3(d1, d2);
+ return (fabsf(ang) < BEVEL_EPSILON_ANG) || (fabsf(ang - (float)M_PI) < BEVEL_EPSILON_ANG);
}
/* Make a new BoundVert of the given kind, insert it at the end of the circular linked
* list with entry point bv->boundstart, and return it. */
static BoundVert *add_new_bound_vert(MemArena *mem_arena, VMesh *vm, const float co[3])
{
- BoundVert *ans = (BoundVert *)BLI_memarena_alloc(mem_arena, sizeof(BoundVert));
-
- copy_v3_v3(ans->nv.co, co);
- if (!vm->boundstart) {
- ans->index = 0;
- vm->boundstart = ans;
- ans->next = ans->prev = ans;
- }
- else {
- BoundVert *tail = vm->boundstart->prev;
- ans->index = tail->index + 1;
- ans->prev = tail;
- ans->next = vm->boundstart;
- tail->next = ans;
- vm->boundstart->prev = ans;
- }
- ans->profile.super_r = PRO_LINE_R;
- ans->adjchain = NULL;
- ans->sinratio = 1.0f;
- ans->visited = false;
- ans->any_seam = false;
- ans->is_arc_start = false;
- ans->is_patch_start = false;
- vm->count++;
- return ans;
+ BoundVert *ans = (BoundVert *)BLI_memarena_alloc(mem_arena, sizeof(BoundVert));
+
+ copy_v3_v3(ans->nv.co, co);
+ if (!vm->boundstart) {
+ ans->index = 0;
+ vm->boundstart = ans;
+ ans->next = ans->prev = ans;
+ }
+ else {
+ BoundVert *tail = vm->boundstart->prev;
+ ans->index = tail->index + 1;
+ ans->prev = tail;
+ ans->next = vm->boundstart;
+ tail->next = ans;
+ vm->boundstart->prev = ans;
+ }
+ ans->profile.super_r = PRO_LINE_R;
+ ans->adjchain = NULL;
+ ans->sinratio = 1.0f;
+ ans->visited = false;
+ ans->any_seam = false;
+ ans->is_arc_start = false;
+ ans->is_patch_start = false;
+ vm->count++;
+ return ans;
}
BLI_INLINE void adjust_bound_vert(BoundVert *bv, const float co[3])
{
- copy_v3_v3(bv->nv.co, co);
+ copy_v3_v3(bv->nv.co, co);
}
/* Mesh verts are indexed (i, j, k) where
@@ -324,49 +325,47 @@ BLI_INLINE void adjust_bound_vert(BoundVert *bv, const float co[3])
* Not all of these are used, and some will share BMVerts */
static NewVert *mesh_vert(VMesh *vm, int i, int j, int k)
{
- int nj = (vm->seg / 2) + 1;
- int nk = vm->seg + 1;
+ int nj = (vm->seg / 2) + 1;
+ int nk = vm->seg + 1;
- return &vm->mesh[i * nk * nj + j * nk + k];
+ return &vm->mesh[i * nk * nj + j * nk + k];
}
static void create_mesh_bmvert(BMesh *bm, VMesh *vm, int i, int j, int k, BMVert *eg)
{
- NewVert *nv = mesh_vert(vm, i, j, k);
- nv->v = BM_vert_create(bm, nv->co, eg, BM_CREATE_NOP);
- BM_elem_flag_disable(nv->v, BM_ELEM_TAG);
- flag_out_vert(bm, nv->v);
+ NewVert *nv = mesh_vert(vm, i, j, k);
+ nv->v = BM_vert_create(bm, nv->co, eg, BM_CREATE_NOP);
+ BM_elem_flag_disable(nv->v, BM_ELEM_TAG);
+ flag_out_vert(bm, nv->v);
}
-static void copy_mesh_vert(
- VMesh *vm, int ito, int jto, int kto,
- int ifrom, int jfrom, int kfrom)
+static void copy_mesh_vert(VMesh *vm, int ito, int jto, int kto, int ifrom, int jfrom, int kfrom)
{
- NewVert *nvto, *nvfrom;
+ NewVert *nvto, *nvfrom;
- nvto = mesh_vert(vm, ito, jto, kto);
- nvfrom = mesh_vert(vm, ifrom, jfrom, kfrom);
- nvto->v = nvfrom->v;
- copy_v3_v3(nvto->co, nvfrom->co);
+ nvto = mesh_vert(vm, ito, jto, kto);
+ nvfrom = mesh_vert(vm, ifrom, jfrom, kfrom);
+ nvto->v = nvfrom->v;
+ copy_v3_v3(nvto->co, nvfrom->co);
}
/* find the EdgeHalf in bv's array that has edge bme */
static EdgeHalf *find_edge_half(BevVert *bv, BMEdge *bme)
{
- int i;
-
- for (i = 0; i < bv->edgecount; i++) {
- if (bv->edges[i].e == bme) {
- return &bv->edges[i];
- }
- }
- return NULL;
+ int i;
+
+ for (i = 0; i < bv->edgecount; i++) {
+ if (bv->edges[i].e == bme) {
+ return &bv->edges[i];
+ }
+ }
+ return NULL;
}
/* find the BevVert corresponding to BMVert bmv */
static BevVert *find_bevvert(BevelParams *bp, BMVert *bmv)
{
- return BLI_ghash_lookup(bp->vert_hash, bmv);
+ return BLI_ghash_lookup(bp->vert_hash, bmv);
}
/* Find the EdgeHalf representing the other end of e->e.
@@ -374,56 +373,56 @@ static BevVert *find_bevvert(BevelParams *bp, BMVert *bmv)
* That may not have been constructed yet, in which case return NULL. */
static EdgeHalf *find_other_end_edge_half(BevelParams *bp, EdgeHalf *e, BevVert **r_bvother)
{
- BevVert *bvo;
- EdgeHalf *eother;
-
- bvo = find_bevvert(bp, e->is_rev ? e->e->v1 : e->e->v2);
- if (bvo) {
- if (r_bvother) {
- *r_bvother = bvo;
- }
- eother = find_edge_half(bvo, e->e);
- BLI_assert(eother != NULL);
- return eother;
- }
- else if (r_bvother) {
- *r_bvother = NULL;
- }
- return NULL;
+ BevVert *bvo;
+ EdgeHalf *eother;
+
+ bvo = find_bevvert(bp, e->is_rev ? e->e->v1 : e->e->v2);
+ if (bvo) {
+ if (r_bvother) {
+ *r_bvother = bvo;
+ }
+ eother = find_edge_half(bvo, e->e);
+ BLI_assert(eother != NULL);
+ return eother;
+ }
+ else if (r_bvother) {
+ *r_bvother = NULL;
+ }
+ return NULL;
}
/* Return the next EdgeHalf after from_e that is beveled.
* If from_e is NULL, find the first beveled edge. */
static EdgeHalf *next_bev(BevVert *bv, EdgeHalf *from_e)
{
- EdgeHalf *e;
-
- if (from_e == NULL) {
- from_e = &bv->edges[bv->edgecount - 1];
- }
- e = from_e;
- do {
- if (e->is_bev) {
- return e;
- }
- } while ((e = e->next) != from_e);
- return NULL;
+ EdgeHalf *e;
+
+ if (from_e == NULL) {
+ from_e = &bv->edges[bv->edgecount - 1];
+ }
+ e = from_e;
+ do {
+ if (e->is_bev) {
+ return e;
+ }
+ } while ((e = e->next) != from_e);
+ return NULL;
}
/* return count of edges between e1 and e2 when going around bv CCW */
static int count_ccw_edges_between(EdgeHalf *e1, EdgeHalf *e2)
{
- int cnt = 0;
- EdgeHalf *e = e1;
-
- do {
- if (e == e2) {
- break;
- }
- e = e->next;
- cnt++;
- } while (e != e1);
- return cnt;
+ int cnt = 0;
+ EdgeHalf *e = e1;
+
+ do {
+ if (e == e2) {
+ break;
+ }
+ e = e->next;
+ cnt++;
+ } while (e != e1);
+ return cnt;
}
/* Assume bme1 and bme2 both share some vert. Do they share a face?
@@ -431,15 +430,15 @@ static int count_ccw_edges_between(EdgeHalf *e1, EdgeHalf *e2)
* where the next or previous edge in the face must be bme2. */
static bool edges_face_connected_at_vert(BMEdge *bme1, BMEdge *bme2)
{
- BMLoop *l;
- BMIter iter;
-
- BM_ITER_ELEM(l, &iter, bme1, BM_LOOPS_OF_EDGE) {
- if (l->prev->e == bme2 || l->next->e == bme2) {
- return true;
- }
- }
- return false;
+ BMLoop *l;
+ BMIter iter;
+
+ BM_ITER_ELEM (l, &iter, bme1, BM_LOOPS_OF_EDGE) {
+ if (l->prev->e == bme2 || l->next->e == bme2) {
+ return true;
+ }
+ }
+ return false;
}
/* Return a good representative face (for materials, etc.) for faces
@@ -449,56 +448,56 @@ static bool edges_face_connected_at_vert(BMEdge *bme1, BMEdge *bme2)
* possible frep, return the other one in that parameter. */
static BMFace *boundvert_rep_face(BoundVert *v, BMFace **r_fother)
{
- BMFace *frep, *frep2;
-
- frep2 = NULL;
- if (v->ebev) {
- frep = v->ebev->fprev;
- if (v->efirst->fprev != frep) {
- frep2 = v->efirst->fprev;
- }
- }
- else if (v->efirst) {
- frep = v->efirst->fprev;
- if (frep) {
- if (v->elast->fnext != frep) {
- frep2 = v->elast->fnext;
- }
- else if (v->efirst->fnext != frep) {
- frep2 = v->efirst->fnext;
- }
- else if (v->elast->fprev != frep) {
- frep2 = v->efirst->fprev;
- }
- }
- else if (v->efirst->fnext) {
- frep = v->efirst->fnext;
- if (v->elast->fnext != frep) {
- frep2 = v->elast->fnext;
- }
- }
- else if (v->elast->fprev) {
- frep = v->elast->fprev;
- }
- }
- else if (v->prev->elast) {
- frep = v->prev->elast->fnext;
- if (v->next->efirst) {
- if (frep) {
- frep2 = v->next->efirst->fprev;
- }
- else {
- frep = v->next->efirst->fprev;
- }
- }
- }
- else {
- frep = NULL;
- }
- if (r_fother) {
- *r_fother = frep2;
- }
- return frep;
+ BMFace *frep, *frep2;
+
+ frep2 = NULL;
+ if (v->ebev) {
+ frep = v->ebev->fprev;
+ if (v->efirst->fprev != frep) {
+ frep2 = v->efirst->fprev;
+ }
+ }
+ else if (v->efirst) {
+ frep = v->efirst->fprev;
+ if (frep) {
+ if (v->elast->fnext != frep) {
+ frep2 = v->elast->fnext;
+ }
+ else if (v->efirst->fnext != frep) {
+ frep2 = v->efirst->fnext;
+ }
+ else if (v->elast->fprev != frep) {
+ frep2 = v->efirst->fprev;
+ }
+ }
+ else if (v->efirst->fnext) {
+ frep = v->efirst->fnext;
+ if (v->elast->fnext != frep) {
+ frep2 = v->elast->fnext;
+ }
+ }
+ else if (v->elast->fprev) {
+ frep = v->elast->fprev;
+ }
+ }
+ else if (v->prev->elast) {
+ frep = v->prev->elast->fnext;
+ if (v->next->efirst) {
+ if (frep) {
+ frep2 = v->next->efirst->fprev;
+ }
+ else {
+ frep = v->next->efirst->fprev;
+ }
+ }
+ }
+ else {
+ frep = NULL;
+ }
+ if (r_fother) {
+ *r_fother = frep2;
+ }
+ return frep;
}
/**
@@ -511,303 +510,318 @@ static BMFace *boundvert_rep_face(BoundVert *v, BMFace **r_fother)
*
* \note ALL face creation goes through this function, this is important to keep!
*/
-static BMFace *bev_create_ngon(
- BMesh *bm, BMVert **vert_arr, const int totv,
- BMFace **face_arr, BMFace *facerep, BMEdge **edge_arr,
- int mat_nr, bool do_interp)
+static BMFace *bev_create_ngon(BMesh *bm,
+ BMVert **vert_arr,
+ const int totv,
+ BMFace **face_arr,
+ BMFace *facerep,
+ BMEdge **edge_arr,
+ int mat_nr,
+ bool do_interp)
{
- BMIter iter;
- BMLoop *l;
- BMFace *f, *interp_f;
- BMEdge *bme;
- float save_co[3];
- int i;
-
- f = BM_face_create_verts(bm, vert_arr, totv, facerep, BM_CREATE_NOP, true);
-
- if ((facerep || (face_arr && face_arr[0])) && f) {
- BM_elem_attrs_copy(bm, bm, facerep ? facerep : face_arr[0], f);
- if (do_interp) {
- i = 0;
- BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) {
- if (face_arr) {
- /* assume loops of created face are in same order as verts */
- BLI_assert(l->v == vert_arr[i]);
- interp_f = face_arr[i];
- }
- else {
- interp_f = facerep;
- }
- if (interp_f) {
- bme = NULL;
- if (edge_arr) {
- bme = edge_arr[i];
- }
- if (bme) {
- copy_v3_v3(save_co, l->v->co);
- closest_to_line_segment_v3(l->v->co, save_co, bme->v1->co, bme->v2->co);
- }
- BM_loop_interp_from_face(bm, l, interp_f, true, true);
- if (bme) {
- copy_v3_v3(l->v->co, save_co);
- }
- }
- i++;
- }
- }
- }
-
- /* not essential for bevels own internal logic,
- * this is done so the operator can select newly created geometry */
- if (f) {
- BM_elem_flag_enable(f, BM_ELEM_TAG);
- BM_ITER_ELEM(bme, &iter, f, BM_EDGES_OF_FACE) {
- flag_out_edge(bm, bme);
- }
- }
-
- if (mat_nr >= 0) {
- f->mat_nr = mat_nr;
- }
- return f;
+ BMIter iter;
+ BMLoop *l;
+ BMFace *f, *interp_f;
+ BMEdge *bme;
+ float save_co[3];
+ int i;
+
+ f = BM_face_create_verts(bm, vert_arr, totv, facerep, BM_CREATE_NOP, true);
+
+ if ((facerep || (face_arr && face_arr[0])) && f) {
+ BM_elem_attrs_copy(bm, bm, facerep ? facerep : face_arr[0], f);
+ if (do_interp) {
+ i = 0;
+ BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) {
+ if (face_arr) {
+ /* assume loops of created face are in same order as verts */
+ BLI_assert(l->v == vert_arr[i]);
+ interp_f = face_arr[i];
+ }
+ else {
+ interp_f = facerep;
+ }
+ if (interp_f) {
+ bme = NULL;
+ if (edge_arr) {
+ bme = edge_arr[i];
+ }
+ if (bme) {
+ copy_v3_v3(save_co, l->v->co);
+ closest_to_line_segment_v3(l->v->co, save_co, bme->v1->co, bme->v2->co);
+ }
+ BM_loop_interp_from_face(bm, l, interp_f, true, true);
+ if (bme) {
+ copy_v3_v3(l->v->co, save_co);
+ }
+ }
+ i++;
+ }
+ }
+ }
+
+ /* not essential for bevels own internal logic,
+ * this is done so the operator can select newly created geometry */
+ if (f) {
+ BM_elem_flag_enable(f, BM_ELEM_TAG);
+ BM_ITER_ELEM (bme, &iter, f, BM_EDGES_OF_FACE) {
+ flag_out_edge(bm, bme);
+ }
+ }
+
+ if (mat_nr >= 0) {
+ f->mat_nr = mat_nr;
+ }
+ return f;
}
-static BMFace *bev_create_quad(
- BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
- BMFace *f1, BMFace *f2, BMFace *f3, BMFace *f4,
- int mat_nr)
+static BMFace *bev_create_quad(BMesh *bm,
+ BMVert *v1,
+ BMVert *v2,
+ BMVert *v3,
+ BMVert *v4,
+ BMFace *f1,
+ BMFace *f2,
+ BMFace *f3,
+ BMFace *f4,
+ int mat_nr)
{
- BMVert *varr[4] = {v1, v2, v3, v4};
- BMFace *farr[4] = {f1, f2, f3, f4};
- return bev_create_ngon(bm, varr, 4, farr, f1, NULL, mat_nr, true);
+ BMVert *varr[4] = {v1, v2, v3, v4};
+ BMFace *farr[4] = {f1, f2, f3, f4};
+ return bev_create_ngon(bm, varr, 4, farr, f1, NULL, mat_nr, true);
}
-static BMFace *bev_create_quad_ex(
- BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
- BMFace *f1, BMFace *f2, BMFace *f3, BMFace *f4,
- BMEdge *e1, BMEdge *e2, BMEdge *e3, BMEdge *e4,
- int mat_nr)
+static BMFace *bev_create_quad_ex(BMesh *bm,
+ BMVert *v1,
+ BMVert *v2,
+ BMVert *v3,
+ BMVert *v4,
+ BMFace *f1,
+ BMFace *f2,
+ BMFace *f3,
+ BMFace *f4,
+ BMEdge *e1,
+ BMEdge *e2,
+ BMEdge *e3,
+ BMEdge *e4,
+ int mat_nr)
{
- BMVert *varr[4] = {v1, v2, v3, v4};
- BMFace *farr[4] = {f1, f2, f3, f4};
- BMEdge *earr[4] = {e1, e2, e3, e4};
- return bev_create_ngon(bm, varr, 4, farr, f1, earr, mat_nr, true);
+ BMVert *varr[4] = {v1, v2, v3, v4};
+ BMFace *farr[4] = {f1, f2, f3, f4};
+ BMEdge *earr[4] = {e1, e2, e3, e4};
+ return bev_create_ngon(bm, varr, 4, farr, f1, earr, mat_nr, true);
}
/* Is Loop layer layer_index contiguous across shared vertex of l1 and l2? */
-static bool contig_ldata_across_loops(
- BMesh *bm, BMLoop *l1, BMLoop *l2,
- int layer_index)
+static bool contig_ldata_across_loops(BMesh *bm, BMLoop *l1, BMLoop *l2, int layer_index)
{
- const int offset = bm->ldata.layers[layer_index].offset;
- const int type = bm->ldata.layers[layer_index].type;
+ const int offset = bm->ldata.layers[layer_index].offset;
+ const int type = bm->ldata.layers[layer_index].type;
- return CustomData_data_equals(type,
- (char *)l1->head.data + offset,
- (char *)l2->head.data + offset);
+ return CustomData_data_equals(
+ type, (char *)l1->head.data + offset, (char *)l2->head.data + offset);
}
/* Are all loop layers with have math (e.g., UVs) contiguous from face f1 to face f2 across edge e? */
static bool contig_ldata_across_edge(BMesh *bm, BMEdge *e, BMFace *f1, BMFace *f2)
{
- BMLoop *lef1, *lef2;
- BMLoop *lv1f1, *lv1f2, *lv2f1, *lv2f2;
- BMVert *v1, *v2;
- int i;
-
- if (bm->ldata.totlayer == 0) {
- return true;
- }
-
- v1 = e->v1;
- v2 = e->v2;
- if (!BM_edge_loop_pair(e, &lef1, &lef2)) {
- return false;
- }
- if (lef1->f == f2) {
- SWAP(BMLoop *, lef1, lef2);
- }
-
- if (lef1->v == v1) {
- lv1f1 = lef1;
- lv2f1 = BM_face_other_edge_loop(f1, e, v2);
- }
- else {
- lv2f1 = lef1;
- lv1f1 = BM_face_other_edge_loop(f1, e, v1);
- }
-
- if (lef2->v == v1) {
- lv1f2 = lef2;
- lv2f2 = BM_face_other_edge_loop(f2, e, v2);
- }
- else {
- lv2f2 = lef2;
- lv1f2 = BM_face_other_edge_loop(f2, e, v1);
- }
-
- for (i = 0; i < bm->ldata.totlayer; i++) {
- if (CustomData_layer_has_math(&bm->ldata, i) &&
- (!contig_ldata_across_loops(bm, lv1f1, lv1f2, i) ||
- !contig_ldata_across_loops(bm, lv2f1, lv2f2, i)))
- {
- return false;
- }
- }
- return true;
+ BMLoop *lef1, *lef2;
+ BMLoop *lv1f1, *lv1f2, *lv2f1, *lv2f2;
+ BMVert *v1, *v2;
+ int i;
+
+ if (bm->ldata.totlayer == 0) {
+ return true;
+ }
+
+ v1 = e->v1;
+ v2 = e->v2;
+ if (!BM_edge_loop_pair(e, &lef1, &lef2)) {
+ return false;
+ }
+ if (lef1->f == f2) {
+ SWAP(BMLoop *, lef1, lef2);
+ }
+
+ if (lef1->v == v1) {
+ lv1f1 = lef1;
+ lv2f1 = BM_face_other_edge_loop(f1, e, v2);
+ }
+ else {
+ lv2f1 = lef1;
+ lv1f1 = BM_face_other_edge_loop(f1, e, v1);
+ }
+
+ if (lef2->v == v1) {
+ lv1f2 = lef2;
+ lv2f2 = BM_face_other_edge_loop(f2, e, v2);
+ }
+ else {
+ lv2f2 = lef2;
+ lv1f2 = BM_face_other_edge_loop(f2, e, v1);
+ }
+
+ for (i = 0; i < bm->ldata.totlayer; i++) {
+ if (CustomData_layer_has_math(&bm->ldata, i) &&
+ (!contig_ldata_across_loops(bm, lv1f1, lv1f2, i) ||
+ !contig_ldata_across_loops(bm, lv2f1, lv2f2, i))) {
+ return false;
+ }
+ }
+ return true;
}
/* Merge (using average) all the UV values for loops of v's faces.
* Caller should ensure that no seams are violated by doing this. */
static void bev_merge_uvs(BMesh *bm, BMVert *v)
{
- BMIter iter;
- MLoopUV *luv;
- BMLoop *l;
- float uv[2];
- int n;
- int num_of_uv_layers = CustomData_number_of_layers(&bm->ldata, CD_MLOOPUV);
- int i;
-
- for (i = 0; i < num_of_uv_layers; i++) {
- int cd_loop_uv_offset = CustomData_get_n_offset(&bm->ldata, CD_MLOOPUV, i);
-
- if (cd_loop_uv_offset == -1) {
- return;
- }
-
- n = 0;
- zero_v2(uv);
- BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- add_v2_v2(uv, luv->uv);
- n++;
- }
- if (n > 1) {
- mul_v2_fl(uv, 1.0f / (float)n);
- BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- copy_v2_v2(luv->uv, uv);
- }
- }
- }
+ BMIter iter;
+ MLoopUV *luv;
+ BMLoop *l;
+ float uv[2];
+ int n;
+ int num_of_uv_layers = CustomData_number_of_layers(&bm->ldata, CD_MLOOPUV);
+ int i;
+
+ for (i = 0; i < num_of_uv_layers; i++) {
+ int cd_loop_uv_offset = CustomData_get_n_offset(&bm->ldata, CD_MLOOPUV, i);
+
+ if (cd_loop_uv_offset == -1) {
+ return;
+ }
+
+ n = 0;
+ zero_v2(uv);
+ BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ add_v2_v2(uv, luv->uv);
+ n++;
+ }
+ if (n > 1) {
+ mul_v2_fl(uv, 1.0f / (float)n);
+ BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
+ luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
+ copy_v2_v2(luv->uv, uv);
+ }
+ }
+ }
}
/* Merge (using average) the UV values for two specific loops of v: those for faces containing v,
* and part of faces that share edge bme */
static void bev_merge_edge_uvs(BMesh *bm, BMEdge *bme, BMVert *v)
{
- BMIter iter;
- MLoopUV *luv;
- BMLoop *l, *l1, *l2;
- float uv[2];
- int num_of_uv_layers = CustomData_number_of_layers(&bm->ldata, CD_MLOOPUV);
- int i;
-
- l1 = NULL;
- l2 = NULL;
- BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
- if (l->e == bme) {
- l1 = l;
- }
- else if (l->prev->e == bme) {
- l2 = l;
- }
- }
- if (l1 == NULL || l2 == NULL) {
- return;
- }
-
- for (i = 0; i < num_of_uv_layers; i++) {
- int cd_loop_uv_offset = CustomData_get_n_offset(&bm->ldata, CD_MLOOPUV, i);
-
- if (cd_loop_uv_offset == -1) {
- return;
- }
-
- zero_v2(uv);
- luv = BM_ELEM_CD_GET_VOID_P(l1, cd_loop_uv_offset);
- add_v2_v2(uv, luv->uv);
- luv = BM_ELEM_CD_GET_VOID_P(l2, cd_loop_uv_offset);
- add_v2_v2(uv, luv->uv);
- mul_v2_fl(uv, 0.5f);
- luv = BM_ELEM_CD_GET_VOID_P(l1, cd_loop_uv_offset);
- copy_v2_v2(luv->uv, uv);
- luv = BM_ELEM_CD_GET_VOID_P(l2, cd_loop_uv_offset);
- copy_v2_v2(luv->uv, uv);
- }
+ BMIter iter;
+ MLoopUV *luv;
+ BMLoop *l, *l1, *l2;
+ float uv[2];
+ int num_of_uv_layers = CustomData_number_of_layers(&bm->ldata, CD_MLOOPUV);
+ int i;
+
+ l1 = NULL;
+ l2 = NULL;
+ BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
+ if (l->e == bme) {
+ l1 = l;
+ }
+ else if (l->prev->e == bme) {
+ l2 = l;
+ }
+ }
+ if (l1 == NULL || l2 == NULL) {
+ return;
+ }
+
+ for (i = 0; i < num_of_uv_layers; i++) {
+ int cd_loop_uv_offset = CustomData_get_n_offset(&bm->ldata, CD_MLOOPUV, i);
+
+ if (cd_loop_uv_offset == -1) {
+ return;
+ }
+
+ zero_v2(uv);
+ luv = BM_ELEM_CD_GET_VOID_P(l1, cd_loop_uv_offset);
+ add_v2_v2(uv, luv->uv);
+ luv = BM_ELEM_CD_GET_VOID_P(l2, cd_loop_uv_offset);
+ add_v2_v2(uv, luv->uv);
+ mul_v2_fl(uv, 0.5f);
+ luv = BM_ELEM_CD_GET_VOID_P(l1, cd_loop_uv_offset);
+ copy_v2_v2(luv->uv, uv);
+ luv = BM_ELEM_CD_GET_VOID_P(l2, cd_loop_uv_offset);
+ copy_v2_v2(luv->uv, uv);
+ }
}
/* Calculate coordinates of a point a distance d from v on e->e and return it in slideco */
static void slide_dist(EdgeHalf *e, BMVert *v, float d, float slideco[3])
{
- float dir[3], len;
-
- sub_v3_v3v3(dir, v->co, BM_edge_other_vert(e->e, v)->co);
- len = normalize_v3(dir);
- if (d > len) {
- d = len - (float)(50.0 * BEVEL_EPSILON_D);
- }
- copy_v3_v3(slideco, v->co);
- madd_v3_v3fl(slideco, dir, -d);
+ float dir[3], len;
+
+ sub_v3_v3v3(dir, v->co, BM_edge_other_vert(e->e, v)->co);
+ len = normalize_v3(dir);
+ if (d > len) {
+ d = len - (float)(50.0 * BEVEL_EPSILON_D);
+ }
+ copy_v3_v3(slideco, v->co);
+ madd_v3_v3fl(slideco, dir, -d);
}
/* Is co not on the edge e? if not, return the closer end of e in ret_closer_v */
static bool is_outside_edge(EdgeHalf *e, const float co[3], BMVert **ret_closer_v)
{
- float h[3], u[3], lambda, lenu, *l1 = e->e->v1->co;
-
- sub_v3_v3v3(u, e->e->v2->co, l1);
- sub_v3_v3v3(h, co, l1);
- lenu = normalize_v3(u);
- lambda = dot_v3v3(u, h);
- if (lambda <= -BEVEL_EPSILON_BIG * lenu) {
- *ret_closer_v = e->e->v1;
- return true;
- }
- else if (lambda >= (1.0f + BEVEL_EPSILON_BIG) * lenu) {
- *ret_closer_v = e->e->v2;
- return true;
- }
- else {
- return false;
- }
+ float h[3], u[3], lambda, lenu, *l1 = e->e->v1->co;
+
+ sub_v3_v3v3(u, e->e->v2->co, l1);
+ sub_v3_v3v3(h, co, l1);
+ lenu = normalize_v3(u);
+ lambda = dot_v3v3(u, h);
+ if (lambda <= -BEVEL_EPSILON_BIG * lenu) {
+ *ret_closer_v = e->e->v1;
+ return true;
+ }
+ else if (lambda >= (1.0f + BEVEL_EPSILON_BIG) * lenu) {
+ *ret_closer_v = e->e->v2;
+ return true;
+ }
+ else {
+ return false;
+ }
}
/* Return -1, 0, or 1 as angle from e1 to e2 is <. =, or > 180 degrees */
static int edges_angle_kind(EdgeHalf *e1, EdgeHalf *e2, BMVert *v)
{
- BMVert *v1, *v2;
- float dir1[3], dir2[3], cross[3], *no, dot;
-
- v1 = BM_edge_other_vert(e1->e, v);
- v2 = BM_edge_other_vert(e2->e, v);
- sub_v3_v3v3(dir1, v->co, v1->co);
- sub_v3_v3v3(dir2, v->co, v2->co);
- normalize_v3(dir1);
- normalize_v3(dir2);
- /* angles are in [0,pi]. need to compare cross product with normal to see if they are reflex */
- cross_v3_v3v3(cross, dir1, dir2);
- normalize_v3(cross);
- if (e1->fnext) {
- no = e1->fnext->no;
- }
- else if (e2->fprev) {
- no = e2->fprev->no;
- }
- else {
- no = v->no;
- }
- dot = dot_v3v3(cross, no);
- if (fabsf(dot) < BEVEL_EPSILON_BIG) {
- return 0;
- }
- else if (dot < 0.0f) {
- return 1;
- }
- else {
- return -1;
- }
+ BMVert *v1, *v2;
+ float dir1[3], dir2[3], cross[3], *no, dot;
+
+ v1 = BM_edge_other_vert(e1->e, v);
+ v2 = BM_edge_other_vert(e2->e, v);
+ sub_v3_v3v3(dir1, v->co, v1->co);
+ sub_v3_v3v3(dir2, v->co, v2->co);
+ normalize_v3(dir1);
+ normalize_v3(dir2);
+ /* angles are in [0,pi]. need to compare cross product with normal to see if they are reflex */
+ cross_v3_v3v3(cross, dir1, dir2);
+ normalize_v3(cross);
+ if (e1->fnext) {
+ no = e1->fnext->no;
+ }
+ else if (e2->fprev) {
+ no = e2->fprev->no;
+ }
+ else {
+ no = v->no;
+ }
+ dot = dot_v3v3(cross, no);
+ if (fabsf(dot) < BEVEL_EPSILON_BIG) {
+ return 0;
+ }
+ else if (dot < 0.0f) {
+ return 1;
+ }
+ else {
+ return -1;
+ }
}
/* co should be approximately on the plane between e1 and e2, which share common vert v
@@ -815,30 +829,30 @@ static int edges_angle_kind(EdgeHalf *e1, EdgeHalf *e2, BMVert *v)
* Is it between those edges, sweeping CCW? */
static bool point_between_edges(float co[3], BMVert *v, BMFace *f, EdgeHalf *e1, EdgeHalf *e2)
{
- BMVert *v1, *v2;
- float dir1[3], dir2[3], dirco[3], no[3];
- float ang11, ang1co;
-
- v1 = BM_edge_other_vert(e1->e, v);
- v2 = BM_edge_other_vert(e2->e, v);
- sub_v3_v3v3(dir1, v->co, v1->co);
- sub_v3_v3v3(dir2, v->co, v2->co);
- sub_v3_v3v3(dirco, v->co, co);
- normalize_v3(dir1);
- normalize_v3(dir2);
- normalize_v3(dirco);
- ang11 = angle_normalized_v3v3(dir1, dir2);
- ang1co = angle_normalized_v3v3(dir1, dirco);
- /* angles are in [0,pi]. need to compare cross product with normal to see if they are reflex */
- cross_v3_v3v3(no, dir1, dir2);
- if (dot_v3v3(no, f->no) < 0.0f) {
- ang11 = (float)(M_PI * 2.0) - ang11;
- }
- cross_v3_v3v3(no, dir1, dirco);
- if (dot_v3v3(no, f->no) < 0.0f) {
- ang1co = (float)(M_PI * 2.0) - ang1co;
- }
- return (ang11 - ang1co > -BEVEL_EPSILON_ANG);
+ BMVert *v1, *v2;
+ float dir1[3], dir2[3], dirco[3], no[3];
+ float ang11, ang1co;
+
+ v1 = BM_edge_other_vert(e1->e, v);
+ v2 = BM_edge_other_vert(e2->e, v);
+ sub_v3_v3v3(dir1, v->co, v1->co);
+ sub_v3_v3v3(dir2, v->co, v2->co);
+ sub_v3_v3v3(dirco, v->co, co);
+ normalize_v3(dir1);
+ normalize_v3(dir2);
+ normalize_v3(dirco);
+ ang11 = angle_normalized_v3v3(dir1, dir2);
+ ang1co = angle_normalized_v3v3(dir1, dirco);
+ /* angles are in [0,pi]. need to compare cross product with normal to see if they are reflex */
+ cross_v3_v3v3(no, dir1, dir2);
+ if (dot_v3v3(no, f->no) < 0.0f) {
+ ang11 = (float)(M_PI * 2.0) - ang11;
+ }
+ cross_v3_v3v3(no, dir1, dirco);
+ if (dot_v3v3(no, f->no) < 0.0f) {
+ ang1co = (float)(M_PI * 2.0) - ang1co;
+ }
+ return (ang11 - ang1co > -BEVEL_EPSILON_ANG);
}
/*
@@ -856,157 +870,158 @@ static bool point_between_edges(float co[3], BMVert *v, BMFace *f, EdgeHalf *e1,
* record the change in offset_l (or offset_r); later we can tell that a change has happened because
* the offset will differ from its original value in offset_l_spec (or offset_r_spec).
*/
-static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, bool edges_between, float meetco[3])
+static void offset_meet(
+ EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, bool edges_between, float meetco[3])
{
- float dir1[3], dir2[3], dir1n[3], dir2p[3], norm_v[3], norm_v1[3], norm_v2[3];
- float norm_perp1[3], norm_perp2[3], off1a[3], off1b[3], off2a[3], off2b[3];
- float isect2[3], dropco[3], plane[4];
- float ang, d;
- BMVert *closer_v;
- EdgeHalf *e, *e1next, *e2prev;
- BMFace *ff;
- int isect_kind;
-
- /* get direction vectors for two offset lines */
- sub_v3_v3v3(dir1, v->co, BM_edge_other_vert(e1->e, v)->co);
- sub_v3_v3v3(dir2, BM_edge_other_vert(e2->e, v)->co, v->co);
-
- if (edges_between) {
- e1next = e1->next;
- e2prev = e2->prev;
- sub_v3_v3v3(dir1n, BM_edge_other_vert(e1next->e, v)->co, v->co);
- sub_v3_v3v3(dir2p, v->co, BM_edge_other_vert(e2prev->e, v)->co);
- }
- else {
- /* shup up 'maybe unused' warnings */
- zero_v3(dir1n);
- zero_v3(dir2p);
- }
-
- ang = angle_v3v3(dir1, dir2);
- if (ang < BEVEL_EPSILON_ANG) {
- /* special case: e1 and e2 are parallel; put offset point perp to both, from v.
- * need to find a suitable plane.
- * this code used to just use offset and dir1, but that makes for visible errors
- * on a circle with > 200 sides, which trips this "nearly perp" code (see T61214).
- * so use the average of the two, and the offset formula for angle bisector.
- * if offsets are different, we're out of luck:
- * use the max of the two (so get consistent looking results if the same situation
- * arises elsewhere in the object but with opposite roles for e1 and e2 */
- if (f) {
- copy_v3_v3(norm_v, f->no);
- }
- else {
- copy_v3_v3(norm_v, v->no);
- }
- add_v3_v3(dir1, dir2);
- cross_v3_v3v3(norm_perp1, dir1, norm_v);
- normalize_v3(norm_perp1);
- copy_v3_v3(off1a, v->co);
- d = max_ff(e1->offset_r, e2->offset_l);
- d = d / cos(ang / 2.0f);
- madd_v3_v3fl(off1a, norm_perp1, d);
- copy_v3_v3(meetco, off1a);
- }
- else if (fabsf(ang - (float)M_PI) < BEVEL_EPSILON_ANG) {
- /* special case e1 and e2 are antiparallel, so bevel is into
- * a zero-area face. Just make the offset point on the
- * common line, at offset distance from v. */
- d = max_ff(e1->offset_r, e2->offset_l);
- slide_dist(e2, v, d, meetco);
- }
- else {
- /* Get normal to plane where meet point should be,
- * using cross product instead of f->no in case f is non-planar.
- * Except: sometimes locally there can be a small angle
- * between dir1 and dir2 that leads to a normal that is actually almost
- * perpendicular to the face normal; in this case it looks wrong to use
- * the local (cross-product) normal, so use the face normal if the angle
- * between dir1 and dir2 is smallish.
- * If e1-v-e2 is a reflex angle (viewed from vertex normal side), need to flip.
- * Use f->no to figure out which side to look at angle from, as even if
- * f is non-planar, will be more accurate than vertex normal */
- if (f && ang < BEVEL_SMALL_ANG) {
- copy_v3_v3(norm_v1, f->no);
- copy_v3_v3(norm_v2, f->no);
- }
- else if (!edges_between) {
- cross_v3_v3v3(norm_v1, dir2, dir1);
- normalize_v3(norm_v1);
- if (dot_v3v3(norm_v1, f ? f->no : v->no) < 0.0f) {
- negate_v3(norm_v1);
- }
- copy_v3_v3(norm_v2, norm_v1);
- }
- else {
- /* separate faces; get face norms at corners for each separately */
- cross_v3_v3v3(norm_v1, dir1n, dir1);
- normalize_v3(norm_v1);
- f = e1->fnext;
- if (dot_v3v3(norm_v1, f ? f->no : v->no) < 0.0f) {
- negate_v3(norm_v1);
- }
- cross_v3_v3v3(norm_v2, dir2, dir2p);
- normalize_v3(norm_v2);
- f = e2->fprev;
- if (dot_v3v3(norm_v2, f ? f->no : v->no) < 0.0f) {
- negate_v3(norm_v2);
- }
- }
-
- /* get vectors perp to each edge, perp to norm_v, and pointing into face */
- cross_v3_v3v3(norm_perp1, dir1, norm_v1);
- cross_v3_v3v3(norm_perp2, dir2, norm_v2);
- normalize_v3(norm_perp1);
- normalize_v3(norm_perp2);
-
- /* get points that are offset distances from each line, then another point on each line */
- copy_v3_v3(off1a, v->co);
- madd_v3_v3fl(off1a, norm_perp1, e1->offset_r);
- add_v3_v3v3(off1b, off1a, dir1);
- copy_v3_v3(off2a, v->co);
- madd_v3_v3fl(off2a, norm_perp2, e2->offset_l);
- add_v3_v3v3(off2b, off2a, dir2);
-
- /* intersect the lines */
- isect_kind = isect_line_line_v3(off1a, off1b, off2a, off2b, meetco, isect2);
- if (isect_kind == 0) {
- /* lines are collinear: we already tested for this, but this used a different epsilon */
- copy_v3_v3(meetco, off1a); /* just to do something */
- }
- else {
- /* The lines intersect, but is it at a reasonable place?
- * One problem to check: if one of the offsets is 0, then don't
- * want an intersection that is outside that edge itself.
- * This can happen if angle between them is > 180 degrees,
- * or if the offset amount is > the edge length*/
- if (e1->offset_r == 0.0f && is_outside_edge(e1, meetco, &closer_v)) {
- copy_v3_v3(meetco, closer_v->co);
- }
- if (e2->offset_l == 0.0f && is_outside_edge(e2, meetco, &closer_v)) {
- copy_v3_v3(meetco, closer_v->co);
- }
- if (edges_between && e1->offset_r > 0.0f && e2->offset_l > 0.0f) {
- /* Try to drop meetco to a face between e1 and e2 */
- if (isect_kind == 2) {
- /* lines didn't meet in 3d: get average of meetco and isect2 */
- mid_v3_v3v3(meetco, meetco, isect2);
- }
- for (e = e1; e != e2; e = e->next) {
- ff = e->fnext;
- if (!ff) {
- continue;
- }
- plane_from_point_normal_v3(plane, v->co, ff->no);
- closest_to_plane_normalized_v3(dropco, plane, meetco);
- if (point_between_edges(dropco, v, ff, e, e->next)) {
- copy_v3_v3(meetco, dropco);
- break;
- }
- }
- }
- }
- }
+ float dir1[3], dir2[3], dir1n[3], dir2p[3], norm_v[3], norm_v1[3], norm_v2[3];
+ float norm_perp1[3], norm_perp2[3], off1a[3], off1b[3], off2a[3], off2b[3];
+ float isect2[3], dropco[3], plane[4];
+ float ang, d;
+ BMVert *closer_v;
+ EdgeHalf *e, *e1next, *e2prev;
+ BMFace *ff;
+ int isect_kind;
+
+ /* get direction vectors for two offset lines */
+ sub_v3_v3v3(dir1, v->co, BM_edge_other_vert(e1->e, v)->co);
+ sub_v3_v3v3(dir2, BM_edge_other_vert(e2->e, v)->co, v->co);
+
+ if (edges_between) {
+ e1next = e1->next;
+ e2prev = e2->prev;
+ sub_v3_v3v3(dir1n, BM_edge_other_vert(e1next->e, v)->co, v->co);
+ sub_v3_v3v3(dir2p, v->co, BM_edge_other_vert(e2prev->e, v)->co);
+ }
+ else {
+ /* shup up 'maybe unused' warnings */
+ zero_v3(dir1n);
+ zero_v3(dir2p);
+ }
+
+ ang = angle_v3v3(dir1, dir2);
+ if (ang < BEVEL_EPSILON_ANG) {
+ /* special case: e1 and e2 are parallel; put offset point perp to both, from v.
+ * need to find a suitable plane.
+ * this code used to just use offset and dir1, but that makes for visible errors
+ * on a circle with > 200 sides, which trips this "nearly perp" code (see T61214).
+ * so use the average of the two, and the offset formula for angle bisector.
+ * if offsets are different, we're out of luck:
+ * use the max of the two (so get consistent looking results if the same situation
+ * arises elsewhere in the object but with opposite roles for e1 and e2 */
+ if (f) {
+ copy_v3_v3(norm_v, f->no);
+ }
+ else {
+ copy_v3_v3(norm_v, v->no);
+ }
+ add_v3_v3(dir1, dir2);
+ cross_v3_v3v3(norm_perp1, dir1, norm_v);
+ normalize_v3(norm_perp1);
+ copy_v3_v3(off1a, v->co);
+ d = max_ff(e1->offset_r, e2->offset_l);
+ d = d / cos(ang / 2.0f);
+ madd_v3_v3fl(off1a, norm_perp1, d);
+ copy_v3_v3(meetco, off1a);
+ }
+ else if (fabsf(ang - (float)M_PI) < BEVEL_EPSILON_ANG) {
+ /* special case e1 and e2 are antiparallel, so bevel is into
+ * a zero-area face. Just make the offset point on the
+ * common line, at offset distance from v. */
+ d = max_ff(e1->offset_r, e2->offset_l);
+ slide_dist(e2, v, d, meetco);
+ }
+ else {
+ /* Get normal to plane where meet point should be,
+ * using cross product instead of f->no in case f is non-planar.
+ * Except: sometimes locally there can be a small angle
+ * between dir1 and dir2 that leads to a normal that is actually almost
+ * perpendicular to the face normal; in this case it looks wrong to use
+ * the local (cross-product) normal, so use the face normal if the angle
+ * between dir1 and dir2 is smallish.
+ * If e1-v-e2 is a reflex angle (viewed from vertex normal side), need to flip.
+ * Use f->no to figure out which side to look at angle from, as even if
+ * f is non-planar, will be more accurate than vertex normal */
+ if (f && ang < BEVEL_SMALL_ANG) {
+ copy_v3_v3(norm_v1, f->no);
+ copy_v3_v3(norm_v2, f->no);
+ }
+ else if (!edges_between) {
+ cross_v3_v3v3(norm_v1, dir2, dir1);
+ normalize_v3(norm_v1);
+ if (dot_v3v3(norm_v1, f ? f->no : v->no) < 0.0f) {
+ negate_v3(norm_v1);
+ }
+ copy_v3_v3(norm_v2, norm_v1);
+ }
+ else {
+ /* separate faces; get face norms at corners for each separately */
+ cross_v3_v3v3(norm_v1, dir1n, dir1);
+ normalize_v3(norm_v1);
+ f = e1->fnext;
+ if (dot_v3v3(norm_v1, f ? f->no : v->no) < 0.0f) {
+ negate_v3(norm_v1);
+ }
+ cross_v3_v3v3(norm_v2, dir2, dir2p);
+ normalize_v3(norm_v2);
+ f = e2->fprev;
+ if (dot_v3v3(norm_v2, f ? f->no : v->no) < 0.0f) {
+ negate_v3(norm_v2);
+ }
+ }
+
+ /* get vectors perp to each edge, perp to norm_v, and pointing into face */
+ cross_v3_v3v3(norm_perp1, dir1, norm_v1);
+ cross_v3_v3v3(norm_perp2, dir2, norm_v2);
+ normalize_v3(norm_perp1);
+ normalize_v3(norm_perp2);
+
+ /* get points that are offset distances from each line, then another point on each line */
+ copy_v3_v3(off1a, v->co);
+ madd_v3_v3fl(off1a, norm_perp1, e1->offset_r);
+ add_v3_v3v3(off1b, off1a, dir1);
+ copy_v3_v3(off2a, v->co);
+ madd_v3_v3fl(off2a, norm_perp2, e2->offset_l);
+ add_v3_v3v3(off2b, off2a, dir2);
+
+ /* intersect the lines */
+ isect_kind = isect_line_line_v3(off1a, off1b, off2a, off2b, meetco, isect2);
+ if (isect_kind == 0) {
+ /* lines are collinear: we already tested for this, but this used a different epsilon */
+ copy_v3_v3(meetco, off1a); /* just to do something */
+ }
+ else {
+ /* The lines intersect, but is it at a reasonable place?
+ * One problem to check: if one of the offsets is 0, then don't
+ * want an intersection that is outside that edge itself.
+ * This can happen if angle between them is > 180 degrees,
+ * or if the offset amount is > the edge length*/
+ if (e1->offset_r == 0.0f && is_outside_edge(e1, meetco, &closer_v)) {
+ copy_v3_v3(meetco, closer_v->co);
+ }
+ if (e2->offset_l == 0.0f && is_outside_edge(e2, meetco, &closer_v)) {
+ copy_v3_v3(meetco, closer_v->co);
+ }
+ if (edges_between && e1->offset_r > 0.0f && e2->offset_l > 0.0f) {
+ /* Try to drop meetco to a face between e1 and e2 */
+ if (isect_kind == 2) {
+ /* lines didn't meet in 3d: get average of meetco and isect2 */
+ mid_v3_v3v3(meetco, meetco, isect2);
+ }
+ for (e = e1; e != e2; e = e->next) {
+ ff = e->fnext;
+ if (!ff) {
+ continue;
+ }
+ plane_from_point_normal_v3(plane, v->co, ff->no);
+ closest_to_plane_normalized_v3(dropco, plane, meetco);
+ if (point_between_edges(dropco, v, ff, e, e->next)) {
+ copy_v3_v3(meetco, dropco);
+ break;
+ }
+ }
+ }
+ }
+ }
}
/* chosen so that 1/sin(BEVEL_GOOD_ANGLE) is about 4, giving that expansion factor to bevel width */
@@ -1017,60 +1032,60 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, bool e
* If r_angle is provided, return the angle between e and emeet in *r_angle.
* If the angle is 0, or it is 180 degrees or larger, there will be no meeting point;
* return false in that case, else true. */
-static bool offset_meet_edge(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, float meetco[3], float *r_angle)
+static bool offset_meet_edge(
+ EdgeHalf *e1, EdgeHalf *e2, BMVert *v, float meetco[3], float *r_angle)
{
- float dir1[3], dir2[3], fno[3], ang, sinang;
-
- sub_v3_v3v3(dir1, BM_edge_other_vert(e1->e, v)->co, v->co);
- sub_v3_v3v3(dir2, BM_edge_other_vert(e2->e, v)->co, v->co);
- normalize_v3(dir1);
- normalize_v3(dir2);
-
- /* find angle from dir1 to dir2 as viewed from vertex normal side */
- ang = angle_normalized_v3v3(dir1, dir2);
- if (fabsf(ang) < BEVEL_GOOD_ANGLE) {
- if (r_angle) {
- *r_angle = 0.0f;
- }
- return false;
- }
- cross_v3_v3v3(fno, dir1, dir2);
- if (dot_v3v3(fno, v->no) < 0.0f) {
- ang = 2.0f * (float)M_PI - ang; /* angle is reflex */
- if (r_angle) {
- *r_angle = ang;
- }
- return false;
- }
- if (r_angle) {
- *r_angle = ang;
- }
-
- if (fabsf(ang - (float)M_PI) < BEVEL_GOOD_ANGLE) {
- return false;
- }
-
- sinang = sinf(ang);
-
- copy_v3_v3(meetco, v->co);
- if (e1->offset_r == 0.0f) {
- madd_v3_v3fl(meetco, dir1, e2->offset_l / sinang);
- }
- else {
- madd_v3_v3fl(meetco, dir2, e1->offset_r / sinang);
- }
- return true;
+ float dir1[3], dir2[3], fno[3], ang, sinang;
+
+ sub_v3_v3v3(dir1, BM_edge_other_vert(e1->e, v)->co, v->co);
+ sub_v3_v3v3(dir2, BM_edge_other_vert(e2->e, v)->co, v->co);
+ normalize_v3(dir1);
+ normalize_v3(dir2);
+
+ /* find angle from dir1 to dir2 as viewed from vertex normal side */
+ ang = angle_normalized_v3v3(dir1, dir2);
+ if (fabsf(ang) < BEVEL_GOOD_ANGLE) {
+ if (r_angle) {
+ *r_angle = 0.0f;
+ }
+ return false;
+ }
+ cross_v3_v3v3(fno, dir1, dir2);
+ if (dot_v3v3(fno, v->no) < 0.0f) {
+ ang = 2.0f * (float)M_PI - ang; /* angle is reflex */
+ if (r_angle) {
+ *r_angle = ang;
+ }
+ return false;
+ }
+ if (r_angle) {
+ *r_angle = ang;
+ }
+
+ if (fabsf(ang - (float)M_PI) < BEVEL_GOOD_ANGLE) {
+ return false;
+ }
+
+ sinang = sinf(ang);
+
+ copy_v3_v3(meetco, v->co);
+ if (e1->offset_r == 0.0f) {
+ madd_v3_v3fl(meetco, dir1, e2->offset_l / sinang);
+ }
+ else {
+ madd_v3_v3fl(meetco, dir2, e1->offset_r / sinang);
+ }
+ return true;
}
/* Return true if it will look good to put the meeting point where offset_on_edge_between
* would put it. This means that neither side sees a reflex angle */
static bool good_offset_on_edge_between(EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid, BMVert *v)
{
- float ang;
- float meet[3];
+ float ang;
+ float meet[3];
- return offset_meet_edge(e1, emid, v, meet, &ang) &&
- offset_meet_edge(emid, e2, v, meet, &ang);
+ return offset_meet_edge(e1, emid, v, meet, &ang) && offset_meet_edge(emid, e2, v, meet, &ang);
}
/* Calculate the best place for a meeting point for the offsets from edges e1 and e2
@@ -1079,39 +1094,38 @@ static bool good_offset_on_edge_between(EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *em
* Return true if we placed meetco as compromise between where two edges met.
* If we did, put ration of sines of angles in *r_sinratio too */
static bool offset_on_edge_between(
- EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid,
- BMVert *v, float meetco[3], float *r_sinratio)
+ EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid, BMVert *v, float meetco[3], float *r_sinratio)
{
- float ang1, ang2;
- float meet1[3], meet2[3];
- bool ok1, ok2;
- bool retval = false;
-
- BLI_assert(e1->is_bev && e2->is_bev && !emid->is_bev);
-
- ok1 = offset_meet_edge(e1, emid, v, meet1, &ang1);
- ok2 = offset_meet_edge(emid, e2, v, meet2, &ang2);
- if (ok1 && ok2) {
- mid_v3_v3v3(meetco, meet1, meet2);
- if (r_sinratio) {
- /* ang1 should not be 0, but be paranoid */
- *r_sinratio = (ang1 == 0.0f) ? 1.0f : sinf(ang2) / sinf(ang1);
- }
- retval = true;
- }
- else if (ok1 && !ok2) {
- copy_v3_v3(meetco, meet1);
- }
- else if (!ok1 && ok2) {
- copy_v3_v3(meetco, meet2);
- }
- else {
- /* Neither offset line met emid.
- * This should only happen if all three lines are on top of each other */
- slide_dist(emid, v, e1->offset_r, meetco);
- }
-
- return retval;
+ float ang1, ang2;
+ float meet1[3], meet2[3];
+ bool ok1, ok2;
+ bool retval = false;
+
+ BLI_assert(e1->is_bev && e2->is_bev && !emid->is_bev);
+
+ ok1 = offset_meet_edge(e1, emid, v, meet1, &ang1);
+ ok2 = offset_meet_edge(emid, e2, v, meet2, &ang2);
+ if (ok1 && ok2) {
+ mid_v3_v3v3(meetco, meet1, meet2);
+ if (r_sinratio) {
+ /* ang1 should not be 0, but be paranoid */
+ *r_sinratio = (ang1 == 0.0f) ? 1.0f : sinf(ang2) / sinf(ang1);
+ }
+ retval = true;
+ }
+ else if (ok1 && !ok2) {
+ copy_v3_v3(meetco, meet1);
+ }
+ else if (!ok1 && ok2) {
+ copy_v3_v3(meetco, meet2);
+ }
+ else {
+ /* Neither offset line met emid.
+ * This should only happen if all three lines are on top of each other */
+ slide_dist(emid, v, e1->offset_r, meetco);
+ }
+
+ return retval;
}
/* Offset by e->offset in plane with normal plane_no, on left if left==true,
@@ -1119,47 +1133,47 @@ static bool offset_on_edge_between(
* from eh's direction. */
static void offset_in_plane(EdgeHalf *e, const float plane_no[3], bool left, float r[3])
{
- float dir[3], no[3], fdir[3];
- BMVert *v;
-
- v = e->is_rev ? e->e->v2 : e->e->v1;
-
- sub_v3_v3v3(dir, BM_edge_other_vert(e->e, v)->co, v->co);
- normalize_v3(dir);
- if (plane_no) {
- copy_v3_v3(no, plane_no);
- }
- else {
- zero_v3(no);
- if (fabsf(dir[0]) < fabsf(dir[1])) {
- no[0] = 1.0f;
- }
- else {
- no[1] = 1.0f;
- }
- }
- if (left) {
- cross_v3_v3v3(fdir, dir, no);
- }
- else {
- cross_v3_v3v3(fdir, no, dir);
- }
- normalize_v3(fdir);
- copy_v3_v3(r, v->co);
- madd_v3_v3fl(r, fdir, left ? e->offset_l : e->offset_r);
+ float dir[3], no[3], fdir[3];
+ BMVert *v;
+
+ v = e->is_rev ? e->e->v2 : e->e->v1;
+
+ sub_v3_v3v3(dir, BM_edge_other_vert(e->e, v)->co, v->co);
+ normalize_v3(dir);
+ if (plane_no) {
+ copy_v3_v3(no, plane_no);
+ }
+ else {
+ zero_v3(no);
+ if (fabsf(dir[0]) < fabsf(dir[1])) {
+ no[0] = 1.0f;
+ }
+ else {
+ no[1] = 1.0f;
+ }
+ }
+ if (left) {
+ cross_v3_v3v3(fdir, dir, no);
+ }
+ else {
+ cross_v3_v3v3(fdir, no, dir);
+ }
+ normalize_v3(fdir);
+ copy_v3_v3(r, v->co);
+ madd_v3_v3fl(r, fdir, left ? e->offset_l : e->offset_r);
}
/* Calculate the point on e where line (co_a, co_b) comes closest to and return it in projco */
static void project_to_edge(BMEdge *e, const float co_a[3], const float co_b[3], float projco[3])
{
- float otherco[3];
+ float otherco[3];
- if (!isect_line_line_v3(e->v1->co, e->v2->co, co_a, co_b, projco, otherco)) {
+ if (!isect_line_line_v3(e->v1->co, e->v2->co, co_a, co_b, projco, otherco)) {
#ifdef BEVEL_ASSERT_PROJECT
- BLI_assert(!"project meet failure");
+ BLI_assert(!"project meet failure");
#endif
- copy_v3_v3(projco, e->v1->co);
- }
+ copy_v3_v3(projco, e->v1->co);
+ }
}
/* If there is a bndv->ebev edge, find the mid control point if necessary.
@@ -1167,159 +1181,159 @@ static void project_to_edge(BMEdge *e, const float co_a[3], const float co_b[3],
* bndv and bndv->next. */
static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv)
{
- EdgeHalf *e;
- Profile *pro;
- float co1[3], co2[3], co3[3], d1[3], d2[3];
- bool do_linear_interp;
-
- copy_v3_v3(co1, bndv->nv.co);
- copy_v3_v3(co2, bndv->next->nv.co);
- pro = &bndv->profile;
- e = bndv->ebev;
- do_linear_interp = true;
- if (e) {
- do_linear_interp = false;
- pro->super_r = bp->pro_super_r;
- /* projection direction is direction of the edge */
- sub_v3_v3v3(pro->proj_dir, e->e->v1->co, e->e->v2->co);
- normalize_v3(pro->proj_dir);
- project_to_edge(e->e, co1, co2, pro->midco);
- if (DEBUG_OLD_PROJ_TO_PERP_PLANE) {
- /* put arc endpoints on plane with normal proj_dir, containing midco */
- add_v3_v3v3(co3, co1, pro->proj_dir);
- if (!isect_line_plane_v3(pro->coa, co1, co3, pro->midco, pro->proj_dir)) {
- /* shouldn't happen */
- copy_v3_v3(pro->coa, co1);
- }
- add_v3_v3v3(co3, co2, pro->proj_dir);
- if (!isect_line_plane_v3(pro->cob, co2, co3, pro->midco, pro->proj_dir)) {
- /* shouldn't happen */
- copy_v3_v3(pro->cob, co2);
- }
- }
- else {
- copy_v3_v3(pro->coa, co1);
- copy_v3_v3(pro->cob, co2);
- }
- /* default plane to project onto is the one with triangle co1 - midco - co2 in it */
- sub_v3_v3v3(d1, pro->midco, co1);
- sub_v3_v3v3(d2, pro->midco, co2);
- normalize_v3(d1);
- normalize_v3(d2);
- cross_v3_v3v3(pro->plane_no, d1, d2);
- normalize_v3(pro->plane_no);
- if (nearly_parallel(d1, d2)) {
- /* co1 - midco -co2 are collinear.
- * Should be case that beveled edge is coplanar with two boundary verts.
- * We want to move the profile to that common plane, if possible.
- * That makes the multi-segment bevels curve nicely in that plane, as users expect.
- * The new midco should be either v (when neighbor edges are unbeveled)
- * or the intersection of the offset lines (if they are).
- * If the profile is going to lead into unbeveled edges on each side
- * (that is, both BoundVerts are "on-edge" points on non-beveled edges)
- */
- if (DEBUG_OLD_PLANE_SPECIAL && (e->prev->is_bev || e->next->is_bev)) {
- do_linear_interp = true;
- }
- else {
- if (DEBUG_OLD_PROJ_TO_PERP_PLANE) {
- copy_v3_v3(pro->coa, co1);
- copy_v3_v3(pro->cob, co2);
- }
- if (DEBUG_OLD_FLAT_MID) {
- copy_v3_v3(pro->midco, bv->v->co);
- }
- else {
- copy_v3_v3(pro->midco, bv->v->co);
- if (e->prev->is_bev && e->next->is_bev && bv->selcount >= 3) {
- /* want mid at the meet point of next and prev offset edges */
- float d3[3], d4[3], co4[3], meetco[3], isect2[3];
- int isect_kind;
-
- sub_v3_v3v3(d3, e->prev->e->v1->co, e->prev->e->v2->co);
- sub_v3_v3v3(d4, e->next->e->v1->co, e->next->e->v2->co);
- normalize_v3(d3);
- normalize_v3(d4);
- if (nearly_parallel(d3, d4)) {
- /* offset lines are collinear - want linear interpolation */
- mid_v3_v3v3(pro->midco, co1, co2);
- do_linear_interp = true;
- }
- else {
- add_v3_v3v3(co3, co1, d3);
- add_v3_v3v3(co4, co2, d4);
- isect_kind = isect_line_line_v3(co1, co3, co2, co4, meetco, isect2);
- if (isect_kind != 0) {
- copy_v3_v3(pro->midco, meetco);
- }
- else {
- /* offset lines don't intersect - want linear interpolation */
- mid_v3_v3v3(pro->midco, co1, co2);
- do_linear_interp = true;
- }
- }
- }
- }
- copy_v3_v3(pro->cob, co2);
- sub_v3_v3v3(d1, pro->midco, co1);
- normalize_v3(d1);
- sub_v3_v3v3(d2, pro->midco, co2);
- normalize_v3(d2);
- cross_v3_v3v3(pro->plane_no, d1, d2);
- normalize_v3(pro->plane_no);
- if (nearly_parallel(d1, d2)) {
- /* whole profile is collinear with edge: just interpolate */
- do_linear_interp = true;
- }
- else {
- copy_v3_v3(pro->plane_co, bv->v->co);
- copy_v3_v3(pro->proj_dir, pro->plane_no);
- }
- }
- }
- copy_v3_v3(pro->plane_co, co1);
- }
- else if (bndv->is_arc_start) {
- /* assume pro->midco was alredy set */
- copy_v3_v3(pro->coa, co1);
- copy_v3_v3(pro->cob, co2);
- pro->super_r = PRO_CIRCLE_R;
- zero_v3(pro->plane_co);
- zero_v3(pro->plane_no);
- zero_v3(pro->proj_dir);
- do_linear_interp = false;
- }
- if (do_linear_interp) {
- pro->super_r = PRO_LINE_R;
- copy_v3_v3(pro->coa, co1);
- copy_v3_v3(pro->cob, co2);
- mid_v3_v3v3(pro->midco, co1, co2);
- /* won't use projection for this line profile */
- zero_v3(pro->plane_co);
- zero_v3(pro->plane_no);
- zero_v3(pro->proj_dir);
- }
+ EdgeHalf *e;
+ Profile *pro;
+ float co1[3], co2[3], co3[3], d1[3], d2[3];
+ bool do_linear_interp;
+
+ copy_v3_v3(co1, bndv->nv.co);
+ copy_v3_v3(co2, bndv->next->nv.co);
+ pro = &bndv->profile;
+ e = bndv->ebev;
+ do_linear_interp = true;
+ if (e) {
+ do_linear_interp = false;
+ pro->super_r = bp->pro_super_r;
+ /* projection direction is direction of the edge */
+ sub_v3_v3v3(pro->proj_dir, e->e->v1->co, e->e->v2->co);
+ normalize_v3(pro->proj_dir);
+ project_to_edge(e->e, co1, co2, pro->midco);
+ if (DEBUG_OLD_PROJ_TO_PERP_PLANE) {
+ /* put arc endpoints on plane with normal proj_dir, containing midco */
+ add_v3_v3v3(co3, co1, pro->proj_dir);
+ if (!isect_line_plane_v3(pro->coa, co1, co3, pro->midco, pro->proj_dir)) {
+ /* shouldn't happen */
+ copy_v3_v3(pro->coa, co1);
+ }
+ add_v3_v3v3(co3, co2, pro->proj_dir);
+ if (!isect_line_plane_v3(pro->cob, co2, co3, pro->midco, pro->proj_dir)) {
+ /* shouldn't happen */
+ copy_v3_v3(pro->cob, co2);
+ }
+ }
+ else {
+ copy_v3_v3(pro->coa, co1);
+ copy_v3_v3(pro->cob, co2);
+ }
+ /* default plane to project onto is the one with triangle co1 - midco - co2 in it */
+ sub_v3_v3v3(d1, pro->midco, co1);
+ sub_v3_v3v3(d2, pro->midco, co2);
+ normalize_v3(d1);
+ normalize_v3(d2);
+ cross_v3_v3v3(pro->plane_no, d1, d2);
+ normalize_v3(pro->plane_no);
+ if (nearly_parallel(d1, d2)) {
+ /* co1 - midco -co2 are collinear.
+ * Should be case that beveled edge is coplanar with two boundary verts.
+ * We want to move the profile to that common plane, if possible.
+ * That makes the multi-segment bevels curve nicely in that plane, as users expect.
+ * The new midco should be either v (when neighbor edges are unbeveled)
+ * or the intersection of the offset lines (if they are).
+ * If the profile is going to lead into unbeveled edges on each side
+ * (that is, both BoundVerts are "on-edge" points on non-beveled edges)
+ */
+ if (DEBUG_OLD_PLANE_SPECIAL && (e->prev->is_bev || e->next->is_bev)) {
+ do_linear_interp = true;
+ }
+ else {
+ if (DEBUG_OLD_PROJ_TO_PERP_PLANE) {
+ copy_v3_v3(pro->coa, co1);
+ copy_v3_v3(pro->cob, co2);
+ }
+ if (DEBUG_OLD_FLAT_MID) {
+ copy_v3_v3(pro->midco, bv->v->co);
+ }
+ else {
+ copy_v3_v3(pro->midco, bv->v->co);
+ if (e->prev->is_bev && e->next->is_bev && bv->selcount >= 3) {
+ /* want mid at the meet point of next and prev offset edges */
+ float d3[3], d4[3], co4[3], meetco[3], isect2[3];
+ int isect_kind;
+
+ sub_v3_v3v3(d3, e->prev->e->v1->co, e->prev->e->v2->co);
+ sub_v3_v3v3(d4, e->next->e->v1->co, e->next->e->v2->co);
+ normalize_v3(d3);
+ normalize_v3(d4);
+ if (nearly_parallel(d3, d4)) {
+ /* offset lines are collinear - want linear interpolation */
+ mid_v3_v3v3(pro->midco, co1, co2);
+ do_linear_interp = true;
+ }
+ else {
+ add_v3_v3v3(co3, co1, d3);
+ add_v3_v3v3(co4, co2, d4);
+ isect_kind = isect_line_line_v3(co1, co3, co2, co4, meetco, isect2);
+ if (isect_kind != 0) {
+ copy_v3_v3(pro->midco, meetco);
+ }
+ else {
+ /* offset lines don't intersect - want linear interpolation */
+ mid_v3_v3v3(pro->midco, co1, co2);
+ do_linear_interp = true;
+ }
+ }
+ }
+ }
+ copy_v3_v3(pro->cob, co2);
+ sub_v3_v3v3(d1, pro->midco, co1);
+ normalize_v3(d1);
+ sub_v3_v3v3(d2, pro->midco, co2);
+ normalize_v3(d2);
+ cross_v3_v3v3(pro->plane_no, d1, d2);
+ normalize_v3(pro->plane_no);
+ if (nearly_parallel(d1, d2)) {
+ /* whole profile is collinear with edge: just interpolate */
+ do_linear_interp = true;
+ }
+ else {
+ copy_v3_v3(pro->plane_co, bv->v->co);
+ copy_v3_v3(pro->proj_dir, pro->plane_no);
+ }
+ }
+ }
+ copy_v3_v3(pro->plane_co, co1);
+ }
+ else if (bndv->is_arc_start) {
+ /* assume pro->midco was alredy set */
+ copy_v3_v3(pro->coa, co1);
+ copy_v3_v3(pro->cob, co2);
+ pro->super_r = PRO_CIRCLE_R;
+ zero_v3(pro->plane_co);
+ zero_v3(pro->plane_no);
+ zero_v3(pro->proj_dir);
+ do_linear_interp = false;
+ }
+ if (do_linear_interp) {
+ pro->super_r = PRO_LINE_R;
+ copy_v3_v3(pro->coa, co1);
+ copy_v3_v3(pro->cob, co2);
+ mid_v3_v3v3(pro->midco, co1, co2);
+ /* won't use projection for this line profile */
+ zero_v3(pro->plane_co);
+ zero_v3(pro->plane_no);
+ zero_v3(pro->proj_dir);
+ }
}
/* Move the profile plane for bndv to the plane containing e1 and e2, which share a vert */
static void move_profile_plane(BoundVert *bndv, EdgeHalf *e1, EdgeHalf *e2)
{
- float d1[3], d2[3], no[3], no2[3], dot;
-
- /* only do this if projecting, and e1, e2, and proj_dir are not coplanar */
- if (is_zero_v3(bndv->profile.proj_dir)) {
- return;
- }
- sub_v3_v3v3(d1, e1->e->v1->co, e1->e->v2->co);
- sub_v3_v3v3(d2, e2->e->v1->co, e2->e->v2->co);
- cross_v3_v3v3(no, d1, d2);
- cross_v3_v3v3(no2, d1, bndv->profile.proj_dir);
- if (normalize_v3(no) > BEVEL_EPSILON_BIG && normalize_v3(no2) > BEVEL_EPSILON_BIG) {
- dot = fabsf(dot_v3v3(no, no2));
- if (fabsf(dot - 1.0f) > BEVEL_EPSILON_BIG) {
- copy_v3_v3(bndv->profile.plane_no, no);
- }
- }
+ float d1[3], d2[3], no[3], no2[3], dot;
+
+ /* only do this if projecting, and e1, e2, and proj_dir are not coplanar */
+ if (is_zero_v3(bndv->profile.proj_dir)) {
+ return;
+ }
+ sub_v3_v3v3(d1, e1->e->v1->co, e1->e->v2->co);
+ sub_v3_v3v3(d2, e2->e->v1->co, e2->e->v2->co);
+ cross_v3_v3v3(no, d1, d2);
+ cross_v3_v3v3(no2, d1, bndv->profile.proj_dir);
+ if (normalize_v3(no) > BEVEL_EPSILON_BIG && normalize_v3(no2) > BEVEL_EPSILON_BIG) {
+ dot = fabsf(dot_v3v3(no, no2));
+ if (fabsf(dot - 1.0f) > BEVEL_EPSILON_BIG) {
+ copy_v3_v3(bndv->profile.plane_no, no);
+ }
+ }
}
/* Move the profile plane for the two BoundVerts involved in a weld.
@@ -1329,49 +1343,49 @@ static void move_profile_plane(BoundVert *bndv, EdgeHalf *e1, EdgeHalf *e2)
* The original vertex should form a third point of the desired plane. */
static void move_weld_profile_planes(BevVert *bv, BoundVert *bndv1, BoundVert *bndv2)
{
- float d1[3], d2[3], no[3], no2[3], no3[3], dot1, dot2, l1, l2, l3;
-
- /* only do this if projecting, and d1, d2, and proj_dir are not coplanar */
- if (is_zero_v3(bndv1->profile.proj_dir) || is_zero_v3(bndv2->profile.proj_dir)) {
- return;
- }
- sub_v3_v3v3(d1, bv->v->co, bndv1->nv.co);
- sub_v3_v3v3(d2, bv->v->co, bndv2->nv.co);
- cross_v3_v3v3(no, d1, d2);
- l1 = normalize_v3(no);
- /* "no" is new normal projection plane, but don't move if
- * it is coplanar with both of the projection dirs */
- cross_v3_v3v3(no2, d1, bndv1->profile.proj_dir);
- l2 = normalize_v3(no2);
- cross_v3_v3v3(no3, d2, bndv2->profile.proj_dir);
- l3 = normalize_v3(no3);
- if (l1 > BEVEL_EPSILON && (l2 > BEVEL_EPSILON || l3 > BEVEL_EPSILON)) {
- dot1 = fabsf(dot_v3v3(no, no2));
- dot2 = fabsf(dot_v3v3(no, no3));
- if (fabsf(dot1 - 1.0f) > BEVEL_EPSILON) {
- copy_v3_v3(bndv1->profile.plane_no, no);
- }
- if (fabsf(dot2 - 1.0f) > BEVEL_EPSILON) {
- copy_v3_v3(bndv2->profile.plane_no, no);
- }
- }
+ float d1[3], d2[3], no[3], no2[3], no3[3], dot1, dot2, l1, l2, l3;
+
+ /* only do this if projecting, and d1, d2, and proj_dir are not coplanar */
+ if (is_zero_v3(bndv1->profile.proj_dir) || is_zero_v3(bndv2->profile.proj_dir)) {
+ return;
+ }
+ sub_v3_v3v3(d1, bv->v->co, bndv1->nv.co);
+ sub_v3_v3v3(d2, bv->v->co, bndv2->nv.co);
+ cross_v3_v3v3(no, d1, d2);
+ l1 = normalize_v3(no);
+ /* "no" is new normal projection plane, but don't move if
+ * it is coplanar with both of the projection dirs */
+ cross_v3_v3v3(no2, d1, bndv1->profile.proj_dir);
+ l2 = normalize_v3(no2);
+ cross_v3_v3v3(no3, d2, bndv2->profile.proj_dir);
+ l3 = normalize_v3(no3);
+ if (l1 > BEVEL_EPSILON && (l2 > BEVEL_EPSILON || l3 > BEVEL_EPSILON)) {
+ dot1 = fabsf(dot_v3v3(no, no2));
+ dot2 = fabsf(dot_v3v3(no, no3));
+ if (fabsf(dot1 - 1.0f) > BEVEL_EPSILON) {
+ copy_v3_v3(bndv1->profile.plane_no, no);
+ }
+ if (fabsf(dot2 - 1.0f) > BEVEL_EPSILON) {
+ copy_v3_v3(bndv2->profile.plane_no, no);
+ }
+ }
}
/* return 1 if a and b are in CCW order on the normal side of f,
* and -1 if they are reversed, and 0 if there is no shared face f */
static int bev_ccw_test(BMEdge *a, BMEdge *b, BMFace *f)
{
- BMLoop *la, *lb;
-
- if (!f) {
- return 0;
- }
- la = BM_face_edge_share_loop(f, a);
- lb = BM_face_edge_share_loop(f, b);
- if (!la || !lb) {
- return 0;
- }
- return lb->next == la ? 1 : -1;
+ BMLoop *la, *lb;
+
+ if (!f) {
+ return 0;
+ }
+ la = BM_face_edge_share_loop(f, a);
+ lb = BM_face_edge_share_loop(f, b);
+ if (!la || !lb) {
+ return 0;
+ }
+ return lb->next == la ? 1 : -1;
}
/* Fill matrix r_mat so that a point in the sheared parallelogram with corners
@@ -1394,44 +1408,45 @@ static int bev_ccw_test(BMEdge *a, BMEdge *b, BMFace *f)
* and B has the right side as columns - both extended into homogeneous coords.
* So M = B*(Ainverse). Doing Ainverse by hand gives the code below.
*/
-static bool make_unit_square_map(
- const float va[3], const float vmid[3], const float vb[3],
- float r_mat[4][4])
+static bool make_unit_square_map(const float va[3],
+ const float vmid[3],
+ const float vb[3],
+ float r_mat[4][4])
{
- float vo[3], vd[3], vb_vmid[3], va_vmid[3], vddir[3];
-
- sub_v3_v3v3(va_vmid, vmid, va);
- sub_v3_v3v3(vb_vmid, vmid, vb);
-
- if (is_zero_v3(va_vmid) || is_zero_v3(vb_vmid)) {
- return false;
- }
-
- if (fabsf(angle_v3v3(va_vmid, vb_vmid) - (float)M_PI) <= BEVEL_EPSILON_ANG) {
- return false;
- }
-
- sub_v3_v3v3(vo, va, vb_vmid);
- cross_v3_v3v3(vddir, vb_vmid, va_vmid);
- normalize_v3(vddir);
- add_v3_v3v3(vd, vo, vddir);
-
- /* The cols of m are: {vmid - va, vmid - vb, vmid + vd - va -vb, va + vb - vmid;
- * blender transform matrices are stored such that m[i][*] is ith column;
- * the last elements of each col remain as they are in unity matrix. */
- sub_v3_v3v3(&r_mat[0][0], vmid, va);
- r_mat[0][3] = 0.0f;
- sub_v3_v3v3(&r_mat[1][0], vmid, vb);
- r_mat[1][3] = 0.0f;
- add_v3_v3v3(&r_mat[2][0], vmid, vd);
- sub_v3_v3(&r_mat[2][0], va);
- sub_v3_v3(&r_mat[2][0], vb);
- r_mat[2][3] = 0.0f;
- add_v3_v3v3(&r_mat[3][0], va, vb);
- sub_v3_v3(&r_mat[3][0], vmid);
- r_mat[3][3] = 1.0f;
-
- return true;
+ float vo[3], vd[3], vb_vmid[3], va_vmid[3], vddir[3];
+
+ sub_v3_v3v3(va_vmid, vmid, va);
+ sub_v3_v3v3(vb_vmid, vmid, vb);
+
+ if (is_zero_v3(va_vmid) || is_zero_v3(vb_vmid)) {
+ return false;
+ }
+
+ if (fabsf(angle_v3v3(va_vmid, vb_vmid) - (float)M_PI) <= BEVEL_EPSILON_ANG) {
+ return false;
+ }
+
+ sub_v3_v3v3(vo, va, vb_vmid);
+ cross_v3_v3v3(vddir, vb_vmid, va_vmid);
+ normalize_v3(vddir);
+ add_v3_v3v3(vd, vo, vddir);
+
+ /* The cols of m are: {vmid - va, vmid - vb, vmid + vd - va -vb, va + vb - vmid;
+ * blender transform matrices are stored such that m[i][*] is ith column;
+ * the last elements of each col remain as they are in unity matrix. */
+ sub_v3_v3v3(&r_mat[0][0], vmid, va);
+ r_mat[0][3] = 0.0f;
+ sub_v3_v3v3(&r_mat[1][0], vmid, vb);
+ r_mat[1][3] = 0.0f;
+ add_v3_v3v3(&r_mat[2][0], vmid, vd);
+ sub_v3_v3(&r_mat[2][0], va);
+ sub_v3_v3(&r_mat[2][0], vb);
+ r_mat[2][3] = 0.0f;
+ add_v3_v3v3(&r_mat[3][0], va, vb);
+ sub_v3_v3(&r_mat[3][0], vmid);
+ r_mat[3][3] = 1.0f;
+
+ return true;
}
/* Like make_unit_square_map, but this one makes a matrix that transforms the
@@ -1450,33 +1465,32 @@ static bool make_unit_square_map(
* and Blender matrices have cols at m[i][*].
*/
static void make_unit_cube_map(
- const float va[3], const float vb[3], const float vc[3],
- const float vd[3], float r_mat[4][4])
+ const float va[3], const float vb[3], const float vc[3], const float vd[3], float r_mat[4][4])
{
- copy_v3_v3(r_mat[0], va);
- sub_v3_v3(r_mat[0], vb);
- sub_v3_v3(r_mat[0], vc);
- add_v3_v3(r_mat[0], vd);
- mul_v3_fl(r_mat[0], 0.5f);
- r_mat[0][3] = 0.0f;
- copy_v3_v3(r_mat[1], vb);
- sub_v3_v3(r_mat[1], va);
- sub_v3_v3(r_mat[1], vc);
- add_v3_v3(r_mat[1], vd);
- mul_v3_fl(r_mat[1], 0.5f);
- r_mat[1][3] = 0.0f;
- copy_v3_v3(r_mat[2], vc);
- sub_v3_v3(r_mat[2], va);
- sub_v3_v3(r_mat[2], vb);
- add_v3_v3(r_mat[2], vd);
- mul_v3_fl(r_mat[2], 0.5f);
- r_mat[2][3] = 0.0f;
- copy_v3_v3(r_mat[3], va);
- add_v3_v3(r_mat[3], vb);
- add_v3_v3(r_mat[3], vc);
- sub_v3_v3(r_mat[3], vd);
- mul_v3_fl(r_mat[3], 0.5f);
- r_mat[3][3] = 1.0f;
+ copy_v3_v3(r_mat[0], va);
+ sub_v3_v3(r_mat[0], vb);
+ sub_v3_v3(r_mat[0], vc);
+ add_v3_v3(r_mat[0], vd);
+ mul_v3_fl(r_mat[0], 0.5f);
+ r_mat[0][3] = 0.0f;
+ copy_v3_v3(r_mat[1], vb);
+ sub_v3_v3(r_mat[1], va);
+ sub_v3_v3(r_mat[1], vc);
+ add_v3_v3(r_mat[1], vd);
+ mul_v3_fl(r_mat[1], 0.5f);
+ r_mat[1][3] = 0.0f;
+ copy_v3_v3(r_mat[2], vc);
+ sub_v3_v3(r_mat[2], va);
+ sub_v3_v3(r_mat[2], vb);
+ add_v3_v3(r_mat[2], vd);
+ mul_v3_fl(r_mat[2], 0.5f);
+ r_mat[2][3] = 0.0f;
+ copy_v3_v3(r_mat[3], va);
+ add_v3_v3(r_mat[3], vb);
+ add_v3_v3(r_mat[3], vc);
+ sub_v3_v3(r_mat[3], vd);
+ mul_v3_fl(r_mat[3], 0.5f);
+ r_mat[3][3] = 1.0f;
}
/* Get the coordinate on the superellipse (x^r + y^r = 1),
@@ -1485,16 +1499,16 @@ static void make_unit_cube_map(
* Assume r > 0.0 */
static double superellipse_co(double x, float r, bool rbig)
{
- BLI_assert(r > 0.0f);
-
- /* If r<1, mirror the superellipse function by (y=x)-line to get a numerically stable range
- * Possible because of symmetry, later mirror back. */
- if (rbig) {
- return pow((1.0 - pow(x, r)), (1.0 / r));
- }
- else {
- return 1.0 - pow((1.0 - pow(1.0 - x, r)), (1.0 / r));
- }
+ BLI_assert(r > 0.0f);
+
+ /* If r<1, mirror the superellipse function by (y=x)-line to get a numerically stable range
+ * Possible because of symmetry, later mirror back. */
+ if (rbig) {
+ return pow((1.0 - pow(x, r)), (1.0 / r));
+ }
+ else {
+ return 1.0 - pow((1.0 - pow(1.0 - x, r)), (1.0 / r));
+ }
}
/* Find the point on given profile at parameter i which goes from 0 to n as
@@ -1506,29 +1520,29 @@ static double superellipse_co(double x, float r, bool rbig)
* method used to make the vmesh pattern. */
static void get_profile_point(BevelParams *bp, const Profile *pro, int i, int n, float r_co[3])
{
- int d;
-
- if (bp->seg == 1) {
- if (i == 0) {
- copy_v3_v3(r_co, pro->coa);
- }
- else {
- copy_v3_v3(r_co, pro->cob);
- }
- }
-
- else {
- if (n == bp->seg) {
- BLI_assert(pro->prof_co != NULL);
- copy_v3_v3(r_co, pro->prof_co + 3 * i);
- }
- else {
- BLI_assert(is_power_of_2_i(n) && n <= bp->pro_spacing.seg_2);
- /* set d to spacing in prof_co_2 between subsamples */
- d = bp->pro_spacing.seg_2 / n;
- copy_v3_v3(r_co, pro->prof_co_2 + 3 * i * d);
- }
- }
+ int d;
+
+ if (bp->seg == 1) {
+ if (i == 0) {
+ copy_v3_v3(r_co, pro->coa);
+ }
+ else {
+ copy_v3_v3(r_co, pro->cob);
+ }
+ }
+
+ else {
+ if (n == bp->seg) {
+ BLI_assert(pro->prof_co != NULL);
+ copy_v3_v3(r_co, pro->prof_co + 3 * i);
+ }
+ else {
+ BLI_assert(is_power_of_2_i(n) && n <= bp->pro_spacing.seg_2);
+ /* set d to spacing in prof_co_2 between subsamples */
+ d = bp->pro_spacing.seg_2 / n;
+ copy_v3_v3(r_co, pro->prof_co_2 + 3 * i * d);
+ }
+ }
}
/* Calculate the actual coordinate values for bndv's profile.
@@ -1540,337 +1554,338 @@ static void get_profile_point(BevelParams *bp, const Profile *pro, int i, int n,
* during construction. */
static void calculate_profile(BevelParams *bp, BoundVert *bndv)
{
- int i, k, ns;
- const double *xvals, *yvals;
- float co[3], co2[3], p[3], m[4][4];
- float *prof_co, *prof_co_k;
- float r;
- bool need_2, map_ok;
- Profile *pro = &bndv->profile;
-
- if (bp->seg == 1) {
- return;
- }
-
- need_2 = bp->seg != bp->pro_spacing.seg_2;
- if (!pro->prof_co) {
- pro->prof_co = (float *)BLI_memarena_alloc(bp->mem_arena, (bp->seg + 1) * 3 * sizeof(float));
- if (need_2) {
- pro->prof_co_2 = (float *)BLI_memarena_alloc(bp->mem_arena, (bp->pro_spacing.seg_2 + 1) * 3 *sizeof(float));
- }
- else {
- pro->prof_co_2 = pro->prof_co;
- }
- }
- r = pro->super_r;
- if (r == PRO_LINE_R) {
- map_ok = false;
- }
- else {
- map_ok = make_unit_square_map(pro->coa, pro->midco, pro->cob, m);
- }
- for (i = 0; i < 2; i++) {
- if (i == 0) {
- ns = bp->seg;
- xvals = bp->pro_spacing.xvals;
- yvals = bp->pro_spacing.yvals;
- prof_co = pro->prof_co;
- }
- else {
- if (!need_2) {
- break; /* shares coords with pro->prof_co */
- }
- ns = bp->pro_spacing.seg_2;
- xvals = bp->pro_spacing.xvals_2;
- yvals = bp->pro_spacing.yvals_2;
- prof_co = pro->prof_co_2;
- }
- BLI_assert((r == PRO_LINE_R || (xvals != NULL && yvals != NULL)) && prof_co != NULL);
- for (k = 0; k <= ns; k++) {
- if (k == 0) {
- copy_v3_v3(co, pro->coa);
- }
- else if (k == ns) {
- copy_v3_v3(co, pro->cob);
- }
- else {
- if (map_ok) {
- p[0] = xvals[k];
- p[1] = yvals[k];
- p[2] = 0.0f;
- mul_v3_m4v3(co, m, p);
- }
- else {
- interp_v3_v3v3(co, pro->coa, pro->cob, (float)k / (float)ns);
- }
- }
- /* project co onto final profile plane */
- prof_co_k = prof_co + 3 * k;
- if (!is_zero_v3(pro->proj_dir)) {
- add_v3_v3v3(co2, co, pro->proj_dir);
- if (!isect_line_plane_v3(prof_co_k, co, co2, pro->plane_co, pro->plane_no)) {
- /* shouldn't happen */
- copy_v3_v3(prof_co_k, co);
- }
- }
- else {
- copy_v3_v3(prof_co_k, co);
- }
- }
- }
+ int i, k, ns;
+ const double *xvals, *yvals;
+ float co[3], co2[3], p[3], m[4][4];
+ float *prof_co, *prof_co_k;
+ float r;
+ bool need_2, map_ok;
+ Profile *pro = &bndv->profile;
+
+ if (bp->seg == 1) {
+ return;
+ }
+
+ need_2 = bp->seg != bp->pro_spacing.seg_2;
+ if (!pro->prof_co) {
+ pro->prof_co = (float *)BLI_memarena_alloc(bp->mem_arena, (bp->seg + 1) * 3 * sizeof(float));
+ if (need_2) {
+ pro->prof_co_2 = (float *)BLI_memarena_alloc(
+ bp->mem_arena, (bp->pro_spacing.seg_2 + 1) * 3 * sizeof(float));
+ }
+ else {
+ pro->prof_co_2 = pro->prof_co;
+ }
+ }
+ r = pro->super_r;
+ if (r == PRO_LINE_R) {
+ map_ok = false;
+ }
+ else {
+ map_ok = make_unit_square_map(pro->coa, pro->midco, pro->cob, m);
+ }
+ for (i = 0; i < 2; i++) {
+ if (i == 0) {
+ ns = bp->seg;
+ xvals = bp->pro_spacing.xvals;
+ yvals = bp->pro_spacing.yvals;
+ prof_co = pro->prof_co;
+ }
+ else {
+ if (!need_2) {
+ break; /* shares coords with pro->prof_co */
+ }
+ ns = bp->pro_spacing.seg_2;
+ xvals = bp->pro_spacing.xvals_2;
+ yvals = bp->pro_spacing.yvals_2;
+ prof_co = pro->prof_co_2;
+ }
+ BLI_assert((r == PRO_LINE_R || (xvals != NULL && yvals != NULL)) && prof_co != NULL);
+ for (k = 0; k <= ns; k++) {
+ if (k == 0) {
+ copy_v3_v3(co, pro->coa);
+ }
+ else if (k == ns) {
+ copy_v3_v3(co, pro->cob);
+ }
+ else {
+ if (map_ok) {
+ p[0] = xvals[k];
+ p[1] = yvals[k];
+ p[2] = 0.0f;
+ mul_v3_m4v3(co, m, p);
+ }
+ else {
+ interp_v3_v3v3(co, pro->coa, pro->cob, (float)k / (float)ns);
+ }
+ }
+ /* project co onto final profile plane */
+ prof_co_k = prof_co + 3 * k;
+ if (!is_zero_v3(pro->proj_dir)) {
+ add_v3_v3v3(co2, co, pro->proj_dir);
+ if (!isect_line_plane_v3(prof_co_k, co, co2, pro->plane_co, pro->plane_no)) {
+ /* shouldn't happen */
+ copy_v3_v3(prof_co_k, co);
+ }
+ }
+ else {
+ copy_v3_v3(prof_co_k, co);
+ }
+ }
+ }
}
/* Snap a direction co to a superellipsoid with parameter super_r.
* For square profiles, midline says whether or not to snap to both planes. */
static void snap_to_superellipsoid(float co[3], const float super_r, bool midline)
{
- float a, b, c, x, y, z, r, rinv, dx, dy;
-
- r = super_r;
- if (r == PRO_CIRCLE_R) {
- normalize_v3(co);
- return;
- }
-
- x = a = max_ff(0.0f, co[0]);
- y = b = max_ff(0.0f, co[1]);
- z = c = max_ff(0.0f, co[2]);
- if (r == PRO_SQUARE_R || r == PRO_SQUARE_IN_R) {
- /* will only be called for 2d profile */
- BLI_assert(fabsf(z) < BEVEL_EPSILON);
- z = 0.0f;
- x = min_ff(1.0f, x);
- y = min_ff(1.0f, y);
- if (r == PRO_SQUARE_R) {
- /* snap to closer of x==1 and y==1 lines, or maybe both */
- dx = 1.0f - x;
- dy = 1.0f - y;
- if (dx < dy) {
- x = 1.0f;
- y = midline ? 1.0f : y;
- }
- else {
- y = 1.0f;
- x = midline ? 1.0f : x;
- }
- }
- else {
- /* snap to closer of x==0 and y==0 lines, or maybe both */
- if (x < y) {
- x = 0.0f;
- y = midline ? 0.0f : y;
- }
- else {
- y = 0.0f;
- x = midline ? 0.0f : x;
- }
- }
- }
- else {
- rinv = 1.0f / r;
- if (a == 0.0f) {
- if (b == 0.0f) {
- x = 0.0f;
- y = 0.0f;
- z = powf(c, rinv);
- }
- else {
- x = 0.0f;
- y = powf(1.0f / (1.0f + powf(c / b, r)), rinv);
- z = c * y / b;
- }
- }
- else {
- x = powf(1.0f / (1.0f + powf(b / a, r) + powf(c / a, r)), rinv);
- y = b * x / a;
- z = c * x / a;
- }
- }
- co[0] = x;
- co[1] = y;
- co[2] = z;
+ float a, b, c, x, y, z, r, rinv, dx, dy;
+
+ r = super_r;
+ if (r == PRO_CIRCLE_R) {
+ normalize_v3(co);
+ return;
+ }
+
+ x = a = max_ff(0.0f, co[0]);
+ y = b = max_ff(0.0f, co[1]);
+ z = c = max_ff(0.0f, co[2]);
+ if (r == PRO_SQUARE_R || r == PRO_SQUARE_IN_R) {
+ /* will only be called for 2d profile */
+ BLI_assert(fabsf(z) < BEVEL_EPSILON);
+ z = 0.0f;
+ x = min_ff(1.0f, x);
+ y = min_ff(1.0f, y);
+ if (r == PRO_SQUARE_R) {
+ /* snap to closer of x==1 and y==1 lines, or maybe both */
+ dx = 1.0f - x;
+ dy = 1.0f - y;
+ if (dx < dy) {
+ x = 1.0f;
+ y = midline ? 1.0f : y;
+ }
+ else {
+ y = 1.0f;
+ x = midline ? 1.0f : x;
+ }
+ }
+ else {
+ /* snap to closer of x==0 and y==0 lines, or maybe both */
+ if (x < y) {
+ x = 0.0f;
+ y = midline ? 0.0f : y;
+ }
+ else {
+ y = 0.0f;
+ x = midline ? 0.0f : x;
+ }
+ }
+ }
+ else {
+ rinv = 1.0f / r;
+ if (a == 0.0f) {
+ if (b == 0.0f) {
+ x = 0.0f;
+ y = 0.0f;
+ z = powf(c, rinv);
+ }
+ else {
+ x = 0.0f;
+ y = powf(1.0f / (1.0f + powf(c / b, r)), rinv);
+ z = c * y / b;
+ }
+ }
+ else {
+ x = powf(1.0f / (1.0f + powf(b / a, r) + powf(c / a, r)), rinv);
+ y = b * x / a;
+ z = c * x / a;
+ }
+ }
+ co[0] = x;
+ co[1] = y;
+ co[2] = z;
}
#define BEV_EXTEND_EDGE_DATA_CHECK(eh, flag) (BM_elem_flag_test(eh->e, flag))
static void check_edge_data_seam_sharp_edges(BevVert *bv, int flag, bool neg)
{
- EdgeHalf *e = &bv->edges[0], *efirst = &bv->edges[0];
-
- /* First first edge with seam or sharp edge data */
- while ((!neg && !BEV_EXTEND_EDGE_DATA_CHECK(e, flag)) || (neg && BEV_EXTEND_EDGE_DATA_CHECK(e, flag))) {
- e = e->next;
- if (e == efirst) {
- break;
- }
- }
-
- /* If no such edge found, return */
- if ((!neg && !BEV_EXTEND_EDGE_DATA_CHECK(e, flag)) || (neg && BEV_EXTEND_EDGE_DATA_CHECK(e, flag))) {
- return;
- }
-
- /* Set efirst to this first encountered edge. */
- efirst = e;
-
- do {
- int flag_count = 0;
- EdgeHalf *ne = e->next;
-
- while (((!neg && !BEV_EXTEND_EDGE_DATA_CHECK(ne, flag)) || (neg && BEV_EXTEND_EDGE_DATA_CHECK(ne, flag))) &&
- ne != efirst)
- {
- if (ne->is_bev) {
- flag_count++;
- }
- ne = ne->next;
- }
- if (ne == e || (ne == efirst && ((!neg && !BEV_EXTEND_EDGE_DATA_CHECK(efirst, flag)) ||
- (neg && BEV_EXTEND_EDGE_DATA_CHECK(efirst, flag)))))
- {
- break;
- }
- /* Set seam_len / sharp_len of starting edge */
- if (flag == BM_ELEM_SEAM) {
- e->rightv->seam_len = flag_count;
- }
- else if (flag == BM_ELEM_SMOOTH) {
- e->rightv->sharp_len = flag_count;
- }
- e = ne;
- } while (e != efirst);
+ EdgeHalf *e = &bv->edges[0], *efirst = &bv->edges[0];
+
+ /* First first edge with seam or sharp edge data */
+ while ((!neg && !BEV_EXTEND_EDGE_DATA_CHECK(e, flag)) ||
+ (neg && BEV_EXTEND_EDGE_DATA_CHECK(e, flag))) {
+ e = e->next;
+ if (e == efirst) {
+ break;
+ }
+ }
+
+ /* If no such edge found, return */
+ if ((!neg && !BEV_EXTEND_EDGE_DATA_CHECK(e, flag)) ||
+ (neg && BEV_EXTEND_EDGE_DATA_CHECK(e, flag))) {
+ return;
+ }
+
+ /* Set efirst to this first encountered edge. */
+ efirst = e;
+
+ do {
+ int flag_count = 0;
+ EdgeHalf *ne = e->next;
+
+ while (((!neg && !BEV_EXTEND_EDGE_DATA_CHECK(ne, flag)) ||
+ (neg && BEV_EXTEND_EDGE_DATA_CHECK(ne, flag))) &&
+ ne != efirst) {
+ if (ne->is_bev) {
+ flag_count++;
+ }
+ ne = ne->next;
+ }
+ if (ne == e || (ne == efirst && ((!neg && !BEV_EXTEND_EDGE_DATA_CHECK(efirst, flag)) ||
+ (neg && BEV_EXTEND_EDGE_DATA_CHECK(efirst, flag))))) {
+ break;
+ }
+ /* Set seam_len / sharp_len of starting edge */
+ if (flag == BM_ELEM_SEAM) {
+ e->rightv->seam_len = flag_count;
+ }
+ else if (flag == BM_ELEM_SMOOTH) {
+ e->rightv->sharp_len = flag_count;
+ }
+ e = ne;
+ } while (e != efirst);
}
static void bevel_extend_edge_data(BevVert *bv)
{
- VMesh *vm = bv->vmesh;
-
- BoundVert *bcur = bv->vmesh->boundstart, *start = bcur;
-
- do {
- /* If current boundvert has a seam length > 0 then it has a seam running along its edges */
- if (bcur->seam_len) {
- if (!bv->vmesh->boundstart->seam_len && start == bv->vmesh->boundstart) {
- start = bcur; /* set start to first boundvert with seam_len > 0 */
- }
-
- /* Now for all the mesh_verts starting at current index and ending at idxlen
- * We go through outermost ring and through all its segments and add seams
- * for those edges */
- int idxlen = bcur->index + bcur->seam_len;
- for (int i = bcur->index; i < idxlen; i++) {
- BMVert *v1 = mesh_vert(vm, i % vm->count, 0, 0)->v, *v2;
- BMEdge *e;
- for (int k = 1; k < vm->seg; k++) {
- v2 = mesh_vert(vm, i % vm->count, 0, k)->v;
-
- /* Here v1 & v2 are current and next BMverts, we find common edge and set its edge data */
- e = v1->e;
- while (e->v1 != v2 && e->v2 != v2) {
- if (e->v1 == v1) {
- e = e->v1_disk_link.next;
- }
- else {
- e = e->v2_disk_link.next;
- }
- }
- BM_elem_flag_set(e, BM_ELEM_SEAM, true);
- v1 = v2;
- }
- BMVert *v3 = mesh_vert(vm, (i + 1) % vm->count, 0, 0)->v;
- e = v1->e; //Do same as above for first and last vert
- while (e->v1 != v3 && e->v2 != v3) {
- if (e->v1 == v1) {
- e = e->v1_disk_link.next;
- }
- else {
- e = e->v2_disk_link.next;
- }
- }
- BM_elem_flag_set(e, BM_ELEM_SEAM, true);
- bcur = bcur->next;
- }
- }
- else {
- bcur = bcur->next;
- }
- } while (bcur != start);
-
-
- bcur = bv->vmesh->boundstart;
- start = bcur;
- do {
- if (bcur->sharp_len) {
- if (!bv->vmesh->boundstart->sharp_len && start == bv->vmesh->boundstart) {
- start = bcur;
- }
-
- int idxlen = bcur->index + bcur->sharp_len;
- for (int i = bcur->index; i < idxlen; i++) {
- BMVert *v1 = mesh_vert(vm, i % vm->count, 0, 0)->v, *v2;
- BMEdge *e;
- for (int k = 1; k < vm->seg; k++) {
- v2 = mesh_vert(vm, i % vm->count, 0, k)->v;
-
- e = v1->e;
- while (e->v1 != v2 && e->v2 != v2) {
- if (e->v1 == v1) {
- e = e->v1_disk_link.next;
- }
- else {
- e = e->v2_disk_link.next;
- }
- }
- BM_elem_flag_set(e, BM_ELEM_SMOOTH, false);
- v1 = v2;
- }
- BMVert *v3 = mesh_vert(vm, (i + 1) % vm->count, 0, 0)->v;
- e = v1->e;
- while (e->v1 != v3 && e->v2 != v3) {
- if (e->v1 == v1) {
- e = e->v1_disk_link.next;
- }
- else {
- e = e->v2_disk_link.next;
- }
- }
- BM_elem_flag_set(e, BM_ELEM_SMOOTH, false);
- bcur = bcur->next;
- }
- }
- else {
- bcur = bcur->next;
- }
- } while (bcur != start);
+ VMesh *vm = bv->vmesh;
+
+ BoundVert *bcur = bv->vmesh->boundstart, *start = bcur;
+
+ do {
+ /* If current boundvert has a seam length > 0 then it has a seam running along its edges */
+ if (bcur->seam_len) {
+ if (!bv->vmesh->boundstart->seam_len && start == bv->vmesh->boundstart) {
+ start = bcur; /* set start to first boundvert with seam_len > 0 */
+ }
+
+ /* Now for all the mesh_verts starting at current index and ending at idxlen
+ * We go through outermost ring and through all its segments and add seams
+ * for those edges */
+ int idxlen = bcur->index + bcur->seam_len;
+ for (int i = bcur->index; i < idxlen; i++) {
+ BMVert *v1 = mesh_vert(vm, i % vm->count, 0, 0)->v, *v2;
+ BMEdge *e;
+ for (int k = 1; k < vm->seg; k++) {
+ v2 = mesh_vert(vm, i % vm->count, 0, k)->v;
+
+ /* Here v1 & v2 are current and next BMverts, we find common edge and set its edge data */
+ e = v1->e;
+ while (e->v1 != v2 && e->v2 != v2) {
+ if (e->v1 == v1) {
+ e = e->v1_disk_link.next;
+ }
+ else {
+ e = e->v2_disk_link.next;
+ }
+ }
+ BM_elem_flag_set(e, BM_ELEM_SEAM, true);
+ v1 = v2;
+ }
+ BMVert *v3 = mesh_vert(vm, (i + 1) % vm->count, 0, 0)->v;
+ e = v1->e; //Do same as above for first and last vert
+ while (e->v1 != v3 && e->v2 != v3) {
+ if (e->v1 == v1) {
+ e = e->v1_disk_link.next;
+ }
+ else {
+ e = e->v2_disk_link.next;
+ }
+ }
+ BM_elem_flag_set(e, BM_ELEM_SEAM, true);
+ bcur = bcur->next;
+ }
+ }
+ else {
+ bcur = bcur->next;
+ }
+ } while (bcur != start);
+
+ bcur = bv->vmesh->boundstart;
+ start = bcur;
+ do {
+ if (bcur->sharp_len) {
+ if (!bv->vmesh->boundstart->sharp_len && start == bv->vmesh->boundstart) {
+ start = bcur;
+ }
+
+ int idxlen = bcur->index + bcur->sharp_len;
+ for (int i = bcur->index; i < idxlen; i++) {
+ BMVert *v1 = mesh_vert(vm, i % vm->count, 0, 0)->v, *v2;
+ BMEdge *e;
+ for (int k = 1; k < vm->seg; k++) {
+ v2 = mesh_vert(vm, i % vm->count, 0, k)->v;
+
+ e = v1->e;
+ while (e->v1 != v2 && e->v2 != v2) {
+ if (e->v1 == v1) {
+ e = e->v1_disk_link.next;
+ }
+ else {
+ e = e->v2_disk_link.next;
+ }
+ }
+ BM_elem_flag_set(e, BM_ELEM_SMOOTH, false);
+ v1 = v2;
+ }
+ BMVert *v3 = mesh_vert(vm, (i + 1) % vm->count, 0, 0)->v;
+ e = v1->e;
+ while (e->v1 != v3 && e->v2 != v3) {
+ if (e->v1 == v1) {
+ e = e->v1_disk_link.next;
+ }
+ else {
+ e = e->v2_disk_link.next;
+ }
+ }
+ BM_elem_flag_set(e, BM_ELEM_SMOOTH, false);
+ bcur = bcur->next;
+ }
+ }
+ else {
+ bcur = bcur->next;
+ }
+ } while (bcur != start);
}
/* Mark edges as sharp if they are between a smooth recon face and a new face. */
static void bevel_edges_sharp_boundary(BMesh *bm, BevelParams *bp)
{
- BMIter fiter, liter;
- BMFace *f, *fother;
- BMLoop *l, *lother;
- FKind fkind;
-
- BM_ITER_MESH(f, &fiter, bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(f, BM_ELEM_SMOOTH)) {
- continue;
- }
- if (get_face_kind(bp, f) != F_RECON) {
- continue;
- }
- BM_ITER_ELEM(l, &liter, f, BM_LOOPS_OF_FACE) {
- /* cases we care about will have exactly one adjacent face */
- lother = l->radial_next;
- fother = lother->f;
- if (lother != l && fother) {
- fkind = get_face_kind(bp, lother->f);
- if (ELEM(fkind, F_EDGE, F_VERT)) {
- BM_elem_flag_disable(l->e, BM_ELEM_SMOOTH);
- }
- }
- }
- }
+ BMIter fiter, liter;
+ BMFace *f, *fother;
+ BMLoop *l, *lother;
+ FKind fkind;
+
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(f, BM_ELEM_SMOOTH)) {
+ continue;
+ }
+ if (get_face_kind(bp, f) != F_RECON) {
+ continue;
+ }
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ /* cases we care about will have exactly one adjacent face */
+ lother = l->radial_next;
+ fother = lother->f;
+ if (lother != l && fother) {
+ fkind = get_face_kind(bp, lother->f);
+ if (ELEM(fkind, F_EDGE, F_VERT)) {
+ BM_elem_flag_disable(l->e, BM_ELEM_SMOOTH);
+ }
+ }
+ }
+ }
}
/**
@@ -1882,285 +1897,282 @@ static void bevel_edges_sharp_boundary(BMesh *bm, BevelParams *bp)
*/
static void bevel_harden_normals(BMesh *bm, BevelParams *bp)
{
- BMIter liter, fiter;
- BMFace *f;
- BMLoop *l, *lnext, *lprev, *lprevprev, *lnextnext;
- BMEdge *estep;
- FKind fkind, fprevkind, fnextkind, fprevprevkind, fnextnextkind;
- int cd_clnors_offset, l_index;
- short *clnors;
- float *pnorm, norm[3];
-
- if (bp->offset == 0.0 || !bp->harden_normals) {
- return;
- }
-
- /* recalculate all face and vertex normals; side effect: ensures vertex, edge, face indices */
- /* I suspect this is not necessary: TODO: test that guess */
- BM_mesh_normals_update(bm);
-
- cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
-
- /* If there is not already a custom split normal layer then making one (with BM_lnorspace_update)
- * will not respect the autosmooth angle between smooth faces. To get that to happen, we have
- * to mark the sharpen the edges that are only sharp because of the angle test -- otherwise would be smooth.
- */
- if (cd_clnors_offset == -1) {
- BM_edges_sharp_from_angle_set(bm, bp->smoothresh);
- bevel_edges_sharp_boundary(bm, bp);
- }
-
- /* ensure that bm->lnor_spacearr has properly stored loop normals; side effect: ensures loop indices */
- BM_lnorspace_update(bm);
-
- if (cd_clnors_offset == -1) {
- cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
- }
-
- BM_ITER_MESH(f, &fiter, bm, BM_FACES_OF_MESH) {
- fkind = get_face_kind(bp, f);
- if (fkind == F_ORIG || fkind == F_RECON) {
- continue;
- }
- BM_ITER_ELEM(l, &liter, f, BM_LOOPS_OF_FACE) {
- estep = l->prev->e; /* causes CW walk around l->v fan */
- lprev = BM_vert_step_fan_loop(l, &estep);
- estep = l->e; /* causes CCW walk around l->v fan */
- lnext = BM_vert_step_fan_loop(l, &estep);
- fprevkind = lprev ? get_face_kind(bp, lprev->f) : F_NONE;
- fnextkind = lnext ? get_face_kind(bp, lnext->f) : F_NONE;
- pnorm = NULL;
- if (fkind == F_EDGE) {
- if (fprevkind == F_EDGE && BM_elem_flag_test(l, BM_ELEM_LONG_TAG)) {
- add_v3_v3v3(norm, f->no, lprev->f->no);
- pnorm = norm;
- }
- else if (fnextkind == F_EDGE && BM_elem_flag_test(lnext, BM_ELEM_LONG_TAG)) {
- add_v3_v3v3(norm, f->no, lnext->f->no);
- pnorm = norm;
- }
- else if (fprevkind == F_RECON && BM_elem_flag_test(l, BM_ELEM_LONG_TAG)) {
- pnorm = lprev->f->no;
- }
- else if (fnextkind == F_RECON && BM_elem_flag_test(l->prev, BM_ELEM_LONG_TAG)) {
- pnorm = lnext->f->no;
- }
- else {
- /* printf("unexpected harden case (edge)\n"); */
- }
- }
- else if (fkind == F_VERT) {
- if (fprevkind == F_VERT && fnextkind == F_VERT) {
- pnorm = l->v->no;
- }
- else if (fprevkind == F_RECON) {
- pnorm = lprev->f->no;
- }
- else if (fnextkind == F_RECON) {
- pnorm = lnext->f->no;
- }
- else {
- if (lprev) {
- estep = lprev->prev->e;
- lprevprev = BM_vert_step_fan_loop(lprev, &estep);
- }
- else {
- lprevprev = NULL;
- }
- if (lnext) {
- estep = lnext->e;
- lnextnext = BM_vert_step_fan_loop(lnext, &estep);
- }
- else {
- lnextnext = NULL;
- }
- fprevprevkind = lprevprev ? get_face_kind(bp, lprevprev->f) : F_NONE;
- fnextnextkind = lnextnext ? get_face_kind(bp, lnextnext->f) : F_NONE;
- if (fprevkind == F_EDGE && fprevprevkind == F_RECON) {
- pnorm = lprevprev->f->no;
- }
- else if (fprevkind == F_EDGE && fnextkind == F_VERT && fprevprevkind == F_EDGE) {
- add_v3_v3v3(norm, lprev->f->no, lprevprev->f->no);
- pnorm = norm;
- }
- else if (fnextkind == F_EDGE && fprevkind == F_VERT && fnextnextkind == F_EDGE) {
- add_v3_v3v3(norm, lnext->f->no, lnextnext->f->no);
- pnorm = norm;
- }
- else {
- /* printf("unexpected harden case (vert)\n"); */
- }
- }
- }
- if (pnorm) {
- if (pnorm == norm) {
- normalize_v3(norm);
- }
- l_index = BM_elem_index_get(l);
- clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
- BKE_lnor_space_custom_normal_to_data(
- bm->lnor_spacearr->lspacearr[l_index], pnorm, clnors);
- }
- }
- }
+ BMIter liter, fiter;
+ BMFace *f;
+ BMLoop *l, *lnext, *lprev, *lprevprev, *lnextnext;
+ BMEdge *estep;
+ FKind fkind, fprevkind, fnextkind, fprevprevkind, fnextnextkind;
+ int cd_clnors_offset, l_index;
+ short *clnors;
+ float *pnorm, norm[3];
+
+ if (bp->offset == 0.0 || !bp->harden_normals) {
+ return;
+ }
+
+ /* recalculate all face and vertex normals; side effect: ensures vertex, edge, face indices */
+ /* I suspect this is not necessary: TODO: test that guess */
+ BM_mesh_normals_update(bm);
+
+ cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
+
+ /* If there is not already a custom split normal layer then making one (with BM_lnorspace_update)
+ * will not respect the autosmooth angle between smooth faces. To get that to happen, we have
+ * to mark the sharpen the edges that are only sharp because of the angle test -- otherwise would be smooth.
+ */
+ if (cd_clnors_offset == -1) {
+ BM_edges_sharp_from_angle_set(bm, bp->smoothresh);
+ bevel_edges_sharp_boundary(bm, bp);
+ }
+
+ /* ensure that bm->lnor_spacearr has properly stored loop normals; side effect: ensures loop indices */
+ BM_lnorspace_update(bm);
+
+ if (cd_clnors_offset == -1) {
+ cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
+ }
+
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ fkind = get_face_kind(bp, f);
+ if (fkind == F_ORIG || fkind == F_RECON) {
+ continue;
+ }
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ estep = l->prev->e; /* causes CW walk around l->v fan */
+ lprev = BM_vert_step_fan_loop(l, &estep);
+ estep = l->e; /* causes CCW walk around l->v fan */
+ lnext = BM_vert_step_fan_loop(l, &estep);
+ fprevkind = lprev ? get_face_kind(bp, lprev->f) : F_NONE;
+ fnextkind = lnext ? get_face_kind(bp, lnext->f) : F_NONE;
+ pnorm = NULL;
+ if (fkind == F_EDGE) {
+ if (fprevkind == F_EDGE && BM_elem_flag_test(l, BM_ELEM_LONG_TAG)) {
+ add_v3_v3v3(norm, f->no, lprev->f->no);
+ pnorm = norm;
+ }
+ else if (fnextkind == F_EDGE && BM_elem_flag_test(lnext, BM_ELEM_LONG_TAG)) {
+ add_v3_v3v3(norm, f->no, lnext->f->no);
+ pnorm = norm;
+ }
+ else if (fprevkind == F_RECON && BM_elem_flag_test(l, BM_ELEM_LONG_TAG)) {
+ pnorm = lprev->f->no;
+ }
+ else if (fnextkind == F_RECON && BM_elem_flag_test(l->prev, BM_ELEM_LONG_TAG)) {
+ pnorm = lnext->f->no;
+ }
+ else {
+ /* printf("unexpected harden case (edge)\n"); */
+ }
+ }
+ else if (fkind == F_VERT) {
+ if (fprevkind == F_VERT && fnextkind == F_VERT) {
+ pnorm = l->v->no;
+ }
+ else if (fprevkind == F_RECON) {
+ pnorm = lprev->f->no;
+ }
+ else if (fnextkind == F_RECON) {
+ pnorm = lnext->f->no;
+ }
+ else {
+ if (lprev) {
+ estep = lprev->prev->e;
+ lprevprev = BM_vert_step_fan_loop(lprev, &estep);
+ }
+ else {
+ lprevprev = NULL;
+ }
+ if (lnext) {
+ estep = lnext->e;
+ lnextnext = BM_vert_step_fan_loop(lnext, &estep);
+ }
+ else {
+ lnextnext = NULL;
+ }
+ fprevprevkind = lprevprev ? get_face_kind(bp, lprevprev->f) : F_NONE;
+ fnextnextkind = lnextnext ? get_face_kind(bp, lnextnext->f) : F_NONE;
+ if (fprevkind == F_EDGE && fprevprevkind == F_RECON) {
+ pnorm = lprevprev->f->no;
+ }
+ else if (fprevkind == F_EDGE && fnextkind == F_VERT && fprevprevkind == F_EDGE) {
+ add_v3_v3v3(norm, lprev->f->no, lprevprev->f->no);
+ pnorm = norm;
+ }
+ else if (fnextkind == F_EDGE && fprevkind == F_VERT && fnextnextkind == F_EDGE) {
+ add_v3_v3v3(norm, lnext->f->no, lnextnext->f->no);
+ pnorm = norm;
+ }
+ else {
+ /* printf("unexpected harden case (vert)\n"); */
+ }
+ }
+ }
+ if (pnorm) {
+ if (pnorm == norm) {
+ normalize_v3(norm);
+ }
+ l_index = BM_elem_index_get(l);
+ clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
+ BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[l_index], pnorm, clnors);
+ }
+ }
+ }
}
static void bevel_set_weighted_normal_face_strength(BMesh *bm, BevelParams *bp)
{
- BMFace *f;
- BMIter fiter;
- FKind fkind;
- int strength;
- int mode = bp->face_strength_mode;
- bool do_set_strength;
- const char *wn_layer_id = MOD_WEIGHTEDNORMALS_FACEWEIGHT_CDLAYER_ID;
- int cd_prop_int_idx = CustomData_get_named_layer_index(&bm->pdata, CD_PROP_INT, wn_layer_id);
-
- if (cd_prop_int_idx == -1) {
- BM_data_layer_add_named(bm, &bm->pdata, CD_PROP_INT, wn_layer_id);
- cd_prop_int_idx = CustomData_get_named_layer_index(&bm->pdata, CD_PROP_INT, wn_layer_id);
- }
- cd_prop_int_idx -= CustomData_get_layer_index(&bm->pdata, CD_PROP_INT);
- const int cd_prop_int_offset = CustomData_get_n_offset(&bm->pdata, CD_PROP_INT, cd_prop_int_idx);
-
- BM_ITER_MESH(f, &fiter, bm, BM_FACES_OF_MESH) {
- fkind = get_face_kind(bp, f);
- do_set_strength = true;
- switch (fkind) {
- case F_VERT:
- strength = FACE_STRENGTH_WEAK;
- do_set_strength = (mode >= BEVEL_FACE_STRENGTH_NEW);
- break;
- case F_EDGE:
- strength = FACE_STRENGTH_MEDIUM;
- do_set_strength = (mode >= BEVEL_FACE_STRENGTH_NEW);
- break;
- case F_RECON:
- strength = FACE_STRENGTH_STRONG;
- do_set_strength = (mode >= BEVEL_FACE_STRENGTH_AFFECTED);
- break;
- case F_ORIG:
- strength = FACE_STRENGTH_STRONG;
- do_set_strength = (mode == BEVEL_FACE_STRENGTH_ALL);
- break;
- default:
- do_set_strength = false;
- }
- if (do_set_strength) {
- int *strength_ptr = BM_ELEM_CD_GET_VOID_P(f, cd_prop_int_offset);
- *strength_ptr = strength;
- }
- }
+ BMFace *f;
+ BMIter fiter;
+ FKind fkind;
+ int strength;
+ int mode = bp->face_strength_mode;
+ bool do_set_strength;
+ const char *wn_layer_id = MOD_WEIGHTEDNORMALS_FACEWEIGHT_CDLAYER_ID;
+ int cd_prop_int_idx = CustomData_get_named_layer_index(&bm->pdata, CD_PROP_INT, wn_layer_id);
+
+ if (cd_prop_int_idx == -1) {
+ BM_data_layer_add_named(bm, &bm->pdata, CD_PROP_INT, wn_layer_id);
+ cd_prop_int_idx = CustomData_get_named_layer_index(&bm->pdata, CD_PROP_INT, wn_layer_id);
+ }
+ cd_prop_int_idx -= CustomData_get_layer_index(&bm->pdata, CD_PROP_INT);
+ const int cd_prop_int_offset = CustomData_get_n_offset(&bm->pdata, CD_PROP_INT, cd_prop_int_idx);
+
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ fkind = get_face_kind(bp, f);
+ do_set_strength = true;
+ switch (fkind) {
+ case F_VERT:
+ strength = FACE_STRENGTH_WEAK;
+ do_set_strength = (mode >= BEVEL_FACE_STRENGTH_NEW);
+ break;
+ case F_EDGE:
+ strength = FACE_STRENGTH_MEDIUM;
+ do_set_strength = (mode >= BEVEL_FACE_STRENGTH_NEW);
+ break;
+ case F_RECON:
+ strength = FACE_STRENGTH_STRONG;
+ do_set_strength = (mode >= BEVEL_FACE_STRENGTH_AFFECTED);
+ break;
+ case F_ORIG:
+ strength = FACE_STRENGTH_STRONG;
+ do_set_strength = (mode == BEVEL_FACE_STRENGTH_ALL);
+ break;
+ default:
+ do_set_strength = false;
+ }
+ if (do_set_strength) {
+ int *strength_ptr = BM_ELEM_CD_GET_VOID_P(f, cd_prop_int_offset);
+ *strength_ptr = strength;
+ }
+ }
}
/* Set the any_seam property for a BevVert and all its BoundVerts */
static void set_bound_vert_seams(BevVert *bv, bool mark_seam, bool mark_sharp)
{
- BoundVert *v;
- EdgeHalf *e;
-
- bv->any_seam = false;
- v = bv->vmesh->boundstart;
- do {
- v->any_seam = false;
- for (e = v->efirst; e; e = e->next) {
- v->any_seam |= e->is_seam;
- if (e == v->elast) {
- break;
- }
- }
- bv->any_seam |= v->any_seam;
- } while ((v = v->next) != bv->vmesh->boundstart);
-
- if (mark_seam) {
- check_edge_data_seam_sharp_edges(bv, BM_ELEM_SEAM, false);
- }
- if (mark_sharp) {
- check_edge_data_seam_sharp_edges(bv, BM_ELEM_SMOOTH, true);
- }
+ BoundVert *v;
+ EdgeHalf *e;
+
+ bv->any_seam = false;
+ v = bv->vmesh->boundstart;
+ do {
+ v->any_seam = false;
+ for (e = v->efirst; e; e = e->next) {
+ v->any_seam |= e->is_seam;
+ if (e == v->elast) {
+ break;
+ }
+ }
+ bv->any_seam |= v->any_seam;
+ } while ((v = v->next) != bv->vmesh->boundstart);
+
+ if (mark_seam) {
+ check_edge_data_seam_sharp_edges(bv, BM_ELEM_SEAM, false);
+ }
+ if (mark_sharp) {
+ check_edge_data_seam_sharp_edges(bv, BM_ELEM_SMOOTH, true);
+ }
}
static int count_bound_vert_seams(BevVert *bv)
{
- int ans, i;
-
- if (!bv->any_seam) {
- return 0;
- }
-
- ans = 0;
- for (i = 0; i < bv->edgecount; i++)
- if (bv->edges[i].is_seam) {
- ans++;
- }
- return ans;
+ int ans, i;
+
+ if (!bv->any_seam) {
+ return 0;
+ }
+
+ ans = 0;
+ for (i = 0; i < bv->edgecount; i++)
+ if (bv->edges[i].is_seam) {
+ ans++;
+ }
+ return ans;
}
/* Is e between two planes where angle between is 180? */
static bool eh_on_plane(EdgeHalf *e)
{
- float dot;
-
- if (e->fprev && e->fnext) {
- dot = dot_v3v3(e->fprev->no, e->fnext->no);
- if (fabsf(dot) <= BEVEL_EPSILON_BIG ||
- fabsf(dot - 1.0f) <= BEVEL_EPSILON_BIG)
- {
- return true;
- }
- }
- return false;
+ float dot;
+
+ if (e->fprev && e->fnext) {
+ dot = dot_v3v3(e->fprev->no, e->fnext->no);
+ if (fabsf(dot) <= BEVEL_EPSILON_BIG || fabsf(dot - 1.0f) <= BEVEL_EPSILON_BIG) {
+ return true;
+ }
+ }
+ return false;
}
/* Calculate the profiles for all the BoundVerts of VMesh vm */
static void calculate_vm_profiles(BevelParams *bp, BevVert *bv, VMesh *vm)
{
- BoundVert *v;
+ BoundVert *v;
- v = vm->boundstart;
- do {
- set_profile_params(bp, bv, v);
- calculate_profile(bp, v);
- } while ((v = v->next) != vm->boundstart);
+ v = vm->boundstart;
+ do {
+ set_profile_params(bp, bv, v);
+ calculate_profile(bp, v);
+ } while ((v = v->next) != vm->boundstart);
}
/* Implements build_boundary for vertex-only case */
static void build_boundary_vertex_only(BevelParams *bp, BevVert *bv, bool construct)
{
- VMesh *vm = bv->vmesh;
- EdgeHalf *efirst, *e;
- BoundVert *v;
- float co[3];
-
- BLI_assert(bp->vertex_only);
-
- e = efirst = &bv->edges[0];
- do {
- slide_dist(e, bv->v, e->offset_l, co);
- if (construct) {
- v = add_new_bound_vert(bp->mem_arena, vm, co);
- v->efirst = v->elast = e;
- e->leftv = e->rightv = v;
- }
- else {
- adjust_bound_vert(e->leftv, co);
- }
- } while ((e = e->next) != efirst);
-
- calculate_vm_profiles(bp, bv, vm);
-
- if (construct) {
- set_bound_vert_seams(bv, bp->mark_seam, bp->mark_sharp);
- if (vm->count == 2) {
- vm->mesh_kind = M_NONE;
- }
- else if (bp->seg == 1) {
- vm->mesh_kind = M_POLY;
- }
- else {
- vm->mesh_kind = M_ADJ;
- }
- }
+ VMesh *vm = bv->vmesh;
+ EdgeHalf *efirst, *e;
+ BoundVert *v;
+ float co[3];
+
+ BLI_assert(bp->vertex_only);
+
+ e = efirst = &bv->edges[0];
+ do {
+ slide_dist(e, bv->v, e->offset_l, co);
+ if (construct) {
+ v = add_new_bound_vert(bp->mem_arena, vm, co);
+ v->efirst = v->elast = e;
+ e->leftv = e->rightv = v;
+ }
+ else {
+ adjust_bound_vert(e->leftv, co);
+ }
+ } while ((e = e->next) != efirst);
+
+ calculate_vm_profiles(bp, bv, vm);
+
+ if (construct) {
+ set_bound_vert_seams(bv, bp->mark_seam, bp->mark_sharp);
+ if (vm->count == 2) {
+ vm->mesh_kind = M_NONE;
+ }
+ else if (bp->seg == 1) {
+ vm->mesh_kind = M_POLY;
+ }
+ else {
+ vm->mesh_kind = M_ADJ;
+ }
+ }
}
/**
@@ -2168,199 +2180,202 @@ static void build_boundary_vertex_only(BevelParams *bp, BevVert *bv, bool constr
* The 'width adjust' part of build_boundary has been done already,
* and \a efirst is the first beveled edge at vertex \a bv.
*/
-static void build_boundary_terminal_edge(BevelParams *bp, BevVert *bv, EdgeHalf *efirst, bool construct)
+static void build_boundary_terminal_edge(BevelParams *bp,
+ BevVert *bv,
+ EdgeHalf *efirst,
+ bool construct)
{
- MemArena *mem_arena = bp->mem_arena;
- VMesh *vm = bv->vmesh;
- BoundVert *v;
- EdgeHalf *e;
- const float *no;
- float co[3], d;
-
- e = efirst;
- if (bv->edgecount == 2) {
- /* only 2 edges in, so terminate the edge with an artificial vertex on the unbeveled edge */
- no = e->fprev ? e->fprev->no : (e->fnext ? e->fnext->no : NULL);
- offset_in_plane(e, no, true, co);
- if (construct) {
- v = add_new_bound_vert(mem_arena, vm, co);
- v->efirst = v->elast = v->ebev = e;
- e->leftv = v;
- }
- else {
- adjust_bound_vert(e->leftv, co);
- }
- no = e->fnext ? e->fnext->no : (e->fprev ? e->fprev->no : NULL);
- offset_in_plane(e, no, false, co);
- if (construct) {
- v = add_new_bound_vert(mem_arena, vm, co);
- v->efirst = v->elast = e;
- e->rightv = v;
- }
- else {
- adjust_bound_vert(e->rightv, co);
- }
- /* make artifical extra point along unbeveled edge, and form triangle */
- slide_dist(e->next, bv->v, e->offset_l, co);
- if (construct) {
- v = add_new_bound_vert(mem_arena, vm, co);
- v->efirst = v->elast = e->next;
- e->next->leftv = e->next->rightv = v;
- /* could use M_POLY too, but tri-fan looks nicer)*/
- vm->mesh_kind = M_TRI_FAN;
- set_bound_vert_seams(bv, bp->mark_seam, bp->mark_sharp);
- }
- else {
- adjust_bound_vert(e->next->leftv, co);
- }
- }
- else {
- /* More than 2 edges in. Put on-edge verts on all the other edges
- * and join with the beveled edge to make a poly or adj mesh,
- * Because e->prev has offset 0, offset_meet will put co on that edge. */
- /* TODO: should do something else if angle between e and e->prev > 180 */
- offset_meet(e->prev, e, bv->v, e->fprev, false, co);
- if (construct) {
- v = add_new_bound_vert(mem_arena, vm, co);
- v->efirst = e->prev;
- v->elast = v->ebev = e;
- e->leftv = v;
- e->prev->leftv = e->prev->rightv = v;
- }
- else {
- adjust_bound_vert(e->leftv, co);
- }
- e = e->next;
- offset_meet(e->prev, e, bv->v, e->fprev, false, co);
- if (construct) {
- v = add_new_bound_vert(mem_arena, vm, co);
- v->efirst = e->prev;
- v->elast = e;
- e->leftv = e->rightv = v;
- e->prev->rightv = v;
- }
- else {
- adjust_bound_vert(e->leftv, co);
- }
- /* For the edges not adjacent to the beveled edge, slide the bevel amount along. */
- d = efirst->offset_l_spec;
- for (e = e->next; e->next != efirst; e = e->next) {
- slide_dist(e, bv->v, d, co);
- if (construct) {
- v = add_new_bound_vert(mem_arena, vm, co);
- v->efirst = v->elast = e;
- e->leftv = e->rightv = v;
- }
- else {
- adjust_bound_vert(e->leftv, co);
- }
- }
- }
- calculate_vm_profiles(bp, bv, vm);
-
- if (bv->edgecount >= 3) {
- /* special case: snap profile to plane of adjacent two edges */
- v = vm->boundstart;
- BLI_assert(v->ebev != NULL);
- move_profile_plane(v, v->efirst, v->next->elast);
- calculate_profile(bp, v);
- }
-
- if (construct) {
- set_bound_vert_seams(bv, bp->mark_seam, bp->mark_sharp);
-
- if (vm->count == 2 && bv->edgecount == 3) {
- vm->mesh_kind = M_NONE;
- }
- else if (vm->count == 3) {
- vm->mesh_kind = M_TRI_FAN;
- }
- else {
- vm->mesh_kind = M_POLY;
- }
- }
+ MemArena *mem_arena = bp->mem_arena;
+ VMesh *vm = bv->vmesh;
+ BoundVert *v;
+ EdgeHalf *e;
+ const float *no;
+ float co[3], d;
+
+ e = efirst;
+ if (bv->edgecount == 2) {
+ /* only 2 edges in, so terminate the edge with an artificial vertex on the unbeveled edge */
+ no = e->fprev ? e->fprev->no : (e->fnext ? e->fnext->no : NULL);
+ offset_in_plane(e, no, true, co);
+ if (construct) {
+ v = add_new_bound_vert(mem_arena, vm, co);
+ v->efirst = v->elast = v->ebev = e;
+ e->leftv = v;
+ }
+ else {
+ adjust_bound_vert(e->leftv, co);
+ }
+ no = e->fnext ? e->fnext->no : (e->fprev ? e->fprev->no : NULL);
+ offset_in_plane(e, no, false, co);
+ if (construct) {
+ v = add_new_bound_vert(mem_arena, vm, co);
+ v->efirst = v->elast = e;
+ e->rightv = v;
+ }
+ else {
+ adjust_bound_vert(e->rightv, co);
+ }
+ /* make artifical extra point along unbeveled edge, and form triangle */
+ slide_dist(e->next, bv->v, e->offset_l, co);
+ if (construct) {
+ v = add_new_bound_vert(mem_arena, vm, co);
+ v->efirst = v->elast = e->next;
+ e->next->leftv = e->next->rightv = v;
+ /* could use M_POLY too, but tri-fan looks nicer)*/
+ vm->mesh_kind = M_TRI_FAN;
+ set_bound_vert_seams(bv, bp->mark_seam, bp->mark_sharp);
+ }
+ else {
+ adjust_bound_vert(e->next->leftv, co);
+ }
+ }
+ else {
+ /* More than 2 edges in. Put on-edge verts on all the other edges
+ * and join with the beveled edge to make a poly or adj mesh,
+ * Because e->prev has offset 0, offset_meet will put co on that edge. */
+ /* TODO: should do something else if angle between e and e->prev > 180 */
+ offset_meet(e->prev, e, bv->v, e->fprev, false, co);
+ if (construct) {
+ v = add_new_bound_vert(mem_arena, vm, co);
+ v->efirst = e->prev;
+ v->elast = v->ebev = e;
+ e->leftv = v;
+ e->prev->leftv = e->prev->rightv = v;
+ }
+ else {
+ adjust_bound_vert(e->leftv, co);
+ }
+ e = e->next;
+ offset_meet(e->prev, e, bv->v, e->fprev, false, co);
+ if (construct) {
+ v = add_new_bound_vert(mem_arena, vm, co);
+ v->efirst = e->prev;
+ v->elast = e;
+ e->leftv = e->rightv = v;
+ e->prev->rightv = v;
+ }
+ else {
+ adjust_bound_vert(e->leftv, co);
+ }
+ /* For the edges not adjacent to the beveled edge, slide the bevel amount along. */
+ d = efirst->offset_l_spec;
+ for (e = e->next; e->next != efirst; e = e->next) {
+ slide_dist(e, bv->v, d, co);
+ if (construct) {
+ v = add_new_bound_vert(mem_arena, vm, co);
+ v->efirst = v->elast = e;
+ e->leftv = e->rightv = v;
+ }
+ else {
+ adjust_bound_vert(e->leftv, co);
+ }
+ }
+ }
+ calculate_vm_profiles(bp, bv, vm);
+
+ if (bv->edgecount >= 3) {
+ /* special case: snap profile to plane of adjacent two edges */
+ v = vm->boundstart;
+ BLI_assert(v->ebev != NULL);
+ move_profile_plane(v, v->efirst, v->next->elast);
+ calculate_profile(bp, v);
+ }
+
+ if (construct) {
+ set_bound_vert_seams(bv, bp->mark_seam, bp->mark_sharp);
+
+ if (vm->count == 2 && bv->edgecount == 3) {
+ vm->mesh_kind = M_NONE;
+ }
+ else if (vm->count == 3) {
+ vm->mesh_kind = M_TRI_FAN;
+ }
+ else {
+ vm->mesh_kind = M_POLY;
+ }
+ }
}
/* Helper for build_boundary to handle special miters */
static void adjust_miter_coords(BevelParams *bp, BevVert *bv, EdgeHalf *emiter)
{
- float co1[3], co2[3], co3[3], edge_dir[3], line_p[3];
- BoundVert *v1, *v2, *v3, *v1prev, *v3next;
- BMVert *vother;
- EdgeHalf *emiter_other;
- int miter_outer = bp->miter_outer;
-
- v1 = emiter->rightv;
- if (miter_outer == BEVEL_MITER_PATCH) {
- v2 = v1->next;
- v3 = v2->next;
- }
- else {
- BLI_assert(miter_outer == BEVEL_MITER_ARC);
- v2 = NULL;
- v3 = v1->next;
- }
- v1prev = v1->prev;
- v3next = v3->next;
- copy_v3_v3(co2, v1->nv.co);
- if (v1->is_arc_start) {
- copy_v3_v3(v1->profile.midco, co2);
- }
-
- /* co1 is intersection of line through co2 in dir of emiter->e
- * and plane with normal the dir of emiter->e and through v1prev */
- vother = BM_edge_other_vert(emiter->e, bv->v);
- sub_v3_v3v3(edge_dir, bv->v->co, vother->co);
- normalize_v3(edge_dir);
- float d = bp->offset / (bp->seg / 2.0f); /* a fallback amount to move */
- madd_v3_v3v3fl(line_p, co2, edge_dir, d);
- if (!isect_line_plane_v3(co1, co2, line_p, v1prev->nv.co, edge_dir)) {
- copy_v3_v3(co1, line_p);
- }
- adjust_bound_vert(v1, co1);
-
- /* co3 is similar, but plane is through v3next and line is other side of miter edge */
- emiter_other = v3->elast; /*v3->efirst;*/
- vother = BM_edge_other_vert(emiter_other->e, bv->v);
- sub_v3_v3v3(edge_dir, bv->v->co, vother->co);
- normalize_v3(edge_dir);
- madd_v3_v3v3fl(line_p, co2, edge_dir, d);
- if (!isect_line_plane_v3(co3, co2, line_p, v3next->nv.co, edge_dir)) {
- copy_v3_v3(co1, line_p);
- }
- adjust_bound_vert(v3, co3);
+ float co1[3], co2[3], co3[3], edge_dir[3], line_p[3];
+ BoundVert *v1, *v2, *v3, *v1prev, *v3next;
+ BMVert *vother;
+ EdgeHalf *emiter_other;
+ int miter_outer = bp->miter_outer;
+
+ v1 = emiter->rightv;
+ if (miter_outer == BEVEL_MITER_PATCH) {
+ v2 = v1->next;
+ v3 = v2->next;
+ }
+ else {
+ BLI_assert(miter_outer == BEVEL_MITER_ARC);
+ v2 = NULL;
+ v3 = v1->next;
+ }
+ v1prev = v1->prev;
+ v3next = v3->next;
+ copy_v3_v3(co2, v1->nv.co);
+ if (v1->is_arc_start) {
+ copy_v3_v3(v1->profile.midco, co2);
+ }
+
+ /* co1 is intersection of line through co2 in dir of emiter->e
+ * and plane with normal the dir of emiter->e and through v1prev */
+ vother = BM_edge_other_vert(emiter->e, bv->v);
+ sub_v3_v3v3(edge_dir, bv->v->co, vother->co);
+ normalize_v3(edge_dir);
+ float d = bp->offset / (bp->seg / 2.0f); /* a fallback amount to move */
+ madd_v3_v3v3fl(line_p, co2, edge_dir, d);
+ if (!isect_line_plane_v3(co1, co2, line_p, v1prev->nv.co, edge_dir)) {
+ copy_v3_v3(co1, line_p);
+ }
+ adjust_bound_vert(v1, co1);
+
+ /* co3 is similar, but plane is through v3next and line is other side of miter edge */
+ emiter_other = v3->elast; /*v3->efirst;*/
+ vother = BM_edge_other_vert(emiter_other->e, bv->v);
+ sub_v3_v3v3(edge_dir, bv->v->co, vother->co);
+ normalize_v3(edge_dir);
+ madd_v3_v3v3fl(line_p, co2, edge_dir, d);
+ if (!isect_line_plane_v3(co3, co2, line_p, v3next->nv.co, edge_dir)) {
+ copy_v3_v3(co1, line_p);
+ }
+ adjust_bound_vert(v3, co3);
}
static void adjust_miter_inner_coords(BevelParams *bp, BevVert *bv, EdgeHalf *emiter)
{
- BoundVert *v, *vstart, *v3;
- EdgeHalf *e;
- BMVert *vother;
- float edge_dir[3], co[3];
-
- v = vstart = bv->vmesh->boundstart;
- do {
- if (v->is_arc_start) {
- v3 = v->next;
- e = v->efirst;
- if (e != emiter) {
- copy_v3_v3(co, v->nv.co);
- vother = BM_edge_other_vert(e->e, bv->v);
- sub_v3_v3v3(edge_dir, vother->co, bv->v->co);
- normalize_v3(edge_dir);
- madd_v3_v3v3fl(v->nv.co, co, edge_dir, bp->spread);
- e = v3->elast;
- vother = BM_edge_other_vert(e->e, bv->v);
- sub_v3_v3v3(edge_dir, vother->co, bv->v->co);
- normalize_v3(edge_dir);
- madd_v3_v3v3fl(v3->nv.co, co, edge_dir, bp->spread);
- }
- v = v3->next;
- }
- else {
- v = v->next;
- }
- } while (v != vstart);
+ BoundVert *v, *vstart, *v3;
+ EdgeHalf *e;
+ BMVert *vother;
+ float edge_dir[3], co[3];
+
+ v = vstart = bv->vmesh->boundstart;
+ do {
+ if (v->is_arc_start) {
+ v3 = v->next;
+ e = v->efirst;
+ if (e != emiter) {
+ copy_v3_v3(co, v->nv.co);
+ vother = BM_edge_other_vert(e->e, bv->v);
+ sub_v3_v3v3(edge_dir, vother->co, bv->v->co);
+ normalize_v3(edge_dir);
+ madd_v3_v3v3fl(v->nv.co, co, edge_dir, bp->spread);
+ e = v3->elast;
+ vother = BM_edge_other_vert(e->e, bv->v);
+ sub_v3_v3v3(edge_dir, vother->co, bv->v->co);
+ normalize_v3(edge_dir);
+ madd_v3_v3v3fl(v3->nv.co, co, edge_dir, bp->spread);
+ }
+ v = v3->next;
+ }
+ else {
+ v = v->next;
+ }
+ } while (v != vstart);
}
/* Make a circular list of BoundVerts for bv, each of which has the coordinates
@@ -2377,319 +2392,329 @@ static void adjust_miter_inner_coords(BevelParams *bp, BevVert *bv, EdgeHalf *em
* Doesn't make the actual BMVerts */
static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
{
- MemArena *mem_arena = bp->mem_arena;
- EdgeHalf *efirst, *e, *e2, *e3, *enip, *eip, *eon, *emiter;
- BoundVert *v, *v1, *v2, *v3;
- VMesh *vm;
- float co[3], r;
- int nip, nnip, miter_outer, miter_inner;
- int ang_kind;
-
- /* Current bevel does nothing if only one edge into a vertex */
- if (bv->edgecount <= 1) {
- return;
- }
-
- if (bp->vertex_only) {
- build_boundary_vertex_only(bp, bv, construct);
- return;
- }
-
- vm = bv->vmesh;
-
- /* Find a beveled edge to be efirst */
- e = efirst = next_bev(bv, NULL);
- BLI_assert(e->is_bev);
-
- if (bv->selcount == 1) {
- /* special case: only one beveled edge in */
- build_boundary_terminal_edge(bp, bv, efirst, construct);
- return;
- }
-
- /* Special miters outside only for 3 or more beveled edges */
- miter_outer = (bv->selcount >= 3) ? bp->miter_outer : BEVEL_MITER_SHARP;
- miter_inner = bp->miter_inner;
-
- /* keep track of the first beveled edge of an outside miter (there can be at most 1 per bv */
- emiter = NULL;
-
- /* Here: there is more than one beveled edge.
- * We make BoundVerts to connect the sides of the beveled edges.
- * Non-beveled edges in between will just join to the appropriate juncture point. */
- e = efirst;
- do {
- BLI_assert(e->is_bev);
- eon = NULL;
- /* Make the BoundVert for the right side of e; other side will be made
- * when the beveled edge to the left of e is handled.
- * Analyze edges until next beveled edge.
- * They are either "in plane" (preceding and subsequent faces are coplanar)
- * or not. The "non-in-plane" edges effect silhouette and we prefer to slide
- * along one of those if possible. */
- nip = nnip = 0; /* counts of in-plane / not-in-plane */
- enip = eip = NULL; /* representatives of each */
- for (e2 = e->next; !e2->is_bev; e2 = e2->next) {
- if (eh_on_plane(e2)) {
- nip++;
- eip = e2;
- }
- else {
- nnip++;
- enip = e2;
- }
- }
- if (nip == 0 && nnip == 0) {
- offset_meet(e, e2, bv->v, e->fnext, false, co);
- }
- else if (nnip > 0) {
- if (bp->loop_slide && nnip == 1 && good_offset_on_edge_between(e, e2, enip, bv->v)) {
- if (offset_on_edge_between(e, e2, enip, bv->v, co, &r)) {
- eon = enip;
- }
- }
- else {
- offset_meet(e, e2, bv->v, NULL, true, co);
- }
- }
- else {
- /* nip > 0 and nnip == 0 */
- if (bp->loop_slide && nip == 1 && good_offset_on_edge_between(e, e2, eip, bv->v)) {
- if (offset_on_edge_between(e, e2, eip, bv->v, co, &r)) {
- eon = eip;
- }
- }
- else {
- offset_meet(e, e2, bv->v, e->fnext, true, co);
- }
- }
- if (construct) {
- v = add_new_bound_vert(mem_arena, vm, co);
- v->efirst = e;
- v->elast = e2;
- v->ebev = e2;
- v->eon = eon;
- if (eon) {
- v->sinratio = r;
- }
- e->rightv = v;
- e2->leftv = v;
- for (e3 = e->next; e3 != e2; e3 = e3->next) {
- e3->leftv = e3->rightv = v;
- }
- ang_kind = edges_angle_kind(e, e2, bv->v);
-
- /* Are we doing special mitering?
- * ang_kind is -1, 0, 1 as angle is <, =, > 180 degrees.
- * There can only be one outer reflex angle, so only one outer miter,
- * and emiter will be set to the first edge of such an edge.
- * A miter kind of BEVEL_MITER_SHARP means no special miter */
-
- if ((miter_outer != BEVEL_MITER_SHARP && !emiter && ang_kind == 1) ||
- (miter_inner != BEVEL_MITER_SHARP && ang_kind == -1))
- {
- if (ang_kind == 1) {
- emiter = e;
- }
- /* make one or two more boundverts; for now all will have same co */
- v1 = v;
- v1->ebev = NULL;
- if (ang_kind == 1 && miter_outer == BEVEL_MITER_PATCH) {
- v2 = add_new_bound_vert(mem_arena, vm, co);
- }
- else {
- v2 = NULL;
- }
- v3 = add_new_bound_vert(mem_arena, vm, co);
- v3->ebev = e2;
- v3->efirst = e2;
- v3->elast = e2;
- v3->eon = NULL;
- e2->leftv = v3;
- if (ang_kind == 1 && miter_outer == BEVEL_MITER_PATCH) {
- v1->is_patch_start = true;
- v2->eon = v1->eon;
- v2->sinratio = v1->sinratio;
- v2->ebev = NULL;
- v1->eon = NULL;
- v1->sinratio = 1.0f;
- v1->elast = e;
- if (e->next == e2) {
- v2->efirst = NULL;
- v2->elast = NULL;
- }
- else {
- v2->efirst = e->next;
- for (e3 = e->next; e3 != e2; e3 = e3->next) {
- e3->leftv = e3->rightv = v2;
- v2->elast = e3;
- }
- }
- }
- else {
- v1->is_arc_start = true;
- copy_v3_v3(v1->profile.midco, co);
- if (e->next == e2) {
- v1->elast = v1->efirst;
- }
- else {
- int between = nip + nnip;
- int bet2 = between / 2;
- bool betodd = (between % 2) == 1;
- int i = 0;
- /* Put first half of in-between edges at index 0,
- * second half at index bp->seg.
- * If between is odd, put middle one at midindex */
- for (e3 = e->next; e3 != e2; e3 = e3->next) {
- v1->elast = e3;
- if (i < bet2) {
- e3->profile_index = 0;
- }
- else if (betodd && i == bet2) {
- e3->profile_index = bp->seg / 2;
- }
- else {
- e3->profile_index = bp->seg;
- }
- i++;
- }
- }
- }
- }
- }
- else {
- ang_kind = edges_angle_kind(e, e2, bv->v);
- if ((miter_outer != BEVEL_MITER_SHARP && !emiter && ang_kind == 1) ||
- (miter_inner != BEVEL_MITER_SHARP && ang_kind == -1))
- {
- if (ang_kind == 1) {
- emiter = e;
- }
- v1 = e->rightv;
- if (ang_kind == 1 && miter_outer == BEVEL_MITER_PATCH) {
- v2 = v1->next;
- v3 = v2->next;
- }
- else {
- v2 = NULL;
- v3 = v1->next;
- }
- adjust_bound_vert(v1, co);
- if (v2) {
- adjust_bound_vert(v2, co);
- }
- adjust_bound_vert(v3, co);
- }
- else {
- adjust_bound_vert(e->rightv, co);
- }
- }
- e = e2;
- } while (e != efirst);
-
- if (miter_inner != BEVEL_MITER_SHARP) {
- adjust_miter_inner_coords(bp, bv, emiter);
- }
- if (emiter) {
- adjust_miter_coords(bp, bv, emiter);
- }
-
- calculate_vm_profiles(bp, bv, vm);
-
- if (construct) {
- set_bound_vert_seams(bv, bp->mark_seam, bp->mark_sharp);
-
- if (vm->count == 2) {
- vm->mesh_kind = M_NONE;
- }
- else if (efirst->seg == 1) {
- vm->mesh_kind = M_POLY;
- }
- else {
- vm->mesh_kind = M_ADJ;
- }
- }
+ MemArena *mem_arena = bp->mem_arena;
+ EdgeHalf *efirst, *e, *e2, *e3, *enip, *eip, *eon, *emiter;
+ BoundVert *v, *v1, *v2, *v3;
+ VMesh *vm;
+ float co[3], r;
+ int nip, nnip, miter_outer, miter_inner;
+ int ang_kind;
+
+ /* Current bevel does nothing if only one edge into a vertex */
+ if (bv->edgecount <= 1) {
+ return;
+ }
+
+ if (bp->vertex_only) {
+ build_boundary_vertex_only(bp, bv, construct);
+ return;
+ }
+
+ vm = bv->vmesh;
+
+ /* Find a beveled edge to be efirst */
+ e = efirst = next_bev(bv, NULL);
+ BLI_assert(e->is_bev);
+
+ if (bv->selcount == 1) {
+ /* special case: only one beveled edge in */
+ build_boundary_terminal_edge(bp, bv, efirst, construct);
+ return;
+ }
+
+ /* Special miters outside only for 3 or more beveled edges */
+ miter_outer = (bv->selcount >= 3) ? bp->miter_outer : BEVEL_MITER_SHARP;
+ miter_inner = bp->miter_inner;
+
+ /* keep track of the first beveled edge of an outside miter (there can be at most 1 per bv */
+ emiter = NULL;
+
+ /* Here: there is more than one beveled edge.
+ * We make BoundVerts to connect the sides of the beveled edges.
+ * Non-beveled edges in between will just join to the appropriate juncture point. */
+ e = efirst;
+ do {
+ BLI_assert(e->is_bev);
+ eon = NULL;
+ /* Make the BoundVert for the right side of e; other side will be made
+ * when the beveled edge to the left of e is handled.
+ * Analyze edges until next beveled edge.
+ * They are either "in plane" (preceding and subsequent faces are coplanar)
+ * or not. The "non-in-plane" edges effect silhouette and we prefer to slide
+ * along one of those if possible. */
+ nip = nnip = 0; /* counts of in-plane / not-in-plane */
+ enip = eip = NULL; /* representatives of each */
+ for (e2 = e->next; !e2->is_bev; e2 = e2->next) {
+ if (eh_on_plane(e2)) {
+ nip++;
+ eip = e2;
+ }
+ else {
+ nnip++;
+ enip = e2;
+ }
+ }
+ if (nip == 0 && nnip == 0) {
+ offset_meet(e, e2, bv->v, e->fnext, false, co);
+ }
+ else if (nnip > 0) {
+ if (bp->loop_slide && nnip == 1 && good_offset_on_edge_between(e, e2, enip, bv->v)) {
+ if (offset_on_edge_between(e, e2, enip, bv->v, co, &r)) {
+ eon = enip;
+ }
+ }
+ else {
+ offset_meet(e, e2, bv->v, NULL, true, co);
+ }
+ }
+ else {
+ /* nip > 0 and nnip == 0 */
+ if (bp->loop_slide && nip == 1 && good_offset_on_edge_between(e, e2, eip, bv->v)) {
+ if (offset_on_edge_between(e, e2, eip, bv->v, co, &r)) {
+ eon = eip;
+ }
+ }
+ else {
+ offset_meet(e, e2, bv->v, e->fnext, true, co);
+ }
+ }
+ if (construct) {
+ v = add_new_bound_vert(mem_arena, vm, co);
+ v->efirst = e;
+ v->elast = e2;
+ v->ebev = e2;
+ v->eon = eon;
+ if (eon) {
+ v->sinratio = r;
+ }
+ e->rightv = v;
+ e2->leftv = v;
+ for (e3 = e->next; e3 != e2; e3 = e3->next) {
+ e3->leftv = e3->rightv = v;
+ }
+ ang_kind = edges_angle_kind(e, e2, bv->v);
+
+ /* Are we doing special mitering?
+ * ang_kind is -1, 0, 1 as angle is <, =, > 180 degrees.
+ * There can only be one outer reflex angle, so only one outer miter,
+ * and emiter will be set to the first edge of such an edge.
+ * A miter kind of BEVEL_MITER_SHARP means no special miter */
+
+ if ((miter_outer != BEVEL_MITER_SHARP && !emiter && ang_kind == 1) ||
+ (miter_inner != BEVEL_MITER_SHARP && ang_kind == -1)) {
+ if (ang_kind == 1) {
+ emiter = e;
+ }
+ /* make one or two more boundverts; for now all will have same co */
+ v1 = v;
+ v1->ebev = NULL;
+ if (ang_kind == 1 && miter_outer == BEVEL_MITER_PATCH) {
+ v2 = add_new_bound_vert(mem_arena, vm, co);
+ }
+ else {
+ v2 = NULL;
+ }
+ v3 = add_new_bound_vert(mem_arena, vm, co);
+ v3->ebev = e2;
+ v3->efirst = e2;
+ v3->elast = e2;
+ v3->eon = NULL;
+ e2->leftv = v3;
+ if (ang_kind == 1 && miter_outer == BEVEL_MITER_PATCH) {
+ v1->is_patch_start = true;
+ v2->eon = v1->eon;
+ v2->sinratio = v1->sinratio;
+ v2->ebev = NULL;
+ v1->eon = NULL;
+ v1->sinratio = 1.0f;
+ v1->elast = e;
+ if (e->next == e2) {
+ v2->efirst = NULL;
+ v2->elast = NULL;
+ }
+ else {
+ v2->efirst = e->next;
+ for (e3 = e->next; e3 != e2; e3 = e3->next) {
+ e3->leftv = e3->rightv = v2;
+ v2->elast = e3;
+ }
+ }
+ }
+ else {
+ v1->is_arc_start = true;
+ copy_v3_v3(v1->profile.midco, co);
+ if (e->next == e2) {
+ v1->elast = v1->efirst;
+ }
+ else {
+ int between = nip + nnip;
+ int bet2 = between / 2;
+ bool betodd = (between % 2) == 1;
+ int i = 0;
+ /* Put first half of in-between edges at index 0,
+ * second half at index bp->seg.
+ * If between is odd, put middle one at midindex */
+ for (e3 = e->next; e3 != e2; e3 = e3->next) {
+ v1->elast = e3;
+ if (i < bet2) {
+ e3->profile_index = 0;
+ }
+ else if (betodd && i == bet2) {
+ e3->profile_index = bp->seg / 2;
+ }
+ else {
+ e3->profile_index = bp->seg;
+ }
+ i++;
+ }
+ }
+ }
+ }
+ }
+ else {
+ ang_kind = edges_angle_kind(e, e2, bv->v);
+ if ((miter_outer != BEVEL_MITER_SHARP && !emiter && ang_kind == 1) ||
+ (miter_inner != BEVEL_MITER_SHARP && ang_kind == -1)) {
+ if (ang_kind == 1) {
+ emiter = e;
+ }
+ v1 = e->rightv;
+ if (ang_kind == 1 && miter_outer == BEVEL_MITER_PATCH) {
+ v2 = v1->next;
+ v3 = v2->next;
+ }
+ else {
+ v2 = NULL;
+ v3 = v1->next;
+ }
+ adjust_bound_vert(v1, co);
+ if (v2) {
+ adjust_bound_vert(v2, co);
+ }
+ adjust_bound_vert(v3, co);
+ }
+ else {
+ adjust_bound_vert(e->rightv, co);
+ }
+ }
+ e = e2;
+ } while (e != efirst);
+
+ if (miter_inner != BEVEL_MITER_SHARP) {
+ adjust_miter_inner_coords(bp, bv, emiter);
+ }
+ if (emiter) {
+ adjust_miter_coords(bp, bv, emiter);
+ }
+
+ calculate_vm_profiles(bp, bv, vm);
+
+ if (construct) {
+ set_bound_vert_seams(bv, bp->mark_seam, bp->mark_sharp);
+
+ if (vm->count == 2) {
+ vm->mesh_kind = M_NONE;
+ }
+ else if (efirst->seg == 1) {
+ vm->mesh_kind = M_POLY;
+ }
+ else {
+ vm->mesh_kind = M_ADJ;
+ }
+ }
}
#ifdef DEBUG_ADJUST
static void print_adjust_stats(BoundVert *vstart)
{
- BoundVert *v;
- EdgeHalf *eleft, *eright;
- double even_residual2, spec_residual2;
- double max_even_r, max_even_r_pct;
- double max_spec_r, max_spec_r_pct;
- double delta, delta_pct;
-
- printf("\nSolution analysis\n");
- even_residual2 = 0.0;
- spec_residual2 = 0.0;
- max_even_r = 0.0;
- max_even_r_pct = 0.0;
- max_spec_r = 0.0;
- max_spec_r_pct = 0.0;
- printf("width matching\n");
- v = vstart;
- do {
- if (v->adjchain != NULL) {
- eright = v->efirst;
- eleft = v->adjchain->elast;
- delta = fabs(eright->offset_r - eleft->offset_l);
- delta_pct = 100.0 * delta / eright->offset_r_spec;
- printf("e%d r(%f) vs l(%f): abs(delta)=%f, delta_pct=%f\n",
- BM_elem_index_get(eright->e), eright->offset_r, eleft->offset_l, delta, delta_pct);
- even_residual2 += delta * delta;
- if (delta > max_even_r) {
- max_even_r = delta;
- }
- if (delta_pct > max_even_r_pct) {
- max_even_r_pct = delta_pct;
- }
- }
- v = v->adjchain;
- } while (v && v != vstart);
-
- printf("spec matching\n");
- v = vstart;
- do {
- if (v->adjchain != NULL) {
- eright = v->efirst;
- eleft = v->adjchain->elast;
- delta = eright->offset_r - eright->offset_r_spec;
- delta_pct = 100.0 * delta / eright->offset_r_spec;
- printf("e%d r(%f) vs r spec(%f): delta=%f, delta_pct=%f\n",
- BM_elem_index_get(eright->e), eright->offset_r, eright->offset_r_spec, delta, delta_pct);
- spec_residual2 += delta * delta;
- delta = fabs(delta);
- delta_pct = fabs(delta_pct);
- if (delta > max_spec_r) {
- max_spec_r = delta;
- }
- if (delta_pct > max_spec_r_pct) {
- max_spec_r_pct = delta_pct;
- }
-
- delta = eleft->offset_l - eleft->offset_l_spec;
- delta_pct = 100.0 * delta / eright->offset_l_spec;
- printf("e%d l(%f) vs l spec(%f): delta=%f, delta_pct=%f\n",
- BM_elem_index_get(eright->e), eleft->offset_l, eleft->offset_l_spec, delta, delta_pct);
- spec_residual2 += delta * delta;
- delta = fabs(delta);
- delta_pct = fabs(delta_pct);
- if (delta > max_spec_r) {
- max_spec_r = delta;
- }
- if (delta_pct > max_spec_r_pct) {
- max_spec_r_pct = delta_pct;
- }
- }
- v = v->adjchain;
- } while (v && v != vstart);
-
- printf("Analysis Result:\n");
- printf("even residual2 = %f, spec residual2 = %f\n", even_residual2, spec_residual2);
- printf("max even delta = %f, max as percent of spec = %f\n", max_even_r, max_even_r_pct);
- printf("max spec delta = %f, max as percent of spec = %f\n", max_spec_r, max_spec_r_pct);
+ BoundVert *v;
+ EdgeHalf *eleft, *eright;
+ double even_residual2, spec_residual2;
+ double max_even_r, max_even_r_pct;
+ double max_spec_r, max_spec_r_pct;
+ double delta, delta_pct;
+
+ printf("\nSolution analysis\n");
+ even_residual2 = 0.0;
+ spec_residual2 = 0.0;
+ max_even_r = 0.0;
+ max_even_r_pct = 0.0;
+ max_spec_r = 0.0;
+ max_spec_r_pct = 0.0;
+ printf("width matching\n");
+ v = vstart;
+ do {
+ if (v->adjchain != NULL) {
+ eright = v->efirst;
+ eleft = v->adjchain->elast;
+ delta = fabs(eright->offset_r - eleft->offset_l);
+ delta_pct = 100.0 * delta / eright->offset_r_spec;
+ printf("e%d r(%f) vs l(%f): abs(delta)=%f, delta_pct=%f\n",
+ BM_elem_index_get(eright->e),
+ eright->offset_r,
+ eleft->offset_l,
+ delta,
+ delta_pct);
+ even_residual2 += delta * delta;
+ if (delta > max_even_r) {
+ max_even_r = delta;
+ }
+ if (delta_pct > max_even_r_pct) {
+ max_even_r_pct = delta_pct;
+ }
+ }
+ v = v->adjchain;
+ } while (v && v != vstart);
+
+ printf("spec matching\n");
+ v = vstart;
+ do {
+ if (v->adjchain != NULL) {
+ eright = v->efirst;
+ eleft = v->adjchain->elast;
+ delta = eright->offset_r - eright->offset_r_spec;
+ delta_pct = 100.0 * delta / eright->offset_r_spec;
+ printf("e%d r(%f) vs r spec(%f): delta=%f, delta_pct=%f\n",
+ BM_elem_index_get(eright->e),
+ eright->offset_r,
+ eright->offset_r_spec,
+ delta,
+ delta_pct);
+ spec_residual2 += delta * delta;
+ delta = fabs(delta);
+ delta_pct = fabs(delta_pct);
+ if (delta > max_spec_r) {
+ max_spec_r = delta;
+ }
+ if (delta_pct > max_spec_r_pct) {
+ max_spec_r_pct = delta_pct;
+ }
+
+ delta = eleft->offset_l - eleft->offset_l_spec;
+ delta_pct = 100.0 * delta / eright->offset_l_spec;
+ printf("e%d l(%f) vs l spec(%f): delta=%f, delta_pct=%f\n",
+ BM_elem_index_get(eright->e),
+ eleft->offset_l,
+ eleft->offset_l_spec,
+ delta,
+ delta_pct);
+ spec_residual2 += delta * delta;
+ delta = fabs(delta);
+ delta_pct = fabs(delta_pct);
+ if (delta > max_spec_r) {
+ max_spec_r = delta;
+ }
+ if (delta_pct > max_spec_r_pct) {
+ max_spec_r_pct = delta_pct;
+ }
+ }
+ v = v->adjchain;
+ } while (v && v != vstart);
+
+ printf("Analysis Result:\n");
+ printf("even residual2 = %f, spec residual2 = %f\n", even_residual2, spec_residual2);
+ printf("max even delta = %f, max as percent of spec = %f\n", max_even_r, max_even_r_pct);
+ printf("max spec delta = %f, max as percent of spec = %f\n", max_spec_r, max_spec_r_pct);
}
#endif
@@ -2704,79 +2729,79 @@ static void print_adjust_stats(BoundVert *vstart)
* But keep it here for a while in case performance issues demand that it be used sometimes. */
static bool adjust_the_cycle_or_chain_fast(BoundVert *vstart, int np, bool iscycle)
{
- BoundVert *v;
- EdgeHalf *eleft, *eright;
- float *g;
- float *g_prod;
- float gprod, gprod_sum, spec_sum, p;
- int i;
-
- g = MEM_mallocN(np * sizeof(float), "beveladjust");
- g_prod = MEM_mallocN(np * sizeof(float), "beveladjust");
-
- v = vstart;
- spec_sum = 0.0f;
- i = 0;
- do {
- g[i] = v->sinratio;
- if (iscycle || v->adjchain != NULL) {
- spec_sum += v->efirst->offset_r;
- }
- else {
- spec_sum += v->elast->offset_l;
- }
- i++;
- v = v->adjchain;
- } while (v && v != vstart);
-
- gprod = 1.00f;
- gprod_sum = 1.0f;
- for (i = np - 1; i > 0; i--) {
- gprod *= g[i];
- g_prod[i] = gprod;
- gprod_sum += gprod;
- }
- g_prod[0] = 1.0f;
- if (iscycle) {
- gprod *= g[0];
- if (fabs(gprod - 1.0f) > BEVEL_EPSILON) {
- /* fast cycle calc only works if total product is 1 */
- MEM_freeN(g);
- MEM_freeN(g_prod);
- return false;
- }
- }
- if (gprod_sum == 0.0f) {
- MEM_freeN(g);
- MEM_freeN(g_prod);
- return false;
- }
- p = spec_sum / gprod_sum;
-
- /* apply the new offsets */
- v = vstart;
- i = 0;
- do {
- if (iscycle || v->adjchain != NULL) {
- eright = v->efirst;
- eleft = v->elast;
- eright->offset_r = g_prod[(i + 1) % np] * p;
- if (iscycle || v != vstart) {
- eleft->offset_l = v->sinratio * eright->offset_r;
- }
- }
- else {
- /* not a cycle, and last of chain */
- eleft = v->elast;
- eleft->offset_l = p;
- }
- i++;
- v = v->adjchain;
- } while (v && v != vstart);
-
- MEM_freeN(g);
- MEM_freeN(g_prod);
- return true;
+ BoundVert *v;
+ EdgeHalf *eleft, *eright;
+ float *g;
+ float *g_prod;
+ float gprod, gprod_sum, spec_sum, p;
+ int i;
+
+ g = MEM_mallocN(np * sizeof(float), "beveladjust");
+ g_prod = MEM_mallocN(np * sizeof(float), "beveladjust");
+
+ v = vstart;
+ spec_sum = 0.0f;
+ i = 0;
+ do {
+ g[i] = v->sinratio;
+ if (iscycle || v->adjchain != NULL) {
+ spec_sum += v->efirst->offset_r;
+ }
+ else {
+ spec_sum += v->elast->offset_l;
+ }
+ i++;
+ v = v->adjchain;
+ } while (v && v != vstart);
+
+ gprod = 1.00f;
+ gprod_sum = 1.0f;
+ for (i = np - 1; i > 0; i--) {
+ gprod *= g[i];
+ g_prod[i] = gprod;
+ gprod_sum += gprod;
+ }
+ g_prod[0] = 1.0f;
+ if (iscycle) {
+ gprod *= g[0];
+ if (fabs(gprod - 1.0f) > BEVEL_EPSILON) {
+ /* fast cycle calc only works if total product is 1 */
+ MEM_freeN(g);
+ MEM_freeN(g_prod);
+ return false;
+ }
+ }
+ if (gprod_sum == 0.0f) {
+ MEM_freeN(g);
+ MEM_freeN(g_prod);
+ return false;
+ }
+ p = spec_sum / gprod_sum;
+
+ /* apply the new offsets */
+ v = vstart;
+ i = 0;
+ do {
+ if (iscycle || v->adjchain != NULL) {
+ eright = v->efirst;
+ eleft = v->elast;
+ eright->offset_r = g_prod[(i + 1) % np] * p;
+ if (iscycle || v != vstart) {
+ eleft->offset_l = v->sinratio * eright->offset_r;
+ }
+ }
+ else {
+ /* not a cycle, and last of chain */
+ eleft = v->elast;
+ eleft->offset_l = p;
+ }
+ i++;
+ v = v->adjchain;
+ } while (v && v != vstart);
+
+ MEM_freeN(g);
+ MEM_freeN(g_prod);
+ return true;
}
#endif
@@ -2789,146 +2814,157 @@ static bool adjust_the_cycle_or_chain_fast(BoundVert *vstart, int np, bool iscyc
*/
static void adjust_the_cycle_or_chain(BoundVert *vstart, bool iscycle)
{
- BoundVert *v;
- EdgeHalf *eleft, *eright, *enextleft;
- LinearSolver *solver;
- double weight, val;
- int i, np, nrows, row;
+ BoundVert *v;
+ EdgeHalf *eleft, *eright, *enextleft;
+ LinearSolver *solver;
+ double weight, val;
+ int i, np, nrows, row;
- np = 0;
+ np = 0;
#ifdef DEBUG_ADJUST
- printf("\nadjust the %s (with eigen)\n", iscycle ? "cycle" : "chain");
+ printf("\nadjust the %s (with eigen)\n", iscycle ? "cycle" : "chain");
#endif
- v = vstart;
- do {
+ v = vstart;
+ do {
#ifdef DEBUG_ADJUST
- eleft = v->elast;
- eright = v->efirst;
- printf(" (left=e%d, right=e%d)", BM_elem_index_get(eleft->e), BM_elem_index_get(eright->e));
+ eleft = v->elast;
+ eright = v->efirst;
+ printf(" (left=e%d, right=e%d)", BM_elem_index_get(eleft->e), BM_elem_index_get(eright->e));
#endif
- np++;
- v = v->adjchain;
- } while (v && v != vstart);
+ np++;
+ v = v->adjchain;
+ } while (v && v != vstart);
#ifdef DEBUG_ADJUST
- printf(" -> %d parms\n", np);
+ printf(" -> %d parms\n", np);
#endif
#ifdef FAST_ADJUST_CODE
- if (adjust_the_cycle_or_chain_fast(vstart, np, iscycle)) {
- return;
- }
+ if (adjust_the_cycle_or_chain_fast(vstart, np, iscycle)) {
+ return;
+ }
#endif
- nrows = iscycle ? 3 * np : 3 * np - 3;
+ nrows = iscycle ? 3 * np : 3 * np - 3;
- solver = EIG_linear_least_squares_solver_new(nrows, np, 1);
+ solver = EIG_linear_least_squares_solver_new(nrows, np, 1);
- v = vstart;
- i = 0;
- weight = BEVEL_MATCH_SPEC_WEIGHT; /* sqrt of factor to weight down importance of spec match */
- do {
- /* except at end of chain, v's indep variable is offset_r of v->efirst */
- if (iscycle || i < np - 1) {
- eright = v->efirst;
- eleft = v->elast;
- enextleft = v->adjchain->elast;
+ v = vstart;
+ i = 0;
+ weight = BEVEL_MATCH_SPEC_WEIGHT; /* sqrt of factor to weight down importance of spec match */
+ do {
+ /* except at end of chain, v's indep variable is offset_r of v->efirst */
+ if (iscycle || i < np - 1) {
+ eright = v->efirst;
+ eleft = v->elast;
+ enextleft = v->adjchain->elast;
#ifdef DEBUG_ADJUST
- printf("p%d: e%d->offset_r = %f\n", i, BM_elem_index_get(eright->e), eright->offset_r);
- if (iscycle || v != vstart) {
- printf(" dependent: e%d->offset_l = %f * p%d\n", BM_elem_index_get(eleft->e), v->sinratio, i);
- }
+ printf("p%d: e%d->offset_r = %f\n", i, BM_elem_index_get(eright->e), eright->offset_r);
+ if (iscycle || v != vstart) {
+ printf(" dependent: e%d->offset_l = %f * p%d\n",
+ BM_elem_index_get(eleft->e),
+ v->sinratio,
+ i);
+ }
#endif
- /* residue i: width difference between eright and eleft of next */
- EIG_linear_solver_matrix_add(solver, i, i, 1.0);
- EIG_linear_solver_right_hand_side_add(solver, 0, i, 0.0);
- if (iscycle) {
- EIG_linear_solver_matrix_add(solver, i > 0 ? i - 1 : np - 1, i, -v->sinratio);
- }
- else {
- if (i > 0) {
- EIG_linear_solver_matrix_add(solver, i - 1, i, -v->sinratio);
- }
- }
-
- /* residue np + 2*i (if cycle) else np - 1 + 2*i:
- * right offset for parm i matches its spec; weighted */
- row = iscycle ? np + 2 * i : np - 1 + 2 * i;
- EIG_linear_solver_matrix_add(solver, row, i, weight);
- EIG_linear_solver_right_hand_side_add(solver, 0, row, weight * eright->offset_r);
+ /* residue i: width difference between eright and eleft of next */
+ EIG_linear_solver_matrix_add(solver, i, i, 1.0);
+ EIG_linear_solver_right_hand_side_add(solver, 0, i, 0.0);
+ if (iscycle) {
+ EIG_linear_solver_matrix_add(solver, i > 0 ? i - 1 : np - 1, i, -v->sinratio);
+ }
+ else {
+ if (i > 0) {
+ EIG_linear_solver_matrix_add(solver, i - 1, i, -v->sinratio);
+ }
+ }
+
+ /* residue np + 2*i (if cycle) else np - 1 + 2*i:
+ * right offset for parm i matches its spec; weighted */
+ row = iscycle ? np + 2 * i : np - 1 + 2 * i;
+ EIG_linear_solver_matrix_add(solver, row, i, weight);
+ EIG_linear_solver_right_hand_side_add(solver, 0, row, weight * eright->offset_r);
#ifdef DEBUG_ADJUST
- printf("b[%d]=%f * %f, for e%d->offset_r\n", row, weight, eright->offset_r, BM_elem_index_get(eright->e));
+ printf("b[%d]=%f * %f, for e%d->offset_r\n",
+ row,
+ weight,
+ eright->offset_r,
+ BM_elem_index_get(eright->e));
#endif
- /* residue np + 2*i + 1 (if cycle) else np - 1 + 2*i + 1:
- * left offset for parm i matches its spec; weighted */
- row = row + 1;
- EIG_linear_solver_matrix_add(solver, row, (i == np - 1) ? 0 : i + 1, weight * v->adjchain->sinratio);
- EIG_linear_solver_right_hand_side_add(solver, 0, row, weight * enextleft->offset_l);
+ /* residue np + 2*i + 1 (if cycle) else np - 1 + 2*i + 1:
+ * left offset for parm i matches its spec; weighted */
+ row = row + 1;
+ EIG_linear_solver_matrix_add(
+ solver, row, (i == np - 1) ? 0 : i + 1, weight * v->adjchain->sinratio);
+ EIG_linear_solver_right_hand_side_add(solver, 0, row, weight * enextleft->offset_l);
#ifdef DEBUG_ADJUST
- printf("b[%d]=%f * %f, for e%d->offset_l\n", row, weight, enextleft->offset_l,
- BM_elem_index_get(enextleft->e));
+ printf("b[%d]=%f * %f, for e%d->offset_l\n",
+ row,
+ weight,
+ enextleft->offset_l,
+ BM_elem_index_get(enextleft->e));
#endif
- }
- else {
- /* not a cycle, and last of chain */
- eleft = v->elast;
+ }
+ else {
+ /* not a cycle, and last of chain */
+ eleft = v->elast;
#ifdef DEBUG_ADJUST
- printf("p%d: e%d->offset_l = %f\n", i, BM_elem_index_get(eleft->e), eleft->offset_l);
+ printf("p%d: e%d->offset_l = %f\n", i, BM_elem_index_get(eleft->e), eleft->offset_l);
#endif
- /* second part of residue i for last i */
- EIG_linear_solver_matrix_add(solver, i - 1, i, -1.0);
- }
- i++;
- v = v->adjchain;
- } while (v && v != vstart);
- EIG_linear_solver_solve(solver);
+ /* second part of residue i for last i */
+ EIG_linear_solver_matrix_add(solver, i - 1, i, -1.0);
+ }
+ i++;
+ v = v->adjchain;
+ } while (v && v != vstart);
+ EIG_linear_solver_solve(solver);
#ifdef DEBUG_ADJUST
- /* Note: this print only works after solve, but by that time b has been cleared */
- EIG_linear_solver_print_matrix(solver);
- printf("\nSolution:\n");
- for (i = 0; i < np; i++) {
- printf("p%d = %f\n", i, EIG_linear_solver_variable_get(solver, 0, i));
- }
+ /* Note: this print only works after solve, but by that time b has been cleared */
+ EIG_linear_solver_print_matrix(solver);
+ printf("\nSolution:\n");
+ for (i = 0; i < np; i++) {
+ printf("p%d = %f\n", i, EIG_linear_solver_variable_get(solver, 0, i));
+ }
#endif
- /* Use the solution to set new widths */
- v = vstart;
- i = 0;
- do {
- val = EIG_linear_solver_variable_get(solver, 0, i);
- if (iscycle || i < np - 1) {
- eright = v->efirst;
- eleft = v->elast;
- eright->offset_r = (float)val;
+ /* Use the solution to set new widths */
+ v = vstart;
+ i = 0;
+ do {
+ val = EIG_linear_solver_variable_get(solver, 0, i);
+ if (iscycle || i < np - 1) {
+ eright = v->efirst;
+ eleft = v->elast;
+ eright->offset_r = (float)val;
#ifdef DEBUG_ADJUST
- printf("e%d->offset_r = %f\n", BM_elem_index_get(eright->e), eright->offset_r);
+ printf("e%d->offset_r = %f\n", BM_elem_index_get(eright->e), eright->offset_r);
#endif
- if (iscycle || v != vstart) {
- eleft->offset_l = (float)(v->sinratio * val);
+ if (iscycle || v != vstart) {
+ eleft->offset_l = (float)(v->sinratio * val);
#ifdef DEBUG_ADJUST
- printf("e%d->offset_l = %f\n", BM_elem_index_get(eleft->e), eleft->offset_l);
+ printf("e%d->offset_l = %f\n", BM_elem_index_get(eleft->e), eleft->offset_l);
#endif
- }
- }
- else {
- /* not a cycle, and last of chain */
- eleft = v->elast;
- eleft->offset_l = (float)val;
+ }
+ }
+ else {
+ /* not a cycle, and last of chain */
+ eleft = v->elast;
+ eleft->offset_l = (float)val;
#ifdef DEBUG_ADJUST
- printf("e%d->offset_l = %f\n", BM_elem_index_get(eleft->e), eleft->offset_l);
+ printf("e%d->offset_l = %f\n", BM_elem_index_get(eleft->e), eleft->offset_l);
#endif
- }
- i++;
- v = v->adjchain;
- } while (v && v != vstart);
+ }
+ i++;
+ v = v->adjchain;
+ } while (v && v != vstart);
#ifdef DEBUG_ADJUST
- print_adjust_stats(vstart);
- EIG_linear_solver_print_matrix(solver);
+ print_adjust_stats(vstart);
+ EIG_linear_solver_print_matrix(solver);
#endif
- EIG_linear_solver_delete(solver);
+ EIG_linear_solver_delete(solver);
}
/* Adjust the offsets to try to make them, as much as possible,
@@ -2943,99 +2979,99 @@ static void adjust_the_cycle_or_chain(BoundVert *vstart, bool iscycle)
*/
static void adjust_offsets(BevelParams *bp, BMesh *bm)
{
- BMVert *bmv;
- BevVert *bv, *bvcur;
- BoundVert *v, *vanchor, *vchainstart, *vchainend, *vnext;
- EdgeHalf *enext;
- BMIter iter;
- bool iscycle;
- int chainlen;
-
- /* find and process chains and cycles of unvisited BoundVerts that have eon set */
- /* note: for repeatability, iterate over all verts of mesh rather than over ghash'ed BMVerts */
- BM_ITER_MESH(bmv, &iter, bm, BM_VERTS_OF_MESH) {
- if (!BM_elem_flag_test(bmv, BM_ELEM_TAG))
- continue;
- bv = bvcur = find_bevvert(bp, bmv);
- if (!bv)
- continue;
- vanchor = bv->vmesh->boundstart;
- do {
- if (vanchor->visited || !vanchor->eon) {
- continue;
- }
-
- /* Find one of (1) a cycle that starts and ends at v
- * where each v has v->eon set and had not been visited before;
- * or (2) a chain of v's where the start and end of the chain do not have
- * v->eon set but all else do.
- * It is OK for the first and last elements to
- * have been visited before, but not any of the inner ones.
- * We chain the v's together through v->adjchain, and are following
- * them in left->right direction, meaning that the left side of one edge
- * pairs with the right side of the next edge in the cycle or chain. */
-
- /* first follow paired edges in left->right direction */
- v = vchainstart = vchainend = vanchor;
- iscycle = false;
- chainlen = 1;
- while (v->eon && !v->visited && !iscycle) {
- v->visited = true;
- if (!v->efirst) {
- break;
- }
- enext = find_other_end_edge_half(bp, v->efirst, &bvcur);
- if (!enext) {
- break;
- }
- BLI_assert(enext != NULL);
- vnext = enext->leftv;
- v->adjchain = vnext;
- vchainend = vnext;
- chainlen++;
- if (vnext->visited) {
- if (vnext != vchainstart) {
- break;
- }
- adjust_the_cycle_or_chain(vchainstart, true);
- iscycle = true;
- }
- v = vnext;
- }
- if (!iscycle) {
- /* right->left direction, changing vchainstart at each step */
- v = vchainstart;
- bvcur = bv;
- do {
- v->visited = true;
- if (!v->elast) {
- break;
- }
- enext = find_other_end_edge_half(bp, v->elast, &bvcur);
- if (!enext) {
- break;
- }
- vnext = enext->rightv;
- vnext->adjchain = v;
- chainlen++;
- vchainstart = vnext;
- v = vnext;
- } while (!v->visited && v->eon);
- if (chainlen >= 3 && !vchainstart->eon && !vchainend->eon) {
- adjust_the_cycle_or_chain(vchainstart, false);
- }
- }
- } while ((vanchor = vanchor->next) != bv->vmesh->boundstart);
- }
-
- /* Rebuild boundaries with new width specs */
- BM_ITER_MESH(bmv, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(bmv, BM_ELEM_TAG)) {
- bv = find_bevvert(bp, bmv);
- if (bv)
- build_boundary(bp, bv, false);
- }
- }
+ BMVert *bmv;
+ BevVert *bv, *bvcur;
+ BoundVert *v, *vanchor, *vchainstart, *vchainend, *vnext;
+ EdgeHalf *enext;
+ BMIter iter;
+ bool iscycle;
+ int chainlen;
+
+ /* find and process chains and cycles of unvisited BoundVerts that have eon set */
+ /* note: for repeatability, iterate over all verts of mesh rather than over ghash'ed BMVerts */
+ BM_ITER_MESH (bmv, &iter, bm, BM_VERTS_OF_MESH) {
+ if (!BM_elem_flag_test(bmv, BM_ELEM_TAG))
+ continue;
+ bv = bvcur = find_bevvert(bp, bmv);
+ if (!bv)
+ continue;
+ vanchor = bv->vmesh->boundstart;
+ do {
+ if (vanchor->visited || !vanchor->eon) {
+ continue;
+ }
+
+ /* Find one of (1) a cycle that starts and ends at v
+ * where each v has v->eon set and had not been visited before;
+ * or (2) a chain of v's where the start and end of the chain do not have
+ * v->eon set but all else do.
+ * It is OK for the first and last elements to
+ * have been visited before, but not any of the inner ones.
+ * We chain the v's together through v->adjchain, and are following
+ * them in left->right direction, meaning that the left side of one edge
+ * pairs with the right side of the next edge in the cycle or chain. */
+
+ /* first follow paired edges in left->right direction */
+ v = vchainstart = vchainend = vanchor;
+ iscycle = false;
+ chainlen = 1;
+ while (v->eon && !v->visited && !iscycle) {
+ v->visited = true;
+ if (!v->efirst) {
+ break;
+ }
+ enext = find_other_end_edge_half(bp, v->efirst, &bvcur);
+ if (!enext) {
+ break;
+ }
+ BLI_assert(enext != NULL);
+ vnext = enext->leftv;
+ v->adjchain = vnext;
+ vchainend = vnext;
+ chainlen++;
+ if (vnext->visited) {
+ if (vnext != vchainstart) {
+ break;
+ }
+ adjust_the_cycle_or_chain(vchainstart, true);
+ iscycle = true;
+ }
+ v = vnext;
+ }
+ if (!iscycle) {
+ /* right->left direction, changing vchainstart at each step */
+ v = vchainstart;
+ bvcur = bv;
+ do {
+ v->visited = true;
+ if (!v->elast) {
+ break;
+ }
+ enext = find_other_end_edge_half(bp, v->elast, &bvcur);
+ if (!enext) {
+ break;
+ }
+ vnext = enext->rightv;
+ vnext->adjchain = v;
+ chainlen++;
+ vchainstart = vnext;
+ v = vnext;
+ } while (!v->visited && v->eon);
+ if (chainlen >= 3 && !vchainstart->eon && !vchainend->eon) {
+ adjust_the_cycle_or_chain(vchainstart, false);
+ }
+ }
+ } while ((vanchor = vanchor->next) != bv->vmesh->boundstart);
+ }
+
+ /* Rebuild boundaries with new width specs */
+ BM_ITER_MESH (bmv, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(bmv, BM_ELEM_TAG)) {
+ bv = find_bevvert(bp, bmv);
+ if (bv)
+ build_boundary(bp, bv, false);
+ }
+ }
}
/* Do the edges at bv form a "pipe"?
@@ -3047,60 +3083,61 @@ static void adjust_offsets(BevelParams *bp, BMesh *bm)
* whose next boundary vert has a beveled, non-pipe edge. */
static BoundVert *pipe_test(BevVert *bv)
{
- EdgeHalf *e, *epipe;
- VMesh *vm;
- BoundVert *v1, *v2, *v3;
- float dir1[3], dir3[3];
-
- vm = bv->vmesh;
- if (vm->count < 3 || vm->count > 4 || bv->selcount < 3 || bv->selcount > 4) {
- return NULL;
- }
-
- /* find v1, v2, v3 all with beveled edges, where v1 and v3 have collinear edges */
- epipe = NULL;
- v1 = vm->boundstart;
- do {
- v2 = v1->next;
- v3 = v2->next;
- if (v1->ebev && v2->ebev && v3->ebev) {
- sub_v3_v3v3(dir1, bv->v->co, BM_edge_other_vert(v1->ebev->e, bv->v)->co);
- sub_v3_v3v3(dir3, BM_edge_other_vert(v3->ebev->e, bv->v)->co, bv->v->co);
- normalize_v3(dir1);
- normalize_v3(dir3);
- if (angle_normalized_v3v3(dir1, dir3) < BEVEL_EPSILON_ANG) {
- epipe = v1->ebev;
- break;
- }
- }
- } while ((v1 = v1->next) != vm->boundstart);
-
- if (!epipe) {
- return NULL;
- }
-
- /* check face planes: all should have normals perpendicular to epipe */
- for (e = &bv->edges[0]; e != &bv->edges[bv->edgecount]; e++) {
- if (e->fnext) {
- if (dot_v3v3(dir1, e->fnext->no) > BEVEL_EPSILON_BIG) {
- return NULL;
- }
- }
- }
- return v1;
+ EdgeHalf *e, *epipe;
+ VMesh *vm;
+ BoundVert *v1, *v2, *v3;
+ float dir1[3], dir3[3];
+
+ vm = bv->vmesh;
+ if (vm->count < 3 || vm->count > 4 || bv->selcount < 3 || bv->selcount > 4) {
+ return NULL;
+ }
+
+ /* find v1, v2, v3 all with beveled edges, where v1 and v3 have collinear edges */
+ epipe = NULL;
+ v1 = vm->boundstart;
+ do {
+ v2 = v1->next;
+ v3 = v2->next;
+ if (v1->ebev && v2->ebev && v3->ebev) {
+ sub_v3_v3v3(dir1, bv->v->co, BM_edge_other_vert(v1->ebev->e, bv->v)->co);
+ sub_v3_v3v3(dir3, BM_edge_other_vert(v3->ebev->e, bv->v)->co, bv->v->co);
+ normalize_v3(dir1);
+ normalize_v3(dir3);
+ if (angle_normalized_v3v3(dir1, dir3) < BEVEL_EPSILON_ANG) {
+ epipe = v1->ebev;
+ break;
+ }
+ }
+ } while ((v1 = v1->next) != vm->boundstart);
+
+ if (!epipe) {
+ return NULL;
+ }
+
+ /* check face planes: all should have normals perpendicular to epipe */
+ for (e = &bv->edges[0]; e != &bv->edges[bv->edgecount]; e++) {
+ if (e->fnext) {
+ if (dot_v3v3(dir1, e->fnext->no) > BEVEL_EPSILON_BIG) {
+ return NULL;
+ }
+ }
+ }
+ return v1;
}
static VMesh *new_adj_vmesh(MemArena *mem_arena, int count, int seg, BoundVert *bounds)
{
- VMesh *vm;
-
- vm = (VMesh *)BLI_memarena_alloc(mem_arena, sizeof(VMesh));
- vm->count = count;
- vm->seg = seg;
- vm->boundstart = bounds;
- vm->mesh = (NewVert *)BLI_memarena_alloc(mem_arena, count * (1 + seg / 2) * (1 + seg) * sizeof(NewVert));
- vm->mesh_kind = M_ADJ;
- return vm;
+ VMesh *vm;
+
+ vm = (VMesh *)BLI_memarena_alloc(mem_arena, sizeof(VMesh));
+ vm->count = count;
+ vm->seg = seg;
+ vm->boundstart = bounds;
+ vm->mesh = (NewVert *)BLI_memarena_alloc(mem_arena,
+ count * (1 + seg / 2) * (1 + seg) * sizeof(NewVert));
+ vm->mesh_kind = M_ADJ;
+ return vm;
}
/* VMesh verts for vertex i have data for (i, 0 <= j <= ns2, 0 <= k <= ns), where ns2 = floor(nseg / 2).
@@ -3112,274 +3149,271 @@ static VMesh *new_adj_vmesh(MemArena *mem_arena, int count, int seg, BoundVert *
* This function returns the canonical one for any i, j, k in [0,n],[0,ns],[0,ns] */
static NewVert *mesh_vert_canon(VMesh *vm, int i, int j, int k)
{
- int n, ns, ns2, odd;
- NewVert *ans;
-
- n = vm->count;
- ns = vm->seg;
- ns2 = ns / 2;
- odd = ns % 2;
- BLI_assert(0 <= i && i <= n && 0 <= j && j <= ns && 0 <= k && k <= ns);
-
- if (!odd && j == ns2 && k == ns2) {
- ans = mesh_vert(vm, 0, j, k);
- }
- else if (j <= ns2 - 1 + odd && k <= ns2) {
- ans = mesh_vert(vm, i, j, k);
- }
- else if (k <= ns2) {
- ans = mesh_vert(vm, (i + n - 1) % n, k, ns - j);
- }
- else {
- ans = mesh_vert(vm, (i + 1) % n, ns - k, j);
- }
- return ans;
+ int n, ns, ns2, odd;
+ NewVert *ans;
+
+ n = vm->count;
+ ns = vm->seg;
+ ns2 = ns / 2;
+ odd = ns % 2;
+ BLI_assert(0 <= i && i <= n && 0 <= j && j <= ns && 0 <= k && k <= ns);
+
+ if (!odd && j == ns2 && k == ns2) {
+ ans = mesh_vert(vm, 0, j, k);
+ }
+ else if (j <= ns2 - 1 + odd && k <= ns2) {
+ ans = mesh_vert(vm, i, j, k);
+ }
+ else if (k <= ns2) {
+ ans = mesh_vert(vm, (i + n - 1) % n, k, ns - j);
+ }
+ else {
+ ans = mesh_vert(vm, (i + 1) % n, ns - k, j);
+ }
+ return ans;
}
static bool is_canon(VMesh *vm, int i, int j, int k)
{
- int ns2 = vm->seg / 2;
- if (vm->seg % 2 == 1) {
- return (j <= ns2 && k <= ns2);
- }
- else {
- return ((j < ns2 && k <= ns2) || (j == ns2 && k == ns2 && i == 0));
- }
+ int ns2 = vm->seg / 2;
+ if (vm->seg % 2 == 1) {
+ return (j <= ns2 && k <= ns2);
+ }
+ else {
+ return ((j < ns2 && k <= ns2) || (j == ns2 && k == ns2 && i == 0));
+ }
}
/* Copy the vertex data to all of vm verts from canonical ones */
static void vmesh_copy_equiv_verts(VMesh *vm)
{
- int n, ns, ns2, i, j, k;
- NewVert *v0, *v1;
-
- n = vm->count;
- ns = vm->seg;
- ns2 = ns / 2;
- for (i = 0; i < n; i++) {
- for (j = 0; j <= ns2; j++) {
- for (k = 0; k <= ns; k++) {
- if (is_canon(vm, i, j, k)) {
- continue;
- }
- v1 = mesh_vert(vm, i, j, k);
- v0 = mesh_vert_canon(vm, i, j, k);
- copy_v3_v3(v1->co, v0->co);
- v1->v = v0->v;
- }
- }
- }
+ int n, ns, ns2, i, j, k;
+ NewVert *v0, *v1;
+
+ n = vm->count;
+ ns = vm->seg;
+ ns2 = ns / 2;
+ for (i = 0; i < n; i++) {
+ for (j = 0; j <= ns2; j++) {
+ for (k = 0; k <= ns; k++) {
+ if (is_canon(vm, i, j, k)) {
+ continue;
+ }
+ v1 = mesh_vert(vm, i, j, k);
+ v0 = mesh_vert_canon(vm, i, j, k);
+ copy_v3_v3(v1->co, v0->co);
+ v1->v = v0->v;
+ }
+ }
+ }
}
/* Calculate and return in r_cent the centroid of the center poly */
static void vmesh_center(VMesh *vm, float r_cent[3])
{
- int n, ns2, i;
-
- n = vm->count;
- ns2 = vm->seg / 2;
- if (vm->seg % 2) {
- zero_v3(r_cent);
- for (i = 0; i < n; i++) {
- add_v3_v3(r_cent, mesh_vert(vm, i, ns2, ns2)->co);
- }
- mul_v3_fl(r_cent, 1.0f / (float) n);
- }
- else {
- copy_v3_v3(r_cent, mesh_vert(vm, 0, ns2, ns2)->co);
- }
+ int n, ns2, i;
+
+ n = vm->count;
+ ns2 = vm->seg / 2;
+ if (vm->seg % 2) {
+ zero_v3(r_cent);
+ for (i = 0; i < n; i++) {
+ add_v3_v3(r_cent, mesh_vert(vm, i, ns2, ns2)->co);
+ }
+ mul_v3_fl(r_cent, 1.0f / (float)n);
+ }
+ else {
+ copy_v3_v3(r_cent, mesh_vert(vm, 0, ns2, ns2)->co);
+ }
}
static void avg4(
- float co[3],
- const NewVert *v0, const NewVert *v1,
- const NewVert *v2, const NewVert *v3)
+ float co[3], const NewVert *v0, const NewVert *v1, const NewVert *v2, const NewVert *v3)
{
- add_v3_v3v3(co, v0->co, v1->co);
- add_v3_v3(co, v2->co);
- add_v3_v3(co, v3->co);
- mul_v3_fl(co, 0.25f);
+ add_v3_v3v3(co, v0->co, v1->co);
+ add_v3_v3(co, v2->co);
+ add_v3_v3(co, v3->co);
+ mul_v3_fl(co, 0.25f);
}
/* gamma needed for smooth Catmull-Clark, Sabin modification */
static float sabin_gamma(int n)
{
- double ans, k, k2, k4, k6, x, y;
-
- /* precalculated for common cases of n */
- if (n < 3) {
- return 0.0f;
- }
- else if (n == 3) {
- ans = 0.065247584f;
- }
- else if (n == 4) {
- ans = 0.25f;
- }
- else if (n == 5) {
- ans = 0.401983447f;
- }
- else if (n == 6) {
- ans = 0.523423277f;
- }
- else {
- k = cos(M_PI / (double)n);
- /* need x, real root of x^3 + (4k^2 - 3)x - 2k = 0.
- * answer calculated via Wolfram Alpha */
- k2 = k * k;
- k4 = k2 * k2;
- k6 = k4 * k2;
- y = pow(M_SQRT3 * sqrt(64.0 * k6 - 144.0 * k4 + 135.0 * k2 - 27.0) + 9.0 * k,
- 1.0 / 3.0);
- x = 0.480749856769136 * y - (0.231120424783545 * (12.0 * k2 - 9.0)) / y;
- ans = (k * x + 2.0 * k2 - 1.0) / (x * x * (k * x + 1.0));
- }
- return (float)ans;
+ double ans, k, k2, k4, k6, x, y;
+
+ /* precalculated for common cases of n */
+ if (n < 3) {
+ return 0.0f;
+ }
+ else if (n == 3) {
+ ans = 0.065247584f;
+ }
+ else if (n == 4) {
+ ans = 0.25f;
+ }
+ else if (n == 5) {
+ ans = 0.401983447f;
+ }
+ else if (n == 6) {
+ ans = 0.523423277f;
+ }
+ else {
+ k = cos(M_PI / (double)n);
+ /* need x, real root of x^3 + (4k^2 - 3)x - 2k = 0.
+ * answer calculated via Wolfram Alpha */
+ k2 = k * k;
+ k4 = k2 * k2;
+ k6 = k4 * k2;
+ y = pow(M_SQRT3 * sqrt(64.0 * k6 - 144.0 * k4 + 135.0 * k2 - 27.0) + 9.0 * k, 1.0 / 3.0);
+ x = 0.480749856769136 * y - (0.231120424783545 * (12.0 * k2 - 9.0)) / y;
+ ans = (k * x + 2.0 * k2 - 1.0) / (x * x * (k * x + 1.0));
+ }
+ return (float)ans;
}
/* Fill frac with fractions of way along ring 0 for vertex i, for use with interp_range function */
static void fill_vmesh_fracs(VMesh *vm, float *frac, int i)
{
- int k, ns;
- float total = 0.0f;
-
- ns = vm->seg;
- frac[0] = 0.0f;
- for (k = 0; k < ns; k++) {
- total += len_v3v3(mesh_vert(vm, i, 0, k)->co, mesh_vert(vm, i, 0, k + 1)->co);
- frac[k + 1] = total;
- }
- if (total > 0.0f) {
- for (k = 1; k <= ns; k++) {
- frac[k] /= total;
- }
- }
- else {
- frac[ns] = 1.0f;
- }
+ int k, ns;
+ float total = 0.0f;
+
+ ns = vm->seg;
+ frac[0] = 0.0f;
+ for (k = 0; k < ns; k++) {
+ total += len_v3v3(mesh_vert(vm, i, 0, k)->co, mesh_vert(vm, i, 0, k + 1)->co);
+ frac[k + 1] = total;
+ }
+ if (total > 0.0f) {
+ for (k = 1; k <= ns; k++) {
+ frac[k] /= total;
+ }
+ }
+ else {
+ frac[ns] = 1.0f;
+ }
}
/* Like fill_vmesh_fracs but want fractions for profile points of bndv, with ns segments */
static void fill_profile_fracs(BevelParams *bp, BoundVert *bndv, float *frac, int ns)
{
- int k;
- float co[3], nextco[3];
- float total = 0.0f;
-
- frac[0] = 0.0f;
- copy_v3_v3(co, bndv->nv.co);
- for (k = 0; k < ns; k++) {
- get_profile_point(bp, &bndv->profile, k + 1, ns, nextco);
- total += len_v3v3(co, nextco);
- frac[k + 1] = total;
- copy_v3_v3(co, nextco);
- }
- if (total > 0.0f) {
- for (k = 1; k <= ns; k++) {
- frac[k] /= total;
- }
- }
- else {
- frac[ns] = 1.0f;
- }
+ int k;
+ float co[3], nextco[3];
+ float total = 0.0f;
+
+ frac[0] = 0.0f;
+ copy_v3_v3(co, bndv->nv.co);
+ for (k = 0; k < ns; k++) {
+ get_profile_point(bp, &bndv->profile, k + 1, ns, nextco);
+ total += len_v3v3(co, nextco);
+ frac[k + 1] = total;
+ copy_v3_v3(co, nextco);
+ }
+ if (total > 0.0f) {
+ for (k = 1; k <= ns; k++) {
+ frac[k] /= total;
+ }
+ }
+ else {
+ frac[ns] = 1.0f;
+ }
}
/* Return i such that frac[i] <= f <= frac[i + 1], where frac[n] == 1.0
* and put fraction of rest of way between frac[i] and frac[i + 1] into r_rest */
static int interp_range(const float *frac, int n, const float f, float *r_rest)
{
- int i;
- float rest;
-
- /* could binary search in frac, but expect n to be reasonably small */
- for (i = 0; i < n; i++) {
- if (f <= frac[i + 1]) {
- rest = f - frac[i];
- if (rest == 0) {
- *r_rest = 0.0f;
- }
- else {
- *r_rest = rest / (frac[i + 1] - frac[i]);
- }
- if (i == n - 1 && *r_rest == 1.0f) {
- i = n;
- *r_rest = 0.0f;
- }
- return i;
- }
- }
- *r_rest = 0.0f;
- return n;
+ int i;
+ float rest;
+
+ /* could binary search in frac, but expect n to be reasonably small */
+ for (i = 0; i < n; i++) {
+ if (f <= frac[i + 1]) {
+ rest = f - frac[i];
+ if (rest == 0) {
+ *r_rest = 0.0f;
+ }
+ else {
+ *r_rest = rest / (frac[i + 1] - frac[i]);
+ }
+ if (i == n - 1 && *r_rest == 1.0f) {
+ i = n;
+ *r_rest = 0.0f;
+ }
+ return i;
+ }
+ }
+ *r_rest = 0.0f;
+ return n;
}
/* Interpolate given vmesh to make one with target nseg border vertices on the profiles */
static VMesh *interp_vmesh(BevelParams *bp, VMesh *vm0, int nseg)
{
- int n, ns0, nseg2, odd, i, j, k, j0, k0, k0prev, j0inc, k0inc;
- float *prev_frac, *frac, *new_frac, *prev_new_frac;
- float f, restj, restk, restkprev;
- float quad[4][3], co[3], center[3];
- VMesh *vm1;
- BoundVert *bndv;
-
- n = vm0->count;
- ns0 = vm0->seg;
- nseg2 = nseg / 2;
- odd = nseg % 2;
- vm1 = new_adj_vmesh(bp->mem_arena, n, nseg, vm0->boundstart);
-
- prev_frac = BLI_array_alloca(prev_frac, (ns0 + 1));
- frac = BLI_array_alloca(frac, (ns0 + 1));
- new_frac = BLI_array_alloca(new_frac, (nseg + 1));
- prev_new_frac = BLI_array_alloca(prev_new_frac, (nseg + 1));
-
- fill_vmesh_fracs(vm0, prev_frac, n - 1);
- bndv = vm0->boundstart;
- fill_profile_fracs(bp, bndv->prev, prev_new_frac, nseg);
- for (i = 0; i < n; i++) {
- fill_vmesh_fracs(vm0, frac, i);
- fill_profile_fracs(bp, bndv, new_frac, nseg);
- for (j = 0; j <= nseg2 - 1 + odd; j++) {
- for (k = 0; k <= nseg2; k++) {
- f = new_frac[k];
- k0 = interp_range(frac, ns0, f, &restk);
- f = prev_new_frac[nseg - j];
- k0prev = interp_range(prev_frac, ns0, f, &restkprev);
- j0 = ns0 - k0prev;
- restj = -restkprev;
- if (restj > -BEVEL_EPSILON) {
- restj = 0.0f;
- }
- else {
- j0 = j0 - 1;
- restj = 1.0f + restj;
- }
- /* Use bilinear interpolation within the source quad; could be smarter here */
- if (restj < BEVEL_EPSILON && restk < BEVEL_EPSILON) {
- copy_v3_v3(co, mesh_vert_canon(vm0, i, j0, k0)->co);
- }
- else {
- j0inc = (restj < BEVEL_EPSILON || j0 == ns0) ? 0 : 1;
- k0inc = (restk < BEVEL_EPSILON || k0 == ns0) ? 0 : 1;
- copy_v3_v3(quad[0], mesh_vert_canon(vm0, i, j0, k0)->co);
- copy_v3_v3(quad[1], mesh_vert_canon(vm0, i, j0, k0 + k0inc)->co);
- copy_v3_v3(quad[2], mesh_vert_canon(vm0, i, j0 + j0inc, k0 + k0inc)->co);
- copy_v3_v3(quad[3], mesh_vert_canon(vm0, i, j0 + j0inc, k0)->co);
- interp_bilinear_quad_v3(quad, restk, restj, co);
- }
- copy_v3_v3(mesh_vert(vm1, i, j, k)->co, co);
- }
- }
- bndv = bndv->next;
- memcpy(prev_frac, frac, (ns0 + 1) * sizeof(float));
- memcpy(prev_new_frac, new_frac, (nseg + 1) * sizeof(float));
- }
- if (!odd) {
- vmesh_center(vm0, center);
- copy_v3_v3(mesh_vert(vm1, 0, nseg2, nseg2)->co, center);
- }
- vmesh_copy_equiv_verts(vm1);
- return vm1;
+ int n, ns0, nseg2, odd, i, j, k, j0, k0, k0prev, j0inc, k0inc;
+ float *prev_frac, *frac, *new_frac, *prev_new_frac;
+ float f, restj, restk, restkprev;
+ float quad[4][3], co[3], center[3];
+ VMesh *vm1;
+ BoundVert *bndv;
+
+ n = vm0->count;
+ ns0 = vm0->seg;
+ nseg2 = nseg / 2;
+ odd = nseg % 2;
+ vm1 = new_adj_vmesh(bp->mem_arena, n, nseg, vm0->boundstart);
+
+ prev_frac = BLI_array_alloca(prev_frac, (ns0 + 1));
+ frac = BLI_array_alloca(frac, (ns0 + 1));
+ new_frac = BLI_array_alloca(new_frac, (nseg + 1));
+ prev_new_frac = BLI_array_alloca(prev_new_frac, (nseg + 1));
+
+ fill_vmesh_fracs(vm0, prev_frac, n - 1);
+ bndv = vm0->boundstart;
+ fill_profile_fracs(bp, bndv->prev, prev_new_frac, nseg);
+ for (i = 0; i < n; i++) {
+ fill_vmesh_fracs(vm0, frac, i);
+ fill_profile_fracs(bp, bndv, new_frac, nseg);
+ for (j = 0; j <= nseg2 - 1 + odd; j++) {
+ for (k = 0; k <= nseg2; k++) {
+ f = new_frac[k];
+ k0 = interp_range(frac, ns0, f, &restk);
+ f = prev_new_frac[nseg - j];
+ k0prev = interp_range(prev_frac, ns0, f, &restkprev);
+ j0 = ns0 - k0prev;
+ restj = -restkprev;
+ if (restj > -BEVEL_EPSILON) {
+ restj = 0.0f;
+ }
+ else {
+ j0 = j0 - 1;
+ restj = 1.0f + restj;
+ }
+ /* Use bilinear interpolation within the source quad; could be smarter here */
+ if (restj < BEVEL_EPSILON && restk < BEVEL_EPSILON) {
+ copy_v3_v3(co, mesh_vert_canon(vm0, i, j0, k0)->co);
+ }
+ else {
+ j0inc = (restj < BEVEL_EPSILON || j0 == ns0) ? 0 : 1;
+ k0inc = (restk < BEVEL_EPSILON || k0 == ns0) ? 0 : 1;
+ copy_v3_v3(quad[0], mesh_vert_canon(vm0, i, j0, k0)->co);
+ copy_v3_v3(quad[1], mesh_vert_canon(vm0, i, j0, k0 + k0inc)->co);
+ copy_v3_v3(quad[2], mesh_vert_canon(vm0, i, j0 + j0inc, k0 + k0inc)->co);
+ copy_v3_v3(quad[3], mesh_vert_canon(vm0, i, j0 + j0inc, k0)->co);
+ interp_bilinear_quad_v3(quad, restk, restj, co);
+ }
+ copy_v3_v3(mesh_vert(vm1, i, j, k)->co, co);
+ }
+ }
+ bndv = bndv->next;
+ memcpy(prev_frac, frac, (ns0 + 1) * sizeof(float));
+ memcpy(prev_new_frac, new_frac, (nseg + 1) * sizeof(float));
+ }
+ if (!odd) {
+ vmesh_center(vm0, center);
+ copy_v3_v3(mesh_vert(vm1, 0, nseg2, nseg2)->co, center);
+ }
+ vmesh_copy_equiv_verts(vm1);
+ return vm1;
}
/* Do one step of cubic subdivision (Catmull-Clark), with special rules at boundaries.
@@ -3388,203 +3422,206 @@ static VMesh *interp_vmesh(BevelParams *bp, VMesh *vm0, int nseg)
* See Levin 1999 paper: "Filling an N-sided hole using combined subdivision schemes". */
static VMesh *cubic_subdiv(BevelParams *bp, VMesh *vm0)
{
- int n, ns0, ns20, ns1;
- int i, j, k, inext;
- float co[3], co1[3], co2[3], acc[3];
- float beta, gamma;
- VMesh *vm1;
- BoundVert *bndv;
-
- n = vm0->count;
- ns0 = vm0->seg;
- ns20 = ns0 / 2;
- BLI_assert(ns0 % 2 == 0);
- ns1 = 2 * ns0;
- vm1 = new_adj_vmesh(bp->mem_arena, n, ns1, vm0->boundstart);
-
- /* First we adjust the boundary vertices of the input mesh, storing in output mesh */
- for (i = 0; i < n; i++) {
- copy_v3_v3(mesh_vert(vm1, i, 0, 0)->co, mesh_vert(vm0, i, 0, 0)->co);
- for (k = 1; k < ns0; k++) {
- /* smooth boundary rule */
- copy_v3_v3(co, mesh_vert(vm0, i, 0, k)->co);
- copy_v3_v3(co1, mesh_vert(vm0, i, 0, k - 1)->co);
- copy_v3_v3(co2, mesh_vert(vm0, i, 0, k + 1)->co);
-
- add_v3_v3v3(acc, co1, co2);
- madd_v3_v3fl(acc, co, -2.0f);
- madd_v3_v3fl(co, acc, -1.0f / 6.0f);
-
- copy_v3_v3(mesh_vert_canon(vm1, i, 0, 2 * k)->co, co);
- }
- }
- /* now do odd ones in output mesh, based on even ones */
- bndv = vm1->boundstart;
- for (i = 0; i < n; i++) {
- for (k = 1; k < ns1; k += 2) {
- get_profile_point(bp, &bndv->profile, k, ns1, co);
- copy_v3_v3(co1, mesh_vert_canon(vm1, i, 0, k - 1)->co);
- copy_v3_v3(co2, mesh_vert_canon(vm1, i, 0, k + 1)->co);
-
- add_v3_v3v3(acc, co1, co2);
- madd_v3_v3fl(acc, co, -2.0f);
- madd_v3_v3fl(co, acc, -1.0f / 6.0f);
-
- copy_v3_v3(mesh_vert_canon(vm1, i, 0, k)->co, co);
- }
- bndv = bndv->next;
- }
- vmesh_copy_equiv_verts(vm1);
-
- /* Copy adjusted verts back into vm0 */
- for (i = 0; i < n; i++) {
- for (k = 0; k < ns0; k++) {
- copy_v3_v3(mesh_vert(vm0, i, 0, k)->co,
- mesh_vert(vm1, i, 0, 2 * k)->co);
- }
- }
-
- vmesh_copy_equiv_verts(vm0);
-
- /* Now we do the internal vertices, using standard Catmull-Clark
- * and assuming all boundary vertices have valence 4 */
-
- /* The new face vertices */
- for (i = 0; i < n; i++) {
- for (j = 0; j < ns20; j++) {
- for (k = 0; k < ns20; k++) {
- /* face up and right from (j, k) */
- avg4(co,
- mesh_vert(vm0, i, j, k),
- mesh_vert(vm0, i, j, k + 1),
- mesh_vert(vm0, i, j + 1, k),
- mesh_vert(vm0, i, j + 1, k + 1));
- copy_v3_v3(mesh_vert(vm1, i, 2 * j + 1, 2 * k + 1)->co, co);
- }
- }
- }
-
- /* The new vertical edge vertices */
- for (i = 0; i < n; i++) {
- for (j = 0; j < ns20; j++) {
- for (k = 1; k <= ns20; k++) {
- /* vertical edge between (j, k) and (j+1, k) */
- avg4(co, mesh_vert(vm0, i, j, k),
- mesh_vert(vm0, i, j + 1, k),
- mesh_vert_canon(vm1, i, 2 * j + 1, 2 * k - 1),
- mesh_vert_canon(vm1, i, 2 * j + 1, 2 * k + 1));
- copy_v3_v3(mesh_vert(vm1, i, 2 * j + 1, 2 * k)->co, co);
- }
- }
- }
-
- /* The new horizontal edge vertices */
- for (i = 0; i < n; i++) {
- for (j = 1; j < ns20; j++) {
- for (k = 0; k < ns20; k++) {
- /* horizontal edge between (j, k) and (j, k+1) */
- avg4(co, mesh_vert(vm0, i, j, k),
- mesh_vert(vm0, i, j, k + 1),
- mesh_vert_canon(vm1, i, 2 * j - 1, 2 * k + 1),
- mesh_vert_canon(vm1, i, 2 * j + 1, 2 * k + 1));
- copy_v3_v3(mesh_vert(vm1, i, 2 * j, 2 * k + 1)->co, co);
- }
- }
- }
-
- /* The new vertices, not on border */
- gamma = 0.25f;
- beta = -gamma;
- for (i = 0; i < n; i++) {
- for (j = 1; j < ns20; j++) {
- for (k = 1; k <= ns20; k++) {
- /* co1 = centroid of adjacent new edge verts */
- avg4(co1, mesh_vert_canon(vm1, i, 2 * j, 2 * k - 1),
- mesh_vert_canon(vm1, i, 2 * j, 2 * k + 1),
- mesh_vert_canon(vm1, i, 2 * j - 1, 2 * k),
- mesh_vert_canon(vm1, i, 2 * j + 1, 2 * k));
- /* co2 = centroid of adjacent new face verts */
- avg4(co2, mesh_vert_canon(vm1, i, 2 * j - 1, 2 * k - 1),
- mesh_vert_canon(vm1, i, 2 * j + 1, 2 * k - 1),
- mesh_vert_canon(vm1, i, 2 * j - 1, 2 * k + 1),
- mesh_vert_canon(vm1, i, 2 * j + 1, 2 * k + 1));
- /* combine with original vert with alpha, beta, gamma factors */
- copy_v3_v3(co, co1); /* alpha = 1.0 */
- madd_v3_v3fl(co, co2, beta);
- madd_v3_v3fl(co, mesh_vert(vm0, i, j, k)->co, gamma);
- copy_v3_v3(mesh_vert(vm1, i, 2 * j, 2 * k)->co, co);
- }
- }
- }
-
- vmesh_copy_equiv_verts(vm1);
-
- /* The center vertex is special */
- gamma = sabin_gamma(n);
- beta = -gamma;
- /* accumulate edge verts in co1, face verts in co2 */
- zero_v3(co1);
- zero_v3(co2);
- for (i = 0; i < n; i++) {
- add_v3_v3(co1, mesh_vert(vm1, i, ns0, ns0 - 1)->co);
- add_v3_v3(co2, mesh_vert(vm1, i, ns0 - 1, ns0 - 1)->co);
- add_v3_v3(co2, mesh_vert(vm1, i, ns0 - 1, ns0 + 1)->co);
- }
- copy_v3_v3(co, co1);
- mul_v3_fl(co, 1.0f / (float)n);
- madd_v3_v3fl(co, co2, beta / (2.0f * (float)n));
- madd_v3_v3fl(co, mesh_vert(vm0, 0, ns20, ns20)->co, gamma);
- for (i = 0; i < n; i++) {
- copy_v3_v3(mesh_vert(vm1, i, ns0, ns0)->co, co);
- }
-
- /* Final step: sample the boundary vertices at even parameter spacing */
- bndv = vm1->boundstart;
- for (i = 0; i < n; i++) {
- inext = (i + 1) % n;
- for (k = 0; k <= ns1; k++) {
- get_profile_point(bp, &bndv->profile, k, ns1, co);
- copy_v3_v3(mesh_vert(vm1, i, 0, k)->co, co);
- if (k >= ns0 && k < ns1) {
- copy_v3_v3(mesh_vert(vm1, inext, ns1 - k, 0)->co, co);
- }
- }
- bndv = bndv->next;
- }
-
- return vm1;
+ int n, ns0, ns20, ns1;
+ int i, j, k, inext;
+ float co[3], co1[3], co2[3], acc[3];
+ float beta, gamma;
+ VMesh *vm1;
+ BoundVert *bndv;
+
+ n = vm0->count;
+ ns0 = vm0->seg;
+ ns20 = ns0 / 2;
+ BLI_assert(ns0 % 2 == 0);
+ ns1 = 2 * ns0;
+ vm1 = new_adj_vmesh(bp->mem_arena, n, ns1, vm0->boundstart);
+
+ /* First we adjust the boundary vertices of the input mesh, storing in output mesh */
+ for (i = 0; i < n; i++) {
+ copy_v3_v3(mesh_vert(vm1, i, 0, 0)->co, mesh_vert(vm0, i, 0, 0)->co);
+ for (k = 1; k < ns0; k++) {
+ /* smooth boundary rule */
+ copy_v3_v3(co, mesh_vert(vm0, i, 0, k)->co);
+ copy_v3_v3(co1, mesh_vert(vm0, i, 0, k - 1)->co);
+ copy_v3_v3(co2, mesh_vert(vm0, i, 0, k + 1)->co);
+
+ add_v3_v3v3(acc, co1, co2);
+ madd_v3_v3fl(acc, co, -2.0f);
+ madd_v3_v3fl(co, acc, -1.0f / 6.0f);
+
+ copy_v3_v3(mesh_vert_canon(vm1, i, 0, 2 * k)->co, co);
+ }
+ }
+ /* now do odd ones in output mesh, based on even ones */
+ bndv = vm1->boundstart;
+ for (i = 0; i < n; i++) {
+ for (k = 1; k < ns1; k += 2) {
+ get_profile_point(bp, &bndv->profile, k, ns1, co);
+ copy_v3_v3(co1, mesh_vert_canon(vm1, i, 0, k - 1)->co);
+ copy_v3_v3(co2, mesh_vert_canon(vm1, i, 0, k + 1)->co);
+
+ add_v3_v3v3(acc, co1, co2);
+ madd_v3_v3fl(acc, co, -2.0f);
+ madd_v3_v3fl(co, acc, -1.0f / 6.0f);
+
+ copy_v3_v3(mesh_vert_canon(vm1, i, 0, k)->co, co);
+ }
+ bndv = bndv->next;
+ }
+ vmesh_copy_equiv_verts(vm1);
+
+ /* Copy adjusted verts back into vm0 */
+ for (i = 0; i < n; i++) {
+ for (k = 0; k < ns0; k++) {
+ copy_v3_v3(mesh_vert(vm0, i, 0, k)->co, mesh_vert(vm1, i, 0, 2 * k)->co);
+ }
+ }
+
+ vmesh_copy_equiv_verts(vm0);
+
+ /* Now we do the internal vertices, using standard Catmull-Clark
+ * and assuming all boundary vertices have valence 4 */
+
+ /* The new face vertices */
+ for (i = 0; i < n; i++) {
+ for (j = 0; j < ns20; j++) {
+ for (k = 0; k < ns20; k++) {
+ /* face up and right from (j, k) */
+ avg4(co,
+ mesh_vert(vm0, i, j, k),
+ mesh_vert(vm0, i, j, k + 1),
+ mesh_vert(vm0, i, j + 1, k),
+ mesh_vert(vm0, i, j + 1, k + 1));
+ copy_v3_v3(mesh_vert(vm1, i, 2 * j + 1, 2 * k + 1)->co, co);
+ }
+ }
+ }
+
+ /* The new vertical edge vertices */
+ for (i = 0; i < n; i++) {
+ for (j = 0; j < ns20; j++) {
+ for (k = 1; k <= ns20; k++) {
+ /* vertical edge between (j, k) and (j+1, k) */
+ avg4(co,
+ mesh_vert(vm0, i, j, k),
+ mesh_vert(vm0, i, j + 1, k),
+ mesh_vert_canon(vm1, i, 2 * j + 1, 2 * k - 1),
+ mesh_vert_canon(vm1, i, 2 * j + 1, 2 * k + 1));
+ copy_v3_v3(mesh_vert(vm1, i, 2 * j + 1, 2 * k)->co, co);
+ }
+ }
+ }
+
+ /* The new horizontal edge vertices */
+ for (i = 0; i < n; i++) {
+ for (j = 1; j < ns20; j++) {
+ for (k = 0; k < ns20; k++) {
+ /* horizontal edge between (j, k) and (j, k+1) */
+ avg4(co,
+ mesh_vert(vm0, i, j, k),
+ mesh_vert(vm0, i, j, k + 1),
+ mesh_vert_canon(vm1, i, 2 * j - 1, 2 * k + 1),
+ mesh_vert_canon(vm1, i, 2 * j + 1, 2 * k + 1));
+ copy_v3_v3(mesh_vert(vm1, i, 2 * j, 2 * k + 1)->co, co);
+ }
+ }
+ }
+
+ /* The new vertices, not on border */
+ gamma = 0.25f;
+ beta = -gamma;
+ for (i = 0; i < n; i++) {
+ for (j = 1; j < ns20; j++) {
+ for (k = 1; k <= ns20; k++) {
+ /* co1 = centroid of adjacent new edge verts */
+ avg4(co1,
+ mesh_vert_canon(vm1, i, 2 * j, 2 * k - 1),
+ mesh_vert_canon(vm1, i, 2 * j, 2 * k + 1),
+ mesh_vert_canon(vm1, i, 2 * j - 1, 2 * k),
+ mesh_vert_canon(vm1, i, 2 * j + 1, 2 * k));
+ /* co2 = centroid of adjacent new face verts */
+ avg4(co2,
+ mesh_vert_canon(vm1, i, 2 * j - 1, 2 * k - 1),
+ mesh_vert_canon(vm1, i, 2 * j + 1, 2 * k - 1),
+ mesh_vert_canon(vm1, i, 2 * j - 1, 2 * k + 1),
+ mesh_vert_canon(vm1, i, 2 * j + 1, 2 * k + 1));
+ /* combine with original vert with alpha, beta, gamma factors */
+ copy_v3_v3(co, co1); /* alpha = 1.0 */
+ madd_v3_v3fl(co, co2, beta);
+ madd_v3_v3fl(co, mesh_vert(vm0, i, j, k)->co, gamma);
+ copy_v3_v3(mesh_vert(vm1, i, 2 * j, 2 * k)->co, co);
+ }
+ }
+ }
+
+ vmesh_copy_equiv_verts(vm1);
+
+ /* The center vertex is special */
+ gamma = sabin_gamma(n);
+ beta = -gamma;
+ /* accumulate edge verts in co1, face verts in co2 */
+ zero_v3(co1);
+ zero_v3(co2);
+ for (i = 0; i < n; i++) {
+ add_v3_v3(co1, mesh_vert(vm1, i, ns0, ns0 - 1)->co);
+ add_v3_v3(co2, mesh_vert(vm1, i, ns0 - 1, ns0 - 1)->co);
+ add_v3_v3(co2, mesh_vert(vm1, i, ns0 - 1, ns0 + 1)->co);
+ }
+ copy_v3_v3(co, co1);
+ mul_v3_fl(co, 1.0f / (float)n);
+ madd_v3_v3fl(co, co2, beta / (2.0f * (float)n));
+ madd_v3_v3fl(co, mesh_vert(vm0, 0, ns20, ns20)->co, gamma);
+ for (i = 0; i < n; i++) {
+ copy_v3_v3(mesh_vert(vm1, i, ns0, ns0)->co, co);
+ }
+
+ /* Final step: sample the boundary vertices at even parameter spacing */
+ bndv = vm1->boundstart;
+ for (i = 0; i < n; i++) {
+ inext = (i + 1) % n;
+ for (k = 0; k <= ns1; k++) {
+ get_profile_point(bp, &bndv->profile, k, ns1, co);
+ copy_v3_v3(mesh_vert(vm1, i, 0, k)->co, co);
+ if (k >= ns0 && k < ns1) {
+ copy_v3_v3(mesh_vert(vm1, inext, ns1 - k, 0)->co, co);
+ }
+ }
+ bndv = bndv->next;
+ }
+
+ return vm1;
}
/* Special case for cube corner, when r is PRO_SQUARE_R, meaning straight sides */
static VMesh *make_cube_corner_square(MemArena *mem_arena, int nseg)
{
- VMesh *vm;
- float co[3];
- int i, j, k, ns2;
-
- ns2 = nseg / 2;
- vm = new_adj_vmesh(mem_arena, 3, nseg, NULL);
- vm->count = 0; // reset, so following loop will end up with correct count
- for (i = 0; i < 3; i++) {
- zero_v3(co);
- co[i] = 1.0f;
- add_new_bound_vert(mem_arena, vm, co);
- }
- for (i = 0; i < 3; i++) {
- for (j = 0; j <= ns2; j++) {
- for (k = 0; k <= ns2; k++) {
- if (!is_canon(vm, i, j, k)) {
- continue;
- }
- co[i] = 1.0f;
- co[(i + 1) % 3] = (float)k * 2.0f / (float)nseg;
- co[(i + 2) % 3] = (float)j * 2.0f / (float)nseg;
- copy_v3_v3(mesh_vert(vm, i, j, k)->co, co);
- }
- }
- }
- vmesh_copy_equiv_verts(vm);
- return vm;
+ VMesh *vm;
+ float co[3];
+ int i, j, k, ns2;
+
+ ns2 = nseg / 2;
+ vm = new_adj_vmesh(mem_arena, 3, nseg, NULL);
+ vm->count = 0; // reset, so following loop will end up with correct count
+ for (i = 0; i < 3; i++) {
+ zero_v3(co);
+ co[i] = 1.0f;
+ add_new_bound_vert(mem_arena, vm, co);
+ }
+ for (i = 0; i < 3; i++) {
+ for (j = 0; j <= ns2; j++) {
+ for (k = 0; k <= ns2; k++) {
+ if (!is_canon(vm, i, j, k)) {
+ continue;
+ }
+ co[i] = 1.0f;
+ co[(i + 1) % 3] = (float)k * 2.0f / (float)nseg;
+ co[(i + 2) % 3] = (float)j * 2.0f / (float)nseg;
+ copy_v3_v3(mesh_vert(vm, i, j, k)->co, co);
+ }
+ }
+ }
+ vmesh_copy_equiv_verts(vm);
+ return vm;
}
/* Special case for cube corner, when r is PRO_SQUARE_IN_R, meaning inward
@@ -3593,42 +3630,41 @@ static VMesh *make_cube_corner_square(MemArena *mem_arena, int nseg)
* with a triangle in the middle for odd nseg */
static VMesh *make_cube_corner_square_in(MemArena *mem_arena, int nseg)
{
- VMesh *vm;
- float co[3];
- float b;
- int i, k, ns2, odd;
-
- ns2 = nseg / 2;
- odd = nseg % 2;
- vm = new_adj_vmesh(mem_arena, 3, nseg, NULL);
- vm->count = 0; // reset, so following loop will end up with correct count
- for (i = 0; i < 3; i++) {
- zero_v3(co);
- co[i] = 1.0f;
- add_new_bound_vert(mem_arena, vm, co);
- }
- if (odd) {
- b = 2.0f / (2.0f * (float)ns2 + (float)M_SQRT2);
- }
- else {
- b = 2.0f / (float)nseg;
- }
- for (i = 0; i < 3; i++) {
- for (k = 0; k <= ns2; k++) {
- co[i] = 1.0f - (float)k * b;
- co[(i + 1) % 3] = 0.0f;
- co[(i + 2) % 3] = 0.0f;
- copy_v3_v3(mesh_vert(vm, i, 0, k)->co, co);
- co[(i + 1) % 3] = 1.0f - (float)k * b;
- co[(i + 2) % 3] = 0.0f;
- co[i] = 0.0f;
- copy_v3_v3(mesh_vert(vm, i, 0, nseg - k)->co, co);
- }
- }
- return vm;
+ VMesh *vm;
+ float co[3];
+ float b;
+ int i, k, ns2, odd;
+
+ ns2 = nseg / 2;
+ odd = nseg % 2;
+ vm = new_adj_vmesh(mem_arena, 3, nseg, NULL);
+ vm->count = 0; // reset, so following loop will end up with correct count
+ for (i = 0; i < 3; i++) {
+ zero_v3(co);
+ co[i] = 1.0f;
+ add_new_bound_vert(mem_arena, vm, co);
+ }
+ if (odd) {
+ b = 2.0f / (2.0f * (float)ns2 + (float)M_SQRT2);
+ }
+ else {
+ b = 2.0f / (float)nseg;
+ }
+ for (i = 0; i < 3; i++) {
+ for (k = 0; k <= ns2; k++) {
+ co[i] = 1.0f - (float)k * b;
+ co[(i + 1) % 3] = 0.0f;
+ co[(i + 2) % 3] = 0.0f;
+ copy_v3_v3(mesh_vert(vm, i, 0, k)->co, co);
+ co[(i + 1) % 3] = 1.0f - (float)k * b;
+ co[(i + 2) % 3] = 0.0f;
+ co[i] = 0.0f;
+ copy_v3_v3(mesh_vert(vm, i, 0, nseg - k)->co, co);
+ }
+ }
+ return vm;
}
-
/* Make a VMesh with nseg segments that covers the unit radius sphere octant
* with center at (0,0,0).
* This has BoundVerts at (1,0,0), (0,1,0) and (0,0,1), with quarter circle arcs
@@ -3636,248 +3672,247 @@ static VMesh *make_cube_corner_square_in(MemArena *mem_arena, int nseg)
*/
static VMesh *make_cube_corner_adj_vmesh(BevelParams *bp)
{
- MemArena *mem_arena = bp->mem_arena;
- int nseg = bp->seg;
- float r = bp->pro_super_r;
- VMesh *vm0, *vm1;
- BoundVert *bndv;
- int i, j, k, ns2;
- float co[3], coc[3];
-
- if (r == PRO_SQUARE_R) {
- return make_cube_corner_square(mem_arena, nseg);
- }
- else if (r == PRO_SQUARE_IN_R) {
- return make_cube_corner_square_in(mem_arena, nseg);
- }
-
- /* initial mesh has 3 sides, 2 segments */
- vm0 = new_adj_vmesh(mem_arena, 3, 2, NULL);
- vm0->count = 0; // reset, so following loop will end up with correct count
- for (i = 0; i < 3; i++) {
- zero_v3(co);
- co[i] = 1.0f;
- add_new_bound_vert(mem_arena, vm0, co);
- }
- bndv = vm0->boundstart;
- for (i = 0; i < 3; i++) {
- /* Get point, 1/2 of the way around profile, on arc between this and next */
- coc[i] = 1.0f;
- coc[(i + 1) % 3] = 1.0f;
- coc[(i + 2) % 3] = 0.0f;
- bndv->profile.super_r = r;
- copy_v3_v3(bndv->profile.coa, bndv->nv.co);
- copy_v3_v3(bndv->profile.cob, bndv->next->nv.co);
- copy_v3_v3(bndv->profile.midco, coc);
- copy_v3_v3(mesh_vert(vm0, i, 0, 0)->co, bndv->profile.coa);
- copy_v3_v3(bndv->profile.plane_co, bndv->profile.coa);
- cross_v3_v3v3(bndv->profile.plane_no, bndv->profile.coa, bndv->profile.cob);
- copy_v3_v3(bndv->profile.proj_dir, bndv->profile.plane_no);
- calculate_profile(bp, bndv);
- get_profile_point(bp, &bndv->profile, 1, 2, mesh_vert(vm0, i, 0, 1)->co);
-
- bndv = bndv->next;
- }
- /* center vertex */
- copy_v3_fl(co, M_SQRT1_3);
-
- if (nseg > 2) {
- if (r > 1.5f) {
- mul_v3_fl(co, 1.4f);
- }
- else if (r < 0.75f) {
- mul_v3_fl(co, 0.6f);
- }
- }
- copy_v3_v3(mesh_vert(vm0, 0, 1, 1)->co, co);
-
- vmesh_copy_equiv_verts(vm0);
-
- vm1 = vm0;
- while (vm1->seg < nseg) {
- vm1 = cubic_subdiv(bp, vm1);
- }
- if (vm1->seg != nseg) {
- vm1 = interp_vmesh(bp, vm1, nseg);
- }
-
- /* Now snap each vertex to the superellipsoid */
- ns2 = nseg / 2;
- for (i = 0; i < 3; i++) {
- for (j = 0; j <= ns2; j++) {
- for (k = 0; k <= nseg; k++) {
- snap_to_superellipsoid(mesh_vert(vm1, i, j, k)->co, r, false);
- }
- }
- }
-
- return vm1;
+ MemArena *mem_arena = bp->mem_arena;
+ int nseg = bp->seg;
+ float r = bp->pro_super_r;
+ VMesh *vm0, *vm1;
+ BoundVert *bndv;
+ int i, j, k, ns2;
+ float co[3], coc[3];
+
+ if (r == PRO_SQUARE_R) {
+ return make_cube_corner_square(mem_arena, nseg);
+ }
+ else if (r == PRO_SQUARE_IN_R) {
+ return make_cube_corner_square_in(mem_arena, nseg);
+ }
+
+ /* initial mesh has 3 sides, 2 segments */
+ vm0 = new_adj_vmesh(mem_arena, 3, 2, NULL);
+ vm0->count = 0; // reset, so following loop will end up with correct count
+ for (i = 0; i < 3; i++) {
+ zero_v3(co);
+ co[i] = 1.0f;
+ add_new_bound_vert(mem_arena, vm0, co);
+ }
+ bndv = vm0->boundstart;
+ for (i = 0; i < 3; i++) {
+ /* Get point, 1/2 of the way around profile, on arc between this and next */
+ coc[i] = 1.0f;
+ coc[(i + 1) % 3] = 1.0f;
+ coc[(i + 2) % 3] = 0.0f;
+ bndv->profile.super_r = r;
+ copy_v3_v3(bndv->profile.coa, bndv->nv.co);
+ copy_v3_v3(bndv->profile.cob, bndv->next->nv.co);
+ copy_v3_v3(bndv->profile.midco, coc);
+ copy_v3_v3(mesh_vert(vm0, i, 0, 0)->co, bndv->profile.coa);
+ copy_v3_v3(bndv->profile.plane_co, bndv->profile.coa);
+ cross_v3_v3v3(bndv->profile.plane_no, bndv->profile.coa, bndv->profile.cob);
+ copy_v3_v3(bndv->profile.proj_dir, bndv->profile.plane_no);
+ calculate_profile(bp, bndv);
+ get_profile_point(bp, &bndv->profile, 1, 2, mesh_vert(vm0, i, 0, 1)->co);
+
+ bndv = bndv->next;
+ }
+ /* center vertex */
+ copy_v3_fl(co, M_SQRT1_3);
+
+ if (nseg > 2) {
+ if (r > 1.5f) {
+ mul_v3_fl(co, 1.4f);
+ }
+ else if (r < 0.75f) {
+ mul_v3_fl(co, 0.6f);
+ }
+ }
+ copy_v3_v3(mesh_vert(vm0, 0, 1, 1)->co, co);
+
+ vmesh_copy_equiv_verts(vm0);
+
+ vm1 = vm0;
+ while (vm1->seg < nseg) {
+ vm1 = cubic_subdiv(bp, vm1);
+ }
+ if (vm1->seg != nseg) {
+ vm1 = interp_vmesh(bp, vm1, nseg);
+ }
+
+ /* Now snap each vertex to the superellipsoid */
+ ns2 = nseg / 2;
+ for (i = 0; i < 3; i++) {
+ for (j = 0; j <= ns2; j++) {
+ for (k = 0; k <= nseg; k++) {
+ snap_to_superellipsoid(mesh_vert(vm1, i, j, k)->co, r, false);
+ }
+ }
+ }
+
+ return vm1;
}
/* Is this a good candidate for using tri_corner_adj_vmesh? */
static int tri_corner_test(BevelParams *bp, BevVert *bv)
{
- float ang, totang, angdiff;
- EdgeHalf *e;
- int i;
- int in_plane_e = 0;
-
- if (bp->vertex_only) {
- return -1;
- }
- if (bv->vmesh->count != 3) {
- return 0;
- }
- totang = 0.0f;
- for (i = 0; i < bv->edgecount; i++) {
- e = &bv->edges[i];
- ang = BM_edge_calc_face_angle_signed_ex(e->e, 0.0f);
- if (ang <= M_PI_4) {
- in_plane_e++;
- }
- else if (ang >= 3.0f * (float) M_PI_4) {
- return -1;
- }
- totang += ang;
- }
- if (in_plane_e != bv->edgecount - 3) {
- return -1;
- }
- angdiff = fabsf(totang - 3.0f * (float)M_PI_2);
- if ((bp->pro_super_r == PRO_SQUARE_R && angdiff > (float)M_PI / 16.0f) ||
- (angdiff > (float)M_PI_4))
- {
- return -1;
- }
- if (bv->edgecount != 3 || bv->selcount != 3) {
- return 0;
- }
- return 1;
+ float ang, totang, angdiff;
+ EdgeHalf *e;
+ int i;
+ int in_plane_e = 0;
+
+ if (bp->vertex_only) {
+ return -1;
+ }
+ if (bv->vmesh->count != 3) {
+ return 0;
+ }
+ totang = 0.0f;
+ for (i = 0; i < bv->edgecount; i++) {
+ e = &bv->edges[i];
+ ang = BM_edge_calc_face_angle_signed_ex(e->e, 0.0f);
+ if (ang <= M_PI_4) {
+ in_plane_e++;
+ }
+ else if (ang >= 3.0f * (float)M_PI_4) {
+ return -1;
+ }
+ totang += ang;
+ }
+ if (in_plane_e != bv->edgecount - 3) {
+ return -1;
+ }
+ angdiff = fabsf(totang - 3.0f * (float)M_PI_2);
+ if ((bp->pro_super_r == PRO_SQUARE_R && angdiff > (float)M_PI / 16.0f) ||
+ (angdiff > (float)M_PI_4)) {
+ return -1;
+ }
+ if (bv->edgecount != 3 || bv->selcount != 3) {
+ return 0;
+ }
+ return 1;
}
static VMesh *tri_corner_adj_vmesh(BevelParams *bp, BevVert *bv)
{
- int i, j, k, ns, ns2;
- float co0[3], co1[3], co2[3];
- float mat[4][4], v[4];
- VMesh *vm;
- BoundVert *bndv;
-
- /*BLI_assert(bv->edgecount == 3 && bv->selcount == 3); Add support for in plane edges */
- bndv = bv->vmesh->boundstart;
- copy_v3_v3(co0, bndv->nv.co);
- bndv = bndv->next;
- copy_v3_v3(co1, bndv->nv.co);
- bndv = bndv->next;
- copy_v3_v3(co2, bndv->nv.co);
- make_unit_cube_map(co0, co1, co2, bv->v->co, mat);
- ns = bp->seg;
- ns2 = ns / 2;
- vm = make_cube_corner_adj_vmesh(bp);
- for (i = 0; i < 3; i++) {
- for (j = 0; j <= ns2; j++) {
- for (k = 0; k <= ns; k++) {
- copy_v3_v3(v, mesh_vert(vm, i, j, k)->co);
- v[3] = 1.0f;
- mul_m4_v4(mat, v);
- copy_v3_v3(mesh_vert(vm, i, j, k)->co, v);
- }
- }
- }
-
- return vm;
+ int i, j, k, ns, ns2;
+ float co0[3], co1[3], co2[3];
+ float mat[4][4], v[4];
+ VMesh *vm;
+ BoundVert *bndv;
+
+ /*BLI_assert(bv->edgecount == 3 && bv->selcount == 3); Add support for in plane edges */
+ bndv = bv->vmesh->boundstart;
+ copy_v3_v3(co0, bndv->nv.co);
+ bndv = bndv->next;
+ copy_v3_v3(co1, bndv->nv.co);
+ bndv = bndv->next;
+ copy_v3_v3(co2, bndv->nv.co);
+ make_unit_cube_map(co0, co1, co2, bv->v->co, mat);
+ ns = bp->seg;
+ ns2 = ns / 2;
+ vm = make_cube_corner_adj_vmesh(bp);
+ for (i = 0; i < 3; i++) {
+ for (j = 0; j <= ns2; j++) {
+ for (k = 0; k <= ns; k++) {
+ copy_v3_v3(v, mesh_vert(vm, i, j, k)->co);
+ v[3] = 1.0f;
+ mul_m4_v4(mat, v);
+ copy_v3_v3(mesh_vert(vm, i, j, k)->co, v);
+ }
+ }
+ }
+
+ return vm;
}
static VMesh *adj_vmesh(BevelParams *bp, BevVert *bv)
{
- int n, ns, i;
- VMesh *vm0, *vm1;
- float co[3], coa[3], cob[3], dir[3];
- BoundVert *bndv;
- MemArena *mem_arena = bp->mem_arena;
- float r, p, fullness;
- /* best fullness for circles, segs = 2,4,6,8,10 */
+ int n, ns, i;
+ VMesh *vm0, *vm1;
+ float co[3], coa[3], cob[3], dir[3];
+ BoundVert *bndv;
+ MemArena *mem_arena = bp->mem_arena;
+ float r, p, fullness;
+ /* best fullness for circles, segs = 2,4,6,8,10 */
#define CIRCLE_FULLNESS_SEGS 11
- static const float circle_fullness[CIRCLE_FULLNESS_SEGS] = {
- 0.0f, /* nsegs ==1 */
- 0.559f, /* 2 */
- 0.642f, /* 3 */
- 0.551f, /* 4 */
- 0.646f, /* 5 */
- 0.624f, /* 6 */
- 0.646f, /* 7 */
- 0.619f, /* 8 */
- 0.647f, /* 9 */
- 0.639f, /* 10 */
- 0.647f, /* 11 */
- };
-
- n = bv->vmesh->count;
-
- /* Same bevel as that of 3 edges of vert in a cube */
- if (n == 3 && tri_corner_test(bp, bv) != -1 && bp->pro_super_r != PRO_SQUARE_IN_R) {
- return tri_corner_adj_vmesh(bp, bv);
- }
-
- /* First construct an initial control mesh, with nseg==2 */
- ns = bv->vmesh->seg;
- vm0 = new_adj_vmesh(mem_arena, n, 2, bv->vmesh->boundstart);
-
- bndv = vm0->boundstart;
- zero_v3(co);
- for (i = 0; i < n; i++) {
- /* Boundaries just divide input polygon edges into 2 even segments */
- copy_v3_v3(mesh_vert(vm0, i, 0, 0)->co, bndv->nv.co);
- get_profile_point(bp, &bndv->profile, 1, 2, mesh_vert(vm0, i, 0, 1)->co);
- add_v3_v3(co, bndv->nv.co);
- bndv = bndv->next;
- }
- /* To place center vertex:
- * coa is original vertex
- * co is centroid of boundary corners
- * cob is reflection of coa in across co.
- * Calculate 'fullness' = fraction of way
- * from co to coa (if positive) or to cob (if negative).
- */
- copy_v3_v3(coa, bv->v->co);
- mul_v3_fl(co, 1.0f / (float)n);
- sub_v3_v3v3(cob, co, coa);
- add_v3_v3(cob, co);
-
- /* An offline optimization process found fullness that let to closest fit to sphere as
- * a function of r and ns (for case of cube corner) */
- r = bp->pro_super_r;
- p = bp->profile;
- if (r == PRO_LINE_R) {
- fullness = 0.0f;
- }
- else if (r == PRO_CIRCLE_R && ns > 0 && ns <= CIRCLE_FULLNESS_SEGS) {
- fullness = circle_fullness[ns - 1];
- }
- else {
- /* linear regression fit found best linear function, separately for even/odd segs */
- if (ns % 2 == 0) {
- fullness = 2.4506f * p - 0.00000300f * ns - 0.6266f;
- }
- else {
- fullness = 2.3635f * p + 0.000152f * ns - 0.6060f;
- }
- }
- sub_v3_v3v3(dir, coa, co);
- if (len_squared_v3(dir) > BEVEL_EPSILON_SQ) {
- madd_v3_v3fl(co, dir, fullness);
- }
- copy_v3_v3(mesh_vert(vm0, 0, 1, 1)->co, co);
- vmesh_copy_equiv_verts(vm0);
-
- vm1 = vm0;
- do {
- vm1 = cubic_subdiv(bp, vm1);
- } while (vm1->seg < ns);
- if (vm1->seg != ns) {
- vm1 = interp_vmesh(bp, vm1, ns);
- }
- return vm1;
+ static const float circle_fullness[CIRCLE_FULLNESS_SEGS] = {
+ 0.0f, /* nsegs ==1 */
+ 0.559f, /* 2 */
+ 0.642f, /* 3 */
+ 0.551f, /* 4 */
+ 0.646f, /* 5 */
+ 0.624f, /* 6 */
+ 0.646f, /* 7 */
+ 0.619f, /* 8 */
+ 0.647f, /* 9 */
+ 0.639f, /* 10 */
+ 0.647f, /* 11 */
+ };
+
+ n = bv->vmesh->count;
+
+ /* Same bevel as that of 3 edges of vert in a cube */
+ if (n == 3 && tri_corner_test(bp, bv) != -1 && bp->pro_super_r != PRO_SQUARE_IN_R) {
+ return tri_corner_adj_vmesh(bp, bv);
+ }
+
+ /* First construct an initial control mesh, with nseg==2 */
+ ns = bv->vmesh->seg;
+ vm0 = new_adj_vmesh(mem_arena, n, 2, bv->vmesh->boundstart);
+
+ bndv = vm0->boundstart;
+ zero_v3(co);
+ for (i = 0; i < n; i++) {
+ /* Boundaries just divide input polygon edges into 2 even segments */
+ copy_v3_v3(mesh_vert(vm0, i, 0, 0)->co, bndv->nv.co);
+ get_profile_point(bp, &bndv->profile, 1, 2, mesh_vert(vm0, i, 0, 1)->co);
+ add_v3_v3(co, bndv->nv.co);
+ bndv = bndv->next;
+ }
+ /* To place center vertex:
+ * coa is original vertex
+ * co is centroid of boundary corners
+ * cob is reflection of coa in across co.
+ * Calculate 'fullness' = fraction of way
+ * from co to coa (if positive) or to cob (if negative).
+ */
+ copy_v3_v3(coa, bv->v->co);
+ mul_v3_fl(co, 1.0f / (float)n);
+ sub_v3_v3v3(cob, co, coa);
+ add_v3_v3(cob, co);
+
+ /* An offline optimization process found fullness that let to closest fit to sphere as
+ * a function of r and ns (for case of cube corner) */
+ r = bp->pro_super_r;
+ p = bp->profile;
+ if (r == PRO_LINE_R) {
+ fullness = 0.0f;
+ }
+ else if (r == PRO_CIRCLE_R && ns > 0 && ns <= CIRCLE_FULLNESS_SEGS) {
+ fullness = circle_fullness[ns - 1];
+ }
+ else {
+ /* linear regression fit found best linear function, separately for even/odd segs */
+ if (ns % 2 == 0) {
+ fullness = 2.4506f * p - 0.00000300f * ns - 0.6266f;
+ }
+ else {
+ fullness = 2.3635f * p + 0.000152f * ns - 0.6060f;
+ }
+ }
+ sub_v3_v3v3(dir, coa, co);
+ if (len_squared_v3(dir) > BEVEL_EPSILON_SQ) {
+ madd_v3_v3fl(co, dir, fullness);
+ }
+ copy_v3_v3(mesh_vert(vm0, 0, 1, 1)->co, co);
+ vmesh_copy_equiv_verts(vm0);
+
+ vm1 = vm0;
+ do {
+ vm1 = cubic_subdiv(bp, vm1);
+ } while (vm1->seg < ns);
+ if (vm1->seg != ns) {
+ vm1 = interp_vmesh(bp, vm1, ns);
+ }
+ return vm1;
}
/* Snap co to the closest point on the profile for vpipe projected onto the plane
@@ -3886,37 +3921,37 @@ static VMesh *adj_vmesh(BevelParams *bp, BevVert *bv)
* or to the midpoint of the profile; do so if midline is true. */
static void snap_to_pipe_profile(BoundVert *vpipe, bool midline, float co[3])
{
- float va[3], vb[3], edir[3], va0[3], vb0[3], vmid0[3];
- float plane[4], m[4][4], minv[4][4], p[3], snap[3];
- Profile *pro = &vpipe->profile;
- EdgeHalf *e = vpipe->ebev;
-
- copy_v3_v3(va, pro->coa);
- copy_v3_v3(vb, pro->cob);
-
- sub_v3_v3v3(edir, e->e->v1->co, e->e->v2->co);
-
- plane_from_point_normal_v3(plane, co, edir);
- closest_to_plane_v3(va0, plane, va);
- closest_to_plane_v3(vb0, plane, vb);
- closest_to_plane_v3(vmid0, plane, pro->midco);
- if (make_unit_square_map(va0, vmid0, vb0, m)) {
- /* Transform co and project it onto superellipse */
- if (!invert_m4_m4(minv, m)) {
- /* shouldn't happen */
- BLI_assert(!"failed inverse during pipe profile snap");
- return;
- }
- mul_v3_m4v3(p, minv, co);
- snap_to_superellipsoid(p, pro->super_r, midline);
- mul_v3_m4v3(snap, m, p);
- copy_v3_v3(co, snap);
- }
- else {
- /* planar case: just snap to line va0--vb0 */
- closest_to_line_segment_v3(p, co, va0, vb0);
- copy_v3_v3(co, p);
- }
+ float va[3], vb[3], edir[3], va0[3], vb0[3], vmid0[3];
+ float plane[4], m[4][4], minv[4][4], p[3], snap[3];
+ Profile *pro = &vpipe->profile;
+ EdgeHalf *e = vpipe->ebev;
+
+ copy_v3_v3(va, pro->coa);
+ copy_v3_v3(vb, pro->cob);
+
+ sub_v3_v3v3(edir, e->e->v1->co, e->e->v2->co);
+
+ plane_from_point_normal_v3(plane, co, edir);
+ closest_to_plane_v3(va0, plane, va);
+ closest_to_plane_v3(vb0, plane, vb);
+ closest_to_plane_v3(vmid0, plane, pro->midco);
+ if (make_unit_square_map(va0, vmid0, vb0, m)) {
+ /* Transform co and project it onto superellipse */
+ if (!invert_m4_m4(minv, m)) {
+ /* shouldn't happen */
+ BLI_assert(!"failed inverse during pipe profile snap");
+ return;
+ }
+ mul_v3_m4v3(p, minv, co);
+ snap_to_superellipsoid(p, pro->super_r, midline);
+ mul_v3_m4v3(snap, m, p);
+ copy_v3_v3(co, snap);
+ }
+ else {
+ /* planar case: just snap to line va0--vb0 */
+ closest_to_line_segment_v3(p, co, va0, vb0);
+ copy_v3_v3(co, p);
+ }
}
/* See pipe_test for conditions that make 'pipe'; vpipe is the return value from that.
@@ -3926,70 +3961,69 @@ static void snap_to_pipe_profile(BoundVert *vpipe, bool midline, float co[3])
* to snap to the midline on the pipe, not just to one plane or the other. */
static VMesh *pipe_adj_vmesh(BevelParams *bp, BevVert *bv, BoundVert *vpipe)
{
- int i, j, k, n, ns, ns2, ipipe1, ipipe2;
- VMesh *vm;
- bool even, midline;
-
- vm = adj_vmesh(bp, bv);
-
- /* Now snap all interior coordinates to be on the epipe profile */
- n = bv->vmesh->count;
- ns = bv->vmesh->seg;
- ns2 = ns / 2;
- even = (ns % 2) == 0;
- ipipe1 = vpipe->index;
- ipipe2 = vpipe->next->next->index;
- for (i = 0; i < n; i++) {
- for (j = 1; j <= ns2; j++) {
- for (k = 0; k <= ns2; k++) {
- if (!is_canon(vm, i, j, k)) {
- continue;
- }
- midline = even && k == ns2 &&
- ((i == 0 && j == ns2) || (i == ipipe1 || i == ipipe2));
- snap_to_pipe_profile(vpipe, midline, mesh_vert(vm, i, j, k)->co);
- }
- }
- }
-
- return vm;
+ int i, j, k, n, ns, ns2, ipipe1, ipipe2;
+ VMesh *vm;
+ bool even, midline;
+
+ vm = adj_vmesh(bp, bv);
+
+ /* Now snap all interior coordinates to be on the epipe profile */
+ n = bv->vmesh->count;
+ ns = bv->vmesh->seg;
+ ns2 = ns / 2;
+ even = (ns % 2) == 0;
+ ipipe1 = vpipe->index;
+ ipipe2 = vpipe->next->next->index;
+ for (i = 0; i < n; i++) {
+ for (j = 1; j <= ns2; j++) {
+ for (k = 0; k <= ns2; k++) {
+ if (!is_canon(vm, i, j, k)) {
+ continue;
+ }
+ midline = even && k == ns2 && ((i == 0 && j == ns2) || (i == ipipe1 || i == ipipe2));
+ snap_to_pipe_profile(vpipe, midline, mesh_vert(vm, i, j, k)->co);
+ }
+ }
+ }
+
+ return vm;
}
static void get_incident_edges(BMFace *f, BMVert *v, BMEdge **r_e1, BMEdge **r_e2)
{
- BMIter iter;
- BMEdge *e;
-
- *r_e1 = NULL;
- *r_e2 = NULL;
- if (!f) {
- return;
- }
- BM_ITER_ELEM (e, &iter, f, BM_EDGES_OF_FACE) {
- if (e->v1 == v || e->v2 == v) {
- if (*r_e1 == NULL) {
- *r_e1 = e;
- }
- else if (*r_e2 == NULL) {
- *r_e2 = e;
- }
- }
- }
+ BMIter iter;
+ BMEdge *e;
+
+ *r_e1 = NULL;
+ *r_e2 = NULL;
+ if (!f) {
+ return;
+ }
+ BM_ITER_ELEM (e, &iter, f, BM_EDGES_OF_FACE) {
+ if (e->v1 == v || e->v2 == v) {
+ if (*r_e1 == NULL) {
+ *r_e1 = e;
+ }
+ else if (*r_e2 == NULL) {
+ *r_e2 = e;
+ }
+ }
+ }
}
static BMEdge *find_closer_edge(float *co, BMEdge *e1, BMEdge *e2)
{
- float dsq1, dsq2;
-
- BLI_assert(e1 != NULL && e2 != NULL);
- dsq1 = dist_squared_to_line_segment_v3(co, e1->v1->co, e1->v2->co);
- dsq2 = dist_squared_to_line_segment_v3(co, e2->v1->co, e2->v2->co);
- if (dsq1 < dsq2) {
- return e1;
- }
- else {
- return e2;
- }
+ float dsq1, dsq2;
+
+ BLI_assert(e1 != NULL && e2 != NULL);
+ dsq1 = dist_squared_to_line_segment_v3(co, e1->v1->co, e1->v2->co);
+ dsq2 = dist_squared_to_line_segment_v3(co, e2->v1->co, e2->v2->co);
+ if (dsq1 < dsq2) {
+ return e1;
+ }
+ else {
+ return e2;
+ }
}
/* Snap co to the closest edge of face f. Return the edge in *r_snap_e,
@@ -3997,69 +4031,69 @@ static BMEdge *find_closer_edge(float *co, BMEdge *e1, BMEdge *e2)
* and the distance squared to the snap point as function return */
static float snap_face_dist_squared(float *co, BMFace *f, BMEdge **r_snap_e, float *r_snap_co)
{
- BMIter iter;
- BMEdge *beste = NULL;
- float d2, beste_d2;
- BMEdge *e;
- float closest[3];
-
- beste_d2 = 1e20;
- BM_ITER_ELEM(e, &iter, f, BM_EDGES_OF_FACE) {
- closest_to_line_segment_v3(closest, co, e->v1->co, e->v2->co);
- d2 = len_squared_v3v3(closest, co);
- if (d2 < beste_d2) {
- beste_d2 = d2;
- beste = e;
- copy_v3_v3(r_snap_co, closest);
- }
- }
- *r_snap_e = beste;
- return beste_d2;
+ BMIter iter;
+ BMEdge *beste = NULL;
+ float d2, beste_d2;
+ BMEdge *e;
+ float closest[3];
+
+ beste_d2 = 1e20;
+ BM_ITER_ELEM (e, &iter, f, BM_EDGES_OF_FACE) {
+ closest_to_line_segment_v3(closest, co, e->v1->co, e->v2->co);
+ d2 = len_squared_v3v3(closest, co);
+ if (d2 < beste_d2) {
+ beste_d2 = d2;
+ beste = e;
+ copy_v3_v3(r_snap_co, closest);
+ }
+ }
+ *r_snap_e = beste;
+ return beste_d2;
}
static void build_center_ngon(BevelParams *bp, BMesh *bm, BevVert *bv, int mat_nr)
{
- VMesh *vm = bv->vmesh;
- BoundVert *v;
- int i, ns2;
- BMFace *frep, *f;
- BMEdge *frep_e1, *frep_e2, *frep_e;
- BMVert **vv = NULL;
- BMFace **vf = NULL;
- BMEdge **ve = NULL;
- BLI_array_staticdeclare(vv, BM_DEFAULT_NGON_STACK_SIZE);
- BLI_array_staticdeclare(vf, BM_DEFAULT_NGON_STACK_SIZE);
- BLI_array_staticdeclare(ve, BM_DEFAULT_NGON_STACK_SIZE);
-
- ns2 = vm->seg / 2;
- if (bv->any_seam) {
- frep = boundvert_rep_face(vm->boundstart, NULL);
- get_incident_edges(frep, bv->v, &frep_e1, &frep_e2);
- }
- else {
- frep = NULL;
- frep_e1 = frep_e2 = NULL;
- }
- v = vm->boundstart;
- do {
- i = v->index;
- BLI_array_append(vv, mesh_vert(vm, i, ns2, ns2)->v);
- if (frep) {
- BLI_array_append(vf, frep);
- frep_e = find_closer_edge(mesh_vert(vm, i, ns2, ns2)->v->co, frep_e1, frep_e2);
- BLI_array_append(ve, v == vm->boundstart ? NULL : frep_e);
- }
- else {
- BLI_array_append(vf, boundvert_rep_face(v, NULL));
- BLI_array_append(ve, NULL);
- }
- } while ((v = v->next) != vm->boundstart);
- f = bev_create_ngon(bm, vv, BLI_array_len(vv), vf, frep, ve, mat_nr, true);
- record_face_kind(bp, f, F_VERT);
-
- BLI_array_free(vv);
- BLI_array_free(vf);
- BLI_array_free(ve);
+ VMesh *vm = bv->vmesh;
+ BoundVert *v;
+ int i, ns2;
+ BMFace *frep, *f;
+ BMEdge *frep_e1, *frep_e2, *frep_e;
+ BMVert **vv = NULL;
+ BMFace **vf = NULL;
+ BMEdge **ve = NULL;
+ BLI_array_staticdeclare(vv, BM_DEFAULT_NGON_STACK_SIZE);
+ BLI_array_staticdeclare(vf, BM_DEFAULT_NGON_STACK_SIZE);
+ BLI_array_staticdeclare(ve, BM_DEFAULT_NGON_STACK_SIZE);
+
+ ns2 = vm->seg / 2;
+ if (bv->any_seam) {
+ frep = boundvert_rep_face(vm->boundstart, NULL);
+ get_incident_edges(frep, bv->v, &frep_e1, &frep_e2);
+ }
+ else {
+ frep = NULL;
+ frep_e1 = frep_e2 = NULL;
+ }
+ v = vm->boundstart;
+ do {
+ i = v->index;
+ BLI_array_append(vv, mesh_vert(vm, i, ns2, ns2)->v);
+ if (frep) {
+ BLI_array_append(vf, frep);
+ frep_e = find_closer_edge(mesh_vert(vm, i, ns2, ns2)->v->co, frep_e1, frep_e2);
+ BLI_array_append(ve, v == vm->boundstart ? NULL : frep_e);
+ }
+ else {
+ BLI_array_append(vf, boundvert_rep_face(v, NULL));
+ BLI_array_append(ve, NULL);
+ }
+ } while ((v = v->next) != vm->boundstart);
+ f = bev_create_ngon(bm, vv, BLI_array_len(vv), vf, frep, ve, mat_nr, true);
+ record_face_kind(bp, f, F_VERT);
+
+ BLI_array_free(vv);
+ BLI_array_free(vf);
+ BLI_array_free(ve);
}
/* Special case of bevel_build_rings when tri-corner and profile is 0.
@@ -4068,46 +4102,46 @@ static void build_center_ngon(BevelParams *bp, BMesh *bm, BevVert *bv, int mat_n
* (i, 0, k) merged with (i+1, 0, ns-k) for k <= ns/2 */
static void build_square_in_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv, VMesh *vm1)
{
- int n, ns, ns2, odd, i, k;
- VMesh *vm;
-
- vm = bv->vmesh;
- n = vm->count;
- ns = vm->seg;
- ns2 = ns / 2;
- odd = ns % 2;
-
- for (i = 0; i < n; i++) {
- for (k = 1; k < ns; k++) {
- copy_v3_v3(mesh_vert(vm, i, 0, k)->co, mesh_vert(vm1, i, 0, k)->co);
- if (i > 0 && k <= ns2) {
- mesh_vert(vm, i, 0, k)->v = mesh_vert(vm, i - 1, 0, ns - k)->v;
- }
- else if (i == n - 1 && k > ns2) {
- mesh_vert(vm, i, 0, k)->v = mesh_vert(vm, 0, 0, ns - k)->v;
- }
- else {
- create_mesh_bmvert(bm, vm, i, 0, k, bv->v);
- }
- }
- }
- if (odd) {
- for (i = 0; i < n; i++) {
- mesh_vert(vm, i, ns2, ns2)->v = mesh_vert(vm, i, 0, ns2)->v;
- }
- build_center_ngon(bp, bm, bv, bp->mat_nr);
- }
+ int n, ns, ns2, odd, i, k;
+ VMesh *vm;
+
+ vm = bv->vmesh;
+ n = vm->count;
+ ns = vm->seg;
+ ns2 = ns / 2;
+ odd = ns % 2;
+
+ for (i = 0; i < n; i++) {
+ for (k = 1; k < ns; k++) {
+ copy_v3_v3(mesh_vert(vm, i, 0, k)->co, mesh_vert(vm1, i, 0, k)->co);
+ if (i > 0 && k <= ns2) {
+ mesh_vert(vm, i, 0, k)->v = mesh_vert(vm, i - 1, 0, ns - k)->v;
+ }
+ else if (i == n - 1 && k > ns2) {
+ mesh_vert(vm, i, 0, k)->v = mesh_vert(vm, 0, 0, ns - k)->v;
+ }
+ else {
+ create_mesh_bmvert(bm, vm, i, 0, k, bv->v);
+ }
+ }
+ }
+ if (odd) {
+ for (i = 0; i < n; i++) {
+ mesh_vert(vm, i, ns2, ns2)->v = mesh_vert(vm, i, 0, ns2)->v;
+ }
+ build_center_ngon(bp, bm, bv, bp->mat_nr);
+ }
}
/* copy whichever of a and b is closer to v into r */
static void closer_v3_v3v3v3(float r[3], float a[3], float b[3], float v[3])
{
- if (len_squared_v3v3(a, v) <= len_squared_v3v3(b, v)) {
- copy_v3_v3(r, a);
- }
- else {
- copy_v3_v3(r, b);
- }
+ if (len_squared_v3v3(a, v) <= len_squared_v3v3(b, v)) {
+ copy_v3_v3(r, a);
+ }
+ else {
+ copy_v3_v3(r, b);
+ }
}
/* Special case of VMesh when profile == 1 and there are 3 or more beveled edges.
@@ -4121,224 +4155,227 @@ static void closer_v3_v3v3v3(float r[3], float a[3], float b[3], float v[3])
*/
static VMesh *square_out_adj_vmesh(BevelParams *bp, BevVert *bv)
{
- int n, ns, ns2, odd, i, j, k, ikind, im1, clstride, iprev, akind;
- float bndco[3], dir1[3], dir2[3], co1[3], co2[3], meet1[3], meet2[3], v1co[3], v2co[3];
- float *on_edge_cur, *on_edge_prev, *p;
- float ns2inv, finalfrac, ang;
- BoundVert *bndv;
- EdgeHalf *e1, *e2;
- VMesh *vm;
- float *centerline;
- bool *cset, v1set, v2set;
-
- n = bv->vmesh->count;
- ns = bv->vmesh->seg;
- ns2 = ns / 2;
- odd = ns % 2;
- ns2inv = 1.0f / (float) ns2;
- vm = new_adj_vmesh(bp->mem_arena, n, ns, bv->vmesh->boundstart);
- clstride = 3 * (ns2 + 1);
- centerline = MEM_mallocN(clstride * n * sizeof(float), "bevel");
- cset = MEM_callocN(n * sizeof(bool), "bevel");
-
- /* find on_edge, place on bndv[i]'s elast where offset line would meet,
- * taking min-distance-to bv->v with position where next sector's offset line would meet */
- bndv = vm->boundstart;
- for (i = 0; i < n; i++) {
- copy_v3_v3(bndco, bndv->nv.co);
- e1 = bndv->efirst;
- e2 = bndv->elast;
- akind = 0;
- if (e1 && e2) {
- akind = edges_angle_kind(e1, e2, bv->v);
- }
- if (bndv->is_patch_start) {
- mid_v3_v3v3(centerline + clstride * i, bndv->nv.co, bndv->next->nv.co);
- cset[i] = true;
- bndv = bndv->next;
- i++;
- mid_v3_v3v3(centerline + clstride * i, bndv->nv.co, bndv->next->nv.co);
- cset[i] = true;
- bndv = bndv->next;
- i++;
- /* leave cset[i] where it was - probably false, unless i == n - 1 */
- }
- else if (bndv->is_arc_start) {
- e1 = bndv->efirst;
- e2 = bndv->next->efirst;
- copy_v3_v3(centerline + clstride * i, bndv->profile.midco);
- bndv = bndv->next;
- cset[i] = true;
- i++;
- /* leave cset[i] where it was - probably false, unless i == n - 1 */
- }
- else if (akind < 0) {
- sub_v3_v3v3(dir1, e1->e->v1->co, e1->e->v2->co);
- sub_v3_v3v3(dir2, e2->e->v1->co, e2->e->v2->co);
- add_v3_v3v3(co1, bndco, dir1);
- add_v3_v3v3(co2, bndco, dir2);
- /* intersect e1 with line through bndv parallel to e2 to get v1co */
- ikind = isect_line_line_v3(e1->e->v1->co, e1->e->v2->co, bndco, co2, meet1, meet2);
- if (ikind == 0) {
- v1set = false;
- }
- else {
- /* if the lines are skew (ikind == 2), want meet1 which is on e1 */
- copy_v3_v3(v1co, meet1);
- v1set = true;
- }
- /* intersect e2 with line through bndv parallel to e1 to get v2co */
- ikind = isect_line_line_v3(e2->e->v1->co, e2->e->v2->co, bndco, co1, meet1, meet2);
- if (ikind == 0) {
- v2set = false;
- }
- else {
- v2set = true;
- copy_v3_v3(v2co, meet1);
- }
-
- /* want on_edge[i] to be min dist to bv->v of v2co and the v1co of next iteration */
- on_edge_cur = centerline + clstride * i;
- iprev = (i == 0) ? n - 1 : i - 1;
- on_edge_prev = centerline + clstride * iprev;
- if (v2set) {
- if (cset[i]) {
- closer_v3_v3v3v3(on_edge_cur, on_edge_cur, v2co, bv->v->co);
- }
- else {
- copy_v3_v3(on_edge_cur, v2co);
- cset[i] = true;
- }
- }
- if (v1set) {
- if (cset[iprev]) {
- closer_v3_v3v3v3(on_edge_prev, on_edge_prev, v1co, bv->v->co);
- }
- else {
- copy_v3_v3(on_edge_prev, v1co);
- cset[iprev] = true;
- }
- }
- }
- bndv = bndv->next;
- }
- /* Maybe not everything was set by the previous loop */
- bndv = vm->boundstart;
- for (i = 0; i < n; i++) {
- if (!cset[i]) {
- on_edge_cur = centerline + clstride * i;
- e1 = bndv->next->efirst;
- copy_v3_v3(co1, bndv->nv.co);
- copy_v3_v3(co2, bndv->next->nv.co);
- if (e1) {
- if (bndv->prev->is_arc_start && bndv->next->is_arc_start) {
- ikind = isect_line_line_v3(e1->e->v1->co, e1->e->v2->co, co1, co2, meet1, meet2);
- if (ikind != 0) {
- copy_v3_v3(on_edge_cur, meet1);
- cset[i] = true;
- }
- }
- else {
- if (bndv->prev->is_arc_start) {
- closest_to_line_segment_v3(on_edge_cur, co1, e1->e->v1->co, e1->e->v2->co);
- }
- else {
- closest_to_line_segment_v3(on_edge_cur, co2, e1->e->v1->co, e1->e->v2->co);
- }
- cset[i] = true;
- }
- }
- if (!cset[i]) {
- mid_v3_v3v3(on_edge_cur, co1, co2);
- cset[i] = true;
- }
- }
- bndv = bndv->next;
- }
-
- /* fill in rest of centerlines by interpolation */
- copy_v3_v3(co2, bv->v->co);
- bndv = vm->boundstart;
- for (i = 0; i < n; i++) {
- if (odd) {
- ang = 0.5f * angle_v3v3v3(bndv->nv.co, co1, bndv->next->nv.co);
- if (ang > BEVEL_SMALL_ANG) {
- /* finalfrac is length along arms of isoceles triangle with top angle 2*ang
- * such that the base of the triangle is 1.
- * This is used in interpolation along centerline in odd case.
- * To avoid too big a drop from bv, cap finalfrac a 0.8 arbitrarily */
- finalfrac = 0.5f / sin(ang);
- if (finalfrac > 0.8f) {
- finalfrac = 0.8f;
- }
- }
- else {
- finalfrac = 0.8f;
- }
- ns2inv = 1.0f / (ns2 + finalfrac);
- }
-
- p = centerline + clstride * i;
- copy_v3_v3(co1, p);
- p += 3;
- for (j = 1; j <= ns2; j++) {
- interp_v3_v3v3(p, co1, co2, j * ns2inv);
- p += 3;
- }
- bndv = bndv->next;
- }
-
- /* coords of edges and mid or near-mid line */
- bndv = vm->boundstart;
- for (i = 0; i < n; i++) {
- copy_v3_v3(co1, bndv->nv.co);
- copy_v3_v3(co2, centerline + clstride * (i == 0 ? n - 1 : i - 1));
- for (j = 0; j < ns2 + odd; j++) {
- interp_v3_v3v3(mesh_vert(vm, i, j, 0)->co, co1, co2, j * ns2inv);
- }
- copy_v3_v3(co2, centerline + clstride * i);
- for (k = 1; k <= ns2; k++) {
- interp_v3_v3v3(mesh_vert(vm, i, 0, k)->co, co1, co2, k * ns2inv);
- }
- bndv = bndv->next;
- }
- if (!odd) {
- copy_v3_v3(mesh_vert(vm, 0, ns2, ns2)->co, bv->v->co);
- }
- vmesh_copy_equiv_verts(vm);
-
- /* fill in interior points by interpolation from edges to centerlines */
- bndv = vm->boundstart;
- for (i = 0; i < n; i++) {
- im1 = (i == 0) ? n - 1 : i - 1;
- for (j = 1; j < ns2 + odd; j++) {
- for (k = 1; k <= ns2; k++) {
- ikind = isect_line_line_v3(
- mesh_vert(vm, i, 0, k)->co, centerline + clstride * im1 + 3 * k,
- mesh_vert(vm, i, j, 0)->co, centerline + clstride * i + 3 * j,
- meet1, meet2);
- if (ikind == 0) {
- /* how can this happen? fall back on interpolation in one direction if it does */
- interp_v3_v3v3(
- mesh_vert(vm, i, j, k)->co,
- mesh_vert(vm, i, 0, k)->co, centerline + clstride * im1 + 3 * k, j * ns2inv);
- }
- else if (ikind == 1) {
- copy_v3_v3(mesh_vert(vm, i, j, k)->co, meet1);
- }
- else {
- mid_v3_v3v3(mesh_vert(vm, i, j, k)->co, meet1, meet2);
- }
- }
- }
- bndv = bndv->next;
- }
-
- vmesh_copy_equiv_verts(vm);
-
- MEM_freeN(centerline);
- MEM_freeN(cset);
- return vm;
+ int n, ns, ns2, odd, i, j, k, ikind, im1, clstride, iprev, akind;
+ float bndco[3], dir1[3], dir2[3], co1[3], co2[3], meet1[3], meet2[3], v1co[3], v2co[3];
+ float *on_edge_cur, *on_edge_prev, *p;
+ float ns2inv, finalfrac, ang;
+ BoundVert *bndv;
+ EdgeHalf *e1, *e2;
+ VMesh *vm;
+ float *centerline;
+ bool *cset, v1set, v2set;
+
+ n = bv->vmesh->count;
+ ns = bv->vmesh->seg;
+ ns2 = ns / 2;
+ odd = ns % 2;
+ ns2inv = 1.0f / (float)ns2;
+ vm = new_adj_vmesh(bp->mem_arena, n, ns, bv->vmesh->boundstart);
+ clstride = 3 * (ns2 + 1);
+ centerline = MEM_mallocN(clstride * n * sizeof(float), "bevel");
+ cset = MEM_callocN(n * sizeof(bool), "bevel");
+
+ /* find on_edge, place on bndv[i]'s elast where offset line would meet,
+ * taking min-distance-to bv->v with position where next sector's offset line would meet */
+ bndv = vm->boundstart;
+ for (i = 0; i < n; i++) {
+ copy_v3_v3(bndco, bndv->nv.co);
+ e1 = bndv->efirst;
+ e2 = bndv->elast;
+ akind = 0;
+ if (e1 && e2) {
+ akind = edges_angle_kind(e1, e2, bv->v);
+ }
+ if (bndv->is_patch_start) {
+ mid_v3_v3v3(centerline + clstride * i, bndv->nv.co, bndv->next->nv.co);
+ cset[i] = true;
+ bndv = bndv->next;
+ i++;
+ mid_v3_v3v3(centerline + clstride * i, bndv->nv.co, bndv->next->nv.co);
+ cset[i] = true;
+ bndv = bndv->next;
+ i++;
+ /* leave cset[i] where it was - probably false, unless i == n - 1 */
+ }
+ else if (bndv->is_arc_start) {
+ e1 = bndv->efirst;
+ e2 = bndv->next->efirst;
+ copy_v3_v3(centerline + clstride * i, bndv->profile.midco);
+ bndv = bndv->next;
+ cset[i] = true;
+ i++;
+ /* leave cset[i] where it was - probably false, unless i == n - 1 */
+ }
+ else if (akind < 0) {
+ sub_v3_v3v3(dir1, e1->e->v1->co, e1->e->v2->co);
+ sub_v3_v3v3(dir2, e2->e->v1->co, e2->e->v2->co);
+ add_v3_v3v3(co1, bndco, dir1);
+ add_v3_v3v3(co2, bndco, dir2);
+ /* intersect e1 with line through bndv parallel to e2 to get v1co */
+ ikind = isect_line_line_v3(e1->e->v1->co, e1->e->v2->co, bndco, co2, meet1, meet2);
+ if (ikind == 0) {
+ v1set = false;
+ }
+ else {
+ /* if the lines are skew (ikind == 2), want meet1 which is on e1 */
+ copy_v3_v3(v1co, meet1);
+ v1set = true;
+ }
+ /* intersect e2 with line through bndv parallel to e1 to get v2co */
+ ikind = isect_line_line_v3(e2->e->v1->co, e2->e->v2->co, bndco, co1, meet1, meet2);
+ if (ikind == 0) {
+ v2set = false;
+ }
+ else {
+ v2set = true;
+ copy_v3_v3(v2co, meet1);
+ }
+
+ /* want on_edge[i] to be min dist to bv->v of v2co and the v1co of next iteration */
+ on_edge_cur = centerline + clstride * i;
+ iprev = (i == 0) ? n - 1 : i - 1;
+ on_edge_prev = centerline + clstride * iprev;
+ if (v2set) {
+ if (cset[i]) {
+ closer_v3_v3v3v3(on_edge_cur, on_edge_cur, v2co, bv->v->co);
+ }
+ else {
+ copy_v3_v3(on_edge_cur, v2co);
+ cset[i] = true;
+ }
+ }
+ if (v1set) {
+ if (cset[iprev]) {
+ closer_v3_v3v3v3(on_edge_prev, on_edge_prev, v1co, bv->v->co);
+ }
+ else {
+ copy_v3_v3(on_edge_prev, v1co);
+ cset[iprev] = true;
+ }
+ }
+ }
+ bndv = bndv->next;
+ }
+ /* Maybe not everything was set by the previous loop */
+ bndv = vm->boundstart;
+ for (i = 0; i < n; i++) {
+ if (!cset[i]) {
+ on_edge_cur = centerline + clstride * i;
+ e1 = bndv->next->efirst;
+ copy_v3_v3(co1, bndv->nv.co);
+ copy_v3_v3(co2, bndv->next->nv.co);
+ if (e1) {
+ if (bndv->prev->is_arc_start && bndv->next->is_arc_start) {
+ ikind = isect_line_line_v3(e1->e->v1->co, e1->e->v2->co, co1, co2, meet1, meet2);
+ if (ikind != 0) {
+ copy_v3_v3(on_edge_cur, meet1);
+ cset[i] = true;
+ }
+ }
+ else {
+ if (bndv->prev->is_arc_start) {
+ closest_to_line_segment_v3(on_edge_cur, co1, e1->e->v1->co, e1->e->v2->co);
+ }
+ else {
+ closest_to_line_segment_v3(on_edge_cur, co2, e1->e->v1->co, e1->e->v2->co);
+ }
+ cset[i] = true;
+ }
+ }
+ if (!cset[i]) {
+ mid_v3_v3v3(on_edge_cur, co1, co2);
+ cset[i] = true;
+ }
+ }
+ bndv = bndv->next;
+ }
+
+ /* fill in rest of centerlines by interpolation */
+ copy_v3_v3(co2, bv->v->co);
+ bndv = vm->boundstart;
+ for (i = 0; i < n; i++) {
+ if (odd) {
+ ang = 0.5f * angle_v3v3v3(bndv->nv.co, co1, bndv->next->nv.co);
+ if (ang > BEVEL_SMALL_ANG) {
+ /* finalfrac is length along arms of isoceles triangle with top angle 2*ang
+ * such that the base of the triangle is 1.
+ * This is used in interpolation along centerline in odd case.
+ * To avoid too big a drop from bv, cap finalfrac a 0.8 arbitrarily */
+ finalfrac = 0.5f / sin(ang);
+ if (finalfrac > 0.8f) {
+ finalfrac = 0.8f;
+ }
+ }
+ else {
+ finalfrac = 0.8f;
+ }
+ ns2inv = 1.0f / (ns2 + finalfrac);
+ }
+
+ p = centerline + clstride * i;
+ copy_v3_v3(co1, p);
+ p += 3;
+ for (j = 1; j <= ns2; j++) {
+ interp_v3_v3v3(p, co1, co2, j * ns2inv);
+ p += 3;
+ }
+ bndv = bndv->next;
+ }
+
+ /* coords of edges and mid or near-mid line */
+ bndv = vm->boundstart;
+ for (i = 0; i < n; i++) {
+ copy_v3_v3(co1, bndv->nv.co);
+ copy_v3_v3(co2, centerline + clstride * (i == 0 ? n - 1 : i - 1));
+ for (j = 0; j < ns2 + odd; j++) {
+ interp_v3_v3v3(mesh_vert(vm, i, j, 0)->co, co1, co2, j * ns2inv);
+ }
+ copy_v3_v3(co2, centerline + clstride * i);
+ for (k = 1; k <= ns2; k++) {
+ interp_v3_v3v3(mesh_vert(vm, i, 0, k)->co, co1, co2, k * ns2inv);
+ }
+ bndv = bndv->next;
+ }
+ if (!odd) {
+ copy_v3_v3(mesh_vert(vm, 0, ns2, ns2)->co, bv->v->co);
+ }
+ vmesh_copy_equiv_verts(vm);
+
+ /* fill in interior points by interpolation from edges to centerlines */
+ bndv = vm->boundstart;
+ for (i = 0; i < n; i++) {
+ im1 = (i == 0) ? n - 1 : i - 1;
+ for (j = 1; j < ns2 + odd; j++) {
+ for (k = 1; k <= ns2; k++) {
+ ikind = isect_line_line_v3(mesh_vert(vm, i, 0, k)->co,
+ centerline + clstride * im1 + 3 * k,
+ mesh_vert(vm, i, j, 0)->co,
+ centerline + clstride * i + 3 * j,
+ meet1,
+ meet2);
+ if (ikind == 0) {
+ /* how can this happen? fall back on interpolation in one direction if it does */
+ interp_v3_v3v3(mesh_vert(vm, i, j, k)->co,
+ mesh_vert(vm, i, 0, k)->co,
+ centerline + clstride * im1 + 3 * k,
+ j * ns2inv);
+ }
+ else if (ikind == 1) {
+ copy_v3_v3(mesh_vert(vm, i, j, k)->co, meet1);
+ }
+ else {
+ mid_v3_v3v3(mesh_vert(vm, i, j, k)->co, meet1, meet2);
+ }
+ }
+ }
+ bndv = bndv->next;
+ }
+
+ vmesh_copy_equiv_verts(vm);
+
+ MEM_freeN(centerline);
+ MEM_freeN(cset);
+ return vm;
}
/*
@@ -4347,176 +4384,188 @@ static VMesh *square_out_adj_vmesh(BevelParams *bp, BevVert *bv)
* using cubic subdivision, then make the BMVerts and the new faces. */
static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv)
{
- int n, ns, ns2, odd, i, j, k, ring;
- VMesh *vm1, *vm;
- BoundVert *v;
- BMVert *bmv1, *bmv2, *bmv3, *bmv4;
- BMFace *f, *f2, *r_f;
- BMEdge *bme, *bme1, *bme2, *bme3;
- EdgeHalf *e;
- BoundVert *vpipe;
- int mat_nr = bp->mat_nr;
-
- n = bv->vmesh->count;
- ns = bv->vmesh->seg;
- ns2 = ns / 2;
- odd = ns % 2;
- BLI_assert(n >= 3 && ns > 1);
-
- /* Add support for profiles in vertex only in-plane bevels */
- if (bp->vertex_only) {
- v = bv->vmesh->boundstart;
- do {
- Profile *pro = &v->profile;
- pro->super_r = bp->pro_super_r;
- copy_v3_v3(pro->midco, bv->v->co);
- calculate_profile(bp, v);
- v = v->next;
- } while (v != bv->vmesh->boundstart);
- }
-
- vpipe = pipe_test(bv);
-
- if (bp->pro_super_r == PRO_SQUARE_R && bv->selcount >= 3 && !odd) {
- vm1 = square_out_adj_vmesh(bp, bv);
- }
- else if (vpipe) {
- vm1 = pipe_adj_vmesh(bp, bv, vpipe);
- }
- else if (tri_corner_test(bp, bv) == 1) {
- vm1 = tri_corner_adj_vmesh(bp, bv);
- /* the PRO_SQUARE_IN_R profile has boundary edges that merge
- * and no internal ring polys except possibly center ngon */
- if (bp->pro_super_r == PRO_SQUARE_IN_R) {
- build_square_in_vmesh(bp, bm, bv, vm1);
- return;
- }
- }
- else {
- vm1 = adj_vmesh(bp, bv);
- }
-
- /* copy final vmesh into bv->vmesh, make BMVerts and BMFaces */
- vm = bv->vmesh;
- for (i = 0; i < n; i++) {
- for (j = 0; j <= ns2; j++) {
- for (k = 0; k <= ns; k++) {
- if (j == 0 && (k == 0 || k == ns)) {
- continue; /* boundary corners already made */
- }
- if (!is_canon(vm, i, j, k)) {
- continue;
- }
- copy_v3_v3(mesh_vert(vm, i, j, k)->co, mesh_vert(vm1, i, j, k)->co);
- create_mesh_bmvert(bm, vm, i, j, k, bv->v);
- }
- }
- }
- vmesh_copy_equiv_verts(vm);
- /* make the polygons */
- v = vm->boundstart;
- do {
- i = v->index;
- f = boundvert_rep_face(v, NULL);
- f2 = boundvert_rep_face(v->next, NULL);
- if (bp->vertex_only) {
- e = v->efirst;
- }
- else {
- e = v->ebev;
- }
- bme = e ? e->e : NULL;
- /* For odd ns, make polys with lower left corner at (i,j,k) for
- * j in [0, ns2-1], k in [0, ns2]. And then the center ngon.
- * For even ns,
- * j in [0, ns2-1], k in [0, ns2-1] */
- for (j = 0; j < ns2; j++) {
- for (k = 0; k < ns2 + odd; k++) {
- bmv1 = mesh_vert(vm, i, j, k)->v;
- bmv2 = mesh_vert(vm, i, j, k + 1)->v;
- bmv3 = mesh_vert(vm, i, j + 1, k + 1)->v;
- bmv4 = mesh_vert(vm, i, j + 1, k)->v;
- BLI_assert(bmv1 && bmv2 && bmv3 && bmv4);
- if (bp->vertex_only) {
- if (j < k) {
- if (k == ns2 && j == ns2 - 1) {
- r_f = bev_create_quad_ex(bm, bmv1, bmv2, bmv3, bmv4, f2, f2, f2, f2,
- NULL, NULL, v->next->efirst->e, bme, mat_nr);
- }
- else {
- r_f = bev_create_quad(bm, bmv1, bmv2, bmv3, bmv4, f2, f2, f2, f2, mat_nr);
- }
- }
- else if (j > k) {
- r_f = bev_create_quad(bm, bmv1, bmv2, bmv3, bmv4, f2, f2, f2, f2, mat_nr);
- }
- else { /* j == k */
- /* only one edge attached to v, since vertex_only */
- if (e->is_seam) {
- r_f = bev_create_quad_ex(bm, bmv1, bmv2, bmv3, bmv4, f2, f2, f2, f2,
- bme, NULL, bme, NULL, mat_nr);
- }
- else {
- r_f = bev_create_quad_ex(bm, bmv1, bmv2, bmv3, bmv4, f2, f2, f2, f,
- bme, NULL, bme, NULL, mat_nr);
- }
- }
- }
- else { /* edge bevel */
- if (odd) {
- if (k == ns2) {
- if (e && e->is_seam) {
- r_f = bev_create_quad_ex(bm, bmv1, bmv2, bmv3, bmv4, f, f, f, f,
- NULL, bme, bme, NULL, mat_nr);
- }
- else {
- r_f = bev_create_quad(bm, bmv1, bmv2, bmv3, bmv4, f, f2, f2, f, mat_nr);
- }
- }
- else {
- r_f = bev_create_quad(bm, bmv1, bmv2, bmv3, bmv4, f, f, f, f, mat_nr);
- }
- }
- else {
- bme1 = k == ns2 - 1 ? bme : NULL;
- bme3 = NULL;
- if (j == ns2 - 1 && v->prev->ebev) {
- bme3 = v->prev->ebev->e;
- }
- bme2 = bme1 != NULL ? bme1 : bme3;
- r_f = bev_create_quad_ex(bm, bmv1, bmv2, bmv3, bmv4, f, f, f, f,
- NULL, bme1, bme2, bme3, mat_nr);
- }
- }
- record_face_kind(bp, r_f, F_VERT);
- }
- }
- } while ((v = v->next) != vm->boundstart);
-
- /* Fix UVs along center lines if even number of segments */
- if (!odd) {
- v = vm->boundstart;
- do {
- i = v->index;
- if (!v->any_seam) {
- for (ring = 1; ring < ns2; ring++) {
- BMVert *v_uv = mesh_vert(vm, i, ring, ns2)->v;
- if (v_uv) {
- bev_merge_uvs(bm, v_uv);
- }
- }
- }
- } while ((v = v->next) != vm->boundstart);
- bmv1 = mesh_vert(vm, 0, ns2, ns2)->v;
- if (bp->vertex_only || count_bound_vert_seams(bv) <= 1) {
- bev_merge_uvs(bm, bmv1);
- }
- }
-
- /* center ngon */
- if (odd) {
- build_center_ngon(bp, bm, bv, mat_nr);
- }
+ int n, ns, ns2, odd, i, j, k, ring;
+ VMesh *vm1, *vm;
+ BoundVert *v;
+ BMVert *bmv1, *bmv2, *bmv3, *bmv4;
+ BMFace *f, *f2, *r_f;
+ BMEdge *bme, *bme1, *bme2, *bme3;
+ EdgeHalf *e;
+ BoundVert *vpipe;
+ int mat_nr = bp->mat_nr;
+
+ n = bv->vmesh->count;
+ ns = bv->vmesh->seg;
+ ns2 = ns / 2;
+ odd = ns % 2;
+ BLI_assert(n >= 3 && ns > 1);
+
+ /* Add support for profiles in vertex only in-plane bevels */
+ if (bp->vertex_only) {
+ v = bv->vmesh->boundstart;
+ do {
+ Profile *pro = &v->profile;
+ pro->super_r = bp->pro_super_r;
+ copy_v3_v3(pro->midco, bv->v->co);
+ calculate_profile(bp, v);
+ v = v->next;
+ } while (v != bv->vmesh->boundstart);
+ }
+
+ vpipe = pipe_test(bv);
+
+ if (bp->pro_super_r == PRO_SQUARE_R && bv->selcount >= 3 && !odd) {
+ vm1 = square_out_adj_vmesh(bp, bv);
+ }
+ else if (vpipe) {
+ vm1 = pipe_adj_vmesh(bp, bv, vpipe);
+ }
+ else if (tri_corner_test(bp, bv) == 1) {
+ vm1 = tri_corner_adj_vmesh(bp, bv);
+ /* the PRO_SQUARE_IN_R profile has boundary edges that merge
+ * and no internal ring polys except possibly center ngon */
+ if (bp->pro_super_r == PRO_SQUARE_IN_R) {
+ build_square_in_vmesh(bp, bm, bv, vm1);
+ return;
+ }
+ }
+ else {
+ vm1 = adj_vmesh(bp, bv);
+ }
+
+ /* copy final vmesh into bv->vmesh, make BMVerts and BMFaces */
+ vm = bv->vmesh;
+ for (i = 0; i < n; i++) {
+ for (j = 0; j <= ns2; j++) {
+ for (k = 0; k <= ns; k++) {
+ if (j == 0 && (k == 0 || k == ns)) {
+ continue; /* boundary corners already made */
+ }
+ if (!is_canon(vm, i, j, k)) {
+ continue;
+ }
+ copy_v3_v3(mesh_vert(vm, i, j, k)->co, mesh_vert(vm1, i, j, k)->co);
+ create_mesh_bmvert(bm, vm, i, j, k, bv->v);
+ }
+ }
+ }
+ vmesh_copy_equiv_verts(vm);
+ /* make the polygons */
+ v = vm->boundstart;
+ do {
+ i = v->index;
+ f = boundvert_rep_face(v, NULL);
+ f2 = boundvert_rep_face(v->next, NULL);
+ if (bp->vertex_only) {
+ e = v->efirst;
+ }
+ else {
+ e = v->ebev;
+ }
+ bme = e ? e->e : NULL;
+ /* For odd ns, make polys with lower left corner at (i,j,k) for
+ * j in [0, ns2-1], k in [0, ns2]. And then the center ngon.
+ * For even ns,
+ * j in [0, ns2-1], k in [0, ns2-1] */
+ for (j = 0; j < ns2; j++) {
+ for (k = 0; k < ns2 + odd; k++) {
+ bmv1 = mesh_vert(vm, i, j, k)->v;
+ bmv2 = mesh_vert(vm, i, j, k + 1)->v;
+ bmv3 = mesh_vert(vm, i, j + 1, k + 1)->v;
+ bmv4 = mesh_vert(vm, i, j + 1, k)->v;
+ BLI_assert(bmv1 && bmv2 && bmv3 && bmv4);
+ if (bp->vertex_only) {
+ if (j < k) {
+ if (k == ns2 && j == ns2 - 1) {
+ r_f = bev_create_quad_ex(bm,
+ bmv1,
+ bmv2,
+ bmv3,
+ bmv4,
+ f2,
+ f2,
+ f2,
+ f2,
+ NULL,
+ NULL,
+ v->next->efirst->e,
+ bme,
+ mat_nr);
+ }
+ else {
+ r_f = bev_create_quad(bm, bmv1, bmv2, bmv3, bmv4, f2, f2, f2, f2, mat_nr);
+ }
+ }
+ else if (j > k) {
+ r_f = bev_create_quad(bm, bmv1, bmv2, bmv3, bmv4, f2, f2, f2, f2, mat_nr);
+ }
+ else { /* j == k */
+ /* only one edge attached to v, since vertex_only */
+ if (e->is_seam) {
+ r_f = bev_create_quad_ex(
+ bm, bmv1, bmv2, bmv3, bmv4, f2, f2, f2, f2, bme, NULL, bme, NULL, mat_nr);
+ }
+ else {
+ r_f = bev_create_quad_ex(
+ bm, bmv1, bmv2, bmv3, bmv4, f2, f2, f2, f, bme, NULL, bme, NULL, mat_nr);
+ }
+ }
+ }
+ else { /* edge bevel */
+ if (odd) {
+ if (k == ns2) {
+ if (e && e->is_seam) {
+ r_f = bev_create_quad_ex(
+ bm, bmv1, bmv2, bmv3, bmv4, f, f, f, f, NULL, bme, bme, NULL, mat_nr);
+ }
+ else {
+ r_f = bev_create_quad(bm, bmv1, bmv2, bmv3, bmv4, f, f2, f2, f, mat_nr);
+ }
+ }
+ else {
+ r_f = bev_create_quad(bm, bmv1, bmv2, bmv3, bmv4, f, f, f, f, mat_nr);
+ }
+ }
+ else {
+ bme1 = k == ns2 - 1 ? bme : NULL;
+ bme3 = NULL;
+ if (j == ns2 - 1 && v->prev->ebev) {
+ bme3 = v->prev->ebev->e;
+ }
+ bme2 = bme1 != NULL ? bme1 : bme3;
+ r_f = bev_create_quad_ex(
+ bm, bmv1, bmv2, bmv3, bmv4, f, f, f, f, NULL, bme1, bme2, bme3, mat_nr);
+ }
+ }
+ record_face_kind(bp, r_f, F_VERT);
+ }
+ }
+ } while ((v = v->next) != vm->boundstart);
+
+ /* Fix UVs along center lines if even number of segments */
+ if (!odd) {
+ v = vm->boundstart;
+ do {
+ i = v->index;
+ if (!v->any_seam) {
+ for (ring = 1; ring < ns2; ring++) {
+ BMVert *v_uv = mesh_vert(vm, i, ring, ns2)->v;
+ if (v_uv) {
+ bev_merge_uvs(bm, v_uv);
+ }
+ }
+ }
+ } while ((v = v->next) != vm->boundstart);
+ bmv1 = mesh_vert(vm, 0, ns2, ns2)->v;
+ if (bp->vertex_only || count_bound_vert_seams(bv) <= 1) {
+ bev_merge_uvs(bm, bmv1);
+ }
+ }
+
+ /* center ngon */
+ if (odd) {
+ build_center_ngon(bp, bm, bv, mat_nr);
+ }
}
/* If we make a poly out of verts around bv, snapping to rep frep, will uv poly have zero area?
@@ -4526,135 +4575,150 @@ static void bevel_build_rings(BevelParams *bp, BMesh *bm, BevVert *bv)
* the other vertices snap to e or snap to an edge at a point that is essentially on e too. */
static bool is_bad_uv_poly(BevVert *bv, BMFace *frep)
{
- BoundVert *v;
- BMEdge *snape, *firste;
- float co[3];
- VMesh *vm = bv->vmesh;
- float d2;
-
- v = vm->boundstart;
- d2 = snap_face_dist_squared(v->nv.v->co, frep, &firste, co);
- if (d2 > BEVEL_EPSILON_BIG_SQ || firste == NULL) {
- return false;
- }
-
- for (v = v->next; v != vm->boundstart; v = v->next) {
- snap_face_dist_squared(v->nv.v->co, frep, &snape, co);
- if (snape != firste) {
- d2 = dist_to_line_v3(co, firste->v1->co, firste->v2->co);
- if (d2 > BEVEL_EPSILON_BIG_SQ) {
- return false;
- }
- }
- }
- return true;
+ BoundVert *v;
+ BMEdge *snape, *firste;
+ float co[3];
+ VMesh *vm = bv->vmesh;
+ float d2;
+
+ v = vm->boundstart;
+ d2 = snap_face_dist_squared(v->nv.v->co, frep, &firste, co);
+ if (d2 > BEVEL_EPSILON_BIG_SQ || firste == NULL) {
+ return false;
+ }
+
+ for (v = v->next; v != vm->boundstart; v = v->next) {
+ snap_face_dist_squared(v->nv.v->co, frep, &snape, co);
+ if (snape != firste) {
+ d2 = dist_to_line_v3(co, firste->v1->co, firste->v2->co);
+ if (d2 > BEVEL_EPSILON_BIG_SQ) {
+ return false;
+ }
+ }
+ }
+ return true;
}
static BMFace *bevel_build_poly(BevelParams *bp, BMesh *bm, BevVert *bv)
{
- BMFace *f, *frep, *frep2;
- int n, k;
- VMesh *vm = bv->vmesh;
- BoundVert *v;
- BMEdge *frep_e1, *frep_e2, *frep_e;
- BMVert **vv = NULL;
- BMFace **vf = NULL;
- BMEdge **ve = NULL;
- BLI_array_staticdeclare(vv, BM_DEFAULT_NGON_STACK_SIZE);
- BLI_array_staticdeclare(vf, BM_DEFAULT_NGON_STACK_SIZE);
- BLI_array_staticdeclare(ve, BM_DEFAULT_NGON_STACK_SIZE);
-
- if (bv->any_seam) {
- frep = boundvert_rep_face(vm->boundstart, &frep2);
- if (frep2 && frep && is_bad_uv_poly(bv, frep)) {
- frep = frep2;
- }
- get_incident_edges(frep, bv->v, &frep_e1, &frep_e2);
- }
- else {
- frep = NULL;
- frep_e1 = frep_e2 = NULL;
- }
- v = vm->boundstart;
- n = 0;
- do {
- /* accumulate vertices for vertex ngon */
- /* also accumulate faces in which uv interpolation is to happen for each */
- BLI_array_append(vv, v->nv.v);
- if (frep) {
- BLI_array_append(vf, frep);
- frep_e = find_closer_edge(v->nv.v->co, frep_e1, frep_e2);
- BLI_array_append(ve, n > 0 ? frep_e : NULL);
- }
- else {
- BLI_array_append(vf, boundvert_rep_face(v, NULL));
- BLI_array_append(ve, NULL);
- }
- n++;
- if (v->ebev && v->ebev->seg > 1) {
- for (k = 1; k < v->ebev->seg; k++) {
- BLI_array_append(vv, mesh_vert(vm, v->index, 0, k)->v);
- if (frep) {
- BLI_array_append(vf, frep);
- frep_e = find_closer_edge(mesh_vert(vm, v->index, 0, k)->v->co, frep_e1, frep_e2);
- BLI_array_append(ve, k < v->ebev->seg / 2 ? NULL : frep_e);
- }
- else {
- BLI_array_append(vf, boundvert_rep_face(v, NULL));
- BLI_array_append(ve, NULL);
- }
- n++;
- }
- }
- } while ((v = v->next) != vm->boundstart);
- if (n > 2) {
- f = bev_create_ngon(bm, vv, n, vf, frep, ve, bp->mat_nr, true);
- record_face_kind(bp, f, F_VERT);
- }
- else {
- f = NULL;
- }
- BLI_array_free(vv);
- BLI_array_free(vf);
- BLI_array_free(ve);
- return f;
+ BMFace *f, *frep, *frep2;
+ int n, k;
+ VMesh *vm = bv->vmesh;
+ BoundVert *v;
+ BMEdge *frep_e1, *frep_e2, *frep_e;
+ BMVert **vv = NULL;
+ BMFace **vf = NULL;
+ BMEdge **ve = NULL;
+ BLI_array_staticdeclare(vv, BM_DEFAULT_NGON_STACK_SIZE);
+ BLI_array_staticdeclare(vf, BM_DEFAULT_NGON_STACK_SIZE);
+ BLI_array_staticdeclare(ve, BM_DEFAULT_NGON_STACK_SIZE);
+
+ if (bv->any_seam) {
+ frep = boundvert_rep_face(vm->boundstart, &frep2);
+ if (frep2 && frep && is_bad_uv_poly(bv, frep)) {
+ frep = frep2;
+ }
+ get_incident_edges(frep, bv->v, &frep_e1, &frep_e2);
+ }
+ else {
+ frep = NULL;
+ frep_e1 = frep_e2 = NULL;
+ }
+ v = vm->boundstart;
+ n = 0;
+ do {
+ /* accumulate vertices for vertex ngon */
+ /* also accumulate faces in which uv interpolation is to happen for each */
+ BLI_array_append(vv, v->nv.v);
+ if (frep) {
+ BLI_array_append(vf, frep);
+ frep_e = find_closer_edge(v->nv.v->co, frep_e1, frep_e2);
+ BLI_array_append(ve, n > 0 ? frep_e : NULL);
+ }
+ else {
+ BLI_array_append(vf, boundvert_rep_face(v, NULL));
+ BLI_array_append(ve, NULL);
+ }
+ n++;
+ if (v->ebev && v->ebev->seg > 1) {
+ for (k = 1; k < v->ebev->seg; k++) {
+ BLI_array_append(vv, mesh_vert(vm, v->index, 0, k)->v);
+ if (frep) {
+ BLI_array_append(vf, frep);
+ frep_e = find_closer_edge(mesh_vert(vm, v->index, 0, k)->v->co, frep_e1, frep_e2);
+ BLI_array_append(ve, k < v->ebev->seg / 2 ? NULL : frep_e);
+ }
+ else {
+ BLI_array_append(vf, boundvert_rep_face(v, NULL));
+ BLI_array_append(ve, NULL);
+ }
+ n++;
+ }
+ }
+ } while ((v = v->next) != vm->boundstart);
+ if (n > 2) {
+ f = bev_create_ngon(bm, vv, n, vf, frep, ve, bp->mat_nr, true);
+ record_face_kind(bp, f, F_VERT);
+ }
+ else {
+ f = NULL;
+ }
+ BLI_array_free(vv);
+ BLI_array_free(vf);
+ BLI_array_free(ve);
+ return f;
}
static void bevel_build_trifan(BevelParams *bp, BMesh *bm, BevVert *bv)
{
- BMFace *f;
- BLI_assert(next_bev(bv, NULL)->seg == 1 || bv->selcount == 1);
-
- f = bevel_build_poly(bp, bm, bv);
-
- if (f) {
- /* we have a polygon which we know starts at the previous vertex, make it into a fan */
- BMLoop *l_fan = BM_FACE_FIRST_LOOP(f)->prev;
- BMVert *v_fan = l_fan->v;
-
- while (f->len > 3) {
- BMLoop *l_new;
- BMFace *f_new;
- BLI_assert(v_fan == l_fan->v);
- f_new = BM_face_split(bm, f, l_fan, l_fan->next->next, &l_new, NULL, false);
- flag_out_edge(bm, l_new->e);
-
- if (f_new->len > f->len) {
- f = f_new;
- if (l_new->v == v_fan) { l_fan = l_new; }
- else if (l_new->next->v == v_fan) { l_fan = l_new->next; }
- else if (l_new->prev->v == v_fan) { l_fan = l_new->prev; }
- else { BLI_assert(0); }
- }
- else {
- if (l_fan->v == v_fan) { /* l_fan = l_fan; */ }
- else if (l_fan->next->v == v_fan) { l_fan = l_fan->next; }
- else if (l_fan->prev->v == v_fan) { l_fan = l_fan->prev; }
- else { BLI_assert(0); }
- }
- record_face_kind(bp, f_new, F_VERT);
- }
- }
+ BMFace *f;
+ BLI_assert(next_bev(bv, NULL)->seg == 1 || bv->selcount == 1);
+
+ f = bevel_build_poly(bp, bm, bv);
+
+ if (f) {
+ /* we have a polygon which we know starts at the previous vertex, make it into a fan */
+ BMLoop *l_fan = BM_FACE_FIRST_LOOP(f)->prev;
+ BMVert *v_fan = l_fan->v;
+
+ while (f->len > 3) {
+ BMLoop *l_new;
+ BMFace *f_new;
+ BLI_assert(v_fan == l_fan->v);
+ f_new = BM_face_split(bm, f, l_fan, l_fan->next->next, &l_new, NULL, false);
+ flag_out_edge(bm, l_new->e);
+
+ if (f_new->len > f->len) {
+ f = f_new;
+ if (l_new->v == v_fan) {
+ l_fan = l_new;
+ }
+ else if (l_new->next->v == v_fan) {
+ l_fan = l_new->next;
+ }
+ else if (l_new->prev->v == v_fan) {
+ l_fan = l_new->prev;
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ else {
+ if (l_fan->v == v_fan) { /* l_fan = l_fan; */
+ }
+ else if (l_fan->next->v == v_fan) {
+ l_fan = l_fan->next;
+ }
+ else if (l_fan->prev->v == v_fan) {
+ l_fan = l_fan->prev;
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ record_face_kind(bp, f_new, F_VERT);
+ }
+ }
}
/* Special case: vertex bevel with only two boundary verts.
@@ -4664,183 +4728,179 @@ static void bevel_build_trifan(BevelParams *bp, BMesh *bm, BevVert *bv)
* we have to make it here. */
static void bevel_vert_two_edges(BevelParams *bp, BMesh *bm, BevVert *bv)
{
- VMesh *vm = bv->vmesh;
- BMVert *v1, *v2;
- BMEdge *e_eg, *bme;
- Profile *pro;
- float co[3];
- BoundVert *bndv;
- int ns, k;
-
- BLI_assert(vm->count == 2 && bp->vertex_only);
-
- v1 = mesh_vert(vm, 0, 0, 0)->v;
- v2 = mesh_vert(vm, 1, 0, 0)->v;
-
- ns = vm->seg;
- if (ns > 1) {
- /* Set up profile parameters */
- bndv = vm->boundstart;
- pro = &bndv->profile;
- pro->super_r = bp->pro_super_r;
- copy_v3_v3(pro->coa, v1->co);
- copy_v3_v3(pro->cob, v2->co);
- copy_v3_v3(pro->midco, bv->v->co);
- /* don't use projection */
- zero_v3(pro->plane_co);
- zero_v3(pro->plane_no);
- zero_v3(pro->proj_dir);
- calculate_profile(bp, bndv);
- for (k = 1; k < ns; k++) {
- get_profile_point(bp, pro, k, ns, co);
- copy_v3_v3(mesh_vert(vm, 0, 0, k)->co, co);
- create_mesh_bmvert(bm, vm, 0, 0, k, bv->v);
- }
- copy_v3_v3(mesh_vert(vm, 0, 0, ns)->co, v2->co);
- for (k = 1; k < ns; k++) {
- copy_mesh_vert(vm, 1, 0, ns - k, 0, 0, k);
- }
- }
-
- if (BM_vert_face_check(bv->v) == false) {
- e_eg = bv->edges[0].e;
- BLI_assert(e_eg != NULL);
- for (k = 0; k < ns; k++) {
- v1 = mesh_vert(vm, 0, 0, k)->v;
- v2 = mesh_vert(vm, 0, 0, k + 1)->v;
- BLI_assert(v1 != NULL && v2 != NULL);
- bme = BM_edge_create(bm, v1, v2, e_eg, BM_CREATE_NO_DOUBLE);
- if (bme) {
- flag_out_edge(bm, bme);
- }
- }
- }
+ VMesh *vm = bv->vmesh;
+ BMVert *v1, *v2;
+ BMEdge *e_eg, *bme;
+ Profile *pro;
+ float co[3];
+ BoundVert *bndv;
+ int ns, k;
+
+ BLI_assert(vm->count == 2 && bp->vertex_only);
+
+ v1 = mesh_vert(vm, 0, 0, 0)->v;
+ v2 = mesh_vert(vm, 1, 0, 0)->v;
+
+ ns = vm->seg;
+ if (ns > 1) {
+ /* Set up profile parameters */
+ bndv = vm->boundstart;
+ pro = &bndv->profile;
+ pro->super_r = bp->pro_super_r;
+ copy_v3_v3(pro->coa, v1->co);
+ copy_v3_v3(pro->cob, v2->co);
+ copy_v3_v3(pro->midco, bv->v->co);
+ /* don't use projection */
+ zero_v3(pro->plane_co);
+ zero_v3(pro->plane_no);
+ zero_v3(pro->proj_dir);
+ calculate_profile(bp, bndv);
+ for (k = 1; k < ns; k++) {
+ get_profile_point(bp, pro, k, ns, co);
+ copy_v3_v3(mesh_vert(vm, 0, 0, k)->co, co);
+ create_mesh_bmvert(bm, vm, 0, 0, k, bv->v);
+ }
+ copy_v3_v3(mesh_vert(vm, 0, 0, ns)->co, v2->co);
+ for (k = 1; k < ns; k++) {
+ copy_mesh_vert(vm, 1, 0, ns - k, 0, 0, k);
+ }
+ }
+
+ if (BM_vert_face_check(bv->v) == false) {
+ e_eg = bv->edges[0].e;
+ BLI_assert(e_eg != NULL);
+ for (k = 0; k < ns; k++) {
+ v1 = mesh_vert(vm, 0, 0, k)->v;
+ v2 = mesh_vert(vm, 0, 0, k + 1)->v;
+ BLI_assert(v1 != NULL && v2 != NULL);
+ bme = BM_edge_create(bm, v1, v2, e_eg, BM_CREATE_NO_DOUBLE);
+ if (bme) {
+ flag_out_edge(bm, bme);
+ }
+ }
+ }
}
/* Given that the boundary is built, now make the actual BMVerts
* for the boundary and the interior of the vertex mesh. */
static void build_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv)
{
- MemArena *mem_arena = bp->mem_arena;
- VMesh *vm = bv->vmesh;
- BoundVert *v, *weld1, *weld2;
- int n, ns, ns2, i, k, weld;
- float *va, *vb, co[3];
-
- n = vm->count;
- ns = vm->seg;
- ns2 = ns / 2;
-
- vm->mesh = (NewVert *)BLI_memarena_alloc(mem_arena, n * (ns2 + 1) * (ns + 1) * sizeof(NewVert));
-
- /* special case: two beveled ends welded together */
- weld = (bv->selcount == 2) && (vm->count == 2);
- weld1 = weld2 = NULL; /* will hold two BoundVerts involved in weld */
-
- /* make (i, 0, 0) mesh verts for all i */
- v = vm->boundstart;
- do {
- i = v->index;
- copy_v3_v3(mesh_vert(vm, i, 0, 0)->co, v->nv.co);
- create_mesh_bmvert(bm, vm, i, 0, 0, bv->v);
- v->nv.v = mesh_vert(vm, i, 0, 0)->v;
- if (weld && v->ebev) {
- if (!weld1) {
- weld1 = v;
- }
- else {
- weld2 = v;
- move_weld_profile_planes(bv, weld1, weld2);
- calculate_profile(bp, weld1);
- calculate_profile(bp, weld2);
- }
- }
- } while ((v = v->next) != vm->boundstart);
-
- /* copy other ends to (i, 0, ns) for all i, and fill in profiles for edges */
- v = vm->boundstart;
- do {
- i = v->index;
- copy_mesh_vert(vm, i, 0, ns, v->next->index, 0, 0);
- for (k = 1; k < ns; k++) {
- if (v->ebev && vm->mesh_kind != M_ADJ) {
- get_profile_point(bp, &v->profile, k, ns, co);
- copy_v3_v3(mesh_vert(vm, i, 0, k)->co, co);
- if (!weld) {
- create_mesh_bmvert(bm, vm, i, 0, k, bv->v);
- }
- }
- else if (n == 2 && !v->ebev && vm->mesh_kind != M_ADJ) {
- /* case of one edge beveled and this is the v without ebev */
- /* want to copy the verts from other v, in reverse order */
- copy_mesh_vert(vm, i, 0, k, 1 - i, 0, ns - k);
- }
- }
- } while ((v = v->next) != vm->boundstart);
-
- if (weld) {
- vm->mesh_kind = M_NONE;
- for (k = 1; k < ns; k++) {
- va = mesh_vert(vm, weld1->index, 0, k)->co;
- vb = mesh_vert(vm, weld2->index, 0, ns - k)->co;
- /* if one of the profiles is on a flat plane,
- * just use the boundary point of the other */
- if (weld1->profile.super_r == PRO_LINE_R &&
- weld2->profile.super_r != PRO_LINE_R)
- {
- copy_v3_v3(co, vb);
- }
- else if (weld2->profile.super_r == PRO_LINE_R &&
- weld1->profile.super_r != PRO_LINE_R)
- {
- copy_v3_v3(co, va);
- }
- else {
- mid_v3_v3v3(co, va, vb);
- }
- copy_v3_v3(mesh_vert(vm, weld1->index, 0, k)->co, co);
- create_mesh_bmvert(bm, vm, weld1->index, 0, k, bv->v);
- }
- for (k = 1; k < ns; k++) {
- copy_mesh_vert(vm, weld2->index, 0, ns - k, weld1->index, 0, k);
- }
- }
-
- switch (vm->mesh_kind) {
- case M_NONE:
- if (n == 2 && bp->vertex_only) {
- bevel_vert_two_edges(bp, bm, bv);
- }
- break;
- case M_POLY:
- bevel_build_poly(bp, bm, bv);
- break;
- case M_ADJ:
- bevel_build_rings(bp, bm, bv);
- break;
- case M_TRI_FAN:
- bevel_build_trifan(bp, bm, bv);
- break;
- }
+ MemArena *mem_arena = bp->mem_arena;
+ VMesh *vm = bv->vmesh;
+ BoundVert *v, *weld1, *weld2;
+ int n, ns, ns2, i, k, weld;
+ float *va, *vb, co[3];
+
+ n = vm->count;
+ ns = vm->seg;
+ ns2 = ns / 2;
+
+ vm->mesh = (NewVert *)BLI_memarena_alloc(mem_arena, n * (ns2 + 1) * (ns + 1) * sizeof(NewVert));
+
+ /* special case: two beveled ends welded together */
+ weld = (bv->selcount == 2) && (vm->count == 2);
+ weld1 = weld2 = NULL; /* will hold two BoundVerts involved in weld */
+
+ /* make (i, 0, 0) mesh verts for all i */
+ v = vm->boundstart;
+ do {
+ i = v->index;
+ copy_v3_v3(mesh_vert(vm, i, 0, 0)->co, v->nv.co);
+ create_mesh_bmvert(bm, vm, i, 0, 0, bv->v);
+ v->nv.v = mesh_vert(vm, i, 0, 0)->v;
+ if (weld && v->ebev) {
+ if (!weld1) {
+ weld1 = v;
+ }
+ else {
+ weld2 = v;
+ move_weld_profile_planes(bv, weld1, weld2);
+ calculate_profile(bp, weld1);
+ calculate_profile(bp, weld2);
+ }
+ }
+ } while ((v = v->next) != vm->boundstart);
+
+ /* copy other ends to (i, 0, ns) for all i, and fill in profiles for edges */
+ v = vm->boundstart;
+ do {
+ i = v->index;
+ copy_mesh_vert(vm, i, 0, ns, v->next->index, 0, 0);
+ for (k = 1; k < ns; k++) {
+ if (v->ebev && vm->mesh_kind != M_ADJ) {
+ get_profile_point(bp, &v->profile, k, ns, co);
+ copy_v3_v3(mesh_vert(vm, i, 0, k)->co, co);
+ if (!weld) {
+ create_mesh_bmvert(bm, vm, i, 0, k, bv->v);
+ }
+ }
+ else if (n == 2 && !v->ebev && vm->mesh_kind != M_ADJ) {
+ /* case of one edge beveled and this is the v without ebev */
+ /* want to copy the verts from other v, in reverse order */
+ copy_mesh_vert(vm, i, 0, k, 1 - i, 0, ns - k);
+ }
+ }
+ } while ((v = v->next) != vm->boundstart);
+
+ if (weld) {
+ vm->mesh_kind = M_NONE;
+ for (k = 1; k < ns; k++) {
+ va = mesh_vert(vm, weld1->index, 0, k)->co;
+ vb = mesh_vert(vm, weld2->index, 0, ns - k)->co;
+ /* if one of the profiles is on a flat plane,
+ * just use the boundary point of the other */
+ if (weld1->profile.super_r == PRO_LINE_R && weld2->profile.super_r != PRO_LINE_R) {
+ copy_v3_v3(co, vb);
+ }
+ else if (weld2->profile.super_r == PRO_LINE_R && weld1->profile.super_r != PRO_LINE_R) {
+ copy_v3_v3(co, va);
+ }
+ else {
+ mid_v3_v3v3(co, va, vb);
+ }
+ copy_v3_v3(mesh_vert(vm, weld1->index, 0, k)->co, co);
+ create_mesh_bmvert(bm, vm, weld1->index, 0, k, bv->v);
+ }
+ for (k = 1; k < ns; k++) {
+ copy_mesh_vert(vm, weld2->index, 0, ns - k, weld1->index, 0, k);
+ }
+ }
+
+ switch (vm->mesh_kind) {
+ case M_NONE:
+ if (n == 2 && bp->vertex_only) {
+ bevel_vert_two_edges(bp, bm, bv);
+ }
+ break;
+ case M_POLY:
+ bevel_build_poly(bp, bm, bv);
+ break;
+ case M_ADJ:
+ bevel_build_rings(bp, bm, bv);
+ break;
+ case M_TRI_FAN:
+ bevel_build_trifan(bp, bm, bv);
+ break;
+ }
}
/* Return the angle between the two faces adjacent to e.
* If there are not two, return 0. */
static float edge_face_angle(EdgeHalf *e)
{
- if (e->fprev && e->fnext) {
- /* angle between faces is supplement of angle between face normals */
- return (float)M_PI - angle_normalized_v3v3(e->fprev->no, e->fnext->no);
- }
- else {
- return 0.0f;
- }
+ if (e->fprev && e->fnext) {
+ /* angle between faces is supplement of angle between face normals */
+ return (float)M_PI - angle_normalized_v3v3(e->fprev->no, e->fnext->no);
+ }
+ else {
+ return 0.0f;
+ }
}
/* take care, this flag isn't cleared before use, it just so happens that its not set */
-#define BM_BEVEL_EDGE_TAG_ENABLE(bme) BM_ELEM_API_FLAG_ENABLE( (bme), _FLAG_OVERLAP)
-#define BM_BEVEL_EDGE_TAG_DISABLE(bme) BM_ELEM_API_FLAG_DISABLE( (bme), _FLAG_OVERLAP)
-#define BM_BEVEL_EDGE_TAG_TEST(bme) BM_ELEM_API_FLAG_TEST( (bme), _FLAG_OVERLAP)
+#define BM_BEVEL_EDGE_TAG_ENABLE(bme) BM_ELEM_API_FLAG_ENABLE((bme), _FLAG_OVERLAP)
+#define BM_BEVEL_EDGE_TAG_DISABLE(bme) BM_ELEM_API_FLAG_DISABLE((bme), _FLAG_OVERLAP)
+#define BM_BEVEL_EDGE_TAG_TEST(bme) BM_ELEM_API_FLAG_TEST((bme), _FLAG_OVERLAP)
/* Try to extend the bv->edges[] array beyond i by finding more successor edges.
* This is a possibly exponential-time search, but it is only exponential in the number
@@ -4851,59 +4911,60 @@ static float edge_face_angle(EdgeHalf *e)
* The path will have the tags of all of its edges set. */
static int bevel_edge_order_extend(BMesh *bm, BevVert *bv, int i)
{
- BMEdge *bme, *bme2, *nextbme;
- BMLoop *l;
- BMIter iter;
- int j, tryj, bestj, nsucs, sucindex, k;
- BMEdge **sucs = NULL;
- BMEdge **save_path = NULL;
- BLI_array_staticdeclare(sucs, 4); /* likely very few faces attached to same edge */
- BLI_array_staticdeclare(save_path, BM_DEFAULT_NGON_STACK_SIZE);
-
- bme = bv->edges[i].e;
- /* fill sucs with all unmarked edges of bmes */
- BM_ITER_ELEM(l, &iter, bme, BM_LOOPS_OF_EDGE) {
- bme2 = (l->v == bv->v) ? l->prev->e : l->next->e;
- if (!BM_BEVEL_EDGE_TAG_TEST(bme2)) {
- BLI_array_append(sucs, bme2);
- }
- }
- nsucs = BLI_array_len(sucs);
-
- bestj = j = i;
- for (sucindex = 0; sucindex < nsucs; sucindex++) {
- nextbme = sucs[sucindex];
- BLI_assert(nextbme != NULL);
- BLI_assert(!BM_BEVEL_EDGE_TAG_TEST(nextbme));
- BLI_assert(j + 1 < bv->edgecount);
- bv->edges[j + 1].e = nextbme;
- BM_BEVEL_EDGE_TAG_ENABLE(nextbme);
- tryj = bevel_edge_order_extend(bm, bv, j + 1);
- if (tryj > bestj || (tryj == bestj && edges_face_connected_at_vert(bv->edges[tryj].e, bv->edges[0].e))) {
- bestj = tryj;
- BLI_array_clear(save_path);
- for (k = j + 1; k <= bestj; k++) {
- BLI_array_append(save_path, bv->edges[k].e);
- }
- }
- /* now reset to path only-going-to-j state */
- for (k = j + 1; k <= tryj; k++) {
- BM_BEVEL_EDGE_TAG_DISABLE(bv->edges[k].e);
- bv->edges[k].e = NULL;
- }
- }
- /* at this point we should be back at invariant on entrance: path up to j */
- if (bestj > j) {
- /* save_path should have from j + 1 to bestj inclusive edges to add to edges[] before returning */
- for (k = j + 1; k <= bestj; k++) {
- BLI_assert(save_path[k - (j + 1)] != NULL);
- bv->edges[k].e = save_path[k - (j + 1)];
- BM_BEVEL_EDGE_TAG_ENABLE(bv->edges[k].e);
- }
- }
- BLI_array_free(sucs);
- BLI_array_free(save_path);
- return bestj;
+ BMEdge *bme, *bme2, *nextbme;
+ BMLoop *l;
+ BMIter iter;
+ int j, tryj, bestj, nsucs, sucindex, k;
+ BMEdge **sucs = NULL;
+ BMEdge **save_path = NULL;
+ BLI_array_staticdeclare(sucs, 4); /* likely very few faces attached to same edge */
+ BLI_array_staticdeclare(save_path, BM_DEFAULT_NGON_STACK_SIZE);
+
+ bme = bv->edges[i].e;
+ /* fill sucs with all unmarked edges of bmes */
+ BM_ITER_ELEM (l, &iter, bme, BM_LOOPS_OF_EDGE) {
+ bme2 = (l->v == bv->v) ? l->prev->e : l->next->e;
+ if (!BM_BEVEL_EDGE_TAG_TEST(bme2)) {
+ BLI_array_append(sucs, bme2);
+ }
+ }
+ nsucs = BLI_array_len(sucs);
+
+ bestj = j = i;
+ for (sucindex = 0; sucindex < nsucs; sucindex++) {
+ nextbme = sucs[sucindex];
+ BLI_assert(nextbme != NULL);
+ BLI_assert(!BM_BEVEL_EDGE_TAG_TEST(nextbme));
+ BLI_assert(j + 1 < bv->edgecount);
+ bv->edges[j + 1].e = nextbme;
+ BM_BEVEL_EDGE_TAG_ENABLE(nextbme);
+ tryj = bevel_edge_order_extend(bm, bv, j + 1);
+ if (tryj > bestj ||
+ (tryj == bestj && edges_face_connected_at_vert(bv->edges[tryj].e, bv->edges[0].e))) {
+ bestj = tryj;
+ BLI_array_clear(save_path);
+ for (k = j + 1; k <= bestj; k++) {
+ BLI_array_append(save_path, bv->edges[k].e);
+ }
+ }
+ /* now reset to path only-going-to-j state */
+ for (k = j + 1; k <= tryj; k++) {
+ BM_BEVEL_EDGE_TAG_DISABLE(bv->edges[k].e);
+ bv->edges[k].e = NULL;
+ }
+ }
+ /* at this point we should be back at invariant on entrance: path up to j */
+ if (bestj > j) {
+ /* save_path should have from j + 1 to bestj inclusive edges to add to edges[] before returning */
+ for (k = j + 1; k <= bestj; k++) {
+ BLI_assert(save_path[k - (j + 1)] != NULL);
+ bv->edges[k].e = save_path[k - (j + 1)];
+ BM_BEVEL_EDGE_TAG_ENABLE(bv->edges[k].e);
+ }
+ }
+ BLI_array_free(sucs);
+ BLI_array_free(save_path);
+ return bestj;
}
/* See if we have usual case for bevel edge order:
@@ -4920,90 +4981,89 @@ static int bevel_edge_order_extend(BMesh *bm, BevVert *bv, int i)
* so for now will continue to use the legacy code. */
static bool fast_bevel_edge_order(BevVert *bv)
{
- int j, k, nsucs;
- BMEdge *bme, *bme2, *bmenext;
- BMIter iter;
- BMLoop *l;
-
- for (j = 1; j < bv->edgecount; j++) {
- bme = bv->edges[j - 1].e;
- bmenext = NULL;
- nsucs = 0;
- BM_ITER_ELEM(l, &iter, bme, BM_LOOPS_OF_EDGE) {
- bme2 = (l->v == bv->v) ? l->prev->e : l->next->e;
- if (!BM_BEVEL_EDGE_TAG_TEST(bme2)) {
- nsucs++;
- if (bmenext == NULL) {
- bmenext = bme2;
- }
- }
- }
- if (nsucs == 0 || (nsucs == 2 && j != 1) || nsucs > 2 ||
- (j == bv->edgecount - 1 && !edges_face_connected_at_vert(bmenext, bv->edges[0].e)))
- {
- for (k = 1; k < j; k++) {
- BM_BEVEL_EDGE_TAG_DISABLE(bv->edges[k].e);
- bv->edges[k].e = NULL;
- }
- return false;
- }
- bv->edges[j].e = bmenext;
- BM_BEVEL_EDGE_TAG_ENABLE(bmenext);
- }
- return true;
+ int j, k, nsucs;
+ BMEdge *bme, *bme2, *bmenext;
+ BMIter iter;
+ BMLoop *l;
+
+ for (j = 1; j < bv->edgecount; j++) {
+ bme = bv->edges[j - 1].e;
+ bmenext = NULL;
+ nsucs = 0;
+ BM_ITER_ELEM (l, &iter, bme, BM_LOOPS_OF_EDGE) {
+ bme2 = (l->v == bv->v) ? l->prev->e : l->next->e;
+ if (!BM_BEVEL_EDGE_TAG_TEST(bme2)) {
+ nsucs++;
+ if (bmenext == NULL) {
+ bmenext = bme2;
+ }
+ }
+ }
+ if (nsucs == 0 || (nsucs == 2 && j != 1) || nsucs > 2 ||
+ (j == bv->edgecount - 1 && !edges_face_connected_at_vert(bmenext, bv->edges[0].e))) {
+ for (k = 1; k < j; k++) {
+ BM_BEVEL_EDGE_TAG_DISABLE(bv->edges[k].e);
+ bv->edges[k].e = NULL;
+ }
+ return false;
+ }
+ bv->edges[j].e = bmenext;
+ BM_BEVEL_EDGE_TAG_ENABLE(bmenext);
+ }
+ return true;
}
#else
static bool fast_bevel_edge_order(BevVert *bv)
{
- BMEdge *bme, *bme2, *first_suc;
- BMIter iter, iter2;
- BMFace *f;
- EdgeHalf *e;
- int i, k, ntot, num_shared_face;
-
- ntot = bv->edgecount;
-
- /* add edges to bv->edges in order that keeps adjacent edges sharing
- * a unique face, if possible */
- e = &bv->edges[0];
- bme = e->e;
- if (!bme->l) {
- return false;
- }
- for (i = 1; i < ntot; i++) {
- /* find an unflagged edge bme2 that shares a face f with previous bme */
- num_shared_face = 0;
- first_suc = NULL; /* keep track of first successor to match legacy behavior */
- BM_ITER_ELEM (bme2, &iter, bv->v, BM_EDGES_OF_VERT) {
- if (BM_BEVEL_EDGE_TAG_TEST(bme2)) {
- continue;
- }
- BM_ITER_ELEM (f, &iter2, bme2, BM_FACES_OF_EDGE) {
- if (BM_face_edge_share_loop(f, bme)) {
- num_shared_face++;
- if (first_suc == NULL) {
- first_suc = bme2;
- }
- }
- }
- if (num_shared_face >= 3) {
- break;
- }
- }
- if (num_shared_face == 1 || (i == 1 && num_shared_face == 2)) {
- e = &bv->edges[i];
- e->e = bme = first_suc;
- BM_BEVEL_EDGE_TAG_ENABLE(bme);
- }
- else {
- for (k = 1; k < i; k++) {
- BM_BEVEL_EDGE_TAG_DISABLE(bv->edges[k].e);
- bv->edges[k].e = NULL;
- }
- return false;
- }
- }
- return true;
+ BMEdge *bme, *bme2, *first_suc;
+ BMIter iter, iter2;
+ BMFace *f;
+ EdgeHalf *e;
+ int i, k, ntot, num_shared_face;
+
+ ntot = bv->edgecount;
+
+ /* add edges to bv->edges in order that keeps adjacent edges sharing
+ * a unique face, if possible */
+ e = &bv->edges[0];
+ bme = e->e;
+ if (!bme->l) {
+ return false;
+ }
+ for (i = 1; i < ntot; i++) {
+ /* find an unflagged edge bme2 that shares a face f with previous bme */
+ num_shared_face = 0;
+ first_suc = NULL; /* keep track of first successor to match legacy behavior */
+ BM_ITER_ELEM (bme2, &iter, bv->v, BM_EDGES_OF_VERT) {
+ if (BM_BEVEL_EDGE_TAG_TEST(bme2)) {
+ continue;
+ }
+ BM_ITER_ELEM (f, &iter2, bme2, BM_FACES_OF_EDGE) {
+ if (BM_face_edge_share_loop(f, bme)) {
+ num_shared_face++;
+ if (first_suc == NULL) {
+ first_suc = bme2;
+ }
+ }
+ }
+ if (num_shared_face >= 3) {
+ break;
+ }
+ }
+ if (num_shared_face == 1 || (i == 1 && num_shared_face == 2)) {
+ e = &bv->edges[i];
+ e->e = bme = first_suc;
+ BM_BEVEL_EDGE_TAG_ENABLE(bme);
+ }
+ else {
+ for (k = 1; k < i; k++) {
+ BM_BEVEL_EDGE_TAG_DISABLE(bv->edges[k].e);
+ bv->edges[k].e = NULL;
+ }
+ return false;
+ }
+ }
+ return true;
}
#endif
@@ -5013,69 +5073,69 @@ static bool fast_bevel_edge_order(BevVert *bv)
* first_bme is a good edge to start with.*/
static void find_bevel_edge_order(BMesh *bm, BevVert *bv, BMEdge *first_bme)
{
- BMEdge *bme, *bme2;
- BMIter iter;
- BMFace *f, *bestf;
- EdgeHalf *e;
- EdgeHalf *e2;
- BMLoop *l;
- int i, ntot;
-
- ntot = bv->edgecount;
- i = 0;
- for (;;) {
- BLI_assert(first_bme != NULL);
- bv->edges[i].e = first_bme;
- BM_BEVEL_EDGE_TAG_ENABLE(first_bme);
- if (i == 0 && fast_bevel_edge_order(bv)) {
- break;
- }
- i = bevel_edge_order_extend(bm, bv, i);
- i++;
- if (i >= bv->edgecount) {
- break;
- }
- /* Not done yet: find a new first_bme */
- first_bme = NULL;
- BM_ITER_ELEM(bme, &iter, bv->v, BM_EDGES_OF_VERT) {
- if (BM_BEVEL_EDGE_TAG_TEST(bme)) {
- continue;
- }
- if (!first_bme) {
- first_bme = bme;
- }
- if (BM_edge_face_count(bme) == 1) {
- first_bme = bme;
- break;
- }
- }
- }
- /* now fill in the faces ... */
- for (i = 0; i < ntot; i++) {
- e = &bv->edges[i];
- e2 = (i == bv->edgecount - 1) ? &bv->edges[0] : &bv->edges[i + 1];
- bme = e->e;
- bme2 = e2->e;
- BLI_assert(bme != NULL);
- if (e->fnext != NULL || e2->fprev != NULL) {
- continue;
- }
- /* Which faces have successive loops that are for bme and bme2?
- * There could be more than one. E.g., in manifold ntot==2 case.
- * Prefer one that has loop in same direction as e. */
- bestf = NULL;
- BM_ITER_ELEM(l, &iter, bme, BM_LOOPS_OF_EDGE) {
- f = l->f;
- if ((l->prev->e == bme2 || l->next->e == bme2)) {
- if (!bestf || l->v == bv->v) {
- bestf = f;
- }
- }
- if (bestf) {
- e->fnext = e2->fprev = bestf;
- }
- }
- }
+ BMEdge *bme, *bme2;
+ BMIter iter;
+ BMFace *f, *bestf;
+ EdgeHalf *e;
+ EdgeHalf *e2;
+ BMLoop *l;
+ int i, ntot;
+
+ ntot = bv->edgecount;
+ i = 0;
+ for (;;) {
+ BLI_assert(first_bme != NULL);
+ bv->edges[i].e = first_bme;
+ BM_BEVEL_EDGE_TAG_ENABLE(first_bme);
+ if (i == 0 && fast_bevel_edge_order(bv)) {
+ break;
+ }
+ i = bevel_edge_order_extend(bm, bv, i);
+ i++;
+ if (i >= bv->edgecount) {
+ break;
+ }
+ /* Not done yet: find a new first_bme */
+ first_bme = NULL;
+ BM_ITER_ELEM (bme, &iter, bv->v, BM_EDGES_OF_VERT) {
+ if (BM_BEVEL_EDGE_TAG_TEST(bme)) {
+ continue;
+ }
+ if (!first_bme) {
+ first_bme = bme;
+ }
+ if (BM_edge_face_count(bme) == 1) {
+ first_bme = bme;
+ break;
+ }
+ }
+ }
+ /* now fill in the faces ... */
+ for (i = 0; i < ntot; i++) {
+ e = &bv->edges[i];
+ e2 = (i == bv->edgecount - 1) ? &bv->edges[0] : &bv->edges[i + 1];
+ bme = e->e;
+ bme2 = e2->e;
+ BLI_assert(bme != NULL);
+ if (e->fnext != NULL || e2->fprev != NULL) {
+ continue;
+ }
+ /* Which faces have successive loops that are for bme and bme2?
+ * There could be more than one. E.g., in manifold ntot==2 case.
+ * Prefer one that has loop in same direction as e. */
+ bestf = NULL;
+ BM_ITER_ELEM (l, &iter, bme, BM_LOOPS_OF_EDGE) {
+ f = l->f;
+ if ((l->prev->e == bme2 || l->next->e == bme2)) {
+ if (!bestf || l->v == bv->v) {
+ bestf = f;
+ }
+ }
+ if (bestf) {
+ e->fnext = e2->fprev = bestf;
+ }
+ }
+ }
}
/*
@@ -5083,540 +5143,537 @@ static void find_bevel_edge_order(BMesh *bm, BevVert *bv, BMEdge *first_bme)
*/
static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
{
- BMEdge *bme;
- BevVert *bv;
- BMEdge *first_bme;
- BMVert *v1, *v2;
- BMIter iter;
- EdgeHalf *e;
- float weight, z;
- int i, ccw_test_sum;
- int nsel = 0;
- int ntot = 0;
- int nwire = 0;
- int fcnt;
-
- /* Gather input selected edges.
- * Only bevel selected edges that have exactly two incident faces.
- * Want edges to be ordered so that they share faces.
- * There may be one or more chains of shared faces broken by
- * gaps where there are no faces.
- * Want to ignore wire edges completely for edge beveling.
- * TODO: make following work when more than one gap.
- */
-
- first_bme = NULL;
- BM_ITER_ELEM (bme, &iter, v, BM_EDGES_OF_VERT) {
- fcnt = BM_edge_face_count(bme);
- BM_BEVEL_EDGE_TAG_DISABLE(bme);
- if (BM_elem_flag_test(bme, BM_ELEM_TAG) && !bp->vertex_only) {
- BLI_assert(fcnt == 2);
- nsel++;
- if (!first_bme) {
- first_bme = bme;
- }
- }
- if (fcnt == 1) {
- /* good to start face chain from this edge */
- first_bme = bme;
- }
- if (fcnt > 0 || bp->vertex_only) {
- ntot++;
- }
- if (BM_edge_is_wire(bme)) {
- nwire++;
- /* If edge beveling, exclude wire edges from edges array.
- * Mark this edge as "chosen" so loop below won't choose it. */
- if (!bp->vertex_only) {
- BM_BEVEL_EDGE_TAG_ENABLE(bme);
- }
- }
- }
- if (!first_bme) {
- first_bme = v->e;
- }
-
- if ((nsel == 0 && !bp->vertex_only) || (ntot < 2 && bp->vertex_only)) {
- /* signal this vert isn't being beveled */
- BM_elem_flag_disable(v, BM_ELEM_TAG);
- return NULL;
- }
-
- bv = (BevVert *)BLI_memarena_alloc(bp->mem_arena, (sizeof(BevVert)));
- bv->v = v;
- bv->edgecount = ntot;
- bv->selcount = nsel;
- bv->wirecount = nwire;
- bv->offset = bp->offset;
- bv->edges = (EdgeHalf *)BLI_memarena_alloc(bp->mem_arena, ntot * sizeof(EdgeHalf));
- if (nwire) {
- bv->wire_edges = (BMEdge **)BLI_memarena_alloc(bp->mem_arena, nwire * sizeof(BMEdge *));
- }
- else {
- bv->wire_edges = NULL;
- }
- bv->vmesh = (VMesh *)BLI_memarena_alloc(bp->mem_arena, sizeof(VMesh));
- bv->vmesh->seg = bp->seg;
-
- if (bp->vertex_only) {
- /* if weighted, modify offset by weight */
- if (bp->dvert != NULL && bp->vertex_group != -1) {
- weight = defvert_find_weight(bp->dvert + BM_elem_index_get(v), bp->vertex_group);
- if (weight <= 0.0f) {
- BM_elem_flag_disable(v, BM_ELEM_TAG);
- return NULL;
- }
- bv->offset *= weight;
- }
- else if (bp->use_weights) {
- weight = BM_elem_float_data_get(&bm->vdata, v, CD_BWEIGHT);
- bv->offset *= weight;
- }
- }
- BLI_ghash_insert(bp->vert_hash, v, bv);
-
- find_bevel_edge_order(bm, bv, first_bme);
-
- /* fill in other attributes of EdgeHalfs */
- for (i = 0; i < ntot; i++) {
- e = &bv->edges[i];
- bme = e->e;
- if (BM_elem_flag_test(bme, BM_ELEM_TAG) && !bp->vertex_only) {
- e->is_bev = true;
- e->seg = bp->seg;
- }
- else {
- e->is_bev = false;
- e->seg = 0;
- }
- e->is_rev = (bme->v2 == v);
- e->leftv = e->rightv = NULL;
- e->profile_index = 0;
- }
-
- /* now done with tag flag */
- BM_ITER_ELEM (bme, &iter, v, BM_EDGES_OF_VERT) {
- BM_BEVEL_EDGE_TAG_DISABLE(bme);
- }
-
- /* if edge array doesn't go CCW around vertex from average normal side,
- * reverse the array, being careful to reverse face pointers too */
- if (ntot > 1) {
- ccw_test_sum = 0;
- for (i = 0; i < ntot; i++) {
- ccw_test_sum += bev_ccw_test(bv->edges[i].e, bv->edges[(i + 1) % ntot].e,
- bv->edges[i].fnext);
- }
- if (ccw_test_sum < 0) {
- for (i = 0; i <= (ntot / 2) - 1; i++) {
- SWAP(EdgeHalf, bv->edges[i], bv->edges[ntot - i - 1]);
- SWAP(BMFace *, bv->edges[i].fprev, bv->edges[i].fnext);
- SWAP(BMFace *, bv->edges[ntot - i - 1].fprev, bv->edges[ntot - i - 1].fnext);
- }
- if (ntot % 2 == 1) {
- i = ntot / 2;
- SWAP(BMFace *, bv->edges[i].fprev, bv->edges[i].fnext);
- }
- }
- }
-
- for (i = 0, e = bv->edges; i < ntot; i++, e++) {
- e->next = &bv->edges[(i + 1) % ntot];
- e->prev = &bv->edges[(i + ntot - 1) % ntot];
-
- /* set offsets */
- if (e->is_bev) {
- /* Convert distance as specified by user into offsets along
- * faces on left side and right side of this edgehalf.
- * Except for percent method, offset will be same on each side. */
-
- switch (bp->offset_type) {
- case BEVEL_AMT_OFFSET:
- e->offset_l_spec = bp->offset;
- break;
- case BEVEL_AMT_WIDTH:
- z = fabsf(2.0f * sinf(edge_face_angle(e) / 2.0f));
- if (z < BEVEL_EPSILON) {
- e->offset_l_spec = 0.01f * bp->offset; /* undefined behavior, so tiny bevel */
- }
- else {
- e->offset_l_spec = bp->offset / z;
- }
- break;
- case BEVEL_AMT_DEPTH:
- z = fabsf(cosf(edge_face_angle(e) / 2.0f));
- if (z < BEVEL_EPSILON) {
- e->offset_l_spec = 0.01f * bp->offset; /* undefined behavior, so tiny bevel */
- }
- else {
- e->offset_l_spec = bp->offset / z;
- }
- break;
- case BEVEL_AMT_PERCENT:
- /* offset needs to be such that it meets adjacent edges at percentage of their lengths */
- v1 = BM_edge_other_vert(e->prev->e, v);
- v2 = BM_edge_other_vert(e->e, v);
- z = sinf(angle_v3v3v3(v1->co, v->co, v2->co));
- e->offset_l_spec = BM_edge_calc_length(e->prev->e) * bp->offset * z / 100.0f;
- v1 = BM_edge_other_vert(e->e, v);
- v2 = BM_edge_other_vert(e->next->e, v);
- z = sinf(angle_v3v3v3(v1->co, v->co, v2->co));
- e->offset_r_spec = BM_edge_calc_length(e->next->e) * bp->offset * z / 100.0f;
- break;
- default:
- BLI_assert(!"bad bevel offset kind");
- e->offset_l_spec = bp->offset;
- break;
- }
- if (bp->offset_type != BEVEL_AMT_PERCENT) {
- e->offset_r_spec = e->offset_l_spec;
- }
- if (bp->use_weights) {
- weight = BM_elem_float_data_get(&bm->edata, e->e, CD_BWEIGHT);
- e->offset_l_spec *= weight;
- e->offset_r_spec *= weight;
- }
- }
- else if (bp->vertex_only) {
- /* Weight has already been applied to bv->offset, if present.
- * Transfer to e->offset_[lr]_spec and treat percent as special case */
- if (bp->offset_type == BEVEL_AMT_PERCENT) {
- v2 = BM_edge_other_vert(e->e, bv->v);
- e->offset_l_spec = BM_edge_calc_length(e->e) * bv->offset / 100.0f;
- }
- else {
- e->offset_l_spec = bv->offset;
- }
- e->offset_r_spec = e->offset_l_spec;
- }
- else {
- e->offset_l_spec = e->offset_r_spec = 0.0f;
- }
- e->offset_l = e->offset_l_spec;
- e->offset_r = e->offset_r_spec;
-
- if (e->fprev && e->fnext) {
- e->is_seam = !contig_ldata_across_edge(bm, e->e, e->fprev, e->fnext);
- }
- else {
- e->is_seam = true;
- }
- }
-
- if (nwire) {
- i = 0;
- BM_ITER_ELEM (bme, &iter, v, BM_EDGES_OF_VERT) {
- if (BM_edge_is_wire(bme)) {
- BLI_assert(i < bv->wirecount);
- bv->wire_edges[i++] = bme;
- }
- }
- BLI_assert(i == bv->wirecount);
- }
-
- return bv;
+ BMEdge *bme;
+ BevVert *bv;
+ BMEdge *first_bme;
+ BMVert *v1, *v2;
+ BMIter iter;
+ EdgeHalf *e;
+ float weight, z;
+ int i, ccw_test_sum;
+ int nsel = 0;
+ int ntot = 0;
+ int nwire = 0;
+ int fcnt;
+
+ /* Gather input selected edges.
+ * Only bevel selected edges that have exactly two incident faces.
+ * Want edges to be ordered so that they share faces.
+ * There may be one or more chains of shared faces broken by
+ * gaps where there are no faces.
+ * Want to ignore wire edges completely for edge beveling.
+ * TODO: make following work when more than one gap.
+ */
+
+ first_bme = NULL;
+ BM_ITER_ELEM (bme, &iter, v, BM_EDGES_OF_VERT) {
+ fcnt = BM_edge_face_count(bme);
+ BM_BEVEL_EDGE_TAG_DISABLE(bme);
+ if (BM_elem_flag_test(bme, BM_ELEM_TAG) && !bp->vertex_only) {
+ BLI_assert(fcnt == 2);
+ nsel++;
+ if (!first_bme) {
+ first_bme = bme;
+ }
+ }
+ if (fcnt == 1) {
+ /* good to start face chain from this edge */
+ first_bme = bme;
+ }
+ if (fcnt > 0 || bp->vertex_only) {
+ ntot++;
+ }
+ if (BM_edge_is_wire(bme)) {
+ nwire++;
+ /* If edge beveling, exclude wire edges from edges array.
+ * Mark this edge as "chosen" so loop below won't choose it. */
+ if (!bp->vertex_only) {
+ BM_BEVEL_EDGE_TAG_ENABLE(bme);
+ }
+ }
+ }
+ if (!first_bme) {
+ first_bme = v->e;
+ }
+
+ if ((nsel == 0 && !bp->vertex_only) || (ntot < 2 && bp->vertex_only)) {
+ /* signal this vert isn't being beveled */
+ BM_elem_flag_disable(v, BM_ELEM_TAG);
+ return NULL;
+ }
+
+ bv = (BevVert *)BLI_memarena_alloc(bp->mem_arena, (sizeof(BevVert)));
+ bv->v = v;
+ bv->edgecount = ntot;
+ bv->selcount = nsel;
+ bv->wirecount = nwire;
+ bv->offset = bp->offset;
+ bv->edges = (EdgeHalf *)BLI_memarena_alloc(bp->mem_arena, ntot * sizeof(EdgeHalf));
+ if (nwire) {
+ bv->wire_edges = (BMEdge **)BLI_memarena_alloc(bp->mem_arena, nwire * sizeof(BMEdge *));
+ }
+ else {
+ bv->wire_edges = NULL;
+ }
+ bv->vmesh = (VMesh *)BLI_memarena_alloc(bp->mem_arena, sizeof(VMesh));
+ bv->vmesh->seg = bp->seg;
+
+ if (bp->vertex_only) {
+ /* if weighted, modify offset by weight */
+ if (bp->dvert != NULL && bp->vertex_group != -1) {
+ weight = defvert_find_weight(bp->dvert + BM_elem_index_get(v), bp->vertex_group);
+ if (weight <= 0.0f) {
+ BM_elem_flag_disable(v, BM_ELEM_TAG);
+ return NULL;
+ }
+ bv->offset *= weight;
+ }
+ else if (bp->use_weights) {
+ weight = BM_elem_float_data_get(&bm->vdata, v, CD_BWEIGHT);
+ bv->offset *= weight;
+ }
+ }
+ BLI_ghash_insert(bp->vert_hash, v, bv);
+
+ find_bevel_edge_order(bm, bv, first_bme);
+
+ /* fill in other attributes of EdgeHalfs */
+ for (i = 0; i < ntot; i++) {
+ e = &bv->edges[i];
+ bme = e->e;
+ if (BM_elem_flag_test(bme, BM_ELEM_TAG) && !bp->vertex_only) {
+ e->is_bev = true;
+ e->seg = bp->seg;
+ }
+ else {
+ e->is_bev = false;
+ e->seg = 0;
+ }
+ e->is_rev = (bme->v2 == v);
+ e->leftv = e->rightv = NULL;
+ e->profile_index = 0;
+ }
+
+ /* now done with tag flag */
+ BM_ITER_ELEM (bme, &iter, v, BM_EDGES_OF_VERT) {
+ BM_BEVEL_EDGE_TAG_DISABLE(bme);
+ }
+
+ /* if edge array doesn't go CCW around vertex from average normal side,
+ * reverse the array, being careful to reverse face pointers too */
+ if (ntot > 1) {
+ ccw_test_sum = 0;
+ for (i = 0; i < ntot; i++) {
+ ccw_test_sum += bev_ccw_test(
+ bv->edges[i].e, bv->edges[(i + 1) % ntot].e, bv->edges[i].fnext);
+ }
+ if (ccw_test_sum < 0) {
+ for (i = 0; i <= (ntot / 2) - 1; i++) {
+ SWAP(EdgeHalf, bv->edges[i], bv->edges[ntot - i - 1]);
+ SWAP(BMFace *, bv->edges[i].fprev, bv->edges[i].fnext);
+ SWAP(BMFace *, bv->edges[ntot - i - 1].fprev, bv->edges[ntot - i - 1].fnext);
+ }
+ if (ntot % 2 == 1) {
+ i = ntot / 2;
+ SWAP(BMFace *, bv->edges[i].fprev, bv->edges[i].fnext);
+ }
+ }
+ }
+
+ for (i = 0, e = bv->edges; i < ntot; i++, e++) {
+ e->next = &bv->edges[(i + 1) % ntot];
+ e->prev = &bv->edges[(i + ntot - 1) % ntot];
+
+ /* set offsets */
+ if (e->is_bev) {
+ /* Convert distance as specified by user into offsets along
+ * faces on left side and right side of this edgehalf.
+ * Except for percent method, offset will be same on each side. */
+
+ switch (bp->offset_type) {
+ case BEVEL_AMT_OFFSET:
+ e->offset_l_spec = bp->offset;
+ break;
+ case BEVEL_AMT_WIDTH:
+ z = fabsf(2.0f * sinf(edge_face_angle(e) / 2.0f));
+ if (z < BEVEL_EPSILON) {
+ e->offset_l_spec = 0.01f * bp->offset; /* undefined behavior, so tiny bevel */
+ }
+ else {
+ e->offset_l_spec = bp->offset / z;
+ }
+ break;
+ case BEVEL_AMT_DEPTH:
+ z = fabsf(cosf(edge_face_angle(e) / 2.0f));
+ if (z < BEVEL_EPSILON) {
+ e->offset_l_spec = 0.01f * bp->offset; /* undefined behavior, so tiny bevel */
+ }
+ else {
+ e->offset_l_spec = bp->offset / z;
+ }
+ break;
+ case BEVEL_AMT_PERCENT:
+ /* offset needs to be such that it meets adjacent edges at percentage of their lengths */
+ v1 = BM_edge_other_vert(e->prev->e, v);
+ v2 = BM_edge_other_vert(e->e, v);
+ z = sinf(angle_v3v3v3(v1->co, v->co, v2->co));
+ e->offset_l_spec = BM_edge_calc_length(e->prev->e) * bp->offset * z / 100.0f;
+ v1 = BM_edge_other_vert(e->e, v);
+ v2 = BM_edge_other_vert(e->next->e, v);
+ z = sinf(angle_v3v3v3(v1->co, v->co, v2->co));
+ e->offset_r_spec = BM_edge_calc_length(e->next->e) * bp->offset * z / 100.0f;
+ break;
+ default:
+ BLI_assert(!"bad bevel offset kind");
+ e->offset_l_spec = bp->offset;
+ break;
+ }
+ if (bp->offset_type != BEVEL_AMT_PERCENT) {
+ e->offset_r_spec = e->offset_l_spec;
+ }
+ if (bp->use_weights) {
+ weight = BM_elem_float_data_get(&bm->edata, e->e, CD_BWEIGHT);
+ e->offset_l_spec *= weight;
+ e->offset_r_spec *= weight;
+ }
+ }
+ else if (bp->vertex_only) {
+ /* Weight has already been applied to bv->offset, if present.
+ * Transfer to e->offset_[lr]_spec and treat percent as special case */
+ if (bp->offset_type == BEVEL_AMT_PERCENT) {
+ v2 = BM_edge_other_vert(e->e, bv->v);
+ e->offset_l_spec = BM_edge_calc_length(e->e) * bv->offset / 100.0f;
+ }
+ else {
+ e->offset_l_spec = bv->offset;
+ }
+ e->offset_r_spec = e->offset_l_spec;
+ }
+ else {
+ e->offset_l_spec = e->offset_r_spec = 0.0f;
+ }
+ e->offset_l = e->offset_l_spec;
+ e->offset_r = e->offset_r_spec;
+
+ if (e->fprev && e->fnext) {
+ e->is_seam = !contig_ldata_across_edge(bm, e->e, e->fprev, e->fnext);
+ }
+ else {
+ e->is_seam = true;
+ }
+ }
+
+ if (nwire) {
+ i = 0;
+ BM_ITER_ELEM (bme, &iter, v, BM_EDGES_OF_VERT) {
+ if (BM_edge_is_wire(bme)) {
+ BLI_assert(i < bv->wirecount);
+ bv->wire_edges[i++] = bme;
+ }
+ }
+ BLI_assert(i == bv->wirecount);
+ }
+
+ return bv;
}
/* Face f has at least one beveled vertex. Rebuild f */
static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
{
- BMIter liter, eiter, fiter;
- BMLoop *l, *lprev;
- BevVert *bv;
- BoundVert *v, *vstart, *vend;
- EdgeHalf *e, *eprev;
- VMesh *vm;
- int i, k, n, kstart, kend;
- bool do_rebuild = false;
- bool go_ccw, corner3special, keep, on_profile_start;
- BMVert *bmv;
- BMEdge *bme, *bme_new, *bme_prev;
- BMFace *f_new, *f_other;
- BMVert **vv = NULL;
- BMVert **vv_fix = NULL;
- BMEdge **ee = NULL;
- BLI_array_staticdeclare(vv, BM_DEFAULT_NGON_STACK_SIZE);
- BLI_array_staticdeclare(vv_fix, BM_DEFAULT_NGON_STACK_SIZE);
- BLI_array_staticdeclare(ee, BM_DEFAULT_NGON_STACK_SIZE);
-
- BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) {
- lprev = l->prev;
- bv = find_bevvert(bp, l->v);
- vm = bv->vmesh;
- e = find_edge_half(bv, l->e);
- BLI_assert(e != NULL);
- bme = e->e;
- eprev = find_edge_half(bv, lprev->e);
- BLI_assert(eprev != NULL);
-
- /* which direction around our vertex do we travel to match orientation of f? */
- if (e->prev == eprev) {
- if (eprev->prev == e) {
- /* valence 2 vertex: use f is one of e->fnext or e->fprev to break tie */
- go_ccw = (e->fnext != f);
- }
- else {
- go_ccw = true; /* going ccw around bv to trace this corner */
- }
- }
- else if (eprev->prev == e) {
- go_ccw = false; /* going cw around bv to trace this corner */
- }
- else {
- /* edges in face are non-contiguous in our ordering around bv.
- * Which way should we go when going from eprev to e? */
- if (count_ccw_edges_between(eprev, e) < count_ccw_edges_between(e, eprev)) {
- /* go counterclockewise from eprev to e */
- go_ccw = true;
- }
- else {
- /* go clockwise from eprev to e */
- go_ccw = false;
- }
- }
- on_profile_start = false;
- if (go_ccw) {
- vstart = eprev->rightv;
- vend = e->leftv;
- if (e->profile_index > 0) {
- vstart = vstart->prev;
- on_profile_start = true;
- }
- }
- else {
- vstart = eprev->leftv;
- vend = e->rightv;
- if (eprev->profile_index > 0) {
- vstart = vstart->next;
- on_profile_start = true;
- }
- }
- BLI_assert(vstart != NULL && vend != NULL);
- v = vstart;
- if (!on_profile_start) {
- BLI_array_append(vv, v->nv.v);
- BLI_array_append(ee, bme);
- }
- while (v != vend) {
- /* check for special case: multisegment 3rd face opposite a beveled edge with no vmesh */
- corner3special = (vm->mesh_kind == M_NONE && v->ebev != e && v->ebev != eprev);
- if (go_ccw) {
- i = v->index;
- if (on_profile_start) {
- kstart = e->profile_index;
- on_profile_start = false;
- }
- else {
- kstart = 1;
- }
- if (eprev->rightv == v && eprev->profile_index > 0) {
- kend = eprev->profile_index;
- }
- else {
- kend = vm->seg;
- }
- for (k = kstart; k <= kend; k++) {
- bmv = mesh_vert(vm, i, 0, k)->v;
- if (bmv) {
- BLI_array_append(vv, bmv);
- BLI_array_append(ee, bme); /* TODO: maybe better edge here */
- if (corner3special && v->ebev && !v->ebev->is_seam && k != vm->seg) {
- BLI_array_append(vv_fix, bmv);
- }
- }
- }
- v = v->next;
- }
- else {
- /* going cw */
- i = v->prev->index;
- if (on_profile_start) {
- kstart = eprev->profile_index;
- on_profile_start = false;
- }
- else {
- kstart = vm->seg - 1;
- }
- if (e->rightv == v->prev && e->profile_index > 0) {
- kend = e->profile_index;
- }
- else {
- kend = 0;
- }
- for (k = kstart; k >= kend; k--) {
- bmv = mesh_vert(vm, i, 0, k)->v;
- if (bmv) {
- BLI_array_append(vv, bmv);
- BLI_array_append(ee, bme);
- if (corner3special && v->ebev && !v->ebev->is_seam && k != 0) {
- BLI_array_append(vv_fix, bmv);
- }
- }
- }
- v = v->prev;
- }
- }
- do_rebuild = true;
- }
- else {
- BLI_array_append(vv, l->v);
- BLI_array_append(ee, l->e);
- }
- }
- if (do_rebuild) {
- n = BLI_array_len(vv);
- f_new = bev_create_ngon(bm, vv, n, NULL, f, NULL, -1, true);
-
- for (k = 0; k < BLI_array_len(vv_fix); k++) {
- bev_merge_uvs(bm, vv_fix[k]);
- }
-
- /* copy attributes from old edges */
- BLI_assert(n == BLI_array_len(ee));
- bme_prev = ee[n - 1];
- for (k = 0; k < n; k++) {
- bme_new = BM_edge_exists(vv[k], vv[(k + 1) % n]);
- BLI_assert(ee[k] && bme_new);
- if (ee[k] != bme_new) {
- BM_elem_attrs_copy(bm, bm, ee[k], bme_new);
- /* want to undo seam and smooth for corner segments
- * if those attrs aren't contiguous around face */
- if (k < n - 1 && ee[k] == ee[k + 1]) {
- if (BM_elem_flag_test(ee[k], BM_ELEM_SEAM) &&
- !BM_elem_flag_test(bme_prev, BM_ELEM_SEAM))
- {
- BM_elem_flag_disable(bme_new, BM_ELEM_SEAM);
- }
- /* actually want "sharp" to be contiguous, so reverse the test */
- if (!BM_elem_flag_test(ee[k], BM_ELEM_SMOOTH) &&
- BM_elem_flag_test(bme_prev, BM_ELEM_SMOOTH))
- {
- BM_elem_flag_enable(bme_new, BM_ELEM_SMOOTH);
- }
- }
- else {
- bme_prev = ee[k];
- }
- }
- }
-
- /* don't select newly or return created boundary faces... */
- if (f_new) {
- record_face_kind(bp, f_new, F_RECON);
- BM_elem_flag_disable(f_new, BM_ELEM_TAG);
- /* Also don't want new edges that aren't part of a new bevel face */
- BM_ITER_ELEM(bme, &eiter, f_new, BM_EDGES_OF_FACE) {
- keep = false;
- BM_ITER_ELEM(f_other, &fiter, bme, BM_FACES_OF_EDGE) {
- if (BM_elem_flag_test(f_other, BM_ELEM_TAG)) {
- keep = true;
- break;
- }
- }
- if (!keep) {
- disable_flag_out_edge(bm, bme);
- }
- }
- }
- }
-
- BLI_array_free(vv);
- BLI_array_free(vv_fix);
- BLI_array_free(ee);
- return do_rebuild;
+ BMIter liter, eiter, fiter;
+ BMLoop *l, *lprev;
+ BevVert *bv;
+ BoundVert *v, *vstart, *vend;
+ EdgeHalf *e, *eprev;
+ VMesh *vm;
+ int i, k, n, kstart, kend;
+ bool do_rebuild = false;
+ bool go_ccw, corner3special, keep, on_profile_start;
+ BMVert *bmv;
+ BMEdge *bme, *bme_new, *bme_prev;
+ BMFace *f_new, *f_other;
+ BMVert **vv = NULL;
+ BMVert **vv_fix = NULL;
+ BMEdge **ee = NULL;
+ BLI_array_staticdeclare(vv, BM_DEFAULT_NGON_STACK_SIZE);
+ BLI_array_staticdeclare(vv_fix, BM_DEFAULT_NGON_STACK_SIZE);
+ BLI_array_staticdeclare(ee, BM_DEFAULT_NGON_STACK_SIZE);
+
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) {
+ lprev = l->prev;
+ bv = find_bevvert(bp, l->v);
+ vm = bv->vmesh;
+ e = find_edge_half(bv, l->e);
+ BLI_assert(e != NULL);
+ bme = e->e;
+ eprev = find_edge_half(bv, lprev->e);
+ BLI_assert(eprev != NULL);
+
+ /* which direction around our vertex do we travel to match orientation of f? */
+ if (e->prev == eprev) {
+ if (eprev->prev == e) {
+ /* valence 2 vertex: use f is one of e->fnext or e->fprev to break tie */
+ go_ccw = (e->fnext != f);
+ }
+ else {
+ go_ccw = true; /* going ccw around bv to trace this corner */
+ }
+ }
+ else if (eprev->prev == e) {
+ go_ccw = false; /* going cw around bv to trace this corner */
+ }
+ else {
+ /* edges in face are non-contiguous in our ordering around bv.
+ * Which way should we go when going from eprev to e? */
+ if (count_ccw_edges_between(eprev, e) < count_ccw_edges_between(e, eprev)) {
+ /* go counterclockewise from eprev to e */
+ go_ccw = true;
+ }
+ else {
+ /* go clockwise from eprev to e */
+ go_ccw = false;
+ }
+ }
+ on_profile_start = false;
+ if (go_ccw) {
+ vstart = eprev->rightv;
+ vend = e->leftv;
+ if (e->profile_index > 0) {
+ vstart = vstart->prev;
+ on_profile_start = true;
+ }
+ }
+ else {
+ vstart = eprev->leftv;
+ vend = e->rightv;
+ if (eprev->profile_index > 0) {
+ vstart = vstart->next;
+ on_profile_start = true;
+ }
+ }
+ BLI_assert(vstart != NULL && vend != NULL);
+ v = vstart;
+ if (!on_profile_start) {
+ BLI_array_append(vv, v->nv.v);
+ BLI_array_append(ee, bme);
+ }
+ while (v != vend) {
+ /* check for special case: multisegment 3rd face opposite a beveled edge with no vmesh */
+ corner3special = (vm->mesh_kind == M_NONE && v->ebev != e && v->ebev != eprev);
+ if (go_ccw) {
+ i = v->index;
+ if (on_profile_start) {
+ kstart = e->profile_index;
+ on_profile_start = false;
+ }
+ else {
+ kstart = 1;
+ }
+ if (eprev->rightv == v && eprev->profile_index > 0) {
+ kend = eprev->profile_index;
+ }
+ else {
+ kend = vm->seg;
+ }
+ for (k = kstart; k <= kend; k++) {
+ bmv = mesh_vert(vm, i, 0, k)->v;
+ if (bmv) {
+ BLI_array_append(vv, bmv);
+ BLI_array_append(ee, bme); /* TODO: maybe better edge here */
+ if (corner3special && v->ebev && !v->ebev->is_seam && k != vm->seg) {
+ BLI_array_append(vv_fix, bmv);
+ }
+ }
+ }
+ v = v->next;
+ }
+ else {
+ /* going cw */
+ i = v->prev->index;
+ if (on_profile_start) {
+ kstart = eprev->profile_index;
+ on_profile_start = false;
+ }
+ else {
+ kstart = vm->seg - 1;
+ }
+ if (e->rightv == v->prev && e->profile_index > 0) {
+ kend = e->profile_index;
+ }
+ else {
+ kend = 0;
+ }
+ for (k = kstart; k >= kend; k--) {
+ bmv = mesh_vert(vm, i, 0, k)->v;
+ if (bmv) {
+ BLI_array_append(vv, bmv);
+ BLI_array_append(ee, bme);
+ if (corner3special && v->ebev && !v->ebev->is_seam && k != 0) {
+ BLI_array_append(vv_fix, bmv);
+ }
+ }
+ }
+ v = v->prev;
+ }
+ }
+ do_rebuild = true;
+ }
+ else {
+ BLI_array_append(vv, l->v);
+ BLI_array_append(ee, l->e);
+ }
+ }
+ if (do_rebuild) {
+ n = BLI_array_len(vv);
+ f_new = bev_create_ngon(bm, vv, n, NULL, f, NULL, -1, true);
+
+ for (k = 0; k < BLI_array_len(vv_fix); k++) {
+ bev_merge_uvs(bm, vv_fix[k]);
+ }
+
+ /* copy attributes from old edges */
+ BLI_assert(n == BLI_array_len(ee));
+ bme_prev = ee[n - 1];
+ for (k = 0; k < n; k++) {
+ bme_new = BM_edge_exists(vv[k], vv[(k + 1) % n]);
+ BLI_assert(ee[k] && bme_new);
+ if (ee[k] != bme_new) {
+ BM_elem_attrs_copy(bm, bm, ee[k], bme_new);
+ /* want to undo seam and smooth for corner segments
+ * if those attrs aren't contiguous around face */
+ if (k < n - 1 && ee[k] == ee[k + 1]) {
+ if (BM_elem_flag_test(ee[k], BM_ELEM_SEAM) &&
+ !BM_elem_flag_test(bme_prev, BM_ELEM_SEAM)) {
+ BM_elem_flag_disable(bme_new, BM_ELEM_SEAM);
+ }
+ /* actually want "sharp" to be contiguous, so reverse the test */
+ if (!BM_elem_flag_test(ee[k], BM_ELEM_SMOOTH) &&
+ BM_elem_flag_test(bme_prev, BM_ELEM_SMOOTH)) {
+ BM_elem_flag_enable(bme_new, BM_ELEM_SMOOTH);
+ }
+ }
+ else {
+ bme_prev = ee[k];
+ }
+ }
+ }
+
+ /* don't select newly or return created boundary faces... */
+ if (f_new) {
+ record_face_kind(bp, f_new, F_RECON);
+ BM_elem_flag_disable(f_new, BM_ELEM_TAG);
+ /* Also don't want new edges that aren't part of a new bevel face */
+ BM_ITER_ELEM (bme, &eiter, f_new, BM_EDGES_OF_FACE) {
+ keep = false;
+ BM_ITER_ELEM (f_other, &fiter, bme, BM_FACES_OF_EDGE) {
+ if (BM_elem_flag_test(f_other, BM_ELEM_TAG)) {
+ keep = true;
+ break;
+ }
+ }
+ if (!keep) {
+ disable_flag_out_edge(bm, bme);
+ }
+ }
+ }
+ }
+
+ BLI_array_free(vv);
+ BLI_array_free(vv_fix);
+ BLI_array_free(ee);
+ return do_rebuild;
}
/* All polygons touching v need rebuilding because beveling v has made new vertices */
static void bevel_rebuild_existing_polygons(BMesh *bm, BevelParams *bp, BMVert *v)
{
- void *faces_stack[BM_DEFAULT_ITER_STACK_SIZE];
- int faces_len, f_index;
- BMFace **faces = BM_iter_as_arrayN(bm, BM_FACES_OF_VERT, v, &faces_len,
- faces_stack, BM_DEFAULT_ITER_STACK_SIZE);
-
- if (LIKELY(faces != NULL)) {
- for (f_index = 0; f_index < faces_len; f_index++) {
- BMFace *f = faces[f_index];
- if (bev_rebuild_polygon(bm, bp, f)) {
- BM_face_kill(bm, f);
- }
- }
-
- if (faces != (BMFace **)faces_stack) {
- MEM_freeN(faces);
- }
- }
+ void *faces_stack[BM_DEFAULT_ITER_STACK_SIZE];
+ int faces_len, f_index;
+ BMFace **faces = BM_iter_as_arrayN(
+ bm, BM_FACES_OF_VERT, v, &faces_len, faces_stack, BM_DEFAULT_ITER_STACK_SIZE);
+
+ if (LIKELY(faces != NULL)) {
+ for (f_index = 0; f_index < faces_len; f_index++) {
+ BMFace *f = faces[f_index];
+ if (bev_rebuild_polygon(bm, bp, f)) {
+ BM_face_kill(bm, f);
+ }
+ }
+
+ if (faces != (BMFace **)faces_stack) {
+ MEM_freeN(faces);
+ }
+ }
}
/* If there were any wire edges, they need to be reattached somewhere */
static void bevel_reattach_wires(BMesh *bm, BevelParams *bp, BMVert *v)
{
- BMEdge *e;
- BMVert *vclosest, *vother, *votherclosest;
- BevVert *bv, *bvother;
- BoundVert *bndv, *bndvother;
- float d, dclosest;
- int i;
-
- bv = find_bevvert(bp, v);
- if (!bv || bv->wirecount == 0 || !bv->vmesh) {
- return;
- }
-
- for (i = 0; i < bv->wirecount; i++) {
- e = bv->wire_edges[i];
- /* look for the new vertex closest to the other end of e */
- vclosest = NULL;
- dclosest = FLT_MAX;
- votherclosest = NULL;
- vother = BM_edge_other_vert(e, v);
- bvother = NULL;
- if (BM_elem_flag_test(vother, BM_ELEM_TAG)) {
- bvother = find_bevvert(bp, vother);
- if (!bvother || !bvother->vmesh) {
- return; /* shouldn't happen */
- }
- }
- bndv = bv->vmesh->boundstart;
- do {
- if (bvother) {
- bndvother = bvother->vmesh->boundstart;
- do {
- d = len_squared_v3v3(bndvother->nv.co, bndv->nv.co);
- if (d < dclosest) {
- vclosest = bndv->nv.v;
- votherclosest = bndvother->nv.v;
- dclosest = d;
-
- }
- } while ((bndvother = bndvother->next) != bvother->vmesh->boundstart);
- }
- else {
- d = len_squared_v3v3(vother->co, bndv->nv.co);
- if (d < dclosest) {
- vclosest = bndv->nv.v;
- votherclosest = vother;
- dclosest = d;
- }
- }
- } while ((bndv = bndv->next) != bv->vmesh->boundstart);
- if (vclosest) {
- BM_edge_create(bm, vclosest, votherclosest, e, BM_CREATE_NO_DOUBLE);
- }
- }
+ BMEdge *e;
+ BMVert *vclosest, *vother, *votherclosest;
+ BevVert *bv, *bvother;
+ BoundVert *bndv, *bndvother;
+ float d, dclosest;
+ int i;
+
+ bv = find_bevvert(bp, v);
+ if (!bv || bv->wirecount == 0 || !bv->vmesh) {
+ return;
+ }
+
+ for (i = 0; i < bv->wirecount; i++) {
+ e = bv->wire_edges[i];
+ /* look for the new vertex closest to the other end of e */
+ vclosest = NULL;
+ dclosest = FLT_MAX;
+ votherclosest = NULL;
+ vother = BM_edge_other_vert(e, v);
+ bvother = NULL;
+ if (BM_elem_flag_test(vother, BM_ELEM_TAG)) {
+ bvother = find_bevvert(bp, vother);
+ if (!bvother || !bvother->vmesh) {
+ return; /* shouldn't happen */
+ }
+ }
+ bndv = bv->vmesh->boundstart;
+ do {
+ if (bvother) {
+ bndvother = bvother->vmesh->boundstart;
+ do {
+ d = len_squared_v3v3(bndvother->nv.co, bndv->nv.co);
+ if (d < dclosest) {
+ vclosest = bndv->nv.v;
+ votherclosest = bndvother->nv.v;
+ dclosest = d;
+ }
+ } while ((bndvother = bndvother->next) != bvother->vmesh->boundstart);
+ }
+ else {
+ d = len_squared_v3v3(vother->co, bndv->nv.co);
+ if (d < dclosest) {
+ vclosest = bndv->nv.v;
+ votherclosest = vother;
+ dclosest = d;
+ }
+ }
+ } while ((bndv = bndv->next) != bv->vmesh->boundstart);
+ if (vclosest) {
+ BM_edge_create(bm, vclosest, votherclosest, e, BM_CREATE_NO_DOUBLE);
+ }
+ }
}
static void bev_merge_end_uvs(BMesh *bm, BevVert *bv, EdgeHalf *e)
{
- VMesh *vm = bv->vmesh;
- int i, k, nseg;
-
- nseg = e->seg;
- i = e->leftv->index;
- for (k = 1; k < nseg; k++) {
- bev_merge_uvs(bm, mesh_vert(vm, i, 0, k)->v);
- }
+ VMesh *vm = bv->vmesh;
+ int i, k, nseg;
+
+ nseg = e->seg;
+ i = e->leftv->index;
+ for (k = 1; k < nseg; k++) {
+ bev_merge_uvs(bm, mesh_vert(vm, i, 0, k)->v);
+ }
}
/*
@@ -5625,9 +5682,9 @@ static void bev_merge_end_uvs(BMesh *bm, BevVert *bv, EdgeHalf *e)
*/
static bool bevvert_is_weld_cross(BevVert *bv)
{
- return (bv->edgecount == 4 && bv->selcount == 2 &&
- ((bv->edges[0].is_bev && bv->edges[2].is_bev) ||
- (bv->edges[1].is_bev && bv->edges[3].is_bev)));
+ return (bv->edgecount == 4 && bv->selcount == 2 &&
+ ((bv->edges[0].is_bev && bv->edges[2].is_bev) ||
+ (bv->edges[1].is_bev && bv->edges[3].is_bev)));
}
/*
@@ -5651,37 +5708,38 @@ static bool bevvert_is_weld_cross(BevVert *bv)
*/
static void weld_cross_attrs_copy(BMesh *bm, BevVert *bv, VMesh *vm, int vmindex, EdgeHalf *e)
{
- BMEdge *bme_prev, *bme_next, *bme;
- int i, nseg;
- bool disable_seam, enable_smooth;
-
- bme_prev = bme_next = NULL;
- for (i = 0; i < 4; i++) {
- if (&bv->edges[i] == e) {
- bme_prev = bv->edges[(i + 3) % 4].e;
- bme_next = bv->edges[(i + 1) % 4].e;
- break;
- }
- }
- BLI_assert(bme_prev && bme_next);
-
- /* want seams and sharp edges to cross only if that way on both sides */
- disable_seam = BM_elem_flag_test(bme_prev, BM_ELEM_SEAM) != BM_elem_flag_test(bme_next, BM_ELEM_SEAM);
- enable_smooth = BM_elem_flag_test(bme_prev, BM_ELEM_SMOOTH) != BM_elem_flag_test(bme_next, BM_ELEM_SMOOTH);
-
- nseg = e->seg;
- for (i = 0; i < nseg; i++) {
- bme = BM_edge_exists(mesh_vert(vm, vmindex, 0, i)->v,
- mesh_vert(vm, vmindex, 0, i + 1)->v);
- BLI_assert(bme);
- BM_elem_attrs_copy(bm, bm, bme_prev, bme);
- if (disable_seam) {
- BM_elem_flag_disable(bme, BM_ELEM_SEAM);
- }
- if (enable_smooth) {
- BM_elem_flag_enable(bme, BM_ELEM_SMOOTH);
- }
- }
+ BMEdge *bme_prev, *bme_next, *bme;
+ int i, nseg;
+ bool disable_seam, enable_smooth;
+
+ bme_prev = bme_next = NULL;
+ for (i = 0; i < 4; i++) {
+ if (&bv->edges[i] == e) {
+ bme_prev = bv->edges[(i + 3) % 4].e;
+ bme_next = bv->edges[(i + 1) % 4].e;
+ break;
+ }
+ }
+ BLI_assert(bme_prev && bme_next);
+
+ /* want seams and sharp edges to cross only if that way on both sides */
+ disable_seam = BM_elem_flag_test(bme_prev, BM_ELEM_SEAM) !=
+ BM_elem_flag_test(bme_next, BM_ELEM_SEAM);
+ enable_smooth = BM_elem_flag_test(bme_prev, BM_ELEM_SMOOTH) !=
+ BM_elem_flag_test(bme_next, BM_ELEM_SMOOTH);
+
+ nseg = e->seg;
+ for (i = 0; i < nseg; i++) {
+ bme = BM_edge_exists(mesh_vert(vm, vmindex, 0, i)->v, mesh_vert(vm, vmindex, 0, i + 1)->v);
+ BLI_assert(bme);
+ BM_elem_attrs_copy(bm, bm, bme_prev, bme);
+ if (disable_seam) {
+ BM_elem_flag_disable(bme, BM_ELEM_SEAM);
+ }
+ if (enable_smooth) {
+ BM_elem_flag_enable(bme, BM_ELEM_SMOOTH);
+ }
+ }
}
/*
@@ -5689,144 +5747,144 @@ static void weld_cross_attrs_copy(BMesh *bm, BevVert *bv, VMesh *vm, int vmindex
*/
static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme)
{
- BevVert *bv1, *bv2;
- BMVert *bmv1, *bmv2, *bmv3, *bmv4;
- VMesh *vm1, *vm2;
- EdgeHalf *e1, *e2;
- BMEdge *bme1, *bme2, *center_bme;
- BMFace *f1, *f2, *f, *r_f;
- BMVert *verts[4];
- BMFace *faces[4];
- BMEdge *edges[4];
- BMLoop *l;
- BMIter iter;
- int k, nseg, i1, i2, odd, mid;
- int mat_nr = bp->mat_nr;
-
- if (!BM_edge_is_manifold(bme)) {
- return;
- }
-
- bv1 = find_bevvert(bp, bme->v1);
- bv2 = find_bevvert(bp, bme->v2);
-
- BLI_assert(bv1 && bv2);
-
- e1 = find_edge_half(bv1, bme);
- e2 = find_edge_half(bv2, bme);
-
- BLI_assert(e1 && e2);
-
- /*
- * bme->v1
- * / | \
- * v1--|--v4
- * | | |
- * | | |
- * v2--|--v3
- * \ | /
- * bme->v2
- */
- nseg = e1->seg;
- BLI_assert(nseg > 0 && nseg == e2->seg);
-
- bmv1 = e1->leftv->nv.v;
- bmv4 = e1->rightv->nv.v;
- bmv2 = e2->rightv->nv.v;
- bmv3 = e2->leftv->nv.v;
-
- BLI_assert(bmv1 && bmv2 && bmv3 && bmv4);
-
- f1 = e1->fprev;
- f2 = e1->fnext;
- faces[0] = faces[1] = f1;
- faces[2] = faces[3] = f2;
- i1 = e1->leftv->index;
- i2 = e2->leftv->index;
- vm1 = bv1->vmesh;
- vm2 = bv2->vmesh;
-
- verts[0] = bmv1;
- verts[1] = bmv2;
- odd = nseg % 2;
- mid = nseg / 2;
- center_bme = NULL;
- for (k = 1; k <= nseg; k++) {
- verts[3] = mesh_vert(vm1, i1, 0, k)->v;
- verts[2] = mesh_vert(vm2, i2, 0, nseg - k)->v;
- if (odd && k == mid + 1) {
- if (e1->is_seam) {
- /* straddles a seam: choose to interpolate in f1 and snap right edge to bme */
- edges[0] = edges[1] = NULL;
- edges[2] = edges[3] = bme;
- r_f = bev_create_ngon(bm, verts, 4, NULL, f1, edges, mat_nr, true);
- }
- else {
- /* straddles but not a seam: interpolate left half in f1, right half in f2 */
- r_f = bev_create_ngon(bm, verts, 4, faces, NULL, NULL, mat_nr, true);
- }
- }
- else if (!odd && k == mid) {
- /* left poly that touches an even center line on right */
- edges[0] = edges[1] = NULL;
- edges[2] = edges[3] = bme;
- r_f = bev_create_ngon(bm, verts, 4, NULL, f1, edges, mat_nr, true);
- center_bme = BM_edge_exists(verts[2], verts[3]);
- BLI_assert(center_bme != NULL);
- }
- else if (!odd && k == mid + 1) {
- /* right poly that touches an even center line on left */
- edges[0] = edges[1] = bme;
- edges[2] = edges[3] = NULL;
- r_f = bev_create_ngon(bm, verts, 4, NULL, f2, edges, mat_nr, true);
- }
- else {
- /* doesn't cross or touch the center line, so interpolate in appropriate f1 or f2 */
- f = (k <= mid) ? f1 : f2;
- r_f = bev_create_ngon(bm, verts, 4, NULL, f, NULL, mat_nr, true);
- }
- record_face_kind(bp, r_f, F_EDGE);
- /* tag the long edges: those out of verts[0] and verts[2] */
- BM_ITER_ELEM(l, &iter, r_f, BM_LOOPS_OF_FACE) {
- if (l->v == verts[0] || l->v == verts[2]) {
- BM_elem_flag_enable(l, BM_ELEM_LONG_TAG);
- }
- }
- verts[0] = verts[3];
- verts[1] = verts[2];
- }
- if (!odd) {
- if (!e1->is_seam) {
- bev_merge_edge_uvs(bm, center_bme, mesh_vert(vm1, i1, 0, mid)->v);
- }
- if (!e2->is_seam) {
- bev_merge_edge_uvs(bm, center_bme, mesh_vert(vm2, i2, 0, mid)->v);
- }
- }
-
- /* Fix UVs along end edge joints. A nop unless other side built already. */
- /* TODO: if some seam, may want to do selective merge */
- if (!bv1->any_seam && bv1->vmesh->mesh_kind == M_NONE) {
- bev_merge_end_uvs(bm, bv1, e1);
- }
- if (!bv2->any_seam && bv2->vmesh->mesh_kind == M_NONE) {
- bev_merge_end_uvs(bm, bv2, e2);
- }
-
- /* Copy edge data to first and last edge */
- bme1 = BM_edge_exists(bmv1, bmv2);
- bme2 = BM_edge_exists(bmv3, bmv4);
- BLI_assert(bme1 && bme2);
- BM_elem_attrs_copy(bm, bm, bme, bme1);
- BM_elem_attrs_copy(bm, bm, bme, bme2);
-
- /* If either end is a "weld cross", want continuity of edge attributes across end edge(s) */
- if (bevvert_is_weld_cross(bv1)) {
- weld_cross_attrs_copy(bm, bv1, vm1, i1, e1);
- }
- if (bevvert_is_weld_cross(bv2)) {
- weld_cross_attrs_copy(bm, bv2, vm2, i2, e2);
- }
+ BevVert *bv1, *bv2;
+ BMVert *bmv1, *bmv2, *bmv3, *bmv4;
+ VMesh *vm1, *vm2;
+ EdgeHalf *e1, *e2;
+ BMEdge *bme1, *bme2, *center_bme;
+ BMFace *f1, *f2, *f, *r_f;
+ BMVert *verts[4];
+ BMFace *faces[4];
+ BMEdge *edges[4];
+ BMLoop *l;
+ BMIter iter;
+ int k, nseg, i1, i2, odd, mid;
+ int mat_nr = bp->mat_nr;
+
+ if (!BM_edge_is_manifold(bme)) {
+ return;
+ }
+
+ bv1 = find_bevvert(bp, bme->v1);
+ bv2 = find_bevvert(bp, bme->v2);
+
+ BLI_assert(bv1 && bv2);
+
+ e1 = find_edge_half(bv1, bme);
+ e2 = find_edge_half(bv2, bme);
+
+ BLI_assert(e1 && e2);
+
+ /*
+ * bme->v1
+ * / | \
+ * v1--|--v4
+ * | | |
+ * | | |
+ * v2--|--v3
+ * \ | /
+ * bme->v2
+ */
+ nseg = e1->seg;
+ BLI_assert(nseg > 0 && nseg == e2->seg);
+
+ bmv1 = e1->leftv->nv.v;
+ bmv4 = e1->rightv->nv.v;
+ bmv2 = e2->rightv->nv.v;
+ bmv3 = e2->leftv->nv.v;
+
+ BLI_assert(bmv1 && bmv2 && bmv3 && bmv4);
+
+ f1 = e1->fprev;
+ f2 = e1->fnext;
+ faces[0] = faces[1] = f1;
+ faces[2] = faces[3] = f2;
+ i1 = e1->leftv->index;
+ i2 = e2->leftv->index;
+ vm1 = bv1->vmesh;
+ vm2 = bv2->vmesh;
+
+ verts[0] = bmv1;
+ verts[1] = bmv2;
+ odd = nseg % 2;
+ mid = nseg / 2;
+ center_bme = NULL;
+ for (k = 1; k <= nseg; k++) {
+ verts[3] = mesh_vert(vm1, i1, 0, k)->v;
+ verts[2] = mesh_vert(vm2, i2, 0, nseg - k)->v;
+ if (odd && k == mid + 1) {
+ if (e1->is_seam) {
+ /* straddles a seam: choose to interpolate in f1 and snap right edge to bme */
+ edges[0] = edges[1] = NULL;
+ edges[2] = edges[3] = bme;
+ r_f = bev_create_ngon(bm, verts, 4, NULL, f1, edges, mat_nr, true);
+ }
+ else {
+ /* straddles but not a seam: interpolate left half in f1, right half in f2 */
+ r_f = bev_create_ngon(bm, verts, 4, faces, NULL, NULL, mat_nr, true);
+ }
+ }
+ else if (!odd && k == mid) {
+ /* left poly that touches an even center line on right */
+ edges[0] = edges[1] = NULL;
+ edges[2] = edges[3] = bme;
+ r_f = bev_create_ngon(bm, verts, 4, NULL, f1, edges, mat_nr, true);
+ center_bme = BM_edge_exists(verts[2], verts[3]);
+ BLI_assert(center_bme != NULL);
+ }
+ else if (!odd && k == mid + 1) {
+ /* right poly that touches an even center line on left */
+ edges[0] = edges[1] = bme;
+ edges[2] = edges[3] = NULL;
+ r_f = bev_create_ngon(bm, verts, 4, NULL, f2, edges, mat_nr, true);
+ }
+ else {
+ /* doesn't cross or touch the center line, so interpolate in appropriate f1 or f2 */
+ f = (k <= mid) ? f1 : f2;
+ r_f = bev_create_ngon(bm, verts, 4, NULL, f, NULL, mat_nr, true);
+ }
+ record_face_kind(bp, r_f, F_EDGE);
+ /* tag the long edges: those out of verts[0] and verts[2] */
+ BM_ITER_ELEM (l, &iter, r_f, BM_LOOPS_OF_FACE) {
+ if (l->v == verts[0] || l->v == verts[2]) {
+ BM_elem_flag_enable(l, BM_ELEM_LONG_TAG);
+ }
+ }
+ verts[0] = verts[3];
+ verts[1] = verts[2];
+ }
+ if (!odd) {
+ if (!e1->is_seam) {
+ bev_merge_edge_uvs(bm, center_bme, mesh_vert(vm1, i1, 0, mid)->v);
+ }
+ if (!e2->is_seam) {
+ bev_merge_edge_uvs(bm, center_bme, mesh_vert(vm2, i2, 0, mid)->v);
+ }
+ }
+
+ /* Fix UVs along end edge joints. A nop unless other side built already. */
+ /* TODO: if some seam, may want to do selective merge */
+ if (!bv1->any_seam && bv1->vmesh->mesh_kind == M_NONE) {
+ bev_merge_end_uvs(bm, bv1, e1);
+ }
+ if (!bv2->any_seam && bv2->vmesh->mesh_kind == M_NONE) {
+ bev_merge_end_uvs(bm, bv2, e2);
+ }
+
+ /* Copy edge data to first and last edge */
+ bme1 = BM_edge_exists(bmv1, bmv2);
+ bme2 = BM_edge_exists(bmv3, bmv4);
+ BLI_assert(bme1 && bme2);
+ BM_elem_attrs_copy(bm, bm, bme, bme1);
+ BM_elem_attrs_copy(bm, bm, bme, bme2);
+
+ /* If either end is a "weld cross", want continuity of edge attributes across end edge(s) */
+ if (bevvert_is_weld_cross(bv1)) {
+ weld_cross_attrs_copy(bm, bv1, vm1, i1, e1);
+ }
+ if (bevvert_is_weld_cross(bv2)) {
+ weld_cross_attrs_copy(bm, bv2, vm2, i2, e2);
+ }
}
/* Find xnew > x0 so that distance((x0,y0), (xnew, ynew)) = dtarget.
@@ -5836,64 +5894,64 @@ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme)
* x in [x0, x0+dtarget] */
static double find_superellipse_chord_endpoint(double x0, double dtarget, float r, bool rbig)
{
- double xmin, xmax, ymin, ymax, dmaxerr, dminerr, dnewerr, xnew, ynew;
- double y0 = superellipse_co(x0, r, rbig);
- const double tol = 1e-13; // accumulates for many segments so use low value
- const int maxiter = 10;
- bool lastupdated_upper;
-
- /* For gradient between -1 and 1, xnew can only be in
- * [x0 + sqrt(2)/2*dtarget, x0 + dtarget]. */
- xmin = x0 + M_SQRT2 / 2.0 * dtarget;
- if (xmin > 1.0) {
- xmin = 1.0;
- }
- xmax = x0 + dtarget;
- if (xmax > 1.0) {
- xmax = 1.0;
- }
- ymin = superellipse_co(xmin, r, rbig);
- ymax = superellipse_co(xmax, r, rbig);
-
- /* Note: using distance**2 (no sqrt needed) does not converge that well. */
- dmaxerr = sqrt(pow((xmax - x0), 2) + pow((ymax - y0), 2)) - dtarget;
- dminerr = sqrt(pow((xmin - x0), 2) + pow((ymin - y0), 2)) - dtarget;
-
- xnew = xmax - dmaxerr * (xmax - xmin) / (dmaxerr - dminerr);
- lastupdated_upper = true;
-
- for (int iter = 0; iter < maxiter; iter++) {
- ynew = superellipse_co(xnew, r, rbig);
- dnewerr = sqrt(pow((xnew - x0), 2) + pow((ynew - y0), 2)) - dtarget;
- if (fabs(dnewerr) < tol) {
- break;
- }
- if (dnewerr < 0) {
- xmin = xnew;
- ymin = ynew;
- dminerr = dnewerr;
- if (!lastupdated_upper) {
- xnew = (dmaxerr / 2 * xmin - dminerr * xmax) / (dmaxerr / 2 - dminerr);
- }
- else {
- xnew = xmax - dmaxerr * (xmax - xmin) / (dmaxerr - dminerr);
- }
- lastupdated_upper = false;
- }
- else {
- xmax = xnew;
- ymax = ynew;
- dmaxerr = dnewerr;
- if (lastupdated_upper) {
- xnew = (dmaxerr * xmin - dminerr / 2 * xmax) / (dmaxerr - dminerr / 2);
- }
- else {
- xnew = xmax - dmaxerr * (xmax - xmin) / (dmaxerr - dminerr);
- }
- lastupdated_upper = true;
- }
- }
- return xnew;
+ double xmin, xmax, ymin, ymax, dmaxerr, dminerr, dnewerr, xnew, ynew;
+ double y0 = superellipse_co(x0, r, rbig);
+ const double tol = 1e-13; // accumulates for many segments so use low value
+ const int maxiter = 10;
+ bool lastupdated_upper;
+
+ /* For gradient between -1 and 1, xnew can only be in
+ * [x0 + sqrt(2)/2*dtarget, x0 + dtarget]. */
+ xmin = x0 + M_SQRT2 / 2.0 * dtarget;
+ if (xmin > 1.0) {
+ xmin = 1.0;
+ }
+ xmax = x0 + dtarget;
+ if (xmax > 1.0) {
+ xmax = 1.0;
+ }
+ ymin = superellipse_co(xmin, r, rbig);
+ ymax = superellipse_co(xmax, r, rbig);
+
+ /* Note: using distance**2 (no sqrt needed) does not converge that well. */
+ dmaxerr = sqrt(pow((xmax - x0), 2) + pow((ymax - y0), 2)) - dtarget;
+ dminerr = sqrt(pow((xmin - x0), 2) + pow((ymin - y0), 2)) - dtarget;
+
+ xnew = xmax - dmaxerr * (xmax - xmin) / (dmaxerr - dminerr);
+ lastupdated_upper = true;
+
+ for (int iter = 0; iter < maxiter; iter++) {
+ ynew = superellipse_co(xnew, r, rbig);
+ dnewerr = sqrt(pow((xnew - x0), 2) + pow((ynew - y0), 2)) - dtarget;
+ if (fabs(dnewerr) < tol) {
+ break;
+ }
+ if (dnewerr < 0) {
+ xmin = xnew;
+ ymin = ynew;
+ dminerr = dnewerr;
+ if (!lastupdated_upper) {
+ xnew = (dmaxerr / 2 * xmin - dminerr * xmax) / (dmaxerr / 2 - dminerr);
+ }
+ else {
+ xnew = xmax - dmaxerr * (xmax - xmin) / (dmaxerr - dminerr);
+ }
+ lastupdated_upper = false;
+ }
+ else {
+ xmax = xnew;
+ ymax = ynew;
+ dmaxerr = dnewerr;
+ if (lastupdated_upper) {
+ xnew = (dmaxerr * xmin - dminerr / 2 * xmax) / (dmaxerr - dminerr / 2);
+ }
+ else {
+ xnew = xmax - dmaxerr * (xmax - xmin) / (dmaxerr - dminerr);
+ }
+ lastupdated_upper = true;
+ }
+ }
+ return xnew;
}
/**
@@ -5907,100 +5965,99 @@ static double find_superellipse_chord_endpoint(double x0, double dtarget, float
*/
static void find_even_superellipse_chords_general(int seg, float r, double *xvals, double *yvals)
{
- const int smoothitermax = 10;
- const double error_tol = 1e-7;
- int i;
- int imax = (seg + 1) / 2 - 1; /* ceiling division - 1 */
-
- double d, dmin, dmax;
- double davg;
- double mx;
- double sum;
- double temp;
-
- bool precision_reached = true;
- bool seg_odd = seg % 2;
- bool rbig;
-
- if (r > 1.0f) {
- rbig = true;
- mx = pow(0.5, 1.0 / r);
- }
- else {
- rbig = false;
- mx = 1 - pow(0.5, 1.0 / r);
- }
-
- /* Initial positions, linear spacing along x axis. */
- for (i = 0; i <= imax; i++) {
- xvals[i] = i * mx / seg * 2;
- yvals[i] = superellipse_co(xvals[i], r, rbig);
- }
- yvals[0] = 1;
-
- /* Smooth distance loop */
- for (int iter = 0; iter < smoothitermax; iter++) {
- sum = 0.0;
- dmin = 2.0;
- dmax = 0.0;
- /* Update distances between neighbor points. Store the highest and
- * lowest to see if the maximum error to average distance (which isn't
- * known yet) is below required precision. */
- for (i = 0; i < imax; i++) {
- d = sqrt(pow((xvals[i + 1] - xvals[i]), 2) + pow((yvals[i + 1] - yvals[i]), 2));
- sum += d;
- if (d > dmax) {
- dmax = d;
- }
- if (d < dmin) {
- dmin = d;
- }
- }
- /* For last distance, weight with 1/2 if seg_odd. */
- if (seg_odd) {
- sum += M_SQRT2 / 2 * (yvals[imax] - xvals[imax]);
- davg = sum / (imax + 0.5);
- }
- else {
- sum += sqrt(pow((xvals[imax] - mx), 2) + pow((yvals[imax] - mx), 2));
- davg = sum / (imax + 1.0);
- }
- /* Max error in tolerance? -> Quit. */
- if (dmax - davg > error_tol) {
- precision_reached = false;
- }
- if (dmin - davg < error_tol) {
- precision_reached = false;
- }
- if (precision_reached) {
- break;
- }
-
-
- /* Update new coordinates. */
- for (i = 1; i <= imax; i++) {
- xvals[i] = find_superellipse_chord_endpoint(xvals[i - 1], davg, r, rbig);
- yvals[i] = superellipse_co(xvals[i], r, rbig);
- }
- }
-
- /* Fill remaining. */
- if (!seg_odd) {
- xvals[imax + 1] = mx;
- yvals[imax + 1] = mx;
- }
- for (i = imax + 1; i <= seg; i++) {
- yvals[i] = xvals[seg - i];
- xvals[i] = yvals[seg - i];
- }
-
- if (!rbig) {
- for (i = 0; i <= seg; i++) {
- temp = xvals[i];
- xvals[i] = 1.0 - yvals[i];
- yvals[i] = 1.0 - temp;
- }
- }
+ const int smoothitermax = 10;
+ const double error_tol = 1e-7;
+ int i;
+ int imax = (seg + 1) / 2 - 1; /* ceiling division - 1 */
+
+ double d, dmin, dmax;
+ double davg;
+ double mx;
+ double sum;
+ double temp;
+
+ bool precision_reached = true;
+ bool seg_odd = seg % 2;
+ bool rbig;
+
+ if (r > 1.0f) {
+ rbig = true;
+ mx = pow(0.5, 1.0 / r);
+ }
+ else {
+ rbig = false;
+ mx = 1 - pow(0.5, 1.0 / r);
+ }
+
+ /* Initial positions, linear spacing along x axis. */
+ for (i = 0; i <= imax; i++) {
+ xvals[i] = i * mx / seg * 2;
+ yvals[i] = superellipse_co(xvals[i], r, rbig);
+ }
+ yvals[0] = 1;
+
+ /* Smooth distance loop */
+ for (int iter = 0; iter < smoothitermax; iter++) {
+ sum = 0.0;
+ dmin = 2.0;
+ dmax = 0.0;
+ /* Update distances between neighbor points. Store the highest and
+ * lowest to see if the maximum error to average distance (which isn't
+ * known yet) is below required precision. */
+ for (i = 0; i < imax; i++) {
+ d = sqrt(pow((xvals[i + 1] - xvals[i]), 2) + pow((yvals[i + 1] - yvals[i]), 2));
+ sum += d;
+ if (d > dmax) {
+ dmax = d;
+ }
+ if (d < dmin) {
+ dmin = d;
+ }
+ }
+ /* For last distance, weight with 1/2 if seg_odd. */
+ if (seg_odd) {
+ sum += M_SQRT2 / 2 * (yvals[imax] - xvals[imax]);
+ davg = sum / (imax + 0.5);
+ }
+ else {
+ sum += sqrt(pow((xvals[imax] - mx), 2) + pow((yvals[imax] - mx), 2));
+ davg = sum / (imax + 1.0);
+ }
+ /* Max error in tolerance? -> Quit. */
+ if (dmax - davg > error_tol) {
+ precision_reached = false;
+ }
+ if (dmin - davg < error_tol) {
+ precision_reached = false;
+ }
+ if (precision_reached) {
+ break;
+ }
+
+ /* Update new coordinates. */
+ for (i = 1; i <= imax; i++) {
+ xvals[i] = find_superellipse_chord_endpoint(xvals[i - 1], davg, r, rbig);
+ yvals[i] = superellipse_co(xvals[i], r, rbig);
+ }
+ }
+
+ /* Fill remaining. */
+ if (!seg_odd) {
+ xvals[imax + 1] = mx;
+ yvals[imax + 1] = mx;
+ }
+ for (i = imax + 1; i <= seg; i++) {
+ yvals[i] = xvals[seg - i];
+ xvals[i] = yvals[seg - i];
+ }
+
+ if (!rbig) {
+ for (i = 0; i <= seg; i++) {
+ temp = xvals[i];
+ xvals[i] = 1.0 - yvals[i];
+ yvals[i] = 1.0 - temp;
+ }
+ }
}
/**
@@ -6013,79 +6070,78 @@ static void find_even_superellipse_chords_general(int seg, float r, double *xval
*/
static void find_even_superellipse_chords(int n, float r, double *xvals, double *yvals)
{
- int i, n2;
- double temp;
- bool seg_odd = n % 2;
-
- n2 = n / 2;
-
- /* Special cases. */
- if (r == PRO_LINE_R) {
- /* Linear spacing */
- for (i = 0; i <= n; i++) {
- xvals[i] = (double) i / n;
- yvals[i] = 1.0 - (double) i / n;
- }
- return;
- }
- if (r == PRO_CIRCLE_R) {
- temp = (M_PI / 2) / n;
- /* Angle spacing. */
- for (i = 0; i <= n; i++) {
- xvals[i] = sin(i * temp);
- yvals[i] = cos(i * temp);
- }
- return;
- }
- if (r == PRO_SQUARE_IN_R) {
- /* n is even, distribute first and second half linear. */
- if (!seg_odd) {
- for (i = 0; i <= n2; i++) {
- xvals[i] = 0.0;
- yvals[i] = 1.0 - (double) i / n2;
- xvals[n - i] = yvals[i];
- yvals[n - i] = xvals[i];
- }
- }
- /* n is odd, so get one corner-cut chord. */
- else {
- temp = 1.0 / (n2 + M_SQRT2 / 2.0);
- for (i = 0; i <= n2; i++) {
- xvals[i] = 0.0;
- yvals[i] = 1.0 - (double) i * temp;
- xvals[n -i ] = yvals[i];
- yvals[n - i] = xvals[i];
- }
- }
- return;
- }
- if (r == PRO_SQUARE_R) {
- /* n is even, distribute first and second half linear. */
- if (!seg_odd) {
- for (i = 0; i <= n2; i++) {
- xvals[i] = (double) i / n2;
- yvals[i] = 1.0;
- xvals[n - i] = yvals[i];
- yvals[n - i] = xvals[i];
- }
- }
- /* n is odd, so get one corner-cut chord. */
- else {
- temp = 1.0 / (n2 + M_SQRT2 / 2);
- for (i = 0; i <= n2; i++) {
- xvals[i] = (double) i * temp;
- yvals[i] = 1.0;
- xvals[n - i] = yvals[i];
- yvals[n - i] = xvals[i];
- }
- }
- return;
- }
- /* For general case use the more expensive search algorithm. */
- find_even_superellipse_chords_general(n, r, xvals, yvals);
+ int i, n2;
+ double temp;
+ bool seg_odd = n % 2;
+
+ n2 = n / 2;
+
+ /* Special cases. */
+ if (r == PRO_LINE_R) {
+ /* Linear spacing */
+ for (i = 0; i <= n; i++) {
+ xvals[i] = (double)i / n;
+ yvals[i] = 1.0 - (double)i / n;
+ }
+ return;
+ }
+ if (r == PRO_CIRCLE_R) {
+ temp = (M_PI / 2) / n;
+ /* Angle spacing. */
+ for (i = 0; i <= n; i++) {
+ xvals[i] = sin(i * temp);
+ yvals[i] = cos(i * temp);
+ }
+ return;
+ }
+ if (r == PRO_SQUARE_IN_R) {
+ /* n is even, distribute first and second half linear. */
+ if (!seg_odd) {
+ for (i = 0; i <= n2; i++) {
+ xvals[i] = 0.0;
+ yvals[i] = 1.0 - (double)i / n2;
+ xvals[n - i] = yvals[i];
+ yvals[n - i] = xvals[i];
+ }
+ }
+ /* n is odd, so get one corner-cut chord. */
+ else {
+ temp = 1.0 / (n2 + M_SQRT2 / 2.0);
+ for (i = 0; i <= n2; i++) {
+ xvals[i] = 0.0;
+ yvals[i] = 1.0 - (double)i * temp;
+ xvals[n - i] = yvals[i];
+ yvals[n - i] = xvals[i];
+ }
+ }
+ return;
+ }
+ if (r == PRO_SQUARE_R) {
+ /* n is even, distribute first and second half linear. */
+ if (!seg_odd) {
+ for (i = 0; i <= n2; i++) {
+ xvals[i] = (double)i / n2;
+ yvals[i] = 1.0;
+ xvals[n - i] = yvals[i];
+ yvals[n - i] = xvals[i];
+ }
+ }
+ /* n is odd, so get one corner-cut chord. */
+ else {
+ temp = 1.0 / (n2 + M_SQRT2 / 2);
+ for (i = 0; i <= n2; i++) {
+ xvals[i] = (double)i * temp;
+ yvals[i] = 1.0;
+ xvals[n - i] = yvals[i];
+ yvals[n - i] = xvals[i];
+ }
+ }
+ return;
+ }
+ /* For general case use the more expensive search algorithm. */
+ find_even_superellipse_chords_general(n, r, xvals, yvals);
}
-
/* The superellipse used for multisegment profiles does not
* have a closed-form way to generate evenly spaced points
* along an arc. We use an expensive search procedure to find
@@ -6096,35 +6152,41 @@ static void find_even_superellipse_chords(int n, float r, double *xvals, double
* precision for final results. */
static void set_profile_spacing(BevelParams *bp)
{
- int seg, seg_2;
-
- seg = bp->seg;
- if (seg > 1) {
- bp->pro_spacing.xvals = (double *)BLI_memarena_alloc(bp->mem_arena, (seg + 1) * sizeof(double));
- bp->pro_spacing.yvals = (double *)BLI_memarena_alloc(bp->mem_arena, (seg + 1) * sizeof(double));
- find_even_superellipse_chords(seg, bp->pro_super_r, bp->pro_spacing.xvals, bp->pro_spacing.yvals);
- seg_2 = power_of_2_max_i(bp->seg);
- if (seg_2 == 2) {
- seg_2 = 4;
- }
- bp->pro_spacing.seg_2 = seg_2;
- if (seg_2 == seg) {
- bp->pro_spacing.xvals_2 = bp->pro_spacing.xvals;
- bp->pro_spacing.yvals_2 = bp->pro_spacing.yvals;
- }
- else {
- bp->pro_spacing.xvals_2 = (double *)BLI_memarena_alloc(bp->mem_arena, (seg_2 + 1) * sizeof(double));
- bp->pro_spacing.yvals_2 = (double *)BLI_memarena_alloc(bp->mem_arena, (seg_2 + 1) * sizeof(double));
- find_even_superellipse_chords(seg_2, bp->pro_super_r, bp->pro_spacing.xvals_2, bp->pro_spacing.yvals_2);
- }
- }
- else {
- bp->pro_spacing.xvals = NULL;
- bp->pro_spacing.yvals = NULL;
- bp->pro_spacing.xvals_2 = NULL;
- bp->pro_spacing.yvals_2 = NULL;
- bp->pro_spacing.seg_2 = 0;
- }
+ int seg, seg_2;
+
+ seg = bp->seg;
+ if (seg > 1) {
+ bp->pro_spacing.xvals = (double *)BLI_memarena_alloc(bp->mem_arena,
+ (seg + 1) * sizeof(double));
+ bp->pro_spacing.yvals = (double *)BLI_memarena_alloc(bp->mem_arena,
+ (seg + 1) * sizeof(double));
+ find_even_superellipse_chords(
+ seg, bp->pro_super_r, bp->pro_spacing.xvals, bp->pro_spacing.yvals);
+ seg_2 = power_of_2_max_i(bp->seg);
+ if (seg_2 == 2) {
+ seg_2 = 4;
+ }
+ bp->pro_spacing.seg_2 = seg_2;
+ if (seg_2 == seg) {
+ bp->pro_spacing.xvals_2 = bp->pro_spacing.xvals;
+ bp->pro_spacing.yvals_2 = bp->pro_spacing.yvals;
+ }
+ else {
+ bp->pro_spacing.xvals_2 = (double *)BLI_memarena_alloc(bp->mem_arena,
+ (seg_2 + 1) * sizeof(double));
+ bp->pro_spacing.yvals_2 = (double *)BLI_memarena_alloc(bp->mem_arena,
+ (seg_2 + 1) * sizeof(double));
+ find_even_superellipse_chords(
+ seg_2, bp->pro_super_r, bp->pro_spacing.xvals_2, bp->pro_spacing.yvals_2);
+ }
+ }
+ else {
+ bp->pro_spacing.xvals = NULL;
+ bp->pro_spacing.yvals = NULL;
+ bp->pro_spacing.xvals_2 = NULL;
+ bp->pro_spacing.yvals_2 = NULL;
+ bp->pro_spacing.seg_2 = 0;
+ }
}
/*
@@ -6152,100 +6214,100 @@ static void set_profile_spacing(BevelParams *bp)
*/
static float geometry_collide_offset(BevelParams *bp, EdgeHalf *eb)
{
- EdgeHalf *ea, *ec, *ebother;
- BevVert *bvc;
- BMLoop *lb;
- BMVert *va, *vb, *vc, *vd;
- float ka, kb, kc, g, h, t, den, no_collide_offset, th1, th2, sin1, sin2, tan1, tan2, limit;
-
- limit = no_collide_offset = bp->offset + 1e6;
- if (bp->offset == 0.0f) {
- return no_collide_offset;
- }
- kb = eb->offset_l_spec;
- ea = eb->next; /* note: this is in direction b --> a */
- ka = ea->offset_r_spec;
- if (eb->is_rev) {
- vc = eb->e->v1;
- vb = eb->e->v2;
- }
- else {
- vb = eb->e->v1;
- vc = eb->e->v2;
- }
- va = ea->is_rev ? ea->e->v1 : ea->e->v2;
- bvc = NULL;
- ebother = find_other_end_edge_half(bp, eb, &bvc);
- if (ebother != NULL) {
- ec = ebother->prev; /* note: this is in direction c --> d*/
- vc = bvc->v;
- kc = ec->offset_l_spec;
- vd = ec->is_rev ? ec->e->v1 : ec->e->v2;
- }
- else {
- /* No bevvert for w, so C can't be beveled */
- kc = 0.0f;
- ec = NULL;
- /* Find an edge from c that has same face */
- lb = BM_face_edge_share_loop(eb->fnext, eb->e);
- if (!lb) {
- return no_collide_offset;
- }
- if (lb->next->v == vc) {
- vd = lb->next->next->v;
- }
- else if (lb->v == vc) {
- vd = lb->prev->v;
- }
- else {
- return no_collide_offset;
- }
- }
- if (ea->e == eb->e || (ec && ec->e == eb->e)) {
- return no_collide_offset;
- }
- ka = ka / bp->offset;
- kb = kb / bp->offset;
- kc = kc / bp->offset;
- th1 = angle_v3v3v3(va->co, vb->co, vc->co);
- th2 = angle_v3v3v3(vb->co, vc->co, vd->co);
-
- /* First calculate offset at which edge B collapses, which happens
- * when advancing clones of A, B, C all meet at a point.
- * This only happens if at least two of those three edges have non-zero k's */
- sin1 = sinf(th1);
- sin2 = sinf(th2);
- if ((ka > 0.0f) + (kb > 0.0f) + (kc > 0.0f) >= 2) {
- tan1 = tanf(th1);
- tan2 = tanf(th2);
- g = tan1 * tan2;
- h = sin1 * sin2;
- den = g * (ka * sin2 + kc * sin1) + kb * h * (tan1 + tan2);
- if (den != 0.0f) {
- t = BM_edge_calc_length(eb->e);
- t *= g * h / den;
- if (t >= 0.0f) {
- limit = t;
- }
- }
- }
-
- /* Now check edge slide cases */
- if (kb > 0.0f && ka == 0.0f /*&& bvb->selcount == 1 && bvb->edgecount > 2*/) {
- t = BM_edge_calc_length(ea->e);
- t *= sin1 / kb;
- if (t >= 0.0f && t < limit) {
- limit = t;
- }
- }
- if (kb > 0.0f && kc == 0.0f /* && bvc && ec && bvc->selcount == 1 && bvc->edgecount > 2 */) {
- t = BM_edge_calc_length(ec->e);
- t *= sin2 / kb;
- if (t >= 0.0f && t < limit) {
- limit = t;
- }
- }
- return limit;
+ EdgeHalf *ea, *ec, *ebother;
+ BevVert *bvc;
+ BMLoop *lb;
+ BMVert *va, *vb, *vc, *vd;
+ float ka, kb, kc, g, h, t, den, no_collide_offset, th1, th2, sin1, sin2, tan1, tan2, limit;
+
+ limit = no_collide_offset = bp->offset + 1e6;
+ if (bp->offset == 0.0f) {
+ return no_collide_offset;
+ }
+ kb = eb->offset_l_spec;
+ ea = eb->next; /* note: this is in direction b --> a */
+ ka = ea->offset_r_spec;
+ if (eb->is_rev) {
+ vc = eb->e->v1;
+ vb = eb->e->v2;
+ }
+ else {
+ vb = eb->e->v1;
+ vc = eb->e->v2;
+ }
+ va = ea->is_rev ? ea->e->v1 : ea->e->v2;
+ bvc = NULL;
+ ebother = find_other_end_edge_half(bp, eb, &bvc);
+ if (ebother != NULL) {
+ ec = ebother->prev; /* note: this is in direction c --> d*/
+ vc = bvc->v;
+ kc = ec->offset_l_spec;
+ vd = ec->is_rev ? ec->e->v1 : ec->e->v2;
+ }
+ else {
+ /* No bevvert for w, so C can't be beveled */
+ kc = 0.0f;
+ ec = NULL;
+ /* Find an edge from c that has same face */
+ lb = BM_face_edge_share_loop(eb->fnext, eb->e);
+ if (!lb) {
+ return no_collide_offset;
+ }
+ if (lb->next->v == vc) {
+ vd = lb->next->next->v;
+ }
+ else if (lb->v == vc) {
+ vd = lb->prev->v;
+ }
+ else {
+ return no_collide_offset;
+ }
+ }
+ if (ea->e == eb->e || (ec && ec->e == eb->e)) {
+ return no_collide_offset;
+ }
+ ka = ka / bp->offset;
+ kb = kb / bp->offset;
+ kc = kc / bp->offset;
+ th1 = angle_v3v3v3(va->co, vb->co, vc->co);
+ th2 = angle_v3v3v3(vb->co, vc->co, vd->co);
+
+ /* First calculate offset at which edge B collapses, which happens
+ * when advancing clones of A, B, C all meet at a point.
+ * This only happens if at least two of those three edges have non-zero k's */
+ sin1 = sinf(th1);
+ sin2 = sinf(th2);
+ if ((ka > 0.0f) + (kb > 0.0f) + (kc > 0.0f) >= 2) {
+ tan1 = tanf(th1);
+ tan2 = tanf(th2);
+ g = tan1 * tan2;
+ h = sin1 * sin2;
+ den = g * (ka * sin2 + kc * sin1) + kb * h * (tan1 + tan2);
+ if (den != 0.0f) {
+ t = BM_edge_calc_length(eb->e);
+ t *= g * h / den;
+ if (t >= 0.0f) {
+ limit = t;
+ }
+ }
+ }
+
+ /* Now check edge slide cases */
+ if (kb > 0.0f && ka == 0.0f /*&& bvb->selcount == 1 && bvb->edgecount > 2*/) {
+ t = BM_edge_calc_length(ea->e);
+ t *= sin1 / kb;
+ if (t >= 0.0f && t < limit) {
+ limit = t;
+ }
+ }
+ if (kb > 0.0f && kc == 0.0f /* && bvc && ec && bvc->selcount == 1 && bvc->edgecount > 2 */) {
+ t = BM_edge_calc_length(ec->e);
+ t *= sin2 / kb;
+ if (t >= 0.0f && t < limit) {
+ limit = t;
+ }
+ }
+ return limit;
}
/*
@@ -6257,23 +6319,23 @@ static float geometry_collide_offset(BevelParams *bp, EdgeHalf *eb)
*/
static float vertex_collide_offset(BevelParams *bp, EdgeHalf *ea)
{
- float limit, ka, kb, no_collide_offset, la, kab;
- EdgeHalf *eb;
-
- limit = no_collide_offset = bp->offset + 1e6;
- if (bp->offset == 0.0f) {
- return no_collide_offset;
- }
- ka = ea->offset_l_spec / bp->offset;
- eb = find_other_end_edge_half(bp, ea, NULL);
- kb = eb ? eb->offset_l_spec / bp->offset : 0.0f;
- kab = ka + kb;
- la = BM_edge_calc_length(ea->e);
- if (kab <= 0.0f) {
- return no_collide_offset;
- }
- limit = la / kab;
- return limit;
+ float limit, ka, kb, no_collide_offset, la, kab;
+ EdgeHalf *eb;
+
+ limit = no_collide_offset = bp->offset + 1e6;
+ if (bp->offset == 0.0f) {
+ return no_collide_offset;
+ }
+ ka = ea->offset_l_spec / bp->offset;
+ eb = find_other_end_edge_half(bp, ea, NULL);
+ kb = eb ? eb->offset_l_spec / bp->offset : 0.0f;
+ kab = ka + kb;
+ la = BM_edge_calc_length(ea->e);
+ if (kab <= 0.0f) {
+ return no_collide_offset;
+ }
+ limit = la / kab;
+ return limit;
}
/*
@@ -6286,60 +6348,60 @@ static float vertex_collide_offset(BevelParams *bp, EdgeHalf *ea)
*/
static void bevel_limit_offset(BevelParams *bp, BMesh *bm)
{
- BevVert *bv;
- EdgeHalf *eh;
- BMIter iter;
- BMVert *bmv;
- float limited_offset, offset_factor, collision_offset;
- int i;
-
- limited_offset = bp->offset;
- BM_ITER_MESH(bmv, &iter, bm, BM_VERTS_OF_MESH) {
- if (!BM_elem_flag_test(bmv, BM_ELEM_TAG))
- continue;
- bv = find_bevvert(bp, bmv);
- if (!bv)
- continue;
- for (i = 0; i < bv->edgecount; i++) {
- eh = &bv->edges[i];
- if (bp->vertex_only) {
- collision_offset = vertex_collide_offset(bp, eh);
- if (collision_offset < limited_offset) {
- limited_offset = collision_offset;
- }
- }
- else {
- collision_offset = geometry_collide_offset(bp, eh);
- if (collision_offset < limited_offset) {
- limited_offset = collision_offset;
- }
- }
- }
- }
-
- if (limited_offset < bp->offset) {
- /* All current offset specs have some number times bp->offset,
- * so we can just multiply them all by the reduction factor
- * of the offset to have the effect of recalculating the specs
- * with the new limited_offset.
- */
- offset_factor = limited_offset / bp->offset;
- BM_ITER_MESH(bmv, &iter, bm, BM_VERTS_OF_MESH) {
- if (!BM_elem_flag_test(bmv, BM_ELEM_TAG))
- continue;
- bv = find_bevvert(bp, bmv);
- if (!bv)
- continue;
- for (i = 0; i < bv->edgecount; i++) {
- eh = &bv->edges[i];
- eh->offset_l_spec *= offset_factor;
- eh->offset_r_spec *= offset_factor;
- eh->offset_l *= offset_factor;
- eh->offset_r *= offset_factor;
- }
- }
- bp->offset = limited_offset;
- }
+ BevVert *bv;
+ EdgeHalf *eh;
+ BMIter iter;
+ BMVert *bmv;
+ float limited_offset, offset_factor, collision_offset;
+ int i;
+
+ limited_offset = bp->offset;
+ BM_ITER_MESH (bmv, &iter, bm, BM_VERTS_OF_MESH) {
+ if (!BM_elem_flag_test(bmv, BM_ELEM_TAG))
+ continue;
+ bv = find_bevvert(bp, bmv);
+ if (!bv)
+ continue;
+ for (i = 0; i < bv->edgecount; i++) {
+ eh = &bv->edges[i];
+ if (bp->vertex_only) {
+ collision_offset = vertex_collide_offset(bp, eh);
+ if (collision_offset < limited_offset) {
+ limited_offset = collision_offset;
+ }
+ }
+ else {
+ collision_offset = geometry_collide_offset(bp, eh);
+ if (collision_offset < limited_offset) {
+ limited_offset = collision_offset;
+ }
+ }
+ }
+ }
+
+ if (limited_offset < bp->offset) {
+ /* All current offset specs have some number times bp->offset,
+ * so we can just multiply them all by the reduction factor
+ * of the offset to have the effect of recalculating the specs
+ * with the new limited_offset.
+ */
+ offset_factor = limited_offset / bp->offset;
+ BM_ITER_MESH (bmv, &iter, bm, BM_VERTS_OF_MESH) {
+ if (!BM_elem_flag_test(bmv, BM_ELEM_TAG))
+ continue;
+ bv = find_bevvert(bp, bmv);
+ if (!bv)
+ continue;
+ for (i = 0; i < bv->edgecount; i++) {
+ eh = &bv->edges[i];
+ eh->offset_l_spec *= offset_factor;
+ eh->offset_r_spec *= offset_factor;
+ eh->offset_l *= offset_factor;
+ eh->offset_r *= offset_factor;
+ }
+ }
+ bp->offset = limited_offset;
+ }
}
/**
@@ -6354,168 +6416,179 @@ static void bevel_limit_offset(BevelParams *bp, BMesh *bm)
*
* \warning all tagged edges _must_ be manifold.
*/
-void BM_mesh_bevel(
- BMesh *bm, const float offset, const int offset_type,
- const float segments, const float profile,
- const bool vertex_only, const bool use_weights, const bool limit_offset,
- const struct MDeformVert *dvert, const int vertex_group, const int mat,
- const bool loop_slide, const bool mark_seam, const bool mark_sharp,
- const bool harden_normals, const int face_strength_mode,
- const int miter_outer, const int miter_inner, const float spread,
- const float smoothresh)
+void BM_mesh_bevel(BMesh *bm,
+ const float offset,
+ const int offset_type,
+ const float segments,
+ const float profile,
+ const bool vertex_only,
+ const bool use_weights,
+ const bool limit_offset,
+ const struct MDeformVert *dvert,
+ const int vertex_group,
+ const int mat,
+ const bool loop_slide,
+ const bool mark_seam,
+ const bool mark_sharp,
+ const bool harden_normals,
+ const int face_strength_mode,
+ const int miter_outer,
+ const int miter_inner,
+ const float spread,
+ const float smoothresh)
{
- BMIter iter, liter;
- BMVert *v, *v_next;
- BMEdge *e;
- BMFace *f;
- BMLoop *l;
- BevVert *bv;
- BevelParams bp = {NULL};
-
- bp.offset = offset;
- bp.offset_type = offset_type;
- bp.seg = segments;
- bp.profile = profile;
- bp.pro_super_r = -log(2.0) / log(sqrt(profile)); /* convert to superellipse exponent */
- bp.vertex_only = vertex_only;
- bp.use_weights = use_weights;
- bp.loop_slide = loop_slide;
- bp.limit_offset = limit_offset;
- bp.offset_adjust = true;
- bp.dvert = dvert;
- bp.vertex_group = vertex_group;
- bp.mat_nr = mat;
- bp.mark_seam = mark_seam;
- bp.mark_sharp = mark_sharp;
- bp.harden_normals = harden_normals;
- bp.face_strength_mode = face_strength_mode;
- bp.miter_outer = miter_outer;
- bp.miter_inner = miter_inner;
- bp.spread = spread;
- bp.smoothresh = smoothresh;
- bp.face_hash = NULL;
-
- if (profile >= 0.950f) { /* r ~ 692, so PRO_SQUARE_R is 1e4 */
- bp.pro_super_r = PRO_SQUARE_R;
- }
-
- if (bp.offset > 0) {
- /* primary alloc */
- bp.vert_hash = BLI_ghash_ptr_new(__func__);
- bp.mem_arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), __func__);
- BLI_memarena_use_calloc(bp.mem_arena);
- set_profile_spacing(&bp);
-
- bp.face_hash = BLI_ghash_ptr_new(__func__);
- BLI_ghash_flag_set(bp.face_hash, GHASH_FLAG_ALLOW_DUPES);
-
- /* Analyze input vertices, sorting edges and assigning initial new vertex positions */
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
- bv = bevel_vert_construct(bm, &bp, v);
- if (!limit_offset && bv) {
- build_boundary(&bp, bv, true);
- }
- }
- }
-
- /* Perhaps clamp offset to avoid geometry colliisions */
- if (limit_offset) {
- bevel_limit_offset(&bp, bm);
-
- /* Assign initial new vertex positions */
- BM_ITER_MESH(v, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
- bv = find_bevvert(&bp, v);
- if (bv)
- build_boundary(&bp, bv, true);
- }
- }
- }
-
- /* Perhaps do a pass to try to even out widths */
- if (!bp.vertex_only && bp.offset_adjust && bp.offset_type != BEVEL_AMT_PERCENT) {
- adjust_offsets(&bp, bm);
- }
-
- /* Build the meshes around vertices, now that positions are final */
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
- bv = find_bevvert(&bp, v);
- if (bv) {
- build_vmesh(&bp, bm, bv);
- }
- }
- }
-
- /* Build polygons for edges */
- if (!bp.vertex_only) {
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
- bevel_build_edge_polygons(bm, &bp, e);
- }
- }
- }
-
- /* Extend edge data like sharp edges and precompute normals for harden */
- BM_ITER_MESH(v, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
- bv = find_bevvert(&bp, v);
- if (bv)
- bevel_extend_edge_data(bv);
- }
- }
-
- /* Rebuild face polygons around affected vertices */
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
- bevel_rebuild_existing_polygons(bm, &bp, v);
- bevel_reattach_wires(bm, &bp, v);
- }
- }
-
- BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
- BLI_assert(find_bevvert(&bp, v) != NULL);
- BM_vert_kill(bm, v);
- }
- }
-
- if (bp.harden_normals) {
- bevel_harden_normals(bm, &bp);
- }
- if (bp.face_strength_mode != BEVEL_FACE_STRENGTH_NONE) {
- bevel_set_weighted_normal_face_strength(bm, &bp);
- }
-
- /* When called from operator (as opposed to modifier), bm->use_toolflags
- * will be set, and we to transfer the oflags to BM_ELEM_TAGs */
- if (bm->use_toolflags) {
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- if (BMO_vert_flag_test(bm, v, VERT_OUT)) {
- BM_elem_flag_enable(v, BM_ELEM_TAG);
- }
- }
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BMO_edge_flag_test(bm, e, EDGE_OUT)) {
- BM_elem_flag_enable(e, BM_ELEM_TAG);
- }
- }
- }
-
- /* clear the BM_ELEM_LONG_TAG tags, which were only set on some edges in F_EDGE faces */
- BM_ITER_MESH(f, &iter, bm, BM_FACES_OF_MESH) {
- if (get_face_kind(&bp, f) != F_EDGE) {
- continue;
- }
- BM_ITER_ELEM(l, &liter, f, BM_LOOPS_OF_FACE) {
- BM_elem_flag_disable(l, BM_ELEM_LONG_TAG);
- }
- }
-
- /* primary free */
- BLI_ghash_free(bp.vert_hash, NULL, NULL);
- BLI_ghash_free(bp.face_hash, NULL, NULL);
- BLI_memarena_free(bp.mem_arena);
- }
+ BMIter iter, liter;
+ BMVert *v, *v_next;
+ BMEdge *e;
+ BMFace *f;
+ BMLoop *l;
+ BevVert *bv;
+ BevelParams bp = {NULL};
+
+ bp.offset = offset;
+ bp.offset_type = offset_type;
+ bp.seg = segments;
+ bp.profile = profile;
+ bp.pro_super_r = -log(2.0) / log(sqrt(profile)); /* convert to superellipse exponent */
+ bp.vertex_only = vertex_only;
+ bp.use_weights = use_weights;
+ bp.loop_slide = loop_slide;
+ bp.limit_offset = limit_offset;
+ bp.offset_adjust = true;
+ bp.dvert = dvert;
+ bp.vertex_group = vertex_group;
+ bp.mat_nr = mat;
+ bp.mark_seam = mark_seam;
+ bp.mark_sharp = mark_sharp;
+ bp.harden_normals = harden_normals;
+ bp.face_strength_mode = face_strength_mode;
+ bp.miter_outer = miter_outer;
+ bp.miter_inner = miter_inner;
+ bp.spread = spread;
+ bp.smoothresh = smoothresh;
+ bp.face_hash = NULL;
+
+ if (profile >= 0.950f) { /* r ~ 692, so PRO_SQUARE_R is 1e4 */
+ bp.pro_super_r = PRO_SQUARE_R;
+ }
+
+ if (bp.offset > 0) {
+ /* primary alloc */
+ bp.vert_hash = BLI_ghash_ptr_new(__func__);
+ bp.mem_arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), __func__);
+ BLI_memarena_use_calloc(bp.mem_arena);
+ set_profile_spacing(&bp);
+
+ bp.face_hash = BLI_ghash_ptr_new(__func__);
+ BLI_ghash_flag_set(bp.face_hash, GHASH_FLAG_ALLOW_DUPES);
+
+ /* Analyze input vertices, sorting edges and assigning initial new vertex positions */
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ bv = bevel_vert_construct(bm, &bp, v);
+ if (!limit_offset && bv) {
+ build_boundary(&bp, bv, true);
+ }
+ }
+ }
+
+ /* Perhaps clamp offset to avoid geometry colliisions */
+ if (limit_offset) {
+ bevel_limit_offset(&bp, bm);
+
+ /* Assign initial new vertex positions */
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ bv = find_bevvert(&bp, v);
+ if (bv)
+ build_boundary(&bp, bv, true);
+ }
+ }
+ }
+
+ /* Perhaps do a pass to try to even out widths */
+ if (!bp.vertex_only && bp.offset_adjust && bp.offset_type != BEVEL_AMT_PERCENT) {
+ adjust_offsets(&bp, bm);
+ }
+
+ /* Build the meshes around vertices, now that positions are final */
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ bv = find_bevvert(&bp, v);
+ if (bv) {
+ build_vmesh(&bp, bm, bv);
+ }
+ }
+ }
+
+ /* Build polygons for edges */
+ if (!bp.vertex_only) {
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ bevel_build_edge_polygons(bm, &bp, e);
+ }
+ }
+ }
+
+ /* Extend edge data like sharp edges and precompute normals for harden */
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ bv = find_bevvert(&bp, v);
+ if (bv)
+ bevel_extend_edge_data(bv);
+ }
+ }
+
+ /* Rebuild face polygons around affected vertices */
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ bevel_rebuild_existing_polygons(bm, &bp, v);
+ bevel_reattach_wires(bm, &bp, v);
+ }
+ }
+
+ BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ BLI_assert(find_bevvert(&bp, v) != NULL);
+ BM_vert_kill(bm, v);
+ }
+ }
+
+ if (bp.harden_normals) {
+ bevel_harden_normals(bm, &bp);
+ }
+ if (bp.face_strength_mode != BEVEL_FACE_STRENGTH_NONE) {
+ bevel_set_weighted_normal_face_strength(bm, &bp);
+ }
+
+ /* When called from operator (as opposed to modifier), bm->use_toolflags
+ * will be set, and we to transfer the oflags to BM_ELEM_TAGs */
+ if (bm->use_toolflags) {
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BMO_vert_flag_test(bm, v, VERT_OUT)) {
+ BM_elem_flag_enable(v, BM_ELEM_TAG);
+ }
+ }
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BMO_edge_flag_test(bm, e, EDGE_OUT)) {
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
+ }
+ }
+ }
+
+ /* clear the BM_ELEM_LONG_TAG tags, which were only set on some edges in F_EDGE faces */
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if (get_face_kind(&bp, f) != F_EDGE) {
+ continue;
+ }
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ BM_elem_flag_disable(l, BM_ELEM_LONG_TAG);
+ }
+ }
+
+ /* primary free */
+ BLI_ghash_free(bp.vert_hash, NULL, NULL);
+ BLI_ghash_free(bp.face_hash, NULL, NULL);
+ BLI_memarena_free(bp.mem_arena);
+ }
}
diff --git a/source/blender/bmesh/tools/bmesh_bevel.h b/source/blender/bmesh/tools/bmesh_bevel.h
index f45a3bec93a..496be9219b7 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.h
+++ b/source/blender/bmesh/tools/bmesh_bevel.h
@@ -23,12 +23,25 @@
struct MDeformVert;
-void BM_mesh_bevel(
- BMesh *bm, const float offset, const int offset_type, const float segments,
- const float profile, const bool vertex_only, const bool use_weights,
- const bool limit_offset, const struct MDeformVert *dvert, const int vertex_group,
- const int mat, const bool loop_slide, const bool mark_seam, const bool mark_sharp,
- const bool harden_normals, const int face_strength_mode, const int miter_outer,
- const int miter_inner, const float spread, const float smoothresh);
+void BM_mesh_bevel(BMesh *bm,
+ const float offset,
+ const int offset_type,
+ const float segments,
+ const float profile,
+ const bool vertex_only,
+ const bool use_weights,
+ const bool limit_offset,
+ const struct MDeformVert *dvert,
+ const int vertex_group,
+ const int mat,
+ const bool loop_slide,
+ const bool mark_seam,
+ const bool mark_sharp,
+ const bool harden_normals,
+ const int face_strength_mode,
+ const int miter_outer,
+ const int miter_inner,
+ const float spread,
+ const float smoothresh);
#endif /* __BMESH_BEVEL_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_bisect_plane.c b/source/blender/bmesh/tools/bmesh_bisect_plane.c
index da7feff70e6..f314ae6848b 100644
--- a/source/blender/bmesh/tools/bmesh_bisect_plane.c
+++ b/source/blender/bmesh/tools/bmesh_bisect_plane.c
@@ -39,36 +39,43 @@
#include "BLI_math.h"
#include "bmesh.h"
-#include "bmesh_bisect_plane.h" /* own include */
-
-#include "BLI_strict_flags.h" /* keep last */
+#include "bmesh_bisect_plane.h" /* own include */
+#include "BLI_strict_flags.h" /* keep last */
/* -------------------------------------------------------------------- */
/* Math utils */
-static short plane_point_test_v3(const float plane[4], const float co[3], const float eps, float *r_depth)
+static short plane_point_test_v3(const float plane[4],
+ const float co[3],
+ const float eps,
+ float *r_depth)
{
- const float f = plane_point_side_v3(plane, co);
- *r_depth = f;
-
- if (f <= -eps) { return -1; }
- else if (f >= eps) { return 1; }
- else { return 0; }
+ const float f = plane_point_side_v3(plane, co);
+ *r_depth = f;
+
+ if (f <= -eps) {
+ return -1;
+ }
+ else if (f >= eps) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
}
-
/* -------------------------------------------------------------------- */
/* Wrappers to hide internal data-structure abuse,
* later we may want to move this into some hash lookup
* to a separate struct, but for now we can store in BMesh data */
-#define BM_VERT_DIR(v) ((short *)(&(v)->head.index))[0] /* Direction -1/0/1 */
-#define BM_VERT_SKIP(v) ((short *)(&(v)->head.index))[1] /* Skip Vert 0/1 */
-#define BM_VERT_DIST(v) ((v)->no[0]) /* Distance from the plane. */
-#define BM_VERT_SORTVAL(v) ((v)->no[1]) /* Temp value for sorting. */
-#define BM_VERT_LOOPINDEX(v) /* The verts index within a face (temp var) */ \
- (*((uint *)(&(v)->no[2])))
+#define BM_VERT_DIR(v) ((short *)(&(v)->head.index))[0] /* Direction -1/0/1 */
+#define BM_VERT_SKIP(v) ((short *)(&(v)->head.index))[1] /* Skip Vert 0/1 */
+#define BM_VERT_DIST(v) ((v)->no[0]) /* Distance from the plane. */
+#define BM_VERT_SORTVAL(v) ((v)->no[1]) /* Temp value for sorting. */
+#define BM_VERT_LOOPINDEX(v) /* The verts index within a face (temp var) */ \
+ (*((uint *)(&(v)->no[2])))
/**
* Hide flag access
@@ -76,220 +83,247 @@ static short plane_point_test_v3(const float plane[4], const float co[3], const
*/
/* enable when vertex is in the center and its faces have been added to the stack */
-BLI_INLINE void vert_is_center_enable(BMVert *v) { BM_elem_flag_enable(v, BM_ELEM_TAG); }
-BLI_INLINE void vert_is_center_disable(BMVert *v) { BM_elem_flag_disable(v, BM_ELEM_TAG); }
-BLI_INLINE bool vert_is_center_test(BMVert *v) { return (BM_elem_flag_test(v, BM_ELEM_TAG) != 0); }
+BLI_INLINE void vert_is_center_enable(BMVert *v)
+{
+ BM_elem_flag_enable(v, BM_ELEM_TAG);
+}
+BLI_INLINE void vert_is_center_disable(BMVert *v)
+{
+ BM_elem_flag_disable(v, BM_ELEM_TAG);
+}
+BLI_INLINE bool vert_is_center_test(BMVert *v)
+{
+ return (BM_elem_flag_test(v, BM_ELEM_TAG) != 0);
+}
/* enable when the edge can be cut */
-BLI_INLINE void edge_is_cut_enable(BMEdge *e) { BM_elem_flag_enable(e, BM_ELEM_TAG); }
-BLI_INLINE void edge_is_cut_disable(BMEdge *e) { BM_elem_flag_disable(e, BM_ELEM_TAG); }
-BLI_INLINE bool edge_is_cut_test(BMEdge *e) { return (BM_elem_flag_test(e, BM_ELEM_TAG) != 0); }
+BLI_INLINE void edge_is_cut_enable(BMEdge *e)
+{
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
+}
+BLI_INLINE void edge_is_cut_disable(BMEdge *e)
+{
+ BM_elem_flag_disable(e, BM_ELEM_TAG);
+}
+BLI_INLINE bool edge_is_cut_test(BMEdge *e)
+{
+ return (BM_elem_flag_test(e, BM_ELEM_TAG) != 0);
+}
/* enable when the faces are added to the stack */
-BLI_INLINE void face_in_stack_enable(BMFace *f) { BM_elem_flag_disable(f, BM_ELEM_TAG); }
-BLI_INLINE void face_in_stack_disable(BMFace *f) { BM_elem_flag_enable(f, BM_ELEM_TAG); }
-BLI_INLINE bool face_in_stack_test(BMFace *f) { return (BM_elem_flag_test(f, BM_ELEM_TAG) == 0); }
+BLI_INLINE void face_in_stack_enable(BMFace *f)
+{
+ BM_elem_flag_disable(f, BM_ELEM_TAG);
+}
+BLI_INLINE void face_in_stack_disable(BMFace *f)
+{
+ BM_elem_flag_enable(f, BM_ELEM_TAG);
+}
+BLI_INLINE bool face_in_stack_test(BMFace *f)
+{
+ return (BM_elem_flag_test(f, BM_ELEM_TAG) == 0);
+}
/* -------------------------------------------------------------------- */
/* BMesh utils */
static int bm_vert_sortval_cb(const void *v_a_v, const void *v_b_v)
{
- const float val_a = BM_VERT_SORTVAL(*((BMVert **)v_a_v));
- const float val_b = BM_VERT_SORTVAL(*((BMVert **)v_b_v));
-
- if (val_a > val_b) { return 1; }
- else if (val_a < val_b) { return -1; }
- else { return 0; }
+ const float val_a = BM_VERT_SORTVAL(*((BMVert **)v_a_v));
+ const float val_b = BM_VERT_SORTVAL(*((BMVert **)v_b_v));
+
+ if (val_a > val_b) {
+ return 1;
+ }
+ else if (val_a < val_b) {
+ return -1;
+ }
+ else {
+ return 0;
+ }
}
-
-static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], const short oflag_center, const short oflag_new)
+static void bm_face_bisect_verts(
+ BMesh *bm, BMFace *f, const float plane[4], const short oflag_center, const short oflag_new)
{
- /* unlikely more than 2 verts are needed */
- const uint f_len_orig = (uint)f->len;
- BMVert **vert_split_arr = BLI_array_alloca(vert_split_arr, f_len_orig);
- STACK_DECLARE(vert_split_arr);
- BMLoop *l_iter, *l_first;
- bool use_dirs[3] = {false, false, false};
- bool is_inside = false;
-
- STACK_INIT(vert_split_arr, f_len_orig);
-
- l_first = BM_FACE_FIRST_LOOP(f);
-
- /* add plane-aligned verts to the stack
- * and check we have verts from both sides in this face,
- * ... that the face doesn't only have boundary verts on the plane for eg. */
- l_iter = l_first;
- do {
- if (vert_is_center_test(l_iter->v)) {
- BLI_assert(BM_VERT_DIR(l_iter->v) == 0);
-
- /* if both are -1 or 1, or both are zero:
- * don't flip 'inside' var while walking */
- BM_VERT_SKIP(l_iter->v) = (((BM_VERT_DIR(l_iter->prev->v) ^ BM_VERT_DIR(l_iter->next->v))) == 0);
-
- STACK_PUSH(vert_split_arr, l_iter->v);
- }
- use_dirs[BM_VERT_DIR(l_iter->v) + 1] = true;
- } while ((l_iter = l_iter->next) != l_first);
-
- if ((STACK_SIZE(vert_split_arr) > 1) &&
- (use_dirs[0] && use_dirs[2]))
- {
- if (LIKELY(STACK_SIZE(vert_split_arr) == 2)) {
- BMLoop *l_new;
- BMLoop *l_a, *l_b;
-
- l_a = BM_face_vert_share_loop(f, vert_split_arr[0]);
- l_b = BM_face_vert_share_loop(f, vert_split_arr[1]);
-
- /* common case, just cut the face once */
- BM_face_split(bm, f, l_a, l_b, &l_new, NULL, true);
- if (l_new) {
- if (oflag_center | oflag_new) {
- BMO_edge_flag_enable(bm, l_new->e, oflag_center | oflag_new);
- }
- if (oflag_new) {
- BMO_face_flag_enable(bm, l_new->f, oflag_new);
- }
- }
- }
- else {
- /* less common case, _complicated_ we need to calculate how to do multiple cuts */
- float (*face_verts_proj_2d)[2] = BLI_array_alloca(face_verts_proj_2d, f_len_orig);
- float axis_mat[3][3];
-
- BMFace **face_split_arr = BLI_array_alloca(face_split_arr, STACK_SIZE(vert_split_arr));
- STACK_DECLARE(face_split_arr);
-
- float sort_dir[3];
- uint i;
-
-
- /* ---- */
- /* Calculate the direction to sort verts in the face intersecting the plane */
-
- /* exact dir isn't so important,
- * just need a dir for sorting verts across face,
- * 'sort_dir' could be flipped either way, it not important, we only need to order the array
- */
- cross_v3_v3v3(sort_dir, f->no, plane);
- if (UNLIKELY(normalize_v3(sort_dir) == 0.0f)) {
- /* find any 2 verts and get their direction */
- for (i = 0; i < STACK_SIZE(vert_split_arr); i++) {
- if (!equals_v3v3(vert_split_arr[0]->co, vert_split_arr[i]->co)) {
- sub_v3_v3v3(sort_dir, vert_split_arr[0]->co, vert_split_arr[i]->co);
- normalize_v3(sort_dir);
- }
- }
- if (UNLIKELY(i == STACK_SIZE(vert_split_arr))) {
- /* ok, we can't do anything useful here,
- * face has no area or so, bail out, this is highly unlikely but not impossible */
- goto finally;
- }
- }
-
-
- /* ---- */
- /* Calculate 2d coords to use for intersection checks */
-
- /* get the faces 2d coords */
- BLI_assert(BM_face_is_normal_valid(f));
- axis_dominant_v3_to_m3(axis_mat, f->no);
-
- l_iter = l_first;
- i = 0;
- do {
- BM_VERT_LOOPINDEX(l_iter->v) = i;
- mul_v2_m3v3(face_verts_proj_2d[i], axis_mat, l_iter->v->co);
- i++;
- } while ((l_iter = l_iter->next) != l_first);
-
-
- /* ---- */
- /* Sort the verts across the face from one side to another */
- for (i = 0; i < STACK_SIZE(vert_split_arr); i++) {
- BMVert *v = vert_split_arr[i];
- BM_VERT_SORTVAL(v) = dot_v3v3(sort_dir, v->co);
- }
-
- qsort(vert_split_arr, STACK_SIZE(vert_split_arr), sizeof(*vert_split_arr), bm_vert_sortval_cb);
-
-
- /* ---- */
- /* Split the face across sorted splits */
-
- /* note: we don't know which face gets which splits,
- * so at the moment we have to search all faces for the vert pair,
- * while not all that nice, typically there are < 5 resulting faces,
- * so its not _that_ bad. */
-
- STACK_INIT(face_split_arr, STACK_SIZE(vert_split_arr));
- STACK_PUSH(face_split_arr, f);
-
- for (i = 0; i < STACK_SIZE(vert_split_arr) - 1; i++) {
- BMVert *v_a = vert_split_arr[i];
- BMVert *v_b = vert_split_arr[i + 1];
-
- if (!BM_VERT_SKIP(v_a)) {
- is_inside = !is_inside;
- }
-
- if (is_inside) {
- BMLoop *l_a, *l_b;
- bool found = false;
- uint j;
-
- for (j = 0; j < STACK_SIZE(face_split_arr); j++) {
- /* would be nice to avoid loop lookup here,
- * but we need to know which face the verts are in */
- if ((l_a = BM_face_vert_share_loop(face_split_arr[j], v_a)) &&
- (l_b = BM_face_vert_share_loop(face_split_arr[j], v_b)))
- {
- found = true;
- break;
- }
- }
-
- /* ideally wont happen, but it can for self intersecting faces */
- // BLI_assert(found == true);
-
- /* in fact this simple test is good enough,
- * test if the loops are adjacent */
- if (found && !BM_loop_is_adjacent(l_a, l_b)) {
- BMLoop *l_new;
- BMFace *f_tmp;
- f_tmp = BM_face_split(bm, face_split_arr[j], l_a, l_b, &l_new, NULL, true);
-
- if (l_new) {
- if (oflag_center | oflag_new) {
- BMO_edge_flag_enable(bm, l_new->e, oflag_center | oflag_new);
- }
- if (oflag_new) {
- BMO_face_flag_enable(bm, l_new->f, oflag_new);
- }
- }
-
- if (f_tmp) {
- if (f_tmp != face_split_arr[j]) {
- STACK_PUSH(face_split_arr, f_tmp);
- BLI_assert(STACK_SIZE(face_split_arr) <= STACK_SIZE(vert_split_arr));
- }
- }
- }
- }
- else {
- // printf("no intersect\n");
- }
- }
- }
- }
-
+ /* unlikely more than 2 verts are needed */
+ const uint f_len_orig = (uint)f->len;
+ BMVert **vert_split_arr = BLI_array_alloca(vert_split_arr, f_len_orig);
+ STACK_DECLARE(vert_split_arr);
+ BMLoop *l_iter, *l_first;
+ bool use_dirs[3] = {false, false, false};
+ bool is_inside = false;
+
+ STACK_INIT(vert_split_arr, f_len_orig);
+
+ l_first = BM_FACE_FIRST_LOOP(f);
+
+ /* add plane-aligned verts to the stack
+ * and check we have verts from both sides in this face,
+ * ... that the face doesn't only have boundary verts on the plane for eg. */
+ l_iter = l_first;
+ do {
+ if (vert_is_center_test(l_iter->v)) {
+ BLI_assert(BM_VERT_DIR(l_iter->v) == 0);
+
+ /* if both are -1 or 1, or both are zero:
+ * don't flip 'inside' var while walking */
+ BM_VERT_SKIP(l_iter->v) = (((BM_VERT_DIR(l_iter->prev->v) ^ BM_VERT_DIR(l_iter->next->v))) ==
+ 0);
+
+ STACK_PUSH(vert_split_arr, l_iter->v);
+ }
+ use_dirs[BM_VERT_DIR(l_iter->v) + 1] = true;
+ } while ((l_iter = l_iter->next) != l_first);
+
+ if ((STACK_SIZE(vert_split_arr) > 1) && (use_dirs[0] && use_dirs[2])) {
+ if (LIKELY(STACK_SIZE(vert_split_arr) == 2)) {
+ BMLoop *l_new;
+ BMLoop *l_a, *l_b;
+
+ l_a = BM_face_vert_share_loop(f, vert_split_arr[0]);
+ l_b = BM_face_vert_share_loop(f, vert_split_arr[1]);
+
+ /* common case, just cut the face once */
+ BM_face_split(bm, f, l_a, l_b, &l_new, NULL, true);
+ if (l_new) {
+ if (oflag_center | oflag_new) {
+ BMO_edge_flag_enable(bm, l_new->e, oflag_center | oflag_new);
+ }
+ if (oflag_new) {
+ BMO_face_flag_enable(bm, l_new->f, oflag_new);
+ }
+ }
+ }
+ else {
+ /* less common case, _complicated_ we need to calculate how to do multiple cuts */
+ float(*face_verts_proj_2d)[2] = BLI_array_alloca(face_verts_proj_2d, f_len_orig);
+ float axis_mat[3][3];
+
+ BMFace **face_split_arr = BLI_array_alloca(face_split_arr, STACK_SIZE(vert_split_arr));
+ STACK_DECLARE(face_split_arr);
+
+ float sort_dir[3];
+ uint i;
+
+ /* ---- */
+ /* Calculate the direction to sort verts in the face intersecting the plane */
+
+ /* exact dir isn't so important,
+ * just need a dir for sorting verts across face,
+ * 'sort_dir' could be flipped either way, it not important, we only need to order the array
+ */
+ cross_v3_v3v3(sort_dir, f->no, plane);
+ if (UNLIKELY(normalize_v3(sort_dir) == 0.0f)) {
+ /* find any 2 verts and get their direction */
+ for (i = 0; i < STACK_SIZE(vert_split_arr); i++) {
+ if (!equals_v3v3(vert_split_arr[0]->co, vert_split_arr[i]->co)) {
+ sub_v3_v3v3(sort_dir, vert_split_arr[0]->co, vert_split_arr[i]->co);
+ normalize_v3(sort_dir);
+ }
+ }
+ if (UNLIKELY(i == STACK_SIZE(vert_split_arr))) {
+ /* ok, we can't do anything useful here,
+ * face has no area or so, bail out, this is highly unlikely but not impossible */
+ goto finally;
+ }
+ }
+
+ /* ---- */
+ /* Calculate 2d coords to use for intersection checks */
+
+ /* get the faces 2d coords */
+ BLI_assert(BM_face_is_normal_valid(f));
+ axis_dominant_v3_to_m3(axis_mat, f->no);
+
+ l_iter = l_first;
+ i = 0;
+ do {
+ BM_VERT_LOOPINDEX(l_iter->v) = i;
+ mul_v2_m3v3(face_verts_proj_2d[i], axis_mat, l_iter->v->co);
+ i++;
+ } while ((l_iter = l_iter->next) != l_first);
+
+ /* ---- */
+ /* Sort the verts across the face from one side to another */
+ for (i = 0; i < STACK_SIZE(vert_split_arr); i++) {
+ BMVert *v = vert_split_arr[i];
+ BM_VERT_SORTVAL(v) = dot_v3v3(sort_dir, v->co);
+ }
+
+ qsort(
+ vert_split_arr, STACK_SIZE(vert_split_arr), sizeof(*vert_split_arr), bm_vert_sortval_cb);
+
+ /* ---- */
+ /* Split the face across sorted splits */
+
+ /* note: we don't know which face gets which splits,
+ * so at the moment we have to search all faces for the vert pair,
+ * while not all that nice, typically there are < 5 resulting faces,
+ * so its not _that_ bad. */
+
+ STACK_INIT(face_split_arr, STACK_SIZE(vert_split_arr));
+ STACK_PUSH(face_split_arr, f);
+
+ for (i = 0; i < STACK_SIZE(vert_split_arr) - 1; i++) {
+ BMVert *v_a = vert_split_arr[i];
+ BMVert *v_b = vert_split_arr[i + 1];
+
+ if (!BM_VERT_SKIP(v_a)) {
+ is_inside = !is_inside;
+ }
+
+ if (is_inside) {
+ BMLoop *l_a, *l_b;
+ bool found = false;
+ uint j;
+
+ for (j = 0; j < STACK_SIZE(face_split_arr); j++) {
+ /* would be nice to avoid loop lookup here,
+ * but we need to know which face the verts are in */
+ if ((l_a = BM_face_vert_share_loop(face_split_arr[j], v_a)) &&
+ (l_b = BM_face_vert_share_loop(face_split_arr[j], v_b))) {
+ found = true;
+ break;
+ }
+ }
+
+ /* ideally wont happen, but it can for self intersecting faces */
+ // BLI_assert(found == true);
+
+ /* in fact this simple test is good enough,
+ * test if the loops are adjacent */
+ if (found && !BM_loop_is_adjacent(l_a, l_b)) {
+ BMLoop *l_new;
+ BMFace *f_tmp;
+ f_tmp = BM_face_split(bm, face_split_arr[j], l_a, l_b, &l_new, NULL, true);
+
+ if (l_new) {
+ if (oflag_center | oflag_new) {
+ BMO_edge_flag_enable(bm, l_new->e, oflag_center | oflag_new);
+ }
+ if (oflag_new) {
+ BMO_face_flag_enable(bm, l_new->f, oflag_new);
+ }
+ }
+
+ if (f_tmp) {
+ if (f_tmp != face_split_arr[j]) {
+ STACK_PUSH(face_split_arr, f_tmp);
+ BLI_assert(STACK_SIZE(face_split_arr) <= STACK_SIZE(vert_split_arr));
+ }
+ }
+ }
+ }
+ else {
+ // printf("no intersect\n");
+ }
+ }
+ }
+ }
finally:
- (void)vert_split_arr;
+ (void)vert_split_arr;
}
/* -------------------------------------------------------------------- */
@@ -300,163 +334,165 @@ finally:
* \param use_tag: Only bisect tagged edges and faces.
* \param oflag_center: Operator flag, enabled for geometry on the axis (existing and created)
*/
-void BM_mesh_bisect_plane(
- BMesh *bm, const float plane[4],
- const bool use_snap_center, const bool use_tag,
- const short oflag_center, const short oflag_new, const float eps)
+void BM_mesh_bisect_plane(BMesh *bm,
+ const float plane[4],
+ const bool use_snap_center,
+ const bool use_tag,
+ const short oflag_center,
+ const short oflag_new,
+ const float eps)
{
- uint einput_len;
- uint i;
- BMEdge **edges_arr = MEM_mallocN(sizeof(*edges_arr) * (size_t)bm->totedge, __func__);
-
- BLI_LINKSTACK_DECLARE(face_stack, BMFace *);
-
- BMVert *v;
- BMFace *f;
-
- BMIter iter;
-
- if (use_tag) {
- /* build tagged edge array */
- BMEdge *e;
- einput_len = 0;
-
- /* flush edge tags to verts */
- BM_mesh_elem_hflag_disable_all(bm, BM_VERT, BM_ELEM_TAG, false);
-
- /* keep face tags as is */
- BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
- if (edge_is_cut_test(e)) {
- edges_arr[einput_len++] = e;
-
- /* flush edge tags to verts */
- BM_elem_flag_enable(e->v1, BM_ELEM_TAG);
- BM_elem_flag_enable(e->v2, BM_ELEM_TAG);
- }
- }
-
- /* face tags are set by caller */
- }
- else {
- BMEdge *e;
- einput_len = (uint)bm->totedge;
- BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
- edge_is_cut_enable(e);
- edges_arr[i] = e;
- }
-
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- face_in_stack_disable(f);
- }
- }
-
-
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
-
- if (use_tag && !BM_elem_flag_test(v, BM_ELEM_TAG)) {
- vert_is_center_disable(v);
-
- /* these should never be accessed */
- BM_VERT_DIR(v) = 0;
- BM_VERT_DIST(v) = 0.0f;
-
- continue;
- }
-
- vert_is_center_disable(v);
- BM_VERT_DIR(v) = plane_point_test_v3(plane, v->co, eps, &(BM_VERT_DIST(v)));
-
- if (BM_VERT_DIR(v) == 0) {
- if (oflag_center) {
- BMO_vert_flag_enable(bm, v, oflag_center);
- }
- if (use_snap_center) {
- closest_to_plane_v3(v->co, plane, v->co);
- }
- }
- }
-
- /* store a stack of faces to be evaluated for splitting */
- BLI_LINKSTACK_INIT(face_stack);
-
- for (i = 0; i < einput_len; i++) {
- /* we could check edge_is_cut_test(e) but there is no point */
- BMEdge *e = edges_arr[i];
- const int side[2] = {BM_VERT_DIR(e->v1), BM_VERT_DIR(e->v2)};
- const float dist[2] = {BM_VERT_DIST(e->v1), BM_VERT_DIST(e->v2)};
-
- if (side[0] && side[1] && (side[0] != side[1])) {
- const float e_fac = dist[0] / (dist[0] - dist[1]);
- BMVert *v_new;
-
- if (e->l) {
- BMLoop *l_iter, *l_first;
- l_iter = l_first = e->l;
- do {
- if (!face_in_stack_test(l_iter->f)) {
- face_in_stack_enable(l_iter->f);
- BLI_LINKSTACK_PUSH(face_stack, l_iter->f);
- }
- } while ((l_iter = l_iter->radial_next) != l_first);
- }
-
- {
- BMEdge *e_new;
- v_new = BM_edge_split(bm, e, e->v1, &e_new, e_fac);
- if (oflag_new) {
- BMO_edge_flag_enable(bm, e_new, oflag_new);
- }
- }
-
- vert_is_center_enable(v_new);
- if (oflag_new | oflag_center) {
- BMO_vert_flag_enable(bm, v_new, oflag_new | oflag_center);
- }
-
- BM_VERT_DIR(v_new) = 0;
- BM_VERT_DIST(v_new) = 0.0f;
- }
- else if (side[0] == 0 || side[1] == 0) {
- /* check if either edge verts are aligned,
- * if so - tag and push all faces that use it into the stack */
- uint j;
- BM_ITER_ELEM_INDEX (v, &iter, e, BM_VERTS_OF_EDGE, j) {
- if (side[j] == 0) {
- if (vert_is_center_test(v) == 0) {
- BMIter itersub;
- BMLoop *l_iter;
-
- vert_is_center_enable(v);
-
- BM_ITER_ELEM (l_iter, &itersub, v, BM_LOOPS_OF_VERT) {
- if (!face_in_stack_test(l_iter->f)) {
- face_in_stack_enable(l_iter->f);
- BLI_LINKSTACK_PUSH(face_stack, l_iter->f);
- }
- }
-
- }
- }
- }
-
- /* if both verts are on the center - tag it */
- if (oflag_center) {
- if (side[0] == 0 && side[1] == 0) {
- BMO_edge_flag_enable(bm, e, oflag_center);
- }
- }
- }
- }
-
- MEM_freeN(edges_arr);
-
- while ((f = BLI_LINKSTACK_POP(face_stack))) {
- bm_face_bisect_verts(bm, f, plane, oflag_center, oflag_new);
- }
-
- /* Caused by access macros: BM_VERT_DIR, BM_VERT_SKIP. */
- bm->elem_index_dirty |= BM_VERT;
-
- /* now we have all faces to split in the stack */
- BLI_LINKSTACK_FREE(face_stack);
+ uint einput_len;
+ uint i;
+ BMEdge **edges_arr = MEM_mallocN(sizeof(*edges_arr) * (size_t)bm->totedge, __func__);
+
+ BLI_LINKSTACK_DECLARE(face_stack, BMFace *);
+
+ BMVert *v;
+ BMFace *f;
+
+ BMIter iter;
+
+ if (use_tag) {
+ /* build tagged edge array */
+ BMEdge *e;
+ einput_len = 0;
+
+ /* flush edge tags to verts */
+ BM_mesh_elem_hflag_disable_all(bm, BM_VERT, BM_ELEM_TAG, false);
+
+ /* keep face tags as is */
+ BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
+ if (edge_is_cut_test(e)) {
+ edges_arr[einput_len++] = e;
+
+ /* flush edge tags to verts */
+ BM_elem_flag_enable(e->v1, BM_ELEM_TAG);
+ BM_elem_flag_enable(e->v2, BM_ELEM_TAG);
+ }
+ }
+
+ /* face tags are set by caller */
+ }
+ else {
+ BMEdge *e;
+ einput_len = (uint)bm->totedge;
+ BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
+ edge_is_cut_enable(e);
+ edges_arr[i] = e;
+ }
+
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ face_in_stack_disable(f);
+ }
+ }
+
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+
+ if (use_tag && !BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ vert_is_center_disable(v);
+
+ /* these should never be accessed */
+ BM_VERT_DIR(v) = 0;
+ BM_VERT_DIST(v) = 0.0f;
+
+ continue;
+ }
+
+ vert_is_center_disable(v);
+ BM_VERT_DIR(v) = plane_point_test_v3(plane, v->co, eps, &(BM_VERT_DIST(v)));
+
+ if (BM_VERT_DIR(v) == 0) {
+ if (oflag_center) {
+ BMO_vert_flag_enable(bm, v, oflag_center);
+ }
+ if (use_snap_center) {
+ closest_to_plane_v3(v->co, plane, v->co);
+ }
+ }
+ }
+
+ /* store a stack of faces to be evaluated for splitting */
+ BLI_LINKSTACK_INIT(face_stack);
+
+ for (i = 0; i < einput_len; i++) {
+ /* we could check edge_is_cut_test(e) but there is no point */
+ BMEdge *e = edges_arr[i];
+ const int side[2] = {BM_VERT_DIR(e->v1), BM_VERT_DIR(e->v2)};
+ const float dist[2] = {BM_VERT_DIST(e->v1), BM_VERT_DIST(e->v2)};
+
+ if (side[0] && side[1] && (side[0] != side[1])) {
+ const float e_fac = dist[0] / (dist[0] - dist[1]);
+ BMVert *v_new;
+
+ if (e->l) {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = e->l;
+ do {
+ if (!face_in_stack_test(l_iter->f)) {
+ face_in_stack_enable(l_iter->f);
+ BLI_LINKSTACK_PUSH(face_stack, l_iter->f);
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+
+ {
+ BMEdge *e_new;
+ v_new = BM_edge_split(bm, e, e->v1, &e_new, e_fac);
+ if (oflag_new) {
+ BMO_edge_flag_enable(bm, e_new, oflag_new);
+ }
+ }
+
+ vert_is_center_enable(v_new);
+ if (oflag_new | oflag_center) {
+ BMO_vert_flag_enable(bm, v_new, oflag_new | oflag_center);
+ }
+
+ BM_VERT_DIR(v_new) = 0;
+ BM_VERT_DIST(v_new) = 0.0f;
+ }
+ else if (side[0] == 0 || side[1] == 0) {
+ /* check if either edge verts are aligned,
+ * if so - tag and push all faces that use it into the stack */
+ uint j;
+ BM_ITER_ELEM_INDEX(v, &iter, e, BM_VERTS_OF_EDGE, j)
+ {
+ if (side[j] == 0) {
+ if (vert_is_center_test(v) == 0) {
+ BMIter itersub;
+ BMLoop *l_iter;
+
+ vert_is_center_enable(v);
+
+ BM_ITER_ELEM (l_iter, &itersub, v, BM_LOOPS_OF_VERT) {
+ if (!face_in_stack_test(l_iter->f)) {
+ face_in_stack_enable(l_iter->f);
+ BLI_LINKSTACK_PUSH(face_stack, l_iter->f);
+ }
+ }
+ }
+ }
+ }
+
+ /* if both verts are on the center - tag it */
+ if (oflag_center) {
+ if (side[0] == 0 && side[1] == 0) {
+ BMO_edge_flag_enable(bm, e, oflag_center);
+ }
+ }
+ }
+ }
+
+ MEM_freeN(edges_arr);
+
+ while ((f = BLI_LINKSTACK_POP(face_stack))) {
+ bm_face_bisect_verts(bm, f, plane, oflag_center, oflag_new);
+ }
+
+ /* Caused by access macros: BM_VERT_DIR, BM_VERT_SKIP. */
+ bm->elem_index_dirty |= BM_VERT;
+
+ /* now we have all faces to split in the stack */
+ BLI_LINKSTACK_FREE(face_stack);
}
diff --git a/source/blender/bmesh/tools/bmesh_bisect_plane.h b/source/blender/bmesh/tools/bmesh_bisect_plane.h
index e3e4a737776..ca6281be99f 100644
--- a/source/blender/bmesh/tools/bmesh_bisect_plane.h
+++ b/source/blender/bmesh/tools/bmesh_bisect_plane.h
@@ -21,9 +21,12 @@
* \ingroup bmesh
*/
-void BM_mesh_bisect_plane(
- BMesh *bm, const float plane[4],
- const bool use_snap_center, const bool use_tag,
- const short oflag_center, const short oflag_new, const float eps);
+void BM_mesh_bisect_plane(BMesh *bm,
+ const float plane[4],
+ const bool use_snap_center,
+ const bool use_tag,
+ const short oflag_center,
+ const short oflag_new,
+ const float eps);
#endif /* __BMESH_BISECT_PLANE_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_decimate.h b/source/blender/bmesh/tools/bmesh_decimate.h
index fa25b35b912..669eb629e70 100644
--- a/source/blender/bmesh/tools/bmesh_decimate.h
+++ b/source/blender/bmesh/tools/bmesh_decimate.h
@@ -21,23 +21,29 @@
* \ingroup bmesh
*/
-void BM_mesh_decimate_collapse(
- BMesh *bm, const float factor,
- float *vweights, float vweight_factor,
- const bool do_triangulate,
- const int symmetry_axis, const float symmetry_eps);
+void BM_mesh_decimate_collapse(BMesh *bm,
+ const float factor,
+ float *vweights,
+ float vweight_factor,
+ const bool do_triangulate,
+ const int symmetry_axis,
+ const float symmetry_eps);
void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const bool tag_only);
void BM_mesh_decimate_unsubdivide(BMesh *bm, const int iterations);
-void BM_mesh_decimate_dissolve_ex(
- BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries,
- BMO_Delimit delimit,
- BMVert **vinput_arr, const int vinput_len,
- BMEdge **einput_arr, const int einput_len,
- const short oflag_out);
-void BM_mesh_decimate_dissolve(
- BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries,
- const BMO_Delimit delimit);
+void BM_mesh_decimate_dissolve_ex(BMesh *bm,
+ const float angle_limit,
+ const bool do_dissolve_boundaries,
+ BMO_Delimit delimit,
+ BMVert **vinput_arr,
+ const int vinput_len,
+ BMEdge **einput_arr,
+ const int einput_len,
+ const short oflag_out);
+void BM_mesh_decimate_dissolve(BMesh *bm,
+ const float angle_limit,
+ const bool do_dissolve_boundaries,
+ const BMO_Delimit delimit);
#endif /* __BMESH_DECIMATE_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c
index c60dd04fbb5..3838f199847 100644
--- a/source/blender/bmesh/tools/bmesh_decimate_collapse.c
+++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c
@@ -24,7 +24,6 @@
#include "MEM_guardedalloc.h"
-
#include "BLI_math.h"
#include "BLI_quadric.h"
#include "BLI_heap.h"
@@ -35,17 +34,16 @@
#include "BLI_polyfill_2d_beautify.h"
#include "BLI_utildefines_stack.h"
-
#include "BKE_customdata.h"
#include "bmesh.h"
-#include "bmesh_decimate.h" /* own include */
+#include "bmesh_decimate.h" /* own include */
#include "../intern/bmesh_structure.h"
#define USE_SYMMETRY
#ifdef USE_SYMMETRY
-#include "BLI_kdtree.h"
+# include "BLI_kdtree.h"
#endif
/* defines for testing */
@@ -56,9 +54,9 @@
/** if the cost from #BLI_quadric_evaluate is 'noise', fallback to topology */
#define USE_TOPOLOGY_FALLBACK
-#ifdef USE_TOPOLOGY_FALLBACK
+#ifdef USE_TOPOLOGY_FALLBACK
/** cost is calculated with double precision, it's ok to use a very small epsilon, see T48154. */
-# define TOPOLOGY_FALLBACK_EPS 1e-12f
+# define TOPOLOGY_FALLBACK_EPS 1e-12f
#endif
#define BOUNDARY_PRESERVE_WEIGHT 100.0f
@@ -68,12 +66,11 @@
#define COST_INVALID FLT_MAX
typedef enum CD_UseFlag {
- CD_DO_VERT = (1 << 0),
- CD_DO_EDGE = (1 << 1),
- CD_DO_LOOP = (1 << 2),
+ CD_DO_VERT = (1 << 0),
+ CD_DO_EDGE = (1 << 1),
+ CD_DO_LOOP = (1 << 2),
} CD_UseFlag;
-
/* BMesh Helper Functions
* ********************** */
@@ -82,150 +79,140 @@ typedef enum CD_UseFlag {
*/
static void bm_decim_build_quadrics(BMesh *bm, Quadric *vquadrics)
{
- BMIter iter;
- BMFace *f;
- BMEdge *e;
-
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- BMLoop *l_first;
- BMLoop *l_iter;
-
- float center[3];
- double plane_db[4];
- Quadric q;
-
- BM_face_calc_center_median(f, center);
- copy_v3db_v3fl(plane_db, f->no);
- plane_db[3] = -dot_v3db_v3fl(plane_db, center);
-
- BLI_quadric_from_plane(&q, plane_db);
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- BLI_quadric_add_qu_qu(&vquadrics[BM_elem_index_get(l_iter->v)], &q);
- } while ((l_iter = l_iter->next) != l_first);
- }
-
- /* boundary edges */
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (UNLIKELY(BM_edge_is_boundary(e))) {
- float edge_vector[3];
- float edge_plane[3];
- double edge_plane_db[4];
- sub_v3_v3v3(edge_vector, e->v2->co, e->v1->co);
- f = e->l->f;
-
- cross_v3_v3v3(edge_plane, edge_vector, f->no);
- copy_v3db_v3fl(edge_plane_db, edge_plane);
-
- if (normalize_v3_d(edge_plane_db) > (double)FLT_EPSILON) {
- Quadric q;
- float center[3];
-
- mid_v3_v3v3(center, e->v1->co, e->v2->co);
-
- edge_plane_db[3] = -dot_v3db_v3fl(edge_plane_db, center);
- BLI_quadric_from_plane(&q, edge_plane_db);
- BLI_quadric_mul(&q, BOUNDARY_PRESERVE_WEIGHT);
-
- BLI_quadric_add_qu_qu(&vquadrics[BM_elem_index_get(e->v1)], &q);
- BLI_quadric_add_qu_qu(&vquadrics[BM_elem_index_get(e->v2)], &q);
- }
- }
- }
+ BMIter iter;
+ BMFace *f;
+ BMEdge *e;
+
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ BMLoop *l_first;
+ BMLoop *l_iter;
+
+ float center[3];
+ double plane_db[4];
+ Quadric q;
+
+ BM_face_calc_center_median(f, center);
+ copy_v3db_v3fl(plane_db, f->no);
+ plane_db[3] = -dot_v3db_v3fl(plane_db, center);
+
+ BLI_quadric_from_plane(&q, plane_db);
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BLI_quadric_add_qu_qu(&vquadrics[BM_elem_index_get(l_iter->v)], &q);
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+
+ /* boundary edges */
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (UNLIKELY(BM_edge_is_boundary(e))) {
+ float edge_vector[3];
+ float edge_plane[3];
+ double edge_plane_db[4];
+ sub_v3_v3v3(edge_vector, e->v2->co, e->v1->co);
+ f = e->l->f;
+
+ cross_v3_v3v3(edge_plane, edge_vector, f->no);
+ copy_v3db_v3fl(edge_plane_db, edge_plane);
+
+ if (normalize_v3_d(edge_plane_db) > (double)FLT_EPSILON) {
+ Quadric q;
+ float center[3];
+
+ mid_v3_v3v3(center, e->v1->co, e->v2->co);
+
+ edge_plane_db[3] = -dot_v3db_v3fl(edge_plane_db, center);
+ BLI_quadric_from_plane(&q, edge_plane_db);
+ BLI_quadric_mul(&q, BOUNDARY_PRESERVE_WEIGHT);
+
+ BLI_quadric_add_qu_qu(&vquadrics[BM_elem_index_get(e->v1)], &q);
+ BLI_quadric_add_qu_qu(&vquadrics[BM_elem_index_get(e->v2)], &q);
+ }
+ }
+ }
}
-
-static void bm_decim_calc_target_co_db(
- BMEdge *e, double optimize_co[3],
- const Quadric *vquadrics)
+static void bm_decim_calc_target_co_db(BMEdge *e, double optimize_co[3], const Quadric *vquadrics)
{
- /* compute an edge contraction target for edge 'e'
- * this is computed by summing it's vertices quadrics and
- * optimizing the result. */
- Quadric q;
-
- BLI_quadric_add_qu_ququ(
- &q,
- &vquadrics[BM_elem_index_get(e->v1)],
- &vquadrics[BM_elem_index_get(e->v2)]);
-
- if (BLI_quadric_optimize(&q, optimize_co, OPTIMIZE_EPS)) {
- /* all is good */
- return;
- }
- else {
- optimize_co[0] = 0.5 * ((double)e->v1->co[0] + (double)e->v2->co[0]);
- optimize_co[1] = 0.5 * ((double)e->v1->co[1] + (double)e->v2->co[1]);
- optimize_co[2] = 0.5 * ((double)e->v1->co[2] + (double)e->v2->co[2]);
- }
+ /* compute an edge contraction target for edge 'e'
+ * this is computed by summing it's vertices quadrics and
+ * optimizing the result. */
+ Quadric q;
+
+ BLI_quadric_add_qu_ququ(
+ &q, &vquadrics[BM_elem_index_get(e->v1)], &vquadrics[BM_elem_index_get(e->v2)]);
+
+ if (BLI_quadric_optimize(&q, optimize_co, OPTIMIZE_EPS)) {
+ /* all is good */
+ return;
+ }
+ else {
+ optimize_co[0] = 0.5 * ((double)e->v1->co[0] + (double)e->v2->co[0]);
+ optimize_co[1] = 0.5 * ((double)e->v1->co[1] + (double)e->v2->co[1]);
+ optimize_co[2] = 0.5 * ((double)e->v1->co[2] + (double)e->v2->co[2]);
+ }
}
-static void bm_decim_calc_target_co_fl(
- BMEdge *e, float optimize_co[3],
- const Quadric *vquadrics)
+static void bm_decim_calc_target_co_fl(BMEdge *e, float optimize_co[3], const Quadric *vquadrics)
{
- double optimize_co_db[3];
- bm_decim_calc_target_co_db(e, optimize_co_db, vquadrics);
- copy_v3fl_v3db(optimize_co, optimize_co_db);
+ double optimize_co_db[3];
+ bm_decim_calc_target_co_db(e, optimize_co_db, vquadrics);
+ copy_v3fl_v3db(optimize_co, optimize_co_db);
}
-
static bool bm_edge_collapse_is_degenerate_flip(BMEdge *e, const float optimize_co[3])
{
- BMIter liter;
- BMLoop *l;
- uint i;
+ BMIter liter;
+ BMLoop *l;
+ uint i;
- for (i = 0; i < 2; i++) {
- /* loop over both verts */
- BMVert *v = *((&e->v1) + i);
+ for (i = 0; i < 2; i++) {
+ /* loop over both verts */
+ BMVert *v = *((&e->v1) + i);
- BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
- if (l->e != e && l->prev->e != e) {
- const float *co_prev = l->prev->v->co;
- const float *co_next = l->next->v->co;
- float cross_exist[3];
- float cross_optim[3];
+ BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
+ if (l->e != e && l->prev->e != e) {
+ const float *co_prev = l->prev->v->co;
+ const float *co_next = l->next->v->co;
+ float cross_exist[3];
+ float cross_optim[3];
#if 1
- /* line between the two outer verts, re-use for both cross products */
- float vec_other[3];
- /* before collapse */
- float vec_exist[3];
- /* after collapse */
- float vec_optim[3];
-
- sub_v3_v3v3(vec_other, co_prev, co_next);
- sub_v3_v3v3(vec_exist, co_prev, v->co);
- sub_v3_v3v3(vec_optim, co_prev, optimize_co);
-
- cross_v3_v3v3(cross_exist, vec_other, vec_exist);
- cross_v3_v3v3(cross_optim, vec_other, vec_optim);
-
- /* avoid normalize */
- if (dot_v3v3(cross_exist, cross_optim) <=
- (len_squared_v3(cross_exist) + len_squared_v3(cross_optim)) * 0.01f)
- {
- return true;
- }
+ /* line between the two outer verts, re-use for both cross products */
+ float vec_other[3];
+ /* before collapse */
+ float vec_exist[3];
+ /* after collapse */
+ float vec_optim[3];
+
+ sub_v3_v3v3(vec_other, co_prev, co_next);
+ sub_v3_v3v3(vec_exist, co_prev, v->co);
+ sub_v3_v3v3(vec_optim, co_prev, optimize_co);
+
+ cross_v3_v3v3(cross_exist, vec_other, vec_exist);
+ cross_v3_v3v3(cross_optim, vec_other, vec_optim);
+
+ /* avoid normalize */
+ if (dot_v3v3(cross_exist, cross_optim) <=
+ (len_squared_v3(cross_exist) + len_squared_v3(cross_optim)) * 0.01f) {
+ return true;
+ }
#else
- normal_tri_v3(cross_exist, v->co, co_prev, co_next);
- normal_tri_v3(cross_optim, optimize_co, co_prev, co_next);
-
- /* use a small value rather then zero so we don't flip a face in multiple steps
- * (first making it zero area, then flipping again) */
- if (dot_v3v3(cross_exist, cross_optim) <= FLT_EPSILON) {
- //printf("no flip\n");
- return true;
- }
+ normal_tri_v3(cross_exist, v->co, co_prev, co_next);
+ normal_tri_v3(cross_optim, optimize_co, co_prev, co_next);
+
+ /* use a small value rather then zero so we don't flip a face in multiple steps
+ * (first making it zero area, then flipping again) */
+ if (dot_v3v3(cross_exist, cross_optim) <= FLT_EPSILON) {
+ //printf("no flip\n");
+ return true;
+ }
#endif
+ }
+ }
+ }
- }
- }
- }
-
- return false;
+ return false;
}
#ifdef USE_TOPOLOGY_FALLBACK
@@ -237,242 +224,241 @@ static bool bm_edge_collapse_is_degenerate_flip(BMEdge *e, const float optimize_
*/
static float bm_decim_build_edge_cost_single_squared__topology(BMEdge *e)
{
- return fabsf(dot_v3v3(e->v1->no, e->v2->no)) / min_ff(-len_squared_v3v3(e->v1->co, e->v2->co), -FLT_EPSILON);
+ return fabsf(dot_v3v3(e->v1->no, e->v2->no)) /
+ min_ff(-len_squared_v3v3(e->v1->co, e->v2->co), -FLT_EPSILON);
}
static float bm_decim_build_edge_cost_single__topology(BMEdge *e)
{
- return fabsf(dot_v3v3(e->v1->no, e->v2->no)) / min_ff(-len_v3v3(e->v1->co, e->v2->co), -FLT_EPSILON);
+ return fabsf(dot_v3v3(e->v1->no, e->v2->no)) /
+ min_ff(-len_v3v3(e->v1->co, e->v2->co), -FLT_EPSILON);
}
-#endif /* USE_TOPOLOGY_FALLBACK */
+#endif /* USE_TOPOLOGY_FALLBACK */
-static void bm_decim_build_edge_cost_single(
- BMEdge *e,
- const Quadric *vquadrics,
- const float *vweights, const float vweight_factor,
- Heap *eheap, HeapNode **eheap_table)
+static void bm_decim_build_edge_cost_single(BMEdge *e,
+ const Quadric *vquadrics,
+ const float *vweights,
+ const float vweight_factor,
+ Heap *eheap,
+ HeapNode **eheap_table)
{
- float cost;
-
- if (UNLIKELY(vweights &&
- ((vweights[BM_elem_index_get(e->v1)] == 0.0f) ||
- (vweights[BM_elem_index_get(e->v2)] == 0.0f))))
- {
- goto clear;
- }
-
- /* check we can collapse, some edges we better not touch */
- if (BM_edge_is_boundary(e)) {
- if (e->l->f->len == 3) {
- /* pass */
- }
- else {
- /* only collapse tri's */
- goto clear;
- }
- }
- else if (BM_edge_is_manifold(e)) {
- if ((e->l->f->len == 3) && (e->l->radial_next->f->len == 3)) {
- /* pass */
- }
- else {
- /* only collapse tri's */
- goto clear;
- }
- }
- else {
- goto clear;
- }
- /* end sanity check */
-
- {
- double optimize_co[3];
- bm_decim_calc_target_co_db(e, optimize_co, vquadrics);
-
- const Quadric *q1, *q2;
- q1 = &vquadrics[BM_elem_index_get(e->v1)];
- q2 = &vquadrics[BM_elem_index_get(e->v2)];
-
- cost = (BLI_quadric_evaluate(q1, optimize_co) +
- BLI_quadric_evaluate(q2, optimize_co));
- }
-
- /* note, 'cost' shouldn't be negative but happens sometimes with small values.
- * this can cause faces that make up a flat surface to over-collapse, see [#37121] */
- cost = fabsf(cost);
+ float cost;
+
+ if (UNLIKELY(vweights && ((vweights[BM_elem_index_get(e->v1)] == 0.0f) ||
+ (vweights[BM_elem_index_get(e->v2)] == 0.0f)))) {
+ goto clear;
+ }
+
+ /* check we can collapse, some edges we better not touch */
+ if (BM_edge_is_boundary(e)) {
+ if (e->l->f->len == 3) {
+ /* pass */
+ }
+ else {
+ /* only collapse tri's */
+ goto clear;
+ }
+ }
+ else if (BM_edge_is_manifold(e)) {
+ if ((e->l->f->len == 3) && (e->l->radial_next->f->len == 3)) {
+ /* pass */
+ }
+ else {
+ /* only collapse tri's */
+ goto clear;
+ }
+ }
+ else {
+ goto clear;
+ }
+ /* end sanity check */
+
+ {
+ double optimize_co[3];
+ bm_decim_calc_target_co_db(e, optimize_co, vquadrics);
+
+ const Quadric *q1, *q2;
+ q1 = &vquadrics[BM_elem_index_get(e->v1)];
+ q2 = &vquadrics[BM_elem_index_get(e->v2)];
+
+ cost = (BLI_quadric_evaluate(q1, optimize_co) + BLI_quadric_evaluate(q2, optimize_co));
+ }
+
+ /* note, 'cost' shouldn't be negative but happens sometimes with small values.
+ * this can cause faces that make up a flat surface to over-collapse, see [#37121] */
+ cost = fabsf(cost);
#ifdef USE_TOPOLOGY_FALLBACK
- if (UNLIKELY(cost < TOPOLOGY_FALLBACK_EPS)) {
- /* subtract existing cost to further differentiate edges from one another
- *
- * keep topology cost below 0.0 so their values don't interfere with quadric cost,
- * (and they get handled first).
- * */
- if (vweights == NULL) {
- cost = bm_decim_build_edge_cost_single_squared__topology(e) - cost;
- }
- else {
- /* with weights we need to use the real length so we can scale them properly */
- const float e_weight = (vweights[BM_elem_index_get(e->v1)] +
- vweights[BM_elem_index_get(e->v2)]);
- cost = bm_decim_build_edge_cost_single__topology(e) - cost;
- /* note, this is rather arbitrary max weight is 2 here,
- * allow for skipping edges 4x the length, based on weights */
- if (e_weight) {
- cost *= 1.0f + (e_weight * vweight_factor);
- }
-
- BLI_assert(cost <= 0.0f);
- }
- }
- else
+ if (UNLIKELY(cost < TOPOLOGY_FALLBACK_EPS)) {
+ /* subtract existing cost to further differentiate edges from one another
+ *
+ * keep topology cost below 0.0 so their values don't interfere with quadric cost,
+ * (and they get handled first).
+ * */
+ if (vweights == NULL) {
+ cost = bm_decim_build_edge_cost_single_squared__topology(e) - cost;
+ }
+ else {
+ /* with weights we need to use the real length so we can scale them properly */
+ const float e_weight = (vweights[BM_elem_index_get(e->v1)] +
+ vweights[BM_elem_index_get(e->v2)]);
+ cost = bm_decim_build_edge_cost_single__topology(e) - cost;
+ /* note, this is rather arbitrary max weight is 2 here,
+ * allow for skipping edges 4x the length, based on weights */
+ if (e_weight) {
+ cost *= 1.0f + (e_weight * vweight_factor);
+ }
+
+ BLI_assert(cost <= 0.0f);
+ }
+ }
+ else
#endif
- if (vweights) {
- const float e_weight = 2.0f - (vweights[BM_elem_index_get(e->v1)] +
- vweights[BM_elem_index_get(e->v2)]);
- if (e_weight) {
- cost += (BM_edge_calc_length(e) * ((e_weight * vweight_factor)));
- }
- }
+ if (vweights) {
+ const float e_weight = 2.0f - (vweights[BM_elem_index_get(e->v1)] +
+ vweights[BM_elem_index_get(e->v2)]);
+ if (e_weight) {
+ cost += (BM_edge_calc_length(e) * ((e_weight * vweight_factor)));
+ }
+ }
- BLI_heap_insert_or_update(eheap, &eheap_table[BM_elem_index_get(e)], cost, e);
- return;
+ BLI_heap_insert_or_update(eheap, &eheap_table[BM_elem_index_get(e)], cost, e);
+ return;
clear:
- if (eheap_table[BM_elem_index_get(e)]) {
- BLI_heap_remove(eheap, eheap_table[BM_elem_index_get(e)]);
- }
- eheap_table[BM_elem_index_get(e)] = NULL;
+ if (eheap_table[BM_elem_index_get(e)]) {
+ BLI_heap_remove(eheap, eheap_table[BM_elem_index_get(e)]);
+ }
+ eheap_table[BM_elem_index_get(e)] = NULL;
}
-
/* use this for degenerate cases - add back to the heap with an invalid cost,
* this way it may be calculated again if surrounding geometry changes */
-static void bm_decim_invalid_edge_cost_single(
- BMEdge *e,
- Heap *eheap, HeapNode **eheap_table)
+static void bm_decim_invalid_edge_cost_single(BMEdge *e, Heap *eheap, HeapNode **eheap_table)
{
- BLI_assert(eheap_table[BM_elem_index_get(e)] == NULL);
- eheap_table[BM_elem_index_get(e)] = BLI_heap_insert(eheap, COST_INVALID, e);
+ BLI_assert(eheap_table[BM_elem_index_get(e)] == NULL);
+ eheap_table[BM_elem_index_get(e)] = BLI_heap_insert(eheap, COST_INVALID, e);
}
-static void bm_decim_build_edge_cost(
- BMesh *bm,
- const Quadric *vquadrics,
- const float *vweights, const float vweight_factor,
- Heap *eheap, HeapNode **eheap_table)
+static void bm_decim_build_edge_cost(BMesh *bm,
+ const Quadric *vquadrics,
+ const float *vweights,
+ const float vweight_factor,
+ Heap *eheap,
+ HeapNode **eheap_table)
{
- BMIter iter;
- BMEdge *e;
- uint i;
-
- BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
- /* keep sanity check happy */
- eheap_table[i] = NULL;
- bm_decim_build_edge_cost_single(e, vquadrics, vweights, vweight_factor, eheap, eheap_table);
- }
+ BMIter iter;
+ BMEdge *e;
+ uint i;
+
+ BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
+ /* keep sanity check happy */
+ eheap_table[i] = NULL;
+ bm_decim_build_edge_cost_single(e, vquadrics, vweights, vweight_factor, eheap, eheap_table);
+ }
}
#ifdef USE_SYMMETRY
struct KD_Symmetry_Data {
- /* pre-flipped coords */
- float e_v1_co[3], e_v2_co[3];
- /* Use to compare the correct endpoints incase v1/v2 are swapped */
- float e_dir[3];
+ /* pre-flipped coords */
+ float e_v1_co[3], e_v2_co[3];
+ /* Use to compare the correct endpoints incase v1/v2 are swapped */
+ float e_dir[3];
- int e_found_index;
+ int e_found_index;
- /* same for all */
- BMEdge **etable;
- float limit_sq;
+ /* same for all */
+ BMEdge **etable;
+ float limit_sq;
};
-static bool bm_edge_symmetry_check_cb(void *user_data, int index, const float UNUSED(co[3]), float UNUSED(dist_sq))
+static bool bm_edge_symmetry_check_cb(void *user_data,
+ int index,
+ const float UNUSED(co[3]),
+ float UNUSED(dist_sq))
{
- struct KD_Symmetry_Data *sym_data = user_data;
- BMEdge *e_other = sym_data->etable[index];
- float e_other_dir[3];
-
- sub_v3_v3v3(e_other_dir, e_other->v2->co, e_other->v1->co);
-
- if (dot_v3v3(e_other_dir, sym_data->e_dir) > 0.0f) {
- if ((len_squared_v3v3(sym_data->e_v1_co, e_other->v1->co) > sym_data->limit_sq) ||
- (len_squared_v3v3(sym_data->e_v2_co, e_other->v2->co) > sym_data->limit_sq))
- {
- return true;
- }
- }
- else {
- if ((len_squared_v3v3(sym_data->e_v1_co, e_other->v2->co) > sym_data->limit_sq) ||
- (len_squared_v3v3(sym_data->e_v2_co, e_other->v1->co) > sym_data->limit_sq))
- {
- return true;
- }
- }
-
- /* exit on first-hit, this is OK since the search range is very small */
- sym_data->e_found_index = index;
- return false;
+ struct KD_Symmetry_Data *sym_data = user_data;
+ BMEdge *e_other = sym_data->etable[index];
+ float e_other_dir[3];
+
+ sub_v3_v3v3(e_other_dir, e_other->v2->co, e_other->v1->co);
+
+ if (dot_v3v3(e_other_dir, sym_data->e_dir) > 0.0f) {
+ if ((len_squared_v3v3(sym_data->e_v1_co, e_other->v1->co) > sym_data->limit_sq) ||
+ (len_squared_v3v3(sym_data->e_v2_co, e_other->v2->co) > sym_data->limit_sq)) {
+ return true;
+ }
+ }
+ else {
+ if ((len_squared_v3v3(sym_data->e_v1_co, e_other->v2->co) > sym_data->limit_sq) ||
+ (len_squared_v3v3(sym_data->e_v2_co, e_other->v1->co) > sym_data->limit_sq)) {
+ return true;
+ }
+ }
+
+ /* exit on first-hit, this is OK since the search range is very small */
+ sym_data->e_found_index = index;
+ return false;
}
static int *bm_edge_symmetry_map(BMesh *bm, uint symmetry_axis, float limit)
{
- struct KD_Symmetry_Data sym_data;
- BMIter iter;
- BMEdge *e, **etable;
- uint i;
- int *edge_symmetry_map;
- const float limit_sq = SQUARE(limit);
- KDTree_3d *tree;
-
- tree = BLI_kdtree_3d_new(bm->totedge);
-
- etable = MEM_mallocN(sizeof(*etable) * bm->totedge, __func__);
- edge_symmetry_map = MEM_mallocN(sizeof(*edge_symmetry_map) * bm->totedge, __func__);
-
- BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
- float co[3];
- mid_v3_v3v3(co, e->v1->co, e->v2->co);
- BLI_kdtree_3d_insert(tree, i, co);
- etable[i] = e;
- edge_symmetry_map[i] = -1;
- }
-
- BLI_kdtree_3d_balance(tree);
-
- sym_data.etable = etable;
- sym_data.limit_sq = limit_sq;
-
- BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
- if (edge_symmetry_map[i] == -1) {
- float co[3];
- mid_v3_v3v3(co, e->v1->co, e->v2->co);
- co[symmetry_axis] *= -1.0f;
-
- copy_v3_v3(sym_data.e_v1_co, e->v1->co);
- copy_v3_v3(sym_data.e_v2_co, e->v2->co);
- sym_data.e_v1_co[symmetry_axis] *= -1.0f;
- sym_data.e_v2_co[symmetry_axis] *= -1.0f;
- sub_v3_v3v3(sym_data.e_dir, sym_data.e_v2_co, sym_data.e_v1_co);
- sym_data.e_found_index = -1;
-
- BLI_kdtree_3d_range_search_cb(tree, co, limit, bm_edge_symmetry_check_cb, &sym_data);
-
- if (sym_data.e_found_index != -1) {
- const int i_other = sym_data.e_found_index;
- edge_symmetry_map[i] = i_other;
- edge_symmetry_map[i_other] = i;
- }
- }
- }
-
- MEM_freeN(etable);
- BLI_kdtree_3d_free(tree);
-
- return edge_symmetry_map;
+ struct KD_Symmetry_Data sym_data;
+ BMIter iter;
+ BMEdge *e, **etable;
+ uint i;
+ int *edge_symmetry_map;
+ const float limit_sq = SQUARE(limit);
+ KDTree_3d *tree;
+
+ tree = BLI_kdtree_3d_new(bm->totedge);
+
+ etable = MEM_mallocN(sizeof(*etable) * bm->totedge, __func__);
+ edge_symmetry_map = MEM_mallocN(sizeof(*edge_symmetry_map) * bm->totedge, __func__);
+
+ BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
+ float co[3];
+ mid_v3_v3v3(co, e->v1->co, e->v2->co);
+ BLI_kdtree_3d_insert(tree, i, co);
+ etable[i] = e;
+ edge_symmetry_map[i] = -1;
+ }
+
+ BLI_kdtree_3d_balance(tree);
+
+ sym_data.etable = etable;
+ sym_data.limit_sq = limit_sq;
+
+ BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
+ if (edge_symmetry_map[i] == -1) {
+ float co[3];
+ mid_v3_v3v3(co, e->v1->co, e->v2->co);
+ co[symmetry_axis] *= -1.0f;
+
+ copy_v3_v3(sym_data.e_v1_co, e->v1->co);
+ copy_v3_v3(sym_data.e_v2_co, e->v2->co);
+ sym_data.e_v1_co[symmetry_axis] *= -1.0f;
+ sym_data.e_v2_co[symmetry_axis] *= -1.0f;
+ sub_v3_v3v3(sym_data.e_dir, sym_data.e_v2_co, sym_data.e_v1_co);
+ sym_data.e_found_index = -1;
+
+ BLI_kdtree_3d_range_search_cb(tree, co, limit, bm_edge_symmetry_check_cb, &sym_data);
+
+ if (sym_data.e_found_index != -1) {
+ const int i_other = sym_data.e_found_index;
+ edge_symmetry_map[i] = i_other;
+ edge_symmetry_map[i_other] = i;
+ }
+ }
+ }
+
+ MEM_freeN(etable);
+ BLI_kdtree_3d_free(tree);
+
+ return edge_symmetry_map;
}
-#endif /* USE_SYMMETRY */
+#endif /* USE_SYMMETRY */
#ifdef USE_TRIANGULATE
/* Temp Triangulation
@@ -490,205 +476,208 @@ static int *bm_edge_symmetry_map(BMesh *bm, uint symmetry_axis, float limit)
*
* \return true if any faces were triangulated.
*/
-static bool bm_face_triangulate(
- BMesh *bm, BMFace *f_base, LinkNode **r_faces_double, int *r_edges_tri_tot,
-
- MemArena *pf_arena,
- /* use for MOD_TRIANGULATE_NGON_BEAUTY only! */
- struct Heap *pf_heap)
+static bool bm_face_triangulate(BMesh *bm,
+ BMFace *f_base,
+ LinkNode **r_faces_double,
+ int *r_edges_tri_tot,
+
+ MemArena *pf_arena,
+ /* use for MOD_TRIANGULATE_NGON_BEAUTY only! */
+ 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 */
-
- bool has_cut = false;
-
- const int f_index = BM_elem_index_get(f_base);
-
- BM_face_triangulate(
- bm, f_base,
- faces_array, &faces_array_tot,
- edges_array, &edges_array_tot,
- r_faces_double,
- quad_method, ngon_method, false,
- pf_arena, pf_heap);
-
- for (int i = 0; i < edges_array_tot; i++) {
- BMLoop *l_iter, *l_first;
- l_iter = l_first = edges_array[i]->l;
- do {
- BM_elem_index_set(l_iter, f_index); /* set_dirty */
- has_cut = true;
- } while ((l_iter = l_iter->radial_next) != l_first);
- }
-
- for (int i = 0; i < faces_array_tot; i++) {
- BM_face_normal_update(faces_array[i]);
- }
-
- *r_edges_tri_tot += edges_array_tot;
-
- return has_cut;
+ 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 */
+
+ bool has_cut = false;
+
+ const int f_index = BM_elem_index_get(f_base);
+
+ BM_face_triangulate(bm,
+ f_base,
+ faces_array,
+ &faces_array_tot,
+ edges_array,
+ &edges_array_tot,
+ r_faces_double,
+ quad_method,
+ ngon_method,
+ false,
+ pf_arena,
+ pf_heap);
+
+ for (int i = 0; i < edges_array_tot; i++) {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = edges_array[i]->l;
+ do {
+ BM_elem_index_set(l_iter, f_index); /* set_dirty */
+ has_cut = true;
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+
+ for (int i = 0; i < faces_array_tot; i++) {
+ BM_face_normal_update(faces_array[i]);
+ }
+
+ *r_edges_tri_tot += edges_array_tot;
+
+ return has_cut;
}
-
static bool bm_decim_triangulate_begin(BMesh *bm, int *r_edges_tri_tot)
{
- BMIter iter;
- BMFace *f;
- bool has_quad = false;
- bool has_ngon = false;
- bool has_cut = false;
-
- BLI_assert((bm->elem_index_dirty & BM_VERT) == 0);
-
- /* first clear loop index values */
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- BMLoop *l_iter;
- BMLoop *l_first;
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- BM_elem_index_set(l_iter, -1); /* set_dirty */
- } while ((l_iter = l_iter->next) != l_first);
-
- has_quad |= (f->len > 3);
- has_ngon |= (f->len > 4);
- }
-
- bm->elem_index_dirty |= BM_LOOP;
-
- {
- MemArena *pf_arena;
- Heap *pf_heap;
-
- LinkNode *faces_double = NULL;
-
- if (has_ngon) {
- pf_arena = BLI_memarena_new(BLI_POLYFILL_ARENA_SIZE, __func__);
- pf_heap = BLI_heap_new_ex(BLI_POLYFILL_ALLOC_NGON_RESERVE);
- }
- else {
- pf_arena = NULL;
- pf_heap = NULL;
- }
-
- /* adding new faces as we loop over faces
- * is normally best avoided, however in this case its not so bad because any face touched twice
- * will already be triangulated*/
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- if (f->len > 3) {
- has_cut |= bm_face_triangulate(
- bm, f, &faces_double,
- r_edges_tri_tot,
-
- pf_arena, pf_heap);
- }
- }
-
- while (faces_double) {
- LinkNode *next = faces_double->next;
- BM_face_kill(bm, faces_double->link);
- MEM_freeN(faces_double);
- faces_double = next;
- }
-
- if (has_ngon) {
- BLI_memarena_free(pf_arena);
- BLI_heap_free(pf_heap, NULL);
- }
-
- BLI_assert((bm->elem_index_dirty & BM_VERT) == 0);
-
- if (has_cut) {
- /* now triangulation is done we need to correct index values */
- BM_mesh_elem_index_ensure(bm, BM_EDGE | BM_FACE);
- }
- }
-
- return has_cut;
+ BMIter iter;
+ BMFace *f;
+ bool has_quad = false;
+ bool has_ngon = false;
+ bool has_cut = false;
+
+ BLI_assert((bm->elem_index_dirty & BM_VERT) == 0);
+
+ /* first clear loop index values */
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ BMLoop *l_iter;
+ BMLoop *l_first;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BM_elem_index_set(l_iter, -1); /* set_dirty */
+ } while ((l_iter = l_iter->next) != l_first);
+
+ has_quad |= (f->len > 3);
+ has_ngon |= (f->len > 4);
+ }
+
+ bm->elem_index_dirty |= BM_LOOP;
+
+ {
+ MemArena *pf_arena;
+ Heap *pf_heap;
+
+ LinkNode *faces_double = NULL;
+
+ if (has_ngon) {
+ pf_arena = BLI_memarena_new(BLI_POLYFILL_ARENA_SIZE, __func__);
+ pf_heap = BLI_heap_new_ex(BLI_POLYFILL_ALLOC_NGON_RESERVE);
+ }
+ else {
+ pf_arena = NULL;
+ pf_heap = NULL;
+ }
+
+ /* adding new faces as we loop over faces
+ * is normally best avoided, however in this case its not so bad because any face touched twice
+ * will already be triangulated*/
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if (f->len > 3) {
+ has_cut |= bm_face_triangulate(bm,
+ f,
+ &faces_double,
+ r_edges_tri_tot,
+
+ pf_arena,
+ pf_heap);
+ }
+ }
+
+ while (faces_double) {
+ LinkNode *next = faces_double->next;
+ BM_face_kill(bm, faces_double->link);
+ MEM_freeN(faces_double);
+ faces_double = next;
+ }
+
+ if (has_ngon) {
+ BLI_memarena_free(pf_arena);
+ BLI_heap_free(pf_heap, NULL);
+ }
+
+ BLI_assert((bm->elem_index_dirty & BM_VERT) == 0);
+
+ if (has_cut) {
+ /* now triangulation is done we need to correct index values */
+ BM_mesh_elem_index_ensure(bm, BM_EDGE | BM_FACE);
+ }
+ }
+
+ return has_cut;
}
-
static void bm_decim_triangulate_end(BMesh *bm, const int edges_tri_tot)
{
- /* decimation finished, now re-join */
- BMIter iter;
- BMEdge *e;
-
- /* we need to collect before merging for ngons since the loops indices will be lost */
- BMEdge **edges_tri = MEM_mallocN(MIN2(edges_tri_tot, bm->totedge) * sizeof(*edges_tri), __func__);
- STACK_DECLARE(edges_tri);
-
- STACK_INIT(edges_tri, MIN2(edges_tri_tot, bm->totedge));
-
- /* boundary edges */
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- BMLoop *l_a, *l_b;
- if (BM_edge_loop_pair(e, &l_a, &l_b)) {
- const int l_a_index = BM_elem_index_get(l_a);
- if (l_a_index != -1) {
- const int l_b_index = BM_elem_index_get(l_b);
- if (l_a_index == l_b_index) {
- if (l_a->v != l_b->v) { /* if this is the case, faces have become flipped */
- /* check we are not making a degenerate quad */
-
-#define CAN_LOOP_MERGE(l) \
- (BM_loop_is_manifold(l) && \
- ((l)->v != (l)->radial_next->v) && \
- (l_a_index == BM_elem_index_get(l)) && \
- (l_a_index == BM_elem_index_get((l)->radial_next)))
-
- if ((l_a->f->len == 3 && l_b->f->len == 3) &&
- (!CAN_LOOP_MERGE(l_a->next)) &&
- (!CAN_LOOP_MERGE(l_a->prev)) &&
- (!CAN_LOOP_MERGE(l_b->next)) &&
- (!CAN_LOOP_MERGE(l_b->prev)))
- {
- BMVert *vquad[4] = {
- e->v1,
- BM_vert_in_edge(e, l_a->next->v) ? l_a->prev->v : l_a->next->v,
- e->v2,
- BM_vert_in_edge(e, l_b->next->v) ? l_b->prev->v : l_b->next->v,
- };
-
- BLI_assert(ELEM(vquad[0], vquad[1], vquad[2], vquad[3]) == false);
- BLI_assert(ELEM(vquad[1], vquad[0], vquad[2], vquad[3]) == false);
- BLI_assert(ELEM(vquad[2], vquad[1], vquad[0], vquad[3]) == false);
- BLI_assert(ELEM(vquad[3], vquad[1], vquad[2], vquad[0]) == false);
-
- if (!is_quad_convex_v3(vquad[0]->co, vquad[1]->co, vquad[2]->co, vquad[3]->co)) {
- continue;
- }
- }
-#undef CAN_LOOP_MERGE
-
- /* highly unlikely to fail, but prevents possible double-ups */
- STACK_PUSH(edges_tri, e);
- }
- }
- }
- }
- }
-
- for (int i = 0; i < STACK_SIZE(edges_tri); i++) {
- BMLoop *l_a, *l_b;
- e = edges_tri[i];
- if (BM_edge_loop_pair(e, &l_a, &l_b)) {
- BMFace *f_array[2] = {l_a->f, l_b->f};
- BM_faces_join(bm, f_array, 2, false);
- if (e->l == NULL) {
- BM_edge_kill(bm, e);
- }
- }
- }
- MEM_freeN(edges_tri);
+ /* decimation finished, now re-join */
+ BMIter iter;
+ BMEdge *e;
+
+ /* we need to collect before merging for ngons since the loops indices will be lost */
+ BMEdge **edges_tri = MEM_mallocN(MIN2(edges_tri_tot, bm->totedge) * sizeof(*edges_tri),
+ __func__);
+ STACK_DECLARE(edges_tri);
+
+ STACK_INIT(edges_tri, MIN2(edges_tri_tot, bm->totedge));
+
+ /* boundary edges */
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ BMLoop *l_a, *l_b;
+ if (BM_edge_loop_pair(e, &l_a, &l_b)) {
+ const int l_a_index = BM_elem_index_get(l_a);
+ if (l_a_index != -1) {
+ const int l_b_index = BM_elem_index_get(l_b);
+ if (l_a_index == l_b_index) {
+ if (l_a->v != l_b->v) { /* if this is the case, faces have become flipped */
+ /* check we are not making a degenerate quad */
+
+# define CAN_LOOP_MERGE(l) \
+ (BM_loop_is_manifold(l) && ((l)->v != (l)->radial_next->v) && \
+ (l_a_index == BM_elem_index_get(l)) && (l_a_index == BM_elem_index_get((l)->radial_next)))
+
+ if ((l_a->f->len == 3 && l_b->f->len == 3) && (!CAN_LOOP_MERGE(l_a->next)) &&
+ (!CAN_LOOP_MERGE(l_a->prev)) && (!CAN_LOOP_MERGE(l_b->next)) &&
+ (!CAN_LOOP_MERGE(l_b->prev))) {
+ BMVert *vquad[4] = {
+ e->v1,
+ BM_vert_in_edge(e, l_a->next->v) ? l_a->prev->v : l_a->next->v,
+ e->v2,
+ BM_vert_in_edge(e, l_b->next->v) ? l_b->prev->v : l_b->next->v,
+ };
+
+ BLI_assert(ELEM(vquad[0], vquad[1], vquad[2], vquad[3]) == false);
+ BLI_assert(ELEM(vquad[1], vquad[0], vquad[2], vquad[3]) == false);
+ BLI_assert(ELEM(vquad[2], vquad[1], vquad[0], vquad[3]) == false);
+ BLI_assert(ELEM(vquad[3], vquad[1], vquad[2], vquad[0]) == false);
+
+ if (!is_quad_convex_v3(vquad[0]->co, vquad[1]->co, vquad[2]->co, vquad[3]->co)) {
+ continue;
+ }
+ }
+# undef CAN_LOOP_MERGE
+
+ /* highly unlikely to fail, but prevents possible double-ups */
+ STACK_PUSH(edges_tri, e);
+ }
+ }
+ }
+ }
+ }
+
+ for (int i = 0; i < STACK_SIZE(edges_tri); i++) {
+ BMLoop *l_a, *l_b;
+ e = edges_tri[i];
+ if (BM_edge_loop_pair(e, &l_a, &l_b)) {
+ BMFace *f_array[2] = {l_a->f, l_b->f};
+ BM_faces_join(bm, f_array, 2, false);
+ if (e->l == NULL) {
+ BM_edge_kill(bm, e);
+ }
+ }
+ }
+ MEM_freeN(edges_tri);
}
-#endif /* USE_TRIANGULATE */
+#endif /* USE_TRIANGULATE */
/* Edge Collapse Functions
* *********************** */
@@ -699,112 +688,114 @@ static void bm_decim_triangulate_end(BMesh *bm, const int edges_tri_tot)
* \param l: defines the vert to collapse into.
*/
static void bm_edge_collapse_loop_customdata(
- BMesh *bm, BMLoop *l, BMVert *v_clear, BMVert *v_other,
- const float customdata_fac)
+ BMesh *bm, BMLoop *l, BMVert *v_clear, BMVert *v_other, const float customdata_fac)
{
- /* disable seam check - the seam check would have to be done per layer, its not really that important */
-//#define USE_SEAM
- /* these don't need to be updated, since they will get removed when the edge collapses */
- BMLoop *l_clear, *l_other;
- const bool is_manifold = BM_edge_is_manifold(l->e);
- int side;
-
- /* first find the loop of 'v_other' thats attached to the face of 'l' */
- if (l->v == v_clear) {
- l_clear = l;
- l_other = l->next;
- }
- else {
- l_clear = l->next;
- l_other = l;
- }
-
- BLI_assert(l_clear->v == v_clear);
- BLI_assert(l_other->v == v_other);
- /* quiet warnings for release */
- (void)v_other;
-
- /* now we have both corners of the face 'l->f' */
- for (side = 0; side < 2; side++) {
-#ifdef USE_SEAM
- bool is_seam = false;
-#endif
- void *src[2];
- BMFace *f_exit = is_manifold ? l->radial_next->f : NULL;
- BMEdge *e_prev = l->e;
- BMLoop *l_first;
- BMLoop *l_iter;
- float w[2];
-
- if (side == 0) {
- l_iter = l_first = l_clear;
- src[0] = l_clear->head.data;
- src[1] = l_other->head.data;
-
- w[0] = customdata_fac;
- w[1] = 1.0f - customdata_fac;
- }
- else {
- l_iter = l_first = l_other;
- src[0] = l_other->head.data;
- src[1] = l_clear->head.data;
-
- w[0] = 1.0f - customdata_fac;
- w[1] = customdata_fac;
- }
-
- // print_v2("weights", w);
-
- /* WATCH IT! - should NOT reference (_clear or _other) vars for this while loop */
-
- /* walk around the fan using 'e_prev' */
- while (((l_iter = BM_vert_step_fan_loop(l_iter, &e_prev)) != l_first) && (l_iter != NULL)) {
- int i;
- /* quit once we hit the opposite face, if we have one */
- if (f_exit && UNLIKELY(f_exit == l_iter->f)) {
- break;
- }
-
-#ifdef USE_SEAM
- /* break out unless we find a match */
- is_seam = true;
-#endif
-
- /* ok. we have a loop. now be smart with it! */
- for (i = 0; i < bm->ldata.totlayer; i++) {
- if (CustomData_layer_has_math(&bm->ldata, i)) {
- const int offset = bm->ldata.layers[i].offset;
- const int type = bm->ldata.layers[i].type;
- const void *cd_src[2] = {
- POINTER_OFFSET(src[0], offset),
- POINTER_OFFSET(src[1], offset),
- };
- void *cd_iter = POINTER_OFFSET(l_iter->head.data, offset);
-
- /* detect seams */
- if (CustomData_data_equals(type, cd_src[0], cd_iter)) {
- CustomData_bmesh_interp_n(
- &bm->ldata, cd_src, w, NULL, ARRAY_SIZE(cd_src),
- POINTER_OFFSET(l_iter->head.data, offset), i);
-#ifdef USE_SEAM
- is_seam = false;
-#endif
- }
- }
- }
-
-#ifdef USE_SEAM
- if (is_seam) {
- break;
- }
-#endif
- }
- }
-
-//#undef USE_SEAM
-
+ /* disable seam check - the seam check would have to be done per layer, its not really that important */
+ //#define USE_SEAM
+ /* these don't need to be updated, since they will get removed when the edge collapses */
+ BMLoop *l_clear, *l_other;
+ const bool is_manifold = BM_edge_is_manifold(l->e);
+ int side;
+
+ /* first find the loop of 'v_other' thats attached to the face of 'l' */
+ if (l->v == v_clear) {
+ l_clear = l;
+ l_other = l->next;
+ }
+ else {
+ l_clear = l->next;
+ l_other = l;
+ }
+
+ BLI_assert(l_clear->v == v_clear);
+ BLI_assert(l_other->v == v_other);
+ /* quiet warnings for release */
+ (void)v_other;
+
+ /* now we have both corners of the face 'l->f' */
+ for (side = 0; side < 2; side++) {
+# ifdef USE_SEAM
+ bool is_seam = false;
+# endif
+ void *src[2];
+ BMFace *f_exit = is_manifold ? l->radial_next->f : NULL;
+ BMEdge *e_prev = l->e;
+ BMLoop *l_first;
+ BMLoop *l_iter;
+ float w[2];
+
+ if (side == 0) {
+ l_iter = l_first = l_clear;
+ src[0] = l_clear->head.data;
+ src[1] = l_other->head.data;
+
+ w[0] = customdata_fac;
+ w[1] = 1.0f - customdata_fac;
+ }
+ else {
+ l_iter = l_first = l_other;
+ src[0] = l_other->head.data;
+ src[1] = l_clear->head.data;
+
+ w[0] = 1.0f - customdata_fac;
+ w[1] = customdata_fac;
+ }
+
+ // print_v2("weights", w);
+
+ /* WATCH IT! - should NOT reference (_clear or _other) vars for this while loop */
+
+ /* walk around the fan using 'e_prev' */
+ while (((l_iter = BM_vert_step_fan_loop(l_iter, &e_prev)) != l_first) && (l_iter != NULL)) {
+ int i;
+ /* quit once we hit the opposite face, if we have one */
+ if (f_exit && UNLIKELY(f_exit == l_iter->f)) {
+ break;
+ }
+
+# ifdef USE_SEAM
+ /* break out unless we find a match */
+ is_seam = true;
+# endif
+
+ /* ok. we have a loop. now be smart with it! */
+ for (i = 0; i < bm->ldata.totlayer; i++) {
+ if (CustomData_layer_has_math(&bm->ldata, i)) {
+ const int offset = bm->ldata.layers[i].offset;
+ const int type = bm->ldata.layers[i].type;
+ const void *cd_src[2] = {
+ POINTER_OFFSET(src[0], offset),
+ POINTER_OFFSET(src[1], offset),
+ };
+ void *cd_iter = POINTER_OFFSET(l_iter->head.data, offset);
+
+ /* detect seams */
+ if (CustomData_data_equals(type, cd_src[0], cd_iter)) {
+ CustomData_bmesh_interp_n(&bm->ldata,
+ cd_src,
+ w,
+ NULL,
+ ARRAY_SIZE(cd_src),
+ POINTER_OFFSET(l_iter->head.data, offset),
+ i);
+# ifdef USE_SEAM
+ is_seam = false;
+# endif
+ }
+ }
+ }
+
+# ifdef USE_SEAM
+ if (is_seam) {
+ break;
+ }
+# endif
+ }
+ }
+
+ //#undef USE_SEAM
}
-#endif /* USE_CUSTOMDATA */
+#endif /* USE_CUSTOMDATA */
/**
* Check if the collapse will result in a degenerate mesh,
@@ -817,131 +808,129 @@ static void bm_edge_collapse_loop_customdata(
static void bm_edge_tag_enable(BMEdge *e)
{
- BM_elem_flag_enable(e->v1, BM_ELEM_TAG);
- BM_elem_flag_enable(e->v2, BM_ELEM_TAG);
- if (e->l) {
- BM_elem_flag_enable(e->l->f, BM_ELEM_TAG);
- if (e->l != e->l->radial_next) {
- BM_elem_flag_enable(e->l->radial_next->f, BM_ELEM_TAG);
- }
- }
+ BM_elem_flag_enable(e->v1, BM_ELEM_TAG);
+ BM_elem_flag_enable(e->v2, BM_ELEM_TAG);
+ if (e->l) {
+ BM_elem_flag_enable(e->l->f, BM_ELEM_TAG);
+ if (e->l != e->l->radial_next) {
+ BM_elem_flag_enable(e->l->radial_next->f, BM_ELEM_TAG);
+ }
+ }
}
static void bm_edge_tag_disable(BMEdge *e)
{
- BM_elem_flag_disable(e->v1, BM_ELEM_TAG);
- BM_elem_flag_disable(e->v2, BM_ELEM_TAG);
- if (e->l) {
- BM_elem_flag_disable(e->l->f, BM_ELEM_TAG);
- if (e->l != e->l->radial_next) {
- BM_elem_flag_disable(e->l->radial_next->f, BM_ELEM_TAG);
- }
- }
+ BM_elem_flag_disable(e->v1, BM_ELEM_TAG);
+ BM_elem_flag_disable(e->v2, BM_ELEM_TAG);
+ if (e->l) {
+ BM_elem_flag_disable(e->l->f, BM_ELEM_TAG);
+ if (e->l != e->l->radial_next) {
+ BM_elem_flag_disable(e->l->radial_next->f, BM_ELEM_TAG);
+ }
+ }
}
static bool bm_edge_tag_test(BMEdge *e)
{
- /* is the edge or one of its faces tagged? */
- return (BM_elem_flag_test(e->v1, BM_ELEM_TAG) ||
- BM_elem_flag_test(e->v2, BM_ELEM_TAG) ||
- (e->l && (BM_elem_flag_test(e->l->f, BM_ELEM_TAG) ||
- (e->l != e->l->radial_next &&
- BM_elem_flag_test(e->l->radial_next->f, BM_ELEM_TAG))))
- );
+ /* is the edge or one of its faces tagged? */
+ return (BM_elem_flag_test(e->v1, BM_ELEM_TAG) || BM_elem_flag_test(e->v2, BM_ELEM_TAG) ||
+ (e->l &&
+ (BM_elem_flag_test(e->l->f, BM_ELEM_TAG) ||
+ (e->l != e->l->radial_next && BM_elem_flag_test(e->l->radial_next->f, BM_ELEM_TAG)))));
}
/* takes the edges loop */
BLI_INLINE int bm_edge_is_manifold_or_boundary(BMLoop *l)
{
#if 0
- /* less optimized version of check below */
- return (BM_edge_is_manifold(l->e) || BM_edge_is_boundary(l->e);
+ /* less optimized version of check below */
+ return (BM_edge_is_manifold(l->e) || BM_edge_is_boundary(l->e);
#else
- /* if the edge is a boundary it points to its self, else this must be a manifold */
- return LIKELY(l) && LIKELY(l->radial_next->radial_next == l);
+ /* if the edge is a boundary it points to its self, else this must be a manifold */
+ return LIKELY(l) && LIKELY(l->radial_next->radial_next == l);
#endif
}
static bool bm_edge_collapse_is_degenerate_topology(BMEdge *e_first)
{
- /* simply check that there is no overlap between faces and edges of each vert,
- * (excluding the 2 faces attached to 'e' and 'e' its self) */
-
- BMEdge *e_iter;
-
- /* clear flags on both disks */
- e_iter = e_first;
- do {
- if (!bm_edge_is_manifold_or_boundary(e_iter->l)) {
- return true;
- }
- bm_edge_tag_disable(e_iter);
- } while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v1)) != e_first);
-
- e_iter = e_first;
- do {
- if (!bm_edge_is_manifold_or_boundary(e_iter->l)) {
- return true;
- }
- bm_edge_tag_disable(e_iter);
- } while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v2)) != e_first);
-
- /* now enable one side... */
- e_iter = e_first;
- do {
- bm_edge_tag_enable(e_iter);
- } while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v1)) != e_first);
-
- /* ... except for the edge we will collapse, we know thats shared,
- * disable this to avoid false positive. We could be smart and never enable these
- * face/edge tags in the first place but easier to do this */
- // bm_edge_tag_disable(e_first);
- /* do inline... */
- {
+ /* simply check that there is no overlap between faces and edges of each vert,
+ * (excluding the 2 faces attached to 'e' and 'e' its self) */
+
+ BMEdge *e_iter;
+
+ /* clear flags on both disks */
+ e_iter = e_first;
+ do {
+ if (!bm_edge_is_manifold_or_boundary(e_iter->l)) {
+ return true;
+ }
+ bm_edge_tag_disable(e_iter);
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v1)) != e_first);
+
+ e_iter = e_first;
+ do {
+ if (!bm_edge_is_manifold_or_boundary(e_iter->l)) {
+ return true;
+ }
+ bm_edge_tag_disable(e_iter);
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v2)) != e_first);
+
+ /* now enable one side... */
+ e_iter = e_first;
+ do {
+ bm_edge_tag_enable(e_iter);
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v1)) != e_first);
+
+ /* ... except for the edge we will collapse, we know thats shared,
+ * disable this to avoid false positive. We could be smart and never enable these
+ * face/edge tags in the first place but easier to do this */
+ // bm_edge_tag_disable(e_first);
+ /* do inline... */
+ {
#if 0
- BMIter iter;
- BMIter liter;
- BMLoop *l;
- BMVert *v;
- BM_ITER_ELEM (l, &liter, e_first, BM_LOOPS_OF_EDGE) {
- BM_elem_flag_disable(l->f, BM_ELEM_TAG);
- BM_ITER_ELEM (v, &iter, l->f, BM_VERTS_OF_FACE) {
- BM_elem_flag_disable(v, BM_ELEM_TAG);
- }
- }
+ BMIter iter;
+ BMIter liter;
+ BMLoop *l;
+ BMVert *v;
+ BM_ITER_ELEM (l, &liter, e_first, BM_LOOPS_OF_EDGE) {
+ BM_elem_flag_disable(l->f, BM_ELEM_TAG);
+ BM_ITER_ELEM (v, &iter, l->f, BM_VERTS_OF_FACE) {
+ BM_elem_flag_disable(v, BM_ELEM_TAG);
+ }
+ }
#else
- /* we know each face is a triangle, no looping/iterators needed here */
-
- BMLoop *l_radial;
- BMLoop *l_face;
-
- l_radial = e_first->l;
- l_face = l_radial;
- BLI_assert(l_face->f->len == 3);
- BM_elem_flag_disable(l_face->f, BM_ELEM_TAG);
- BM_elem_flag_disable((l_face = l_radial)->v, BM_ELEM_TAG);
- BM_elem_flag_disable((l_face = l_face->next)->v, BM_ELEM_TAG);
- BM_elem_flag_disable(( l_face->next)->v, BM_ELEM_TAG);
- l_face = l_radial->radial_next;
- if (l_radial != l_face) {
- BLI_assert(l_face->f->len == 3);
- BM_elem_flag_disable(l_face->f, BM_ELEM_TAG);
- BM_elem_flag_disable((l_face = l_radial->radial_next)->v, BM_ELEM_TAG);
- BM_elem_flag_disable((l_face = l_face->next)->v, BM_ELEM_TAG);
- BM_elem_flag_disable(( l_face->next)->v, BM_ELEM_TAG);
- }
+ /* we know each face is a triangle, no looping/iterators needed here */
+
+ BMLoop *l_radial;
+ BMLoop *l_face;
+
+ l_radial = e_first->l;
+ l_face = l_radial;
+ BLI_assert(l_face->f->len == 3);
+ BM_elem_flag_disable(l_face->f, BM_ELEM_TAG);
+ BM_elem_flag_disable((l_face = l_radial)->v, BM_ELEM_TAG);
+ BM_elem_flag_disable((l_face = l_face->next)->v, BM_ELEM_TAG);
+ BM_elem_flag_disable((l_face->next)->v, BM_ELEM_TAG);
+ l_face = l_radial->radial_next;
+ if (l_radial != l_face) {
+ BLI_assert(l_face->f->len == 3);
+ BM_elem_flag_disable(l_face->f, BM_ELEM_TAG);
+ BM_elem_flag_disable((l_face = l_radial->radial_next)->v, BM_ELEM_TAG);
+ BM_elem_flag_disable((l_face = l_face->next)->v, BM_ELEM_TAG);
+ BM_elem_flag_disable((l_face->next)->v, BM_ELEM_TAG);
+ }
#endif
- }
+ }
- /* and check for overlap */
- e_iter = e_first;
- do {
- if (bm_edge_tag_test(e_iter)) {
- return true;
- }
- } while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v2)) != e_first);
+ /* and check for overlap */
+ e_iter = e_first;
+ do {
+ if (bm_edge_tag_test(e_iter)) {
+ return true;
+ }
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v2)) != e_first);
- return false;
+ return false;
}
/**
@@ -954,334 +943,340 @@ static bool bm_edge_collapse_is_degenerate_topology(BMEdge *e_first)
* \param r_e_clear_other: Let caller know what edges we remove besides \a e_clear
* \param customdata_flag: Merge factor, scales from 0 - 1 ('v_clear' -> 'v_other')
*/
-static bool bm_edge_collapse(
- BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e_clear_other[2],
+static bool bm_edge_collapse(BMesh *bm,
+ BMEdge *e_clear,
+ BMVert *v_clear,
+ int r_e_clear_other[2],
#ifdef USE_SYMMETRY
- int *edge_symmetry_map,
+ int *edge_symmetry_map,
#endif
#ifdef USE_CUSTOMDATA
- const CD_UseFlag customdata_flag,
- const float customdata_fac
+ const CD_UseFlag customdata_flag,
+ const float customdata_fac
#else
- const CD_UseFlag UNUSED(customdata_flag),
- const float UNUSED(customdata_fac)
+ const CD_UseFlag UNUSED(customdata_flag),
+ const float UNUSED(customdata_fac)
#endif
- )
+)
{
- BMVert *v_other;
-
- v_other = BM_edge_other_vert(e_clear, v_clear);
- BLI_assert(v_other != NULL);
-
- if (BM_edge_is_manifold(e_clear)) {
- BMLoop *l_a, *l_b;
- BMEdge *e_a_other[2], *e_b_other[2];
- bool ok;
-
- ok = BM_edge_loop_pair(e_clear, &l_a, &l_b);
-
- BLI_assert(ok == true);
- BLI_assert(l_a->f->len == 3);
- BLI_assert(l_b->f->len == 3);
- UNUSED_VARS_NDEBUG(ok);
-
- /* keep 'v_clear' 0th */
- if (BM_vert_in_edge(l_a->prev->e, v_clear)) {
- e_a_other[0] = l_a->prev->e;
- e_a_other[1] = l_a->next->e;
- }
- else {
- e_a_other[1] = l_a->prev->e;
- e_a_other[0] = l_a->next->e;
- }
-
- if (BM_vert_in_edge(l_b->prev->e, v_clear)) {
- e_b_other[0] = l_b->prev->e;
- e_b_other[1] = l_b->next->e;
- }
- else {
- e_b_other[1] = l_b->prev->e;
- e_b_other[0] = l_b->next->e;
- }
-
- /* we could assert this case, but better just bail out */
+ BMVert *v_other;
+
+ v_other = BM_edge_other_vert(e_clear, v_clear);
+ BLI_assert(v_other != NULL);
+
+ if (BM_edge_is_manifold(e_clear)) {
+ BMLoop *l_a, *l_b;
+ BMEdge *e_a_other[2], *e_b_other[2];
+ bool ok;
+
+ ok = BM_edge_loop_pair(e_clear, &l_a, &l_b);
+
+ BLI_assert(ok == true);
+ BLI_assert(l_a->f->len == 3);
+ BLI_assert(l_b->f->len == 3);
+ UNUSED_VARS_NDEBUG(ok);
+
+ /* keep 'v_clear' 0th */
+ if (BM_vert_in_edge(l_a->prev->e, v_clear)) {
+ e_a_other[0] = l_a->prev->e;
+ e_a_other[1] = l_a->next->e;
+ }
+ else {
+ e_a_other[1] = l_a->prev->e;
+ e_a_other[0] = l_a->next->e;
+ }
+
+ if (BM_vert_in_edge(l_b->prev->e, v_clear)) {
+ e_b_other[0] = l_b->prev->e;
+ e_b_other[1] = l_b->next->e;
+ }
+ else {
+ e_b_other[1] = l_b->prev->e;
+ e_b_other[0] = l_b->next->e;
+ }
+
+ /* we could assert this case, but better just bail out */
#if 0
- BLI_assert(e_a_other[0] != e_b_other[0]);
- BLI_assert(e_a_other[0] != e_b_other[1]);
- BLI_assert(e_b_other[0] != e_a_other[0]);
- BLI_assert(e_b_other[0] != e_a_other[1]);
+ BLI_assert(e_a_other[0] != e_b_other[0]);
+ BLI_assert(e_a_other[0] != e_b_other[1]);
+ BLI_assert(e_b_other[0] != e_a_other[0]);
+ BLI_assert(e_b_other[0] != e_a_other[1]);
#endif
- /* not totally common but we want to avoid */
- if (ELEM(e_a_other[0], e_b_other[0], e_b_other[1]) ||
- ELEM(e_a_other[1], e_b_other[0], e_b_other[1]))
- {
- return false;
- }
+ /* not totally common but we want to avoid */
+ if (ELEM(e_a_other[0], e_b_other[0], e_b_other[1]) ||
+ ELEM(e_a_other[1], e_b_other[0], e_b_other[1])) {
+ return false;
+ }
- BLI_assert(BM_edge_share_vert(e_a_other[0], e_b_other[0]));
- BLI_assert(BM_edge_share_vert(e_a_other[1], e_b_other[1]));
+ BLI_assert(BM_edge_share_vert(e_a_other[0], e_b_other[0]));
+ BLI_assert(BM_edge_share_vert(e_a_other[1], e_b_other[1]));
- r_e_clear_other[0] = BM_elem_index_get(e_a_other[0]);
- r_e_clear_other[1] = BM_elem_index_get(e_b_other[0]);
+ r_e_clear_other[0] = BM_elem_index_get(e_a_other[0]);
+ r_e_clear_other[1] = BM_elem_index_get(e_b_other[0]);
#ifdef USE_CUSTOMDATA
- /* before killing, do customdata */
- if (customdata_flag & CD_DO_VERT) {
- BM_data_interp_from_verts(bm, v_other, v_clear, v_other, customdata_fac);
- }
- if (customdata_flag & CD_DO_EDGE) {
- BM_data_interp_from_edges(bm, e_a_other[1], e_a_other[0], e_a_other[1], customdata_fac);
- BM_data_interp_from_edges(bm, e_b_other[1], e_b_other[0], e_b_other[1], customdata_fac);
- }
- if (customdata_flag & CD_DO_LOOP) {
- bm_edge_collapse_loop_customdata(bm, e_clear->l, v_clear, v_other, customdata_fac);
- bm_edge_collapse_loop_customdata(bm, e_clear->l->radial_next, v_clear, v_other, customdata_fac);
- }
+ /* before killing, do customdata */
+ if (customdata_flag & CD_DO_VERT) {
+ BM_data_interp_from_verts(bm, v_other, v_clear, v_other, customdata_fac);
+ }
+ if (customdata_flag & CD_DO_EDGE) {
+ BM_data_interp_from_edges(bm, e_a_other[1], e_a_other[0], e_a_other[1], customdata_fac);
+ BM_data_interp_from_edges(bm, e_b_other[1], e_b_other[0], e_b_other[1], customdata_fac);
+ }
+ if (customdata_flag & CD_DO_LOOP) {
+ bm_edge_collapse_loop_customdata(bm, e_clear->l, v_clear, v_other, customdata_fac);
+ bm_edge_collapse_loop_customdata(
+ bm, e_clear->l->radial_next, v_clear, v_other, customdata_fac);
+ }
#endif
- BM_edge_kill(bm, e_clear);
+ BM_edge_kill(bm, e_clear);
- v_other->head.hflag |= v_clear->head.hflag;
- BM_vert_splice(bm, v_other, v_clear);
+ v_other->head.hflag |= v_clear->head.hflag;
+ BM_vert_splice(bm, v_other, v_clear);
- e_a_other[1]->head.hflag |= e_a_other[0]->head.hflag;
- e_b_other[1]->head.hflag |= e_b_other[0]->head.hflag;
- BM_edge_splice(bm, e_a_other[1], e_a_other[0]);
- BM_edge_splice(bm, e_b_other[1], e_b_other[0]);
+ e_a_other[1]->head.hflag |= e_a_other[0]->head.hflag;
+ e_b_other[1]->head.hflag |= e_b_other[0]->head.hflag;
+ BM_edge_splice(bm, e_a_other[1], e_a_other[0]);
+ BM_edge_splice(bm, e_b_other[1], e_b_other[0]);
#ifdef USE_SYMMETRY
- /* update mirror map */
- if (edge_symmetry_map) {
- if (edge_symmetry_map[r_e_clear_other[0]] != -1) {
- edge_symmetry_map[edge_symmetry_map[r_e_clear_other[0]]] = BM_elem_index_get(e_a_other[1]);
- }
- if (edge_symmetry_map[r_e_clear_other[1]] != -1) {
- edge_symmetry_map[edge_symmetry_map[r_e_clear_other[1]]] = BM_elem_index_get(e_b_other[1]);
- }
- }
+ /* update mirror map */
+ if (edge_symmetry_map) {
+ if (edge_symmetry_map[r_e_clear_other[0]] != -1) {
+ edge_symmetry_map[edge_symmetry_map[r_e_clear_other[0]]] = BM_elem_index_get(e_a_other[1]);
+ }
+ if (edge_symmetry_map[r_e_clear_other[1]] != -1) {
+ edge_symmetry_map[edge_symmetry_map[r_e_clear_other[1]]] = BM_elem_index_get(e_b_other[1]);
+ }
+ }
#endif
- // BM_mesh_validate(bm);
+ // BM_mesh_validate(bm);
- return true;
- }
- else if (BM_edge_is_boundary(e_clear)) {
- /* same as above but only one triangle */
- BMLoop *l_a;
- BMEdge *e_a_other[2];
+ return true;
+ }
+ else if (BM_edge_is_boundary(e_clear)) {
+ /* same as above but only one triangle */
+ BMLoop *l_a;
+ BMEdge *e_a_other[2];
- l_a = e_clear->l;
+ l_a = e_clear->l;
- BLI_assert(l_a->f->len == 3);
+ BLI_assert(l_a->f->len == 3);
- /* keep 'v_clear' 0th */
- if (BM_vert_in_edge(l_a->prev->e, v_clear)) {
- e_a_other[0] = l_a->prev->e;
- e_a_other[1] = l_a->next->e;
- }
- else {
- e_a_other[1] = l_a->prev->e;
- e_a_other[0] = l_a->next->e;
- }
+ /* keep 'v_clear' 0th */
+ if (BM_vert_in_edge(l_a->prev->e, v_clear)) {
+ e_a_other[0] = l_a->prev->e;
+ e_a_other[1] = l_a->next->e;
+ }
+ else {
+ e_a_other[1] = l_a->prev->e;
+ e_a_other[0] = l_a->next->e;
+ }
- r_e_clear_other[0] = BM_elem_index_get(e_a_other[0]);
- r_e_clear_other[1] = -1;
+ r_e_clear_other[0] = BM_elem_index_get(e_a_other[0]);
+ r_e_clear_other[1] = -1;
#ifdef USE_CUSTOMDATA
- /* before killing, do customdata */
- if (customdata_flag & CD_DO_VERT) {
- BM_data_interp_from_verts(bm, v_other, v_clear, v_other, customdata_fac);
- }
- if (customdata_flag & CD_DO_EDGE) {
- BM_data_interp_from_edges(bm, e_a_other[1], e_a_other[0], e_a_other[1], customdata_fac);
- }
- if (customdata_flag & CD_DO_LOOP) {
- bm_edge_collapse_loop_customdata(bm, e_clear->l, v_clear, v_other, customdata_fac);
- }
+ /* before killing, do customdata */
+ if (customdata_flag & CD_DO_VERT) {
+ BM_data_interp_from_verts(bm, v_other, v_clear, v_other, customdata_fac);
+ }
+ if (customdata_flag & CD_DO_EDGE) {
+ BM_data_interp_from_edges(bm, e_a_other[1], e_a_other[0], e_a_other[1], customdata_fac);
+ }
+ if (customdata_flag & CD_DO_LOOP) {
+ bm_edge_collapse_loop_customdata(bm, e_clear->l, v_clear, v_other, customdata_fac);
+ }
#endif
- BM_edge_kill(bm, e_clear);
+ BM_edge_kill(bm, e_clear);
- v_other->head.hflag |= v_clear->head.hflag;
- BM_vert_splice(bm, v_other, v_clear);
+ v_other->head.hflag |= v_clear->head.hflag;
+ BM_vert_splice(bm, v_other, v_clear);
- e_a_other[1]->head.hflag |= e_a_other[0]->head.hflag;
- BM_edge_splice(bm, e_a_other[1], e_a_other[0]);
+ e_a_other[1]->head.hflag |= e_a_other[0]->head.hflag;
+ BM_edge_splice(bm, e_a_other[1], e_a_other[0]);
#ifdef USE_SYMMETRY
- /* update mirror map */
- if (edge_symmetry_map) {
- if (edge_symmetry_map[r_e_clear_other[0]] != -1) {
- edge_symmetry_map[edge_symmetry_map[r_e_clear_other[0]]] = BM_elem_index_get(e_a_other[1]);
- }
- }
+ /* update mirror map */
+ if (edge_symmetry_map) {
+ if (edge_symmetry_map[r_e_clear_other[0]] != -1) {
+ edge_symmetry_map[edge_symmetry_map[r_e_clear_other[0]]] = BM_elem_index_get(e_a_other[1]);
+ }
+ }
#endif
- // BM_mesh_validate(bm);
+ // BM_mesh_validate(bm);
- return true;
- }
- else {
- return false;
- }
+ return true;
+ }
+ else {
+ return false;
+ }
}
-
/**
* Collapse e the edge, removing e->v2
*
* \return true when the edge was collapsed.
*/
-static bool bm_decim_edge_collapse(
- BMesh *bm, BMEdge *e,
- Quadric *vquadrics,
- float *vweights, const float vweight_factor,
- Heap *eheap, HeapNode **eheap_table,
+static bool bm_decim_edge_collapse(BMesh *bm,
+ BMEdge *e,
+ Quadric *vquadrics,
+ float *vweights,
+ const float vweight_factor,
+ Heap *eheap,
+ HeapNode **eheap_table,
#ifdef USE_SYMMETRY
- int *edge_symmetry_map,
+ int *edge_symmetry_map,
#endif
- const CD_UseFlag customdata_flag,
- float optimize_co[3], bool optimize_co_calc
- )
+ const CD_UseFlag customdata_flag,
+ float optimize_co[3],
+ bool optimize_co_calc)
{
- int e_clear_other[2];
- BMVert *v_other = e->v1;
- const int v_other_index = BM_elem_index_get(e->v1);
- /* the vert is removed so only store the index */
- const int v_clear_index = BM_elem_index_get(e->v2);
- float customdata_fac;
+ int e_clear_other[2];
+ BMVert *v_other = e->v1;
+ const int v_other_index = BM_elem_index_get(e->v1);
+ /* the vert is removed so only store the index */
+ const int v_clear_index = BM_elem_index_get(e->v2);
+ float customdata_fac;
#ifdef USE_VERT_NORMAL_INTERP
- float v_clear_no[3];
- copy_v3_v3(v_clear_no, e->v2->no);
+ float v_clear_no[3];
+ copy_v3_v3(v_clear_no, e->v2->no);
#endif
- /* when false, use without degenerate checks */
- if (optimize_co_calc) {
- /* disallow collapsing which results in degenerate cases */
- if (UNLIKELY(bm_edge_collapse_is_degenerate_topology(e))) {
- /* add back with a high cost */
- bm_decim_invalid_edge_cost_single(e, eheap, eheap_table);
- return false;
- }
-
- bm_decim_calc_target_co_fl(e, optimize_co, vquadrics);
-
- /* check if this would result in an overlapping face */
- if (UNLIKELY(bm_edge_collapse_is_degenerate_flip(e, optimize_co))) {
- /* add back with a high cost */
- bm_decim_invalid_edge_cost_single(e, eheap, eheap_table);
- return false;
- }
- }
-
- /* use for customdata merging */
- if (LIKELY(compare_v3v3(e->v1->co, e->v2->co, FLT_EPSILON) == false)) {
- customdata_fac = line_point_factor_v3(optimize_co, e->v1->co, e->v2->co);
+ /* when false, use without degenerate checks */
+ if (optimize_co_calc) {
+ /* disallow collapsing which results in degenerate cases */
+ if (UNLIKELY(bm_edge_collapse_is_degenerate_topology(e))) {
+ /* add back with a high cost */
+ bm_decim_invalid_edge_cost_single(e, eheap, eheap_table);
+ return false;
+ }
+
+ bm_decim_calc_target_co_fl(e, optimize_co, vquadrics);
+
+ /* check if this would result in an overlapping face */
+ if (UNLIKELY(bm_edge_collapse_is_degenerate_flip(e, optimize_co))) {
+ /* add back with a high cost */
+ bm_decim_invalid_edge_cost_single(e, eheap, eheap_table);
+ return false;
+ }
+ }
+
+ /* use for customdata merging */
+ if (LIKELY(compare_v3v3(e->v1->co, e->v2->co, FLT_EPSILON) == false)) {
+ customdata_fac = line_point_factor_v3(optimize_co, e->v1->co, e->v2->co);
#if 0
- /* simple test for stupid collapse */
- if (customdata_fac < 0.0 - FLT_EPSILON || customdata_fac > 1.0f + FLT_EPSILON) {
- return false;
- }
+ /* simple test for stupid collapse */
+ if (customdata_fac < 0.0 - FLT_EPSILON || customdata_fac > 1.0f + FLT_EPSILON) {
+ return false;
+ }
#endif
- }
- else {
- /* avoid divide by zero */
- customdata_fac = 0.5f;
- }
-
- if (bm_edge_collapse(
- bm, e, e->v2, e_clear_other,
+ }
+ else {
+ /* avoid divide by zero */
+ customdata_fac = 0.5f;
+ }
+
+ if (bm_edge_collapse(bm,
+ e,
+ e->v2,
+ e_clear_other,
#ifdef USE_SYMMETRY
- edge_symmetry_map,
+ edge_symmetry_map,
#endif
- customdata_flag, customdata_fac))
- {
- /* update collapse info */
- int i;
-
- if (vweights) {
- float v_other_weight = interpf(vweights[v_other_index], vweights[v_clear_index], customdata_fac);
- CLAMP(v_other_weight, 0.0f, 1.0f);
- vweights[v_other_index] = v_other_weight;
- }
-
- /* paranoid safety check */
- e = NULL;
-
- copy_v3_v3(v_other->co, optimize_co);
-
- /* remove eheap */
- for (i = 0; i < 2; i++) {
- /* highly unlikely 'eheap_table[ke_other[i]]' would be NULL, but do for sanity sake */
- if ((e_clear_other[i] != -1) && (eheap_table[e_clear_other[i]] != NULL)) {
- BLI_heap_remove(eheap, eheap_table[e_clear_other[i]]);
- eheap_table[e_clear_other[i]] = NULL;
- }
- }
-
- /* update vertex quadric, add kept vertex from killed vertex */
- BLI_quadric_add_qu_qu(&vquadrics[v_other_index], &vquadrics[v_clear_index]);
-
- /* update connected normals */
-
- /* in fact face normals are not used for progressive updates, no need to update them */
- // BM_vert_normal_update_all(v);
+ customdata_flag,
+ customdata_fac)) {
+ /* update collapse info */
+ int i;
+
+ if (vweights) {
+ float v_other_weight = interpf(
+ vweights[v_other_index], vweights[v_clear_index], customdata_fac);
+ CLAMP(v_other_weight, 0.0f, 1.0f);
+ vweights[v_other_index] = v_other_weight;
+ }
+
+ /* paranoid safety check */
+ e = NULL;
+
+ copy_v3_v3(v_other->co, optimize_co);
+
+ /* remove eheap */
+ for (i = 0; i < 2; i++) {
+ /* highly unlikely 'eheap_table[ke_other[i]]' would be NULL, but do for sanity sake */
+ if ((e_clear_other[i] != -1) && (eheap_table[e_clear_other[i]] != NULL)) {
+ BLI_heap_remove(eheap, eheap_table[e_clear_other[i]]);
+ eheap_table[e_clear_other[i]] = NULL;
+ }
+ }
+
+ /* update vertex quadric, add kept vertex from killed vertex */
+ BLI_quadric_add_qu_qu(&vquadrics[v_other_index], &vquadrics[v_clear_index]);
+
+ /* update connected normals */
+
+ /* in fact face normals are not used for progressive updates, no need to update them */
+ // BM_vert_normal_update_all(v);
#ifdef USE_VERT_NORMAL_INTERP
- interp_v3_v3v3(v_other->no, v_other->no, v_clear_no, customdata_fac);
- normalize_v3(v_other->no);
+ interp_v3_v3v3(v_other->no, v_other->no, v_clear_no, customdata_fac);
+ normalize_v3(v_other->no);
#else
- BM_vert_normal_update(v_other);
+ BM_vert_normal_update(v_other);
#endif
-
- /* update error costs and the eheap */
- if (LIKELY(v_other->e)) {
- BMEdge *e_iter;
- BMEdge *e_first;
- e_iter = e_first = v_other->e;
- do {
- BLI_assert(BM_edge_find_double(e_iter) == NULL);
- bm_decim_build_edge_cost_single(e_iter, vquadrics, vweights, vweight_factor, eheap, eheap_table);
- } while ((e_iter = bmesh_disk_edge_next(e_iter, v_other)) != e_first);
- }
-
- /* this block used to be disabled,
- * but enable now since surrounding faces may have been
- * set to COST_INVALID because of a face overlap that no longer occurs */
+ /* update error costs and the eheap */
+ if (LIKELY(v_other->e)) {
+ BMEdge *e_iter;
+ BMEdge *e_first;
+ e_iter = e_first = v_other->e;
+ do {
+ BLI_assert(BM_edge_find_double(e_iter) == NULL);
+ bm_decim_build_edge_cost_single(
+ e_iter, vquadrics, vweights, vweight_factor, eheap, eheap_table);
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v_other)) != e_first);
+ }
+
+ /* this block used to be disabled,
+ * but enable now since surrounding faces may have been
+ * set to COST_INVALID because of a face overlap that no longer occurs */
#if 1
- /* optional, update edges around the vertex face fan */
- {
- BMIter liter;
- BMLoop *l;
- BM_ITER_ELEM (l, &liter, v_other, BM_LOOPS_OF_VERT) {
- if (l->f->len == 3) {
- BMEdge *e_outer;
- if (BM_vert_in_edge(l->prev->e, l->v)) {
- e_outer = l->next->e;
- }
- else {
- e_outer = l->prev->e;
- }
-
- BLI_assert(BM_vert_in_edge(e_outer, l->v) == false);
-
- bm_decim_build_edge_cost_single(e_outer, vquadrics, vweights, vweight_factor, eheap, eheap_table);
- }
- }
- }
- /* end optional update */
- return true;
+ /* optional, update edges around the vertex face fan */
+ {
+ BMIter liter;
+ BMLoop *l;
+ BM_ITER_ELEM (l, &liter, v_other, BM_LOOPS_OF_VERT) {
+ if (l->f->len == 3) {
+ BMEdge *e_outer;
+ if (BM_vert_in_edge(l->prev->e, l->v)) {
+ e_outer = l->next->e;
+ }
+ else {
+ e_outer = l->prev->e;
+ }
+
+ BLI_assert(BM_vert_in_edge(e_outer, l->v) == false);
+
+ bm_decim_build_edge_cost_single(
+ e_outer, vquadrics, vweights, vweight_factor, eheap, eheap_table);
+ }
+ }
+ }
+ /* end optional update */
+ return true;
#endif
- }
- else {
- /* add back with a high cost */
- bm_decim_invalid_edge_cost_single(e, eheap, eheap_table);
- return false;
- }
+ }
+ else {
+ /* add back with a high cost */
+ bm_decim_invalid_edge_cost_single(e, eheap, eheap_table);
+ return false;
+ }
}
-
/* Main Decimate Function
* ********************** */
@@ -1294,233 +1289,251 @@ static bool bm_decim_edge_collapse(
* \param symmetry_axis: Axis of symmetry, -1 to disable mirror decimate.
* \param symmetry_eps: Threshold when matching mirror verts.
*/
-void BM_mesh_decimate_collapse(
- BMesh *bm,
- const float factor,
- float *vweights, float vweight_factor,
- const bool do_triangulate,
- const int symmetry_axis, const float symmetry_eps)
+void BM_mesh_decimate_collapse(BMesh *bm,
+ const float factor,
+ float *vweights,
+ float vweight_factor,
+ const bool do_triangulate,
+ const int symmetry_axis,
+ const float symmetry_eps)
{
- /* edge heap */
- Heap *eheap;
- /* edge index aligned table pointing to the eheap */
- HeapNode **eheap_table;
- /* vert index aligned quadrics */
- Quadric *vquadrics;
- int tot_edge_orig;
- int face_tot_target;
+ /* edge heap */
+ Heap *eheap;
+ /* edge index aligned table pointing to the eheap */
+ HeapNode **eheap_table;
+ /* vert index aligned quadrics */
+ Quadric *vquadrics;
+ int tot_edge_orig;
+ int face_tot_target;
- CD_UseFlag customdata_flag = 0;
+ CD_UseFlag customdata_flag = 0;
#ifdef USE_SYMMETRY
- bool use_symmetry = (symmetry_axis != -1);
- int *edge_symmetry_map;
+ bool use_symmetry = (symmetry_axis != -1);
+ int *edge_symmetry_map;
#endif
#ifdef USE_TRIANGULATE
- int edges_tri_tot = 0;
- /* temp convert quads to triangles */
- bool use_triangulate = bm_decim_triangulate_begin(bm, &edges_tri_tot);
+ int edges_tri_tot = 0;
+ /* temp convert quads to triangles */
+ bool use_triangulate = bm_decim_triangulate_begin(bm, &edges_tri_tot);
#else
- UNUSED_VARS(do_triangulate);
+ UNUSED_VARS(do_triangulate);
#endif
+ /* alloc vars */
+ vquadrics = MEM_callocN(sizeof(Quadric) * bm->totvert, __func__);
+ /* since some edges may be degenerate, we might be over allocing a little here */
+ eheap = BLI_heap_new_ex(bm->totedge);
+ eheap_table = MEM_mallocN(sizeof(HeapNode *) * bm->totedge, __func__);
+ tot_edge_orig = bm->totedge;
- /* alloc vars */
- vquadrics = MEM_callocN(sizeof(Quadric) * bm->totvert, __func__);
- /* since some edges may be degenerate, we might be over allocing a little here */
- eheap = BLI_heap_new_ex(bm->totedge);
- eheap_table = MEM_mallocN(sizeof(HeapNode *) * bm->totedge, __func__);
- tot_edge_orig = bm->totedge;
-
-
- /* build initial edge collapse cost data */
- bm_decim_build_quadrics(bm, vquadrics);
+ /* build initial edge collapse cost data */
+ bm_decim_build_quadrics(bm, vquadrics);
- bm_decim_build_edge_cost(bm, vquadrics, vweights, vweight_factor, eheap, eheap_table);
+ bm_decim_build_edge_cost(bm, vquadrics, vweights, vweight_factor, eheap, eheap_table);
- face_tot_target = bm->totface * factor;
- bm->elem_index_dirty |= BM_ALL;
+ face_tot_target = bm->totface * factor;
+ bm->elem_index_dirty |= BM_ALL;
#ifdef USE_SYMMETRY
- edge_symmetry_map = (use_symmetry) ? bm_edge_symmetry_map(bm, symmetry_axis, symmetry_eps) : NULL;
+ edge_symmetry_map = (use_symmetry) ? bm_edge_symmetry_map(bm, symmetry_axis, symmetry_eps) :
+ NULL;
#else
- UNUSED_VARS(symmetry_axis, symmetry_eps);
+ UNUSED_VARS(symmetry_axis, symmetry_eps);
#endif
#ifdef USE_CUSTOMDATA
- /* initialize customdata flag, we only need math for loops */
- if (CustomData_has_interp(&bm->vdata)) { customdata_flag |= CD_DO_VERT; }
- if (CustomData_has_interp(&bm->edata)) { customdata_flag |= CD_DO_EDGE; }
- if (CustomData_has_math(&bm->ldata)) { customdata_flag |= CD_DO_LOOP; }
+ /* initialize customdata flag, we only need math for loops */
+ if (CustomData_has_interp(&bm->vdata)) {
+ customdata_flag |= CD_DO_VERT;
+ }
+ if (CustomData_has_interp(&bm->edata)) {
+ customdata_flag |= CD_DO_EDGE;
+ }
+ if (CustomData_has_math(&bm->ldata)) {
+ customdata_flag |= CD_DO_LOOP;
+ }
#endif
- /* iterative edge collapse and maintain the eheap */
+ /* iterative edge collapse and maintain the eheap */
#ifdef USE_SYMMETRY
- if (use_symmetry == false)
+ if (use_symmetry == false)
#endif
- {
- /* simple non-mirror case */
- while ((bm->totface > face_tot_target) &&
- (BLI_heap_is_empty(eheap) == false) &&
- (BLI_heap_top_value(eheap) != COST_INVALID))
- {
- // const float value = BLI_heap_node_value(BLI_heap_top(eheap));
- BMEdge *e = BLI_heap_pop_min(eheap);
- float optimize_co[3];
- /* handy to detect corruptions elsewhere */
- BLI_assert(BM_elem_index_get(e) < tot_edge_orig);
-
- /* under normal conditions wont be accessed again,
- * but NULL just incase so we don't use freed node */
- eheap_table[BM_elem_index_get(e)] = NULL;
-
- bm_decim_edge_collapse(
- bm, e, vquadrics, vweights, vweight_factor, eheap, eheap_table,
+ {
+ /* simple non-mirror case */
+ while ((bm->totface > face_tot_target) && (BLI_heap_is_empty(eheap) == false) &&
+ (BLI_heap_top_value(eheap) != COST_INVALID)) {
+ // const float value = BLI_heap_node_value(BLI_heap_top(eheap));
+ BMEdge *e = BLI_heap_pop_min(eheap);
+ float optimize_co[3];
+ /* handy to detect corruptions elsewhere */
+ BLI_assert(BM_elem_index_get(e) < tot_edge_orig);
+
+ /* under normal conditions wont be accessed again,
+ * but NULL just incase so we don't use freed node */
+ eheap_table[BM_elem_index_get(e)] = NULL;
+
+ bm_decim_edge_collapse(bm,
+ e,
+ vquadrics,
+ vweights,
+ vweight_factor,
+ eheap,
+ eheap_table,
#ifdef USE_SYMMETRY
- edge_symmetry_map,
+ edge_symmetry_map,
#endif
- customdata_flag,
- optimize_co, true
- );
- }
- }
+ customdata_flag,
+ optimize_co,
+ true);
+ }
+ }
#ifdef USE_SYMMETRY
- else {
- while ((bm->totface > face_tot_target) &&
- (BLI_heap_is_empty(eheap) == false) &&
- (BLI_heap_top_value(eheap) != COST_INVALID))
- {
- /**
- * \note
- * - `eheap_table[e_index_mirr]` is only removed from the heap at the last moment
- * since its possible (in theory) for collapsing `e` to remove `e_mirr`.
- * - edges sharing a vertex are ignored, so the pivot vertex isnt moved to one side.
- */
-
- BMEdge *e = BLI_heap_pop_min(eheap);
- const int e_index = BM_elem_index_get(e);
- const int e_index_mirr = edge_symmetry_map[e_index];
- BMEdge *e_mirr = NULL;
- float optimize_co[3];
- char e_invalidate = 0;
-
- BLI_assert(e_index < tot_edge_orig);
-
- eheap_table[e_index] = NULL;
-
- if (e_index_mirr != -1) {
- if (e_index_mirr == e_index) {
- /* pass */
- }
- else if (eheap_table[e_index_mirr]) {
- e_mirr = BLI_heap_node_ptr(eheap_table[e_index_mirr]);
- /* for now ignore edges with a shared vertex */
- if (BM_edge_share_vert_check(e, e_mirr)) {
- /* ignore permanently!
- * Otherwise we would keep re-evaluating and attempting to collapse. */
- // e_invalidate |= (1 | 2);
- goto invalidate;
- }
- }
- else {
- /* mirror edge can't be operated on (happens with asymmetrical meshes) */
- e_invalidate |= 1;
- goto invalidate;
- }
- }
-
- /* when false, use without degenerate checks */
- {
- /* run both before checking (since they invalidate surrounding geometry) */
- bool ok_a, ok_b;
-
- ok_a = !bm_edge_collapse_is_degenerate_topology(e);
- ok_b = e_mirr ? !bm_edge_collapse_is_degenerate_topology(e_mirr) : true;
-
- /* disallow collapsing which results in degenerate cases */
-
- if (UNLIKELY(!ok_a || !ok_b)) {
- e_invalidate |= (1 | (e_mirr ? 2 : 0));
- goto invalidate;
- }
-
- bm_decim_calc_target_co_fl(e, optimize_co, vquadrics);
-
- if (e_index_mirr == e_index) {
- optimize_co[symmetry_axis] = 0.0f;
- }
-
- /* check if this would result in an overlapping face */
- if (UNLIKELY(bm_edge_collapse_is_degenerate_flip(e, optimize_co))) {
- e_invalidate |= (1 | (e_mirr ? 2 : 0));
- goto invalidate;
- }
- }
-
- if (bm_decim_edge_collapse(
- bm, e, vquadrics, vweights, vweight_factor, eheap, eheap_table,
- edge_symmetry_map,
- customdata_flag,
- optimize_co, false))
- {
- if (e_mirr && (eheap_table[e_index_mirr])) {
- BLI_assert(e_index_mirr != e_index);
- BLI_heap_remove(eheap, eheap_table[e_index_mirr]);
- eheap_table[e_index_mirr] = NULL;
- optimize_co[symmetry_axis] *= -1.0f;
- bm_decim_edge_collapse(
- bm, e_mirr, vquadrics, vweights, vweight_factor, eheap, eheap_table,
- edge_symmetry_map,
- customdata_flag,
- optimize_co, false);
- }
- }
- else {
- if (e_mirr && (eheap_table[e_index_mirr])) {
- e_invalidate |= 2;
- goto invalidate;
- }
- }
-
- BLI_assert(e_invalidate == 0);
- continue;
-
-invalidate:
- if (e_invalidate & 1) {
- bm_decim_invalid_edge_cost_single(e, eheap, eheap_table);
- }
-
- if (e_invalidate & 2) {
- BLI_assert(eheap_table[e_index_mirr] != NULL);
- BLI_heap_remove(eheap, eheap_table[e_index_mirr]);
- eheap_table[e_index_mirr] = NULL;
- bm_decim_invalid_edge_cost_single(e_mirr, eheap, eheap_table);
- }
- }
-
- MEM_freeN((void *)edge_symmetry_map);
- }
-#endif /* USE_SYMMETRY */
+ else {
+ while ((bm->totface > face_tot_target) && (BLI_heap_is_empty(eheap) == false) &&
+ (BLI_heap_top_value(eheap) != COST_INVALID)) {
+ /**
+ * \note
+ * - `eheap_table[e_index_mirr]` is only removed from the heap at the last moment
+ * since its possible (in theory) for collapsing `e` to remove `e_mirr`.
+ * - edges sharing a vertex are ignored, so the pivot vertex isnt moved to one side.
+ */
+
+ BMEdge *e = BLI_heap_pop_min(eheap);
+ const int e_index = BM_elem_index_get(e);
+ const int e_index_mirr = edge_symmetry_map[e_index];
+ BMEdge *e_mirr = NULL;
+ float optimize_co[3];
+ char e_invalidate = 0;
+
+ BLI_assert(e_index < tot_edge_orig);
+
+ eheap_table[e_index] = NULL;
+
+ if (e_index_mirr != -1) {
+ if (e_index_mirr == e_index) {
+ /* pass */
+ }
+ else if (eheap_table[e_index_mirr]) {
+ e_mirr = BLI_heap_node_ptr(eheap_table[e_index_mirr]);
+ /* for now ignore edges with a shared vertex */
+ if (BM_edge_share_vert_check(e, e_mirr)) {
+ /* ignore permanently!
+ * Otherwise we would keep re-evaluating and attempting to collapse. */
+ // e_invalidate |= (1 | 2);
+ goto invalidate;
+ }
+ }
+ else {
+ /* mirror edge can't be operated on (happens with asymmetrical meshes) */
+ e_invalidate |= 1;
+ goto invalidate;
+ }
+ }
+
+ /* when false, use without degenerate checks */
+ {
+ /* run both before checking (since they invalidate surrounding geometry) */
+ bool ok_a, ok_b;
+
+ ok_a = !bm_edge_collapse_is_degenerate_topology(e);
+ ok_b = e_mirr ? !bm_edge_collapse_is_degenerate_topology(e_mirr) : true;
+
+ /* disallow collapsing which results in degenerate cases */
+
+ if (UNLIKELY(!ok_a || !ok_b)) {
+ e_invalidate |= (1 | (e_mirr ? 2 : 0));
+ goto invalidate;
+ }
+
+ bm_decim_calc_target_co_fl(e, optimize_co, vquadrics);
+
+ if (e_index_mirr == e_index) {
+ optimize_co[symmetry_axis] = 0.0f;
+ }
+
+ /* check if this would result in an overlapping face */
+ if (UNLIKELY(bm_edge_collapse_is_degenerate_flip(e, optimize_co))) {
+ e_invalidate |= (1 | (e_mirr ? 2 : 0));
+ goto invalidate;
+ }
+ }
+
+ if (bm_decim_edge_collapse(bm,
+ e,
+ vquadrics,
+ vweights,
+ vweight_factor,
+ eheap,
+ eheap_table,
+ edge_symmetry_map,
+ customdata_flag,
+ optimize_co,
+ false)) {
+ if (e_mirr && (eheap_table[e_index_mirr])) {
+ BLI_assert(e_index_mirr != e_index);
+ BLI_heap_remove(eheap, eheap_table[e_index_mirr]);
+ eheap_table[e_index_mirr] = NULL;
+ optimize_co[symmetry_axis] *= -1.0f;
+ bm_decim_edge_collapse(bm,
+ e_mirr,
+ vquadrics,
+ vweights,
+ vweight_factor,
+ eheap,
+ eheap_table,
+ edge_symmetry_map,
+ customdata_flag,
+ optimize_co,
+ false);
+ }
+ }
+ else {
+ if (e_mirr && (eheap_table[e_index_mirr])) {
+ e_invalidate |= 2;
+ goto invalidate;
+ }
+ }
+
+ BLI_assert(e_invalidate == 0);
+ continue;
+
+ invalidate:
+ if (e_invalidate & 1) {
+ bm_decim_invalid_edge_cost_single(e, eheap, eheap_table);
+ }
+
+ if (e_invalidate & 2) {
+ BLI_assert(eheap_table[e_index_mirr] != NULL);
+ BLI_heap_remove(eheap, eheap_table[e_index_mirr]);
+ eheap_table[e_index_mirr] = NULL;
+ bm_decim_invalid_edge_cost_single(e_mirr, eheap, eheap_table);
+ }
+ }
+
+ MEM_freeN((void *)edge_symmetry_map);
+ }
+#endif /* USE_SYMMETRY */
#ifdef USE_TRIANGULATE
- if (do_triangulate == false) {
- /* its possible we only had triangles, skip this step in that case */
- if (LIKELY(use_triangulate)) {
- /* temp convert quads to triangles */
- bm_decim_triangulate_end(bm, edges_tri_tot);
- }
- }
+ if (do_triangulate == false) {
+ /* its possible we only had triangles, skip this step in that case */
+ if (LIKELY(use_triangulate)) {
+ /* temp convert quads to triangles */
+ bm_decim_triangulate_end(bm, edges_tri_tot);
+ }
+ }
#endif
- /* free vars */
- MEM_freeN(vquadrics);
- MEM_freeN(eheap_table);
- BLI_heap_free(eheap, NULL);
+ /* free vars */
+ MEM_freeN(vquadrics);
+ MEM_freeN(eheap_table);
+ BLI_heap_free(eheap, NULL);
- /* testing only */
- // BM_mesh_validate(bm);
+ /* testing only */
+ // BM_mesh_validate(bm);
- /* quiet release build warning */
- (void)tot_edge_orig;
+ /* quiet release build warning */
+ (void)tot_edge_orig;
}
diff --git a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c
index 6069175348c..0fbb2d14766 100644
--- a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c
+++ b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c
@@ -20,7 +20,6 @@
* BMesh decimator that dissolves flat areas into polygons (ngons).
*/
-
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
@@ -29,14 +28,13 @@
#include "BKE_customdata.h"
#include "bmesh.h"
-#include "bmesh_decimate.h" /* own include */
+#include "bmesh_decimate.h" /* own include */
/* check that collapsing a vertex between 2 edges doesn't cause a degenerate face. */
#define USE_DEGENERATE_CHECK
#define COST_INVALID FLT_MAX
-
/* multiply vertex edge angle by face angle
* this means we are not left with sharp corners between _almost_ planer faces
* convert angles [0-PI/2] -> [0-1], multiply together, then convert back to radians. */
@@ -45,492 +43,477 @@ static float bm_vert_edge_face_angle(BMVert *v)
#define UNIT_TO_ANGLE DEG2RADF(90.0f)
#define ANGLE_TO_UNIT (1.0f / UNIT_TO_ANGLE)
- const float angle = BM_vert_calc_edge_angle(v);
- /* note: could be either edge, it doesn't matter */
- if (v->e && BM_edge_is_manifold(v->e)) {
- return ((angle * ANGLE_TO_UNIT) * (BM_edge_calc_face_angle(v->e) * ANGLE_TO_UNIT)) * UNIT_TO_ANGLE;
- }
- else {
- return angle;
- }
+ const float angle = BM_vert_calc_edge_angle(v);
+ /* note: could be either edge, it doesn't matter */
+ if (v->e && BM_edge_is_manifold(v->e)) {
+ return ((angle * ANGLE_TO_UNIT) * (BM_edge_calc_face_angle(v->e) * ANGLE_TO_UNIT)) *
+ UNIT_TO_ANGLE;
+ }
+ else {
+ return angle;
+ }
#undef UNIT_TO_ANGLE
#undef ANGLE_TO_UNIT
}
struct DelimitData {
- int cd_loop_type;
- int cd_loop_size;
- int cd_loop_offset;
- int cd_loop_offset_end;
+ int cd_loop_type;
+ int cd_loop_size;
+ int cd_loop_offset;
+ int cd_loop_offset_end;
};
-static bool bm_edge_is_contiguous_loop_cd_all(
- const BMEdge *e, const struct DelimitData *delimit_data)
+static bool bm_edge_is_contiguous_loop_cd_all(const BMEdge *e,
+ const struct DelimitData *delimit_data)
{
- int cd_loop_offset;
- for (cd_loop_offset = delimit_data->cd_loop_offset;
- cd_loop_offset < delimit_data->cd_loop_offset_end;
- cd_loop_offset += delimit_data->cd_loop_size)
- {
- if (BM_edge_is_contiguous_loop_cd(e, delimit_data->cd_loop_type, cd_loop_offset) == false) {
- return false;
- }
- }
-
- return true;
+ int cd_loop_offset;
+ for (cd_loop_offset = delimit_data->cd_loop_offset;
+ cd_loop_offset < delimit_data->cd_loop_offset_end;
+ cd_loop_offset += delimit_data->cd_loop_size) {
+ if (BM_edge_is_contiguous_loop_cd(e, delimit_data->cd_loop_type, cd_loop_offset) == false) {
+ return false;
+ }
+ }
+
+ return true;
}
-static float bm_edge_calc_dissolve_error(
- const BMEdge *e, const BMO_Delimit delimit,
- const struct DelimitData *delimit_data)
+static float bm_edge_calc_dissolve_error(const BMEdge *e,
+ const BMO_Delimit delimit,
+ const struct DelimitData *delimit_data)
{
- if (!BM_edge_is_manifold(e)) {
- goto fail;
- }
-
- if ((delimit & BMO_DELIM_SEAM) &&
- (BM_elem_flag_test(e, BM_ELEM_SEAM)))
- {
- goto fail;
- }
-
- if ((delimit & BMO_DELIM_SHARP) &&
- (BM_elem_flag_test(e, BM_ELEM_SMOOTH) == 0))
- {
- goto fail;
- }
-
- if ((delimit & BMO_DELIM_MATERIAL) &&
- (e->l->f->mat_nr != e->l->radial_next->f->mat_nr))
- {
- goto fail;
- }
-
- const bool is_contig = BM_edge_is_contiguous(e);
-
- if ((delimit & BMO_DELIM_NORMAL) &&
- (is_contig == false))
- {
- goto fail;
- }
-
- if ((delimit & BMO_DELIM_UV) &&
- (bm_edge_is_contiguous_loop_cd_all(e, delimit_data) == 0))
- {
- goto fail;
- }
-
- float angle_cos_neg = dot_v3v3(e->l->f->no, e->l->radial_next->f->no);
- if (is_contig) {
- angle_cos_neg *= -1;
- }
-
- return angle_cos_neg;
+ if (!BM_edge_is_manifold(e)) {
+ goto fail;
+ }
+
+ if ((delimit & BMO_DELIM_SEAM) && (BM_elem_flag_test(e, BM_ELEM_SEAM))) {
+ goto fail;
+ }
+
+ if ((delimit & BMO_DELIM_SHARP) && (BM_elem_flag_test(e, BM_ELEM_SMOOTH) == 0)) {
+ goto fail;
+ }
+
+ if ((delimit & BMO_DELIM_MATERIAL) && (e->l->f->mat_nr != e->l->radial_next->f->mat_nr)) {
+ goto fail;
+ }
+
+ const bool is_contig = BM_edge_is_contiguous(e);
+
+ if ((delimit & BMO_DELIM_NORMAL) && (is_contig == false)) {
+ goto fail;
+ }
+
+ if ((delimit & BMO_DELIM_UV) && (bm_edge_is_contiguous_loop_cd_all(e, delimit_data) == 0)) {
+ goto fail;
+ }
+
+ float angle_cos_neg = dot_v3v3(e->l->f->no, e->l->radial_next->f->no);
+ if (is_contig) {
+ angle_cos_neg *= -1;
+ }
+
+ return angle_cos_neg;
fail:
- return COST_INVALID;
+ return COST_INVALID;
}
-
#ifdef USE_DEGENERATE_CHECK
static void mul_v2_m3v3_center(float r[2], float m[3][3], const float a[3], const float center[3])
{
- BLI_assert(r != a);
- BLI_assert(r != center);
+ BLI_assert(r != a);
+ BLI_assert(r != center);
- float co[3];
- sub_v3_v3v3(co, a, center);
+ float co[3];
+ sub_v3_v3v3(co, a, center);
- r[0] = m[0][0] * co[0] + m[1][0] * co[1] + m[2][0] * co[2];
- r[1] = m[0][1] * co[0] + m[1][1] * co[1] + m[2][1] * co[2];
+ r[0] = m[0][0] * co[0] + m[1][0] * co[1] + m[2][0] * co[2];
+ r[1] = m[0][1] * co[0] + m[1][1] * co[1] + m[2][1] * co[2];
}
static bool bm_loop_collapse_is_degenerate(BMLoop *l_ear)
{
- /* calculate relative to the centeral vertex for higher precision */
- const float *center = l_ear->v->co;
-
- float tri_2d[3][2];
- float axis_mat[3][3];
-
- axis_dominant_v3_to_m3(axis_mat, l_ear->f->no);
-
- {
- mul_v2_m3v3_center(tri_2d[0], axis_mat, l_ear->prev->v->co, center);
-#if 0
- mul_v2_m3v3_center(tri_2d[1], axis_mat, l_ear->v->co, center);
-#else
- zero_v2(tri_2d[1]);
-#endif
- mul_v2_m3v3_center(tri_2d[2], axis_mat, l_ear->next->v->co, center);
- }
-
- /* check we're not flipping face corners before or after the ear */
- {
- float adjacent_2d[2];
-
- if (!BM_vert_is_edge_pair(l_ear->prev->v)) {
- mul_v2_m3v3_center(adjacent_2d, axis_mat, l_ear->prev->prev->v->co, center);
- if (signum_i(cross_tri_v2(adjacent_2d, tri_2d[0], tri_2d[1])) !=
- signum_i(cross_tri_v2(adjacent_2d, tri_2d[0], tri_2d[2])))
- {
- return true;
- }
- }
-
- if (!BM_vert_is_edge_pair(l_ear->next->v)) {
- mul_v2_m3v3_center(adjacent_2d, axis_mat, l_ear->next->next->v->co, center);
- if (signum_i(cross_tri_v2(adjacent_2d, tri_2d[2], tri_2d[1])) !=
- signum_i(cross_tri_v2(adjacent_2d, tri_2d[2], tri_2d[0])))
- {
- return true;
- }
- }
- }
-
- /* check no existing verts are inside the triangle */
- {
- /* triangle may be concave, if so - flip so we can use clockwise check */
- if (cross_tri_v2(UNPACK3(tri_2d)) < 0.0f) {
- swap_v2_v2(tri_2d[1], tri_2d[2]);
- }
-
- /* skip l_ear and adjacent verts */
- BMLoop *l_iter, *l_first;
-
- l_iter = l_ear->next->next;
- l_first = l_ear->prev;
- do {
- float co_2d[2];
- mul_v2_m3v3_center(co_2d, axis_mat, l_iter->v->co, center);
- if (isect_point_tri_v2_cw(co_2d, tri_2d[0], tri_2d[1], tri_2d[2])) {
- return true;
- }
- } while ((l_iter = l_iter->next) != l_first);
- }
-
- return false;
+ /* calculate relative to the centeral vertex for higher precision */
+ const float *center = l_ear->v->co;
+
+ float tri_2d[3][2];
+ float axis_mat[3][3];
+
+ axis_dominant_v3_to_m3(axis_mat, l_ear->f->no);
+
+ {
+ mul_v2_m3v3_center(tri_2d[0], axis_mat, l_ear->prev->v->co, center);
+# if 0
+ mul_v2_m3v3_center(tri_2d[1], axis_mat, l_ear->v->co, center);
+# else
+ zero_v2(tri_2d[1]);
+# endif
+ mul_v2_m3v3_center(tri_2d[2], axis_mat, l_ear->next->v->co, center);
+ }
+
+ /* check we're not flipping face corners before or after the ear */
+ {
+ float adjacent_2d[2];
+
+ if (!BM_vert_is_edge_pair(l_ear->prev->v)) {
+ mul_v2_m3v3_center(adjacent_2d, axis_mat, l_ear->prev->prev->v->co, center);
+ if (signum_i(cross_tri_v2(adjacent_2d, tri_2d[0], tri_2d[1])) !=
+ signum_i(cross_tri_v2(adjacent_2d, tri_2d[0], tri_2d[2]))) {
+ return true;
+ }
+ }
+
+ if (!BM_vert_is_edge_pair(l_ear->next->v)) {
+ mul_v2_m3v3_center(adjacent_2d, axis_mat, l_ear->next->next->v->co, center);
+ if (signum_i(cross_tri_v2(adjacent_2d, tri_2d[2], tri_2d[1])) !=
+ signum_i(cross_tri_v2(adjacent_2d, tri_2d[2], tri_2d[0]))) {
+ return true;
+ }
+ }
+ }
+
+ /* check no existing verts are inside the triangle */
+ {
+ /* triangle may be concave, if so - flip so we can use clockwise check */
+ if (cross_tri_v2(UNPACK3(tri_2d)) < 0.0f) {
+ swap_v2_v2(tri_2d[1], tri_2d[2]);
+ }
+
+ /* skip l_ear and adjacent verts */
+ BMLoop *l_iter, *l_first;
+
+ l_iter = l_ear->next->next;
+ l_first = l_ear->prev;
+ do {
+ float co_2d[2];
+ mul_v2_m3v3_center(co_2d, axis_mat, l_iter->v->co, center);
+ if (isect_point_tri_v2_cw(co_2d, tri_2d[0], tri_2d[1], tri_2d[2])) {
+ return true;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+
+ return false;
}
-static bool bm_vert_collapse_is_degenerate(BMVert *v)
+static bool bm_vert_collapse_is_degenerate(BMVert *v)
{
- BMEdge *e_pair[2];
- BMVert *v_pair[2];
-
- if (BM_vert_edge_pair(v, &e_pair[0], &e_pair[1])) {
-
- /* allow wire edges */
- if (BM_edge_is_wire(e_pair[0]) || BM_edge_is_wire(e_pair[1])) {
- return false;
- }
-
- v_pair[0] = BM_edge_other_vert(e_pair[0], v);
- v_pair[1] = BM_edge_other_vert(e_pair[1], v);
-
- if (fabsf(cos_v3v3v3(v_pair[0]->co, v->co, v_pair[1]->co)) < (1.0f - FLT_EPSILON)) {
- BMLoop *l_iter, *l_first;
- l_iter = l_first = e_pair[1]->l;
- do {
- if (l_iter->f->len > 3) {
- BMLoop *l_pivot = (l_iter->v == v ? l_iter : l_iter->next);
- BLI_assert(v == l_pivot->v);
- if (bm_loop_collapse_is_degenerate(l_pivot)) {
- return true;
- }
- }
- } while ((l_iter = l_iter->radial_next) != l_first);
- }
- return false;
- }
- else {
- return true;
- }
+ BMEdge *e_pair[2];
+ BMVert *v_pair[2];
+
+ if (BM_vert_edge_pair(v, &e_pair[0], &e_pair[1])) {
+
+ /* allow wire edges */
+ if (BM_edge_is_wire(e_pair[0]) || BM_edge_is_wire(e_pair[1])) {
+ return false;
+ }
+
+ v_pair[0] = BM_edge_other_vert(e_pair[0], v);
+ v_pair[1] = BM_edge_other_vert(e_pair[1], v);
+
+ if (fabsf(cos_v3v3v3(v_pair[0]->co, v->co, v_pair[1]->co)) < (1.0f - FLT_EPSILON)) {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = e_pair[1]->l;
+ do {
+ if (l_iter->f->len > 3) {
+ BMLoop *l_pivot = (l_iter->v == v ? l_iter : l_iter->next);
+ BLI_assert(v == l_pivot->v);
+ if (bm_loop_collapse_is_degenerate(l_pivot)) {
+ return true;
+ }
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+ return false;
+ }
+ else {
+ return true;
+ }
}
-#endif /* USE_DEGENERATE_CHECK */
-
-
-void BM_mesh_decimate_dissolve_ex(
- BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries,
- BMO_Delimit delimit,
- BMVert **vinput_arr, const int vinput_len,
- BMEdge **einput_arr, const int einput_len,
- const short oflag_out)
+#endif /* USE_DEGENERATE_CHECK */
+
+void BM_mesh_decimate_dissolve_ex(BMesh *bm,
+ const float angle_limit,
+ const bool do_dissolve_boundaries,
+ BMO_Delimit delimit,
+ BMVert **vinput_arr,
+ const int vinput_len,
+ BMEdge **einput_arr,
+ const int einput_len,
+ const short oflag_out)
{
- const float angle_limit_cos_neg = -cosf(angle_limit);
- struct DelimitData delimit_data = {0};
- const int eheap_table_len = do_dissolve_boundaries ? einput_len : max_ii(einput_len, vinput_len);
- void *_heap_table = MEM_mallocN(sizeof(HeapNode *) * eheap_table_len, __func__);
-
- int i;
-
- if (delimit & BMO_DELIM_UV) {
- const int layer_len = CustomData_number_of_layers(&bm->ldata, CD_MLOOPUV);
- if (layer_len == 0) {
- delimit &= ~BMO_DELIM_UV;
- }
- else {
- delimit_data.cd_loop_type = CD_MLOOPUV;
- delimit_data.cd_loop_size = CustomData_sizeof(delimit_data.cd_loop_type);
- delimit_data.cd_loop_offset = CustomData_get_n_offset(&bm->ldata, CD_MLOOPUV, 0);
- delimit_data.cd_loop_offset_end = delimit_data.cd_loop_size * layer_len;
- }
- }
-
- /* --- first edges --- */
- if (1) {
- BMEdge **earray;
- Heap *eheap;
- HeapNode **eheap_table = _heap_table;
- HeapNode *enode_top;
- int *vert_reverse_lookup;
- BMIter iter;
- BMEdge *e_iter;
-
- /* --- setup heap --- */
- eheap = BLI_heap_new_ex(einput_len);
-
- /* wire -> tag */
- BM_ITER_MESH (e_iter, &iter, bm, BM_EDGES_OF_MESH) {
- BM_elem_flag_set(e_iter, BM_ELEM_TAG, BM_edge_is_wire(e_iter));
- BM_elem_index_set(e_iter, -1); /* set dirty */
- }
- bm->elem_index_dirty |= BM_EDGE;
-
- /* build heap */
- for (i = 0; i < einput_len; i++) {
- BMEdge *e = einput_arr[i];
- const float cost = bm_edge_calc_dissolve_error(e, delimit, &delimit_data);
- eheap_table[i] = BLI_heap_insert(eheap, cost, e);
- BM_elem_index_set(e, i); /* set dirty */
- }
-
- while ((BLI_heap_is_empty(eheap) == false) &&
- (BLI_heap_node_value((enode_top = BLI_heap_top(eheap))) < angle_limit_cos_neg))
- {
- BMFace *f_new = NULL;
- BMEdge *e;
-
- e = BLI_heap_node_ptr(enode_top);
- i = BM_elem_index_get(e);
-
- if (BM_edge_is_manifold(e)) {
- f_new = BM_faces_join_pair(bm, e->l, e->l->radial_next, false);
-
- if (f_new) {
- BMLoop *l_first, *l_iter;
-
- BLI_heap_remove(eheap, enode_top);
- eheap_table[i] = NULL;
-
- /* update normal */
- BM_face_normal_update(f_new);
- if (oflag_out) {
- BMO_face_flag_enable(bm, f_new, oflag_out);
- }
-
- /* re-calculate costs */
- l_iter = l_first = BM_FACE_FIRST_LOOP(f_new);
- do {
- const int j = BM_elem_index_get(l_iter->e);
- if (j != -1 && eheap_table[j]) {
- const float cost = bm_edge_calc_dissolve_error(l_iter->e, delimit, &delimit_data);
- BLI_heap_node_value_update(eheap, eheap_table[j], cost);
- }
- } while ((l_iter = l_iter->next) != l_first);
- }
- else {
- BMO_error_clear(bm);
- }
- }
-
- if (UNLIKELY(f_new == NULL)) {
- BLI_heap_node_value_update(eheap, enode_top, COST_INVALID);
- }
- }
-
- /* prepare for cleanup */
- BM_mesh_elem_index_ensure(bm, BM_VERT);
- vert_reverse_lookup = MEM_mallocN(sizeof(int) * bm->totvert, __func__);
- copy_vn_i(vert_reverse_lookup, bm->totvert, -1);
- for (i = 0; i < vinput_len; i++) {
- BMVert *v = vinput_arr[i];
- vert_reverse_lookup[BM_elem_index_get(v)] = i;
- }
-
- /* --- cleanup --- */
- earray = MEM_mallocN(sizeof(BMEdge *) * bm->totedge, __func__);
- BM_ITER_MESH_INDEX (e_iter, &iter, bm, BM_EDGES_OF_MESH, i) {
- earray[i] = e_iter;
- }
- /* remove all edges/verts left behind from dissolving, NULL'ing the vertex array so we dont re-use */
- for (i = bm->totedge - 1; i != -1; i--) {
- e_iter = earray[i];
-
- if (BM_edge_is_wire(e_iter) && (BM_elem_flag_test(e_iter, BM_ELEM_TAG) == false)) {
- /* edge has become wire */
- int vidx_reverse;
- BMVert *v1 = e_iter->v1;
- BMVert *v2 = e_iter->v2;
- BM_edge_kill(bm, e_iter);
- if (v1->e == NULL) {
- vidx_reverse = vert_reverse_lookup[BM_elem_index_get(v1)];
- if (vidx_reverse != -1) {
- vinput_arr[vidx_reverse] = NULL;
- }
- BM_vert_kill(bm, v1);
- }
- if (v2->e == NULL) {
- vidx_reverse = vert_reverse_lookup[BM_elem_index_get(v2)];
- if (vidx_reverse != -1) {
- vinput_arr[vidx_reverse] = NULL;
- }
- BM_vert_kill(bm, v2);
- }
- }
- }
- MEM_freeN(vert_reverse_lookup);
- MEM_freeN(earray);
-
- BLI_heap_free(eheap, NULL);
- }
-
-
- /* --- second verts --- */
- if (do_dissolve_boundaries) {
- /* simple version of the branch below, since we will dissolve _all_ verts that use 2 edges */
- for (i = 0; i < vinput_len; i++) {
- BMVert *v = vinput_arr[i];
- if (LIKELY(v != NULL) &&
- BM_vert_is_edge_pair(v))
- {
- BM_vert_collapse_edge(bm, v->e, v, true, true); /* join edges */
- }
- }
- }
- else {
- Heap *vheap;
- HeapNode **vheap_table = _heap_table;
- HeapNode *vnode_top;
-
- BMVert *v_iter;
- BMIter iter;
-
- BM_ITER_MESH (v_iter, &iter, bm, BM_VERTS_OF_MESH) {
- BM_elem_index_set(v_iter, -1); /* set dirty */
- }
- bm->elem_index_dirty |= BM_VERT;
-
- vheap = BLI_heap_new_ex(vinput_len);
-
- for (i = 0; i < vinput_len; i++) {
- BMVert *v = vinput_arr[i];
- if (LIKELY(v != NULL)) {
- const float cost = bm_vert_edge_face_angle(v);
- vheap_table[i] = BLI_heap_insert(vheap, cost, v);
- BM_elem_index_set(v, i); /* set dirty */
- }
- }
-
- while ((BLI_heap_is_empty(vheap) == false) &&
- (BLI_heap_node_value((vnode_top = BLI_heap_top(vheap))) < angle_limit))
- {
- BMEdge *e_new = NULL;
- BMVert *v;
-
- v = BLI_heap_node_ptr(vnode_top);
- i = BM_elem_index_get(v);
-
- if (
+ const float angle_limit_cos_neg = -cosf(angle_limit);
+ struct DelimitData delimit_data = {0};
+ const int eheap_table_len = do_dissolve_boundaries ? einput_len : max_ii(einput_len, vinput_len);
+ void *_heap_table = MEM_mallocN(sizeof(HeapNode *) * eheap_table_len, __func__);
+
+ int i;
+
+ if (delimit & BMO_DELIM_UV) {
+ const int layer_len = CustomData_number_of_layers(&bm->ldata, CD_MLOOPUV);
+ if (layer_len == 0) {
+ delimit &= ~BMO_DELIM_UV;
+ }
+ else {
+ delimit_data.cd_loop_type = CD_MLOOPUV;
+ delimit_data.cd_loop_size = CustomData_sizeof(delimit_data.cd_loop_type);
+ delimit_data.cd_loop_offset = CustomData_get_n_offset(&bm->ldata, CD_MLOOPUV, 0);
+ delimit_data.cd_loop_offset_end = delimit_data.cd_loop_size * layer_len;
+ }
+ }
+
+ /* --- first edges --- */
+ if (1) {
+ BMEdge **earray;
+ Heap *eheap;
+ HeapNode **eheap_table = _heap_table;
+ HeapNode *enode_top;
+ int *vert_reverse_lookup;
+ BMIter iter;
+ BMEdge *e_iter;
+
+ /* --- setup heap --- */
+ eheap = BLI_heap_new_ex(einput_len);
+
+ /* wire -> tag */
+ BM_ITER_MESH (e_iter, &iter, bm, BM_EDGES_OF_MESH) {
+ BM_elem_flag_set(e_iter, BM_ELEM_TAG, BM_edge_is_wire(e_iter));
+ BM_elem_index_set(e_iter, -1); /* set dirty */
+ }
+ bm->elem_index_dirty |= BM_EDGE;
+
+ /* build heap */
+ for (i = 0; i < einput_len; i++) {
+ BMEdge *e = einput_arr[i];
+ const float cost = bm_edge_calc_dissolve_error(e, delimit, &delimit_data);
+ eheap_table[i] = BLI_heap_insert(eheap, cost, e);
+ BM_elem_index_set(e, i); /* set dirty */
+ }
+
+ while ((BLI_heap_is_empty(eheap) == false) &&
+ (BLI_heap_node_value((enode_top = BLI_heap_top(eheap))) < angle_limit_cos_neg)) {
+ BMFace *f_new = NULL;
+ BMEdge *e;
+
+ e = BLI_heap_node_ptr(enode_top);
+ i = BM_elem_index_get(e);
+
+ if (BM_edge_is_manifold(e)) {
+ f_new = BM_faces_join_pair(bm, e->l, e->l->radial_next, false);
+
+ if (f_new) {
+ BMLoop *l_first, *l_iter;
+
+ BLI_heap_remove(eheap, enode_top);
+ eheap_table[i] = NULL;
+
+ /* update normal */
+ BM_face_normal_update(f_new);
+ if (oflag_out) {
+ BMO_face_flag_enable(bm, f_new, oflag_out);
+ }
+
+ /* re-calculate costs */
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_new);
+ do {
+ const int j = BM_elem_index_get(l_iter->e);
+ if (j != -1 && eheap_table[j]) {
+ const float cost = bm_edge_calc_dissolve_error(l_iter->e, delimit, &delimit_data);
+ BLI_heap_node_value_update(eheap, eheap_table[j], cost);
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ else {
+ BMO_error_clear(bm);
+ }
+ }
+
+ if (UNLIKELY(f_new == NULL)) {
+ BLI_heap_node_value_update(eheap, enode_top, COST_INVALID);
+ }
+ }
+
+ /* prepare for cleanup */
+ BM_mesh_elem_index_ensure(bm, BM_VERT);
+ vert_reverse_lookup = MEM_mallocN(sizeof(int) * bm->totvert, __func__);
+ copy_vn_i(vert_reverse_lookup, bm->totvert, -1);
+ for (i = 0; i < vinput_len; i++) {
+ BMVert *v = vinput_arr[i];
+ vert_reverse_lookup[BM_elem_index_get(v)] = i;
+ }
+
+ /* --- cleanup --- */
+ earray = MEM_mallocN(sizeof(BMEdge *) * bm->totedge, __func__);
+ BM_ITER_MESH_INDEX (e_iter, &iter, bm, BM_EDGES_OF_MESH, i) {
+ earray[i] = e_iter;
+ }
+ /* remove all edges/verts left behind from dissolving, NULL'ing the vertex array so we dont re-use */
+ for (i = bm->totedge - 1; i != -1; i--) {
+ e_iter = earray[i];
+
+ if (BM_edge_is_wire(e_iter) && (BM_elem_flag_test(e_iter, BM_ELEM_TAG) == false)) {
+ /* edge has become wire */
+ int vidx_reverse;
+ BMVert *v1 = e_iter->v1;
+ BMVert *v2 = e_iter->v2;
+ BM_edge_kill(bm, e_iter);
+ if (v1->e == NULL) {
+ vidx_reverse = vert_reverse_lookup[BM_elem_index_get(v1)];
+ if (vidx_reverse != -1) {
+ vinput_arr[vidx_reverse] = NULL;
+ }
+ BM_vert_kill(bm, v1);
+ }
+ if (v2->e == NULL) {
+ vidx_reverse = vert_reverse_lookup[BM_elem_index_get(v2)];
+ if (vidx_reverse != -1) {
+ vinput_arr[vidx_reverse] = NULL;
+ }
+ BM_vert_kill(bm, v2);
+ }
+ }
+ }
+ MEM_freeN(vert_reverse_lookup);
+ MEM_freeN(earray);
+
+ BLI_heap_free(eheap, NULL);
+ }
+
+ /* --- second verts --- */
+ if (do_dissolve_boundaries) {
+ /* simple version of the branch below, since we will dissolve _all_ verts that use 2 edges */
+ for (i = 0; i < vinput_len; i++) {
+ BMVert *v = vinput_arr[i];
+ if (LIKELY(v != NULL) && BM_vert_is_edge_pair(v)) {
+ BM_vert_collapse_edge(bm, v->e, v, true, true); /* join edges */
+ }
+ }
+ }
+ else {
+ Heap *vheap;
+ HeapNode **vheap_table = _heap_table;
+ HeapNode *vnode_top;
+
+ BMVert *v_iter;
+ BMIter iter;
+
+ BM_ITER_MESH (v_iter, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_elem_index_set(v_iter, -1); /* set dirty */
+ }
+ bm->elem_index_dirty |= BM_VERT;
+
+ vheap = BLI_heap_new_ex(vinput_len);
+
+ for (i = 0; i < vinput_len; i++) {
+ BMVert *v = vinput_arr[i];
+ if (LIKELY(v != NULL)) {
+ const float cost = bm_vert_edge_face_angle(v);
+ vheap_table[i] = BLI_heap_insert(vheap, cost, v);
+ BM_elem_index_set(v, i); /* set dirty */
+ }
+ }
+
+ while ((BLI_heap_is_empty(vheap) == false) &&
+ (BLI_heap_node_value((vnode_top = BLI_heap_top(vheap))) < angle_limit)) {
+ BMEdge *e_new = NULL;
+ BMVert *v;
+
+ v = BLI_heap_node_ptr(vnode_top);
+ i = BM_elem_index_get(v);
+
+ if (
#ifdef USE_DEGENERATE_CHECK
- !bm_vert_collapse_is_degenerate(v)
+ !bm_vert_collapse_is_degenerate(v)
#else
- BM_vert_is_edge_pair(v)
+ BM_vert_is_edge_pair(v)
#endif
- )
- {
- e_new = BM_vert_collapse_edge(bm, v->e, v, true, true); /* join edges */
-
- if (e_new) {
-
- BLI_heap_remove(vheap, vnode_top);
- vheap_table[i] = NULL;
-
- /* update normal */
- if (e_new->l) {
- BMLoop *l_first, *l_iter;
- l_iter = l_first = e_new->l;
- do {
- BM_face_normal_update(l_iter->f);
- } while ((l_iter = l_iter->radial_next) != l_first);
- }
-
- /* re-calculate costs */
- BM_ITER_ELEM (v_iter, &iter, e_new, BM_VERTS_OF_EDGE) {
- const int j = BM_elem_index_get(v_iter);
- if (j != -1 && vheap_table[j]) {
- const float cost = bm_vert_edge_face_angle(v_iter);
- BLI_heap_node_value_update(vheap, vheap_table[j], cost);
- }
- }
+ ) {
+ e_new = BM_vert_collapse_edge(bm, v->e, v, true, true); /* join edges */
+
+ if (e_new) {
+
+ BLI_heap_remove(vheap, vnode_top);
+ vheap_table[i] = NULL;
+
+ /* update normal */
+ if (e_new->l) {
+ BMLoop *l_first, *l_iter;
+ l_iter = l_first = e_new->l;
+ do {
+ BM_face_normal_update(l_iter->f);
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+
+ /* re-calculate costs */
+ BM_ITER_ELEM (v_iter, &iter, e_new, BM_VERTS_OF_EDGE) {
+ const int j = BM_elem_index_get(v_iter);
+ if (j != -1 && vheap_table[j]) {
+ const float cost = bm_vert_edge_face_angle(v_iter);
+ BLI_heap_node_value_update(vheap, vheap_table[j], cost);
+ }
+ }
#ifdef USE_DEGENERATE_CHECK
- /* dissolving a vertex may mean vertices we previously weren't able to dissolve
- * can now be re-evaluated. */
- if (e_new->l) {
- BMLoop *l_first, *l_iter;
- l_iter = l_first = e_new->l;
- do {
- /* skip vertices part of this edge, evaluated above */
- BMLoop *l_cycle_first, *l_cycle_iter;
- l_cycle_iter = l_iter->next->next;
- l_cycle_first = l_iter->prev;
- do {
- const int j = BM_elem_index_get(l_cycle_iter->v);
- if (j != -1 && vheap_table[j] &&
- (BLI_heap_node_value(vheap_table[j]) == COST_INVALID))
- {
- const float cost = bm_vert_edge_face_angle(l_cycle_iter->v);
- BLI_heap_node_value_update(vheap, vheap_table[j], cost);
- }
- } while ((l_cycle_iter = l_cycle_iter->next) != l_cycle_first);
-
- } while ((l_iter = l_iter->radial_next) != l_first);
- }
-#endif /* USE_DEGENERATE_CHECK */
-
- }
- }
-
- if (UNLIKELY(e_new == NULL)) {
- BLI_heap_node_value_update(vheap, vnode_top, COST_INVALID);
- }
- }
-
- BLI_heap_free(vheap, NULL);
- }
-
- MEM_freeN(_heap_table);
+ /* dissolving a vertex may mean vertices we previously weren't able to dissolve
+ * can now be re-evaluated. */
+ if (e_new->l) {
+ BMLoop *l_first, *l_iter;
+ l_iter = l_first = e_new->l;
+ do {
+ /* skip vertices part of this edge, evaluated above */
+ BMLoop *l_cycle_first, *l_cycle_iter;
+ l_cycle_iter = l_iter->next->next;
+ l_cycle_first = l_iter->prev;
+ do {
+ const int j = BM_elem_index_get(l_cycle_iter->v);
+ if (j != -1 && vheap_table[j] &&
+ (BLI_heap_node_value(vheap_table[j]) == COST_INVALID)) {
+ const float cost = bm_vert_edge_face_angle(l_cycle_iter->v);
+ BLI_heap_node_value_update(vheap, vheap_table[j], cost);
+ }
+ } while ((l_cycle_iter = l_cycle_iter->next) != l_cycle_first);
+
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+#endif /* USE_DEGENERATE_CHECK */
+ }
+ }
+
+ if (UNLIKELY(e_new == NULL)) {
+ BLI_heap_node_value_update(vheap, vnode_top, COST_INVALID);
+ }
+ }
+
+ BLI_heap_free(vheap, NULL);
+ }
+
+ MEM_freeN(_heap_table);
}
-void BM_mesh_decimate_dissolve(
- BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries,
- const BMO_Delimit delimit)
+void BM_mesh_decimate_dissolve(BMesh *bm,
+ const float angle_limit,
+ const bool do_dissolve_boundaries,
+ const BMO_Delimit delimit)
{
- int vinput_len;
- int einput_len;
-
- BMVert **vinput_arr = BM_iter_as_arrayN(bm, BM_VERTS_OF_MESH, NULL, &vinput_len, NULL, 0);
- BMEdge **einput_arr = BM_iter_as_arrayN(bm, BM_EDGES_OF_MESH, NULL, &einput_len, NULL, 0);
-
-
- BM_mesh_decimate_dissolve_ex(bm, angle_limit, do_dissolve_boundaries,
- delimit,
- vinput_arr, vinput_len,
- einput_arr, einput_len,
- 0);
-
- MEM_freeN(vinput_arr);
- MEM_freeN(einput_arr);
+ int vinput_len;
+ int einput_len;
+
+ BMVert **vinput_arr = BM_iter_as_arrayN(bm, BM_VERTS_OF_MESH, NULL, &vinput_len, NULL, 0);
+ BMEdge **einput_arr = BM_iter_as_arrayN(bm, BM_EDGES_OF_MESH, NULL, &einput_len, NULL, 0);
+
+ BM_mesh_decimate_dissolve_ex(bm,
+ angle_limit,
+ do_dissolve_boundaries,
+ delimit,
+ vinput_arr,
+ vinput_len,
+ einput_arr,
+ einput_len,
+ 0);
+
+ MEM_freeN(vinput_arr);
+ MEM_freeN(einput_arr);
}
diff --git a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c
index 90fca4fe184..13ada1756de 100644
--- a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c
+++ b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c
@@ -20,149 +20,146 @@
* BMesh decimator that uses a grid un-subdivide method.
*/
-
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
#include "bmesh.h"
-#include "bmesh_decimate.h" /* own include */
-
+#include "bmesh_decimate.h" /* own include */
static bool bm_vert_dissolve_fan_test(BMVert *v)
{
- /* check if we should walk over these verts */
- BMIter iter;
- BMEdge *e;
-
- BMVert *varr[4];
-
- uint tot_edge = 0;
- uint tot_edge_boundary = 0;
- uint tot_edge_manifold = 0;
- uint tot_edge_wire = 0;
-
- BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
- if (BM_edge_is_boundary(e)) {
- tot_edge_boundary++;
- }
- else if (BM_edge_is_manifold(e)) {
- tot_edge_manifold++;
- }
- else if (BM_edge_is_wire(e)) {
- tot_edge_wire++;
- }
-
- /* bail out early */
- if (tot_edge == 4) {
- return false;
- }
-
- /* used to check overlapping faces */
- varr[tot_edge] = BM_edge_other_vert(e, v);
-
- tot_edge++;
- }
-
- if (((tot_edge == 4) && (tot_edge_boundary == 0) && (tot_edge_manifold == 4)) ||
- ((tot_edge == 3) && (tot_edge_boundary == 0) && (tot_edge_manifold == 3)) ||
- ((tot_edge == 3) && (tot_edge_boundary == 2) && (tot_edge_manifold == 1)))
- {
- if (!BM_face_exists(varr, tot_edge)) {
- return true;
- }
- }
- else if ((tot_edge == 2) && (tot_edge_wire == 2)) {
- return true;
- }
- return false;
+ /* check if we should walk over these verts */
+ BMIter iter;
+ BMEdge *e;
+
+ BMVert *varr[4];
+
+ uint tot_edge = 0;
+ uint tot_edge_boundary = 0;
+ uint tot_edge_manifold = 0;
+ uint tot_edge_wire = 0;
+
+ BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
+ if (BM_edge_is_boundary(e)) {
+ tot_edge_boundary++;
+ }
+ else if (BM_edge_is_manifold(e)) {
+ tot_edge_manifold++;
+ }
+ else if (BM_edge_is_wire(e)) {
+ tot_edge_wire++;
+ }
+
+ /* bail out early */
+ if (tot_edge == 4) {
+ return false;
+ }
+
+ /* used to check overlapping faces */
+ varr[tot_edge] = BM_edge_other_vert(e, v);
+
+ tot_edge++;
+ }
+
+ if (((tot_edge == 4) && (tot_edge_boundary == 0) && (tot_edge_manifold == 4)) ||
+ ((tot_edge == 3) && (tot_edge_boundary == 0) && (tot_edge_manifold == 3)) ||
+ ((tot_edge == 3) && (tot_edge_boundary == 2) && (tot_edge_manifold == 1))) {
+ if (!BM_face_exists(varr, tot_edge)) {
+ return true;
+ }
+ }
+ else if ((tot_edge == 2) && (tot_edge_wire == 2)) {
+ return true;
+ }
+ return false;
}
static bool bm_vert_dissolve_fan(BMesh *bm, BMVert *v)
{
- /* collapse under 2 conditions.
- * - vert connects to 4 manifold edges (and 4 faces).
- * - vert connects to 1 manifold edge, 2 boundary edges (and 2 faces).
- *
- * This covers boundary verts of a quad grid and center verts.
- * note that surrounding faces dont have to be quads.
- */
-
- BMIter iter;
- BMEdge *e;
-
- uint tot_loop = 0;
- uint tot_edge = 0;
- uint tot_edge_boundary = 0;
- uint tot_edge_manifold = 0;
- uint tot_edge_wire = 0;
-
- BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
- if (BM_edge_is_boundary(e)) {
- tot_edge_boundary++;
- }
- else if (BM_edge_is_manifold(e)) {
- tot_edge_manifold++;
- }
- else if (BM_edge_is_wire(e)) {
- tot_edge_wire++;
- }
- tot_edge++;
- }
-
- if (tot_edge == 2) {
- /* check for 2 wire verts only */
- if (tot_edge_wire == 2) {
- return (BM_vert_collapse_edge(bm, v->e, v, true, true) != NULL);
- }
- }
- else if (tot_edge == 4) {
- /* check for 4 faces surrounding */
- if (tot_edge_boundary == 0 && tot_edge_manifold == 4) {
- /* good to go! */
- tot_loop = 4;
- }
- }
- else if (tot_edge == 3) {
- /* check for 2 faces surrounding at a boundary */
- if (tot_edge_boundary == 2 && tot_edge_manifold == 1) {
- /* good to go! */
- tot_loop = 2;
- }
- else if (tot_edge_boundary == 0 && tot_edge_manifold == 3) {
- /* good to go! */
- tot_loop = 3;
- }
- }
-
- if (tot_loop) {
- BMLoop *f_loop[4];
- uint i;
-
- /* ensure there are exactly tot_loop loops */
- BLI_assert(BM_iter_at_index(bm, BM_LOOPS_OF_VERT, v, tot_loop) == NULL);
- BM_iter_as_array(bm, BM_LOOPS_OF_VERT, v, (void **)f_loop, tot_loop);
-
- for (i = 0; i < tot_loop; i++) {
- BMLoop *l = f_loop[i];
- if (l->f->len > 3) {
- BMLoop *l_new;
- BLI_assert(l->prev->v != l->next->v);
- BM_face_split(bm, l->f, l->prev, l->next, &l_new, NULL, true);
- BM_elem_flag_merge_into(l_new->e, l->e, l->prev->e);
- }
- }
-
- return BM_vert_dissolve(bm, v);
- }
-
- return false;
+ /* collapse under 2 conditions.
+ * - vert connects to 4 manifold edges (and 4 faces).
+ * - vert connects to 1 manifold edge, 2 boundary edges (and 2 faces).
+ *
+ * This covers boundary verts of a quad grid and center verts.
+ * note that surrounding faces dont have to be quads.
+ */
+
+ BMIter iter;
+ BMEdge *e;
+
+ uint tot_loop = 0;
+ uint tot_edge = 0;
+ uint tot_edge_boundary = 0;
+ uint tot_edge_manifold = 0;
+ uint tot_edge_wire = 0;
+
+ BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
+ if (BM_edge_is_boundary(e)) {
+ tot_edge_boundary++;
+ }
+ else if (BM_edge_is_manifold(e)) {
+ tot_edge_manifold++;
+ }
+ else if (BM_edge_is_wire(e)) {
+ tot_edge_wire++;
+ }
+ tot_edge++;
+ }
+
+ if (tot_edge == 2) {
+ /* check for 2 wire verts only */
+ if (tot_edge_wire == 2) {
+ return (BM_vert_collapse_edge(bm, v->e, v, true, true) != NULL);
+ }
+ }
+ else if (tot_edge == 4) {
+ /* check for 4 faces surrounding */
+ if (tot_edge_boundary == 0 && tot_edge_manifold == 4) {
+ /* good to go! */
+ tot_loop = 4;
+ }
+ }
+ else if (tot_edge == 3) {
+ /* check for 2 faces surrounding at a boundary */
+ if (tot_edge_boundary == 2 && tot_edge_manifold == 1) {
+ /* good to go! */
+ tot_loop = 2;
+ }
+ else if (tot_edge_boundary == 0 && tot_edge_manifold == 3) {
+ /* good to go! */
+ tot_loop = 3;
+ }
+ }
+
+ if (tot_loop) {
+ BMLoop *f_loop[4];
+ uint i;
+
+ /* ensure there are exactly tot_loop loops */
+ BLI_assert(BM_iter_at_index(bm, BM_LOOPS_OF_VERT, v, tot_loop) == NULL);
+ BM_iter_as_array(bm, BM_LOOPS_OF_VERT, v, (void **)f_loop, tot_loop);
+
+ for (i = 0; i < tot_loop; i++) {
+ BMLoop *l = f_loop[i];
+ if (l->f->len > 3) {
+ BMLoop *l_new;
+ BLI_assert(l->prev->v != l->next->v);
+ BM_face_split(bm, l->f, l->prev, l->next, &l_new, NULL, true);
+ BM_elem_flag_merge_into(l_new->e, l->e, l->prev->e);
+ }
+ }
+
+ return BM_vert_dissolve(bm, v);
+ }
+
+ return false;
}
enum {
- VERT_INDEX_DO_COLLAPSE = -1,
- VERT_INDEX_INIT = 0,
- VERT_INDEX_IGNORE = 1,
+ VERT_INDEX_DO_COLLAPSE = -1,
+ VERT_INDEX_INIT = 0,
+ VERT_INDEX_IGNORE = 1,
};
// #define USE_WALKER /* gives uneven results, disable for now */
@@ -178,172 +175,176 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const bool
#ifdef USE_WALKER
# define ELE_VERT_TAG 1
#else
- BMVert **vert_seek_a = MEM_mallocN(sizeof(BMVert *) * bm->totvert, __func__);
- BMVert **vert_seek_b = MEM_mallocN(sizeof(BMVert *) * bm->totvert, __func__);
- unsigned vert_seek_a_tot = 0;
- unsigned vert_seek_b_tot = 0;
+ BMVert **vert_seek_a = MEM_mallocN(sizeof(BMVert *) * bm->totvert, __func__);
+ BMVert **vert_seek_b = MEM_mallocN(sizeof(BMVert *) * bm->totvert, __func__);
+ unsigned vert_seek_a_tot = 0;
+ unsigned vert_seek_b_tot = 0;
#endif
- BMIter iter;
+ BMIter iter;
- const uint offset = 0;
- const uint nth = 2;
+ const uint offset = 0;
+ const uint nth = 2;
- int iter_step;
+ int iter_step;
- /* if tag_only is set, we assume the caller knows what verts to tag
- * needed for the operator */
- if (tag_only == false) {
- BMVert *v;
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- BM_elem_flag_enable(v, BM_ELEM_TAG);
- }
- }
+ /* if tag_only is set, we assume the caller knows what verts to tag
+ * needed for the operator */
+ if (tag_only == false) {
+ BMVert *v;
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_elem_flag_enable(v, BM_ELEM_TAG);
+ }
+ }
- for (iter_step = 0; iter_step < iterations; iter_step++) {
- BMVert *v, *v_next;
- bool iter_done;
+ for (iter_step = 0; iter_step < iterations; iter_step++) {
+ BMVert *v, *v_next;
+ bool iter_done;
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_TAG) && bm_vert_dissolve_fan_test(v)) {
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_TAG) && bm_vert_dissolve_fan_test(v)) {
#ifdef USE_WALKER
- BMO_vert_flag_enable(bm, v, ELE_VERT_TAG);
+ BMO_vert_flag_enable(bm, v, ELE_VERT_TAG);
#endif
- BM_elem_index_set(v, VERT_INDEX_INIT); /* set_dirty! */
- }
- else {
- BM_elem_index_set(v, VERT_INDEX_IGNORE); /* set_dirty! */
- }
- }
- /* done with selecting tagged verts */
-
-
- /* main loop, keep tagging until we can't tag any more islands */
- while (true) {
+ BM_elem_index_set(v, VERT_INDEX_INIT); /* set_dirty! */
+ }
+ else {
+ BM_elem_index_set(v, VERT_INDEX_IGNORE); /* set_dirty! */
+ }
+ }
+ /* done with selecting tagged verts */
+
+ /* main loop, keep tagging until we can't tag any more islands */
+ while (true) {
#ifdef USE_WALKER
- BMWalker walker;
+ BMWalker walker;
#else
- uint depth = 1;
- uint i;
+ uint depth = 1;
+ uint i;
#endif
- BMVert *v_first = NULL;
+ BMVert *v_first = NULL;
- /* we could avoid iterating from the start each time */
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- if (v->e && (BM_elem_index_get(v) == VERT_INDEX_INIT)) {
+ /* we could avoid iterating from the start each time */
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (v->e && (BM_elem_index_get(v) == VERT_INDEX_INIT)) {
#ifdef USE_WALKER
- if (BMO_vert_flag_test(bm, v, ELE_VERT_TAG))
+ if (BMO_vert_flag_test(bm, v, ELE_VERT_TAG))
#endif
- {
- /* check again incase the topology changed */
- if (bm_vert_dissolve_fan_test(v)) {
- v_first = v;
- }
- break;
- }
- }
- }
- if (v_first == NULL) {
- break;
- }
+ {
+ /* check again incase the topology changed */
+ if (bm_vert_dissolve_fan_test(v)) {
+ v_first = v;
+ }
+ break;
+ }
+ }
+ }
+ if (v_first == NULL) {
+ break;
+ }
#ifdef USE_WALKER
- /* Walk over selected elements starting at active */
- BMW_init(&walker, bm, BMW_CONNECTED_VERTEX,
- ELE_VERT_TAG, BMW_MASK_NOP, BMW_MASK_NOP,
- BMW_FLAG_NOP, /* don't use BMW_FLAG_TEST_HIDDEN here since we want to desel all */
- BMW_NIL_LAY);
-
- BLI_assert(walker.order == BMW_BREADTH_FIRST);
- for (v = BMW_begin(&walker, v_first); v != NULL; v = BMW_step(&walker)) {
- /* Deselect elements that aren't at "nth" depth from active */
- if (BM_elem_index_get(v) == VERT_INDEX_INIT) {
- if ((offset + BMW_current_depth(&walker)) % nth) {
- /* tag for removal */
- BM_elem_index_set(v, VERT_INDEX_DO_COLLAPSE); /* set_dirty! */
- }
- else {
- /* works better to allow these verts to be checked again */
- //BM_elem_index_set(v, VERT_INDEX_IGNORE); /* set_dirty! */
- }
- }
- }
- BMW_end(&walker);
+ /* Walk over selected elements starting at active */
+ BMW_init(&walker,
+ bm,
+ BMW_CONNECTED_VERTEX,
+ ELE_VERT_TAG,
+ BMW_MASK_NOP,
+ BMW_MASK_NOP,
+ BMW_FLAG_NOP, /* don't use BMW_FLAG_TEST_HIDDEN here since we want to desel all */
+ BMW_NIL_LAY);
+
+ BLI_assert(walker.order == BMW_BREADTH_FIRST);
+ for (v = BMW_begin(&walker, v_first); v != NULL; v = BMW_step(&walker)) {
+ /* Deselect elements that aren't at "nth" depth from active */
+ if (BM_elem_index_get(v) == VERT_INDEX_INIT) {
+ if ((offset + BMW_current_depth(&walker)) % nth) {
+ /* tag for removal */
+ BM_elem_index_set(v, VERT_INDEX_DO_COLLAPSE); /* set_dirty! */
+ }
+ else {
+ /* works better to allow these verts to be checked again */
+ //BM_elem_index_set(v, VERT_INDEX_IGNORE); /* set_dirty! */
+ }
+ }
+ }
+ BMW_end(&walker);
#else
- BM_elem_index_set(v_first, ((offset + depth) % nth) ? VERT_INDEX_IGNORE : VERT_INDEX_DO_COLLAPSE); /* set_dirty! */
-
- vert_seek_b_tot = 0;
- vert_seek_b[vert_seek_b_tot++] = v_first;
-
- while (true) {
- BMEdge *e;
-
- if ((offset + depth) % nth) {
- vert_seek_a_tot = 0;
- for (i = 0; i < vert_seek_b_tot; i++) {
- v = vert_seek_b[i];
- BLI_assert(BM_elem_index_get(v) == VERT_INDEX_IGNORE);
- BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
- BMVert *v_other = BM_edge_other_vert(e, v);
- if (BM_elem_index_get(v_other) == VERT_INDEX_INIT) {
- BM_elem_index_set(v_other, VERT_INDEX_DO_COLLAPSE); /* set_dirty! */
- vert_seek_a[vert_seek_a_tot++] = v_other;
- }
- }
- }
- if (vert_seek_a_tot == 0) {
- break;
- }
- }
- else {
- vert_seek_b_tot = 0;
- for (i = 0; i < vert_seek_a_tot; i++) {
- v = vert_seek_a[i];
- BLI_assert(BM_elem_index_get(v) == VERT_INDEX_DO_COLLAPSE);
- BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
- BMVert *v_other = BM_edge_other_vert(e, v);
- if (BM_elem_index_get(v_other) == VERT_INDEX_INIT) {
- BM_elem_index_set(v_other, VERT_INDEX_IGNORE); /* set_dirty! */
- vert_seek_b[vert_seek_b_tot++] = v_other;
- }
- }
- }
- if (vert_seek_b_tot == 0) {
- break;
- }
- }
-
- depth++;
- }
-#endif /* USE_WALKER */
-
- }
-
- /* now we tagged all verts -1 for removal, lets loop over and rebuild faces */
- iter_done = false;
- BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_index_get(v) == VERT_INDEX_DO_COLLAPSE) {
- if (bm_vert_dissolve_fan(bm, v)) {
- iter_done = true;
- }
- }
- }
-
- if (iter_done == false) {
- break;
- }
- }
-
- bm->elem_index_dirty |= BM_VERT;
+ BM_elem_index_set(v_first,
+ ((offset + depth) % nth) ? VERT_INDEX_IGNORE :
+ VERT_INDEX_DO_COLLAPSE); /* set_dirty! */
+
+ vert_seek_b_tot = 0;
+ vert_seek_b[vert_seek_b_tot++] = v_first;
+
+ while (true) {
+ BMEdge *e;
+
+ if ((offset + depth) % nth) {
+ vert_seek_a_tot = 0;
+ for (i = 0; i < vert_seek_b_tot; i++) {
+ v = vert_seek_b[i];
+ BLI_assert(BM_elem_index_get(v) == VERT_INDEX_IGNORE);
+ BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
+ BMVert *v_other = BM_edge_other_vert(e, v);
+ if (BM_elem_index_get(v_other) == VERT_INDEX_INIT) {
+ BM_elem_index_set(v_other, VERT_INDEX_DO_COLLAPSE); /* set_dirty! */
+ vert_seek_a[vert_seek_a_tot++] = v_other;
+ }
+ }
+ }
+ if (vert_seek_a_tot == 0) {
+ break;
+ }
+ }
+ else {
+ vert_seek_b_tot = 0;
+ for (i = 0; i < vert_seek_a_tot; i++) {
+ v = vert_seek_a[i];
+ BLI_assert(BM_elem_index_get(v) == VERT_INDEX_DO_COLLAPSE);
+ BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
+ BMVert *v_other = BM_edge_other_vert(e, v);
+ if (BM_elem_index_get(v_other) == VERT_INDEX_INIT) {
+ BM_elem_index_set(v_other, VERT_INDEX_IGNORE); /* set_dirty! */
+ vert_seek_b[vert_seek_b_tot++] = v_other;
+ }
+ }
+ }
+ if (vert_seek_b_tot == 0) {
+ break;
+ }
+ }
+
+ depth++;
+ }
+#endif /* USE_WALKER */
+ }
+
+ /* now we tagged all verts -1 for removal, lets loop over and rebuild faces */
+ iter_done = false;
+ BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_index_get(v) == VERT_INDEX_DO_COLLAPSE) {
+ if (bm_vert_dissolve_fan(bm, v)) {
+ iter_done = true;
+ }
+ }
+ }
+
+ if (iter_done == false) {
+ break;
+ }
+ }
+
+ bm->elem_index_dirty |= BM_VERT;
#ifndef USE_WALKER
- MEM_freeN(vert_seek_a);
- MEM_freeN(vert_seek_b);
+ MEM_freeN(vert_seek_a);
+ MEM_freeN(vert_seek_b);
#endif
}
void BM_mesh_decimate_unsubdivide(BMesh *bm, const int iterations)
{
- BM_mesh_decimate_unsubdivide_ex(bm, iterations, false);
+ BM_mesh_decimate_unsubdivide_ex(bm, iterations, false);
}
diff --git a/source/blender/bmesh/tools/bmesh_edgenet.c b/source/blender/bmesh/tools/bmesh_edgenet.c
index 528a89a06ab..a3b9ce76b47 100644
--- a/source/blender/bmesh/tools/bmesh_edgenet.c
+++ b/source/blender/bmesh/tools/bmesh_edgenet.c
@@ -30,21 +30,20 @@
#include "BLI_linklist.h"
#include "bmesh.h"
-#include "bmesh_edgenet.h" /* own include */
-
-#include "BLI_strict_flags.h" /* keep last */
+#include "bmesh_edgenet.h" /* own include */
+#include "BLI_strict_flags.h" /* keep last */
/* Struct for storing a path of verts walked over */
typedef struct VertNetInfo {
- BMVert *prev; /* previous vertex */
- int pass; /* path scanning pass value, for internal calculation */
- int face; /* face index connected to the edge between this and the previous vert */
- int flag; /* flag */
+ BMVert *prev; /* previous vertex */
+ int pass; /* path scanning pass value, for internal calculation */
+ int face; /* face index connected to the edge between this and the previous vert */
+ int flag; /* flag */
} VertNetInfo;
enum {
- VNINFO_FLAG_IS_MIXFACE = (1 << 0),
+ VNINFO_FLAG_IS_MIXFACE = (1 << 0),
};
/**
@@ -52,137 +51,134 @@ enum {
*/
static bool bm_edge_step_ok(BMEdge *e)
{
- return BM_elem_flag_test(e, BM_ELEM_TAG) && ((e->l == NULL) || (e->l->radial_next == e->l));
+ return BM_elem_flag_test(e, BM_ELEM_TAG) && ((e->l == NULL) || (e->l->radial_next == e->l));
}
static int bm_edge_face(BMEdge *e)
{
- return e->l ? BM_elem_index_get(e->l->f) : -1;
+ return e->l ? BM_elem_index_get(e->l->f) : -1;
}
/**
* Get the next available edge we can use to attempt tp calculate a path from.
*/
-static BMEdge *bm_edgenet_edge_get_next(
- BMesh *bm,
- LinkNode **edge_queue, BLI_mempool *edge_queue_pool)
+static BMEdge *bm_edgenet_edge_get_next(BMesh *bm,
+ LinkNode **edge_queue,
+ BLI_mempool *edge_queue_pool)
{
- BMEdge *e;
- BMIter iter;
-
- while (*edge_queue) {
- e = BLI_linklist_pop_pool(edge_queue, edge_queue_pool);
- if (bm_edge_step_ok(e)) {
- return e;
- }
- }
-
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (bm_edge_step_ok(e)) {
- return e;
- }
- }
-
- return NULL;
+ BMEdge *e;
+ BMIter iter;
+
+ while (*edge_queue) {
+ e = BLI_linklist_pop_pool(edge_queue, edge_queue_pool);
+ if (bm_edge_step_ok(e)) {
+ return e;
+ }
+ }
+
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (bm_edge_step_ok(e)) {
+ return e;
+ }
+ }
+
+ return NULL;
}
-
/**
* Edge loops are built up using links to the 'prev' member.
* with each side of the loop having its own pass (negated from the other).
*
* This function returns half a loop, the caller needs to run twice to get both sides.
*/
-static uint bm_edgenet_path_from_pass(
- BMVert *v, LinkNode **v_ls,
- VertNetInfo *vnet_info, BLI_mempool *path_pool)
+static uint bm_edgenet_path_from_pass(BMVert *v,
+ LinkNode **v_ls,
+ VertNetInfo *vnet_info,
+ BLI_mempool *path_pool)
{
- VertNetInfo *vn = &vnet_info[BM_elem_index_get(v)];
- const int pass = vn->pass;
- uint v_ls_tot = 0;
-
- do {
- BLI_linklist_prepend_pool(v_ls, v, path_pool);
- v_ls_tot += 1;
- v = vn->prev;
- vn = &vnet_info[BM_elem_index_get(v)];
- } while (vn->pass == pass);
-
- return v_ls_tot;
+ VertNetInfo *vn = &vnet_info[BM_elem_index_get(v)];
+ const int pass = vn->pass;
+ uint v_ls_tot = 0;
+
+ do {
+ BLI_linklist_prepend_pool(v_ls, v, path_pool);
+ v_ls_tot += 1;
+ v = vn->prev;
+ vn = &vnet_info[BM_elem_index_get(v)];
+ } while (vn->pass == pass);
+
+ return v_ls_tot;
}
/**
* Specialized wrapper for #BM_face_exists_overlap_subset
* that gets the verts from a path before we allocate it in the correct order.
*/
-static bool bm_edgenet_path_check_overlap(
- BMVert *v1, BMVert *v2,
- VertNetInfo *vnet_info)
+static bool bm_edgenet_path_check_overlap(BMVert *v1, BMVert *v2, VertNetInfo *vnet_info)
{
- /* vert order doesn't matter */
- uint v_ls_tot = 0;
- LinkNode *v_ls = NULL;
- BMVert *v_pair[2] = {v1, v2};
- uint i;
-
- for (i = 0; i < 2; i++) {
- BMVert *v = v_pair[i];
- VertNetInfo *vn = &vnet_info[BM_elem_index_get(v)];
- const int pass = vn->pass;
- do {
- BLI_linklist_prepend_alloca(&v_ls, v);
- v_ls_tot += 1;
- v = vn->prev;
- vn = &vnet_info[BM_elem_index_get(v)];
- } while (vn->pass == pass);
- }
-
- if (v_ls_tot) {
- BMVert **vert_arr = BLI_array_alloca(vert_arr, v_ls_tot);
- LinkNode *v_lnk;
- for (i = 0, v_lnk = v_ls; i < v_ls_tot; v_lnk = v_lnk->next, i++) {
- vert_arr[i] = v_lnk->link;
- }
-
- return BM_face_exists_overlap_subset(vert_arr, (int)v_ls_tot);
- }
- else {
- return false;
- }
+ /* vert order doesn't matter */
+ uint v_ls_tot = 0;
+ LinkNode *v_ls = NULL;
+ BMVert *v_pair[2] = {v1, v2};
+ uint i;
+
+ for (i = 0; i < 2; i++) {
+ BMVert *v = v_pair[i];
+ VertNetInfo *vn = &vnet_info[BM_elem_index_get(v)];
+ const int pass = vn->pass;
+ do {
+ BLI_linklist_prepend_alloca(&v_ls, v);
+ v_ls_tot += 1;
+ v = vn->prev;
+ vn = &vnet_info[BM_elem_index_get(v)];
+ } while (vn->pass == pass);
+ }
+
+ if (v_ls_tot) {
+ BMVert **vert_arr = BLI_array_alloca(vert_arr, v_ls_tot);
+ LinkNode *v_lnk;
+ for (i = 0, v_lnk = v_ls; i < v_ls_tot; v_lnk = v_lnk->next, i++) {
+ vert_arr[i] = v_lnk->link;
+ }
+
+ return BM_face_exists_overlap_subset(vert_arr, (int)v_ls_tot);
+ }
+ else {
+ return false;
+ }
}
/**
* Create a face from the path.
*/
-static BMFace *bm_edgenet_face_from_path(
- BMesh *bm, LinkNode *path, const uint path_len)
+static BMFace *bm_edgenet_face_from_path(BMesh *bm, LinkNode *path, const uint path_len)
{
- BMFace *f;
- LinkNode *v_lnk;
- int i;
- bool ok;
+ BMFace *f;
+ LinkNode *v_lnk;
+ int i;
+ bool ok;
- BMVert **vert_arr = BLI_array_alloca(vert_arr, path_len);
- BMEdge **edge_arr = BLI_array_alloca(edge_arr, path_len);
+ BMVert **vert_arr = BLI_array_alloca(vert_arr, path_len);
+ BMEdge **edge_arr = BLI_array_alloca(edge_arr, path_len);
- for (v_lnk = path, i = 0; v_lnk; v_lnk = v_lnk->next, i++) {
- vert_arr[i] = v_lnk->link;
- }
+ for (v_lnk = path, i = 0; v_lnk; v_lnk = v_lnk->next, i++) {
+ vert_arr[i] = v_lnk->link;
+ }
- ok = BM_edges_from_verts(edge_arr, vert_arr, i);
- BLI_assert(ok);
- UNUSED_VARS_NDEBUG(ok);
+ ok = BM_edges_from_verts(edge_arr, vert_arr, i);
+ BLI_assert(ok);
+ UNUSED_VARS_NDEBUG(ok);
- /* no need for this, we do overlap checks before allowing the path to be used */
+ /* no need for this, we do overlap checks before allowing the path to be used */
#if 0
- if (BM_face_exists_multi(vert_arr, edge_arr, path_len)) {
- return NULL;
- }
+ if (BM_face_exists_multi(vert_arr, edge_arr, path_len)) {
+ return NULL;
+ }
#endif
- f = BM_face_create(bm, vert_arr, edge_arr, (int)path_len, NULL, BM_CREATE_NOP);
+ f = BM_face_create(bm, vert_arr, edge_arr, (int)path_len, NULL, BM_CREATE_NOP);
- return f;
+ return f;
}
/**
@@ -190,78 +186,75 @@ static BMFace *bm_edgenet_face_from_path(
*
* \return The connecting edge if the path is found, otherwise NULL.
*/
-static BMEdge *bm_edgenet_path_step(
- BMVert *v_curr, LinkNode **v_ls,
- VertNetInfo *vnet_info, BLI_mempool *path_pool)
+static BMEdge *bm_edgenet_path_step(BMVert *v_curr,
+ LinkNode **v_ls,
+ VertNetInfo *vnet_info,
+ BLI_mempool *path_pool)
{
- const VertNetInfo *vn_curr;
-
- BMEdge *e;
- BMIter iter;
- uint tot;
- uint v_ls_tot;
+ const VertNetInfo *vn_curr;
+ BMEdge *e;
+ BMIter iter;
+ uint tot;
+ uint v_ls_tot;
begin:
- tot = 0;
- v_ls_tot = 0;
- vn_curr = &vnet_info[BM_elem_index_get(v_curr)];
-
- BM_ITER_ELEM (e, &iter, v_curr, BM_EDGES_OF_VERT) {
- BMVert *v_next = BM_edge_other_vert(e, v_curr);
- if (v_next != vn_curr->prev) {
- if (bm_edge_step_ok(e)) {
- VertNetInfo *vn_next = &vnet_info[BM_elem_index_get(v_next)];
-
- /* check we're not looping back on ourselves */
- if (vn_curr->pass != vn_next->pass) {
-
- if (vn_curr->pass == -vn_next->pass) {
- if ((vn_curr->flag & VNINFO_FLAG_IS_MIXFACE) ||
- (vn_next->flag & VNINFO_FLAG_IS_MIXFACE))
- {
- /* found connecting edge */
- if (bm_edgenet_path_check_overlap(v_curr, v_next, vnet_info) == false) {
- return e;
- }
- }
- }
- else {
- vn_next->face = bm_edge_face(e);
- vn_next->pass = vn_curr->pass;
- vn_next->prev = v_curr;
-
- /* flush flag down the path */
- vn_next->flag &= ~VNINFO_FLAG_IS_MIXFACE;
- if ((vn_curr->flag & VNINFO_FLAG_IS_MIXFACE) ||
- (vn_next->face == -1) ||
- (vn_next->face != vn_curr->face))
- {
- vn_next->flag |= VNINFO_FLAG_IS_MIXFACE;
- }
-
- /* add to the list! */
- BLI_linklist_prepend_pool(v_ls, v_next, path_pool);
- v_ls_tot += 1;
- }
- }
- }
- tot += 1;
- }
- }
-
- /* trick to walk along wire-edge paths */
- if (v_ls_tot == 1 && tot == 1) {
- v_curr = BLI_linklist_pop_pool(v_ls, path_pool);
- /* avoid recursion, can crash on very large nets */
+ tot = 0;
+ v_ls_tot = 0;
+ vn_curr = &vnet_info[BM_elem_index_get(v_curr)];
+
+ BM_ITER_ELEM (e, &iter, v_curr, BM_EDGES_OF_VERT) {
+ BMVert *v_next = BM_edge_other_vert(e, v_curr);
+ if (v_next != vn_curr->prev) {
+ if (bm_edge_step_ok(e)) {
+ VertNetInfo *vn_next = &vnet_info[BM_elem_index_get(v_next)];
+
+ /* check we're not looping back on ourselves */
+ if (vn_curr->pass != vn_next->pass) {
+
+ if (vn_curr->pass == -vn_next->pass) {
+ if ((vn_curr->flag & VNINFO_FLAG_IS_MIXFACE) ||
+ (vn_next->flag & VNINFO_FLAG_IS_MIXFACE)) {
+ /* found connecting edge */
+ if (bm_edgenet_path_check_overlap(v_curr, v_next, vnet_info) == false) {
+ return e;
+ }
+ }
+ }
+ else {
+ vn_next->face = bm_edge_face(e);
+ vn_next->pass = vn_curr->pass;
+ vn_next->prev = v_curr;
+
+ /* flush flag down the path */
+ vn_next->flag &= ~VNINFO_FLAG_IS_MIXFACE;
+ if ((vn_curr->flag & VNINFO_FLAG_IS_MIXFACE) || (vn_next->face == -1) ||
+ (vn_next->face != vn_curr->face)) {
+ vn_next->flag |= VNINFO_FLAG_IS_MIXFACE;
+ }
+
+ /* add to the list! */
+ BLI_linklist_prepend_pool(v_ls, v_next, path_pool);
+ v_ls_tot += 1;
+ }
+ }
+ }
+ tot += 1;
+ }
+ }
+
+ /* trick to walk along wire-edge paths */
+ if (v_ls_tot == 1 && tot == 1) {
+ v_curr = BLI_linklist_pop_pool(v_ls, path_pool);
+ /* avoid recursion, can crash on very large nets */
#if 0
- bm_edgenet_path_step(v_curr, v_ls, vnet_info, path_pool);
+ bm_edgenet_path_step(v_curr, v_ls, vnet_info, path_pool);
#else
- goto begin;
+ goto begin;
#endif
- }
+ }
- return NULL;
+ return NULL;
}
/**
@@ -269,166 +262,167 @@ begin:
*
* \return A linked list of verts.
*/
-static LinkNode *bm_edgenet_path_calc(
- BMEdge *e, const int pass_nr, const uint path_cost_max,
- uint *r_path_len, uint *r_path_cost,
- VertNetInfo *vnet_info, BLI_mempool *path_pool)
+static LinkNode *bm_edgenet_path_calc(BMEdge *e,
+ const int pass_nr,
+ const uint path_cost_max,
+ uint *r_path_len,
+ uint *r_path_cost,
+ VertNetInfo *vnet_info,
+ BLI_mempool *path_pool)
{
- VertNetInfo *vn_1, *vn_2;
- const int f_index = bm_edge_face(e);
- bool found;
-
- LinkNode *v_ls_prev = NULL;
- LinkNode *v_ls_next = NULL;
+ VertNetInfo *vn_1, *vn_2;
+ const int f_index = bm_edge_face(e);
+ bool found;
- uint path_cost_accum = 0;
+ LinkNode *v_ls_prev = NULL;
+ LinkNode *v_ls_next = NULL;
- BLI_assert(bm_edge_step_ok(e));
+ uint path_cost_accum = 0;
- *r_path_len = 0;
- *r_path_cost = 0;
+ BLI_assert(bm_edge_step_ok(e));
- vn_1 = &vnet_info[BM_elem_index_get(e->v1)];
- vn_2 = &vnet_info[BM_elem_index_get(e->v2)];
+ *r_path_len = 0;
+ *r_path_cost = 0;
- vn_1->pass = pass_nr;
- vn_2->pass = -pass_nr;
+ vn_1 = &vnet_info[BM_elem_index_get(e->v1)];
+ vn_2 = &vnet_info[BM_elem_index_get(e->v2)];
- vn_1->prev = e->v2;
- vn_2->prev = e->v1;
+ vn_1->pass = pass_nr;
+ vn_2->pass = -pass_nr;
- vn_1->face =
- vn_2->face = f_index;
+ vn_1->prev = e->v2;
+ vn_2->prev = e->v1;
- vn_1->flag =
- vn_2->flag = (f_index == -1) ? VNINFO_FLAG_IS_MIXFACE : 0;
+ vn_1->face = vn_2->face = f_index;
- /* prime the searchlist */
- BLI_linklist_prepend_pool(&v_ls_prev, e->v1, path_pool);
- BLI_linklist_prepend_pool(&v_ls_prev, e->v2, path_pool);
+ vn_1->flag = vn_2->flag = (f_index == -1) ? VNINFO_FLAG_IS_MIXFACE : 0;
- do {
- found = false;
+ /* prime the searchlist */
+ BLI_linklist_prepend_pool(&v_ls_prev, e->v1, path_pool);
+ BLI_linklist_prepend_pool(&v_ls_prev, e->v2, path_pool);
- /* no point to continue, we're over budget */
- if (path_cost_accum >= path_cost_max) {
- BLI_linklist_free_pool(v_ls_next, NULL, path_pool);
- BLI_linklist_free_pool(v_ls_prev, NULL, path_pool);
- return NULL;
- }
+ do {
+ found = false;
- while (v_ls_prev) {
- const LinkNode *v_ls_next_old = v_ls_next;
- BMVert *v = BLI_linklist_pop_pool(&v_ls_prev, path_pool);
- BMEdge *e_found = bm_edgenet_path_step(v, &v_ls_next, vnet_info, path_pool);
+ /* no point to continue, we're over budget */
+ if (path_cost_accum >= path_cost_max) {
+ BLI_linklist_free_pool(v_ls_next, NULL, path_pool);
+ BLI_linklist_free_pool(v_ls_prev, NULL, path_pool);
+ return NULL;
+ }
- if (e_found) {
- LinkNode *path = NULL;
- uint path_len;
- BLI_linklist_free_pool(v_ls_next, NULL, path_pool);
- BLI_linklist_free_pool(v_ls_prev, NULL, path_pool);
+ while (v_ls_prev) {
+ const LinkNode *v_ls_next_old = v_ls_next;
+ BMVert *v = BLI_linklist_pop_pool(&v_ls_prev, path_pool);
+ BMEdge *e_found = bm_edgenet_path_step(v, &v_ls_next, vnet_info, path_pool);
- // BLI_assert(BLI_mempool_len(path_pool) == 0);
+ if (e_found) {
+ LinkNode *path = NULL;
+ uint path_len;
+ BLI_linklist_free_pool(v_ls_next, NULL, path_pool);
+ BLI_linklist_free_pool(v_ls_prev, NULL, path_pool);
- path_len = bm_edgenet_path_from_pass(e_found->v1, &path, vnet_info, path_pool);
- BLI_linklist_reverse(&path);
- path_len += bm_edgenet_path_from_pass(e_found->v2, &path, vnet_info, path_pool);
- *r_path_len = path_len;
- *r_path_cost = path_cost_accum;
- return path;
- }
- else {
- /* check if a change was made */
- if (v_ls_next_old != v_ls_next) {
- found = true;
- }
- }
+ // BLI_assert(BLI_mempool_len(path_pool) == 0);
- }
- BLI_assert(v_ls_prev == NULL);
+ path_len = bm_edgenet_path_from_pass(e_found->v1, &path, vnet_info, path_pool);
+ BLI_linklist_reverse(&path);
+ path_len += bm_edgenet_path_from_pass(e_found->v2, &path, vnet_info, path_pool);
+ *r_path_len = path_len;
+ *r_path_cost = path_cost_accum;
+ return path;
+ }
+ else {
+ /* check if a change was made */
+ if (v_ls_next_old != v_ls_next) {
+ found = true;
+ }
+ }
+ }
+ BLI_assert(v_ls_prev == NULL);
- path_cost_accum++;
+ path_cost_accum++;
- /* swap */
- v_ls_prev = v_ls_next;
- v_ls_next = NULL;
+ /* swap */
+ v_ls_prev = v_ls_next;
+ v_ls_next = NULL;
- } while (found);
+ } while (found);
- BLI_assert(v_ls_prev == NULL);
- BLI_assert(v_ls_next == NULL);
+ BLI_assert(v_ls_prev == NULL);
+ BLI_assert(v_ls_next == NULL);
- /* tag not to search again */
- BM_elem_flag_disable(e, BM_ELEM_TAG);
+ /* tag not to search again */
+ BM_elem_flag_disable(e, BM_ELEM_TAG);
- return NULL;
+ return NULL;
}
/**
* Wrapper for #bm_edgenet_path_calc which ensures all included edges
* _don't_ have a better option.
*/
-static LinkNode *bm_edgenet_path_calc_best(
- BMEdge *e, int *pass_nr, uint path_cost_max,
- uint *r_path_len, uint *r_path_cost,
- VertNetInfo *vnet_info, BLI_mempool *path_pool)
+static LinkNode *bm_edgenet_path_calc_best(BMEdge *e,
+ int *pass_nr,
+ uint path_cost_max,
+ uint *r_path_len,
+ uint *r_path_cost,
+ VertNetInfo *vnet_info,
+ BLI_mempool *path_pool)
{
- LinkNode *path;
- uint path_cost;
-
- path = bm_edgenet_path_calc(e, *pass_nr, path_cost_max,
- r_path_len, &path_cost,
- vnet_info, path_pool);
- (*pass_nr)++;
-
- if (path == NULL) {
- return NULL;
- }
- else if (path_cost < 1) {
- /* any face that takes 1 iteration to find we consider valid */
- return path;
- }
- else {
- /* Check every edge to see if any can give a better path.
- * This avoids very strange/long paths from being created. */
-
- const uint path_len = *r_path_len;
- uint i, i_prev;
- BMVert **vert_arr = BLI_array_alloca(vert_arr, path_len);
- LinkNode *v_lnk;
-
- for (v_lnk = path, i = 0; v_lnk; v_lnk = v_lnk->next, i++) {
- vert_arr[i] = v_lnk->link;
- }
-
- i_prev = path_len - 1;
- for (i = 0; i < path_len; i++) {
- BMEdge *e_other = BM_edge_exists(vert_arr[i], vert_arr[i_prev]);
- if (e_other != e) {
- LinkNode *path_test;
- uint path_len_test;
- uint path_cost_test;
-
- path_test = bm_edgenet_path_calc(e_other, *pass_nr, path_cost,
- &path_len_test, &path_cost_test,
- vnet_info, path_pool);
- (*pass_nr)++;
-
- if (path_test) {
- BLI_assert(path_cost_test < path_cost);
-
- BLI_linklist_free_pool(path, NULL, path_pool);
- path = path_test;
- *r_path_len = path_len_test;
- *r_path_cost = path_cost_test;
- path_cost = path_cost_test;
- }
- }
-
- i_prev = i;
- }
- }
- return path;
+ LinkNode *path;
+ uint path_cost;
+
+ path = bm_edgenet_path_calc(
+ e, *pass_nr, path_cost_max, r_path_len, &path_cost, vnet_info, path_pool);
+ (*pass_nr)++;
+
+ if (path == NULL) {
+ return NULL;
+ }
+ else if (path_cost < 1) {
+ /* any face that takes 1 iteration to find we consider valid */
+ return path;
+ }
+ else {
+ /* Check every edge to see if any can give a better path.
+ * This avoids very strange/long paths from being created. */
+
+ const uint path_len = *r_path_len;
+ uint i, i_prev;
+ BMVert **vert_arr = BLI_array_alloca(vert_arr, path_len);
+ LinkNode *v_lnk;
+
+ for (v_lnk = path, i = 0; v_lnk; v_lnk = v_lnk->next, i++) {
+ vert_arr[i] = v_lnk->link;
+ }
+
+ i_prev = path_len - 1;
+ for (i = 0; i < path_len; i++) {
+ BMEdge *e_other = BM_edge_exists(vert_arr[i], vert_arr[i_prev]);
+ if (e_other != e) {
+ LinkNode *path_test;
+ uint path_len_test;
+ uint path_cost_test;
+
+ path_test = bm_edgenet_path_calc(
+ e_other, *pass_nr, path_cost, &path_len_test, &path_cost_test, vnet_info, path_pool);
+ (*pass_nr)++;
+
+ if (path_test) {
+ BLI_assert(path_cost_test < path_cost);
+
+ BLI_linklist_free_pool(path, NULL, path_pool);
+ path = path_test;
+ *r_path_len = path_len_test;
+ *r_path_cost = path_cost_test;
+ path_cost = path_cost_test;
+ }
+ }
+
+ i_prev = i;
+ }
+ }
+ return path;
}
/**
@@ -440,70 +434,67 @@ static LinkNode *bm_edgenet_path_calc_best(
* \param bm: The mesh to operate on.
* \param use_edge_tag: Only fill tagged edges.
*/
-void BM_mesh_edgenet(
- BMesh *bm,
- const bool use_edge_tag, const bool use_new_face_tag)
+void BM_mesh_edgenet(BMesh *bm, const bool use_edge_tag, const bool use_new_face_tag)
{
- VertNetInfo *vnet_info = MEM_callocN(sizeof(*vnet_info) * (size_t)bm->totvert, __func__);
- BLI_mempool *edge_queue_pool = BLI_mempool_create(sizeof(LinkNode), 0, 512, BLI_MEMPOOL_NOP);
- BLI_mempool *path_pool = BLI_mempool_create(sizeof(LinkNode), 0, 512, BLI_MEMPOOL_NOP);
- LinkNode *edge_queue = NULL;
-
- BMEdge *e;
- BMIter iter;
-
- int pass_nr = 1;
-
- if (use_edge_tag == false) {
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- BM_elem_flag_set(e, BM_ELEM_TAG, bm_edge_step_ok(e));
- }
- }
-
- BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
-
- while (true) {
- LinkNode *path = NULL;
- uint path_len;
- uint path_cost;
-
- e = bm_edgenet_edge_get_next(bm, &edge_queue, edge_queue_pool);
- if (e == NULL) {
- break;
- }
-
- BLI_assert(bm_edge_step_ok(e) == true);
-
- path = bm_edgenet_path_calc_best(e, &pass_nr, UINT_MAX,
- &path_len, &path_cost,
- vnet_info, path_pool);
-
- if (path) {
- BMFace *f = bm_edgenet_face_from_path(bm, path, path_len);
- /* queue edges to operate on */
- BMLoop *l_first, *l_iter;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if (bm_edge_step_ok(l_iter->e)) {
- BLI_linklist_prepend_pool(&edge_queue, l_iter->e, edge_queue_pool);
- }
- } while ((l_iter = l_iter->next) != l_first);
-
- if (use_new_face_tag) {
- BM_elem_flag_enable(f, BM_ELEM_TAG);
- }
-
- /* the face index only needs to be unique, not kept valid */
- BM_elem_index_set(f, bm->totface - 1); /* set_dirty */
- }
-
- BLI_linklist_free_pool(path, NULL, path_pool);
- BLI_assert(BLI_mempool_len(path_pool) == 0);
- }
-
- bm->elem_index_dirty |= BM_FACE | BM_LOOP;
-
- BLI_mempool_destroy(edge_queue_pool);
- BLI_mempool_destroy(path_pool);
- MEM_freeN(vnet_info);
+ VertNetInfo *vnet_info = MEM_callocN(sizeof(*vnet_info) * (size_t)bm->totvert, __func__);
+ BLI_mempool *edge_queue_pool = BLI_mempool_create(sizeof(LinkNode), 0, 512, BLI_MEMPOOL_NOP);
+ BLI_mempool *path_pool = BLI_mempool_create(sizeof(LinkNode), 0, 512, BLI_MEMPOOL_NOP);
+ LinkNode *edge_queue = NULL;
+
+ BMEdge *e;
+ BMIter iter;
+
+ int pass_nr = 1;
+
+ if (use_edge_tag == false) {
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ BM_elem_flag_set(e, BM_ELEM_TAG, bm_edge_step_ok(e));
+ }
+ }
+
+ BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
+
+ while (true) {
+ LinkNode *path = NULL;
+ uint path_len;
+ uint path_cost;
+
+ e = bm_edgenet_edge_get_next(bm, &edge_queue, edge_queue_pool);
+ if (e == NULL) {
+ break;
+ }
+
+ BLI_assert(bm_edge_step_ok(e) == true);
+
+ path = bm_edgenet_path_calc_best(
+ e, &pass_nr, UINT_MAX, &path_len, &path_cost, vnet_info, path_pool);
+
+ if (path) {
+ BMFace *f = bm_edgenet_face_from_path(bm, path, path_len);
+ /* queue edges to operate on */
+ BMLoop *l_first, *l_iter;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (bm_edge_step_ok(l_iter->e)) {
+ BLI_linklist_prepend_pool(&edge_queue, l_iter->e, edge_queue_pool);
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+
+ if (use_new_face_tag) {
+ BM_elem_flag_enable(f, BM_ELEM_TAG);
+ }
+
+ /* the face index only needs to be unique, not kept valid */
+ BM_elem_index_set(f, bm->totface - 1); /* set_dirty */
+ }
+
+ BLI_linklist_free_pool(path, NULL, path_pool);
+ BLI_assert(BLI_mempool_len(path_pool) == 0);
+ }
+
+ bm->elem_index_dirty |= BM_FACE | BM_LOOP;
+
+ BLI_mempool_destroy(edge_queue_pool);
+ BLI_mempool_destroy(path_pool);
+ MEM_freeN(vnet_info);
}
diff --git a/source/blender/bmesh/tools/bmesh_edgenet.h b/source/blender/bmesh/tools/bmesh_edgenet.h
index 0a72ded8949..5db0e1170f3 100644
--- a/source/blender/bmesh/tools/bmesh_edgenet.h
+++ b/source/blender/bmesh/tools/bmesh_edgenet.h
@@ -21,8 +21,6 @@
* \ingroup bmesh
*/
-void BM_mesh_edgenet(
- BMesh *bm,
- const bool use_edge_tag, const bool use_new_face_tag);
+void BM_mesh_edgenet(BMesh *bm, const bool use_edge_tag, const bool use_new_face_tag);
#endif /* __BMESH_EDGENET_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_edgesplit.c b/source/blender/bmesh/tools/bmesh_edgesplit.c
index 198b3efa8cc..332672d7c3c 100644
--- a/source/blender/bmesh/tools/bmesh_edgesplit.c
+++ b/source/blender/bmesh/tools/bmesh_edgesplit.c
@@ -26,113 +26,112 @@
#include "bmesh.h"
-#include "bmesh_edgesplit.h" /* own include */
+#include "bmesh_edgesplit.h" /* own include */
/**
* \param use_verts: Use flagged verts instead of edges.
* \param tag_only: Only split tagged edges.
* \param copy_select: Copy selection history.
*/
-void BM_mesh_edgesplit(
- BMesh *bm,
- const bool use_verts,
- const bool tag_only, const bool copy_select)
+void BM_mesh_edgesplit(BMesh *bm,
+ const bool use_verts,
+ const bool tag_only,
+ const bool copy_select)
{
- BMIter iter;
- BMEdge *e;
-
- bool use_ese = false;
- GHash *ese_gh = NULL;
-
- if (copy_select && bm->selected.first) {
- BMEditSelection *ese;
-
- ese_gh = BLI_ghash_ptr_new(__func__);
- for (ese = bm->selected.first; ese; ese = ese->next) {
- if (ese->htype != BM_FACE) {
- BLI_ghash_insert(ese_gh, ese->ele, ese);
- }
- }
-
- use_ese = true;
- }
-
- if (tag_only == false) {
- BM_mesh_elem_hflag_enable_all(bm, BM_EDGE | (use_verts ? BM_VERT : 0), BM_ELEM_TAG, false);
- }
-
- if (use_verts) {
- /* prevent one edge having both verts unflagged
- * we could alternately disable these edges, either way its a corner case.
- *
- * This is needed so we don't split off the edge but then none of its verts which
- * would leave a duplicate edge.
- */
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
- if (UNLIKELY(((BM_elem_flag_test(e->v1, BM_ELEM_TAG) == false) &&
- (BM_elem_flag_test(e->v2, BM_ELEM_TAG) == false))))
- {
- BM_elem_flag_enable(e->v1, BM_ELEM_TAG);
- BM_elem_flag_enable(e->v2, BM_ELEM_TAG);
- }
- }
- }
- }
-
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
- BM_elem_flag_enable(e->v1, BM_ELEM_TAG);
- BM_elem_flag_enable(e->v2, BM_ELEM_TAG);
- }
- }
-
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
- uint i;
- for (i = 0; i < 2; i++) {
- BMVert *v = ((&e->v1)[i]);
- if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
- BM_elem_flag_disable(v, BM_ELEM_TAG);
-
- if (use_ese) {
- BMVert **vtar;
- int vtar_len;
-
- BM_vert_separate_hflag(bm, v, BM_ELEM_TAG, copy_select, &vtar, &vtar_len);
-
- /* first value is always in 'v' */
- if (vtar_len > 1) {
- BMEditSelection *ese = BLI_ghash_lookup(ese_gh, v);
- BLI_assert(v == vtar[0]);
- if (UNLIKELY(ese)) {
- int j;
- for (j = 1; j < vtar_len; j++) {
- BLI_assert(v != vtar[j]);
- BM_select_history_store_after_notest(bm, ese, vtar[j]);
- }
- }
- }
- MEM_freeN(vtar);
- }
- else {
- BM_vert_separate_hflag(bm, v, BM_ELEM_TAG, copy_select, NULL, NULL);
- }
- }
- }
- }
- }
+ BMIter iter;
+ BMEdge *e;
+
+ bool use_ese = false;
+ GHash *ese_gh = NULL;
+
+ if (copy_select && bm->selected.first) {
+ BMEditSelection *ese;
+
+ ese_gh = BLI_ghash_ptr_new(__func__);
+ for (ese = bm->selected.first; ese; ese = ese->next) {
+ if (ese->htype != BM_FACE) {
+ BLI_ghash_insert(ese_gh, ese->ele, ese);
+ }
+ }
+
+ use_ese = true;
+ }
+
+ if (tag_only == false) {
+ BM_mesh_elem_hflag_enable_all(bm, BM_EDGE | (use_verts ? BM_VERT : 0), BM_ELEM_TAG, false);
+ }
+
+ if (use_verts) {
+ /* prevent one edge having both verts unflagged
+ * we could alternately disable these edges, either way its a corner case.
+ *
+ * This is needed so we don't split off the edge but then none of its verts which
+ * would leave a duplicate edge.
+ */
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ if (UNLIKELY(((BM_elem_flag_test(e->v1, BM_ELEM_TAG) == false) &&
+ (BM_elem_flag_test(e->v2, BM_ELEM_TAG) == false)))) {
+ BM_elem_flag_enable(e->v1, BM_ELEM_TAG);
+ BM_elem_flag_enable(e->v2, BM_ELEM_TAG);
+ }
+ }
+ }
+ }
+
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ BM_elem_flag_enable(e->v1, BM_ELEM_TAG);
+ BM_elem_flag_enable(e->v2, BM_ELEM_TAG);
+ }
+ }
+
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ uint i;
+ for (i = 0; i < 2; i++) {
+ BMVert *v = ((&e->v1)[i]);
+ if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ BM_elem_flag_disable(v, BM_ELEM_TAG);
+
+ if (use_ese) {
+ BMVert **vtar;
+ int vtar_len;
+
+ BM_vert_separate_hflag(bm, v, BM_ELEM_TAG, copy_select, &vtar, &vtar_len);
+
+ /* first value is always in 'v' */
+ if (vtar_len > 1) {
+ BMEditSelection *ese = BLI_ghash_lookup(ese_gh, v);
+ BLI_assert(v == vtar[0]);
+ if (UNLIKELY(ese)) {
+ int j;
+ for (j = 1; j < vtar_len; j++) {
+ BLI_assert(v != vtar[j]);
+ BM_select_history_store_after_notest(bm, ese, vtar[j]);
+ }
+ }
+ }
+ MEM_freeN(vtar);
+ }
+ else {
+ BM_vert_separate_hflag(bm, v, BM_ELEM_TAG, copy_select, NULL, NULL);
+ }
+ }
+ }
+ }
+ }
#ifndef NDEBUG
- /* ensure we don't have any double edges! */
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
- BLI_assert(BM_edge_find_double(e) == NULL);
- }
- }
+ /* ensure we don't have any double edges! */
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ BLI_assert(BM_edge_find_double(e) == NULL);
+ }
+ }
#endif
- if (use_ese) {
- BLI_ghash_free(ese_gh, NULL, NULL);
- }
+ if (use_ese) {
+ BLI_ghash_free(ese_gh, NULL, NULL);
+ }
}
diff --git a/source/blender/bmesh/tools/bmesh_edgesplit.h b/source/blender/bmesh/tools/bmesh_edgesplit.h
index f7faeb1fa19..0b3884ec888 100644
--- a/source/blender/bmesh/tools/bmesh_edgesplit.h
+++ b/source/blender/bmesh/tools/bmesh_edgesplit.h
@@ -21,9 +21,9 @@
* \ingroup bmesh
*/
-void BM_mesh_edgesplit(
- BMesh *bm,
- const bool use_verts,
- const bool tag_only, const bool copy_select);
+void BM_mesh_edgesplit(BMesh *bm,
+ const bool use_verts,
+ const bool tag_only,
+ const bool copy_select);
#endif /* __BMESH_EDGESPLIT_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_intersect.c b/source/blender/bmesh/tools/bmesh_intersect.c
index 2445978e294..66845b6f33c 100644
--- a/source/blender/bmesh/tools/bmesh_intersect.c
+++ b/source/blender/bmesh/tools/bmesh_intersect.c
@@ -50,7 +50,7 @@
#include "bmesh.h"
#include "intern/bmesh_private.h"
-#include "bmesh_intersect.h" /* own include */
+#include "bmesh_intersect.h" /* own include */
#include "tools/bmesh_edgesplit.h"
@@ -78,61 +78,59 @@
// #define USE_DUMP
-static void tri_v3_scale(
- float v1[3], float v2[3], float v3[3],
- const float t)
+static void tri_v3_scale(float v1[3], float v2[3], float v3[3], const float t)
{
- float p[3];
+ float p[3];
- mid_v3_v3v3v3(p, v1, v2, v3);
+ mid_v3_v3v3v3(p, v1, v2, v3);
- interp_v3_v3v3(v1, p, v1, t);
- interp_v3_v3v3(v2, p, v2, t);
- interp_v3_v3v3(v3, p, v3, t);
+ interp_v3_v3v3(v1, p, v1, t);
+ interp_v3_v3v3(v2, p, v2, t);
+ interp_v3_v3v3(v3, p, v3, t);
}
#ifdef USE_DISSOLVE
/* other edge when a vert only has 2 edges */
static BMEdge *bm_vert_other_edge(BMVert *v, BMEdge *e)
{
- BLI_assert(BM_vert_is_edge_pair(v));
- BLI_assert(BM_vert_in_edge(e, v));
-
- if (v->e != e) {
- return v->e;
- }
- else {
- return BM_DISK_EDGE_NEXT(v->e, v);
- }
+ BLI_assert(BM_vert_is_edge_pair(v));
+ BLI_assert(BM_vert_in_edge(e, v));
+
+ if (v->e != e) {
+ return v->e;
+ }
+ else {
+ return BM_DISK_EDGE_NEXT(v->e, v);
+ }
}
#endif
enum ISectType {
- IX_NONE = -1,
- IX_EDGE_TRI_EDGE0,
- IX_EDGE_TRI_EDGE1,
- IX_EDGE_TRI_EDGE2,
- IX_EDGE_TRI,
- IX_TOT,
+ IX_NONE = -1,
+ IX_EDGE_TRI_EDGE0,
+ IX_EDGE_TRI_EDGE1,
+ IX_EDGE_TRI_EDGE2,
+ IX_EDGE_TRI,
+ IX_TOT,
};
struct ISectEpsilon {
- float eps, eps_sq;
- float eps2x, eps2x_sq;
- float eps_margin, eps_margin_sq;
+ float eps, eps_sq;
+ float eps2x, eps2x_sq;
+ float eps_margin, eps_margin_sq;
};
struct ISectState {
- BMesh *bm;
- GHash *edgetri_cache; /* int[4]: BMVert */
- GHash *edge_verts; /* BMEdge: LinkList(of verts), new and original edges */
- GHash *face_edges; /* BMFace-index: LinkList(of edges), only original faces */
- GSet *wire_edges; /* BMEdge (could use tags instead) */
- LinkNode *vert_dissolve; /* BMVert's */
+ BMesh *bm;
+ GHash *edgetri_cache; /* int[4]: BMVert */
+ GHash *edge_verts; /* BMEdge: LinkList(of verts), new and original edges */
+ GHash *face_edges; /* BMFace-index: LinkList(of edges), only original faces */
+ GSet *wire_edges; /* BMEdge (could use tags instead) */
+ LinkNode *vert_dissolve; /* BMVert's */
- MemArena *mem_arena;
+ MemArena *mem_arena;
- struct ISectEpsilon epsilon;
+ struct ISectEpsilon epsilon;
};
/**
@@ -140,829 +138,809 @@ struct ISectState {
* Also means we don't need to update the GHash value each time.
*/
struct LinkBase {
- LinkNode *list;
- uint list_len;
+ LinkNode *list;
+ uint list_len;
};
-static bool ghash_insert_link(
- GHash *gh, void *key, void *val, bool use_test,
- MemArena *mem_arena)
+static bool ghash_insert_link(GHash *gh, void *key, void *val, bool use_test, MemArena *mem_arena)
{
- void **ls_base_p;
- struct LinkBase *ls_base;
- LinkNode *ls;
-
- if (!BLI_ghash_ensure_p(gh, key, &ls_base_p)) {
- ls_base = *ls_base_p = BLI_memarena_alloc(mem_arena, sizeof(*ls_base));
- ls_base->list = NULL;
- ls_base->list_len = 0;
- }
- else {
- ls_base = *ls_base_p;
- if (use_test && (BLI_linklist_index(ls_base->list, val) != -1)) {
- return false;
- }
- }
-
- ls = BLI_memarena_alloc(mem_arena, sizeof(*ls));
- ls->next = ls_base->list;
- ls->link = val;
- ls_base->list = ls;
- ls_base->list_len += 1;
-
- return true;
+ void **ls_base_p;
+ struct LinkBase *ls_base;
+ LinkNode *ls;
+
+ if (!BLI_ghash_ensure_p(gh, key, &ls_base_p)) {
+ ls_base = *ls_base_p = BLI_memarena_alloc(mem_arena, sizeof(*ls_base));
+ ls_base->list = NULL;
+ ls_base->list_len = 0;
+ }
+ else {
+ ls_base = *ls_base_p;
+ if (use_test && (BLI_linklist_index(ls_base->list, val) != -1)) {
+ return false;
+ }
+ }
+
+ ls = BLI_memarena_alloc(mem_arena, sizeof(*ls));
+ ls->next = ls_base->list;
+ ls->link = val;
+ ls_base->list = ls;
+ ls_base->list_len += 1;
+
+ return true;
}
struct vert_sort_t {
- float val;
- BMVert *v;
+ float val;
+ BMVert *v;
};
#ifdef USE_SPLICE
static void edge_verts_sort(const float co[3], struct LinkBase *v_ls_base)
{
- /* not optimal but list will be typically < 5 */
- uint i;
- struct vert_sort_t *vert_sort = BLI_array_alloca(vert_sort, v_ls_base->list_len);
- LinkNode *node;
+ /* not optimal but list will be typically < 5 */
+ uint i;
+ struct vert_sort_t *vert_sort = BLI_array_alloca(vert_sort, v_ls_base->list_len);
+ LinkNode *node;
- BLI_assert(v_ls_base->list_len > 1);
+ BLI_assert(v_ls_base->list_len > 1);
- for (i = 0, node = v_ls_base->list; i < v_ls_base->list_len; i++, node = node->next) {
- BMVert *v = node->link;
- BLI_assert(v->head.htype == BM_VERT);
- vert_sort[i].val = len_squared_v3v3(co, v->co);
- vert_sort[i].v = v;
- }
+ for (i = 0, node = v_ls_base->list; i < v_ls_base->list_len; i++, node = node->next) {
+ BMVert *v = node->link;
+ BLI_assert(v->head.htype == BM_VERT);
+ vert_sort[i].val = len_squared_v3v3(co, v->co);
+ vert_sort[i].v = v;
+ }
- qsort(vert_sort, v_ls_base->list_len, sizeof(*vert_sort), BLI_sortutil_cmp_float);
+ qsort(vert_sort, v_ls_base->list_len, sizeof(*vert_sort), BLI_sortutil_cmp_float);
- for (i = 0, node = v_ls_base->list; i < v_ls_base->list_len; i++, node = node->next) {
- node->link = vert_sort[i].v;
- }
+ for (i = 0, node = v_ls_base->list; i < v_ls_base->list_len; i++, node = node->next) {
+ node->link = vert_sort[i].v;
+ }
}
#endif
-static void edge_verts_add(
- struct ISectState *s,
- BMEdge *e,
- BMVert *v,
- const bool use_test
- )
+static void edge_verts_add(struct ISectState *s, BMEdge *e, BMVert *v, const bool use_test)
{
- BLI_assert(e->head.htype == BM_EDGE);
- BLI_assert(v->head.htype == BM_VERT);
- ghash_insert_link(s->edge_verts, (void *)e, v, use_test, s->mem_arena);
+ BLI_assert(e->head.htype == BM_EDGE);
+ BLI_assert(v->head.htype == BM_VERT);
+ ghash_insert_link(s->edge_verts, (void *)e, v, use_test, s->mem_arena);
}
-static void face_edges_add(
- struct ISectState *s,
- const int f_index,
- BMEdge *e,
- const bool use_test)
+static void face_edges_add(struct ISectState *s, const int f_index, BMEdge *e, const bool use_test)
{
- void *f_index_key = POINTER_FROM_INT(f_index);
- BLI_assert(e->head.htype == BM_EDGE);
- BLI_assert(BM_edge_in_face(e, s->bm->ftable[f_index]) == false);
- BLI_assert(BM_elem_index_get(s->bm->ftable[f_index]) == f_index);
+ void *f_index_key = POINTER_FROM_INT(f_index);
+ BLI_assert(e->head.htype == BM_EDGE);
+ BLI_assert(BM_edge_in_face(e, s->bm->ftable[f_index]) == false);
+ BLI_assert(BM_elem_index_get(s->bm->ftable[f_index]) == f_index);
- ghash_insert_link(s->face_edges, f_index_key, e, use_test, s->mem_arena);
+ ghash_insert_link(s->face_edges, f_index_key, e, use_test, s->mem_arena);
}
#ifdef USE_NET
-static void face_edges_split(
- BMesh *bm, BMFace *f, struct LinkBase *e_ls_base,
- bool use_island_connect, bool use_partial_connect,
- MemArena *mem_arena_edgenet)
+static void face_edges_split(BMesh *bm,
+ BMFace *f,
+ struct LinkBase *e_ls_base,
+ bool use_island_connect,
+ bool use_partial_connect,
+ MemArena *mem_arena_edgenet)
{
- uint i;
- uint edge_arr_len = e_ls_base->list_len;
- BMEdge **edge_arr = BLI_array_alloca(edge_arr, edge_arr_len);
- LinkNode *node;
- BLI_assert(f->head.htype == BM_FACE);
-
- for (i = 0, node = e_ls_base->list; i < e_ls_base->list_len; i++, node = node->next) {
- edge_arr[i] = node->link;
- }
- BLI_assert(node == NULL);
-
-#ifdef USE_DUMP
- printf("# %s: %d %u\n", __func__, BM_elem_index_get(f), e_ls_base->list_len);
-#endif
-
-#ifdef USE_NET_ISLAND_CONNECT
- if (use_island_connect) {
- uint edge_arr_holes_len;
- BMEdge **edge_arr_holes;
- if (BM_face_split_edgenet_connect_islands(
- bm, f,
- edge_arr, edge_arr_len,
- use_partial_connect,
- mem_arena_edgenet,
- &edge_arr_holes, &edge_arr_holes_len))
- {
- edge_arr_len = edge_arr_holes_len;
- edge_arr = edge_arr_holes; /* owned by the arena */
- }
- }
-#else
- UNUSED_VARS(use_island_connect, mem_arena_edgenet);
-#endif
-
- BM_face_split_edgenet(bm, f, edge_arr, (int)edge_arr_len, NULL, NULL);
+ uint i;
+ uint edge_arr_len = e_ls_base->list_len;
+ BMEdge **edge_arr = BLI_array_alloca(edge_arr, edge_arr_len);
+ LinkNode *node;
+ BLI_assert(f->head.htype == BM_FACE);
+
+ for (i = 0, node = e_ls_base->list; i < e_ls_base->list_len; i++, node = node->next) {
+ edge_arr[i] = node->link;
+ }
+ BLI_assert(node == NULL);
+
+# ifdef USE_DUMP
+ printf("# %s: %d %u\n", __func__, BM_elem_index_get(f), e_ls_base->list_len);
+# endif
+
+# ifdef USE_NET_ISLAND_CONNECT
+ if (use_island_connect) {
+ uint edge_arr_holes_len;
+ BMEdge **edge_arr_holes;
+ if (BM_face_split_edgenet_connect_islands(bm,
+ f,
+ edge_arr,
+ edge_arr_len,
+ use_partial_connect,
+ mem_arena_edgenet,
+ &edge_arr_holes,
+ &edge_arr_holes_len)) {
+ edge_arr_len = edge_arr_holes_len;
+ edge_arr = edge_arr_holes; /* owned by the arena */
+ }
+ }
+# else
+ UNUSED_VARS(use_island_connect, mem_arena_edgenet);
+# endif
+
+ BM_face_split_edgenet(bm, f, edge_arr, (int)edge_arr_len, NULL, NULL);
}
#endif
#ifdef USE_DISSOLVE
-static void vert_dissolve_add(
- struct ISectState *s,
- BMVert *v)
+static void vert_dissolve_add(struct ISectState *s, BMVert *v)
{
- BLI_assert(v->head.htype == BM_VERT);
- BLI_assert(!BM_elem_flag_test(v, BM_ELEM_TAG));
- BLI_assert(BLI_linklist_index(s->vert_dissolve, v) == -1);
+ BLI_assert(v->head.htype == BM_VERT);
+ BLI_assert(!BM_elem_flag_test(v, BM_ELEM_TAG));
+ BLI_assert(BLI_linklist_index(s->vert_dissolve, v) == -1);
- BM_elem_flag_enable(v, BM_ELEM_TAG);
- BLI_linklist_prepend_arena(&s->vert_dissolve, v, s->mem_arena);
+ BM_elem_flag_enable(v, BM_ELEM_TAG);
+ BLI_linklist_prepend_arena(&s->vert_dissolve, v, s->mem_arena);
}
#endif
-static enum ISectType intersect_line_tri(
- const float p0[3], const float p1[3],
- const float *t_cos[3], const float t_nor[3],
- float r_ix[3],
- const struct ISectEpsilon *e)
+static enum ISectType intersect_line_tri(const float p0[3],
+ const float p1[3],
+ const float *t_cos[3],
+ const float t_nor[3],
+ float r_ix[3],
+ const struct ISectEpsilon *e)
{
- float p_dir[3];
- uint i_t0;
- float fac;
-
- sub_v3_v3v3(p_dir, p0, p1);
- normalize_v3(p_dir);
-
- for (i_t0 = 0; i_t0 < 3; i_t0++) {
- const uint i_t1 = (i_t0 + 1) % 3;
- float te_dir[3];
-
- sub_v3_v3v3(te_dir, t_cos[i_t0], t_cos[i_t1]);
- normalize_v3(te_dir);
- if (fabsf(dot_v3v3(p_dir, te_dir)) >= 1.0f - e->eps) {
- /* co-linear */
- }
- else {
- float ix_pair[2][3];
- int ix_pair_type;
-
- ix_pair_type = isect_line_line_epsilon_v3(p0, p1, t_cos[i_t0], t_cos[i_t1], ix_pair[0], ix_pair[1], 0.0f);
-
- if (ix_pair_type != 0) {
- if (ix_pair_type == 1) {
- copy_v3_v3(ix_pair[1], ix_pair[0]);
- }
-
- if ((ix_pair_type == 1) ||
- (len_squared_v3v3(ix_pair[0], ix_pair[1]) <= e->eps_margin_sq))
- {
- fac = line_point_factor_v3(ix_pair[1], t_cos[i_t0], t_cos[i_t1]);
- if ((fac >= e->eps_margin) && (fac <= 1.0f - e->eps_margin)) {
- fac = line_point_factor_v3(ix_pair[0], p0, p1);
- if ((fac >= e->eps_margin) && (fac <= 1.0f - e->eps_margin)) {
- copy_v3_v3(r_ix, ix_pair[0]);
- return (IX_EDGE_TRI_EDGE0 + (enum ISectType)i_t0);
- }
- }
- }
- }
- }
- }
-
- /* check ray isn't planar with tri */
- if (fabsf(dot_v3v3(p_dir, t_nor)) >= e->eps) {
- if (isect_line_segment_tri_epsilon_v3(p0, p1, t_cos[0], t_cos[1], t_cos[2], &fac, NULL, 0.0f)) {
- if ((fac >= e->eps_margin) && (fac <= 1.0f - e->eps_margin)) {
- interp_v3_v3v3(r_ix, p0, p1, fac);
- if (min_fff(len_squared_v3v3(t_cos[0], r_ix),
- len_squared_v3v3(t_cos[1], r_ix),
- len_squared_v3v3(t_cos[2], r_ix)) >= e->eps_margin_sq)
- {
- return IX_EDGE_TRI;
- }
- }
- }
- }
-
- /* r_ix may be unset */
- return IX_NONE;
+ float p_dir[3];
+ uint i_t0;
+ float fac;
+
+ sub_v3_v3v3(p_dir, p0, p1);
+ normalize_v3(p_dir);
+
+ for (i_t0 = 0; i_t0 < 3; i_t0++) {
+ const uint i_t1 = (i_t0 + 1) % 3;
+ float te_dir[3];
+
+ sub_v3_v3v3(te_dir, t_cos[i_t0], t_cos[i_t1]);
+ normalize_v3(te_dir);
+ if (fabsf(dot_v3v3(p_dir, te_dir)) >= 1.0f - e->eps) {
+ /* co-linear */
+ }
+ else {
+ float ix_pair[2][3];
+ int ix_pair_type;
+
+ ix_pair_type = isect_line_line_epsilon_v3(
+ p0, p1, t_cos[i_t0], t_cos[i_t1], ix_pair[0], ix_pair[1], 0.0f);
+
+ if (ix_pair_type != 0) {
+ if (ix_pair_type == 1) {
+ copy_v3_v3(ix_pair[1], ix_pair[0]);
+ }
+
+ if ((ix_pair_type == 1) ||
+ (len_squared_v3v3(ix_pair[0], ix_pair[1]) <= e->eps_margin_sq)) {
+ fac = line_point_factor_v3(ix_pair[1], t_cos[i_t0], t_cos[i_t1]);
+ if ((fac >= e->eps_margin) && (fac <= 1.0f - e->eps_margin)) {
+ fac = line_point_factor_v3(ix_pair[0], p0, p1);
+ if ((fac >= e->eps_margin) && (fac <= 1.0f - e->eps_margin)) {
+ copy_v3_v3(r_ix, ix_pair[0]);
+ return (IX_EDGE_TRI_EDGE0 + (enum ISectType)i_t0);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* check ray isn't planar with tri */
+ if (fabsf(dot_v3v3(p_dir, t_nor)) >= e->eps) {
+ if (isect_line_segment_tri_epsilon_v3(
+ p0, p1, t_cos[0], t_cos[1], t_cos[2], &fac, NULL, 0.0f)) {
+ if ((fac >= e->eps_margin) && (fac <= 1.0f - e->eps_margin)) {
+ interp_v3_v3v3(r_ix, p0, p1, fac);
+ if (min_fff(len_squared_v3v3(t_cos[0], r_ix),
+ len_squared_v3v3(t_cos[1], r_ix),
+ len_squared_v3v3(t_cos[2], r_ix)) >= e->eps_margin_sq) {
+ return IX_EDGE_TRI;
+ }
+ }
+ }
+ }
+
+ /* r_ix may be unset */
+ return IX_NONE;
}
-static BMVert *bm_isect_edge_tri(
- struct ISectState *s,
- BMVert *e_v0, BMVert *e_v1,
- BMVert *t[3], const int t_index,
- const float *t_cos[3], const float t_nor[3],
- enum ISectType *r_side)
+static BMVert *bm_isect_edge_tri(struct ISectState *s,
+ BMVert *e_v0,
+ BMVert *e_v1,
+ BMVert *t[3],
+ const int t_index,
+ const float *t_cos[3],
+ const float t_nor[3],
+ enum ISectType *r_side)
{
- BMesh *bm = s->bm;
- int k_arr[IX_TOT][4];
- uint i;
- const int ti[3] = {UNPACK3_EX(BM_elem_index_get, t, )};
- float ix[3];
+ BMesh *bm = s->bm;
+ int k_arr[IX_TOT][4];
+ uint i;
+ const int ti[3] = {UNPACK3_EX(BM_elem_index_get, t, )};
+ float ix[3];
- if (BM_elem_index_get(e_v0) > BM_elem_index_get(e_v1)) {
- SWAP(BMVert *, e_v0, e_v1);
- }
+ if (BM_elem_index_get(e_v0) > BM_elem_index_get(e_v1)) {
+ SWAP(BMVert *, e_v0, e_v1);
+ }
#ifdef USE_PARANOID
- BLI_assert(len_squared_v3v3(e_v0->co, t[0]->co) >= s->epsilon.eps_sq);
- BLI_assert(len_squared_v3v3(e_v0->co, t[1]->co) >= s->epsilon.eps_sq);
- BLI_assert(len_squared_v3v3(e_v0->co, t[2]->co) >= s->epsilon.eps_sq);
- BLI_assert(len_squared_v3v3(e_v1->co, t[0]->co) >= s->epsilon.eps_sq);
- BLI_assert(len_squared_v3v3(e_v1->co, t[1]->co) >= s->epsilon.eps_sq);
- BLI_assert(len_squared_v3v3(e_v1->co, t[2]->co) >= s->epsilon.eps_sq);
+ BLI_assert(len_squared_v3v3(e_v0->co, t[0]->co) >= s->epsilon.eps_sq);
+ BLI_assert(len_squared_v3v3(e_v0->co, t[1]->co) >= s->epsilon.eps_sq);
+ BLI_assert(len_squared_v3v3(e_v0->co, t[2]->co) >= s->epsilon.eps_sq);
+ BLI_assert(len_squared_v3v3(e_v1->co, t[0]->co) >= s->epsilon.eps_sq);
+ BLI_assert(len_squared_v3v3(e_v1->co, t[1]->co) >= s->epsilon.eps_sq);
+ BLI_assert(len_squared_v3v3(e_v1->co, t[2]->co) >= s->epsilon.eps_sq);
#endif
-#define KEY_SET(k, i0, i1, i2, i3) { \
- (k)[0] = i0; \
- (k)[1] = i1; \
- (k)[2] = i2; \
- (k)[3] = i3; \
-} (void)0
-
- /* order tri, then order (1-2, 2-3)*/
-#define KEY_EDGE_TRI_ORDER(k) { \
- if (k[2] > k[3]) { \
- SWAP(int, k[2], k[3]); \
- } \
- if (k[0] > k[2]) { \
- SWAP(int, k[0], k[2]); \
- SWAP(int, k[1], k[3]); \
- } \
-} (void)0
-
- KEY_SET(k_arr[IX_EDGE_TRI], BM_elem_index_get(e_v0), BM_elem_index_get(e_v1), t_index, -1);
- /* need to order here */
- KEY_SET(k_arr[IX_EDGE_TRI_EDGE0], BM_elem_index_get(e_v0), BM_elem_index_get(e_v1), ti[0], ti[1]);
- KEY_SET(k_arr[IX_EDGE_TRI_EDGE1], BM_elem_index_get(e_v0), BM_elem_index_get(e_v1), ti[1], ti[2]);
- KEY_SET(k_arr[IX_EDGE_TRI_EDGE2], BM_elem_index_get(e_v0), BM_elem_index_get(e_v1), ti[2], ti[0]);
-
- KEY_EDGE_TRI_ORDER(k_arr[IX_EDGE_TRI_EDGE0]);
- KEY_EDGE_TRI_ORDER(k_arr[IX_EDGE_TRI_EDGE1]);
- KEY_EDGE_TRI_ORDER(k_arr[IX_EDGE_TRI_EDGE2]);
+#define KEY_SET(k, i0, i1, i2, i3) \
+ { \
+ (k)[0] = i0; \
+ (k)[1] = i1; \
+ (k)[2] = i2; \
+ (k)[3] = i3; \
+ } \
+ (void)0
+
+ /* order tri, then order (1-2, 2-3)*/
+#define KEY_EDGE_TRI_ORDER(k) \
+ { \
+ if (k[2] > k[3]) { \
+ SWAP(int, k[2], k[3]); \
+ } \
+ if (k[0] > k[2]) { \
+ SWAP(int, k[0], k[2]); \
+ SWAP(int, k[1], k[3]); \
+ } \
+ } \
+ (void)0
+
+ KEY_SET(k_arr[IX_EDGE_TRI], BM_elem_index_get(e_v0), BM_elem_index_get(e_v1), t_index, -1);
+ /* need to order here */
+ KEY_SET(
+ k_arr[IX_EDGE_TRI_EDGE0], BM_elem_index_get(e_v0), BM_elem_index_get(e_v1), ti[0], ti[1]);
+ KEY_SET(
+ k_arr[IX_EDGE_TRI_EDGE1], BM_elem_index_get(e_v0), BM_elem_index_get(e_v1), ti[1], ti[2]);
+ KEY_SET(
+ k_arr[IX_EDGE_TRI_EDGE2], BM_elem_index_get(e_v0), BM_elem_index_get(e_v1), ti[2], ti[0]);
+
+ KEY_EDGE_TRI_ORDER(k_arr[IX_EDGE_TRI_EDGE0]);
+ KEY_EDGE_TRI_ORDER(k_arr[IX_EDGE_TRI_EDGE1]);
+ KEY_EDGE_TRI_ORDER(k_arr[IX_EDGE_TRI_EDGE2]);
#undef KEY_SET
#undef KEY_EDGE_TRI_ORDER
+ for (i = 0; i < ARRAY_SIZE(k_arr); i++) {
+ BMVert *iv;
+ iv = BLI_ghash_lookup(s->edgetri_cache, k_arr[i]);
- for (i = 0; i < ARRAY_SIZE(k_arr); i++) {
- BMVert *iv;
-
- iv = BLI_ghash_lookup(s->edgetri_cache, k_arr[i]);
-
- if (iv) {
+ if (iv) {
#ifdef USE_DUMP
- printf("# cache hit (%d, %d, %d, %d)\n", UNPACK4(k_arr[i]));
+ printf("# cache hit (%d, %d, %d, %d)\n", UNPACK4(k_arr[i]));
#endif
- *r_side = (enum ISectType)i;
- return iv;
- }
- }
-
- *r_side = intersect_line_tri(e_v0->co, e_v1->co, t_cos, t_nor, ix, &s->epsilon);
- if (*r_side != IX_NONE) {
- BMVert *iv;
- BMEdge *e;
+ *r_side = (enum ISectType)i;
+ return iv;
+ }
+ }
+
+ *r_side = intersect_line_tri(e_v0->co, e_v1->co, t_cos, t_nor, ix, &s->epsilon);
+ if (*r_side != IX_NONE) {
+ BMVert *iv;
+ BMEdge *e;
#ifdef USE_DUMP
- printf("# new vertex (%.6f, %.6f, %.6f) %d\n", UNPACK3(ix), *r_side);
+ printf("# new vertex (%.6f, %.6f, %.6f) %d\n", UNPACK3(ix), *r_side);
#endif
#ifdef USE_PARANOID
- BLI_assert(len_squared_v3v3(ix, e_v0->co) > s->epsilon.eps_sq);
- BLI_assert(len_squared_v3v3(ix, e_v1->co) > s->epsilon.eps_sq);
- BLI_assert(len_squared_v3v3(ix, t[0]->co) > s->epsilon.eps_sq);
- BLI_assert(len_squared_v3v3(ix, t[1]->co) > s->epsilon.eps_sq);
- BLI_assert(len_squared_v3v3(ix, t[2]->co) > s->epsilon.eps_sq);
+ BLI_assert(len_squared_v3v3(ix, e_v0->co) > s->epsilon.eps_sq);
+ BLI_assert(len_squared_v3v3(ix, e_v1->co) > s->epsilon.eps_sq);
+ BLI_assert(len_squared_v3v3(ix, t[0]->co) > s->epsilon.eps_sq);
+ BLI_assert(len_squared_v3v3(ix, t[1]->co) > s->epsilon.eps_sq);
+ BLI_assert(len_squared_v3v3(ix, t[2]->co) > s->epsilon.eps_sq);
#endif
- iv = BM_vert_create(bm, ix, NULL, 0);
+ iv = BM_vert_create(bm, ix, NULL, 0);
- e = BM_edge_exists(e_v0, e_v1);
- if (e) {
+ e = BM_edge_exists(e_v0, e_v1);
+ if (e) {
#ifdef USE_DUMP
- printf("# adding to edge %d\n", BM_elem_index_get(e));
+ printf("# adding to edge %d\n", BM_elem_index_get(e));
#endif
- edge_verts_add(s, e, iv, false);
- }
- else {
+ edge_verts_add(s, e, iv, false);
+ }
+ else {
#ifdef USE_DISSOLVE
- vert_dissolve_add(s, iv);
+ vert_dissolve_add(s, iv);
#endif
- }
+ }
- if ((*r_side >= IX_EDGE_TRI_EDGE0) && (*r_side <= IX_EDGE_TRI_EDGE2)) {
- i = (uint)(*r_side - IX_EDGE_TRI_EDGE0);
- e = BM_edge_exists(t[i], t[(i + 1) % 3]);
- if (e) {
- edge_verts_add(s, e, iv, false);
- }
- }
+ if ((*r_side >= IX_EDGE_TRI_EDGE0) && (*r_side <= IX_EDGE_TRI_EDGE2)) {
+ i = (uint)(*r_side - IX_EDGE_TRI_EDGE0);
+ e = BM_edge_exists(t[i], t[(i + 1) % 3]);
+ if (e) {
+ edge_verts_add(s, e, iv, false);
+ }
+ }
- {
- int *k = BLI_memarena_alloc(s->mem_arena, sizeof(int[4]));
- memcpy(k, k_arr[*r_side], sizeof(int[4]));
- BLI_ghash_insert(s->edgetri_cache, k, iv);
- }
+ {
+ int *k = BLI_memarena_alloc(s->mem_arena, sizeof(int[4]));
+ memcpy(k, k_arr[*r_side], sizeof(int[4]));
+ BLI_ghash_insert(s->edgetri_cache, k, iv);
+ }
- return iv;
+ return iv;
+ }
- }
+ *r_side = IX_NONE;
- *r_side = IX_NONE;
-
- return NULL;
+ return NULL;
}
struct LoopFilterWrap {
- int (*test_fn)(BMFace *f, void *user_data);
- void *user_data;
+ int (*test_fn)(BMFace *f, void *user_data);
+ void *user_data;
};
static bool bm_loop_filter_fn(const BMLoop *l, void *user_data)
{
- if (BM_elem_flag_test(l->e, BM_ELEM_TAG)) {
- return false;
- }
-
- if (l->radial_next != l) {
- struct LoopFilterWrap *data = user_data;
- BMLoop *l_iter = l->radial_next;
- const int face_side = data->test_fn(l->f, data->user_data);
- do {
- const int face_side_other = data->test_fn(l_iter->f, data->user_data);
- if (UNLIKELY(face_side_other == -1)) {
- /* pass */
- }
- else if (face_side_other != face_side) {
- return false;
- }
- } while ((l_iter = l_iter->radial_next) != l);
- return true;
- }
- return false;
+ if (BM_elem_flag_test(l->e, BM_ELEM_TAG)) {
+ return false;
+ }
+
+ if (l->radial_next != l) {
+ struct LoopFilterWrap *data = user_data;
+ BMLoop *l_iter = l->radial_next;
+ const int face_side = data->test_fn(l->f, data->user_data);
+ do {
+ const int face_side_other = data->test_fn(l_iter->f, data->user_data);
+ if (UNLIKELY(face_side_other == -1)) {
+ /* pass */
+ }
+ else if (face_side_other != face_side) {
+ return false;
+ }
+ } while ((l_iter = l_iter->radial_next) != l);
+ return true;
+ }
+ return false;
}
/**
* Return true if we have any intersections.
*/
static void bm_isect_tri_tri(
- struct ISectState *s,
- int a_index, int b_index,
- BMLoop **a, BMLoop **b)
+ struct ISectState *s, int a_index, int b_index, BMLoop **a, BMLoop **b)
{
- BMFace *f_a = (*a)->f;
- BMFace *f_b = (*b)->f;
- BMVert *fv_a[3] = {UNPACK3_EX(, a, ->v)};
- BMVert *fv_b[3] = {UNPACK3_EX(, b, ->v)};
- const float *f_a_cos[3] = {UNPACK3_EX(, fv_a, ->co)};
- const float *f_b_cos[3] = {UNPACK3_EX(, fv_b, ->co)};
- float f_a_nor[3];
- float f_b_nor[3];
- uint i;
-
-
- /* should be enough but may need to bump */
- BMVert *iv_ls_a[8];
- BMVert *iv_ls_b[8];
- STACK_DECLARE(iv_ls_a);
- STACK_DECLARE(iv_ls_b);
-
- if (UNLIKELY(ELEM(fv_a[0], UNPACK3(fv_b)) ||
- ELEM(fv_a[1], UNPACK3(fv_b)) ||
- ELEM(fv_a[2], UNPACK3(fv_b))))
- {
- return;
- }
-
- STACK_INIT(iv_ls_a, ARRAY_SIZE(iv_ls_a));
- STACK_INIT(iv_ls_b, ARRAY_SIZE(iv_ls_b));
+ BMFace *f_a = (*a)->f;
+ BMFace *f_b = (*b)->f;
+ BMVert *fv_a[3] = {UNPACK3_EX(, a, ->v)};
+ BMVert *fv_b[3] = {UNPACK3_EX(, b, ->v)};
+ const float *f_a_cos[3] = {UNPACK3_EX(, fv_a, ->co)};
+ const float *f_b_cos[3] = {UNPACK3_EX(, fv_b, ->co)};
+ float f_a_nor[3];
+ float f_b_nor[3];
+ uint i;
+
+ /* should be enough but may need to bump */
+ BMVert *iv_ls_a[8];
+ BMVert *iv_ls_b[8];
+ STACK_DECLARE(iv_ls_a);
+ STACK_DECLARE(iv_ls_b);
+
+ if (UNLIKELY(ELEM(fv_a[0], UNPACK3(fv_b)) || ELEM(fv_a[1], UNPACK3(fv_b)) ||
+ ELEM(fv_a[2], UNPACK3(fv_b)))) {
+ return;
+ }
+
+ STACK_INIT(iv_ls_a, ARRAY_SIZE(iv_ls_a));
+ STACK_INIT(iv_ls_b, ARRAY_SIZE(iv_ls_b));
#define VERT_VISIT_A _FLAG_WALK
#define VERT_VISIT_B _FLAG_WALK_ALT
#define STACK_PUSH_TEST_A(ele) \
- if (BM_ELEM_API_FLAG_TEST(ele, VERT_VISIT_A) == 0) { \
- BM_ELEM_API_FLAG_ENABLE(ele, VERT_VISIT_A); \
- STACK_PUSH(iv_ls_a, ele); \
- } ((void)0)
+ if (BM_ELEM_API_FLAG_TEST(ele, VERT_VISIT_A) == 0) { \
+ BM_ELEM_API_FLAG_ENABLE(ele, VERT_VISIT_A); \
+ STACK_PUSH(iv_ls_a, ele); \
+ } \
+ ((void)0)
#define STACK_PUSH_TEST_B(ele) \
- if (BM_ELEM_API_FLAG_TEST(ele, VERT_VISIT_B) == 0) { \
- BM_ELEM_API_FLAG_ENABLE(ele, VERT_VISIT_B); \
- STACK_PUSH(iv_ls_b, ele); \
- } ((void)0)
-
-
- /* vert-vert
- * --------- */
- {
- /* first check in any verts are touching
- * (any case where we wont create new verts)
- */
- uint i_a;
- for (i_a = 0; i_a < 3; i_a++) {
- uint i_b;
- for (i_b = 0; i_b < 3; i_b++) {
- if (len_squared_v3v3(fv_a[i_a]->co, fv_b[i_b]->co) <= s->epsilon.eps2x_sq) {
+ if (BM_ELEM_API_FLAG_TEST(ele, VERT_VISIT_B) == 0) { \
+ BM_ELEM_API_FLAG_ENABLE(ele, VERT_VISIT_B); \
+ STACK_PUSH(iv_ls_b, ele); \
+ } \
+ ((void)0)
+
+ /* vert-vert
+ * --------- */
+ {
+ /* first check in any verts are touching
+ * (any case where we wont create new verts)
+ */
+ uint i_a;
+ for (i_a = 0; i_a < 3; i_a++) {
+ uint i_b;
+ for (i_b = 0; i_b < 3; i_b++) {
+ if (len_squared_v3v3(fv_a[i_a]->co, fv_b[i_b]->co) <= s->epsilon.eps2x_sq) {
#ifdef USE_DUMP
- if (BM_ELEM_API_FLAG_TEST(fv_a[i_a], VERT_VISIT) == 0) {
- printf(" ('VERT-VERT-A') %d, %d),\n",
- i_a, BM_elem_index_get(fv_a[i_a]));
- }
- if (BM_ELEM_API_FLAG_TEST(fv_b[i_b], VERT_VISIT) == 0) {
- printf(" ('VERT-VERT-B') %d, %d),\n",
- i_b, BM_elem_index_get(fv_b[i_b]));
- }
+ if (BM_ELEM_API_FLAG_TEST(fv_a[i_a], VERT_VISIT) == 0) {
+ printf(" ('VERT-VERT-A') %d, %d),\n", i_a, BM_elem_index_get(fv_a[i_a]));
+ }
+ if (BM_ELEM_API_FLAG_TEST(fv_b[i_b], VERT_VISIT) == 0) {
+ printf(" ('VERT-VERT-B') %d, %d),\n", i_b, BM_elem_index_get(fv_b[i_b]));
+ }
#endif
- STACK_PUSH_TEST_A(fv_a[i_a]);
- STACK_PUSH_TEST_B(fv_b[i_b]);
- }
- }
- }
- }
-
- /* vert-edge
- * --------- */
- {
- uint i_a;
- for (i_a = 0; i_a < 3; i_a++) {
- if (BM_ELEM_API_FLAG_TEST(fv_a[i_a], VERT_VISIT_A) == 0) {
- uint i_b_e0;
- for (i_b_e0 = 0; i_b_e0 < 3; i_b_e0++) {
- uint i_b_e1 = (i_b_e0 + 1) % 3;
-
- if (BM_ELEM_API_FLAG_TEST(fv_b[i_b_e0], VERT_VISIT_B) ||
- BM_ELEM_API_FLAG_TEST(fv_b[i_b_e1], VERT_VISIT_B))
- {
- continue;
- }
-
- const float fac = line_point_factor_v3(fv_a[i_a]->co, fv_b[i_b_e0]->co, fv_b[i_b_e1]->co);
- if ((fac > 0.0f - s->epsilon.eps) && (fac < 1.0f + s->epsilon.eps)) {
- float ix[3];
- interp_v3_v3v3(ix, fv_b[i_b_e0]->co, fv_b[i_b_e1]->co, fac);
- if (len_squared_v3v3(ix, fv_a[i_a]->co) <= s->epsilon.eps2x_sq) {
- BMEdge *e;
- STACK_PUSH_TEST_B(fv_a[i_a]);
- // STACK_PUSH_TEST_A(fv_a[i_a]);
- e = BM_edge_exists(fv_b[i_b_e0], fv_b[i_b_e1]);
+ STACK_PUSH_TEST_A(fv_a[i_a]);
+ STACK_PUSH_TEST_B(fv_b[i_b]);
+ }
+ }
+ }
+ }
+
+ /* vert-edge
+ * --------- */
+ {
+ uint i_a;
+ for (i_a = 0; i_a < 3; i_a++) {
+ if (BM_ELEM_API_FLAG_TEST(fv_a[i_a], VERT_VISIT_A) == 0) {
+ uint i_b_e0;
+ for (i_b_e0 = 0; i_b_e0 < 3; i_b_e0++) {
+ uint i_b_e1 = (i_b_e0 + 1) % 3;
+
+ if (BM_ELEM_API_FLAG_TEST(fv_b[i_b_e0], VERT_VISIT_B) ||
+ BM_ELEM_API_FLAG_TEST(fv_b[i_b_e1], VERT_VISIT_B)) {
+ continue;
+ }
+
+ const float fac = line_point_factor_v3(
+ fv_a[i_a]->co, fv_b[i_b_e0]->co, fv_b[i_b_e1]->co);
+ if ((fac > 0.0f - s->epsilon.eps) && (fac < 1.0f + s->epsilon.eps)) {
+ float ix[3];
+ interp_v3_v3v3(ix, fv_b[i_b_e0]->co, fv_b[i_b_e1]->co, fac);
+ if (len_squared_v3v3(ix, fv_a[i_a]->co) <= s->epsilon.eps2x_sq) {
+ BMEdge *e;
+ STACK_PUSH_TEST_B(fv_a[i_a]);
+ // STACK_PUSH_TEST_A(fv_a[i_a]);
+ e = BM_edge_exists(fv_b[i_b_e0], fv_b[i_b_e1]);
#ifdef USE_DUMP
- printf(" ('VERT-EDGE-A', %d, %d),\n",
- BM_elem_index_get(fv_b[i_b_e0]), BM_elem_index_get(fv_b[i_b_e1]));
+ printf(" ('VERT-EDGE-A', %d, %d),\n",
+ BM_elem_index_get(fv_b[i_b_e0]),
+ BM_elem_index_get(fv_b[i_b_e1]));
#endif
- if (e) {
+ if (e) {
#ifdef USE_DUMP
- printf("# adding to edge %d\n", BM_elem_index_get(e));
+ printf("# adding to edge %d\n", BM_elem_index_get(e));
#endif
- edge_verts_add(s, e, fv_a[i_a], true);
- }
- break;
- }
- }
- }
- }
- }
- }
-
- {
- uint i_b;
- for (i_b = 0; i_b < 3; i_b++) {
- if (BM_ELEM_API_FLAG_TEST(fv_b[i_b], VERT_VISIT_B) == 0) {
- uint i_a_e0;
- for (i_a_e0 = 0; i_a_e0 < 3; i_a_e0++) {
- uint i_a_e1 = (i_a_e0 + 1) % 3;
-
- if (BM_ELEM_API_FLAG_TEST(fv_a[i_a_e0], VERT_VISIT_A) ||
- BM_ELEM_API_FLAG_TEST(fv_a[i_a_e1], VERT_VISIT_A))
- {
- continue;
- }
-
- const float fac = line_point_factor_v3(fv_b[i_b]->co, fv_a[i_a_e0]->co, fv_a[i_a_e1]->co);
- if ((fac > 0.0f - s->epsilon.eps) && (fac < 1.0f + s->epsilon.eps)) {
- float ix[3];
- interp_v3_v3v3(ix, fv_a[i_a_e0]->co, fv_a[i_a_e1]->co, fac);
- if (len_squared_v3v3(ix, fv_b[i_b]->co) <= s->epsilon.eps2x_sq) {
- BMEdge *e;
- STACK_PUSH_TEST_A(fv_b[i_b]);
- // STACK_PUSH_NOTEST(iv_ls_b, fv_b[i_b]);
- e = BM_edge_exists(fv_a[i_a_e0], fv_a[i_a_e1]);
+ edge_verts_add(s, e, fv_a[i_a], true);
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ {
+ uint i_b;
+ for (i_b = 0; i_b < 3; i_b++) {
+ if (BM_ELEM_API_FLAG_TEST(fv_b[i_b], VERT_VISIT_B) == 0) {
+ uint i_a_e0;
+ for (i_a_e0 = 0; i_a_e0 < 3; i_a_e0++) {
+ uint i_a_e1 = (i_a_e0 + 1) % 3;
+
+ if (BM_ELEM_API_FLAG_TEST(fv_a[i_a_e0], VERT_VISIT_A) ||
+ BM_ELEM_API_FLAG_TEST(fv_a[i_a_e1], VERT_VISIT_A)) {
+ continue;
+ }
+
+ const float fac = line_point_factor_v3(
+ fv_b[i_b]->co, fv_a[i_a_e0]->co, fv_a[i_a_e1]->co);
+ if ((fac > 0.0f - s->epsilon.eps) && (fac < 1.0f + s->epsilon.eps)) {
+ float ix[3];
+ interp_v3_v3v3(ix, fv_a[i_a_e0]->co, fv_a[i_a_e1]->co, fac);
+ if (len_squared_v3v3(ix, fv_b[i_b]->co) <= s->epsilon.eps2x_sq) {
+ BMEdge *e;
+ STACK_PUSH_TEST_A(fv_b[i_b]);
+ // STACK_PUSH_NOTEST(iv_ls_b, fv_b[i_b]);
+ e = BM_edge_exists(fv_a[i_a_e0], fv_a[i_a_e1]);
#ifdef USE_DUMP
- printf(" ('VERT-EDGE-B', %d, %d),\n",
- BM_elem_index_get(fv_a[i_a_e0]), BM_elem_index_get(fv_a[i_a_e1]));
+ printf(" ('VERT-EDGE-B', %d, %d),\n",
+ BM_elem_index_get(fv_a[i_a_e0]),
+ BM_elem_index_get(fv_a[i_a_e1]));
#endif
- if (e) {
+ if (e) {
#ifdef USE_DUMP
- printf("# adding to edge %d\n", BM_elem_index_get(e));
+ printf("# adding to edge %d\n", BM_elem_index_get(e));
#endif
- edge_verts_add(s, e, fv_b[i_b], true);
- }
- break;
- }
- }
- }
- }
- }
- }
-
- /* vert-tri
- * -------- */
- {
-
- float t_scale[3][3];
- uint i_a;
-
- copy_v3_v3(t_scale[0], fv_b[0]->co);
- copy_v3_v3(t_scale[1], fv_b[1]->co);
- copy_v3_v3(t_scale[2], fv_b[2]->co);
- tri_v3_scale(UNPACK3(t_scale), 1.0f - s->epsilon.eps2x);
-
- // second check for verts intersecting the triangle
- for (i_a = 0; i_a < 3; i_a++) {
- if (BM_ELEM_API_FLAG_TEST(fv_a[i_a], VERT_VISIT_A)) {
- continue;
- }
-
- float ix[3];
- if (isect_point_tri_v3(fv_a[i_a]->co, UNPACK3(t_scale), ix)) {
- if (len_squared_v3v3(ix, fv_a[i_a]->co) <= s->epsilon.eps2x_sq) {
- STACK_PUSH_TEST_A(fv_a[i_a]);
- STACK_PUSH_TEST_B(fv_a[i_a]);
+ edge_verts_add(s, e, fv_b[i_b], true);
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* vert-tri
+ * -------- */
+ {
+
+ float t_scale[3][3];
+ uint i_a;
+
+ copy_v3_v3(t_scale[0], fv_b[0]->co);
+ copy_v3_v3(t_scale[1], fv_b[1]->co);
+ copy_v3_v3(t_scale[2], fv_b[2]->co);
+ tri_v3_scale(UNPACK3(t_scale), 1.0f - s->epsilon.eps2x);
+
+ // second check for verts intersecting the triangle
+ for (i_a = 0; i_a < 3; i_a++) {
+ if (BM_ELEM_API_FLAG_TEST(fv_a[i_a], VERT_VISIT_A)) {
+ continue;
+ }
+
+ float ix[3];
+ if (isect_point_tri_v3(fv_a[i_a]->co, UNPACK3(t_scale), ix)) {
+ if (len_squared_v3v3(ix, fv_a[i_a]->co) <= s->epsilon.eps2x_sq) {
+ STACK_PUSH_TEST_A(fv_a[i_a]);
+ STACK_PUSH_TEST_B(fv_a[i_a]);
#ifdef USE_DUMP
- printf(" 'VERT TRI-A',\n");
+ printf(" 'VERT TRI-A',\n");
#endif
- }
- }
- }
- }
-
- {
- float t_scale[3][3];
- uint i_b;
-
- copy_v3_v3(t_scale[0], fv_a[0]->co);
- copy_v3_v3(t_scale[1], fv_a[1]->co);
- copy_v3_v3(t_scale[2], fv_a[2]->co);
- tri_v3_scale(UNPACK3(t_scale), 1.0f - s->epsilon.eps2x);
-
- for (i_b = 0; i_b < 3; i_b++) {
- if (BM_ELEM_API_FLAG_TEST(fv_b[i_b], VERT_VISIT_B)) {
- continue;
- }
-
- float ix[3];
- if (isect_point_tri_v3(fv_b[i_b]->co, UNPACK3(t_scale), ix)) {
- if (len_squared_v3v3(ix, fv_b[i_b]->co) <= s->epsilon.eps2x_sq) {
- STACK_PUSH_TEST_A(fv_b[i_b]);
- STACK_PUSH_TEST_B(fv_b[i_b]);
+ }
+ }
+ }
+ }
+
+ {
+ float t_scale[3][3];
+ uint i_b;
+
+ copy_v3_v3(t_scale[0], fv_a[0]->co);
+ copy_v3_v3(t_scale[1], fv_a[1]->co);
+ copy_v3_v3(t_scale[2], fv_a[2]->co);
+ tri_v3_scale(UNPACK3(t_scale), 1.0f - s->epsilon.eps2x);
+
+ for (i_b = 0; i_b < 3; i_b++) {
+ if (BM_ELEM_API_FLAG_TEST(fv_b[i_b], VERT_VISIT_B)) {
+ continue;
+ }
+
+ float ix[3];
+ if (isect_point_tri_v3(fv_b[i_b]->co, UNPACK3(t_scale), ix)) {
+ if (len_squared_v3v3(ix, fv_b[i_b]->co) <= s->epsilon.eps2x_sq) {
+ STACK_PUSH_TEST_A(fv_b[i_b]);
+ STACK_PUSH_TEST_B(fv_b[i_b]);
#ifdef USE_DUMP
- printf(" 'VERT TRI-B',\n");
+ printf(" 'VERT TRI-B',\n");
#endif
- }
- }
- }
- }
-
- if ((STACK_SIZE(iv_ls_a) >= 3) &&
- (STACK_SIZE(iv_ls_b) >= 3))
- {
+ }
+ }
+ }
+ }
+
+ if ((STACK_SIZE(iv_ls_a) >= 3) && (STACK_SIZE(iv_ls_b) >= 3)) {
#ifdef USE_DUMP
- printf("# OVERLAP\n");
+ printf("# OVERLAP\n");
#endif
- goto finally;
- }
-
- normal_tri_v3(f_a_nor, UNPACK3(f_a_cos));
- normal_tri_v3(f_b_nor, UNPACK3(f_b_cos));
-
- /* edge-tri & edge-edge
- * -------------------- */
- {
- for (uint i_a_e0 = 0; i_a_e0 < 3; i_a_e0++) {
- uint i_a_e1 = (i_a_e0 + 1) % 3;
- enum ISectType side;
- BMVert *iv;
-
- if (BM_ELEM_API_FLAG_TEST(fv_a[i_a_e0], VERT_VISIT_A) ||
- BM_ELEM_API_FLAG_TEST(fv_a[i_a_e1], VERT_VISIT_A))
- {
- continue;
- }
-
- iv = bm_isect_edge_tri(s, fv_a[i_a_e0], fv_a[i_a_e1], fv_b, b_index, f_b_cos, f_b_nor, &side);
- if (iv) {
- STACK_PUSH_TEST_A(iv);
- STACK_PUSH_TEST_B(iv);
+ goto finally;
+ }
+
+ normal_tri_v3(f_a_nor, UNPACK3(f_a_cos));
+ normal_tri_v3(f_b_nor, UNPACK3(f_b_cos));
+
+ /* edge-tri & edge-edge
+ * -------------------- */
+ {
+ for (uint i_a_e0 = 0; i_a_e0 < 3; i_a_e0++) {
+ uint i_a_e1 = (i_a_e0 + 1) % 3;
+ enum ISectType side;
+ BMVert *iv;
+
+ if (BM_ELEM_API_FLAG_TEST(fv_a[i_a_e0], VERT_VISIT_A) ||
+ BM_ELEM_API_FLAG_TEST(fv_a[i_a_e1], VERT_VISIT_A)) {
+ continue;
+ }
+
+ iv = bm_isect_edge_tri(
+ s, fv_a[i_a_e0], fv_a[i_a_e1], fv_b, b_index, f_b_cos, f_b_nor, &side);
+ if (iv) {
+ STACK_PUSH_TEST_A(iv);
+ STACK_PUSH_TEST_B(iv);
#ifdef USE_DUMP
- printf(" ('EDGE-TRI-A', %d),\n", side);
+ printf(" ('EDGE-TRI-A', %d),\n", side);
#endif
- }
- }
-
- for (uint i_b_e0 = 0; i_b_e0 < 3; i_b_e0++) {
- uint i_b_e1 = (i_b_e0 + 1) % 3;
- enum ISectType side;
- BMVert *iv;
-
- if (BM_ELEM_API_FLAG_TEST(fv_b[i_b_e0], VERT_VISIT_B) ||
- BM_ELEM_API_FLAG_TEST(fv_b[i_b_e1], VERT_VISIT_B))
- {
- continue;
- }
-
- iv = bm_isect_edge_tri(s, fv_b[i_b_e0], fv_b[i_b_e1], fv_a, a_index, f_a_cos, f_a_nor, &side);
- if (iv) {
- STACK_PUSH_TEST_A(iv);
- STACK_PUSH_TEST_B(iv);
+ }
+ }
+
+ for (uint i_b_e0 = 0; i_b_e0 < 3; i_b_e0++) {
+ uint i_b_e1 = (i_b_e0 + 1) % 3;
+ enum ISectType side;
+ BMVert *iv;
+
+ if (BM_ELEM_API_FLAG_TEST(fv_b[i_b_e0], VERT_VISIT_B) ||
+ BM_ELEM_API_FLAG_TEST(fv_b[i_b_e1], VERT_VISIT_B)) {
+ continue;
+ }
+
+ iv = bm_isect_edge_tri(
+ s, fv_b[i_b_e0], fv_b[i_b_e1], fv_a, a_index, f_a_cos, f_a_nor, &side);
+ if (iv) {
+ STACK_PUSH_TEST_A(iv);
+ STACK_PUSH_TEST_B(iv);
#ifdef USE_DUMP
- printf(" ('EDGE-TRI-B', %d),\n", side);
+ printf(" ('EDGE-TRI-B', %d),\n", side);
#endif
- }
- }
- }
-
- {
- for (i = 0; i < 2; i++) {
- BMVert **ie_vs;
- BMFace *f;
- bool ie_exists;
- BMEdge *ie;
-
- if (i == 0) {
- if (STACK_SIZE(iv_ls_a) != 2) {
- continue;
- }
- ie_vs = iv_ls_a;
- f = f_a;
- }
- else {
- if (STACK_SIZE(iv_ls_b) != 2) {
- continue;
- }
- ie_vs = iv_ls_b;
- f = f_b;
- }
-
- /* possible but unlikely we get this - for edge-edge intersection */
- ie = BM_edge_exists(UNPACK2(ie_vs));
- if (ie == NULL) {
- ie_exists = false;
- /* one of the verts must be new if we are making an edge
- * ...no, we need this in case 2x quads intersect at either ends.
- * if not (ie_vs[0].index == -1 or ie_vs[1].index == -1):
- * continue */
- ie = BM_edge_create(s->bm, UNPACK2(ie_vs), NULL, 0);
- BLI_gset_insert(s->wire_edges, ie);
- }
- else {
- ie_exists = true;
- /* may already exist */
- BLI_gset_add(s->wire_edges, ie);
-
- if (BM_edge_in_face(ie, f)) {
- continue;
- }
- }
-
- face_edges_add(s, BM_elem_index_get(f), ie, ie_exists);
- // BLI_assert(len(ie_vs) <= 2)
- }
- }
+ }
+ }
+ }
+
+ {
+ for (i = 0; i < 2; i++) {
+ BMVert **ie_vs;
+ BMFace *f;
+ bool ie_exists;
+ BMEdge *ie;
+
+ if (i == 0) {
+ if (STACK_SIZE(iv_ls_a) != 2) {
+ continue;
+ }
+ ie_vs = iv_ls_a;
+ f = f_a;
+ }
+ else {
+ if (STACK_SIZE(iv_ls_b) != 2) {
+ continue;
+ }
+ ie_vs = iv_ls_b;
+ f = f_b;
+ }
+
+ /* possible but unlikely we get this - for edge-edge intersection */
+ ie = BM_edge_exists(UNPACK2(ie_vs));
+ if (ie == NULL) {
+ ie_exists = false;
+ /* one of the verts must be new if we are making an edge
+ * ...no, we need this in case 2x quads intersect at either ends.
+ * if not (ie_vs[0].index == -1 or ie_vs[1].index == -1):
+ * continue */
+ ie = BM_edge_create(s->bm, UNPACK2(ie_vs), NULL, 0);
+ BLI_gset_insert(s->wire_edges, ie);
+ }
+ else {
+ ie_exists = true;
+ /* may already exist */
+ BLI_gset_add(s->wire_edges, ie);
+
+ if (BM_edge_in_face(ie, f)) {
+ continue;
+ }
+ }
+
+ face_edges_add(s, BM_elem_index_get(f), ie, ie_exists);
+ // BLI_assert(len(ie_vs) <= 2)
+ }
+ }
finally:
- for (i = 0; i < STACK_SIZE(iv_ls_a); i++) {
- BM_ELEM_API_FLAG_DISABLE(iv_ls_a[i], VERT_VISIT_A); \
- }
- for (i = 0; i < STACK_SIZE(iv_ls_b); i++) {
- BM_ELEM_API_FLAG_DISABLE(iv_ls_b[i], VERT_VISIT_B); \
- }
-
+ for (i = 0; i < STACK_SIZE(iv_ls_a); i++) {
+ BM_ELEM_API_FLAG_DISABLE(iv_ls_a[i], VERT_VISIT_A);
+ }
+ for (i = 0; i < STACK_SIZE(iv_ls_b); i++) {
+ BM_ELEM_API_FLAG_DISABLE(iv_ls_b[i], VERT_VISIT_B);
+ }
}
#ifdef USE_BVH
struct RaycastData {
- const float **looptris;
- BLI_Buffer *z_buffer;
+ const float **looptris;
+ BLI_Buffer *z_buffer;
};
-#ifdef USE_KDOPBVH_WATERTIGHT
+# ifdef USE_KDOPBVH_WATERTIGHT
static const struct IsectRayPrecalc isect_precalc_x = {1, 2, 0, 0, 0, 1};
-#endif
+# endif
static void raycast_callback(void *userdata,
int index,
const BVHTreeRay *ray,
BVHTreeRayHit *UNUSED(hit))
{
- struct RaycastData *raycast_data = userdata;
- const float **looptris = raycast_data->looptris;
- const float *v0 = looptris[index * 3 + 0];
- const float *v1 = looptris[index * 3 + 1];
- const float *v2 = looptris[index * 3 + 2];
- float dist;
-
- if (
-#ifdef USE_KDOPBVH_WATERTIGHT
- isect_ray_tri_watertight_v3(ray->origin, &isect_precalc_x, v0, v1, v2, &dist, NULL)
-#else
- isect_ray_tri_epsilon_v3(ray->origin, ray->direction, v0, v1, v2, &dist, NULL, FLT_EPSILON)
-#endif
- )
- {
- if (dist >= 0.0f) {
-#ifdef USE_DUMP
- printf("%s:\n", __func__);
- print_v3(" origin", ray->origin);
- print_v3(" direction", ray->direction);
- printf(" dist %f\n", dist);
- print_v3(" v0", v0);
- print_v3(" v1", v1);
- print_v3(" v2", v2);
-#endif
-
-#ifdef USE_DUMP
- printf("%s: Adding depth %f\n", __func__, dist);
-#endif
- BLI_buffer_append(raycast_data->z_buffer, float, dist);
- }
- }
+ struct RaycastData *raycast_data = userdata;
+ const float **looptris = raycast_data->looptris;
+ const float *v0 = looptris[index * 3 + 0];
+ const float *v1 = looptris[index * 3 + 1];
+ const float *v2 = looptris[index * 3 + 2];
+ float dist;
+
+ if (
+# ifdef USE_KDOPBVH_WATERTIGHT
+ isect_ray_tri_watertight_v3(ray->origin, &isect_precalc_x, v0, v1, v2, &dist, NULL)
+# else
+ isect_ray_tri_epsilon_v3(ray->origin, ray->direction, v0, v1, v2, &dist, NULL, FLT_EPSILON)
+# endif
+ ) {
+ if (dist >= 0.0f) {
+# ifdef USE_DUMP
+ printf("%s:\n", __func__);
+ print_v3(" origin", ray->origin);
+ print_v3(" direction", ray->direction);
+ printf(" dist %f\n", dist);
+ print_v3(" v0", v0);
+ print_v3(" v1", v1);
+ print_v3(" v2", v2);
+# endif
+
+# ifdef USE_DUMP
+ printf("%s: Adding depth %f\n", __func__, dist);
+# endif
+ BLI_buffer_append(raycast_data->z_buffer, float, dist);
+ }
+ }
}
-static int isect_bvhtree_point_v3(
- BVHTree *tree,
- const float **looptris,
- const float co[3])
+static int isect_bvhtree_point_v3(BVHTree *tree, const float **looptris, const float co[3])
{
- BLI_buffer_declare_static(float, z_buffer, BLI_BUFFER_NOP, 64);
-
- struct RaycastData raycast_data = {
- looptris,
- &z_buffer,
- };
- BVHTreeRayHit hit = {0};
- float dir[3] = {1.0f, 0.0f, 0.0f};
-
- /* Need to initialize hit even tho it's not used.
- * This is to make it so kdotree believes we didn't intersect anything and
- * keeps calling the intersect callback.
- */
- hit.index = -1;
- hit.dist = BVH_RAYCAST_DIST_MAX;
-
- BLI_bvhtree_ray_cast(tree,
- co, dir,
- 0.0f,
- &hit,
- raycast_callback,
- &raycast_data);
-
-#ifdef USE_DUMP
- printf("%s: Total intersections: %d\n", __func__, z_buffer.count);
-#endif
-
- int num_isect;
-
- if (z_buffer.count == 0) {
- num_isect = 0;
- }
- else if (z_buffer.count == 1) {
- num_isect = 1;
- }
- else {
- /* 2 or more */
- const float eps = FLT_EPSILON * 10;
- num_isect = 1; /* always count first */
-
- qsort(z_buffer.data, z_buffer.count, sizeof(float), BLI_sortutil_cmp_float);
-
- const float *depth_arr = z_buffer.data;
- float depth_last = depth_arr[0];
-
- for (uint i = 1; i < z_buffer.count; i++) {
- if (depth_arr[i] - depth_last > eps) {
- depth_last = depth_arr[i];
- num_isect++;
- }
- }
-
- BLI_buffer_free(&z_buffer);
- }
-
-
- // return (num_isect & 1) == 1;
- return num_isect;
+ BLI_buffer_declare_static(float, z_buffer, BLI_BUFFER_NOP, 64);
+
+ struct RaycastData raycast_data = {
+ looptris,
+ &z_buffer,
+ };
+ BVHTreeRayHit hit = {0};
+ float dir[3] = {1.0f, 0.0f, 0.0f};
+
+ /* Need to initialize hit even tho it's not used.
+ * This is to make it so kdotree believes we didn't intersect anything and
+ * keeps calling the intersect callback.
+ */
+ hit.index = -1;
+ hit.dist = BVH_RAYCAST_DIST_MAX;
+
+ BLI_bvhtree_ray_cast(tree, co, dir, 0.0f, &hit, raycast_callback, &raycast_data);
+
+# ifdef USE_DUMP
+ printf("%s: Total intersections: %d\n", __func__, z_buffer.count);
+# endif
+
+ int num_isect;
+
+ if (z_buffer.count == 0) {
+ num_isect = 0;
+ }
+ else if (z_buffer.count == 1) {
+ num_isect = 1;
+ }
+ else {
+ /* 2 or more */
+ const float eps = FLT_EPSILON * 10;
+ num_isect = 1; /* always count first */
+
+ qsort(z_buffer.data, z_buffer.count, sizeof(float), BLI_sortutil_cmp_float);
+
+ const float *depth_arr = z_buffer.data;
+ float depth_last = depth_arr[0];
+
+ for (uint i = 1; i < z_buffer.count; i++) {
+ if (depth_arr[i] - depth_last > eps) {
+ depth_last = depth_arr[i];
+ num_isect++;
+ }
+ }
+
+ BLI_buffer_free(&z_buffer);
+ }
+
+ // return (num_isect & 1) == 1;
+ return num_isect;
}
-#endif /* USE_BVH */
+#endif /* USE_BVH */
/**
* Intersect tessellated faces
@@ -972,710 +950,690 @@ static int isect_bvhtree_point_v3(
* \param boolean_mode: -1: no-boolean, 0: intersection... see #BMESH_ISECT_BOOLEAN_ISECT.
* \return true if the mesh is changed (intersections cut or faces removed from boolean).
*/
-bool BM_mesh_intersect(
- BMesh *bm,
- struct BMLoop *(*looptris)[3], const int looptris_tot,
- int (*test_fn)(BMFace *f, void *user_data), void *user_data,
- const bool use_self, const bool use_separate, const bool use_dissolve, const bool use_island_connect,
- const bool use_partial_connect, const bool use_edge_tag, const int boolean_mode,
- const float eps)
+bool BM_mesh_intersect(BMesh *bm,
+ struct BMLoop *(*looptris)[3],
+ const int looptris_tot,
+ int (*test_fn)(BMFace *f, void *user_data),
+ void *user_data,
+ const bool use_self,
+ const bool use_separate,
+ const bool use_dissolve,
+ const bool use_island_connect,
+ const bool use_partial_connect,
+ const bool use_edge_tag,
+ const int boolean_mode,
+ const float eps)
{
- struct ISectState s;
- const int totface_orig = bm->totface;
+ struct ISectState s;
+ const int totface_orig = bm->totface;
- /* use to check if we made any changes */
- bool has_edit_isect = false, has_edit_boolean = false;
+ /* use to check if we made any changes */
+ bool has_edit_isect = false, has_edit_boolean = false;
- /* needed for boolean, since cutting up faces moves the loops within the face */
- const float **looptri_coords = NULL;
+ /* needed for boolean, since cutting up faces moves the loops within the face */
+ const float **looptri_coords = NULL;
#ifdef USE_BVH
- BVHTree *tree_a, *tree_b;
- uint tree_overlap_tot;
- BVHTreeOverlap *overlap;
+ BVHTree *tree_a, *tree_b;
+ uint tree_overlap_tot;
+ BVHTreeOverlap *overlap;
#else
- int i_a, i_b;
+ int i_a, i_b;
#endif
- s.bm = bm;
+ s.bm = bm;
- s.edgetri_cache = BLI_ghash_new(BLI_ghashutil_inthash_v4_p, BLI_ghashutil_inthash_v4_cmp, __func__);
+ s.edgetri_cache = BLI_ghash_new(
+ BLI_ghashutil_inthash_v4_p, BLI_ghashutil_inthash_v4_cmp, __func__);
- s.edge_verts = BLI_ghash_ptr_new(__func__);
- s.face_edges = BLI_ghash_int_new(__func__);
- s.wire_edges = BLI_gset_ptr_new(__func__);
- s.vert_dissolve = NULL;
+ s.edge_verts = BLI_ghash_ptr_new(__func__);
+ s.face_edges = BLI_ghash_int_new(__func__);
+ s.wire_edges = BLI_gset_ptr_new(__func__);
+ s.vert_dissolve = NULL;
- s.mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+ s.mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
- /* setup epsilon from base */
- s.epsilon.eps = eps;
- s.epsilon.eps2x = eps * 2.0f;
- s.epsilon.eps_margin = s.epsilon.eps2x * 10.0f;
+ /* setup epsilon from base */
+ s.epsilon.eps = eps;
+ s.epsilon.eps2x = eps * 2.0f;
+ s.epsilon.eps_margin = s.epsilon.eps2x * 10.0f;
- s.epsilon.eps_sq = s.epsilon.eps * s.epsilon.eps;
- s.epsilon.eps2x_sq = s.epsilon.eps2x * s.epsilon.eps2x;
- s.epsilon.eps_margin_sq = s.epsilon.eps_margin * s.epsilon.eps_margin;
+ s.epsilon.eps_sq = s.epsilon.eps * s.epsilon.eps;
+ s.epsilon.eps2x_sq = s.epsilon.eps2x * s.epsilon.eps2x;
+ s.epsilon.eps_margin_sq = s.epsilon.eps_margin * s.epsilon.eps_margin;
- BM_mesh_elem_index_ensure(
- bm,
- BM_VERT |
- BM_EDGE |
+ BM_mesh_elem_index_ensure(bm,
+ BM_VERT | BM_EDGE |
#ifdef USE_NET
- BM_FACE |
+ BM_FACE |
#endif
- 0);
-
+ 0);
- BM_mesh_elem_table_ensure(
- bm,
+ BM_mesh_elem_table_ensure(bm,
#ifdef USE_SPLICE
- BM_EDGE |
+ BM_EDGE |
#endif
#ifdef USE_NET
- BM_FACE |
+ BM_FACE |
#endif
- 0);
+ 0);
#ifdef USE_DISSOLVE
- if (use_dissolve) {
- BM_mesh_elem_hflag_disable_all(bm, BM_EDGE | BM_VERT, BM_ELEM_TAG, false);
- }
+ if (use_dissolve) {
+ BM_mesh_elem_hflag_disable_all(bm, BM_EDGE | BM_VERT, BM_ELEM_TAG, false);
+ }
#else
- UNUSED_VARS(use_dissolve);
+ UNUSED_VARS(use_dissolve);
#endif
#ifdef USE_DUMP
- printf("data = [\n");
+ printf("data = [\n");
#endif
- if (boolean_mode != BMESH_ISECT_BOOLEAN_NONE) {
- /* keep original geometrty for raycast callbacks */
- float **cos;
- int i, j;
+ if (boolean_mode != BMESH_ISECT_BOOLEAN_NONE) {
+ /* keep original geometrty for raycast callbacks */
+ float **cos;
+ int i, j;
- cos = MEM_mallocN((size_t)looptris_tot * sizeof(*looptri_coords) * 3, __func__);
- for (i = 0, j = 0; i < looptris_tot; i++) {
- cos[j++] = looptris[i][0]->v->co;
- cos[j++] = looptris[i][1]->v->co;
- cos[j++] = looptris[i][2]->v->co;
- }
- looptri_coords = (const float **)cos;
- }
+ cos = MEM_mallocN((size_t)looptris_tot * sizeof(*looptri_coords) * 3, __func__);
+ for (i = 0, j = 0; i < looptris_tot; i++) {
+ cos[j++] = looptris[i][0]->v->co;
+ cos[j++] = looptris[i][1]->v->co;
+ cos[j++] = looptris[i][2]->v->co;
+ }
+ looptri_coords = (const float **)cos;
+ }
#ifdef USE_BVH
- {
- int i;
- tree_a = BLI_bvhtree_new(looptris_tot, s.epsilon.eps_margin, 8, 8);
- for (i = 0; i < looptris_tot; i++) {
- if (test_fn(looptris[i][0]->f, user_data) == 0) {
- const float t_cos[3][3] = {
- {UNPACK3(looptris[i][0]->v->co)},
- {UNPACK3(looptris[i][1]->v->co)},
- {UNPACK3(looptris[i][2]->v->co)},
- };
-
- BLI_bvhtree_insert(tree_a, i, (const float *)t_cos, 3);
- }
- }
- BLI_bvhtree_balance(tree_a);
- }
-
- if (use_self == false) {
- int i;
- tree_b = BLI_bvhtree_new(looptris_tot, s.epsilon.eps_margin, 8, 8);
- for (i = 0; i < looptris_tot; i++) {
- if (test_fn(looptris[i][0]->f, user_data) == 1) {
- const float t_cos[3][3] = {
- {UNPACK3(looptris[i][0]->v->co)},
- {UNPACK3(looptris[i][1]->v->co)},
- {UNPACK3(looptris[i][2]->v->co)},
- };
-
- BLI_bvhtree_insert(tree_b, i, (const float *)t_cos, 3);
- }
- }
- BLI_bvhtree_balance(tree_b);
- }
- else {
- tree_b = tree_a;
- }
-
- overlap = BLI_bvhtree_overlap(tree_b, tree_a, &tree_overlap_tot, NULL, NULL);
-
- if (overlap) {
- uint i;
-
- for (i = 0; i < tree_overlap_tot; i++) {
-#ifdef USE_DUMP
- printf(" ((%d, %d), (\n",
- overlap[i].indexA,
- overlap[i].indexB);
-#endif
- bm_isect_tri_tri(
- &s,
- overlap[i].indexA,
- overlap[i].indexB,
- looptris[overlap[i].indexA],
- looptris[overlap[i].indexB]);
-#ifdef USE_DUMP
- printf(")),\n");
-#endif
- }
- MEM_freeN(overlap);
- }
-
- if (boolean_mode == BMESH_ISECT_BOOLEAN_NONE) {
- /* no booleans, just free immediate */
- BLI_bvhtree_free(tree_a);
- if (tree_a != tree_b) {
- BLI_bvhtree_free(tree_b);
- }
- }
+ {
+ int i;
+ tree_a = BLI_bvhtree_new(looptris_tot, s.epsilon.eps_margin, 8, 8);
+ for (i = 0; i < looptris_tot; i++) {
+ if (test_fn(looptris[i][0]->f, user_data) == 0) {
+ const float t_cos[3][3] = {
+ {UNPACK3(looptris[i][0]->v->co)},
+ {UNPACK3(looptris[i][1]->v->co)},
+ {UNPACK3(looptris[i][2]->v->co)},
+ };
+
+ BLI_bvhtree_insert(tree_a, i, (const float *)t_cos, 3);
+ }
+ }
+ BLI_bvhtree_balance(tree_a);
+ }
+
+ if (use_self == false) {
+ int i;
+ tree_b = BLI_bvhtree_new(looptris_tot, s.epsilon.eps_margin, 8, 8);
+ for (i = 0; i < looptris_tot; i++) {
+ if (test_fn(looptris[i][0]->f, user_data) == 1) {
+ const float t_cos[3][3] = {
+ {UNPACK3(looptris[i][0]->v->co)},
+ {UNPACK3(looptris[i][1]->v->co)},
+ {UNPACK3(looptris[i][2]->v->co)},
+ };
+
+ BLI_bvhtree_insert(tree_b, i, (const float *)t_cos, 3);
+ }
+ }
+ BLI_bvhtree_balance(tree_b);
+ }
+ else {
+ tree_b = tree_a;
+ }
+
+ overlap = BLI_bvhtree_overlap(tree_b, tree_a, &tree_overlap_tot, NULL, NULL);
+
+ if (overlap) {
+ uint i;
+
+ for (i = 0; i < tree_overlap_tot; i++) {
+# ifdef USE_DUMP
+ printf(" ((%d, %d), (\n", overlap[i].indexA, overlap[i].indexB);
+# endif
+ bm_isect_tri_tri(&s,
+ overlap[i].indexA,
+ overlap[i].indexB,
+ looptris[overlap[i].indexA],
+ looptris[overlap[i].indexB]);
+# ifdef USE_DUMP
+ printf(")),\n");
+# endif
+ }
+ MEM_freeN(overlap);
+ }
+
+ if (boolean_mode == BMESH_ISECT_BOOLEAN_NONE) {
+ /* no booleans, just free immediate */
+ BLI_bvhtree_free(tree_a);
+ if (tree_a != tree_b) {
+ BLI_bvhtree_free(tree_b);
+ }
+ }
#else
- {
- for (i_a = 0; i_a < looptris_tot; i_a++) {
- const int t_a = test_fn(looptris[i_a][0]->f, user_data);
- for (i_b = i_a + 1; i_b < looptris_tot; i_b++) {
- const int t_b = test_fn(looptris[i_b][0]->f, user_data);
-
- if (use_self) {
- if ((t_a != 0) || (t_b != 0)) {
- continue;
- }
- }
- else {
- if ((t_a != t_b) && !ELEM(-1, t_a, t_b)) {
- continue;
- }
- }
-
-#ifdef USE_DUMP
- printf(" ((%d, %d), (",
- i_a, i_b);
-#endif
- bm_isect_tri_tri(
- &s,
- i_a,
- i_b,
- looptris[i_a],
- looptris[i_b]);
-#ifdef USE_DUMP
- printf(")),\n");
-#endif
- }
- }
- }
-#endif /* USE_BVH */
+ {
+ for (i_a = 0; i_a < looptris_tot; i_a++) {
+ const int t_a = test_fn(looptris[i_a][0]->f, user_data);
+ for (i_b = i_a + 1; i_b < looptris_tot; i_b++) {
+ const int t_b = test_fn(looptris[i_b][0]->f, user_data);
+
+ if (use_self) {
+ if ((t_a != 0) || (t_b != 0)) {
+ continue;
+ }
+ }
+ else {
+ if ((t_a != t_b) && !ELEM(-1, t_a, t_b)) {
+ continue;
+ }
+ }
+
+# ifdef USE_DUMP
+ printf(" ((%d, %d), (", i_a, i_b);
+# endif
+ bm_isect_tri_tri(&s, i_a, i_b, looptris[i_a], looptris[i_b]);
+# ifdef USE_DUMP
+ printf(")),\n");
+# endif
+ }
+ }
+ }
+#endif /* USE_BVH */
#ifdef USE_DUMP
- printf("]\n");
+ printf("]\n");
#endif
- /* --------- */
+ /* --------- */
#ifdef USE_SPLICE
- {
- GHashIterator gh_iter;
-
- GHASH_ITER (gh_iter, s.edge_verts) {
- BMEdge *e = BLI_ghashIterator_getKey(&gh_iter);
- struct LinkBase *v_ls_base = BLI_ghashIterator_getValue(&gh_iter);
-
- BMVert *v_start;
- BMVert *v_end;
- BMVert *v_prev;
- bool is_wire;
-
- LinkNode *node;
-
- /* direction is arbitrary, could be swapped */
- v_start = e->v1;
- v_end = e->v2;
-
- if (v_ls_base->list_len > 1) {
- edge_verts_sort(v_start->co, v_ls_base);
- }
-
-#ifdef USE_DUMP
- printf("# SPLITTING EDGE: %d, %d\n", BM_elem_index_get(e), v_ls_base->list_len);
+ {
+ GHashIterator gh_iter;
+
+ GHASH_ITER (gh_iter, s.edge_verts) {
+ BMEdge *e = BLI_ghashIterator_getKey(&gh_iter);
+ struct LinkBase *v_ls_base = BLI_ghashIterator_getValue(&gh_iter);
+
+ BMVert *v_start;
+ BMVert *v_end;
+ BMVert *v_prev;
+ bool is_wire;
+
+ LinkNode *node;
+
+ /* direction is arbitrary, could be swapped */
+ v_start = e->v1;
+ v_end = e->v2;
+
+ if (v_ls_base->list_len > 1) {
+ edge_verts_sort(v_start->co, v_ls_base);
+ }
+
+# ifdef USE_DUMP
+ printf("# SPLITTING EDGE: %d, %d\n", BM_elem_index_get(e), v_ls_base->list_len);
+# endif
+ /* intersect */
+ is_wire = BLI_gset_haskey(s.wire_edges, e);
+
+# ifdef USE_PARANOID
+ for (node = v_ls_base->list; node; node = node->next) {
+ BMVert *_v = node->link;
+ BLI_assert(len_squared_v3v3(_v->co, e->v1->co) > s.epsilon.eps_sq);
+ BLI_assert(len_squared_v3v3(_v->co, e->v2->co) > s.epsilon.eps_sq);
+ }
+# endif
+
+ v_prev = v_start;
+
+ for (node = v_ls_base->list; node; node = node->next) {
+ BMVert *vi = node->link;
+ const float fac = line_point_factor_v3(vi->co, e->v1->co, e->v2->co);
+
+ if (BM_vert_in_edge(e, v_prev)) {
+ BMEdge *e_split;
+ v_prev = BM_edge_split(bm, e, v_prev, &e_split, clamp_f(fac, 0.0f, 1.0f));
+ BLI_assert(BM_vert_in_edge(e, v_end));
+
+ if (!BM_edge_exists(v_prev, vi) && !BM_vert_splice_check_double(v_prev, vi) &&
+ !BM_vert_pair_share_face_check(v_prev, vi)) {
+ BM_vert_splice(bm, vi, v_prev);
+ }
+ else {
+ copy_v3_v3(v_prev->co, vi->co);
+ }
+ v_prev = vi;
+ if (is_wire) {
+ BLI_gset_insert(s.wire_edges, e_split);
+ }
+ }
+ }
+ UNUSED_VARS_NDEBUG(v_end);
+ }
+ }
#endif
- /* intersect */
- is_wire = BLI_gset_haskey(s.wire_edges, e);
-#ifdef USE_PARANOID
- for (node = v_ls_base->list; node; node = node->next) {
- BMVert *_v = node->link;
- BLI_assert(len_squared_v3v3(_v->co, e->v1->co) > s.epsilon.eps_sq);
- BLI_assert(len_squared_v3v3(_v->co, e->v2->co) > s.epsilon.eps_sq);
- }
-#endif
+ /* important to handle before edgenet */
+#ifdef USE_DISSOLVE
+ if (use_dissolve && (boolean_mode == BMESH_ISECT_BOOLEAN_NONE)) {
+ /* first pass */
+ BMVert *(*splice_ls)[2];
+ STACK_DECLARE(splice_ls);
+ LinkNode *node;
+
+ for (node = s.vert_dissolve; node; node = node->next) {
+ BMVert *v = node->link;
+ if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ if (!BM_vert_is_edge_pair(v)) {
+ BM_elem_flag_disable(v, BM_ELEM_TAG);
+ }
+ }
+ }
+
+ splice_ls = MEM_mallocN(BLI_gset_len(s.wire_edges) * sizeof(*splice_ls), __func__);
+ STACK_INIT(splice_ls, BLI_gset_len(s.wire_edges));
+
+ for (node = s.vert_dissolve; node; node = node->next) {
+ BMEdge *e_pair[2];
+ BMVert *v = node->link;
+ BMVert *v_a, *v_b;
+
+ if (!BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ continue;
+ }
+
+ /* get chain */
+ e_pair[0] = v->e;
+ e_pair[1] = BM_DISK_EDGE_NEXT(v->e, v);
+
+ if (BM_elem_flag_test(e_pair[0], BM_ELEM_TAG) || BM_elem_flag_test(e_pair[1], BM_ELEM_TAG)) {
+ continue;
+ }
+
+ v_a = BM_edge_other_vert(e_pair[0], v);
+ v_b = BM_edge_other_vert(e_pair[1], v);
+
+ /* simple case */
+ if (BM_elem_flag_test(v_a, BM_ELEM_TAG) && BM_elem_flag_test(v_b, BM_ELEM_TAG)) {
+ /* only start on an edge-case */
+ /* pass */
+ }
+ else if ((!BM_elem_flag_test(v_a, BM_ELEM_TAG)) && (!BM_elem_flag_test(v_b, BM_ELEM_TAG))) {
+ /* simple case, single edge spans face */
+ BMVert **splice_pair;
+ BM_elem_flag_enable(e_pair[1], BM_ELEM_TAG);
+ splice_pair = STACK_PUSH_RET(splice_ls);
+ splice_pair[0] = v;
+ splice_pair[1] = v_b;
+# ifdef USE_DUMP
+ printf("# Simple Case!\n");
+# endif
+ }
+ else {
+# ifdef USE_PARANOID
+ BMEdge *e_keep;
+# endif
+ BMEdge *e;
+ BMEdge *e_step;
+ BMVert *v_step;
+
+ /* walk the chain! */
+ if (BM_elem_flag_test(v_a, BM_ELEM_TAG)) {
+ e = e_pair[0];
+# ifdef USE_PARANOID
+ e_keep = e_pair[1];
+# endif
+ }
+ else {
+ SWAP(BMVert *, v_a, v_b);
+ e = e_pair[1];
+# ifdef USE_PARANOID
+ e_keep = e_pair[0];
+# endif
+ }
+
+ /* WALK */
+ v_step = v;
+ e_step = e;
+
+ while (true) {
+ BMEdge *e_next;
+ BMVert *v_next;
+
+ v_next = BM_edge_other_vert(e_step, v_step);
+ BM_elem_flag_enable(e_step, BM_ELEM_TAG);
+ if (!BM_elem_flag_test(v_next, BM_ELEM_TAG)) {
+ BMVert **splice_pair;
+# ifdef USE_PARANOID
+ BLI_assert(e_step != e_keep);
+# endif
+ splice_pair = STACK_PUSH_RET(splice_ls);
+ splice_pair[0] = v;
+ splice_pair[1] = v_next;
+ break;
+ }
+ else {
+ e_next = bm_vert_other_edge(v_next, e_step);
+ }
+
+ e_step = e_next;
+ v_step = v_next;
+ BM_elem_flag_enable(e_step, BM_ELEM_TAG);
+# ifdef USE_PARANOID
+ BLI_assert(e_step != e_keep);
+# endif
+# ifdef USE_DUMP
+ printf("# walk step %p %p\n", e_next, v_next);
+# endif
+ }
+# ifdef USE_PARANOID
+ BLI_assert(BM_elem_flag_test(e_keep, BM_ELEM_TAG) == 0);
+# endif
+ }
+ }
+
+ /* Remove edges! */
+ {
+ GHashIterator gh_iter;
+
+ GHASH_ITER (gh_iter, s.face_edges) {
+ struct LinkBase *e_ls_base = BLI_ghashIterator_getValue(&gh_iter);
+ LinkNode **node_prev_p;
+ uint i;
+
+ node_prev_p = &e_ls_base->list;
+ for (i = 0, node = e_ls_base->list; node; i++, node = node->next) {
+ BMEdge *e = node->link;
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ /* allocated by arena, don't free */
+ *node_prev_p = node->next;
+ e_ls_base->list_len--;
+ }
+ else {
+ node_prev_p = &node->next;
+ }
+ }
+ }
+ }
+
+ {
+ BMIter eiter;
+ BMEdge *e, *e_next;
+
+ BM_ITER_MESH_MUTABLE (e, e_next, &eiter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+
+ /* in rare and annoying cases,
+ * there can be faces from 's.face_edges' removed by the edges.
+ * These are degenerate cases, so just make sure we don't reference the faces again. */
+ if (e->l) {
+ BMLoop *l_iter = e->l;
+ BMFace **faces;
+
+ faces = bm->ftable;
+
+ do {
+ const int f_index = BM_elem_index_get(l_iter->f);
+ if (f_index >= 0) {
+ BLI_assert(f_index < totface_orig);
+ /* we could check if these are in: 's.face_edges', but easier just to remove */
+ faces[f_index] = NULL;
+ }
+ } while ((l_iter = l_iter->radial_next) != e->l);
+ }
+
+ BLI_gset_remove(s.wire_edges, e, NULL);
+ BM_edge_kill(bm, e);
+ }
+ }
+ }
+
+ /* Remove verts! */
+ {
+ GSet *verts_invalid = BLI_gset_ptr_new(__func__);
+
+ for (node = s.vert_dissolve; node; node = node->next) {
+ /* arena allocated, don't free */
+ BMVert *v = node->link;
+ if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ if (!v->e) {
+ BLI_gset_add(verts_invalid, v);
+ BM_vert_kill(bm, v);
+ }
+ }
+ }
+
+ {
+ uint i;
+ for (i = 0; i < STACK_SIZE(splice_ls); i++) {
+ if (!BLI_gset_haskey(verts_invalid, splice_ls[i][0]) &&
+ !BLI_gset_haskey(verts_invalid, splice_ls[i][1])) {
+ if (!BM_edge_exists(UNPACK2(splice_ls[i])) &&
+ !BM_vert_splice_check_double(UNPACK2(splice_ls[i]))) {
+ BM_vert_splice(bm, splice_ls[i][1], splice_ls[i][0]);
+ }
+ }
+ }
+ }
+
+ BLI_gset_free(verts_invalid, NULL);
+ }
+
+ MEM_freeN(splice_ls);
+ }
+#endif /* USE_DISSOLVE */
+
+ /* now split faces */
+#ifdef USE_NET
+ {
+ GHashIterator gh_iter;
+ BMFace **faces;
- v_prev = v_start;
-
- for (node = v_ls_base->list; node; node = node->next) {
- BMVert *vi = node->link;
- const float fac = line_point_factor_v3(vi->co, e->v1->co, e->v2->co);
-
- if (BM_vert_in_edge(e, v_prev)) {
- BMEdge *e_split;
- v_prev = BM_edge_split(bm, e, v_prev, &e_split, clamp_f(fac, 0.0f, 1.0f));
- BLI_assert(BM_vert_in_edge(e, v_end));
-
- if (!BM_edge_exists(v_prev, vi) &&
- !BM_vert_splice_check_double(v_prev, vi) &&
- !BM_vert_pair_share_face_check(v_prev, vi))
- {
- BM_vert_splice(bm, vi, v_prev);
- }
- else {
- copy_v3_v3(v_prev->co, vi->co);
- }
- v_prev = vi;
- if (is_wire) {
- BLI_gset_insert(s.wire_edges, e_split);
- }
- }
- }
- UNUSED_VARS_NDEBUG(v_end);
- }
- }
-#endif
+ MemArena *mem_arena_edgenet = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+ faces = bm->ftable;
- /* important to handle before edgenet */
-#ifdef USE_DISSOLVE
- if (use_dissolve && (boolean_mode == BMESH_ISECT_BOOLEAN_NONE)) {
- /* first pass */
- BMVert *(*splice_ls)[2];
- STACK_DECLARE(splice_ls);
- LinkNode *node;
-
-
- for (node = s.vert_dissolve; node; node = node->next) {
- BMVert *v = node->link;
- if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
- if (!BM_vert_is_edge_pair(v)) {
- BM_elem_flag_disable(v, BM_ELEM_TAG);
- }
- }
- }
-
- splice_ls = MEM_mallocN(BLI_gset_len(s.wire_edges) * sizeof(*splice_ls), __func__);
- STACK_INIT(splice_ls, BLI_gset_len(s.wire_edges));
-
- for (node = s.vert_dissolve; node; node = node->next) {
- BMEdge *e_pair[2];
- BMVert *v = node->link;
- BMVert *v_a, *v_b;
-
- if (!BM_elem_flag_test(v, BM_ELEM_TAG)) {
- continue;
- }
-
- /* get chain */
- e_pair[0] = v->e;
- e_pair[1] = BM_DISK_EDGE_NEXT(v->e, v);
-
- if (BM_elem_flag_test(e_pair[0], BM_ELEM_TAG) ||
- BM_elem_flag_test(e_pair[1], BM_ELEM_TAG))
- {
- continue;
- }
-
- v_a = BM_edge_other_vert(e_pair[0], v);
- v_b = BM_edge_other_vert(e_pair[1], v);
-
- /* simple case */
- if (BM_elem_flag_test(v_a, BM_ELEM_TAG) &&
- BM_elem_flag_test(v_b, BM_ELEM_TAG))
- {
- /* only start on an edge-case */
- /* pass */
- }
- else if ((!BM_elem_flag_test(v_a, BM_ELEM_TAG)) &&
- (!BM_elem_flag_test(v_b, BM_ELEM_TAG)))
- {
- /* simple case, single edge spans face */
- BMVert **splice_pair;
- BM_elem_flag_enable(e_pair[1], BM_ELEM_TAG);
- splice_pair = STACK_PUSH_RET(splice_ls);
- splice_pair[0] = v;
- splice_pair[1] = v_b;
-#ifdef USE_DUMP
- printf("# Simple Case!\n");
-#endif
- }
- else {
-#ifdef USE_PARANOID
- BMEdge *e_keep;
-#endif
- BMEdge *e;
- BMEdge *e_step;
- BMVert *v_step;
+ GHASH_ITER (gh_iter, s.face_edges) {
+ const int f_index = POINTER_AS_INT(BLI_ghashIterator_getKey(&gh_iter));
+ BMFace *f;
+ struct LinkBase *e_ls_base = BLI_ghashIterator_getValue(&gh_iter);
- /* walk the chain! */
- if (BM_elem_flag_test(v_a, BM_ELEM_TAG)) {
- e = e_pair[0];
-#ifdef USE_PARANOID
- e_keep = e_pair[1];
-#endif
- }
- else {
- SWAP(BMVert *, v_a, v_b);
- e = e_pair[1];
-#ifdef USE_PARANOID
- e_keep = e_pair[0];
-#endif
- }
+ BLI_assert(f_index >= 0 && f_index < totface_orig);
- /* WALK */
- v_step = v;
- e_step = e;
+ f = faces[f_index];
+ if (UNLIKELY(f == NULL)) {
+ continue;
+ }
- while (true) {
- BMEdge *e_next;
- BMVert *v_next;
+ BLI_assert(BM_elem_index_get(f) == f_index);
- v_next = BM_edge_other_vert(e_step, v_step);
- BM_elem_flag_enable(e_step, BM_ELEM_TAG);
- if (!BM_elem_flag_test(v_next, BM_ELEM_TAG)) {
- BMVert **splice_pair;
-#ifdef USE_PARANOID
- BLI_assert(e_step != e_keep);
-#endif
- splice_pair = STACK_PUSH_RET(splice_ls);
- splice_pair[0] = v;
- splice_pair[1] = v_next;
- break;
- }
- else {
- e_next = bm_vert_other_edge(v_next, e_step);
- }
-
- e_step = e_next;
- v_step = v_next;
- BM_elem_flag_enable(e_step, BM_ELEM_TAG);
-#ifdef USE_PARANOID
- BLI_assert(e_step != e_keep);
-#endif
-#ifdef USE_DUMP
- printf("# walk step %p %p\n", e_next, v_next);
-#endif
- }
-#ifdef USE_PARANOID
- BLI_assert(BM_elem_flag_test(e_keep, BM_ELEM_TAG) == 0);
-#endif
- }
- }
-
- /* Remove edges! */
- {
- GHashIterator gh_iter;
-
- GHASH_ITER (gh_iter, s.face_edges) {
- struct LinkBase *e_ls_base = BLI_ghashIterator_getValue(&gh_iter);
- LinkNode **node_prev_p;
- uint i;
-
- node_prev_p = &e_ls_base->list;
- for (i = 0, node = e_ls_base->list; node; i++, node = node->next) {
- BMEdge *e = node->link;
- if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
- /* allocated by arena, don't free */
- *node_prev_p = node->next;
- e_ls_base->list_len--;
- }
- else {
- node_prev_p = &node->next;
- }
- }
- }
- }
-
- {
- BMIter eiter;
- BMEdge *e, *e_next;
-
- BM_ITER_MESH_MUTABLE (e, e_next, &eiter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
-
- /* in rare and annoying cases,
- * there can be faces from 's.face_edges' removed by the edges.
- * These are degenerate cases, so just make sure we don't reference the faces again. */
- if (e->l) {
- BMLoop *l_iter = e->l;
- BMFace **faces;
-
- faces = bm->ftable;
-
- do {
- const int f_index = BM_elem_index_get(l_iter->f);
- if (f_index >= 0) {
- BLI_assert(f_index < totface_orig);
- /* we could check if these are in: 's.face_edges', but easier just to remove */
- faces[f_index] = NULL;
- }
- } while ((l_iter = l_iter->radial_next) != e->l);
- }
-
- BLI_gset_remove(s.wire_edges, e, NULL);
- BM_edge_kill(bm, e);
- }
- }
- }
-
- /* Remove verts! */
- {
- GSet *verts_invalid = BLI_gset_ptr_new(__func__);
-
- for (node = s.vert_dissolve; node; node = node->next) {
- /* arena allocated, don't free */
- BMVert *v = node->link;
- if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
- if (!v->e) {
- BLI_gset_add(verts_invalid, v);
- BM_vert_kill(bm, v);
- }
- }
- }
-
- {
- uint i;
- for (i = 0; i < STACK_SIZE(splice_ls); i++) {
- if (!BLI_gset_haskey(verts_invalid, splice_ls[i][0]) &&
- !BLI_gset_haskey(verts_invalid, splice_ls[i][1]))
- {
- if (!BM_edge_exists(UNPACK2(splice_ls[i])) &&
- !BM_vert_splice_check_double(UNPACK2(splice_ls[i])))
- {
- BM_vert_splice(bm, splice_ls[i][1], splice_ls[i][0]);
- }
- }
- }
- }
-
- BLI_gset_free(verts_invalid, NULL);
- }
-
- MEM_freeN(splice_ls);
- }
-#endif /* USE_DISSOLVE */
-
-
- /* now split faces */
-#ifdef USE_NET
- {
- GHashIterator gh_iter;
- BMFace **faces;
+ face_edges_split(
+ bm, f, e_ls_base, use_island_connect, use_partial_connect, mem_arena_edgenet);
- MemArena *mem_arena_edgenet = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+ BLI_memarena_clear(mem_arena_edgenet);
+ }
- faces = bm->ftable;
-
- GHASH_ITER (gh_iter, s.face_edges) {
- const int f_index = POINTER_AS_INT(BLI_ghashIterator_getKey(&gh_iter));
- BMFace *f;
- struct LinkBase *e_ls_base = BLI_ghashIterator_getValue(&gh_iter);
+ BLI_memarena_free(mem_arena_edgenet);
+ }
+#else
+ UNUSED_VARS(use_island_connect);
+#endif /* USE_NET */
+ (void)totface_orig;
- BLI_assert(f_index >= 0 && f_index < totface_orig);
+#ifdef USE_SEPARATE
+ if (use_separate) {
+ GSetIterator gs_iter;
- f = faces[f_index];
- if (UNLIKELY(f == NULL)) {
- continue;
- }
+ BM_mesh_elem_hflag_disable_all(bm, BM_EDGE, BM_ELEM_TAG, false);
- BLI_assert(BM_elem_index_get(f) == f_index);
+ GSET_ITER (gs_iter, s.wire_edges) {
+ BMEdge *e = BLI_gsetIterator_getKey(&gs_iter);
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
+ }
- face_edges_split(bm, f, e_ls_base, use_island_connect, use_partial_connect, mem_arena_edgenet);
+ BM_mesh_edgesplit(bm, false, true, false);
+ }
+ else if (boolean_mode != BMESH_ISECT_BOOLEAN_NONE || use_edge_tag) {
+ GSetIterator gs_iter;
- BLI_memarena_clear(mem_arena_edgenet);
- }
+ /* no need to clear for boolean */
- BLI_memarena_free(mem_arena_edgenet);
- }
+ GSET_ITER (gs_iter, s.wire_edges) {
+ BMEdge *e = BLI_gsetIterator_getKey(&gs_iter);
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
+ }
+ }
#else
- UNUSED_VARS(use_island_connect);
-#endif /* USE_NET */
- (void)totface_orig;
-
-#ifdef USE_SEPARATE
- if (use_separate) {
- GSetIterator gs_iter;
+ (void)use_separate;
+#endif /* USE_SEPARATE */
- BM_mesh_elem_hflag_disable_all(bm, BM_EDGE, BM_ELEM_TAG, false);
+ if ((boolean_mode != BMESH_ISECT_BOOLEAN_NONE)) {
+ BVHTree *tree_pair[2] = {tree_a, tree_b};
- GSET_ITER (gs_iter, s.wire_edges) {
- BMEdge *e = BLI_gsetIterator_getKey(&gs_iter);
- BM_elem_flag_enable(e, BM_ELEM_TAG);
- }
+ /* group vars */
+ int *groups_array;
+ int(*group_index)[2];
+ int group_tot;
+ int i;
+ BMFace **ftable;
- BM_mesh_edgesplit(bm, false, true, false);
- }
- else if (boolean_mode != BMESH_ISECT_BOOLEAN_NONE || use_edge_tag) {
- GSetIterator gs_iter;
+ BM_mesh_elem_table_ensure(bm, BM_FACE);
+ ftable = bm->ftable;
- /* no need to clear for boolean */
+ /* wrap the face-test callback to make it into an edge-loop delimiter */
+ struct LoopFilterWrap user_data_wrap = {
+ .test_fn = test_fn,
+ .user_data = user_data,
+ };
- GSET_ITER (gs_iter, s.wire_edges) {
- BMEdge *e = BLI_gsetIterator_getKey(&gs_iter);
- BM_elem_flag_enable(e, BM_ELEM_TAG);
- }
- }
-#else
- (void)use_separate;
-#endif /* USE_SEPARATE */
-
- if ((boolean_mode != BMESH_ISECT_BOOLEAN_NONE)) {
- BVHTree *tree_pair[2] = {tree_a, tree_b};
-
- /* group vars */
- int *groups_array;
- int (*group_index)[2];
- int group_tot;
- int i;
- BMFace **ftable;
-
- BM_mesh_elem_table_ensure(bm, BM_FACE);
- ftable = bm->ftable;
-
- /* wrap the face-test callback to make it into an edge-loop delimiter */
- struct LoopFilterWrap user_data_wrap = {
- .test_fn = test_fn,
- .user_data = user_data,
- };
-
- groups_array = MEM_mallocN(sizeof(*groups_array) * (size_t)bm->totface, __func__);
- group_tot = BM_mesh_calc_face_groups(
- bm, groups_array, &group_index,
- bm_loop_filter_fn, &user_data_wrap,
- 0, BM_EDGE);
+ groups_array = MEM_mallocN(sizeof(*groups_array) * (size_t)bm->totface, __func__);
+ group_tot = BM_mesh_calc_face_groups(
+ bm, groups_array, &group_index, bm_loop_filter_fn, &user_data_wrap, 0, BM_EDGE);
#ifdef USE_DUMP
- printf("%s: Total face-groups: %d\n", __func__, group_tot);
+ printf("%s: Total face-groups: %d\n", __func__, group_tot);
#endif
- /* Check if island is inside/outside */
- for (i = 0; i < group_tot; i++) {
- int fg = group_index[i][0];
- int fg_end = group_index[i][1] + fg;
- bool do_remove, do_flip;
-
- {
- /* for now assyme this is an OK face to test with (not degenerate!) */
- BMFace *f = ftable[groups_array[fg]];
- float co[3];
- int hits;
- int side = test_fn(f, user_data);
-
- if (side == -1) {
- continue;
- }
- BLI_assert(ELEM(side, 0, 1));
- side = !side;
-
- // BM_face_calc_center_median(f, co);
- BM_face_calc_point_in_face(f, co);
-
- hits = isect_bvhtree_point_v3(tree_pair[side], looptri_coords, co);
-
- switch (boolean_mode) {
- case BMESH_ISECT_BOOLEAN_ISECT:
- do_remove = ((hits & 1) != 1);
- do_flip = false;
- break;
- case BMESH_ISECT_BOOLEAN_UNION:
- do_remove = ((hits & 1) == 1);
- do_flip = false;
- break;
- case BMESH_ISECT_BOOLEAN_DIFFERENCE:
- do_remove = ((hits & 1) == 1) == side;
- do_flip = (side == 0);
- break;
- }
- }
-
- if (do_remove) {
- for (; fg != fg_end; fg++) {
- /* postpone killing the face since we access below, mark instead */
- // BM_face_kill_loose(bm, ftable[groups_array[fg]]);
- ftable[groups_array[fg]]->mat_nr = -1;
- }
- }
- else if (do_flip) {
- for (; fg != fg_end; fg++) {
- BM_face_normal_flip(bm, ftable[groups_array[fg]]);
- }
- }
-
- has_edit_boolean |= (do_flip || do_remove);
- }
-
- MEM_freeN(groups_array);
- MEM_freeN(group_index);
+ /* Check if island is inside/outside */
+ for (i = 0; i < group_tot; i++) {
+ int fg = group_index[i][0];
+ int fg_end = group_index[i][1] + fg;
+ bool do_remove, do_flip;
+
+ {
+ /* for now assyme this is an OK face to test with (not degenerate!) */
+ BMFace *f = ftable[groups_array[fg]];
+ float co[3];
+ int hits;
+ int side = test_fn(f, user_data);
+
+ if (side == -1) {
+ continue;
+ }
+ BLI_assert(ELEM(side, 0, 1));
+ side = !side;
+
+ // BM_face_calc_center_median(f, co);
+ BM_face_calc_point_in_face(f, co);
+
+ hits = isect_bvhtree_point_v3(tree_pair[side], looptri_coords, co);
+
+ switch (boolean_mode) {
+ case BMESH_ISECT_BOOLEAN_ISECT:
+ do_remove = ((hits & 1) != 1);
+ do_flip = false;
+ break;
+ case BMESH_ISECT_BOOLEAN_UNION:
+ do_remove = ((hits & 1) == 1);
+ do_flip = false;
+ break;
+ case BMESH_ISECT_BOOLEAN_DIFFERENCE:
+ do_remove = ((hits & 1) == 1) == side;
+ do_flip = (side == 0);
+ break;
+ }
+ }
+
+ if (do_remove) {
+ for (; fg != fg_end; fg++) {
+ /* postpone killing the face since we access below, mark instead */
+ // BM_face_kill_loose(bm, ftable[groups_array[fg]]);
+ ftable[groups_array[fg]]->mat_nr = -1;
+ }
+ }
+ else if (do_flip) {
+ for (; fg != fg_end; fg++) {
+ BM_face_normal_flip(bm, ftable[groups_array[fg]]);
+ }
+ }
+
+ has_edit_boolean |= (do_flip || do_remove);
+ }
+
+ MEM_freeN(groups_array);
+ MEM_freeN(group_index);
#ifdef USE_DISSOLVE
- /* We have dissolve code above, this is alternative logic,
- * we need to do it after the boolean is executed. */
- if (use_dissolve) {
- LinkNode *node;
- for (node = s.vert_dissolve; node; node = node->next) {
- BMVert *v = node->link;
- if (BM_vert_is_edge_pair(v)) {
- /* we wont create degenerate faces from this */
- bool ok = true;
-
- /* would we create a 2-sided-face?
- * if so, don't dissolve this since we may */
- if (v->e->l) {
- BMLoop *l_iter = v->e->l;
- do {
- if (l_iter->f->len == 3) {
- ok = false;
- break;
- }
- } while ((l_iter = l_iter->radial_next) != v->e->l);
- }
-
- if (ok) {
- BM_vert_collapse_edge(bm, v->e, v, true, false);
- }
- }
- }
- }
+ /* We have dissolve code above, this is alternative logic,
+ * we need to do it after the boolean is executed. */
+ if (use_dissolve) {
+ LinkNode *node;
+ for (node = s.vert_dissolve; node; node = node->next) {
+ BMVert *v = node->link;
+ if (BM_vert_is_edge_pair(v)) {
+ /* we wont create degenerate faces from this */
+ bool ok = true;
+
+ /* would we create a 2-sided-face?
+ * if so, don't dissolve this since we may */
+ if (v->e->l) {
+ BMLoop *l_iter = v->e->l;
+ do {
+ if (l_iter->f->len == 3) {
+ ok = false;
+ break;
+ }
+ } while ((l_iter = l_iter->radial_next) != v->e->l);
+ }
+
+ if (ok) {
+ BM_vert_collapse_edge(bm, v->e, v, true, false);
+ }
+ }
+ }
+ }
#endif
- {
- int tot = bm->totface;
- for (i = 0; i < tot; i++) {
- if (ftable[i]->mat_nr == -1) {
- BM_face_kill_loose(bm, ftable[i]);
- }
- }
- }
- }
+ {
+ int tot = bm->totface;
+ for (i = 0; i < tot; i++) {
+ if (ftable[i]->mat_nr == -1) {
+ BM_face_kill_loose(bm, ftable[i]);
+ }
+ }
+ }
+ }
- if (boolean_mode != BMESH_ISECT_BOOLEAN_NONE) {
- MEM_freeN((void *)looptri_coords);
+ if (boolean_mode != BMESH_ISECT_BOOLEAN_NONE) {
+ MEM_freeN((void *)looptri_coords);
- /* no booleans, just free immediate */
- BLI_bvhtree_free(tree_a);
- if (tree_a != tree_b) {
- BLI_bvhtree_free(tree_b);
- }
- }
+ /* no booleans, just free immediate */
+ BLI_bvhtree_free(tree_a);
+ if (tree_a != tree_b) {
+ BLI_bvhtree_free(tree_b);
+ }
+ }
- has_edit_isect = (BLI_ghash_len(s.face_edges) != 0);
+ has_edit_isect = (BLI_ghash_len(s.face_edges) != 0);
- /* cleanup */
- BLI_ghash_free(s.edgetri_cache, NULL, NULL);
+ /* cleanup */
+ BLI_ghash_free(s.edgetri_cache, NULL, NULL);
- BLI_ghash_free(s.edge_verts, NULL, NULL);
- BLI_ghash_free(s.face_edges, NULL, NULL);
- BLI_gset_free(s.wire_edges, NULL);
+ BLI_ghash_free(s.edge_verts, NULL, NULL);
+ BLI_ghash_free(s.face_edges, NULL, NULL);
+ BLI_gset_free(s.wire_edges, NULL);
- BLI_memarena_free(s.mem_arena);
+ BLI_memarena_free(s.mem_arena);
- return (has_edit_isect || has_edit_boolean);
+ return (has_edit_isect || has_edit_boolean);
}
diff --git a/source/blender/bmesh/tools/bmesh_intersect.h b/source/blender/bmesh/tools/bmesh_intersect.h
index 6e8e1d42161..cbbc74d3f82 100644
--- a/source/blender/bmesh/tools/bmesh_intersect.h
+++ b/source/blender/bmesh/tools/bmesh_intersect.h
@@ -21,20 +21,26 @@
* \ingroup bmesh
*/
-bool BM_mesh_intersect(
- BMesh *bm,
- struct BMLoop *(*looptris)[3], const int looptris_tot,
- int (*test_fn)(BMFace *f, void *user_data), void *user_data,
- const bool use_self, const bool use_separate, const bool use_dissolve, const bool use_island_connect,
- const bool use_partial_connect, const bool use_edge_tag, const int boolean_mode,
- const float eps);
+bool BM_mesh_intersect(BMesh *bm,
+ struct BMLoop *(*looptris)[3],
+ const int looptris_tot,
+ int (*test_fn)(BMFace *f, void *user_data),
+ void *user_data,
+ const bool use_self,
+ const bool use_separate,
+ const bool use_dissolve,
+ const bool use_island_connect,
+ const bool use_partial_connect,
+ const bool use_edge_tag,
+ const int boolean_mode,
+ const float eps);
enum {
- BMESH_ISECT_BOOLEAN_NONE = -1,
- /* aligned with BooleanModifierOp */
- BMESH_ISECT_BOOLEAN_ISECT = 0,
- BMESH_ISECT_BOOLEAN_UNION = 1,
- BMESH_ISECT_BOOLEAN_DIFFERENCE = 2,
+ BMESH_ISECT_BOOLEAN_NONE = -1,
+ /* aligned with BooleanModifierOp */
+ BMESH_ISECT_BOOLEAN_ISECT = 0,
+ BMESH_ISECT_BOOLEAN_UNION = 1,
+ BMESH_ISECT_BOOLEAN_DIFFERENCE = 2,
};
#endif /* __BMESH_INTERSECT_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_path.c b/source/blender/bmesh/tools/bmesh_path.c
index 4710c3929c4..a874965c978 100644
--- a/source/blender/bmesh/tools/bmesh_path.c
+++ b/source/blender/bmesh/tools/bmesh_path.c
@@ -27,8 +27,7 @@
#include "BLI_heap_simple.h"
#include "bmesh.h"
-#include "bmesh_path.h" /* own include */
-
+#include "bmesh_path.h" /* own include */
/* -------------------------------------------------------------------- */
/* Generic Helpers */
@@ -37,161 +36,161 @@
* Use skip options when we want to start measuring from a boundary.
*/
static float step_cost_3_v3_ex(
- const float v1[3], const float v2[3], const float v3[3],
- bool skip_12, bool skip_23)
+ const float v1[3], const float v2[3], const float v3[3], bool skip_12, bool skip_23)
{
- float d1[3], d2[3];
-
- /* The cost is based on the simple sum of the length of the two edgees... */
- sub_v3_v3v3(d1, v2, v1);
- sub_v3_v3v3(d2, v3, v2);
- const float cost_12 = normalize_v3(d1);
- const float cost_23 = normalize_v3(d2);
- const float cost = ((skip_12 ? 0.0f : cost_12) +
- (skip_23 ? 0.0f : cost_23));
-
- /* but is biased to give higher values to sharp turns, so that it will take
- * paths with fewer "turns" when selecting between equal-weighted paths between
- * the two edges */
- return cost * (1.0f + 0.5f * (2.0f - sqrtf(fabsf(dot_v3v3(d1, d2)))));
+ float d1[3], d2[3];
+
+ /* The cost is based on the simple sum of the length of the two edgees... */
+ sub_v3_v3v3(d1, v2, v1);
+ sub_v3_v3v3(d2, v3, v2);
+ const float cost_12 = normalize_v3(d1);
+ const float cost_23 = normalize_v3(d2);
+ const float cost = ((skip_12 ? 0.0f : cost_12) + (skip_23 ? 0.0f : cost_23));
+
+ /* but is biased to give higher values to sharp turns, so that it will take
+ * paths with fewer "turns" when selecting between equal-weighted paths between
+ * the two edges */
+ return cost * (1.0f + 0.5f * (2.0f - sqrtf(fabsf(dot_v3v3(d1, d2)))));
}
-static float step_cost_3_v3(
- const float v1[3], const float v2[3], const float v3[3])
+static float step_cost_3_v3(const float v1[3], const float v2[3], const float v3[3])
{
- return step_cost_3_v3_ex(v1, v2, v3, false, false);
+ return step_cost_3_v3_ex(v1, v2, v3, false, false);
}
-
/* -------------------------------------------------------------------- */
/* BM_mesh_calc_path_vert */
-static void verttag_add_adjacent(
- HeapSimple *heap, BMVert *v_a, BMVert **verts_prev, float *cost,
- const struct BMCalcPathParams *params)
+static void verttag_add_adjacent(HeapSimple *heap,
+ BMVert *v_a,
+ BMVert **verts_prev,
+ float *cost,
+ const struct BMCalcPathParams *params)
{
- const int v_a_index = BM_elem_index_get(v_a);
-
- {
- BMIter eiter;
- BMEdge *e;
- /* loop over faces of face, but do so by first looping over loops */
- BM_ITER_ELEM (e, &eiter, v_a, BM_EDGES_OF_VERT) {
- BMVert *v_b = BM_edge_other_vert(e, v_a);
- if (!BM_elem_flag_test(v_b, BM_ELEM_TAG)) {
- /* we know 'v_b' is not visited, check it out! */
- const int v_b_index = BM_elem_index_get(v_b);
- const float cost_cut = params->use_topology_distance ?
- 1.0f : len_v3v3(v_a->co, v_b->co);
- const float cost_new = cost[v_a_index] + cost_cut;
-
- if (cost[v_b_index] > cost_new) {
- cost[v_b_index] = cost_new;
- verts_prev[v_b_index] = v_a;
- BLI_heapsimple_insert(heap, cost_new, v_b);
- }
- }
- }
- }
-
- if (params->use_step_face) {
- BMIter liter;
- BMLoop *l;
- /* loop over faces of face, but do so by first looping over loops */
- BM_ITER_ELEM (l, &liter, v_a, BM_LOOPS_OF_VERT) {
- if (l->f->len > 3) {
- /* skip loops on adjacent edges */
- BMLoop *l_iter = l->next->next;
- do {
- BMVert *v_b = l_iter->v;
- if (!BM_elem_flag_test(v_b, BM_ELEM_TAG)) {
- /* we know 'v_b' is not visited, check it out! */
- const int v_b_index = BM_elem_index_get(v_b);
- const float cost_cut = params->use_topology_distance ?
- 1.0f : len_v3v3(v_a->co, v_b->co);
- const float cost_new = cost[v_a_index] + cost_cut;
-
- if (cost[v_b_index] > cost_new) {
- cost[v_b_index] = cost_new;
- verts_prev[v_b_index] = v_a;
- BLI_heapsimple_insert(heap, cost_new, v_b);
- }
- }
- } while ((l_iter = l_iter->next) != l->prev);
- }
- }
- }
+ const int v_a_index = BM_elem_index_get(v_a);
+
+ {
+ BMIter eiter;
+ BMEdge *e;
+ /* loop over faces of face, but do so by first looping over loops */
+ BM_ITER_ELEM (e, &eiter, v_a, BM_EDGES_OF_VERT) {
+ BMVert *v_b = BM_edge_other_vert(e, v_a);
+ if (!BM_elem_flag_test(v_b, BM_ELEM_TAG)) {
+ /* we know 'v_b' is not visited, check it out! */
+ const int v_b_index = BM_elem_index_get(v_b);
+ const float cost_cut = params->use_topology_distance ? 1.0f : len_v3v3(v_a->co, v_b->co);
+ const float cost_new = cost[v_a_index] + cost_cut;
+
+ if (cost[v_b_index] > cost_new) {
+ cost[v_b_index] = cost_new;
+ verts_prev[v_b_index] = v_a;
+ BLI_heapsimple_insert(heap, cost_new, v_b);
+ }
+ }
+ }
+ }
+
+ if (params->use_step_face) {
+ BMIter liter;
+ BMLoop *l;
+ /* loop over faces of face, but do so by first looping over loops */
+ BM_ITER_ELEM (l, &liter, v_a, BM_LOOPS_OF_VERT) {
+ if (l->f->len > 3) {
+ /* skip loops on adjacent edges */
+ BMLoop *l_iter = l->next->next;
+ do {
+ BMVert *v_b = l_iter->v;
+ if (!BM_elem_flag_test(v_b, BM_ELEM_TAG)) {
+ /* we know 'v_b' is not visited, check it out! */
+ const int v_b_index = BM_elem_index_get(v_b);
+ const float cost_cut = params->use_topology_distance ? 1.0f :
+ len_v3v3(v_a->co, v_b->co);
+ const float cost_new = cost[v_a_index] + cost_cut;
+
+ if (cost[v_b_index] > cost_new) {
+ cost[v_b_index] = cost_new;
+ verts_prev[v_b_index] = v_a;
+ BLI_heapsimple_insert(heap, cost_new, v_b);
+ }
+ }
+ } while ((l_iter = l_iter->next) != l->prev);
+ }
+ }
+ }
}
-LinkNode *BM_mesh_calc_path_vert(
- BMesh *bm, BMVert *v_src, BMVert *v_dst, const struct BMCalcPathParams *params,
- bool (*filter_fn)(BMVert *, void *user_data), void *user_data)
+LinkNode *BM_mesh_calc_path_vert(BMesh *bm,
+ BMVert *v_src,
+ BMVert *v_dst,
+ const struct BMCalcPathParams *params,
+ bool (*filter_fn)(BMVert *, void *user_data),
+ void *user_data)
{
- LinkNode *path = NULL;
- /* BM_ELEM_TAG flag is used to store visited edges */
- BMVert *v;
- BMIter viter;
- HeapSimple *heap;
- float *cost;
- BMVert **verts_prev;
- int i, totvert;
-
- /* note, would pass BM_EDGE except we are looping over all faces anyway */
- // BM_mesh_elem_index_ensure(bm, BM_VERT /* | BM_EDGE */); // NOT NEEDED FOR FACETAG
-
- BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
- BM_elem_flag_set(v, BM_ELEM_TAG, !filter_fn(v, user_data));
- BM_elem_index_set(v, i); /* set_inline */
- }
- bm->elem_index_dirty &= ~BM_VERT;
-
- /* alloc */
- totvert = bm->totvert;
- verts_prev = MEM_callocN(sizeof(*verts_prev) * totvert, __func__);
- cost = MEM_mallocN(sizeof(*cost) * totvert, __func__);
-
- copy_vn_fl(cost, totvert, 1e20f);
-
- /*
- * Arrays are now filled as follows:
- *
- * As the search continues, verts_prev[n] will be the previous verts on the shortest
- * path found so far to face n. BM_ELEM_TAG is used to tag elements we have visited,
- * cost[n] will contain the length of the shortest
- * path to face n found so far, Finally, heap is a priority heap which is built on the
- * the same data as the cost array, but inverted: it is a worklist of faces prioritized
- * by the shortest path found so far to the face.
- */
-
- /* regular dijkstra shortest path, but over faces instead of vertices */
- heap = BLI_heapsimple_new();
- BLI_heapsimple_insert(heap, 0.0f, v_src);
- cost[BM_elem_index_get(v_src)] = 0.0f;
-
- while (!BLI_heapsimple_is_empty(heap)) {
- v = BLI_heapsimple_pop_min(heap);
-
- if (v == v_dst) {
- break;
- }
-
- if (!BM_elem_flag_test(v, BM_ELEM_TAG)) {
- BM_elem_flag_enable(v, BM_ELEM_TAG);
- verttag_add_adjacent(heap, v, verts_prev, cost, params);
- }
- }
-
- if (v == v_dst) {
- do {
- BLI_linklist_prepend(&path, v);
- } while ((v = verts_prev[BM_elem_index_get(v)]));
- }
-
- MEM_freeN(verts_prev);
- MEM_freeN(cost);
- BLI_heapsimple_free(heap, NULL);
-
- return path;
+ LinkNode *path = NULL;
+ /* BM_ELEM_TAG flag is used to store visited edges */
+ BMVert *v;
+ BMIter viter;
+ HeapSimple *heap;
+ float *cost;
+ BMVert **verts_prev;
+ int i, totvert;
+
+ /* note, would pass BM_EDGE except we are looping over all faces anyway */
+ // BM_mesh_elem_index_ensure(bm, BM_VERT /* | BM_EDGE */); // NOT NEEDED FOR FACETAG
+
+ BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
+ BM_elem_flag_set(v, BM_ELEM_TAG, !filter_fn(v, user_data));
+ BM_elem_index_set(v, i); /* set_inline */
+ }
+ bm->elem_index_dirty &= ~BM_VERT;
+
+ /* alloc */
+ totvert = bm->totvert;
+ verts_prev = MEM_callocN(sizeof(*verts_prev) * totvert, __func__);
+ cost = MEM_mallocN(sizeof(*cost) * totvert, __func__);
+
+ copy_vn_fl(cost, totvert, 1e20f);
+
+ /*
+ * Arrays are now filled as follows:
+ *
+ * As the search continues, verts_prev[n] will be the previous verts on the shortest
+ * path found so far to face n. BM_ELEM_TAG is used to tag elements we have visited,
+ * cost[n] will contain the length of the shortest
+ * path to face n found so far, Finally, heap is a priority heap which is built on the
+ * the same data as the cost array, but inverted: it is a worklist of faces prioritized
+ * by the shortest path found so far to the face.
+ */
+
+ /* regular dijkstra shortest path, but over faces instead of vertices */
+ heap = BLI_heapsimple_new();
+ BLI_heapsimple_insert(heap, 0.0f, v_src);
+ cost[BM_elem_index_get(v_src)] = 0.0f;
+
+ while (!BLI_heapsimple_is_empty(heap)) {
+ v = BLI_heapsimple_pop_min(heap);
+
+ if (v == v_dst) {
+ break;
+ }
+
+ if (!BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ BM_elem_flag_enable(v, BM_ELEM_TAG);
+ verttag_add_adjacent(heap, v, verts_prev, cost, params);
+ }
+ }
+
+ if (v == v_dst) {
+ do {
+ BLI_linklist_prepend(&path, v);
+ } while ((v = verts_prev[BM_elem_index_get(v)]));
+ }
+
+ MEM_freeN(verts_prev);
+ MEM_freeN(cost);
+ BLI_heapsimple_free(heap, NULL);
+
+ return path;
}
/* -------------------------------------------------------------------- */
@@ -199,357 +198,372 @@ LinkNode *BM_mesh_calc_path_vert(
static float edgetag_cut_cost_vert(BMEdge *e_a, BMEdge *e_b, BMVert *v)
{
- BMVert *v1 = BM_edge_other_vert(e_a, v);
- BMVert *v2 = BM_edge_other_vert(e_b, v);
- return step_cost_3_v3(v1->co, v->co, v2->co);
+ BMVert *v1 = BM_edge_other_vert(e_a, v);
+ BMVert *v2 = BM_edge_other_vert(e_b, v);
+ return step_cost_3_v3(v1->co, v->co, v2->co);
}
static float edgetag_cut_cost_face(BMEdge *e_a, BMEdge *e_b, BMFace *f)
{
- float e_a_cent[3], e_b_cent[3], f_cent[3];
+ float e_a_cent[3], e_b_cent[3], f_cent[3];
- mid_v3_v3v3(e_a_cent, e_a->v1->co, e_a->v1->co);
- mid_v3_v3v3(e_b_cent, e_b->v1->co, e_b->v1->co);
+ mid_v3_v3v3(e_a_cent, e_a->v1->co, e_a->v1->co);
+ mid_v3_v3v3(e_b_cent, e_b->v1->co, e_b->v1->co);
- BM_face_calc_center_median_weighted(f, f_cent);
+ BM_face_calc_center_median_weighted(f, f_cent);
- return step_cost_3_v3(e_a_cent, e_b_cent, f_cent);
+ return step_cost_3_v3(e_a_cent, e_b_cent, f_cent);
}
-static void edgetag_add_adjacent(
- HeapSimple *heap, BMEdge *e_a, BMEdge **edges_prev, float *cost,
- const struct BMCalcPathParams *params)
+static void edgetag_add_adjacent(HeapSimple *heap,
+ BMEdge *e_a,
+ BMEdge **edges_prev,
+ float *cost,
+ const struct BMCalcPathParams *params)
{
- const int e_a_index = BM_elem_index_get(e_a);
-
- /* unlike vert/face, stepping faces disables scanning connected edges
- * and only steps over faces (selecting a ring of edges instead of a loop) */
- if (params->use_step_face == false) {
- BMIter viter;
- BMVert *v;
-
- BMIter eiter;
- BMEdge *e_b;
-
- BM_ITER_ELEM (v, &viter, e_a, BM_VERTS_OF_EDGE) {
-
- /* don't walk over previous vertex */
- if ((edges_prev[e_a_index]) &&
- (BM_vert_in_edge(edges_prev[e_a_index], v)))
- {
- continue;
- }
-
- BM_ITER_ELEM (e_b, &eiter, v, BM_EDGES_OF_VERT) {
- if (!BM_elem_flag_test(e_b, BM_ELEM_TAG)) {
- /* we know 'e_b' is not visited, check it out! */
- const int e_b_index = BM_elem_index_get(e_b);
- const float cost_cut = params->use_topology_distance ?
- 1.0f : edgetag_cut_cost_vert(e_a, e_b, v);
- const float cost_new = cost[e_a_index] + cost_cut;
-
- if (cost[e_b_index] > cost_new) {
- cost[e_b_index] = cost_new;
- edges_prev[e_b_index] = e_a;
- BLI_heapsimple_insert(heap, cost_new, e_b);
- }
- }
- }
- }
- }
- else {
- BMLoop *l_first, *l_iter;
-
- l_iter = l_first = e_a->l;
- do {
- BMLoop *l_cycle_iter, *l_cycle_end;
-
- l_cycle_iter = l_iter->next;
- l_cycle_end = l_iter;
-
- /* good, but we need to allow this otherwise paths may fail to connect at all */
+ const int e_a_index = BM_elem_index_get(e_a);
+
+ /* unlike vert/face, stepping faces disables scanning connected edges
+ * and only steps over faces (selecting a ring of edges instead of a loop) */
+ if (params->use_step_face == false) {
+ BMIter viter;
+ BMVert *v;
+
+ BMIter eiter;
+ BMEdge *e_b;
+
+ BM_ITER_ELEM (v, &viter, e_a, BM_VERTS_OF_EDGE) {
+
+ /* don't walk over previous vertex */
+ if ((edges_prev[e_a_index]) && (BM_vert_in_edge(edges_prev[e_a_index], v))) {
+ continue;
+ }
+
+ BM_ITER_ELEM (e_b, &eiter, v, BM_EDGES_OF_VERT) {
+ if (!BM_elem_flag_test(e_b, BM_ELEM_TAG)) {
+ /* we know 'e_b' is not visited, check it out! */
+ const int e_b_index = BM_elem_index_get(e_b);
+ const float cost_cut = params->use_topology_distance ?
+ 1.0f :
+ edgetag_cut_cost_vert(e_a, e_b, v);
+ const float cost_new = cost[e_a_index] + cost_cut;
+
+ if (cost[e_b_index] > cost_new) {
+ cost[e_b_index] = cost_new;
+ edges_prev[e_b_index] = e_a;
+ BLI_heapsimple_insert(heap, cost_new, e_b);
+ }
+ }
+ }
+ }
+ }
+ else {
+ BMLoop *l_first, *l_iter;
+
+ l_iter = l_first = e_a->l;
+ do {
+ BMLoop *l_cycle_iter, *l_cycle_end;
+
+ l_cycle_iter = l_iter->next;
+ l_cycle_end = l_iter;
+
+ /* good, but we need to allow this otherwise paths may fail to connect at all */
#if 0
- if (l_iter->f->len > 3) {
- l_cycle_iter = l_cycle_iter->next;
- l_cycle_end = l_cycle_end->prev;
- }
+ if (l_iter->f->len > 3) {
+ l_cycle_iter = l_cycle_iter->next;
+ l_cycle_end = l_cycle_end->prev;
+ }
#endif
- do {
- BMEdge *e_b = l_cycle_iter->e;
- if (!BM_elem_flag_test(e_b, BM_ELEM_TAG)) {
- /* we know 'e_b' is not visited, check it out! */
- const int e_b_index = BM_elem_index_get(e_b);
- const float cost_cut = params->use_topology_distance ?
- 1.0f : edgetag_cut_cost_face(e_a, e_b, l_iter->f);
- const float cost_new = cost[e_a_index] + cost_cut;
-
- if (cost[e_b_index] > cost_new) {
- cost[e_b_index] = cost_new;
- edges_prev[e_b_index] = e_a;
- BLI_heapsimple_insert(heap, cost_new, e_b);
- }
- }
- } while ((l_cycle_iter = l_cycle_iter->next) != l_cycle_end);
- } while ((l_iter = l_iter->radial_next) != l_first);
- }
+ do {
+ BMEdge *e_b = l_cycle_iter->e;
+ if (!BM_elem_flag_test(e_b, BM_ELEM_TAG)) {
+ /* we know 'e_b' is not visited, check it out! */
+ const int e_b_index = BM_elem_index_get(e_b);
+ const float cost_cut = params->use_topology_distance ?
+ 1.0f :
+ edgetag_cut_cost_face(e_a, e_b, l_iter->f);
+ const float cost_new = cost[e_a_index] + cost_cut;
+
+ if (cost[e_b_index] > cost_new) {
+ cost[e_b_index] = cost_new;
+ edges_prev[e_b_index] = e_a;
+ BLI_heapsimple_insert(heap, cost_new, e_b);
+ }
+ }
+ } while ((l_cycle_iter = l_cycle_iter->next) != l_cycle_end);
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
}
-
-LinkNode *BM_mesh_calc_path_edge(
- BMesh *bm, BMEdge *e_src, BMEdge *e_dst, const struct BMCalcPathParams *params,
- bool (*filter_fn)(BMEdge *, void *user_data), void *user_data)
+LinkNode *BM_mesh_calc_path_edge(BMesh *bm,
+ BMEdge *e_src,
+ BMEdge *e_dst,
+ const struct BMCalcPathParams *params,
+ bool (*filter_fn)(BMEdge *, void *user_data),
+ void *user_data)
{
- LinkNode *path = NULL;
- /* BM_ELEM_TAG flag is used to store visited edges */
- BMEdge *e;
- BMIter eiter;
- HeapSimple *heap;
- float *cost;
- BMEdge **edges_prev;
- int i, totedge;
-
- /* note, would pass BM_EDGE except we are looping over all edges anyway */
- BM_mesh_elem_index_ensure(bm, BM_VERT /* | BM_EDGE */);
-
- BM_ITER_MESH_INDEX (e, &eiter, bm, BM_EDGES_OF_MESH, i) {
- BM_elem_flag_set(e, BM_ELEM_TAG, !filter_fn(e, user_data));
- BM_elem_index_set(e, i); /* set_inline */
- }
- bm->elem_index_dirty &= ~BM_EDGE;
-
- /* alloc */
- totedge = bm->totedge;
- edges_prev = MEM_callocN(sizeof(*edges_prev) * totedge, "SeamPathPrevious");
- cost = MEM_mallocN(sizeof(*cost) * totedge, "SeamPathCost");
-
- copy_vn_fl(cost, totedge, 1e20f);
-
- /*
- * Arrays are now filled as follows:
- *
- * As the search continues, prevedge[n] will be the previous edge on the shortest
- * path found so far to edge n. BM_ELEM_TAG is used to tag elements we have visited,
- * cost[n] will contain the length of the shortest
- * path to edge n found so far, Finally, heap is a priority heap which is built on the
- * the same data as the cost array, but inverted: it is a worklist of edges prioritized
- * by the shortest path found so far to the edge.
- */
-
- /* regular dijkstra shortest path, but over edges instead of vertices */
- heap = BLI_heapsimple_new();
- BLI_heapsimple_insert(heap, 0.0f, e_src);
- cost[BM_elem_index_get(e_src)] = 0.0f;
-
- while (!BLI_heapsimple_is_empty(heap)) {
- e = BLI_heapsimple_pop_min(heap);
-
- if (e == e_dst) {
- break;
- }
-
- if (!BM_elem_flag_test(e, BM_ELEM_TAG)) {
- BM_elem_flag_enable(e, BM_ELEM_TAG);
- edgetag_add_adjacent(heap, e, edges_prev, cost, params);
- }
- }
-
- if (e == e_dst) {
- do {
- BLI_linklist_prepend(&path, e);
- } while ((e = edges_prev[BM_elem_index_get(e)]));
- }
-
- MEM_freeN(edges_prev);
- MEM_freeN(cost);
- BLI_heapsimple_free(heap, NULL);
-
- return path;
+ LinkNode *path = NULL;
+ /* BM_ELEM_TAG flag is used to store visited edges */
+ BMEdge *e;
+ BMIter eiter;
+ HeapSimple *heap;
+ float *cost;
+ BMEdge **edges_prev;
+ int i, totedge;
+
+ /* note, would pass BM_EDGE except we are looping over all edges anyway */
+ BM_mesh_elem_index_ensure(bm, BM_VERT /* | BM_EDGE */);
+
+ BM_ITER_MESH_INDEX (e, &eiter, bm, BM_EDGES_OF_MESH, i) {
+ BM_elem_flag_set(e, BM_ELEM_TAG, !filter_fn(e, user_data));
+ BM_elem_index_set(e, i); /* set_inline */
+ }
+ bm->elem_index_dirty &= ~BM_EDGE;
+
+ /* alloc */
+ totedge = bm->totedge;
+ edges_prev = MEM_callocN(sizeof(*edges_prev) * totedge, "SeamPathPrevious");
+ cost = MEM_mallocN(sizeof(*cost) * totedge, "SeamPathCost");
+
+ copy_vn_fl(cost, totedge, 1e20f);
+
+ /*
+ * Arrays are now filled as follows:
+ *
+ * As the search continues, prevedge[n] will be the previous edge on the shortest
+ * path found so far to edge n. BM_ELEM_TAG is used to tag elements we have visited,
+ * cost[n] will contain the length of the shortest
+ * path to edge n found so far, Finally, heap is a priority heap which is built on the
+ * the same data as the cost array, but inverted: it is a worklist of edges prioritized
+ * by the shortest path found so far to the edge.
+ */
+
+ /* regular dijkstra shortest path, but over edges instead of vertices */
+ heap = BLI_heapsimple_new();
+ BLI_heapsimple_insert(heap, 0.0f, e_src);
+ cost[BM_elem_index_get(e_src)] = 0.0f;
+
+ while (!BLI_heapsimple_is_empty(heap)) {
+ e = BLI_heapsimple_pop_min(heap);
+
+ if (e == e_dst) {
+ break;
+ }
+
+ if (!BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
+ edgetag_add_adjacent(heap, e, edges_prev, cost, params);
+ }
+ }
+
+ if (e == e_dst) {
+ do {
+ BLI_linklist_prepend(&path, e);
+ } while ((e = edges_prev[BM_elem_index_get(e)]));
+ }
+
+ MEM_freeN(edges_prev);
+ MEM_freeN(cost);
+ BLI_heapsimple_free(heap, NULL);
+
+ return path;
}
-
/* -------------------------------------------------------------------- */
/* BM_mesh_calc_path_face */
-static float facetag_cut_cost_edge(BMFace *f_a, BMFace *f_b, BMEdge *e, const void * const f_endpoints[2])
+static float facetag_cut_cost_edge(BMFace *f_a,
+ BMFace *f_b,
+ BMEdge *e,
+ const void *const f_endpoints[2])
{
- float f_a_cent[3];
- float f_b_cent[3];
- float e_cent[3];
+ float f_a_cent[3];
+ float f_b_cent[3];
+ float e_cent[3];
- BM_face_calc_center_median_weighted(f_a, f_a_cent);
- BM_face_calc_center_median_weighted(f_b, f_b_cent);
+ BM_face_calc_center_median_weighted(f_a, f_a_cent);
+ BM_face_calc_center_median_weighted(f_b, f_b_cent);
#if 0
- mid_v3_v3v3(e_cent, e->v1->co, e->v2->co);
+ mid_v3_v3v3(e_cent, e->v1->co, e->v2->co);
#else
- /* for triangle fans it gives better results to pick a point on the edge */
- {
- float ix_e[3], ix_f[3], f;
- isect_line_line_v3(e->v1->co, e->v2->co, f_a_cent, f_b_cent, ix_e, ix_f);
- f = line_point_factor_v3(ix_e, e->v1->co, e->v2->co);
- if (f < 0.0f) {
- copy_v3_v3(e_cent, e->v1->co);
- }
- else if (f > 1.0f) {
- copy_v3_v3(e_cent, e->v2->co);
- }
- else {
- copy_v3_v3(e_cent, ix_e);
- }
- }
+ /* for triangle fans it gives better results to pick a point on the edge */
+ {
+ float ix_e[3], ix_f[3], f;
+ isect_line_line_v3(e->v1->co, e->v2->co, f_a_cent, f_b_cent, ix_e, ix_f);
+ f = line_point_factor_v3(ix_e, e->v1->co, e->v2->co);
+ if (f < 0.0f) {
+ copy_v3_v3(e_cent, e->v1->co);
+ }
+ else if (f > 1.0f) {
+ copy_v3_v3(e_cent, e->v2->co);
+ }
+ else {
+ copy_v3_v3(e_cent, ix_e);
+ }
+ }
#endif
- return step_cost_3_v3_ex(
- f_a_cent, e_cent, f_b_cent,
- (f_a == f_endpoints[0]), (f_b == f_endpoints[1]));
+ return step_cost_3_v3_ex(
+ f_a_cent, e_cent, f_b_cent, (f_a == f_endpoints[0]), (f_b == f_endpoints[1]));
}
-static float facetag_cut_cost_vert(BMFace *f_a, BMFace *f_b, BMVert *v, const void * const f_endpoints[2])
+static float facetag_cut_cost_vert(BMFace *f_a,
+ BMFace *f_b,
+ BMVert *v,
+ const void *const f_endpoints[2])
{
- float f_a_cent[3];
- float f_b_cent[3];
+ float f_a_cent[3];
+ float f_b_cent[3];
- BM_face_calc_center_median_weighted(f_a, f_a_cent);
- BM_face_calc_center_median_weighted(f_b, f_b_cent);
+ BM_face_calc_center_median_weighted(f_a, f_a_cent);
+ BM_face_calc_center_median_weighted(f_b, f_b_cent);
- return step_cost_3_v3_ex(
- f_a_cent, v->co, f_b_cent,
- (f_a == f_endpoints[0]), (f_b == f_endpoints[1]));
+ return step_cost_3_v3_ex(
+ f_a_cent, v->co, f_b_cent, (f_a == f_endpoints[0]), (f_b == f_endpoints[1]));
}
-static void facetag_add_adjacent(
- HeapSimple *heap, BMFace *f_a, BMFace **faces_prev, float *cost,
- const void * const f_endpoints[2], const struct BMCalcPathParams *params)
+static void facetag_add_adjacent(HeapSimple *heap,
+ BMFace *f_a,
+ BMFace **faces_prev,
+ float *cost,
+ const void *const f_endpoints[2],
+ const struct BMCalcPathParams *params)
{
- const int f_a_index = BM_elem_index_get(f_a);
-
- /* loop over faces of face, but do so by first looping over loops */
- {
- BMIter liter;
- BMLoop *l_a;
-
- BM_ITER_ELEM (l_a, &liter, f_a, BM_LOOPS_OF_FACE) {
- BMLoop *l_first, *l_iter;
-
- l_iter = l_first = l_a;
- do {
- BMFace *f_b = l_iter->f;
- if (!BM_elem_flag_test(f_b, BM_ELEM_TAG)) {
- /* we know 'f_b' is not visited, check it out! */
- const int f_b_index = BM_elem_index_get(f_b);
- const float cost_cut = params->use_topology_distance ?
- 1.0f : facetag_cut_cost_edge(f_a, f_b, l_iter->e, f_endpoints);
- const float cost_new = cost[f_a_index] + cost_cut;
-
- if (cost[f_b_index] > cost_new) {
- cost[f_b_index] = cost_new;
- faces_prev[f_b_index] = f_a;
- BLI_heapsimple_insert(heap, cost_new, f_b);
- }
- }
- } while ((l_iter = l_iter->radial_next) != l_first);
- }
- }
-
- if (params->use_step_face) {
- BMIter liter;
- BMLoop *l_a;
-
- BM_ITER_ELEM (l_a, &liter, f_a, BM_LOOPS_OF_FACE) {
- BMIter litersub;
- BMLoop *l_b;
- BM_ITER_ELEM (l_b, &litersub, l_a->v, BM_LOOPS_OF_VERT) {
- if ((l_a != l_b) && !BM_loop_share_edge_check(l_a, l_b)) {
- BMFace *f_b = l_b->f;
- if (!BM_elem_flag_test(f_b, BM_ELEM_TAG)) {
- /* we know 'f_b' is not visited, check it out! */
- const int f_b_index = BM_elem_index_get(f_b);
- const float cost_cut = params->use_topology_distance ?
- 1.0f : facetag_cut_cost_vert(f_a, f_b, l_a->v, f_endpoints);
- const float cost_new = cost[f_a_index] + cost_cut;
-
- if (cost[f_b_index] > cost_new) {
- cost[f_b_index] = cost_new;
- faces_prev[f_b_index] = f_a;
- BLI_heapsimple_insert(heap, cost_new, f_b);
- }
- }
- }
- }
- }
- }
+ const int f_a_index = BM_elem_index_get(f_a);
+
+ /* loop over faces of face, but do so by first looping over loops */
+ {
+ BMIter liter;
+ BMLoop *l_a;
+
+ BM_ITER_ELEM (l_a, &liter, f_a, BM_LOOPS_OF_FACE) {
+ BMLoop *l_first, *l_iter;
+
+ l_iter = l_first = l_a;
+ do {
+ BMFace *f_b = l_iter->f;
+ if (!BM_elem_flag_test(f_b, BM_ELEM_TAG)) {
+ /* we know 'f_b' is not visited, check it out! */
+ const int f_b_index = BM_elem_index_get(f_b);
+ const float cost_cut = params->use_topology_distance ?
+ 1.0f :
+ facetag_cut_cost_edge(f_a, f_b, l_iter->e, f_endpoints);
+ const float cost_new = cost[f_a_index] + cost_cut;
+
+ if (cost[f_b_index] > cost_new) {
+ cost[f_b_index] = cost_new;
+ faces_prev[f_b_index] = f_a;
+ BLI_heapsimple_insert(heap, cost_new, f_b);
+ }
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+ }
+
+ if (params->use_step_face) {
+ BMIter liter;
+ BMLoop *l_a;
+
+ BM_ITER_ELEM (l_a, &liter, f_a, BM_LOOPS_OF_FACE) {
+ BMIter litersub;
+ BMLoop *l_b;
+ BM_ITER_ELEM (l_b, &litersub, l_a->v, BM_LOOPS_OF_VERT) {
+ if ((l_a != l_b) && !BM_loop_share_edge_check(l_a, l_b)) {
+ BMFace *f_b = l_b->f;
+ if (!BM_elem_flag_test(f_b, BM_ELEM_TAG)) {
+ /* we know 'f_b' is not visited, check it out! */
+ const int f_b_index = BM_elem_index_get(f_b);
+ const float cost_cut = params->use_topology_distance ?
+ 1.0f :
+ facetag_cut_cost_vert(f_a, f_b, l_a->v, f_endpoints);
+ const float cost_new = cost[f_a_index] + cost_cut;
+
+ if (cost[f_b_index] > cost_new) {
+ cost[f_b_index] = cost_new;
+ faces_prev[f_b_index] = f_a;
+ BLI_heapsimple_insert(heap, cost_new, f_b);
+ }
+ }
+ }
+ }
+ }
+ }
}
-LinkNode *BM_mesh_calc_path_face(
- BMesh *bm, BMFace *f_src, BMFace *f_dst, const struct BMCalcPathParams *params,
- bool (*filter_fn)(BMFace *, void *user_data), void *user_data)
+LinkNode *BM_mesh_calc_path_face(BMesh *bm,
+ BMFace *f_src,
+ BMFace *f_dst,
+ const struct BMCalcPathParams *params,
+ bool (*filter_fn)(BMFace *, void *user_data),
+ void *user_data)
{
- LinkNode *path = NULL;
- /* BM_ELEM_TAG flag is used to store visited edges */
- BMFace *f;
- BMIter fiter;
- HeapSimple *heap;
- float *cost;
- BMFace **faces_prev;
- int i, totface;
-
- /* Start measuring face path at the face edges, ignoring their centers. */
- const void * const f_endpoints[2] = {f_src, f_dst};
-
- /* note, would pass BM_EDGE except we are looping over all faces anyway */
- // BM_mesh_elem_index_ensure(bm, BM_VERT /* | BM_EDGE */); // NOT NEEDED FOR FACETAG
-
- BM_ITER_MESH_INDEX (f, &fiter, bm, BM_FACES_OF_MESH, i) {
- BM_elem_flag_set(f, BM_ELEM_TAG, !filter_fn(f, user_data));
- BM_elem_index_set(f, i); /* set_inline */
- }
- bm->elem_index_dirty &= ~BM_FACE;
-
- /* alloc */
- totface = bm->totface;
- faces_prev = MEM_callocN(sizeof(*faces_prev) * totface, __func__);
- cost = MEM_mallocN(sizeof(*cost) * totface, __func__);
-
- copy_vn_fl(cost, totface, 1e20f);
-
- /*
- * Arrays are now filled as follows:
- *
- * As the search continues, faces_prev[n] will be the previous face on the shortest
- * path found so far to face n. BM_ELEM_TAG is used to tag elements we have visited,
- * cost[n] will contain the length of the shortest
- * path to face n found so far, Finally, heap is a priority heap which is built on the
- * the same data as the cost array, but inverted: it is a worklist of faces prioritized
- * by the shortest path found so far to the face.
- */
-
- /* regular dijkstra shortest path, but over faces instead of vertices */
- heap = BLI_heapsimple_new();
- BLI_heapsimple_insert(heap, 0.0f, f_src);
- cost[BM_elem_index_get(f_src)] = 0.0f;
-
- while (!BLI_heapsimple_is_empty(heap)) {
- f = BLI_heapsimple_pop_min(heap);
-
- if (f == f_dst) {
- break;
- }
-
- if (!BM_elem_flag_test(f, BM_ELEM_TAG)) {
- BM_elem_flag_enable(f, BM_ELEM_TAG);
- facetag_add_adjacent(heap, f, faces_prev, cost, f_endpoints, params);
- }
- }
-
- if (f == f_dst) {
- do {
- BLI_linklist_prepend(&path, f);
- } while ((f = faces_prev[BM_elem_index_get(f)]));
- }
-
- MEM_freeN(faces_prev);
- MEM_freeN(cost);
- BLI_heapsimple_free(heap, NULL);
-
- return path;
+ LinkNode *path = NULL;
+ /* BM_ELEM_TAG flag is used to store visited edges */
+ BMFace *f;
+ BMIter fiter;
+ HeapSimple *heap;
+ float *cost;
+ BMFace **faces_prev;
+ int i, totface;
+
+ /* Start measuring face path at the face edges, ignoring their centers. */
+ const void *const f_endpoints[2] = {f_src, f_dst};
+
+ /* note, would pass BM_EDGE except we are looping over all faces anyway */
+ // BM_mesh_elem_index_ensure(bm, BM_VERT /* | BM_EDGE */); // NOT NEEDED FOR FACETAG
+
+ BM_ITER_MESH_INDEX (f, &fiter, bm, BM_FACES_OF_MESH, i) {
+ BM_elem_flag_set(f, BM_ELEM_TAG, !filter_fn(f, user_data));
+ BM_elem_index_set(f, i); /* set_inline */
+ }
+ bm->elem_index_dirty &= ~BM_FACE;
+
+ /* alloc */
+ totface = bm->totface;
+ faces_prev = MEM_callocN(sizeof(*faces_prev) * totface, __func__);
+ cost = MEM_mallocN(sizeof(*cost) * totface, __func__);
+
+ copy_vn_fl(cost, totface, 1e20f);
+
+ /*
+ * Arrays are now filled as follows:
+ *
+ * As the search continues, faces_prev[n] will be the previous face on the shortest
+ * path found so far to face n. BM_ELEM_TAG is used to tag elements we have visited,
+ * cost[n] will contain the length of the shortest
+ * path to face n found so far, Finally, heap is a priority heap which is built on the
+ * the same data as the cost array, but inverted: it is a worklist of faces prioritized
+ * by the shortest path found so far to the face.
+ */
+
+ /* regular dijkstra shortest path, but over faces instead of vertices */
+ heap = BLI_heapsimple_new();
+ BLI_heapsimple_insert(heap, 0.0f, f_src);
+ cost[BM_elem_index_get(f_src)] = 0.0f;
+
+ while (!BLI_heapsimple_is_empty(heap)) {
+ f = BLI_heapsimple_pop_min(heap);
+
+ if (f == f_dst) {
+ break;
+ }
+
+ if (!BM_elem_flag_test(f, BM_ELEM_TAG)) {
+ BM_elem_flag_enable(f, BM_ELEM_TAG);
+ facetag_add_adjacent(heap, f, faces_prev, cost, f_endpoints, params);
+ }
+ }
+
+ if (f == f_dst) {
+ do {
+ BLI_linklist_prepend(&path, f);
+ } while ((f = faces_prev[BM_elem_index_get(f)]));
+ }
+
+ MEM_freeN(faces_prev);
+ MEM_freeN(cost);
+ BLI_heapsimple_free(heap, NULL);
+
+ return path;
}
diff --git a/source/blender/bmesh/tools/bmesh_path.h b/source/blender/bmesh/tools/bmesh_path.h
index 792ba6c7dce..6d22a7e7e07 100644
--- a/source/blender/bmesh/tools/bmesh_path.h
+++ b/source/blender/bmesh/tools/bmesh_path.h
@@ -22,23 +22,32 @@
*/
struct BMCalcPathParams {
- uint use_topology_distance : 1;
- uint use_step_face : 1;
+ uint use_topology_distance : 1;
+ uint use_step_face : 1;
};
-struct LinkNode *BM_mesh_calc_path_vert(
- BMesh *bm, BMVert *v_src, BMVert *v_dst, const struct BMCalcPathParams *params,
- bool (*filter_fn)(BMVert *, void *), void *user_data)
-ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3, 5);
+struct LinkNode *BM_mesh_calc_path_vert(BMesh *bm,
+ BMVert *v_src,
+ BMVert *v_dst,
+ const struct BMCalcPathParams *params,
+ bool (*filter_fn)(BMVert *, void *),
+ void *user_data) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL(1, 2, 3, 5);
-struct LinkNode *BM_mesh_calc_path_edge(
- BMesh *bm, BMEdge *e_src, BMEdge *e_dst, const struct BMCalcPathParams *params,
- bool (*filter_fn)(BMEdge *, void *), void *user_data)
-ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3, 5);
+struct LinkNode *BM_mesh_calc_path_edge(BMesh *bm,
+ BMEdge *e_src,
+ BMEdge *e_dst,
+ const struct BMCalcPathParams *params,
+ bool (*filter_fn)(BMEdge *, void *),
+ void *user_data) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL(1, 2, 3, 5);
-struct LinkNode *BM_mesh_calc_path_face(
- BMesh *bm, BMFace *f_src, BMFace *f_dst, const struct BMCalcPathParams *params,
- bool (*filter_fn)(BMFace *, void *), void *user_data)
-ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3, 5);
+struct LinkNode *BM_mesh_calc_path_face(BMesh *bm,
+ BMFace *f_src,
+ BMFace *f_dst,
+ const struct BMCalcPathParams *params,
+ bool (*filter_fn)(BMFace *, void *),
+ void *user_data) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL(1, 2, 3, 5);
#endif /* __BMESH_PATH_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_path_region.c b/source/blender/bmesh/tools/bmesh_path_region.c
index 8eb5b50b2a2..9ec3b51f29a 100644
--- a/source/blender/bmesh/tools/bmesh_path_region.c
+++ b/source/blender/bmesh/tools/bmesh_path_region.c
@@ -29,8 +29,7 @@
#include "BLI_alloca.h"
#include "bmesh.h"
-#include "bmesh_path_region.h" /* own include */
-
+#include "bmesh_path_region.h" /* own include */
/**
* Special handling of vertices with 2 edges
@@ -45,7 +44,6 @@
*/
#define USE_EDGE_CHAIN
-
#ifdef USE_EDGE_CHAIN
/**
* Takes a vertex with 2 edge users and assigns the vertices at each end-point,
@@ -54,66 +52,62 @@
*/
static bool bm_vert_pair_ends(BMVert *v_pivot, BMVert *v_end_pair[2])
{
- BMEdge *e = v_pivot->e;
- int j = 0;
- do {
- BMEdge *e_chain = e;
- BMVert *v_other = BM_edge_other_vert(e_chain, v_pivot);
- while (BM_vert_is_edge_pair_manifold(v_other)) {
- BMEdge *e_chain_next = BM_DISK_EDGE_NEXT(e_chain, v_other);
- BLI_assert(BM_DISK_EDGE_NEXT(e_chain_next, v_other) == e_chain);
- v_other = BM_edge_other_vert(e_chain_next, v_other);
- if (v_other == v_pivot) {
- return false;
- }
- e_chain = e_chain_next;
- }
- v_end_pair[j++] = v_other;
- } while ((e = BM_DISK_EDGE_NEXT(e, v_pivot)) != v_pivot->e);
-
- BLI_assert(j == 2);
- return true;
+ BMEdge *e = v_pivot->e;
+ int j = 0;
+ do {
+ BMEdge *e_chain = e;
+ BMVert *v_other = BM_edge_other_vert(e_chain, v_pivot);
+ while (BM_vert_is_edge_pair_manifold(v_other)) {
+ BMEdge *e_chain_next = BM_DISK_EDGE_NEXT(e_chain, v_other);
+ BLI_assert(BM_DISK_EDGE_NEXT(e_chain_next, v_other) == e_chain);
+ v_other = BM_edge_other_vert(e_chain_next, v_other);
+ if (v_other == v_pivot) {
+ return false;
+ }
+ e_chain = e_chain_next;
+ }
+ v_end_pair[j++] = v_other;
+ } while ((e = BM_DISK_EDGE_NEXT(e, v_pivot)) != v_pivot->e);
+
+ BLI_assert(j == 2);
+ return true;
}
-#endif /* USE_EDGE_CHAIN */
-
+#endif /* USE_EDGE_CHAIN */
/** \name Vertex in Region Checks
* \{ */
-static bool bm_vert_region_test(BMVert *v, int * const depths[2], const int pass)
+static bool bm_vert_region_test(BMVert *v, int *const depths[2], const int pass)
{
- const int index = BM_elem_index_get(v);
- return (((depths[0][index] != -1) && (depths[1][index] != -1)) && \
- ((depths[0][index] + depths[1][index]) < pass));
+ const int index = BM_elem_index_get(v);
+ return (((depths[0][index] != -1) && (depths[1][index] != -1)) &&
+ ((depths[0][index] + depths[1][index]) < pass));
}
#ifdef USE_EDGE_CHAIN
-static bool bm_vert_region_test_chain(BMVert *v, int * const depths[2], const int pass)
+static bool bm_vert_region_test_chain(BMVert *v, int *const depths[2], const int pass)
{
- BMVert *v_end_pair[2];
- if (bm_vert_region_test(v, depths, pass)) {
- return true;
- }
- else if (BM_vert_is_edge_pair_manifold(v) &&
- bm_vert_pair_ends(v, v_end_pair) &&
- bm_vert_region_test(v_end_pair[0], depths, pass) &&
- bm_vert_region_test(v_end_pair[1], depths, pass))
- {
- return true;
- }
-
- return false;
+ BMVert *v_end_pair[2];
+ if (bm_vert_region_test(v, depths, pass)) {
+ return true;
+ }
+ else if (BM_vert_is_edge_pair_manifold(v) && bm_vert_pair_ends(v, v_end_pair) &&
+ bm_vert_region_test(v_end_pair[0], depths, pass) &&
+ bm_vert_region_test(v_end_pair[1], depths, pass)) {
+ return true;
+ }
+
+ return false;
}
#else
-static bool bm_vert_region_test_chain(BMVert *v, int * const depths[2], const int pass)
+static bool bm_vert_region_test_chain(BMVert *v, int *const depths[2], const int pass)
{
- return bm_vert_region_test(v, depths, pass);
+ return bm_vert_region_test(v, depths, pass);
}
#endif
/** \} */
-
/**
* Main logic for calculating region between 2 elements.
*
@@ -126,358 +120,359 @@ static bool bm_vert_region_test_chain(BMVert *v, int * const depths[2], const in
*
* \note Only verts without BM_ELEM_TAG will be walked over.
*/
-static LinkNode *mesh_calc_path_region_elem(
- BMesh *bm,
- BMElem *ele_src, BMElem *ele_dst,
- const char path_htype)
+static LinkNode *mesh_calc_path_region_elem(BMesh *bm,
+ BMElem *ele_src,
+ BMElem *ele_dst,
+ const char path_htype)
{
- int ele_verts_len[2];
- BMVert **ele_verts[2];
-
- /* Get vertices from any `ele_src/ele_dst` elements. */
- for (int side = 0; side < 2; side++) {
- BMElem *ele = side ? ele_dst : ele_src;
- int j = 0;
-
- if (ele->head.htype == BM_FACE) {
- BMFace *f = (BMFace *)ele;
- ele_verts[side] = BLI_array_alloca(ele_verts[side], f->len);
-
- BMLoop *l_first, *l_iter;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- ele_verts[side][j++] = l_iter->v;
- } while ((l_iter = l_iter->next) != l_first);
- }
- else if (ele->head.htype == BM_EDGE) {
- BMEdge *e = (BMEdge *)ele;
- ele_verts[side] = BLI_array_alloca(ele_verts[side], 2);
-
- ele_verts[side][j++] = e->v1;
- ele_verts[side][j++] = e->v2;
- }
- else if (ele->head.htype == BM_VERT) {
- BMVert *v = (BMVert *)ele;
- ele_verts[side] = BLI_array_alloca(ele_verts[side], 1);
-
- ele_verts[side][j++] = v;
- }
- else {
- BLI_assert(0);
- }
- ele_verts_len[side] = j;
- }
-
- int *depths[2] = {NULL};
- int pass = 0;
-
- BMVert **stack = MEM_mallocN(sizeof(*stack) * bm->totvert, __func__);
- BMVert **stack_other = MEM_mallocN(sizeof(*stack_other) * bm->totvert, __func__);
-
- STACK_DECLARE(stack);
- STACK_INIT(stack, bm->totvert);
-
- STACK_DECLARE(stack_other);
- STACK_INIT(stack_other, bm->totvert);
-
- BM_mesh_elem_index_ensure(bm, BM_VERT);
-
- /* After exhausting all possible elements, we should have found all elements on the 'side_other'.
- * otherwise, exit early. */
- bool found_all = false;
-
- for (int side = 0; side < 2; side++) {
- const int side_other = !side;
-
- /* initialize depths to -1 (un-touched), fill in with the depth as we walk over the edges. */
- depths[side] = MEM_mallocN(sizeof(*depths[side]) * bm->totvert, __func__);
- copy_vn_i(depths[side], bm->totvert, -1);
-
- /* needed for second side */
- STACK_CLEAR(stack);
- STACK_CLEAR(stack_other);
-
- for (int i = 0; i < ele_verts_len[side]; i++) {
- BMVert *v = ele_verts[side][i];
- depths[side][BM_elem_index_get(v)] = 0;
- if (v->e && !BM_elem_flag_test(v, BM_ELEM_TAG)) {
- STACK_PUSH(stack, v);
- }
- }
+ int ele_verts_len[2];
+ BMVert **ele_verts[2];
+
+ /* Get vertices from any `ele_src/ele_dst` elements. */
+ for (int side = 0; side < 2; side++) {
+ BMElem *ele = side ? ele_dst : ele_src;
+ int j = 0;
+
+ if (ele->head.htype == BM_FACE) {
+ BMFace *f = (BMFace *)ele;
+ ele_verts[side] = BLI_array_alloca(ele_verts[side], f->len);
+
+ BMLoop *l_first, *l_iter;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ ele_verts[side][j++] = l_iter->v;
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ else if (ele->head.htype == BM_EDGE) {
+ BMEdge *e = (BMEdge *)ele;
+ ele_verts[side] = BLI_array_alloca(ele_verts[side], 2);
+
+ ele_verts[side][j++] = e->v1;
+ ele_verts[side][j++] = e->v2;
+ }
+ else if (ele->head.htype == BM_VERT) {
+ BMVert *v = (BMVert *)ele;
+ ele_verts[side] = BLI_array_alloca(ele_verts[side], 1);
+
+ ele_verts[side][j++] = v;
+ }
+ else {
+ BLI_assert(0);
+ }
+ ele_verts_len[side] = j;
+ }
+
+ int *depths[2] = {NULL};
+ int pass = 0;
+
+ BMVert **stack = MEM_mallocN(sizeof(*stack) * bm->totvert, __func__);
+ BMVert **stack_other = MEM_mallocN(sizeof(*stack_other) * bm->totvert, __func__);
+
+ STACK_DECLARE(stack);
+ STACK_INIT(stack, bm->totvert);
+
+ STACK_DECLARE(stack_other);
+ STACK_INIT(stack_other, bm->totvert);
+
+ BM_mesh_elem_index_ensure(bm, BM_VERT);
+
+ /* After exhausting all possible elements, we should have found all elements on the 'side_other'.
+ * otherwise, exit early. */
+ bool found_all = false;
+
+ for (int side = 0; side < 2; side++) {
+ const int side_other = !side;
+
+ /* initialize depths to -1 (un-touched), fill in with the depth as we walk over the edges. */
+ depths[side] = MEM_mallocN(sizeof(*depths[side]) * bm->totvert, __func__);
+ copy_vn_i(depths[side], bm->totvert, -1);
+
+ /* needed for second side */
+ STACK_CLEAR(stack);
+ STACK_CLEAR(stack_other);
+
+ for (int i = 0; i < ele_verts_len[side]; i++) {
+ BMVert *v = ele_verts[side][i];
+ depths[side][BM_elem_index_get(v)] = 0;
+ if (v->e && !BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ STACK_PUSH(stack, v);
+ }
+ }
#ifdef USE_EDGE_CHAIN
- /* Expand initial state to end-point vertices when they only have 2x edges,
- * this prevents odd behavior when source or destination are in the middle of a long chain of edges. */
- if (ELEM(path_htype, BM_VERT, BM_EDGE)) {
- for (int i = 0; i < ele_verts_len[side]; i++) {
- BMVert *v = ele_verts[side][i];
- BMVert *v_end_pair[2];
- if (BM_vert_is_edge_pair_manifold(v) && bm_vert_pair_ends(v, v_end_pair)) {
- for (int j = 0; j < 2; j++) {
- const int v_end_index = BM_elem_index_get(v_end_pair[j]);
- if (depths[side][v_end_index] == -1) {
- depths[side][v_end_index] = 0;
- if (!BM_elem_flag_test(v_end_pair[j], BM_ELEM_TAG)) {
- STACK_PUSH(stack, v_end_pair[j]);
- }
- }
- }
- }
- }
- }
-#endif /* USE_EDGE_CHAIN */
-
- /* Keep walking over connected geometry until we find all the vertices in `ele_verts[side_other]`,
- * or exit the loop when theres no connection. */
- found_all = false;
- for (pass = 1; (STACK_SIZE(stack) != 0); pass++) {
- while (STACK_SIZE(stack) != 0) {
- BMVert *v_a = STACK_POP(stack);
- // const int v_a_index = BM_elem_index_get(v_a); /* only for assert */
- BMEdge *e = v_a->e;
-
- do {
- BMVert *v_b = BM_edge_other_vert(e, v_a);
- int v_b_index = BM_elem_index_get(v_b);
- if (depths[side][v_b_index] == -1) {
+ /* Expand initial state to end-point vertices when they only have 2x edges,
+ * this prevents odd behavior when source or destination are in the middle of a long chain of edges. */
+ if (ELEM(path_htype, BM_VERT, BM_EDGE)) {
+ for (int i = 0; i < ele_verts_len[side]; i++) {
+ BMVert *v = ele_verts[side][i];
+ BMVert *v_end_pair[2];
+ if (BM_vert_is_edge_pair_manifold(v) && bm_vert_pair_ends(v, v_end_pair)) {
+ for (int j = 0; j < 2; j++) {
+ const int v_end_index = BM_elem_index_get(v_end_pair[j]);
+ if (depths[side][v_end_index] == -1) {
+ depths[side][v_end_index] = 0;
+ if (!BM_elem_flag_test(v_end_pair[j], BM_ELEM_TAG)) {
+ STACK_PUSH(stack, v_end_pair[j]);
+ }
+ }
+ }
+ }
+ }
+ }
+#endif /* USE_EDGE_CHAIN */
+
+ /* Keep walking over connected geometry until we find all the vertices in `ele_verts[side_other]`,
+ * or exit the loop when theres no connection. */
+ found_all = false;
+ for (pass = 1; (STACK_SIZE(stack) != 0); pass++) {
+ while (STACK_SIZE(stack) != 0) {
+ BMVert *v_a = STACK_POP(stack);
+ // const int v_a_index = BM_elem_index_get(v_a); /* only for assert */
+ BMEdge *e = v_a->e;
+
+ do {
+ BMVert *v_b = BM_edge_other_vert(e, v_a);
+ int v_b_index = BM_elem_index_get(v_b);
+ if (depths[side][v_b_index] == -1) {
#ifdef USE_EDGE_CHAIN
- /* Walk along the chain, fill in values until we reach a vertex with 3+ edges. */
- {
- BMEdge *e_chain = e;
- while (BM_vert_is_edge_pair_manifold(v_b) &&
- ((depths[side][v_b_index] == -1)))
- {
- depths[side][v_b_index] = pass;
-
- BMEdge *e_chain_next = BM_DISK_EDGE_NEXT(e_chain, v_b);
- BLI_assert(BM_DISK_EDGE_NEXT(e_chain_next, v_b) == e_chain);
- v_b = BM_edge_other_vert(e_chain_next, v_b);
- v_b_index = BM_elem_index_get(v_b);
- e_chain = e_chain_next;
- }
- }
-#endif /* USE_EDGE_CHAIN */
-
- /* Add the other vertex to the stack, to be traversed in the next pass. */
- if (depths[side][v_b_index] == -1) {
+ /* Walk along the chain, fill in values until we reach a vertex with 3+ edges. */
+ {
+ BMEdge *e_chain = e;
+ while (BM_vert_is_edge_pair_manifold(v_b) && ((depths[side][v_b_index] == -1))) {
+ depths[side][v_b_index] = pass;
+
+ BMEdge *e_chain_next = BM_DISK_EDGE_NEXT(e_chain, v_b);
+ BLI_assert(BM_DISK_EDGE_NEXT(e_chain_next, v_b) == e_chain);
+ v_b = BM_edge_other_vert(e_chain_next, v_b);
+ v_b_index = BM_elem_index_get(v_b);
+ e_chain = e_chain_next;
+ }
+ }
+#endif /* USE_EDGE_CHAIN */
+
+ /* Add the other vertex to the stack, to be traversed in the next pass. */
+ if (depths[side][v_b_index] == -1) {
#ifdef USE_EDGE_CHAIN
- BLI_assert(!BM_vert_is_edge_pair_manifold(v_b));
+ BLI_assert(!BM_vert_is_edge_pair_manifold(v_b));
#endif
- BLI_assert(pass == depths[side][BM_elem_index_get(v_a)] + 1);
- depths[side][v_b_index] = pass;
- if (!BM_elem_flag_test(v_b, BM_ELEM_TAG)) {
- STACK_PUSH(stack_other, v_b);
- }
- }
- }
- } while ((e = BM_DISK_EDGE_NEXT(e, v_a)) != v_a->e);
- }
-
- /* Stop searching once theres none left.
- * Note that this looks in-efficient, however until the target elements reached,
- * it will exit immediately.
- * After that, it takes as many passes as the element has edges to finish off. */
- found_all = true;
- for (int i = 0; i < ele_verts_len[side_other]; i++) {
- if (depths[side][BM_elem_index_get(ele_verts[side_other][i])] == -1) {
- found_all = false;
- break;
- }
- }
- if (found_all == true) {
- pass++;
- break;
- }
-
- STACK_SWAP(stack, stack_other);
- }
-
- /* if we have nothing left, and didn't find all elements on the other side,
- * exit early and don't continue */
- if (found_all == false) {
- break;
- }
- }
-
- MEM_freeN(stack);
- MEM_freeN(stack_other);
-
-
- /* Now we have depths recorded from both sides,
- * select elements that use tagged verts. */
- LinkNode *path = NULL;
-
- if (found_all == false) {
- /* fail! (do nothing) */
- }
- else if (path_htype == BM_FACE) {
- BMIter fiter;
- BMFace *f;
-
- BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
- if (!BM_elem_flag_test(f, BM_ELEM_TAG)) {
- /* check all verts in face are tagged */
- BMLoop *l_first, *l_iter;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- bool ok = true;
+ BLI_assert(pass == depths[side][BM_elem_index_get(v_a)] + 1);
+ depths[side][v_b_index] = pass;
+ if (!BM_elem_flag_test(v_b, BM_ELEM_TAG)) {
+ STACK_PUSH(stack_other, v_b);
+ }
+ }
+ }
+ } while ((e = BM_DISK_EDGE_NEXT(e, v_a)) != v_a->e);
+ }
+
+ /* Stop searching once theres none left.
+ * Note that this looks in-efficient, however until the target elements reached,
+ * it will exit immediately.
+ * After that, it takes as many passes as the element has edges to finish off. */
+ found_all = true;
+ for (int i = 0; i < ele_verts_len[side_other]; i++) {
+ if (depths[side][BM_elem_index_get(ele_verts[side_other][i])] == -1) {
+ found_all = false;
+ break;
+ }
+ }
+ if (found_all == true) {
+ pass++;
+ break;
+ }
+
+ STACK_SWAP(stack, stack_other);
+ }
+
+ /* if we have nothing left, and didn't find all elements on the other side,
+ * exit early and don't continue */
+ if (found_all == false) {
+ break;
+ }
+ }
+
+ MEM_freeN(stack);
+ MEM_freeN(stack_other);
+
+ /* Now we have depths recorded from both sides,
+ * select elements that use tagged verts. */
+ LinkNode *path = NULL;
+
+ if (found_all == false) {
+ /* fail! (do nothing) */
+ }
+ else if (path_htype == BM_FACE) {
+ BMIter fiter;
+ BMFace *f;
+
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ if (!BM_elem_flag_test(f, BM_ELEM_TAG)) {
+ /* check all verts in face are tagged */
+ BMLoop *l_first, *l_iter;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ bool ok = true;
#if 0
- do {
- if (!bm_vert_region_test_chain(l_iter->v, depths, pass)) {
- ok = false;
- break;
- }
- } while ((l_iter = l_iter->next) != l_first);
+ do {
+ if (!bm_vert_region_test_chain(l_iter->v, depths, pass)) {
+ ok = false;
+ break;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
#else
- /* Allowing a single failure on a face gives fewer 'gaps'.
- * While correct, in practice they're often part of what a user would consider the 'region'. */
- int ok_tests = f->len > 3 ? 1 : 0; /* how many times we may fail */
- do {
- if (!bm_vert_region_test_chain(l_iter->v, depths, pass)) {
- if (ok_tests == 0) {
- ok = false;
- break;
- }
- ok_tests--;
- }
- } while ((l_iter = l_iter->next) != l_first);
+ /* Allowing a single failure on a face gives fewer 'gaps'.
+ * While correct, in practice they're often part of what a user would consider the 'region'. */
+ int ok_tests = f->len > 3 ? 1 : 0; /* how many times we may fail */
+ do {
+ if (!bm_vert_region_test_chain(l_iter->v, depths, pass)) {
+ if (ok_tests == 0) {
+ ok = false;
+ break;
+ }
+ ok_tests--;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
#endif
- if (ok) {
- BLI_linklist_prepend(&path, f);
- }
- }
- }
- }
- else if (path_htype == BM_EDGE) {
- BMIter eiter;
- BMEdge *e;
-
- BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
- if (!BM_elem_flag_test(e, BM_ELEM_TAG)) {
- /* check all verts in edge are tagged */
- bool ok = true;
- for (int j = 0; j < 2; j++) {
- if (!bm_vert_region_test_chain(*((&e->v1) + j), depths, pass)) {
- ok = false;
- break;
- }
- }
-
- if (ok) {
- BLI_linklist_prepend(&path, e);
- }
- }
- }
- }
- else if (path_htype == BM_VERT) {
- BMIter viter;
- BMVert *v;
-
- BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
- if (bm_vert_region_test_chain(v, depths, pass)) {
- BLI_linklist_prepend(&path, v);
- }
- }
- }
-
-
- for (int side = 0; side < 2; side++) {
- if (depths[side]) {
- MEM_freeN(depths[side]);
- }
- }
-
- return path;
+ if (ok) {
+ BLI_linklist_prepend(&path, f);
+ }
+ }
+ }
+ }
+ else if (path_htype == BM_EDGE) {
+ BMIter eiter;
+ BMEdge *e;
+
+ BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
+ if (!BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ /* check all verts in edge are tagged */
+ bool ok = true;
+ for (int j = 0; j < 2; j++) {
+ if (!bm_vert_region_test_chain(*((&e->v1) + j), depths, pass)) {
+ ok = false;
+ break;
+ }
+ }
+
+ if (ok) {
+ BLI_linklist_prepend(&path, e);
+ }
+ }
+ }
+ }
+ else if (path_htype == BM_VERT) {
+ BMIter viter;
+ BMVert *v;
+
+ BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
+ if (bm_vert_region_test_chain(v, depths, pass)) {
+ BLI_linklist_prepend(&path, v);
+ }
+ }
+ }
+
+ for (int side = 0; side < 2; side++) {
+ if (depths[side]) {
+ MEM_freeN(depths[side]);
+ }
+ }
+
+ return path;
}
#undef USE_EDGE_CHAIN
-
/** \name Main Functions (exposed externally).
* \{ */
-LinkNode *BM_mesh_calc_path_region_vert(
- BMesh *bm, BMElem *ele_src, BMElem *ele_dst,
- bool (*filter_fn)(BMVert *, void *user_data), void *user_data)
+LinkNode *BM_mesh_calc_path_region_vert(BMesh *bm,
+ BMElem *ele_src,
+ BMElem *ele_dst,
+ bool (*filter_fn)(BMVert *, void *user_data),
+ void *user_data)
{
- LinkNode *path = NULL;
- /* BM_ELEM_TAG flag is used to store visited verts */
- BMVert *v;
- BMIter viter;
- int i;
+ LinkNode *path = NULL;
+ /* BM_ELEM_TAG flag is used to store visited verts */
+ BMVert *v;
+ BMIter viter;
+ int i;
- BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
- BM_elem_flag_set(v, BM_ELEM_TAG, !filter_fn(v, user_data));
- BM_elem_index_set(v, i); /* set_inline */
- }
- bm->elem_index_dirty &= ~BM_VERT;
+ BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
+ BM_elem_flag_set(v, BM_ELEM_TAG, !filter_fn(v, user_data));
+ BM_elem_index_set(v, i); /* set_inline */
+ }
+ bm->elem_index_dirty &= ~BM_VERT;
- path = mesh_calc_path_region_elem(bm, ele_src, ele_dst, BM_VERT);
+ path = mesh_calc_path_region_elem(bm, ele_src, ele_dst, BM_VERT);
- return path;
+ return path;
}
-LinkNode *BM_mesh_calc_path_region_edge(
- BMesh *bm, BMElem *ele_src, BMElem *ele_dst,
- bool (*filter_fn)(BMEdge *, void *user_data), void *user_data)
+LinkNode *BM_mesh_calc_path_region_edge(BMesh *bm,
+ BMElem *ele_src,
+ BMElem *ele_dst,
+ bool (*filter_fn)(BMEdge *, void *user_data),
+ void *user_data)
{
- LinkNode *path = NULL;
- /* BM_ELEM_TAG flag is used to store visited verts */
- BMEdge *e;
- BMIter eiter;
- int i;
-
- /* flush flag to verts */
- BM_mesh_elem_hflag_enable_all(bm, BM_VERT, BM_ELEM_TAG, false);
-
- BM_ITER_MESH_INDEX (e, &eiter, bm, BM_EDGES_OF_MESH, i) {
- bool test;
- BM_elem_flag_set(e, BM_ELEM_TAG, test = !filter_fn(e, user_data));
-
- /* flush tag to verts */
- if (test == false) {
- for (int j = 0; j < 2; j++) {
- BM_elem_flag_disable(*((&e->v1) + j), BM_ELEM_TAG);
- }
- }
- }
-
- path = mesh_calc_path_region_elem(bm, ele_src, ele_dst, BM_EDGE);
-
- return path;
+ LinkNode *path = NULL;
+ /* BM_ELEM_TAG flag is used to store visited verts */
+ BMEdge *e;
+ BMIter eiter;
+ int i;
+
+ /* flush flag to verts */
+ BM_mesh_elem_hflag_enable_all(bm, BM_VERT, BM_ELEM_TAG, false);
+
+ BM_ITER_MESH_INDEX (e, &eiter, bm, BM_EDGES_OF_MESH, i) {
+ bool test;
+ BM_elem_flag_set(e, BM_ELEM_TAG, test = !filter_fn(e, user_data));
+
+ /* flush tag to verts */
+ if (test == false) {
+ for (int j = 0; j < 2; j++) {
+ BM_elem_flag_disable(*((&e->v1) + j), BM_ELEM_TAG);
+ }
+ }
+ }
+
+ path = mesh_calc_path_region_elem(bm, ele_src, ele_dst, BM_EDGE);
+
+ return path;
}
-LinkNode *BM_mesh_calc_path_region_face(
- BMesh *bm, BMElem *ele_src, BMElem *ele_dst,
- bool (*filter_fn)(BMFace *, void *user_data), void *user_data)
+LinkNode *BM_mesh_calc_path_region_face(BMesh *bm,
+ BMElem *ele_src,
+ BMElem *ele_dst,
+ bool (*filter_fn)(BMFace *, void *user_data),
+ void *user_data)
{
- LinkNode *path = NULL;
- /* BM_ELEM_TAG flag is used to store visited verts */
- BMFace *f;
- BMIter fiter;
- int i;
-
- /* flush flag to verts */
- BM_mesh_elem_hflag_enable_all(bm, BM_VERT, BM_ELEM_TAG, false);
-
- BM_ITER_MESH_INDEX (f, &fiter, bm, BM_FACES_OF_MESH, i) {
- bool test;
- BM_elem_flag_set(f, BM_ELEM_TAG, test = !filter_fn(f, user_data));
-
- /* flush tag to verts */
- if (test == false) {
- BMLoop *l_first, *l_iter;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- BM_elem_flag_disable(l_iter->v, BM_ELEM_TAG);
- } while ((l_iter = l_iter->next) != l_first);
- }
- }
-
- path = mesh_calc_path_region_elem(bm, ele_src, ele_dst, BM_FACE);
-
- return path;
+ LinkNode *path = NULL;
+ /* BM_ELEM_TAG flag is used to store visited verts */
+ BMFace *f;
+ BMIter fiter;
+ int i;
+
+ /* flush flag to verts */
+ BM_mesh_elem_hflag_enable_all(bm, BM_VERT, BM_ELEM_TAG, false);
+
+ BM_ITER_MESH_INDEX (f, &fiter, bm, BM_FACES_OF_MESH, i) {
+ bool test;
+ BM_elem_flag_set(f, BM_ELEM_TAG, test = !filter_fn(f, user_data));
+
+ /* flush tag to verts */
+ if (test == false) {
+ BMLoop *l_first, *l_iter;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BM_elem_flag_disable(l_iter->v, BM_ELEM_TAG);
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ }
+
+ path = mesh_calc_path_region_elem(bm, ele_src, ele_dst, BM_FACE);
+
+ return path;
}
/** \} */
diff --git a/source/blender/bmesh/tools/bmesh_path_region.h b/source/blender/bmesh/tools/bmesh_path_region.h
index f3ed50f91fd..5204aa45da2 100644
--- a/source/blender/bmesh/tools/bmesh_path_region.h
+++ b/source/blender/bmesh/tools/bmesh_path_region.h
@@ -21,19 +21,25 @@
* \ingroup bmesh
*/
-struct LinkNode *BM_mesh_calc_path_region_vert(
- BMesh *bm, BMElem *ele_src, BMElem *ele_dst,
- bool (*test_fn)(BMVert *, void *user_data), void *user_data)
-ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3);
+struct LinkNode *BM_mesh_calc_path_region_vert(BMesh *bm,
+ BMElem *ele_src,
+ BMElem *ele_dst,
+ bool (*test_fn)(BMVert *, void *user_data),
+ void *user_data) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL(1, 2, 3);
-struct LinkNode *BM_mesh_calc_path_region_edge(
- BMesh *bm, BMElem *ele_src, BMElem *ele_dst,
- bool (*test_fn)(BMEdge *, void *user_data), void *user_data)
-ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3);
+struct LinkNode *BM_mesh_calc_path_region_edge(BMesh *bm,
+ BMElem *ele_src,
+ BMElem *ele_dst,
+ bool (*test_fn)(BMEdge *, void *user_data),
+ void *user_data) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL(1, 2, 3);
-struct LinkNode *BM_mesh_calc_path_region_face(
- BMesh *bm, BMElem *ele_src, BMElem *ele_dst,
- bool (*test_fn)(BMFace *, void *user_data), void *user_data)
-ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3);
+struct LinkNode *BM_mesh_calc_path_region_face(BMesh *bm,
+ BMElem *ele_src,
+ BMElem *ele_dst,
+ bool (*test_fn)(BMFace *, void *user_data),
+ void *user_data) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL(1, 2, 3);
#endif /* __BMESH_PATH_REGION_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_region_match.c b/source/blender/bmesh/tools/bmesh_region_match.c
index a89c41eecc0..6ddbaa6bb2e 100644
--- a/source/blender/bmesh/tools/bmesh_region_match.c
+++ b/source/blender/bmesh/tools/bmesh_region_match.c
@@ -43,7 +43,7 @@
#include "bmesh.h"
-#include "tools/bmesh_region_match.h" /* own incldue */
+#include "tools/bmesh_region_match.h" /* own incldue */
/* avoid re-creating ghash and pools for each search */
#define USE_WALKER_REUSE
@@ -66,7 +66,6 @@
#include "BLI_strict_flags.h"
-
/* -------------------------------------------------------------------- */
/* UUID-Walk API */
@@ -79,261 +78,251 @@ typedef uintptr_t UUID_Int;
typedef struct UUIDWalk {
- /* List of faces we can step onto (UUIDFaceStep's) */
- ListBase faces_step;
+ /* List of faces we can step onto (UUIDFaceStep's) */
+ ListBase faces_step;
- /* Face & Vert UUID's */
- GHash *verts_uuid;
- GHash *faces_uuid;
+ /* Face & Vert UUID's */
+ GHash *verts_uuid;
+ GHash *faces_uuid;
- /* memory pool for LinkNode's */
- BLI_mempool *link_pool;
+ /* memory pool for LinkNode's */
+ BLI_mempool *link_pool;
- /* memory pool for LinkBase's */
- BLI_mempool *lbase_pool;
+ /* memory pool for LinkBase's */
+ BLI_mempool *lbase_pool;
- /* memory pool for UUIDFaceStep's */
- BLI_mempool *step_pool;
- BLI_mempool *step_pool_items;
+ /* memory pool for UUIDFaceStep's */
+ BLI_mempool *step_pool;
+ BLI_mempool *step_pool_items;
- /* Optionaly use face-tag to isolate search */
- bool use_face_isolate;
+ /* Optionaly use face-tag to isolate search */
+ bool use_face_isolate;
- /* Increment for each pass added */
- UUID_Int pass;
+ /* Increment for each pass added */
+ UUID_Int pass;
- /* runtime vars, aviod re-creating each pass */
- struct {
- GHash *verts_uuid; /* BMVert -> UUID */
- GSet *faces_step; /* BMFace */
+ /* runtime vars, aviod re-creating each pass */
+ struct {
+ GHash *verts_uuid; /* BMVert -> UUID */
+ GSet *faces_step; /* BMFace */
- GHash *faces_from_uuid; /* UUID -> UUIDFaceStepItem */
+ GHash *faces_from_uuid; /* UUID -> UUIDFaceStepItem */
- UUID_Int *rehash_store;
- uint rehash_store_len;
- } cache;
+ UUID_Int *rehash_store;
+ uint rehash_store_len;
+ } cache;
} UUIDWalk;
/* stores a set of potential faces to step onto */
typedef struct UUIDFaceStep {
- struct UUIDFaceStep *next, *prev;
+ struct UUIDFaceStep *next, *prev;
- /* unsorted 'BMFace' */
- LinkNode *faces;
+ /* unsorted 'BMFace' */
+ LinkNode *faces;
- /* faces sorted into 'UUIDFaceStepItem' */
- ListBase items;
+ /* faces sorted into 'UUIDFaceStepItem' */
+ ListBase items;
} UUIDFaceStep;
/* store face-lists with same uuid */
typedef struct UUIDFaceStepItem {
- struct UUIDFaceStepItem *next, *prev;
- uintptr_t uuid;
+ struct UUIDFaceStepItem *next, *prev;
+ uintptr_t uuid;
- LinkNode *list;
- uint list_len;
+ LinkNode *list;
+ uint list_len;
} UUIDFaceStepItem;
-BLI_INLINE bool bm_uuidwalk_face_test(
- UUIDWalk *uuidwalk, BMFace *f)
+BLI_INLINE bool bm_uuidwalk_face_test(UUIDWalk *uuidwalk, BMFace *f)
{
- if (uuidwalk->use_face_isolate) {
- return BM_elem_flag_test_bool(f, BM_ELEM_TAG);
- }
- else {
- return true;
- }
+ if (uuidwalk->use_face_isolate) {
+ return BM_elem_flag_test_bool(f, BM_ELEM_TAG);
+ }
+ else {
+ return true;
+ }
}
-BLI_INLINE bool bm_uuidwalk_vert_lookup(
- UUIDWalk *uuidwalk, BMVert *v, UUID_Int *r_uuid)
+BLI_INLINE bool bm_uuidwalk_vert_lookup(UUIDWalk *uuidwalk, BMVert *v, UUID_Int *r_uuid)
{
- void **ret;
- ret = BLI_ghash_lookup_p(uuidwalk->verts_uuid, v);
- if (ret) {
- *r_uuid = (UUID_Int)(*ret);
- return true;
- }
- else {
- return false;
- }
+ void **ret;
+ ret = BLI_ghash_lookup_p(uuidwalk->verts_uuid, v);
+ if (ret) {
+ *r_uuid = (UUID_Int)(*ret);
+ return true;
+ }
+ else {
+ return false;
+ }
}
-BLI_INLINE bool bm_uuidwalk_face_lookup(
- UUIDWalk *uuidwalk, BMFace *f, UUID_Int *r_uuid)
+BLI_INLINE bool bm_uuidwalk_face_lookup(UUIDWalk *uuidwalk, BMFace *f, UUID_Int *r_uuid)
{
- void **ret;
- ret = BLI_ghash_lookup_p(uuidwalk->faces_uuid, f);
- if (ret) {
- *r_uuid = (UUID_Int)(*ret);
- return true;
- }
- else {
- return false;
- }
+ void **ret;
+ ret = BLI_ghash_lookup_p(uuidwalk->faces_uuid, f);
+ if (ret) {
+ *r_uuid = (UUID_Int)(*ret);
+ return true;
+ }
+ else {
+ return false;
+ }
}
static uint ghashutil_bmelem_indexhash(const void *key)
{
- const BMElem *ele = key;
- return (uint)BM_elem_index_get(ele);
+ const BMElem *ele = key;
+ return (uint)BM_elem_index_get(ele);
}
static bool ghashutil_bmelem_indexcmp(const void *a, const void *b)
{
- BLI_assert((a != b) == (BM_elem_index_get((BMElem *)a) != BM_elem_index_get((BMElem *)b)));
- return (a != b);
+ BLI_assert((a != b) == (BM_elem_index_get((BMElem *)a) != BM_elem_index_get((BMElem *)b)));
+ return (a != b);
}
-static GHash *ghash_bmelem_new_ex(
- const char *info,
- const uint nentries_reserve)
+static GHash *ghash_bmelem_new_ex(const char *info, const uint nentries_reserve)
{
- return BLI_ghash_new_ex(ghashutil_bmelem_indexhash, ghashutil_bmelem_indexcmp, info, nentries_reserve);
+ return BLI_ghash_new_ex(
+ ghashutil_bmelem_indexhash, ghashutil_bmelem_indexcmp, info, nentries_reserve);
}
-static GSet *gset_bmelem_new_ex(
- const char *info,
- const uint nentries_reserve)
+static GSet *gset_bmelem_new_ex(const char *info, const uint nentries_reserve)
{
- return BLI_gset_new_ex(ghashutil_bmelem_indexhash, ghashutil_bmelem_indexcmp, info, nentries_reserve);
+ return BLI_gset_new_ex(
+ ghashutil_bmelem_indexhash, ghashutil_bmelem_indexcmp, info, nentries_reserve);
}
-
static GHash *ghash_bmelem_new(const char *info)
{
- return ghash_bmelem_new_ex(info, 0);
+ return ghash_bmelem_new_ex(info, 0);
}
static GSet *gset_bmelem_new(const char *info)
{
- return gset_bmelem_new_ex(info, 0);
+ return gset_bmelem_new_ex(info, 0);
}
-
-static void bm_uuidwalk_init(
- UUIDWalk *uuidwalk,
- const uint faces_src_region_len,
- const uint verts_src_region_len)
+static void bm_uuidwalk_init(UUIDWalk *uuidwalk,
+ const uint faces_src_region_len,
+ const uint verts_src_region_len)
{
- BLI_listbase_clear(&uuidwalk->faces_step);
+ BLI_listbase_clear(&uuidwalk->faces_step);
- uuidwalk->verts_uuid = ghash_bmelem_new_ex(__func__, verts_src_region_len);
- uuidwalk->faces_uuid = ghash_bmelem_new_ex(__func__, faces_src_region_len);
+ uuidwalk->verts_uuid = ghash_bmelem_new_ex(__func__, verts_src_region_len);
+ uuidwalk->faces_uuid = ghash_bmelem_new_ex(__func__, faces_src_region_len);
- uuidwalk->cache.verts_uuid = ghash_bmelem_new(__func__);
- uuidwalk->cache.faces_step = gset_bmelem_new(__func__);
+ uuidwalk->cache.verts_uuid = ghash_bmelem_new(__func__);
+ uuidwalk->cache.faces_step = gset_bmelem_new(__func__);
- /* works because 'int' ghash works for intptr_t too */
- uuidwalk->cache.faces_from_uuid = BLI_ghash_int_new(__func__);
+ /* works because 'int' ghash works for intptr_t too */
+ uuidwalk->cache.faces_from_uuid = BLI_ghash_int_new(__func__);
- uuidwalk->cache.rehash_store = NULL;
- uuidwalk->cache.rehash_store_len = 0;
+ uuidwalk->cache.rehash_store = NULL;
+ uuidwalk->cache.rehash_store_len = 0;
- uuidwalk->use_face_isolate = false;
+ uuidwalk->use_face_isolate = false;
- /* smaller pool's for faster clearing */
- uuidwalk->link_pool = BLI_mempool_create(sizeof(LinkNode), 64, 64, BLI_MEMPOOL_NOP);
- uuidwalk->step_pool = BLI_mempool_create(sizeof(UUIDFaceStep), 64, 64, BLI_MEMPOOL_NOP);
- uuidwalk->step_pool_items = BLI_mempool_create(sizeof(UUIDFaceStepItem), 64, 64, BLI_MEMPOOL_NOP);
+ /* smaller pool's for faster clearing */
+ uuidwalk->link_pool = BLI_mempool_create(sizeof(LinkNode), 64, 64, BLI_MEMPOOL_NOP);
+ uuidwalk->step_pool = BLI_mempool_create(sizeof(UUIDFaceStep), 64, 64, BLI_MEMPOOL_NOP);
+ uuidwalk->step_pool_items = BLI_mempool_create(
+ sizeof(UUIDFaceStepItem), 64, 64, BLI_MEMPOOL_NOP);
- uuidwalk->pass = 1;
+ uuidwalk->pass = 1;
}
-static void bm_uuidwalk_clear(
- UUIDWalk *uuidwalk)
+static void bm_uuidwalk_clear(UUIDWalk *uuidwalk)
{
- BLI_listbase_clear(&uuidwalk->faces_step);
+ BLI_listbase_clear(&uuidwalk->faces_step);
- BLI_ghash_clear(uuidwalk->verts_uuid, NULL, NULL);
- BLI_ghash_clear(uuidwalk->faces_uuid, NULL, NULL);
+ BLI_ghash_clear(uuidwalk->verts_uuid, NULL, NULL);
+ BLI_ghash_clear(uuidwalk->faces_uuid, NULL, NULL);
- BLI_ghash_clear(uuidwalk->cache.verts_uuid, NULL, NULL);
- BLI_gset_clear(uuidwalk->cache.faces_step, NULL);
- BLI_ghash_clear(uuidwalk->cache.faces_from_uuid, NULL, NULL);
+ BLI_ghash_clear(uuidwalk->cache.verts_uuid, NULL, NULL);
+ BLI_gset_clear(uuidwalk->cache.faces_step, NULL);
+ BLI_ghash_clear(uuidwalk->cache.faces_from_uuid, NULL, NULL);
- /* keep rehash_store as-is, for reuse */
+ /* keep rehash_store as-is, for reuse */
- uuidwalk->use_face_isolate = false;
+ uuidwalk->use_face_isolate = false;
- BLI_mempool_clear(uuidwalk->link_pool);
- BLI_mempool_clear(uuidwalk->step_pool);
- BLI_mempool_clear(uuidwalk->step_pool_items);
+ BLI_mempool_clear(uuidwalk->link_pool);
+ BLI_mempool_clear(uuidwalk->step_pool);
+ BLI_mempool_clear(uuidwalk->step_pool_items);
- uuidwalk->pass = 1;
+ uuidwalk->pass = 1;
}
-static void bm_uuidwalk_free(
- UUIDWalk *uuidwalk)
+static void bm_uuidwalk_free(UUIDWalk *uuidwalk)
{
- /**
- * Handled by pools
- *
- * - uuidwalk->faces_step
- */
-
- BLI_ghash_free(uuidwalk->verts_uuid, NULL, NULL);
- BLI_ghash_free(uuidwalk->faces_uuid, NULL, NULL);
-
- /* cache */
- BLI_ghash_free(uuidwalk->cache.verts_uuid, NULL, NULL);
- BLI_gset_free(uuidwalk->cache.faces_step, NULL);
- BLI_ghash_free(uuidwalk->cache.faces_from_uuid, NULL, NULL);
- MEM_SAFE_FREE(uuidwalk->cache.rehash_store);
-
- BLI_mempool_destroy(uuidwalk->link_pool);
- BLI_mempool_destroy(uuidwalk->step_pool);
- BLI_mempool_destroy(uuidwalk->step_pool_items);
+ /**
+ * Handled by pools
+ *
+ * - uuidwalk->faces_step
+ */
+
+ BLI_ghash_free(uuidwalk->verts_uuid, NULL, NULL);
+ BLI_ghash_free(uuidwalk->faces_uuid, NULL, NULL);
+
+ /* cache */
+ BLI_ghash_free(uuidwalk->cache.verts_uuid, NULL, NULL);
+ BLI_gset_free(uuidwalk->cache.faces_step, NULL);
+ BLI_ghash_free(uuidwalk->cache.faces_from_uuid, NULL, NULL);
+ MEM_SAFE_FREE(uuidwalk->cache.rehash_store);
+
+ BLI_mempool_destroy(uuidwalk->link_pool);
+ BLI_mempool_destroy(uuidwalk->step_pool);
+ BLI_mempool_destroy(uuidwalk->step_pool_items);
}
-static UUID_Int bm_uuidwalk_calc_vert_uuid(
- UUIDWalk *uuidwalk, BMVert *v)
+static UUID_Int bm_uuidwalk_calc_vert_uuid(UUIDWalk *uuidwalk, BMVert *v)
{
-#define PRIME_VERT_SMALL 7
-#define PRIME_VERT_MID 43
-#define PRIME_VERT_LARGE 1031
-
-#define PRIME_FACE_SMALL 13
-#define PRIME_FACE_MID 53
-
- UUID_Int uuid;
-
- uuid = uuidwalk->pass * PRIME_VERT_LARGE;
-
- /* vert -> other */
- {
- uint tot = 0;
- BMIter eiter;
- BMEdge *e;
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- BMVert *v_other = BM_edge_other_vert(e, v);
- UUID_Int uuid_other;
- if (bm_uuidwalk_vert_lookup(uuidwalk, v_other, &uuid_other)) {
- uuid ^= (uuid_other * PRIME_VERT_SMALL);
- tot += 1;
- }
- }
- uuid ^= (tot * PRIME_VERT_MID);
- }
-
- /* faces */
- {
- uint tot = 0;
- BMIter iter;
- BMFace *f;
-
- BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) {
- UUID_Int uuid_other;
- if (bm_uuidwalk_face_lookup(uuidwalk, f, &uuid_other)) {
- uuid ^= (uuid_other * PRIME_FACE_SMALL);
- tot += 1;
- }
- }
- uuid ^= (tot * PRIME_FACE_MID);
- }
-
- return uuid;
+#define PRIME_VERT_SMALL 7
+#define PRIME_VERT_MID 43
+#define PRIME_VERT_LARGE 1031
+
+#define PRIME_FACE_SMALL 13
+#define PRIME_FACE_MID 53
+
+ UUID_Int uuid;
+
+ uuid = uuidwalk->pass * PRIME_VERT_LARGE;
+
+ /* vert -> other */
+ {
+ uint tot = 0;
+ BMIter eiter;
+ BMEdge *e;
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ BMVert *v_other = BM_edge_other_vert(e, v);
+ UUID_Int uuid_other;
+ if (bm_uuidwalk_vert_lookup(uuidwalk, v_other, &uuid_other)) {
+ uuid ^= (uuid_other * PRIME_VERT_SMALL);
+ tot += 1;
+ }
+ }
+ uuid ^= (tot * PRIME_VERT_MID);
+ }
+
+ /* faces */
+ {
+ uint tot = 0;
+ BMIter iter;
+ BMFace *f;
+
+ BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) {
+ UUID_Int uuid_other;
+ if (bm_uuidwalk_face_lookup(uuidwalk, f, &uuid_other)) {
+ uuid ^= (uuid_other * PRIME_FACE_SMALL);
+ tot += 1;
+ }
+ }
+ uuid ^= (tot * PRIME_FACE_MID);
+ }
+
+ return uuid;
#undef PRIME_VERT_SMALL
#undef PRIME_VERT_MID
@@ -343,50 +332,49 @@ static UUID_Int bm_uuidwalk_calc_vert_uuid(
#undef PRIME_FACE_MID
}
-static UUID_Int bm_uuidwalk_calc_face_uuid(
- UUIDWalk *uuidwalk, BMFace *f)
+static UUID_Int bm_uuidwalk_calc_face_uuid(UUIDWalk *uuidwalk, BMFace *f)
{
-#define PRIME_VERT_SMALL 11
-
-#define PRIME_FACE_SMALL 17
-#define PRIME_FACE_LARGE 1013
-
- UUID_Int uuid;
-
- uuid = uuidwalk->pass * (uint)f->len * PRIME_FACE_LARGE;
-
- /* face-verts */
- {
- BMLoop *l_iter, *l_first;
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- UUID_Int uuid_other;
- if (bm_uuidwalk_vert_lookup(uuidwalk, l_iter->v, &uuid_other)) {
- uuid ^= (uuid_other * PRIME_VERT_SMALL);
- }
- } while ((l_iter = l_iter->next) != l_first);
- }
-
- /* face-faces (connected by edge) */
- {
- BMLoop *l_iter, *l_first;
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if (l_iter->radial_next != l_iter) {
- BMLoop *l_iter_radial = l_iter->radial_next;
- do {
- UUID_Int uuid_other;
- if (bm_uuidwalk_face_lookup(uuidwalk, l_iter_radial->f, &uuid_other)) {
- uuid ^= (uuid_other * PRIME_FACE_SMALL);
- }
- } while ((l_iter_radial = l_iter_radial->radial_next) != l_iter);
- }
- } while ((l_iter = l_iter->next) != l_first);
- }
-
- return uuid;
+#define PRIME_VERT_SMALL 11
+
+#define PRIME_FACE_SMALL 17
+#define PRIME_FACE_LARGE 1013
+
+ UUID_Int uuid;
+
+ uuid = uuidwalk->pass * (uint)f->len * PRIME_FACE_LARGE;
+
+ /* face-verts */
+ {
+ BMLoop *l_iter, *l_first;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ UUID_Int uuid_other;
+ if (bm_uuidwalk_vert_lookup(uuidwalk, l_iter->v, &uuid_other)) {
+ uuid ^= (uuid_other * PRIME_VERT_SMALL);
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+
+ /* face-faces (connected by edge) */
+ {
+ BMLoop *l_iter, *l_first;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (l_iter->radial_next != l_iter) {
+ BMLoop *l_iter_radial = l_iter->radial_next;
+ do {
+ UUID_Int uuid_other;
+ if (bm_uuidwalk_face_lookup(uuidwalk, l_iter_radial->f, &uuid_other)) {
+ uuid ^= (uuid_other * PRIME_FACE_SMALL);
+ }
+ } while ((l_iter_radial = l_iter_radial->radial_next) != l_iter);
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+
+ return uuid;
#undef PRIME_VERT_SMALL
@@ -394,346 +382,342 @@ static UUID_Int bm_uuidwalk_calc_face_uuid(
#undef PRIME_FACE_LARGE
}
-static void bm_uuidwalk_rehash_reserve(
- UUIDWalk *uuidwalk, uint rehash_store_len_new)
+static void bm_uuidwalk_rehash_reserve(UUIDWalk *uuidwalk, uint rehash_store_len_new)
{
- if (UNLIKELY(rehash_store_len_new > uuidwalk->cache.rehash_store_len)) {
- /* avoid re-allocs */
- rehash_store_len_new *= 2;
- uuidwalk->cache.rehash_store =
- MEM_reallocN(uuidwalk->cache.rehash_store,
- rehash_store_len_new * sizeof(*uuidwalk->cache.rehash_store));
- uuidwalk->cache.rehash_store_len = rehash_store_len_new;
- }
+ if (UNLIKELY(rehash_store_len_new > uuidwalk->cache.rehash_store_len)) {
+ /* avoid re-allocs */
+ rehash_store_len_new *= 2;
+ uuidwalk->cache.rehash_store = MEM_reallocN(uuidwalk->cache.rehash_store,
+ rehash_store_len_new *
+ sizeof(*uuidwalk->cache.rehash_store));
+ uuidwalk->cache.rehash_store_len = rehash_store_len_new;
+ }
}
/**
* Re-hash all elements, delay updating so as not to create feedback loop.
*/
-static void bm_uuidwalk_rehash(
- UUIDWalk *uuidwalk)
+static void bm_uuidwalk_rehash(UUIDWalk *uuidwalk)
{
- GHashIterator gh_iter;
- UUID_Int *uuid_store;
- uint i;
-
- uint rehash_store_len_new = MAX2(BLI_ghash_len(uuidwalk->verts_uuid),
- BLI_ghash_len(uuidwalk->faces_uuid));
-
- bm_uuidwalk_rehash_reserve(uuidwalk, rehash_store_len_new);
- uuid_store = uuidwalk->cache.rehash_store;
-
- /* verts */
- i = 0;
- GHASH_ITER (gh_iter, uuidwalk->verts_uuid) {
- BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
- uuid_store[i++] = bm_uuidwalk_calc_vert_uuid(uuidwalk, v);
- }
- i = 0;
- GHASH_ITER (gh_iter, uuidwalk->verts_uuid) {
- void **uuid_p = BLI_ghashIterator_getValue_p(&gh_iter);
- *((UUID_Int *)uuid_p) = uuid_store[i++];
- }
-
- /* faces */
- i = 0;
- GHASH_ITER (gh_iter, uuidwalk->faces_uuid) {
- BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
- uuid_store[i++] = bm_uuidwalk_calc_face_uuid(uuidwalk, f);
- }
- i = 0;
- GHASH_ITER (gh_iter, uuidwalk->faces_uuid) {
- void **uuid_p = BLI_ghashIterator_getValue_p(&gh_iter);
- *((UUID_Int *)uuid_p) = uuid_store[i++];
- }
+ GHashIterator gh_iter;
+ UUID_Int *uuid_store;
+ uint i;
+
+ uint rehash_store_len_new = MAX2(BLI_ghash_len(uuidwalk->verts_uuid),
+ BLI_ghash_len(uuidwalk->faces_uuid));
+
+ bm_uuidwalk_rehash_reserve(uuidwalk, rehash_store_len_new);
+ uuid_store = uuidwalk->cache.rehash_store;
+
+ /* verts */
+ i = 0;
+ GHASH_ITER (gh_iter, uuidwalk->verts_uuid) {
+ BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
+ uuid_store[i++] = bm_uuidwalk_calc_vert_uuid(uuidwalk, v);
+ }
+ i = 0;
+ GHASH_ITER (gh_iter, uuidwalk->verts_uuid) {
+ void **uuid_p = BLI_ghashIterator_getValue_p(&gh_iter);
+ *((UUID_Int *)uuid_p) = uuid_store[i++];
+ }
+
+ /* faces */
+ i = 0;
+ GHASH_ITER (gh_iter, uuidwalk->faces_uuid) {
+ BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+ uuid_store[i++] = bm_uuidwalk_calc_face_uuid(uuidwalk, f);
+ }
+ i = 0;
+ GHASH_ITER (gh_iter, uuidwalk->faces_uuid) {
+ void **uuid_p = BLI_ghashIterator_getValue_p(&gh_iter);
+ *((UUID_Int *)uuid_p) = uuid_store[i++];
+ }
}
-static void bm_uuidwalk_rehash_facelinks(
- UUIDWalk *uuidwalk,
- LinkNode *faces, const uint faces_len,
- const bool is_init)
+static void bm_uuidwalk_rehash_facelinks(UUIDWalk *uuidwalk,
+ LinkNode *faces,
+ const uint faces_len,
+ const bool is_init)
{
- UUID_Int *uuid_store;
- LinkNode *f_link;
- uint i;
-
- bm_uuidwalk_rehash_reserve(uuidwalk, faces_len);
- uuid_store = uuidwalk->cache.rehash_store;
-
- i = 0;
- for (f_link = faces; f_link; f_link = f_link->next) {
- BMFace *f = f_link->link;
- uuid_store[i++] = bm_uuidwalk_calc_face_uuid(uuidwalk, f);
- }
-
- i = 0;
- if (is_init) {
- for (f_link = faces; f_link; f_link = f_link->next) {
- BMFace *f = f_link->link;
- BLI_ghash_insert(uuidwalk->faces_uuid, f, (void *)uuid_store[i++]);
- }
- }
- else {
- for (f_link = faces; f_link; f_link = f_link->next) {
- BMFace *f = f_link->link;
- void **uuid_p = BLI_ghash_lookup_p(uuidwalk->faces_uuid, f);
- *((UUID_Int *)uuid_p) = uuid_store[i++];
- }
- }
+ UUID_Int *uuid_store;
+ LinkNode *f_link;
+ uint i;
+
+ bm_uuidwalk_rehash_reserve(uuidwalk, faces_len);
+ uuid_store = uuidwalk->cache.rehash_store;
+
+ i = 0;
+ for (f_link = faces; f_link; f_link = f_link->next) {
+ BMFace *f = f_link->link;
+ uuid_store[i++] = bm_uuidwalk_calc_face_uuid(uuidwalk, f);
+ }
+
+ i = 0;
+ if (is_init) {
+ for (f_link = faces; f_link; f_link = f_link->next) {
+ BMFace *f = f_link->link;
+ BLI_ghash_insert(uuidwalk->faces_uuid, f, (void *)uuid_store[i++]);
+ }
+ }
+ else {
+ for (f_link = faces; f_link; f_link = f_link->next) {
+ BMFace *f = f_link->link;
+ void **uuid_p = BLI_ghash_lookup_p(uuidwalk->faces_uuid, f);
+ *((UUID_Int *)uuid_p) = uuid_store[i++];
+ }
+ }
}
-static bool bm_vert_is_uuid_connect(
- UUIDWalk *uuidwalk, BMVert *v)
+static bool bm_vert_is_uuid_connect(UUIDWalk *uuidwalk, BMVert *v)
{
- BMIter eiter;
- BMEdge *e;
-
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- BMVert *v_other = BM_edge_other_vert(e, v);
- if (BLI_ghash_haskey(uuidwalk->verts_uuid, v_other)) {
- return true;
- }
- }
- return false;
+ BMIter eiter;
+ BMEdge *e;
+
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ BMVert *v_other = BM_edge_other_vert(e, v);
+ if (BLI_ghash_haskey(uuidwalk->verts_uuid, v_other)) {
+ return true;
+ }
+ }
+ return false;
}
-static void bm_uuidwalk_pass_add(
- UUIDWalk *uuidwalk, LinkNode *faces_pass, const uint faces_pass_len)
+static void bm_uuidwalk_pass_add(UUIDWalk *uuidwalk,
+ LinkNode *faces_pass,
+ const uint faces_pass_len)
{
- GHashIterator gh_iter;
- GHash *verts_uuid_pass;
- GSet *faces_step_next;
- LinkNode *f_link;
-
- UUIDFaceStep *fstep;
-
- BLI_assert(faces_pass_len == (uint)BLI_linklist_count(faces_pass));
-
- /* rehash faces now all their verts have been added */
- bm_uuidwalk_rehash_facelinks(uuidwalk, faces_pass, faces_pass_len, true);
-
- /* create verts_new */
- verts_uuid_pass = uuidwalk->cache.verts_uuid;
- faces_step_next = uuidwalk->cache.faces_step;
-
- BLI_assert(BLI_ghash_len(verts_uuid_pass) == 0);
- BLI_assert(BLI_gset_len(faces_step_next) == 0);
-
- /* Add the face_step data from connected faces, creating new passes */
- fstep = BLI_mempool_alloc(uuidwalk->step_pool);
- BLI_addhead(&uuidwalk->faces_step, fstep);
- fstep->faces = NULL;
- BLI_listbase_clear(&fstep->items);
-
- for (f_link = faces_pass; f_link; f_link = f_link->next) {
- BMFace *f = f_link->link;
- BMLoop *l_iter, *l_first;
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- /* fill verts_new */
- void **val_p;
- if (!BLI_ghash_haskey(uuidwalk->verts_uuid, l_iter->v) &&
- !BLI_ghash_ensure_p(verts_uuid_pass, l_iter->v, &val_p) &&
- (bm_vert_is_uuid_connect(uuidwalk, l_iter->v) == true))
- {
- const UUID_Int uuid = bm_uuidwalk_calc_vert_uuid(uuidwalk, l_iter->v);
- *val_p = (void *)uuid;
- }
-
- /* fill faces_step_next */
- if (l_iter->radial_next != l_iter) {
- BMLoop *l_iter_radial = l_iter->radial_next;
- do {
- if (!BLI_ghash_haskey(uuidwalk->faces_uuid, l_iter_radial->f) &&
- !BLI_gset_haskey(faces_step_next, l_iter_radial->f) &&
- (bm_uuidwalk_face_test(uuidwalk, l_iter_radial->f)))
- {
- BLI_gset_insert(faces_step_next, l_iter_radial->f);
-
- /* add to fstep */
- BLI_linklist_prepend_pool(&fstep->faces, l_iter_radial->f, uuidwalk->link_pool);
- }
- } while ((l_iter_radial = l_iter_radial->radial_next) != l_iter);
- }
- } while ((l_iter = l_iter->next) != l_first);
- }
-
- /* faces_uuid.update(verts_new) */
- GHASH_ITER (gh_iter, verts_uuid_pass) {
- BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
- void *uuid_p = BLI_ghashIterator_getValue(&gh_iter);
- BLI_ghash_insert(uuidwalk->verts_uuid, v, uuid_p);
- }
-
- /* rehash faces now all their verts have been added */
- bm_uuidwalk_rehash_facelinks(uuidwalk, faces_pass, faces_pass_len, false);
-
- uuidwalk->pass += 1;
-
- BLI_ghash_clear(uuidwalk->cache.verts_uuid, NULL, NULL);
- BLI_gset_clear(uuidwalk->cache.faces_step, NULL);
+ GHashIterator gh_iter;
+ GHash *verts_uuid_pass;
+ GSet *faces_step_next;
+ LinkNode *f_link;
+
+ UUIDFaceStep *fstep;
+
+ BLI_assert(faces_pass_len == (uint)BLI_linklist_count(faces_pass));
+
+ /* rehash faces now all their verts have been added */
+ bm_uuidwalk_rehash_facelinks(uuidwalk, faces_pass, faces_pass_len, true);
+
+ /* create verts_new */
+ verts_uuid_pass = uuidwalk->cache.verts_uuid;
+ faces_step_next = uuidwalk->cache.faces_step;
+
+ BLI_assert(BLI_ghash_len(verts_uuid_pass) == 0);
+ BLI_assert(BLI_gset_len(faces_step_next) == 0);
+
+ /* Add the face_step data from connected faces, creating new passes */
+ fstep = BLI_mempool_alloc(uuidwalk->step_pool);
+ BLI_addhead(&uuidwalk->faces_step, fstep);
+ fstep->faces = NULL;
+ BLI_listbase_clear(&fstep->items);
+
+ for (f_link = faces_pass; f_link; f_link = f_link->next) {
+ BMFace *f = f_link->link;
+ BMLoop *l_iter, *l_first;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ /* fill verts_new */
+ void **val_p;
+ if (!BLI_ghash_haskey(uuidwalk->verts_uuid, l_iter->v) &&
+ !BLI_ghash_ensure_p(verts_uuid_pass, l_iter->v, &val_p) &&
+ (bm_vert_is_uuid_connect(uuidwalk, l_iter->v) == true)) {
+ const UUID_Int uuid = bm_uuidwalk_calc_vert_uuid(uuidwalk, l_iter->v);
+ *val_p = (void *)uuid;
+ }
+
+ /* fill faces_step_next */
+ if (l_iter->radial_next != l_iter) {
+ BMLoop *l_iter_radial = l_iter->radial_next;
+ do {
+ if (!BLI_ghash_haskey(uuidwalk->faces_uuid, l_iter_radial->f) &&
+ !BLI_gset_haskey(faces_step_next, l_iter_radial->f) &&
+ (bm_uuidwalk_face_test(uuidwalk, l_iter_radial->f))) {
+ BLI_gset_insert(faces_step_next, l_iter_radial->f);
+
+ /* add to fstep */
+ BLI_linklist_prepend_pool(&fstep->faces, l_iter_radial->f, uuidwalk->link_pool);
+ }
+ } while ((l_iter_radial = l_iter_radial->radial_next) != l_iter);
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+
+ /* faces_uuid.update(verts_new) */
+ GHASH_ITER (gh_iter, verts_uuid_pass) {
+ BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
+ void *uuid_p = BLI_ghashIterator_getValue(&gh_iter);
+ BLI_ghash_insert(uuidwalk->verts_uuid, v, uuid_p);
+ }
+
+ /* rehash faces now all their verts have been added */
+ bm_uuidwalk_rehash_facelinks(uuidwalk, faces_pass, faces_pass_len, false);
+
+ uuidwalk->pass += 1;
+
+ BLI_ghash_clear(uuidwalk->cache.verts_uuid, NULL, NULL);
+ BLI_gset_clear(uuidwalk->cache.faces_step, NULL);
}
static int bm_face_len_cmp(const void *v1, const void *v2)
{
- const BMFace *f1 = v1, *f2 = v2;
-
- if (f1->len > f2->len) { return 1; }
- else if (f1->len < f2->len) { return -1; }
- else { return 0; }
+ const BMFace *f1 = v1, *f2 = v2;
+
+ if (f1->len > f2->len) {
+ return 1;
+ }
+ else if (f1->len < f2->len) {
+ return -1;
+ }
+ else {
+ return 0;
+ }
}
-static uint bm_uuidwalk_init_from_edge(
- UUIDWalk *uuidwalk, BMEdge *e)
+static uint bm_uuidwalk_init_from_edge(UUIDWalk *uuidwalk, BMEdge *e)
{
- BMLoop *l_iter = e->l;
- uint f_arr_len = (uint)BM_edge_face_count(e);
- BMFace **f_arr = BLI_array_alloca(f_arr, f_arr_len);
- uint fstep_num = 0, i = 0;
-
- do {
- BMFace *f = l_iter->f;
- if (bm_uuidwalk_face_test(uuidwalk, f)) {
- f_arr[i++] = f;
- }
- } while ((l_iter = l_iter->radial_next) != e->l);
- BLI_assert(i <= f_arr_len);
- f_arr_len = i;
-
- qsort(f_arr, f_arr_len, sizeof(*f_arr), bm_face_len_cmp);
-
- /* start us off! */
- {
- const UUID_Int uuid = PRIME_VERT_INIT;
- BLI_ghash_insert(uuidwalk->verts_uuid, e->v1, (void *)uuid);
- BLI_ghash_insert(uuidwalk->verts_uuid, e->v2, (void *)uuid);
- }
-
- /* turning an array into LinkNode's seems odd,
- * but this is just for initialization,
- * elsewhere using LinkNode's makes more sense */
- for (i = 0; i < f_arr_len; ) {
- LinkNode *faces_pass = NULL;
- const uint i_init = i;
- const int f_len = f_arr[i]->len;
-
- do {
- BLI_linklist_prepend_pool(&faces_pass, f_arr[i++], uuidwalk->link_pool);
- } while (i < f_arr_len && (f_len == f_arr[i]->len));
-
- bm_uuidwalk_pass_add(uuidwalk, faces_pass, i - i_init);
- BLI_linklist_free_pool(faces_pass, NULL, uuidwalk->link_pool);
- fstep_num += 1;
- }
-
- return fstep_num;
+ BMLoop *l_iter = e->l;
+ uint f_arr_len = (uint)BM_edge_face_count(e);
+ BMFace **f_arr = BLI_array_alloca(f_arr, f_arr_len);
+ uint fstep_num = 0, i = 0;
+
+ do {
+ BMFace *f = l_iter->f;
+ if (bm_uuidwalk_face_test(uuidwalk, f)) {
+ f_arr[i++] = f;
+ }
+ } while ((l_iter = l_iter->radial_next) != e->l);
+ BLI_assert(i <= f_arr_len);
+ f_arr_len = i;
+
+ qsort(f_arr, f_arr_len, sizeof(*f_arr), bm_face_len_cmp);
+
+ /* start us off! */
+ {
+ const UUID_Int uuid = PRIME_VERT_INIT;
+ BLI_ghash_insert(uuidwalk->verts_uuid, e->v1, (void *)uuid);
+ BLI_ghash_insert(uuidwalk->verts_uuid, e->v2, (void *)uuid);
+ }
+
+ /* turning an array into LinkNode's seems odd,
+ * but this is just for initialization,
+ * elsewhere using LinkNode's makes more sense */
+ for (i = 0; i < f_arr_len;) {
+ LinkNode *faces_pass = NULL;
+ const uint i_init = i;
+ const int f_len = f_arr[i]->len;
+
+ do {
+ BLI_linklist_prepend_pool(&faces_pass, f_arr[i++], uuidwalk->link_pool);
+ } while (i < f_arr_len && (f_len == f_arr[i]->len));
+
+ bm_uuidwalk_pass_add(uuidwalk, faces_pass, i - i_init);
+ BLI_linklist_free_pool(faces_pass, NULL, uuidwalk->link_pool);
+ fstep_num += 1;
+ }
+
+ return fstep_num;
}
#undef PRIME_VERT_INIT
/** \} */
-
/** \name Internal UUIDFaceStep API
* \{ */
static int facestep_sort(const void *a, const void *b)
{
- const UUIDFaceStepItem *fstep_a = a;
- const UUIDFaceStepItem *fstep_b = b;
- return (fstep_a->uuid > fstep_b->uuid) ? 1 : 0;
+ const UUIDFaceStepItem *fstep_a = a;
+ const UUIDFaceStepItem *fstep_b = b;
+ return (fstep_a->uuid > fstep_b->uuid) ? 1 : 0;
}
/**
* Put faces in lists based on their uuid's,
* re-run for each pass since rehashing may differentiate face-groups.
*/
-static bool bm_uuidwalk_facestep_begin(
- UUIDWalk *uuidwalk, UUIDFaceStep *fstep)
+static bool bm_uuidwalk_facestep_begin(UUIDWalk *uuidwalk, UUIDFaceStep *fstep)
{
- LinkNode *f_link, *f_link_next, **f_link_prev_p;
- bool ok = false;
-
- BLI_assert(BLI_ghash_len(uuidwalk->cache.faces_from_uuid) == 0);
- BLI_assert(BLI_listbase_is_empty(&fstep->items));
-
- f_link_prev_p = &fstep->faces;
- for (f_link = fstep->faces; f_link; f_link = f_link_next) {
- BMFace *f = f_link->link;
- f_link_next = f_link->next;
-
- /* possible another pass added this face already, free in that case */
- if (!BLI_ghash_haskey(uuidwalk->faces_uuid, f)) {
- const UUID_Int uuid = bm_uuidwalk_calc_face_uuid(uuidwalk, f);
- UUIDFaceStepItem *fstep_item;
- void **val_p;
-
- ok = true;
-
- if (BLI_ghash_ensure_p(uuidwalk->cache.faces_from_uuid, (void *)uuid, &val_p)) {
- fstep_item = *val_p;
- }
- else {
- fstep_item = *val_p = BLI_mempool_alloc(uuidwalk->step_pool_items);
-
- /* add to start, so its handled on the next round of passes */
- BLI_addhead(&fstep->items, fstep_item);
- fstep_item->uuid = uuid;
- fstep_item->list = NULL;
- fstep_item->list_len = 0;
- }
-
- BLI_linklist_prepend_pool(&fstep_item->list, f, uuidwalk->link_pool);
- fstep_item->list_len += 1;
-
- f_link_prev_p = &f_link->next;
- }
- else {
- *f_link_prev_p = f_link->next;
- BLI_mempool_free(uuidwalk->link_pool, f_link);
- }
- }
-
- BLI_ghash_clear(uuidwalk->cache.faces_from_uuid, NULL, NULL);
-
- BLI_listbase_sort(&fstep->items, facestep_sort);
-
- return ok;
+ LinkNode *f_link, *f_link_next, **f_link_prev_p;
+ bool ok = false;
+
+ BLI_assert(BLI_ghash_len(uuidwalk->cache.faces_from_uuid) == 0);
+ BLI_assert(BLI_listbase_is_empty(&fstep->items));
+
+ f_link_prev_p = &fstep->faces;
+ for (f_link = fstep->faces; f_link; f_link = f_link_next) {
+ BMFace *f = f_link->link;
+ f_link_next = f_link->next;
+
+ /* possible another pass added this face already, free in that case */
+ if (!BLI_ghash_haskey(uuidwalk->faces_uuid, f)) {
+ const UUID_Int uuid = bm_uuidwalk_calc_face_uuid(uuidwalk, f);
+ UUIDFaceStepItem *fstep_item;
+ void **val_p;
+
+ ok = true;
+
+ if (BLI_ghash_ensure_p(uuidwalk->cache.faces_from_uuid, (void *)uuid, &val_p)) {
+ fstep_item = *val_p;
+ }
+ else {
+ fstep_item = *val_p = BLI_mempool_alloc(uuidwalk->step_pool_items);
+
+ /* add to start, so its handled on the next round of passes */
+ BLI_addhead(&fstep->items, fstep_item);
+ fstep_item->uuid = uuid;
+ fstep_item->list = NULL;
+ fstep_item->list_len = 0;
+ }
+
+ BLI_linklist_prepend_pool(&fstep_item->list, f, uuidwalk->link_pool);
+ fstep_item->list_len += 1;
+
+ f_link_prev_p = &f_link->next;
+ }
+ else {
+ *f_link_prev_p = f_link->next;
+ BLI_mempool_free(uuidwalk->link_pool, f_link);
+ }
+ }
+
+ BLI_ghash_clear(uuidwalk->cache.faces_from_uuid, NULL, NULL);
+
+ BLI_listbase_sort(&fstep->items, facestep_sort);
+
+ return ok;
}
/**
* Cleans up temp data from #bm_uuidwalk_facestep_begin
*/
-static void bm_uuidwalk_facestep_end(
- UUIDWalk *uuidwalk, UUIDFaceStep *fstep)
+static void bm_uuidwalk_facestep_end(UUIDWalk *uuidwalk, UUIDFaceStep *fstep)
{
- UUIDFaceStepItem *fstep_item;
+ UUIDFaceStepItem *fstep_item;
- while ((fstep_item = BLI_pophead(&fstep->items))) {
- BLI_mempool_free(uuidwalk->step_pool_items, fstep_item);
- }
+ while ((fstep_item = BLI_pophead(&fstep->items))) {
+ BLI_mempool_free(uuidwalk->step_pool_items, fstep_item);
+ }
}
-static void bm_uuidwalk_facestep_free(
- UUIDWalk *uuidwalk, UUIDFaceStep *fstep)
+static void bm_uuidwalk_facestep_free(UUIDWalk *uuidwalk, UUIDFaceStep *fstep)
{
- LinkNode *f_link, *f_link_next;
+ LinkNode *f_link, *f_link_next;
- BLI_assert(BLI_listbase_is_empty(&fstep->items));
+ BLI_assert(BLI_listbase_is_empty(&fstep->items));
- for (f_link = fstep->faces; f_link; f_link = f_link_next) {
- f_link_next = f_link->next;
- BLI_mempool_free(uuidwalk->link_pool, f_link);
- }
+ for (f_link = fstep->faces; f_link; f_link = f_link_next) {
+ f_link_next = f_link->next;
+ BLI_mempool_free(uuidwalk->link_pool, f_link);
+ }
- BLI_remlink(&uuidwalk->faces_step, fstep);
- BLI_mempool_free(uuidwalk->step_pool, fstep);
+ BLI_remlink(&uuidwalk->faces_step, fstep);
+ BLI_mempool_free(uuidwalk->step_pool, fstep);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/* Main Loop to match up regions */
@@ -743,197 +727,191 @@ static void bm_uuidwalk_facestep_free(
*/
static BMFace **bm_mesh_region_match_pair(
#ifdef USE_WALKER_REUSE
- UUIDWalk *w_src, UUIDWalk *w_dst,
+ UUIDWalk *w_src,
+ UUIDWalk *w_dst,
#endif
- BMEdge *e_src, BMEdge *e_dst,
- const uint faces_src_region_len,
- const uint verts_src_region_len,
- uint *r_faces_result_len)
+ BMEdge *e_src,
+ BMEdge *e_dst,
+ const uint faces_src_region_len,
+ const uint verts_src_region_len,
+ uint *r_faces_result_len)
{
#ifndef USE_WALKER_REUSE
- UUIDWalk w_src_, w_dst_;
- UUIDWalk *w_src = &w_src_, *w_dst = &w_dst_;
+ UUIDWalk w_src_, w_dst_;
+ UUIDWalk *w_src = &w_src_, *w_dst = &w_dst_;
#endif
- BMFace **faces_result = NULL;
- bool found = false;
+ BMFace **faces_result = NULL;
+ bool found = false;
- BLI_assert(e_src != e_dst);
+ BLI_assert(e_src != e_dst);
#ifndef USE_WALKER_REUSE
- bm_uuidwalk_init(w_src, faces_src_region_len, verts_src_region_len);
- bm_uuidwalk_init(w_dst, faces_src_region_len, verts_src_region_len);
+ bm_uuidwalk_init(w_src, faces_src_region_len, verts_src_region_len);
+ bm_uuidwalk_init(w_dst, faces_src_region_len, verts_src_region_len);
#endif
- w_src->use_face_isolate = true;
-
- /* setup the initial state */
- if (UNLIKELY(bm_uuidwalk_init_from_edge(w_src, e_src) !=
- bm_uuidwalk_init_from_edge(w_dst, e_dst)))
- {
- /* should never happen, if verts passed are compatible, but to be safe... */
- goto finally;
- }
-
- bm_uuidwalk_rehash_reserve(w_src, MAX2(faces_src_region_len, verts_src_region_len));
- bm_uuidwalk_rehash_reserve(w_dst, MAX2(faces_src_region_len, verts_src_region_len));
-
- while (true) {
- bool ok = false;
-
- UUIDFaceStep *fstep_src = w_src->faces_step.first;
- UUIDFaceStep *fstep_dst = w_dst->faces_step.first;
-
- BLI_assert(BLI_listbase_count(&w_src->faces_step) == BLI_listbase_count(&w_dst->faces_step));
-
- while (fstep_src) {
-
- /* even if the destination has faces,
- * it's not important, since the source doesn't, free and move-on. */
- if (fstep_src->faces == NULL) {
- UUIDFaceStep *fstep_src_next = fstep_src->next;
- UUIDFaceStep *fstep_dst_next = fstep_dst->next;
- bm_uuidwalk_facestep_free(w_src, fstep_src);
- bm_uuidwalk_facestep_free(w_dst, fstep_dst);
- fstep_src = fstep_src_next;
- fstep_dst = fstep_dst_next;
- continue;
- }
-
- if (bm_uuidwalk_facestep_begin(w_src, fstep_src) &&
- bm_uuidwalk_facestep_begin(w_dst, fstep_dst))
- {
- /* Step over face-lists with matching UUID's
- * both lists are sorted, so no need for lookups.
- * The data is created on 'begin' and cleared on 'end' */
- UUIDFaceStepItem *fstep_item_src;
- UUIDFaceStepItem *fstep_item_dst;
- for (fstep_item_src = fstep_src->items.first,
- fstep_item_dst = fstep_dst->items.first;
- fstep_item_src && fstep_item_dst;
- fstep_item_src = fstep_item_src->next,
- fstep_item_dst = fstep_item_dst->next)
- {
- while ((fstep_item_dst != NULL) &&
- (fstep_item_dst->uuid < fstep_item_src->uuid))
- {
- fstep_item_dst = fstep_item_dst->next;
- }
-
- if ((fstep_item_dst == NULL) ||
- (fstep_item_src->uuid != fstep_item_dst->uuid) ||
- (fstep_item_src->list_len > fstep_item_dst->list_len))
- {
- /* if the target walker has less than the source
- * then the islands don't match, bail early */
- ok = false;
- break;
- }
-
- if (fstep_item_src->list_len == fstep_item_dst->list_len) {
- /* found a match */
- bm_uuidwalk_pass_add(w_src, fstep_item_src->list, fstep_item_src->list_len);
- bm_uuidwalk_pass_add(w_dst, fstep_item_dst->list, fstep_item_dst->list_len);
-
- BLI_linklist_free_pool(fstep_item_src->list, NULL, w_src->link_pool);
- BLI_linklist_free_pool(fstep_item_dst->list, NULL, w_dst->link_pool);
-
- fstep_item_src->list = NULL;
- fstep_item_src->list_len = 0;
-
- fstep_item_dst->list = NULL;
- fstep_item_dst->list_len = 0;
-
- ok = true;
- }
- }
- }
-
- bm_uuidwalk_facestep_end(w_src, fstep_src);
- bm_uuidwalk_facestep_end(w_dst, fstep_dst);
-
- /* lock-step */
- fstep_src = fstep_src->next;
- fstep_dst = fstep_dst->next;
- }
-
- if (!ok) {
- break;
- }
-
- found = (BLI_ghash_len(w_dst->faces_uuid) == faces_src_region_len);
- if (found) {
- break;
- }
-
- /* Expensive! but some cases fails without.
- * (also faster in other cases since it can rule-out invalid regions) */
- bm_uuidwalk_rehash(w_src);
- bm_uuidwalk_rehash(w_dst);
- }
-
- if (found) {
- GHashIterator gh_iter;
- const uint faces_result_len = BLI_ghash_len(w_dst->faces_uuid);
- uint i;
-
- faces_result = MEM_mallocN(sizeof(*faces_result) * (faces_result_len + 1), __func__);
- GHASH_ITER_INDEX (gh_iter, w_dst->faces_uuid, i) {
- BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
- faces_result[i] = f;
- }
- faces_result[faces_result_len] = NULL;
- *r_faces_result_len = faces_result_len;
- }
- else {
- *r_faces_result_len = 0;
- }
+ w_src->use_face_isolate = true;
+
+ /* setup the initial state */
+ if (UNLIKELY(bm_uuidwalk_init_from_edge(w_src, e_src) !=
+ bm_uuidwalk_init_from_edge(w_dst, e_dst))) {
+ /* should never happen, if verts passed are compatible, but to be safe... */
+ goto finally;
+ }
+
+ bm_uuidwalk_rehash_reserve(w_src, MAX2(faces_src_region_len, verts_src_region_len));
+ bm_uuidwalk_rehash_reserve(w_dst, MAX2(faces_src_region_len, verts_src_region_len));
+
+ while (true) {
+ bool ok = false;
+
+ UUIDFaceStep *fstep_src = w_src->faces_step.first;
+ UUIDFaceStep *fstep_dst = w_dst->faces_step.first;
+
+ BLI_assert(BLI_listbase_count(&w_src->faces_step) == BLI_listbase_count(&w_dst->faces_step));
+
+ while (fstep_src) {
+
+ /* even if the destination has faces,
+ * it's not important, since the source doesn't, free and move-on. */
+ if (fstep_src->faces == NULL) {
+ UUIDFaceStep *fstep_src_next = fstep_src->next;
+ UUIDFaceStep *fstep_dst_next = fstep_dst->next;
+ bm_uuidwalk_facestep_free(w_src, fstep_src);
+ bm_uuidwalk_facestep_free(w_dst, fstep_dst);
+ fstep_src = fstep_src_next;
+ fstep_dst = fstep_dst_next;
+ continue;
+ }
+
+ if (bm_uuidwalk_facestep_begin(w_src, fstep_src) &&
+ bm_uuidwalk_facestep_begin(w_dst, fstep_dst)) {
+ /* Step over face-lists with matching UUID's
+ * both lists are sorted, so no need for lookups.
+ * The data is created on 'begin' and cleared on 'end' */
+ UUIDFaceStepItem *fstep_item_src;
+ UUIDFaceStepItem *fstep_item_dst;
+ for (fstep_item_src = fstep_src->items.first, fstep_item_dst = fstep_dst->items.first;
+ fstep_item_src && fstep_item_dst;
+ fstep_item_src = fstep_item_src->next, fstep_item_dst = fstep_item_dst->next) {
+ while ((fstep_item_dst != NULL) && (fstep_item_dst->uuid < fstep_item_src->uuid)) {
+ fstep_item_dst = fstep_item_dst->next;
+ }
+
+ if ((fstep_item_dst == NULL) || (fstep_item_src->uuid != fstep_item_dst->uuid) ||
+ (fstep_item_src->list_len > fstep_item_dst->list_len)) {
+ /* if the target walker has less than the source
+ * then the islands don't match, bail early */
+ ok = false;
+ break;
+ }
+
+ if (fstep_item_src->list_len == fstep_item_dst->list_len) {
+ /* found a match */
+ bm_uuidwalk_pass_add(w_src, fstep_item_src->list, fstep_item_src->list_len);
+ bm_uuidwalk_pass_add(w_dst, fstep_item_dst->list, fstep_item_dst->list_len);
+
+ BLI_linklist_free_pool(fstep_item_src->list, NULL, w_src->link_pool);
+ BLI_linklist_free_pool(fstep_item_dst->list, NULL, w_dst->link_pool);
+
+ fstep_item_src->list = NULL;
+ fstep_item_src->list_len = 0;
+
+ fstep_item_dst->list = NULL;
+ fstep_item_dst->list_len = 0;
+
+ ok = true;
+ }
+ }
+ }
+
+ bm_uuidwalk_facestep_end(w_src, fstep_src);
+ bm_uuidwalk_facestep_end(w_dst, fstep_dst);
+
+ /* lock-step */
+ fstep_src = fstep_src->next;
+ fstep_dst = fstep_dst->next;
+ }
+
+ if (!ok) {
+ break;
+ }
+
+ found = (BLI_ghash_len(w_dst->faces_uuid) == faces_src_region_len);
+ if (found) {
+ break;
+ }
+
+ /* Expensive! but some cases fails without.
+ * (also faster in other cases since it can rule-out invalid regions) */
+ bm_uuidwalk_rehash(w_src);
+ bm_uuidwalk_rehash(w_dst);
+ }
+
+ if (found) {
+ GHashIterator gh_iter;
+ const uint faces_result_len = BLI_ghash_len(w_dst->faces_uuid);
+ uint i;
+
+ faces_result = MEM_mallocN(sizeof(*faces_result) * (faces_result_len + 1), __func__);
+ GHASH_ITER_INDEX(gh_iter, w_dst->faces_uuid, i)
+ {
+ BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+ faces_result[i] = f;
+ }
+ faces_result[faces_result_len] = NULL;
+ *r_faces_result_len = faces_result_len;
+ }
+ else {
+ *r_faces_result_len = 0;
+ }
finally:
#ifdef USE_WALKER_REUSE
- bm_uuidwalk_clear(w_src);
- bm_uuidwalk_clear(w_dst);
+ bm_uuidwalk_clear(w_src);
+ bm_uuidwalk_clear(w_dst);
#else
- bm_uuidwalk_free(w_src);
- bm_uuidwalk_free(w_dst);
+ bm_uuidwalk_free(w_src);
+ bm_uuidwalk_free(w_dst);
#endif
- return faces_result;
+ return faces_result;
}
/**
* Tag as visited, avoid re-use.
*/
-static void bm_face_array_visit(
- BMFace **faces, const uint faces_len,
- uint *r_verts_len,
- bool visit_faces)
+static void bm_face_array_visit(BMFace **faces,
+ const uint faces_len,
+ uint *r_verts_len,
+ bool visit_faces)
{
- uint verts_len = 0;
- uint i;
- for (i = 0; i < faces_len; i++) {
- BMFace *f = faces[i];
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if (r_verts_len) {
- if (!BM_elem_flag_test(l_iter->v, BM_ELEM_TAG)) {
- verts_len += 1;
- }
- }
-
- BM_elem_flag_enable(l_iter->e, BM_ELEM_TAG);
- BM_elem_flag_enable(l_iter->v, BM_ELEM_TAG);
- } while ((l_iter = l_iter->next) != l_first);
-
- if (visit_faces) {
- BM_elem_flag_enable(f, BM_ELEM_TAG);
- }
- }
-
- if (r_verts_len) {
- *r_verts_len = verts_len;
- }
+ uint verts_len = 0;
+ uint i;
+ for (i = 0; i < faces_len; i++) {
+ BMFace *f = faces[i];
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (r_verts_len) {
+ if (!BM_elem_flag_test(l_iter->v, BM_ELEM_TAG)) {
+ verts_len += 1;
+ }
+ }
+
+ BM_elem_flag_enable(l_iter->e, BM_ELEM_TAG);
+ BM_elem_flag_enable(l_iter->v, BM_ELEM_TAG);
+ } while ((l_iter = l_iter->next) != l_first);
+
+ if (visit_faces) {
+ BM_elem_flag_enable(f, BM_ELEM_TAG);
+ }
+ }
+
+ if (r_verts_len) {
+ *r_verts_len = verts_len;
+ }
}
#ifdef USE_PIVOT_SEARCH
@@ -946,74 +924,73 @@ typedef intptr_t SUID_Int;
static bool bm_edge_is_region_boundary(BMEdge *e)
{
- if (e->l->radial_next != e->l) {
- BMLoop *l_iter = e->l;
- do {
- if (!BM_elem_flag_test(l_iter->f, BM_ELEM_TAG)) {
- return true;
- }
- } while ((l_iter = l_iter->radial_next) != e->l);
- return false;
- }
- else {
- /* boundary */
- return true;
- }
+ if (e->l->radial_next != e->l) {
+ BMLoop *l_iter = e->l;
+ do {
+ if (!BM_elem_flag_test(l_iter->f, BM_ELEM_TAG)) {
+ return true;
+ }
+ } while ((l_iter = l_iter->radial_next) != e->l);
+ return false;
+ }
+ else {
+ /* boundary */
+ return true;
+ }
}
-static void bm_face_region_pivot_edge_use_best(
- GHash *gh, BMEdge *e_test,
- BMEdge **r_e_pivot_best,
- SUID_Int e_pivot_best_id[2])
+static void bm_face_region_pivot_edge_use_best(GHash *gh,
+ BMEdge *e_test,
+ BMEdge **r_e_pivot_best,
+ SUID_Int e_pivot_best_id[2])
{
- SUID_Int e_pivot_test_id[2];
-
- e_pivot_test_id[0] = (SUID_Int)BLI_ghash_lookup(gh, e_test->v1);
- e_pivot_test_id[1] = (SUID_Int)BLI_ghash_lookup(gh, e_test->v2);
- if (e_pivot_test_id[0] > e_pivot_test_id[1]) {
- SWAP(SUID_Int, e_pivot_test_id[0], e_pivot_test_id[1]);
- }
-
- if ((*r_e_pivot_best == NULL) ||
- ((e_pivot_best_id[0] != e_pivot_test_id[0]) ?
- (e_pivot_best_id[0] < e_pivot_test_id[0]) :
- (e_pivot_best_id[1] < e_pivot_test_id[1])))
- {
- e_pivot_best_id[0] = e_pivot_test_id[0];
- e_pivot_best_id[1] = e_pivot_test_id[1];
-
- /* both verts are from the same pass, record this! */
- *r_e_pivot_best = e_test;
- }
+ SUID_Int e_pivot_test_id[2];
+
+ e_pivot_test_id[0] = (SUID_Int)BLI_ghash_lookup(gh, e_test->v1);
+ e_pivot_test_id[1] = (SUID_Int)BLI_ghash_lookup(gh, e_test->v2);
+ if (e_pivot_test_id[0] > e_pivot_test_id[1]) {
+ SWAP(SUID_Int, e_pivot_test_id[0], e_pivot_test_id[1]);
+ }
+
+ if ((*r_e_pivot_best == NULL) ||
+ ((e_pivot_best_id[0] != e_pivot_test_id[0]) ? (e_pivot_best_id[0] < e_pivot_test_id[0]) :
+ (e_pivot_best_id[1] < e_pivot_test_id[1]))) {
+ e_pivot_best_id[0] = e_pivot_test_id[0];
+ e_pivot_best_id[1] = e_pivot_test_id[1];
+
+ /* both verts are from the same pass, record this! */
+ *r_e_pivot_best = e_test;
+ }
}
/* quick id from a boundary vertex */
static SUID_Int bm_face_region_vert_boundary_id(BMVert *v)
{
-#define PRIME_VERT_SMALL_A 7
-#define PRIME_VERT_SMALL_B 13
-#define PRIME_VERT_MID_A 103
-#define PRIME_VERT_MID_B 131
-
- int tot = 0;
- BMIter iter;
- BMLoop *l;
- SUID_Int id = PRIME_VERT_MID_A;
-
- BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
- const bool is_boundary_vert = (bm_edge_is_region_boundary(l->e) || bm_edge_is_region_boundary(l->prev->e));
- id ^= l->f->len * (is_boundary_vert ? PRIME_VERT_SMALL_A : PRIME_VERT_SMALL_B);
- tot += 1;
- }
-
- id ^= (tot * PRIME_VERT_MID_B);
-
- return id ? ABS(id) : 1;
-
-#undef PRIME_VERT_SMALL_A
-#undef PRIME_VERT_SMALL_B
-#undef PRIME_VERT_MID_A
-#undef PRIME_VERT_MID_B
+# define PRIME_VERT_SMALL_A 7
+# define PRIME_VERT_SMALL_B 13
+# define PRIME_VERT_MID_A 103
+# define PRIME_VERT_MID_B 131
+
+ int tot = 0;
+ BMIter iter;
+ BMLoop *l;
+ SUID_Int id = PRIME_VERT_MID_A;
+
+ BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
+ const bool is_boundary_vert = (bm_edge_is_region_boundary(l->e) ||
+ bm_edge_is_region_boundary(l->prev->e));
+ id ^= l->f->len * (is_boundary_vert ? PRIME_VERT_SMALL_A : PRIME_VERT_SMALL_B);
+ tot += 1;
+ }
+
+ id ^= (tot * PRIME_VERT_MID_B);
+
+ return id ? ABS(id) : 1;
+
+# undef PRIME_VERT_SMALL_A
+# undef PRIME_VERT_SMALL_B
+# undef PRIME_VERT_MID_A
+# undef PRIME_VERT_MID_B
}
/**
@@ -1021,52 +998,52 @@ static SUID_Int bm_face_region_vert_boundary_id(BMVert *v)
*/
static SUID_Int bm_face_region_vert_pass_id(GHash *gh, BMVert *v)
{
- BMIter eiter;
- BMEdge *e;
- SUID_Int tot = 0;
- SUID_Int v_sum_face_len = 0;
- SUID_Int v_sum_id = 0;
- SUID_Int id;
- SUID_Int id_min = INTPTR_MIN + 1;
-
-#define PRIME_VERT_MID_A 23
-#define PRIME_VERT_MID_B 31
-
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
- BMVert *v_other = BM_edge_other_vert(e, v);
- if (BM_elem_flag_test(v_other, BM_ELEM_TAG)) {
- /* non-zero values aren't allowed... so no need to check haskey */
- SUID_Int v_other_id = (SUID_Int)BLI_ghash_lookup(gh, v_other);
- if (v_other_id > 0) {
- v_sum_id += v_other_id;
- tot += 1;
-
- /* face-count */
- {
- BMLoop *l_iter = e->l;
- do {
- if (BM_elem_flag_test(l_iter->f, BM_ELEM_TAG)) {
- v_sum_face_len += l_iter->f->len;
- }
- } while ((l_iter = l_iter->radial_next) != e->l);
- }
- }
- }
- }
- }
-
- id = (tot * PRIME_VERT_MID_A);
- id ^= (v_sum_face_len * PRIME_VERT_MID_B);
- id ^= v_sum_id;
-
- /* disallow 0 & min (since it can't be flipped) */
- id = (UNLIKELY(id == 0) ? 1 : UNLIKELY(id < id_min) ? id_min : id);
-
- return ABS(id);
-
-#undef PRIME_VERT_MID_A
-#undef PRIME_VERT_MID_B
+ BMIter eiter;
+ BMEdge *e;
+ SUID_Int tot = 0;
+ SUID_Int v_sum_face_len = 0;
+ SUID_Int v_sum_id = 0;
+ SUID_Int id;
+ SUID_Int id_min = INTPTR_MIN + 1;
+
+# define PRIME_VERT_MID_A 23
+# define PRIME_VERT_MID_B 31
+
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ BMVert *v_other = BM_edge_other_vert(e, v);
+ if (BM_elem_flag_test(v_other, BM_ELEM_TAG)) {
+ /* non-zero values aren't allowed... so no need to check haskey */
+ SUID_Int v_other_id = (SUID_Int)BLI_ghash_lookup(gh, v_other);
+ if (v_other_id > 0) {
+ v_sum_id += v_other_id;
+ tot += 1;
+
+ /* face-count */
+ {
+ BMLoop *l_iter = e->l;
+ do {
+ if (BM_elem_flag_test(l_iter->f, BM_ELEM_TAG)) {
+ v_sum_face_len += l_iter->f->len;
+ }
+ } while ((l_iter = l_iter->radial_next) != e->l);
+ }
+ }
+ }
+ }
+ }
+
+ id = (tot * PRIME_VERT_MID_A);
+ id ^= (v_sum_face_len * PRIME_VERT_MID_B);
+ id ^= v_sum_id;
+
+ /* disallow 0 & min (since it can't be flipped) */
+ id = (UNLIKELY(id == 0) ? 1 : UNLIKELY(id < id_min) ? id_min : id);
+
+ return ABS(id);
+
+# undef PRIME_VERT_MID_A
+# undef PRIME_VERT_MID_B
}
/**
@@ -1076,185 +1053,184 @@ static SUID_Int bm_face_region_vert_pass_id(GHash *gh, BMVert *v)
*
* This is only called once on the source region (no need to be highly optimized).
*/
-static BMEdge *bm_face_region_pivot_edge_find(
- BMFace **faces_region, uint faces_region_len,
- uint verts_region_len,
- uint *r_depth)
+static BMEdge *bm_face_region_pivot_edge_find(BMFace **faces_region,
+ uint faces_region_len,
+ uint verts_region_len,
+ uint *r_depth)
{
- /* note, keep deterministic where possible (geometry order independent)
- * this function assumed all visit faces & edges are tagged */
-
- BLI_LINKSTACK_DECLARE(vert_queue_prev, BMVert *);
- BLI_LINKSTACK_DECLARE(vert_queue_next, BMVert *);
-
- GHash *gh = BLI_ghash_ptr_new(__func__);
- uint i;
-
- BMEdge *e_pivot = NULL;
- /* pick any non-boundary edge (not ideal) */
- BMEdge *e_pivot_fallback = NULL;
-
- SUID_Int pass = 0;
-
- /* total verts in 'gs' we have visited - aka - not v_init_none */
- uint vert_queue_used = 0;
-
- BLI_LINKSTACK_INIT(vert_queue_prev);
- BLI_LINKSTACK_INIT(vert_queue_next);
-
- /* face-verts */
- for (i = 0; i < faces_region_len; i++) {
- BMFace *f = faces_region[i];
-
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- BMEdge *e = l_iter->e;
- if (bm_edge_is_region_boundary(e)) {
- uint j;
- for (j = 0; j < 2; j++) {
- void **val_p;
- if (!BLI_ghash_ensure_p(gh, (&e->v1)[j], &val_p)) {
- SUID_Int v_id = bm_face_region_vert_boundary_id((&e->v1)[j]);
- *val_p = (void *)v_id;
- BLI_LINKSTACK_PUSH(vert_queue_prev, (&e->v1)[j]);
- vert_queue_used += 1;
- }
- }
- }
- else {
- /* use incase (depth == 0), no interior verts */
- e_pivot_fallback = e;
- }
- } while ((l_iter = l_iter->next) != l_first);
- }
-
- while (BLI_LINKSTACK_SIZE(vert_queue_prev)) {
- BMVert *v;
- while ((v = BLI_LINKSTACK_POP(vert_queue_prev))) {
- BMIter eiter;
- BMEdge *e;
- BLI_assert(BLI_ghash_haskey(gh, v));
- BLI_assert((SUID_Int)BLI_ghash_lookup(gh, v) > 0);
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
- BMVert *v_other = BM_edge_other_vert(e, v);
- if (BM_elem_flag_test(v_other, BM_ELEM_TAG)) {
- void **val_p;
- if (!BLI_ghash_ensure_p(gh, v_other, &val_p)) {
- /* add as negative, so we know not to read from them this pass */
- const SUID_Int v_id_other = -bm_face_region_vert_pass_id(gh, v_other);
- *val_p = (void *)v_id_other;
- BLI_LINKSTACK_PUSH(vert_queue_next, v_other);
- vert_queue_used += 1;
- }
- }
- }
- }
- }
-
- /* flip all the newly added hashes to positive */
- {
- LinkNode *v_link;
- for (v_link = vert_queue_next; v_link; v_link = v_link->next) {
- SUID_Int *v_id_p = (SUID_Int *)BLI_ghash_lookup_p(gh, v_link->link);
- *v_id_p = -(*v_id_p);
- BLI_assert(*v_id_p > 0);
- }
- }
-
- BLI_LINKSTACK_SWAP(vert_queue_prev, vert_queue_next);
- pass += 1;
-
- if (vert_queue_used == verts_region_len) {
- break;
- }
- }
-
- if (BLI_LINKSTACK_SIZE(vert_queue_prev) >= 2) {
- /* common case - we managed to find some interior verts */
- LinkNode *v_link;
- BMEdge *e_pivot_best = NULL;
- SUID_Int e_pivot_best_id[2] = {0, 0};
-
- /* temp untag, so we can quickly know what other verts are in this last pass */
- for (v_link = vert_queue_prev; v_link; v_link = v_link->next) {
- BMVert *v = v_link->link;
- BM_elem_flag_disable(v, BM_ELEM_TAG);
- }
-
- /* restore correct tagging */
- for (v_link = vert_queue_prev; v_link; v_link = v_link->next) {
- BMIter eiter;
- BMEdge *e_test;
-
- BMVert *v = v_link->link;
- BM_elem_flag_enable(v, BM_ELEM_TAG);
-
- BM_ITER_ELEM (e_test, &eiter, v, BM_EDGES_OF_VERT) {
- if (BM_elem_flag_test(e_test, BM_ELEM_TAG)) {
- BMVert *v_other = BM_edge_other_vert(e_test, v);
- if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == false) {
- bm_face_region_pivot_edge_use_best(gh, e_test, &e_pivot_best, e_pivot_best_id);
- }
- }
- }
- }
-
- e_pivot = e_pivot_best;
- }
-
- if ((e_pivot == NULL) && BLI_LINKSTACK_SIZE(vert_queue_prev)) {
- /* find the best single edge */
- BMEdge *e_pivot_best = NULL;
- SUID_Int e_pivot_best_id[2] = {0, 0};
-
- LinkNode *v_link;
-
- /* reduce a pass since we're having to step into a previous passes vert,
- * and will be closer to the boundary */
- BLI_assert(pass != 0);
- pass -= 1;
-
- for (v_link = vert_queue_prev; v_link; v_link = v_link->next) {
- BMVert *v = v_link->link;
-
- BMIter eiter;
- BMEdge *e_test;
- BM_ITER_ELEM (e_test, &eiter, v, BM_EDGES_OF_VERT) {
- if (BM_elem_flag_test(e_test, BM_ELEM_TAG)) {
- BMVert *v_other = BM_edge_other_vert(e_test, v);
- if (BM_elem_flag_test(v_other, BM_ELEM_TAG)) {
- bm_face_region_pivot_edge_use_best(gh, e_test, &e_pivot_best, e_pivot_best_id);
- }
- }
- }
- }
-
- e_pivot = e_pivot_best;
- }
-
- BLI_LINKSTACK_FREE(vert_queue_prev);
- BLI_LINKSTACK_FREE(vert_queue_next);
-
- BLI_ghash_free(gh, NULL, NULL);
-
- if (e_pivot == NULL) {
-#ifdef DEBUG_PRINT
- printf("%s: using fallback edge!\n", __func__);
-#endif
- e_pivot = e_pivot_fallback;
- pass = 0;
- }
-
- *r_depth = (uint)pass;
-
- return e_pivot;
+ /* note, keep deterministic where possible (geometry order independent)
+ * this function assumed all visit faces & edges are tagged */
+
+ BLI_LINKSTACK_DECLARE(vert_queue_prev, BMVert *);
+ BLI_LINKSTACK_DECLARE(vert_queue_next, BMVert *);
+
+ GHash *gh = BLI_ghash_ptr_new(__func__);
+ uint i;
+
+ BMEdge *e_pivot = NULL;
+ /* pick any non-boundary edge (not ideal) */
+ BMEdge *e_pivot_fallback = NULL;
+
+ SUID_Int pass = 0;
+
+ /* total verts in 'gs' we have visited - aka - not v_init_none */
+ uint vert_queue_used = 0;
+
+ BLI_LINKSTACK_INIT(vert_queue_prev);
+ BLI_LINKSTACK_INIT(vert_queue_next);
+
+ /* face-verts */
+ for (i = 0; i < faces_region_len; i++) {
+ BMFace *f = faces_region[i];
+
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ BMEdge *e = l_iter->e;
+ if (bm_edge_is_region_boundary(e)) {
+ uint j;
+ for (j = 0; j < 2; j++) {
+ void **val_p;
+ if (!BLI_ghash_ensure_p(gh, (&e->v1)[j], &val_p)) {
+ SUID_Int v_id = bm_face_region_vert_boundary_id((&e->v1)[j]);
+ *val_p = (void *)v_id;
+ BLI_LINKSTACK_PUSH(vert_queue_prev, (&e->v1)[j]);
+ vert_queue_used += 1;
+ }
+ }
+ }
+ else {
+ /* use incase (depth == 0), no interior verts */
+ e_pivot_fallback = e;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+
+ while (BLI_LINKSTACK_SIZE(vert_queue_prev)) {
+ BMVert *v;
+ while ((v = BLI_LINKSTACK_POP(vert_queue_prev))) {
+ BMIter eiter;
+ BMEdge *e;
+ BLI_assert(BLI_ghash_haskey(gh, v));
+ BLI_assert((SUID_Int)BLI_ghash_lookup(gh, v) > 0);
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ BMVert *v_other = BM_edge_other_vert(e, v);
+ if (BM_elem_flag_test(v_other, BM_ELEM_TAG)) {
+ void **val_p;
+ if (!BLI_ghash_ensure_p(gh, v_other, &val_p)) {
+ /* add as negative, so we know not to read from them this pass */
+ const SUID_Int v_id_other = -bm_face_region_vert_pass_id(gh, v_other);
+ *val_p = (void *)v_id_other;
+ BLI_LINKSTACK_PUSH(vert_queue_next, v_other);
+ vert_queue_used += 1;
+ }
+ }
+ }
+ }
+ }
+
+ /* flip all the newly added hashes to positive */
+ {
+ LinkNode *v_link;
+ for (v_link = vert_queue_next; v_link; v_link = v_link->next) {
+ SUID_Int *v_id_p = (SUID_Int *)BLI_ghash_lookup_p(gh, v_link->link);
+ *v_id_p = -(*v_id_p);
+ BLI_assert(*v_id_p > 0);
+ }
+ }
+
+ BLI_LINKSTACK_SWAP(vert_queue_prev, vert_queue_next);
+ pass += 1;
+
+ if (vert_queue_used == verts_region_len) {
+ break;
+ }
+ }
+
+ if (BLI_LINKSTACK_SIZE(vert_queue_prev) >= 2) {
+ /* common case - we managed to find some interior verts */
+ LinkNode *v_link;
+ BMEdge *e_pivot_best = NULL;
+ SUID_Int e_pivot_best_id[2] = {0, 0};
+
+ /* temp untag, so we can quickly know what other verts are in this last pass */
+ for (v_link = vert_queue_prev; v_link; v_link = v_link->next) {
+ BMVert *v = v_link->link;
+ BM_elem_flag_disable(v, BM_ELEM_TAG);
+ }
+
+ /* restore correct tagging */
+ for (v_link = vert_queue_prev; v_link; v_link = v_link->next) {
+ BMIter eiter;
+ BMEdge *e_test;
+
+ BMVert *v = v_link->link;
+ BM_elem_flag_enable(v, BM_ELEM_TAG);
+
+ BM_ITER_ELEM (e_test, &eiter, v, BM_EDGES_OF_VERT) {
+ if (BM_elem_flag_test(e_test, BM_ELEM_TAG)) {
+ BMVert *v_other = BM_edge_other_vert(e_test, v);
+ if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == false) {
+ bm_face_region_pivot_edge_use_best(gh, e_test, &e_pivot_best, e_pivot_best_id);
+ }
+ }
+ }
+ }
+
+ e_pivot = e_pivot_best;
+ }
+
+ if ((e_pivot == NULL) && BLI_LINKSTACK_SIZE(vert_queue_prev)) {
+ /* find the best single edge */
+ BMEdge *e_pivot_best = NULL;
+ SUID_Int e_pivot_best_id[2] = {0, 0};
+
+ LinkNode *v_link;
+
+ /* reduce a pass since we're having to step into a previous passes vert,
+ * and will be closer to the boundary */
+ BLI_assert(pass != 0);
+ pass -= 1;
+
+ for (v_link = vert_queue_prev; v_link; v_link = v_link->next) {
+ BMVert *v = v_link->link;
+
+ BMIter eiter;
+ BMEdge *e_test;
+ BM_ITER_ELEM (e_test, &eiter, v, BM_EDGES_OF_VERT) {
+ if (BM_elem_flag_test(e_test, BM_ELEM_TAG)) {
+ BMVert *v_other = BM_edge_other_vert(e_test, v);
+ if (BM_elem_flag_test(v_other, BM_ELEM_TAG)) {
+ bm_face_region_pivot_edge_use_best(gh, e_test, &e_pivot_best, e_pivot_best_id);
+ }
+ }
+ }
+ }
+
+ e_pivot = e_pivot_best;
+ }
+
+ BLI_LINKSTACK_FREE(vert_queue_prev);
+ BLI_LINKSTACK_FREE(vert_queue_next);
+
+ BLI_ghash_free(gh, NULL, NULL);
+
+ if (e_pivot == NULL) {
+# ifdef DEBUG_PRINT
+ printf("%s: using fallback edge!\n", __func__);
+# endif
+ e_pivot = e_pivot_fallback;
+ pass = 0;
+ }
+
+ *r_depth = (uint)pass;
+
+ return e_pivot;
}
/** \} */
-#endif /* USE_PIVOT_SEARCH */
-
+#endif /* USE_PIVOT_SEARCH */
/* -------------------------------------------------------------------- */
/* Quick UUID pass - identify candidates */
@@ -1268,104 +1244,96 @@ typedef uintptr_t UUIDFashMatch;
static UUIDFashMatch bm_vert_fasthash_single(BMVert *v)
{
- BMIter eiter;
- BMEdge *e;
- UUIDFashMatch e_num = 0, f_num = 0, l_num = 0;
-
-#define PRIME_EDGE 7
-#define PRIME_FACE 31
-#define PRIME_LOOP 61
-
- BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
- if (!BM_edge_is_wire(e)) {
- BMLoop *l_iter = e->l;
- e_num += 1;
- do {
- f_num += 1;
- l_num += (uint)l_iter->f->len;
- } while ((l_iter = l_iter->radial_next) != e->l);
- }
- }
-
- return ((e_num * PRIME_EDGE) ^
- (f_num * PRIME_FACE) *
- (l_num * PRIME_LOOP));
-
-#undef PRIME_EDGE
-#undef PRIME_FACE
-#undef PRIME_LOOP
+ BMIter eiter;
+ BMEdge *e;
+ UUIDFashMatch e_num = 0, f_num = 0, l_num = 0;
+
+# define PRIME_EDGE 7
+# define PRIME_FACE 31
+# define PRIME_LOOP 61
+
+ BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
+ if (!BM_edge_is_wire(e)) {
+ BMLoop *l_iter = e->l;
+ e_num += 1;
+ do {
+ f_num += 1;
+ l_num += (uint)l_iter->f->len;
+ } while ((l_iter = l_iter->radial_next) != e->l);
+ }
+ }
+
+ return ((e_num * PRIME_EDGE) ^ (f_num * PRIME_FACE) * (l_num * PRIME_LOOP));
+
+# undef PRIME_EDGE
+# undef PRIME_FACE
+# undef PRIME_LOOP
}
-static UUIDFashMatch *bm_vert_fasthash_create(
- BMesh *bm, const uint depth)
+static UUIDFashMatch *bm_vert_fasthash_create(BMesh *bm, const uint depth)
{
- UUIDFashMatch *id_prev;
- UUIDFashMatch *id_curr;
- uint pass, i;
- BMVert *v;
- BMIter iter;
+ UUIDFashMatch *id_prev;
+ UUIDFashMatch *id_curr;
+ uint pass, i;
+ BMVert *v;
+ BMIter iter;
- id_prev = MEM_mallocN(sizeof(*id_prev) * (uint)bm->totvert, __func__);
- id_curr = MEM_mallocN(sizeof(*id_curr) * (uint)bm->totvert, __func__);
+ id_prev = MEM_mallocN(sizeof(*id_prev) * (uint)bm->totvert, __func__);
+ id_curr = MEM_mallocN(sizeof(*id_curr) * (uint)bm->totvert, __func__);
- BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
- id_prev[i] = bm_vert_fasthash_single(v);
- }
+ BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
+ id_prev[i] = bm_vert_fasthash_single(v);
+ }
- for (pass = 0; pass < depth; pass++) {
- BMEdge *e;
+ for (pass = 0; pass < depth; pass++) {
+ BMEdge *e;
- memcpy(id_curr, id_prev, sizeof(*id_prev) * (uint)bm->totvert);
+ memcpy(id_curr, id_prev, sizeof(*id_prev) * (uint)bm->totvert);
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_edge_is_wire(e) == false) {
- const int i1 = BM_elem_index_get(e->v1);
- const int i2 = BM_elem_index_get(e->v2);
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_edge_is_wire(e) == false) {
+ const int i1 = BM_elem_index_get(e->v1);
+ const int i2 = BM_elem_index_get(e->v2);
- id_curr[i1] += id_prev[i2];
- id_curr[i2] += id_prev[i1];
- }
- }
- }
- MEM_freeN(id_prev);
+ id_curr[i1] += id_prev[i2];
+ id_curr[i2] += id_prev[i1];
+ }
+ }
+ }
+ MEM_freeN(id_prev);
- return id_curr;
+ return id_curr;
}
-static void bm_vert_fasthash_edge_order(
- UUIDFashMatch *fm, const BMEdge *e, UUIDFashMatch e_fm[2])
+static void bm_vert_fasthash_edge_order(UUIDFashMatch *fm, const BMEdge *e, UUIDFashMatch e_fm[2])
{
- e_fm[0] = fm[BM_elem_index_get(e->v1)];
- e_fm[1] = fm[BM_elem_index_get(e->v2)];
+ e_fm[0] = fm[BM_elem_index_get(e->v1)];
+ e_fm[1] = fm[BM_elem_index_get(e->v2)];
- if (e_fm[0] > e_fm[1]) {
- SWAP(UUIDFashMatch, e_fm[0], e_fm[1]);
- }
+ if (e_fm[0] > e_fm[1]) {
+ SWAP(UUIDFashMatch, e_fm[0], e_fm[1]);
+ }
}
-static bool bm_vert_fasthash_edge_is_match(
- UUIDFashMatch *fm, const BMEdge *e_a, const BMEdge *e_b)
+static bool bm_vert_fasthash_edge_is_match(UUIDFashMatch *fm, const BMEdge *e_a, const BMEdge *e_b)
{
- UUIDFashMatch e_a_fm[2];
- UUIDFashMatch e_b_fm[2];
+ UUIDFashMatch e_a_fm[2];
+ UUIDFashMatch e_b_fm[2];
- bm_vert_fasthash_edge_order(fm, e_a, e_a_fm);
- bm_vert_fasthash_edge_order(fm, e_b, e_b_fm);
+ bm_vert_fasthash_edge_order(fm, e_a, e_a_fm);
+ bm_vert_fasthash_edge_order(fm, e_b, e_b_fm);
- return ((e_a_fm[0] == e_b_fm[0]) &&
- (e_a_fm[1] == e_b_fm[1]));
+ return ((e_a_fm[0] == e_b_fm[0]) && (e_a_fm[1] == e_b_fm[1]));
}
-static void bm_vert_fasthash_destroy(
- UUIDFashMatch *fm)
+static void bm_vert_fasthash_destroy(UUIDFashMatch *fm)
{
- MEM_freeN(fm);
+ MEM_freeN(fm);
}
/** \} */
-#endif /* USE_PIVOT_FASTMATCH */
-
+#endif /* USE_PIVOT_FASTMATCH */
/**
* Take a face-region and return a list of matching face-regions.
@@ -1373,143 +1341,142 @@ static void bm_vert_fasthash_destroy(
* \param faces_region: A single, contiguous face-region.
* \return A list of matching null-terminated face-region arrays.
*/
-int BM_mesh_region_match(
- BMesh *bm,
- BMFace **faces_region, uint faces_region_len,
- ListBase *r_face_regions)
+int BM_mesh_region_match(BMesh *bm,
+ BMFace **faces_region,
+ uint faces_region_len,
+ ListBase *r_face_regions)
{
- BMEdge *e_src;
- BMEdge *e_dst;
- BMIter iter;
- uint verts_region_len = 0;
- uint faces_result_len = 0;
- /* number of steps from e_src to a boundary vert */
- uint depth;
-
+ BMEdge *e_src;
+ BMEdge *e_dst;
+ BMIter iter;
+ uint verts_region_len = 0;
+ uint faces_result_len = 0;
+ /* number of steps from e_src to a boundary vert */
+ uint depth;
#ifdef USE_WALKER_REUSE
- UUIDWalk w_src, w_dst;
+ UUIDWalk w_src, w_dst;
#endif
#ifdef USE_PIVOT_FASTMATCH
- UUIDFashMatch *fm;
+ UUIDFashMatch *fm;
#endif
#ifdef DEBUG_PRINT
- int search_num = 0;
+ int search_num = 0;
#endif
#ifdef DEBUG_TIME
- TIMEIT_START(region_match);
+ TIMEIT_START(region_match);
#endif
- /* initialize visited verts */
- BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
- bm_face_array_visit(faces_region, faces_region_len, &verts_region_len, true);
+ /* initialize visited verts */
+ BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
+ bm_face_array_visit(faces_region, faces_region_len, &verts_region_len, true);
- /* needed for 'ghashutil_bmelem_indexhash' */
- BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
+ /* needed for 'ghashutil_bmelem_indexhash' */
+ BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
#ifdef USE_PIVOT_SEARCH
- e_src = bm_face_region_pivot_edge_find(
- faces_region, faces_region_len,
- verts_region_len, &depth);
-
- /* see which edge is added */
-#if 0
- BM_select_history_clear(bm);
- if (e_src) {
- BM_select_history_store(bm, e_src);
- }
-#endif
+ e_src = bm_face_region_pivot_edge_find(faces_region, faces_region_len, verts_region_len, &depth);
+
+ /* see which edge is added */
+# if 0
+ BM_select_history_clear(bm);
+ if (e_src) {
+ BM_select_history_store(bm, e_src);
+ }
+# endif
#else
- /* quick test only! */
- e_src = BM_mesh_active_edge_get(bm);
+ /* quick test only! */
+ e_src = BM_mesh_active_edge_get(bm);
#endif
- if (e_src == NULL) {
+ if (e_src == NULL) {
#ifdef DEBUG_PRINT
- printf("Couldn't find 'e_src'");
+ printf("Couldn't find 'e_src'");
#endif
- return 0;
- }
+ return 0;
+ }
- BLI_listbase_clear(r_face_regions);
+ BLI_listbase_clear(r_face_regions);
#ifdef USE_PIVOT_FASTMATCH
- if (depth > 0) {
- fm = bm_vert_fasthash_create(bm, depth);
- }
- else {
- fm = NULL;
- }
+ if (depth > 0) {
+ fm = bm_vert_fasthash_create(bm, depth);
+ }
+ else {
+ fm = NULL;
+ }
#endif
#ifdef USE_WALKER_REUSE
- bm_uuidwalk_init(&w_src, faces_region_len, verts_region_len);
- bm_uuidwalk_init(&w_dst, faces_region_len, verts_region_len);
+ bm_uuidwalk_init(&w_src, faces_region_len, verts_region_len);
+ bm_uuidwalk_init(&w_dst, faces_region_len, verts_region_len);
#endif
- BM_ITER_MESH (e_dst, &iter, bm, BM_EDGES_OF_MESH) {
- BMFace **faces_result;
- uint faces_result_len_out;
+ BM_ITER_MESH (e_dst, &iter, bm, BM_EDGES_OF_MESH) {
+ BMFace **faces_result;
+ uint faces_result_len_out;
- if (BM_elem_flag_test(e_dst, BM_ELEM_TAG) || BM_edge_is_wire(e_dst)) {
- continue;
- }
+ if (BM_elem_flag_test(e_dst, BM_ELEM_TAG) || BM_edge_is_wire(e_dst)) {
+ continue;
+ }
#ifdef USE_PIVOT_FASTMATCH
- if (fm && !bm_vert_fasthash_edge_is_match(fm, e_src, e_dst)) {
- continue;
- }
+ if (fm && !bm_vert_fasthash_edge_is_match(fm, e_src, e_dst)) {
+ continue;
+ }
#endif
#ifdef DEBUG_PRINT
- search_num += 1;
+ search_num += 1;
#endif
- faces_result = bm_mesh_region_match_pair(
+ faces_result = bm_mesh_region_match_pair(
#ifdef USE_WALKER_REUSE
- &w_src, &w_dst,
+ &w_src,
+ &w_dst,
#endif
- e_src, e_dst,
- faces_region_len,
- verts_region_len,
- &faces_result_len_out);
+ e_src,
+ e_dst,
+ faces_region_len,
+ verts_region_len,
+ &faces_result_len_out);
- /* tag verts as visited */
- if (faces_result) {
- LinkData *link;
+ /* tag verts as visited */
+ if (faces_result) {
+ LinkData *link;
- bm_face_array_visit(faces_result, faces_result_len_out, NULL, false);
+ bm_face_array_visit(faces_result, faces_result_len_out, NULL, false);
- link = BLI_genericNodeN(faces_result);
- BLI_addtail(r_face_regions, link);
- faces_result_len += 1;
- }
- }
+ link = BLI_genericNodeN(faces_result);
+ BLI_addtail(r_face_regions, link);
+ faces_result_len += 1;
+ }
+ }
#ifdef USE_WALKER_REUSE
- bm_uuidwalk_free(&w_src);
- bm_uuidwalk_free(&w_dst);
+ bm_uuidwalk_free(&w_src);
+ bm_uuidwalk_free(&w_dst);
#else
- (void)bm_uuidwalk_clear;
+ (void)bm_uuidwalk_clear;
#endif
#ifdef USE_PIVOT_FASTMATCH
- if (fm) {
- bm_vert_fasthash_destroy(fm);
- }
+ if (fm) {
+ bm_vert_fasthash_destroy(fm);
+ }
#endif
#ifdef DEBUG_PRINT
- printf("%s: search: %d, found %d\n", __func__, search_num, faces_result_len);
+ printf("%s: search: %d, found %d\n", __func__, search_num, faces_result_len);
#endif
#ifdef DEBUG_TIME
- TIMEIT_END(region_match);
+ TIMEIT_END(region_match);
#endif
- return (int)faces_result_len;
+ return (int)faces_result_len;
}
diff --git a/source/blender/bmesh/tools/bmesh_region_match.h b/source/blender/bmesh/tools/bmesh_region_match.h
index 1c460bb7ede..a0625543c51 100644
--- a/source/blender/bmesh/tools/bmesh_region_match.h
+++ b/source/blender/bmesh/tools/bmesh_region_match.h
@@ -21,9 +21,9 @@
* \ingroup bmesh
*/
-int BM_mesh_region_match(
- BMesh *bm,
- BMFace **faces_region, uint faces_region_len,
- ListBase *r_face_regions);
+int BM_mesh_region_match(BMesh *bm,
+ BMFace **faces_region,
+ uint faces_region_len,
+ ListBase *r_face_regions);
#endif /* __BMESH_REGION_MATCH_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_separate.c b/source/blender/bmesh/tools/bmesh_separate.c
index 9e8163c167b..59c82448fa9 100644
--- a/source/blender/bmesh/tools/bmesh_separate.c
+++ b/source/blender/bmesh/tools/bmesh_separate.c
@@ -30,100 +30,97 @@
#include "bmesh.h"
#include "intern/bmesh_private.h"
-#include "bmesh_separate.h" /* own include */
+#include "bmesh_separate.h" /* own include */
/**
* Split all faces that match `filter_fn`.
* \note
*/
-void BM_mesh_separate_faces(
- BMesh *bm,
- BMFaceFilterFunc filter_fn, void *user_data)
+void BM_mesh_separate_faces(BMesh *bm, BMFaceFilterFunc filter_fn, void *user_data)
{
- BMFace **faces_array_all = MEM_mallocN(bm->totface * sizeof(BMFace *), __func__);
- /*
- * - Create an array of faces based on 'filter_fn'.
- * First part of array for match, for non-match.
- *
- * - Enable all vertex tags, then clear all tagged vertices from 'faces_b'.
- *
- * - Loop over 'faces_a', checking each vertex,
- * splitting out any which aren't tagged (and therefor shared), disabling tags as we go.
- */
-
- BMFace *f;
- BMIter iter;
-
- uint faces_a_len = 0;
- uint faces_b_len = 0;
- {
- int i_a = 0;
- int i_b = bm->totface;
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- faces_array_all[filter_fn(f, user_data) ? i_a++ : --i_b] = f;
- }
- faces_a_len = i_a;
- faces_b_len = bm->totface - i_a;
- }
-
- BMFace **faces_a = faces_array_all;
- BMFace **faces_b = faces_array_all + faces_a_len;
-
- /* Enable for all */
- BM_mesh_elem_hflag_enable_all(bm, BM_VERT, BM_ELEM_TAG, false);
-
- /* Disable vert tag on faces_b */
- for (uint i = 0; i < faces_b_len; i++) {
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(faces_b[i]);
- do {
- BM_elem_flag_disable(l_iter->v, BM_ELEM_TAG);
- } while ((l_iter = l_iter->next) != l_first);
- }
-
-
- BLI_buffer_declare_static(BMLoop **, loop_split, 0, 128);
-
- /* Check shared verts ('faces_a' tag and disable) */
- for (uint i = 0; i < faces_a_len; i++) {
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(faces_a[i]);
- do {
- if (!BM_elem_flag_test(l_iter->v, BM_ELEM_TAG)) {
- BMVert *v = l_iter->v;
- /* Enable, since we may visit this vertex again on other faces */
- BM_elem_flag_enable(v, BM_ELEM_TAG);
-
- /* We know the vertex is shared, collect all vertices and split them off. */
-
- /* Fill 'loop_split' */
- {
- BMEdge *e_first, *e_iter;
- e_iter = e_first = l_iter->e;
- do {
- if (e_iter->l != NULL) {
- BMLoop *l_radial_first, *l_radial_iter;
- l_radial_first = l_radial_iter = e_iter->l;
- do {
- if (l_radial_iter->v == v) {
- if (filter_fn(l_radial_iter->f, user_data)) {
- BLI_buffer_append(&loop_split, BMLoop *, l_radial_iter);
- }
- }
- } while ((l_radial_iter = l_radial_iter->radial_next) != l_radial_first);
- }
- } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
- }
-
- /* Perform the split */
- BM_face_loop_separate_multi(bm, loop_split.data, loop_split.count);
-
- BLI_buffer_clear(&loop_split);
- }
- } while ((l_iter = l_iter->next) != l_first);
- }
-
- BLI_buffer_free(&loop_split);
-
- MEM_freeN(faces_array_all);
+ BMFace **faces_array_all = MEM_mallocN(bm->totface * sizeof(BMFace *), __func__);
+ /*
+ * - Create an array of faces based on 'filter_fn'.
+ * First part of array for match, for non-match.
+ *
+ * - Enable all vertex tags, then clear all tagged vertices from 'faces_b'.
+ *
+ * - Loop over 'faces_a', checking each vertex,
+ * splitting out any which aren't tagged (and therefor shared), disabling tags as we go.
+ */
+
+ BMFace *f;
+ BMIter iter;
+
+ uint faces_a_len = 0;
+ uint faces_b_len = 0;
+ {
+ int i_a = 0;
+ int i_b = bm->totface;
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ faces_array_all[filter_fn(f, user_data) ? i_a++ : --i_b] = f;
+ }
+ faces_a_len = i_a;
+ faces_b_len = bm->totface - i_a;
+ }
+
+ BMFace **faces_a = faces_array_all;
+ BMFace **faces_b = faces_array_all + faces_a_len;
+
+ /* Enable for all */
+ BM_mesh_elem_hflag_enable_all(bm, BM_VERT, BM_ELEM_TAG, false);
+
+ /* Disable vert tag on faces_b */
+ for (uint i = 0; i < faces_b_len; i++) {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(faces_b[i]);
+ do {
+ BM_elem_flag_disable(l_iter->v, BM_ELEM_TAG);
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+
+ BLI_buffer_declare_static(BMLoop **, loop_split, 0, 128);
+
+ /* Check shared verts ('faces_a' tag and disable) */
+ for (uint i = 0; i < faces_a_len; i++) {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(faces_a[i]);
+ do {
+ if (!BM_elem_flag_test(l_iter->v, BM_ELEM_TAG)) {
+ BMVert *v = l_iter->v;
+ /* Enable, since we may visit this vertex again on other faces */
+ BM_elem_flag_enable(v, BM_ELEM_TAG);
+
+ /* We know the vertex is shared, collect all vertices and split them off. */
+
+ /* Fill 'loop_split' */
+ {
+ BMEdge *e_first, *e_iter;
+ e_iter = e_first = l_iter->e;
+ do {
+ if (e_iter->l != NULL) {
+ BMLoop *l_radial_first, *l_radial_iter;
+ l_radial_first = l_radial_iter = e_iter->l;
+ do {
+ if (l_radial_iter->v == v) {
+ if (filter_fn(l_radial_iter->f, user_data)) {
+ BLI_buffer_append(&loop_split, BMLoop *, l_radial_iter);
+ }
+ }
+ } while ((l_radial_iter = l_radial_iter->radial_next) != l_radial_first);
+ }
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
+ }
+
+ /* Perform the split */
+ BM_face_loop_separate_multi(bm, loop_split.data, loop_split.count);
+
+ BLI_buffer_clear(&loop_split);
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+
+ BLI_buffer_free(&loop_split);
+
+ MEM_freeN(faces_array_all);
}
diff --git a/source/blender/bmesh/tools/bmesh_separate.h b/source/blender/bmesh/tools/bmesh_separate.h
index 711a94c9242..13293b155fd 100644
--- a/source/blender/bmesh/tools/bmesh_separate.h
+++ b/source/blender/bmesh/tools/bmesh_separate.h
@@ -21,8 +21,6 @@
* \ingroup bmesh
*/
-void BM_mesh_separate_faces(
- BMesh *bm,
- BMFaceFilterFunc filter_fn, void *user_data);
+void BM_mesh_separate_faces(BMesh *bm, BMFaceFilterFunc filter_fn, void *user_data);
#endif /* __BMESH_SEPARATE_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_triangulate.c b/source/blender/bmesh/tools/bmesh_triangulate.c
index 3209732ba66..5c13292e556 100644
--- a/source/blender/bmesh/tools/bmesh_triangulate.c
+++ b/source/blender/bmesh/tools/bmesh_triangulate.c
@@ -20,7 +20,7 @@
* Triangulate.
*/
-#include "DNA_modifier_types.h" /* for MOD_TRIANGULATE_NGON_BEAUTY only */
+#include "DNA_modifier_types.h" /* for MOD_TRIANGULATE_NGON_BEAUTY only */
#include "MEM_guardedalloc.h"
@@ -36,113 +36,133 @@
#include "bmesh.h"
-#include "bmesh_triangulate.h" /* own include */
+#include "bmesh_triangulate.h" /* own include */
/**
* a version of #BM_face_triangulate that maps to #BMOpSlot
*/
-static void bm_face_triangulate_mapping(
- BMesh *bm, BMFace *face,
- const int quad_method, const int ngon_method,
- const bool use_tag,
- BMOperator *op, BMOpSlot *slot_facemap_out, BMOpSlot *slot_facemap_double_out,
-
- MemArena *pf_arena,
- /* use for MOD_TRIANGULATE_NGON_BEAUTY only! */
- struct Heap *pf_heap)
+static void bm_face_triangulate_mapping(BMesh *bm,
+ BMFace *face,
+ const int quad_method,
+ const int ngon_method,
+ const bool use_tag,
+ BMOperator *op,
+ BMOpSlot *slot_facemap_out,
+ BMOpSlot *slot_facemap_double_out,
+
+ MemArena *pf_arena,
+ /* use for MOD_TRIANGULATE_NGON_BEAUTY only! */
+ struct Heap *pf_heap)
{
- int faces_array_tot = face->len - 3;
- BMFace **faces_array = BLI_array_alloca(faces_array, faces_array_tot);
- LinkNode *faces_double = NULL;
- BLI_assert(face->len > 3);
-
- BM_face_triangulate(
- bm, face,
- faces_array, &faces_array_tot,
- NULL, NULL,
- &faces_double,
- quad_method, ngon_method, use_tag,
- pf_arena,
- pf_heap);
-
- if (faces_array_tot) {
- int i;
- BMO_slot_map_elem_insert(op, slot_facemap_out, face, face);
- for (i = 0; i < faces_array_tot; i++) {
- BMO_slot_map_elem_insert(op, slot_facemap_out, faces_array[i], face);
- }
-
- while (faces_double) {
- LinkNode *next = faces_double->next;
- BMO_slot_map_elem_insert(op, slot_facemap_double_out, faces_double->link, face);
- MEM_freeN(faces_double);
- faces_double = next;
- }
- }
+ int faces_array_tot = face->len - 3;
+ BMFace **faces_array = BLI_array_alloca(faces_array, faces_array_tot);
+ LinkNode *faces_double = NULL;
+ BLI_assert(face->len > 3);
+
+ BM_face_triangulate(bm,
+ face,
+ faces_array,
+ &faces_array_tot,
+ NULL,
+ NULL,
+ &faces_double,
+ quad_method,
+ ngon_method,
+ use_tag,
+ pf_arena,
+ pf_heap);
+
+ if (faces_array_tot) {
+ int i;
+ BMO_slot_map_elem_insert(op, slot_facemap_out, face, face);
+ for (i = 0; i < faces_array_tot; i++) {
+ BMO_slot_map_elem_insert(op, slot_facemap_out, faces_array[i], face);
+ }
+
+ while (faces_double) {
+ LinkNode *next = faces_double->next;
+ BMO_slot_map_elem_insert(op, slot_facemap_double_out, faces_double->link, face);
+ MEM_freeN(faces_double);
+ faces_double = next;
+ }
+ }
}
-
-void BM_mesh_triangulate(
- BMesh *bm, const int quad_method, const int ngon_method, const int min_vertices,
- const bool tag_only, BMOperator *op, BMOpSlot *slot_facemap_out,
- BMOpSlot *slot_facemap_double_out)
+void BM_mesh_triangulate(BMesh *bm,
+ const int quad_method,
+ const int ngon_method,
+ const int min_vertices,
+ const bool tag_only,
+ BMOperator *op,
+ BMOpSlot *slot_facemap_out,
+ BMOpSlot *slot_facemap_double_out)
{
- BMIter iter;
- BMFace *face;
- MemArena *pf_arena;
- Heap *pf_heap;
-
- pf_arena = BLI_memarena_new(BLI_POLYFILL_ARENA_SIZE, __func__);
-
- if (ngon_method == MOD_TRIANGULATE_NGON_BEAUTY) {
- pf_heap = BLI_heap_new_ex(BLI_POLYFILL_ALLOC_NGON_RESERVE);
- }
- else {
- pf_heap = NULL;
- }
-
- if (slot_facemap_out) {
- /* same as below but call: bm_face_triangulate_mapping() */
- BM_ITER_MESH (face, &iter, bm, BM_FACES_OF_MESH) {
- if (face->len >= min_vertices) {
- if (tag_only == false || BM_elem_flag_test(face, BM_ELEM_TAG)) {
- bm_face_triangulate_mapping(
- bm, face,
- quad_method, ngon_method, tag_only,
- op, slot_facemap_out, slot_facemap_double_out,
- pf_arena, pf_heap);
- }
- }
- }
- }
- else {
- LinkNode *faces_double = NULL;
-
- BM_ITER_MESH (face, &iter, bm, BM_FACES_OF_MESH) {
- if (face->len >= min_vertices) {
- if (tag_only == false || BM_elem_flag_test(face, BM_ELEM_TAG)) {
- BM_face_triangulate(
- bm, face,
- NULL, NULL,
- NULL, NULL,
- &faces_double,
- quad_method, ngon_method, tag_only,
- pf_arena, pf_heap);
- }
- }
- }
-
- while (faces_double) {
- LinkNode *next = faces_double->next;
- BM_face_kill(bm, faces_double->link);
- MEM_freeN(faces_double);
- faces_double = next;
- }
- }
-
- BLI_memarena_free(pf_arena);
-
- if (ngon_method == MOD_TRIANGULATE_NGON_BEAUTY) {
- BLI_heap_free(pf_heap, NULL);
- }
+ BMIter iter;
+ BMFace *face;
+ MemArena *pf_arena;
+ Heap *pf_heap;
+
+ pf_arena = BLI_memarena_new(BLI_POLYFILL_ARENA_SIZE, __func__);
+
+ if (ngon_method == MOD_TRIANGULATE_NGON_BEAUTY) {
+ pf_heap = BLI_heap_new_ex(BLI_POLYFILL_ALLOC_NGON_RESERVE);
+ }
+ else {
+ pf_heap = NULL;
+ }
+
+ if (slot_facemap_out) {
+ /* same as below but call: bm_face_triangulate_mapping() */
+ BM_ITER_MESH (face, &iter, bm, BM_FACES_OF_MESH) {
+ if (face->len >= min_vertices) {
+ if (tag_only == false || BM_elem_flag_test(face, BM_ELEM_TAG)) {
+ bm_face_triangulate_mapping(bm,
+ face,
+ quad_method,
+ ngon_method,
+ tag_only,
+ op,
+ slot_facemap_out,
+ slot_facemap_double_out,
+ pf_arena,
+ pf_heap);
+ }
+ }
+ }
+ }
+ else {
+ LinkNode *faces_double = NULL;
+
+ BM_ITER_MESH (face, &iter, bm, BM_FACES_OF_MESH) {
+ if (face->len >= min_vertices) {
+ if (tag_only == false || BM_elem_flag_test(face, BM_ELEM_TAG)) {
+ BM_face_triangulate(bm,
+ face,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ &faces_double,
+ quad_method,
+ ngon_method,
+ tag_only,
+ pf_arena,
+ pf_heap);
+ }
+ }
+ }
+
+ while (faces_double) {
+ LinkNode *next = faces_double->next;
+ BM_face_kill(bm, faces_double->link);
+ MEM_freeN(faces_double);
+ faces_double = next;
+ }
+ }
+
+ BLI_memarena_free(pf_arena);
+
+ if (ngon_method == MOD_TRIANGULATE_NGON_BEAUTY) {
+ BLI_heap_free(pf_heap, NULL);
+ }
}
diff --git a/source/blender/bmesh/tools/bmesh_triangulate.h b/source/blender/bmesh/tools/bmesh_triangulate.h
index b254246720c..ababd78f9a1 100644
--- a/source/blender/bmesh/tools/bmesh_triangulate.h
+++ b/source/blender/bmesh/tools/bmesh_triangulate.h
@@ -23,9 +23,13 @@
#ifndef __BMESH_TRIANGULATE_H__
#define __BMESH_TRIANGULATE_H__
-void BM_mesh_triangulate(
- BMesh *bm, const int quad_method, const int ngon_method,
- const int min_vertices, const bool tag_only,
- BMOperator *op, BMOpSlot *slot_facemap_out, BMOpSlot *slot_doubles_out);
+void BM_mesh_triangulate(BMesh *bm,
+ const int quad_method,
+ const int ngon_method,
+ const int min_vertices,
+ const bool tag_only,
+ BMOperator *op,
+ BMOpSlot *slot_facemap_out,
+ BMOpSlot *slot_doubles_out);
-#endif /* __BMESH_TRIANGULATE_H__ */
+#endif /* __BMESH_TRIANGULATE_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_wireframe.c b/source/blender/bmesh/tools/bmesh_wireframe.c
index 82fc4b2334e..0026cab7419 100644
--- a/source/blender/bmesh/tools/bmesh_wireframe.c
+++ b/source/blender/bmesh/tools/bmesh_wireframe.c
@@ -35,122 +35,121 @@
static BMLoop *bm_edge_tag_faceloop(BMEdge *e)
{
- BMLoop *l, *l_first;
+ BMLoop *l, *l_first;
- l = l_first = e->l;
- do {
- if (BM_elem_flag_test(l->f, BM_ELEM_TAG)) {
- return l;
- }
- } while ((l = l->radial_next) != l_first);
+ l = l_first = e->l;
+ do {
+ if (BM_elem_flag_test(l->f, BM_ELEM_TAG)) {
+ return l;
+ }
+ } while ((l = l->radial_next) != l_first);
- /* in the case this is used, we know this will never happen */
- return NULL;
+ /* in the case this is used, we know this will never happen */
+ return NULL;
}
static void bm_vert_boundary_tangent(
- BMVert *v, float r_no[3], float r_no_face[3],
- BMVert **r_va_other, BMVert **r_vb_other)
+ BMVert *v, float r_no[3], float r_no_face[3], BMVert **r_va_other, BMVert **r_vb_other)
{
- BMIter iter;
- BMEdge *e_iter;
-
- BMEdge *e_a = NULL, *e_b = NULL;
- BMVert *v_a, *v_b;
-
- BMLoop *l_a, *l_b;
-
- float no_face[3], no_edge[3];
- float tvec_a[3], tvec_b[3];
-
- /* get 2 boundary edges, there should only _be_ 2,
- * in case there are more - results wont be valid of course */
- BM_ITER_ELEM (e_iter, &iter, v, BM_EDGES_OF_VERT) {
- if (BM_elem_flag_test(e_iter, BM_ELEM_TAG)) {
- if (e_a == NULL) {
- e_a = e_iter;
- }
- else {
- e_b = e_iter;
- break;
- }
- }
- }
-
- if (e_a && e_b) {
- /* note, with an incorrectly flushed selection this can crash */
- l_a = bm_edge_tag_faceloop(e_a);
- l_b = bm_edge_tag_faceloop(e_b);
-
- /* average edge face normal */
- add_v3_v3v3(no_face, l_a->f->no, l_b->f->no);
- normalize_v3(no_face);
-
- /* average edge direction */
- v_a = BM_edge_other_vert(e_a, v);
- v_b = BM_edge_other_vert(e_b, v);
-
- sub_v3_v3v3(tvec_a, v->co, v_a->co);
- sub_v3_v3v3(tvec_b, v_b->co, v->co);
- normalize_v3(tvec_a);
- normalize_v3(tvec_b);
- add_v3_v3v3(no_edge, tvec_a, tvec_b); /* not unit length but this is ok */
-
- /* check are we flipped the right way */
- BM_edge_calc_face_tangent(e_a, l_a, tvec_a);
- BM_edge_calc_face_tangent(e_b, l_b, tvec_b);
- add_v3_v3(tvec_a, tvec_b);
-
- *r_va_other = v_a;
- *r_vb_other = v_b;
- }
- else {
- /* degenerate case - vertex connects a boundary edged face to other faces,
- * so we have only one boundary face - only use it for calculations */
- l_a = bm_edge_tag_faceloop(e_a);
-
- copy_v3_v3(no_face, l_a->f->no);
-
- /* edge direction */
- v_a = BM_edge_other_vert(e_a, v);
- v_b = NULL;
-
- sub_v3_v3v3(no_edge, v->co, v_a->co);
-
- /* check are we flipped the right way */
- BM_edge_calc_face_tangent(e_a, l_a, tvec_a);
-
- *r_va_other = NULL;
- *r_vb_other = NULL;
- }
-
- /* find the normal */
- cross_v3_v3v3(r_no, no_edge, no_face);
- normalize_v3(r_no);
-
- if (dot_v3v3(r_no, tvec_a) > 0.0f) {
- negate_v3(r_no);
- }
-
- copy_v3_v3(r_no_face, no_face);
+ BMIter iter;
+ BMEdge *e_iter;
+
+ BMEdge *e_a = NULL, *e_b = NULL;
+ BMVert *v_a, *v_b;
+
+ BMLoop *l_a, *l_b;
+
+ float no_face[3], no_edge[3];
+ float tvec_a[3], tvec_b[3];
+
+ /* get 2 boundary edges, there should only _be_ 2,
+ * in case there are more - results wont be valid of course */
+ BM_ITER_ELEM (e_iter, &iter, v, BM_EDGES_OF_VERT) {
+ if (BM_elem_flag_test(e_iter, BM_ELEM_TAG)) {
+ if (e_a == NULL) {
+ e_a = e_iter;
+ }
+ else {
+ e_b = e_iter;
+ break;
+ }
+ }
+ }
+
+ if (e_a && e_b) {
+ /* note, with an incorrectly flushed selection this can crash */
+ l_a = bm_edge_tag_faceloop(e_a);
+ l_b = bm_edge_tag_faceloop(e_b);
+
+ /* average edge face normal */
+ add_v3_v3v3(no_face, l_a->f->no, l_b->f->no);
+ normalize_v3(no_face);
+
+ /* average edge direction */
+ v_a = BM_edge_other_vert(e_a, v);
+ v_b = BM_edge_other_vert(e_b, v);
+
+ sub_v3_v3v3(tvec_a, v->co, v_a->co);
+ sub_v3_v3v3(tvec_b, v_b->co, v->co);
+ normalize_v3(tvec_a);
+ normalize_v3(tvec_b);
+ add_v3_v3v3(no_edge, tvec_a, tvec_b); /* not unit length but this is ok */
+
+ /* check are we flipped the right way */
+ BM_edge_calc_face_tangent(e_a, l_a, tvec_a);
+ BM_edge_calc_face_tangent(e_b, l_b, tvec_b);
+ add_v3_v3(tvec_a, tvec_b);
+
+ *r_va_other = v_a;
+ *r_vb_other = v_b;
+ }
+ else {
+ /* degenerate case - vertex connects a boundary edged face to other faces,
+ * so we have only one boundary face - only use it for calculations */
+ l_a = bm_edge_tag_faceloop(e_a);
+
+ copy_v3_v3(no_face, l_a->f->no);
+
+ /* edge direction */
+ v_a = BM_edge_other_vert(e_a, v);
+ v_b = NULL;
+
+ sub_v3_v3v3(no_edge, v->co, v_a->co);
+
+ /* check are we flipped the right way */
+ BM_edge_calc_face_tangent(e_a, l_a, tvec_a);
+
+ *r_va_other = NULL;
+ *r_vb_other = NULL;
+ }
+
+ /* find the normal */
+ cross_v3_v3v3(r_no, no_edge, no_face);
+ normalize_v3(r_no);
+
+ if (dot_v3v3(r_no, tvec_a) > 0.0f) {
+ negate_v3(r_no);
+ }
+
+ copy_v3_v3(r_no_face, no_face);
}
/* check if we are the only tagged loop-face around this edge */
static bool bm_loop_is_radial_boundary(BMLoop *l_first)
{
- BMLoop *l = l_first->radial_next;
-
- if (l == l_first) {
- return true; /* a real boundary */
- }
- else {
- do {
- if (BM_elem_flag_test(l->f, BM_ELEM_TAG)) {
- return false;
- }
- } while ((l = l->radial_next) != l_first);
- }
- return true;
+ BMLoop *l = l_first->radial_next;
+
+ if (l == l_first) {
+ return true; /* a real boundary */
+ }
+ else {
+ do {
+ if (BM_elem_flag_test(l->f, BM_ELEM_TAG)) {
+ return false;
+ }
+ } while ((l = l->radial_next) != l_first);
+ }
+ return true;
}
/**
@@ -159,445 +158,442 @@ static bool bm_loop_is_radial_boundary(BMLoop *l_first)
* \note All edge tags must be cleared.
* \note Behavior matches MOD_solidify.c
*/
-void BM_mesh_wireframe(
- BMesh *bm,
- const float offset,
- const float offset_fac,
- const float offset_fac_vg,
- const bool use_replace,
- const bool use_boundary,
- const bool use_even_offset,
- const bool use_relative_offset,
- const bool use_crease,
- const float crease_weight,
- const int defgrp_index,
- const bool defgrp_invert,
- const short mat_offset,
- const short mat_max,
- /* for operators */
- const bool use_tag
- )
+void BM_mesh_wireframe(BMesh *bm,
+ const float offset,
+ const float offset_fac,
+ const float offset_fac_vg,
+ const bool use_replace,
+ const bool use_boundary,
+ const bool use_even_offset,
+ const bool use_relative_offset,
+ const bool use_crease,
+ const float crease_weight,
+ const int defgrp_index,
+ const bool defgrp_invert,
+ const short mat_offset,
+ const short mat_max,
+ /* for operators */
+ const bool use_tag)
{
- const float ofs_orig = -(((-offset_fac + 1.0f) * 0.5f) * offset);
- const float ofs_new = offset + ofs_orig;
- const float ofs_mid = (ofs_orig + ofs_new) / 2.0f;
- const float inset = offset / 2.0f;
- int cd_edge_crease_offset = use_crease ? CustomData_get_offset(&bm->edata, CD_CREASE) : -1;
- const int cd_dvert_offset = (defgrp_index != -1) ? CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT) : -1;
- const float offset_fac_vg_inv = 1.0f - offset_fac_vg;
-
- const int totvert_orig = bm->totvert;
-
- BMIter iter;
- BMIter itersub;
-
- /* filled only with boundary verts */
- BMVert **verts_src = MEM_mallocN(sizeof(BMVert *) * totvert_orig, __func__);
- BMVert **verts_neg = MEM_mallocN(sizeof(BMVert *) * totvert_orig, __func__);
- BMVert **verts_pos = MEM_mallocN(sizeof(BMVert *) * totvert_orig, __func__);
-
- /* will over-alloc, but makes for easy lookups by index to keep aligned */
- BMVert **verts_boundary = use_boundary ?
- MEM_mallocN(sizeof(BMVert *) * totvert_orig, __func__) : NULL;
-
- float *verts_relfac = (use_relative_offset || (cd_dvert_offset != -1)) ?
- MEM_mallocN(sizeof(float) * totvert_orig, __func__) : NULL;
-
- /* may over-alloc if not all faces have wire */
- BMVert **verts_loop;
- int verts_loop_tot = 0;
-
- BMVert *v_src;
-
- BMFace *f_src;
- BMLoop *l;
-
- float tvec[3];
- float fac, fac_shell;
-
- int i;
-
- if (use_crease && cd_edge_crease_offset == -1) {
- BM_data_layer_add(bm, &bm->edata, CD_CREASE);
- cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE);
- }
-
- BM_ITER_MESH_INDEX (v_src, &iter, bm, BM_VERTS_OF_MESH, i) {
- BM_elem_index_set(v_src, i); /* set_inline */
-
- verts_src[i] = v_src;
- BM_elem_flag_disable(v_src, BM_ELEM_TAG);
- }
- bm->elem_index_dirty &= ~BM_VERT;
-
- /* setup tags, all faces and verts will be tagged which will be duplicated */
-
- BM_ITER_MESH_INDEX (f_src, &iter, bm, BM_FACES_OF_MESH, i) {
- BM_elem_index_set(f_src, i); /* set_inline */
-
- if (use_tag) {
- if (!BM_elem_flag_test(f_src, BM_ELEM_TAG)) {
- continue;
- }
- }
- else {
- BM_elem_flag_enable(f_src, BM_ELEM_TAG);
- }
-
-
- verts_loop_tot += f_src->len;
- BM_ITER_ELEM (l, &itersub, f_src, BM_LOOPS_OF_FACE) {
- BM_elem_flag_enable(l->v, BM_ELEM_TAG);
-
- /* also tag boundary edges */
- BM_elem_flag_set(l->e, BM_ELEM_TAG, bm_loop_is_radial_boundary(l));
- }
- }
- bm->elem_index_dirty &= ~BM_FACE;
-
- /* duplicate tagged verts */
- for (i = 0; i < totvert_orig; i++) {
- v_src = verts_src[i];
- if (BM_elem_flag_test(v_src, BM_ELEM_TAG)) {
- fac = 1.0f;
-
- if (verts_relfac) {
- if (use_relative_offset) {
- verts_relfac[i] = BM_vert_calc_median_tagged_edge_length(v_src);
- }
- else {
- verts_relfac[i] = 1.0f;
- }
-
-
- if (cd_dvert_offset != -1) {
- MDeformVert *dvert = BM_ELEM_CD_GET_VOID_P(v_src, cd_dvert_offset);
- float defgrp_fac = defvert_find_weight(dvert, defgrp_index);
-
- if (defgrp_invert) {
- defgrp_fac = 1.0f - defgrp_fac;
- }
-
- if (offset_fac_vg > 0.0f) {
- defgrp_fac = (offset_fac_vg + (defgrp_fac * offset_fac_vg_inv));
- }
-
- verts_relfac[i] *= defgrp_fac;
- }
-
- fac *= verts_relfac[i];
- }
-
-
- verts_neg[i] = BM_vert_create(bm, NULL, v_src, BM_CREATE_NOP);
- verts_pos[i] = BM_vert_create(bm, NULL, v_src, BM_CREATE_NOP);
-
- if (offset == 0.0f) {
- madd_v3_v3v3fl(verts_neg[i]->co, v_src->co, v_src->no, ofs_orig * fac);
- madd_v3_v3v3fl(verts_pos[i]->co, v_src->co, v_src->no, ofs_new * fac);
- }
- else {
- madd_v3_v3v3fl(tvec, v_src->co, v_src->no, ofs_mid * fac);
-
- madd_v3_v3v3fl(verts_neg[i]->co, tvec, v_src->no, (ofs_orig - ofs_mid) * fac);
- madd_v3_v3v3fl(verts_pos[i]->co, tvec, v_src->no, (ofs_new - ofs_mid) * fac);
- }
- }
- else {
- /* could skip this */
- verts_neg[i] = NULL;
- verts_pos[i] = NULL;
- }
-
- /* conflicts with BM_vert_calc_median_tagged_edge_length */
- if (use_relative_offset == false) {
- BM_elem_flag_disable(v_src, BM_ELEM_TAG);
- }
- }
-
- if (use_relative_offset) {
- BM_mesh_elem_hflag_disable_all(bm, BM_VERT, BM_ELEM_TAG, false);
- }
-
- verts_loop = MEM_mallocN(sizeof(BMVert *) * verts_loop_tot, __func__);
- verts_loop_tot = 0; /* count up again */
-
- BM_ITER_MESH (f_src, &iter, bm, BM_FACES_OF_MESH) {
-
- if (use_tag && !BM_elem_flag_test(f_src, BM_ELEM_TAG)) {
- continue;
- }
-
- BM_ITER_ELEM (l, &itersub, f_src, BM_LOOPS_OF_FACE) {
- /* Because some faces might be skipped! */
- BM_elem_index_set(l, verts_loop_tot); /* set_dirty */
-
- BM_loop_calc_face_tangent(l, tvec);
-
- /* create offset vert */
- fac = 1.0f;
-
- if (verts_relfac) {
- fac *= verts_relfac[BM_elem_index_get(l->v)];
- }
-
- fac_shell = fac;
- if (use_even_offset) {
- fac_shell *= shell_angle_to_dist(((float)M_PI - BM_loop_calc_face_angle(l)) * 0.5f);
- }
-
-
- madd_v3_v3v3fl(tvec, l->v->co, tvec, inset * fac_shell);
- if (offset != 0.0f) {
- madd_v3_v3fl(tvec, l->v->no, ofs_mid * fac);
- }
- verts_loop[verts_loop_tot] = BM_vert_create(bm, tvec, l->v, BM_CREATE_NOP);
-
-
- if (use_boundary) {
- if (BM_elem_flag_test(l->e, BM_ELEM_TAG)) { /* is this a boundary? */
- BMVert *v_pair[2] = {l->v, l->next->v};
-
- for (i = 0; i < 2; i++) {
- BMVert *v_boundary = v_pair[i];
- if (!BM_elem_flag_test(v_boundary, BM_ELEM_TAG)) {
- const int v_boundary_index = BM_elem_index_get(v_boundary);
- float no_face[3];
- BMVert *va_other;
- BMVert *vb_other;
-
- BM_elem_flag_enable(v_boundary, BM_ELEM_TAG);
-
- bm_vert_boundary_tangent(v_boundary, tvec, no_face, &va_other, &vb_other);
-
- /* create offset vert */
- /* similar to code above but different angle calc */
- fac = 1.0f;
-
- if (verts_relfac) {
- fac *= verts_relfac[v_boundary_index];
- }
-
- fac_shell = fac;
- if (use_even_offset) {
- if (va_other) { /* for verts with only one boundary edge - this will be NULL */
- fac_shell *= shell_angle_to_dist(((float)M_PI -
- angle_on_axis_v3v3v3_v3(va_other->co,
- v_boundary->co,
- vb_other->co,
- no_face)) * 0.5f);
- }
- }
-
-
- madd_v3_v3v3fl(tvec, v_boundary->co, tvec, inset * fac_shell);
- if (offset != 0.0f) {
- madd_v3_v3fl(tvec, v_boundary->no, ofs_mid * fac);
- }
- verts_boundary[v_boundary_index] = BM_vert_create(bm, tvec, v_boundary, BM_CREATE_NOP);
- }
- }
- }
- }
-
- verts_loop_tot++;
- }
- }
- bm->elem_index_dirty |= BM_LOOP;
-
- BM_ITER_MESH (f_src, &iter, bm, BM_FACES_OF_MESH) {
-
- /* skip recently added faces */
- if (BM_elem_index_get(f_src) == -1) {
- continue;
- }
-
- if (use_tag && !BM_elem_flag_test(f_src, BM_ELEM_TAG)) {
- continue;
- }
-
- BM_elem_flag_disable(f_src, BM_ELEM_TAG);
-
- BM_ITER_ELEM (l, &itersub, f_src, BM_LOOPS_OF_FACE) {
- BMFace *f_new;
- BMLoop *l_new;
- BMLoop *l_next = l->next;
- BMVert *v_l1 = verts_loop[BM_elem_index_get(l)];
- BMVert *v_l2 = verts_loop[BM_elem_index_get(l_next)];
-
- BMVert *v_src_l1 = l->v;
- BMVert *v_src_l2 = l_next->v;
-
- const int i_1 = BM_elem_index_get(v_src_l1);
- const int i_2 = BM_elem_index_get(v_src_l2);
-
- BMVert *v_neg1 = verts_neg[i_1];
- BMVert *v_neg2 = verts_neg[i_2];
-
- BMVert *v_pos1 = verts_pos[i_1];
- BMVert *v_pos2 = verts_pos[i_2];
-
- f_new = BM_face_create_quad_tri(bm, v_l1, v_l2, v_neg2, v_neg1, f_src, BM_CREATE_NOP);
- if (mat_offset) {
- f_new->mat_nr = CLAMPIS(f_new->mat_nr + mat_offset, 0, mat_max);
- }
- BM_elem_flag_enable(f_new, BM_ELEM_TAG);
- l_new = BM_FACE_FIRST_LOOP(f_new);
-
- BM_elem_attrs_copy(bm, bm, l, l_new);
- BM_elem_attrs_copy(bm, bm, l, l_new->prev);
- BM_elem_attrs_copy(bm, bm, l_next, l_new->next);
- BM_elem_attrs_copy(bm, bm, l_next, l_new->next->next);
-
- f_new = BM_face_create_quad_tri(bm, v_l2, v_l1, v_pos1, v_pos2, f_src, BM_CREATE_NOP);
-
- if (mat_offset) {
- f_new->mat_nr = CLAMPIS(f_new->mat_nr + mat_offset, 0, mat_max);
- }
- BM_elem_flag_enable(f_new, BM_ELEM_TAG);
- l_new = BM_FACE_FIRST_LOOP(f_new);
-
- BM_elem_attrs_copy(bm, bm, l_next, l_new);
- BM_elem_attrs_copy(bm, bm, l_next, l_new->prev);
- BM_elem_attrs_copy(bm, bm, l, l_new->next);
- BM_elem_attrs_copy(bm, bm, l, l_new->next->next);
-
- if (use_boundary) {
- if (BM_elem_flag_test(l->e, BM_ELEM_TAG)) {
- /* we know its a boundary and this is the only face user (which is being wire'd) */
- /* we know we only touch this edge/face once */
- BMVert *v_b1 = verts_boundary[i_1];
- BMVert *v_b2 = verts_boundary[i_2];
-
- f_new = BM_face_create_quad_tri(bm, v_b2, v_b1, v_neg1, v_neg2, f_src, BM_CREATE_NOP);
- if (mat_offset) {
- f_new->mat_nr = CLAMPIS(f_new->mat_nr + mat_offset, 0, mat_max);
- }
- BM_elem_flag_enable(f_new, BM_ELEM_TAG);
- l_new = BM_FACE_FIRST_LOOP(f_new);
-
- BM_elem_attrs_copy(bm, bm, l_next, l_new);
- BM_elem_attrs_copy(bm, bm, l_next, l_new->prev);
- BM_elem_attrs_copy(bm, bm, l, l_new->next);
- BM_elem_attrs_copy(bm, bm, l, l_new->next->next);
-
- f_new = BM_face_create_quad_tri(bm, v_b1, v_b2, v_pos2, v_pos1, f_src, BM_CREATE_NOP);
- if (mat_offset) {
- f_new->mat_nr = CLAMPIS(f_new->mat_nr + mat_offset, 0, mat_max);
- }
- BM_elem_flag_enable(f_new, BM_ELEM_TAG);
- l_new = BM_FACE_FIRST_LOOP(f_new);
-
- BM_elem_attrs_copy(bm, bm, l, l_new);
- BM_elem_attrs_copy(bm, bm, l, l_new->prev);
- BM_elem_attrs_copy(bm, bm, l_next, l_new->next);
- BM_elem_attrs_copy(bm, bm, l_next, l_new->next->next);
-
- if (use_crease) {
- BMEdge *e_new;
- e_new = BM_edge_exists(v_pos1, v_b1);
- BM_ELEM_CD_SET_FLOAT(e_new, cd_edge_crease_offset, crease_weight);
-
- e_new = BM_edge_exists(v_pos2, v_b2);
- BM_ELEM_CD_SET_FLOAT(e_new, cd_edge_crease_offset, crease_weight);
-
- e_new = BM_edge_exists(v_neg1, v_b1);
- BM_ELEM_CD_SET_FLOAT(e_new, cd_edge_crease_offset, crease_weight);
-
- e_new = BM_edge_exists(v_neg2, v_b2);
- BM_ELEM_CD_SET_FLOAT(e_new, cd_edge_crease_offset, crease_weight);
- }
- }
- }
-
- if (use_crease) {
- BMEdge *e_new;
- e_new = BM_edge_exists(v_pos1, v_l1);
- BM_ELEM_CD_SET_FLOAT(e_new, cd_edge_crease_offset, crease_weight);
-
- e_new = BM_edge_exists(v_pos2, v_l2);
- BM_ELEM_CD_SET_FLOAT(e_new, cd_edge_crease_offset, crease_weight);
-
- e_new = BM_edge_exists(v_neg1, v_l1);
- BM_ELEM_CD_SET_FLOAT(e_new, cd_edge_crease_offset, crease_weight);
-
- e_new = BM_edge_exists(v_neg2, v_l2);
- BM_ELEM_CD_SET_FLOAT(e_new, cd_edge_crease_offset, crease_weight);
- }
-
- }
- }
-
- if (use_boundary) {
- MEM_freeN(verts_boundary);
- }
-
- if (verts_relfac) {
- MEM_freeN(verts_relfac);
- }
-
- if (use_replace) {
-
- if (use_tag) {
- /* only remove faces which are original and used to make wire,
- * use 'verts_pos' and 'verts_neg' to avoid a feedback loop. */
-
- /* vertex must be from 'verts_src' */
-#define VERT_DUPE_TEST_ORIG(v) (verts_neg[BM_elem_index_get(v)] != NULL)
-#define VERT_DUPE_TEST(v) (verts_pos[BM_elem_index_get(v)] != NULL)
-#define VERT_DUPE_CLEAR(v) { verts_pos[BM_elem_index_get(v)] = NULL; } (void)0
-
- /* first ensure we keep all verts which are used in faces that weren't
- * entirely made into wire. */
- BM_ITER_MESH (f_src, &iter, bm, BM_FACES_OF_MESH) {
- int mix_flag = 0;
- BMLoop *l_iter, *l_first;
-
- /* skip new faces */
- if (BM_elem_index_get(f_src) == -1) {
- continue;
- }
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(f_src);
- do {
- mix_flag |= (VERT_DUPE_TEST_ORIG(l_iter->v) ? 1 : 2);
- if (mix_flag == (1 | 2)) {
- break;
- }
- } while ((l_iter = l_iter->next) != l_first);
-
- if (mix_flag == (1 | 2)) {
- l_iter = l_first = BM_FACE_FIRST_LOOP(f_src);
- do {
- VERT_DUPE_CLEAR(l_iter->v);
- } while ((l_iter = l_iter->next) != l_first);
- }
- }
-
- /* now remove any verts which were made into wire by all faces */
- for (i = 0; i < totvert_orig; i++) {
- v_src = verts_src[i];
- BLI_assert(i == BM_elem_index_get(v_src));
- if (VERT_DUPE_TEST(v_src)) {
- BM_vert_kill(bm, v_src);
- }
- }
+ const float ofs_orig = -(((-offset_fac + 1.0f) * 0.5f) * offset);
+ const float ofs_new = offset + ofs_orig;
+ const float ofs_mid = (ofs_orig + ofs_new) / 2.0f;
+ const float inset = offset / 2.0f;
+ int cd_edge_crease_offset = use_crease ? CustomData_get_offset(&bm->edata, CD_CREASE) : -1;
+ const int cd_dvert_offset = (defgrp_index != -1) ?
+ CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT) :
+ -1;
+ const float offset_fac_vg_inv = 1.0f - offset_fac_vg;
+
+ const int totvert_orig = bm->totvert;
+
+ BMIter iter;
+ BMIter itersub;
+
+ /* filled only with boundary verts */
+ BMVert **verts_src = MEM_mallocN(sizeof(BMVert *) * totvert_orig, __func__);
+ BMVert **verts_neg = MEM_mallocN(sizeof(BMVert *) * totvert_orig, __func__);
+ BMVert **verts_pos = MEM_mallocN(sizeof(BMVert *) * totvert_orig, __func__);
+
+ /* will over-alloc, but makes for easy lookups by index to keep aligned */
+ BMVert **verts_boundary = use_boundary ? MEM_mallocN(sizeof(BMVert *) * totvert_orig, __func__) :
+ NULL;
+
+ float *verts_relfac = (use_relative_offset || (cd_dvert_offset != -1)) ?
+ MEM_mallocN(sizeof(float) * totvert_orig, __func__) :
+ NULL;
+
+ /* may over-alloc if not all faces have wire */
+ BMVert **verts_loop;
+ int verts_loop_tot = 0;
+
+ BMVert *v_src;
+
+ BMFace *f_src;
+ BMLoop *l;
+
+ float tvec[3];
+ float fac, fac_shell;
+
+ int i;
+
+ if (use_crease && cd_edge_crease_offset == -1) {
+ BM_data_layer_add(bm, &bm->edata, CD_CREASE);
+ cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE);
+ }
+
+ BM_ITER_MESH_INDEX (v_src, &iter, bm, BM_VERTS_OF_MESH, i) {
+ BM_elem_index_set(v_src, i); /* set_inline */
+
+ verts_src[i] = v_src;
+ BM_elem_flag_disable(v_src, BM_ELEM_TAG);
+ }
+ bm->elem_index_dirty &= ~BM_VERT;
+
+ /* setup tags, all faces and verts will be tagged which will be duplicated */
+
+ BM_ITER_MESH_INDEX (f_src, &iter, bm, BM_FACES_OF_MESH, i) {
+ BM_elem_index_set(f_src, i); /* set_inline */
+
+ if (use_tag) {
+ if (!BM_elem_flag_test(f_src, BM_ELEM_TAG)) {
+ continue;
+ }
+ }
+ else {
+ BM_elem_flag_enable(f_src, BM_ELEM_TAG);
+ }
+
+ verts_loop_tot += f_src->len;
+ BM_ITER_ELEM (l, &itersub, f_src, BM_LOOPS_OF_FACE) {
+ BM_elem_flag_enable(l->v, BM_ELEM_TAG);
+
+ /* also tag boundary edges */
+ BM_elem_flag_set(l->e, BM_ELEM_TAG, bm_loop_is_radial_boundary(l));
+ }
+ }
+ bm->elem_index_dirty &= ~BM_FACE;
+
+ /* duplicate tagged verts */
+ for (i = 0; i < totvert_orig; i++) {
+ v_src = verts_src[i];
+ if (BM_elem_flag_test(v_src, BM_ELEM_TAG)) {
+ fac = 1.0f;
+
+ if (verts_relfac) {
+ if (use_relative_offset) {
+ verts_relfac[i] = BM_vert_calc_median_tagged_edge_length(v_src);
+ }
+ else {
+ verts_relfac[i] = 1.0f;
+ }
+
+ if (cd_dvert_offset != -1) {
+ MDeformVert *dvert = BM_ELEM_CD_GET_VOID_P(v_src, cd_dvert_offset);
+ float defgrp_fac = defvert_find_weight(dvert, defgrp_index);
+
+ if (defgrp_invert) {
+ defgrp_fac = 1.0f - defgrp_fac;
+ }
+
+ if (offset_fac_vg > 0.0f) {
+ defgrp_fac = (offset_fac_vg + (defgrp_fac * offset_fac_vg_inv));
+ }
+
+ verts_relfac[i] *= defgrp_fac;
+ }
+
+ fac *= verts_relfac[i];
+ }
+
+ verts_neg[i] = BM_vert_create(bm, NULL, v_src, BM_CREATE_NOP);
+ verts_pos[i] = BM_vert_create(bm, NULL, v_src, BM_CREATE_NOP);
+
+ if (offset == 0.0f) {
+ madd_v3_v3v3fl(verts_neg[i]->co, v_src->co, v_src->no, ofs_orig * fac);
+ madd_v3_v3v3fl(verts_pos[i]->co, v_src->co, v_src->no, ofs_new * fac);
+ }
+ else {
+ madd_v3_v3v3fl(tvec, v_src->co, v_src->no, ofs_mid * fac);
+
+ madd_v3_v3v3fl(verts_neg[i]->co, tvec, v_src->no, (ofs_orig - ofs_mid) * fac);
+ madd_v3_v3v3fl(verts_pos[i]->co, tvec, v_src->no, (ofs_new - ofs_mid) * fac);
+ }
+ }
+ else {
+ /* could skip this */
+ verts_neg[i] = NULL;
+ verts_pos[i] = NULL;
+ }
+
+ /* conflicts with BM_vert_calc_median_tagged_edge_length */
+ if (use_relative_offset == false) {
+ BM_elem_flag_disable(v_src, BM_ELEM_TAG);
+ }
+ }
+
+ if (use_relative_offset) {
+ BM_mesh_elem_hflag_disable_all(bm, BM_VERT, BM_ELEM_TAG, false);
+ }
+
+ verts_loop = MEM_mallocN(sizeof(BMVert *) * verts_loop_tot, __func__);
+ verts_loop_tot = 0; /* count up again */
+
+ BM_ITER_MESH (f_src, &iter, bm, BM_FACES_OF_MESH) {
+
+ if (use_tag && !BM_elem_flag_test(f_src, BM_ELEM_TAG)) {
+ continue;
+ }
+
+ BM_ITER_ELEM (l, &itersub, f_src, BM_LOOPS_OF_FACE) {
+ /* Because some faces might be skipped! */
+ BM_elem_index_set(l, verts_loop_tot); /* set_dirty */
+
+ BM_loop_calc_face_tangent(l, tvec);
+
+ /* create offset vert */
+ fac = 1.0f;
+
+ if (verts_relfac) {
+ fac *= verts_relfac[BM_elem_index_get(l->v)];
+ }
+
+ fac_shell = fac;
+ if (use_even_offset) {
+ fac_shell *= shell_angle_to_dist(((float)M_PI - BM_loop_calc_face_angle(l)) * 0.5f);
+ }
+
+ madd_v3_v3v3fl(tvec, l->v->co, tvec, inset * fac_shell);
+ if (offset != 0.0f) {
+ madd_v3_v3fl(tvec, l->v->no, ofs_mid * fac);
+ }
+ verts_loop[verts_loop_tot] = BM_vert_create(bm, tvec, l->v, BM_CREATE_NOP);
+
+ if (use_boundary) {
+ if (BM_elem_flag_test(l->e, BM_ELEM_TAG)) { /* is this a boundary? */
+ BMVert *v_pair[2] = {l->v, l->next->v};
+
+ for (i = 0; i < 2; i++) {
+ BMVert *v_boundary = v_pair[i];
+ if (!BM_elem_flag_test(v_boundary, BM_ELEM_TAG)) {
+ const int v_boundary_index = BM_elem_index_get(v_boundary);
+ float no_face[3];
+ BMVert *va_other;
+ BMVert *vb_other;
+
+ BM_elem_flag_enable(v_boundary, BM_ELEM_TAG);
+
+ bm_vert_boundary_tangent(v_boundary, tvec, no_face, &va_other, &vb_other);
+
+ /* create offset vert */
+ /* similar to code above but different angle calc */
+ fac = 1.0f;
+
+ if (verts_relfac) {
+ fac *= verts_relfac[v_boundary_index];
+ }
+
+ fac_shell = fac;
+ if (use_even_offset) {
+ if (va_other) { /* for verts with only one boundary edge - this will be NULL */
+ fac_shell *= shell_angle_to_dist(
+ ((float)M_PI - angle_on_axis_v3v3v3_v3(
+ va_other->co, v_boundary->co, vb_other->co, no_face)) *
+ 0.5f);
+ }
+ }
+
+ madd_v3_v3v3fl(tvec, v_boundary->co, tvec, inset * fac_shell);
+ if (offset != 0.0f) {
+ madd_v3_v3fl(tvec, v_boundary->no, ofs_mid * fac);
+ }
+ verts_boundary[v_boundary_index] = BM_vert_create(
+ bm, tvec, v_boundary, BM_CREATE_NOP);
+ }
+ }
+ }
+ }
+
+ verts_loop_tot++;
+ }
+ }
+ bm->elem_index_dirty |= BM_LOOP;
+
+ BM_ITER_MESH (f_src, &iter, bm, BM_FACES_OF_MESH) {
+
+ /* skip recently added faces */
+ if (BM_elem_index_get(f_src) == -1) {
+ continue;
+ }
+
+ if (use_tag && !BM_elem_flag_test(f_src, BM_ELEM_TAG)) {
+ continue;
+ }
+
+ BM_elem_flag_disable(f_src, BM_ELEM_TAG);
+
+ BM_ITER_ELEM (l, &itersub, f_src, BM_LOOPS_OF_FACE) {
+ BMFace *f_new;
+ BMLoop *l_new;
+ BMLoop *l_next = l->next;
+ BMVert *v_l1 = verts_loop[BM_elem_index_get(l)];
+ BMVert *v_l2 = verts_loop[BM_elem_index_get(l_next)];
+
+ BMVert *v_src_l1 = l->v;
+ BMVert *v_src_l2 = l_next->v;
+
+ const int i_1 = BM_elem_index_get(v_src_l1);
+ const int i_2 = BM_elem_index_get(v_src_l2);
+
+ BMVert *v_neg1 = verts_neg[i_1];
+ BMVert *v_neg2 = verts_neg[i_2];
+
+ BMVert *v_pos1 = verts_pos[i_1];
+ BMVert *v_pos2 = verts_pos[i_2];
+
+ f_new = BM_face_create_quad_tri(bm, v_l1, v_l2, v_neg2, v_neg1, f_src, BM_CREATE_NOP);
+ if (mat_offset) {
+ f_new->mat_nr = CLAMPIS(f_new->mat_nr + mat_offset, 0, mat_max);
+ }
+ BM_elem_flag_enable(f_new, BM_ELEM_TAG);
+ l_new = BM_FACE_FIRST_LOOP(f_new);
+
+ BM_elem_attrs_copy(bm, bm, l, l_new);
+ BM_elem_attrs_copy(bm, bm, l, l_new->prev);
+ BM_elem_attrs_copy(bm, bm, l_next, l_new->next);
+ BM_elem_attrs_copy(bm, bm, l_next, l_new->next->next);
+
+ f_new = BM_face_create_quad_tri(bm, v_l2, v_l1, v_pos1, v_pos2, f_src, BM_CREATE_NOP);
+
+ if (mat_offset) {
+ f_new->mat_nr = CLAMPIS(f_new->mat_nr + mat_offset, 0, mat_max);
+ }
+ BM_elem_flag_enable(f_new, BM_ELEM_TAG);
+ l_new = BM_FACE_FIRST_LOOP(f_new);
+
+ BM_elem_attrs_copy(bm, bm, l_next, l_new);
+ BM_elem_attrs_copy(bm, bm, l_next, l_new->prev);
+ BM_elem_attrs_copy(bm, bm, l, l_new->next);
+ BM_elem_attrs_copy(bm, bm, l, l_new->next->next);
+
+ if (use_boundary) {
+ if (BM_elem_flag_test(l->e, BM_ELEM_TAG)) {
+ /* we know its a boundary and this is the only face user (which is being wire'd) */
+ /* we know we only touch this edge/face once */
+ BMVert *v_b1 = verts_boundary[i_1];
+ BMVert *v_b2 = verts_boundary[i_2];
+
+ f_new = BM_face_create_quad_tri(bm, v_b2, v_b1, v_neg1, v_neg2, f_src, BM_CREATE_NOP);
+ if (mat_offset) {
+ f_new->mat_nr = CLAMPIS(f_new->mat_nr + mat_offset, 0, mat_max);
+ }
+ BM_elem_flag_enable(f_new, BM_ELEM_TAG);
+ l_new = BM_FACE_FIRST_LOOP(f_new);
+
+ BM_elem_attrs_copy(bm, bm, l_next, l_new);
+ BM_elem_attrs_copy(bm, bm, l_next, l_new->prev);
+ BM_elem_attrs_copy(bm, bm, l, l_new->next);
+ BM_elem_attrs_copy(bm, bm, l, l_new->next->next);
+
+ f_new = BM_face_create_quad_tri(bm, v_b1, v_b2, v_pos2, v_pos1, f_src, BM_CREATE_NOP);
+ if (mat_offset) {
+ f_new->mat_nr = CLAMPIS(f_new->mat_nr + mat_offset, 0, mat_max);
+ }
+ BM_elem_flag_enable(f_new, BM_ELEM_TAG);
+ l_new = BM_FACE_FIRST_LOOP(f_new);
+
+ BM_elem_attrs_copy(bm, bm, l, l_new);
+ BM_elem_attrs_copy(bm, bm, l, l_new->prev);
+ BM_elem_attrs_copy(bm, bm, l_next, l_new->next);
+ BM_elem_attrs_copy(bm, bm, l_next, l_new->next->next);
+
+ if (use_crease) {
+ BMEdge *e_new;
+ e_new = BM_edge_exists(v_pos1, v_b1);
+ BM_ELEM_CD_SET_FLOAT(e_new, cd_edge_crease_offset, crease_weight);
+
+ e_new = BM_edge_exists(v_pos2, v_b2);
+ BM_ELEM_CD_SET_FLOAT(e_new, cd_edge_crease_offset, crease_weight);
+
+ e_new = BM_edge_exists(v_neg1, v_b1);
+ BM_ELEM_CD_SET_FLOAT(e_new, cd_edge_crease_offset, crease_weight);
+
+ e_new = BM_edge_exists(v_neg2, v_b2);
+ BM_ELEM_CD_SET_FLOAT(e_new, cd_edge_crease_offset, crease_weight);
+ }
+ }
+ }
+
+ if (use_crease) {
+ BMEdge *e_new;
+ e_new = BM_edge_exists(v_pos1, v_l1);
+ BM_ELEM_CD_SET_FLOAT(e_new, cd_edge_crease_offset, crease_weight);
+
+ e_new = BM_edge_exists(v_pos2, v_l2);
+ BM_ELEM_CD_SET_FLOAT(e_new, cd_edge_crease_offset, crease_weight);
+
+ e_new = BM_edge_exists(v_neg1, v_l1);
+ BM_ELEM_CD_SET_FLOAT(e_new, cd_edge_crease_offset, crease_weight);
+
+ e_new = BM_edge_exists(v_neg2, v_l2);
+ BM_ELEM_CD_SET_FLOAT(e_new, cd_edge_crease_offset, crease_weight);
+ }
+ }
+ }
+
+ if (use_boundary) {
+ MEM_freeN(verts_boundary);
+ }
+
+ if (verts_relfac) {
+ MEM_freeN(verts_relfac);
+ }
+
+ if (use_replace) {
+
+ if (use_tag) {
+ /* only remove faces which are original and used to make wire,
+ * use 'verts_pos' and 'verts_neg' to avoid a feedback loop. */
+
+ /* vertex must be from 'verts_src' */
+#define VERT_DUPE_TEST_ORIG(v) (verts_neg[BM_elem_index_get(v)] != NULL)
+#define VERT_DUPE_TEST(v) (verts_pos[BM_elem_index_get(v)] != NULL)
+#define VERT_DUPE_CLEAR(v) \
+ { \
+ verts_pos[BM_elem_index_get(v)] = NULL; \
+ } \
+ (void)0
+
+ /* first ensure we keep all verts which are used in faces that weren't
+ * entirely made into wire. */
+ BM_ITER_MESH (f_src, &iter, bm, BM_FACES_OF_MESH) {
+ int mix_flag = 0;
+ BMLoop *l_iter, *l_first;
+
+ /* skip new faces */
+ if (BM_elem_index_get(f_src) == -1) {
+ continue;
+ }
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_src);
+ do {
+ mix_flag |= (VERT_DUPE_TEST_ORIG(l_iter->v) ? 1 : 2);
+ if (mix_flag == (1 | 2)) {
+ break;
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+
+ if (mix_flag == (1 | 2)) {
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f_src);
+ do {
+ VERT_DUPE_CLEAR(l_iter->v);
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ }
+
+ /* now remove any verts which were made into wire by all faces */
+ for (i = 0; i < totvert_orig; i++) {
+ v_src = verts_src[i];
+ BLI_assert(i == BM_elem_index_get(v_src));
+ if (VERT_DUPE_TEST(v_src)) {
+ BM_vert_kill(bm, v_src);
+ }
+ }
#undef VERT_DUPE_TEST_ORIG
#undef VERT_DUPE_TEST
#undef VERT_DUPE_CLEAR
-
- }
- else {
- /* simple case, no tags - replace all */
- for (i = 0; i < totvert_orig; i++) {
- BM_vert_kill(bm, verts_src[i]);
- }
- }
- }
-
- MEM_freeN(verts_src);
- MEM_freeN(verts_neg);
- MEM_freeN(verts_pos);
- MEM_freeN(verts_loop);
+ }
+ else {
+ /* simple case, no tags - replace all */
+ for (i = 0; i < totvert_orig; i++) {
+ BM_vert_kill(bm, verts_src[i]);
+ }
+ }
+ }
+
+ MEM_freeN(verts_src);
+ MEM_freeN(verts_neg);
+ MEM_freeN(verts_pos);
+ MEM_freeN(verts_loop);
}
diff --git a/source/blender/bmesh/tools/bmesh_wireframe.h b/source/blender/bmesh/tools/bmesh_wireframe.h
index 7c71e15beb9..3be43b2e9f5 100644
--- a/source/blender/bmesh/tools/bmesh_wireframe.h
+++ b/source/blender/bmesh/tools/bmesh_wireframe.h
@@ -23,21 +23,20 @@
#ifndef __BMESH_WIREFRAME_H__
#define __BMESH_WIREFRAME_H__
-void BM_mesh_wireframe(
- BMesh *bm,
- const float offset,
- const float offset_fac,
- const float offset_fac_vg,
- const bool use_replace,
- const bool use_boundary,
- const bool use_even_offset,
- const bool use_relative_offset,
- const bool use_crease,
- const float crease_weight,
- const int defgrp_index,
- const bool defgrp_invert,
- const short mat_offset,
- const short mat_max,
- const bool use_tag);
+void BM_mesh_wireframe(BMesh *bm,
+ const float offset,
+ const float offset_fac,
+ const float offset_fac_vg,
+ const bool use_replace,
+ const bool use_boundary,
+ const bool use_even_offset,
+ const bool use_relative_offset,
+ const bool use_crease,
+ const float crease_weight,
+ const int defgrp_index,
+ const bool defgrp_invert,
+ const short mat_offset,
+ const short mat_max,
+ const bool use_tag);
-#endif /* __BMESH_WIREFRAME_H__ */
+#endif /* __BMESH_WIREFRAME_H__ */