33 const bool use_toolflags,
39 size_t vert_size, edge_size, loop_size, face_size;
41 if (use_toolflags ==
true) {
44 loop_size =
sizeof(
BMLoop);
48 vert_size =
sizeof(
BMVert);
49 edge_size =
sizeof(
BMEdge);
50 loop_size =
sizeof(
BMLoop);
51 face_size =
sizeof(
BMFace);
85 if (
bm->vtoolflagpool &&
bm->etoolflagpool &&
bm->ftoolflagpool) {
101 toolflagpool =
bm->etoolflagpool;
107 toolflagpool =
bm->ftoolflagpool;
117 if (
bm->vtoolflagpool) {
119 bm->vtoolflagpool =
nullptr;
121 if (
bm->etoolflagpool) {
123 bm->etoolflagpool =
nullptr;
125 if (
bm->ftoolflagpool) {
127 bm->ftoolflagpool =
nullptr;
140 bm->use_toolflags =
params->use_toolflags;
141 bm->toolflag_index = 0;
177 if (is_ldata_free || is_pdata_free) {
191 if (
bm->vdata.totlayer) {
194 if (
bm->edata.totlayer) {
197 if (
bm->ldata.totlayer) {
200 if (
bm->pdata.totlayer) {
229#ifdef USE_BMESH_HOLES
235 if (
bm->lnor_spacearr) {
245 const bool use_toolflags =
bm->use_toolflags;
246 void *py_handle =
bm->py_handle;
255 bm->use_toolflags = use_toolflags;
256 bm->py_handle = py_handle;
258 bm->toolflag_index = 0;
275 bm->py_handle =
nullptr;
288#ifdef BMOP_UNTAN_MULTIRES_ENABLED
292 bmesh_mdisps_space_set(
bm, MULTIRES_SPACE_TANGENT, MULTIRES_SPACE_ABSOLUTE);
295 bmesh_rationalize_normals(
bm, 0);
306#ifdef BMOP_UNTAN_MULTIRES_ENABLED
310 bmesh_rationalize_normals(
bm, 1);
311 bmesh_mdisps_space_set(
bm, MULTIRES_SPACE_ABSOLUTE, MULTIRES_SPACE_TANGENT);
313 else if (
flag & BMO_OP_FLAG_RATIONALIZE_NORMALS) {
314 bmesh_rationalize_normals(
bm, 1);
325 select_history =
bm->selected;
334 bm->selected = select_history;
348 if (elem_offset ==
nullptr) {
350 const char htype_needed =
bm->elem_index_dirty & htype;
351 if (htype_needed == 0) {
357 if ((
bm->elem_index_dirty &
BM_VERT) || (elem_offset && elem_offset[0])) {
361 int index = elem_offset ? elem_offset[0] : 0;
373 if ((
bm->elem_index_dirty &
BM_EDGE) || (elem_offset && elem_offset[1])) {
377 int index = elem_offset ? elem_offset[1] : 0;
390 (elem_offset && (elem_offset[2] || elem_offset[3])))
395 const bool update_face = (htype &
BM_FACE) && (
bm->elem_index_dirty &
BM_FACE);
396 const bool update_loop = (htype &
BM_LOOP) && (
bm->elem_index_dirty &
BM_LOOP);
398 int index_loop = elem_offset ? elem_offset[2] : 0;
399 int index = elem_offset ? elem_offset[3] : 0;
412 }
while ((l_iter = l_iter->
next) != l_first);
416 BLI_assert(elem_offset || !update_face || index ==
bm->totface);
418 BLI_assert(elem_offset || !update_loop || index_loop ==
bm->totloop);
427 bm->elem_index_dirty &= ~htype;
430 elem_offset[0] +=
bm->totvert;
431 if (elem_offset[0] !=
bm->totvert) {
436 elem_offset[1] +=
bm->totedge;
437 if (elem_offset[1] !=
bm->totedge) {
442 elem_offset[2] +=
bm->totloop;
443 if (elem_offset[2] !=
bm->totloop) {
448 elem_offset[3] +=
bm->totface;
449 if (elem_offset[3] !=
bm->totface) {
462 BMesh *
bm,
const char *location,
const char *func,
const char *msg_a,
const char *msg_b)
467 const char *type_names[3] = {
"vert",
"edge",
"face"};
472 bool is_any_error =
false;
474 for (i = 0; i < 3; i++) {
475 const bool is_dirty = (flag_types[i] &
bm->elem_index_dirty) != 0;
477 bool is_error =
false;
493 if ((is_error ==
true) && (is_dirty ==
false)) {
496 "Invalid Index: at %s, %s, %s[%d] invalid index %d, '%s', '%s'\n",
505 else if ((is_error ==
false) && (is_dirty ==
true)) {
511 "Invalid Dirty: at %s, %s (%s), dirty flag was set but all index values are "
512 "correct, '%s', '%s'\n",
524 if (is_any_error == 0) {
525 fprintf(stderr,
"Valid Index Success: at %s, %s, '%s', '%s'\n", location, func, msg_a, msg_b);
540 if (
bm->vtable && ((
bm->elem_table_dirty &
BM_VERT) == 0)) {
542 if (ele != (
BMElem *)
bm->vtable[i]) {
548 if (
bm->etable && ((
bm->elem_table_dirty &
BM_EDGE) == 0)) {
550 if (ele != (
BMElem *)
bm->etable[i]) {
556 if (
bm->ftable && ((
bm->elem_table_dirty &
BM_FACE) == 0)) {
558 if (ele != (
BMElem *)
bm->ftable[i]) {
571 const char htype_needed =
582 if (htype_needed == 0) {
587 if (
bm->vtable &&
bm->totvert <=
bm->vtable_tot &&
bm->totvert * 2 >=
bm->vtable_tot) {
594 bm->vtable =
static_cast<BMVert **
>(
596 bm->vtable_tot =
bm->totvert;
601 if (
bm->etable &&
bm->totedge <=
bm->etable_tot &&
bm->totedge * 2 >=
bm->etable_tot) {
608 bm->etable =
static_cast<BMEdge **
>(
610 bm->etable_tot =
bm->totedge;
615 if (
bm->ftable &&
bm->totface <=
bm->ftable_tot &&
bm->totface * 2 >=
bm->ftable_tot) {
622 bm->ftable =
static_cast<BMFace **
>(
624 bm->ftable_tot =
bm->totface;
634 bm->elem_table_dirty &= ~htype_needed;
690 }
while ((l_iter = l_iter->
next) != l_first);
699 if ((
bm->elem_table_dirty &
BM_VERT) == 0) {
700 return (index < bm->totvert) ?
bm->vtable[index] :
nullptr;
707 if ((
bm->elem_table_dirty &
BM_EDGE) == 0) {
708 return (index < bm->totedge) ?
bm->etable[index] :
nullptr;
715 if ((
bm->elem_table_dirty &
BM_FACE) == 0) {
716 return (index < bm->totface) ?
bm->ftable[index] :
nullptr;
742 GHash *vptr_map =
nullptr, *eptr_map =
nullptr, *fptr_map =
nullptr;
749 if (!(vert_idx || edge_idx || face_idx)) {
758 BMVert **verts_pool, *verts_copy, **vep;
759 int i, totvert =
bm->totvert;
769 verts_pool =
bm->vtable;
770 verts_copy =
static_cast<BMVert *
>(
772 void **pyptrs = (cd_vert_pyptr != -1) ?
773 static_cast<void **
>(
MEM_mallocN(
sizeof(
void *) * totvert, __func__)) :
775 for (i = totvert, ve = verts_copy + totvert - 1, vep = verts_pool + totvert - 1; i--;
780 if (cd_vert_pyptr != -1) {
787 new_idx = vert_idx + totvert - 1;
788 ve = verts_copy + totvert - 1;
789 vep = verts_pool + totvert - 1;
790 for (i = totvert; i--; new_idx--, ve--, vep--) {
791 BMVert *new_vep = verts_pool[*new_idx];
795 "mapping vert from %d to %d (%p/%p to %p)\n", i, *new_idx, *vep, verts_pool[i], new_vep);
798 if (cd_vert_pyptr != -1) {
799 void **pyptr =
static_cast<void **
>(
801 *pyptr = pyptrs[*new_idx];
815 BMEdge **edges_pool, *edges_copy, **edp;
816 int i, totedge =
bm->totedge;
826 edges_pool =
bm->etable;
827 edges_copy =
static_cast<BMEdge *
>(
829 void **pyptrs = (cd_edge_pyptr != -1) ?
830 static_cast<void **
>(
MEM_mallocN(
sizeof(
void *) * totedge, __func__)) :
832 for (i = totedge, ed = edges_copy + totedge - 1, edp = edges_pool + totedge - 1; i--;
836 if (cd_edge_pyptr != -1) {
843 new_idx = edge_idx + totedge - 1;
844 ed = edges_copy + totedge - 1;
845 edp = edges_pool + totedge - 1;
846 for (i = totedge; i--; new_idx--, ed--, edp--) {
847 BMEdge *new_edp = edges_pool[*new_idx];
852 "mapping edge from %d to %d (%p/%p to %p)\n", i, *new_idx, *edp, edges_pool[i], new_edp);
854 if (cd_edge_pyptr != -1) {
855 void **pyptr =
static_cast<void **
>(
857 *pyptr = pyptrs[*new_idx];
871 BMFace **faces_pool, *faces_copy, **fap;
872 int i, totface =
bm->totface;
882 faces_pool =
bm->ftable;
883 faces_copy =
static_cast<BMFace *
>(
885 void **pyptrs = (cd_poly_pyptr != -1) ?
886 static_cast<void **
>(
MEM_mallocN(
sizeof(
void *) * totface, __func__)) :
888 for (i = totface, fa = faces_copy + totface - 1, fap = faces_pool + totface - 1; i--;
892 if (cd_poly_pyptr != -1) {
899 new_idx = face_idx + totface - 1;
900 fa = faces_copy + totface - 1;
901 fap = faces_pool + totface - 1;
902 for (i = totface; i--; new_idx--, fa--, fap--) {
903 BMFace *new_fap = faces_pool[*new_idx];
906 if (cd_poly_pyptr != -1) {
907 void **pyptr =
static_cast<void **
>(
909 *pyptr = pyptrs[*new_idx];
937 if (vptr_map || eptr_map) {
951 printf(
"Edge v1_disk_link prev: %p -> %p\n",
954 printf(
"Edge v1_disk_link next: %p -> %p\n",
957 printf(
"Edge v2_disk_link prev: %p -> %p\n",
960 printf(
"Edge v2_disk_link next: %p -> %p\n",
1004 switch (ese->htype) {
1052 const char remap = (vpool_dst ?
BM_VERT : 0) | (epool_dst ?
BM_EDGE : 0) |
1056 sizeof(
BMVert *) *
bm->totvert, __func__)) :
1059 sizeof(
BMEdge *) *
bm->totedge, __func__)) :
1062 sizeof(
BMLoop *) *
bm->totloop, __func__)) :
1065 sizeof(
BMFace *) *
bm->totface, __func__)) :
1068 const bool use_toolflags =
params->use_toolflags;
1076 memcpy(v_dst, v_src,
sizeof(
BMVert));
1077 if (use_toolflags) {
1084 vtable_dst[index] = v_dst;
1095 memcpy(e_dst, e_src,
sizeof(
BMEdge));
1096 if (use_toolflags) {
1103 etable_dst[index] = e_dst;
1110 int index, index_loop = 0;
1116 memcpy(f_dst, f_src,
sizeof(
BMFace));
1117 if (use_toolflags) {
1124 ftable_dst[index] = f_dst;
1130 BMLoop *l_iter_src, *l_first_src;
1134 memcpy(l_dst, l_iter_src,
sizeof(
BMLoop));
1135 ltable_dst[index_loop] = l_dst;
1137 }
while ((l_iter_src = l_iter_src->
next) != l_first_src);
1142#define MAP_VERT(ele) vtable_dst[BM_elem_index_get(ele)]
1143#define MAP_EDGE(ele) etable_dst[BM_elem_index_get(ele)]
1144#define MAP_LOOP(ele) ltable_dst[BM_elem_index_get(ele)]
1145#define MAP_FACE(ele) ftable_dst[BM_elem_index_get(ele)]
1147#define REMAP_VERT(ele) \
1149 if (remap & BM_VERT) { \
1150 ele = MAP_VERT(ele); \
1154#define REMAP_EDGE(ele) \
1156 if (remap & BM_EDGE) { \
1157 ele = MAP_EDGE(ele); \
1161#define REMAP_LOOP(ele) \
1163 if (remap & BM_LOOP) { \
1164 ele = MAP_LOOP(ele); \
1168#define REMAP_FACE(ele) \
1170 if (remap & BM_FACE) { \
1171 ele = MAP_FACE(ele); \
1178 for (
int i = 0; i <
bm->totvert; i++) {
1188 for (
int i = 0; i <
bm->totedge; i++) {
1204 for (
int i = 0; i <
bm->totface; i++) {
1205 BMFace *f = ftable_dst[i];
1209 BMLoop *l_iter, *l_first;
1220 }
while ((l_iter = l_iter->
next) != l_first);
1226 switch (ese->htype) {
1264 std::swap(vtable_dst,
bm->vtable);
1265 bm->vtable_tot =
bm->totvert;
1270 bm->vpool = vpool_dst;
1275 std::swap(etable_dst,
bm->etable);
1276 bm->etable_tot =
bm->totedge;
1281 bm->epool = epool_dst;
1288 bm->lpool = lpool_dst;
1293 std::swap(ftable_dst,
bm->ftable);
1294 bm->ftable_tot =
bm->totface;
1299 bm->fpool = fpool_dst;
1305 if (
bm->use_toolflags == use_toolflags) {
1315 bm_mempool_init_ex(&allocsize, use_toolflags, &vpool_dst, &epool_dst,
nullptr, &fpool_dst);
1317 if (use_toolflags ==
false) {
1322 bm->vtoolflagpool =
nullptr;
1323 bm->etoolflagpool =
nullptr;
1324 bm->ftoolflagpool =
nullptr;
1327 params.use_toolflags = use_toolflags;
1331 bm->use_toolflags = use_toolflags;
1344 positions[i] =
v->co;
1376 const float (*vert_coords)[3],
1377 const float mat[4][4])
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, int totelem)
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(struct ListBase *lb)
void void BLI_freelistN(struct 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)
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_mesh_select_mode_flush(BMesh *bm)
void BM_mesh_elem_toolflags_clear(BMesh *bm)
void BM_mesh_vert_coords_apply_with_mat4(BMesh *bm, const float(*vert_coords)[3], const float mat[4][4])
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_vert_coords_apply(BMesh *bm, const float(*vert_coords)[3])
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_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)
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
void bpy_bm_generic_invalidate(struct BPy_BMGeneric *)
static float normals[][3]
void *(* MEM_mallocN)(size_t len, const char *str)
void MEM_freeN(void *vmemh)
void *(* MEM_callocN)(size_t len, const char *str)
VecBase< float, 3 > float3
struct BMFlagLayer * oflags
struct BMFlagLayer * oflags
struct BMLoop * radial_prev
struct BMLoop * radial_next
struct BMFlagLayer * oflags