Docs: clarify radial/cycle use for BMesh loops

Also add minor corrections clarifications elsewhere.
This commit is contained in:
2021-02-24 15:37:37 +11:00
parent b2c7ea6d82
commit 5c2e10d5ed

View File

@@ -18,10 +18,11 @@
/** \file
* \ingroup bmesh
*
* #BMesh data structures, used for mesh editing operations
* that benefit from accessing connectivity information.
*/
/* bmesh data structures */
/* disable holes for now,
* these are ifdef'd because they use more memory and cant be saved in DNA currently */
// #define USE_BMESH_HOLES
@@ -46,15 +47,15 @@ struct BLI_mempool;
// #pragma GCC diagnostic error "-Wpadded"
/**
* BMHeader
* #BMHeader
*
* All mesh elements begin with a BMHeader. This structure
* All mesh elements begin with a #BMHeader. This structure
* hold several types of data
*
* 1: The type of the element (vert, edge, loop or face)
* 2: Persistent "header" flags/markings (smooth, seam, select, hidden, etc)
* note that this is different from the "tool" flags.
* 3: Unique ID in the bmesh.
* note that this is different from the "tool" flags.
* 3: Unique ID in the #BMesh.
* 4: some elements for internal record keeping.
*/
typedef struct BMHeader {
@@ -102,7 +103,7 @@ typedef struct BMVert {
* Pointer to (any) edge using this vertex (for disk cycles).
*
* \note Some higher level functions set this to different edges that use this vertex,
* which is a bit of an abuse of internal bmesh data but also works OK for now
* which is a bit of an abuse of internal #BMesh data but also works OK for now
* (use with care!).
*/
struct BMEdge *e;
@@ -121,10 +122,21 @@ typedef struct BMDiskLink {
typedef struct BMEdge {
BMHeader head;
struct BMVert *v1, *v2; /* vertices (unordered) */
/**
* Vertices (unordered),
*
* Although the order can be used at times,
* when extruding a face from a wire-edge for example.
*
* Operations that create/subdivide edges shouldn't flip the order
* unless there is a good reason to do so.
*/
BMVert *v1, *v2;
/* the list of loops around the edge (use l->radial_prev/next)
* to access the other loops using the edge */
/**
* The list of loops around the edge, see doc-string for #BMLoop.radial_next
* for an example of using this to loop over all faces used by an edge.
*/
struct BMLoop *l;
/**
@@ -145,17 +157,92 @@ typedef struct BMLoop {
BMHeader head;
/* notice no flags layer */
/**
* The vertex this loop points to.
*
* - This vertex must be unique within the cycle.
*/
struct BMVert *v;
struct BMEdge *e; /* edge, using verts (v, next->v) */
/**
* The edge this loop uses.
*
* Vertices (#BMLoop.v & #BMLoop.next.v) always contain vertices from (#BMEdge.v1 & #BMEdge.v2).
* Although no assumptions can be made about the order,
* as this isn't meaningful for mesh topology.
*
* - This edge must be unique within the cycle (defined by #BMLoop.next & #BMLoop.prev links).
*/
struct BMEdge *e;
/**
* The face this loop is part of.
*
* - This face must be shared by all within the cycle.
* Used as a back-pointer so loops can know the face they define.
*/
struct BMFace *f;
/* circular linked list of loops which all use the same edge as this one '->e',
* but not necessarily the same vertex (can be either v1 or v2 of our own '->e') */
/**
* Other loops connected to this edge,.
*
* This is typically use for accessing an edges faces,
* however this is done by stepping over it's loops.
*
* - This is a circular list, so there are no first/last storage of the "radial" data.
* Instead #BMEdge.l points to any one of the loops that use it.
*
* - Since the list is circular, the particular loop referenced doesn't matter,
* as all other loops can be accessed from it.
*
* - Every loop in this radial list has the same value for #BMLoop.e.
*
* - The value for #BMLoop.v might not match the radial next/previous
* as this depends on the face-winding.
* You can be sure #BMLoop.v will either #BMEdge.v1 or #BMEdge.v2 of #BMLoop.e,
*
* - Unlike face-winding (which defines if the direction the face points),
* next and previous are insignificant. The list could be reversed for example,
* without any impact on the topology.
*
* This is an example of looping over an edges faces using #BMLoop.radial_next.
*
* \code{.c}
* BMLoop *l_iter = edge->l;
* do {
* operate_on_face(l_iter->f);
* } while ((l_iter = l_iter->radial_next) != edge->l);
* \endcode
*/
struct BMLoop *radial_next, *radial_prev;
/* these were originally commented as private but are used all over the code */
/* can't use ListBase API, due to head */
struct BMLoop *next, *prev; /* next/prev verts around the face */
/**
* Other loops that are part of this face.
*
* This is typically used for accessing all vertices/edges in a faces.
*
* - This is a circular list, so there are no first/last storage of the "cycle" data.
* Instead #BMFace.l_first points to any one of the loops that are part of this face.
*
* - Since the list is circular, the particular loop referenced doesn't matter,
* as all other loops can be accessed from it.
*
* - Every loop in this "cycle" list has the same value for #BMLoop.f.
*
* - The direction of this list defines the face winding.
* Reversing the list flips the face.
*
* This is an example loop over all vertices and edges of a face.
*
* \code{.c}
* BMLoop *l_first, *l_iter;
* l_iter = l_first = BM_FACE_FIRST_LOOP(f);
* do {
* operate_on_vert(l_iter->v);
* operate_on_edge(l_iter->e);
* } while ((l_iter = l_iter->next) != l_first);
* \endcode
*/
struct BMLoop *next, *prev;
} BMLoop;
/* can cast BMFace/BMEdge/BMVert, but NOT BMLoop, since these don't have a flag layer */
@@ -185,7 +272,11 @@ typedef struct BMFace {
#else
BMLoop *l_first;
#endif
int len; /* number of vertices in the face */
/**
* Number of vertices in the face
* (the length of #BMFace.l_first circular linked list).
*/
int len;
float no[3]; /* face normal */
short mat_nr; /* material index */
// short _pad[3];
@@ -206,13 +297,17 @@ typedef struct BMesh {
int totvert, totedge, totloop, totface;
int totvertsel, totedgesel, totfacesel;
/* flag index arrays as being dirty so we can check if they are clean and
/**
* Flag index arrays as being dirty so we can check if they are clean and
* avoid looping over the entire vert/edge/face/loop array in those cases.
* valid flags are - BM_VERT | BM_EDGE | BM_FACE | BM_LOOP. */
* valid flags are: `(BM_VERT | BM_EDGE | BM_FACE | BM_LOOP)`
*/
char elem_index_dirty;
/* flag array table as being dirty so we know when its safe to use it,
* or when it needs to be re-created */
/**
* Flag array table as being dirty so we know when its safe to use it,
* or when it needs to be re-created.
*/
char elem_table_dirty;
/* element pools */
@@ -248,8 +343,8 @@ typedef struct BMesh {
struct MLoopNorSpaceArray *lnor_spacearr;
char spacearr_dirty;
/* should be copy of scene select mode */
/* stored in BMEditMesh too, this is a bit confusing,
/* Should be copy of scene select mode. */
/* Stored in #BMEditMesh too, this is a bit confusing,
* make sure they're in sync!
* Only use when the edit mesh cant be accessed - campbell */
short selectmode;
@@ -260,14 +355,30 @@ typedef struct BMesh {
int totflags;
ListBase selected;
/**
* The active face.
* This is kept even when unselected, mainly so UV editing can keep showing the
* active faces image while the selection is being modified in the 3D viewport.
*
* Without this the active image in the UV editor would flicker in a distracting way
* while changing selection in the 3D viewport.
*/
BMFace *act_face;
/** List of #BMOpError, used for operator error handling. */
ListBase errorstack;
/**
* Keep a single reference to the Python instance of this #BMesh (if any exists).
*
* This allows save invalidation of a #BMesh when it's freed,
* so the Python object will report it as having been removed,
* instead of crashing on invalid memory access.
*/
void *py_handle;
} BMesh;
/* BMHeader->htype (char) */
/** #BMHeader.htype (char) */
enum {
BM_VERT = 1,
BM_EDGE = 2,
@@ -288,7 +399,7 @@ typedef struct BMLoopNorEditDataArray {
BMLoopNorEditData *lnor_editdata;
/**
* This one has full amount of loops,
* used to map loop index to actual BMLoopNorEditData struct.
* used to map loop index to actual #BMLoopNorEditData struct.
*/
BMLoopNorEditData **lidx_to_lnor_editdata;
@@ -299,6 +410,7 @@ typedef struct BMLoopNorEditDataArray {
#define BM_ALL (BM_VERT | BM_EDGE | BM_LOOP | BM_FACE)
#define BM_ALL_NOLOOP (BM_VERT | BM_EDGE | BM_FACE)
/** #BMesh.spacearr_dirty */
enum {
BM_SPACEARR_DIRTY = 1 << 0,
BM_SPACEARR_DIRTY_ALL = 1 << 1,
@@ -354,7 +466,7 @@ enum {
# define BM_CHECK_TYPE_ELEM_ASSIGN(ele) (BM_CHECK_TYPE_ELEM(ele)), ele
#endif
/* BMHeader->hflag (char) */
/** #BMHeader.hflag (char) */
enum {
BM_ELEM_SELECT = (1 << 0),
BM_ELEM_HIDDEN = (1 << 1),
@@ -364,21 +476,23 @@ enum {
* this is a sharp edge when disabled */
BM_ELEM_SMOOTH = (1 << 3),
/**
* internal flag, used for ensuring correct normals
* during multires interpolation, and any other time
* Internal flag, used for ensuring correct normals
* during multi-resolution interpolation, and any other time
* when temp tagging is handy.
* always assume dirty & clear before use. */
* always assume dirty & clear before use.
*/
BM_ELEM_TAG = (1 << 4),
BM_ELEM_DRAW = (1 << 5), /* edge display */
/* spare tag, assumed dirty, use define in each function to name based on use */
/** Spare tag, assumed dirty, use define in each function to name based on use. */
BM_ELEM_TAG_ALT = (1 << 6),
/**
* For low level internal API tagging,
* since tools may want to tag verts and not have functions clobber them.
* Leave cleared! */
* Leave cleared!
*/
BM_ELEM_INTERNAL_TAG = (1 << 7),
};