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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/BKE_mesh.h')
-rw-r--r--source/blender/blenkernel/BKE_mesh.h347
1 files changed, 333 insertions, 14 deletions
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index be9b84ccd62..c39583d234a 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -84,21 +84,51 @@ struct Mesh *BKE_mesh_from_bmesh_for_eval_nomain(struct BMesh *bm,
const struct CustomData_MeshMasks *cd_mask_extra,
const struct Mesh *me_settings);
+/**
+ * Find the index of the loop in 'poly' which references vertex,
+ * returns -1 if not found
+ */
int poly_find_loop_from_vert(const struct MPoly *poly, const struct MLoop *loopstart, uint vert);
+/**
+ * Fill \a r_adj with the loop indices in \a poly adjacent to the
+ * vertex. Returns the index of the loop matching vertex, or -1 if the
+ * vertex is not in \a poly
+ */
int poly_get_adj_loops_from_vert(const struct MPoly *poly,
const struct MLoop *mloop,
unsigned int vert,
unsigned int r_adj[2]);
+/**
+ * Return the index of the edge vert that is not equal to \a v. If
+ * neither edge vertex is equal to \a v, returns -1.
+ */
int BKE_mesh_edge_other_vert(const struct MEdge *e, int v);
+/**
+ * Sets each output array element to the edge index if it is a real edge, or -1.
+ */
void BKE_mesh_looptri_get_real_edges(const struct Mesh *mesh,
const struct MLoopTri *looptri,
int r_edges[3]);
+/**
+ * Free (or release) any data used by this mesh (does not free the mesh itself).
+ * Only use for undo, in most cases `BKE_id_free(nullptr, me)` should be used.
+ */
void BKE_mesh_free_data_for_undo(struct Mesh *me);
void BKE_mesh_clear_geometry(struct Mesh *me);
struct Mesh *BKE_mesh_add(struct Main *bmain, const char *name);
+/**
+ * A version of #BKE_mesh_copy_parameters that is intended for evaluated output
+ * (the modifier stack for example).
+ *
+ * \warning User counts are not handled for ID's.
+ */
void BKE_mesh_copy_parameters_for_eval(struct Mesh *me_dst, const struct Mesh *me_src);
+/**
+ * Copy user editable settings that we want to preserve
+ * when a new mesh is based on an existing mesh.
+ */
void BKE_mesh_copy_parameters(struct Mesh *me_dst, const struct Mesh *me_src);
void BKE_mesh_update_customdata_pointers(struct Mesh *me, const bool do_ensure_tess_cd);
void BKE_mesh_ensure_skin_customdata(struct Mesh *me);
@@ -121,12 +151,16 @@ struct Mesh *BKE_mesh_new_nomain_from_template_ex(const struct Mesh *me_src,
void BKE_mesh_eval_delete(struct Mesh *mesh_eval);
-/* Performs copy for use during evaluation,
- * optional referencing original arrays to reduce memory. */
+/**
+ * Performs copy for use during evaluation,
+ * optional referencing original arrays to reduce memory.
+ */
struct Mesh *BKE_mesh_copy_for_eval(const struct Mesh *source, bool reference);
-/* These functions construct a new Mesh,
- * contrary to BKE_mesh_to_curve_nurblist which modifies ob itself. */
+/**
+ * These functions construct a new Mesh,
+ * contrary to #BKE_mesh_to_curve_nurblist which modifies ob itself.
+ */
struct Mesh *BKE_mesh_new_nomain_from_curve(const struct Object *ob);
struct Mesh *BKE_mesh_new_nomain_from_curve_displist(const struct Object *ob,
const struct ListBase *dispbase);
@@ -136,6 +170,16 @@ bool BKE_mesh_clear_facemap_customdata(struct Mesh *me);
float (*BKE_mesh_orco_verts_get(struct Object *ob))[3];
void BKE_mesh_orco_verts_transform(struct Mesh *me, float (*orco)[3], int totvert, int invert);
+
+/**
+ * Add a #CD_ORCO layer to the Mesh if there is none already.
+ */
+void BKE_mesh_orco_ensure(struct Object *ob, struct Mesh *mesh);
+
+/**
+ * Rotates the vertices of a face in case v[2] or v[3] (vertex index) is = 0.
+ * this is necessary to make the if #MFace.v4 check for quads work.
+ */
int BKE_mesh_mface_index_validate(struct MFace *mface,
struct CustomData *mfdata,
int mfindex,
@@ -166,9 +210,17 @@ void BKE_mesh_material_index_clear(struct Mesh *me);
void BKE_mesh_material_remap(struct Mesh *me, const unsigned int *remap, unsigned int remap_len);
void BKE_mesh_smooth_flag_set(struct Mesh *me, const bool use_smooth);
-/* Needed after converting a mesh with subsurf optimal display to mesh. */
+/**
+ * Needed after converting a mesh with subsurf optimal display to mesh.
+ */
void BKE_mesh_edges_set_draw_render(struct Mesh *me);
+/**
+ * Used for unit testing; compares two meshes, checking only
+ * differences we care about. should be usable with leaf's
+ * testing framework I get RNA work done, will use hackish
+ * testing code for now.
+ */
const char *BKE_mesh_cmp(struct Mesh *me1, struct Mesh *me2, float thresh);
struct BoundBox *BKE_mesh_boundbox_get(struct Object *ob);
@@ -177,34 +229,49 @@ void BKE_mesh_texspace_calc(struct Mesh *me);
void BKE_mesh_texspace_ensure(struct Mesh *me);
void BKE_mesh_texspace_get(struct Mesh *me, float r_loc[3], float r_size[3]);
void BKE_mesh_texspace_get_reference(struct Mesh *me,
- short **r_texflag,
+ char **r_texflag,
float **r_loc,
float **r_size);
void BKE_mesh_texspace_copy_from_object(struct Mesh *me, struct Object *ob);
+/**
+ * Split faces based on the edge angle and loop normals.
+ * Matches behavior of face splitting in render engines.
+ *
+ * \note Will leave #CD_NORMAL loop data layer which is used by render engines to set shading up.
+ */
void BKE_mesh_split_faces(struct Mesh *mesh, bool free_loop_normals);
-/* Create new mesh from the given object at its current state.
+/**
+ * Create new mesh from the given object at its current state.
* The owner of this mesh is unknown, it is up to the caller to decide.
*
* If preserve_all_data_layers is truth then the modifier stack is re-evaluated to ensure it
* preserves all possible custom data layers.
*
- * NOTE: Dependency graph argument is required when preserve_all_data_layers is truth, and is
- * ignored otherwise. */
+ * \note Dependency graph argument is required when preserve_all_data_layers is truth, and is
+ * ignored otherwise.
+ */
struct Mesh *BKE_mesh_new_from_object(struct Depsgraph *depsgraph,
struct Object *object,
const bool preserve_all_data_layers,
const bool preserve_origindex);
-/* This is a version of BKE_mesh_new_from_object() which stores mesh in the given main database.
+/**
+ * This is a version of BKE_mesh_new_from_object() which stores mesh in the given main database.
* However, that function enforces object type to be a geometry one, and ensures a mesh is always
- * generated, be it empty. */
+ * generated, be it empty.
+ */
struct Mesh *BKE_mesh_new_from_object_to_bmain(struct Main *bmain,
struct Depsgraph *depsgraph,
struct Object *object,
bool preserve_all_data_layers);
+/**
+ * \param use_virtual_modifiers: When enabled calculate virtual-modifiers before applying `md_eval`
+ * support this since virtual-modifiers are not modifiers from a user perspective,
+ * allowing shape keys to be included with the modifier being applied, see: T91923.
+ */
struct Mesh *BKE_mesh_create_derived_for_modifier(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob_eval,
@@ -212,7 +279,9 @@ struct Mesh *BKE_mesh_create_derived_for_modifier(struct Depsgraph *depsgraph,
const bool use_virtual_modifiers,
const bool build_shapekey_layers);
-/* Copies a nomain-Mesh into an existing Mesh. */
+/**
+ * Copies a nomain-Mesh into an existing Mesh.
+ */
void BKE_mesh_nomain_to_mesh(struct Mesh *mesh_src,
struct Mesh *mesh_dst,
struct Object *ob,
@@ -222,6 +291,7 @@ void BKE_mesh_nomain_to_meshkey(struct Mesh *mesh_src, struct Mesh *mesh_dst, st
/* vertex level transformations & checks (no derived mesh) */
+/* basic vertex data functions */
bool BKE_mesh_minmax(const struct Mesh *me, float r_min[3], float r_max[3]);
void BKE_mesh_transform(struct Mesh *me, const float mat[4][4], bool do_keys);
void BKE_mesh_translate(struct Mesh *me, const float offset[3], const bool do_keys);
@@ -233,7 +303,13 @@ void BKE_mesh_do_versions_cd_flag_init(struct Mesh *mesh);
void BKE_mesh_mselect_clear(struct Mesh *me);
void BKE_mesh_mselect_validate(struct Mesh *me);
+/**
+ * \return the index within `me->mselect`, or -1
+ */
int BKE_mesh_mselect_find(struct Mesh *me, int index, int type);
+/**
+ * \return The index of the active element.
+ */
int BKE_mesh_mselect_active_get(struct Mesh *me, int type);
void BKE_mesh_mselect_active_set(struct Mesh *me, int index, int type);
@@ -250,6 +326,17 @@ void BKE_mesh_vert_normals_apply(struct Mesh *mesh, const short (*vert_normals)[
/* *** mesh_tessellate.c *** */
+/**
+ * Recreate #MFace Tessellation.
+ *
+ * \param do_face_nor_copy: Controls whether the normals from the poly
+ * are copied to the tessellated faces.
+ *
+ * \return number of tessellation faces.
+ *
+ * \note This doesn't use multi-threading like #BKE_mesh_recalc_looptri since
+ * it's not used in many places and #MFace should be phased out.
+ */
int BKE_mesh_tessface_calc_ex(struct CustomData *fdata,
struct CustomData *ldata,
struct CustomData *pdata,
@@ -260,12 +347,23 @@ int BKE_mesh_tessface_calc_ex(struct CustomData *fdata,
const bool do_face_nor_copy);
void BKE_mesh_tessface_calc(struct Mesh *mesh);
+/**
+ * Calculate tessellation into #MLoopTri which exist only for this purpose.
+ */
void BKE_mesh_recalc_looptri(const struct MLoop *mloop,
const struct MPoly *mpoly,
const struct MVert *mvert,
int totloop,
int totpoly,
struct MLoopTri *mlooptri);
+/**
+ * A version of #BKE_mesh_recalc_looptri which takes pre-calculated polygon normals
+ * (used to avoid having to calculate the face normal for NGON tessellation).
+ *
+ * \note Only use this function if normals have already been calculated, there is no need
+ * to calculate normals just to use this function as it will cause the normals for triangles
+ * to be calculated which aren't needed for tessellation.
+ */
void BKE_mesh_recalc_looptri_with_normals(const struct MLoop *mloop,
const struct MPoly *mpoly,
const struct MVert *mvert,
@@ -292,8 +390,15 @@ void BKE_mesh_calc_normals_poly_and_vertex(struct MVert *mvert,
int mpoly_len,
float (*r_poly_normals)[3],
float (*r_vert_normals)[3]);
+/**
+ * \note this does not update the #CD_NORMAL layer,
+ * but does update the normals in the #CD_MVERT layer.
+ */
void BKE_mesh_calc_normals(struct Mesh *me);
void BKE_mesh_ensure_normals(struct Mesh *me);
+/**
+ * Called after calculating all modifiers.
+ */
void BKE_mesh_ensure_normals_for_display(struct Mesh *mesh);
void BKE_mesh_calc_normals_looptri(struct MVert *mverts,
int numVerts,
@@ -311,6 +416,12 @@ void BKE_mesh_loop_manifold_fan_around_vert_next(const struct MLoop *mloops,
int *r_mlfan_vert_index,
int *r_mpfan_curr_index);
+/**
+ * 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 BKE_edges_sharp_from_angle_set(const struct MVert *mverts,
const int numVerts,
struct MEdge *medges,
@@ -379,17 +490,42 @@ void BKE_lnor_spacearr_init(MLoopNorSpaceArray *lnors_spacearr,
void BKE_lnor_spacearr_clear(MLoopNorSpaceArray *lnors_spacearr);
void BKE_lnor_spacearr_free(MLoopNorSpaceArray *lnors_spacearr);
+/**
+ * Utility for multi-threaded calculation that ensures
+ * `lnors_spacearr_tls` doesn't share memory with `lnors_spacearr`
+ * that would cause it not to be thread safe.
+ *
+ * \note This works as long as threads never operate on the same loops at once.
+ */
void BKE_lnor_spacearr_tls_init(MLoopNorSpaceArray *lnors_spacearr,
MLoopNorSpaceArray *lnors_spacearr_tls);
+/**
+ * Utility for multi-threaded calculation
+ * that merges `lnors_spacearr_tls` into `lnors_spacearr`.
+ */
void BKE_lnor_spacearr_tls_join(MLoopNorSpaceArray *lnors_spacearr,
MLoopNorSpaceArray *lnors_spacearr_tls);
MLoopNorSpace *BKE_lnor_space_create(MLoopNorSpaceArray *lnors_spacearr);
+/**
+ * Should only be called once.
+ * Beware, this modifies ref_vec and other_vec in place!
+ * In case no valid space can be generated, ref_alpha and ref_beta are set to zero
+ * (which means 'use auto lnors').
+ */
void BKE_lnor_space_define(MLoopNorSpace *lnor_space,
const float lnor[3],
float vec_ref[3],
float vec_other[3],
struct BLI_Stack *edge_vectors);
+/**
+ * Add a new given loop to given lnor_space.
+ * Depending on \a lnor_space->data_type, we expect \a bm_loop to be a pointer to BMLoop struct
+ * (in case of BMLOOP_PTR), or nullptr (in case of LOOP_INDEX), loop index is then stored in
+ * pointer. If \a is_single is set, the BMLoop or loop index is directly stored in \a
+ * lnor_space->loops pointer (since there is only one loop in this fan), else it is added to the
+ * linked list of loops in the fan.
+ */
void BKE_lnor_space_add_loop(MLoopNorSpaceArray *lnors_spacearr,
MLoopNorSpace *lnor_space,
const int ml_index,
@@ -403,6 +539,12 @@ void BKE_lnor_space_custom_normal_to_data(MLoopNorSpace *lnor_space,
short r_clnor_data[2]);
/* Medium-level custom normals functions. */
+
+/**
+ * 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 BKE_mesh_normals_loop_split(const struct MVert *mverts,
const int numVerts,
struct MEdge *medges,
@@ -442,20 +584,49 @@ void BKE_mesh_normals_loop_custom_from_vertices_set(const struct MVert *mverts,
const int numPolys,
short (*r_clnors_data)[2]);
+/**
+ * Computes average per-vertex normals from given custom loop normals.
+ *
+ * \param clnors: The computed custom loop normals.
+ * \param r_vert_clnors: The (already allocated) array where to store averaged per-vertex normals.
+ */
void BKE_mesh_normals_loop_to_vertex(const int numVerts,
const struct MLoop *mloops,
const int numLoops,
const float (*clnors)[3],
float (*r_vert_clnors)[3]);
-/* High-level custom normals functions. */
+/**
+ * High-level custom normals functions.
+ */
bool BKE_mesh_has_custom_loop_normals(struct Mesh *me);
void BKE_mesh_calc_normals_split(struct Mesh *mesh);
+/**
+ * Compute 'split' (aka loop, or per face corner's) normals.
+ *
+ * \param r_lnors_spacearr: Allows to get computed loop normal space array.
+ * That data, among other things, contains 'smooth fan' info, useful e.g.
+ * to split geometry along sharp edges.
+ */
void BKE_mesh_calc_normals_split_ex(struct Mesh *mesh,
struct MLoopNorSpaceArray *r_lnors_spacearr);
+/**
+ * Higher level functions hiding most of the code needed around call to
+ * #BKE_mesh_normals_loop_custom_set().
+ *
+ * \param r_custom_loopnors: is not const, since code will replace zero_v3 normals there
+ * with automatically computed vectors.
+ */
void BKE_mesh_set_custom_normals(struct Mesh *mesh, float (*r_custom_loopnors)[3]);
+/**
+ * Higher level functions hiding most of the code needed around call to
+ * #BKE_mesh_normals_loop_custom_from_vertices_set().
+ *
+ * \param r_custom_vertnors: is not const, since code will replace zero_v3 normals there
+ * with automatically computed vectors.
+ */
void BKE_mesh_set_custom_normals_from_vertices(struct Mesh *mesh, float (*r_custom_vertnors)[3]);
/* *** mesh_evaluate.cc *** */
@@ -472,6 +643,7 @@ void BKE_mesh_calc_poly_center(const struct MPoly *mpoly,
const struct MLoop *loopstart,
const struct MVert *mvarray,
float r_cent[3]);
+/* NOTE: passing poly-normal is only a speedup so we can skip calculating it. */
float BKE_mesh_calc_poly_area(const struct MPoly *mpoly,
const struct MLoop *loopstart,
const struct MVert *mvarray);
@@ -490,11 +662,25 @@ void BKE_mesh_poly_edgebitmap_insert(unsigned int *edge_bitmap,
const struct MLoop *mloop);
bool BKE_mesh_center_median(const struct Mesh *me, float r_cent[3]);
+/**
+ * Calculate the center from polygons,
+ * use when we want to ignore vertex locations that don't have connected faces.
+ */
bool BKE_mesh_center_median_from_polys(const struct Mesh *me, float r_cent[3]);
bool BKE_mesh_center_bounds(const struct Mesh *me, float r_cent[3]);
bool BKE_mesh_center_of_surface(const struct Mesh *me, float r_cent[3]);
+/**
+ * \note Mesh must be manifold with consistent face-winding,
+ * see #mesh_calc_poly_volume_centroid for details.
+ */
bool BKE_mesh_center_of_volume(const struct Mesh *me, float r_cent[3]);
+/**
+ * Calculate the volume and center.
+ *
+ * \param r_volume: Volume (unsigned).
+ * \param r_center: Center of mass.
+ */
void BKE_mesh_calc_volume(const struct MVert *mverts,
const int mverts_num,
const struct MLoopTri *mlooptri,
@@ -505,6 +691,19 @@ void BKE_mesh_calc_volume(const struct MVert *mverts,
/* tessface */
void BKE_mesh_convert_mfaces_to_mpolys(struct Mesh *mesh);
+/**
+ * The same as #BKE_mesh_convert_mfaces_to_mpolys
+ * but oriented to be used in #do_versions from `readfile.c`
+ * the difference is how active/render/clone/stencil indices are handled here.
+ *
+ * normally they're being set from `pdata` which totally makes sense for meshes which are already
+ * converted to #BMesh structures, but when loading older files indices shall be updated in other
+ * way around, so newly added `pdata` and `ldata` would have this indices set
+ * based on `fdata` layer.
+ *
+ * this is normally only needed when reading older files,
+ * in all other cases #BKE_mesh_convert_mfaces_to_mpolys shall be always used.
+ */
void BKE_mesh_do_versions_convert_mfaces_to_mpolys(struct Mesh *mesh);
void BKE_mesh_convert_mfaces_to_mpolys_ex(struct ID *id,
struct CustomData *fdata,
@@ -521,8 +720,20 @@ void BKE_mesh_convert_mfaces_to_mpolys_ex(struct ID *id,
struct MLoop **r_mloop,
struct MPoly **r_mpoly);
+/**
+ * Flip a single MLoop's #MDisps structure,
+ * low level function to be called from face-flipping code which re-arranged the mdisps themselves.
+ */
void BKE_mesh_mdisp_flip(struct MDisps *md, const bool use_loop_mdisp_flip);
+/**
+ * Flip (invert winding of) the given \a mpoly, i.e. reverse order of its loops
+ * (keeping the same vertex as 'start point').
+ *
+ * \param mpoly: the polygon to flip.
+ * \param mloop: the full loops array.
+ * \param ldata: the loops custom data.
+ */
void BKE_mesh_polygon_flip_ex(struct MPoly *mpoly,
struct MLoop *mloop,
struct CustomData *ldata,
@@ -530,6 +741,11 @@ void BKE_mesh_polygon_flip_ex(struct MPoly *mpoly,
struct MDisps *mdisp,
const bool use_loop_mdisp_flip);
void BKE_mesh_polygon_flip(struct MPoly *mpoly, struct MLoop *mloop, struct CustomData *ldata);
+/**
+ * Flip (invert winding of) all polygons (used to inverse their normals).
+ *
+ * \note Invalidates tessellation, caller must handle that.
+ */
void BKE_mesh_polygons_flip(struct MPoly *mpoly,
struct MLoop *mloop,
struct CustomData *ldata,
@@ -542,12 +758,48 @@ enum {
MESH_MERGE_VERTS_DUMP_IF_MAPPED,
MESH_MERGE_VERTS_DUMP_IF_EQUAL,
};
+/**
+ * Merge Verts
+ *
+ * This frees the given mesh and returns a new mesh.
+ *
+ * \param vtargetmap: The table that maps vertices to target vertices. a value of -1
+ * indicates a vertex is a target, and is to be kept.
+ * This array is aligned with 'mesh->totvert'
+ * \warning \a vtargetmap must **not** contain any chained mapping (v1 -> v2 -> v3 etc.),
+ * this is not supported and will likely generate corrupted geometry.
+ *
+ * \param tot_vtargetmap: The number of non '-1' values in vtargetmap. (not the size)
+ *
+ * \param merge_mode: enum with two modes.
+ * - #MESH_MERGE_VERTS_DUMP_IF_MAPPED
+ * When called by the Mirror Modifier,
+ * In this mode it skips any faces that have all vertices merged (to avoid creating pairs
+ * of faces sharing the same set of vertices)
+ * - #MESH_MERGE_VERTS_DUMP_IF_EQUAL
+ * When called by the Array Modifier,
+ * In this mode, faces where all vertices are merged are double-checked,
+ * to see whether all target vertices actually make up a poly already.
+ * Indeed it could be that all of a poly's vertices are merged,
+ * but merged to vertices that do not make up a single poly,
+ * in which case the original poly should not be dumped.
+ * Actually this later behavior could apply to the Mirror Modifier as well,
+ * but the additional checks are costly and not necessary in the case of mirror,
+ * because each vertex is only merged to its own mirror.
+ *
+ * \note #BKE_mesh_tessface_calc_ex has to run on the returned DM
+ * if you want to access tess-faces.
+ */
struct Mesh *BKE_mesh_merge_verts(struct Mesh *mesh,
const int *vtargetmap,
const int tot_vtargetmap,
const int merge_mode);
-/* flush flags */
+/* Flush flags. */
+
+/**
+ * Update the hide flag for edges and faces from the corresponding flag in verts.
+ */
void BKE_mesh_flush_hidden_from_verts_ex(const struct MVert *mvert,
const struct MLoop *mloop,
struct MEdge *medge,
@@ -562,6 +814,9 @@ void BKE_mesh_flush_hidden_from_polys_ex(struct MVert *mvert,
const struct MPoly *mpoly,
const int totpoly);
void BKE_mesh_flush_hidden_from_polys(struct Mesh *me);
+/**
+ * simple poly -> vert/edge selection.
+ */
void BKE_mesh_flush_select_from_polys_ex(struct MVert *mvert,
const int totvert,
const struct MLoop *mloop,
@@ -580,6 +835,17 @@ void BKE_mesh_flush_select_from_verts_ex(const struct MVert *mvert,
void BKE_mesh_flush_select_from_verts(struct Mesh *me);
/* spatial evaluation */
+/**
+ * This function takes the difference between 2 vertex-coord-arrays
+ * (\a vert_cos_src, \a vert_cos_dst),
+ * and applies the difference to \a vert_cos_new relative to \a vert_cos_org.
+ *
+ * \param vert_cos_src: reference deform source.
+ * \param vert_cos_dst: reference deform destination.
+ *
+ * \param vert_cos_org: reference for the output location.
+ * \param vert_cos_new: resulting coords.
+ */
void BKE_mesh_calc_relative_deform(const struct MPoly *mpoly,
const int totpoly,
const struct MLoop *mloop,
@@ -593,10 +859,41 @@ void BKE_mesh_calc_relative_deform(const struct MPoly *mpoly,
/* *** mesh_validate.c *** */
+/**
+ * Validates and corrects a Mesh.
+ *
+ * \returns true if a change is made.
+ */
bool BKE_mesh_validate(struct Mesh *me, const bool do_verbose, const bool cddata_check_mask);
+/**
+ * Checks if a Mesh is valid without any modification. This is always verbose.
+ *
+ * \see #DM_is_valid to call on derived meshes
+ *
+ * \returns is_valid.
+ */
bool BKE_mesh_is_valid(struct Mesh *me);
+/**
+ * Check all material indices of polygons are valid, invalid ones are set to 0.
+ * \returns is_valid.
+ */
bool BKE_mesh_validate_material_indices(struct Mesh *me);
+/**
+ * Validate the mesh, \a do_fixes requires \a mesh to be non-null.
+ *
+ * \return false if no changes needed to be made.
+ *
+ * Vertex Normals
+ * ==============
+ *
+ * While zeroed normals are checked, these checks aren't comprehensive.
+ * Technically, to detect errors here a normal recalculation and comparison is necessary.
+ * However this function is mainly to prevent severe errors in geometry
+ * (invalid data that will crash Blender, or cause some features to behave incorrectly),
+ * not to detect subtle differences in the resulting normals which could be caused
+ * by importers that load normals (for example).
+ */
bool BKE_mesh_validate_arrays(struct Mesh *me,
struct MVert *mverts,
unsigned int totvert,
@@ -613,6 +910,9 @@ bool BKE_mesh_validate_arrays(struct Mesh *me,
const bool do_fixes,
bool *r_change);
+/**
+ * \returns is_valid.
+ */
bool BKE_mesh_validate_all_customdata(struct CustomData *vdata,
const uint totvert,
struct CustomData *edata,
@@ -627,12 +927,31 @@ bool BKE_mesh_validate_all_customdata(struct CustomData *vdata,
bool *r_change);
void BKE_mesh_strip_loose_faces(struct Mesh *me);
+/**
+ * Works on both loops and polys!
+ *
+ * \note It won't try to guess which loops of an invalid poly to remove!
+ * this is the work of the caller, to mark those loops.
+ * See e.g. #BKE_mesh_validate_arrays().
+ */
void BKE_mesh_strip_loose_polysloops(struct Mesh *me);
void BKE_mesh_strip_loose_edges(struct Mesh *me);
+/**
+ * If the mesh is from a very old blender version,
+ * convert mface->edcode to edge drawflags
+ */
void BKE_mesh_calc_edges_legacy(struct Mesh *me, const bool use_old);
void BKE_mesh_calc_edges_loose(struct Mesh *mesh);
+/**
+ * Calculate edges from polygons.
+ */
void BKE_mesh_calc_edges(struct Mesh *mesh, bool keep_existing_edges, const bool select_new_edges);
+/**
+ * Calculate/create edges from tessface data
+ *
+ * \param mesh: The mesh to add edges into
+ */
void BKE_mesh_calc_edges_tessface(struct Mesh *mesh);
/* In DerivedMesh.cc */