Blender V5.0
bmo_connect_pair.cc File Reference
#include "MEM_guardedalloc.h"
#include "BLI_heap_simple.h"
#include "BLI_math_matrix.h"
#include "BLI_math_vector.h"
#include "BLI_utildefines.h"
#include "bmesh.hh"
#include "intern/bmesh_operators_private.hh"
#include "BLI_mempool.h"

Go to the source code of this file.

Classes

struct  PathContext
struct  PathLinkState
struct  MinDistDir

Macros

#define CONNECT_EPS   0.0001f
#define VERT_OUT   1
#define VERT_EXCLUDE   2
#define FACE_EXCLUDE   2
#define ELE_TOUCHED   4
#define FACE_WALK_TEST(f)
#define VERT_WALK_TEST(v)
#define ELE_TOUCH_MARK(e)
#define ELE_TOUCH_TEST_VERT(v)
#define ELE_TOUCH_TEST_EDGE(e)

Functions

static int state_isect_co_pair (const PathContext *pc, const float co_a[3], const float co_b[3])
static int state_isect_co_exact (const PathContext *pc, const float co[3])
static float state_calc_co_pair_fac (const PathContext *pc, const float co_a[3], const float co_b[3])
static void state_calc_co_pair (const PathContext *pc, const float co_a[3], const float co_b[3], float r_co[3])
static bool state_link_find (const PathLinkState *state, BMElem *ele)
static void state_link_add (PathContext *pc, PathLinkState *state, BMElem *ele, BMElem *ele_from)
static PathLinkStatestate_dupe_add (PathLinkState *state, const PathLinkState *state_orig)
static PathLinkStatestate_link_add_test (PathContext *pc, PathLinkState *state, const PathLinkState *state_orig, BMElem *ele, BMElem *ele_from)
static PathLinkStatestate_step__face_edges (PathContext *pc, PathLinkState *state, const PathLinkState *state_orig, BMLoop *l_iter, BMLoop *l_last, MinDistDir *mddir)
static PathLinkStatestate_step__face_verts (PathContext *pc, PathLinkState *state, const PathLinkState *state_orig, BMLoop *l_iter, BMLoop *l_last, MinDistDir *mddir)
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])
void bmo_connect_vert_pair_exec (BMesh *bm, BMOperator *op)

Min Dist Dir Utilities

Simply getting the closest intersecting vert/edge is not good enough. see #43792 we need to get the closest in both directions since the absolute closest may be a dead-end.

Logic is simple:

  • First intersection, store the direction.
  • Successive intersections will update the first distance if its aligned with the first hit. otherwise update the opposite distance.
  • Caller stores best outcome in both directions.
#define MIN_DIST_DIR_INIT
static int min_dist_dir_test (MinDistDir *mddir, const float dist_dir[3], const float dist_sq)
static void min_dist_dir_update (MinDistDir *dist, const float dist_dir[3])

Detailed Description

Connect vertex pair across multiple faces (splits faces).

Definition in file bmo_connect_pair.cc.

Macro Definition Documentation

◆ CONNECT_EPS

#define CONNECT_EPS   0.0001f

Method for connecting across many faces.

  • use the line between both verts and their normal average to construct a matrix.
  • using the matrix, we can find all intersecting verts/edges.
  • walk the connected data and find the shortest path.
    • store a heap of paths which are being scanned (PathContext.states).
    • continuously search the shortest path in the heap.
    • never step over the same element twice (tag elements as ELE_TOUCHED). this avoids going into an eternal loop if there are many possible branches (see #45582).
    • when running into a branch, create a new PathLinkState state and add to the heap.
    • when the target is reached, finish - since none of the other paths can be shorter than the one just found.
  • if the connection can't be found - fail.
  • with the connection found, split all edges tagging verts (or tag verts that sit on the intersection).
  • run the standard connect operator.

Definition at line 43 of file bmo_connect_pair.cc.

Referenced by state_isect_co_exact(), and state_isect_co_pair().

◆ ELE_TOUCH_MARK

#define ELE_TOUCH_MARK ( e)
Value:
{ \
CHECK_TYPE_ANY(e, BMVert *, BMEdge *, BMElem *, BMElemF *); \
BMO_elem_flag_enable(pc->bm_bmoflag, (BMElemF *)e, ELE_TOUCHED); \
} \
((void)0)
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
#define ELE_TOUCHED

Definition at line 63 of file bmo_connect_pair.cc.

Referenced by state_link_add().

◆ ELE_TOUCH_TEST_EDGE

#define ELE_TOUCH_TEST_EDGE ( e)
Value:
BMO_edge_flag_test(pc->bm_bmoflag, e, ELE_TOUCHED)
#define BMO_edge_flag_test(bm, e, oflag)

Definition at line 73 of file bmo_connect_pair.cc.

Referenced by state_step__face_edges().

◆ ELE_TOUCH_TEST_VERT

#define ELE_TOUCH_TEST_VERT ( v)
Value:
BMO_vert_flag_test(pc->bm_bmoflag, v, ELE_TOUCHED)
#define BMO_vert_flag_test(bm, e, oflag)
ATTR_WARN_UNUSED_RESULT const BMVert * v

Definition at line 70 of file bmo_connect_pair.cc.

Referenced by state_step(), and state_step__face_verts().

◆ ELE_TOUCHED

#define ELE_TOUCHED   4

Definition at line 51 of file bmo_connect_pair.cc.

◆ FACE_EXCLUDE

#define FACE_EXCLUDE   2

Definition at line 48 of file bmo_connect_pair.cc.

◆ FACE_WALK_TEST

#define FACE_WALK_TEST ( f)
Value:
(CHECK_TYPE_INLINE(f, BMFace *), BMO_face_flag_test(pc->bm_bmoflag, f, FACE_EXCLUDE) == 0)
#define CHECK_TYPE_INLINE(val, type)
#define BMO_face_flag_test(bm, e, oflag)
#define FACE_EXCLUDE

Definition at line 53 of file bmo_connect_pair.cc.

Referenced by state_step(), state_step__face_edges(), and state_step__face_verts().

◆ MIN_DIST_DIR_INIT

#define MIN_DIST_DIR_INIT
Value:
{ \
{ \
} \
}
#define FLT_MAX
Definition stdcycles.h:14

Definition at line 133 of file bmo_connect_pair.cc.

Referenced by state_step().

◆ VERT_EXCLUDE

#define VERT_EXCLUDE   2

Definition at line 45 of file bmo_connect_pair.cc.

Referenced by bmo_connect_vert_pair_exec().

◆ VERT_OUT

#define VERT_OUT   1

Definition at line 44 of file bmo_connect_pair.cc.

Referenced by BM_mesh_bevel(), bmo_connect_vert_pair_exec(), and flag_out_vert().

◆ VERT_WALK_TEST

#define VERT_WALK_TEST ( v)
Value:
#define VERT_EXCLUDE

Definition at line 55 of file bmo_connect_pair.cc.

Referenced by state_step().

Function Documentation

◆ bm_vert_pair_to_matrix()

void bm_vert_pair_to_matrix ( BMVert * v_pair[2],
float r_unit_mat[3][3] )
static

◆ bmo_connect_vert_pair_exec()

◆ min_dist_dir_test()

int min_dist_dir_test ( MinDistDir * mddir,
const float dist_dir[3],
const float dist_sq )
static

◆ min_dist_dir_update()

void min_dist_dir_update ( MinDistDir * dist,
const float dist_dir[3] )
static

◆ state_calc_co_pair()

void state_calc_co_pair ( const PathContext * pc,
const float co_a[3],
const float co_b[3],
float r_co[3] )
static

Definition at line 201 of file bmo_connect_pair.cc.

References interp_v3_v3v3(), and state_calc_co_pair_fac().

Referenced by state_link_add(), and state_step__face_edges().

◆ state_calc_co_pair_fac()

float state_calc_co_pair_fac ( const PathContext * pc,
const float co_a[3],
const float co_b[3] )
static

◆ state_dupe_add()

PathLinkState * state_dupe_add ( PathLinkState * state,
const PathLinkState * state_orig )
static

Definition at line 291 of file bmo_connect_pair.cc.

References MEM_mallocN(), and state.

Referenced by state_link_add_test().

◆ state_isect_co_exact()

int state_isect_co_exact ( const PathContext * pc,
const float co[3] )
static

◆ state_isect_co_pair()

int state_isect_co_pair ( const PathContext * pc,
const float co_a[3],
const float co_b[3] )
static

◆ state_link_add()

◆ state_link_add_test()

PathLinkState * state_link_add_test ( PathContext * pc,
PathLinkState * state,
const PathLinkState * state_orig,
BMElem * ele,
BMElem * ele_from )
static

◆ state_link_find()

bool state_link_find ( const PathLinkState * state,
BMElem * ele )
static

Ideally we wouldn't need this and for most cases we don't. But when a face has vertices that are on the boundary more than once this becomes tricky.

Definition at line 215 of file bmo_connect_pair.cc.

References BLI_assert, BM_EDGE, BM_FACE, BM_VERT, PathLink::ele, ELEM, BMElem::head, BMHeader::htype, PathLink::next, and state.

Referenced by state_link_add().

◆ state_step()

◆ state_step__face_edges()

◆ state_step__face_verts()