Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/bmesh')
-rw-r--r--source/blender/bmesh/intern/bmesh_construct.c97
-rw-r--r--source/blender/bmesh/intern/bmesh_construct.h92
-rw-r--r--source/blender/bmesh/intern/bmesh_core.c287
-rw-r--r--source/blender/bmesh/intern/bmesh_core.h290
-rw-r--r--source/blender/bmesh/intern/bmesh_delete.c8
-rw-r--r--source/blender/bmesh/intern/bmesh_delete.h8
-rw-r--r--source/blender/bmesh/intern/bmesh_edgeloop.c13
-rw-r--r--source/blender/bmesh/intern/bmesh_edgeloop.h17
-rw-r--r--source/blender/bmesh/intern/bmesh_error.h18
-rw-r--r--source/blender/bmesh/intern/bmesh_interp.c46
-rw-r--r--source/blender/bmesh/intern/bmesh_interp.h46
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators.c45
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators.h60
-rw-r--r--source/blender/bmesh/intern/bmesh_log.c119
-rw-r--r--source/blender/bmesh/intern/bmesh_log.h119
-rw-r--r--source/blender/bmesh/intern/bmesh_marking.c73
-rw-r--r--source/blender/bmesh/intern/bmesh_marking.h86
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.c81
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.h88
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_convert.c31
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_convert.h31
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_duplicate.c3
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_duplicate.h3
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_normals.c44
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_normals.h41
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_partial_update.c28
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_partial_update.h28
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_tessellate.c3
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_tessellate.h3
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_validate.c6
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_validate.h6
-rw-r--r--source/blender/bmesh/intern/bmesh_mods.c187
-rw-r--r--source/blender/bmesh/intern/bmesh_mods.h187
-rw-r--r--source/blender/bmesh/intern/bmesh_operator_api.h272
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.c148
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.h42
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.c186
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.h180
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon_edgenet.c16
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon_edgenet.h18
-rw-r--r--source/blender/bmesh/intern/bmesh_private.h12
-rw-r--r--source/blender/bmesh/intern/bmesh_query.c533
-rw-r--r--source/blender/bmesh/intern/bmesh_query.h526
-rw-r--r--source/blender/bmesh/intern/bmesh_query_uv.c23
-rw-r--r--source/blender/bmesh/intern/bmesh_query_uv.h23
-rw-r--r--source/blender/bmesh/intern/bmesh_structure.c60
-rw-r--r--source/blender/bmesh/intern/bmesh_structure.h60
-rw-r--r--source/blender/bmesh/intern/bmesh_walkers.c53
-rw-r--r--source/blender/bmesh/intern/bmesh_walkers.h52
-rw-r--r--source/blender/bmesh/intern/bmesh_walkers_impl.c17
-rw-r--r--source/blender/bmesh/operators/bmo_connect_pair.c11
-rw-r--r--source/blender/bmesh/operators/bmo_create.c7
-rw-r--r--source/blender/bmesh/operators/bmo_dissolve.c1
-rw-r--r--source/blender/bmesh/operators/bmo_primitive.c42
-rw-r--r--source/blender/bmesh/operators/bmo_split_edges.c1
-rw-r--r--source/blender/bmesh/operators/bmo_subdivide.c6
-rw-r--r--source/blender/bmesh/operators/bmo_subdivide_edgering.c3
-rw-r--r--source/blender/bmesh/operators/bmo_unsubdivide.c5
-rw-r--r--source/blender/bmesh/tools/bmesh_beautify.c9
-rw-r--r--source/blender/bmesh/tools/bmesh_beautify.h9
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c12
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.h12
-rw-r--r--source/blender/bmesh/tools/bmesh_bisect_plane.c7
-rw-r--r--source/blender/bmesh/tools/bmesh_bisect_plane.h5
-rw-r--r--source/blender/bmesh/tools/bmesh_boolean.cc8
-rw-r--r--source/blender/bmesh/tools/bmesh_boolean.h10
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate.h16
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate_collapse.c14
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c2
-rw-r--r--source/blender/bmesh/tools/bmesh_edgenet.c9
-rw-r--r--source/blender/bmesh/tools/bmesh_edgenet.h9
-rw-r--r--source/blender/bmesh/tools/bmesh_edgesplit.c5
-rw-r--r--source/blender/bmesh/tools/bmesh_edgesplit.h5
-rw-r--r--source/blender/bmesh/tools/bmesh_intersect.c8
-rw-r--r--source/blender/bmesh/tools/bmesh_intersect.h8
-rw-r--r--source/blender/bmesh/tools/bmesh_path.c1
-rw-r--r--source/blender/bmesh/tools/bmesh_path_uv.c1
-rw-r--r--source/blender/bmesh/tools/bmesh_region_match.c7
-rw-r--r--source/blender/bmesh/tools/bmesh_region_match.h6
-rw-r--r--source/blender/bmesh/tools/bmesh_separate.c4
-rw-r--r--source/blender/bmesh/tools/bmesh_separate.h4
-rw-r--r--source/blender/bmesh/tools/bmesh_wireframe.c6
-rw-r--r--source/blender/bmesh/tools/bmesh_wireframe.h6
83 files changed, 2371 insertions, 2303 deletions
diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c
index a10a911b06c..5a9d1ba7bc4 100644
--- a/source/blender/bmesh/intern/bmesh_construct.c
+++ b/source/blender/bmesh/intern/bmesh_construct.c
@@ -39,11 +39,6 @@
#define SELECT 1
-/**
- * Fill in a vertex array from an edge array.
- *
- * \returns false if any verts aren't found.
- */
bool BM_verts_from_edges(BMVert **vert_arr, BMEdge **edge_arr, const int len)
{
int i, i_prev = len - 1;
@@ -57,11 +52,6 @@ bool BM_verts_from_edges(BMVert **vert_arr, BMEdge **edge_arr, const int len)
return true;
}
-/**
- * Fill in an edge array from a vertex array (connected polygon loop).
- *
- * \returns false if any edges aren't found.
- */
bool BM_edges_from_verts(BMEdge **edge_arr, BMVert **vert_arr, const int len)
{
int i, i_prev = len - 1;
@@ -75,10 +65,6 @@ bool BM_edges_from_verts(BMEdge **edge_arr, BMVert **vert_arr, const int len)
return true;
}
-/**
- * Fill in an edge array from a vertex array (connected polygon loop).
- * Creating edges as-needed.
- */
void BM_edges_from_verts_ensure(BMesh *bm, BMEdge **edge_arr, BMVert **vert_arr, const int len)
{
int i, i_prev = len - 1;
@@ -93,20 +79,6 @@ void BM_edges_from_verts_ensure(BMesh *bm, BMEdge **edge_arr, BMVert **vert_arr,
static void bm_loop_attrs_copy(
BMesh *bm_src, BMesh *bm_dst, const BMLoop *l_src, BMLoop *l_dst, CustomDataMask mask_exclude);
-/**
- * \brief Make Quad/Triangle
- *
- * Creates a new quad or triangle from a list of 3 or 4 vertices.
- * If \a no_double is true, 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, its 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,
BMVert *v1,
BMVert *v2,
@@ -119,16 +91,6 @@ BMFace *BM_face_create_quad_tri(BMesh *bm,
return BM_face_create_verts(bm, vtar, v4 ? 4 : 3, f_example, create_flag, true);
}
-/**
- * \brief copies face loop data from shared adjacent faces.
- *
- * \param filter_fn: A function that filters the source loops before copying
- * (don't always want to copy all).
- *
- * \note when a matching edge is found, both loops of that edge are copied
- * this is done since the face may not be completely surrounded by faces,
- * this way: a quad with 2 connected quads on either side will still get all 4 loops updated
- */
void BM_face_copy_shared(BMesh *bm, BMFace *f, BMLoopFilterFunc filter_fn, void *user_data)
{
BMLoop *l_first;
@@ -260,20 +222,6 @@ error:
return false;
}
-/**
- * \brief Make NGon
- *
- * Makes an ngon from an unordered list of edges.
- * Verts \a v1 and \a v2 define the winding of the new face.
- *
- * \a edges are not required to be ordered, simply to form
- * a single closed loop as a whole.
- *
- * \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
- * avoids some unnecessary work.
- */
BMFace *BM_face_create_ngon(BMesh *bm,
BMVert *v1,
BMVert *v2,
@@ -294,14 +242,6 @@ BMFace *BM_face_create_ngon(BMesh *bm,
return NULL;
}
-/**
- * Create an ngon from an array of sorted verts
- *
- * Special features this has over other functions.
- * - Optionally calculate winding based on surrounding edges.
- * - Optionally create edges between vertices.
- * - Uses verts so no need to find edges (handy when you only have verts)
- */
BMFace *BM_face_create_ngon_verts(BMesh *bm,
BMVert **vert_arr,
const int len,
@@ -367,22 +307,6 @@ BMFace *BM_face_create_ngon_verts(BMesh *bm,
bm, v_winding[winding[0]], v_winding[winding[1]], edge_arr, len, f_example, create_flag);
}
-/**
- * Makes an NGon from an un-ordered set of verts
- *
- * assumes...
- * - that verts are only once in the list.
- * - that the verts have roughly planer bounds
- * - that the verts are roughly circular
- * there can be concave areas but overlapping folds from the center point will fail.
- *
- * a brief explanation of the method used
- * - find the center point
- * - find the normal of the vcloud
- * - order the verts around the face based on their angle to the normal vector at the center point.
- *
- * \note Since this is a vcloud there is no direction.
- */
void BM_verts_sort_radial_plane(BMVert **vert_arr, int len)
{
struct SortIntByFloat *vang = BLI_array_alloca(vang, len);
@@ -467,13 +391,6 @@ static void bm_face_attrs_copy(
f_dst->mat_nr = f_src->mat_nr;
}
-/* BMESH_TODO: Special handling for hide flags? */
-/* BMESH_TODO: swap src/dst args, everywhere else in bmesh does other way round */
-
-/**
- * Copies attributes, e.g. customdata, header flags, etc, from one element
- * to another of the same type.
- */
void BM_elem_attrs_copy_ex(BMesh *bm_src,
BMesh *bm_dst,
const void *ele_src_v,
@@ -481,6 +398,9 @@ void BM_elem_attrs_copy_ex(BMesh *bm_src,
const char hflag_mask,
const uint64_t cd_mask_exclude)
{
+ /* TODO: Special handling for hide flags? */
+ /* TODO: swap src/dst args, everywhere else in bmesh does other way round. */
+
const BMHeader *ele_src = ele_src_v;
BMHeader *ele_dst = ele_dst_v;
@@ -626,15 +546,6 @@ void BM_mesh_copy_init_customdata(BMesh *bm_dst, BMesh *bm_src, const BMAllocTem
CustomData_bmesh_init_pool(&bm_dst->pdata, allocsize->totface, BM_FACE);
}
-/**
- * Similar to #BM_mesh_copy_init_customdata but copies all layers ignoring
- * flags like #CD_FLAG_NOCOPY.
- *
- * \param bm_dst: BMesh whose custom-data layers will be added.
- * \param bm_src: BMesh whose custom-data layers will be copied.
- * \param htype: Specifies which custom-data layers will be initiated.
- * \param allocsize: Initialize the memory-pool before use (may be an estimate).
- */
void BM_mesh_copy_init_customdata_all_layers(BMesh *bm_dst,
BMesh *bm_src,
const char htype,
@@ -786,7 +697,6 @@ BMesh *BM_mesh_copy(BMesh *bm_old)
return bm_new;
}
-/* ME -> BM */
char BM_vert_flag_from_mflag(const char mflag)
{
return (((mflag & SELECT) ? BM_ELEM_SELECT : 0) | ((mflag & ME_HIDE) ? BM_ELEM_HIDDEN : 0));
@@ -804,7 +714,6 @@ char BM_face_flag_from_mflag(const char mflag)
((mflag & ME_SMOOTH) ? BM_ELEM_SMOOTH : 0) | ((mflag & ME_HIDE) ? BM_ELEM_HIDDEN : 0));
}
-/* BM -> ME */
char BM_vert_flag_to_mflag(BMVert *v)
{
const char hflag = v->head.hflag;
diff --git a/source/blender/bmesh/intern/bmesh_construct.h b/source/blender/bmesh/intern/bmesh_construct.h
index f2b5e2b4daa..692f3b403b5 100644
--- a/source/blender/bmesh/intern/bmesh_construct.h
+++ b/source/blender/bmesh/intern/bmesh_construct.h
@@ -25,14 +25,57 @@
struct BMAllocTemplate;
struct Mesh;
+/**
+ * Fill in a vertex array from an edge array.
+ *
+ * \returns false if any verts aren't found.
+ */
bool BM_verts_from_edges(BMVert **vert_arr, BMEdge **edge_arr, const int len);
+/**
+ * Fill in an edge array from a vertex array (connected polygon loop).
+ *
+ * \returns false if any edges aren't found.
+ */
bool BM_edges_from_verts(BMEdge **edge_arr, BMVert **vert_arr, const int len);
+/**
+ * Fill in an edge array from a vertex array (connected polygon loop).
+ * Creating edges as-needed.
+ */
void BM_edges_from_verts_ensure(BMesh *bm, BMEdge **edge_arr, BMVert **vert_arr, const int len);
-/* sort before creation */
+/**
+ * Makes an NGon from an un-ordered set of verts.
+ *
+ * Assumes:
+ * - that verts are only once in the list.
+ * - that the verts have roughly planer bounds
+ * - that the verts are roughly circular
+ *
+ * There can be concave areas but overlapping folds from the center point will fail.
+ *
+ * A brief explanation of the method used
+ * - find the center point
+ * - find the normal of the vertex-cloud
+ * - order the verts around the face based on their angle to the normal vector at the center point.
+ *
+ * \note Since this is a vertex-cloud there is no direction.
+ */
void BM_verts_sort_radial_plane(BMVert **vert_arr, int len);
+/**
+ * \brief Make Quad/Triangle
+ *
+ * Creates a new quad or triangle from a list of 3 or 4 vertices.
+ * If \a no_double is true, 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, its 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,
BMVert *v1,
BMVert *v2,
@@ -41,8 +84,32 @@ BMFace *BM_face_create_quad_tri(BMesh *bm,
const BMFace *f_example,
const eBMCreateFlag create_flag);
+/**
+ * \brief copies face loop data from shared adjacent faces.
+ *
+ * \param filter_fn: A function that filters the source loops before copying
+ * (don't always want to copy all).
+ *
+ * \note when a matching edge is found, both loops of that edge are copied
+ * this is done since the face may not be completely surrounded by faces,
+ * this way: a quad with 2 connected quads on either side will still get all 4 loops updated
+ */
void BM_face_copy_shared(BMesh *bm, BMFace *f, BMLoopFilterFunc filter_fn, void *user_data);
+/**
+ * \brief Make NGon
+ *
+ * Makes an ngon from an unordered list of edges.
+ * Verts \a v1 and \a v2 define the winding of the new face.
+ *
+ * \a edges are not required to be ordered, simply to form
+ * a single closed loop as a whole.
+ *
+ * \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
+ * avoids some unnecessary work.
+ */
BMFace *BM_face_create_ngon(BMesh *bm,
BMVert *v1,
BMVert *v2,
@@ -50,6 +117,14 @@ BMFace *BM_face_create_ngon(BMesh *bm,
const int len,
const BMFace *f_example,
const eBMCreateFlag create_flag);
+/**
+ * Create an ngon from an array of sorted verts
+ *
+ * Special features this has over other functions.
+ * - Optionally calculate winding based on surrounding edges.
+ * - Optionally create edges between vertices.
+ * - Uses verts so no need to find edges (handy when you only have verts)
+ */
BMFace *BM_face_create_ngon_verts(BMesh *bm,
BMVert **vert_arr,
const int len,
@@ -58,6 +133,10 @@ BMFace *BM_face_create_ngon_verts(BMesh *bm,
const bool calc_winding,
const bool create_edges);
+/**
+ * Copies attributes, e.g. customdata, header flags, etc, from one element
+ * to another of the same type.
+ */
void BM_elem_attrs_copy_ex(BMesh *bm_src,
BMesh *bm_dst,
const void *ele_src_v,
@@ -73,6 +152,15 @@ void BM_mesh_copy_init_customdata_from_mesh(BMesh *bm_dst,
void BM_mesh_copy_init_customdata(BMesh *bm_dst,
BMesh *bm_src,
const struct BMAllocTemplate *allocsize);
+/**
+ * Similar to #BM_mesh_copy_init_customdata but copies all layers ignoring
+ * flags like #CD_FLAG_NOCOPY.
+ *
+ * \param bm_dst: BMesh whose custom-data layers will be added.
+ * \param bm_src: BMesh whose custom-data layers will be copied.
+ * \param htype: Specifies which custom-data layers will be initiated.
+ * \param allocsize: Initialize the memory-pool before use (may be an estimate).
+ */
void BM_mesh_copy_init_customdata_all_layers(BMesh *bm_dst,
BMesh *bm_src,
const char htype,
@@ -81,7 +169,9 @@ BMesh *BM_mesh_copy(BMesh *bm_old);
char BM_face_flag_from_mflag(const char mflag);
char BM_edge_flag_from_mflag(const short mflag);
+/* ME -> BM */
char BM_vert_flag_from_mflag(const char mflag);
char BM_face_flag_to_mflag(BMFace *f);
short BM_edge_flag_to_mflag(BMEdge *e);
+/* BM -> ME */
char BM_vert_flag_to_mflag(BMVert *v);
diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c
index e72c689ddfb..1d7d10de96f 100644
--- a/source/blender/bmesh/intern/bmesh_core.c
+++ b/source/blender/bmesh/intern/bmesh_core.c
@@ -52,9 +52,6 @@
#endif
-/**
- * \brief Main function for creating a new vertex.
- */
BMVert *BM_vert_create(BMesh *bm,
const float co[3],
const BMVert *v_example,
@@ -137,13 +134,6 @@ BMVert *BM_vert_create(BMesh *bm,
return v;
}
-/**
- * \brief Main function for creating a new edge.
- *
- * \note Duplicate edges are supported by the API however users should _never_ see them.
- * so unless you need a unique edge or know the edge won't exist,
- * you should call with \a no_double = true.
- */
BMEdge *BM_edge_create(
BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *e_example, const eBMCreateFlag create_flag)
{
@@ -416,15 +406,6 @@ BLI_INLINE BMFace *bm_face_create__internal(BMesh *bm)
return f;
}
-/**
- * Main face creation function
- *
- * \param bm: The mesh
- * \param verts: A sorted array of verts size of len
- * \param edges: A sorted array of edges size of len
- * \param len: Length of the face
- * \param create_flag: Options for creating the face
- */
BMFace *BM_face_create(BMesh *bm,
BMVert **verts,
BMEdge **edges,
@@ -494,9 +475,6 @@ BMFace *BM_face_create(BMesh *bm,
return f;
}
-/**
- * Wrapper for #BM_face_create when you don't have an edge array
- */
BMFace *BM_face_create_verts(BMesh *bm,
BMVert **vert_arr,
const int len,
@@ -520,12 +498,6 @@ BMFace *BM_face_create_verts(BMesh *bm,
#ifndef NDEBUG
-/**
- * Check the element is valid.
- *
- * BMESH_TODO, when this raises an error the output is incredibly confusing.
- * need to have some nice way to print/debug what the heck's going on.
- */
int bmesh_elem_check(void *element, const char htype)
{
BMHeader *head = element;
@@ -833,10 +805,6 @@ static void bm_kill_only_loop(BMesh *bm, BMLoop *l)
BLI_mempool_free(bm->lpool, l);
}
-/**
- * kills all edges associated with \a f, along with any other faces containing
- * those edges
- */
void BM_face_edges_kill(BMesh *bm, BMFace *f)
{
BMEdge **edges = BLI_array_alloca(edges, f->len);
@@ -854,10 +822,6 @@ void BM_face_edges_kill(BMesh *bm, BMFace *f)
}
}
-/**
- * kills all verts associated with \a f, along with any other faces containing
- * those vertices
- */
void BM_face_verts_kill(BMesh *bm, BMFace *f)
{
BMVert **verts = BLI_array_alloca(verts, f->len);
@@ -875,9 +839,6 @@ void BM_face_verts_kill(BMesh *bm, BMFace *f)
}
}
-/**
- * Kills \a f and its loops.
- */
void BM_face_kill(BMesh *bm, BMFace *f)
{
#ifdef USE_BMESH_HOLES
@@ -922,10 +883,6 @@ void BM_face_kill(BMesh *bm, BMFace *f)
bm_kill_only_face(bm, f);
}
-/**
- * A version of #BM_face_kill which removes edges and verts
- * which have no remaining connected geometry.
- */
void BM_face_kill_loose(BMesh *bm, BMFace *f)
{
#ifdef USE_BMESH_HOLES
@@ -981,9 +938,6 @@ void BM_face_kill_loose(BMesh *bm, BMFace *f)
bm_kill_only_face(bm, f);
}
-/**
- * kills \a e and all faces that use it.
- */
void BM_edge_kill(BMesh *bm, BMEdge *e)
{
while (e->l) {
@@ -996,9 +950,6 @@ void BM_edge_kill(BMesh *bm, BMEdge *e)
bm_kill_only_edge(bm, e);
}
-/**
- * kills \a v and all edges that use it.
- */
void BM_vert_kill(BMesh *bm, BMVert *v)
{
while (v->e) {
@@ -1025,15 +976,6 @@ static int UNUSED_FUNCTION(bm_loop_length)(BMLoop *l)
return i;
}
-/**
- * \brief Loop Reverse
- *
- * Changes the winding order of a face from CW to CCW or vice versa.
- *
- * \param cd_loop_mdisp_offset: Cached result of `CustomData_get_offset(&bm->ldata, CD_MDISPS)`.
- * \param use_loop_mdisp_flip: When set, flip the Z-depth of the mdisp,
- * (use when flipping normals, disable when mirroring, eg: symmetrize).
- */
void bmesh_kernel_loop_reverse(BMesh *bm,
BMFace *f,
const int cd_loop_mdisp_offset,
@@ -1192,20 +1134,6 @@ static bool bm_vert_is_manifold_flagged(BMVert *v, const char api_flag)
/* Mid-level 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.
- *
- * \return The newly created combine BMFace.
- *
- * \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
- */
BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del)
{
BMFace *f, *f_new;
@@ -1422,44 +1350,6 @@ static BMFace *bm_face_create__sfme(BMesh *bm, BMFace *f_example)
return f;
}
-/**
- * \brief Split Face Make Edge (SFME)
- *
- * \warning this is a low level function, most likely you want to use #BM_face_split()
- *
- * 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.
- *
- * \par Examples:
- * <pre>
- * Before: After:
- * +--------+ +--------+
- * | | | |
- * | | | f1 |
- * v1 f1 v2 v1======v2
- * | | | f2 |
- * | | | |
- * +--------+ +--------+
- * </pre>
- *
- * \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.
- *
- * \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 existing face first, since
- * you cannot have linked list links inside multiple lists.
- *
- * \return A BMFace pointer
- */
BMFace *bmesh_kernel_split_face_make_edge(BMesh *bm,
BMFace *f,
BMLoop *l_v1,
@@ -1599,24 +1489,6 @@ BMFace *bmesh_kernel_split_face_make_edge(BMesh *bm,
return f2;
}
-/**
- * \brief Split Edge Make Vert (SEMV)
- *
- * Takes \a e edge and splits it into two, creating a new vert.
- * \a tv should be one end of \a e : the newly created edge
- * will be attached to that end and is returned in \a r_e.
- *
- * \par Examples:
- *
- * <pre>
- * E
- * Before: OV-------------TV
- * E RE
- * After: OV------NV-----TV
- * </pre>
- *
- * \return The newly created BMVert pointer.
- */
BMVert *bmesh_kernel_split_edge_make_vert(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e)
{
BMLoop *l_next;
@@ -1770,36 +1642,6 @@ BMVert *bmesh_kernel_split_edge_make_vert(BMesh *bm, BMVert *tv, BMEdge *e, BMEd
return v_new;
}
-/**
- * \brief Join Edge Kill Vert (JEKV)
- *
- * Takes an edge \a e_kill and pointer to one of its vertices \a v_kill
- * and collapses the edge on that vertex.
- *
- * \par Examples:
- *
- * <pre>
- * Before: e_old e_kill
- * +-------+-------+
- * | | |
- * v_old v_kill v_target
- *
- * After: e_old
- * +---------------+
- * | |
- * v_old v_target
- * </pre>
- *
- * \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).
- *
- * \return 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_kernel_join_edge_kill_vert(BMesh *bm,
BMEdge *e_kill,
BMVert *v_kill,
@@ -1967,24 +1809,6 @@ BMEdge *bmesh_kernel_join_edge_kill_vert(BMesh *bm,
return NULL;
}
-/**
- * \brief Join Vert Kill Edge (JVKE)
- *
- * Collapse an edge, merging surrounding data.
- *
- * Unlike #BM_vert_collapse_edge & #bmesh_kernel_join_edge_kill_vert
- * which only handle 2 valence verts,
- * this can handle any number of connected edges/faces.
- *
- * <pre>
- * Before: -> After:
- * +-+-+-+ +-+-+-+
- * | | | | | \ / |
- * +-+-+-+ +--+--+
- * | | | | | / \ |
- * +-+-+-+ +-+-+-+
- * </pre>
- */
BMVert *bmesh_kernel_join_vert_kill_edge(BMesh *bm,
BMEdge *e_kill,
BMVert *v_kill,
@@ -2068,37 +1892,6 @@ BMVert *bmesh_kernel_join_vert_kill_edge(BMesh *bm,
return v_target;
}
-/**
- * \brief Join Face Kill Edge (JFKE)
- *
- * Takes two faces joined by a single 2-manifold edge and fuses them together.
- * The edge shared by the faces must not be connected to any other edges which have
- * Both faces in its radial cycle
- *
- * \par Examples:
- * <pre>
- * A B
- * +--------+ +--------+
- * | | | |
- * | f1 | | f1 |
- * v1========v2 = Ok! v1==V2==v3 == Wrong!
- * | f2 | | f2 |
- * | | | |
- * +--------+ +--------+
- * </pre>
- *
- * 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_kernel_join_edge_kill_vert on the extra edges
- * before attempting to fuse \a f1 and \a 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,
- * etc are inherited from \a f1, not \a f2.
- *
- * \return A BMFace pointer
- */
BMFace *bmesh_kernel_join_face_kill_edge(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
{
BMLoop *l_iter, *l_f1 = NULL, *l_f2 = NULL;
@@ -2221,11 +2014,6 @@ BMFace *bmesh_kernel_join_face_kill_edge(BMesh *bm, BMFace *f1, BMFace *f2, BMEd
return f1;
}
-/**
- * Check if splicing vertices would create any double edges.
- *
- * \note assume caller will handle case where verts share an edge.
- */
bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b)
{
bool is_double = false;
@@ -2269,18 +2057,6 @@ bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b)
return is_double;
}
-/**
- * \brief Splice Vert
- *
- * Merges two verts into one
- * (\a v_src into \a v_dst, removing \a v_src).
- *
- * \return Success
- *
- * \warning This doesn't work for collapsing edges,
- * where \a v and \a vtarget are connected by an edge
- * (assert checks for this case).
- */
bool BM_vert_splice(BMesh *bm, BMVert *v_dst, BMVert *v_src)
{
BMEdge *e;
@@ -2317,17 +2093,6 @@ BLI_INLINE bool bm_edge_supports_separate(const BMEdge *e)
return (e->l && e->l->radial_next != e->l);
}
-/**
- * \brief Separate Vert
- *
- * Separates all disjoint fans that meet at a vertex, making a unique
- * vertex for each region. returns an array of all resulting vertices.
- *
- * \note this is a low level function, bm_edge_separate needs to run on edges first
- * or, the faces sharing verts must not be sharing edges for them to split at least.
- *
- * \return Success
- */
void bmesh_kernel_vert_separate(
BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, const bool copy_select)
{
@@ -2480,9 +2245,6 @@ static void bmesh_kernel_vert_separate__cleanup(BMesh *bm, LinkNode *edges_separ
} while ((edges_separate = edges_separate->next));
}
-/**
- * High level function which wraps both #bmesh_kernel_vert_separate and #bmesh_kernel_edge_separate
- */
void BM_vert_separate(BMesh *bm,
BMVert *v,
BMEdge **e_in,
@@ -2516,9 +2278,6 @@ void BM_vert_separate(BMesh *bm,
}
}
-/**
- * A version of #BM_vert_separate which takes a flag.
- */
void BM_vert_separate_hflag(BMesh *bm,
BMVert *v,
const char hflag,
@@ -2584,16 +2343,6 @@ void BM_vert_separate_tested_edges(BMesh *UNUSED(bm),
/** \} */
-/**
- * \brief Splice Edge
- *
- * Splice two unique edges which share the same two vertices into one edge.
- * (\a e_src into \a e_dst, removing e_src).
- *
- * \return Success
- *
- * \note Edges must already have the same vertices.
- */
bool BM_edge_splice(BMesh *bm, BMEdge *e_dst, BMEdge *e_src)
{
BMLoop *l;
@@ -2627,17 +2376,6 @@ bool BM_edge_splice(BMesh *bm, BMEdge *e_dst, BMEdge *e_src)
return true;
}
-/**
- * \brief Separate Edge
- *
- * Separates a single edge into two edge: the original edge and
- * a new edge that has only \a l_sep in its radial.
- *
- * \return Success
- *
- * \note Does nothing if \a l_sep is already the only loop in the
- * edge radial.
- */
void bmesh_kernel_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep, const bool copy_select)
{
BMEdge *e_new;
@@ -2673,15 +2411,6 @@ void bmesh_kernel_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep, const bool
BM_CHECK_ELEMENT(e);
}
-/**
- * \brief Un-glue Region Make Vert (URMV)
- *
- * Disconnects a face from its vertex fan at loop \a l_sep
- *
- * \return The newly created BMVert
- *
- * \note Will be a no-op and return original vertex if only two edges at that vertex.
- */
BMVert *bmesh_kernel_unglue_region_make_vert(BMesh *bm, BMLoop *l_sep)
{
BMVert *v_new = NULL;
@@ -2744,13 +2473,6 @@ BMVert *bmesh_kernel_unglue_region_make_vert(BMesh *bm, BMLoop *l_sep)
return v_new;
}
-/**
- * A version of #bmesh_kernel_unglue_region_make_vert that disconnects multiple loops at once.
- * The loops must all share the same vertex, can be in any order
- * and are all moved to use a single new vertex - which is returned.
- *
- * This function handles the details of finding fans boundaries.
- */
BMVert *bmesh_kernel_unglue_region_make_vert_multi(BMesh *bm, BMLoop **larr, int larr_len)
{
BMVert *v_sep = larr[0]->v;
@@ -2931,10 +2653,6 @@ static void bmesh_edge_vert_swap__recursive(BMEdge *e, BMVert *v_dst, BMVert *v_
} while ((l_iter = l_iter->radial_next) != l_first);
}
-/**
- * This function assumes l_sep is a part of a larger fan which has already been
- * isolated by calling #bmesh_kernel_edge_separate to segregate it radially.
- */
BMVert *bmesh_kernel_unglue_region_make_vert_multi_isolated(BMesh *bm, BMLoop *l_sep)
{
BMVert *v_new = BM_vert_create(bm, l_sep->v->co, l_sep->v, BM_CREATE_NOP);
@@ -2944,11 +2662,6 @@ BMVert *bmesh_kernel_unglue_region_make_vert_multi_isolated(BMesh *bm, BMLoop *l
return v_new;
}
-/**
- * Avoid calling this where possible,
- * low level function so both face pointers remain intact but point to swapped data.
- * \note must be from the same bmesh.
- */
void bmesh_face_swap_data(BMFace *f_a, BMFace *f_b)
{
BMLoop *l_iter, *l_first;
diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h
index 8f7580714ae..cd0e1754cd1 100644
--- a/source/blender/bmesh/intern/bmesh_core.h
+++ b/source/blender/bmesh/intern/bmesh_core.h
@@ -25,26 +25,50 @@ BMFace *BM_face_copy(
typedef enum eBMCreateFlag {
BM_CREATE_NOP = 0,
- /* faces and edges only */
+ /** Faces and edges only. */
BM_CREATE_NO_DOUBLE = (1 << 1),
- /* Skip CustomData - for all element types data,
- * use if we immediately write customdata into the element so this skips copying from 'example'
- * args or setting defaults, speeds up conversion when data is converted all at once. */
+ /**
+ * Skip custom-data - for all element types data,
+ * use if we immediately write custom-data into the element so this skips copying from 'example'
+ * arguments or setting defaults, speeds up conversion when data is converted all at once.
+ */
BM_CREATE_SKIP_CD = (1 << 2),
} eBMCreateFlag;
+/**
+ * \brief Main function for creating a new vertex.
+ */
BMVert *BM_vert_create(BMesh *bm,
const float co[3],
const BMVert *v_example,
const eBMCreateFlag create_flag);
+/**
+ * \brief Main function for creating a new edge.
+ *
+ * \note Duplicate edges are supported by the API however users should _never_ see them.
+ * so unless you need a unique edge or know the edge won't exist,
+ * you should call with \a no_double = true.
+ */
BMEdge *BM_edge_create(
BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *e_example, const eBMCreateFlag create_flag);
+/**
+ * Main face creation function
+ *
+ * \param bm: The mesh
+ * \param verts: A sorted array of verts size of len
+ * \param edges: A sorted array of edges size of len
+ * \param len: Length of the face
+ * \param create_flag: Options for creating the face
+ */
BMFace *BM_face_create(BMesh *bm,
BMVert **verts,
BMEdge **edges,
const int len,
const BMFace *f_example,
const eBMCreateFlag create_flag);
+/**
+ * Wrapper for #BM_face_create when you don't have an edge array
+ */
BMFace *BM_face_create_verts(BMesh *bm,
BMVert **vert_arr,
const int len,
@@ -52,27 +76,105 @@ BMFace *BM_face_create_verts(BMesh *bm,
const eBMCreateFlag create_flag,
const bool create_edges);
+/**
+ * Kills all edges associated with \a f, along with any other faces containing those edges.
+ */
void BM_face_edges_kill(BMesh *bm, BMFace *f);
+/**
+ * kills all verts associated with \a f, along with any other faces containing
+ * those vertices
+ */
void BM_face_verts_kill(BMesh *bm, BMFace *f);
+/**
+ * A version of #BM_face_kill which removes edges and verts
+ * which have no remaining connected geometry.
+ */
void BM_face_kill_loose(BMesh *bm, BMFace *f);
+/**
+ * Kills \a f and its loops.
+ */
void BM_face_kill(BMesh *bm, BMFace *f);
+/**
+ * Kills \a e and all faces that use it.
+ */
void BM_edge_kill(BMesh *bm, BMEdge *e);
+/**
+ * Kills \a v and all edges that use it.
+ */
void BM_vert_kill(BMesh *bm, BMVert *v);
+/**
+ * \brief Splice Edge
+ *
+ * Splice two unique edges which share the same two vertices into one edge.
+ * (\a e_src into \a e_dst, removing e_src).
+ *
+ * \return Success
+ *
+ * \note Edges must already have the same vertices.
+ */
bool BM_edge_splice(BMesh *bm, BMEdge *e_dst, BMEdge *e_src);
+/**
+ * \brief Splice Vert
+ *
+ * Merges two verts into one
+ * (\a v_src into \a v_dst, removing \a v_src).
+ *
+ * \return Success
+ *
+ * \warning This doesn't work for collapsing edges,
+ * where \a v and \a vtarget are connected by an edge
+ * (assert checks for this case).
+ */
bool BM_vert_splice(BMesh *bm, BMVert *v_dst, BMVert *v_src);
+/**
+ * Check if splicing vertices would create any double edges.
+ *
+ * \note assume caller will handle case where verts share an edge.
+ */
bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b);
+/**
+ * \brief Loop Reverse
+ *
+ * Changes the winding order of a face from CW to CCW or vice versa.
+ *
+ * \param cd_loop_mdisp_offset: Cached result of `CustomData_get_offset(&bm->ldata, CD_MDISPS)`.
+ * \param use_loop_mdisp_flip: When set, flip the Z-depth of the mdisp,
+ * (use when flipping normals, disable when mirroring, eg: symmetrize).
+ */
void bmesh_kernel_loop_reverse(BMesh *bm,
BMFace *f,
const int cd_loop_mdisp_offset,
const bool use_loop_mdisp_flip);
+/**
+ * Avoid calling this where possible,
+ * low level function so both face pointers remain intact but point to swapped data.
+ * \note must be from the same bmesh.
+ */
void bmesh_face_swap_data(BMFace *f_a, BMFace *f_b);
+/**
+ * \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.
+ *
+ * \return The newly created combine BMFace.
+ *
+ * \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
+ */
BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del);
+/**
+ * High level function which wraps both #bmesh_kernel_vert_separate and #bmesh_kernel_edge_separate
+ */
void BM_vert_separate(BMesh *bm,
BMVert *v,
BMEdge **e_in,
@@ -80,6 +182,9 @@ void BM_vert_separate(BMesh *bm,
const bool copy_select,
BMVert ***r_vout,
int *r_vout_len);
+/**
+ * A version of #BM_vert_separate which takes a flag.
+ */
void BM_vert_separate_hflag(BMesh *bm,
BMVert *v,
const char hflag,
@@ -94,10 +199,70 @@ void BM_vert_separate_tested_edges(
*
* Names are on the verbose side but these are only for low-level access.
*/
+/**
+ * \brief Separate Vert
+ *
+ * Separates all disjoint fans that meet at a vertex, making a unique
+ * vertex for each region. returns an array of all resulting vertices.
+ *
+ * \note this is a low level function, bm_edge_separate needs to run on edges first
+ * or, the faces sharing verts must not be sharing edges for them to split at least.
+ *
+ * \return Success
+ */
void bmesh_kernel_vert_separate(
BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, const bool copy_select);
+/**
+ * \brief Separate Edge
+ *
+ * Separates a single edge into two edge: the original edge and
+ * a new edge that has only \a l_sep in its radial.
+ *
+ * \return Success
+ *
+ * \note Does nothing if \a l_sep is already the only loop in the
+ * edge radial.
+ */
void bmesh_kernel_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep, const bool copy_select);
+/**
+ * \brief Split Face Make Edge (SFME)
+ *
+ * \warning this is a low level function, most likely you want to use #BM_face_split()
+ *
+ * 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.
+ *
+ * \par Examples:
+ * <pre>
+ * Before: After:
+ * +--------+ +--------+
+ * | | | |
+ * | | | f1 |
+ * v1 f1 v2 v1======v2
+ * | | | f2 |
+ * | | | |
+ * +--------+ +--------+
+ * </pre>
+ *
+ * \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.
+ *
+ * \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 existing face first, since
+ * you cannot have linked list links inside multiple lists.
+ *
+ * \return A BMFace pointer
+ */
BMFace *bmesh_kernel_split_face_make_edge(BMesh *bm,
BMFace *f,
BMLoop *l_v1,
@@ -109,7 +274,55 @@ BMFace *bmesh_kernel_split_face_make_edge(BMesh *bm,
BMEdge *example,
const bool no_double);
+/**
+ * \brief Split Edge Make Vert (SEMV)
+ *
+ * Takes \a e edge and splits it into two, creating a new vert.
+ * \a tv should be one end of \a e : the newly created edge
+ * will be attached to that end and is returned in \a r_e.
+ *
+ * \par Examples:
+ *
+ * <pre>
+ * E
+ * Before: OV-------------TV
+ * E RE
+ * After: OV------NV-----TV
+ * </pre>
+ *
+ * \return The newly created BMVert pointer.
+ */
BMVert *bmesh_kernel_split_edge_make_vert(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e);
+/**
+ * \brief Join Edge Kill Vert (JEKV)
+ *
+ * Takes an edge \a e_kill and pointer to one of its vertices \a v_kill
+ * and collapses the edge on that vertex.
+ *
+ * \par Examples:
+ *
+ * <pre>
+ * Before: e_old e_kill
+ * +-------+-------+
+ * | | |
+ * v_old v_kill v_target
+ *
+ * After: e_old
+ * +---------------+
+ * | |
+ * v_old v_target
+ * </pre>
+ *
+ * \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).
+ *
+ * \return 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_kernel_join_edge_kill_vert(BMesh *bm,
BMEdge *e_kill,
BMVert *v_kill,
@@ -117,14 +330,83 @@ BMEdge *bmesh_kernel_join_edge_kill_vert(BMesh *bm,
const bool check_edge_exists,
const bool kill_degenerate_faces,
const bool kill_duplicate_faces);
+/**
+ * \brief Join Vert Kill Edge (JVKE)
+ *
+ * Collapse an edge, merging surrounding data.
+ *
+ * Unlike #BM_vert_collapse_edge & #bmesh_kernel_join_edge_kill_vert
+ * which only handle 2 valence verts,
+ * this can handle any number of connected edges/faces.
+ *
+ * <pre>
+ * Before: -> After:
+ * +-+-+-+ +-+-+-+
+ * | | | | | \ / |
+ * +-+-+-+ +--+--+
+ * | | | | | / \ |
+ * +-+-+-+ +-+-+-+
+ * </pre>
+ */
BMVert *bmesh_kernel_join_vert_kill_edge(BMesh *bm,
BMEdge *e_kill,
BMVert *v_kill,
const bool do_del,
const bool check_edge_exists,
const bool kill_degenerate_faces);
+/**
+ * \brief Join Face Kill Edge (JFKE)
+ *
+ * Takes two faces joined by a single 2-manifold edge and fuses them together.
+ * The edge shared by the faces must not be connected to any other edges which have
+ * Both faces in its radial cycle
+ *
+ * \par Examples:
+ * <pre>
+ * A B
+ * +--------+ +--------+
+ * | | | |
+ * | f1 | | f1 |
+ * v1========v2 = Ok! v1==V2==v3 == Wrong!
+ * | f2 | | f2 |
+ * | | | |
+ * +--------+ +--------+
+ * </pre>
+ *
+ * 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_kernel_join_edge_kill_vert on the extra edges
+ * before attempting to fuse \a f1 and \a 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,
+ * etc are inherited from \a f1, not \a f2.
+ *
+ * \return A BMFace pointer
+ */
BMFace *bmesh_kernel_join_face_kill_edge(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e);
+/**
+ * \brief Un-glue Region Make Vert (URMV)
+ *
+ * Disconnects a face from its vertex fan at loop \a l_sep
+ *
+ * \return The newly created BMVert
+ *
+ * \note Will be a no-op and return original vertex if only two edges at that vertex.
+ */
BMVert *bmesh_kernel_unglue_region_make_vert(BMesh *bm, BMLoop *l_sep);
+/**
+ * A version of #bmesh_kernel_unglue_region_make_vert that disconnects multiple loops at once.
+ * The loops must all share the same vertex, can be in any order
+ * and are all moved to use a single new vertex - which is returned.
+ *
+ * This function handles the details of finding fans boundaries.
+ */
BMVert *bmesh_kernel_unglue_region_make_vert_multi(BMesh *bm, BMLoop **larr, int larr_len);
+/**
+ * This function assumes l_sep is a part of a larger fan which has already been
+ * isolated by calling #bmesh_kernel_edge_separate to segregate it radially.
+ */
BMVert *bmesh_kernel_unglue_region_make_vert_multi_isolated(BMesh *bm, BMLoop *l_sep);
diff --git a/source/blender/bmesh/intern/bmesh_delete.c b/source/blender/bmesh/intern/bmesh_delete.c
index 9f2fb1370bb..ae93795d51c 100644
--- a/source/blender/bmesh/intern/bmesh_delete.c
+++ b/source/blender/bmesh/intern/bmesh_delete.c
@@ -99,10 +99,6 @@ void BMO_mesh_delete_oflag_tagged(BMesh *bm, const short oflag, const char htype
}
}
-/**
- * \warning oflag applies to different types in some contexts,
- * not just the type being removed.
- */
void BMO_mesh_delete_oflag_context(BMesh *bm, const short oflag, const int type)
{
BMEdge *e;
@@ -275,10 +271,6 @@ void BM_mesh_delete_hflag_tagged(BMesh *bm, const char hflag, const char htype)
}
}
-/**
- * \warning oflag applies to different types in some contexts,
- * not just the type being removed.
- */
void BM_mesh_delete_hflag_context(BMesh *bm, const char hflag, const int type)
{
BMEdge *e;
diff --git a/source/blender/bmesh/intern/bmesh_delete.h b/source/blender/bmesh/intern/bmesh_delete.h
index fcbcb8a90fc..18e278a99fd 100644
--- a/source/blender/bmesh/intern/bmesh_delete.h
+++ b/source/blender/bmesh/intern/bmesh_delete.h
@@ -23,5 +23,13 @@
void BMO_mesh_delete_oflag_tagged(BMesh *bm, const short oflag, const char htype);
void BM_mesh_delete_hflag_tagged(BMesh *bm, const char hflag, const char htype);
+/**
+ * \warning oflag applies to different types in some contexts,
+ * not just the type being removed.
+ */
void BMO_mesh_delete_oflag_context(BMesh *bm, const short oflag, const int type);
+/**
+ * \warning oflag applies to different types in some contexts,
+ * not just the type being removed.
+ */
void BM_mesh_delete_hflag_context(BMesh *bm, const char hflag, const int type);
diff --git a/source/blender/bmesh/intern/bmesh_edgeloop.c b/source/blender/bmesh/intern/bmesh_edgeloop.c
index ab14ec23fad..3c79d2bce04 100644
--- a/source/blender/bmesh/intern/bmesh_edgeloop.c
+++ b/source/blender/bmesh/intern/bmesh_edgeloop.c
@@ -121,9 +121,6 @@ static bool bm_loop_build(BMEdgeLoopStore *el_store, BMVert *v_prev, BMVert *v,
return true;
}
-/**
- * \return listbase of listbases, each linking to a vertex.
- */
int BM_mesh_edgeloops_find(BMesh *bm,
ListBase *r_eloops,
bool (*test_fn)(BMEdge *, void *user_data),
@@ -506,7 +503,6 @@ void BM_mesh_edgeloops_calc_order(BMesh *UNUSED(bm), ListBase *eloops, const boo
/* -------------------------------------------------------------------- */
/* BM_edgeloop_*** functions */
-/* return new edgeloops */
BMEdgeLoopStore *BM_edgeloop_copy(BMEdgeLoopStore *el_store)
{
BMEdgeLoopStore *el_store_copy = MEM_mallocN(sizeof(*el_store), __func__);
@@ -565,9 +561,6 @@ const float *BM_edgeloop_center_get(struct BMEdgeLoopStore *el_store)
#define NODE_AS_V(n) ((BMVert *)((LinkData *)n)->data)
#define NODE_AS_CO(n) ((BMVert *)((LinkData *)n)->data)->co
-/**
- * edges are assigned to one vert -> the next.
- */
void BM_edgeloop_edges_get(struct BMEdgeLoopStore *el_store, BMEdge **e_arr)
{
LinkData *node;
@@ -653,12 +646,6 @@ bool BM_edgeloop_calc_normal(BMesh *UNUSED(bm), BMEdgeLoopStore *el_store)
return true;
}
-/**
- * For open loops that are straight lines,
- * calculating the normal as if it were a polygon is meaningless.
- *
- * Instead use an alignment vector and calculate the normal based on that.
- */
bool BM_edgeloop_calc_normal_aligned(BMesh *UNUSED(bm),
BMEdgeLoopStore *el_store,
const float no_align[3])
diff --git a/source/blender/bmesh/intern/bmesh_edgeloop.h b/source/blender/bmesh/intern/bmesh_edgeloop.h
index 34fc4c0ccc1..58b0d92fb72 100644
--- a/source/blender/bmesh/intern/bmesh_edgeloop.h
+++ b/source/blender/bmesh/intern/bmesh_edgeloop.h
@@ -28,6 +28,9 @@ struct GSet;
struct ListBase;
/* multiple edgeloops (ListBase) */
+/**
+ * \return listbase of listbases, each linking to a vertex.
+ */
int BM_mesh_edgeloops_find(BMesh *bm,
struct ListBase *r_eloops,
bool (*test_fn)(BMEdge *, void *user_data),
@@ -47,7 +50,10 @@ void BM_mesh_edgeloops_calc_normal_aligned(BMesh *bm,
const float no_align[3]);
void BM_mesh_edgeloops_calc_order(BMesh *bm, ListBase *eloops, const bool use_normals);
-/* single edgeloop */
+/**
+ * Copy a single edge-loop.
+ * \return new edge-loops.
+ */
struct BMEdgeLoopStore *BM_edgeloop_copy(struct BMEdgeLoopStore *el_store);
struct BMEdgeLoopStore *BM_edgeloop_from_verts(BMVert **v_arr,
const int v_arr_tot,
@@ -59,9 +65,18 @@ int BM_edgeloop_length_get(struct BMEdgeLoopStore *el_store);
struct ListBase *BM_edgeloop_verts_get(struct BMEdgeLoopStore *el_store);
const float *BM_edgeloop_normal_get(struct BMEdgeLoopStore *el_store);
const float *BM_edgeloop_center_get(struct BMEdgeLoopStore *el_store);
+/**
+ * Edges are assigned to one vert -> the next.
+ */
void BM_edgeloop_edges_get(struct BMEdgeLoopStore *el_store, BMEdge **e_arr);
void BM_edgeloop_calc_center(BMesh *bm, struct BMEdgeLoopStore *el_store);
bool BM_edgeloop_calc_normal(BMesh *bm, struct BMEdgeLoopStore *el_store);
+/**
+ * For open loops that are straight lines,
+ * calculating the normal as if it were a polygon is meaningless.
+ *
+ * Instead use an alignment vector and calculate the normal based on that.
+ */
bool BM_edgeloop_calc_normal_aligned(BMesh *bm,
struct BMEdgeLoopStore *el_store,
const float no_align[3]);
diff --git a/source/blender/bmesh/intern/bmesh_error.h b/source/blender/bmesh/intern/bmesh_error.h
index 7694d4dbfb6..68ec3fe3ee8 100644
--- a/source/blender/bmesh/intern/bmesh_error.h
+++ b/source/blender/bmesh/intern/bmesh_error.h
@@ -48,13 +48,17 @@ typedef enum eBMOpErrorLevel {
BMO_ERROR_FATAL = 2,
} eBMOpErrorLevel;
-/* Pushes an error onto the bmesh error stack.
- * if msg is null, then the default message for the `errcode` is used. */
+/**
+ * Pushes an error onto the bmesh error stack.
+ * if msg is null, then the default message for the `errcode` is used.
+ */
void BMO_error_raise(BMesh *bm, BMOperator *owner, eBMOpErrorLevel level, const char *msg)
ATTR_NONNULL(1, 2, 4);
-/* Gets the topmost error from the stack.
- * returns error code or 0 if no error. */
+/**
+ * Gets the topmost error from the stack.
+ * returns error code or 0 if no error.
+ */
bool BMO_error_get(BMesh *bm, const char **r_msg, BMOperator **r_op, eBMOpErrorLevel *r_level);
bool BMO_error_get_at_level(BMesh *bm,
eBMOpErrorLevel level,
@@ -83,8 +87,10 @@ void BMO_error_clear(BMesh *bm);
# define _BMESH_DUMMY_ABORT() (void)0
#endif
-/* This is meant to be higher level than BLI_assert(),
- * its enabled even when in Release mode. */
+/**
+ * This is meant to be higher level than BLI_assert(),
+ * its enabled even when in Release mode.
+ */
#define BMESH_ASSERT(a) \
(void)((!(a)) ? ((fprintf(stderr, \
"BMESH_ASSERT failed: %s, %s(), %d at \'%s\'\n", \
diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c
index 288c5fa8158..a1bcd8e6258 100644
--- a/source/blender/bmesh/intern/bmesh_interp.c
+++ b/source/blender/bmesh/intern/bmesh_interp.c
@@ -81,13 +81,6 @@ static void bm_data_interp_from_elem(CustomData *data_layer,
}
}
-/**
- * \brief Data, Interp From Verts
- *
- * Interpolates per-vertex data from two sources to \a v_dst
- *
- * \note This is an exact match to #BM_data_interp_from_edges
- */
void BM_data_interp_from_verts(
BMesh *bm, const BMVert *v_src_1, const BMVert *v_src_2, BMVert *v_dst, const float fac)
{
@@ -95,13 +88,6 @@ void BM_data_interp_from_verts(
&bm->vdata, (const BMElem *)v_src_1, (const BMElem *)v_src_2, (BMElem *)v_dst, fac);
}
-/**
- * \brief Data, Interp From Edges
- *
- * Interpolates per-edge data from two sources to \a e_dst.
- *
- * \note This is an exact match to #BM_data_interp_from_verts
- */
void BM_data_interp_from_edges(
BMesh *bm, const BMEdge *e_src_1, const BMEdge *e_src_2, BMEdge *e_dst, const float fac)
{
@@ -120,12 +106,6 @@ static void UNUSED_FUNCTION(BM_Data_Vert_Average)(BMesh *UNUSED(bm), BMFace *UNU
// BMIter iter;
}
-/**
- * \brief Data Face-Vert Edge Interp
- *
- * Walks around the faces of \a e and interpolates
- * the loop data between two sources.
- */
void BM_data_interp_face_vert_edge(BMesh *bm,
const BMVert *v_src_1,
const BMVert *UNUSED(v_src_2),
@@ -169,14 +149,6 @@ void BM_data_interp_face_vert_edge(BMesh *bm,
} while ((l_iter = l_iter->radial_next) != e->l);
}
-/**
- * \brief Data Interp From Face
- *
- * projects target onto source, and pulls interpolated customdata from
- * source.
- *
- * \note Only handles loop customdata. multires is handled.
- */
void BM_face_interp_from_face_ex(BMesh *bm,
BMFace *f_dst,
const BMFace *f_src,
@@ -570,9 +542,6 @@ void BM_loop_interp_multires_ex(BMesh *UNUSED(bm),
BLI_task_parallel_range(0, res, &data, loop_interp_multires_cb, &settings);
}
-/**
- * project the multires grid in target onto f_src's set of multires grids
- */
void BM_loop_interp_multires(BMesh *bm, BMLoop *l_dst, const BMFace *f_src)
{
const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
@@ -618,10 +587,6 @@ void BM_face_interp_multires(BMesh *bm, BMFace *f_dst, const BMFace *f_src)
}
}
-/**
- * smooths boundaries between multires grids,
- * including some borders in adjacent faces
- */
void BM_face_multires_bounds_smooth(BMesh *bm, BMFace *f)
{
const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
@@ -730,10 +695,6 @@ void BM_face_multires_bounds_smooth(BMesh *bm, BMFace *f)
}
}
-/**
- * projects a single loop, target, onto f_src for customdata interpolation. multires is handled.
- * if do_vertex is true, target's vert data will also get interpolated.
- */
void BM_loop_interp_from_face(
BMesh *bm, BMLoop *l_dst, const BMFace *f_src, const bool do_vertex, const bool do_multires)
{
@@ -1246,9 +1207,6 @@ static void bm_vert_loop_groups_data_layer_merge_weights__single(
}
}
-/**
- * Take existing custom data and merge each fan's data.
- */
void BM_vert_loop_groups_data_layer_merge(BMesh *bm, LinkNode *groups, const int layer_n)
{
const int type = bm->ldata.layers[layer_n].type;
@@ -1260,10 +1218,6 @@ void BM_vert_loop_groups_data_layer_merge(BMesh *bm, LinkNode *groups, const int
} while ((groups = groups->next));
}
-/**
- * A version of #BM_vert_loop_groups_data_layer_merge
- * that takes an array of loop-weights (aligned with #BM_LOOPS_OF_VERT iterator)
- */
void BM_vert_loop_groups_data_layer_merge_weights(BMesh *bm,
LinkNode *groups,
const int layer_n,
diff --git a/source/blender/bmesh/intern/bmesh_interp.h b/source/blender/bmesh/intern/bmesh_interp.h
index c77281bd798..d1a73509a4a 100644
--- a/source/blender/bmesh/intern/bmesh_interp.h
+++ b/source/blender/bmesh/intern/bmesh_interp.h
@@ -29,6 +29,9 @@ void BM_loop_interp_multires_ex(BMesh *bm,
const float f_dst_center[3],
const float f_src_center[3],
const int cd_loop_mdisp_offset);
+/**
+ * Project the multi-resolution grid in target onto f_src's set of multi-resolution grids.
+ */
void BM_loop_interp_multires(BMesh *bm, BMLoop *l_dst, const BMFace *f_src);
void BM_face_interp_multires_ex(BMesh *bm,
@@ -41,10 +44,30 @@ void BM_face_interp_multires(BMesh *bm, BMFace *f_dst, const BMFace *f_src);
void BM_vert_interp_from_face(BMesh *bm, BMVert *v_dst, const BMFace *f_src);
+/**
+ * \brief Data, Interpolate From Verts
+ *
+ * Interpolates per-vertex data from two sources to \a v_dst
+ *
+ * \note This is an exact match to #BM_data_interp_from_edges.
+ */
void BM_data_interp_from_verts(
BMesh *bm, const BMVert *v_src_1, const BMVert *v_src_2, BMVert *v_dst, const float fac);
+/**
+ * \brief Data, Interpolate From Edges
+ *
+ * Interpolates per-edge data from two sources to \a e_dst.
+ *
+ * \note This is an exact match to #BM_data_interp_from_verts.
+ */
void BM_data_interp_from_edges(
BMesh *bm, const BMEdge *e_src_1, const BMEdge *e_src_2, BMEdge *e_dst, const float fac);
+/**
+ * \brief Data Face-Vert Edge Interpolate
+ *
+ * Walks around the faces of \a e and interpolates
+ * the loop data between two sources.
+ */
void BM_data_interp_face_vert_edge(BMesh *bm,
const BMVert *v_src_1,
const BMVert *v_src_2,
@@ -60,6 +83,13 @@ void BM_data_layer_copy(BMesh *bm, CustomData *data, int type, int src_n, int ds
float BM_elem_float_data_get(CustomData *cd, void *element, int type);
void BM_elem_float_data_set(CustomData *cd, void *element, int type, const float val);
+/**
+ * \brief Data Interpolate From Face
+ *
+ * Projects target onto source, and pulls interpolated custom-data from source.
+ *
+ * \note Only handles loop custom-data. multi-res is handled.
+ */
void BM_face_interp_from_face_ex(BMesh *bm,
BMFace *f_dst,
const BMFace *f_src,
@@ -69,14 +99,30 @@ void BM_face_interp_from_face_ex(BMesh *bm,
float (*cos_2d)[2],
float axis_mat[3][3]);
void BM_face_interp_from_face(BMesh *bm, BMFace *f_dst, const BMFace *f_src, const bool do_vertex);
+/**
+ * Projects a single loop, target, onto f_src for custom-data interpolation.
+ * multi-resolution is handled.
+ * \param do_vertex: When true the target's vert data will also get interpolated.
+ */
void BM_loop_interp_from_face(
BMesh *bm, BMLoop *l_dst, const BMFace *f_src, const bool do_vertex, const bool do_multires);
+/**
+ * Smooths boundaries between multi-res grids,
+ * including some borders in adjacent faces.
+ */
void BM_face_multires_bounds_smooth(BMesh *bm, BMFace *f);
struct LinkNode *BM_vert_loop_groups_data_layer_create(
BMesh *bm, BMVert *v, const int layer_n, const float *loop_weights, struct MemArena *arena);
+/**
+ * Take existing custom data and merge each fan's data.
+ */
void BM_vert_loop_groups_data_layer_merge(BMesh *bm, struct LinkNode *groups, const int layer_n);
+/**
+ * A version of #BM_vert_loop_groups_data_layer_merge
+ * that takes an array of loop-weights (aligned with #BM_LOOPS_OF_VERT iterator).
+ */
void BM_vert_loop_groups_data_layer_merge_weights(BMesh *bm,
struct LinkNode *groups,
const int layer_n,
diff --git a/source/blender/bmesh/intern/bmesh_iterators.c b/source/blender/bmesh/intern/bmesh_iterators.c
index bd28022de4b..6a27e54c6a6 100644
--- a/source/blender/bmesh/intern/bmesh_iterators.c
+++ b/source/blender/bmesh/intern/bmesh_iterators.c
@@ -47,9 +47,6 @@ const char bm_iter_itype_htype_map[BM_ITYPE_MAX] = {
BM_LOOP, /* BM_LOOPS_OF_EDGE */
};
-/**
- * Utility function.
- */
int BM_iter_mesh_count(const char itype, BMesh *bm)
{
int count;
@@ -73,9 +70,6 @@ int BM_iter_mesh_count(const char itype, BMesh *bm)
return count;
}
-/**
- * \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)
{
BMIter iter;
@@ -98,12 +92,6 @@ void *BM_iter_at_index(BMesh *bm, const char itype, void *data, int index)
return val;
}
-/**
- * \brief Iterator as Array
- *
- * Sometimes its convenient to get the iterator as an array
- * to avoid multiple calls to #BM_iter_at_index.
- */
int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, const int len)
{
int i = 0;
@@ -124,11 +112,6 @@ int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, cons
return i;
}
-/**
- * \brief Operator Iterator as Array
- *
- * Sometimes its convenient to get the iterator as an array.
- */
int BMO_iter_as_array(BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
const char *slot_name,
const char restrictmask,
@@ -155,16 +138,6 @@ int BMO_iter_as_array(BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
return i;
}
-/**
- * \brief Iterator as Array
- *
- * Allocates a new array, has the advantage that you don't need to know the size ahead of time.
- *
- * Takes advantage of less common iterator usage to avoid counting twice,
- * which you might end up doing when #BM_iter_as_array is used.
- *
- * Caller needs to free the array.
- */
void *BM_iter_as_arrayN(BMesh *bm,
const char itype,
void *data,
@@ -272,9 +245,6 @@ int BM_iter_mesh_bitmap_from_filter(const char itype,
return bitmap_enabled;
}
-/**
- * Needed when we want to check faces, but return a loop aligned array.
- */
int BM_iter_mesh_bitmap_from_filter_tessface(BMesh *bm,
BLI_bitmap *bitmap,
bool (*test_fn)(BMFace *, void *user_data),
@@ -305,11 +275,6 @@ int BM_iter_mesh_bitmap_from_filter_tessface(BMesh *bm,
return bitmap_enabled;
}
-/**
- * \brief Elem Iter Flag Count
- *
- * Counts how many flagged / unflagged items are found in this element.
- */
int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, const bool value)
{
BMIter iter;
@@ -325,11 +290,6 @@ int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, cons
return count;
}
-/**
- * \brief Elem Iter Tool Flag Count
- *
- * Counts how many flagged / unflagged items are found in this element.
- */
int BMO_iter_elem_count_flag(
BMesh *bm, const char itype, void *data, const short oflag, const bool value)
{
@@ -371,11 +331,6 @@ int BMO_iter_elem_count_flag(
return count;
}
-/**
- * \brief Mesh Iter Flag Count
- *
- * Counts how many flagged / unflagged items are found in this mesh.
- */
int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const bool value)
{
BMIter iter;
diff --git a/source/blender/bmesh/intern/bmesh_iterators.h b/source/blender/bmesh/intern/bmesh_iterators.h
index ab4427e6968..12b3581b0a1 100644
--- a/source/blender/bmesh/intern/bmesh_iterators.h
+++ b/source/blender/bmesh/intern/bmesh_iterators.h
@@ -34,13 +34,6 @@
#include "BLI_compiler_attrs.h"
#include "BLI_mempool.h"
-/* Defines for passing to BM_iter_new.
- *
- * "OF" can be substituted for "around"
- * so BM_VERTS_OF_FACE means "vertices
- * around a face."
- */
-
/* these iterator over all elements of a specific
* type in the mesh.
*
@@ -75,6 +68,12 @@ typedef enum BMIterType {
/* the iterator htype for each iterator */
extern const char bm_iter_itype_htype_map[BM_ITYPE_MAX];
+/* -------------------------------------------------------------------- */
+/** \name Defines for passing to #BM_iter_new.
+ *
+ * "OF" can be substituted for "around" so #BM_VERTS_OF_FACE means "vertices* around a face."
+ * \{ */
+
#define BM_ITER_MESH(ele, iter, bm, itype) \
for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, bm, itype, NULL); ele; \
BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_step(iter))
@@ -108,6 +107,8 @@ extern const char bm_iter_itype_htype_map[BM_ITYPE_MAX];
for (BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_new(iter, NULL, itype, data), indexvar = 0; ele; \
BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BM_iter_step(iter), (indexvar)++)
+/** \} */
+
/* iterator type structs */
struct BMIter__elem_of_mesh {
BLI_mempool_iter pooliter;
@@ -184,14 +185,38 @@ typedef struct BMIter {
char itype;
} BMIter;
+/**
+ * \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) ATTR_WARN_UNUSED_RESULT;
+/**
+ * \brief Iterator as Array
+ *
+ * Sometimes its convenient to get the iterator as an array
+ * to avoid multiple calls to #BM_iter_at_index.
+ */
int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, const int len);
+/**
+ * \brief Iterator as Array
+ *
+ * Allocates a new array, has the advantage that you don't need to know the size ahead of time.
+ *
+ * Takes advantage of less common iterator usage to avoid counting twice,
+ * which you might end up doing when #BM_iter_as_array is used.
+ *
+ * Caller needs to free the array.
+ */
void *BM_iter_as_arrayN(BMesh *bm,
const char itype,
void *data,
int *r_len,
void **stack_array,
int stack_array_size) ATTR_WARN_UNUSED_RESULT;
+/**
+ * \brief Operator Iterator as Array
+ *
+ * Sometimes its convenient to get the iterator as an array.
+ */
int BMO_iter_as_array(BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
const char *slot_name,
const char restrictmask,
@@ -210,15 +235,36 @@ int BM_iter_mesh_bitmap_from_filter(const char itype,
uint *bitmap,
bool (*test_fn)(BMElem *, void *user_data),
void *user_data);
+/**
+ * Needed when we want to check faces, but return a loop aligned array.
+ */
int BM_iter_mesh_bitmap_from_filter_tessface(BMesh *bm,
uint *bitmap,
bool (*test_fn)(BMFace *, void *user_data),
void *user_data);
+/**
+ * \brief Elem Iter Flag Count
+ *
+ * Counts how many flagged / unflagged items are found in this element.
+ */
int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, const bool value);
+/**
+ * \brief Elem Iter Tool Flag Count
+ *
+ * Counts how many flagged / unflagged items are found in this element.
+ */
int BMO_iter_elem_count_flag(
BMesh *bm, const char itype, void *data, const short oflag, const bool value);
+/**
+ * Utility function.
+ */
int BM_iter_mesh_count(const char itype, BMesh *bm);
+/**
+ * \brief Mesh Iter Flag Count
+ *
+ * Counts how many flagged / unflagged items are found in this mesh.
+ */
int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const bool value);
/* private for bmesh_iterators_inline.c */
diff --git a/source/blender/bmesh/intern/bmesh_log.c b/source/blender/bmesh/intern/bmesh_log.c
index 9033e43374b..e667505caca 100644
--- a/source/blender/bmesh/intern/bmesh_log.c
+++ b/source/blender/bmesh/intern/bmesh_log.c
@@ -468,7 +468,6 @@ static void bm_log_id_ghash_release(BMLog *log, GHash *id_ghash)
/***************************** Public API *****************************/
-/* Allocate, initialize, and assign a new BMLog */
BMLog *BM_log_create(BMesh *bm)
{
BMLog *log = MEM_callocN(sizeof(*log), __func__);
@@ -506,14 +505,6 @@ void BM_log_cleanup_entry(BMLogEntry *entry)
}
}
-/* Allocate and initialize a new BMLog using existing BMLogEntries
- *
- * The 'entry' should be the last entry in the BMLog. Its prev pointer
- * will be followed back to find the first entry.
- *
- * The unused IDs field of the log will be initialized by taking all
- * keys from all GHashes in the log entry.
- */
BMLog *BM_log_from_existing_entries_create(BMesh *bm, BMLogEntry *entry)
{
BMLog *log = BM_log_create(bm);
@@ -555,7 +546,6 @@ BMLog *BM_log_from_existing_entries_create(BMesh *bm, BMLogEntry *entry)
return log;
}
-/* Free all the data in a BMLog including the log itself */
void BM_log_free(BMLog *log)
{
BMLogEntry *entry;
@@ -581,13 +571,11 @@ void BM_log_free(BMLog *log)
MEM_freeN(log);
}
-/* Get the number of log entries */
int BM_log_length(const BMLog *log)
{
return BLI_listbase_count(&log->entries);
}
-/* Apply a consistent ordering to BMesh vertices */
void BM_log_mesh_elems_reorder(BMesh *bm, BMLog *log)
{
uint *varr;
@@ -639,16 +627,6 @@ void BM_log_mesh_elems_reorder(BMesh *bm, BMLog *log)
MEM_freeN(farr);
}
-/* Start a new log entry and update the log entry list
- *
- * If the log entry list is empty, or if the current log entry is the
- * last entry, the new entry is simply appended to the end.
- *
- * Otherwise, the new entry is added after the current entry and all
- * following entries are deleted.
- *
- * In either case, the new entry is set as the current log entry.
- */
BMLogEntry *BM_log_entry_add(BMLog *log)
{
/* WARNING: this is now handled by the UndoSystem: BKE_UNDOSYS_TYPE_SCULPT
@@ -676,15 +654,6 @@ BMLogEntry *BM_log_entry_add(BMLog *log)
return entry;
}
-/* Remove an entry from the log
- *
- * Uses entry->log as the log. If the log is NULL, the entry will be
- * free'd but not removed from any list, nor shall its IDs be
- * released.
- *
- * This operation is only valid on the first and last entries in the
- * log. Deleting from the middle will assert.
- */
void BM_log_entry_drop(BMLogEntry *entry)
{
BMLog *log = entry->log;
@@ -751,9 +720,6 @@ void BM_log_entry_drop(BMLogEntry *entry)
BLI_freelinkN(&log->entries, entry);
}
-/* Undo one BMLogEntry
- *
- * Has no effect if there's nothing left to undo */
void BM_log_undo(BMesh *bm, BMLog *log)
{
BMLogEntry *entry = log->current_entry;
@@ -775,9 +741,6 @@ void BM_log_undo(BMesh *bm, BMLog *log)
}
}
-/* Redo one BMLogEntry
- *
- * Has no effect if there's nothing left to redo */
void BM_log_redo(BMesh *bm, BMLog *log)
{
BMLogEntry *entry = log->current_entry;
@@ -812,29 +775,6 @@ void BM_log_redo(BMesh *bm, BMLog *log)
}
}
-/* Log a vertex before it is modified
- *
- * Before modifying vertex coordinates, masks, or hflags, call this
- * function to log its current values. This is better than logging
- * after the coordinates have been modified, because only those
- * vertices that are modified need to have their original values
- * stored.
- *
- * Handles two separate cases:
- *
- * If the vertex was added in the current log entry, update the
- * vertex in the map of added vertices.
- *
- * If the vertex already existed prior to the current log entry, a
- * separate key/value map of modified vertices is used (using the
- * vertex's ID as the key). The values stored in that case are
- * the vertex's original state so that an undo can restore the
- * previous state.
- *
- * On undo, the current vertex state will be swapped with the stored
- * state so that a subsequent redo operation will restore the newer
- * vertex state.
- */
void BM_log_vert_before_modified(BMLog *log, BMVert *v, const int cd_vert_mask_offset)
{
BMLogEntry *entry = log->current_entry;
@@ -853,12 +793,6 @@ void BM_log_vert_before_modified(BMLog *log, BMVert *v, const int cd_vert_mask_o
}
}
-/* Log a new vertex as added to the BMesh
- *
- * The new vertex gets a unique ID assigned. It is then added to a map
- * of added vertices, with the key being its ID and the value
- * containing everything needed to reconstruct that vertex.
- */
void BM_log_vert_added(BMLog *log, BMVert *v, const int cd_vert_mask_offset)
{
BMLogVert *lv;
@@ -870,11 +804,6 @@ void BM_log_vert_added(BMLog *log, BMVert *v, const int cd_vert_mask_offset)
BLI_ghash_insert(log->current_entry->added_verts, key, lv);
}
-/* Log a face before it is modified
- *
- * This is intended to handle only header flags and we always
- * assume face has been added before
- */
void BM_log_face_modified(BMLog *log, BMFace *f)
{
BMLogFace *lf;
@@ -885,12 +814,6 @@ void BM_log_face_modified(BMLog *log, BMFace *f)
BLI_ghash_insert(log->current_entry->modified_faces, key, lf);
}
-/* Log a new face as added to the BMesh
- *
- * The new face gets a unique ID assigned. It is then added to a map
- * of added faces, with the key being its ID and the value containing
- * everything needed to reconstruct that face.
- */
void BM_log_face_added(BMLog *log, BMFace *f)
{
BMLogFace *lf;
@@ -905,22 +828,6 @@ void BM_log_face_added(BMLog *log, BMFace *f)
BLI_ghash_insert(log->current_entry->added_faces, key, lf);
}
-/* Log a vertex as removed from the BMesh
- *
- * A couple things can happen here:
- *
- * If the vertex was added as part of the current log entry, then it's
- * deleted and forgotten about entirely. Its unique ID is returned to
- * the unused pool.
- *
- * If the vertex was already part of the BMesh before the current log
- * entry, it is added to a map of deleted vertices, with the key being
- * its ID and the value containing everything needed to reconstruct
- * that vertex.
- *
- * If there's a move record for the vertex, that's used as the
- * vertices original location, then the move record is deleted.
- */
void BM_log_vert_removed(BMLog *log, BMVert *v, const int cd_vert_mask_offset)
{
BMLogEntry *entry = log->current_entry;
@@ -949,19 +856,6 @@ void BM_log_vert_removed(BMLog *log, BMVert *v, const int cd_vert_mask_offset)
}
}
-/* Log a face as removed from the BMesh
- *
- * A couple things can happen here:
- *
- * If the face was added as part of the current log entry, then it's
- * deleted and forgotten about entirely. Its unique ID is returned to
- * the unused pool.
- *
- * If the face was already part of the BMesh before the current log
- * entry, it is added to a map of deleted faces, with the key being
- * its ID and the value containing everything needed to reconstruct
- * that face.
- */
void BM_log_face_removed(BMLog *log, BMFace *f)
{
BMLogEntry *entry = log->current_entry;
@@ -983,7 +877,6 @@ void BM_log_face_removed(BMLog *log, BMFace *f)
}
}
-/* Log all vertices/faces in the BMesh as added */
void BM_log_all_added(BMesh *bm, BMLog *log)
{
const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK);
@@ -1011,7 +904,6 @@ void BM_log_all_added(BMesh *bm, BMLog *log)
}
}
-/* Log all vertices/faces in the BMesh as removed */
void BM_log_before_all_removed(BMesh *bm, BMLog *log)
{
const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK);
@@ -1030,9 +922,6 @@ void BM_log_before_all_removed(BMesh *bm, BMLog *log)
}
}
-/* Get the logged coordinates of a vertex
- *
- * Does not modify the log or the vertex */
const float *BM_log_original_vert_co(BMLog *log, BMVert *v)
{
BMLogEntry *entry = log->current_entry;
@@ -1048,9 +937,6 @@ const float *BM_log_original_vert_co(BMLog *log, BMVert *v)
return lv->co;
}
-/* Get the logged normal of a vertex
- *
- * Does not modify the log or the vertex */
const short *BM_log_original_vert_no(BMLog *log, BMVert *v)
{
BMLogEntry *entry = log->current_entry;
@@ -1066,9 +952,6 @@ const short *BM_log_original_vert_no(BMLog *log, BMVert *v)
return lv->no;
}
-/* Get the logged mask of a vertex
- *
- * Does not modify the log or the vertex */
float BM_log_original_mask(BMLog *log, BMVert *v)
{
BMLogEntry *entry = log->current_entry;
@@ -1102,13 +985,11 @@ void BM_log_original_vert_data(BMLog *log, BMVert *v, const float **r_co, const
/************************ Debugging and Testing ***********************/
-/* For internal use only (unit testing) */
BMLogEntry *BM_log_current_entry(BMLog *log)
{
return log->current_entry;
}
-/* For internal use only (unit testing) */
RangeTreeUInt *BM_log_unused_ids(BMLog *log)
{
return log->unused_ids;
diff --git a/source/blender/bmesh/intern/bmesh_log.h b/source/blender/bmesh/intern/bmesh_log.h
index 5c0ca78bddf..c6df87168ee 100644
--- a/source/blender/bmesh/intern/bmesh_log.h
+++ b/source/blender/bmesh/intern/bmesh_log.h
@@ -29,71 +29,190 @@ typedef struct BMLog BMLog;
typedef struct BMLogEntry BMLogEntry;
/* Allocate and initialize a new BMLog */
+/* Allocate, initialize, and assign a new BMLog */
BMLog *BM_log_create(BMesh *bm);
/* Allocate and initialize a new BMLog using existing BMLogEntries */
+/* Allocate and initialize a new BMLog using existing BMLogEntries
+ *
+ * The 'entry' should be the last entry in the BMLog. Its prev pointer
+ * will be followed back to find the first entry.
+ *
+ * The unused IDs field of the log will be initialized by taking all
+ * keys from all GHashes in the log entry.
+ */
BMLog *BM_log_from_existing_entries_create(BMesh *bm, BMLogEntry *entry);
/* Free all the data in a BMLog including the log itself */
+/* Free all the data in a BMLog including the log itself */
void BM_log_free(BMLog *log);
/* Get the number of log entries */
+/* Get the number of log entries */
int BM_log_length(const BMLog *log);
/* Apply a consistent ordering to BMesh vertices and faces */
+/* Apply a consistent ordering to BMesh vertices */
void BM_log_mesh_elems_reorder(BMesh *bm, BMLog *log);
/* Start a new log entry and update the log entry list */
+/* Start a new log entry and update the log entry list
+ *
+ * If the log entry list is empty, or if the current log entry is the
+ * last entry, the new entry is simply appended to the end.
+ *
+ * Otherwise, the new entry is added after the current entry and all
+ * following entries are deleted.
+ *
+ * In either case, the new entry is set as the current log entry.
+ */
BMLogEntry *BM_log_entry_add(BMLog *log);
/* Mark all used ids as unused for this node */
void BM_log_cleanup_entry(BMLogEntry *entry);
/* Remove an entry from the log */
+/* Remove an entry from the log
+ *
+ * Uses entry->log as the log. If the log is NULL, the entry will be
+ * free'd but not removed from any list, nor shall its IDs be
+ * released.
+ *
+ * This operation is only valid on the first and last entries in the
+ * log. Deleting from the middle will assert.
+ */
void BM_log_entry_drop(BMLogEntry *entry);
/* Undo one BMLogEntry */
+/* Undo one BMLogEntry
+ *
+ * Has no effect if there's nothing left to undo */
void BM_log_undo(BMesh *bm, BMLog *log);
/* Redo one BMLogEntry */
+/* Redo one BMLogEntry
+ *
+ * Has no effect if there's nothing left to redo */
void BM_log_redo(BMesh *bm, BMLog *log);
/* Log a vertex before it is modified */
+/* Log a vertex before it is modified
+ *
+ * Before modifying vertex coordinates, masks, or hflags, call this
+ * function to log its current values. This is better than logging
+ * after the coordinates have been modified, because only those
+ * vertices that are modified need to have their original values
+ * stored.
+ *
+ * Handles two separate cases:
+ *
+ * If the vertex was added in the current log entry, update the
+ * vertex in the map of added vertices.
+ *
+ * If the vertex already existed prior to the current log entry, a
+ * separate key/value map of modified vertices is used (using the
+ * vertex's ID as the key). The values stored in that case are
+ * the vertex's original state so that an undo can restore the
+ * previous state.
+ *
+ * On undo, the current vertex state will be swapped with the stored
+ * state so that a subsequent redo operation will restore the newer
+ * vertex state.
+ */
void BM_log_vert_before_modified(BMLog *log, struct BMVert *v, const int cd_vert_mask_offset);
/* Log a new vertex as added to the BMesh */
+/* Log a new vertex as added to the BMesh
+ *
+ * The new vertex gets a unique ID assigned. It is then added to a map
+ * of added vertices, with the key being its ID and the value
+ * containing everything needed to reconstruct that vertex.
+ */
void BM_log_vert_added(BMLog *log, struct BMVert *v, const int cd_vert_mask_offset);
/* Log a face before it is modified */
+/* Log a face before it is modified
+ *
+ * This is intended to handle only header flags and we always
+ * assume face has been added before
+ */
void BM_log_face_modified(BMLog *log, struct BMFace *f);
/* Log a new face as added to the BMesh */
+/* Log a new face as added to the BMesh
+ *
+ * The new face gets a unique ID assigned. It is then added to a map
+ * of added faces, with the key being its ID and the value containing
+ * everything needed to reconstruct that face.
+ */
void BM_log_face_added(BMLog *log, struct BMFace *f);
/* Log a vertex as removed from the BMesh */
+/* Log a vertex as removed from the BMesh
+ *
+ * A couple things can happen here:
+ *
+ * If the vertex was added as part of the current log entry, then it's
+ * deleted and forgotten about entirely. Its unique ID is returned to
+ * the unused pool.
+ *
+ * If the vertex was already part of the BMesh before the current log
+ * entry, it is added to a map of deleted vertices, with the key being
+ * its ID and the value containing everything needed to reconstruct
+ * that vertex.
+ *
+ * If there's a move record for the vertex, that's used as the
+ * vertices original location, then the move record is deleted.
+ */
void BM_log_vert_removed(BMLog *log, struct BMVert *v, const int cd_vert_mask_offset);
/* Log a face as removed from the BMesh */
+/* Log a face as removed from the BMesh
+ *
+ * A couple things can happen here:
+ *
+ * If the face was added as part of the current log entry, then it's
+ * deleted and forgotten about entirely. Its unique ID is returned to
+ * the unused pool.
+ *
+ * If the face was already part of the BMesh before the current log
+ * entry, it is added to a map of deleted faces, with the key being
+ * its ID and the value containing everything needed to reconstruct
+ * that face.
+ */
void BM_log_face_removed(BMLog *log, struct BMFace *f);
/* Log all vertices/faces in the BMesh as added */
+/* Log all vertices/faces in the BMesh as added */
void BM_log_all_added(BMesh *bm, BMLog *log);
/* Log all vertices/faces in the BMesh as removed */
+/* Log all vertices/faces in the BMesh as removed */
void BM_log_before_all_removed(BMesh *bm, BMLog *log);
/* Get the logged coordinates of a vertex */
+/* Get the logged coordinates of a vertex
+ *
+ * Does not modify the log or the vertex */
const float *BM_log_original_vert_co(BMLog *log, BMVert *v);
/* Get the logged normal of a vertex */
+/* Get the logged normal of a vertex
+ *
+ * Does not modify the log or the vertex */
const short *BM_log_original_vert_no(BMLog *log, BMVert *v);
/* Get the logged mask of a vertex */
+/* Get the logged mask of a vertex
+ *
+ * Does not modify the log or the vertex */
float BM_log_original_mask(BMLog *log, BMVert *v);
/* Get the logged data of a vertex (avoid multiple lookups) */
void BM_log_original_vert_data(BMLog *log, BMVert *v, const float **r_co, const short **r_no);
/* For internal use only (unit testing) */
+/* For internal use only (unit testing) */
BMLogEntry *BM_log_current_entry(BMLog *log);
+/* For internal use only (unit testing) */
struct RangeTreeUInt *BM_log_unused_ids(BMLog *log);
diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c
index b70e26f51ea..b756aa25edd 100644
--- a/source/blender/bmesh/intern/bmesh_marking.c
+++ b/source/blender/bmesh/intern/bmesh_marking.c
@@ -251,14 +251,6 @@ static bool bm_edge_is_face_visible_any(const BMEdge *e)
/** \} */
-/**
- * \brief Select Mode Clean
- *
- * Remove isolated selected elements when in a mode doesn't support them.
- * eg: in edge-mode a selected vertex must be connected to a selected edge.
- *
- * \note this could be made a part of #BM_mesh_select_mode_flush_ex
- */
void BM_mesh_select_mode_clean_ex(BMesh *bm, const short selectmode)
{
if (selectmode & SCE_SELECT_VERTEX) {
@@ -424,13 +416,6 @@ static void bm_mesh_select_mode_flush_edge_to_face(BMesh *bm)
bm->totfacesel += chunk_data.delta_selection_len;
}
-/**
- * \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_ex(BMesh *bm, const short selectmode, eBMSelectionFlushFLags flags)
{
if (selectmode & SCE_SELECT_VERTEX) {
@@ -463,9 +448,6 @@ void BM_mesh_select_mode_flush(BMesh *bm)
/** \} */
-/**
- * mode independent flushing up/down
- */
void BM_mesh_deselect_flush(BMesh *bm)
{
BMIter eiter;
@@ -498,9 +480,6 @@ void BM_mesh_deselect_flush(BMesh *bm)
recount_totsels(bm);
}
-/**
- * mode independent flushing up/down
- */
void BM_mesh_select_flush(BMesh *bm)
{
BMEdge *e;
@@ -542,12 +521,6 @@ void BM_mesh_select_flush(BMesh *bm)
recount_totsels(bm);
}
-/**
- * \brief Select Vert
- *
- * Changes selection state of a single vertex
- * in a mesh
- */
void BM_vert_select_set(BMesh *bm, BMVert *v, const bool select)
{
BLI_assert(v->head.htype == BM_VERT);
@@ -570,11 +543,6 @@ void BM_vert_select_set(BMesh *bm, BMVert *v, const bool select)
}
}
-/**
- * \brief Select Edge
- *
- * Changes selection state of a single edge in a mesh.
- */
void BM_edge_select_set(BMesh *bm, BMEdge *e, const bool select)
{
BLI_assert(e->head.htype == BM_EDGE);
@@ -615,12 +583,6 @@ void BM_edge_select_set(BMesh *bm, BMEdge *e, const bool select)
}
}
-/**
- * \brief Select Face
- *
- * Changes selection state of a single
- * face in a mesh.
- */
void BM_face_select_set(BMesh *bm, BMFace *f, const bool select)
{
BMLoop *l_iter;
@@ -746,12 +708,6 @@ void BM_face_select_set_noflush(BMesh *bm, BMFace *f, const bool select)
/** \} */
-/**
- * Select Mode Set
- *
- * Sets the selection mode for the bmesh,
- * updating the selection state.
- */
void BM_mesh_select_mode_set(BMesh *bm, int selectmode)
{
BMIter iter;
@@ -867,10 +823,6 @@ int BM_mesh_elem_hflag_count_disabled(BMesh *bm,
return bm_mesh_flag_count(bm, htype, hflag, respecthide, false);
}
-/**
- * \note use BM_elem_flag_test(ele, BM_ELEM_SELECT) to test selection
- * \note by design, this will not touch the editselection history stuff
- */
void BM_elem_select_set(BMesh *bm, BMElem *ele, const bool select)
{
switch (ele->head.htype) {
@@ -889,7 +841,6 @@ void BM_elem_select_set(BMesh *bm, BMElem *ele, const bool select)
}
}
-/* this replaces the active flag used in uv/face mode */
void BM_mesh_active_face_set(BMesh *bm, BMFace *f)
{
bm->act_face = f;
@@ -974,15 +925,6 @@ BMElem *BM_mesh_active_elem_get(BMesh *bm)
return NULL;
}
-/**
- * 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.
- *
- * - #BM_editselection_center
- * - #BM_editselection_normal
- * - #BM_editselection_plane
- */
void BM_editselection_center(BMEditSelection *ese, float r_center[3])
{
if (ese->htype == BM_VERT) {
@@ -1027,11 +969,6 @@ void BM_editselection_normal(BMEditSelection *ese, float r_normal[3])
}
}
-/**
- * Calculate a plane that is right angles to the edge/vert/faces normal
- * also make the plane run along an axis that is related to the geometry,
- * because this is used for the gizmos Y axis.
- */
void BM_editselection_plane(BMEditSelection *ese, float r_plane[3])
{
if (ese->htype == BM_VERT) {
@@ -1098,6 +1035,7 @@ static BMEditSelection *bm_select_history_create(BMHeader *ele)
}
/* --- macro wrapped funcs --- */
+
bool _bm_select_history_check(BMesh *bm, const BMHeader *ele)
{
return (BLI_findptr(&bm->selected, ele, offsetof(BMEditSelection, ele)) != NULL);
@@ -1170,9 +1108,6 @@ void BM_select_history_validate(BMesh *bm)
}
}
-/**
- * Get the active mesh element (with active-face fallback).
- */
bool BM_select_history_active_get(BMesh *bm, BMEditSelection *ese)
{
BMEditSelection *ese_last = bm->selected.last;
@@ -1209,9 +1144,6 @@ bool BM_select_history_active_get(BMesh *bm, BMEditSelection *ese)
return true;
}
-/**
- * Return a map from BMVert/Edge/Face -> BMEditSelection
- */
GHash *BM_select_history_map_create(BMesh *bm)
{
BMEditSelection *ese;
@@ -1230,9 +1162,6 @@ GHash *BM_select_history_map_create(BMesh *bm)
return map;
}
-/**
- * Map arguments may all be the same pointer.
- */
void BM_select_history_merge_from_targetmap(
BMesh *bm, GHash *vert_map, GHash *edge_map, GHash *face_map, const bool use_chain)
{
diff --git a/source/blender/bmesh/intern/bmesh_marking.h b/source/blender/bmesh/intern/bmesh_marking.h
index 99feae1d66c..72b520cc72c 100644
--- a/source/blender/bmesh/intern/bmesh_marking.h
+++ b/source/blender/bmesh/intern/bmesh_marking.h
@@ -36,14 +36,20 @@ typedef enum eBMSelectionFlushFLags {
BM_SELECT_LEN_FLUSH_RECALC_FACE),
} eBMSelectionFlushFLags;
-/* geometry hiding code */
+/* Geometry hiding code. */
+
#define BM_elem_hide_set(bm, ele, hide) _bm_elem_hide_set(bm, &(ele)->head, hide)
void _bm_elem_hide_set(BMesh *bm, BMHeader *head, const bool hide);
void BM_vert_hide_set(BMVert *v, const bool hide);
void BM_edge_hide_set(BMEdge *e, const bool hide);
void BM_face_hide_set(BMFace *f, const bool hide);
-/* Selection code */
+/* Selection code. */
+
+/**
+ * \note use BM_elem_flag_test(ele, BM_ELEM_SELECT) to test selection
+ * \note by design, this will not touch the editselection history stuff
+ */
void BM_elem_select_set(BMesh *bm, BMElem *ele, const bool select);
void BM_mesh_elem_hflag_enable_test(BMesh *bm,
@@ -68,24 +74,70 @@ void BM_mesh_elem_hflag_disable_all(BMesh *bm,
const char hflag,
const bool respecthide);
-/* Individual element select functions, BM_elem_select_set is a shortcut for these
+/* Individual element select functions, #BM_elem_select_set is a shortcut for these
* that automatically detects which one to use. */
+
+/**
+ * \brief Select Vert
+ *
+ * Changes selection state of a single vertex
+ * in a mesh
+ */
void BM_vert_select_set(BMesh *bm, BMVert *v, const bool select);
+/**
+ * \brief Select Edge
+ *
+ * Changes selection state of a single edge in a mesh.
+ */
void BM_edge_select_set(BMesh *bm, BMEdge *e, const bool select);
+/**
+ * \brief Select Face
+ *
+ * Changes selection state of a single
+ * face in a mesh.
+ */
void BM_face_select_set(BMesh *bm, BMFace *f, const bool select);
-/* lower level functions which don't do flushing */
+/* Lower level functions which don't do flushing. */
+
void BM_edge_select_set_noflush(BMesh *bm, BMEdge *e, const bool select);
void BM_face_select_set_noflush(BMesh *bm, BMFace *f, const bool select);
+/**
+ * \brief Select Mode Clean
+ *
+ * Remove isolated selected elements when in a mode doesn't support them.
+ * eg: in edge-mode a selected vertex must be connected to a selected edge.
+ *
+ * \note this could be made a part of #BM_mesh_select_mode_flush_ex
+ */
void BM_mesh_select_mode_clean_ex(BMesh *bm, const short selectmode);
void BM_mesh_select_mode_clean(BMesh *bm);
+/**
+ * Select Mode Set
+ *
+ * Sets the selection mode for the bmesh,
+ * updating the selection state.
+ */
void BM_mesh_select_mode_set(BMesh *bm, int selectmode);
+/**
+ * \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_ex(BMesh *bm, const short selectmode, eBMSelectionFlushFLags flags);
void BM_mesh_select_mode_flush(BMesh *bm);
+/**
+ * Mode independent de-selection flush (up/down).
+ */
void BM_mesh_deselect_flush(BMesh *bm);
+/**
+ * Mode independent selection flush (up/down).
+ */
void BM_mesh_select_flush(BMesh *bm);
int BM_mesh_elem_hflag_count_enabled(BMesh *bm,
@@ -97,15 +149,30 @@ int BM_mesh_elem_hflag_count_disabled(BMesh *bm,
const char hflag,
const bool respecthide);
-/* edit selection stuff */
+/* Edit selection stuff. */
+
void BM_mesh_active_face_set(BMesh *bm, BMFace *f);
BMFace *BM_mesh_active_face_get(BMesh *bm, const bool is_sloppy, const bool is_selected);
BMEdge *BM_mesh_active_edge_get(BMesh *bm);
BMVert *BM_mesh_active_vert_get(BMesh *bm);
BMElem *BM_mesh_active_elem_get(BMesh *bm);
+/**
+ * Generic way to get data from an #BMEditSelection type
+ * These functions were written to be used by the Modifier widget
+ * when in Rotate about active mode, but can be used anywhere.
+ *
+ * - #BM_editselection_center
+ * - #BM_editselection_normal
+ * - #BM_editselection_plane
+ */
void BM_editselection_center(BMEditSelection *ese, float r_center[3]);
void BM_editselection_normal(BMEditSelection *ese, float r_normal[3]);
+/**
+ * Calculate a plane that is right angles to the edge/vert/faces normal
+ * also make the plane run along an axis that is related to the geometry,
+ * because this is used for the gizmos Y axis.
+ */
void BM_editselection_plane(BMEditSelection *ese, float r_plane[3]);
#define BM_select_history_check(bm, ele) _bm_select_history_check(bm, &(ele)->head)
@@ -131,9 +198,18 @@ void _bm_select_history_store_after_notest(BMesh *bm, BMEditSelection *ese_ref,
void BM_select_history_validate(BMesh *bm);
void BM_select_history_clear(BMesh *bm);
+/**
+ * Get the active mesh element (with active-face fallback).
+ */
bool BM_select_history_active_get(BMesh *bm, struct BMEditSelection *ese);
+/**
+ * Return a map from #BMVert/#BMEdge/#BMFace -> #BMEditSelection.
+ */
struct GHash *BM_select_history_map_create(BMesh *bm);
+/**
+ * Map arguments may all be the same pointer.
+ */
void BM_select_history_merge_from_targetmap(
BMesh *bm, GHash *vert_map, GHash *edge_map, GHash *face_map, const bool use_chain);
diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c
index b2958a9e744..ad52daa4731 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.c
+++ b/source/blender/bmesh/intern/bmesh_mesh.c
@@ -34,7 +34,6 @@
#include "bmesh.h"
-/* used as an extern, defined in bmesh.h */
const BMAllocTemplate bm_mesh_allocsize_default = {512, 1024, 2048, 512};
const BMAllocTemplate bm_mesh_chunksize_default = {512, 1024, 2048, 512};
@@ -137,15 +136,6 @@ void BM_mesh_elem_toolflags_clear(BMesh *bm)
}
}
-/**
- * \brief BMesh Make Mesh
- *
- * Allocates a new BMesh structure.
- *
- * \return The New bmesh
- *
- * \note ob is needed by multires
- */
BMesh *BM_mesh_create(const BMAllocTemplate *allocsize, const struct BMeshCreateParams *params)
{
/* allocate the structure */
@@ -167,13 +157,6 @@ BMesh *BM_mesh_create(const BMAllocTemplate *allocsize, const struct BMeshCreate
return bm;
}
-/**
- * \brief BMesh Free Mesh Data
- *
- * Frees a BMesh structure.
- *
- * \note frees mesh, but not actual BMesh struct
- */
void BM_mesh_data_free(BMesh *bm)
{
BMVert *v;
@@ -265,11 +248,6 @@ void BM_mesh_data_free(BMesh *bm)
BMO_error_clear(bm);
}
-/**
- * \brief BMesh Clear Mesh
- *
- * Clear all data in bm
- */
void BM_mesh_clear(BMesh *bm)
{
const bool use_toolflags = bm->use_toolflags;
@@ -291,11 +269,6 @@ void BM_mesh_clear(BMesh *bm)
CustomData_reset(&bm->pdata);
}
-/**
- * \brief BMesh Free Mesh
- *
- * Frees a BMesh data and its structure.
- */
void BM_mesh_free(BMesh *bm)
{
BM_mesh_data_free(bm);
@@ -310,13 +283,6 @@ void BM_mesh_free(BMesh *bm)
MEM_freeN(bm);
}
-/**
- * \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.
- */
void bmesh_edit_begin(BMesh *UNUSED(bm), BMOpTypeFlag UNUSED(type_flag))
{
/* Most operators seem to be using BMO_OPTYPE_FLAG_UNTAN_MULTIRES to change the MDisps to
@@ -337,9 +303,6 @@ void bmesh_edit_begin(BMesh *UNUSED(bm), BMOpTypeFlag UNUSED(type_flag))
#endif
}
-/**
- * \brief BMesh End Edit
- */
void bmesh_edit_end(BMesh *bm, BMOpTypeFlag type_flag)
{
ListBase select_history;
@@ -499,18 +462,6 @@ void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
BM_mesh_elem_index_ensure_ex(bm, htype, NULL);
}
-/**
- * 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.
- *
- * Code that calls this functions may depend on dirty indices on being set.
- * Keep this function read-only.
- */
-
void BM_mesh_elem_index_validate(
BMesh *bm, const char *location, const char *func, const char *msg_a, const char *msg_b)
{
@@ -693,7 +644,6 @@ finally:
bm->elem_table_dirty &= ~htype_needed;
}
-/* use BM_mesh_elem_table_ensure where possible to avoid full rebuild */
void BM_mesh_elem_table_init(BMesh *bm, const char htype)
{
BLI_assert((htype & ~BM_ALL_NOLOOP) == 0);
@@ -754,11 +704,6 @@ BMLoop *BM_loop_at_index_find(BMesh *bm, const int index)
return NULL;
}
-/**
- * Use lookup table when available, else use slower find functions.
- *
- * \note Try to use #BM_mesh_elem_table_ensure instead.
- */
BMVert *BM_vert_at_index_find_or_table(BMesh *bm, const int index)
{
if ((bm->elem_table_dirty & BM_VERT) == 0) {
@@ -783,9 +728,6 @@ BMFace *BM_face_at_index_find_or_table(BMesh *bm, const int index)
return BM_face_at_index_find(bm, index);
}
-/**
- * Return the amount of element of type 'type' in a given bmesh.
- */
int BM_mesh_elem_count(BMesh *bm, const char htype)
{
BLI_assert((htype & ~BM_ALL_NOLOOP) == 0);
@@ -804,20 +746,6 @@ int BM_mesh_elem_count(BMesh *bm, const char htype)
}
}
-/**
- * Remaps the vertices, edges and/or faces of the bmesh as indicated by vert/edge/face_idx arrays
- * (xxx_idx[org_index] = new_index).
- *
- * A NULL array means no changes.
- *
- * \note
- * - Does not mess with indices, just sets elem_index_dirty flag.
- * - For verts/edges/faces only (as loops must remain "ordered" and "aligned"
- * on a per-face basis...).
- *
- * \warning Be careful if you keep pointers to affected BM elements,
- * or arrays, when using this func!
- */
void BM_mesh_remap(BMesh *bm, const uint *vert_idx, const uint *edge_idx, const uint *face_idx)
{
/* Mapping old to new pointers. */
@@ -1106,12 +1034,6 @@ void BM_mesh_remap(BMesh *bm, const uint *vert_idx, const uint *edge_idx, const
}
}
-/**
- * Use new memory pools for this mesh.
- *
- * \note needed for re-sizing elements (adding/removing tool flags)
- * but could also be used for packing fragmented bmeshes.
- */
void BM_mesh_rebuild(BMesh *bm,
const struct BMeshCreateParams *params,
BLI_mempool *vpool_dst,
@@ -1363,9 +1285,6 @@ void BM_mesh_rebuild(BMesh *bm,
}
}
-/**
- * Re-allocates mesh data with/without toolflags.
- */
void BM_mesh_toolflags_set(BMesh *bm, bool use_toolflags)
{
if (bm->use_toolflags == use_toolflags) {
diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h
index bd0504b038a..e00461ba571 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.h
+++ b/source/blender/bmesh/intern/bmesh_mesh.h
@@ -34,28 +34,83 @@ struct BMeshCreateParams {
uint use_toolflags : 1;
};
+/**
+ * \brief BMesh Make Mesh
+ *
+ * Allocates a new BMesh structure.
+ *
+ * \return The New bmesh
+ *
+ * \note ob is needed by multires
+ */
BMesh *BM_mesh_create(const struct BMAllocTemplate *allocsize,
const struct BMeshCreateParams *params);
+/**
+ * \brief BMesh Free Mesh
+ *
+ * Frees a BMesh data and its structure.
+ */
void BM_mesh_free(BMesh *bm);
+/**
+ * \brief BMesh Free Mesh Data
+ *
+ * Frees a BMesh structure.
+ *
+ * \note frees mesh, but not actual BMesh struct
+ */
void BM_mesh_data_free(BMesh *bm);
+/**
+ * \brief BMesh Clear Mesh
+ *
+ * Clear all data in bm
+ */
void BM_mesh_clear(BMesh *bm);
+/**
+ * \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.
+ */
void bmesh_edit_begin(BMesh *bm, const BMOpTypeFlag type_flag);
+/**
+ * \brief BMesh End Edit
+ */
void bmesh_edit_end(BMesh *bm, const BMOpTypeFlag type_flag);
void BM_mesh_elem_index_ensure_ex(BMesh *bm, const char htype, int elem_offset[4]);
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype);
+/**
+ * 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.
+ *
+ * Functions that calls this function may depend on dirty indices on being set.
+ *
+ * This is read-only, so it can be used for assertions that don't impact behavior.
+ */
void BM_mesh_elem_index_validate(
BMesh *bm, const char *location, const char *func, const char *msg_a, const char *msg_b);
-void BM_mesh_toolflags_set(BMesh *bm, bool use_toolflags);
-
#ifndef NDEBUG
+/**
+ * \see #BM_mesh_elem_index_validate the same rationale applies to this function.
+ */
bool BM_mesh_elem_table_check(BMesh *bm);
#endif
+/**
+ * Re-allocates mesh data with/without toolflags.
+ */
+void BM_mesh_toolflags_set(BMesh *bm, bool use_toolflags);
+
void BM_mesh_elem_table_ensure(BMesh *bm, const char htype);
+/* use BM_mesh_elem_table_ensure where possible to avoid full rebuild */
void BM_mesh_elem_table_init(BMesh *bm, const char htype);
void BM_mesh_elem_table_free(BMesh *bm, const char htype);
@@ -83,16 +138,44 @@ BMEdge *BM_edge_at_index_find(BMesh *bm, const int index);
BMFace *BM_face_at_index_find(BMesh *bm, const int index);
BMLoop *BM_loop_at_index_find(BMesh *bm, const int index);
+/**
+ * Use lookup table when available, else use slower find functions.
+ *
+ * \note Try to use #BM_mesh_elem_table_ensure instead.
+ */
BMVert *BM_vert_at_index_find_or_table(BMesh *bm, const int index);
BMEdge *BM_edge_at_index_find_or_table(BMesh *bm, const int index);
BMFace *BM_face_at_index_find_or_table(BMesh *bm, const int index);
// XXX
+/**
+ * Return the amount of element of type 'type' in a given bmesh.
+ */
int BM_mesh_elem_count(BMesh *bm, const char htype);
+/**
+ * Remaps the vertices, edges and/or faces of the bmesh as indicated by vert/edge/face_idx arrays
+ * (xxx_idx[org_index] = new_index).
+ *
+ * A NULL array means no changes.
+ *
+ * \note
+ * - Does not mess with indices, just sets elem_index_dirty flag.
+ * - For verts/edges/faces only (as loops must remain "ordered" and "aligned"
+ * on a per-face basis...).
+ *
+ * \warning Be careful if you keep pointers to affected BM elements,
+ * or arrays, when using this func!
+ */
void BM_mesh_remap(BMesh *bm, const uint *vert_idx, const uint *edge_idx, const uint *face_idx);
+/**
+ * Use new memory pools for this mesh.
+ *
+ * \note needed for re-sizing elements (adding/removing tool flags)
+ * but could also be used for packing fragmented bmeshes.
+ */
void BM_mesh_rebuild(BMesh *bm,
const struct BMeshCreateParams *params,
struct BLI_mempool *vpool,
@@ -104,6 +187,7 @@ typedef struct BMAllocTemplate {
int totvert, totedge, totloop, totface;
} BMAllocTemplate;
+/* used as an extern, defined in bmesh.h */
extern const BMAllocTemplate bm_mesh_allocsize_default;
extern const BMAllocTemplate bm_mesh_chunksize_default;
diff --git a/source/blender/bmesh/intern/bmesh_mesh_convert.c b/source/blender/bmesh/intern/bmesh_mesh_convert.c
index 9d29a90a7a4..544a81f7020 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_convert.c
+++ b/source/blender/bmesh/intern/bmesh_mesh_convert.c
@@ -176,16 +176,6 @@ static BMFace *bm_face_create_from_mpoly(
return BM_face_create(bm, verts, edges, mp->totloop, NULL, BM_CREATE_SKIP_CD);
}
-/**
- * \brief Mesh -> BMesh
- * \param bm: The mesh to write into, while this is typically a newly created BMesh,
- * merging into existing data is supported.
- * Note the custom-data layout isn't used.
- * If more comprehensive merging is needed we should move this into a separate function
- * since this should be kept fast for edit-mode switching and storing undo steps.
- *
- * \warning This function doesn't calculate face normals.
- */
void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshParams *params)
{
const bool is_new = !(bm->totvert || (bm->vdata.totlayer || bm->edata.totlayer ||
@@ -582,10 +572,6 @@ BLI_INLINE void bmesh_quick_edgedraw_flag(MEdge *med, BMEdge *e)
}
}
-/**
- *
- * \param bmain: May be NULL in case \a calc_object_remap parameter option is not set.
- */
void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMeshParams *params)
{
MEdge *med;
@@ -1005,23 +991,6 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
BKE_mesh_runtime_clear_geometry(me);
}
-/**
- * A version of #BM_mesh_bm_to_me intended for getting the mesh
- * to pass to the modifier stack for evaluation,
- * instead of mode switching (where we make sure all data is kept
- * and do expensive lookups to maintain shape keys).
- *
- * Key differences:
- *
- * - Don't support merging with existing mesh.
- * - Ignore shape-keys.
- * - Ignore vertex-parents.
- * - Ignore selection history.
- * - Uses simpler method to calculate #ME_EDGEDRAW
- * - Uses #CD_MASK_DERIVEDMESH instead of #CD_MASK_MESH.
- *
- * \note Was `cddm_from_bmesh_ex` in 2.7x, removed `MFace` support.
- */
void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *cd_mask_extra)
{
/* Must be an empty mesh. */
diff --git a/source/blender/bmesh/intern/bmesh_mesh_convert.h b/source/blender/bmesh/intern/bmesh_mesh_convert.h
index 1b5d001d35d..ea114487285 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_convert.h
+++ b/source/blender/bmesh/intern/bmesh_mesh_convert.h
@@ -43,6 +43,16 @@ struct BMeshFromMeshParams {
int active_shapekey;
struct CustomData_MeshMasks cd_mask_extra;
};
+/**
+ * \brief Mesh -> BMesh
+ * \param bm: The mesh to write into, while this is typically a newly created BMesh,
+ * merging into existing data is supported.
+ * Note the custom-data layout isn't used.
+ * If more comprehensive merging is needed we should move this into a separate function
+ * since this should be kept fast for edit-mode switching and storing undo steps.
+ *
+ * \warning This function doesn't calculate face normals.
+ */
void BM_mesh_bm_from_me(BMesh *bm, const struct Mesh *me, const struct BMeshFromMeshParams *params)
ATTR_NONNULL(1, 3);
@@ -61,11 +71,32 @@ struct BMeshToMeshParams {
uint update_shapekey_indices : 1;
struct CustomData_MeshMasks cd_mask_extra;
};
+/**
+ *
+ * \param bmain: May be NULL in case \a calc_object_remap parameter option is not set.
+ */
void BM_mesh_bm_to_me(struct Main *bmain,
BMesh *bm,
struct Mesh *me,
const struct BMeshToMeshParams *params) ATTR_NONNULL(2, 3, 4);
+/**
+ * A version of #BM_mesh_bm_to_me intended for getting the mesh
+ * to pass to the modifier stack for evaluation,
+ * instead of mode switching (where we make sure all data is kept
+ * and do expensive lookups to maintain shape keys).
+ *
+ * Key differences:
+ *
+ * - Don't support merging with existing mesh.
+ * - Ignore shape-keys.
+ * - Ignore vertex-parents.
+ * - Ignore selection history.
+ * - Uses simpler method to calculate #ME_EDGEDRAW
+ * - Uses #CD_MASK_DERIVEDMESH instead of #CD_MASK_MESH.
+ *
+ * \note Was `cddm_from_bmesh_ex` in 2.7x, removed `MFace` support.
+ */
void BM_mesh_bm_to_me_for_eval(BMesh *bm,
struct Mesh *me,
const struct CustomData_MeshMasks *cd_mask_extra)
diff --git a/source/blender/bmesh/intern/bmesh_mesh_duplicate.c b/source/blender/bmesh/intern/bmesh_mesh_duplicate.c
index 1d393abcd56..db21e50bb71 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_duplicate.c
+++ b/source/blender/bmesh/intern/bmesh_mesh_duplicate.c
@@ -85,9 +85,6 @@ static BMFace *bm_face_copy_with_arrays(
return f_dst;
}
-/**
- * Geometry must be completely isolated.
- */
void BM_mesh_copy_arrays(BMesh *bm_src,
BMesh *bm_dst,
BMVert **verts_src,
diff --git a/source/blender/bmesh/intern/bmesh_mesh_duplicate.h b/source/blender/bmesh/intern/bmesh_mesh_duplicate.h
index 8ace555d61f..d15ef8f4ab2 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_duplicate.h
+++ b/source/blender/bmesh/intern/bmesh_mesh_duplicate.h
@@ -20,6 +20,9 @@
* \ingroup bmesh
*/
+/**
+ * Geometry must be completely isolated.
+ */
void BM_mesh_copy_arrays(BMesh *bm_src,
BMesh *bm_dst,
BMVert **verts_src,
diff --git a/source/blender/bmesh/intern/bmesh_mesh_normals.c b/source/blender/bmesh/intern/bmesh_mesh_normals.c
index 8119d9eb57d..34c07b4f310 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_normals.c
+++ b/source/blender/bmesh/intern/bmesh_mesh_normals.c
@@ -247,11 +247,6 @@ static void bm_face_calc_normals_cb(void *UNUSED(userdata),
BM_face_calc_normal(f, f->no);
}
-/**
- * \brief BMesh Compute Normals
- *
- * Updates the normals of a mesh.
- */
void BM_mesh_normals_update_ex(BMesh *bm, const struct BMeshNormalsUpdate_Params *params)
{
if (params->face_normals) {
@@ -295,10 +290,6 @@ static void bm_partial_verts_parallel_range_calc_normal_cb(
bm_vert_calc_normals_impl(v);
}
-/**
- * A version of #BM_mesh_normals_update that updates a subset of geometry,
- * used to avoid the overhead of updating everything.
- */
void BM_mesh_normals_update_with_partial_ex(BMesh *UNUSED(bm),
const BMPartialUpdate *bmpinfo,
const struct BMeshNormalsUpdate_Params *params)
@@ -343,12 +334,6 @@ void BM_mesh_normals_update_with_partial(BMesh *bm, const BMPartialUpdate *bmpin
/** \name Update Vertex & Face Normals (Custom Coords)
* \{ */
-/**
- * \brief BMesh Compute Normals from/to external data.
- *
- * Computes the vertex normals of a mesh into vnos,
- * using given vertex coordinates (vcos) and polygon normals (fnos).
- */
void BM_verts_calc_normal_vcos(BMesh *bm,
const float (*fnos)[3],
const float (*vcos)[3],
@@ -435,12 +420,6 @@ static void bm_mesh_edges_sharp_tag(BMesh *bm,
bm->elem_index_dirty &= ~BM_EDGE;
}
-/**
- * Define sharp edges as needed to mimic 'autosmooth' from angle threshold.
- *
- * Used when defining an empty custom loop normals data layer,
- * to keep same shading as with auto-smooth!
- */
void BM_edges_sharp_from_angle_set(BMesh *bm, const float split_angle)
{
if (split_angle >= (float)M_PI) {
@@ -457,11 +436,6 @@ void BM_edges_sharp_from_angle_set(BMesh *bm, const float split_angle)
/** \name Loop Normals Calculation API
* \{ */
-/**
- * Check whether given loop is part of an unknown-so-far cyclic smooth fan, or not.
- * Needed because cyclic smooth fans have no obvious 'entry point',
- * and yet we need to walk them once, and only once.
- */
bool BM_loop_check_cyclic_smooth_fan(BMLoop *l_curr)
{
BMLoop *lfan_pivot_next = l_curr;
@@ -520,7 +494,8 @@ static int bm_mesh_loops_calc_normals_for_loop(BMesh *bm,
float (*r_lnos)[3],
MLoopNorSpaceArray *r_lnors_spacearr)
{
- BLI_assert((bm->elem_index_dirty & (BM_FACE | BM_LOOP)) == 0);
+ BLI_assert((bm->elem_index_dirty & BM_LOOP) == 0);
+ BLI_assert((fnos == NULL) || ((bm->elem_index_dirty & BM_FACE) == 0));
BLI_assert((vcos == NULL) || ((bm->elem_index_dirty & BM_VERT) == 0));
UNUSED_VARS_NDEBUG(bm);
@@ -1719,13 +1694,6 @@ static void bm_mesh_loops_calc_normals_no_autosmooth(BMesh *bm,
}
}
-/**
- * \brief BMesh Compute Loop Normals from/to external data.
- *
- * Compute split normals, i.e. vertex normals associated with each poly (hence 'loop normals').
- * Useful to materialize sharp edges (or non-smooth faces) without actually modifying the geometry
- * (splitting edges).
- */
void BM_loops_calc_normal_vcos(BMesh *bm,
const float (*vcos)[3],
const float (*vnos)[3],
@@ -1932,10 +1900,6 @@ void BM_lnorspace_rebuild(BMesh *bm, bool preserve_clnor)
#endif
}
-/**
- * \warning This function sets #BM_ELEM_TAG on loops & edges via #bm_mesh_loops_calc_normals,
- * take care to run this before setting up tags.
- */
void BM_lnorspace_update(BMesh *bm)
{
if (bm->lnor_spacearr == NULL) {
@@ -2249,10 +2213,6 @@ void BM_loop_normal_editdata_array_free(BMLoopNorEditDataArray *lnors_ed_arr)
/** \name Custom Normals / Vector Layer Conversion
* \{ */
-/**
- * \warning This function sets #BM_ELEM_TAG on loops & edges via #bm_mesh_loops_calc_normals,
- * take care to run this before setting up tags.
- */
bool BM_custom_loop_normals_to_vector_layer(BMesh *bm)
{
BMFace *f;
diff --git a/source/blender/bmesh/intern/bmesh_mesh_normals.h b/source/blender/bmesh/intern/bmesh_mesh_normals.h
index ecd627d4bfe..a2e64b1dc9b 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_normals.h
+++ b/source/blender/bmesh/intern/bmesh_mesh_normals.h
@@ -30,17 +30,39 @@ struct BMeshNormalsUpdate_Params {
bool face_normals;
};
+/**
+ * \brief BMesh Compute Normals
+ *
+ * Updates the normals of a mesh.
+ */
void BM_mesh_normals_update_ex(BMesh *bm, const struct BMeshNormalsUpdate_Params *param);
void BM_mesh_normals_update(BMesh *bm);
+/**
+ * A version of #BM_mesh_normals_update that updates a subset of geometry,
+ * used to avoid the overhead of updating everything.
+ */
void BM_mesh_normals_update_with_partial_ex(BMesh *bm,
const struct BMPartialUpdate *bmpinfo,
const struct BMeshNormalsUpdate_Params *param);
void BM_mesh_normals_update_with_partial(BMesh *bm, const struct BMPartialUpdate *bmpinfo);
+/**
+ * \brief BMesh Compute Normals from/to external data.
+ *
+ * Computes the vertex normals of a mesh into vnos,
+ * using given vertex coordinates (vcos) and polygon normals (fnos).
+ */
void BM_verts_calc_normal_vcos(BMesh *bm,
const float (*fnos)[3],
const float (*vcos)[3],
float (*vnos)[3]);
+/**
+ * \brief BMesh Compute Loop Normals from/to external data.
+ *
+ * Compute split normals, i.e. vertex normals associated with each poly (hence 'loop normals').
+ * Useful to materialize sharp edges (or non-smooth faces) without actually modifying the geometry
+ * (splitting edges).
+ */
void BM_loops_calc_normal_vcos(BMesh *bm,
const float (*vcos)[3],
const float (*vnos)[3],
@@ -53,10 +75,19 @@ void BM_loops_calc_normal_vcos(BMesh *bm,
const int cd_loop_clnors_offset,
const bool do_rebuild);
+/**
+ * Check whether given loop is part of an unknown-so-far cyclic smooth fan, or not.
+ * Needed because cyclic smooth fans have no obvious 'entry point',
+ * and yet we need to walk them once, and only once.
+ */
bool BM_loop_check_cyclic_smooth_fan(BMLoop *l_curr);
void BM_lnorspacearr_store(BMesh *bm, float (*r_lnors)[3]);
void BM_lnorspace_invalidate(BMesh *bm, const bool do_invalidate_all);
void BM_lnorspace_rebuild(BMesh *bm, bool preserve_clnor);
+/**
+ * \warning This function sets #BM_ELEM_TAG on loops & edges via #bm_mesh_loops_calc_normals,
+ * take care to run this before setting up tags.
+ */
void BM_lnorspace_update(BMesh *bm);
void BM_normals_loops_edges_tag(BMesh *bm, const bool do_edges);
#ifndef NDEBUG
@@ -68,7 +99,17 @@ struct BMLoopNorEditDataArray *BM_loop_normal_editdata_array_init(BMesh *bm,
const bool do_all_loops_of_vert);
void BM_loop_normal_editdata_array_free(struct BMLoopNorEditDataArray *lnors_ed_arr);
+/**
+ * \warning This function sets #BM_ELEM_TAG on loops & edges via #bm_mesh_loops_calc_normals,
+ * take care to run this before setting up tags.
+ */
bool BM_custom_loop_normals_to_vector_layer(struct BMesh *bm);
void BM_custom_loop_normals_from_vector_layer(struct BMesh *bm, bool add_sharp_edges);
+/**
+ * Define sharp edges as needed to mimic 'autosmooth' from angle threshold.
+ *
+ * Used when defining an empty custom loop normals data layer,
+ * to keep same shading as with auto-smooth!
+ */
void BM_edges_sharp_from_angle_set(BMesh *bm, const float split_angle);
diff --git a/source/blender/bmesh/intern/bmesh_mesh_partial_update.c b/source/blender/bmesh/intern/bmesh_mesh_partial_update.c
index 46fd2ad9a31..ad9b8414525 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_partial_update.c
+++ b/source/blender/bmesh/intern/bmesh_mesh_partial_update.c
@@ -103,10 +103,6 @@ BLI_INLINE bool partial_elem_face_ensure(BMPartialUpdate *bmpinfo,
return false;
}
-/**
- * All Tagged & Connected, see: #BM_mesh_partial_create_from_verts
- * Operate on everything that's tagged as well as connected geometry.
- */
BMPartialUpdate *BM_mesh_partial_create_from_verts(BMesh *bm,
const BMPartialUpdate_Params *params,
const BLI_bitmap *verts_mask,
@@ -216,11 +212,6 @@ BMPartialUpdate *BM_mesh_partial_create_from_verts(BMesh *bm,
return bmpinfo;
}
-/**
- * All Connected, operate on all faces that have both tagged and un-tagged vertices.
- *
- * Reduces computations when transforming isolated regions.
- */
BMPartialUpdate *BM_mesh_partial_create_from_verts_group_single(
BMesh *bm,
const BMPartialUpdate_Params *params,
@@ -314,25 +305,6 @@ BMPartialUpdate *BM_mesh_partial_create_from_verts_group_single(
return bmpinfo;
}
-/**
- * All Connected, operate on all faces that have vertices in the same group.
- *
- * Reduces computations when transforming isolated regions.
- *
- * This is a version of #BM_mesh_partial_create_from_verts_group_single
- * that handles multiple groups instead of a bitmap mask.
- *
- * This is needed for example when transform has mirror enabled,
- * since one side needs to have a different group to the other since a face that has vertices
- * attached to both won't have an affine transformation.
- *
- * \param verts_groups: Vertex aligned array of groups.
- * Values are used as follows:
- * - >0: Each face is grouped with other faces of the same group.
- * - 0: Not in a group (don't handle these).
- * - -1: Don't use grouping logic (include any face that contains a vertex with this group).
- * \param verts_groups_count: The number of non-zero values in `verts_groups`.
- */
BMPartialUpdate *BM_mesh_partial_create_from_verts_group_multi(
BMesh *bm,
const BMPartialUpdate_Params *params,
diff --git a/source/blender/bmesh/intern/bmesh_mesh_partial_update.h b/source/blender/bmesh/intern/bmesh_mesh_partial_update.h
index cf4eab22836..57f57053606 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_partial_update.h
+++ b/source/blender/bmesh/intern/bmesh_mesh_partial_update.h
@@ -52,18 +52,46 @@ typedef struct BMPartialUpdate {
BMPartialUpdate_Params params;
} BMPartialUpdate;
+/**
+ * All Tagged & Connected, see: #BM_mesh_partial_create_from_verts
+ * Operate on everything that's tagged as well as connected geometry.
+ */
BMPartialUpdate *BM_mesh_partial_create_from_verts(BMesh *bm,
const BMPartialUpdate_Params *params,
const unsigned int *verts_mask,
const int verts_mask_count)
ATTR_NONNULL(1, 2, 3) ATTR_WARN_UNUSED_RESULT;
+/**
+ * All Connected, operate on all faces that have both tagged and un-tagged vertices.
+ *
+ * Reduces computations when transforming isolated regions.
+ */
BMPartialUpdate *BM_mesh_partial_create_from_verts_group_single(
BMesh *bm,
const BMPartialUpdate_Params *params,
const unsigned int *verts_mask,
const int verts_mask_count) ATTR_NONNULL(1, 2, 3) ATTR_WARN_UNUSED_RESULT;
+/**
+ * All Connected, operate on all faces that have vertices in the same group.
+ *
+ * Reduces computations when transforming isolated regions.
+ *
+ * This is a version of #BM_mesh_partial_create_from_verts_group_single
+ * that handles multiple groups instead of a bitmap mask.
+ *
+ * This is needed for example when transform has mirror enabled,
+ * since one side needs to have a different group to the other since a face that has vertices
+ * attached to both won't have an affine transformation.
+ *
+ * \param verts_group: Vertex aligned array of groups.
+ * Values are used as follows:
+ * - >0: Each face is grouped with other faces of the same group.
+ * - 0: Not in a group (don't handle these).
+ * - -1: Don't use grouping logic (include any face that contains a vertex with this group).
+ * \param verts_group_count: The number of non-zero values in `verts_groups`.
+ */
BMPartialUpdate *BM_mesh_partial_create_from_verts_group_multi(
BMesh *bm,
const BMPartialUpdate_Params *params,
diff --git a/source/blender/bmesh/intern/bmesh_mesh_tessellate.c b/source/blender/bmesh/intern/bmesh_mesh_tessellate.c
index 9f477bc8a9c..94d8901edf8 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_tessellate.c
+++ b/source/blender/bmesh/intern/bmesh_mesh_tessellate.c
@@ -549,9 +549,6 @@ static int bmesh_calc_tessellation_for_face_beauty(BMLoop *(*looptris)[3],
}
}
-/**
- * A version of #BM_mesh_calc_tessellation that avoids degenerate triangles.
- */
void BM_mesh_calc_tessellation_beauty(BMesh *bm, BMLoop *(*looptris)[3])
{
#ifndef NDEBUG
diff --git a/source/blender/bmesh/intern/bmesh_mesh_tessellate.h b/source/blender/bmesh/intern/bmesh_mesh_tessellate.h
index 9a6a20d7568..91eac6bc6fc 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_tessellate.h
+++ b/source/blender/bmesh/intern/bmesh_mesh_tessellate.h
@@ -35,6 +35,9 @@ void BM_mesh_calc_tessellation_ex(BMesh *bm,
const struct BMeshCalcTessellation_Params *params);
void BM_mesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3]);
+/**
+ * A version of #BM_mesh_calc_tessellation that avoids degenerate triangles.
+ */
void BM_mesh_calc_tessellation_beauty(BMesh *bm, BMLoop *(*looptris)[3]);
void BM_mesh_calc_tessellation_with_partial_ex(BMesh *bm,
diff --git a/source/blender/bmesh/intern/bmesh_mesh_validate.c b/source/blender/bmesh/intern/bmesh_mesh_validate.c
index f8830e1557b..3145ceceafd 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_validate.c
+++ b/source/blender/bmesh/intern/bmesh_mesh_validate.c
@@ -50,12 +50,6 @@
(void)0
# endif
-/**
- * Check of this BMesh is valid,
- * this function can be slow since its intended to help with debugging.
- *
- * \return true when the mesh is valid.
- */
bool BM_mesh_validate(BMesh *bm)
{
EdgeHash *edge_hash = BLI_edgehash_new_ex(__func__, bm->totedge);
diff --git a/source/blender/bmesh/intern/bmesh_mesh_validate.h b/source/blender/bmesh/intern/bmesh_mesh_validate.h
index 2112e1f3200..203c8a89c55 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_validate.h
+++ b/source/blender/bmesh/intern/bmesh_mesh_validate.h
@@ -23,4 +23,10 @@
* \ingroup bmesh
*/
+/**
+ * Check of this #BMesh is valid,
+ * this function can be slow since its intended to help with debugging.
+ *
+ * \return true when the mesh is valid.
+ */
bool BM_mesh_validate(BMesh *bm);
diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c
index 5fa12397a07..0a3857a6e0a 100644
--- a/source/blender/bmesh/intern/bmesh_mods.c
+++ b/source/blender/bmesh/intern/bmesh_mods.c
@@ -31,31 +31,6 @@
#include "bmesh.h"
#include "intern/bmesh_private.h"
-/**
- * \brief Dissolve Vert
- *
- * Turns the face region surrounding a manifold vertex into a single polygon.
- *
- * \par Example:
- * <pre>
- * +---------+ +---------+
- * | \ / | | |
- * Before: | v | After: | |
- * | / \ | | |
- * +---------+ +---------+
- * </pre>
- *
- * This function can also collapse edges too
- * in cases when it can't merge into faces.
- *
- * \par Example:
- * <pre>
- * Before: +----v----+ After: +---------+
- * </pre>
- *
- * \note dissolves vert, in more situations than BM_disk_dissolve
- * (e.g. if the vert is part of a wire edge, etc).
- */
bool BM_vert_dissolve(BMesh *bm, BMVert *v)
{
/* logic for 3 or more is identical */
@@ -87,9 +62,6 @@ bool BM_vert_dissolve(BMesh *bm, BMVert *v)
return BM_disk_dissolve(bm, v);
}
-/**
- * dissolves all faces around a vert, and removes it.
- */
bool BM_disk_dissolve(BMesh *bm, BMVert *v)
{
BMEdge *e, *keepedge = NULL, *baseedge = NULL;
@@ -205,19 +177,6 @@ bool BM_disk_dissolve(BMesh *bm, BMVert *v)
return true;
}
-/**
- * \brief Faces Join Pair
- *
- * Joins two adjacent faces together.
- *
- * \note This method calls to #BM_faces_join to do its work.
- * This means connected edges which also share the two faces will be joined.
- *
- * If the windings do not match the winding of the new face will follow
- * \a l_a's winding (i.e. \a l_b will be reversed before the join).
- *
- * \return The combined face or NULL on failure.
- */
BMFace *BM_faces_join_pair(BMesh *bm, BMLoop *l_a, BMLoop *l_b, const bool do_del)
{
BLI_assert((l_a != l_b) && (l_a->e == l_b->e));
@@ -231,24 +190,6 @@ BMFace *BM_faces_join_pair(BMesh *bm, BMLoop *l_a, BMLoop *l_b, const bool do_de
return BM_faces_join(bm, faces, 2, do_del);
}
-/**
- * \brief Face Split
- *
- * 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 l_a, l_b: Loops of this face, their vertices define
- * the split edge to be created (must be differ and not can't be adjacent in the face).
- * \param r_l: pointer which will receive the BMLoop for the split edge in the new face
- * \param example: Edge used for attributes of splitting edge, if non-NULL
- * \param no_double: Use an existing edge if found
- *
- * \return Pointer to the newly created face representing one side of the split
- * if the split is successful (and the original face will be the other side).
- * NULL if the split fails.
- */
BMFace *BM_face_split(BMesh *bm,
BMFace *f,
BMLoop *l_a,
@@ -313,24 +254,6 @@ BMFace *BM_face_split(BMesh *bm,
return f_new;
}
-/**
- * \brief Face Split with intermediate points
- *
- * Like BM_face_split, but with an edge split by \a n intermediate points with given coordinates.
- *
- * \param bm: The bmesh.
- * \param f: the original face.
- * \param l_a, l_b: Vertices which define the split edge, must be different.
- * \param cos: Array of coordinates for intermediate points.
- * \param n: Length of \a cos (must be > 0).
- * \param r_l: pointer which will receive the BMLoop.
- * for the first split edge (from \a l_a) in the new face.
- * \param example: Edge used for attributes of splitting edge, if non-NULL.
- *
- * \return Pointer to the newly created face representing one side of the split
- * if the split is successful (and the original face will be the other side).
- * NULL if the split fails.
- */
BMFace *BM_face_split_n(BMesh *bm,
BMFace *f,
BMLoop *l_a,
@@ -404,29 +327,6 @@ BMFace *BM_face_split_n(BMesh *bm,
return f_new;
}
-/**
- * \brief Vert Collapse Faces
- *
- * Collapses vertex \a v_kill 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.
- *
- * \param bm: The bmesh
- * \param e_kill: The edge to collapse
- * \param v_kill: 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 *e_kill,
BMVert *v_kill,
@@ -513,13 +413,6 @@ BMEdge *BM_vert_collapse_faces(BMesh *bm,
return e_new;
}
-/**
- * \brief Vert Collapse Faces
- *
- * Collapses a vertex onto another vertex it shares an edge with.
- *
- * \return The New Edge
- */
BMEdge *BM_vert_collapse_edge(BMesh *bm,
BMEdge *e_kill,
BMVert *v_kill,
@@ -560,34 +453,12 @@ BMEdge *BM_vert_collapse_edge(BMesh *bm,
#undef DO_V_INTERP
-/**
- * Collapse and edge into a single vertex.
- */
BMVert *BM_edge_collapse(
BMesh *bm, BMEdge *e_kill, BMVert *v_kill, const bool do_del, const bool kill_degenerate_faces)
{
return bmesh_kernel_join_vert_kill_edge(bm, e_kill, v_kill, do_del, true, kill_degenerate_faces);
}
-/**
- * \brief Edge Split
- *
- * <pre>
- * Before: v
- * +-----------------------------------+
- * e
- *
- * After: v v_new (returned)
- * +-----------------+-----------------+
- * r_e e
- * </pre>
- *
- * \param e: The edge to split.
- * \param v: One of the vertices in \a e and defines the "from" end of the splitting operation,
- * the new vertex will be \a fac of the way from \a v to the other end.
- * \param r_e: The newly created edge.
- * \return The new vertex.
- */
BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac)
{
BMVert *v_new, *v_other;
@@ -703,11 +574,6 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac)
return v_new;
}
-/**
- * \brief Split an edge multiple times evenly
- *
- * \param r_varr: Optional array, verts in between (v1 -> v2)
- */
BMVert *BM_edge_split_n(BMesh *bm, BMEdge *e, int numcuts, BMVert **r_varr)
{
int i;
@@ -725,11 +591,6 @@ BMVert *BM_edge_split_n(BMesh *bm, BMEdge *e, int numcuts, BMVert **r_varr)
return v_new;
}
-/**
- * Swap v1 & v2
- *
- * \note Typically we shouldn't care about this, however it's used when extruding wire edges.
- */
void BM_edge_verts_swap(BMEdge *e)
{
SWAP(BMVert *, e->v1, e->v2);
@@ -785,20 +646,6 @@ bool BM_face_validate(BMFace *face, FILE *err)
}
#endif
-/**
- * Calculate the 2 loops which _would_ make up the newly rotated Edge
- * but don't actually change anything.
- *
- * Use this to further inspect if the loops to be connected have issues:
- *
- * Examples:
- * - the newly formed edge already exists
- * - the new face would be degenerate (zero area / concave / bow-tie)
- * - may want to measure if the new edge gives improved results topology.
- * over the old one, as with beauty fill.
- *
- * \note #BM_edge_rotate_check must have already run.
- */
void BM_edge_calc_rotate(BMEdge *e, const bool ccw, BMLoop **r_l1, BMLoop **r_l2)
{
BMVert *v1, *v2;
@@ -825,12 +672,6 @@ void BM_edge_calc_rotate(BMEdge *e, const bool ccw, BMLoop **r_l1, BMLoop **r_l2
*r_l2 = BM_face_other_vert_loop(fa, v1, v2);
}
-/**
- * \brief Check if Rotate Edge is OK
- *
- * Quick check to see if we could rotate the edge,
- * use this to avoid calling exceptions on common cases.
- */
bool BM_edge_rotate_check(BMEdge *e)
{
BMFace *fa, *fb;
@@ -860,17 +701,6 @@ bool BM_edge_rotate_check(BMEdge *e)
return false;
}
-/**
- * \brief Check if Edge Rotate Gives Degenerate Faces
- *
- * Check 2 cases
- * 1) does the newly forms edge form a flipped face (compare with previous cross product)
- * 2) does the newly formed edge cause a zero area corner (or close enough to be almost zero)
- *
- * \param e: The edge to test rotation.
- * \param l1, l2: are the loops of the proposed verts to rotate too and should
- * be the result of calling #BM_edge_calc_rotate
- */
bool BM_edge_rotate_check_degenerate(BMEdge *e, BMLoop *l1, BMLoop *l2)
{
/* NOTE: for these vars 'old' just means initial edge state. */
@@ -966,20 +796,6 @@ bool BM_edge_rotate_check_beauty(BMEdge *e, BMLoop *l1, BMLoop *l2)
return (len_squared_v3v3(e->v1->co, e->v2->co) > len_squared_v3v3(l1->v->co, l2->v->co));
}
-/**
- * \brief Rotate Edge
- *
- * Spins an edge topologically,
- * either counter-clockwise or clockwise depending on \a ccw.
- *
- * \return The spun edge, 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.
- *
- * \see header definition for \a check_flag enum.
- */
BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const bool ccw, const short check_flag)
{
BMVert *v1, *v2;
@@ -1091,9 +907,6 @@ BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const bool ccw, const short check_f
return e_new;
}
-/**
- * \brief Rip a single face from a vertex fan
- */
BMVert *BM_face_loop_separate(BMesh *bm, BMLoop *l_sep)
{
return bmesh_kernel_unglue_region_make_vert(bm, l_sep);
diff --git a/source/blender/bmesh/intern/bmesh_mods.h b/source/blender/bmesh/intern/bmesh_mods.h
index 4328187b95e..f4a5a0bce33 100644
--- a/source/blender/bmesh/intern/bmesh_mods.h
+++ b/source/blender/bmesh/intern/bmesh_mods.h
@@ -20,14 +20,73 @@
* \ingroup bmesh
*/
+/**
+ * \brief Dissolve Vert
+ *
+ * Turns the face region surrounding a manifold vertex into a single polygon.
+ *
+ * \par Example:
+ * <pre>
+ * +---------+ +---------+
+ * | \ / | | |
+ * Before: | v | After: | |
+ * | / \ | | |
+ * +---------+ +---------+
+ * </pre>
+ *
+ * This function can also collapse edges too
+ * in cases when it can't merge into faces.
+ *
+ * \par Example:
+ * <pre>
+ * Before: +----v----+ After: +---------+
+ * </pre>
+ *
+ * \note dissolves vert, in more situations than BM_disk_dissolve
+ * (e.g. if the vert is part of a wire edge, etc).
+ */
bool BM_vert_dissolve(BMesh *bm, BMVert *v);
+/**
+ * dissolves all faces around a vert, and removes it.
+ */
bool BM_disk_dissolve(BMesh *bm, BMVert *v);
+/**
+ * \brief Faces Join Pair
+ *
+ * Joins two adjacent faces together.
+ *
+ * \note This method calls to #BM_faces_join to do its work.
+ * This means connected edges which also share the two faces will be joined.
+ *
+ * If the windings do not match the winding of the new face will follow
+ * \a l_a's winding (i.e. \a l_b will be reversed before the join).
+ *
+ * \return The combined face or NULL on failure.
+ */
BMFace *BM_faces_join_pair(BMesh *bm, BMLoop *l_a, BMLoop *l_b, const bool do_del);
/** see: bmesh_polygon_edgenet.h for #BM_face_split_edgenet */
+/**
+ * \brief Face Split
+ *
+ * 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 l_a, l_b: Loops of this face, their vertices define
+ * the split edge to be created (must be differ and not can't be adjacent in the face).
+ * \param r_l: pointer which will receive the BMLoop for the split edge in the new face
+ * \param example: Edge used for attributes of splitting edge, if non-NULL
+ * \param no_double: Use an existing edge if found
+ *
+ * \return Pointer to the newly created face representing one side of the split
+ * if the split is successful (and the original face will be the other side).
+ * NULL if the split fails.
+ */
BMFace *BM_face_split(BMesh *bm,
BMFace *f,
BMLoop *l_a,
@@ -36,6 +95,24 @@ BMFace *BM_face_split(BMesh *bm,
BMEdge *example,
const bool no_double);
+/**
+ * \brief Face Split with intermediate points
+ *
+ * Like BM_face_split, but with an edge split by \a n intermediate points with given coordinates.
+ *
+ * \param bm: The bmesh.
+ * \param f: the original face.
+ * \param l_a, l_b: Vertices which define the split edge, must be different.
+ * \param cos: Array of coordinates for intermediate points.
+ * \param n: Length of \a cos (must be > 0).
+ * \param r_l: pointer which will receive the BMLoop.
+ * for the first split edge (from \a l_a) in the new face.
+ * \param example: Edge used for attributes of splitting edge, if non-NULL.
+ *
+ * \return Pointer to the newly created face representing one side of the split
+ * if the split is successful (and the original face will be the other side).
+ * NULL if the split fails.
+ */
BMFace *BM_face_split_n(BMesh *bm,
BMFace *f,
BMLoop *l_a,
@@ -45,6 +122,29 @@ BMFace *BM_face_split_n(BMesh *bm,
BMLoop **r_l,
BMEdge *example);
+/**
+ * \brief Vert Collapse Faces
+ *
+ * Collapses vertex \a v_kill 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.
+ *
+ * \param bm: The bmesh
+ * \param e_kill: The edge to collapse
+ * \param v_kill: 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 *e_kill,
BMVert *v_kill,
@@ -53,6 +153,13 @@ BMEdge *BM_vert_collapse_faces(BMesh *bm,
const bool join_faces,
const bool kill_degenerate_faces,
const bool kill_duplicate_faces);
+/**
+ * \brief Vert Collapse Faces
+ *
+ * Collapses a vertex onto another vertex it shares an edge with.
+ *
+ * \return The New Edge
+ */
BMEdge *BM_vert_collapse_edge(BMesh *bm,
BMEdge *e_kill,
BMVert *v_kill,
@@ -60,24 +167,101 @@ BMEdge *BM_vert_collapse_edge(BMesh *bm,
const bool kill_degenerate_faces,
const bool kill_duplicate_faces);
+/**
+ * Collapse and edge into a single vertex.
+ */
BMVert *BM_edge_collapse(BMesh *bm,
BMEdge *e_kill,
BMVert *v_kill,
const bool do_del,
const bool kill_degenerate_faces);
+/**
+ * \brief Edge Split
+ *
+ * <pre>
+ * Before: v
+ * +-----------------------------------+
+ * e
+ *
+ * After: v v_new (returned)
+ * +-----------------+-----------------+
+ * r_e e
+ * </pre>
+ *
+ * \param e: The edge to split.
+ * \param v: One of the vertices in \a e and defines the "from" end of the splitting operation,
+ * the new vertex will be \a fac of the way from \a v to the other end.
+ * \param r_e: The newly created edge.
+ * \return The new vertex.
+ */
BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac);
+/**
+ * \brief Split an edge multiple times evenly
+ *
+ * \param r_varr: Optional array, verts in between (v1 -> v2)
+ */
BMVert *BM_edge_split_n(BMesh *bm, BMEdge *e, int numcuts, BMVert **r_varr);
+/**
+ * Swap v1 & v2
+ *
+ * \note Typically we shouldn't care about this, however it's used when extruding wire edges.
+ */
void BM_edge_verts_swap(BMEdge *e);
bool BM_face_validate(BMFace *face, FILE *err);
+/**
+ * Calculate the 2 loops which _would_ make up the newly rotated Edge
+ * but don't actually change anything.
+ *
+ * Use this to further inspect if the loops to be connected have issues:
+ *
+ * Examples:
+ * - the newly formed edge already exists
+ * - the new face would be degenerate (zero area / concave / bow-tie)
+ * - may want to measure if the new edge gives improved results topology.
+ * over the old one, as with beauty fill.
+ *
+ * \note #BM_edge_rotate_check must have already run.
+ */
void BM_edge_calc_rotate(BMEdge *e, const bool ccw, BMLoop **r_l1, BMLoop **r_l2);
+/**
+ * \brief Check if Rotate Edge is OK
+ *
+ * Quick check to see if we could rotate the edge,
+ * use this to avoid calling exceptions on common cases.
+ */
bool BM_edge_rotate_check(BMEdge *e);
+/**
+ * \brief Check if Edge Rotate Gives Degenerate Faces
+ *
+ * Check 2 cases
+ * 1) does the newly forms edge form a flipped face (compare with previous cross product)
+ * 2) does the newly formed edge cause a zero area corner (or close enough to be almost zero)
+ *
+ * \param e: The edge to test rotation.
+ * \param l1, l2: are the loops of the proposed verts to rotate too and should
+ * be the result of calling #BM_edge_calc_rotate
+ */
bool BM_edge_rotate_check_degenerate(BMEdge *e, BMLoop *l1, BMLoop *l2);
bool BM_edge_rotate_check_beauty(BMEdge *e, BMLoop *l1, BMLoop *l2);
+/**
+ * \brief Rotate Edge
+ *
+ * Spins an edge topologically,
+ * either counter-clockwise or clockwise depending on \a ccw.
+ *
+ * \return The spun edge, 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.
+ *
+ * \see header definition for \a check_flag enum.
+ */
BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const bool ccw, const short check_flag);
/** Flags for #BM_edge_rotate */
@@ -92,6 +276,9 @@ enum {
BM_EDGEROT_CHECK_BEAUTY = (1 << 3),
};
+/**
+ * \brief Rip a single face from a vertex fan
+ */
BMVert *BM_face_loop_separate(BMesh *bm, BMLoop *l_sep);
BMVert *BM_face_loop_separate_multi_isolated(BMesh *bm, BMLoop *l_sep);
BMVert *BM_face_loop_separate_multi(BMesh *bm, BMLoop **larr, int larr_len);
diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h
index 0f9488bd091..c60e8af68e5 100644
--- a/source/blender/bmesh/intern/bmesh_operator_api.h
+++ b/source/blender/bmesh/intern/bmesh_operator_api.h
@@ -341,50 +341,161 @@ typedef struct BMOpDefine {
BMOpTypeFlag type_flag;
} BMOpDefine;
-/*------------- Operator API --------------*/
-
-/* data types that use pointers (arrays, etc) should never
- * have it set directly. and never use BMO_slot_ptr_set to
- * pass in a list of edges or any arrays, really. */
+/* -------------------------------------------------------------------- */
+/** \name BMesh Operator API
+ *
+ * \note data types that use pointers (arrays, etc) must _never_ have it set directly.
+ * Don't #BMO_slot_ptr_set to pass in a list of edges or any arrays.
+ * \{ */
+/**
+ * \brief BMESH OPSTACK INIT OP
+ *
+ * Initializes an operator structure to a certain type
+ */
void BMO_op_init(BMesh *bm, BMOperator *op, const int flag, const char *opname);
-/* executes an operator, pushing and popping a new tool flag
- * layer as appropriate. */
+/**
+ * \brief BMESH OPSTACK EXEC OP
+ *
+ * Executes a passed in operator.
+ *
+ * This handles the allocation and freeing of temporary tool 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);
-/* finishes an operator (though note the operator's tool flag is removed
- * after it finishes executing in BMO_op_exec). */
+/**
+ * \brief BMESH OPSTACK FINISH OP
+ *
+ * Does housekeeping chores related to finishing up an operator.
+ *
+ * \note the operator's tool flag is removed after it finishes executing in #BMO_op_exec.
+ */
void BMO_op_finish(BMesh *bm, BMOperator *op);
-/* count the number of elements with the specified flag enabled.
- * type can be a bitmask of BM_FACE, BM_EDGE, or BM_FACE. */
+/**
+ * Count the number of elements with the specified flag enabled.
+ * type can be a bit-mask of #BM_FACE, #BM_EDGE, or #BM_FACE.
+ */
int BMO_mesh_enabled_flag_count(BMesh *bm, const char htype, const short oflag);
-/* count the number of elements with the specified flag disabled.
- * type can be a bitmask of BM_FACE, BM_EDGE, or BM_FACE. */
+/**
+ * Count the number of elements with the specified flag disabled.
+ * type can be a bit-mask of #BM_FACE, #BM_EDGE, or #BM_FACE.
+ */
int BMO_mesh_disabled_flag_count(BMesh *bm, const char htype, const short oflag);
-/*---------formatted operator initialization/execution-----------*/
+/**
+ * \brief BMESH OPSTACK PUSH
+ *
+ * Pushes the operator-stack down one level and allocates a new flag layer if appropriate.
+ */
void BMO_push(BMesh *bm, BMOperator *op);
+/**
+ * \brief BMESH OPSTACK POP
+ *
+ * Pops the operator-stack one level and frees a flag layer if appropriate
+ *
+ * BMESH_TODO: investigate NOT freeing flag layers.
+ */
void BMO_pop(BMesh *bm);
-/* Executes an operator. */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Formatted Operator Initialization/Execution
+ *
+ * Format Strings for #BMOperator Initialization.
+ *
+ * This system is used to execute or initialize an operator,
+ * using a formatted-string system.
+ *
+ * The basic format for the format string is:
+ * `[operatorname] [slot_name]=%[code] [slot_name]=%[code]`
+ *
+ * Example:
+ *
+ * \code{.c}
+ * BMO_op_callf(bm, BMO_FLAG_DEFAULTS,
+ * "delete context=%i geom=%hv",
+ * DEL_ONLYFACES, BM_ELEM_SELECT);
+ * \endcode
+ * **Primitive Types**
+ * - `b` - boolean (same as int but 1/0 only). #BMO_OP_SLOT_BOOL
+ * - `i` - int. #BMO_OP_SLOT_INT
+ * - `f` - float. #BMO_OP_SLOT_FLT
+ * - `p` - pointer (normally to a Scene/Mesh/Object/BMesh). #BMO_OP_SLOT_PTR
+ * - `m3` - 3x3 matrix of floats. #BMO_OP_SLOT_MAT
+ * - `m4` - 4x4 matrix of floats. #BMO_OP_SLOT_MAT
+ * - `v` - 3D vector of floats. #BMO_OP_SLOT_VEC
+ * **Utility**
+ *
+ * Pass an existing slot which is copied to either an input or output slot.
+ * Taking the operator and slot-name pair of args (BMOperator *, const char *).
+ * - `s` - slot_in (lower case)
+ * - `S` - slot_out (upper case)
+ * **Element Buffer** (#BMO_OP_SLOT_ELEMENT_BUF)
+ * - `e` - single element vert/edge/face (use with #BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE).
+ * - `eb` - elem buffer, take an array and a length.
+ * - `av` - all verts
+ * - `ae` - all edges
+ * - `af` - all faces
+ * - `hv` - header flagged verts (hflag)
+ * - `he` - header flagged edges (hflag)
+ * - `hf` - header flagged faces (hflag)
+ * - `Hv` - header flagged verts (hflag off)
+ * - `He` - header flagged edges (hflag off)
+ * - `Hf` - header flagged faces (hflag off)
+ * - `fv` - flagged verts (oflag)
+ * - `fe` - flagged edges (oflag)
+ * - `ff` - flagged faces (oflag)
+ * - `Fv` - flagged verts (oflag off)
+ * - `Fe` - flagged edges (oflag off)
+ * - `Ff` - flagged faces (oflag off)
+ *
+ * \note The common v/e/f suffix can be mixed,
+ * so `avef` is can be used for all verts, edges and faces.
+ * Order is not important so `Hfev` is also valid (all un-flagged verts, edges and faces).
+ *
+ * \{ */
+
+/** Executes an operator. */
bool BMO_op_callf(BMesh *bm, const int flag, const char *fmt, ...);
-/* initializes, but doesn't execute an operator. this is so you can
+/**
+ * Initializes, but doesn't execute an operator. this is so you can
* gain access to the outputs of the operator. note that you have
- * to execute/finish (BMO_op_exec and BMO_op_finish) yourself. */
+ * to execute/finish (BMO_op_exec and BMO_op_finish) yourself.
+ */
bool BMO_op_initf(BMesh *bm, BMOperator *op, const int flag, const char *fmt, ...);
-/* va_list version, used to implement the above two functions,
- * plus EDBM_op_callf in editmesh_utils.c. */
+/**
+ * A `va_list` version, used to implement the above two functions,
+ * plus #EDBM_op_callf in editmesh_utils.c.
+ */
bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *fmt, va_list vlist);
-/* test whether a named slot exists */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name BMesh Operator Slot Access
+ * \{ */
+
+/**
+ * \brief BMESH OPSTACK HAS SLOT
+ *
+ * \return Success if the slot if found.
+ */
bool BMO_slot_exists(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier);
/* get a pointer to a slot. this may be removed layer on from the public API. */
+/**
+ * \brief BMESH OPSTACK GET SLOT
+ *
+ * Returns a pointer to the slot of type 'slot_code'
+ */
BMOpSlot *BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier);
/* copies the data of a slot from one operator to another. src and dst are the
@@ -393,12 +504,20 @@ BMOpSlot *BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identif
_bmo_slot_copy( \
(op_src)->slots_src, slot_name_src, (op_dst)->slots_dst, slot_name_dst, (op_dst)->arena)
+/**
+ * \brief BMESH OPSTACK COPY SLOT
+ *
+ * define used.
+ * Copies data from one slot to another.
+ */
void _bmo_slot_copy(BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS],
const char *slot_name_src,
BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS],
const char *slot_name_dst,
struct MemArena *arena_dst);
+/** \} */
+
/* del "context" slot values, used for operator too */
enum {
DEL_VERTS = 1,
@@ -433,6 +552,10 @@ typedef enum {
void BMO_op_flag_enable(BMesh *bm, BMOperator *op, const int op_flag);
void BMO_op_flag_disable(BMesh *bm, BMOperator *op, const int op_flag);
+/* -------------------------------------------------------------------- */
+/** \name BMesh Operator Slot Get/Set
+ * \{ */
+
void BMO_slot_float_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
const char *slot_name,
const float f);
@@ -441,13 +564,17 @@ void BMO_slot_int_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_nam
int BMO_slot_int_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
void BMO_slot_bool_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const bool i);
bool BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
+/**
+ * Return a copy of the element buffer.
+ */
void *BMO_slot_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, int *len);
-/* don't pass in arrays that are supposed to map to elements this way.
+/**
+ * Don't pass in arrays that are supposed to map to elements this way.
*
* so, e.g. passing in list of floats per element in another slot is bad.
- * passing in, e.g. pointer to an editmesh for the conversion operator is fine
- * though. */
+ * passing in, e.g. pointer to an edit-mesh for the conversion operator is fine though.
+ */
void BMO_slot_ptr_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, void *p);
void *BMO_slot_ptr_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
void BMO_slot_vec_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
@@ -455,10 +582,12 @@ void BMO_slot_vec_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
const float vec[3]);
void BMO_slot_vec_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_vec[3]);
-/* only supports square mats */
-/* size must be 3 or 4; this api is meant only for transformation matrices.
- * note that internally the matrix is stored in 4x4 form, and it's safe to
- * call whichever BMO_Get_MatXXX function you want. */
+/**
+ * Only supports square matrices.
+ * size must be 3 or 4; this api is meant only for transformation matrices.
+ *
+ * \note the matrix is stored in 4x4 form, and it's safe to call whichever function you want.
+ */
void BMO_slot_mat_set(BMOperator *op,
BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
const char *slot_name,
@@ -471,6 +600,8 @@ void BMO_slot_mat3_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
const char *slot_name,
float r_mat[3][3]);
+/** \} */
+
void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *op, const char htype, const short oflag);
void BMO_mesh_selected_remap(BMesh *bm,
@@ -479,19 +610,25 @@ void BMO_mesh_selected_remap(BMesh *bm,
BMOpSlot *slot_face_map,
const bool check_select);
-/* copies the values from another slot to the end of the output slot */
+/**
+ * Copies the values from another slot to the end of the output slot.
+ */
#define BMO_slot_buffer_append( \
op_src, slots_src, slot_name_src, op_dst, slots_dst, slot_name_dst) \
_bmo_slot_buffer_append( \
(op_src)->slots_src, slot_name_src, (op_dst)->slots_dst, slot_name_dst, (op_dst)->arena)
+/**
+ * Copies the values from another slot to the end of the output slot.
+ */
void _bmo_slot_buffer_append(BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS],
const char *slot_name_dst,
BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS],
const char *slot_name_src,
struct MemArena *arena_dst);
-/* puts every element of type 'type' (which is a bitmask) with tool
- * flag 'flag', into a slot. */
+/**
+ * Puts every element of type 'type' (which is a bit-mask) with tool flag 'flag', into a slot.
+ */
void BMO_slot_buffer_from_enabled_flag(BMesh *bm,
BMOperator *op,
BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
@@ -499,8 +636,9 @@ void BMO_slot_buffer_from_enabled_flag(BMesh *bm,
const char htype,
const short oflag);
-/* puts every element of type 'type' (which is a bitmask) without tool
- * flag 'flag', into a slot. */
+/**
+ * Puts every element of type 'type' (which is a bit-mask) without tool flag 'flag', into a slot.
+ */
void BMO_slot_buffer_from_disabled_flag(BMesh *bm,
BMOperator *op,
BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
@@ -508,27 +646,45 @@ void BMO_slot_buffer_from_disabled_flag(BMesh *bm,
const char htype,
const short oflag);
-/* tool-flags all elements inside an element slot array with flag flag. */
+/**
+ * \brief BMO_FLAG_BUFFER
+ *
+ * Flags elements in a slots buffer
+ */
void BMO_slot_buffer_flag_enable(BMesh *bm,
BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
const char *slot_name,
const char htype,
const short oflag);
-/* clears tool-flag flag from all elements inside a slot array. */
+/**
+ * \brief BMO_FLAG_BUFFER
+ *
+ * Removes flags from elements in a slots buffer
+ */
void BMO_slot_buffer_flag_disable(BMesh *bm,
BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
const char *slot_name,
const char htype,
const short oflag);
-/* tool-flags all elements inside an element slot array with flag flag. */
+/**
+ * \brief BMO_FLAG_BUFFER
+ *
+ * Header Flags elements in a slots buffer, automatically
+ * using the selection API where appropriate.
+ */
void BMO_slot_buffer_hflag_enable(BMesh *bm,
BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
const char *slot_name,
const char htype,
const char hflag,
const bool do_flush);
-/* clears tool-flag flag from all elements inside a slot array. */
+/**
+ * \brief BMO_FLAG_BUFFER
+ *
+ * Removes flags from elements in a slots buffer, automatically
+ * using the selection API where appropriate.
+ */
void BMO_slot_buffer_hflag_disable(BMesh *bm,
BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
const char *slot_name,
@@ -536,19 +692,20 @@ void BMO_slot_buffer_hflag_disable(BMesh *bm,
const char hflag,
const bool do_flush);
-/* puts every element of type 'type' (which is a bitmask) with header
- * flag 'flag', into a slot. NOTE: ignores hidden elements
- * (e.g. elements with header flag BM_ELEM_HIDDEN set). */
+/**
+ * Puts every element of type 'type' (which is a bit-mask) with header flag 'flag', into a slot.
+ * \note ignores hidden elements (e.g. elements with header flag BM_ELEM_HIDDEN set).
+ */
void BMO_slot_buffer_from_enabled_hflag(BMesh *bm,
BMOperator *op,
BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
const char *slot_name,
const char htype,
const char hflag);
-
-/* puts every element of type 'type' (which is a bitmask) without
- * header flag 'flag', into a slot. NOTE: ignores hidden elements
- * (e.g. elements with header flag BM_ELEM_HIDDEN set). */
+/**
+ * Puts every element of type 'type' (which is a bit-mask) without header flag 'flag', into a slot.
+ * \note ignores hidden elements (e.g. elements with header flag BM_ELEM_HIDDEN set).
+ */
void BMO_slot_buffer_from_disabled_hflag(BMesh *bm,
BMOperator *op,
BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
@@ -564,14 +721,21 @@ void BMO_slot_buffer_from_array(BMOperator *op,
void BMO_slot_buffer_from_single(BMOperator *op, BMOpSlot *slot, BMHeader *ele);
void *BMO_slot_buffer_get_single(BMOpSlot *slot);
-/* counts number of elements inside a slot array. */
+/** Return the number of elements inside a slot array. */
int BMO_slot_buffer_len(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
+/** Return the number of elements inside a slot map. */
int BMO_slot_map_len(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
+/**
+ * Inserts a key/value mapping into a mapping slot. note that it copies the
+ * value, it doesn't store a reference to it.
+ */
void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot, const void *element, const void *data);
-/* flags all elements in a mapping. note that the mapping must only have
- * bmesh elements in it. */
+/**
+ * Flags all elements in a mapping.
+ * \note that the mapping must only have #BMesh elements in it.
+ */
void BMO_slot_map_to_flag(BMesh *bm,
BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
const char *slot_name,
@@ -583,6 +747,11 @@ void *BMO_slot_buffer_alloc(BMOperator *op,
const char *slot_name,
const int len);
+/**
+ * \brief BMO_ALL_TO_SLOT
+ *
+ * Copies all elements of a certain type into an operator slot.
+ */
void BMO_slot_buffer_from_all(BMesh *bm,
BMOperator *op,
BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
@@ -636,12 +805,22 @@ typedef struct BMOIter {
void *BMO_slot_buffer_get_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name);
+/**
+ * \brief New Iterator
+ *
+ * \param restrictmask: restricts the iteration to certain element types
+ * (e.g. combination of BM_VERT, BM_EDGE, BM_FACE), if iterating
+ * over an element buffer (not a mapping). */
void *BMO_iter_new(BMOIter *iter,
BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
const char *slot_name,
const char restrictmask);
void *BMO_iter_step(BMOIter *iter);
+/**
+ * Returns a pointer to the key-value when iterating over mappings.
+ * remember for pointer maps this will be a pointer to a pointer.
+ */
void **BMO_iter_map_value_p(BMOIter *iter);
void *BMO_iter_map_value_ptr(BMOIter *iter);
@@ -660,6 +839,7 @@ bool BMO_iter_map_value_bool(BMOIter *iter);
ele; \
BM_CHECK_TYPE_ELEM_ASSIGN(ele) = BMO_iter_step(iter), i_++)
+/* operator slot type information - size of one element of the type given. */
extern const int BMO_OPSLOT_TYPEINFO[BMO_OP_SLOT_TOTAL_TYPES];
int BMO_opcode_from_opname(const char *opname);
diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c
index 221994aa313..dd35f0feee7 100644
--- a/source/blender/bmesh/intern/bmesh_operators.c
+++ b/source/blender/bmesh/intern/bmesh_operators.c
@@ -42,7 +42,6 @@ static int bmo_name_to_slotcode(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char
static int bmo_name_to_slotcode_check(BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
const char *identifier);
-/* operator slot type information - size of one element of the type given. */
const int BMO_OPSLOT_TYPEINFO[BMO_OP_SLOT_TOTAL_TYPES] = {
0, /* 0: BMO_OP_SLOT_SENTINEL */
sizeof(int), /* 1: BMO_OP_SLOT_BOOL */
@@ -70,11 +69,6 @@ void BMO_op_flag_disable(BMesh *UNUSED(bm), BMOperator *op, const int op_flag)
op->flag &= ~op_flag;
}
-/**
- * \brief BMESH OPSTACK PUSH
- *
- * Pushes the opstack down one level and allocates a new flag layer if appropriate.
- */
void BMO_push(BMesh *bm, BMOperator *UNUSED(op))
{
bm->toolflag_index++;
@@ -90,13 +84,6 @@ void BMO_push(BMesh *bm, BMOperator *UNUSED(op))
}
}
-/**
- * \brief BMESH OPSTACK POP
- *
- * Pops the opstack one level and frees a flag layer if appropriate
- *
- * BMESH_TODO: investigate NOT freeing flag layers.
- */
void BMO_pop(BMesh *bm)
{
if (bm->toolflag_index > 0) {
@@ -152,11 +139,6 @@ static void bmo_op_slots_free(const BMOSlotType *slot_types, BMOpSlot *slot_args
}
}
-/**
- * \brief BMESH OPSTACK INIT OP
- *
- * Initializes an operator structure to a certain type
- */
void BMO_op_init(BMesh *bm, BMOperator *op, const int flag, const char *opname)
{
int opcode = BMO_opcode_from_opname(opname);
@@ -188,15 +170,6 @@ void BMO_op_init(BMesh *bm, BMOperator *op, const int flag, const char *opname)
BLI_memarena_use_calloc(op->arena);
}
-/**
- * \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.
- */
void BMO_op_exec(BMesh *bm, BMOperator *op)
{
/* allocate tool flags on demand */
@@ -216,11 +189,6 @@ void BMO_op_exec(BMesh *bm, BMOperator *op)
BMO_pop(bm);
}
-/**
- * \brief BMESH OPSTACK FINISH OP
- *
- * Does housekeeping chores related to finishing up an operator.
- */
void BMO_op_finish(BMesh *bm, BMOperator *op)
{
bmo_op_slots_free(bmo_opdefines[op->type]->slot_types_in, op->slots_in);
@@ -238,22 +206,12 @@ void BMO_op_finish(BMesh *bm, BMOperator *op)
#endif
}
-/**
- * \brief BMESH OPSTACK HAS SLOT
- *
- * \return Success if the slot if found.
- */
bool BMO_slot_exists(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier)
{
int slot_code = bmo_name_to_slotcode(slot_args, identifier);
return (slot_code >= 0);
}
-/**
- * \brief BMESH OPSTACK GET SLOT
- *
- * Returns a pointer to the slot of type 'slot_code'
- */
BMOpSlot *BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier)
{
int slot_code = bmo_name_to_slotcode_check(slot_args, identifier);
@@ -267,12 +225,6 @@ BMOpSlot *BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identif
return &slot_args[slot_code];
}
-/**
- * \brief BMESH OPSTACK COPY SLOT
- *
- * define used.
- * Copies data from one slot to another.
- */
void _bmo_slot_copy(BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS],
const char *slot_name_src,
BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS],
@@ -393,7 +345,6 @@ void BMO_slot_bool_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_na
slot->data.i = i;
}
-/* only supports square mats */
void BMO_slot_mat_set(BMOperator *op,
BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
const char *slot_name,
@@ -515,7 +466,6 @@ bool BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_na
return slot->data.i;
}
-/* if you want a copy of the elem buffer */
void *BMO_slot_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, int *len)
{
BMOpSlot *slot = BMO_slot_get(slot_args, slot_name);
@@ -698,9 +648,6 @@ int BMO_slot_map_len(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name
return BLI_ghash_len(slot->data.ghash);
}
-/* inserts a key/value mapping into a mapping slot. note that it copies the
- * value, it doesn't store a reference to it. */
-
void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot, const void *element, const void *data)
{
(void)op; /* Ignored in release builds. */
@@ -796,11 +743,6 @@ void *BMO_slot_buffer_alloc(BMOperator *op,
return slot->data.buf;
}
-/**
- * \brief BMO_ALL_TO_SLOT
- *
- * Copies all elements of a certain type into an operator slot.
- */
void BMO_slot_buffer_from_all(BMesh *bm,
BMOperator *op,
BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
@@ -987,9 +929,6 @@ void *BMO_slot_buffer_get_single(BMOpSlot *slot)
return slot->len ? (BMHeader *)slot->data.buf[0] : NULL;
}
-/**
- * Copies the values from another slot to the end of the output slot.
- */
void _bmo_slot_buffer_append(BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS],
const char *slot_name_dst,
BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS],
@@ -1115,12 +1054,6 @@ void BMO_slot_buffer_from_disabled_flag(BMesh *bm,
bmo_slot_buffer_from_flag(bm, op, slot_args, slot_name, htype, oflag, false);
}
-/**
- * \brief BMO_FLAG_BUFFER
- *
- * Header Flags elements in a slots buffer, automatically
- * using the selection API where appropriate.
- */
void BMO_slot_buffer_hflag_enable(BMesh *bm,
BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
const char *slot_name,
@@ -1155,12 +1088,6 @@ void BMO_slot_buffer_hflag_enable(BMesh *bm,
}
}
-/**
- * \brief BMO_FLAG_BUFFER
- *
- * Removes flags from elements in a slots buffer, automatically
- * using the selection API where appropriate.
- */
void BMO_slot_buffer_hflag_disable(BMesh *bm,
BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
const char *slot_name,
@@ -1194,11 +1121,6 @@ void BMO_slot_buffer_hflag_disable(BMesh *bm,
}
}
-/**
- * \brief BMO_FLAG_BUFFER
- *
- * Flags elements in a slots buffer
- */
void BMO_slot_buffer_flag_enable(BMesh *bm,
BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
const char *slot_name,
@@ -1221,11 +1143,6 @@ void BMO_slot_buffer_flag_enable(BMesh *bm,
}
}
-/**
- * \brief BMO_FLAG_BUFFER
- *
- * Removes flags from elements in a slots buffer
- */
void BMO_slot_buffer_flag_disable(BMesh *bm,
BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
const char *slot_name,
@@ -1434,12 +1351,6 @@ void *BMO_slot_buffer_get_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char
return slot->data.buf ? *slot->data.buf : NULL;
}
-/**
- * \brief New Iterator
- *
- * \param restrictmask: restricts the iteration to certain element types
- * (e.g. combination of BM_VERT, BM_EDGE, BM_FACE), if iterating
- * over an element buffer (not a mapping). */
void *BMO_iter_new(BMOIter *iter,
BMOpSlot slot_args[BMO_OP_MAX_SLOTS],
const char *slot_name,
@@ -1513,10 +1424,6 @@ void *BMO_iter_step(BMOIter *iter)
/* used for iterating over mappings */
-/**
- * Returns a pointer to the key-value when iterating over mappings.
- * remember for pointer maps this will be a pointer to a pointer.
- */
void **BMO_iter_map_value_p(BMOIter *iter)
{
return iter->val;
@@ -1584,7 +1491,6 @@ bool BMO_error_occurred_at_level(BMesh *bm, eBMOpErrorLevel level)
return false;
}
-/* returns error code or 0 if no error */
bool BMO_error_get(BMesh *bm, const char **r_msg, BMOperator **r_op, eBMOpErrorLevel *r_level)
{
BMOpError *err = bm->errorstack.first;
@@ -1694,60 +1600,6 @@ static int BMO_opcode_from_opname_check(const char *opname)
return i;
}
-/**
- * \brief Format Strings for #BMOperator Initialization.
- *
- * This system is used to execute or initialize an operator,
- * using a formatted-string system.
- *
- * The basic format for the format string is:
- * `[operatorname] [slot_name]=%[code] [slot_name]=%[code]`
- *
- * Example:
- *
- * \code{.c}
- * BMO_op_callf(bm, BMO_FLAG_DEFAULTS,
- * "delete context=%i geom=%hv",
- * DEL_ONLYFACES, BM_ELEM_SELECT);
- * \endcode
- * **Primitive Types**
- * - `b` - boolean (same as int but 1/0 only). #BMO_OP_SLOT_BOOL
- * - `i` - int. #BMO_OP_SLOT_INT
- * - `f` - float. #BMO_OP_SLOT_FLT
- * - `p` - pointer (normally to a Scene/Mesh/Object/BMesh). #BMO_OP_SLOT_PTR
- * - `m3` - 3x3 matrix of floats. #BMO_OP_SLOT_MAT
- * - `m4` - 4x4 matrix of floats. #BMO_OP_SLOT_MAT
- * - `v` - 3D vector of floats. #BMO_OP_SLOT_VEC
- * **Utility**
- *
- * Pass an existing slot which is copied to either an input or output slot.
- * Taking the operator and slot-name pair of args (BMOperator *, const char *).
- * - `s` - slot_in (lower case)
- * - `S` - slot_out (upper case)
- * **Element Buffer** (#BMO_OP_SLOT_ELEMENT_BUF)
- * - `e` - single element vert/edge/face (use with #BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE).
- * - `eb` - elem buffer, take an array and a length.
- * - `av` - all verts
- * - `ae` - all edges
- * - `af` - all faces
- * - `hv` - header flagged verts (hflag)
- * - `he` - header flagged edges (hflag)
- * - `hf` - header flagged faces (hflag)
- * - `Hv` - header flagged verts (hflag off)
- * - `He` - header flagged edges (hflag off)
- * - `Hf` - header flagged faces (hflag off)
- * - `fv` - flagged verts (oflag)
- * - `fe` - flagged edges (oflag)
- * - `ff` - flagged faces (oflag)
- * - `Fv` - flagged verts (oflag off)
- * - `Fe` - flagged edges (oflag off)
- * - `Ff` - flagged faces (oflag off)
- *
- * \note The common v/e/f suffix can be mixed,
- * so `avef` is can be used for all verts, edges and faces.
- * Order is not important so `Hfev` is also valid (all un-flagged verts, edges and faces).
- */
-
bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, va_list vlist)
{
// BMOpDefine *def;
diff --git a/source/blender/bmesh/intern/bmesh_operators.h b/source/blender/bmesh/intern/bmesh_operators.h
index a701fe3eb85..83f2c402c35 100644
--- a/source/blender/bmesh/intern/bmesh_operators.h
+++ b/source/blender/bmesh/intern/bmesh_operators.h
@@ -170,17 +170,50 @@ void BM_mesh_esubdivide(BMesh *bm,
const short use_only_quads,
const int seed);
+/**
+ * Fills first available UV-map with grid-like UV's for all faces with `oflag` set.
+ *
+ * \param bm: The BMesh to operate on
+ * \param x_segments: The x-resolution of the grid
+ * \param y_segments: The y-resolution of the grid
+ * \param oflag: The flag to check faces with.
+ */
void BM_mesh_calc_uvs_grid(BMesh *bm,
const uint x_segments,
const uint y_segments,
const short oflag,
const int cd_loop_uv_offset);
+/**
+ * Fills first available UV-map with spherical projected UVs for all faces with `oflag` set.
+ *
+ * \param bm: The BMesh to operate on
+ * \param oflag: The flag to check faces with.
+ */
void BM_mesh_calc_uvs_sphere(BMesh *bm, const short oflag, const int cd_loop_uv_offset);
+/**
+ * Fills first available UV-map with 2D projected UVs for all faces with `oflag` set.
+ *
+ * \param bm: The BMesh to operate on.
+ * \param mat: The transform matrix applied to the created circle.
+ * \param radius: The size of the circle.
+ * \param oflag: The flag to check faces with.
+ */
void BM_mesh_calc_uvs_circle(BMesh *bm,
float mat[4][4],
const float radius,
const short oflag,
const int cd_loop_uv_offset);
+/**
+ * Fills first available UV-map with cylinder/cone-like UVs for all faces with `oflag` set.
+ *
+ * \param bm: The BMesh to operate on.
+ * \param mat: The transform matrix applied to the created cone/cylinder.
+ * \param radius_top: The size of the top end of the cone/cylinder.
+ * \param radius_bottom: The size of the bottom end of the cone/cylinder.
+ * \param segments: The number of subdivisions in the sides of the cone/cylinder.
+ * \param cap_ends: Whether the ends of the cone/cylinder are filled or not.
+ * \param oflag: The flag to check faces with.
+ */
void BM_mesh_calc_uvs_cone(BMesh *bm,
float mat[4][4],
const float radius_top,
@@ -189,6 +222,15 @@ void BM_mesh_calc_uvs_cone(BMesh *bm,
const bool cap_ends,
const short oflag,
const int cd_loop_uv_offset);
+/**
+ * Fills first available UV-map with cube-like UVs for all faces with `oflag` set.
+ *
+ * \note Expects tagged faces to be six quads.
+ * \note Caller must order faces for correct alignment.
+ *
+ * \param bm: The BMesh to operate on.
+ * \param oflag: The flag to check faces with.
+ */
void BM_mesh_calc_uvs_cube(BMesh *bm, const short oflag);
#include "intern/bmesh_operator_api_inline.h"
diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c
index 51ae47adacc..e9eaf865e3c 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.c
+++ b/source/blender/bmesh/intern/bmesh_polygon.c
@@ -117,15 +117,6 @@ static void bm_face_calc_poly_center_median_vertex_cos(const BMFace *f,
mul_v3_fl(r_cent, 1.0f / f->len);
}
-/**
- * For tools that insist on using triangles, ideally we would cache this data.
- *
- * \param use_fixed_quad: When true,
- * always split quad along (0 -> 2) regardless of concave corners,
- * (as done in #BM_mesh_calc_tessellation).
- * \param r_loops: Store face loop pointers, (f->len)
- * \param r_index: Store triangle triples, indices into \a r_loops, `((f->len - 2) * 3)`
- */
void BM_face_calc_tessellation(const BMFace *f,
const bool use_fixed_quad,
BMLoop **r_loops,
@@ -177,9 +168,6 @@ void BM_face_calc_tessellation(const BMFace *f,
}
}
-/**
- * Return a point inside the face.
- */
void BM_face_calc_point_in_face(const BMFace *f, float r_co[3])
{
const BMLoop *l_tri[3];
@@ -218,9 +206,6 @@ void BM_face_calc_point_in_face(const BMFace *f, float r_co[3])
mid_v3_v3v3v3(r_co, l_tri[0]->v->co, l_tri[1]->v->co, l_tri[2]->v->co);
}
-/**
- * get the area of the face
- */
float BM_face_calc_area(const BMFace *f)
{
/* inline 'area_poly_v3' logic, avoid creating a temp array */
@@ -235,9 +220,6 @@ float BM_face_calc_area(const BMFace *f)
return len_v3(n) * 0.5f;
}
-/**
- * Get the area of the face in world space.
- */
float BM_face_calc_area_with_mat3(const BMFace *f, const float mat3[3][3])
{
/* inline 'area_poly_v3' logic, avoid creating a temp array */
@@ -257,9 +239,6 @@ float BM_face_calc_area_with_mat3(const BMFace *f, const float mat3[3][3])
return len_v3(n) * 0.5f;
}
-/**
- * get the area of UV face
- */
float BM_face_calc_area_uv(const BMFace *f, int cd_loop_uv_offset)
{
/* inline 'area_poly_v2' logic, avoid creating a temp array */
@@ -276,9 +255,6 @@ float BM_face_calc_area_uv(const BMFace *f, int cd_loop_uv_offset)
return fabsf(cross * 0.5f);
}
-/**
- * compute the perimeter of an ngon
- */
float BM_face_calc_perimeter(const BMFace *f)
{
const BMLoop *l_iter, *l_first;
@@ -292,9 +268,6 @@ float BM_face_calc_perimeter(const BMFace *f)
return perimeter;
}
-/**
- * Calculate the perimeter of a ngon in world space.
- */
float BM_face_calc_perimeter_with_mat3(const BMFace *f, const float mat3[3][3])
{
const BMLoop *l_iter, *l_first;
@@ -355,14 +328,6 @@ static int bm_vert_tri_find_unique_edge(BMVert *verts[3])
return order[0];
}
-/**
- * Calculate a tangent from any 3 vertices.
- *
- * The tangent aligns to the most *unique* edge
- * (the edge most unlike the other two).
- *
- * \param r_tangent: Calculated unit length tangent (return value).
- */
void BM_vert_tri_calc_tangent_edge(BMVert *verts[3], float r_tangent[3])
{
const int index = bm_vert_tri_find_unique_edge(verts);
@@ -372,14 +337,6 @@ void BM_vert_tri_calc_tangent_edge(BMVert *verts[3], float r_tangent[3])
normalize_v3(r_tangent);
}
-/**
- * Calculate a tangent from any 3 vertices,
- *
- * The tangent follows the center-line formed by the most unique edges center
- * and the opposite vertex.
- *
- * \param r_tangent: Calculated unit length tangent (return value).
- */
void BM_vert_tri_calc_tangent_edge_pair(BMVert *verts[3], float r_tangent[3])
{
const int index = bm_vert_tri_find_unique_edge(verts);
@@ -394,9 +351,6 @@ void BM_vert_tri_calc_tangent_edge_pair(BMVert *verts[3], float r_tangent[3])
normalize_v3(r_tangent);
}
-/**
- * Compute the tangent of the face, using the longest edge.
- */
void BM_face_calc_tangent_edge(const BMFace *f, float r_tangent[3])
{
const BMLoop *l_long = BM_face_find_longest_loop((BMFace *)f);
@@ -406,11 +360,6 @@ void BM_face_calc_tangent_edge(const BMFace *f, float r_tangent[3])
normalize_v3(r_tangent);
}
-/**
- * Compute the tangent of the face, using the two longest disconnected edges.
- *
- * \param r_tangent: Calculated unit length tangent (return value).
- */
void BM_face_calc_tangent_edge_pair(const BMFace *f, float r_tangent[3])
{
if (f->len == 3) {
@@ -471,11 +420,6 @@ void BM_face_calc_tangent_edge_pair(const BMFace *f, float r_tangent[3])
}
}
-/**
- * Compute the tangent of the face, using the edge farthest away from any vertex in the face.
- *
- * \param r_tangent: Calculated unit length tangent (return value).
- */
void BM_face_calc_tangent_edge_diagonal(const BMFace *f, float r_tangent[3])
{
BMLoop *l_iter, *l_first;
@@ -508,11 +452,6 @@ void BM_face_calc_tangent_edge_diagonal(const BMFace *f, float r_tangent[3])
normalize_v3(r_tangent);
}
-/**
- * Compute the tangent of the face, using longest distance between vertices on the face.
- *
- * \note The logic is almost identical to #BM_face_calc_tangent_edge_diagonal
- */
void BM_face_calc_tangent_vert_diagonal(const BMFace *f, float r_tangent[3])
{
BMLoop *l_iter, *l_first;
@@ -541,11 +480,6 @@ void BM_face_calc_tangent_vert_diagonal(const BMFace *f, float r_tangent[3])
normalize_v3(r_tangent);
}
-/**
- * Compute a meaningful direction along the face (use for gizmo axis).
- *
- * \note Callers shouldn't depend on the *exact* method used here.
- */
void BM_face_calc_tangent_auto(const BMFace *f, float r_tangent[3])
{
if (f->len == 3) {
@@ -564,9 +498,6 @@ void BM_face_calc_tangent_auto(const BMFace *f, float r_tangent[3])
}
}
-/**
- * expands bounds (min/max must be initialized).
- */
void BM_face_calc_bounds_expand(const BMFace *f, float min[3], float max[3])
{
const BMLoop *l_iter, *l_first;
@@ -576,9 +507,6 @@ void BM_face_calc_bounds_expand(const BMFace *f, float min[3], float max[3])
} while ((l_iter = l_iter->next) != l_first);
}
-/**
- * computes center of face in 3d. uses center of bounding box.
- */
void BM_face_calc_center_bounds(const BMFace *f, float r_cent[3])
{
const BMLoop *l_iter, *l_first;
@@ -594,9 +522,6 @@ void BM_face_calc_center_bounds(const BMFace *f, float r_cent[3])
mid_v3_v3v3(r_cent, min, max);
}
-/**
- * computes center of face in 3d. uses center of bounding box.
- */
void BM_face_calc_center_bounds_vcos(const BMesh *bm,
const BMFace *f,
float r_cent[3],
@@ -619,9 +544,6 @@ void BM_face_calc_center_bounds_vcos(const BMesh *bm,
mid_v3_v3v3(r_cent, min, max);
}
-/**
- * computes the center of a face, using the mean average
- */
void BM_face_calc_center_median(const BMFace *f, float r_cent[3])
{
const BMLoop *l_iter, *l_first;
@@ -635,10 +557,6 @@ void BM_face_calc_center_median(const BMFace *f, float r_cent[3])
mul_v3_fl(r_cent, 1.0f / (float)f->len);
}
-/**
- * computes the center of a face, using the mean average
- * weighted by edge length
- */
void BM_face_calc_center_median_weighted(const BMFace *f, float r_cent[3])
{
const BMLoop *l_iter;
@@ -663,12 +581,6 @@ void BM_face_calc_center_median_weighted(const BMFace *f, float r_cent[3])
}
}
-/**
- * \brief POLY ROTATE PLANE
- *
- * Rotates a polygon so that its
- * normal is pointing towards the mesh Z axis
- */
void poly_rotate_plane(const float normal[3], float (*verts)[3], const uint nverts)
{
float mat[3][3];
@@ -684,9 +596,6 @@ void poly_rotate_plane(const float normal[3], float (*verts)[3], const uint nver
}
}
-/**
- * updates face and vertex normals incident on an edge
- */
void BM_edge_normals_update(BMEdge *e)
{
BMIter iter;
@@ -800,24 +709,11 @@ void BM_vert_normal_update_all(BMVert *v)
}
}
-/**
- * update a vert normal (but not the faces incident on it)
- */
void BM_vert_normal_update(BMVert *v)
{
BM_vert_calc_normal(v, v->no);
}
-/**
- * \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.
- */
-
float BM_face_calc_normal(const BMFace *f, float r_no[3])
{
BMLoop *l;
@@ -849,7 +745,6 @@ void BM_face_normal_update(BMFace *f)
BM_face_calc_normal(f, f->no);
}
-/* exact same as 'BM_face_calc_normal' but accepts vertex coords */
float BM_face_calc_normal_vcos(const BMesh *bm,
const BMFace *f,
float r_no[3],
@@ -884,12 +779,6 @@ float BM_face_calc_normal_vcos(const BMesh *bm,
}
}
-/**
- * Calculate a normal from a vertex cloud.
- *
- * \note We could make a higher quality version that takes all vertices into account.
- * Currently it finds 4 outer most points returning its normal.
- */
void BM_verts_calc_normal_from_cloud_ex(
BMVert **varr, int varr_len, float r_normal[3], float r_center[3], int *r_index_tangent)
{
@@ -991,9 +880,6 @@ void BM_verts_calc_normal_from_cloud(BMVert **varr, int varr_len, float r_normal
BM_verts_calc_normal_from_cloud_ex(varr, varr_len, r_normal, NULL, NULL);
}
-/**
- * Calculates the face subset normal.
- */
float BM_face_calc_normal_subset(const BMLoop *l_first, const BMLoop *l_last, float r_no[3])
{
const float *v_prev, *v_curr;
@@ -1014,7 +900,6 @@ float BM_face_calc_normal_subset(const BMLoop *l_first, const BMLoop *l_last, fl
return normalize_v3(r_no);
}
-/* exact same as 'BM_face_calc_normal' but accepts vertex coords */
void BM_face_calc_center_median_vcos(const BMesh *bm,
const BMFace *f,
float r_cent[3],
@@ -1027,12 +912,6 @@ void BM_face_calc_center_median_vcos(const BMesh *bm,
bm_face_calc_poly_center_median_vertex_cos(f, r_cent, vertexCos);
}
-/**
- * \brief Face Flip Normal
- *
- * Reverses the winding of a face.
- * \note This updates the calculated normal.
- */
void BM_face_normal_flip_ex(BMesh *bm,
BMFace *f,
const int cd_loop_mdisp_offset,
@@ -1048,16 +927,6 @@ void BM_face_normal_flip(BMesh *bm, BMFace *f)
BM_face_normal_flip_ex(bm, f, cd_loop_mdisp_offset, true);
}
-/**
- * BM POINT IN FACE
- *
- * Projects co onto face f, and returns true if it is inside
- * the face bounds.
- *
- * \note this uses a best-axis projection test,
- * instead of projecting co directly into f's orientation space,
- * so there might be accuracy issues.
- */
bool BM_face_point_inside_test(const BMFace *f, const float co[3])
{
float axis_mat[3][3];
@@ -1080,29 +949,6 @@ bool BM_face_point_inside_test(const BMFace *f, const float co[3])
return isect_point_poly_v2(co_2d, projverts, f->len, false);
}
-/**
- * \brief BMESH TRIANGULATE FACE
- *
- * Breaks all quads and ngons down to triangles.
- * It uses polyfill for the ngons splitting, and
- * the beautify operator when use_beauty is true.
- *
- * \param r_faces_new: if non-null, must be an array of BMFace pointers,
- * with a length equal to (f->len - 3). It will be filled with the new
- * triangles (not including the original triangle).
- *
- * \param r_faces_double: When newly created faces are duplicates of existing faces,
- * they're added to this list. Caller must handle de-duplication.
- * This is done because its possible _all_ faces exist already,
- * and in that case we would have to remove all faces including the one passed,
- * which causes complications adding/removing faces while looking over them.
- *
- * \note The number of faces is _almost_ always (f->len - 3),
- * However there may be faces that already occupying the
- * triangles we would make, so the caller must check \a r_faces_new_tot.
- *
- * \note use_tag tags new flags and edges.
- */
void BM_face_triangulate(BMesh *bm,
BMFace *f,
BMFace **r_faces_new,
@@ -1325,14 +1171,6 @@ void BM_face_triangulate(BMesh *bm,
}
}
-/**
- * each pair of loops defines a new edge, a split. this function goes
- * through and sets pairs that are geometrically invalid to null. a
- * split is invalid, if it forms a concave angle or it intersects other
- * edges in the face, or it intersects another split. in the case of
- * intersecting splits, only the first of the set of intersecting
- * splits survives
- */
void BM_face_splits_check_legal(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len)
{
float out[2] = {-FLT_MAX, -FLT_MAX};
@@ -1430,10 +1268,6 @@ void BM_face_splits_check_legal(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int l
#undef EDGE_SHARE_VERT
}
-/**
- * This simply checks that the verts don't connect faces which would have more optimal splits.
- * but _not_ check for correctness.
- */
void BM_face_splits_check_optimal(BMFace *f, BMLoop *(*loops)[2], int len)
{
int i;
@@ -1447,12 +1281,6 @@ void BM_face_splits_check_optimal(BMFace *f, BMLoop *(*loops)[2], int len)
}
}
-/**
- * Small utility functions for fast access
- *
- * faster alternative to:
- * BM_iter_as_array(bm, BM_VERTS_OF_FACE, f, (void **)v, 3);
- */
void BM_face_as_array_vert_tri(BMFace *f, BMVert *r_verts[3])
{
BMLoop *l = BM_FACE_FIRST_LOOP(f);
@@ -1466,10 +1294,6 @@ void BM_face_as_array_vert_tri(BMFace *f, BMVert *r_verts[3])
r_verts[2] = l->v;
}
-/**
- * faster alternative to:
- * BM_iter_as_array(bm, BM_VERTS_OF_FACE, f, (void **)v, 4);
- */
void BM_face_as_array_vert_quad(BMFace *f, BMVert *r_verts[4])
{
BMLoop *l = BM_FACE_FIRST_LOOP(f);
@@ -1485,12 +1309,6 @@ void BM_face_as_array_vert_quad(BMFace *f, BMVert *r_verts[4])
r_verts[3] = l->v;
}
-/**
- * Small utility functions for fast access
- *
- * faster alternative to:
- * BM_iter_as_array(bm, BM_LOOPS_OF_FACE, f, (void **)l, 3);
- */
void BM_face_as_array_loop_tri(BMFace *f, BMLoop *r_loops[3])
{
BMLoop *l = BM_FACE_FIRST_LOOP(f);
@@ -1504,10 +1322,6 @@ void BM_face_as_array_loop_tri(BMFace *f, BMLoop *r_loops[3])
r_loops[2] = l;
}
-/**
- * faster alternative to:
- * BM_iter_as_array(bm, BM_LOOPS_OF_FACE, f, (void **)l, 4);
- */
void BM_face_as_array_loop_quad(BMFace *f, BMLoop *r_loops[4])
{
BMLoop *l = BM_FACE_FIRST_LOOP(f);
diff --git a/source/blender/bmesh/intern/bmesh_polygon.h b/source/blender/bmesh/intern/bmesh_polygon.h
index 5be7f4a5f3b..e4545e610a0 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.h
+++ b/source/blender/bmesh/intern/bmesh_polygon.h
@@ -25,68 +25,200 @@ struct Heap;
#include "BLI_compiler_attrs.h"
+/**
+ * For tools that insist on using triangles, ideally we would cache this data.
+ *
+ * \param use_fixed_quad: When true,
+ * always split quad along (0 -> 2) regardless of concave corners,
+ * (as done in #BM_mesh_calc_tessellation).
+ * \param r_loops: Store face loop pointers, (f->len)
+ * \param r_index: Store triangle triples, indices into \a r_loops, `((f->len - 2) * 3)`
+ */
void BM_face_calc_tessellation(const BMFace *f,
const bool use_fixed_quad,
BMLoop **r_loops,
uint (*r_index)[3]);
+/**
+ * Return a point inside the face.
+ */
void BM_face_calc_point_in_face(const BMFace *f, float r_co[3]);
+
+/**
+ * \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.
+ */
float BM_face_calc_normal(const BMFace *f, float r_no[3]) ATTR_NONNULL();
+/* exact same as 'BM_face_calc_normal' but accepts vertex coords */
float BM_face_calc_normal_vcos(const BMesh *bm,
const BMFace *f,
float r_no[3],
float const (*vertexCos)[3]) ATTR_NONNULL();
+/**
+ * Calculate a normal from a vertex cloud.
+ *
+ * \note We could make a higher quality version that takes all vertices into account.
+ * Currently it finds 4 outer most points returning its normal.
+ */
void BM_verts_calc_normal_from_cloud_ex(
BMVert **varr, int varr_len, float r_normal[3], float r_center[3], int *r_index_tangent);
void BM_verts_calc_normal_from_cloud(BMVert **varr, int varr_len, float r_normal[3]);
+/**
+ * Calculates the face subset normal.
+ */
float BM_face_calc_normal_subset(const BMLoop *l_first, const BMLoop *l_last, float r_no[3])
ATTR_NONNULL();
+/**
+ * get the area of the face
+ */
float BM_face_calc_area(const BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * Get the area of the face in world space.
+ */
float BM_face_calc_area_with_mat3(const BMFace *f, const float mat3[3][3]) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
+/**
+ * get the area of UV face
+ */
float BM_face_calc_area_uv(const BMFace *f, int cd_loop_uv_offset) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
+/**
+ * compute the perimeter of an ngon
+ */
float BM_face_calc_perimeter(const BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * Calculate the perimeter of a ngon in world space.
+ */
float BM_face_calc_perimeter_with_mat3(const BMFace *f,
const float mat3[3][3]) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
+/**
+ * Compute the tangent of the face, using the longest edge.
+ */
void BM_face_calc_tangent_edge(const BMFace *f, float r_tangent[3]) ATTR_NONNULL();
+/**
+ * Compute the tangent of the face, using the two longest disconnected edges.
+ *
+ * \param r_tangent: Calculated unit length tangent (return value).
+ */
void BM_face_calc_tangent_edge_pair(const BMFace *f, float r_tangent[3]) ATTR_NONNULL();
+/**
+ * Compute the tangent of the face, using the edge farthest away from any vertex in the face.
+ *
+ * \param r_tangent: Calculated unit length tangent (return value).
+ */
void BM_face_calc_tangent_edge_diagonal(const BMFace *f, float r_tangent[3]) ATTR_NONNULL();
+/**
+ * Compute the tangent of the face, using longest distance between vertices on the face.
+ *
+ * \note The logic is almost identical to #BM_face_calc_tangent_edge_diagonal
+ */
void BM_face_calc_tangent_vert_diagonal(const BMFace *f, float r_tangent[3]) ATTR_NONNULL();
+/**
+ * Compute a meaningful direction along the face (use for gizmo axis).
+ *
+ * \note Callers shouldn't depend on the *exact* method used here.
+ */
void BM_face_calc_tangent_auto(const BMFace *f, float r_tangent[3]) ATTR_NONNULL();
+/**
+ * computes center of face in 3d. uses center of bounding box.
+ */
void BM_face_calc_center_bounds(const BMFace *f, float r_cent[3]) ATTR_NONNULL();
+/**
+ * computes center of face in 3d. uses center of bounding box.
+ */
void BM_face_calc_center_bounds_vcos(const BMesh *bm,
const BMFace *f,
float r_center[3],
float const (*vertexCos)[3]) ATTR_NONNULL();
+/**
+ * computes the center of a face, using the mean average
+ */
void BM_face_calc_center_median(const BMFace *f, float r_center[3]) ATTR_NONNULL();
+/* exact same as 'BM_face_calc_normal' but accepts vertex coords */
void BM_face_calc_center_median_vcos(const BMesh *bm,
const BMFace *f,
float r_center[3],
float const (*vertexCos)[3]) ATTR_NONNULL();
+/**
+ * computes the center of a face, using the mean average
+ * weighted by edge length
+ */
void BM_face_calc_center_median_weighted(const BMFace *f, float r_cent[3]) ATTR_NONNULL();
+/**
+ * expands bounds (min/max must be initialized).
+ */
void BM_face_calc_bounds_expand(const BMFace *f, float min[3], float max[3]);
void BM_face_normal_update(BMFace *f) ATTR_NONNULL();
+/**
+ * updates face and vertex normals incident on an edge
+ */
void BM_edge_normals_update(BMEdge *e) ATTR_NONNULL();
bool BM_vert_calc_normal_ex(const BMVert *v, const char hflag, float r_no[3]);
bool BM_vert_calc_normal(const BMVert *v, float r_no[3]);
+/**
+ * update a vert normal (but not the faces incident on it)
+ */
void BM_vert_normal_update(BMVert *v) ATTR_NONNULL();
void BM_vert_normal_update_all(BMVert *v) ATTR_NONNULL();
+/**
+ * \brief Face Flip Normal
+ *
+ * Reverses the winding of a face.
+ * \note This updates the calculated normal.
+ */
void BM_face_normal_flip_ex(BMesh *bm,
BMFace *f,
const int cd_loop_mdisp_offset,
const bool use_loop_mdisp_flip) ATTR_NONNULL();
void BM_face_normal_flip(BMesh *bm, BMFace *f) ATTR_NONNULL();
+/**
+ * BM POINT IN FACE
+ *
+ * Projects co onto face f, and returns true if it is inside
+ * the face bounds.
+ *
+ * \note this uses a best-axis projection test,
+ * instead of projecting co directly into f's orientation space,
+ * so there might be accuracy issues.
+ */
bool BM_face_point_inside_test(const BMFace *f, const float co[3]) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
+/**
+ * \brief BMESH TRIANGULATE FACE
+ *
+ * Breaks all quads and ngons down to triangles.
+ * It uses poly-fill for the ngons splitting, and
+ * the beautify operator when use_beauty is true.
+ *
+ * \param r_faces_new: if non-null, must be an array of BMFace pointers,
+ * with a length equal to (f->len - 3). It will be filled with the new
+ * triangles (not including the original triangle).
+ *
+ * \param r_faces_double: When newly created faces are duplicates of existing faces,
+ * they're added to this list. Caller must handle de-duplication.
+ * This is done because its possible _all_ faces exist already,
+ * and in that case we would have to remove all faces including the one passed,
+ * which causes complications adding/removing faces while looking over them.
+ *
+ * \note The number of faces is _almost_ always (f->len - 3),
+ * However there may be faces that already occupying the
+ * triangles we would make, so the caller must check \a r_faces_new_tot.
+ *
+ * \note use_tag tags new flags and edges.
+ */
void BM_face_triangulate(BMesh *bm,
BMFace *f,
BMFace **r_faces_new,
@@ -100,14 +232,62 @@ void BM_face_triangulate(BMesh *bm,
struct MemArena *pf_arena,
struct Heap *pf_heap) ATTR_NONNULL(1, 2);
+/**
+ * each pair of loops defines a new edge, a split. this function goes
+ * through and sets pairs that are geometrically invalid to null. a
+ * split is invalid, if it forms a concave angle or it intersects other
+ * edges in the face, or it intersects another split. in the case of
+ * intersecting splits, only the first of the set of intersecting
+ * splits survives
+ */
void BM_face_splits_check_legal(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len) ATTR_NONNULL();
+/**
+ * This simply checks that the verts don't connect faces which would have more optimal splits.
+ * but _not_ check for correctness.
+ */
void BM_face_splits_check_optimal(BMFace *f, BMLoop *(*loops)[2], int len) ATTR_NONNULL();
+/**
+ * Small utility functions for fast access
+ *
+ * faster alternative to:
+ * BM_iter_as_array(bm, BM_VERTS_OF_FACE, f, (void **)v, 3);
+ */
void BM_face_as_array_vert_tri(BMFace *f, BMVert *r_verts[3]) ATTR_NONNULL();
+/**
+ * faster alternative to:
+ * BM_iter_as_array(bm, BM_VERTS_OF_FACE, f, (void **)v, 4);
+ */
void BM_face_as_array_vert_quad(BMFace *f, BMVert *r_verts[4]) ATTR_NONNULL();
+/**
+ * Small utility functions for fast access
+ *
+ * faster alternative to:
+ * BM_iter_as_array(bm, BM_LOOPS_OF_FACE, f, (void **)l, 3);
+ */
void BM_face_as_array_loop_tri(BMFace *f, BMLoop *r_loops[3]) ATTR_NONNULL();
+/**
+ * faster alternative to:
+ * BM_iter_as_array(bm, BM_LOOPS_OF_FACE, f, (void **)l, 4);
+ */
void BM_face_as_array_loop_quad(BMFace *f, BMLoop *r_loops[4]) ATTR_NONNULL();
+/**
+ * Calculate a tangent from any 3 vertices.
+ *
+ * The tangent aligns to the most *unique* edge
+ * (the edge most unlike the other two).
+ *
+ * \param r_tangent: Calculated unit length tangent (return value).
+ */
void BM_vert_tri_calc_tangent_edge(BMVert *verts[3], float r_tangent[3]);
+/**
+ * Calculate a tangent from any 3 vertices,
+ *
+ * The tangent follows the center-line formed by the most unique edges center
+ * and the opposite vertex.
+ *
+ * \param r_tangent: Calculated unit length tangent (return value).
+ */
void BM_vert_tri_calc_tangent_edge_pair(BMVert *verts[3], float r_tangent[3]);
diff --git a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c
index 103d7621f87..24d9c194054 100644
--- a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c
+++ b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c
@@ -452,14 +452,6 @@ static bool bm_face_split_edgenet_find_loop(BMVert *v_init,
return false;
}
-/**
- * Splits a face into many smaller faces defined by an edge-net.
- * handle customdata and degenerate cases.
- *
- * - Isolated holes or unsupported face configurations, will be ignored.
- * - Customdata calculations aren't efficient
- * (need to calculate weights for each vert).
- */
bool BM_face_split_edgenet(BMesh *bm,
BMFace *f,
BMEdge **edge_net,
@@ -1223,14 +1215,6 @@ static bool bm_vert_partial_connect_check_overlap(const int *remap,
#endif /* USE_PARTIAL_CONNECT */
-/**
- * For when the edge-net has holes in it-this connects them.
- *
- * \param use_partial_connect: Support for handling islands connected by only a single edge,
- * \note that this is quite slow so avoid using where possible.
- * \param mem_arena: Avoids many small allocs & should be cleared after each use.
- * take care since \a edge_net_new is stored in \a r_edge_net_new.
- */
bool BM_face_split_edgenet_connect_islands(BMesh *bm,
BMFace *f,
BMEdge **edge_net_init,
diff --git a/source/blender/bmesh/intern/bmesh_polygon_edgenet.h b/source/blender/bmesh/intern/bmesh_polygon_edgenet.h
index 6833f067421..a25f38a84b3 100644
--- a/source/blender/bmesh/intern/bmesh_polygon_edgenet.h
+++ b/source/blender/bmesh/intern/bmesh_polygon_edgenet.h
@@ -20,6 +20,14 @@
* \ingroup bmesh
*/
+/**
+ * Splits a face into many smaller faces defined by an edge-net.
+ * handle customdata and degenerate cases.
+ *
+ * - Isolated holes or unsupported face configurations, will be ignored.
+ * - Customdata calculations aren't efficient
+ * (need to calculate weights for each vert).
+ */
bool BM_face_split_edgenet(BMesh *bm,
BMFace *f,
BMEdge **edge_net,
@@ -27,12 +35,20 @@ bool BM_face_split_edgenet(BMesh *bm,
BMFace ***r_face_arr,
int *r_face_arr_len);
+/**
+ * For when the edge-net has holes in it-this connects them.
+ *
+ * \param use_partial_connect: Support for handling islands connected by only a single edge,
+ * \note that this is quite slow so avoid using where possible.
+ * \param mem_arena: Avoids many small allocs & should be cleared after each use.
+ * take care since \a edge_net_new is stored in \a r_edge_net_new.
+ */
bool BM_face_split_edgenet_connect_islands(BMesh *bm,
BMFace *f,
BMEdge **edge_net_init,
const uint edge_net_init_len,
bool use_partial_connect,
- struct MemArena *arena,
+ struct MemArena *mem_arena,
BMEdge ***r_edge_net_new,
uint *r_edge_net_new_len) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL(1, 2, 3, 6, 7, 8);
diff --git a/source/blender/bmesh/intern/bmesh_private.h b/source/blender/bmesh/intern/bmesh_private.h
index e1df7744e41..e7e8b7107e5 100644
--- a/source/blender/bmesh/intern/bmesh_private.h
+++ b/source/blender/bmesh/intern/bmesh_private.h
@@ -34,6 +34,12 @@
* it can take most of the CPU time when running some tools. */
# define BM_CHECK_ELEMENT(el) (void)(el)
#else
+/**
+ * Check the element is valid.
+ *
+ * BMESH_TODO, when this raises an error the output is incredibly confusing.
+ * need to have some nice way to print/debug what the heck's going on.
+ */
int bmesh_elem_check(void *element, const char htype);
# define BM_CHECK_ELEMENT(el) \
{ \
@@ -86,6 +92,12 @@ enum {
} \
(void)0
+/**
+ * \brief POLY ROTATE PLANE
+ *
+ * Rotates a polygon so that its
+ * normal is pointing towards the mesh Z axis
+ */
void poly_rotate_plane(const float normal[3], float (*verts)[3], const uint nverts);
/* include the rest of our private declarations */
diff --git a/source/blender/bmesh/intern/bmesh_query.c b/source/blender/bmesh/intern/bmesh_query.c
index 795d8829ee7..fe2142670a2 100644
--- a/source/blender/bmesh/intern/bmesh_query.c
+++ b/source/blender/bmesh/intern/bmesh_query.c
@@ -37,24 +37,6 @@
#include "bmesh.h"
#include "intern/bmesh_private.h"
-/**
- * \brief Other Loop in Face Sharing an Edge
- *
- * Finds the other loop that shares \a v with \a e loop in \a f.
- * <pre>
- * +----------+
- * | |
- * | f |
- * | |
- * +----------+ <-- return the face loop of this vertex.
- * v --> e
- * ^ ^ <------- These vert args define direction
- * in the face to check.
- * The faces loop direction is ignored.
- * </pre>
- *
- * \note caller must ensure \a e is used in \a f
- */
BMLoop *BM_face_other_edge_loop(BMFace *f, BMEdge *e, BMVert *v)
{
BMLoop *l = BM_face_edge_share_loop(f, e);
@@ -62,38 +44,12 @@ BMLoop *BM_face_other_edge_loop(BMFace *f, BMEdge *e, BMVert *v)
return BM_loop_other_edge_loop(l, v);
}
-/**
- * See #BM_face_other_edge_loop This is the same functionality
- * to be used when the edges loop is already known.
- */
BMLoop *BM_loop_other_edge_loop(BMLoop *l, BMVert *v)
{
BLI_assert(BM_vert_in_edge(l->e, v));
return l->v == v ? l->prev : l->next;
}
-/**
- * \brief Other Loop in Face Sharing a Vertex
- *
- * Finds the other loop in a face.
- *
- * This function returns a loop in \a f that shares an edge with \a v
- * The direction is defined by \a v_prev, where the return value is
- * the loop of what would be 'v_next'
- * <pre>
- * +----------+ <-- return the face loop of this vertex.
- * | |
- * | f |
- * | |
- * +----------+
- * v_prev --> v
- * ^^^^^^ ^ <-- These vert args define direction
- * in the face to check.
- * The faces loop direction is ignored.
- * </pre>
- *
- * \note \a v_prev and \a v _implicitly_ define an edge.
- */
BMLoop *BM_face_other_vert_loop(BMFace *f, BMVert *v_prev, BMVert *v)
{
BMLoop *l_iter = BM_face_vert_share_loop(f, v);
@@ -116,22 +72,6 @@ BMLoop *BM_face_other_vert_loop(BMFace *f, BMVert *v_prev, BMVert *v)
return NULL;
}
-/**
- * \brief Other Loop in Face Sharing a Vert
- *
- * Finds the other loop that shares \a v with \a e loop in \a f.
- * <pre>
- * +----------+ <-- return the face loop of this vertex.
- * | |
- * | |
- * | |
- * +----------+ <-- This vertex defines the direction.
- * l v
- * ^ <------- This loop defines both the face to search
- * and the edge, in combination with 'v'
- * The faces loop direction is ignored.
- * </pre>
- */
BMLoop *BM_loop_other_vert_loop(BMLoop *l, BMVert *v)
{
#if 0 /* works but slow */
@@ -157,22 +97,6 @@ BMLoop *BM_loop_other_vert_loop(BMLoop *l, BMVert *v)
#endif
}
-/**
- * Return the other loop that uses this edge.
- *
- * In this case the loop defines the vertex,
- * the edge passed in defines the direction to step.
- *
- * <pre>
- * +----------+ <-- Return the face-loop of this vertex.
- * | |
- * | e | <-- This edge defines the direction.
- * | |
- * +----------+ <-- This loop defines the face and vertex..
- * l
- * </pre>
- *
- */
BMLoop *BM_loop_other_vert_loop_by_edge(BMLoop *l, BMEdge *e)
{
BLI_assert(BM_vert_in_edge(e, l->v));
@@ -187,9 +111,6 @@ BMLoop *BM_loop_other_vert_loop_by_edge(BMLoop *l, BMEdge *e)
return NULL;
}
-/**
- * Check if verts share a face.
- */
bool BM_vert_pair_share_face_check(BMVert *v_a, BMVert *v_b)
{
if (v_a->e && v_b->e) {
@@ -255,9 +176,6 @@ BMFace *BM_vert_pair_shared_face_cb(BMVert *v_a,
return NULL;
}
-/**
- * Given 2 verts, find the smallest face they share and give back both loops.
- */
BMFace *BM_vert_pair_share_face_by_len(
BMVert *v_a, BMVert *v_b, BMLoop **r_l_a, BMLoop **r_l_b, const bool allow_adjacent)
{
@@ -325,24 +243,12 @@ static float bm_face_calc_split_dot(BMLoop *l_a, BMLoop *l_b)
return -1.0f;
}
-/**
- * Check if a point is inside the corner defined by a loop
- * (within the 2 planes defined by the loops corner & face normal).
- *
- * \return signed, squared distance to the loops planes, less than 0.0 when outside.
- */
float BM_loop_point_side_of_loop_test(const BMLoop *l, const float co[3])
{
const float *axis = l->f->no;
return dist_signed_squared_to_corner_v3v3v3(co, l->prev->v->co, l->v->co, l->next->v->co, axis);
}
-/**
- * Check if a point is inside the edge defined by a loop
- * (within the plane defined by the loops edge & face normal).
- *
- * \return signed, squared distance to the edge plane, less than 0.0 when outside.
- */
float BM_loop_point_side_of_edge_test(const BMLoop *l, const float co[3])
{
const float *axis = l->f->no;
@@ -356,13 +262,6 @@ float BM_loop_point_side_of_edge_test(const BMLoop *l, const float co[3])
return dist_signed_squared_to_plane_v3(co, plane);
}
-/**
- * Given 2 verts,
- * find a face they share that has the lowest angle across these verts and give back both loops.
- *
- * This can be better than #BM_vert_pair_share_face_by_len
- * because concave splits are ranked lowest.
- */
BMFace *BM_vert_pair_share_face_by_angle(
BMVert *v_a, BMVert *v_b, BMLoop **r_l_a, BMLoop **r_l_b, const bool allow_adjacent)
{
@@ -409,25 +308,15 @@ BMFace *BM_vert_pair_share_face_by_angle(
return f_cur;
}
-/**
- * Get the first loop of a vert. Uses the same initialization code for the first loop of the
- * iterator API
- */
BMLoop *BM_vert_find_first_loop(BMVert *v)
{
return v->e ? bmesh_disk_faceloop_find_first(v->e, v) : NULL;
}
-/**
- * A version of #BM_vert_find_first_loop that ignores hidden loops.
- */
BMLoop *BM_vert_find_first_loop_visible(BMVert *v)
{
return v->e ? bmesh_disk_faceloop_find_first_visible(v->e, v) : NULL;
}
-/**
- * Returns true if the vertex is used in a given face.
- */
bool BM_vert_in_face(BMVert *v, BMFace *f)
{
BMLoop *l_iter, *l_first;
@@ -452,10 +341,6 @@ bool BM_vert_in_face(BMVert *v, BMFace *f)
return false;
}
-/**
- * Compares the number of vertices in an array
- * that appear in a given face
- */
int BM_verts_in_face_count(BMVert **varr, int len, BMFace *f)
{
BMLoop *l_iter, *l_first;
@@ -496,9 +381,6 @@ int BM_verts_in_face_count(BMVert **varr, int len, BMFace *f)
return count;
}
-/**
- * Return true if all verts are in the face.
- */
bool BM_verts_in_face(BMVert **varr, int len, BMFace *f)
{
BMLoop *l_iter, *l_first;
@@ -549,9 +431,6 @@ bool BM_verts_in_face(BMVert **varr, int len, BMFace *f)
return ok;
}
-/**
- * Returns whether or not a given edge is part of a given face.
- */
bool BM_edge_in_face(const BMEdge *e, const BMFace *f)
{
if (e->l) {
@@ -568,22 +447,6 @@ bool BM_edge_in_face(const BMEdge *e, const BMFace *f)
return false;
}
-/**
- * Given a edge and a loop (assumes the edge is manifold). returns
- * the other faces loop, sharing the same vertex.
- *
- * <pre>
- * +-------------------+
- * | |
- * | |
- * |l_other <-- return |
- * +-------------------+ <-- A manifold edge between 2 faces
- * |l e <-- edge |
- * |^ <-------- loop |
- * | |
- * +-------------------+
- * </pre>
- */
BMLoop *BM_edge_other_loop(BMEdge *e, BMLoop *l)
{
BMLoop *l_other;
@@ -609,31 +472,6 @@ BMLoop *BM_edge_other_loop(BMEdge *e, BMLoop *l)
return l_other;
}
-/**
- * Utility function to step around a fan of loops,
- * using an edge to mark the previous side.
- *
- * \note all edges must be manifold,
- * once a non manifold edge is hit, return NULL.
- *
- * <pre>
- * ,.,-->|
- * _,-' |
- * ,' | (notice how 'e_step'
- * / | and 'l' define the
- * / | direction the arrow
- * | return | points).
- * | loop --> |
- * ---------------------+---------------------
- * ^ l --> |
- * | |
- * assign e_step |
- * |
- * begin e_step ----> |
- * |
- * </pre>
- */
-
BMLoop *BM_vert_step_fan_loop(BMLoop *l, BMEdge **e_step)
{
BMEdge *e_prev = *e_step;
@@ -655,12 +493,6 @@ BMLoop *BM_vert_step_fan_loop(BMLoop *l, BMEdge **e_step)
return NULL;
}
-/**
- * The function takes a vertex at the center of a fan and returns the opposite edge in the fan.
- * All edges in the fan must be manifold, otherwise return NULL.
- *
- * \note This could (probably) be done more efficiently.
- */
BMEdge *BM_vert_other_disk_edge(BMVert *v, BMEdge *e_first)
{
BMLoop *l_a;
@@ -707,28 +539,16 @@ BMEdge *BM_vert_other_disk_edge(BMVert *v, BMEdge *e_first)
return NULL;
}
-/**
- * Returns edge length
- */
float BM_edge_calc_length(const BMEdge *e)
{
return len_v3v3(e->v1->co, e->v2->co);
}
-/**
- * Returns edge length squared (for comparisons)
- */
float BM_edge_calc_length_squared(const BMEdge *e)
{
return len_squared_v3v3(e->v1->co, e->v2->co);
}
-/**
- * Utility function, since enough times we have an edge
- * and want to access 2 connected faces.
- *
- * \return true when only 2 faces are found.
- */
bool BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb)
{
BMLoop *la, *lb;
@@ -744,12 +564,6 @@ bool BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb)
return false;
}
-/**
- * Utility function, since enough times we have an edge
- * and want to access 2 connected loops.
- *
- * \return true when only 2 faces are found.
- */
bool BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb)
{
BMLoop *la, *lb;
@@ -765,9 +579,6 @@ bool BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb)
return false;
}
-/**
- * Fast alternative to `(BM_vert_edge_count(v) == 2)`.
- */
bool BM_vert_is_edge_pair(const BMVert *v)
{
const BMEdge *e = v->e;
@@ -778,10 +589,6 @@ bool BM_vert_is_edge_pair(const BMVert *v)
return false;
}
-/**
- * Fast alternative to `(BM_vert_edge_count(v) == 2)`
- * that checks both edges connect to the same faces.
- */
bool BM_vert_is_edge_pair_manifold(const BMVert *v)
{
const BMEdge *e = v->e;
@@ -794,11 +601,6 @@ bool BM_vert_is_edge_pair_manifold(const BMVert *v)
return false;
}
-/**
- * Access a verts 2 connected edges.
- *
- * \return true when only 2 verts are found.
- */
bool BM_vert_edge_pair(BMVert *v, BMEdge **r_e_a, BMEdge **r_e_b)
{
BMEdge *e_a = v->e;
@@ -816,9 +618,6 @@ bool BM_vert_edge_pair(BMVert *v, BMEdge **r_e_a, BMEdge **r_e_b)
return false;
}
-/**
- * Returns the number of edges around this vertex.
- */
int BM_vert_edge_count(const BMVert *v)
{
return bmesh_disk_count(v);
@@ -841,9 +640,6 @@ int BM_vert_edge_count_nonwire(const BMVert *v)
}
return count;
}
-/**
- * Returns the number of faces around this edge
- */
int BM_edge_face_count(const BMEdge *e)
{
int count = 0;
@@ -879,10 +675,6 @@ int BM_edge_face_count_at_most(const BMEdge *e, const int count_max)
return count;
}
-/**
- * Returns the number of faces around this vert
- * length matches #BM_LOOPS_OF_VERT iterator
- */
int BM_vert_face_count(const BMVert *v)
{
return bmesh_disk_facevert_count(v);
@@ -893,11 +685,6 @@ int BM_vert_face_count_at_most(const BMVert *v, int count_max)
return bmesh_disk_facevert_count_at_most(v, count_max);
}
-/**
- * Return true if the vertex is connected to _any_ faces.
- *
- * same as `BM_vert_face_count(v) != 0` or `BM_vert_find_first_loop(v) == NULL`.
- */
bool BM_vert_face_check(const BMVert *v)
{
if (v->e != NULL) {
@@ -912,10 +699,6 @@ bool BM_vert_face_check(const BMVert *v)
return false;
}
-/**
- * Tests whether or not the vertex is part of a wire edge.
- * (ie: has no faces attached to it)
- */
bool BM_vert_is_wire(const BMVert *v)
{
if (v->e) {
@@ -933,13 +716,6 @@ bool BM_vert_is_wire(const BMVert *v)
return false;
}
-/**
- * A vertex is non-manifold if it meets the following conditions:
- * 1: Loose - (has no edges/faces incident upon it).
- * 2: Joins two distinct regions - (two pyramids joined at the tip).
- * 3: Is part of an edge with more than 2 faces.
- * 4: Is part of a wire edge.
- */
bool BM_vert_is_manifold(const BMVert *v)
{
BMEdge *e_iter, *e_first, *e_prev;
@@ -1064,9 +840,6 @@ static int bm_loop_region_count__clear(BMLoop *l)
return count;
}
-/**
- * The number of loops connected to this loop (not including disconnected regions).
- */
int BM_loop_region_loops_count_at_most(BMLoop *l, int *r_loop_total)
{
const int count = bm_loop_region_count__recursive(l->e, l->v);
@@ -1085,10 +858,6 @@ int BM_loop_region_loops_count(BMLoop *l)
return BM_loop_region_loops_count_at_most(l, NULL);
}
-/**
- * A version of #BM_vert_is_manifold
- * which only checks if we're connected to multiple isolated regions.
- */
bool BM_vert_is_manifold_region(const BMVert *v)
{
BMLoop *l_first = BM_vert_find_first_loop((BMVert *)v);
@@ -1100,10 +869,6 @@ bool BM_vert_is_manifold_region(const BMVert *v)
return true;
}
-/**
- * Check if the edge is convex or concave
- * (depends on face winding)
- */
bool BM_edge_is_convex(const BMEdge *e)
{
if (BM_edge_is_manifold(e)) {
@@ -1121,9 +886,6 @@ bool BM_edge_is_convex(const BMEdge *e)
return true;
}
-/**
- * \return true when loop customdata is contiguous.
- */
bool BM_edge_is_contiguous_loop_cd(const BMEdge *e,
const int cd_loop_type,
const int cd_loop_offset)
@@ -1182,11 +944,6 @@ bool BM_vert_is_boundary(const BMVert *v)
return false;
}
-/**
- * Returns the number of faces that are adjacent to both f1 and f2,
- * \note Could be sped up a bit by not using iterators and by tagging
- * faces on either side, then count the tags rather then searching.
- */
int BM_face_share_face_count(BMFace *f_a, BMFace *f_b)
{
BMIter iter1, iter2;
@@ -1205,9 +962,6 @@ int BM_face_share_face_count(BMFace *f_a, BMFace *f_b)
return count;
}
-/**
- * same as #BM_face_share_face_count but returns a bool
- */
bool BM_face_share_face_check(BMFace *f_a, BMFace *f_b)
{
BMIter iter1, iter2;
@@ -1225,9 +979,6 @@ bool BM_face_share_face_check(BMFace *f_a, BMFace *f_b)
return false;
}
-/**
- * Counts the number of edges two faces share (if any)
- */
int BM_face_share_edge_count(BMFace *f_a, BMFace *f_b)
{
BMLoop *l_iter;
@@ -1244,9 +995,6 @@ int BM_face_share_edge_count(BMFace *f_a, BMFace *f_b)
return count;
}
-/**
- * Returns true if the faces share an edge
- */
bool BM_face_share_edge_check(BMFace *f1, BMFace *f2)
{
BMLoop *l_iter;
@@ -1262,9 +1010,6 @@ bool BM_face_share_edge_check(BMFace *f1, BMFace *f2)
return false;
}
-/**
- * Counts the number of verts two faces share (if any).
- */
int BM_face_share_vert_count(BMFace *f_a, BMFace *f_b)
{
BMLoop *l_iter;
@@ -1281,9 +1026,6 @@ int BM_face_share_vert_count(BMFace *f_a, BMFace *f_b)
return count;
}
-/**
- * Returns true if the faces share a vert.
- */
bool BM_face_share_vert_check(BMFace *f_a, BMFace *f_b)
{
BMLoop *l_iter;
@@ -1299,18 +1041,12 @@ bool BM_face_share_vert_check(BMFace *f_a, BMFace *f_b)
return false;
}
-/**
- * Returns true when 2 loops share an edge (are adjacent in the face-fan)
- */
bool BM_loop_share_edge_check(BMLoop *l_a, BMLoop *l_b)
{
BLI_assert(l_a->v == l_b->v);
return (ELEM(l_a->e, l_b->e, l_b->prev->e) || ELEM(l_b->e, l_a->e, l_a->prev->e));
}
-/**
- * Test if e1 shares any faces with e2
- */
bool BM_edge_share_face_check(BMEdge *e1, BMEdge *e2)
{
BMLoop *l;
@@ -1329,9 +1065,6 @@ bool BM_edge_share_face_check(BMEdge *e1, BMEdge *e2)
return false;
}
-/**
- * Test if e1 shares any quad faces with e2
- */
bool BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2)
{
BMLoop *l;
@@ -1352,17 +1085,11 @@ bool BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2)
return false;
}
-/**
- * Tests to see if e1 shares a vertex with e2
- */
bool BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2)
{
return (e1->v1 == e2->v1 || e1->v1 == e2->v2 || e1->v2 == e2->v1 || e1->v2 == e2->v2);
}
-/**
- * Return the shared vertex between the two edges or NULL
- */
BMVert *BM_edge_share_vert(BMEdge *e1, BMEdge *e2)
{
BLI_assert(e1 != e2);
@@ -1375,14 +1102,6 @@ BMVert *BM_edge_share_vert(BMEdge *e1, BMEdge *e2)
return NULL;
}
-/**
- * \brief Return the Loop Shared by Edge and Vert
- *
- * Finds the loop used which uses \a in face loop \a l
- *
- * \note this function takes a loop rather than an edge
- * so we can select the face that the loop should be from.
- */
BMLoop *BM_edge_vert_share_loop(BMLoop *l, BMVert *v)
{
BLI_assert(BM_vert_in_edge(l->e, v));
@@ -1392,14 +1111,6 @@ BMLoop *BM_edge_vert_share_loop(BMLoop *l, BMVert *v)
return l->next;
}
-/**
- * \brief Return the Loop Shared by Face and Vertex
- *
- * Finds the loop used which uses \a v in face loop \a l
- *
- * \note currently this just uses simple loop in future may be sped up
- * using radial vars
- */
BMLoop *BM_face_vert_share_loop(BMFace *f, BMVert *v)
{
BMLoop *l_first;
@@ -1415,14 +1126,6 @@ BMLoop *BM_face_vert_share_loop(BMFace *f, BMVert *v)
return NULL;
}
-/**
- * \brief Return the Loop Shared by Face and Edge
- *
- * Finds the loop used which uses \a e in face loop \a l
- *
- * \note currently this just uses simple loop in future may be sped up
- * using radial vars
- */
BMLoop *BM_face_edge_share_loop(BMFace *f, BMEdge *e)
{
BMLoop *l_first;
@@ -1438,18 +1141,6 @@ BMLoop *BM_face_edge_share_loop(BMFace *f, BMEdge *e)
return NULL;
}
-/**
- * Returns the verts of an edge as used in a face
- * if used in a face at all, otherwise just assign as used in the edge.
- *
- * Useful to get a deterministic winding order when calling
- * BM_face_create_ngon() on an arbitrary array of verts,
- * though be sure to pick an edge which has a face.
- *
- * \note This is in fact quite a simple check,
- * mainly include this function so the intent is more obvious.
- * We know these 2 verts will _always_ make up the loops edge
- */
void BM_edge_ordered_verts_ex(const BMEdge *edge,
BMVert **r_v1,
BMVert **r_v2,
@@ -1466,9 +1157,6 @@ void BM_edge_ordered_verts(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2)
BM_edge_ordered_verts_ex(edge, r_v1, r_v2, edge->l);
}
-/**
- * \return The previous loop, over \a eps_sq distance from \a l (or \a NULL if l_stop is reached).
- */
BMLoop *BM_loop_find_prev_nodouble(BMLoop *l, BMLoop *l_stop, const float eps_sq)
{
BMLoop *l_step = l->prev;
@@ -1486,9 +1174,6 @@ BMLoop *BM_loop_find_prev_nodouble(BMLoop *l, BMLoop *l_stop, const float eps_sq
return l_step;
}
-/**
- * \return The next loop, over \a eps_sq distance from \a l (or \a NULL if l_stop is reached).
- */
BMLoop *BM_loop_find_next_nodouble(BMLoop *l, BMLoop *l_stop, const float eps_sq)
{
BMLoop *l_step = l->next;
@@ -1506,10 +1191,6 @@ BMLoop *BM_loop_find_next_nodouble(BMLoop *l, BMLoop *l_stop, const float eps_sq
return l_step;
}
-/**
- * Check if the loop is convex or concave
- * (depends on face normal)
- */
bool BM_loop_is_convex(const BMLoop *l)
{
float e_dir_prev[3];
@@ -1522,26 +1203,11 @@ bool BM_loop_is_convex(const BMLoop *l)
return dot_v3v3(l_no, l->f->no) > 0.0f;
}
-/**
- * Calculates the angle between the previous and next loops
- * (angle at this loops face corner).
- *
- * \return angle in radians
- */
float BM_loop_calc_face_angle(const BMLoop *l)
{
return angle_v3v3v3(l->prev->v->co, l->v->co, l->next->v->co);
}
-/**
- * \brief BM_loop_calc_face_normal
- *
- * Calculate the normal at this loop corner or fallback to the face normal on straight lines.
- *
- * \param l: The loop to calculate the normal at.
- * \param epsilon_sq: Value to avoid numeric errors (1e-5f works well).
- * \param r_normal: Resulting normal.
- */
float BM_loop_calc_face_normal_safe_ex(const BMLoop *l, const float epsilon_sq, float r_normal[3])
{
/* NOTE: we cannot use result of normal_tri_v3 here to detect colinear vectors
@@ -1571,9 +1237,6 @@ float BM_loop_calc_face_normal_safe_ex(const BMLoop *l, const float epsilon_sq,
return 0.0f;
}
-/**
- * A version of BM_loop_calc_face_normal_safe_ex which takes vertex coordinates.
- */
float BM_loop_calc_face_normal_safe_vcos_ex(const BMLoop *l,
const float normal_fallback[3],
float const (*vertexCos)[3],
@@ -1604,11 +1267,6 @@ float BM_loop_calc_face_normal_safe_vcos_ex(const BMLoop *l,
return 0.0f;
}
-/**
- * #BM_loop_calc_face_normal_safe_ex with predefined sane epsilon.
- *
- * Since this doesn't scale based on triangle size, fixed value works well.
- */
float BM_loop_calc_face_normal_safe(const BMLoop *l, float r_normal[3])
{
return BM_loop_calc_face_normal_safe_ex(l, 1e-5f, r_normal);
@@ -1623,15 +1281,6 @@ float BM_loop_calc_face_normal_safe_vcos(const BMLoop *l,
return BM_loop_calc_face_normal_safe_vcos_ex(l, normal_fallback, vertexCos, 1e-5f, r_normal);
}
-/**
- * \brief BM_loop_calc_face_normal
- *
- * Calculate the normal at this loop corner or fallback to the face normal on straight lines.
- *
- * \param l: The loop to calculate the normal at
- * \param r_normal: Resulting normal
- * \return The length of the cross product (double the area).
- */
float BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3])
{
float v1[3], v2[3];
@@ -1646,14 +1295,6 @@ float BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3])
return len;
}
-/**
- * \brief BM_loop_calc_face_direction
- *
- * Calculate the direction a loop is pointing.
- *
- * \param l: The loop to calculate the direction at
- * \param r_dir: Resulting direction
- */
void BM_loop_calc_face_direction(const BMLoop *l, float r_dir[3])
{
float v_prev[3];
@@ -1669,15 +1310,6 @@ void BM_loop_calc_face_direction(const BMLoop *l, float r_dir[3])
normalize_v3(r_dir);
}
-/**
- * \brief BM_loop_calc_face_tangent
- *
- * Calculate the tangent at this loop corner or fallback to the face normal on straight lines.
- * This vector always points inward into the face.
- *
- * \param l: The loop to calculate the tangent at
- * \param r_tangent: Resulting tangent
- */
void BM_loop_calc_face_tangent(const BMLoop *l, float r_tangent[3])
{
float v_prev[3];
@@ -1708,14 +1340,6 @@ void BM_loop_calc_face_tangent(const BMLoop *l, float r_tangent[3])
normalize_v3(r_tangent);
}
-/**
- * \brief BMESH EDGE/FACE ANGLE
- *
- * Calculates the angle between two faces.
- * Assumes the face normals are correct.
- *
- * \return angle in radians
- */
float BM_edge_calc_face_angle_ex(const BMEdge *e, const float fallback)
{
if (BM_edge_is_manifold(e)) {
@@ -1730,14 +1354,6 @@ float BM_edge_calc_face_angle(const BMEdge *e)
return BM_edge_calc_face_angle_ex(e, DEG2RADF(90.0f));
}
-/**
- * \brief BMESH EDGE/FACE ANGLE
- *
- * Calculates the angle between two faces in world space.
- * Assumes the face normals are correct.
- *
- * \return angle in radians
- */
float BM_edge_calc_face_angle_with_imat3_ex(const BMEdge *e,
const float imat3[3][3],
const float fallback)
@@ -1764,14 +1380,6 @@ float BM_edge_calc_face_angle_with_imat3(const BMEdge *e, const float imat3[3][3
return BM_edge_calc_face_angle_with_imat3_ex(e, imat3, DEG2RADF(90.0f));
}
-/**
- * \brief BMESH EDGE/FACE ANGLE
- *
- * Calculates the angle between two faces.
- * Assumes the face normals are correct.
- *
- * \return angle in radians
- */
float BM_edge_calc_face_angle_signed_ex(const BMEdge *e, const float fallback)
{
if (BM_edge_is_manifold(e)) {
@@ -1787,19 +1395,6 @@ float BM_edge_calc_face_angle_signed(const BMEdge *e)
return BM_edge_calc_face_angle_signed_ex(e, DEG2RADF(90.0f));
}
-/**
- * \brief BMESH EDGE/FACE TANGENT
- *
- * Calculate the tangent at this loop corner or fallback to the face normal on straight lines.
- * This vector always points inward into the face.
- *
- * \brief BM_edge_calc_face_tangent
- * \param e:
- * \param e_loop: The loop to calculate the tangent at,
- * used to get the face and winding direction.
- * \param r_tangent: The loop corner tangent to set
- */
-
void BM_edge_calc_face_tangent(const BMEdge *e, const BMLoop *e_loop, float r_tangent[3])
{
float tvec[3];
@@ -1813,13 +1408,6 @@ void BM_edge_calc_face_tangent(const BMEdge *e, const BMLoop *e_loop, float r_ta
normalize_v3(r_tangent);
}
-/**
- * \brief BMESH VERT/EDGE ANGLE
- *
- * Calculates the angle a verts 2 edges.
- *
- * \returns the angle in radians
- */
float BM_vert_calc_edge_angle_ex(const BMVert *v, const float fallback)
{
BMEdge *e1, *e2;
@@ -1843,10 +1431,6 @@ float BM_vert_calc_edge_angle(const BMVert *v)
return BM_vert_calc_edge_angle_ex(v, DEG2RADF(90.0f));
}
-/**
- * \note this isn't optimal to run on an array of verts,
- * see 'solidify_add_thickness' for a function which runs on an array.
- */
float BM_vert_calc_shell_factor(const BMVert *v)
{
BMIter iter;
@@ -1865,8 +1449,6 @@ float BM_vert_calc_shell_factor(const BMVert *v)
}
return 1.0f;
}
-/* alternate version of #BM_vert_calc_shell_factor which only
- * uses 'hflag' faces, but falls back to all if none found. */
float BM_vert_calc_shell_factor_ex(const BMVert *v, const float no[3], const char hflag)
{
BMIter iter;
@@ -1896,10 +1478,6 @@ float BM_vert_calc_shell_factor_ex(const BMVert *v, const float no[3], const cha
return 1.0f;
}
-/**
- * \note quite an obscure function.
- * used in bmesh operators that have a relative scale options,
- */
float BM_vert_calc_median_tagged_edge_length(const BMVert *v)
{
BMIter iter;
@@ -1920,9 +1498,6 @@ float BM_vert_calc_median_tagged_edge_length(const BMVert *v)
return 0.0f;
}
-/**
- * Returns the loop of the shortest edge in f.
- */
BMLoop *BM_face_find_shortest_loop(BMFace *f)
{
BMLoop *shortest_loop = NULL;
@@ -1944,9 +1519,6 @@ BMLoop *BM_face_find_shortest_loop(BMFace *f)
return shortest_loop;
}
-/**
- * Returns the loop of the longest edge in f.
- */
BMLoop *BM_face_find_longest_loop(BMFace *f)
{
BMLoop *longest_loop = NULL;
@@ -2020,11 +1592,6 @@ BMEdge *BM_edge_exists(BMVert *v_a, BMVert *v_b)
}
#endif
-/**
- * Returns an edge sharing the same vertices as this one.
- * This isn't an invalid state but tools should clean up these cases before
- * returning the mesh to the user.
- */
BMEdge *BM_edge_find_double(BMEdge *e)
{
BMVert *v = e->v1;
@@ -2042,10 +1609,6 @@ BMEdge *BM_edge_find_double(BMEdge *e)
return NULL;
}
-/**
- * Only #BMEdge.l access us needed, however when we want the first visible loop,
- * a utility function is needed.
- */
BMLoop *BM_edge_find_first_loop_visible(BMEdge *e)
{
if (e->l != NULL) {
@@ -2060,13 +1623,6 @@ BMLoop *BM_edge_find_first_loop_visible(BMEdge *e)
return NULL;
}
-/**
- * Given a set of vertices (varr), find out if
- * there is a face with exactly those vertices
- * (and only those vertices).
- *
- * \note there used to be a BM_face_exists_overlap function that checks for partial overlap.
- */
BMFace *BM_face_exists(BMVert **varr, int len)
{
if (varr[0]->e) {
@@ -2115,9 +1671,6 @@ BMFace *BM_face_exists(BMVert **varr, int len)
return NULL;
}
-/**
- * Check if the face has an exact duplicate (both winding directions).
- */
BMFace *BM_face_find_double(BMFace *f)
{
BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
@@ -2150,18 +1703,6 @@ BMFace *BM_face_find_double(BMFace *f)
return NULL;
}
-/**
- * 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
- * many overlapping faces.
- *
- * 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)
- *
- * \a earr and \a varr can be in any order, however they _must_ form a closed loop.
- */
bool BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len)
{
BMFace *f;
@@ -2270,7 +1811,6 @@ finally:
return ok;
}
-/* same as 'BM_face_exists_multi' but built vert array from edges */
bool BM_face_exists_multi_edge(BMEdge **earr, int len)
{
BMVert **varr = BLI_array_alloca(varr, len);
@@ -2284,20 +1824,6 @@ bool BM_face_exists_multi_edge(BMEdge **earr, int len)
return BM_face_exists_multi(varr, earr, len);
}
-/**
- * Given a set of vertices (varr), find out if
- * all those vertices overlap an existing face.
- *
- * \note The face may contain other verts \b not in \a varr.
- *
- * \note Its possible there are more than one overlapping faces,
- * in this case the first one found will be returned.
- *
- * \param varr: Array of unordered verts.
- * \param len: \a varr array length.
- * \return The face or NULL.
- */
-
BMFace *BM_face_exists_overlap(BMVert **varr, const int len)
{
BMIter viter;
@@ -2336,14 +1862,6 @@ BMFace *BM_face_exists_overlap(BMVert **varr, const int len)
return f_overlap;
}
-/**
- * Given a set of vertices (varr), find out if
- * there is a face that uses vertices only from this list
- * (that the face is a subset or made from the vertices given).
- *
- * \param varr: Array of unordered verts.
- * \param len: varr array length.
- */
bool BM_face_exists_overlap_subset(BMVert **varr, const int len)
{
BMIter viter;
@@ -2477,7 +1995,6 @@ bool BM_edge_is_any_face_flag_test(const BMEdge *e, const char hflag)
return false;
}
-/* convenience functions for checking flags */
bool BM_edge_is_any_vert_flag_test(const BMEdge *e, const char hflag)
{
return (BM_elem_flag_test(e->v1, hflag) || BM_elem_flag_test(e->v2, hflag));
@@ -2527,9 +2044,6 @@ bool BM_edge_is_any_face_len_test(const BMEdge *e, const int len)
return false;
}
-/**
- * Use within assert's to check normals are valid.
- */
bool BM_face_is_normal_valid(const BMFace *f)
{
const float eps = 0.0001f;
@@ -2591,23 +2105,6 @@ double BM_mesh_calc_volume(BMesh *bm, bool is_signed)
return vol;
}
-/* NOTE: almost duplicate of #BM_mesh_calc_edge_groups, keep in sync. */
-/**
- * Calculate isolated groups of faces with optional filtering.
- *
- * \param bm: the BMesh.
- * \param r_groups_array: Array of ints to fill in, length of bm->totface
- * (or when hflag_test is set, the number of flagged faces).
- * \param r_group_index: index, length pairs into \a r_groups_array, size of return value
- * int pairs: (array_start, array_length).
- * \param filter_fn: Filter the edge-loops or vert-loops we step over (depends on \a htype_step).
- * \param user_data: Optional user data for \a filter_fn, can be NULL.
- * \param hflag_test: Optional flag to test faces,
- * use to exclude faces from the calculation, 0 for all faces.
- * \param htype_step: BM_VERT to walk over face-verts, BM_EDGE to walk over faces edges
- * (having both set is supported too).
- * \return The number of groups found.
- */
int BM_mesh_calc_face_groups(BMesh *bm,
int *r_groups_array,
int (**r_group_index)[2],
@@ -2617,6 +2114,8 @@ int BM_mesh_calc_face_groups(BMesh *bm,
const char hflag_test,
const char htype_step)
{
+ /* NOTE: almost duplicate of #BM_mesh_calc_edge_groups, keep in sync. */
+
#ifdef DEBUG
int group_index_len = 1;
#else
@@ -2755,25 +2254,6 @@ int BM_mesh_calc_face_groups(BMesh *bm,
return group_curr;
}
-/* NOTE: almost duplicate of #BM_mesh_calc_face_groups, keep in sync. */
-/**
- * Calculate isolated groups of edges with optional filtering.
- *
- * \param bm: the BMesh.
- * \param r_groups_array: Array of ints to fill in, length of bm->totedge
- * (or when hflag_test is set, the number of flagged edges).
- * \param r_group_index: index, length pairs into \a r_groups_array, size of return value
- * int pairs: (array_start, array_length).
- * \param filter_fn: Filter the edges or verts we step over (depends on \a htype_step)
- * as to which types we deal with.
- * \param user_data: Optional user data for \a filter_fn, can be NULL.
- * \param hflag_test: Optional flag to test edges,
- * use to exclude edges from the calculation, 0 for all edges.
- * \return The number of groups found.
- *
- * \note Unlike #BM_mesh_calc_face_groups there is no 'htype_step' argument,
- * since we always walk over verts.
- */
int BM_mesh_calc_edge_groups(BMesh *bm,
int *r_groups_array,
int (**r_group_index)[2],
@@ -2781,6 +2261,8 @@ int BM_mesh_calc_edge_groups(BMesh *bm,
void *user_data,
const char hflag_test)
{
+ /* NOTE: almost duplicate of #BM_mesh_calc_face_groups, keep in sync. */
+
#ifdef DEBUG
int group_index_len = 1;
#else
@@ -2892,13 +2374,6 @@ int BM_mesh_calc_edge_groups(BMesh *bm,
return group_curr;
}
-/**
- * This is an alternative to #BM_mesh_calc_edge_groups.
- *
- * While we could call this, then create vertex & face arrays,
- * it requires looping over geometry connectivity twice,
- * this slows down edit-mesh separate by loose parts, see: T70864.
- */
int BM_mesh_calc_edge_groups_as_arrays(
BMesh *bm, BMVert **verts, BMEdge **edges, BMFace **faces, int (**r_groups)[3])
{
diff --git a/source/blender/bmesh/intern/bmesh_query.h b/source/blender/bmesh/intern/bmesh_query.h
index 021358f81ad..48a1d100c72 100644
--- a/source/blender/bmesh/intern/bmesh_query.h
+++ b/source/blender/bmesh/intern/bmesh_query.h
@@ -20,11 +20,24 @@
* \ingroup bmesh
*/
+/**
+ * Returns true if the vertex is used in a given face.
+ */
bool BM_vert_in_face(BMVert *v, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * Compares the number of vertices in an array
+ * that appear in a given face
+ */
int BM_verts_in_face_count(BMVert **varr, int len, BMFace *f) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
+/**
+ * Return true if all verts are in the face.
+ */
bool BM_verts_in_face(BMVert **varr, int len, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * Returns whether or not a given edge is part of a given face.
+ */
bool BM_edge_in_face(const BMEdge *e, const BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BLI_INLINE bool BM_edge_in_loop(const BMEdge *e, const BMLoop *l) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
@@ -35,27 +48,175 @@ BLI_INLINE bool BM_verts_in_edge(const BMVert *v1,
const BMVert *v2,
const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * Returns edge length
+ */
float BM_edge_calc_length(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * Returns edge length squared (for comparisons)
+ */
float BM_edge_calc_length_squared(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * Utility function, since enough times we have an edge
+ * and want to access 2 connected faces.
+ *
+ * \return true when only 2 faces are found.
+ */
bool BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb) ATTR_NONNULL();
+/**
+ * Utility function, since enough times we have an edge
+ * and want to access 2 connected loops.
+ *
+ * \return true when only 2 faces are found.
+ */
bool BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb) ATTR_NONNULL();
BLI_INLINE BMVert *BM_edge_other_vert(BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
+/**
+ * Given a edge and a loop (assumes the edge is manifold). returns
+ * the other faces loop, sharing the same vertex.
+ *
+ * <pre>
+ * +-------------------+
+ * | |
+ * | |
+ * |l_other <-- return |
+ * +-------------------+ <-- A manifold edge between 2 faces
+ * |l e <-- edge |
+ * |^ <-------- loop |
+ * | |
+ * +-------------------+
+ * </pre>
+ */
BMLoop *BM_edge_other_loop(BMEdge *e, BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * \brief Other Loop in Face Sharing an Edge
+ *
+ * Finds the other loop that shares \a v with \a e loop in \a f.
+ * <pre>
+ * +----------+
+ * | |
+ * | f |
+ * | |
+ * +----------+ <-- return the face loop of this vertex.
+ * v --> e
+ * ^ ^ <------- These vert args define direction
+ * in the face to check.
+ * The faces loop direction is ignored.
+ * </pre>
+ *
+ * \note caller must ensure \a e is used in \a f
+ */
BMLoop *BM_face_other_edge_loop(BMFace *f, BMEdge *e, BMVert *v) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
+/**
+ * See #BM_face_other_edge_loop This is the same functionality
+ * to be used when the edges loop is already known.
+ */
BMLoop *BM_loop_other_edge_loop(BMLoop *l, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * \brief Other Loop in Face Sharing a Vertex
+ *
+ * Finds the other loop in a face.
+ *
+ * This function returns a loop in \a f that shares an edge with \a v
+ * The direction is defined by \a v_prev, where the return value is
+ * the loop of what would be 'v_next'
+ * <pre>
+ * +----------+ <-- return the face loop of this vertex.
+ * | |
+ * | f |
+ * | |
+ * +----------+
+ * v_prev --> v
+ * ^^^^^^ ^ <-- These vert args define direction
+ * in the face to check.
+ * The faces loop direction is ignored.
+ * </pre>
+ *
+ * \note \a v_prev and \a v _implicitly_ define an edge.
+ */
BMLoop *BM_face_other_vert_loop(BMFace *f, BMVert *v_prev, BMVert *v) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
+/**
+ * Return the other loop that uses this edge.
+ *
+ * In this case the loop defines the vertex,
+ * the edge passed in defines the direction to step.
+ *
+ * <pre>
+ * +----------+ <-- Return the face-loop of this vertex.
+ * | |
+ * | e | <-- This edge defines the direction.
+ * | |
+ * +----------+ <-- This loop defines the face and vertex..
+ * l
+ * </pre>
+ *
+ */
BMLoop *BM_loop_other_vert_loop_by_edge(BMLoop *l, BMEdge *e) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
+/**
+ * \brief Other Loop in Face Sharing a Vert
+ *
+ * Finds the other loop that shares \a v with \a e loop in \a f.
+ * <pre>
+ * +----------+ <-- return the face loop of this vertex.
+ * | |
+ * | |
+ * | |
+ * +----------+ <-- This vertex defines the direction.
+ * l v
+ * ^ <------- This loop defines both the face to search
+ * and the edge, in combination with 'v'
+ * The faces loop direction is ignored.
+ * </pre>
+ */
BMLoop *BM_loop_other_vert_loop(BMLoop *l, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * Utility function to step around a fan of loops,
+ * using an edge to mark the previous side.
+ *
+ * \note all edges must be manifold,
+ * once a non manifold edge is hit, return NULL.
+ *
+ * \code{.unparsed}
+ * ,.,-->|
+ * _,-' |
+ * ,' | (notice how 'e_step'
+ * / | and 'l' define the
+ * / | direction the arrow
+ * | return | points).
+ * | loop --> |
+ * ---------------------+---------------------
+ * ^ l --> |
+ * | |
+ * assign e_step |
+ * |
+ * begin e_step ----> |
+ * |
+ * \endcode
+ */
BMLoop *BM_vert_step_fan_loop(BMLoop *l, BMEdge **e_step) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * Get the first loop of a vert. Uses the same initialization code for the first loop of the
+ * iterator API
+ */
BMLoop *BM_vert_find_first_loop(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * A version of #BM_vert_find_first_loop that ignores hidden loops.
+ */
BMLoop *BM_vert_find_first_loop_visible(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * Only #BMEdge.l access us needed, however when we want the first visible loop,
+ * a utility function is needed.
+ */
BMLoop *BM_edge_find_first_loop_visible(BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * Check if verts share a face.
+ */
bool BM_vert_pair_share_face_check(BMVert *v_a, BMVert *v_b) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
bool BM_vert_pair_share_face_check_cb(BMVert *v_a,
@@ -70,11 +231,21 @@ BMFace *BM_vert_pair_shared_face_cb(BMVert *v_a,
void *user_data,
BMLoop **r_l_a,
BMLoop **r_l_b) ATTR_NONNULL(1, 2, 4, 6, 7);
+/**
+ * Given 2 verts, find the smallest face they share and give back both loops.
+ */
BMFace *BM_vert_pair_share_face_by_len(BMVert *v_a,
BMVert *v_b,
BMLoop **r_l_a,
BMLoop **r_l_b,
const bool allow_adjacent) ATTR_NONNULL();
+/**
+ * Given 2 verts,
+ * find a face they share that has the lowest angle across these verts and give back both loops.
+ *
+ * This can be better than #BM_vert_pair_share_face_by_len
+ * because concave splits are ranked lowest.
+ */
BMFace *BM_vert_pair_share_face_by_angle(BMVert *v_a,
BMVert *v_b,
BMLoop **r_l_a,
@@ -92,57 +263,169 @@ int BM_vert_edge_count_nonwire(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NON
#define BM_vert_edge_count_is_over(v, n) (BM_vert_edge_count_at_most(v, (n) + 1) == (n) + 1)
int BM_vert_edge_count_at_most(const BMVert *v, const int count_max) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
+/**
+ * Returns the number of edges around this vertex.
+ */
int BM_vert_edge_count(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
#define BM_edge_face_count_is_equal(e, n) (BM_edge_face_count_at_most(e, (n) + 1) == n)
#define BM_edge_face_count_is_over(e, n) (BM_edge_face_count_at_most(e, (n) + 1) == (n) + 1)
int BM_edge_face_count_at_most(const BMEdge *e, const int count_max) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
+/**
+ * Returns the number of faces around this edge
+ */
int BM_edge_face_count(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
#define BM_vert_face_count_is_equal(v, n) (BM_vert_face_count_at_most(v, (n) + 1) == n)
#define BM_vert_face_count_is_over(v, n) (BM_vert_face_count_at_most(v, (n) + 1) == (n) + 1)
int BM_vert_face_count_at_most(const BMVert *v, int count_max) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
+/**
+ * Returns the number of faces around this vert
+ * length matches #BM_LOOPS_OF_VERT iterator
+ */
int BM_vert_face_count(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * The function takes a vertex at the center of a fan and returns the opposite edge in the fan.
+ * All edges in the fan must be manifold, otherwise return NULL.
+ *
+ * \note This could (probably) be done more efficiently.
+ */
BMEdge *BM_vert_other_disk_edge(BMVert *v, BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * Fast alternative to `(BM_vert_edge_count(v) == 2)`.
+ */
bool BM_vert_is_edge_pair(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * Fast alternative to `(BM_vert_edge_count(v) == 2)`
+ * that checks both edges connect to the same faces.
+ */
bool BM_vert_is_edge_pair_manifold(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * Access a verts 2 connected edges.
+ *
+ * \return true when only 2 verts are found.
+ */
bool BM_vert_edge_pair(BMVert *v, BMEdge **r_e_a, BMEdge **r_e_b);
+/**
+ * Return true if the vertex is connected to _any_ faces.
+ *
+ * same as `BM_vert_face_count(v) != 0` or `BM_vert_find_first_loop(v) == NULL`.
+ */
bool BM_vert_face_check(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * Tests whether or not the vertex is part of a wire edge.
+ * (ie: has no faces attached to it)
+ */
bool BM_vert_is_wire(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BLI_INLINE bool BM_edge_is_wire(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * A vertex is non-manifold if it meets the following conditions:
+ * 1: Loose - (has no edges/faces incident upon it).
+ * 2: Joins two distinct regions - (two pyramids joined at the tip).
+ * 3: Is part of an edge with more than 2 faces.
+ * 4: Is part of a wire edge.
+ */
bool BM_vert_is_manifold(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * A version of #BM_vert_is_manifold
+ * which only checks if we're connected to multiple isolated regions.
+ */
bool BM_vert_is_manifold_region(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BLI_INLINE bool BM_edge_is_manifold(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
bool BM_vert_is_boundary(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BLI_INLINE bool BM_edge_is_boundary(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BLI_INLINE bool BM_edge_is_contiguous(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * Check if the edge is convex or concave
+ * (depends on face winding)
+ */
bool BM_edge_is_convex(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * \return true when loop customdata is contiguous.
+ */
bool BM_edge_is_contiguous_loop_cd(const BMEdge *e,
const int cd_loop_type,
const int cd_loop_offset) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
+/**
+ * The number of loops connected to this loop (not including disconnected regions).
+ */
int BM_loop_region_loops_count_at_most(BMLoop *l, int *r_loop_total) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL(1);
int BM_loop_region_loops_count(BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+/**
+ * Check if the loop is convex or concave
+ * (depends on face normal)
+ */
bool BM_loop_is_convex(const BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BLI_INLINE bool BM_loop_is_adjacent(const BMLoop *l_a, const BMLoop *l_b) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
+/**
+ * Check if a point is inside the corner defined by a loop
+ * (within the 2 planes defined by the loops corner & face normal).
+ *
+ * \return signed, squared distance to the loops planes, less than 0.0 when outside.
+ */
float BM_loop_point_side_of_loop_test(const BMLoop *l, const float co[3]) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
+/**
+ * Check if a point is inside the edge defined by a loop
+ * (within the plane defined by the loops edge & face normal).
+ *
+ * \return signed, squared distance to the edge plane, less than 0.0 when outside.
+ */
float BM_loop_point_side_of_edge_test(const BMLoop *l, const float co[3]) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
+/**
+ * \return The previous loop, over \a eps_sq distance from \a l (or \a NULL if l_stop is reached).
+ */
BMLoop *BM_loop_find_prev_nodouble(BMLoop *l, BMLoop *l_stop, const float eps_sq);
+/**
+ * \return The next loop, over \a eps_sq distance from \a l (or \a NULL if l_stop is reached).
+ */
BMLoop *BM_loop_find_next_nodouble(BMLoop *l, BMLoop *l_stop, const float eps_sq);
+/**
+ * Calculates the angle between the previous and next loops
+ * (angle at this loops face corner).
+ *
+ * \return angle in radians
+ */
float BM_loop_calc_face_angle(const BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * \brief BM_loop_calc_face_normal
+ *
+ * Calculate the normal at this loop corner or fallback to the face normal on straight lines.
+ *
+ * \param l: The loop to calculate the normal at
+ * \param r_normal: Resulting normal
+ * \return The length of the cross product (double the area).
+ */
float BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3]) ATTR_NONNULL();
+/**
+ * #BM_loop_calc_face_normal_safe_ex with predefined sane epsilon.
+ *
+ * Since this doesn't scale based on triangle size, fixed value works well.
+ */
float BM_loop_calc_face_normal_safe(const BMLoop *l, float r_normal[3]) ATTR_NONNULL();
-float BM_loop_calc_face_normal_safe_ex(const BMLoop *l, const float epsilon, float r_normal[3])
+/**
+ * \brief BM_loop_calc_face_normal
+ *
+ * Calculate the normal at this loop corner or fallback to the face normal on straight lines.
+ *
+ * \param l: The loop to calculate the normal at.
+ * \param epsilon_sq: Value to avoid numeric errors (1e-5f works well).
+ * \param r_normal: Resulting normal.
+ */
+float BM_loop_calc_face_normal_safe_ex(const BMLoop *l, const float epsilon_sq, float r_normal[3])
ATTR_NONNULL();
+/**
+ * A version of BM_loop_calc_face_normal_safe_ex which takes vertex coordinates.
+ */
float BM_loop_calc_face_normal_safe_vcos_ex(const BMLoop *l,
const float normal_fallback[3],
float const (*vertexCos)[3],
@@ -153,15 +436,56 @@ float BM_loop_calc_face_normal_safe_vcos(const BMLoop *l,
float const (*vertexCos)[3],
float r_normal[3]) ATTR_NONNULL();
+/**
+ * \brief BM_loop_calc_face_direction
+ *
+ * Calculate the direction a loop is pointing.
+ *
+ * \param l: The loop to calculate the direction at
+ * \param r_dir: Resulting direction
+ */
void BM_loop_calc_face_direction(const BMLoop *l, float r_dir[3]);
+/**
+ * \brief BM_loop_calc_face_tangent
+ *
+ * Calculate the tangent at this loop corner or fallback to the face normal on straight lines.
+ * This vector always points inward into the face.
+ *
+ * \param l: The loop to calculate the tangent at
+ * \param r_tangent: Resulting tangent
+ */
void BM_loop_calc_face_tangent(const BMLoop *l, float r_tangent[3]);
+/**
+ * \brief BMESH EDGE/FACE ANGLE
+ *
+ * Calculates the angle between two faces.
+ * Assumes the face normals are correct.
+ *
+ * \return angle in radians
+ */
float BM_edge_calc_face_angle_ex(const BMEdge *e, const float fallback) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
float BM_edge_calc_face_angle(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * \brief BMESH EDGE/FACE ANGLE
+ *
+ * Calculates the angle between two faces.
+ * Assumes the face normals are correct.
+ *
+ * \return angle in radians
+ */
float BM_edge_calc_face_angle_signed_ex(const BMEdge *e,
const float fallback) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
+/**
+ * \brief BMESH EDGE/FACE ANGLE
+ *
+ * Calculates the angle between two faces in world space.
+ * Assumes the face normals are correct.
+ *
+ * \return angle in radians
+ */
float BM_edge_calc_face_angle_with_imat3_ex(const BMEdge *e,
const float imat3[3][3],
const float fallback) ATTR_WARN_UNUSED_RESULT
@@ -170,55 +494,210 @@ float BM_edge_calc_face_angle_with_imat3(const BMEdge *e,
const float imat3[3][3]) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
float BM_edge_calc_face_angle_signed(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * \brief BMESH EDGE/FACE TANGENT
+ *
+ * Calculate the tangent at this loop corner or fallback to the face normal on straight lines.
+ * This vector always points inward into the face.
+ *
+ * \brief BM_edge_calc_face_tangent
+ * \param e:
+ * \param e_loop: The loop to calculate the tangent at,
+ * used to get the face and winding direction.
+ * \param r_tangent: The loop corner tangent to set
+ */
void BM_edge_calc_face_tangent(const BMEdge *e, const BMLoop *e_loop, float r_tangent[3])
ATTR_NONNULL();
float BM_vert_calc_edge_angle(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * \brief BMESH VERT/EDGE ANGLE
+ *
+ * Calculates the angle a verts 2 edges.
+ *
+ * \returns the angle in radians
+ */
float BM_vert_calc_edge_angle_ex(const BMVert *v, const float fallback) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
+/**
+ * \note this isn't optimal to run on an array of verts,
+ * see 'solidify_add_thickness' for a function which runs on an array.
+ */
float BM_vert_calc_shell_factor(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/* alternate version of #BM_vert_calc_shell_factor which only
+ * uses 'hflag' faces, but falls back to all if none found. */
float BM_vert_calc_shell_factor_ex(const BMVert *v,
const float no[3],
const char hflag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * \note quite an obscure function.
+ * used in bmesh operators that have a relative scale options,
+ */
float BM_vert_calc_median_tagged_edge_length(const BMVert *v) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
+/**
+ * Returns the loop of the shortest edge in f.
+ */
BMLoop *BM_face_find_shortest_loop(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * Returns the loop of the longest edge in f.
+ */
BMLoop *BM_face_find_longest_loop(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BMEdge *BM_edge_exists(BMVert *v_a, BMVert *v_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * Returns an edge sharing the same vertices as this one.
+ * This isn't an invalid state but tools should clean up these cases before
+ * returning the mesh to the user.
+ */
BMEdge *BM_edge_find_double(BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * Given a set of vertices (varr), find out if
+ * there is a face with exactly those vertices
+ * (and only those vertices).
+ *
+ * \note there used to be a BM_face_exists_overlap function that checks for partial overlap.
+ */
BMFace *BM_face_exists(BMVert **varr, int len) ATTR_NONNULL(1);
+/**
+ * Check if the face has an exact duplicate (both winding directions).
+ */
BMFace *BM_face_find_double(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * 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
+ * many overlapping faces.
+ *
+ * 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)
+ *
+ * \a earr and \a varr can be in any order, however they _must_ form a closed loop.
+ */
bool BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
+/* same as 'BM_face_exists_multi' but built vert array from edges */
bool BM_face_exists_multi_edge(BMEdge **earr, int len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * Given a set of vertices (varr), find out if
+ * all those vertices overlap an existing face.
+ *
+ * \note The face may contain other verts \b not in \a varr.
+ *
+ * \note Its possible there are more than one overlapping faces,
+ * in this case the first one found will be returned.
+ *
+ * \param varr: Array of unordered verts.
+ * \param len: \a varr array length.
+ * \return The face or NULL.
+ */
BMFace *BM_face_exists_overlap(BMVert **varr, const int len) ATTR_WARN_UNUSED_RESULT;
+/**
+ * Given a set of vertices (varr), find out if
+ * there is a face that uses vertices only from this list
+ * (that the face is a subset or made from the vertices given).
+ *
+ * \param varr: Array of unordered verts.
+ * \param len: varr array length.
+ */
bool BM_face_exists_overlap_subset(BMVert **varr, const int len) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
+/**
+ * Returns the number of faces that are adjacent to both f1 and f2,
+ * \note Could be sped up a bit by not using iterators and by tagging
+ * faces on either side, then count the tags rather then searching.
+ */
int BM_face_share_face_count(BMFace *f_a, BMFace *f_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * Counts the number of edges two faces share (if any)
+ */
int BM_face_share_edge_count(BMFace *f_a, BMFace *f_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * Counts the number of verts two faces share (if any).
+ */
int BM_face_share_vert_count(BMFace *f_a, BMFace *f_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * same as #BM_face_share_face_count but returns a bool
+ */
bool BM_face_share_face_check(BMFace *f_a, BMFace *f_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * Returns true if the faces share an edge
+ */
bool BM_face_share_edge_check(BMFace *f_a, BMFace *f_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * Returns true if the faces share a vert.
+ */
bool BM_face_share_vert_check(BMFace *f_a, BMFace *f_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * Returns true when 2 loops share an edge (are adjacent in the face-fan)
+ */
bool BM_loop_share_edge_check(BMLoop *l_a, BMLoop *l_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * Test if e1 shares any faces with e2
+ */
bool BM_edge_share_face_check(BMEdge *e1, BMEdge *e2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * Test if e1 shares any quad faces with e2
+ */
bool BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * Tests to see if e1 shares a vertex with e2
+ */
bool BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * Return the shared vertex between the two edges or NULL
+ */
BMVert *BM_edge_share_vert(BMEdge *e1, BMEdge *e2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * \brief Return the Loop Shared by Edge and Vert
+ *
+ * Finds the loop used which uses \a in face loop \a l
+ *
+ * \note this function takes a loop rather than an edge
+ * so we can select the face that the loop should be from.
+ */
BMLoop *BM_edge_vert_share_loop(BMLoop *l, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * \brief Return the Loop Shared by Face and Vertex
+ *
+ * Finds the loop used which uses \a v in face loop \a l
+ *
+ * \note currently this just uses simple loop in future may be sped up
+ * using radial vars
+ */
BMLoop *BM_face_vert_share_loop(BMFace *f, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * \brief Return the Loop Shared by Face and Edge
+ *
+ * Finds the loop used which uses \a e in face loop \a l
+ *
+ * \note currently this just uses simple loop in future may be sped up
+ * using radial vars
+ */
BMLoop *BM_face_edge_share_loop(BMFace *f, BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
void BM_edge_ordered_verts(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2) ATTR_NONNULL();
+/**
+ * Returns the verts of an edge as used in a face
+ * if used in a face at all, otherwise just assign as used in the edge.
+ *
+ * Useful to get a deterministic winding order when calling
+ * BM_face_create_ngon() on an arbitrary array of verts,
+ * though be sure to pick an edge which has a face.
+ *
+ * \note This is in fact quite a simple check,
+ * mainly include this function so the intent is more obvious.
+ * We know these 2 verts will _always_ make up the loops edge
+ */
void BM_edge_ordered_verts_ex(const BMEdge *edge,
BMVert **r_v1,
BMVert **r_v2,
@@ -234,6 +713,7 @@ bool BM_edge_is_all_face_flag_test(const BMEdge *e,
const char hflag,
const bool respect_hide) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/* convenience functions for checking flags */
bool BM_edge_is_any_vert_flag_test(const BMEdge *e, const char hflag) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
bool BM_edge_is_any_face_flag_test(const BMEdge *e, const char hflag) ATTR_WARN_UNUSED_RESULT
@@ -246,10 +726,29 @@ bool BM_face_is_any_edge_flag_test(const BMFace *f, const char hflag) ATTR_WARN_
bool BM_edge_is_any_face_len_test(const BMEdge *e, const int len) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
+/**
+ * Use within assert's to check normals are valid.
+ */
bool BM_face_is_normal_valid(const BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
double BM_mesh_calc_volume(BMesh *bm, bool is_signed) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * Calculate isolated groups of faces with optional filtering.
+ *
+ * \param bm: the BMesh.
+ * \param r_groups_array: Array of ints to fill in, length of bm->totface
+ * (or when hflag_test is set, the number of flagged faces).
+ * \param r_group_index: index, length pairs into \a r_groups_array, size of return value
+ * int pairs: (array_start, array_length).
+ * \param filter_fn: Filter the edge-loops or vert-loops we step over (depends on \a htype_step).
+ * \param user_data: Optional user data for \a filter_fn, can be NULL.
+ * \param hflag_test: Optional flag to test faces,
+ * use to exclude faces from the calculation, 0 for all faces.
+ * \param htype_step: BM_VERT to walk over face-verts, BM_EDGE to walk over faces edges
+ * (having both set is supported too).
+ * \return The number of groups found.
+ */
int BM_mesh_calc_face_groups(BMesh *bm,
int *r_groups_array,
int (**r_group_index)[2],
@@ -258,6 +757,24 @@ int BM_mesh_calc_face_groups(BMesh *bm,
void *user_data,
const char hflag_test,
const char htype_step) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3);
+/**
+ * Calculate isolated groups of edges with optional filtering.
+ *
+ * \param bm: the BMesh.
+ * \param r_groups_array: Array of ints to fill in, length of `bm->totedge`
+ * (or when hflag_test is set, the number of flagged edges).
+ * \param r_group_index: index, length pairs into \a r_groups_array, size of return value
+ * int pairs: (array_start, array_length).
+ * \param filter_fn: Filter the edges or verts we step over (depends on \a htype_step)
+ * as to which types we deal with.
+ * \param user_data: Optional user data for \a filter_fn, can be NULL.
+ * \param hflag_test: Optional flag to test edges,
+ * use to exclude edges from the calculation, 0 for all edges.
+ * \return The number of groups found.
+ *
+ * \note Unlike #BM_mesh_calc_face_groups there is no 'htype_step' argument,
+ * since we always walk over verts.
+ */
int BM_mesh_calc_edge_groups(BMesh *bm,
int *r_groups_array,
int (**r_group_index)[2],
@@ -265,6 +782,13 @@ int BM_mesh_calc_edge_groups(BMesh *bm,
void *user_data,
const char hflag_test) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3);
+/**
+ * This is an alternative to #BM_mesh_calc_edge_groups.
+ *
+ * While we could call this, then create vertex & face arrays,
+ * it requires looping over geometry connectivity twice,
+ * this slows down edit-mesh separate by loose parts, see: T70864.
+ */
int BM_mesh_calc_edge_groups_as_arrays(BMesh *bm,
BMVert **verts,
BMEdge **edges,
diff --git a/source/blender/bmesh/intern/bmesh_query_uv.c b/source/blender/bmesh/intern/bmesh_query_uv.c
index f9b87e4e71c..f069613f5b3 100644
--- a/source/blender/bmesh/intern/bmesh_query_uv.c
+++ b/source/blender/bmesh/intern/bmesh_query_uv.c
@@ -48,14 +48,6 @@ static void uv_aspect(const BMLoop *l,
*/
#define UV_ASPECT(l, r_uv) uv_aspect(l, aspect, cd_loop_uv_offset, r_uv)
-/**
- * Computes the UV center of a face, using the mean average weighted by edge length.
- *
- * See #BM_face_calc_center_median_weighted for matching spatial functionality.
- *
- * \param aspect: Calculate the center scaling by these values, and finally dividing.
- * Since correct weighting depends on having the correct aspect.
- */
void BM_face_uv_calc_center_median_weighted(const BMFace *f,
const float aspect[2],
const int cd_loop_uv_offset,
@@ -109,9 +101,6 @@ void BM_face_uv_calc_center_median(const BMFace *f, const int cd_loop_uv_offset,
mul_v2_fl(r_cent, 1.0f / (float)f->len);
}
-/**
- * Calculate the UV cross product (use the sign to check the winding).
- */
float BM_face_uv_calc_cross(const BMFace *f, const int cd_loop_uv_offset)
{
float(*uvs)[2] = BLI_array_alloca(uvs, f->len);
@@ -148,9 +137,6 @@ void BM_face_uv_transform(BMFace *f, const float matrix[2][2], const int cd_loop
} while ((l_iter = l_iter->next) != l_first);
}
-/**
- * Check if two loops that share an edge also have the same UV coordinates.
- */
bool BM_loop_uv_share_edge_check(BMLoop *l_a, BMLoop *l_b, const int cd_loop_uv_offset)
{
BLI_assert(l_a->e == l_b->e);
@@ -165,9 +151,6 @@ bool BM_loop_uv_share_edge_check(BMLoop *l_a, BMLoop *l_b, const int cd_loop_uv_
equals_v2v2(luv_a_next->uv, luv_b_next->uv));
}
-/**
- * Check if two loops that share a vertex also have the same UV coordinates.
- */
bool BM_loop_uv_share_vert_check(BMLoop *l_a, BMLoop *l_b, const int cd_loop_uv_offset)
{
BLI_assert(l_a->v == l_b->v);
@@ -179,9 +162,6 @@ bool BM_loop_uv_share_vert_check(BMLoop *l_a, BMLoop *l_b, const int cd_loop_uv_
return true;
}
-/**
- * Check if two loops that share a vertex also have the same UV coordinates.
- */
bool BM_edge_uv_share_vert_check(BMEdge *e, BMLoop *l_a, BMLoop *l_b, const int cd_loop_uv_offset)
{
BLI_assert(l_a->v == l_b->v);
@@ -204,9 +184,6 @@ bool BM_edge_uv_share_vert_check(BMEdge *e, BMLoop *l_a, BMLoop *l_b, const int
return true;
}
-/**
- * Check if the point is inside the UV face.
- */
bool BM_face_uv_point_inside_test(const BMFace *f, const float co[2], const int cd_loop_uv_offset)
{
float(*projverts)[2] = BLI_array_alloca(projverts, f->len);
diff --git a/source/blender/bmesh/intern/bmesh_query_uv.h b/source/blender/bmesh/intern/bmesh_query_uv.h
index 850b27d3894..d63b8e5e701 100644
--- a/source/blender/bmesh/intern/bmesh_query_uv.h
+++ b/source/blender/bmesh/intern/bmesh_query_uv.h
@@ -27,6 +27,14 @@ float BM_loop_uv_calc_edge_length(const BMLoop *l,
const int cd_loop_uv_offset) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
+/**
+ * Computes the UV center of a face, using the mean average weighted by edge length.
+ *
+ * See #BM_face_calc_center_median_weighted for matching spatial functionality.
+ *
+ * \param aspect: Calculate the center scaling by these values, and finally dividing.
+ * Since correct weighting depends on having the correct aspect.
+ */
void BM_face_uv_calc_center_median_weighted(const BMFace *f,
const float aspect[2],
const int cd_loop_uv_offset,
@@ -34,6 +42,9 @@ void BM_face_uv_calc_center_median_weighted(const BMFace *f,
void BM_face_uv_calc_center_median(const BMFace *f, const int cd_loop_uv_offset, float r_cent[2])
ATTR_NONNULL();
+/**
+ * Calculate the UV cross product (use the sign to check the winding).
+ */
float BM_face_uv_calc_cross(const BMFace *f, const int cd_loop_uv_offset) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
@@ -46,19 +57,31 @@ bool BM_loop_uv_share_edge_check_with_limit(BMLoop *l_a,
const int cd_loop_uv_offset) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
+/**
+ * Check if two loops that share an edge also have the same UV coordinates.
+ */
bool BM_loop_uv_share_edge_check(BMLoop *l_a,
BMLoop *l_b,
const int cd_loop_uv_offset) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
+/**
+ * Check if two loops that share a vertex also have the same UV coordinates.
+ */
bool BM_edge_uv_share_vert_check(BMEdge *e, BMLoop *l_a, BMLoop *l_b, const int cd_loop_uv_offset)
ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * Check if two loops that share a vertex also have the same UV coordinates.
+ */
bool BM_loop_uv_share_vert_check(BMLoop *l_a,
BMLoop *l_b,
const int cd_loop_uv_offset) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
+/**
+ * Check if the point is inside the UV face.
+ */
bool BM_face_uv_point_inside_test(const BMFace *f,
const float co[2],
const int cd_loop_uv_offset) ATTR_WARN_UNUSED_RESULT
diff --git a/source/blender/bmesh/intern/bmesh_structure.c b/source/blender/bmesh/intern/bmesh_structure.c
index 1f1ad0bae5b..08b0920c115 100644
--- a/source/blender/bmesh/intern/bmesh_structure.c
+++ b/source/blender/bmesh/intern/bmesh_structure.c
@@ -47,11 +47,6 @@ void bmesh_disk_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src)
}
}
-/**
- * Handles all connected data, use with care.
- *
- * Assumes caller has setup correct state before the swap is done.
- */
void bmesh_edge_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src)
{
/* swap out loops */
@@ -268,14 +263,6 @@ bool bmesh_disk_validate(int len, BMEdge *e, BMVert *v)
return true;
}
-/**
- * \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(const BMVert *v)
{
/* is there an edge on this vert at all */
@@ -315,14 +302,6 @@ int bmesh_disk_facevert_count_at_most(const BMVert *v, const int count_max)
return count;
}
-/**
- * \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(const BMEdge *e, const BMVert *v)
{
const BMEdge *e_iter = e;
@@ -334,11 +313,6 @@ BMEdge *bmesh_disk_faceedge_find_first(const BMEdge *e, const BMVert *v)
return NULL;
}
-/**
- * Special case for BM_LOOPS_OF_VERT & BM_FACES_OF_VERT, avoids 2x calls.
- *
- * The returned BMLoop.e matches the result of #bmesh_disk_faceedge_find_first
- */
BMLoop *bmesh_disk_faceloop_find_first(const BMEdge *e, const BMVert *v)
{
const BMEdge *e_iter = e;
@@ -350,9 +324,6 @@ BMLoop *bmesh_disk_faceloop_find_first(const BMEdge *e, const BMVert *v)
return NULL;
}
-/**
- * A version of #bmesh_disk_faceloop_find_first that ignores hidden faces.
- */
BMLoop *bmesh_disk_faceloop_find_first_visible(const BMEdge *e, const BMVert *v)
{
const BMEdge *e_iter = e;
@@ -384,7 +355,6 @@ BMEdge *bmesh_disk_faceedge_find_next(const BMEdge *e, const BMVert *v)
return (BMEdge *)e;
}
-/*****radial cycle functions, e.g. loops surrounding edges**** */
bool bmesh_radial_validate(int radlen, BMLoop *l)
{
BMLoop *l_iter = l;
@@ -442,14 +412,6 @@ void bmesh_radial_loop_append(BMEdge *e, BMLoop *l)
l->e = e;
}
-/**
- * \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
- * updated (in the case that the edge's link into the radial
- * cycle was the loop which is being removed from the cycle).
- */
void bmesh_radial_loop_remove(BMEdge *e, BMLoop *l)
{
/* if e is non-NULL, l must be in the radial cycle of e */
@@ -480,10 +442,6 @@ void bmesh_radial_loop_remove(BMEdge *e, BMLoop *l)
l->e = NULL;
}
-/**
- * A version of #bmesh_radial_loop_remove which only performs the radial unlink,
- * leaving the edge untouched.
- */
void bmesh_radial_loop_unlink(BMLoop *l)
{
if (l->radial_next != l) {
@@ -497,12 +455,6 @@ void bmesh_radial_loop_unlink(BMLoop *l)
l->e = NULL;
}
-/**
- * \brief BME RADIAL FIND FIRST FACE VERT
- *
- * Finds the first loop of v around radial
- * cycle
- */
BMLoop *bmesh_radial_faceloop_find_first(const BMLoop *l, const BMVert *v)
{
const BMLoop *l_iter;
@@ -553,12 +505,6 @@ int bmesh_radial_length(const BMLoop *l)
return i;
}
-/**
- * \brief RADIAL COUNT FACE VERT
- *
- * Returns the number of times a vertex appears
- * in a radial cycle
- */
int bmesh_radial_facevert_count(const BMLoop *l, const BMVert *v)
{
const BMLoop *l_iter;
@@ -590,11 +536,6 @@ int bmesh_radial_facevert_count_at_most(const BMLoop *l, const BMVert *v, const
return count;
}
-/**
- * \brief RADIAL CHECK FACE VERT
- *
- * Quicker check for `bmesh_radial_facevert_count(...) != 0`.
- */
bool bmesh_radial_facevert_check(const BMLoop *l, const BMVert *v)
{
const BMLoop *l_iter;
@@ -608,7 +549,6 @@ bool bmesh_radial_facevert_check(const BMLoop *l, const BMVert *v)
return false;
}
-/*****loop cycle functions, e.g. loops surrounding a face**** */
bool bmesh_loop_validate(BMFace *f)
{
int i;
diff --git a/source/blender/bmesh/intern/bmesh_structure.h b/source/blender/bmesh/intern/bmesh_structure.h
index ca51a9c39de..e2e26a69d44 100644
--- a/source/blender/bmesh/intern/bmesh_structure.h
+++ b/source/blender/bmesh/intern/bmesh_structure.h
@@ -31,6 +31,7 @@
*/
/* LOOP CYCLE MANAGEMENT */
+/*****loop cycle functions, e.g. loops surrounding a face**** */
bool bmesh_loop_validate(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
/* DISK CYCLE MANAGEMENT */
@@ -48,11 +49,35 @@ BLI_INLINE BMEdge *bmesh_disk_edge_prev(const BMEdge *e, const BMVert *v) ATTR_W
ATTR_NONNULL();
int bmesh_disk_facevert_count_at_most(const BMVert *v, const int count_max) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
+/**
+ * \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(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/**
+ * \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(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
+/**
+ * Special case for BM_LOOPS_OF_VERT & BM_FACES_OF_VERT, avoids 2x calls.
+ *
+ * The returned BMLoop.e matches the result of #bmesh_disk_faceedge_find_first
+ */
BMLoop *bmesh_disk_faceloop_find_first(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
+/**
+ * A version of #bmesh_disk_faceloop_find_first that ignores hidden faces.
+ */
BMLoop *bmesh_disk_faceloop_find_first_visible(const BMEdge *e,
const BMVert *v) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
@@ -61,7 +86,19 @@ BMEdge *bmesh_disk_faceedge_find_next(const BMEdge *e, const BMVert *v) ATTR_WAR
/* RADIAL CYCLE MANAGEMENT */
void bmesh_radial_loop_append(BMEdge *e, BMLoop *l) ATTR_NONNULL();
+/**
+ * \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
+ * updated (in the case that the edge's link into the radial
+ * cycle was the loop which is being removed from the cycle).
+ */
void bmesh_radial_loop_remove(BMEdge *e, BMLoop *l) ATTR_NONNULL();
+/**
+ * A version of #bmesh_radial_loop_remove which only performs the radial unlink,
+ * leaving the edge untouched.
+ */
void bmesh_radial_loop_unlink(BMLoop *l) ATTR_NONNULL();
/* NOTE:
* bmesh_radial_loop_next(BMLoop *l) / prev.
@@ -71,20 +108,43 @@ int bmesh_radial_facevert_count_at_most(const BMLoop *l,
const BMVert *v,
const int count_max) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
+/**
+ * \brief RADIAL COUNT FACE VERT
+ *
+ * Returns the number of times a vertex appears
+ * in a radial cycle
+ */
int bmesh_radial_facevert_count(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
+/**
+ * \brief RADIAL CHECK FACE VERT
+ *
+ * Quicker check for `bmesh_radial_facevert_count(...) != 0`.
+ */
bool bmesh_radial_facevert_check(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
+/**
+ * \brief BME RADIAL FIND FIRST FACE VERT
+ *
+ * Finds the first loop of v around radial
+ * cycle
+ */
BMLoop *bmesh_radial_faceloop_find_first(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
BMLoop *bmesh_radial_faceloop_find_next(const BMLoop *l, const BMVert *v) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
BMLoop *bmesh_radial_faceloop_find_vert(const BMFace *f, const BMVert *v) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
+/*****radial cycle functions, e.g. loops surrounding edges**** */
bool bmesh_radial_validate(int radlen, BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
/* EDGE UTILITIES */
void bmesh_disk_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src) ATTR_NONNULL();
+/**
+ * Handles all connected data, use with care.
+ *
+ * Assumes caller has setup correct state before the swap is done.
+ */
void bmesh_edge_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src) ATTR_NONNULL();
void bmesh_disk_vert_replace(BMEdge *e, BMVert *v_dst, BMVert *v_src) ATTR_NONNULL();
BMEdge *bmesh_disk_edge_exists(const BMVert *v1, const BMVert *v2) ATTR_WARN_UNUSED_RESULT
diff --git a/source/blender/bmesh/intern/bmesh_walkers.c b/source/blender/bmesh/intern/bmesh_walkers.c
index b8fdd534842..e1f7430bc53 100644
--- a/source/blender/bmesh/intern/bmesh_walkers.c
+++ b/source/blender/bmesh/intern/bmesh_walkers.c
@@ -60,12 +60,6 @@ void *BMW_begin(BMWalker *walker, void *start)
return BMW_current_state(walker) ? walker->step(walker) : NULL;
}
-/**
- * \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,
@@ -124,11 +118,6 @@ void BMW_init(BMWalker *walker,
BLI_listbase_clear(&walker->states);
}
-/**
- * \brief End Walker
- *
- * Frees a walker's worklist.
- */
void BMW_end(BMWalker *walker)
{
BLI_mempool_destroy(walker->worklist);
@@ -136,9 +125,6 @@ void BMW_end(BMWalker *walker)
BLI_gset_free(walker->visit_set_alt, NULL);
}
-/**
- * \brief Step Walker
- */
void *BMW_step(BMWalker *walker)
{
BMHeader *head;
@@ -148,22 +134,11 @@ void *BMW_step(BMWalker *walker)
return head;
}
-/**
- * \brief Walker Current Depth
- *
- * Returns the current depth of the walker.
- */
-
int BMW_current_depth(BMWalker *walker)
{
return walker->depth;
}
-/**
- * \brief Main Walking Function
- *
- * Steps a mesh walker forward by one element
- */
void *BMW_walk(BMWalker *walker)
{
void *current = NULL;
@@ -177,13 +152,6 @@ void *BMW_walk(BMWalker *walker)
return NULL;
}
-/**
- * \brief Current Walker State
- *
- * Returns the first state from the walker state
- * worklist. This state is the next in the
- * worklist for processing.
- */
void *BMW_current_state(BMWalker *walker)
{
BMwGenericWalker *currentstate = walker->states.first;
@@ -203,12 +171,6 @@ void *BMW_current_state(BMWalker *walker)
return currentstate;
}
-/**
- * \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;
@@ -217,15 +179,6 @@ void BMW_state_remove(BMWalker *walker)
BLI_mempool_free(walker->worklist, oldstate);
}
-/**
- * \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
- * can fill in the state data. The new state will be inserted
- * at the front for depth-first walks, and at the end for
- * breadth-first walks.
- */
void *BMW_state_add(BMWalker *walker)
{
BMwGenericWalker *newstate;
@@ -245,12 +198,6 @@ void *BMW_state_add(BMWalker *walker)
return newstate;
}
-/**
- * \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)) {
diff --git a/source/blender/bmesh/intern/bmesh_walkers.h b/source/blender/bmesh/intern/bmesh_walkers.h
index d0348aa11dc..f36f77ce009 100644
--- a/source/blender/bmesh/intern/bmesh_walkers.h
+++ b/source/blender/bmesh/intern/bmesh_walkers.h
@@ -67,6 +67,12 @@ typedef struct BMWalker {
/* define to make BMW_init more clear */
#define BMW_MASK_NOP 0
+/**
+ * \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(struct BMWalker *walker,
BMesh *bm,
int type,
@@ -76,15 +82,61 @@ void BMW_init(struct BMWalker *walker,
BMWFlag flag,
int layer);
void *BMW_begin(BMWalker *walker, void *start);
+/**
+ * \brief Step Walker
+ */
void *BMW_step(struct BMWalker *walker);
+/**
+ * \brief End Walker
+ *
+ * Frees a walker's worklist.
+ */
void BMW_end(struct BMWalker *walker);
+/**
+ * \brief Walker Current Depth
+ *
+ * Returns the current depth of the walker.
+ */
int BMW_current_depth(BMWalker *walker);
/* These are used by custom walkers. */
+/**
+ * \brief Current Walker State
+ *
+ * Returns the first state from the walker state
+ * worklist. This state is the next in the
+ * worklist for processing.
+ */
void *BMW_current_state(BMWalker *walker);
+/**
+ * \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
+ * can fill in the state data. The new state will be inserted
+ * at the front for depth-first walks, and at the end for
+ * breadth-first walks.
+ */
void *BMW_state_add(BMWalker *walker);
+/**
+ * \brief Remove Current Walker State
+ *
+ * Remove and free an item from the end of the walker state
+ * worklist.
+ */
void BMW_state_remove(BMWalker *walker);
+/**
+ * \brief Main Walking Function
+ *
+ * Steps a mesh walker forward by one element
+ */
void *BMW_walk(BMWalker *walker);
+/**
+ * \brief Reset Walker
+ *
+ * Frees all states from the worklist, resetting the walker
+ * for reuse in a new walk.
+ */
void BMW_reset(BMWalker *walker);
#define BMW_ITER(ele, walker, data) \
diff --git a/source/blender/bmesh/intern/bmesh_walkers_impl.c b/source/blender/bmesh/intern/bmesh_walkers_impl.c
index 7931e953295..15d3a6a6a53 100644
--- a/source/blender/bmesh/intern/bmesh_walkers_impl.c
+++ b/source/blender/bmesh/intern/bmesh_walkers_impl.c
@@ -94,6 +94,7 @@ static bool bmw_edge_is_wire(const BMWalker *walker, const BMEdge *e)
}
return BM_edge_is_wire(e);
}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -107,6 +108,7 @@ static bool bmw_edge_is_wire(const BMWalker *walker, const BMEdge *e)
*
* \todo Add restriction flag/callback for wire edges.
* \{ */
+
static void bmw_VertShellWalker_visitEdge(BMWalker *walker, BMEdge *e)
{
BMwShellWalker *shellWalk = NULL;
@@ -236,6 +238,7 @@ static void *bmw_VertShellWalker_step(BMWalker *walker)
*
* \note this is mainly useful to loop over a shell delimited by edges.
* \{ */
+
static void bmw_LoopShellWalker_visitLoop(BMWalker *walker, BMLoop *l)
{
BMwLoopShellWalker *shellWalk = NULL;
@@ -509,6 +512,7 @@ static void *bmw_LoopShellWireWalker_step(BMWalker *walker)
* Starts at an edge on the mesh and walks over the 'shell' it belongs
* to via visiting connected faces.
* \{ */
+
static void bmw_FaceShellWalker_visitEdge(BMWalker *walker, BMEdge *e)
{
BMwShellWalker *shellWalk = NULL;
@@ -564,6 +568,7 @@ static void *bmw_FaceShellWalker_step(BMWalker *walker)
return e;
}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -573,6 +578,7 @@ static void *bmw_FaceShellWalker_step(BMWalker *walker)
*
* Walk from a vertex to all connected vertices.
* \{ */
+
static void bmw_ConnectedVertexWalker_visitVertex(BMWalker *walker, BMVert *v)
{
BMwConnectedVertexWalker *vwalk;
@@ -640,6 +646,7 @@ static void *bmw_ConnectedVertexWalker_step(BMWalker *walker)
*
* \todo Add restriction flag/callback for wire edges.
* \{ */
+
static void bmw_IslandboundWalker_begin(BMWalker *walker, void *data)
{
BMLoop *l = data;
@@ -735,6 +742,7 @@ static void *bmw_IslandboundWalker_step(BMWalker *walker)
*
* \todo Add restriction flag/callback for wire edges.
* \{ */
+
static void bmw_IslandWalker_begin(BMWalker *walker, void *data)
{
BMwIslandWalker *iwalk = NULL;
@@ -1299,6 +1307,7 @@ static void *bmw_FaceLoopWalker_step(BMWalker *walker)
* Conditions for starting and stepping the edge ring have been
* tuned to match behavior users expect (dating back to v2.4x).
* \{ */
+
static void bmw_EdgeringWalker_begin(BMWalker *walker, void *data)
{
BMwEdgeringWalker *lwalk, owalk, *owalk_pt;
@@ -1850,6 +1859,12 @@ static BMWalker bmw_ConnectedVertexWalker_Type = {
BM_VERT, /* Valid restrict masks. */
};
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name All Walker Types
+ * \{ */
+
BMWalker *bm_walker_types[] = {
&bmw_VertShellWalker_Type, /* #BMW_VERT_SHELL */
&bmw_LoopShellWalker_Type, /* #BMW_LOOP_SHELL */
@@ -1868,3 +1883,5 @@ BMWalker *bm_walker_types[] = {
};
const int bm_totwalkers = ARRAY_SIZE(bm_walker_types);
+
+/** \} */
diff --git a/source/blender/bmesh/operators/bmo_connect_pair.c b/source/blender/bmesh/operators/bmo_connect_pair.c
index 660633e8a0f..29fd8d9094b 100644
--- a/source/blender/bmesh/operators/bmo_connect_pair.c
+++ b/source/blender/bmesh/operators/bmo_connect_pair.c
@@ -120,19 +120,18 @@ typedef struct PathLinkState {
float co_prev[3];
} PathLinkState;
-/**
- * \name Min Dist Dir Util
+/* -------------------------------------------------------------------- */
+/** \name Min Dist Dir Util
*
* Simply getting the closest intersecting vert/edge is _not_ good enough. see T43792
* we need to get the closest in both directions since the absolute closest may be a dead-end.
*
* Logic is simple:
*
- * - first intersection, store the direction.
- * - successive intersections will update the first distance if its aligned with the first hit.
+ * - First intersection, store the direction.
+ * - Successive intersections will update the first distance if its aligned with the first hit.
* otherwise update the opposite distance.
- * - caller stores best outcome in both directions.
- *
+ * - Caller stores best outcome in both directions.
* \{ */
typedef struct MinDistDir {
diff --git a/source/blender/bmesh/operators/bmo_create.c b/source/blender/bmesh/operators/bmo_create.c
index a740e4d66e8..c337724d096 100644
--- a/source/blender/bmesh/operators/bmo_create.c
+++ b/source/blender/bmesh/operators/bmo_create.c
@@ -31,12 +31,11 @@
#define ELE_NEW 1
#define ELE_OUT 2
-/* This is what runs when pressing the F key
- * doing the best thing here isn't always easy create vs dissolve, its nice to support
- * but it _really_ gives issues we might have to not call dissolve. - campbell
- */
void bmo_contextual_create_exec(BMesh *bm, BMOperator *op)
{
+ /* NOTE(@campbellbarton): doing the best thing here isn't always easy create vs dissolve,
+ * its nice to support but it _really_ gives issues we might have to not call dissolve. */
+
BMOIter oiter;
BMHeader *h;
int totv = 0, tote = 0, totf = 0;
diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c
index 360dcc2c79e..82d277ec3af 100644
--- a/source/blender/bmesh/operators/bmo_dissolve.c
+++ b/source/blender/bmesh/operators/bmo_dissolve.c
@@ -488,7 +488,6 @@ void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op)
/* done with cleanup */
}
-/* Limited Dissolve */
void bmo_dissolve_limit_exec(BMesh *bm, BMOperator *op)
{
BMOpSlot *einput = BMO_slot_get(op->slots_in, "edges");
diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c
index d8047499780..69404c8ba0e 100644
--- a/source/blender/bmesh/operators/bmo_primitive.c
+++ b/source/blender/bmesh/operators/bmo_primitive.c
@@ -787,14 +787,6 @@ void bmo_create_grid_exec(BMesh *bm, BMOperator *op)
}
}
-/**
- * Fills first available UV-map with grid-like UV's for all faces with `oflag` set.
- *
- * \param bm: The BMesh to operate on
- * \param x_segments: The x-resolution of the grid
- * \param y_segments: The y-resolution of the grid
- * \param oflag: The flag to check faces with.
- */
void BM_mesh_calc_uvs_grid(BMesh *bm,
const uint x_segments,
const uint y_segments,
@@ -1130,12 +1122,6 @@ static void bm_mesh_calc_uvs_sphere_face(BMFace *f, const int cd_loop_uv_offset)
}
}
-/**
- * Fills first available UV-map with spherical projected UVs for all faces with `oflag` set.
- *
- * \param bm: The BMesh to operate on
- * \param oflag: The flag to check faces with.
- */
void BM_mesh_calc_uvs_sphere(BMesh *bm, const short oflag, const int cd_loop_uv_offset)
{
BMFace *f;
@@ -1343,14 +1329,6 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op)
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK);
}
-/**
- * Fills first available UV-map with 2D projected UVs for all faces with `oflag` set.
- *
- * \param bm: The BMesh to operate on.
- * \param mat: The transform matrix applied to the created circle.
- * \param radius: The size of the circle.
- * \param oflag: The flag to check faces with.
- */
void BM_mesh_calc_uvs_circle(
BMesh *bm, float mat[4][4], const float radius, const short oflag, const int cd_loop_uv_offset)
{
@@ -1534,17 +1512,6 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op)
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK);
}
-/**
- * Fills first available UV-map with cylinder/cone-like UVs for all faces with `oflag` set.
- *
- * \param bm: The BMesh to operate on.
- * \param mat: The transform matrix applied to the created cone/cylinder.
- * \param radius_top: The size of the top end of the cone/cylinder.
- * \param radius_bottom: The size of the bottom end of the cone/cylinder.
- * \param segments: The number of subdivisions in the sides of the cone/cylinder.
- * \param cap_ends: Whether the ends of the cone/cylinder are filled or not.
- * \param oflag: The flag to check faces with.
- */
void BM_mesh_calc_uvs_cone(BMesh *bm,
float mat[4][4],
const float radius_top,
@@ -1710,15 +1677,6 @@ void bmo_create_cube_exec(BMesh *bm, BMOperator *op)
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK);
}
-/**
- * Fills first available UV-map with cube-like UVs for all faces with `oflag` set.
- *
- * \note Expects tagged faces to be six quads.
- * \note Caller must order faces for correct alignment.
- *
- * \param bm: The BMesh to operate on.
- * \param oflag: The flag to check faces with.
- */
void BM_mesh_calc_uvs_cube(BMesh *bm, const short oflag)
{
BMFace *f;
diff --git a/source/blender/bmesh/operators/bmo_split_edges.c b/source/blender/bmesh/operators/bmo_split_edges.c
index d030a6e11b0..5a00094ef45 100644
--- a/source/blender/bmesh/operators/bmo_split_edges.c
+++ b/source/blender/bmesh/operators/bmo_split_edges.c
@@ -27,7 +27,6 @@
#include "intern/bmesh_operators_private.h" /* own include */
-/* keep this operator fast, its used in a modifier */
void bmo_split_edges_exec(BMesh *bm, BMOperator *op)
{
const bool use_verts = BMO_slot_bool_get(op->slots_in, "use_verts");
diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c
index 7311c94a0d8..05837ae2a0e 100644
--- a/source/blender/bmesh/operators/bmo_subdivide.c
+++ b/source/blender/bmesh/operators/bmo_subdivide.c
@@ -1187,12 +1187,14 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op)
vlen = BLI_array_len(loops);
/* find the boundary of one of the split edges */
- for (a = 1; a < vlen; a++) {
- if (!BMO_vert_flag_test(bm, loops[a - 1]->v, ELE_INNER) &&
+ for (a = 0; a < vlen; a++) {
+ if (!BMO_vert_flag_test(bm, loops[a ? (a - 1) : (vlen - 1)]->v, ELE_INNER) &&
BMO_vert_flag_test(bm, loops[a]->v, ELE_INNER)) {
break;
}
}
+ /* Failure to break means there is an internal error. */
+ BLI_assert(a < vlen);
if (BMO_vert_flag_test(bm, loops[(a + numcuts + 1) % vlen]->v, ELE_INNER)) {
b = (a + numcuts + 1) % vlen;
diff --git a/source/blender/bmesh/operators/bmo_subdivide_edgering.c b/source/blender/bmesh/operators/bmo_subdivide_edgering.c
index 6a80f360f59..7f0bfc5e2c9 100644
--- a/source/blender/bmesh/operators/bmo_subdivide_edgering.c
+++ b/source/blender/bmesh/operators/bmo_subdivide_edgering.c
@@ -1061,9 +1061,10 @@ static bool bm_edge_rim_test_cb(BMEdge *e, void *bm_v)
return BMO_edge_flag_test_bool(bm, e, EDGE_RIM);
}
-/* keep this operator fast, its used in a modifier */
void bmo_subdivide_edgering_exec(BMesh *bm, BMOperator *op)
{
+ /* NOTE: keep this operator fast, its used in a modifier. */
+
ListBase eloops_rim = {NULL};
BMOIter siter;
BMEdge *e;
diff --git a/source/blender/bmesh/operators/bmo_unsubdivide.c b/source/blender/bmesh/operators/bmo_unsubdivide.c
index c5de6df34a7..f11e359e962 100644
--- a/source/blender/bmesh/operators/bmo_unsubdivide.c
+++ b/source/blender/bmesh/operators/bmo_unsubdivide.c
@@ -29,11 +29,10 @@
#include "intern/bmesh_operators_private.h" /* own include */
-/* - BMVert.flag & BM_ELEM_TAG: shows we touched this vert
- * - BMVert.index == -1: shows we will remove this vert
- */
void bmo_unsubdivide_exec(BMesh *bm, BMOperator *op)
{
+ /* - `BMVert.flag & BM_ELEM_TAG`: Shows we touched this vert.
+ * - `BMVert.index == -1`: Shows we will remove this vert. */
BMVert *v;
BMIter iter;
diff --git a/source/blender/bmesh/tools/bmesh_beautify.c b/source/blender/bmesh/tools/bmesh_beautify.c
index d5c5063f2cb..b7cf9c88282 100644
--- a/source/blender/bmesh/tools/bmesh_beautify.c
+++ b/source/blender/bmesh/tools/bmesh_beautify.c
@@ -235,12 +235,6 @@ static float bm_edge_calc_rotate_beauty__angle(const float v1[3],
return FLT_MAX;
}
-/**
- * Assuming we have 2 triangles sharing an edge (2 - 4),
- * check if the edge running from (1 - 3) gives better results.
- *
- * \return (negative number means the edge can be rotated, lager == better).
- */
float BM_verts_calc_rotate_beauty(const BMVert *v1,
const BMVert *v2,
const BMVert *v3,
@@ -374,9 +368,6 @@ static void bm_edge_update_beauty_cost(BMEdge *e,
/* -------------------------------------------------------------------- */
/* Beautify Fill */
-/**
- * \note This function sets the edge indices to invalid values.
- */
void BM_mesh_beautify_fill(BMesh *bm,
BMEdge **edge_array,
const int edge_array_len,
diff --git a/source/blender/bmesh/tools/bmesh_beautify.h b/source/blender/bmesh/tools/bmesh_beautify.h
index d0fef828e7c..2e7950118c1 100644
--- a/source/blender/bmesh/tools/bmesh_beautify.h
+++ b/source/blender/bmesh/tools/bmesh_beautify.h
@@ -27,6 +27,9 @@ enum {
EDGE_RESTRICT_DEGENERATE = (1 << 1),
};
+/**
+ * \note This function sets the edge indices to invalid values.
+ */
void BM_mesh_beautify_fill(BMesh *bm,
BMEdge **edge_array,
const int edge_array_len,
@@ -35,6 +38,12 @@ void BM_mesh_beautify_fill(BMesh *bm,
const short oflag_edge,
const short oflag_face);
+/**
+ * Assuming we have 2 triangles sharing an edge (2 - 4),
+ * check if the edge running from (1 - 3) gives better results.
+ *
+ * \return (negative number means the edge can be rotated, lager == better).
+ */
float BM_verts_calc_rotate_beauty(const BMVert *v1,
const BMVert *v2,
const BMVert *v3,
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index 6cf3641fed2..2f471bf0b81 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -7443,18 +7443,6 @@ static void bevel_limit_offset(BevelParams *bp, BMesh *bm)
}
}
-/**
- * - Currently only bevels BM_ELEM_TAG'd verts and edges.
- *
- * - Newly created faces, edges, and verts are BM_ELEM_TAG'd too,
- * the caller needs to ensure these are cleared before calling
- * if its going to use this tag.
- *
- * - If limit_offset is set, adjusts offset down if necessary
- * to avoid geometry collisions.
- *
- * \warning all tagged edges _must_ be manifold.
- */
void BM_mesh_bevel(BMesh *bm,
const float offset,
const int offset_type,
diff --git a/source/blender/bmesh/tools/bmesh_bevel.h b/source/blender/bmesh/tools/bmesh_bevel.h
index de57e1c62a9..03c10ee9f80 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.h
+++ b/source/blender/bmesh/tools/bmesh_bevel.h
@@ -23,6 +23,18 @@
struct CurveProfile;
struct MDeformVert;
+/**
+ * - Currently only bevels BM_ELEM_TAG'd verts and edges.
+ *
+ * - Newly created faces, edges, and verts are BM_ELEM_TAG'd too,
+ * the caller needs to ensure these are cleared before calling
+ * if its going to use this tag.
+ *
+ * - If limit_offset is set, adjusts offset down if necessary
+ * to avoid geometry collisions.
+ *
+ * \warning all tagged edges _must_ be manifold.
+ */
void BM_mesh_bevel(BMesh *bm,
const float offset,
const int offset_type,
diff --git a/source/blender/bmesh/tools/bmesh_bisect_plane.c b/source/blender/bmesh/tools/bmesh_bisect_plane.c
index 8f03b86b859..d220b183b8d 100644
--- a/source/blender/bmesh/tools/bmesh_bisect_plane.c
+++ b/source/blender/bmesh/tools/bmesh_bisect_plane.c
@@ -88,7 +88,7 @@ static short plane_point_test_v3(const float plane[4],
*
* Hide flag access
* (for more readable code since same flag is used differently for vert/edge-face).
- */
+ * \{ */
/** Enable when vertex is in the center and its faces have been added to the stack. */
BLI_INLINE void vert_is_center_enable(BMVert *v)
@@ -411,11 +411,6 @@ finally:
/** \name Public BMesh Bisect Function
* \{ */
-/**
- * \param use_snap_center: Snap verts onto the plane.
- * \param use_tag: Only bisect tagged edges and faces.
- * \param oflag_center: Operator flag, enabled for geometry on the axis (existing and created)
- */
void BM_mesh_bisect_plane(BMesh *bm,
const float plane[4],
const bool use_snap_center,
diff --git a/source/blender/bmesh/tools/bmesh_bisect_plane.h b/source/blender/bmesh/tools/bmesh_bisect_plane.h
index f64b5d8097c..120935296b7 100644
--- a/source/blender/bmesh/tools/bmesh_bisect_plane.h
+++ b/source/blender/bmesh/tools/bmesh_bisect_plane.h
@@ -20,6 +20,11 @@
* \ingroup bmesh
*/
+/**
+ * \param use_snap_center: Snap verts onto the plane.
+ * \param use_tag: Only bisect tagged edges and faces.
+ * \param oflag_center: Operator flag, enabled for geometry on the axis (existing and created)
+ */
void BM_mesh_bisect_plane(BMesh *bm,
const float plane[4],
const bool use_snap_center,
diff --git a/source/blender/bmesh/tools/bmesh_boolean.cc b/source/blender/bmesh/tools/bmesh_boolean.cc
index 487ef6427af..e244bc377db 100644
--- a/source/blender/bmesh/tools/bmesh_boolean.cc
+++ b/source/blender/bmesh/tools/bmesh_boolean.cc
@@ -456,14 +456,6 @@ bool BM_mesh_boolean(BMesh *bm,
static_cast<blender::meshintersect::BoolOpType>(boolean_mode));
}
-/**
- * Perform a Knife Intersection operation on the mesh bm.
- * There are either one or two operands, the same as described above for BM_mesh_boolean().
- * If use_separate_all is true, each edge that is created from the intersection should
- * be used to separate all its incident faces. TODO: implement that.
- * TODO: need to ensure that "selected/non-selected" flag of original faces gets propagated
- * to the intersection result faces.
- */
bool BM_mesh_boolean_knife(BMesh *bm,
struct BMLoop *(*looptris)[3],
const int looptris_tot,
diff --git a/source/blender/bmesh/tools/bmesh_boolean.h b/source/blender/bmesh/tools/bmesh_boolean.h
index ed77242e14c..4dacc7b1095 100644
--- a/source/blender/bmesh/tools/bmesh_boolean.h
+++ b/source/blender/bmesh/tools/bmesh_boolean.h
@@ -35,6 +35,16 @@ bool BM_mesh_boolean(BMesh *bm,
const bool hole_tolerant,
const int boolean_mode);
+/**
+ * Perform a Knife Intersection operation on the mesh `bm`.
+ * There are either one or two operands, the same as described above for #BM_mesh_boolean().
+ *
+ * \param use_separate_all: When true, each edge that is created from the intersection should
+ * be used to separate all its incident faces. TODO: implement that.
+ *
+ * TODO: need to ensure that "selected/non-selected" flag of original faces gets propagated
+ * to the intersection result faces.
+ */
bool BM_mesh_boolean_knife(BMesh *bm,
struct BMLoop *(*looptris)[3],
const int looptris_tot,
diff --git a/source/blender/bmesh/tools/bmesh_decimate.h b/source/blender/bmesh/tools/bmesh_decimate.h
index c62288c269a..1de241a1326 100644
--- a/source/blender/bmesh/tools/bmesh_decimate.h
+++ b/source/blender/bmesh/tools/bmesh_decimate.h
@@ -20,6 +20,20 @@
* \ingroup bmesh
*/
+/**
+ * \brief BM_mesh_decimate
+ * \param bm: The mesh
+ * \param factor: face count multiplier [0 - 1]
+ * \param vweights: Optional array of vertex aligned weights [0 - 1],
+ * a vertex group is the usual source for this.
+ * \param symmetry_axis: Axis of symmetry, -1 to disable mirror decimate.
+ * \param symmetry_eps: Threshold when matching mirror verts.
+ *
+ * \note The caller is responsible for recalculating face and vertex normals.
+ * - Vertex normals are maintained while decimating,
+ * although they won't necessarily match the final recalculated normals.
+ * - Face normals are not maintained at all.
+ */
void BM_mesh_decimate_collapse(BMesh *bm,
const float factor,
float *vweights,
@@ -28,6 +42,8 @@ void BM_mesh_decimate_collapse(BMesh *bm,
const int symmetry_axis,
const float symmetry_eps);
+/**
+ * \param tag_only: so we can call this from an operator */
void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const bool tag_only);
void BM_mesh_decimate_unsubdivide(BMesh *bm, const int iterations);
diff --git a/source/blender/bmesh/tools/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c
index 97fccbe01fd..e90e50ef8ff 100644
--- a/source/blender/bmesh/tools/bmesh_decimate_collapse.c
+++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c
@@ -1277,20 +1277,6 @@ static bool bm_decim_edge_collapse(BMesh *bm,
/* Main Decimate Function
* ********************** */
-/**
- * \brief BM_mesh_decimate
- * \param bm: The mesh
- * \param factor: face count multiplier [0 - 1]
- * \param vweights: Optional array of vertex aligned weights [0 - 1],
- * a vertex group is the usual source for this.
- * \param symmetry_axis: Axis of symmetry, -1 to disable mirror decimate.
- * \param symmetry_eps: Threshold when matching mirror verts.
- *
- * \note The caller is responsible for recalculating face and vertex normals.
- * - Vertex normals are maintained while decimating,
- * although they won't necessarily match the final recalculated normals.
- * - Face normals are not maintained at all.
- */
void BM_mesh_decimate_collapse(BMesh *bm,
const float factor,
float *vweights,
diff --git a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c
index c96a7be1adf..ca0f31fdf75 100644
--- a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c
+++ b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c
@@ -168,8 +168,6 @@ enum {
* - BMVert.index == -1: shows we will remove this vert
*/
-/**
- * \param tag_only: so we can call this from an operator */
void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const bool tag_only)
{
#ifdef USE_WALKER
diff --git a/source/blender/bmesh/tools/bmesh_edgenet.c b/source/blender/bmesh/tools/bmesh_edgenet.c
index 242b269ed47..4cad1d3cb3c 100644
--- a/source/blender/bmesh/tools/bmesh_edgenet.c
+++ b/source/blender/bmesh/tools/bmesh_edgenet.c
@@ -422,15 +422,6 @@ static LinkNode *bm_edgenet_path_calc_best(BMEdge *e,
return path;
}
-/**
- * Fill in faces from an edgenet made up of boundary and wire edges.
- *
- * \note New faces currently don't have their normals calculated and are flipped randomly.
- * The caller needs to flip faces correctly.
- *
- * \param bm: The mesh to operate on.
- * \param use_edge_tag: Only fill tagged edges.
- */
void BM_mesh_edgenet(BMesh *bm, const bool use_edge_tag, const bool use_new_face_tag)
{
VertNetInfo *vnet_info = MEM_callocN(sizeof(*vnet_info) * (size_t)bm->totvert, __func__);
diff --git a/source/blender/bmesh/tools/bmesh_edgenet.h b/source/blender/bmesh/tools/bmesh_edgenet.h
index 7855b2e2886..20edb30442c 100644
--- a/source/blender/bmesh/tools/bmesh_edgenet.h
+++ b/source/blender/bmesh/tools/bmesh_edgenet.h
@@ -20,4 +20,13 @@
* \ingroup bmesh
*/
+/**
+ * Fill in faces from an edgenet made up of boundary and wire edges.
+ *
+ * \note New faces currently don't have their normals calculated and are flipped randomly.
+ * The caller needs to flip faces correctly.
+ *
+ * \param bm: The mesh to operate on.
+ * \param use_edge_tag: Only fill tagged edges.
+ */
void BM_mesh_edgenet(BMesh *bm, const bool use_edge_tag, const bool use_new_face_tag);
diff --git a/source/blender/bmesh/tools/bmesh_edgesplit.c b/source/blender/bmesh/tools/bmesh_edgesplit.c
index 388e7f41aba..cd5200a660d 100644
--- a/source/blender/bmesh/tools/bmesh_edgesplit.c
+++ b/source/blender/bmesh/tools/bmesh_edgesplit.c
@@ -28,11 +28,6 @@
#include "bmesh_edgesplit.h" /* own include */
-/**
- * \param use_verts: Use flagged verts instead of edges.
- * \param tag_only: Only split tagged edges.
- * \param copy_select: Copy selection history.
- */
void BM_mesh_edgesplit(BMesh *bm,
const bool use_verts,
const bool tag_only,
diff --git a/source/blender/bmesh/tools/bmesh_edgesplit.h b/source/blender/bmesh/tools/bmesh_edgesplit.h
index 4d3db67ef5f..bcbb3ab7857 100644
--- a/source/blender/bmesh/tools/bmesh_edgesplit.h
+++ b/source/blender/bmesh/tools/bmesh_edgesplit.h
@@ -24,6 +24,11 @@
extern "C" {
#endif
+/**
+ * \param use_verts: Use flagged verts instead of edges.
+ * \param tag_only: Only split tagged edges.
+ * \param copy_select: Copy selection history.
+ */
void BM_mesh_edgesplit(BMesh *bm,
const bool use_verts,
const bool tag_only,
diff --git a/source/blender/bmesh/tools/bmesh_intersect.c b/source/blender/bmesh/tools/bmesh_intersect.c
index 947442c7bd8..6824dd5008a 100644
--- a/source/blender/bmesh/tools/bmesh_intersect.c
+++ b/source/blender/bmesh/tools/bmesh_intersect.c
@@ -947,14 +947,6 @@ static int isect_bvhtree_point_v3(BVHTree *tree, const float **looptris, const f
#endif /* USE_BVH */
-/**
- * Intersect tessellated faces
- * leaving the resulting edges tagged.
- *
- * \param test_fn: Return value: -1: skip, 0: tree_a, 1: tree_b (use_self == false)
- * \param boolean_mode: -1: no-boolean, 0: intersection... see #BMESH_ISECT_BOOLEAN_ISECT.
- * \return true if the mesh is changed (intersections cut or faces removed from boolean).
- */
bool BM_mesh_intersect(BMesh *bm,
struct BMLoop *(*looptris)[3],
const int looptris_tot,
diff --git a/source/blender/bmesh/tools/bmesh_intersect.h b/source/blender/bmesh/tools/bmesh_intersect.h
index d09ea67a3bb..a6c91715f31 100644
--- a/source/blender/bmesh/tools/bmesh_intersect.h
+++ b/source/blender/bmesh/tools/bmesh_intersect.h
@@ -24,6 +24,14 @@
extern "C" {
#endif
+/**
+ * Intersect tessellated faces
+ * leaving the resulting edges tagged.
+ *
+ * \param test_fn: Return value: -1: skip, 0: tree_a, 1: tree_b (use_self == false)
+ * \param boolean_mode: -1: no-boolean, 0: intersection... see #BMESH_ISECT_BOOLEAN_ISECT.
+ * \return true if the mesh is changed (intersections cut or faces removed from boolean).
+ */
bool BM_mesh_intersect(BMesh *bm,
struct BMLoop *(*looptris)[3],
const int looptris_tot,
diff --git a/source/blender/bmesh/tools/bmesh_path.c b/source/blender/bmesh/tools/bmesh_path.c
index ea1e7eb1e43..52bb92a6221 100644
--- a/source/blender/bmesh/tools/bmesh_path.c
+++ b/source/blender/bmesh/tools/bmesh_path.c
@@ -580,4 +580,5 @@ LinkNode *BM_mesh_calc_path_face(BMesh *bm,
return path;
}
+
/** \} */
diff --git a/source/blender/bmesh/tools/bmesh_path_uv.c b/source/blender/bmesh/tools/bmesh_path_uv.c
index 30b109d4731..131a8aa0085 100644
--- a/source/blender/bmesh/tools/bmesh_path_uv.c
+++ b/source/blender/bmesh/tools/bmesh_path_uv.c
@@ -198,6 +198,7 @@ struct LinkNode *BM_mesh_calc_path_uv_vert(BMesh *bm,
/* -------------------------------------------------------------------- */
/** \name BM_mesh_calc_path_uv_edge
* \{ */
+
/* TODO(campbell): not very urgent, since the operator fakes this using vertex path. */
/** \} */
diff --git a/source/blender/bmesh/tools/bmesh_region_match.c b/source/blender/bmesh/tools/bmesh_region_match.c
index 924538490ad..2ada18f51e7 100644
--- a/source/blender/bmesh/tools/bmesh_region_match.c
+++ b/source/blender/bmesh/tools/bmesh_region_match.c
@@ -1223,6 +1223,7 @@ static BMEdge *bm_face_region_pivot_edge_find(BMFace **faces_region,
return e_pivot;
}
+
/** \} */
#endif /* USE_PIVOT_SEARCH */
@@ -1332,12 +1333,6 @@ static void bm_vert_fasthash_destroy(UUIDFashMatch *fm)
#endif /* USE_PIVOT_FASTMATCH */
-/**
- * Take a face-region and return a list of matching face-regions.
- *
- * \param faces_region: A single, contiguous face-region.
- * \return A list of matching null-terminated face-region arrays.
- */
int BM_mesh_region_match(BMesh *bm,
BMFace **faces_region,
uint faces_region_len,
diff --git a/source/blender/bmesh/tools/bmesh_region_match.h b/source/blender/bmesh/tools/bmesh_region_match.h
index 799af938c31..7b7233783ce 100644
--- a/source/blender/bmesh/tools/bmesh_region_match.h
+++ b/source/blender/bmesh/tools/bmesh_region_match.h
@@ -20,6 +20,12 @@
* \ingroup bmesh
*/
+/**
+ * Take a face-region and return a list of matching face-regions.
+ *
+ * \param faces_region: A single, contiguous face-region.
+ * \return A list of matching null-terminated face-region arrays.
+ */
int BM_mesh_region_match(BMesh *bm,
BMFace **faces_region,
uint faces_region_len,
diff --git a/source/blender/bmesh/tools/bmesh_separate.c b/source/blender/bmesh/tools/bmesh_separate.c
index 3c69ea111bf..e00829604d5 100644
--- a/source/blender/bmesh/tools/bmesh_separate.c
+++ b/source/blender/bmesh/tools/bmesh_separate.c
@@ -32,10 +32,6 @@
#include "bmesh_separate.h" /* own include */
#include "intern/bmesh_private.h"
-/**
- * Split all faces that match `filter_fn`.
- * \note
- */
void BM_mesh_separate_faces(BMesh *bm, BMFaceFilterFunc filter_fn, void *user_data)
{
BMFace **faces_array_all = MEM_mallocN(bm->totface * sizeof(BMFace *), __func__);
diff --git a/source/blender/bmesh/tools/bmesh_separate.h b/source/blender/bmesh/tools/bmesh_separate.h
index 9260903a8fa..8c599eef2b0 100644
--- a/source/blender/bmesh/tools/bmesh_separate.h
+++ b/source/blender/bmesh/tools/bmesh_separate.h
@@ -20,4 +20,8 @@
* \ingroup bmesh
*/
+/**
+ * Split all faces that match `filter_fn`.
+ * \note
+ */
void BM_mesh_separate_faces(BMesh *bm, BMFaceFilterFunc filter_fn, void *user_data);
diff --git a/source/blender/bmesh/tools/bmesh_wireframe.c b/source/blender/bmesh/tools/bmesh_wireframe.c
index af4a4424103..67010fc89c7 100644
--- a/source/blender/bmesh/tools/bmesh_wireframe.c
+++ b/source/blender/bmesh/tools/bmesh_wireframe.c
@@ -152,12 +152,6 @@ static bool bm_loop_is_radial_boundary(BMLoop *l_first)
return true;
}
-/**
- * \param defgrp_index: Vertex group index, -1 for no vertex groups.
- *
- * \note All edge tags must be cleared.
- * \note Behavior matches MOD_solidify.c
- */
void BM_mesh_wireframe(BMesh *bm,
const float offset,
const float offset_fac,
diff --git a/source/blender/bmesh/tools/bmesh_wireframe.h b/source/blender/bmesh/tools/bmesh_wireframe.h
index b2c2f5f5523..5b64a16435f 100644
--- a/source/blender/bmesh/tools/bmesh_wireframe.h
+++ b/source/blender/bmesh/tools/bmesh_wireframe.h
@@ -22,6 +22,12 @@
#pragma once
+/**
+ * \param defgrp_index: Vertex group index, -1 for no vertex groups.
+ *
+ * \note All edge tags must be cleared.
+ * \note Behavior matches MOD_solidify.c
+ */
void BM_mesh_wireframe(BMesh *bm,
const float offset,
const float offset_fac,