Blender  V3.3
Classes | Macros
bmo_inset.c File Reference
#include "MEM_guardedalloc.h"
#include "BLI_alloca.h"
#include "BLI_math.h"
#include "BLI_memarena.h"
#include "BLI_utildefines_stack.h"
#include "BKE_customdata.h"
#include "bmesh.h"
#include "intern/bmesh_operators_private.h"

Go to the source code of this file.

Classes

struct  InterpFace
 
struct  SplitEdgeInfo
 

Macros

#define USE_LOOP_CUSTOMDATA_MERGE
 
#define ELE_NEW   1
 
#define VERT_ORIG_STORE(_v)
 
#define VERT_ORIG_GET(_v)   (const float *)BLI_ghash_lookup_default(vert_coords, (_v), (_v)->co)
 
#define VERT_ORIG_REMOVE(_v)   BLI_ghash_remove(vert_coords, (_v), NULL, NULL)
 

Functions

Inset Individual

Each face has a smaller face created inside it (simple logic).

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)
 
void bmo_inset_individual_exec (BMesh *bm, BMOperator *op)
 

Generic Face Interpolation

Use for both kinds of inset.

Interpolation, this is more complex for regions since we're not creating new faces and throwing away old ones, so instead, store face data needed for interpolation.

Note
This uses CustomData functions in quite a low-level way which should be avoided, but in this case its hard to do without storing a duplicate mesh.
typedef struct InterpFace InterpFace
 
static void bm_interp_face_store (InterpFace *iface, BMesh *bm, BMFace *f, MemArena *interp_arena)
 
static void bm_interp_face_free (InterpFace *iface, BMesh *bm)
 
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)
 

Inset Region

The boundary between tagged and untagged faces is inset (more involved logic).

typedef struct SplitEdgeInfo SplitEdgeInfo
 
static BMLoopbm_edge_is_mixed_face_tag (BMLoop *l)
 
static float bm_edge_info_average_length (BMVert *v, SplitEdgeInfo *edge_info)
 
static float bm_edge_info_average_length_fallback (BMVert *v_lookup, SplitEdgeInfo *edge_info, BMesh *bm, void **vert_lengths_p)
 
static float bm_edge_info_average_length_with_fallback (BMVert *v, SplitEdgeInfo *edge_info, BMesh *bm, void **vert_lengths_p)
 
void bmo_inset_region_exec (BMesh *bm, BMOperator *op)
 

Detailed Description

Inset face regions. Inset individual faces.

Definition in file bmo_inset.c.

Macro Definition Documentation

◆ ELE_NEW

#define ELE_NEW   1

Definition at line 26 of file bmo_inset.c.

◆ USE_LOOP_CUSTOMDATA_MERGE

#define USE_LOOP_CUSTOMDATA_MERGE

Definition at line 24 of file bmo_inset.c.

◆ VERT_ORIG_GET

#define VERT_ORIG_GET (   _v)    (const float *)BLI_ghash_lookup_default(vert_coords, (_v), (_v)->co)

◆ VERT_ORIG_REMOVE

#define VERT_ORIG_REMOVE (   _v)    BLI_ghash_remove(vert_coords, (_v), NULL, NULL)

◆ VERT_ORIG_STORE

#define VERT_ORIG_STORE (   _v)
Value:
{ \
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
void * BLI_memarena_alloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
Definition: BLI_memarena.c:116
SyclQueue void void size_t num_bytes void

Typedef Documentation

◆ InterpFace

typedef struct InterpFace InterpFace

◆ SplitEdgeInfo

typedef struct SplitEdgeInfo SplitEdgeInfo

Function Documentation

◆ bm_edge_info_average_length()

static float bm_edge_info_average_length ( BMVert v,
SplitEdgeInfo edge_info 
)
static

◆ bm_edge_info_average_length_fallback()

static float bm_edge_info_average_length_fallback ( BMVert v_lookup,
SplitEdgeInfo edge_info,
BMesh bm,
void **  vert_lengths_p 
)
static

Fill in any vertices that are in the inset region but not connected to an edge being inset.

This is lazily initialized since it's a relatively expensive operation, and it's not needed in cases where all vertices being inset are connected to edges that are part of the inset.

Note
This only runs under the following conditions:
  • "depth" is non-zero.
  • "use_relative_offset" is enabled.
  • There are interior vertices which aren't used by an edge being inset.

Use to fill in length accumulated values based on the topological distance to vertices at the inset boundaries.

Unlike edge-lengths of vertices immediately around the vertex, this ensures the values are more evenly distributed.

The number of connected vertices we have added to length_accum. The sign of the value is used to avoid mixing current and previous passes.

  • Zero: Uninitialized, can be added to vert_stack.
  • Positive: Part of the current pass, length_accum has not yet been divided.
  • Minus One: Part of previous passes, length_accum value has been divided.

Definition at line 534 of file bmo_inset.c.

References BLI_assert, bm, bm_edge_info_average_length(), BM_edge_other_vert(), BM_EDGES_OF_MESH, BM_EDGES_OF_VERT, BM_elem_flag_test, BM_elem_index_get, BM_ELEM_TAG, BM_ITER_ELEM, BM_ITER_MESH, BM_mesh_elem_index_ensure(), BM_VERT, count, e, float(), MEM_callocN, MEM_freeN, MEM_mallocN, NULL, STACK_DECLARE, STACK_INIT, STACK_PUSH, STACK_REMOVE, STACK_SIZE, BMesh::totvert, UNLIKELY, and v.

Referenced by bm_edge_info_average_length_with_fallback().

◆ bm_edge_info_average_length_with_fallback()

static float bm_edge_info_average_length_with_fallback ( BMVert v,
SplitEdgeInfo edge_info,
BMesh bm,
void **  vert_lengths_p 
)
static

◆ bm_edge_is_mixed_face_tag()

static BMLoop* bm_edge_is_mixed_face_tag ( BMLoop l)
static

Return the tag loop where there is:

  • only 1 tagged face attached to this edge.
  • 1 or more untagged faces.
Note
this function looks to be expensive but in most cases it will only do 2 iterations.

Definition at line 470 of file bmo_inset.c.

References BM_elem_flag_test, BM_ELEM_TAG, BMLoop::f, l, LIKELY, NULL, and BMLoop::radial_next.

Referenced by bmo_inset_region_exec().

◆ bm_interp_face_free()

static void bm_interp_face_free ( InterpFace iface,
BMesh bm 
)
static

◆ bm_interp_face_store()

static void bm_interp_face_store ( InterpFace iface,
BMesh bm,
BMFace f,
MemArena interp_arena 
)
static

◆ bm_loop_customdata_merge()

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

This function merges loop customdata (UV's) where interpolating the values across the face causes values to diverge.

Check for diverged values at the vert shared by l_a_inner & l_b_inner.

 -----------------------+
          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)) |      |
           /     |      |

Definition at line 103 of file bmo_inset.c.

References BLI_assert, bm, BM_edge_in_face(), BM_edge_other_loop(), BM_ELEM_CD_GET_VOID_P, BM_elem_flag_test, BM_ELEM_TAG, BM_ITER_ELEM, BM_LOOPS_OF_VERT, CDT_MIX_MIX, CustomData_data_copy_value(), CustomData_data_equals(), CustomData_data_mix_value(), CustomData_layer_has_math(), BMLoop::e, ELEM, BMLoop::f, CustomData::layers, BMesh::ldata, BMLoop::next, offset, CustomDataLayer::offset, BMLoop::prev, CustomData::totlayer, type, CustomDataLayer::type, BMLoop::v, and void.

Referenced by bmo_inset_region_exec().

◆ bmo_face_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

◆ bmo_inset_individual_exec()

void bmo_inset_individual_exec ( BMesh bm,
BMOperator op 
)

Individual Face Inset. Find all tagged faces (f), duplicate edges around faces, inset verts of created edges, create new faces between old and new edges, fill face between connected new edges, kill old face (f).

Definition at line 401 of file bmo_inset.c.

References BLI_memarena_clear(), BLI_memarena_free(), BLI_memarena_new(), BLI_MEMARENA_STD_BUFSIZE, bm, BM_ELEM_TAG, BM_FACE, BM_mesh_elem_hflag_disable_all(), bmo_face_inset_individual(), BMO_ITER, BMO_slot_bool_get(), BMO_slot_buffer_from_enabled_flag(), BMO_slot_buffer_hflag_enable(), BMO_slot_float_get(), ELE_NEW, NULL, BMOperator::slots_in, and BMOperator::slots_out.

◆ bmo_inset_region_exec()

void bmo_inset_region_exec ( BMesh bm,
BMOperator op 
)

This case where only one edge attached to #v_split is used. i.e. 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.

Loops vars from newly created face (face_a/b)

             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)        |   |
|   +----------------------------+   |
|  /                              \  |
| /                                \ |
|/                                  |
+------------------------------------+

Definition at line 651 of file bmo_inset.c.

References add_v3_v3(), add_v3_v3v3(), InterpFace::axis_mat, BLI_assert, BLI_ghash_free(), BLI_ghash_ptr_new(), BLI_memarena_alloc(), BLI_memarena_free(), BLI_memarena_new(), BLI_MEMARENA_STD_BUFSIZE, InterpFace::blocks_l, InterpFace::blocks_v, bm, BM_CREATE_NOP, BM_EDGE, BM_edge_calc_face_tangent(), BM_edge_calc_length(), BM_edge_create(), bm_edge_info_average_length_with_fallback(), BM_edge_is_boundary(), BM_edge_is_manifold(), bm_edge_is_mixed_face_tag(), BM_edge_ordered_verts_ex(), BM_edge_other_loop(), BM_edge_other_vert(), BM_EDGES_OF_MESH, BM_EDGES_OF_VERT, BM_elem_attrs_copy(), BM_elem_flag_disable, BM_elem_flag_enable, BM_elem_flag_test, BM_elem_index_get, BM_elem_index_set, BM_ELEM_TAG, BM_FACE, BM_face_copy_shared(), BM_face_create_verts(), BM_FACE_FIRST_LOOP, BM_face_interp_from_face_ex(), BM_FACES_OF_VERT, bm_interp_face_free(), bm_interp_face_store(), BM_ITER_ELEM, BM_ITER_MESH, BM_ITER_MESH_INDEX, bm_loop_customdata_merge(), BM_loop_other_vert_loop(), BM_mesh_elem_hflag_disable_all(), BM_mesh_elem_hflag_enable_all(), BM_VERT, BM_vert_calc_shell_factor(), BM_vert_create(), BM_vert_splice(), BM_VERTS_OF_EDGE, BM_VERTS_OF_MESH, bmesh_kernel_edge_separate(), bmesh_kernel_vert_separate(), BMO_face_flag_enable, BMO_ITER, BMO_slot_bool_get(), BMO_slot_buffer_from_enabled_flag(), BMO_slot_buffer_hflag_disable(), BMO_slot_buffer_hflag_enable(), BMO_slot_float_get(), BMVert::co, compare_v3v3(), copy_v3_v3(), InterpFace::cos_2d, cross_v3_v3v3(), CustomData_bmesh_copy_data(), CustomData_bmesh_free_block_data(), CustomData_has_math(), BMHeader::data, dot_v3v3(), BMVert::e, BMLoop::e, e, SplitEdgeInfo::e_new, SplitEdgeInfo::e_old, ELE_NEW, BMesh::elem_index_dirty, BMLoop::f, InterpFace::f, float(), BMLoop::head, if(), BMEdge::l, l, SplitEdgeInfo::l, l_b, BMesh::ldata, len_squared_v3(), len_squared_v3v3(), blender::math::length(), SplitEdgeInfo::length, madd_v3_v3fl(), madd_v3_v3v3fl(), MEM_callocN, MEM_freeN, MEM_mallocN, mid_v3_v3v3(), mul_v3_fl(), negate_v3(), BMLoop::next, BMVert::no, BMFace::no, SplitEdgeInfo::no, normalize_v3(), NULL, BMLoop::prev, shell_v3v3_mid_normalized_to_dist(), shell_v3v3_normalized_to_dist(), BMOperator::slots_in, BMOperator::slots_out, sub_v3_v3v3(), BMesh::totface, BMesh::totvert, BMLoop::v, v, BMEdge::v1, v1, BMEdge::v2, v2, VERT_ORIG_GET, VERT_ORIG_REMOVE, VERT_ORIG_STORE, and zero_v3().