Blender V5.0
bmesh_class.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#pragma once
6
13
14#include "BLI_assert.h"
15#include "BLI_sys_types.h"
16
18#include "DNA_listBase.h"
19
20/* disable holes for now,
21 * these are ifdef'd because they use more memory and can't be saved in DNA currently */
22// #define USE_BMESH_HOLES
23
24struct BMEdge;
25struct BMFace;
26struct BMLoop;
27struct BMVert;
28struct BMesh;
29
31
32struct BLI_mempool;
33
34// #pragma GCC diagnostic push
35// #pragma GCC diagnostic error "-Wpadded"
36
49struct BMHeader {
50
51 /* NOTE: it its essential the #BMHeader is at least the size of two pointers.
52 * This is a requirement of mempool's method of iteration.
53 *
54 * Even though there is only a single pointer, the struct will be padded to two. */
55
57 void *data;
58
67 int index;
68
70 char htype;
72 char hflag;
73
81 // char _pad;
82};
83
84BLI_STATIC_ASSERT((sizeof(BMHeader) <= 16), "BMHeader size has grown!");
85
86/* NOTE: need some way to specify custom locations for custom data layers. so we can
87 * make them point directly into structs. and some way to make it only happen to the
88 * active layer, and properly update when switching active layers. */
89
90struct BMVert {
93 float co[3];
95 float no[3];
96
104 struct BMEdge *e;
105};
106
111
117 struct BMEdge *next, *prev;
118};
119
148
153
154struct BMLoop {
156 /* Notice no #BMFlagLayer, making this different from other elements. */
157
163 struct BMVert *v;
164
174 struct BMEdge *e;
181 struct BMFace *f;
182
215
243 struct BMLoop *next, *prev;
244};
245
250struct BMElemF {
252};
253
258struct BMElem {
260};
261
262#ifdef USE_BMESH_HOLES
267struct BMLoopList {
268 struct BMLoopList *next, *prev;
269 struct BMLoop *first, *last;
270};
271#endif
272
273struct BMFace {
275
276#ifdef USE_BMESH_HOLES
278 int totbounds;
279 ListBase loops;
280#else
282#endif
287 int len;
291 float no[3];
301 short mat_nr;
302 // short _pad[3];
303};
304
309
311 short f; /* flags */
312};
313
314// #pragma GCC diagnostic pop
315
316struct BMesh {
319
326
332
335
336 /* #BLI_mempool lookup tables (optional).
337 * Map indices to elements via #BM_mesh_elem_table_ensure and associated functions.
338 * Don't touch this or read it directly.
339 * Use #BM_mesh_elem_table_ensure(), `BM_vert/edge/face_at_index()`. */
340
347
348 /* Size of allocated tables. */
349
353
356
358
373
375
377
378#ifdef USE_BMESH_HOLES
379 struct BLI_mempool *looplistpool;
380#endif
381
384
392
395
398
408
411
422};
423
425enum {
430};
431
435 float niloc[3];
436 float nloc[3];
437 float *loc;
439};
440
452
453#define BM_ALL (BM_VERT | BM_EDGE | BM_LOOP | BM_FACE)
454#define BM_ALL_NOLOOP (BM_VERT | BM_EDGE | BM_FACE)
455
457enum {
461};
462
463/* args for _Generic */
464#define _BM_GENERIC_TYPE_ELEM_NONCONST \
465 void *, BMVert *, BMEdge *, BMLoop *, BMFace *, BMVert_OFlag *, BMEdge_OFlag *, BMFace_OFlag *, \
466 BMElem *, BMElemF *, BMHeader *
467
468#define _BM_GENERIC_TYPE_ELEM_CONST \
469 const void *, const BMVert *, const BMEdge *, const BMLoop *, const BMFace *, \
470 const BMVert_OFlag *, const BMEdge_OFlag *, const BMFace_OFlag *, const BMElem *, \
471 const BMElemF *, const BMHeader *
472
473#define BM_CHECK_TYPE_ELEM_CONST(ele) CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPES_CONST)
474
475#define BM_CHECK_TYPE_ELEM_NONCONST(ele) CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_ELEM_NONCONST)
476
477#define BM_CHECK_TYPE_ELEM(ele) \
478 CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_ELEM_NONCONST, _BM_GENERIC_TYPE_ELEM_CONST)
479
480/* vert */
481#define _BM_GENERIC_TYPE_VERT_NONCONST BMVert *, BMVert_OFlag *
482#define _BM_GENERIC_TYPE_VERT_CONST const BMVert *, const BMVert_OFlag *
483#define BM_CHECK_TYPE_VERT_CONST(ele) CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_VERT_CONST)
484#define BM_CHECK_TYPE_VERT_NONCONST(ele) CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_ELEM_NONCONST)
485#define BM_CHECK_TYPE_VERT(ele) \
486 CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_VERT_NONCONST, _BM_GENERIC_TYPE_VERT_CONST)
487/* edge */
488#define _BM_GENERIC_TYPE_EDGE_NONCONST BMEdge *, BMEdge_OFlag *
489#define _BM_GENERIC_TYPE_EDGE_CONST const BMEdge *, const BMEdge_OFlag *
490#define BM_CHECK_TYPE_EDGE_CONST(ele) CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_EDGE_CONST)
491#define BM_CHECK_TYPE_EDGE_NONCONST(ele) CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_ELEM_NONCONST)
492#define BM_CHECK_TYPE_EDGE(ele) \
493 CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_EDGE_NONCONST, _BM_GENERIC_TYPE_EDGE_CONST)
494/* face */
495#define _BM_GENERIC_TYPE_FACE_NONCONST BMFace *, BMFace_OFlag *
496#define _BM_GENERIC_TYPE_FACE_CONST const BMFace *, const BMFace_OFlag *
497#define BM_CHECK_TYPE_FACE_CONST(ele) CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_FACE_CONST)
498#define BM_CHECK_TYPE_FACE_NONCONST(ele) CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_ELEM_NONCONST)
499#define BM_CHECK_TYPE_FACE(ele) \
500 CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_FACE_NONCONST, _BM_GENERIC_TYPE_FACE_CONST)
501
506#define BM_CHECK_TYPE_ELEM_ASSIGN(ele) (BM_CHECK_TYPE_ELEM(ele)), *((void **)&ele)
507
509enum {
510 BM_ELEM_SELECT = (1 << 0),
511 BM_ELEM_HIDDEN = (1 << 1),
512 BM_ELEM_SEAM = (1 << 2),
514 BM_ELEM_SMOOTH = (1 << 3),
521 BM_ELEM_TAG = (1 << 4),
522
528
530 BM_ELEM_TAG_ALT = (1 << 6),
531
538};
539
540/* Only for #BMLoop to select an edge. */
541#define BM_ELEM_SELECT_UV_EDGE BM_ELEM_SEAM
542
543struct BPy_BMGeneric;
544extern void bpy_bm_generic_invalidate(struct BPy_BMGeneric *self);
545
546using BMElemFilterFunc = bool (*)(const BMElem *, void *user_data);
547using BMVertFilterFunc = bool (*)(const BMVert *, void *user_data);
548using BMEdgeFilterFunc = bool (*)(const BMEdge *, void *user_data);
549using BMFaceFilterFunc = bool (*)(const BMFace *, void *user_data);
550using BMLoopFilterFunc = bool (*)(const BMLoop *, void *user_data);
551using BMLoopPairFilterFunc = bool (*)(const BMLoop *, const BMLoop *, void *user_data);
552
553/* defines */
554#define BM_ELEM_CD_SET_INT(ele, offset, f) \
555 { \
556 CHECK_TYPE_NONCONST(ele); \
557 BLI_assert(offset != -1); \
558 *((int *)((char *)(ele)->head.data + (offset))) = (f); \
559 } \
560 (void)0
561
562#define BM_ELEM_CD_GET_INT(ele, offset) \
563 (BLI_assert(offset != -1), *((int *)((char *)(ele)->head.data + (offset))))
564
565#define BM_ELEM_CD_SET_BOOL(ele, offset, f) \
566 { \
567 CHECK_TYPE_NONCONST(ele); \
568 BLI_assert(offset != -1); \
569 *((bool *)((char *)(ele)->head.data + (offset))) = (f); \
570 } \
571 (void)0
572
573#define BM_ELEM_CD_GET_BOOL(ele, offset) \
574 (BLI_assert(offset != -1), *((bool *)((char *)(ele)->head.data + (offset))))
575
576#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
577# define BM_ELEM_CD_GET_BOOL_P(ele, offset) \
578 (BLI_assert(offset != -1), \
579 _Generic(ele, \
580 GENERIC_TYPE_ANY((bool *)POINTER_OFFSET((ele)->head.data, offset), \
581 _BM_GENERIC_TYPE_ELEM_NONCONST), \
582 GENERIC_TYPE_ANY((const bool *)POINTER_OFFSET((ele)->head.data, offset), \
583 _BM_GENERIC_TYPE_ELEM_CONST)))
584#else
585# define BM_ELEM_CD_GET_BOOL_P(ele, offset) \
586 (BLI_assert(offset != -1), (bool *)((char *)(ele)->head.data + (offset)))
587#endif
588
589#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
590# define BM_ELEM_CD_GET_VOID_P(ele, offset) \
591 (BLI_assert(offset != -1), \
592 _Generic(ele, \
593 GENERIC_TYPE_ANY(POINTER_OFFSET((ele)->head.data, offset), \
594 _BM_GENERIC_TYPE_ELEM_NONCONST), \
595 GENERIC_TYPE_ANY((const void *)POINTER_OFFSET((ele)->head.data, offset), \
596 _BM_GENERIC_TYPE_ELEM_CONST)))
597#else
598# define BM_ELEM_CD_GET_VOID_P(ele, offset) \
599 (BLI_assert(offset != -1), (void *)((char *)(ele)->head.data + (offset)))
600#endif
601
602#define BM_ELEM_CD_SET_FLOAT(ele, offset, f) \
603 { \
604 CHECK_TYPE_NONCONST(ele); \
605 BLI_assert(offset != -1); \
606 *((float *)((char *)(ele)->head.data + (offset))) = (f); \
607 } \
608 (void)0
609
610#define BM_ELEM_CD_GET_FLOAT(ele, offset) \
611 (BLI_assert(offset != -1), *((float *)((char *)(ele)->head.data + (offset))))
612
613#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
614
615# define BM_ELEM_CD_GET_FLOAT_P(ele, offset) \
616 (BLI_assert(offset != -1), \
617 _Generic(ele, \
618 GENERIC_TYPE_ANY((float *)POINTER_OFFSET((ele)->head.data, offset), \
619 _BM_GENERIC_TYPE_ELEM_NONCONST), \
620 GENERIC_TYPE_ANY((const float *)POINTER_OFFSET((ele)->head.data, offset), \
621 _BM_GENERIC_TYPE_ELEM_CONST)))
622
623# define BM_ELEM_CD_GET_FLOAT2_P(ele, offset) \
624 (BLI_assert(offset != -1), \
625 _Generic(ele, \
626 GENERIC_TYPE_ANY((float (*)[2])POINTER_OFFSET((ele)->head.data, offset), \
627 _BM_GENERIC_TYPE_ELEM_NONCONST), \
628 GENERIC_TYPE_ANY((const float (*)[2])POINTER_OFFSET((ele)->head.data, offset), \
629 _BM_GENERIC_TYPE_ELEM_CONST)))
630
631# define BM_ELEM_CD_GET_FLOAT3_P(ele, offset) \
632 (BLI_assert(offset != -1), \
633 _Generic(ele, \
634 GENERIC_TYPE_ANY((float (*)[3])POINTER_OFFSET((ele)->head.data, offset), \
635 _BM_GENERIC_TYPE_ELEM_NONCONST), \
636 GENERIC_TYPE_ANY((const float (*)[3])POINTER_OFFSET((ele)->head.data, offset), \
637 _BM_GENERIC_TYPE_ELEM_CONST)))
638
639#else
640
641# define BM_ELEM_CD_GET_FLOAT_P(ele, offset) \
642 (BLI_assert(offset != -1), (float *)((char *)(ele)->head.data + (offset)))
643
644# define BM_ELEM_CD_GET_FLOAT2_P(ele, offset) \
645 (BLI_assert(offset != -1), (float (*)[2])((char *)(ele)->head.data + (offset)))
646
647# define BM_ELEM_CD_GET_FLOAT3_P(ele, offset) \
648 (BLI_assert(offset != -1), (float (*)[3])((char *)(ele)->head.data + (offset)))
649
650#endif
651
652#define BM_ELEM_CD_SET_FLOAT2(ele, offset, f) \
653 { \
654 CHECK_TYPE_NONCONST(ele); \
655 BLI_assert(offset != -1); \
656 ((float *)((char *)(ele)->head.data + (offset)))[0] = (f)[0]; \
657 ((float *)((char *)(ele)->head.data + (offset)))[1] = (f)[1]; \
658 } \
659 (void)0
660
661#define BM_ELEM_CD_SET_FLOAT3(ele, offset, f) \
662 { \
663 CHECK_TYPE_NONCONST(ele); \
664 BLI_assert(offset != -1); \
665 ((float *)((char *)(ele)->head.data + (offset)))[0] = (f)[0]; \
666 ((float *)((char *)(ele)->head.data + (offset)))[1] = (f)[1]; \
667 ((float *)((char *)(ele)->head.data + (offset)))[2] = (f)[2]; \
668 } \
669 (void)0
670
671#define BM_ELEM_CD_GET_FLOAT_AS_UCHAR(ele, offset) \
672 (BLI_assert(offset != -1), (uchar)(BM_ELEM_CD_GET_FLOAT(ele, offset) * 255.0f))
673
674/* Forward declarations. */
675
676#ifdef USE_BMESH_HOLES
677# define BM_FACE_FIRST_LOOP(p) (((BMLoopList *)((p)->loops.first))->first)
678#else
679# define BM_FACE_FIRST_LOOP(p) ((p)->l_first)
680#endif
681
682#define BM_DISK_EDGE_NEXT(e, v) \
683 (CHECK_TYPE_INLINE(e, BMEdge *), \
684 CHECK_TYPE_INLINE(v, BMVert *), \
685 BLI_assert(BM_vert_in_edge(e, v)), \
686 (((&e->v1_disk_link)[v == e->v2]).next))
687#define BM_DISK_EDGE_PREV(e, v) \
688 (CHECK_TYPE_INLINE(e, BMEdge *), \
689 CHECK_TYPE_INLINE(v, BMVert *), \
690 BLI_assert(BM_vert_in_edge(e, v)), \
691 (((&e->v1_disk_link)[v == e->v2]).prev))
692
697#define BM_DEFAULT_NGON_STACK_SIZE 32
703#define BM_DEFAULT_ITER_STACK_SIZE 16
704
706#define BM_LOOP_RADIAL_MAX 10000
707#define BM_NGON_MAX 100000
708
710#define BM_THREAD_LIMIT 10000
#define BLI_STATIC_ASSERT(a, msg)
Definition BLI_assert.h:83
These structs are the foundation for all linked lists in the library system.
bool(*)(const BMEdge *, void *user_data) BMEdgeFilterFunc
bool(*)(const BMFace *, void *user_data) BMFaceFilterFunc
@ BM_SPACEARR_BMO_SET
@ BM_SPACEARR_DIRTY_ALL
@ BM_SPACEARR_DIRTY
bool(*)(const BMLoop *, void *user_data) BMLoopFilterFunc
@ BM_ELEM_HIDDEN
@ BM_ELEM_SEAM
@ BM_ELEM_SELECT
@ BM_ELEM_SMOOTH
@ BM_ELEM_INTERNAL_TAG
@ BM_ELEM_SELECT_UV
@ BM_ELEM_TAG
@ BM_ELEM_TAG_ALT
bool(*)(const BMElem *, void *user_data) BMElemFilterFunc
void bpy_bm_generic_invalidate(struct BPy_BMGeneric *self)
bool(*)(const BMVert *, void *user_data) BMVertFilterFunc
@ BM_LOOP
bool(*)(const BMLoop *, const BMLoop *, void *user_data) BMLoopPairFilterFunc
#define BM_FACE
#define BM_EDGE
#define BM_VERT
PyObject * self
static ulong * next
struct BMFlagLayer * oflags
BMHeader head
BMVert * v1
BMDiskLink v2_disk_link
BMDiskLink v1_disk_link
BMVert * v2
struct BMLoop * l
BMHeader head
BMHeader head
struct BMFlagLayer * oflags
short mat_nr
BMHeader head
float no[3]
BMLoop * l_first
void * data
char api_flag
BMLoopNorEditData ** lidx_to_lnor_editdata
BMLoopNorEditData * lnor_editdata
BMHeader head
struct BMVert * v
struct BMEdge * e
struct BMLoop * radial_prev
struct BMLoop * radial_next
struct BMLoop * prev
struct BMFace * f
struct BMLoop * next
struct BMFlagLayer * oflags
float co[3]
struct BMEdge * e
float no[3]
BMHeader head
int totvert
BMEdge ** etable
bool uv_select_sync_valid
struct BLI_mempool * epool
int totflags
int totfacesel
struct MLoopNorSpaceArray * lnor_spacearr
int shapenr
char elem_index_dirty
CustomData vdata
int totedge
char elem_table_dirty
struct BLI_mempool * vtoolflagpool
ListBase selected
CustomData edata
int totvertsel
int totloop
int ftable_tot
void * py_handle
struct BLI_mempool * etoolflagpool
BMFace * act_face
short selectmode
BMVert ** vtable
bool use_toolflags
struct BLI_mempool * ftoolflagpool
int totedgesel
char spacearr_dirty
CustomData pdata
CustomData ldata
int vtable_tot
BMFace ** ftable
int totface
int toolflag_index
int etable_tot
struct BLI_mempool * fpool
struct BLI_mempool * vpool
struct BLI_mempool * lpool
ListBase errorstack