34 const bool use_toolflags,
40 size_t vert_size, edge_size, loop_size, face_size;
42 if (use_toolflags ==
true) {
45 loop_size =
sizeof(
BMLoop);
49 vert_size =
sizeof(
BMVert);
50 edge_size =
sizeof(
BMEdge);
51 loop_size =
sizeof(
BMLoop);
52 face_size =
sizeof(
BMFace);
86 if (
bm->vtoolflagpool &&
bm->etoolflagpool &&
bm->ftoolflagpool) {
102 toolflagpool =
bm->etoolflagpool;
108 toolflagpool =
bm->ftoolflagpool;
118 if (
bm->vtoolflagpool) {
120 bm->vtoolflagpool =
nullptr;
122 if (
bm->etoolflagpool) {
124 bm->etoolflagpool =
nullptr;
126 if (
bm->ftoolflagpool) {
128 bm->ftoolflagpool =
nullptr;
141 bm->use_toolflags =
params->use_toolflags;
142 bm->toolflag_index = 0;
178 if (is_ldata_free || is_pdata_free) {
192 if (
bm->vdata.totlayer) {
195 if (
bm->edata.totlayer) {
198 if (
bm->ldata.totlayer) {
201 if (
bm->pdata.totlayer) {
230#ifdef USE_BMESH_HOLES
236 if (
bm->lnor_spacearr) {
246 const bool use_toolflags =
bm->use_toolflags;
247 void *py_handle =
bm->py_handle;
256 bm->use_toolflags = use_toolflags;
257 bm->py_handle = py_handle;
259 bm->toolflag_index = 0;
276 bm->py_handle =
nullptr;
289#ifdef BMOP_UNTAN_MULTIRES_ENABLED
293 bmesh_mdisps_space_set(
bm, MULTIRES_SPACE_TANGENT, MULTIRES_SPACE_ABSOLUTE);
296 bmesh_rationalize_normals(
bm, 0);
307#ifdef BMOP_UNTAN_MULTIRES_ENABLED
311 bmesh_rationalize_normals(
bm, 1);
312 bmesh_mdisps_space_set(
bm, MULTIRES_SPACE_ABSOLUTE, MULTIRES_SPACE_TANGENT);
314 else if (
flag & BMO_OP_FLAG_RATIONALIZE_NORMALS) {
315 bmesh_rationalize_normals(
bm, 1);
326 select_history =
bm->selected;
335 bm->selected = select_history;
349 if (elem_offset ==
nullptr) {
351 const char htype_needed =
bm->elem_index_dirty & htype;
352 if (htype_needed == 0) {
358 if ((
bm->elem_index_dirty &
BM_VERT) || (elem_offset && elem_offset[0])) {
362 int index = elem_offset ? elem_offset[0] : 0;
374 if ((
bm->elem_index_dirty &
BM_EDGE) || (elem_offset && elem_offset[1])) {
378 int index = elem_offset ? elem_offset[1] : 0;
391 (elem_offset && (elem_offset[2] || elem_offset[3])))
396 const bool update_face = (htype &
BM_FACE) && (
bm->elem_index_dirty &
BM_FACE);
397 const bool update_loop = (htype &
BM_LOOP) && (
bm->elem_index_dirty &
BM_LOOP);
399 int index_loop = elem_offset ? elem_offset[2] : 0;
400 int index = elem_offset ? elem_offset[3] : 0;
413 }
while ((l_iter = l_iter->
next) != l_first);
417 BLI_assert(elem_offset || !update_face || index ==
bm->totface);
419 BLI_assert(elem_offset || !update_loop || index_loop ==
bm->totloop);
428 bm->elem_index_dirty &= ~htype;
431 elem_offset[0] +=
bm->totvert;
432 if (elem_offset[0] !=
bm->totvert) {
437 elem_offset[1] +=
bm->totedge;
438 if (elem_offset[1] !=
bm->totedge) {
443 elem_offset[2] +=
bm->totloop;
444 if (elem_offset[2] !=
bm->totloop) {
449 elem_offset[3] +=
bm->totface;
450 if (elem_offset[3] !=
bm->totface) {
463 BMesh *
bm,
const char *location,
const char *func,
const char *msg_a,
const char *msg_b)
468 const char *type_names[3] = {
"vert",
"edge",
"face"};
473 bool is_any_error =
false;
475 for (
i = 0;
i < 3;
i++) {
476 const bool is_dirty = (flag_types[
i] &
bm->elem_index_dirty) != 0;
478 bool is_error =
false;
494 if ((is_error ==
true) && (is_dirty ==
false)) {
497 "Invalid Index: at %s, %s, %s[%d] invalid index %d, '%s', '%s'\n",
506 else if ((is_error ==
false) && (is_dirty ==
true)) {
512 "Invalid Dirty: at %s, %s (%s), dirty flag was set but all index values are "
513 "correct, '%s', '%s'\n",
525 if (is_any_error == 0) {
526 fprintf(stderr,
"Valid Index Success: at %s, %s, '%s', '%s'\n", location, func, msg_a, msg_b);
541 if (
bm->vtable && ((
bm->elem_table_dirty &
BM_VERT) == 0)) {
549 if (
bm->etable && ((
bm->elem_table_dirty &
BM_EDGE) == 0)) {
557 if (
bm->ftable && ((
bm->elem_table_dirty &
BM_FACE) == 0)) {
572 const char htype_needed =
583 if (htype_needed == 0) {
588 if (
bm->vtable &&
bm->totvert <=
bm->vtable_tot &&
bm->totvert * 2 >=
bm->vtable_tot) {
595 bm->vtable =
static_cast<BMVert **
>(
597 bm->vtable_tot =
bm->totvert;
602 if (
bm->etable &&
bm->totedge <=
bm->etable_tot &&
bm->totedge * 2 >=
bm->etable_tot) {
609 bm->etable =
static_cast<BMEdge **
>(
611 bm->etable_tot =
bm->totedge;
616 if (
bm->ftable &&
bm->totface <=
bm->ftable_tot &&
bm->totface * 2 >=
bm->ftable_tot) {
623 bm->ftable =
static_cast<BMFace **
>(
625 bm->ftable_tot =
bm->totface;
635 bm->elem_table_dirty &= ~htype_needed;
691 }
while ((l_iter = l_iter->
next) != l_first);
700 if ((
bm->elem_table_dirty &
BM_VERT) == 0) {
701 return (index < bm->totvert) ?
bm->vtable[index] :
nullptr;
708 if ((
bm->elem_table_dirty &
BM_EDGE) == 0) {
709 return (index < bm->totedge) ?
bm->etable[index] :
nullptr;
716 if ((
bm->elem_table_dirty &
BM_FACE) == 0) {
717 return (index < bm->totface) ?
bm->ftable[index] :
nullptr;
743 GHash *vptr_map =
nullptr, *eptr_map =
nullptr, *fptr_map =
nullptr;
750 if (!(vert_idx || edge_idx || face_idx)) {
759 BMVert **verts_pool, *verts_copy, **vep;
760 int i, totvert =
bm->totvert;
770 verts_pool =
bm->vtable;
773 for (
i = totvert, ve = verts_copy + totvert - 1, vep = verts_pool + totvert - 1;
i--;
778 if (cd_vert_pyptr != -1) {
785 new_idx = vert_idx + totvert - 1;
786 ve = verts_copy + totvert - 1;
787 vep = verts_pool + totvert - 1;
788 for (
i = totvert;
i--; new_idx--, ve--, vep--) {
789 BMVert *new_vep = verts_pool[*new_idx];
793 "mapping vert from %d to %d (%p/%p to %p)\n",
i, *new_idx, *vep, verts_pool[
i], new_vep);
796 if (cd_vert_pyptr != -1) {
797 void **pyptr =
static_cast<void **
>(
799 *pyptr = pyptrs[*new_idx];
813 BMEdge **edges_pool, *edges_copy, **edp;
814 int i, totedge =
bm->totedge;
824 edges_pool =
bm->etable;
827 for (
i = totedge, ed = edges_copy + totedge - 1, edp = edges_pool + totedge - 1;
i--;
831 if (cd_edge_pyptr != -1) {
838 new_idx = edge_idx + totedge - 1;
839 ed = edges_copy + totedge - 1;
840 edp = edges_pool + totedge - 1;
841 for (
i = totedge;
i--; new_idx--, ed--, edp--) {
842 BMEdge *new_edp = edges_pool[*new_idx];
847 "mapping edge from %d to %d (%p/%p to %p)\n",
i, *new_idx, *edp, edges_pool[
i], new_edp);
849 if (cd_edge_pyptr != -1) {
850 void **pyptr =
static_cast<void **
>(
852 *pyptr = pyptrs[*new_idx];
866 BMFace **faces_pool, *faces_copy, **fap;
867 int i, totface =
bm->totface;
877 faces_pool =
bm->ftable;
880 for (
i = totface, fa = faces_copy + totface - 1, fap = faces_pool + totface - 1;
i--;
884 if (cd_poly_pyptr != -1) {
891 new_idx = face_idx + totface - 1;
892 fa = faces_copy + totface - 1;
893 fap = faces_pool + totface - 1;
894 for (
i = totface;
i--; new_idx--, fa--, fap--) {
895 BMFace *new_fap = faces_pool[*new_idx];
898 if (cd_poly_pyptr != -1) {
899 void **pyptr =
static_cast<void **
>(
901 *pyptr = pyptrs[*new_idx];
929 if (vptr_map || eptr_map) {
943 printf(
"Edge v1_disk_link prev: %p -> %p\n",
946 printf(
"Edge v1_disk_link next: %p -> %p\n",
949 printf(
"Edge v2_disk_link prev: %p -> %p\n",
952 printf(
"Edge v2_disk_link next: %p -> %p\n",
996 switch (ese->htype) {
1044 const char remap = (vpool_dst ?
BM_VERT : 0) | (epool_dst ?
BM_EDGE : 0) |
1056 const bool use_toolflags =
params->use_toolflags;
1064 memcpy(v_dst, v_src,
sizeof(
BMVert));
1065 if (use_toolflags) {
1072 vtable_dst[index] = v_dst;
1083 memcpy(e_dst, e_src,
sizeof(
BMEdge));
1084 if (use_toolflags) {
1091 etable_dst[index] = e_dst;
1098 int index, index_loop = 0;
1104 memcpy(f_dst, f_src,
sizeof(
BMFace));
1105 if (use_toolflags) {
1112 ftable_dst[index] = f_dst;
1118 BMLoop *l_iter_src, *l_first_src;
1122 memcpy(l_dst, l_iter_src,
sizeof(
BMLoop));
1123 ltable_dst[index_loop] = l_dst;
1125 }
while ((l_iter_src = l_iter_src->
next) != l_first_src);
1130#define MAP_VERT(ele) vtable_dst[BM_elem_index_get(ele)]
1131#define MAP_EDGE(ele) etable_dst[BM_elem_index_get(ele)]
1132#define MAP_LOOP(ele) ltable_dst[BM_elem_index_get(ele)]
1133#define MAP_FACE(ele) ftable_dst[BM_elem_index_get(ele)]
1135#define REMAP_VERT(ele) \
1137 if (remap & BM_VERT) { \
1138 ele = MAP_VERT(ele); \
1142#define REMAP_EDGE(ele) \
1144 if (remap & BM_EDGE) { \
1145 ele = MAP_EDGE(ele); \
1149#define REMAP_LOOP(ele) \
1151 if (remap & BM_LOOP) { \
1152 ele = MAP_LOOP(ele); \
1156#define REMAP_FACE(ele) \
1158 if (remap & BM_FACE) { \
1159 ele = MAP_FACE(ele); \
1166 for (
int i = 0;
i <
bm->totvert;
i++) {
1176 for (
int i = 0;
i <
bm->totedge;
i++) {
1192 for (
int i = 0;
i <
bm->totface;
i++) {
1197 BMLoop *l_iter, *l_first;
1208 }
while ((l_iter = l_iter->
next) != l_first);
1214 switch (ese->htype) {
1252 std::swap(vtable_dst,
bm->vtable);
1253 bm->vtable_tot =
bm->totvert;
1258 bm->vpool = vpool_dst;
1263 std::swap(etable_dst,
bm->etable);
1264 bm->etable_tot =
bm->totedge;
1269 bm->epool = epool_dst;
1276 bm->lpool = lpool_dst;
1281 std::swap(ftable_dst,
bm->ftable);
1282 bm->ftable_tot =
bm->totface;
1287 bm->fpool = fpool_dst;
1293 if (
bm->use_toolflags == use_toolflags) {
1303 bm_mempool_init_ex(&allocsize, use_toolflags, &vpool_dst, &epool_dst,
nullptr, &fpool_dst);
1305 if (use_toolflags ==
false) {
1310 bm->vtoolflagpool =
nullptr;
1311 bm->etoolflagpool =
nullptr;
1312 bm->ftoolflagpool =
nullptr;
1315 params.use_toolflags = use_toolflags;
1319 bm->use_toolflags = use_toolflags;
1332 positions[
i] =
v->co;
CustomData interface, see also DNA_customdata_types.h.
int CustomData_get_offset(const CustomData *data, eCustomDataType type)
void CustomData_bmesh_free_block(CustomData *data, void **block)
void CustomData_reset(CustomData *data)
void CustomData_free(CustomData *data)
bool CustomData_bmesh_has_free(const CustomData *data)
bool CustomData_has_layer(const CustomData *data, eCustomDataType type)
void BKE_lnor_spacearr_free(MLoopNorSpaceArray *lnors_spacearr)
GHash * BLI_ghash_ptr_new_ex(const char *info, unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void * BLI_ghash_lookup(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
void BLI_ghash_insert(GHash *gh, void *key, void *val)
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE void BLI_listbase_clear(ListBase *lb)
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
void mul_v3_m4v3(float r[3], const float mat[4][4], const float vec[3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
void * BLI_mempool_alloc(BLI_mempool *pool) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(1)
BLI_mempool * BLI_mempool_create(unsigned int esize, unsigned int elem_num, unsigned int pchunk, unsigned int flag) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL
void * BLI_mempool_findelem(BLI_mempool *pool, unsigned int index) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void * BLI_mempool_calloc(BLI_mempool *pool) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(1)
void BLI_mempool_destroy(BLI_mempool *pool) ATTR_NONNULL(1)
These structs are the foundation for all linked lists in the library system.
Read Guarded memory(de)allocation.
#define BM_FACE_FIRST_LOOP(p)
#define BM_ELEM_CD_GET_VOID_P(ele, offset)
void BMO_error_clear(BMesh *bm)
#define BM_ELEM_INDEX_VALIDATE(_bm, _msg_a, _msg_b)
#define BM_elem_index_get(ele)
#define BM_elem_index_set(ele, index)
int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, const int len)
Iterator as Array.
#define BM_ITER_ELEM(ele, iter, data, itype)
#define BM_ITER_MESH(ele, iter, bm, itype)
#define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar)
void BM_mesh_select_mode_flush(BMesh *bm)
void BM_mesh_elem_toolflags_clear(BMesh *bm)
const BMAllocTemplate bm_mesh_allocsize_default
void BM_mesh_toolflags_set(BMesh *bm, bool use_toolflags)
void BM_mesh_data_free(BMesh *bm)
BMesh Free Mesh Data.
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)
void BM_mesh_remap(BMesh *bm, const uint *vert_idx, const uint *edge_idx, const uint *face_idx)
void BM_mesh_clear(BMesh *bm)
BMesh Clear Mesh.
void bmesh_edit_begin(BMesh *, BMOpTypeFlag)
BMesh Begin Edit.
const BMAllocTemplate bm_mesh_chunksize_default
static void bm_mempool_init(BMesh *bm, const BMAllocTemplate *allocsize, const bool use_toolflags)
void BM_mesh_elem_toolflags_ensure(BMesh *bm)
void BM_mesh_rebuild(BMesh *bm, const BMeshCreateParams *params, BLI_mempool *vpool_dst, BLI_mempool *epool_dst, BLI_mempool *lpool_dst, BLI_mempool *fpool_dst)
void BM_mesh_vert_coords_apply(BMesh *bm, const Span< float3 > vert_coords)
void BM_mesh_free(BMesh *bm)
BMesh Free Mesh.
BMLoop * BM_loop_at_index_find(BMesh *bm, const int index)
void BM_mesh_vert_coords_get(BMesh *bm, MutableSpan< float3 > positions)
Array< float3 > BM_mesh_vert_coords_alloc(BMesh *bm)
BMVert * BM_vert_at_index_find_or_table(BMesh *bm, const int index)
void BM_mesh_elem_table_free(BMesh *bm, const char htype)
void BM_mesh_vert_normals_get(BMesh *bm, MutableSpan< float3 > normals)
int BM_mesh_elem_count(BMesh *bm, const char htype)
BMEdge * BM_edge_at_index_find(BMesh *bm, const int index)
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_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)
BMEdge * BM_edge_at_index_find_or_table(BMesh *bm, const int index)
void bmesh_edit_end(BMesh *bm, BMOpTypeFlag type_flag)
BMesh End Edit.
bool BM_mesh_elem_table_check(BMesh *bm)
void BM_mesh_vert_coords_apply_with_mat4(BMesh *bm, const Span< float3 > vert_coords, const float4x4 &transform)
BMVert * BM_vert_at_index_find(BMesh *bm, const int index)
BMFace * BM_face_at_index_find(BMesh *bm, const int index)
BMesh * BM_mesh_create(const BMAllocTemplate *allocsize, const BMeshCreateParams *params)
BMesh Make Mesh.
BMFace * BM_face_at_index_find_or_table(BMesh *bm, const int index)
void BM_mesh_elem_index_ensure_ex(BMesh *bm, const char htype, int elem_offset[4])
#define BMALLOC_TEMPLATE_FROM_BM(bm)
void BM_mesh_normals_update(BMesh *bm)
@ BMO_OPTYPE_FLAG_INVALIDATE_CLNOR_ALL
@ BMO_OPTYPE_FLAG_SELECT_VALIDATE
@ BMO_OPTYPE_FLAG_UNTAN_MULTIRES
@ BMO_OPTYPE_FLAG_NORMALS_CALC
@ BMO_OPTYPE_FLAG_SELECT_FLUSH
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
void bpy_bm_generic_invalidate(struct BPy_BMGeneric *)
static float normals[][3]
void * MEM_mallocN(size_t len, const char *str)
void * MEM_callocN(size_t len, const char *str)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
void MEM_freeN(void *vmemh)
MatBase< float, 4, 4 > float4x4
VecBase< float, 3 > float3
struct BMFlagLayer * oflags
struct BMFlagLayer * oflags
struct BMLoop * radial_prev
struct BMLoop * radial_next
struct BMFlagLayer * oflags