Blender V4.3
bmesh_polygon_edgenet.cc File Reference
#include "MEM_guardedalloc.h"
#include "BLI_alloca.h"
#include "BLI_kdopbvh.h"
#include "BLI_linklist_stack.h"
#include "BLI_math_geom.h"
#include "BLI_math_matrix.h"
#include "BLI_math_vector.h"
#include "BLI_memarena.h"
#include "BLI_sort_utils.h"
#include "BLI_utildefines_stack.h"
#include "BLI_vector.hh"
#include "BKE_customdata.hh"
#include "bmesh.hh"
#include "intern/bmesh_private.hh"

Go to the source code of this file.

Classes

struct  VertOrder
 
struct  EdgeGroupIsland
 
struct  Edges_VertVert_BVHTreeTest
 
struct  Edges_VertRay_BVHTreeTest
 
struct  EdgeGroup_FindConnection_Args
 

Macros

#define USE_FASTPATH_NOFORK
 
#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_)
 
#define EDGE_NOT_IN_STACK   BM_ELEM_INTERNAL_TAG
 
#define VERT_NOT_IN_STACK   BM_ELEM_INTERNAL_TAG
 
#define VERT_IN_ARRAY   BM_ELEM_INTERNAL_TAG
 

Face Split Edge-Net

BM_face_split_edgenet and helper functions.

Note
Don't use BM_edge_is_wire or BM_edge_is_boundary since we need to take flagged faces into account. Also take care accessing e->l directly.
#define FACE_NET   _FLAG_WALK
 
#define EDGE_NET   _FLAG_WALK
 
#define VERT_VISIT   _FLAG_WALK
 
#define VERT_IN_QUEUE   _FLAG_WALK_ALT
 
static uint bm_edge_flagged_radial_count (BMEdge *e)
 
static BMLoopbm_edge_flagged_radial_first (BMEdge *e)
 
static void normalize_v2_m3_v3v3 (float out[2], const float axis_mat[3][3], const float v1[3], const float v2[3])
 
static bool bm_face_split_edgenet_find_loop_pair (BMVert *v_init, const float face_normal[3], const float face_normal_matrix[3][3], BMEdge *e_pair[2])
 
static bool bm_face_split_edgenet_find_loop_pair_exists (BMVert *v_init)
 
static bool bm_face_split_edgenet_find_loop_walk (BMVert *v_init, const float face_normal[3], VertOrder *edge_order, const uint edge_order_len, BMEdge *e_pair[2])
 
static bool bm_face_split_edgenet_find_loop (BMVert *v_init, const float face_normal[3], const float face_normal_matrix[3][3], VertOrder *edge_order, const uint edge_order_len, BMVert **r_face_verts, int *r_face_verts_len)
 
bool BM_face_split_edgenet (BMesh *bm, BMFace *f, BMEdge **edge_net, const int edge_net_len, blender::Vector< BMFace * > *r_face_arr)
 

Face Split Edge-Net Connect Islands

BM_face_split_edgenet_connect_islands and helper functions.

Connect isolated mesh 'islands' so they form legal regions from which we can create faces.

Intended to be used as a pre-processing step for BM_face_split_edgenet.

Warning
Currently this risks running out of stack memory (#alloca), likely we'll pass in a memory arena (cleared each use) eventually.
#define USE_PARTIAL_CONNECT
 
#define VERT_IS_VALID   BM_ELEM_INTERNAL_TAG
 
#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 int axis_pt_cmp (const float pt_a[2], const float pt_b[2])
 
static int group_min_cmp_fn (const void *p1, const void *p2)
 
static void bvhtree_test_edges_isect_2d_vert_cb (void *user_data, int index, const BVHTreeRay *, BVHTreeRayHit *hit)
 
static void bvhtree_test_edges_isect_2d_ray_cb (void *user_data, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
 
static BMEdgetest_edges_isect_2d_vert (const EdgeGroup_FindConnection_Args *args, BMVert *v_origin, BMVert *v_other)
 
static BMEdgetest_edges_isect_2d_ray (const EdgeGroup_FindConnection_Args *args, BMVert *v_origin, const float dir[3])
 
static int bm_face_split_edgenet_find_connection (const EdgeGroup_FindConnection_Args *args, BMVert *v_origin, bool direction_sign)
 
static bool test_tagged_and_notface (BMEdge *e, void *fptr)
 
static BMVertbm_face_split_edgenet_partial_connect (BMesh *bm, BMVert *v_delimit, BMFace *f)
 
static bool bm_vert_partial_connect_check_overlap (const int *remap, const int v_a_index, const int v_b_index)
 
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)
 

Detailed Description

This file contains functions for splitting faces into isolated regions, defined by connected edges.

Definition in file bmesh_polygon_edgenet.cc.

Macro Definition Documentation

◆ EDGE_NET

◆ EDGE_NOT_IN_STACK [1/2]

◆ EDGE_NOT_IN_STACK [2/2]

#define EDGE_NOT_IN_STACK   BM_ELEM_INTERNAL_TAG

◆ FACE_NET

◆ FOREACH_VERT_EDGE

#define FOREACH_VERT_EDGE ( v_,
e_,
body_ )
Value:
{ \
BMEdge *e_ = v_->e; \
do { \
body_ \
} while ((e_ = BM_DISK_EDGE_NEXT(e_, v_)) != v_->e); \
} \
((void)0)
#define BM_DISK_EDGE_NEXT(e, v)

Referenced by bm_face_split_edgenet_partial_connect().

◆ SORT_AXIS

#define SORT_AXIS   0

Definition at line 693 of file bmesh_polygon_edgenet.cc.

Referenced by bm_face_split_edgenet_find_connection().

◆ USE_FASTPATH_NOFORK

#define USE_FASTPATH_NOFORK

◆ USE_PARTIAL_CONNECT

#define USE_PARTIAL_CONNECT

Definition at line 688 of file bmesh_polygon_edgenet.cc.

◆ VERT_IN_ARRAY

◆ VERT_IN_QUEUE

#define VERT_IN_QUEUE   _FLAG_WALK_ALT

Definition at line 50 of file bmesh_polygon_edgenet.cc.

Referenced by BM_face_split_edgenet().

◆ VERT_IS_VALID

#define VERT_IS_VALID   BM_ELEM_INTERNAL_TAG

Definition at line 690 of file bmesh_polygon_edgenet.cc.

Referenced by bm_face_split_edgenet_find_connection().

◆ VERT_NOT_IN_STACK [1/2]

◆ VERT_NOT_IN_STACK [2/2]

#define VERT_NOT_IN_STACK   BM_ELEM_INTERNAL_TAG

◆ VERT_VISIT

#define VERT_VISIT   _FLAG_WALK

Function Documentation

◆ axis_pt_cmp()

BLI_INLINE int axis_pt_cmp ( const float pt_a[2],
const float pt_b[2] )

◆ bm_edge_flagged_radial_count()

◆ bm_edge_flagged_radial_first()

static BMLoop * bm_edge_flagged_radial_first ( BMEdge * e)
static

◆ BM_face_split_edgenet()

bool BM_face_split_edgenet ( BMesh * bm,
BMFace * f,
BMEdge ** edge_net,
int edge_net_len,
blender::Vector< BMFace * > * r_face_arr )

Splits a face into many smaller faces defined by an edge-net. handle customdata and degenerate cases.

  • Isolated holes or unsupported face configurations, will be ignored.
  • Customdata calculations aren't efficient (need to calculate weights for each vert).

Definition at line 445 of file bmesh_polygon_edgenet.cc.

References blender::Vector< T, InlineBufferCapacity, Allocator >::append(), axis_dominant_v3_to_m3(), BLI_array_alloca, BLI_assert, bm, BM_CREATE_NOP, BM_edge_in_face(), BM_ELEM_API_FLAG_DISABLE, BM_ELEM_API_FLAG_ENABLE, BM_ELEM_API_FLAG_TEST, BM_ELEM_SELECT, BM_face_create_verts(), BM_FACE_FIRST_LOOP, BM_face_kill(), bm_face_split_edgenet_find_loop(), bm_face_split_edgenet_find_loop_pair_exists(), BM_ITER_ELEM, BM_LOOPS_OF_VERT, BM_VERTS_OF_EDGE, bmesh_face_swap_data(), blender::Vector< T, InlineBufferCapacity, Allocator >::clear_and_shrink(), BMVert::co, copy_v3_v3(), CustomData_bmesh_copy_block(), CustomData_bmesh_interp(), CustomData_has_math(), BMHeader::data, BMLoop::e, EDGE_NET, BMLoop::f, FACE_NET, float, BMFace::head, BMLoop::head, BMHeader::hflag, interp_weights_poly_v2(), blender::Vector< T, InlineBufferCapacity, Allocator >::is_empty(), BMesh::ldata, BMFace::len, MEM_freeN(), MEM_mallocN, mul_v2_m3v3(), BMLoop::next, BMFace::no, STACK_DECLARE, STACK_INIT, STACK_POP, STACK_PUSH, BMesh::totfacesel, BMLoop::v, v, v2, VERT_IN_QUEUE, VERT_VISIT, and w().

Referenced by bm_face_split_by_edges(), bm_face_split_by_edges_island_connect(), BM_mesh_intersect_edges(), bpy_bm_utils_face_split_edgenet(), face_edges_split(), and knife_make_face_cuts().

◆ BM_face_split_edgenet_connect_islands()

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 we have holes to fill. (avoid thrashing the area when the initial check isn't so intensive on the stack).

Definition at line 1200 of file bmesh_polygon_edgenet.cc.

References axis_dominant_v3_to_m3(), axis_pt_cmp(), BLI_assert, BLI_bvhtree_balance(), BLI_bvhtree_free(), BLI_bvhtree_insert(), BLI_bvhtree_new(), BLI_linklist_prepend_arena(), BLI_linklist_prepend_nlink(), BLI_memarena_alloc(), BLI_SMALLSTACK_DECLARE, BLI_SMALLSTACK_POP, BLI_SMALLSTACK_PUSH, bm, BM_DISK_EDGE_NEXT, BM_EDGE, BM_edge_create(), BM_edge_exists(), BM_edge_find_double(), BM_edge_kill(), BM_edge_other_vert(), BM_elem_flag_disable, BM_elem_flag_enable, BM_elem_flag_test, BM_elem_index_get, BM_elem_index_set, BM_FACE_FIRST_LOOP, bm_face_split_edgenet_find_connection(), bm_face_split_edgenet_partial_connect(), BM_VERT, bm_vert_partial_connect_check_overlap(), BM_vert_splice(), EdgeGroup_FindConnection_Args::bvhtree, BMVert::co, copy_v2_v2(), copy_v3_v3(), copy_vn_i(), dot_m3_v3_row_x(), dot_m3_v3_row_y(), BMLoop::e, BMVert::e, e, EdgeGroupIsland::edge_len, EdgeGroupIsland::edge_links, EDGE_NOT_IN_STACK, BMesh::elem_index_dirty, float, FLT_MAX, group_min_cmp_fn(), EdgeGroupIsland::has_prev_edge, BMVert::head, BMHeader::htype, BMFace::len, len, LinkNode::link, EdgeGroupIsland::max, mem_arena, EdgeGroupIsland::min, min_axis(), mul_v2_m3v3(), BMLoop::next, LinkNode::next, next, BMFace::no, sub_v3_v3(), UNLIKELY, UNPACK2, UNPACK3, BMLoop::v, v, BMEdge::v1, v2, VERT_IN_ARRAY, EdgeGroupIsland::vert_len, VERT_NOT_IN_STACK, and EdgeGroupIsland::vert_span.

Referenced by bm_face_split_by_edges_island_connect(), face_edges_split(), and knife_make_face_cuts().

◆ bm_face_split_edgenet_find_connection()

static int bm_face_split_edgenet_find_connection ( const EdgeGroup_FindConnection_Args * args,
BMVert * v_origin,
bool direction_sign )
static

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 there's no right answer (without subdividing edges), so return a fall-back vertex in that case.

Definition at line 957 of file bmesh_polygon_edgenet.cc.

References ARRAY_SET_ITEMS, BLI_SMALLSTACK_DECLARE, BLI_SMALLSTACK_POP, BLI_SMALLSTACK_PUSH, BM_elem_flag_disable, BM_elem_flag_enable, BM_elem_flag_test, BM_elem_index_get, BMVert::co, len_squared_v2v2(), printf, SORT_AXIS, test_edges_isect_2d_ray(), test_edges_isect_2d_vert(), v, BMEdge::v1, BMEdge::v2, and VERT_IS_VALID.

Referenced by BM_face_split_edgenet_connect_islands().

◆ bm_face_split_edgenet_find_loop()

static bool bm_face_split_edgenet_find_loop ( BMVert * v_init,
const float face_normal[3],
const float face_normal_matrix[3][3],
VertOrder * edge_order,
const uint edge_order_len,
BMVert ** r_face_verts,
int * r_face_verts_len )
static

◆ bm_face_split_edgenet_find_loop_pair()

static bool bm_face_split_edgenet_find_loop_pair ( BMVert * v_init,
const float face_normal[3],
const float face_normal_matrix[3][3],
BMEdge * e_pair[2] )
static

◆ bm_face_split_edgenet_find_loop_pair_exists()

static bool bm_face_split_edgenet_find_loop_pair_exists ( BMVert * v_init)
static

A reduced version of bm_face_split_edgenet_find_loop_pair that only checks if it would return true.

Note
There is no use in caching resulting edges here, since between this check and running bm_face_split_edgenet_find_loop, the selected edges may have had faces attached.

Definition at line 218 of file bmesh_polygon_edgenet.cc.

References BM_DISK_EDGE_NEXT, bm_edge_flagged_radial_count(), BM_ELEM_API_FLAG_TEST, count, BMVert::e, e, and EDGE_NET.

Referenced by BM_face_split_edgenet().

◆ bm_face_split_edgenet_find_loop_walk()

◆ bm_face_split_edgenet_partial_connect()

static BMVert * bm_face_split_edgenet_partial_connect ( BMesh * bm,
BMVert * v_delimit,
BMFace * f )
static

◆ bm_vert_partial_connect_check_overlap()

static bool bm_vert_partial_connect_check_overlap ( const int * remap,
const int v_a_index,
const int v_b_index )
static

Check if connecting vertices would cause an edge with duplicate verts.

Definition at line 1187 of file bmesh_polygon_edgenet.cc.

References UNLIKELY.

Referenced by BM_face_split_edgenet_connect_islands().

◆ bvhtree_test_edges_isect_2d_ray_cb()

static void bvhtree_test_edges_isect_2d_ray_cb ( void * user_data,
int index,
const BVHTreeRay * ray,
BVHTreeRayHit * hit )
static

Definition at line 806 of file bmesh_polygon_edgenet.cc.

References BM_elem_index_get, BMVert::co, e, isect_ray_seg_v2(), and LIKELY.

Referenced by test_edges_isect_2d_ray().

◆ bvhtree_test_edges_isect_2d_vert_cb()

static void bvhtree_test_edges_isect_2d_vert_cb ( void * user_data,
int index,
const BVHTreeRay * ,
BVHTreeRayHit * hit )
static

◆ edge_isect_verts_point_2d()

BLI_INLINE bool edge_isect_verts_point_2d ( const BMEdge * e,
const BMVert * v_a,
const BMVert * v_b,
float r_isect[2] )

◆ group_min_cmp_fn()

static int group_min_cmp_fn ( const void * p1,
const void * p2 )
static

◆ normalize_v2_m3_v3v3()

static void normalize_v2_m3_v3v3 ( float out[2],
const float axis_mat[3][3],
const float v1[3],
const float v2[3] )
static

◆ test_edges_isect_2d_ray()

◆ test_edges_isect_2d_vert()

◆ test_tagged_and_notface()

static bool test_tagged_and_notface ( BMEdge * e,
void * fptr )
static

Support for connecting islands that have single-edge connections. This options is not very optimal (however its not needed for booleans either). Used to identify edges that get split off when making island from partial connection. fptr should be a BMFace*, but is a void* for general interface to BM_vert_separate_tested_edges

Definition at line 1044 of file bmesh_polygon_edgenet.cc.

References BM_edge_in_face(), BM_elem_flag_test, BM_ELEM_INTERNAL_TAG, and e.

Referenced by bm_face_split_edgenet_partial_connect().