update doxygen comments for bmesh.
This commit is contained in:
@@ -49,20 +49,18 @@
|
||||
static void bm_loop_attrs_copy(BMesh *source_mesh, BMesh *target_mesh,
|
||||
const BMLoop *source_loop, BMLoop *target_loop);
|
||||
|
||||
/*
|
||||
* BMESH MAKE QUADTRIANGLE
|
||||
/**
|
||||
* \brief Make Quad/Triangle
|
||||
*
|
||||
* Creates a new quad or triangle from
|
||||
* a list of 3 or 4 vertices. If nodouble
|
||||
* equals 1, then a check is done to see
|
||||
* if a face with these vertices already
|
||||
* exists and returns it instead. If a pointer
|
||||
* to an example face is provided, it's custom
|
||||
* data and properties will be copied to the new
|
||||
* face.
|
||||
* Creates a new quad or triangle from a list of 3 or 4 vertices.
|
||||
* If \a nodouble is TRUE, then a check is done to see if a face
|
||||
* with these vertices already exists and returns it instead.
|
||||
*
|
||||
* Note that the winding of the face is determined
|
||||
* by the order of the vertices in the vertex array
|
||||
* If a pointer to an example face is provided, it's custom data
|
||||
* and properties will be copied to the new face.
|
||||
*
|
||||
* \note The winding of the face is determined by the order
|
||||
* of the vertices in the vertex array.
|
||||
*/
|
||||
|
||||
BMFace *BM_face_create_quad_tri(BMesh *bm,
|
||||
@@ -128,17 +126,18 @@ void BM_face_copy_shared(BMesh *bm, BMFace *f)
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief BMESH MAKE NGON
|
||||
* \brief Make NGon
|
||||
*
|
||||
* Makes an ngon from an unordered list of edges. v1 and v2 must be the verts
|
||||
* defining edges[0], and define the winding of the new face.
|
||||
* Makes an ngon from an unordered list of edges. \a v1 and \a v2
|
||||
* must be the verts defining edges[0],
|
||||
* and define the winding of the new face.
|
||||
*
|
||||
* The edges are not required to be ordered, simply to to form
|
||||
* a single closed loop as a whole
|
||||
* \a edges are not required to be ordered, simply to to form
|
||||
* a single closed loop as a whole.
|
||||
*
|
||||
* Note that while this function will work fine when the edges
|
||||
* \note While this function will work fine when the edges
|
||||
* are already sorted, if the edges are always going to be sorted,
|
||||
* BM_face_create should be considered over this function as it
|
||||
* #BM_face_create should be considered over this function as it
|
||||
* avoids some unnecessary work.
|
||||
*/
|
||||
BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, int len, int nodouble)
|
||||
@@ -268,14 +267,10 @@ err:
|
||||
/* bmesh_make_face_from_face(BMesh *bm, BMFace *source, BMFace *target) */
|
||||
|
||||
|
||||
/*
|
||||
* REMOVE TAGGED XXX
|
||||
*
|
||||
/**
|
||||
* Called by operators to remove elements that they have marked for
|
||||
* removal.
|
||||
*
|
||||
*/
|
||||
|
||||
void BMO_remove_tagged_faces(BMesh *bm, const short oflag)
|
||||
{
|
||||
BMFace *f;
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file blender/bmesh/intern/bmesh_newcore.c
|
||||
/** \file blender/bmesh/intern/bmesh_core.c
|
||||
* \ingroup bmesh
|
||||
*
|
||||
*/
|
||||
@@ -445,7 +445,8 @@ int bmesh_elem_check(BMesh *UNUSED(bm), void *element, const char htype)
|
||||
return err;
|
||||
}
|
||||
|
||||
/* low level function, only free's,
|
||||
/**
|
||||
* low level function, only free's,
|
||||
* does not change adjust surrounding geometry */
|
||||
static void bm_kill_only_vert(BMesh *bm, BMVert *v)
|
||||
{
|
||||
@@ -632,21 +633,6 @@ void BM_vert_kill(BMesh *bm, BMVert *v)
|
||||
|
||||
/********** private disk and radial cycle functions ********** */
|
||||
|
||||
/**
|
||||
* bmesh_loop_reverse
|
||||
*
|
||||
* FLIP FACE EULER
|
||||
*
|
||||
* Changes the winding order of a face from CW to CCW or vice versa.
|
||||
* This euler is a bit peculiar in compairson to others as it is its
|
||||
* own inverse.
|
||||
*
|
||||
* BMESH_TODO: reinsert validation code.
|
||||
*
|
||||
* Returns -
|
||||
* 1 for success, 0 for failure.
|
||||
*/
|
||||
|
||||
static int bm_loop_length(BMLoop *l)
|
||||
{
|
||||
BMLoop *l_first = l;
|
||||
@@ -659,6 +645,17 @@ static int bm_loop_length(BMLoop *l)
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Loop Reverse
|
||||
*
|
||||
* Changes the winding order of a face from CW to CCW or vice versa.
|
||||
* This euler is a bit peculiar in compairson to others as it is its
|
||||
* own inverse.
|
||||
*
|
||||
* BMESH_TODO: reinsert validation code.
|
||||
*
|
||||
* \return Success
|
||||
*/
|
||||
static int bm_loop_reverse_loop(BMesh *bm, BMFace *f
|
||||
#ifdef USE_BMESH_HOLES
|
||||
, BMLoopList *lst
|
||||
@@ -856,16 +853,18 @@ static int disk_is_flagged(BMVert *v, int flag)
|
||||
/* Midlevel Topology Manipulation Functions */
|
||||
|
||||
/**
|
||||
* \brief Join Connected Faces
|
||||
*
|
||||
* Joins a collected group of faces into one. Only restriction on
|
||||
* the input data is that the faces must be connected to each other.
|
||||
*
|
||||
* If a pair of faces share multiple edges, the pair of
|
||||
* faces will be joined at every edge.
|
||||
* \return The newly created combine BMFace.
|
||||
*
|
||||
* Returns a pointer to the combined face.
|
||||
* \note If a pair of faces share multiple edges,
|
||||
* the pair of faces will be joined at every edge.
|
||||
*
|
||||
* \note this is a generic, flexible join faces function, almost everything
|
||||
* uses this, including #BM_faces_join_pair
|
||||
* \note this is a generic, flexible join faces function,
|
||||
* almost everything uses this, including #BM_faces_join_pair
|
||||
*/
|
||||
BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface)
|
||||
{
|
||||
@@ -1045,8 +1044,6 @@ error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* BMESH_TODO - this is only used once, investigate sharing code with BM_face_create
|
||||
*/
|
||||
static BMFace *bm_face_create__sfme(BMesh *bm, BMFace *UNUSED(example))
|
||||
{
|
||||
BMFace *f;
|
||||
@@ -1069,41 +1066,38 @@ static BMFace *bm_face_create__sfme(BMesh *bm, BMFace *UNUSED(example))
|
||||
}
|
||||
|
||||
/**
|
||||
* bmesh_SFME
|
||||
* \brief Split Face Make Edge (SFME)
|
||||
*
|
||||
* SPLIT FACE MAKE EDGE:
|
||||
* Takes as input two vertices in a single face. An edge is created which divides the original face
|
||||
* into two distinct regions. One of the regions is assigned to the original face and it is closed off.
|
||||
* The second region has a new face assigned to it.
|
||||
*
|
||||
* Takes as input two vertices in a single face. An edge is created which divides the original face
|
||||
* into two distinct regions. One of the regions is assigned to the original face and it is closed off.
|
||||
* The second region has a new face assigned to it.
|
||||
*
|
||||
* Examples:
|
||||
* \par Examples:
|
||||
*
|
||||
* Before: After:
|
||||
* ---------- ----------
|
||||
* | | | |
|
||||
* | | | f1 |
|
||||
* v1 f1 v2 v1======v2
|
||||
* | | | f2 |
|
||||
* | | | |
|
||||
* ---------- ----------
|
||||
* ---------- ----------
|
||||
* | | | |
|
||||
* | | | f1 |
|
||||
* v1 f1 v2 v1======v2
|
||||
* | | | f2 |
|
||||
* | | | |
|
||||
* ---------- ----------
|
||||
*
|
||||
* Note that the input vertices can be part of the same edge. This will
|
||||
* result in a two edged face. This is desirable for advanced construction
|
||||
* tools and particularly essential for edge bevel. Because of this it is
|
||||
* up to the caller to decide what to do with the extra edge.
|
||||
* \note the input vertices can be part of the same edge. This will
|
||||
* result in a two edged face. This is desirable for advanced construction
|
||||
* tools and particularly essential for edge bevel. Because of this it is
|
||||
* up to the caller to decide what to do with the extra edge.
|
||||
*
|
||||
* If holes is NULL, then both faces will lose
|
||||
* all holes from the original face. Also, you cannot split between
|
||||
* a hole vert and a boundary vert; that case is handled by higher-
|
||||
* level wrapping functions (when holes are fully implemented, anyway).
|
||||
* \note If \a holes is NULL, then both faces will lose
|
||||
* all holes from the original face. Also, you cannot split between
|
||||
* a hole vert and a boundary vert; that case is handled by higher-
|
||||
* level wrapping functions (when holes are fully implemented, anyway).
|
||||
*
|
||||
* Note that holes represents which holes goes to the new face, and of
|
||||
* course this requires removing them from the exitsing face first, since
|
||||
* you cannot have linked list links inside multiple lists.
|
||||
* \note that holes represents which holes goes to the new face, and of
|
||||
* course this requires removing them from the exitsing face first, since
|
||||
* you cannot have linked list links inside multiple lists.
|
||||
*
|
||||
* Returns -
|
||||
* A BMFace pointer
|
||||
* \return A BMFace pointer
|
||||
*/
|
||||
BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2,
|
||||
BMLoop **r_l,
|
||||
@@ -1211,20 +1205,17 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2,
|
||||
}
|
||||
|
||||
/**
|
||||
* bmesh_SEMV
|
||||
* \brief Split Edge Make Vert (SEMV)
|
||||
*
|
||||
* SPLIT EDGE MAKE VERT:
|
||||
* Takes a given edge and splits it into two, creating a new vert.
|
||||
* Takes \a e edge and splits it into two, creating a new vert.
|
||||
*
|
||||
* \par Examples:
|
||||
*
|
||||
* Before: OV---------TV
|
||||
* After: OV----NV---TV
|
||||
*
|
||||
* Returns -
|
||||
* BMVert pointer.
|
||||
* Before: OV---------TV
|
||||
* After: OV----NV---TV
|
||||
*
|
||||
* \return The newly created BMVert pointer.
|
||||
*/
|
||||
|
||||
BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e)
|
||||
{
|
||||
BMLoop *nextl;
|
||||
@@ -1385,35 +1376,33 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e)
|
||||
}
|
||||
|
||||
/**
|
||||
* bmesh_JEKV
|
||||
* \brief Join Edge Kill Vert (JEKV)
|
||||
*
|
||||
* JOIN EDGE KILL VERT:
|
||||
* Takes a an edge and pointer to one of its vertices and collapses
|
||||
* the edge on that vertex.
|
||||
* Takes an edge \a ke and pointer to one of its vertices \a kv
|
||||
* and collapses the edge on that vertex.
|
||||
*
|
||||
* Before: OE KE
|
||||
* ------- -------
|
||||
* | || |
|
||||
* OV KV TV
|
||||
* \par Examples:
|
||||
*
|
||||
* Before: OE KE
|
||||
* ------- -------
|
||||
* | || |
|
||||
* OV KV TV
|
||||
*
|
||||
*
|
||||
* After: OE
|
||||
* ---------------
|
||||
* | |
|
||||
* OV TV
|
||||
* After: OE
|
||||
* ---------------
|
||||
* | |
|
||||
* OV TV
|
||||
*
|
||||
* \par Restrictions:
|
||||
* KV is a vertex that must have a valance of exactly two. Furthermore
|
||||
* both edges in KV's disk cycle (OE and KE) must be unique (no double edges).
|
||||
*
|
||||
* Restrictions:
|
||||
* KV is a vertex that must have a valance of exactly two. Furthermore
|
||||
* both edges in KV's disk cycle (OE and KE) must be unique (no double
|
||||
* edges).
|
||||
* \return The resulting edge, NULL for failure.
|
||||
*
|
||||
* It should also be noted that this euler has the possibility of creating
|
||||
* faces with just 2 edges. It is up to the caller to decide what to do with
|
||||
* these faces.
|
||||
*
|
||||
* Returns -
|
||||
* The resulting edge, NULL for failure.
|
||||
* \note This euler has the possibility of creating
|
||||
* faces with just 2 edges. It is up to the caller to decide what to do with
|
||||
* these faces.
|
||||
*/
|
||||
BMEdge *bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv, const short check_edge_double)
|
||||
{
|
||||
@@ -1548,35 +1537,34 @@ BMEdge *bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv, const short check_edge_dou
|
||||
}
|
||||
|
||||
/**
|
||||
* bmesh_JFKE
|
||||
* \brief Join Face Kill Edge (JFKE)
|
||||
*
|
||||
* JOIN FACE KILL EDGE:
|
||||
* Takes two faces joined by a single 2-manifold edge and fuses them togather.
|
||||
* The edge shared by the faces must not be connected to any other edges which have
|
||||
* Both faces in its radial cycle
|
||||
*
|
||||
* Takes two faces joined by a single 2-manifold edge and fuses them togather.
|
||||
* The edge shared by the faces must not be connected to any other edges which have
|
||||
* Both faces in its radial cycle
|
||||
* \par Examples:
|
||||
*
|
||||
* Examples:
|
||||
* A B
|
||||
* ---------- ----------
|
||||
* | | | |
|
||||
* | f1 | | f1 |
|
||||
* v1========v2 = Ok! v1==V2==v3 == Wrong!
|
||||
* | f2 | | f2 |
|
||||
* | | | |
|
||||
* ---------- ----------
|
||||
*
|
||||
* A B
|
||||
* ---------- ----------
|
||||
* | | | |
|
||||
* | f1 | | f1 |
|
||||
* v1========v2 = Ok! v1==V2==v3 == Wrong!
|
||||
* | f2 | | f2 |
|
||||
* | | | |
|
||||
* ---------- ----------
|
||||
* In the example A, faces \a f1 and \a f2 are joined by a single edge,
|
||||
* and the euler can safely be used.
|
||||
* In example B however, \a f1 and \a f2 are joined by multiple edges and will produce an error.
|
||||
* The caller in this case should call #bmesh_jekv on the extra edges
|
||||
* before attempting to fuse \a f1 and \a f2.
|
||||
*
|
||||
* In the example A, faces f1 and f2 are joined by a single edge, and the euler can safely be used.
|
||||
* In example B however, f1 and f2 are joined by multiple edges and will produce an error. The caller
|
||||
* in this case should call bmesh_JEKV on the extra edges before attempting to fuse f1 and f2.
|
||||
* \note The order of arguments decides whether or not certain per-face attributes are present
|
||||
* in the resultant face. For instance vertex winding, material index, smooth flags, ect are inherited
|
||||
* from \a f1, not \a f2.
|
||||
*
|
||||
* Also note that the order of arguments decides whether or not certain per-face attributes are present
|
||||
* in the resultant face. For instance vertex winding, material index, smooth flags, ect are inherited
|
||||
* from f1, not f2.
|
||||
*
|
||||
* Returns -
|
||||
* A BMFace pointer
|
||||
* \return A BMFace pointer
|
||||
*/
|
||||
BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
|
||||
{
|
||||
@@ -1703,10 +1691,12 @@ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
|
||||
return f1;
|
||||
}
|
||||
|
||||
/*
|
||||
* BMESH SPLICE VERT
|
||||
/**
|
||||
* \brief Splice Vert
|
||||
*
|
||||
* merges two verts into one (v into vtarget).
|
||||
* Merges two verts into one (\a v into \a vtarget).
|
||||
*
|
||||
* \return Success
|
||||
*/
|
||||
static int bm_vert_splice(BMesh *bm, BMVert *v, BMVert *vtarget)
|
||||
{
|
||||
@@ -1740,11 +1730,13 @@ static int bm_vert_splice(BMesh *bm, BMVert *v, BMVert *vtarget)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* BMESH CUT VERT
|
||||
/**
|
||||
* \brief Cut Vert
|
||||
*
|
||||
* cut all disjoint fans that meet at a vertex, making a unique
|
||||
* vertex for each region. returns an array of all resulting
|
||||
* vertices.
|
||||
* Cut all disjoint fans that meet at a vertex, making a unique
|
||||
* vertex for each region. returns an array of all resulting vertices.
|
||||
*
|
||||
* \return Success
|
||||
*/
|
||||
static int bm_vert_cut(BMesh *bm, BMVert *v, BMVert ***vout, int *len)
|
||||
{
|
||||
@@ -1843,11 +1835,14 @@ static int bm_vert_cut(BMesh *bm, BMVert *v, BMVert ***vout, int *len)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* BMESH SPLICE EDGE
|
||||
/**
|
||||
* \brief Splice Edge
|
||||
*
|
||||
* splice two unique edges which share the same two vertices into one edge.
|
||||
* Splice two unique edges which share the same two vertices into one edge.
|
||||
*
|
||||
* edges must already have the same vertices
|
||||
* \return Success
|
||||
*
|
||||
* \note Edges must already have the same vertices.
|
||||
*/
|
||||
static int bm_edge_splice(BMesh *bm, BMEdge *e, BMEdge *etarget)
|
||||
{
|
||||
@@ -1877,13 +1872,15 @@ static int bm_edge_splice(BMesh *bm, BMEdge *e, BMEdge *etarget)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* BMESH CUT EDGE
|
||||
/**
|
||||
* \brief Cut Edge
|
||||
*
|
||||
* Cuts a single edge into two edge: the original edge and
|
||||
* a new edge that has only "cutl" in its radial.
|
||||
* a new edge that has only \a cutl in its radial.
|
||||
*
|
||||
* Does nothing if cutl is already the only loop in the
|
||||
* \return Success
|
||||
*
|
||||
* \note Does nothing if \a cutl is already the only loop in the
|
||||
* edge radial.
|
||||
*/
|
||||
static int bm_edge_cut(BMesh *bm, BMEdge *e, BMLoop *cutl)
|
||||
@@ -1918,10 +1915,12 @@ static int bm_edge_cut(BMesh *bm, BMEdge *e, BMLoop *cutl)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* BMESH UNGLUE REGION MAKE VERT
|
||||
/**
|
||||
* \brief Unglue Region Make Vert (URMV)
|
||||
*
|
||||
* Disconnects a face from its vertex fan at loop sl.
|
||||
* Disconnects a face from its vertex fan at loop \a sl
|
||||
*
|
||||
* \return The newly created BMVert
|
||||
*/
|
||||
static BMVert *bm_urmv_loop(BMesh *bm, BMLoop *sl)
|
||||
{
|
||||
@@ -1991,10 +1990,12 @@ static BMVert *bm_urmv_loop(BMesh *bm, BMLoop *sl)
|
||||
return nv;
|
||||
}
|
||||
|
||||
/*
|
||||
* BMESH UNGLUE REGION MAKE VERT
|
||||
/**
|
||||
* \brief Unglue Region Make Vert (URMV)
|
||||
*
|
||||
* Disconnects sf from the vertex fan at sv
|
||||
* Disconnects sf from the vertex fan at \a sv
|
||||
*
|
||||
* \return The newly created BMVert
|
||||
*/
|
||||
BMVert *bmesh_urmv(BMesh *bm, BMFace *sf, BMVert *sv)
|
||||
{
|
||||
|
||||
@@ -46,9 +46,9 @@
|
||||
#include "bmesh_private.h"
|
||||
|
||||
/**
|
||||
* bmesh_data_interp_from_verts
|
||||
* \brief Data, Interp From Verts
|
||||
*
|
||||
* Interpolates per-vertex data from two sources to a target.
|
||||
* Interpolates per-vertex data from two sources to a target.
|
||||
*/
|
||||
void BM_data_interp_from_verts(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v, const float fac)
|
||||
{
|
||||
@@ -85,29 +85,23 @@ void BM_data_interp_from_verts(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v, con
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* BM Data Vert Average
|
||||
/**
|
||||
* \brief Data Vert Average
|
||||
*
|
||||
* Sets all the customdata (e.g. vert, loop) associated with a vert
|
||||
* to the average of the face regions surrounding it.
|
||||
*/
|
||||
|
||||
|
||||
static void UNUSED_FUNCTION(BM_Data_Vert_Average)(BMesh *UNUSED(bm), BMFace *UNUSED(f))
|
||||
{
|
||||
// BMIter iter;
|
||||
}
|
||||
|
||||
/**
|
||||
* bmesh_data_facevert_edgeinterp
|
||||
* \brief Data Face-Vert Edge Interp
|
||||
*
|
||||
* Walks around the faces of an edge and interpolates the per-face-edge
|
||||
* data between two sources to a target.
|
||||
*
|
||||
* Returns -
|
||||
* Nothing
|
||||
* Walks around the faces of an edge and interpolates the per-face-edge
|
||||
* data between two sources to a target.
|
||||
*/
|
||||
|
||||
void BM_data_interp_face_vert_edge(BMesh *bm, BMVert *v1, BMVert *UNUSED(v2), BMVert *v, BMEdge *e1, const float fac)
|
||||
{
|
||||
void *src[2];
|
||||
@@ -146,12 +140,12 @@ void BM_data_interp_face_vert_edge(BMesh *bm, BMVert *v1, BMVert *UNUSED(v2), BM
|
||||
}
|
||||
|
||||
/**
|
||||
* BM_data_interp_from_face
|
||||
* \brief Data Interp From Face
|
||||
*
|
||||
* projects target onto source, and pulls interpolated customdata from
|
||||
* source.
|
||||
* projects target onto source, and pulls interpolated customdata from
|
||||
* source.
|
||||
*
|
||||
* \note only does loop customdata. multires is handled.
|
||||
* \note Only handles loop customdata. multires is handled.
|
||||
*/
|
||||
void BM_face_interp_from_face(BMesh *bm, BMFace *target, BMFace *source)
|
||||
{
|
||||
@@ -188,19 +182,19 @@ void BM_face_interp_from_face(BMesh *bm, BMFace *target, BMFace *source)
|
||||
BLI_array_fixedstack_free(blocks);
|
||||
}
|
||||
|
||||
/***** multires interpolation*****
|
||||
/**
|
||||
* \brief Multires Interpolation
|
||||
*
|
||||
* mdisps is a grid of displacements, ordered thus:
|
||||
*
|
||||
* v1/center----v4/next -> x
|
||||
* | |
|
||||
* | |
|
||||
* v2/prev------v3/cur
|
||||
* |
|
||||
* V
|
||||
* y
|
||||
* v1/center----v4/next -> x
|
||||
* | |
|
||||
* | |
|
||||
* v2/prev------v3/cur
|
||||
* |
|
||||
* V
|
||||
* y
|
||||
*/
|
||||
|
||||
static int compute_mdisp_quad(BMLoop *l, float v1[3], float v2[3], float v3[3], float v4[3],
|
||||
float e1[3], float e2[3])
|
||||
{
|
||||
|
||||
@@ -50,8 +50,8 @@ const char bm_iter_itype_htype_map[BM_ITYPE_MAX] = {
|
||||
BM_LOOP /* BM_LOOPS_OF_EDGE */
|
||||
};
|
||||
|
||||
/*
|
||||
* note, we have BM_vert_at_index/BM_edge_at_index/BM_face_at_index for arrays
|
||||
/**
|
||||
* \note Use #BM_vert_at_index / #BM_edge_at_index / #BM_face_at_index for mesh arrays.
|
||||
*/
|
||||
void *BM_iter_at_index(BMesh *bm, const char itype, void *data, int index)
|
||||
{
|
||||
@@ -76,13 +76,12 @@ void *BM_iter_at_index(BMesh *bm, const char itype, void *data, int index)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ITERATOR AS ARRAY
|
||||
/**
|
||||
* \brief Iterator as Array
|
||||
*
|
||||
* Sometimes its convenient to get the iterator as an array
|
||||
* to avoid multiple calls to BM_iter_at_index.
|
||||
* to avoid multiple calls to #BM_iter_at_index.
|
||||
*/
|
||||
|
||||
int BM_iter_as_array(BMesh *bm, const char type, void *data, void **array, const int len)
|
||||
{
|
||||
int i = 0;
|
||||
@@ -106,14 +105,11 @@ int BM_iter_as_array(BMesh *bm, const char type, void *data, void **array, const
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* INIT ITERATOR
|
||||
*
|
||||
* Clears the internal state of an iterator
|
||||
* For begin() callbacks.
|
||||
/**
|
||||
* \brief Init Iterator
|
||||
*
|
||||
* Clears the internal state of an iterator for begin() callbacks.
|
||||
*/
|
||||
|
||||
static void init_iterator(BMIter *iter)
|
||||
{
|
||||
iter->firstvert = iter->nextvert = NULL;
|
||||
@@ -123,17 +119,14 @@ static void init_iterator(BMIter *iter)
|
||||
iter->ldata = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Notes on iterator implementation:
|
||||
*
|
||||
* Iterators keep track of the next element
|
||||
* in a sequence. When a step() callback is
|
||||
* invoked the current value of 'next' is stored
|
||||
* to be returned later and the next variable is
|
||||
* incremented.
|
||||
* Iterators keep track of the next element in a sequence.
|
||||
* When a step() callback is invoked the current value of 'next'
|
||||
* is stored to be returned later and the next variable is incremented.
|
||||
*
|
||||
* When the end of a sequence is
|
||||
* reached, next should always equal NULL
|
||||
* When the end of a sequence is reached, next should always equal NULL
|
||||
*
|
||||
* The 'bmiter__' prefix is used because these are used in
|
||||
* bmesh_iterators_inine.c but should otherwise be seen as
|
||||
@@ -142,7 +135,6 @@ static void init_iterator(BMIter *iter)
|
||||
|
||||
/*
|
||||
* VERT OF MESH CALLBACKS
|
||||
*
|
||||
*/
|
||||
|
||||
void bmiter__vert_of_mesh_begin(BMIter *iter)
|
||||
@@ -180,7 +172,6 @@ void *bmiter__face_of_mesh_step(BMIter *iter)
|
||||
|
||||
/*
|
||||
* EDGE OF VERT CALLBACKS
|
||||
*
|
||||
*/
|
||||
|
||||
void bmiter__edge_of_vert_begin(BMIter *iter)
|
||||
@@ -206,7 +197,6 @@ void *bmiter__edge_of_vert_step(BMIter *iter)
|
||||
|
||||
/*
|
||||
* FACE OF VERT CALLBACKS
|
||||
*
|
||||
*/
|
||||
|
||||
void bmiter__face_of_vert_begin(BMIter *iter)
|
||||
@@ -347,7 +337,6 @@ void *bmiter__loops_of_loop_step(BMIter *iter)
|
||||
|
||||
/*
|
||||
* FACE OF EDGE CALLBACKS
|
||||
*
|
||||
*/
|
||||
|
||||
void bmiter__face_of_edge_begin(BMIter *iter)
|
||||
@@ -373,7 +362,6 @@ void *bmiter__face_of_edge_step(BMIter *iter)
|
||||
|
||||
/*
|
||||
* VERTS OF EDGE CALLBACKS
|
||||
*
|
||||
*/
|
||||
|
||||
void bmiter__vert_of_edge_begin(BMIter *iter)
|
||||
@@ -397,7 +385,6 @@ void *bmiter__vert_of_edge_step(BMIter *iter)
|
||||
|
||||
/*
|
||||
* VERT OF FACE CALLBACKS
|
||||
*
|
||||
*/
|
||||
|
||||
void bmiter__vert_of_face_begin(BMIter *iter)
|
||||
@@ -418,7 +405,6 @@ void *bmiter__vert_of_face_step(BMIter *iter)
|
||||
|
||||
/*
|
||||
* EDGE OF FACE CALLBACKS
|
||||
*
|
||||
*/
|
||||
|
||||
void bmiter__edge_of_face_begin(BMIter *iter)
|
||||
@@ -439,7 +425,6 @@ void *bmiter__edge_of_face_step(BMIter *iter)
|
||||
|
||||
/*
|
||||
* LOOP OF FACE CALLBACKS
|
||||
*
|
||||
*/
|
||||
|
||||
void bmiter__loop_of_face_begin(BMIter *iter)
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
* \ingroup bmesh
|
||||
*/
|
||||
|
||||
/*
|
||||
* BMESH ITERATORS
|
||||
/**
|
||||
* \brief BMesh Iterators
|
||||
*
|
||||
* The functions and structures in this file
|
||||
* provide a unified method for iterating over
|
||||
@@ -51,7 +51,8 @@
|
||||
/* these iterator over all elements of a specific
|
||||
* type in the mesh.
|
||||
*
|
||||
* be sure to keep 'bm_iter_itype_htype_map' in sync with any changes */
|
||||
* be sure to keep 'bm_iter_itype_htype_map' in sync with any changes
|
||||
*/
|
||||
typedef enum BMIterType {
|
||||
BM_VERTS_OF_MESH = 1,
|
||||
BM_EDGES_OF_MESH = 2,
|
||||
@@ -90,7 +91,7 @@ extern const char bm_iter_itype_htype_map[BM_ITYPE_MAX];
|
||||
ele = BM_iter_new(iter, bm, itype, data); \
|
||||
for (indexvar = 0; ele; indexvar++, ele = BM_iter_step(iter))
|
||||
|
||||
/*Iterator Structure*/
|
||||
/* Iterator Structure */
|
||||
typedef struct BMIter {
|
||||
BLI_mempool_iter pooliter;
|
||||
|
||||
|
||||
@@ -34,26 +34,23 @@
|
||||
/* inline here optimizes out the switch statement when called with
|
||||
* constant values (which is very common), nicer for loop-in-loop situations */
|
||||
|
||||
/*
|
||||
* BMESH ITERATOR STEP
|
||||
/**
|
||||
* \brief Iterator Step
|
||||
*
|
||||
* Calls an iterators step fucntion to return
|
||||
* the next element.
|
||||
* Calls an iterators step fucntion to return the next element.
|
||||
*/
|
||||
|
||||
BM_INLINE void *BM_iter_step(BMIter *iter)
|
||||
{
|
||||
return iter->step(iter);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* BMESH ITERATOR INIT
|
||||
/**
|
||||
* \brief Iterator Init
|
||||
*
|
||||
* Takes a bmesh iterator structure and fills
|
||||
* it with the appropriate function pointers based
|
||||
* upon its type.
|
||||
*
|
||||
*/
|
||||
BM_INLINE int BM_iter_init(BMIter *iter, BMesh *bm, const char itype, void *data)
|
||||
{
|
||||
@@ -173,8 +170,8 @@ BM_INLINE int BM_iter_init(BMIter *iter, BMesh *bm, const char itype, void *data
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* BMESH ITERATOR NEW
|
||||
/**
|
||||
* \brief Iterator New
|
||||
*
|
||||
* Takes a bmesh iterator structure and fills
|
||||
* it with the appropriate function pointers based
|
||||
|
||||
@@ -40,18 +40,6 @@
|
||||
|
||||
#include "bmesh.h"
|
||||
|
||||
|
||||
/*
|
||||
* BMESH SELECTMODE FLUSH
|
||||
*
|
||||
* Makes sure to flush selections
|
||||
* 'upwards' (ie: all verts of an edge
|
||||
* selects the edge and so on). This
|
||||
* should only be called by system and not
|
||||
* tool authors.
|
||||
*
|
||||
*/
|
||||
|
||||
static void recount_totsels(BMesh *bm)
|
||||
{
|
||||
BMIter iter;
|
||||
@@ -76,6 +64,13 @@ static void recount_totsels(BMesh *bm)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Select Mode Flush
|
||||
*
|
||||
* Makes sure to flush selections 'upwards'
|
||||
* (ie: all verts of an edge selects the edge and so on).
|
||||
* This should only be called by system and not tool authors.
|
||||
*/
|
||||
void BM_mesh_select_mode_flush(BMesh *bm)
|
||||
{
|
||||
BMEdge *e;
|
||||
@@ -243,13 +238,11 @@ void BM_mesh_select_flush(BMesh *bm)
|
||||
}
|
||||
|
||||
/**
|
||||
* BMESH SELECT VERT
|
||||
* \brief Select Vert
|
||||
*
|
||||
* Changes selection state of a single vertex
|
||||
* in a mesh
|
||||
*
|
||||
*/
|
||||
|
||||
void BM_vert_select_set(BMesh *bm, BMVert *v, int select)
|
||||
{
|
||||
/* BMIter iter; */
|
||||
@@ -273,14 +266,11 @@ void BM_vert_select_set(BMesh *bm, BMVert *v, int select)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* BMESH SELECT EDGE
|
||||
*
|
||||
* Changes selection state of a single edge
|
||||
* in a mesh.
|
||||
/**
|
||||
* \brief Select Edge
|
||||
*
|
||||
* Changes selection state of a single edge in a mesh.
|
||||
*/
|
||||
|
||||
void BM_edge_select_set(BMesh *bm, BMEdge *e, int select)
|
||||
{
|
||||
if (BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
|
||||
@@ -333,15 +323,12 @@ void BM_edge_select_set(BMesh *bm, BMEdge *e, int select)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* BMESH SELECT FACE
|
||||
/**
|
||||
* \brief Select Face
|
||||
*
|
||||
* Changes selection state of a single
|
||||
* face in a mesh.
|
||||
*
|
||||
*/
|
||||
|
||||
void BM_face_select_set(BMesh *bm, BMFace *f, int select)
|
||||
{
|
||||
BMLoop *l_iter;
|
||||
@@ -401,13 +388,12 @@ void BM_face_select_set(BMesh *bm, BMFace *f, int select)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* BMESH SELECTMODE SET
|
||||
*
|
||||
* Sets the selection mode for the bmesh
|
||||
/**
|
||||
* Select Mode Set
|
||||
*
|
||||
* Sets the selection mode for the bmesh,
|
||||
* updating the selection state.
|
||||
*/
|
||||
|
||||
void BM_select_mode_set(BMesh *bm, int selectmode)
|
||||
{
|
||||
BMVert *v;
|
||||
@@ -545,13 +531,14 @@ BMFace *BM_active_face_get(BMesh *bm, int sloppy)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Generic way to get data from an EditSelection type
|
||||
/**
|
||||
* Generic way to get data from an EditSelection type
|
||||
* These functions were written to be used by the Modifier widget
|
||||
* when in Rotate about active mode, but can be used anywhere.
|
||||
*
|
||||
* - EM_editselection_center
|
||||
* - EM_editselection_normal
|
||||
* - EM_editselection_plane
|
||||
* - #EM_editselection_center
|
||||
* - #EM_editselection_normal
|
||||
* - #EM_editselection_plane
|
||||
*/
|
||||
void BM_editselection_center(BMesh *bm, float r_center[3], BMEditSelection *ese)
|
||||
{
|
||||
|
||||
@@ -62,15 +62,14 @@ static void bm_mempool_init(BMesh *bm, const int allocsize[4])
|
||||
}
|
||||
|
||||
/**
|
||||
* BMESH MAKE MESH
|
||||
* \brief BMesh Make Mesh
|
||||
*
|
||||
* Allocates a new BMesh structure.
|
||||
* Returns -
|
||||
* Pointer to a BM
|
||||
* Allocates a new BMesh structure.
|
||||
*
|
||||
* \return The New bmesh
|
||||
*
|
||||
* \note ob is needed by multires
|
||||
*/
|
||||
|
||||
BMesh *BM_mesh_create(struct Object *ob, const int allocsize[4])
|
||||
{
|
||||
/* allocate the structure */
|
||||
@@ -89,7 +88,7 @@ BMesh *BM_mesh_create(struct Object *ob, const int allocsize[4])
|
||||
}
|
||||
|
||||
/**
|
||||
* BMESH FREE MESH
|
||||
* \brief BMesh Free Mesh Data
|
||||
*
|
||||
* Frees a BMesh structure.
|
||||
*
|
||||
@@ -158,7 +157,9 @@ void BM_mesh_data_free(BMesh *bm)
|
||||
}
|
||||
|
||||
/**
|
||||
* clear all data in bm
|
||||
* \brief BMesh Clear Mesh
|
||||
*
|
||||
* Clear all data in bm
|
||||
*/
|
||||
void BM_mesh_clear(BMesh *bm)
|
||||
{
|
||||
@@ -178,26 +179,22 @@ void BM_mesh_clear(BMesh *bm)
|
||||
bm->totflags = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* BMESH FREE MESH
|
||||
/**
|
||||
* \brief BMesh Free Mesh
|
||||
*
|
||||
* Frees a BMesh structure.
|
||||
* Frees a BMesh data and its structure.
|
||||
*/
|
||||
|
||||
void BM_mesh_free(BMesh *bm)
|
||||
{
|
||||
BM_mesh_data_free(bm);
|
||||
MEM_freeN(bm);
|
||||
}
|
||||
|
||||
/*
|
||||
* BMESH COMPUTE NORMALS
|
||||
*
|
||||
* Updates the normals of a mesh.
|
||||
* Note that this can only be called
|
||||
/**
|
||||
* \brief BMesh Compute Normals
|
||||
*
|
||||
* Updates the normals of a mesh.
|
||||
*/
|
||||
|
||||
void BM_mesh_normals_update(BMesh *bm, const short skip_hidden)
|
||||
{
|
||||
BMVert *v;
|
||||
@@ -313,13 +310,14 @@ void BM_mesh_normals_update(BMesh *bm, const short skip_hidden)
|
||||
}
|
||||
|
||||
/*
|
||||
This function ensures correct normals for the mesh, but
|
||||
sets the flag BM_ELEM_TAG in flipped faces, to allow restoration
|
||||
of original normals.
|
||||
|
||||
if undo is 0: calculate right normals
|
||||
if undo is 1: restore original normals
|
||||
* This function ensures correct normals for the mesh, but
|
||||
* sets the flag BM_ELEM_TAG in flipped faces, to allow restoration
|
||||
* of original normals.
|
||||
*
|
||||
* if undo is 0: calculate right normals
|
||||
* if undo is 1: restore original normals
|
||||
*/
|
||||
|
||||
//keep in sycn with utils.c!
|
||||
#define FACE_FLIP 8
|
||||
static void bm_rationalize_normals(BMesh *bm, int undo)
|
||||
@@ -404,12 +402,12 @@ static void bm_mdisps_space_set(BMesh *bm, int from, int to)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* BMESH BEGIN/END EDIT
|
||||
/**
|
||||
* \brief BMesh Begin Edit
|
||||
*
|
||||
* Functions for setting up a mesh for editing and cleaning up after
|
||||
* the editing operations are done. These are called by the tools/operator
|
||||
* API for each time a tool is executed.
|
||||
* Functions for setting up a mesh for editing and cleaning up after
|
||||
* the editing operations are done. These are called by the tools/operator
|
||||
* API for each time a tool is executed.
|
||||
*/
|
||||
void bmesh_edit_begin(BMesh *bm, int flag)
|
||||
{
|
||||
@@ -439,6 +437,9 @@ void bmesh_edit_begin(BMesh *bm, int flag)
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief BMesh End Edit
|
||||
*/
|
||||
void bmesh_edit_end(BMesh *bm, int flag)
|
||||
{
|
||||
/* BMO_OP_FLAG_UNTAN_MULTIRES disabled for now, see comment above in bmesh_edit_begin. */
|
||||
@@ -521,14 +522,15 @@ void BM_mesh_elem_index_ensure(BMesh *bm, const char hflag)
|
||||
}
|
||||
|
||||
|
||||
/* array checking/setting macros */
|
||||
/* currently vert/edge/loop/face index data is being abused, but we should
|
||||
* eventually be able to rely on it being valid. To this end, there are macros
|
||||
* that validate them (so blender doesnt crash), but also print errors so we can
|
||||
* fix the offending parts of the code, this way after some months we can
|
||||
* confine this code for debug mode.
|
||||
/**
|
||||
* Array checking/setting macros
|
||||
*
|
||||
* Currently vert/edge/loop/face index data is being abused, in a few areas of the code.
|
||||
*
|
||||
* To avoid correcting them afterwards, set 'bm->elem_index_dirty' however its possible
|
||||
* this flag is set incorrectly which could crash blender.
|
||||
*
|
||||
* These functions ensure its correct and are called more often in debug mode.
|
||||
*/
|
||||
|
||||
void BM_mesh_elem_index_validate(BMesh *bm, const char *location, const char *func,
|
||||
|
||||
@@ -40,24 +40,22 @@
|
||||
#include "bmesh_private.h"
|
||||
|
||||
/**
|
||||
* bmesh_dissolve_disk
|
||||
* \brief Dissolve Vert
|
||||
*
|
||||
* Turns the face region surrounding a manifold vertex into
|
||||
* A single polygon.
|
||||
* Turns the face region surrounding a manifold vertex into a single polygon.
|
||||
*
|
||||
*
|
||||
* Example:
|
||||
* \par Example:
|
||||
*
|
||||
* |=========| |=========|
|
||||
* | \ / | | |
|
||||
* Before: | V | After: | |
|
||||
* | / \ | | |
|
||||
* |=========| |=========|
|
||||
* |=========| |=========|
|
||||
* | \ / | | |
|
||||
* Before: | V | After: | |
|
||||
* | / \ | | |
|
||||
* |=========| |=========|
|
||||
*
|
||||
*
|
||||
* \note dissolves vert, in more situations then BM_disk_dissolve
|
||||
* (e.g. if the vert is part of a wire edge, etc).
|
||||
*
|
||||
*/
|
||||
int BM_vert_dissolve(BMesh *bm, BMVert *v)
|
||||
{
|
||||
@@ -98,7 +96,6 @@ int BM_vert_dissolve(BMesh *bm, BMVert *v)
|
||||
/**
|
||||
* dissolves all faces around a vert, and removes it.
|
||||
*/
|
||||
|
||||
int BM_disk_dissolve(BMesh *bm, BMVert *v)
|
||||
{
|
||||
BMFace *f, *f2;
|
||||
@@ -207,20 +204,19 @@ int BM_disk_dissolve(BMesh *bm, BMVert *v)
|
||||
}
|
||||
|
||||
/**
|
||||
* BM_faces_join_pair
|
||||
* \brief Faces Join Pair
|
||||
*
|
||||
* Joins two adjacenct faces togather.
|
||||
* Joins two adjacenct faces togather.
|
||||
*
|
||||
* Because this method calls to BM_faces_join to do its work, ff a pair
|
||||
* of faces share multiple edges, the pair of faces will be joined at
|
||||
* every edge (not just edge e). This part of the functionality might need
|
||||
* to be reconsidered.
|
||||
* Because this method calls to #BM_faces_join to do its work, if a pair
|
||||
* of faces share multiple edges, the pair of faces will be joined at
|
||||
* every edge (not just edge \a e). This part of the functionality might need
|
||||
* to be reconsidered.
|
||||
*
|
||||
* If the windings do not match the winding of the new face will follow
|
||||
* f1's winding (i.e. f2 will be reversed before the join).
|
||||
* If the windings do not match the winding of the new face will follow
|
||||
* \a f1's winding (i.e. \a f2 will be reversed before the join).
|
||||
*
|
||||
* Returns:
|
||||
* pointer to the combined face
|
||||
* \return pointer to the combined face
|
||||
*/
|
||||
|
||||
BMFace *BM_faces_join_pair(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
|
||||
@@ -265,13 +261,17 @@ BMFace *BM_faces_join_pair(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Connect Verts, Split Face
|
||||
*
|
||||
* connects two verts together, automatically (if very naively) finding the
|
||||
* face they both share (if there is one) and splittling it. use this at your
|
||||
* face they both share (if there is one) and splittling it. Use this at your
|
||||
* own risk, as it doesn't handle the many complex cases it should (like zero-area faces,
|
||||
* multiple faces, etc).
|
||||
*
|
||||
* this is really only meant for cases where you don't know before hand the face
|
||||
* the two verts belong to for splitting (e.g. the subdivision operator).
|
||||
*
|
||||
* \return The newly created edge.
|
||||
*/
|
||||
|
||||
BMEdge *BM_verts_connect(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **r_f)
|
||||
@@ -297,19 +297,23 @@ BMEdge *BM_verts_connect(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **r_f)
|
||||
}
|
||||
}
|
||||
|
||||
if (r_f) *r_f = NULL;
|
||||
if (r_f) {
|
||||
*r_f = NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Split a face along two vertices. returns the newly made face, and sets
|
||||
* the 'r_l' member to a loop in the newly created edge.
|
||||
* \brief Face Split
|
||||
*
|
||||
* \param the original face
|
||||
* \param v1,v2 vertices which define the split edge, must be different
|
||||
* Split a face along two vertices. returns the newly made face, and sets
|
||||
* the \a r_l member to a loop in the newly created edge.
|
||||
*
|
||||
* \param bm The bmesh
|
||||
* \param f the original face
|
||||
* \param v1, v2 vertices which define the split edge, must be different
|
||||
* \param r_l pointer which will receive the BMLoop for the split edge in the new face
|
||||
*
|
||||
* \param example Face used to initialize settings
|
||||
*
|
||||
* \return Pointer to the newly created face representing one side of the split
|
||||
* if the split is successful (and the original original face will be the
|
||||
@@ -366,26 +370,31 @@ BMFace *BM_face_split(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, BMLoop **r_l
|
||||
}
|
||||
|
||||
/**
|
||||
* Collapses a vertex that has only two manifold edges
|
||||
* onto a vertex it shares an edge with. Fac defines
|
||||
* the amount of interpolation for Custom Data.
|
||||
* \brief Vert Collapse Faces
|
||||
*
|
||||
* Collapses vertex \a kv that has only two manifold edges
|
||||
* onto a vertex it shares an edge with.
|
||||
* \a fac defines the amount of interpolation for Custom Data.
|
||||
*
|
||||
* \note that this is not a general edge collapse function.
|
||||
*
|
||||
* \note this function is very close to #BM_vert_collapse_edge, both collapse
|
||||
* a vertex and return a new edge. Except this takes a factor and merges
|
||||
* custom data.
|
||||
* \note this function is very close to #BM_vert_collapse_edge,
|
||||
* both collapse a vertex and return a new edge.
|
||||
* Except this takes a factor and merges custom data.
|
||||
*
|
||||
* BMESH_TODO:
|
||||
* Insert error checking for KV valance.
|
||||
*
|
||||
* \param bm The bmesh
|
||||
* \param ke The edge to collapse
|
||||
* \param kv The vertex to collapse into the edge
|
||||
* \param fac The factor along the edge
|
||||
* \param join_faces When true the faces around the vertex will be joined
|
||||
* otherwise collapse the vertex by merging the 2 edges this vert touches into one.
|
||||
* \param kill_degenerate_faces Removes faces with less than 3 verts after collapsing.
|
||||
*
|
||||
* \returns The New Edge
|
||||
*/
|
||||
|
||||
BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *ke, BMVert *kv, float fac,
|
||||
const short join_faces, const short kill_degenerate_faces)
|
||||
{
|
||||
@@ -477,12 +486,11 @@ BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *ke, BMVert *kv, float fac,
|
||||
|
||||
|
||||
/**
|
||||
* BM_vert_collapse_edge
|
||||
* \brief Vert Collapse Faces
|
||||
*
|
||||
* Collapses a vertex onto another vertex it shares an edge with.
|
||||
*
|
||||
* Returns -
|
||||
* The New Edge
|
||||
* \return The New Edge
|
||||
*/
|
||||
|
||||
BMEdge *BM_vert_collapse_edge(BMesh *bm, BMEdge *ke, BMVert *kv,
|
||||
@@ -522,16 +530,13 @@ BMEdge *BM_vert_collapse_edge(BMesh *bm, BMEdge *ke, BMVert *kv,
|
||||
#undef DO_V_INTERP
|
||||
|
||||
/**
|
||||
* BM_split_edge
|
||||
* \brief Edge Split
|
||||
*
|
||||
* Splits an edge. v should be one of the vertices in e and
|
||||
* defines the direction of the splitting operation for interpolation
|
||||
* purposes.
|
||||
* Splits an edge. \a v should be one of the vertices in \a e and defines
|
||||
* the direction of the splitting operation for interpolation purposes.
|
||||
*
|
||||
* Returns -
|
||||
* the new vert
|
||||
* \return The new vert
|
||||
*/
|
||||
|
||||
BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float percent)
|
||||
{
|
||||
BMVert *nv, *v2;
|
||||
@@ -703,19 +708,17 @@ int BM_face_validate(BMesh *bm, BMFace *face, FILE *err)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* BM Rotate Edge
|
||||
/**
|
||||
* \brief Rotate Edge
|
||||
*
|
||||
* Spins an edge topologically, either counter-clockwise or clockwise.
|
||||
* If ccw is true, the edge is spun counter-clockwise, otherwise it is
|
||||
* spun clockwise.
|
||||
* Spins an edge topologically,
|
||||
* either counter-clockwise or clockwise depending on \a ccw.
|
||||
*
|
||||
* Returns the spun edge. Note that this works by dissolving the edge
|
||||
* then re-creating it, so the returned edge won't have the same pointer
|
||||
* address as the original one.
|
||||
* \return The spun edge, NULL on error
|
||||
* (e.g., if the edge isn't surrounded by exactly two faces).
|
||||
*
|
||||
* Returns NULL on error (e.g., if the edge isn't surrounded by exactly
|
||||
* two faces).
|
||||
* \note This works by dissolving the edge then re-creating it,
|
||||
* so the returned edge won't have the same pointer address as the original one.
|
||||
*/
|
||||
BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, int ccw)
|
||||
{
|
||||
|
||||
@@ -89,12 +89,10 @@ void BMO_op_flag_disable(BMesh *UNUSED(bm), BMOperator *op, const int op_flag)
|
||||
op->flag &= ~op_flag;
|
||||
}
|
||||
|
||||
/*
|
||||
* BMESH OPSTACK PUSH
|
||||
/**
|
||||
* \brief BMESH OPSTACK PUSH
|
||||
*
|
||||
* Pushes the opstack down one level
|
||||
* and allocates a new flag layer if
|
||||
* appropriate.
|
||||
* Pushes the opstack down one level and allocates a new flag layer if appropriate.
|
||||
*/
|
||||
void BMO_push(BMesh *bm, BMOperator *UNUSED(op))
|
||||
{
|
||||
@@ -107,13 +105,12 @@ void BMO_push(BMesh *bm, BMOperator *UNUSED(op))
|
||||
bmo_flag_layer_clear(bm);
|
||||
}
|
||||
|
||||
/*
|
||||
* BMESH OPSTACK POP
|
||||
/**
|
||||
* \brief BMESH OPSTACK POP
|
||||
*
|
||||
* Pops the opstack one level
|
||||
* and frees a flag layer if appropriate
|
||||
* BMESH_TODO: investigate NOT freeing flag
|
||||
* layers.
|
||||
* Pops the opstack one level and frees a flag layer if appropriate
|
||||
*
|
||||
* BMESH_TODO: investigate NOT freeing flag layers.
|
||||
*/
|
||||
void BMO_pop(BMesh *bm)
|
||||
{
|
||||
@@ -123,11 +120,10 @@ void BMO_pop(BMesh *bm)
|
||||
bm->stackdepth--;
|
||||
}
|
||||
|
||||
/*
|
||||
* BMESH OPSTACK INIT OP
|
||||
/**
|
||||
* \brief BMESH OPSTACK INIT OP
|
||||
*
|
||||
* Initializes an operator structure
|
||||
* to a certain type
|
||||
* Initializes an operator structure to a certain type
|
||||
*/
|
||||
void BMO_op_init(BMesh *bm, BMOperator *op, const char *opname)
|
||||
{
|
||||
@@ -161,14 +157,14 @@ void BMO_op_init(BMesh *bm, BMOperator *op, const char *opname)
|
||||
BLI_memarena_use_calloc (op->arena);
|
||||
}
|
||||
|
||||
/*
|
||||
* BMESH OPSTACK EXEC OP
|
||||
/**
|
||||
* \brief BMESH OPSTACK EXEC OP
|
||||
*
|
||||
* Executes a passed in operator. This handles
|
||||
* the allocation and freeing of temporary flag
|
||||
* layers and starting/stopping the modeling
|
||||
* loop. Can be called from other operators
|
||||
* exec callbacks as well.
|
||||
* Executes a passed in operator.
|
||||
*
|
||||
* This handles the allocation and freeing of temporary flag
|
||||
* layers and starting/stopping the modeling loop.
|
||||
* Can be called from other operators exec callbacks as well.
|
||||
*/
|
||||
void BMO_op_exec(BMesh *bm, BMOperator *op)
|
||||
{
|
||||
@@ -185,11 +181,10 @@ void BMO_op_exec(BMesh *bm, BMOperator *op)
|
||||
BMO_pop(bm);
|
||||
}
|
||||
|
||||
/*
|
||||
* BMESH OPSTACK FINISH OP
|
||||
/**
|
||||
* \brief BMESH OPSTACK FINISH OP
|
||||
*
|
||||
* Does housekeeping chores related to finishing
|
||||
* up an operator.
|
||||
* Does housekeeping chores related to finishing up an operator.
|
||||
*/
|
||||
void BMO_op_finish(BMesh *bm, BMOperator *op)
|
||||
{
|
||||
@@ -213,11 +208,10 @@ void BMO_op_finish(BMesh *bm, BMOperator *op)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* BMESH OPSTACK HAS SLOT
|
||||
/**
|
||||
* \brief BMESH OPSTACK HAS SLOT
|
||||
*
|
||||
* Returns 1 if the named slot exists on the given operator,
|
||||
* otherwise returns 0.
|
||||
* \return Success if the slot if found.
|
||||
*/
|
||||
int BMO_slot_exists(BMOperator *op, const char *slotname)
|
||||
{
|
||||
@@ -225,11 +219,10 @@ int BMO_slot_exists(BMOperator *op, const char *slotname)
|
||||
return (slotcode >= 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* BMESH OPSTACK GET SLOT
|
||||
/**
|
||||
* \brief BMESH OPSTACK GET SLOT
|
||||
*
|
||||
* Returns a pointer to the slot of
|
||||
* type 'slotcode'
|
||||
* Returns a pointer to the slot of type 'slotcode'
|
||||
*/
|
||||
BMOpSlot *BMO_slot_get(BMOperator *op, const char *slotname)
|
||||
{
|
||||
@@ -242,10 +235,10 @@ BMOpSlot *BMO_slot_get(BMOperator *op, const char *slotname)
|
||||
return &(op->slots[slotcode]);
|
||||
}
|
||||
|
||||
/*
|
||||
* BMESH OPSTACK COPY SLOT
|
||||
/**
|
||||
* \brief BMESH OPSTACK COPY SLOT
|
||||
*
|
||||
* Copies data from one slot to another
|
||||
* Copies data from one slot to another.
|
||||
*/
|
||||
void BMO_slot_copy(BMOperator *source_op, BMOperator *dest_op, const char *src, const char *dst)
|
||||
{
|
||||
@@ -304,7 +297,6 @@ void BMO_slot_copy(BMOperator *source_op, BMOperator *dest_op, const char *src,
|
||||
* BMESH OPSTACK SET XXX
|
||||
*
|
||||
* Sets the value of a slot depending on it's type
|
||||
*
|
||||
*/
|
||||
|
||||
void BMO_slot_float_set(BMOperator *op, const char *slotname, const float f)
|
||||
@@ -638,13 +630,11 @@ static void *bmo_slot_buffer_alloc(BMOperator *op, const char *slotname, int len
|
||||
return slot->data.buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* BMO_ALL_TO_SLOT
|
||||
/**
|
||||
* \brief BMO_ALL_TO_SLOT
|
||||
*
|
||||
* Copies all elements of a certain type into an operator slot.
|
||||
*
|
||||
*/
|
||||
|
||||
static void BMO_slot_from_all(BMesh *bm, BMOperator *op, const char *slotname, const char htype)
|
||||
{
|
||||
BMIter elements;
|
||||
@@ -682,13 +672,12 @@ static void BMO_slot_from_all(BMesh *bm, BMOperator *op, const char *slotname, c
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* BMO_HEADERFLAG_TO_SLOT
|
||||
/**
|
||||
* \brief BMO_HEADERFLAG_TO_SLOT
|
||||
*
|
||||
* Copies elements of a certain type, which have a certain header flag set
|
||||
* into a slot for an operator.
|
||||
*/
|
||||
|
||||
void BMO_slot_from_hflag(BMesh *bm, BMOperator *op, const char *slotname,
|
||||
const char hflag, const char htype)
|
||||
{
|
||||
@@ -734,8 +723,8 @@ void BMO_slot_from_hflag(BMesh *bm, BMOperator *op, const char *slotname,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* BMO_FLAG_TO_SLOT
|
||||
/**
|
||||
* \brief BMO_FLAG_TO_SLOT
|
||||
*
|
||||
* Copies elements of a certain type, which have a certain flag set
|
||||
* into an output slot for an operator.
|
||||
@@ -785,9 +774,8 @@ void BMO_slot_from_flag(BMesh *bm, BMOperator *op, const char *slotname,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* BMO_FLAG_BUFFER
|
||||
/**
|
||||
* \brief BMO_FLAG_BUFFER
|
||||
*
|
||||
* Header Flags elements in a slots buffer, automatically
|
||||
* using the selection API where appropriate.
|
||||
@@ -816,9 +804,8 @@ void BMO_slot_buffer_hflag_enable(BMesh *bm, BMOperator *op, const char *slotnam
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* BMO_FLAG_BUFFER
|
||||
/**
|
||||
* \brief BMO_FLAG_BUFFER
|
||||
*
|
||||
* Removes flags from elements in a slots buffer, automatically
|
||||
* using the selection API where appropriate.
|
||||
@@ -866,9 +853,8 @@ int BMO_vert_edge_flags_count(BMesh *bm, BMVert *v, const short oflag)
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* BMO_FLAG_BUFFER
|
||||
/**
|
||||
* \brief BMO_FLAG_BUFFER
|
||||
*
|
||||
* Flags elements in a slots buffer
|
||||
*/
|
||||
@@ -889,9 +875,8 @@ void BMO_slot_buffer_flag_enable(BMesh *bm, BMOperator *op, const char *slotname
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* BMO_FLAG_BUFFER
|
||||
/**
|
||||
* \brief BMO_FLAG_BUFFER
|
||||
*
|
||||
* Removes flags from elements in a slots buffer
|
||||
*/
|
||||
@@ -911,19 +896,18 @@ void BMO_slot_buffer_flag_disable(BMesh *bm, BMOperator *op, const char *slotnam
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
/**
|
||||
* \brief ALLOC/FREE FLAG LAYER
|
||||
*
|
||||
* ALLOC/FREE FLAG LAYER
|
||||
* Used by operator stack to free/allocate
|
||||
* private flag data. This is allocated
|
||||
* using a mempool so the allocation/frees
|
||||
* should be quite fast.
|
||||
*
|
||||
* Used by operator stack to free/allocate
|
||||
* private flag data. This is allocated
|
||||
* using a mempool so the allocation/frees
|
||||
* should be quite fast.
|
||||
*
|
||||
* BMESH_TODO:
|
||||
* Investigate not freeing flag layers until
|
||||
* all operators have been executed. This would
|
||||
* save a lot of realloc potentially.
|
||||
* BMESH_TODO:
|
||||
* Investigate not freeing flag layers until
|
||||
* all operators have been executed. This would
|
||||
* save a lot of realloc potentially.
|
||||
*/
|
||||
static void bmo_flag_layer_alloc(BMesh *bm)
|
||||
{
|
||||
|
||||
@@ -43,14 +43,12 @@
|
||||
#include "bmesh.h"
|
||||
#include "bmesh_private.h"
|
||||
|
||||
/*
|
||||
* TEST EDGE SIDE and POINT IN TRIANGLE
|
||||
/**
|
||||
* \brief TEST EDGE SIDE and POINT IN TRIANGLE
|
||||
*
|
||||
* Point in triangle tests stolen from scanfill.c.
|
||||
* Used for tesselator
|
||||
*
|
||||
*/
|
||||
|
||||
static short testedgeside(const double v1[2], const double v2[2], const double v3[2])
|
||||
{
|
||||
/* is v3 to the right of v1 - v2 ? With exception: v3 == v1 || v3 == v2 */
|
||||
@@ -95,15 +93,13 @@ static int point_in_triangle(const double v1[2], const double v2[2], const doubl
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* COMPUTE POLY NORMAL
|
||||
/**
|
||||
* \brief COMPUTE POLY NORMAL
|
||||
*
|
||||
* Computes the normal of a planar
|
||||
* polygon See Graphics Gems for
|
||||
* computing newell normal.
|
||||
*
|
||||
*/
|
||||
|
||||
static void compute_poly_normal(float normal[3], float (*verts)[3], int nverts)
|
||||
{
|
||||
|
||||
@@ -179,15 +175,13 @@ static void compute_poly_normal(float normal[3], float (*verts)[3], int nverts)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* COMPUTE POLY CENTER
|
||||
/**
|
||||
* \brief COMPUTE POLY CENTER
|
||||
*
|
||||
* Computes the centroid and
|
||||
* area of a polygon in the X/Y
|
||||
* plane.
|
||||
*
|
||||
*/
|
||||
|
||||
static int compute_poly_center(float center[3], float *r_area, float (*verts)[3], int nverts)
|
||||
{
|
||||
int i, j;
|
||||
@@ -292,9 +286,7 @@ void BM_face_center_mean_calc(BMesh *bm, BMFace *f, float r_cent[3])
|
||||
* Projects a set polygon's vertices to
|
||||
* a plane defined by the average
|
||||
* of its edges cross products
|
||||
*
|
||||
*/
|
||||
|
||||
void compute_poly_plane(float (*verts)[3], int nverts)
|
||||
{
|
||||
|
||||
@@ -339,14 +331,13 @@ void compute_poly_plane(float (*verts)[3], int nverts)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* BM LEGAL EDGES
|
||||
/**
|
||||
* \brief BM LEGAL EDGES
|
||||
*
|
||||
* takes in a face and a list of edges, and sets to NULL any edge in
|
||||
* the list that bridges a concave region of the face or intersects
|
||||
* any of the faces's edges.
|
||||
*/
|
||||
|
||||
static void shrink_edgef(float v1[3], float v2[3], const float fac)
|
||||
{
|
||||
float mid[3];
|
||||
@@ -364,14 +355,12 @@ static void shrink_edgef(float v1[3], float v2[3], const float fac)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* POLY ROTATE PLANE
|
||||
/**
|
||||
* \brief POLY ROTATE PLANE
|
||||
*
|
||||
* Rotates a polygon so that it's
|
||||
* normal is pointing towards the mesh Z axis
|
||||
*
|
||||
*/
|
||||
|
||||
void poly_rotate_plane(const float normal[3], float (*verts)[3], const int nverts)
|
||||
{
|
||||
|
||||
@@ -393,17 +382,15 @@ void poly_rotate_plane(const float normal[3], float (*verts)[3], const int nvert
|
||||
mul_m3_v3(mat, verts[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* BMESH UPDATE FACE NORMAL
|
||||
/**
|
||||
* \brief BMESH UPDATE FACE NORMAL
|
||||
*
|
||||
* Updates the stored normal for the
|
||||
* given face. Requires that a buffer
|
||||
* of sufficient length to store projected
|
||||
* coordinates for all of the face's vertices
|
||||
* is passed in as well.
|
||||
*
|
||||
*/
|
||||
|
||||
void BM_face_normal_update(BMesh *bm, BMFace *f)
|
||||
{
|
||||
if (f->len >= 3) {
|
||||
@@ -588,12 +575,11 @@ void bmesh_face_normal_update_vertex_cos(BMesh *bm, BMFace *f, float no[3],
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* BMESH FLIP NORMAL
|
||||
/**
|
||||
* \brief Face Flip Normal
|
||||
*
|
||||
* Reverses the winding of a face.
|
||||
* Note that this updates the calculated
|
||||
* normal.
|
||||
* Reverses the winding of a face.
|
||||
* \note This updates the calculated normal.
|
||||
*/
|
||||
void BM_face_normal_flip(BMesh *bm, BMFace *f)
|
||||
{
|
||||
@@ -743,15 +729,14 @@ static int goodline(float (*projectverts)[3], BMFace *f, int v1i,
|
||||
} while ((l_iter = l_iter->next) != l_first);
|
||||
return TRUE;
|
||||
}
|
||||
/*
|
||||
* FIND EAR
|
||||
|
||||
/**
|
||||
* \brief FIND EAR
|
||||
*
|
||||
* Used by tesselator to find
|
||||
* the next triangle to 'clip off'
|
||||
* of a polygon while tesselating.
|
||||
*
|
||||
*/
|
||||
|
||||
static BMLoop *find_ear(BMesh *UNUSED(bm), BMFace *f, float (*verts)[3], const int nvert)
|
||||
{
|
||||
BMVert *v1, *v2, *v3;
|
||||
@@ -800,7 +785,7 @@ static BMLoop *find_ear(BMesh *UNUSED(bm), BMFace *f, float (*verts)[3], const i
|
||||
}
|
||||
|
||||
/**
|
||||
* BMESH TRIANGULATE FACE
|
||||
* \brief BMESH TRIANGULATE FACE
|
||||
*
|
||||
* Triangulates a face using a simple 'ear clipping' algorithm that tries to
|
||||
* favor non-skinny triangles (angles less than 90 degrees).
|
||||
|
||||
@@ -63,7 +63,7 @@ int BM_vert_in_edge(BMEdge *e, BMVert *v)
|
||||
}
|
||||
|
||||
/**
|
||||
* BMESH OTHER EDGE IN FACE SHARING A VERTEX
|
||||
* \brief BMESH OTHER EDGE IN FACE SHARING A VERTEX
|
||||
*
|
||||
* Finds the other loop that shares 'v' with 'e's loop in 'f'.
|
||||
*/
|
||||
@@ -475,6 +475,8 @@ float BM_loop_face_angle(BMesh *UNUSED(bm), BMLoop *l)
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief BMESH EDGE/FACE ANGLE
|
||||
*
|
||||
* Calculates the angle between two faces.
|
||||
* Assumes the face normals are correct.
|
||||
*
|
||||
@@ -493,9 +495,9 @@ float BM_edge_face_angle(BMesh *UNUSED(bm), BMEdge *e)
|
||||
}
|
||||
|
||||
/**
|
||||
* BMESH FACE ANGLE
|
||||
* \brief BMESH VERT/EDGE ANGLE
|
||||
*
|
||||
* Calculates the angle a verts 2 edges.
|
||||
* Calculates the angle a verts 2 edges.
|
||||
*
|
||||
* \returns the angle in radians
|
||||
*/
|
||||
@@ -541,7 +543,7 @@ BMEdge *BM_edge_exists(BMVert *v1, BMVert *v2)
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a set of vertices (varr), find out if
|
||||
* Given a set of vertices \a varr, find out if
|
||||
* all those vertices overlap an existing face.
|
||||
*
|
||||
* \note Making a face here is valid but in some cases you wont want to
|
||||
@@ -606,7 +608,7 @@ int BM_face_exists(BMesh *bm, BMVert **varr, int len, BMFace **r_existface)
|
||||
|
||||
|
||||
/**
|
||||
* Given a set of vertices and edges (varr, earr), find out if
|
||||
* Given a set of vertices and edges (\a varr, \a earr), find out if
|
||||
* all those vertices are filled in by existing faces that _only_ use those vertices.
|
||||
*
|
||||
* This is for use in cases where creating a face is possible but would result in
|
||||
@@ -615,7 +617,7 @@ int BM_face_exists(BMesh *bm, BMVert **varr, int len, BMFace **r_existface)
|
||||
* An example of how this is used: when 2 tri's are selected that share an edge,
|
||||
* pressing Fkey would make a new overlapping quad (without a check like this)
|
||||
*
|
||||
* 'earr' and 'varr' can be in any order, however they _must_ form a closed loop.
|
||||
* \a earr and \a varr can be in any order, however they _must_ form a closed loop.
|
||||
*/
|
||||
int BM_face_exists_multi(BMesh *bm, BMVert **varr, BMEdge **earr, int len)
|
||||
{
|
||||
|
||||
@@ -80,75 +80,80 @@ int bmesh_edge_swapverts(BMEdge *e, BMVert *orig, BMVert *newv)
|
||||
}
|
||||
|
||||
/**
|
||||
* BMESH CYCLES
|
||||
* \section bm_cycles BMesh Cycles
|
||||
* (this is somewhat outdate, though bits of its API are still used) - joeedh
|
||||
*
|
||||
* Cycles are circular doubly linked lists that form the basis of adjacency
|
||||
* information in the BME modeller. Full adjacency relations can be derived
|
||||
* from examining these cycles very quickly. Although each cycle is a double
|
||||
* circular linked list, each one is considered to have a 'base' or 'head',
|
||||
* and care must be taken by Euler code when modifying the contents of a cycle.
|
||||
* Cycles are circular doubly linked lists that form the basis of adjacency
|
||||
* information in the BME modeller. Full adjacency relations can be derived
|
||||
* from examining these cycles very quickly. Although each cycle is a double
|
||||
* circular linked list, each one is considered to have a 'base' or 'head',
|
||||
* and care must be taken by Euler code when modifying the contents of a cycle.
|
||||
*
|
||||
* The contents of this file are split into two parts. First there are the
|
||||
* bmesh_cycle family of functions which are generic circular double linked list
|
||||
* procedures. The second part contains higher level procedures for supporting
|
||||
* modification of specific cycle types.
|
||||
* The contents of this file are split into two parts. First there are the
|
||||
* bmesh_cycle family of functions which are generic circular double linked list
|
||||
* procedures. The second part contains higher level procedures for supporting
|
||||
* modification of specific cycle types.
|
||||
*
|
||||
* The three cycles explicitly stored in the BM data structure are as follows:
|
||||
*
|
||||
* 1: The Disk Cycle - A circle of edges around a vertex
|
||||
* Base: vertex->edge pointer.
|
||||
*
|
||||
* This cycle is the most complicated in terms of its structure. Each bmesh_Edge contains
|
||||
* two bmesh_CycleNode structures to keep track of that edge's membership in the disk cycle
|
||||
* of each of its vertices. However for any given vertex it may be the first in some edges
|
||||
* in its disk cycle and the second for others. The bmesh_disk_XXX family of functions contain
|
||||
* some nice utilities for navigating disk cycles in a way that hides this detail from the
|
||||
* tool writer.
|
||||
*
|
||||
* Note that the disk cycle is completley independent from face data. One advantage of this
|
||||
* is that wire edges are fully integrated into the topology database. Another is that the
|
||||
* the disk cycle has no problems dealing with non-manifold conditions involving faces.
|
||||
*
|
||||
* Functions relating to this cycle:
|
||||
*
|
||||
* bmesh_disk_edge_append
|
||||
* bmesh_disk_edge_remove
|
||||
* bmesh_disk_edge_next
|
||||
*
|
||||
* 2: The Radial Cycle - A circle of face edges (bmesh_Loop) around an edge
|
||||
* Base: edge->l->radial structure.
|
||||
*
|
||||
* The radial cycle is similar to the radial cycle in the radial edge data structure.*
|
||||
* Unlike the radial edge however, the radial cycle does not require a large amount of memory
|
||||
* to store non-manifold conditions since BM does not keep track of region/shell
|
||||
* information.
|
||||
*
|
||||
* Functions relating to this cycle:
|
||||
*
|
||||
* bmesh_radial_append
|
||||
* bmesh_radial_loop_remove
|
||||
* bmesh_radial_loop_next
|
||||
* bmesh_radial_face_find
|
||||
* The three cycles explicitly stored in the BM data structure are as follows:
|
||||
*
|
||||
*
|
||||
* 3: The Loop Cycle - A circle of face edges around a polygon.
|
||||
* Base: polygon->lbase.
|
||||
* 1: The Disk Cycle - A circle of edges around a vertex
|
||||
* Base: vertex->edge pointer.
|
||||
*
|
||||
* The loop cycle keeps track of a faces vertices and edges. It should be noted that the
|
||||
* direction of a loop cycle is either CW or CCW depending on the face normal, and is
|
||||
* not oriented to the faces editedges.
|
||||
* This cycle is the most complicated in terms of its structure. Each bmesh_Edge contains
|
||||
* two bmesh_CycleNode structures to keep track of that edge's membership in the disk cycle
|
||||
* of each of its vertices. However for any given vertex it may be the first in some edges
|
||||
* in its disk cycle and the second for others. The bmesh_disk_XXX family of functions contain
|
||||
* some nice utilities for navigating disk cycles in a way that hides this detail from the
|
||||
* tool writer.
|
||||
*
|
||||
* Functions relating to this cycle:
|
||||
* Note that the disk cycle is completley independent from face data. One advantage of this
|
||||
* is that wire edges are fully integrated into the topology database. Another is that the
|
||||
* the disk cycle has no problems dealing with non-manifold conditions involving faces.
|
||||
*
|
||||
* bmesh_cycle_XXX family of functions.
|
||||
* Functions relating to this cycle:
|
||||
* - #bmesh_disk_edge_append
|
||||
* - #bmesh_disk_edge_remove
|
||||
* - #bmesh_disk_edge_next
|
||||
* - #bmesh_disk_edge_prev
|
||||
* - #bmesh_disk_facevert_count
|
||||
* - #bmesh_disk_faceedge_find_first
|
||||
* - #bmesh_disk_faceedge_find_next
|
||||
*
|
||||
*
|
||||
* Note that the order of elements in all cycles except the loop cycle is undefined. This
|
||||
* leads to slightly increased seek time for deriving some adjacency relations, however the
|
||||
* advantage is that no intrinsic properties of the data structures are dependant upon the
|
||||
* cycle order and all non-manifold conditions are represented trivially.
|
||||
* 2: The Radial Cycle - A circle of face edges (bmesh_Loop) around an edge
|
||||
* Base: edge->l->radial structure.
|
||||
*
|
||||
* The radial cycle is similar to the radial cycle in the radial edge data structure.*
|
||||
* Unlike the radial edge however, the radial cycle does not require a large amount of memory
|
||||
* to store non-manifold conditions since BM does not keep track of region/shell information.
|
||||
*
|
||||
* Functions relating to this cycle:
|
||||
* - #bmesh_radial_append
|
||||
* - #bmesh_radial_loop_remove
|
||||
* - #bmesh_radial_loop_next
|
||||
* - #bmesh_radial_face_find
|
||||
* - #bmesh_radial_facevert_count
|
||||
* - #bmesh_radial_faceloop_find_first
|
||||
* - #bmesh_radial_faceloop_find_next
|
||||
* - #bmesh_radial_validate
|
||||
*
|
||||
*
|
||||
* 3: The Loop Cycle - A circle of face edges around a polygon.
|
||||
* Base: polygon->lbase.
|
||||
*
|
||||
* The loop cycle keeps track of a faces vertices and edges. It should be noted that the
|
||||
* direction of a loop cycle is either CW or CCW depending on the face normal, and is
|
||||
* not oriented to the faces editedges.
|
||||
*
|
||||
* Functions relating to this cycle:
|
||||
* - bmesh_cycle_XXX family of functions.
|
||||
*
|
||||
*
|
||||
* \note the order of elements in all cycles except the loop cycle is undefined. This
|
||||
* leads to slightly increased seek time for deriving some adjacency relations, however the
|
||||
* advantage is that no intrinsic properties of the data structures are dependant upon the
|
||||
* cycle order and all non-manifold conditions are represented trivially.
|
||||
*/
|
||||
int bmesh_disk_edge_append(BMEdge *e, BMVert *v)
|
||||
{
|
||||
@@ -286,15 +291,14 @@ int bmesh_disk_validate(int len, BMEdge *e, BMVert *v)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* BME DISK COUNT FACE VERT
|
||||
/**
|
||||
* \brief DISK COUNT FACE VERT
|
||||
*
|
||||
* Counts the number of loop users
|
||||
* for this vertex. Note that this is
|
||||
* equivalent to counting the number of
|
||||
* faces incident upon this vertex
|
||||
*/
|
||||
|
||||
int bmesh_disk_facevert_count(BMVert *v)
|
||||
{
|
||||
/* is there an edge on this vert at all */
|
||||
@@ -316,15 +320,14 @@ int bmesh_disk_facevert_count(BMVert *v)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* BME FIND FIRST FACE EDGE
|
||||
/**
|
||||
* \brief FIND FIRST FACE EDGE
|
||||
*
|
||||
* Finds the first edge in a vertices
|
||||
* Disk cycle that has one of this
|
||||
* vert's loops attached
|
||||
* to it.
|
||||
*/
|
||||
|
||||
BMEdge *bmesh_disk_faceedge_find_first(BMEdge *e, BMVert *v)
|
||||
{
|
||||
BMEdge *searchedge = NULL;
|
||||
@@ -381,8 +384,8 @@ int bmesh_radial_validate(int radlen, BMLoop *l)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* BMESH RADIAL REMOVE LOOP
|
||||
/**
|
||||
* \brief BMESH RADIAL REMOVE LOOP
|
||||
*
|
||||
* Removes a loop from an radial cycle. If edge e is non-NULL
|
||||
* it should contain the radial cycle, and it will also get
|
||||
@@ -421,8 +424,8 @@ void bmesh_radial_loop_remove(BMLoop *l, BMEdge *e)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* BME RADIAL FIND FIRST FACE VERT
|
||||
/**
|
||||
* \brief BME RADIAL FIND FIRST FACE VERT
|
||||
*
|
||||
* Finds the first loop of v around radial
|
||||
* cycle
|
||||
@@ -518,14 +521,12 @@ int bmesh_radial_face_find(BMEdge *e, BMFace *f)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* BME RADIAL COUNT FACE VERT
|
||||
/**
|
||||
* \brief RADIAL COUNT FACE VERT
|
||||
*
|
||||
* Returns the number of times a vertex appears
|
||||
* in a radial cycle
|
||||
*
|
||||
*/
|
||||
|
||||
int bmesh_radial_facevert_count(BMLoop *l, BMVert *v)
|
||||
{
|
||||
BMLoop *l_iter;
|
||||
|
||||
@@ -36,7 +36,8 @@
|
||||
|
||||
#include "bmesh_walkers_private.h"
|
||||
|
||||
/* - joeedh -
|
||||
/**
|
||||
* - joeedh -
|
||||
* design notes:
|
||||
*
|
||||
* original desing: walkers directly emulation recursive functions.
|
||||
@@ -49,8 +50,8 @@
|
||||
* using the first non-visited one. this choise is the flagged as visited using
|
||||
* the ghash. each step may push multiple new states onto the worklist at once.
|
||||
*
|
||||
* - walkers use tool flags, not header flags
|
||||
* - walkers now use ghash for storing visited elements,
|
||||
* - Walkers use tool flags, not header flags.
|
||||
* - Walkers now use ghash for storing visited elements,
|
||||
* rather then stealing flags. ghash can be rewritten
|
||||
* to be faster if necassary, in the far future :) .
|
||||
* - tools should ALWAYS have necassary error handling
|
||||
@@ -64,14 +65,13 @@ void *BMW_begin(BMWalker *walker, void *start)
|
||||
return BMW_current_state(walker) ? walker->step(walker) : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* BMW_CREATE
|
||||
/**
|
||||
* \brief Init Walker
|
||||
*
|
||||
* Allocates and returns a new mesh walker of
|
||||
* a given type. The elements visited are filtered
|
||||
* by the bitmask 'searchmask'.
|
||||
*/
|
||||
|
||||
void BMW_init(BMWalker *walker, BMesh *bm, int type,
|
||||
short mask_vert, short mask_edge, short mask_loop, short mask_face,
|
||||
int layer)
|
||||
@@ -117,12 +117,11 @@ void BMW_init(BMWalker *walker, BMesh *bm, int type,
|
||||
walker->states.first = walker->states.last = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* BMW_end
|
||||
/**
|
||||
* \brief End Walker
|
||||
*
|
||||
* Frees a walker's worklist.
|
||||
*/
|
||||
|
||||
void BMW_end(BMWalker *walker)
|
||||
{
|
||||
BLI_mempool_destroy(walker->worklist);
|
||||
@@ -130,10 +129,9 @@ void BMW_end(BMWalker *walker)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* BMW_step
|
||||
/**
|
||||
* \brief Step Walker
|
||||
*/
|
||||
|
||||
void *BMW_step(BMWalker *walker)
|
||||
{
|
||||
BMHeader *head;
|
||||
@@ -143,8 +141,8 @@ void *BMW_step(BMWalker *walker)
|
||||
return head;
|
||||
}
|
||||
|
||||
/*
|
||||
* BMW_current_depth
|
||||
/**
|
||||
* \brief Walker Current Depth
|
||||
*
|
||||
* Returns the current depth of the walker.
|
||||
*/
|
||||
@@ -154,15 +152,11 @@ int BMW_current_depth(BMWalker *walker)
|
||||
return walker->depth;
|
||||
}
|
||||
|
||||
/*
|
||||
* BMW_WALK
|
||||
/**
|
||||
* \brief Main Walking Function
|
||||
*
|
||||
* Steps a mesh walker forward by one element
|
||||
*
|
||||
* BMESH_TODO:
|
||||
* -add searchmask filtering
|
||||
*/
|
||||
|
||||
void *BMW_walk(BMWalker *walker)
|
||||
{
|
||||
void *current = NULL;
|
||||
@@ -176,14 +170,13 @@ void *BMW_walk(BMWalker *walker)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* BMW_current_state
|
||||
/**
|
||||
* \brief Current Walker State
|
||||
*
|
||||
* Returns the first state from the walker state
|
||||
* worklist. This state is the the next in the
|
||||
* worklist for processing.
|
||||
*/
|
||||
|
||||
void *BMW_current_state(BMWalker *walker)
|
||||
{
|
||||
bmesh_walkerGeneric *currentstate = walker->states.first;
|
||||
@@ -203,13 +196,12 @@ void *BMW_current_state(BMWalker *walker)
|
||||
return currentstate;
|
||||
}
|
||||
|
||||
/*
|
||||
* BMW_state_remove
|
||||
/**
|
||||
* \brief Remove Current Walker State
|
||||
*
|
||||
* Remove and free an item from the end of the walker state
|
||||
* worklist.
|
||||
*/
|
||||
|
||||
void BMW_state_remove(BMWalker *walker)
|
||||
{
|
||||
void *oldstate;
|
||||
@@ -218,8 +210,8 @@ void BMW_state_remove(BMWalker *walker)
|
||||
BLI_mempool_free(walker->worklist, oldstate);
|
||||
}
|
||||
|
||||
/*
|
||||
* BMW_newstate
|
||||
/**
|
||||
* \brief Add a new Walker State
|
||||
*
|
||||
* Allocate a new empty state and put it on the worklist.
|
||||
* A pointer to the new state is returned so that the caller
|
||||
@@ -227,7 +219,6 @@ void BMW_state_remove(BMWalker *walker)
|
||||
* at the front for depth-first walks, and at the end for
|
||||
* breadth-first walks.
|
||||
*/
|
||||
|
||||
void *BMW_state_add(BMWalker *walker)
|
||||
{
|
||||
bmesh_walkerGeneric *newstate;
|
||||
@@ -248,13 +239,12 @@ void *BMW_state_add(BMWalker *walker)
|
||||
return newstate;
|
||||
}
|
||||
|
||||
/*
|
||||
* BMW_reset
|
||||
/**
|
||||
* \brief Reset Walker
|
||||
*
|
||||
* Frees all states from the worklist, resetting the walker
|
||||
* for reuse in a new walk.
|
||||
*/
|
||||
|
||||
void BMW_reset(BMWalker *walker)
|
||||
{
|
||||
while (BMW_current_state(walker)) {
|
||||
|
||||
Reference in New Issue
Block a user