Blender  V3.3
Classes | Macros | Typedefs | Enumerations | Functions
editmesh_rip.c File Reference
#include "MEM_guardedalloc.h"
#include "DNA_object_types.h"
#include "BLI_array.h"
#include "BLI_math.h"
#include "BKE_context.h"
#include "BKE_editmesh.h"
#include "BKE_layer.h"
#include "BKE_report.h"
#include "RNA_access.h"
#include "RNA_define.h"
#include "WM_types.h"
#include "ED_mesh.h"
#include "ED_screen.h"
#include "ED_transform.h"
#include "ED_view3d.h"
#include "bmesh.h"
#include "bmesh_tools.h"
#include "mesh_intern.h"

Go to the source code of this file.

Classes

struct  EdgeLoopPair
 
struct  UnorderedLoopPair
 

Macros

#define INSET_DEFAULT   0.00001f
 
#define IS_VISIT_POSSIBLE(e)   (BM_edge_is_manifold(e) && BM_elem_flag_test(e, BM_ELEM_TAG))
 
#define IS_VISIT_DONE(e)   ((e)->l && (BM_elem_index_get((e)->l) != INVALID_UID))
 
#define INVALID_UID   INT_MIN
 

Typedefs

typedef struct EdgeLoopPair EdgeLoopPair
 
typedef struct UnorderedLoopPair UnorderedLoopPair
 

Enumerations

enum  { ULP_FLIP_0 = (1 << 0) , ULP_FLIP_1 = (1 << 1) }
 

Functions

static float edbm_rip_edgedist_squared (ARegion *region, float mat[4][4], const float co1[3], const float co2[3], const float mvalf[2], const float inset)
 
static void edbm_calc_loop_co (BMLoop *l, float l_mid_co[3])
 
static float edbm_rip_edge_side_measure (BMEdge *e, BMLoop *e_l, ARegion *region, float projectMat[4][4], const float fmval[2])
 
static BMEdgeedbm_ripsel_edge_mark_step (BMVert *v, const int uid)
 
static EdgeLoopPairedbm_ripsel_looptag_helper (BMesh *bm)
 
static BMEdgeedbm_ripsel_edge_uid_step (BMEdge *e_orig, BMVert **v_prev)
 
static BMVertedbm_ripsel_edloop_pair_start_vert (BMEdge *e)
 
static void edbm_ripsel_deselect_helper (BMesh *bm, EdgeLoopPair *eloop_pairs, ARegion *region, float projectMat[4][4], const float fmval[2])
 
static UnorderedLoopPairedbm_tagged_loop_pairs_to_fill (BMesh *bm)
 
static void edbm_tagged_loop_pairs_do_fill_faces (BMesh *bm, UnorderedLoopPair *uloop_pairs)
 
static int edbm_rip_invoke__vert (bContext *C, const wmEvent *event, Object *obedit, bool do_fill)
 
static int edbm_rip_invoke__edge (bContext *C, const wmEvent *event, Object *obedit, bool do_fill)
 
static int edbm_rip_invoke (bContext *C, wmOperator *op, const wmEvent *event)
 
void MESH_OT_rip (wmOperatorType *ot)
 

Macro Definition Documentation

◆ INSET_DEFAULT

#define INSET_DEFAULT   0.00001f

helper to find edge for edge_rip,

Parameters
insetis used so we get some useful distance when comparing multiple edges that meet at the same point and would result in the same distance.

Definition at line 42 of file editmesh_rip.c.

◆ INVALID_UID

#define INVALID_UID   INT_MIN

Definition at line 183 of file editmesh_rip.c.

◆ IS_VISIT_DONE

#define IS_VISIT_DONE (   e)    ((e)->l && (BM_elem_index_get((e)->l) != INVALID_UID))

Definition at line 182 of file editmesh_rip.c.

◆ IS_VISIT_POSSIBLE

#define IS_VISIT_POSSIBLE (   e)    (BM_edge_is_manifold(e) && BM_elem_flag_test(e, BM_ELEM_TAG))

How rip selection works

Firstly - rip is basically edge split with side-selection & grab. Things would be much more simple if we didn't have to worry about side selection

The method used for checking the side of selection is as follows...

  • First tag all rip-able edges.
  • Build a contiguous edge list by looping over tagged edges and following each one's tagged siblings in both directions.
    • The loops are not stored in an array. Instead both loops on either side of each edge has its index values set to count down from the last edge. This way once we have the 'last' edge it's very easy to walk down the connected edge loops. The reason for using loops like this is because when the edges are split we don't know which face user gets the newly created edge (it's as good as random so we can't assume new edges will be on one side). After splitting, it's very simple to walk along boundary loops since each only has one edge from a single side.
  • The end loop pairs are stored in an array however to support multiple edge-selection-islands, so you can rip multiple selections at once.
  • * Execute the split *
  • For each EdgeLoopPair walk down both sides of the split using the loops and measure which is facing the mouse.
  • Deselect the edge loop facing away.

Limitation! This currently works very poorly with intersecting edge islands (verts with more than 2 tagged edges). This is nice to do but for now not essential.

  • campbell.

Definition at line 181 of file editmesh_rip.c.

Typedef Documentation

◆ EdgeLoopPair

typedef struct EdgeLoopPair EdgeLoopPair

◆ UnorderedLoopPair

return an un-ordered array of loop pairs use for rebuilding face-fill

Note
the method currently used fails for edges with 3+ face users and gives nasty holes in the mesh, there isn't a good way of knowing ahead of time which loops will be split apart (its possible to figure out but quite involved). So for now this is a known limitation of current rip-fill option.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
ULP_FLIP_0 
ULP_FLIP_1 

Definition at line 382 of file editmesh_rip.c.

Function Documentation

◆ edbm_calc_loop_co()

static void edbm_calc_loop_co ( BMLoop l,
float  l_mid_co[3] 
)
static

Calculates a point along the loop tangent which can be used to measure against edges.

Definition at line 87 of file editmesh_rip.c.

References add_v3_v3(), BM_edge_calc_length(), BM_loop_calc_face_tangent(), BMVert::co, BMLoop::e, l, mul_v3_fl(), BMLoop::prev, and BMLoop::v.

Referenced by edbm_rip_invoke__vert().

◆ edbm_rip_edge_side_measure()

static float edbm_rip_edge_side_measure ( BMEdge e,
BMLoop e_l,
ARegion region,
float  projectMat[4][4],
const float  fmval[2] 
)
static

◆ edbm_rip_edgedist_squared()

static float edbm_rip_edgedist_squared ( ARegion region,
float  mat[4][4],
const float  co1[3],
const float  co2[3],
const float  mvalf[2],
const float  inset 
)
static

◆ edbm_rip_invoke()

static int edbm_rip_invoke ( bContext C,
wmOperator op,
const wmEvent event 
)
static

◆ edbm_rip_invoke__edge()

static int edbm_rip_invoke__edge ( bContext C,
const wmEvent event,
Object obedit,
bool  do_fill 
)
static

◆ edbm_rip_invoke__vert()

static int edbm_rip_invoke__vert ( bContext C,
const wmEvent event,
Object obedit,
bool  do_fill 
)
static

◆ edbm_ripsel_deselect_helper()

static void edbm_ripsel_deselect_helper ( BMesh bm,
EdgeLoopPair eloop_pairs,
ARegion region,
float  projectMat[4][4],
const float  fmval[2] 
)
static

◆ edbm_ripsel_edge_mark_step()

static BMEdge* edbm_ripsel_edge_mark_step ( BMVert v,
const int  uid 
)
static

◆ edbm_ripsel_edge_uid_step()

static BMEdge* edbm_ripsel_edge_uid_step ( BMEdge e_orig,
BMVert **  v_prev 
)
static

◆ edbm_ripsel_edloop_pair_start_vert()

static BMVert* edbm_ripsel_edloop_pair_start_vert ( BMEdge e)
static

Definition at line 325 of file editmesh_rip.c.

References e, and edbm_ripsel_edge_uid_step().

Referenced by edbm_ripsel_deselect_helper().

◆ edbm_ripsel_looptag_helper()

static EdgeLoopPair* edbm_ripsel_looptag_helper ( BMesh bm)
static

◆ edbm_tagged_loop_pairs_do_fill_faces()

static void edbm_tagged_loop_pairs_do_fill_faces ( BMesh bm,
UnorderedLoopPair uloop_pairs 
)
static

◆ edbm_tagged_loop_pairs_to_fill()

static UnorderedLoopPair* edbm_tagged_loop_pairs_to_fill ( BMesh bm)
static

◆ MESH_OT_rip()

void MESH_OT_rip ( wmOperatorType ot)