From c4e041da23b9c45273fcd4874308c536b6a315d1 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 3 Dec 2021 19:29:35 +1100 Subject: Cleanup: move public doc-strings into headers for 'bmesh' Some minor improvements to doc-strings too. Ref T92709 --- source/blender/bmesh/intern/bmesh_construct.c | 91 ---- source/blender/bmesh/intern/bmesh_construct.h | 92 +++- source/blender/bmesh/intern/bmesh_core.c | 287 ------------ source/blender/bmesh/intern/bmesh_core.h | 290 +++++++++++- source/blender/bmesh/intern/bmesh_delete.c | 8 - source/blender/bmesh/intern/bmesh_delete.h | 8 + source/blender/bmesh/intern/bmesh_edgeloop.c | 13 - source/blender/bmesh/intern/bmesh_edgeloop.h | 17 +- source/blender/bmesh/intern/bmesh_error.h | 18 +- source/blender/bmesh/intern/bmesh_interp.c | 46 -- source/blender/bmesh/intern/bmesh_interp.h | 46 ++ source/blender/bmesh/intern/bmesh_iterators.c | 45 -- source/blender/bmesh/intern/bmesh_iterators.h | 60 ++- source/blender/bmesh/intern/bmesh_log.c | 119 ----- source/blender/bmesh/intern/bmesh_log.h | 119 +++++ source/blender/bmesh/intern/bmesh_marking.c | 73 +-- source/blender/bmesh/intern/bmesh_marking.h | 86 +++- source/blender/bmesh/intern/bmesh_mesh.c | 81 ---- source/blender/bmesh/intern/bmesh_mesh.h | 88 +++- source/blender/bmesh/intern/bmesh_mesh_convert.c | 31 -- source/blender/bmesh/intern/bmesh_mesh_convert.h | 31 ++ source/blender/bmesh/intern/bmesh_mesh_duplicate.c | 3 - source/blender/bmesh/intern/bmesh_mesh_duplicate.h | 3 + source/blender/bmesh/intern/bmesh_mesh_normals.c | 41 -- source/blender/bmesh/intern/bmesh_mesh_normals.h | 41 ++ .../bmesh/intern/bmesh_mesh_partial_update.c | 28 -- .../bmesh/intern/bmesh_mesh_partial_update.h | 28 ++ .../blender/bmesh/intern/bmesh_mesh_tessellate.c | 3 - .../blender/bmesh/intern/bmesh_mesh_tessellate.h | 3 + source/blender/bmesh/intern/bmesh_mesh_validate.c | 6 - source/blender/bmesh/intern/bmesh_mesh_validate.h | 6 + source/blender/bmesh/intern/bmesh_mods.c | 187 -------- source/blender/bmesh/intern/bmesh_mods.h | 187 ++++++++ source/blender/bmesh/intern/bmesh_operator_api.h | 272 ++++++++++-- source/blender/bmesh/intern/bmesh_operators.c | 148 ------- source/blender/bmesh/intern/bmesh_operators.h | 42 ++ source/blender/bmesh/intern/bmesh_polygon.c | 186 -------- source/blender/bmesh/intern/bmesh_polygon.h | 180 ++++++++ .../blender/bmesh/intern/bmesh_polygon_edgenet.c | 16 - .../blender/bmesh/intern/bmesh_polygon_edgenet.h | 16 + source/blender/bmesh/intern/bmesh_private.h | 12 + source/blender/bmesh/intern/bmesh_query.c | 490 --------------------- source/blender/bmesh/intern/bmesh_query.h | 488 ++++++++++++++++++++ source/blender/bmesh/intern/bmesh_query_uv.c | 23 - source/blender/bmesh/intern/bmesh_query_uv.h | 23 + source/blender/bmesh/intern/bmesh_structure.c | 60 --- source/blender/bmesh/intern/bmesh_structure.h | 60 +++ source/blender/bmesh/intern/bmesh_walkers.c | 53 --- source/blender/bmesh/intern/bmesh_walkers.h | 52 +++ 49 files changed, 2197 insertions(+), 2109 deletions(-) (limited to 'source/blender/bmesh/intern') diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c index a10a911b06c..789165f2e40 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); @@ -470,10 +394,6 @@ static void bm_face_attrs_copy( /* 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, @@ -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: - *
- *     Before:               After:
- *      +--------+           +--------+
- *      |        |           |        |
- *      |        |           |   f1   |
- *     v1   f1   v2          v1======v2
- *      |        |           |   f2   |
- *      |        |           |        |
- *      +--------+           +--------+
- * 
- * - * \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: - * - *
- *                     E
- *     Before: OV-------------TV
- *                 E       RE
- *     After:  OV------NV-----TV
- * 
- * - * \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: - * - *
- *     Before:    e_old  e_kill
- *              +-------+-------+
- *              |       |       |
- *              v_old   v_kill  v_target
- *
- *     After:           e_old
- *              +---------------+
- *              |               |
- *              v_old           v_target
- * 
- * - * \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. - * - *
- * Before: -> After:
- * +-+-+-+    +-+-+-+
- * | | | |    | \ / |
- * +-+-+-+    +--+--+
- * | | | |    | / \ |
- * +-+-+-+    +-+-+-+
- * 
- */ 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: - *
- *           A                   B
- *      +--------+           +--------+
- *      |        |           |        |
- *      |   f1   |           |   f1   |
- *     v1========v2 = Ok!    v1==V2==v3 == Wrong!
- *      |   f2   |           |   f2   |
- *      |        |           |        |
- *      +--------+           +--------+
- * 
- * - * In the example A, faces \a f1 and \a f2 are joined by a single edge, - * and the euler can safely be used. - * In example B however, \a f1 and \a f2 are joined by multiple edges and will produce an error. - * The caller in this case should call #bmesh_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: + *
+ *     Before:               After:
+ *      +--------+           +--------+
+ *      |        |           |        |
+ *      |        |           |   f1   |
+ *     v1   f1   v2          v1======v2
+ *      |        |           |   f2   |
+ *      |        |           |        |
+ *      +--------+           +--------+
+ * 
+ * + * \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: + * + *
+ *                     E
+ *     Before: OV-------------TV
+ *                 E       RE
+ *     After:  OV------NV-----TV
+ * 
+ * + * \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: + * + *
+ *     Before:    e_old  e_kill
+ *              +-------+-------+
+ *              |       |       |
+ *              v_old   v_kill  v_target
+ *
+ *     After:           e_old
+ *              +---------------+
+ *              |               |
+ *              v_old           v_target
+ * 
+ * + * \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. + * + *
+ * Before: -> After:
+ * +-+-+-+    +-+-+-+
+ * | | | |    | \ / |
+ * +-+-+-+    +--+--+
+ * | | | |    | / \ |
+ * +-+-+-+    +-+-+-+
+ * 
+ */ 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: + *
+ *           A                   B
+ *      +--------+           +--------+
+ *      |        |           |        |
+ *      |   f1   |           |   f1   |
+ *     v1========v2 = Ok!    v1==V2==v3 == Wrong!
+ *      |   f2   |           |   f2   |
+ *      |        |           |        |
+ *      +--------+           +--------+
+ * 
+ * + * In the example A, faces \a f1 and \a f2 are joined by a single edge, + * and the euler can safely be used. + * In example B however, \a f1 and \a f2 are joined by multiple edges and will produce an error. + * The caller in this case should call #bmesh_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 b7dc51abae1..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; @@ -1720,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], @@ -1933,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) { @@ -2250,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..5b667c68315 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_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_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: - *
- *              +---------+             +---------+
- *              |  \   /  |             |         |
- *     Before:  |    v    |      After: |         |
- *              |  /   \  |             |         |
- *              +---------+             +---------+
- * 
- * - * This function can also collapse edges too - * in cases when it can't merge into faces. - * - * \par Example: - *
- *     Before:  +----v----+      After: +---------+
- * 
- * - * \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 - * - *
- * Before: v
- *         +-----------------------------------+
- *                           e
- *
- * After:  v                 v_new (returned)
- *         +-----------------+-----------------+
- *                 r_e                e
- * 
- * - * \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: + *
+ *              +---------+             +---------+
+ *              |  \   /  |             |         |
+ *     Before:  |    v    |      After: |         |
+ *              |  /   \  |             |         |
+ *              +---------+             +---------+
+ * 
+ * + * This function can also collapse edges too + * in cases when it can't merge into faces. + * + * \par Example: + *
+ *     Before:  +----v----+      After: +---------+
+ * 
+ * + * \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 + * + *
+ * Before: v
+ *         +-----------------------------------+
+ *                           e
+ *
+ * After:  v                 v_new (returned)
+ *         +-----------------+-----------------+
+ *                 r_e                e
+ * 
+ * + * \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..216726f0a83 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 opstack down one level and allocates a new flag layer if appropriate. + */ void BMO_push(BMesh *bm, BMOperator *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); -/* 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..11f578fc6ff 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 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, @@ -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..b346d37d546 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,6 +35,14 @@ 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, 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..7936ca18f5c 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. - *
- *     +----------+
- *     |          |
- *     |    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.
- * 
- * - * \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' - *
- *     +----------+ <-- 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.
- * 
- * - * \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. - *
- *     +----------+ <-- 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.
- * 
- */ 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. - * - *
- *     +----------+ <-- Return the face-loop of this vertex.
- *     |          |
- *     |        e | <-- This edge defines the direction.
- *     |          |
- *     +----------+ <-- This loop defines the face and vertex..
- *                l
- * 
- * - */ 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. - * - *
- * +-------------------+
- * |                   |
- * |                   |
- * |l_other <-- return |
- * +-------------------+ <-- A manifold edge between 2 faces
- * |l    e  <-- edge   |
- * |^ <-------- loop   |
- * |                   |
- * +-------------------+
- * 
- */ BMLoop *BM_edge_other_loop(BMEdge *e, BMLoop *l) { BMLoop *l_other; @@ -655,12 +518,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 +564,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 +589,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 +604,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 +614,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 +626,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 +643,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 +665,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 +700,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 +710,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 +724,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 +741,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 +865,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 +883,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 +894,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 +911,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 +969,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 +987,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 +1004,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 +1020,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 +1035,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 +1051,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 +1066,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 +1090,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 +1110,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 +1127,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 +1136,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 +1151,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 +1166,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 +1182,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 +1199,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 +1216,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 +1228,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 +1262,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 +1292,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 +1306,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 +1320,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 +1335,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 +1365,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 +1379,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 +1405,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)) { @@ -1799,7 +1432,6 @@ float BM_edge_calc_face_angle_signed(const BMEdge *e) * 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 +1445,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 +1468,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 +1486,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 +1515,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 +1535,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 +1556,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 +1629,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 +1646,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 +1660,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 +1708,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 +1740,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 +1848,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 +1861,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 +1899,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 +2032,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 +2081,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; @@ -2592,22 +2143,6 @@ double BM_mesh_calc_volume(BMesh *bm, bool is_signed) } /* 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], @@ -2756,24 +2291,6 @@ int BM_mesh_calc_face_groups(BMesh *bm, } /* 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], @@ -2892,13 +2409,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..a88215c0e07 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,151 @@ 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. + * + *
+ * +-------------------+
+ * |                   |
+ * |                   |
+ * |l_other <-- return |
+ * +-------------------+ <-- A manifold edge between 2 faces
+ * |l    e  <-- edge   |
+ * |^ <-------- loop   |
+ * |                   |
+ * +-------------------+
+ * 
+ */ 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. + *
+ *     +----------+
+ *     |          |
+ *     |    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.
+ * 
+ * + * \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' + *
+ *     +----------+ <-- 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.
+ * 
+ * + * \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. + * + *
+ *     +----------+ <-- Return the face-loop of this vertex.
+ *     |          |
+ *     |        e | <-- This edge defines the direction.
+ *     |          |
+ *     +----------+ <-- This loop defines the face and vertex..
+ *                l
+ * 
+ * + */ 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. + *
+ *     +----------+ <-- 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.
+ * 
+ */ BMLoop *BM_loop_other_vert_loop(BMLoop *l, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); 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 +207,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 +239,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(); +/** + * \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, 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 +412,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 @@ -173,52 +473,195 @@ float BM_edge_calc_face_angle_signed(const BMEdge *e) ATTR_WARN_UNUSED_RESULT AT 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 +677,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 +690,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 +721,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 +746,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) \ -- cgit v1.2.3