Blender V4.3
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
14#include "BLI_assert.h"
15
16/* disable holes for now,
17 * these are ifdef'd because they use more memory and can't be saved in DNA currently */
18// #define USE_BMESH_HOLES
19
20struct BMEdge;
21struct BMFace;
22struct BMLoop;
23struct BMVert;
24struct BMesh;
25
27
28struct BLI_mempool;
29
30/* NOTE: it is very important for BMHeader to start with two
31 * pointers. this is a requirement of mempool's method of
32 * iteration.
33 *
34 * hrm. it doesn't but still works ok, remove the comment above? - campbell.
35 */
36
37// #pragma GCC diagnostic error "-Wpadded"
38
51typedef struct BMHeader {
53 void *data;
54
63 int index;
64
66 char htype;
68 char hflag;
69
77 // char _pad;
79
80BLI_STATIC_ASSERT((sizeof(BMHeader) <= 16), "BMHeader size has grown!");
81
82/* NOTE: need some way to specify custom locations for custom data layers. so we can
83 * make them point directly into structs. and some way to make it only happen to the
84 * active layer, and properly update when switching active layers. */
85
86typedef struct BMVert {
88
89 float co[3]; /* vertex coordinates */
90 float no[3]; /* vertex normal */
91
99 struct BMEdge *e;
101
106
107/* disk link structure, only used by edges */
108typedef struct BMDiskLink {
109 struct BMEdge *next, *prev;
111
140
145
146typedef struct BMLoop {
148 /* notice no flags layer */
149
155 struct BMVert *v;
156
166 struct BMEdge *e;
173 struct BMFace *f;
174
207
235 struct BMLoop *next, *prev;
237
238/* can cast BMFace/BMEdge/BMVert, but NOT BMLoop, since these don't have a flag layer */
242
243/* can cast anything to this, including BMLoop */
244typedef struct BMElem {
247
248#ifdef USE_BMESH_HOLES
249/* eventually, this structure will be used for supporting holes in faces */
250typedef struct BMLoopList {
251 struct BMLoopList *next, *prev;
252 struct BMLoop *first, *last;
253} BMLoopList;
254#endif
255
256typedef struct BMFace {
258
259#ifdef USE_BMESH_HOLES
260 int totbounds; /* Total boundaries, is one plus the number of holes in the face. */
261 ListBase loops;
262#else
264#endif
269 int len;
273 float no[3];
283 short mat_nr;
284 // short _pad[3];
286
291
292typedef struct BMFlagLayer {
293 short f; /* flags */
295
296// #pragma GCC diagnostic ignored "-Wpadded"
297
298typedef struct BMesh {
301
308
314
315 /* element pools */
317
318 /* mempool lookup tables (optional)
319 * index tables, to map indices to elements via
320 * BM_mesh_elem_table_ensure and associated functions. don't
321 * touch this or read it directly.\
322 * Use BM_mesh_elem_table_ensure(), BM_vert/edge/face_at_index() */
326
327 /* size of allocated tables */
331
332 /* Operator API stuff (must be all null or all allocated). */
334
336
338
340
341#ifdef USE_BMESH_HOLES
342 struct BLI_mempool *looplistpool;
343#endif
344
347
348 /* Should be copy of scene select mode. */
349 /* Stored in #BMEditMesh too, this is a bit confusing,
350 * make sure they're in sync!
351 * Only use when the edit mesh can't be accessed - campbell */
353
354 /* ID of the shape key this bmesh came from */
356
359
369
372
384
386enum {
391};
392
401
413
414#define BM_ALL (BM_VERT | BM_EDGE | BM_LOOP | BM_FACE)
415#define BM_ALL_NOLOOP (BM_VERT | BM_EDGE | BM_FACE)
416
418enum {
422};
423
424/* args for _Generic */
425#define _BM_GENERIC_TYPE_ELEM_NONCONST \
426 void *, BMVert *, BMEdge *, BMLoop *, BMFace *, BMVert_OFlag *, BMEdge_OFlag *, BMFace_OFlag *, \
427 BMElem *, BMElemF *, BMHeader *
428
429#define _BM_GENERIC_TYPE_ELEM_CONST \
430 const void *, const BMVert *, const BMEdge *, const BMLoop *, const BMFace *, \
431 const BMVert_OFlag *, const BMEdge_OFlag *, const BMFace_OFlag *, const BMElem *, \
432 const BMElemF *, const BMHeader *
433
434#define BM_CHECK_TYPE_ELEM_CONST(ele) CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPES_CONST)
435
436#define BM_CHECK_TYPE_ELEM_NONCONST(ele) CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_ELEM_NONCONST)
437
438#define BM_CHECK_TYPE_ELEM(ele) \
439 CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_ELEM_NONCONST, _BM_GENERIC_TYPE_ELEM_CONST)
440
441/* vert */
442#define _BM_GENERIC_TYPE_VERT_NONCONST BMVert *, BMVert_OFlag *
443#define _BM_GENERIC_TYPE_VERT_CONST const BMVert *, const BMVert_OFlag *
444#define BM_CHECK_TYPE_VERT_CONST(ele) CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_VERT_CONST)
445#define BM_CHECK_TYPE_VERT_NONCONST(ele) CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_ELEM_NONCONST)
446#define BM_CHECK_TYPE_VERT(ele) \
447 CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_VERT_NONCONST, _BM_GENERIC_TYPE_VERT_CONST)
448/* edge */
449#define _BM_GENERIC_TYPE_EDGE_NONCONST BMEdge *, BMEdge_OFlag *
450#define _BM_GENERIC_TYPE_EDGE_CONST const BMEdge *, const BMEdge_OFlag *
451#define BM_CHECK_TYPE_EDGE_CONST(ele) CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_EDGE_CONST)
452#define BM_CHECK_TYPE_EDGE_NONCONST(ele) CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_ELEM_NONCONST)
453#define BM_CHECK_TYPE_EDGE(ele) \
454 CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_EDGE_NONCONST, _BM_GENERIC_TYPE_EDGE_CONST)
455/* face */
456#define _BM_GENERIC_TYPE_FACE_NONCONST BMFace *, BMFace_OFlag *
457#define _BM_GENERIC_TYPE_FACE_CONST const BMFace *, const BMFace_OFlag *
458#define BM_CHECK_TYPE_FACE_CONST(ele) CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_FACE_CONST)
459#define BM_CHECK_TYPE_FACE_NONCONST(ele) CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_ELEM_NONCONST)
460#define BM_CHECK_TYPE_FACE(ele) \
461 CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_FACE_NONCONST, _BM_GENERIC_TYPE_FACE_CONST)
462
463/* Assignment from a void* to a typed pointer is not allowed in C++,
464 * casting the LHS to void works fine though.
465 */
466#define BM_CHECK_TYPE_ELEM_ASSIGN(ele) (BM_CHECK_TYPE_ELEM(ele)), *((void **)&ele)
467
469enum {
470 BM_ELEM_SELECT = (1 << 0),
471 BM_ELEM_HIDDEN = (1 << 1),
472 BM_ELEM_SEAM = (1 << 2),
474 BM_ELEM_SMOOTH = (1 << 3),
481 BM_ELEM_TAG = (1 << 4),
482
483 BM_ELEM_DRAW = (1 << 5), /* edge display */
484
486 BM_ELEM_TAG_ALT = (1 << 6),
487
494};
495
496struct BPy_BMGeneric;
497extern void bpy_bm_generic_invalidate(struct BPy_BMGeneric *self);
498
499typedef bool (*BMElemFilterFunc)(const BMElem *, void *user_data);
500typedef bool (*BMVertFilterFunc)(const BMVert *, void *user_data);
501typedef bool (*BMEdgeFilterFunc)(const BMEdge *, void *user_data);
502typedef bool (*BMFaceFilterFunc)(const BMFace *, void *user_data);
503typedef bool (*BMLoopFilterFunc)(const BMLoop *, void *user_data);
504typedef bool (*BMLoopPairFilterFunc)(const BMLoop *, const BMLoop *, void *user_data);
505
506/* defines */
507#define BM_ELEM_CD_SET_INT(ele, offset, f) \
508 { \
509 CHECK_TYPE_NONCONST(ele); \
510 BLI_assert(offset != -1); \
511 *((int *)((char *)(ele)->head.data + (offset))) = (f); \
512 } \
513 (void)0
514
515#define BM_ELEM_CD_GET_INT(ele, offset) \
516 (BLI_assert(offset != -1), *((int *)((char *)(ele)->head.data + (offset))))
517
518#define BM_ELEM_CD_SET_BOOL(ele, offset, f) \
519 { \
520 CHECK_TYPE_NONCONST(ele); \
521 BLI_assert(offset != -1); \
522 *((bool *)((char *)(ele)->head.data + (offset))) = (f); \
523 } \
524 (void)0
525
526#define BM_ELEM_CD_GET_BOOL(ele, offset) \
527 (BLI_assert(offset != -1), *((bool *)((char *)(ele)->head.data + (offset))))
528
529#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
530# define BM_ELEM_CD_GET_BOOL_P(ele, offset) \
531 (BLI_assert(offset != -1), \
532 _Generic(ele, \
533 GENERIC_TYPE_ANY((bool *)POINTER_OFFSET((ele)->head.data, offset), \
534 _BM_GENERIC_TYPE_ELEM_NONCONST), \
535 GENERIC_TYPE_ANY((const bool *)POINTER_OFFSET((ele)->head.data, offset), \
536 _BM_GENERIC_TYPE_ELEM_CONST)))
537#else
538# define BM_ELEM_CD_GET_BOOL_P(ele, offset) \
539 (BLI_assert(offset != -1), (bool *)((char *)(ele)->head.data + (offset)))
540#endif
541
542#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
543# define BM_ELEM_CD_GET_VOID_P(ele, offset) \
544 (BLI_assert(offset != -1), \
545 _Generic(ele, \
546 GENERIC_TYPE_ANY(POINTER_OFFSET((ele)->head.data, offset), _BM_GENERIC_TYPE_ELEM_NONCONST), \
547 GENERIC_TYPE_ANY((const void *)POINTER_OFFSET((ele)->head.data, offset), \
548 _BM_GENERIC_TYPE_ELEM_CONST)))
549#else
550# define BM_ELEM_CD_GET_VOID_P(ele, offset) \
551 (BLI_assert(offset != -1), (void *)((char *)(ele)->head.data + (offset)))
552#endif
553
554#define BM_ELEM_CD_SET_FLOAT(ele, offset, f) \
555 { \
556 CHECK_TYPE_NONCONST(ele); \
557 BLI_assert(offset != -1); \
558 *((float *)((char *)(ele)->head.data + (offset))) = (f); \
559 } \
560 (void)0
561
562#define BM_ELEM_CD_GET_FLOAT(ele, offset) \
563 (BLI_assert(offset != -1), *((float *)((char *)(ele)->head.data + (offset))))
564
565#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
566
567# define BM_ELEM_CD_GET_FLOAT_P(ele, offset) \
568 (BLI_assert(offset != -1), \
569 _Generic(ele, \
570 GENERIC_TYPE_ANY((float *)POINTER_OFFSET((ele)->head.data, offset), \
571 _BM_GENERIC_TYPE_ELEM_NONCONST), \
572 GENERIC_TYPE_ANY((const float *)POINTER_OFFSET((ele)->head.data, offset), \
573 _BM_GENERIC_TYPE_ELEM_CONST)))
574
575# define BM_ELEM_CD_GET_FLOAT2_P(ele, offset) \
576 (BLI_assert(offset != -1), \
577 _Generic(ele, \
578 GENERIC_TYPE_ANY((float(*)[2])POINTER_OFFSET((ele)->head.data, offset), \
579 _BM_GENERIC_TYPE_ELEM_NONCONST), \
580 GENERIC_TYPE_ANY((const float(*)[2])POINTER_OFFSET((ele)->head.data, offset), \
581 _BM_GENERIC_TYPE_ELEM_CONST)))
582
583# define BM_ELEM_CD_GET_FLOAT3_P(ele, offset) \
584 (BLI_assert(offset != -1), \
585 _Generic(ele, \
586 GENERIC_TYPE_ANY((float(*)[3])POINTER_OFFSET((ele)->head.data, offset), \
587 _BM_GENERIC_TYPE_ELEM_NONCONST), \
588 GENERIC_TYPE_ANY((const float(*)[3])POINTER_OFFSET((ele)->head.data, offset), \
589 _BM_GENERIC_TYPE_ELEM_CONST)))
590
591#else
592
593# define BM_ELEM_CD_GET_FLOAT_P(ele, offset) \
594 (BLI_assert(offset != -1), (float *)((char *)(ele)->head.data + (offset)))
595
596# define BM_ELEM_CD_GET_FLOAT2_P(ele, offset) \
597 (BLI_assert(offset != -1), (float(*)[2])((char *)(ele)->head.data + (offset)))
598
599# define BM_ELEM_CD_GET_FLOAT3_P(ele, offset) \
600 (BLI_assert(offset != -1), (float(*)[3])((char *)(ele)->head.data + (offset)))
601
602#endif
603
604#define BM_ELEM_CD_SET_FLOAT2(ele, offset, f) \
605 { \
606 CHECK_TYPE_NONCONST(ele); \
607 BLI_assert(offset != -1); \
608 ((float *)((char *)(ele)->head.data + (offset)))[0] = (f)[0]; \
609 ((float *)((char *)(ele)->head.data + (offset)))[1] = (f)[1]; \
610 } \
611 (void)0
612
613#define BM_ELEM_CD_SET_FLOAT3(ele, offset, f) \
614 { \
615 CHECK_TYPE_NONCONST(ele); \
616 BLI_assert(offset != -1); \
617 ((float *)((char *)(ele)->head.data + (offset)))[0] = (f)[0]; \
618 ((float *)((char *)(ele)->head.data + (offset)))[1] = (f)[1]; \
619 ((float *)((char *)(ele)->head.data + (offset)))[2] = (f)[2]; \
620 } \
621 (void)0
622
623#define BM_ELEM_CD_GET_FLOAT_AS_UCHAR(ele, offset) \
624 (BLI_assert(offset != -1), (uchar)(BM_ELEM_CD_GET_FLOAT(ele, offset) * 255.0f))
625
626/* Forward declarations. */
627
628#ifdef USE_BMESH_HOLES
629# define BM_FACE_FIRST_LOOP(p) (((BMLoopList *)((p)->loops.first))->first)
630#else
631# define BM_FACE_FIRST_LOOP(p) ((p)->l_first)
632#endif
633
634#define BM_DISK_EDGE_NEXT(e, v) \
635 (CHECK_TYPE_INLINE(e, BMEdge *), \
636 CHECK_TYPE_INLINE(v, BMVert *), \
637 BLI_assert(BM_vert_in_edge(e, v)), \
638 (((&e->v1_disk_link)[v == e->v2]).next))
639#define BM_DISK_EDGE_PREV(e, v) \
640 (CHECK_TYPE_INLINE(e, BMEdge *), \
641 CHECK_TYPE_INLINE(v, BMVert *), \
642 BLI_assert(BM_vert_in_edge(e, v)), \
643 (((&e->v1_disk_link)[v == e->v2]).prev))
644
649#define BM_DEFAULT_NGON_STACK_SIZE 32
655#define BM_DEFAULT_ITER_STACK_SIZE 16
656
657/* avoid inf loop, this value is arbitrary
658 * but should not error on valid cases */
659#define BM_LOOP_RADIAL_MAX 10000
660#define BM_NGON_MAX 100000
661
662/* Minimum number of elements before using threading. */
663#define BM_THREAD_LIMIT 10000
#define BLI_STATIC_ASSERT(a, msg)
Definition BLI_assert.h:87
unsigned int uint
struct BMDiskLink BMDiskLink
bool(* BMFaceFilterFunc)(const BMFace *, void *user_data)
struct BMFace BMFace
@ BM_LOOP
@ BM_FACE
@ BM_VERT
@ BM_EDGE
struct BMFace_OFlag BMFace_OFlag
bool(* BMElemFilterFunc)(const BMElem *, void *user_data)
bool(* BMVertFilterFunc)(const BMVert *, void *user_data)
struct BMElemF BMElemF
bool(* BMLoopFilterFunc)(const BMLoop *, void *user_data)
struct BMElem BMElem
struct BMHeader BMHeader
struct BMEdge BMEdge
struct BMVert_OFlag BMVert_OFlag
struct BMLoop BMLoop
@ BM_SPACEARR_BMO_SET
@ BM_SPACEARR_DIRTY_ALL
@ BM_SPACEARR_DIRTY
@ BM_ELEM_HIDDEN
@ BM_ELEM_SEAM
@ BM_ELEM_SELECT
@ BM_ELEM_SMOOTH
@ BM_ELEM_INTERNAL_TAG
@ BM_ELEM_TAG
@ BM_ELEM_DRAW
@ BM_ELEM_TAG_ALT
struct BMesh BMesh
struct BMLoopNorEditData BMLoopNorEditData
struct BMEdge_OFlag BMEdge_OFlag
struct BMVert BMVert
void bpy_bm_generic_invalidate(struct BPy_BMGeneric *self)
bool(* BMEdgeFilterFunc)(const BMEdge *, void *user_data)
bool(* BMLoopPairFilterFunc)(const BMLoop *, const BMLoop *, void *user_data)
struct BMLoopNorEditDataArray BMLoopNorEditDataArray
struct BMFlagLayer BMFlagLayer
PyObject * self
static ulong * next
SymEdge< T > * prev(const SymEdge< T > *se)
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
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
BMHeader head
int totvert
BMEdge ** etable
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
uint use_toolflags
int totvertsel
int totloop
int ftable_tot
void * py_handle
struct BLI_mempool * etoolflagpool
BMFace * act_face
short selectmode
BMVert ** vtable
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