main sync #3

Merged
Patrick Busch merged 318 commits from blender/blender:main into main 2023-03-17 15:52:21 +01:00
295 changed files with 1385 additions and 1607 deletions
Showing only changes of commit 1dc57a89e9 - Show all commits

View File

@ -316,24 +316,10 @@ void BKE_mesh_vert_coords_apply(struct Mesh *mesh, const float (*vert_coords)[3]
void BKE_mesh_recalc_looptri(const struct MLoop *mloop, void BKE_mesh_recalc_looptri(const struct MLoop *mloop,
const struct MPoly *polys, const struct MPoly *polys,
const float (*vert_positions)[3], const float (*vert_positions)[3],
int totvert,
int totloop, int totloop,
int totpoly, int totpoly,
struct MLoopTri *mlooptri); 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 *polys,
const float (*vert_positions)[3],
int totloop,
int totpoly,
struct MLoopTri *mlooptri,
const float (*poly_normals)[3]);
/* *** mesh_normals.cc *** */ /* *** mesh_normals.cc *** */
@ -409,63 +395,17 @@ bool BKE_mesh_vert_normals_are_dirty(const struct Mesh *mesh);
*/ */
bool BKE_mesh_poly_normals_are_dirty(const struct Mesh *mesh); bool BKE_mesh_poly_normals_are_dirty(const struct Mesh *mesh);
void BKE_mesh_calc_poly_normal(const struct MPoly *polys, void BKE_mesh_calc_poly_normal(const struct MLoop *poly_loops,
const struct MLoop *loopstart, int poly_size,
const float (*vert_positions)[3], const float (*vert_positions)[3],
int verts_num,
float r_no[3]); float r_no[3]);
/**
* Calculate face normals directly into a result array.
*
* \note Usually #BKE_mesh_poly_normals_ensure is the preferred way to access face normals,
* since they may already be calculated and cached on the mesh.
*/
void BKE_mesh_calc_normals_poly(const float (*vert_positions)[3],
int mvert_len,
const struct MLoop *mloop,
int mloop_len,
const struct MPoly *polys,
int polys_len,
float (*r_poly_normals)[3]);
/**
* Calculate face and vertex normals directly into result arrays.
*
* \note Usually #BKE_mesh_vert_normals_ensure is the preferred way to access vertex normals,
* since they may already be calculated and cached on the mesh.
*/
void BKE_mesh_calc_normals_poly_and_vertex(const float (*vert_positions)[3],
int mvert_len,
const struct MLoop *mloop,
int mloop_len,
const struct MPoly *polys,
int polys_len,
float (*r_poly_normals)[3],
float (*r_vert_normals)[3]);
/** /**
* Called after calculating all modifiers. * Called after calculating all modifiers.
*/ */
void BKE_mesh_ensure_normals_for_display(struct Mesh *mesh); void BKE_mesh_ensure_normals_for_display(struct Mesh *mesh);
/**
* 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!
*
* \param sharp_faces: Optional array used to mark specific faces for sharp shading.
*/
void BKE_edges_sharp_from_angle_set(int numEdges,
const struct MLoop *mloops,
int numLoops,
const struct MPoly *polys,
const float (*poly_normals)[3],
const bool *sharp_faces,
int numPolys,
float split_angle,
bool *sharp_edges);
/** /**
* References a contiguous loop-fan with normal offset vars. * References a contiguous loop-fan with normal offset vars.
*/ */
@ -569,66 +509,6 @@ void BKE_lnor_space_custom_normal_to_data(const MLoopNorSpace *lnor_space,
const float custom_lnor[3], const float custom_lnor[3],
short r_clnor_data[2]); 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).
*
* \param loop_to_poly_map: Optional pre-created map from loops to their polygon.
* \param sharp_faces: Optional array used to mark specific faces for sharp shading.
* \param sharp_edges: Optional array of sharp edge tags, used to split the evaluated normals on
* each side of the edge.
*/
void BKE_mesh_normals_loop_split(const float (*vert_positions)[3],
const float (*vert_normals)[3],
int numVerts,
const struct MEdge *edges,
int numEdges,
const struct MLoop *mloops,
float (*r_loop_normals)[3],
int numLoops,
const struct MPoly *polys,
const float (*poly_normals)[3],
int numPolys,
bool use_split_normals,
float split_angle,
const bool *sharp_edges,
const bool *sharp_faces,
const int *loop_to_poly_map,
MLoopNorSpaceArray *r_lnors_spacearr,
short (*clnors_data)[2]);
void BKE_mesh_normals_loop_custom_set(const float (*vert_positions)[3],
const float (*vert_normals)[3],
int numVerts,
const struct MEdge *edges,
int numEdges,
const struct MLoop *mloops,
float (*r_custom_loop_normals)[3],
int numLoops,
const struct MPoly *polys,
const float (*poly_normals)[3],
const bool *sharp_faces,
int numPolys,
bool *sharp_edges,
short (*r_clnors_data)[2]);
void BKE_mesh_normals_loop_custom_from_verts_set(const float (*vert_positions)[3],
const float (*vert_normals)[3],
float (*r_custom_vert_normals)[3],
int numVerts,
const struct MEdge *edges,
int numEdges,
const struct MLoop *mloops,
int numLoops,
const struct MPoly *polys,
const float (*poly_normals)[3],
const bool *sharp_faces,
int numPolys,
bool *sharp_edges,
short (*r_clnors_data)[2]);
/** /**
* Computes average per-vertex normals from given custom loop normals. * Computes average per-vertex normals from given custom loop normals.
* *
@ -660,7 +540,7 @@ void BKE_mesh_calc_normals_split_ex(struct Mesh *mesh,
/** /**
* Higher level functions hiding most of the code needed around call to * Higher level functions hiding most of the code needed around call to
* #BKE_mesh_normals_loop_custom_set(). * #normals_loop_custom_set().
* *
* \param r_custom_loop_normals: is not const, since code will replace zero_v3 normals there * \param r_custom_loop_normals: is not const, since code will replace zero_v3 normals there
* with automatically computed vectors. * with automatically computed vectors.
@ -668,7 +548,7 @@ void BKE_mesh_calc_normals_split_ex(struct Mesh *mesh,
void BKE_mesh_set_custom_normals(struct Mesh *mesh, float (*r_custom_loop_normals)[3]); void BKE_mesh_set_custom_normals(struct Mesh *mesh, float (*r_custom_loop_normals)[3]);
/** /**
* Higher level functions hiding most of the code needed around call to * Higher level functions hiding most of the code needed around call to
* #BKE_mesh_normals_loop_custom_from_verts_set(). * #normals_loop_custom_set_from_verts().
* *
* \param r_custom_vert_normals: is not const, since code will replace zero_v3 normals there * \param r_custom_vert_normals: is not const, since code will replace zero_v3 normals there
* with automatically computed vectors. * with automatically computed vectors.
@ -677,25 +557,22 @@ void BKE_mesh_set_custom_normals_from_verts(struct Mesh *mesh, float (*r_custom_
/* *** mesh_evaluate.cc *** */ /* *** mesh_evaluate.cc *** */
void BKE_mesh_calc_poly_center(const struct MPoly *poly, void BKE_mesh_calc_poly_center(const struct MLoop *poly_loops,
const struct MLoop *loopstart, int poly_size,
const float (*vert_positions)[3], const float (*vert_positions)[3],
int verts_num,
float r_cent[3]); 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 MLoop *poly_loops,
float BKE_mesh_calc_poly_area(const struct MPoly *poly, int poly_size,
const struct MLoop *loopstart, const float (*vert_positions)[3],
const float (*vert_positions)[3]); int verts_num);
float BKE_mesh_calc_area(const struct Mesh *me); float BKE_mesh_calc_area(const struct Mesh *me);
void BKE_mesh_calc_poly_angles(const struct MPoly *poly,
const struct MLoop *loopstart,
const float (*vert_positions)[3],
float angles[]);
void BKE_mesh_poly_edgehash_insert(struct EdgeHash *ehash, void BKE_mesh_poly_edgehash_insert(struct EdgeHash *ehash,
const struct MPoly *mp, const struct MPoly *poly,
const struct MLoop *mloop); const struct MLoop *mloop);
void BKE_mesh_poly_edgebitmap_insert(unsigned int *edge_bitmap, void BKE_mesh_poly_edgebitmap_insert(unsigned int *edge_bitmap,
const struct MPoly *mp, const struct MPoly *poly,
const struct MLoop *mloop); const struct MLoop *mloop);
bool BKE_mesh_center_median(const struct Mesh *me, float r_cent[3]); bool BKE_mesh_center_median(const struct Mesh *me, float r_cent[3]);
@ -988,73 +865,4 @@ BLI_INLINE MDeformVert *BKE_mesh_deform_verts_for_write(Mesh *mesh)
} }
#endif #endif
#ifdef __cplusplus
# include "BLI_math_vector_types.hh"
# include "BLI_span.hh"
inline blender::Span<blender::float3> Mesh::vert_positions() const
{
return {reinterpret_cast<const blender::float3 *>(BKE_mesh_vert_positions(this)), this->totvert};
}
inline blender::MutableSpan<blender::float3> Mesh::vert_positions_for_write()
{
return {reinterpret_cast<blender::float3 *>(BKE_mesh_vert_positions_for_write(this)),
this->totvert};
}
inline blender::Span<MEdge> Mesh::edges() const
{
return {BKE_mesh_edges(this), this->totedge};
}
inline blender::MutableSpan<MEdge> Mesh::edges_for_write()
{
return {BKE_mesh_edges_for_write(this), this->totedge};
}
inline blender::Span<MPoly> Mesh::polys() const
{
return {BKE_mesh_polys(this), this->totpoly};
}
inline blender::MutableSpan<MPoly> Mesh::polys_for_write()
{
return {BKE_mesh_polys_for_write(this), this->totpoly};
}
inline blender::Span<MLoop> Mesh::loops() const
{
return {BKE_mesh_loops(this), this->totloop};
}
inline blender::MutableSpan<MLoop> Mesh::loops_for_write()
{
return {BKE_mesh_loops_for_write(this), this->totloop};
}
inline blender::Span<MDeformVert> Mesh::deform_verts() const
{
const MDeformVert *dverts = BKE_mesh_deform_verts(this);
if (!dverts) {
return {};
}
return {dverts, this->totvert};
}
inline blender::MutableSpan<MDeformVert> Mesh::deform_verts_for_write()
{
return {BKE_mesh_deform_verts_for_write(this), this->totvert};
}
inline blender::Span<blender::float3> Mesh::poly_normals() const
{
return {reinterpret_cast<const blender::float3 *>(BKE_mesh_poly_normals_ensure(this)),
this->totpoly};
}
inline blender::Span<blender::float3> Mesh::vert_normals() const
{
return {reinterpret_cast<const blender::float3 *>(BKE_mesh_vert_normals_ensure(this)),
this->totvert};
}
#endif
/** \} */ /** \} */

View File

@ -0,0 +1,211 @@
/* SPDX-License-Identifier: GPL-2.0-or-later. */
#pragma once
/** \file
* \ingroup bke
*/
#include "BKE_mesh.h"
namespace blender::bke::mesh {
/* -------------------------------------------------------------------- */
/** \name Polygon Data Evaluation
* \{ */
/** Calculate the up direction for the polygon, depending on its winding direction. */
float3 poly_normal_calc(Span<float3> vert_positions, Span<MLoop> poly_loops);
/**
* Calculate tessellation into #MLoopTri which exist only for this purpose.
*/
void looptris_calc(Span<float3> vert_positions,
Span<MPoly> polys,
Span<MLoop> loops,
MutableSpan<MLoopTri> looptris);
/**
* A version of #looptris_calc 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.
*/
void looptris_calc_with_normals(Span<float3> vert_positions,
Span<MPoly> polys,
Span<MLoop> loops,
Span<float3> poly_normals,
MutableSpan<MLoopTri> looptris);
/** Calculate the average position of the vertices in the polygon. */
float3 poly_center_calc(Span<float3> vert_positions, Span<MLoop> poly_loops);
/** Calculate the surface area of the polygon described by the indexed vertices. */
float poly_area_calc(Span<float3> vert_positions, Span<MLoop> poly_loops);
/** Calculate the angles at each of the polygons's corners. */
void poly_angles_calc(Span<float3> vert_positions,
Span<MLoop> poly_loops,
MutableSpan<float> angles);
/** \} */
/* -------------------------------------------------------------------- */
/** \name Medium-Level Normals Calculation
* \{ */
/**
* Calculate face normals directly into a result array.
*
* \note Usually #Mesh::poly_normals() is the preferred way to access face normals,
* since they may already be calculated and cached on the mesh.
*/
void normals_calc_polys(Span<float3> vert_positions,
Span<MPoly> polys,
Span<MLoop> loops,
MutableSpan<float3> poly_normals);
/**
* Calculate face and vertex normals directly into result arrays.
*
* \note Usually #Mesh::vert_normals() is the preferred way to access vertex normals,
* since they may already be calculated and cached on the mesh.
*/
void normals_calc_poly_vert(Span<float3> vert_positions,
Span<MPoly> polys,
Span<MLoop> loops,
MutableSpan<float3> poly_normals,
MutableSpan<float3> vert_normals);
/**
* 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).
*
* \param loop_to_poly_map: Optional pre-created map from loops to their polygon.
* \param sharp_edges: Optional array of sharp edge tags, used to split the evaluated normals on
* each side of the edge.
*/
void normals_calc_loop(Span<float3> vert_positions,
Span<MEdge> edges,
Span<MPoly> polys,
Span<MLoop> loops,
Span<int> loop_to_poly_map,
Span<float3> vert_normals,
Span<float3> poly_normals,
const bool *sharp_edges,
const bool *sharp_faces,
bool use_split_normals,
float split_angle,
short (*clnors_data)[2],
MLoopNorSpaceArray *r_lnors_spacearr,
MutableSpan<float3> r_loop_normals);
void normals_loop_custom_set(Span<float3> vert_positions,
Span<MEdge> edges,
Span<MPoly> polys,
Span<MLoop> loops,
Span<float3> vert_normals,
Span<float3> poly_normals,
const bool *sharp_faces,
MutableSpan<bool> sharp_edges,
MutableSpan<float3> r_custom_loop_normals,
short (*r_clnors_data)[2]);
void normals_loop_custom_set_from_verts(Span<float3> vert_positions,
Span<MEdge> edges,
Span<MPoly> polys,
Span<MLoop> loops,
Span<float3> vert_normals,
Span<float3> poly_normals,
const bool *sharp_faces,
MutableSpan<bool> sharp_edges,
MutableSpan<float3> r_custom_vert_normals,
short (*r_clnors_data)[2]);
/**
* 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!
*
* \param sharp_faces: Optional array used to mark specific faces for sharp shading.
*/
void edges_sharp_from_angle_set(Span<MPoly> polys,
Span<MLoop> loops,
Span<float3> poly_normals,
const bool *sharp_faces,
const float split_angle,
MutableSpan<bool> sharp_edges);
} // namespace blender::bke::mesh
/** \} */
/* -------------------------------------------------------------------- */
/** \name Inline Mesh Data Access
* \{ */
inline blender::Span<blender::float3> Mesh::vert_positions() const
{
return {reinterpret_cast<const blender::float3 *>(BKE_mesh_vert_positions(this)), this->totvert};
}
inline blender::MutableSpan<blender::float3> Mesh::vert_positions_for_write()
{
return {reinterpret_cast<blender::float3 *>(BKE_mesh_vert_positions_for_write(this)),
this->totvert};
}
inline blender::Span<MEdge> Mesh::edges() const
{
return {BKE_mesh_edges(this), this->totedge};
}
inline blender::MutableSpan<MEdge> Mesh::edges_for_write()
{
return {BKE_mesh_edges_for_write(this), this->totedge};
}
inline blender::Span<MPoly> Mesh::polys() const
{
return {BKE_mesh_polys(this), this->totpoly};
}
inline blender::MutableSpan<MPoly> Mesh::polys_for_write()
{
return {BKE_mesh_polys_for_write(this), this->totpoly};
}
inline blender::Span<MLoop> Mesh::loops() const
{
return {BKE_mesh_loops(this), this->totloop};
}
inline blender::MutableSpan<MLoop> Mesh::loops_for_write()
{
return {BKE_mesh_loops_for_write(this), this->totloop};
}
inline blender::Span<MDeformVert> Mesh::deform_verts() const
{
const MDeformVert *dverts = BKE_mesh_deform_verts(this);
if (!dverts) {
return {};
}
return {dverts, this->totvert};
}
inline blender::MutableSpan<MDeformVert> Mesh::deform_verts_for_write()
{
return {BKE_mesh_deform_verts_for_write(this), this->totvert};
}
inline blender::Span<blender::float3> Mesh::poly_normals() const
{
return {reinterpret_cast<const blender::float3 *>(BKE_mesh_poly_normals_ensure(this)),
this->totpoly};
}
inline blender::Span<blender::float3> Mesh::vert_normals() const
{
return {reinterpret_cast<const blender::float3 *>(BKE_mesh_vert_normals_ensure(this)),
this->totvert};
}
/** \} */

View File

@ -221,6 +221,7 @@ void BKE_mesh_remap_calc_polys_from_mesh(int mode,
float ray_radius, float ray_radius,
const struct Mesh *mesh_dst, const struct Mesh *mesh_dst,
const float (*vert_positions_dst)[3], const float (*vert_positions_dst)[3],
int numverts_dst,
const struct MLoop *loops_dst, const struct MLoop *loops_dst,
const struct MPoly *polys_dst, const struct MPoly *polys_dst,
int numpolys_dst, int numpolys_dst,

View File

@ -420,6 +420,7 @@ set(SRC
BKE_mball.h BKE_mball.h
BKE_mball_tessellate.h BKE_mball_tessellate.h
BKE_mesh.h BKE_mesh.h
BKE_mesh.hh
BKE_mesh_boolean_convert.hh BKE_mesh_boolean_convert.hh
BKE_mesh_fair.h BKE_mesh_fair.h
BKE_mesh_iterators.h BKE_mesh_iterators.h

View File

@ -42,7 +42,7 @@
#include "BKE_layer.h" #include "BKE_layer.h"
#include "BKE_lib_id.h" #include "BKE_lib_id.h"
#include "BKE_material.h" #include "BKE_material.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_iterators.h" #include "BKE_mesh_iterators.h"
#include "BKE_mesh_mapping.h" #include "BKE_mesh_mapping.h"
#include "BKE_mesh_runtime.h" #include "BKE_mesh_runtime.h"
@ -1914,14 +1914,15 @@ static void mesh_init_origspace(Mesh *mesh)
} }
else { else {
const MLoop *l = &loops[poly.loopstart]; const MLoop *l = &loops[poly.loopstart];
float p_nor[3], co[3]; float co[3];
float mat[3][3]; float mat[3][3];
float min[2] = {FLT_MAX, FLT_MAX}, max[2] = {-FLT_MAX, -FLT_MAX}; float min[2] = {FLT_MAX, FLT_MAX}, max[2] = {-FLT_MAX, -FLT_MAX};
float translate[2], scale[2]; float translate[2], scale[2];
BKE_mesh_calc_poly_normal( const float3 p_nor = blender::bke::mesh::poly_normal_calc(
&poly, l, reinterpret_cast<const float(*)[3]>(positions.data()), p_nor); positions, loops.slice(poly.loopstart, poly.totloop));
axis_dominant_v3_to_m3(mat, p_nor); axis_dominant_v3_to_m3(mat, p_nor);
vcos_2d.resize(poly.totloop); vcos_2d.resize(poly.totloop);

View File

@ -31,7 +31,7 @@
#include "BKE_curves.hh" #include "BKE_curves.hh"
#include "BKE_customdata.h" #include "BKE_customdata.h"
#include "BKE_editmesh.h" #include "BKE_editmesh.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_pointcloud.h" #include "BKE_pointcloud.h"
#include "BKE_report.h" #include "BKE_report.h"

View File

@ -6,7 +6,7 @@
#include "BKE_customdata.h" #include "BKE_customdata.h"
#include "BKE_deform.h" #include "BKE_deform.h"
#include "BKE_geometry_set.hh" #include "BKE_geometry_set.hh"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_pointcloud.h" #include "BKE_pointcloud.h"
#include "BKE_type_conversions.hh" #include "BKE_type_conversions.hh"

View File

@ -24,7 +24,7 @@
#include "BKE_attribute.hh" #include "BKE_attribute.hh"
#include "BKE_bvhutils.h" #include "BKE_bvhutils.h"
#include "BKE_editmesh.h" #include "BKE_editmesh.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_runtime.h" #include "BKE_mesh_runtime.h"
#include "MEM_guardedalloc.h" #include "MEM_guardedalloc.h"

View File

@ -20,7 +20,7 @@
#include "BKE_cdderivedmesh.h" #include "BKE_cdderivedmesh.h"
#include "BKE_curve.h" #include "BKE_curve.h"
#include "BKE_editmesh.h" #include "BKE_editmesh.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_mapping.h" #include "BKE_mesh_mapping.h"
#include "BKE_object.h" #include "BKE_object.h"
#include "BKE_paint.h" #include "BKE_paint.h"
@ -121,12 +121,11 @@ static void cdDM_recalc_looptri(DerivedMesh *dm)
DM_ensure_looptri_data(dm); DM_ensure_looptri_data(dm);
BLI_assert(totpoly == 0 || cddm->dm.looptris.array_wip != NULL); BLI_assert(totpoly == 0 || cddm->dm.looptris.array_wip != NULL);
BKE_mesh_recalc_looptri(cddm->mloop, blender::bke::mesh::looptris_calc(
cddm->mpoly, {reinterpret_cast<const blender::float3 *>(cddm->vert_positions), dm->numVertData},
cddm->vert_positions, {cddm->mpoly, totpoly},
totloop, {cddm->mloop, totloop},
totpoly, {dm->looptris.array_wip, dm->looptris.num});
cddm->dm.looptris.array_wip);
BLI_assert(cddm->dm.looptris.array == NULL); BLI_assert(cddm->dm.looptris.array == NULL);
atomic_cas_ptr( atomic_cas_ptr(

View File

@ -27,7 +27,7 @@
#include "BKE_effect.h" #include "BKE_effect.h"
#include "BKE_global.h" #include "BKE_global.h"
#include "BKE_lib_id.h" #include "BKE_lib_id.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_runtime.h" #include "BKE_mesh_runtime.h"
#include "BKE_modifier.h" #include "BKE_modifier.h"
#include "BKE_pointcache.h" #include "BKE_pointcache.h"

View File

@ -24,7 +24,7 @@
#include "BKE_editmesh.h" #include "BKE_editmesh.h"
#include "BKE_geometry_set.hh" #include "BKE_geometry_set.hh"
#include "BKE_lib_id.h" #include "BKE_lib_id.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_wrapper.h" #include "BKE_mesh_wrapper.h"
#include "BKE_modifier.h" #include "BKE_modifier.h"
#include "BKE_multires.h" #include "BKE_multires.h"

View File

@ -12,7 +12,7 @@
#include "BKE_curves.hh" #include "BKE_curves.hh"
#include "BKE_geometry_set.hh" #include "BKE_geometry_set.hh"
#include "BKE_material.h" #include "BKE_material.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_curve_to_mesh.hh" #include "BKE_curve_to_mesh.hh"

View File

@ -24,7 +24,7 @@
#include "BKE_customdata.h" #include "BKE_customdata.h"
#include "BKE_data_transfer.h" #include "BKE_data_transfer.h"
#include "BKE_deform.h" #include "BKE_deform.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_mapping.h" #include "BKE_mesh_mapping.h"
#include "BKE_mesh_remap.h" #include "BKE_mesh_remap.h"
#include "BKE_mesh_runtime.h" #include "BKE_mesh_runtime.h"
@ -351,12 +351,6 @@ static void data_transfer_dtdata_type_preprocess(Mesh *me_src,
{ {
if (dtdata_type == DT_TYPE_LNOR) { if (dtdata_type == DT_TYPE_LNOR) {
/* Compute custom normals into regular loop normals, which will be used for the transfer. */ /* Compute custom normals into regular loop normals, which will be used for the transfer. */
const float(*positions_dst)[3] = BKE_mesh_vert_positions(me_dst);
const int num_verts_dst = me_dst->totvert;
const blender::Span<MEdge> edges_dst = me_dst->edges();
const blender::Span<MPoly> polys_dst = me_dst->polys();
const blender::Span<MLoop> loops_dst = me_dst->loops();
CustomData *ldata_dst = &me_dst->ldata; CustomData *ldata_dst = &me_dst->ldata;
const bool use_split_nors_dst = (me_dst->flag & ME_AUTOSMOOTH) != 0; const bool use_split_nors_dst = (me_dst->flag & ME_AUTOSMOOTH) != 0;
@ -366,17 +360,16 @@ static void data_transfer_dtdata_type_preprocess(Mesh *me_src,
BLI_assert(CustomData_get_layer(&me_src->ldata, CD_NORMAL) != nullptr); BLI_assert(CustomData_get_layer(&me_src->ldata, CD_NORMAL) != nullptr);
(void)me_src; (void)me_src;
float(*loop_nors_dst)[3];
short(*custom_nors_dst)[2] = static_cast<short(*)[2]>( short(*custom_nors_dst)[2] = static_cast<short(*)[2]>(
CustomData_get_layer_for_write(ldata_dst, CD_CUSTOMLOOPNORMAL, me_dst->totloop)); CustomData_get_layer_for_write(ldata_dst, CD_CUSTOMLOOPNORMAL, me_dst->totloop));
/* Cache loop nors into a temp CDLayer. */ /* Cache loop nors into a temp CDLayer. */
loop_nors_dst = static_cast<float(*)[3]>( blender::float3 *loop_nors_dst = static_cast<blender::float3 *>(
CustomData_get_layer_for_write(ldata_dst, CD_NORMAL, me_dst->totloop)); CustomData_get_layer_for_write(ldata_dst, CD_NORMAL, me_dst->totloop));
const bool do_loop_nors_dst = (loop_nors_dst == nullptr); const bool do_loop_nors_dst = (loop_nors_dst == nullptr);
if (do_loop_nors_dst) { if (do_loop_nors_dst) {
loop_nors_dst = static_cast<float(*)[3]>( loop_nors_dst = static_cast<blender::float3 *>(
CustomData_add_layer(ldata_dst, CD_NORMAL, CD_SET_DEFAULT, nullptr, loops_dst.size())); CustomData_add_layer(ldata_dst, CD_NORMAL, CD_SET_DEFAULT, nullptr, me_dst->totloop));
CustomData_set_layer_flag(ldata_dst, CD_NORMAL, CD_FLAG_TEMPORARY); CustomData_set_layer_flag(ldata_dst, CD_NORMAL, CD_FLAG_TEMPORARY);
} }
if (dirty_nors_dst || do_loop_nors_dst) { if (dirty_nors_dst || do_loop_nors_dst) {
@ -384,24 +377,20 @@ static void data_transfer_dtdata_type_preprocess(Mesh *me_src,
CustomData_get_layer_named(&me_dst->edata, CD_PROP_BOOL, "sharp_edge")); CustomData_get_layer_named(&me_dst->edata, CD_PROP_BOOL, "sharp_edge"));
const bool *sharp_faces = static_cast<const bool *>( const bool *sharp_faces = static_cast<const bool *>(
CustomData_get_layer_named(&me_dst->pdata, CD_PROP_BOOL, "sharp_face")); CustomData_get_layer_named(&me_dst->pdata, CD_PROP_BOOL, "sharp_face"));
BKE_mesh_normals_loop_split(positions_dst, blender::bke::mesh::normals_calc_loop(me_dst->vert_positions(),
BKE_mesh_vert_normals_ensure(me_dst), me_dst->edges(),
num_verts_dst, me_dst->polys(),
edges_dst.data(), me_dst->loops(),
edges_dst.size(), {},
loops_dst.data(), me_dst->vert_normals(),
loop_nors_dst, me_dst->poly_normals(),
loops_dst.size(), sharp_edges,
polys_dst.data(), sharp_faces,
BKE_mesh_poly_normals_ensure(me_dst), use_split_nors_dst,
polys_dst.size(), split_angle_dst,
use_split_nors_dst, custom_nors_dst,
split_angle_dst, nullptr,
sharp_edges, {loop_nors_dst, me_dst->totloop});
sharp_faces,
nullptr,
nullptr,
custom_nors_dst);
} }
} }
} }
@ -418,47 +407,35 @@ static void data_transfer_dtdata_type_postprocess(Object * /*ob_src*/,
if (!changed) { if (!changed) {
return; return;
} }
/* Bake edited destination loop normals into custom normals again. */ /* Bake edited destination loop normals into custom normals again. */
const float(*positions_dst)[3] = BKE_mesh_vert_positions(me_dst);
const int num_verts_dst = me_dst->totvert;
const blender::Span<MEdge> edges_dst = me_dst->edges();
blender::MutableSpan<MPoly> polys_dst = me_dst->polys_for_write();
blender::MutableSpan<MLoop> loops_dst = me_dst->loops_for_write();
CustomData *ldata_dst = &me_dst->ldata; CustomData *ldata_dst = &me_dst->ldata;
const float(*poly_nors_dst)[3] = BKE_mesh_poly_normals_ensure(me_dst); blender::float3 *loop_nors_dst = static_cast<blender::float3 *>(
float(*loop_nors_dst)[3] = static_cast<float(*)[3]>(
CustomData_get_layer_for_write(ldata_dst, CD_NORMAL, me_dst->totloop)); CustomData_get_layer_for_write(ldata_dst, CD_NORMAL, me_dst->totloop));
short(*custom_nors_dst)[2] = static_cast<short(*)[2]>( short(*custom_nors_dst)[2] = static_cast<short(*)[2]>(
CustomData_get_layer_for_write(ldata_dst, CD_CUSTOMLOOPNORMAL, me_dst->totloop)); CustomData_get_layer_for_write(ldata_dst, CD_CUSTOMLOOPNORMAL, me_dst->totloop));
if (!custom_nors_dst) { if (!custom_nors_dst) {
custom_nors_dst = static_cast<short(*)[2]>(CustomData_add_layer( custom_nors_dst = static_cast<short(*)[2]>(CustomData_add_layer(
ldata_dst, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, nullptr, loops_dst.size())); ldata_dst, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, nullptr, me_dst->totloop));
} }
bke::MutableAttributeAccessor attributes = me_dst->attributes_for_write(); bke::MutableAttributeAccessor attributes = me_dst->attributes_for_write();
bke::SpanAttributeWriter<bool> sharp_edges = attributes.lookup_or_add_for_write_span<bool>( bke::SpanAttributeWriter<bool> sharp_edges = attributes.lookup_or_add_for_write_span<bool>(
"sharp_edge", ATTR_DOMAIN_EDGE); "sharp_edge", ATTR_DOMAIN_EDGE);
const bool *sharp_faces = static_cast<const bool *>(
CustomData_get_layer_named(&me_dst->pdata, CD_PROP_BOOL, "sharp_face"));
/* Note loop_nors_dst contains our custom normals as transferred from source... */ /* Note loop_nors_dst contains our custom normals as transferred from source... */
BKE_mesh_normals_loop_custom_set(positions_dst, blender::bke::mesh::normals_loop_custom_set(me_dst->vert_positions(),
BKE_mesh_vert_normals_ensure(me_dst), me_dst->edges(),
num_verts_dst, me_dst->polys(),
edges_dst.data(), me_dst->loops(),
edges_dst.size(), me_dst->vert_normals(),
loops_dst.data(), me_dst->poly_normals(),
loop_nors_dst, sharp_faces,
loops_dst.size(), sharp_edges.span,
polys_dst.data(), {loop_nors_dst, me_dst->totloop},
poly_nors_dst, custom_nors_dst);
static_cast<const bool *>(CustomData_get_layer_named(
&me_dst->pdata, CD_PROP_BOOL, "sharp_face")),
polys_dst.size(),
sharp_edges.span.data(),
custom_nors_dst);
sharp_edges.finish(); sharp_edges.finish();
} }
} }
@ -1715,6 +1692,7 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph,
ray_radius, ray_radius,
me_dst, me_dst,
positions_dst, positions_dst,
num_verts_dst,
loops_dst.data(), loops_dst.data(),
polys_dst.data(), polys_dst.data(),
polys_dst.size(), polys_dst.size(),

View File

@ -31,7 +31,7 @@
#include "BKE_customdata.h" #include "BKE_customdata.h"
#include "BKE_data_transfer.h" #include "BKE_data_transfer.h"
#include "BKE_deform.h" /* own include */ #include "BKE_deform.h" /* own include */
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_mapping.h" #include "BKE_mesh_mapping.h"
#include "BKE_object.h" #include "BKE_object.h"
#include "BKE_object_deform.h" #include "BKE_object_deform.h"

View File

@ -36,7 +36,7 @@
#include "BKE_key.h" #include "BKE_key.h"
#include "BKE_lib_id.h" #include "BKE_lib_id.h"
#include "BKE_mball.h" #include "BKE_mball.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_modifier.h" #include "BKE_modifier.h"
#include "BKE_object.h" #include "BKE_object.h"
#include "BKE_vfont.h" #include "BKE_vfont.h"

View File

@ -48,7 +48,7 @@
#include "BKE_lib_id.h" #include "BKE_lib_id.h"
#include "BKE_main.h" #include "BKE_main.h"
#include "BKE_material.h" #include "BKE_material.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_mapping.h" #include "BKE_mesh_mapping.h"
#include "BKE_mesh_runtime.h" #include "BKE_mesh_runtime.h"
#include "BKE_modifier.h" #include "BKE_modifier.h"

View File

@ -19,7 +19,7 @@
#include "BKE_editmesh.h" #include "BKE_editmesh.h"
#include "BKE_editmesh_cache.h" #include "BKE_editmesh_cache.h"
#include "BKE_lib_id.h" #include "BKE_lib_id.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_iterators.h" #include "BKE_mesh_iterators.h"
#include "BKE_mesh_wrapper.h" #include "BKE_mesh_wrapper.h"
#include "BKE_object.h" #include "BKE_object.h"

View File

@ -14,7 +14,7 @@
#include "BKE_customdata.h" #include "BKE_customdata.h"
#include "BKE_editmesh.h" #include "BKE_editmesh.h"
#include "BKE_editmesh_tangent.h" #include "BKE_editmesh_tangent.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_tangent.h" /* for utility functions */ #include "BKE_mesh_tangent.h" /* for utility functions */
#include "MEM_guardedalloc.h" #include "MEM_guardedalloc.h"

View File

@ -56,7 +56,7 @@
# include "BKE_colortools.h" # include "BKE_colortools.h"
# include "BKE_customdata.h" # include "BKE_customdata.h"
# include "BKE_deform.h" # include "BKE_deform.h"
# include "BKE_mesh.h" # include "BKE_mesh.hh"
# include "BKE_mesh_runtime.h" # include "BKE_mesh_runtime.h"
# include "BKE_object.h" # include "BKE_object.h"
# include "BKE_particle.h" # include "BKE_particle.h"

View File

@ -12,7 +12,7 @@
#include "BKE_geometry_fields.hh" #include "BKE_geometry_fields.hh"
#include "BKE_geometry_set.hh" #include "BKE_geometry_set.hh"
#include "BKE_lib_id.h" #include "BKE_lib_id.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_mapping.h" #include "BKE_mesh_mapping.h"
#include "FN_multi_function_builder.hh" #include "FN_multi_function_builder.hh"

View File

@ -7,7 +7,7 @@
#include "BKE_geometry_fields.hh" #include "BKE_geometry_fields.hh"
#include "BKE_geometry_set.hh" #include "BKE_geometry_set.hh"
#include "BKE_instances.hh" #include "BKE_instances.hh"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_pointcloud.h" #include "BKE_pointcloud.h"
#include "BKE_type_conversions.hh" #include "BKE_type_conversions.hh"

View File

@ -11,7 +11,7 @@
#include "BKE_geometry_set.hh" #include "BKE_geometry_set.hh"
#include "BKE_instances.hh" #include "BKE_instances.hh"
#include "BKE_lib_id.h" #include "BKE_lib_id.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_wrapper.h" #include "BKE_mesh_wrapper.h"
#include "BKE_modifier.h" #include "BKE_modifier.h"
#include "BKE_pointcloud.h" #include "BKE_pointcloud.h"

View File

@ -4,7 +4,7 @@
#include "BKE_geometry_set_instances.hh" #include "BKE_geometry_set_instances.hh"
#include "BKE_instances.hh" #include "BKE_instances.hh"
#include "BKE_material.h" #include "BKE_material.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_wrapper.h" #include "BKE_mesh_wrapper.h"
#include "BKE_modifier.h" #include "BKE_modifier.h"
#include "BKE_pointcloud.h" #include "BKE_pointcloud.h"

View File

@ -43,7 +43,7 @@
#include "BKE_gpencil_geom.h" #include "BKE_gpencil_geom.h"
#include "BKE_main.h" #include "BKE_main.h"
#include "BKE_material.h" #include "BKE_material.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_object.h" #include "BKE_object.h"
#include "DEG_depsgraph_query.h" #include "DEG_depsgraph_query.h"

View File

@ -42,7 +42,7 @@
#include "BKE_lib_id.h" #include "BKE_lib_id.h"
#include "BKE_lib_query.h" #include "BKE_lib_query.h"
#include "BKE_main.h" #include "BKE_main.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_scene.h" #include "BKE_scene.h"
#include "RNA_access.h" #include "RNA_access.h"
@ -2258,23 +2258,19 @@ void BKE_keyblock_mesh_calc_normals(const KeyBlock *kb,
} }
if (poly_normals_needed) { if (poly_normals_needed) {
BKE_mesh_calc_normals_poly(positions, blender::bke::mesh::normals_calc_polys(
mesh->totvert, {reinterpret_cast<const blender::float3 *>(positions), mesh->totvert},
loops.data(), polys,
loops.size(), loops,
polys.data(), {reinterpret_cast<blender::float3 *>(poly_normals), polys.size()});
polys.size(),
poly_normals);
} }
if (vert_normals_needed) { if (vert_normals_needed) {
BKE_mesh_calc_normals_poly_and_vertex(positions, blender::bke::mesh::normals_calc_poly_vert(
mesh->totvert, {reinterpret_cast<const blender::float3 *>(positions), mesh->totvert},
loops.data(), polys,
loops.size(), loops,
polys.data(), {reinterpret_cast<blender::float3 *>(poly_normals), polys.size()},
polys.size(), {reinterpret_cast<blender::float3 *>(vert_normals), mesh->totvert});
poly_normals,
vert_normals);
} }
if (loop_normals_needed) { if (loop_normals_needed) {
short(*clnors)[2] = static_cast<short(*)[2]>(CustomData_get_layer_for_write( short(*clnors)[2] = static_cast<short(*)[2]>(CustomData_get_layer_for_write(
@ -2283,24 +2279,21 @@ void BKE_keyblock_mesh_calc_normals(const KeyBlock *kb,
CustomData_get_layer_named(&mesh->edata, CD_PROP_BOOL, "sharp_edge")); CustomData_get_layer_named(&mesh->edata, CD_PROP_BOOL, "sharp_edge"));
const bool *sharp_faces = static_cast<const bool *>( const bool *sharp_faces = static_cast<const bool *>(
CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, "sharp_face")); CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, "sharp_face"));
BKE_mesh_normals_loop_split(positions, blender::bke::mesh::normals_calc_loop(
vert_normals, {reinterpret_cast<const blender::float3 *>(positions), mesh->totvert},
mesh->totvert, edges,
edges.data(), polys,
mesh->totedge, loops,
loops.data(), {},
r_loop_normals, {reinterpret_cast<blender::float3 *>(vert_normals), mesh->totvert},
loops.size(), {reinterpret_cast<blender::float3 *>(poly_normals), polys.size()},
polys.data(), sharp_edges,
poly_normals, sharp_faces,
polys.size(), (mesh->flag & ME_AUTOSMOOTH) != 0,
(mesh->flag & ME_AUTOSMOOTH) != 0, mesh->smoothresh,
mesh->smoothresh, clnors,
sharp_edges, nullptr,
sharp_faces, {reinterpret_cast<blender::float3 *>(r_loop_normals), loops.size()});
nullptr,
nullptr,
clnors);
} }
if (free_vert_normals) { if (free_vert_normals) {

View File

@ -20,7 +20,7 @@
#include "BKE_lib_id.h" #include "BKE_lib_id.h"
#include "BKE_lib_remap.h" #include "BKE_lib_remap.h"
#include "BKE_main.h" #include "BKE_main.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_node.h" #include "BKE_node.h"
#include "BKE_object.h" #include "BKE_object.h"
#include "BKE_scene.h" #include "BKE_scene.h"

View File

@ -56,7 +56,7 @@
#include "BKE_lib_query.h" #include "BKE_lib_query.h"
#include "BKE_main.h" #include "BKE_main.h"
#include "BKE_material.h" #include "BKE_material.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_node.h" #include "BKE_node.h"
#include "BKE_node_runtime.hh" #include "BKE_node_runtime.hh"
#include "BKE_object.h" #include "BKE_object.h"

View File

@ -48,7 +48,7 @@
#include "BKE_material.h" #include "BKE_material.h"
#include "BKE_mball.h" #include "BKE_mball.h"
#include "BKE_mball_tessellate.h" #include "BKE_mball_tessellate.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_object.h" #include "BKE_object.h"
#include "BKE_scene.h" #include "BKE_scene.h"

View File

@ -30,7 +30,7 @@
#include "BKE_global.h" #include "BKE_global.h"
#include "BKE_lib_id.h" #include "BKE_lib_id.h"
#include "BKE_mball_tessellate.h" /* own include */ #include "BKE_mball_tessellate.h" /* own include */
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_object.h" #include "BKE_object.h"
#include "BKE_scene.h" #include "BKE_scene.h"

View File

@ -50,7 +50,7 @@
#include "BKE_lib_query.h" #include "BKE_lib_query.h"
#include "BKE_main.h" #include "BKE_main.h"
#include "BKE_material.h" #include "BKE_material.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_legacy_convert.h" #include "BKE_mesh_legacy_convert.h"
#include "BKE_mesh_runtime.h" #include "BKE_mesh_runtime.h"
#include "BKE_mesh_wrapper.h" #include "BKE_mesh_wrapper.h"
@ -1854,29 +1854,22 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh,
CustomData_get_layer_named(&mesh->edata, CD_PROP_BOOL, "sharp_edge")); CustomData_get_layer_named(&mesh->edata, CD_PROP_BOOL, "sharp_edge"));
const bool *sharp_faces = static_cast<const bool *>( const bool *sharp_faces = static_cast<const bool *>(
CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, "sharp_face")); CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, "sharp_face"));
const Span<float3> positions = mesh->vert_positions();
const Span<MEdge> edges = mesh->edges();
const Span<MPoly> polys = mesh->polys();
const Span<MLoop> loops = mesh->loops();
BKE_mesh_normals_loop_split(reinterpret_cast<const float(*)[3]>(positions.data()), blender::bke::mesh::normals_calc_loop(
BKE_mesh_vert_normals_ensure(mesh), mesh->vert_positions(),
positions.size(), mesh->edges(),
edges.data(), mesh->polys(),
edges.size(), mesh->loops(),
loops.data(), {},
r_corner_normals, mesh->vert_normals(),
loops.size(), mesh->poly_normals(),
polys.data(), sharp_edges,
BKE_mesh_poly_normals_ensure(mesh), sharp_faces,
polys.size(), use_split_normals,
use_split_normals, split_angle,
split_angle, clnors,
sharp_edges, nullptr,
sharp_faces, {reinterpret_cast<float3 *>(r_corner_normals), mesh->totloop});
nullptr,
r_lnors_spacearr,
clnors);
} }
void BKE_mesh_calc_normals_split(Mesh *mesh) void BKE_mesh_calc_normals_split(Mesh *mesh)

View File

@ -12,7 +12,7 @@
#include "BKE_attribute.hh" #include "BKE_attribute.hh"
#include "BKE_customdata.h" #include "BKE_customdata.h"
#include "BKE_material.h" #include "BKE_material.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_boolean_convert.hh" #include "BKE_mesh_boolean_convert.hh"
#include "BLI_alloca.h" #include "BLI_alloca.h"
@ -547,11 +547,7 @@ static void get_poly2d_cos(const Mesh *me,
const Span<MLoop> poly_loops = loops.slice(poly->loopstart, poly->totloop); const Span<MLoop> poly_loops = loops.slice(poly->loopstart, poly->totloop);
/* Project coordinates to 2d in cos_2d, using normal as projection axis. */ /* Project coordinates to 2d in cos_2d, using normal as projection axis. */
float axis_dominant[3]; const float3 axis_dominant = bke::mesh::poly_normal_calc(positions, poly_loops);
BKE_mesh_calc_poly_normal(poly,
&loops[poly->loopstart],
reinterpret_cast<const float(*)[3]>(positions.data()),
axis_dominant);
axis_dominant_v3_to_m3(r_axis_mat, axis_dominant); axis_dominant_v3_to_m3(r_axis_mat, axis_dominant);
for (const int i : poly_loops.index_range()) { for (const int i : poly_loops.index_range()) {
float3 co = positions[poly_loops[i].v]; float3 co = positions[poly_loops[i].v];

View File

@ -15,7 +15,7 @@
#include "BKE_attribute.hh" #include "BKE_attribute.hh"
#include "BKE_customdata.h" #include "BKE_customdata.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
namespace blender::bke::calc_edges { namespace blender::bke::calc_edges {

View File

@ -40,7 +40,7 @@
#include "BKE_main.h" #include "BKE_main.h"
#include "BKE_material.h" #include "BKE_material.h"
#include "BKE_mball.h" #include "BKE_mball.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_runtime.h" #include "BKE_mesh_runtime.h"
#include "BKE_mesh_wrapper.h" #include "BKE_mesh_wrapper.h"
#include "BKE_modifier.h" #include "BKE_modifier.h"

View File

@ -23,7 +23,7 @@
# include "BKE_customdata.h" # include "BKE_customdata.h"
# include "BKE_mesh.h" # include "BKE_mesh.hh"
# include "BLI_dynstr.h" # include "BLI_dynstr.h"

View File

@ -24,10 +24,9 @@
#include "BLI_utildefines.h" #include "BLI_utildefines.h"
#include "BLI_virtual_array.hh" #include "BLI_virtual_array.hh"
#include "BKE_customdata.h"
#include "BKE_attribute.hh" #include "BKE_attribute.hh"
#include "BKE_mesh.h" #include "BKE_customdata.h"
#include "BKE_mesh.hh"
#include "BKE_multires.h" #include "BKE_multires.h"
using blender::float3; using blender::float3;
@ -39,65 +38,81 @@ using blender::VArray;
/** \name Polygon Calculations /** \name Polygon Calculations
* \{ */ * \{ */
static void mesh_calc_ngon_center(const MPoly *poly, namespace blender::bke::mesh {
const MLoop *loopstart,
const float (*positions)[3], static float3 poly_center_calc_ngon(const Span<float3> vert_positions,
float cent[3]) const Span<MLoop> poly_loops)
{ {
const float w = 1.0f / float(poly->totloop); const float w = 1.0f / float(poly_loops.size());
zero_v3(cent); float3 center(0);
for (const int i : poly_loops.index_range()) {
for (int i = 0; i < poly->totloop; i++) { center += vert_positions[poly_loops[i].v] * w;
madd_v3_v3fl(cent, positions[(loopstart++)->v], w);
} }
return center;
} }
void BKE_mesh_calc_poly_center(const MPoly *poly, float3 poly_center_calc(const Span<float3> vert_positions, const Span<MLoop> poly_loops)
const MLoop *loopstart, {
if (poly_loops.size() == 3) {
float3 center;
mid_v3_v3v3v3(center,
vert_positions[poly_loops[0].v],
vert_positions[poly_loops[1].v],
vert_positions[poly_loops[2].v]);
return center;
}
if (poly_loops.size() == 4) {
float3 center;
mid_v3_v3v3v3v3(center,
vert_positions[poly_loops[0].v],
vert_positions[poly_loops[1].v],
vert_positions[poly_loops[2].v],
vert_positions[poly_loops[3].v]);
return center;
}
return poly_center_calc_ngon(vert_positions, poly_loops);
}
} // namespace blender::bke::mesh
void BKE_mesh_calc_poly_center(const MLoop *poly_loops,
const int poly_size,
const float (*vert_positions)[3], const float (*vert_positions)[3],
const int verts_num,
float r_cent[3]) float r_cent[3])
{ {
if (poly->totloop == 3) { copy_v3_v3(r_cent,
mid_v3_v3v3v3(r_cent, blender::bke::mesh::poly_center_calc(
vert_positions[loopstart[0].v], {reinterpret_cast<const blender::float3 *>(vert_positions), verts_num},
vert_positions[loopstart[1].v], {poly_loops, poly_size}));
vert_positions[loopstart[2].v]);
}
else if (poly->totloop == 4) {
mid_v3_v3v3v3v3(r_cent,
vert_positions[loopstart[0].v],
vert_positions[loopstart[1].v],
vert_positions[loopstart[2].v],
vert_positions[loopstart[3].v]);
}
else {
mesh_calc_ngon_center(poly, loopstart, vert_positions, r_cent);
}
} }
float BKE_mesh_calc_poly_area(const MPoly *poly, namespace blender::bke::mesh {
const MLoop *loopstart,
const float (*vert_positions)[3]) float poly_area_calc(const Span<float3> vert_positions, const Span<MLoop> poly_loops)
{ {
if (poly->totloop == 3) { if (poly_loops.size() == 3) {
return area_tri_v3(vert_positions[loopstart[0].v], return area_tri_v3(vert_positions[poly_loops[0].v],
vert_positions[loopstart[1].v], vert_positions[poly_loops[1].v],
vert_positions[loopstart[2].v]); vert_positions[poly_loops[2].v]);
} }
Array<float3, 32> poly_coords(poly_loops.size());
const MLoop *l_iter = loopstart; for (const int i : poly_loops.index_range()) {
float(*vertexcos)[3] = (float(*)[3])BLI_array_alloca(vertexcos, size_t(poly->totloop)); poly_coords[i] = vert_positions[poly_loops[i].v];
/* pack vertex cos into an array for area_poly_v3 */
for (int i = 0; i < poly->totloop; i++, l_iter++) {
copy_v3_v3(vertexcos[i], vert_positions[l_iter->v]);
} }
return area_poly_v3((const float(*)[3])poly_coords.data(), poly_loops.size());
}
/* finally calculate the area */ } // namespace blender::bke::mesh
float area = area_poly_v3((const float(*)[3])vertexcos, uint(poly->totloop));
return area; float BKE_mesh_calc_poly_area(const MLoop *poly_loops,
const int poly_size,
const float (*vert_positions)[3],
const int verts_num)
{
return blender::bke::mesh::poly_area_calc(
{reinterpret_cast<const float3 *>(vert_positions), verts_num}, {poly_loops, poly_size});
} }
float BKE_mesh_calc_area(const Mesh *me) float BKE_mesh_calc_area(const Mesh *me)
@ -108,14 +123,14 @@ float BKE_mesh_calc_area(const Mesh *me)
float total_area = 0.0f; float total_area = 0.0f;
for (const MPoly &poly : polys) { for (const MPoly &poly : polys) {
total_area += BKE_mesh_calc_poly_area( total_area += blender::bke::mesh::poly_area_calc(positions,
&poly, &loops[poly.loopstart], reinterpret_cast<const float(*)[3]>(positions.data())); loops.slice(poly.loopstart, poly.totloop));
} }
return total_area; return total_area;
} }
static float UNUSED_FUNCTION(mesh_calc_poly_volume_centroid)(const MPoly *poly, static float UNUSED_FUNCTION(mesh_calc_poly_volume_centroid)(const MLoop *poly_loops,
const MLoop *loopstart, const int poly_size,
const float (*positions)[3], const float (*positions)[3],
float r_cent[3]) float r_cent[3])
{ {
@ -124,11 +139,11 @@ static float UNUSED_FUNCTION(mesh_calc_poly_volume_centroid)(const MPoly *poly,
zero_v3(r_cent); zero_v3(r_cent);
v_pivot = positions[loopstart[0].v]; v_pivot = positions[poly_loops[0].v];
v_step1 = positions[loopstart[1].v]; v_step1 = positions[poly_loops[1].v];
for (int i = 2; i < poly->totloop; i++) { for (int i = 2; i < poly_size; i++) {
const float *v_step2 = positions[loopstart[i].v]; const float *v_step2 = positions[poly_loops[i].v];
/* Calculate the 6x volume of the tetrahedron formed by the 3 vertices /* Calculate the 6x volume of the tetrahedron formed by the 3 vertices
* of the triangle and the origin as the fourth vertex */ * of the triangle and the origin as the fourth vertex */
@ -151,26 +166,27 @@ static float UNUSED_FUNCTION(mesh_calc_poly_volume_centroid)(const MPoly *poly,
return total_volume; return total_volume;
} }
namespace blender::bke::mesh {
/** /**
* A version of mesh_calc_poly_volume_centroid that takes an initial reference center, * A version of mesh_calc_poly_volume_centroid that takes an initial reference center,
* use this to increase numeric stability as the quality of the result becomes * use this to increase numeric stability as the quality of the result becomes
* very low quality as the value moves away from 0.0, see: #65986. * very low quality as the value moves away from 0.0, see: #65986.
*/ */
static float mesh_calc_poly_volume_centroid_with_reference_center(const MPoly *poly, static float mesh_calc_poly_volume_centroid_with_reference_center(const Span<float3> positions,
const MLoop *loopstart, const Span<MLoop> poly_loops,
const Span<float3> positions, const float3 &reference_center,
const float reference_center[3],
float r_cent[3]) float r_cent[3])
{ {
/* See: mesh_calc_poly_volume_centroid for comments. */ /* See: mesh_calc_poly_volume_centroid for comments. */
float v_pivot[3], v_step1[3]; float v_pivot[3], v_step1[3];
float total_volume = 0.0f; float total_volume = 0.0f;
zero_v3(r_cent); zero_v3(r_cent);
sub_v3_v3v3(v_pivot, positions[loopstart[0].v], reference_center); sub_v3_v3v3(v_pivot, positions[poly_loops[0].v], reference_center);
sub_v3_v3v3(v_step1, positions[loopstart[1].v], reference_center); sub_v3_v3v3(v_step1, positions[poly_loops[1].v], reference_center);
for (int i = 2; i < poly->totloop; i++) { for (int i = 2; i < poly_loops.size(); i++) {
float v_step2[3]; float v_step2[3];
sub_v3_v3v3(v_step2, positions[loopstart[i].v], reference_center); sub_v3_v3v3(v_step2, positions[poly_loops[i].v], reference_center);
const float tetra_volume = volume_tri_tetrahedron_signed_v3_6x(v_pivot, v_step1, v_step2); const float tetra_volume = volume_tri_tetrahedron_signed_v3_6x(v_pivot, v_step1, v_step2);
total_volume += tetra_volume; total_volume += tetra_volume;
for (uint j = 0; j < 3; j++) { for (uint j = 0; j < 3; j++) {
@ -187,21 +203,22 @@ static float mesh_calc_poly_volume_centroid_with_reference_center(const MPoly *p
* - This has the advantage over #mesh_calc_poly_volume_centroid * - This has the advantage over #mesh_calc_poly_volume_centroid
* that it doesn't depend on solid geometry, instead it weights the surface by volume. * that it doesn't depend on solid geometry, instead it weights the surface by volume.
*/ */
static float mesh_calc_poly_area_centroid(const MPoly *poly, static float poly_area_centroid_calc(const Span<float3> positions,
const MLoop *loopstart, const Span<MLoop> poly_loops,
const float (*positions)[3], float r_cent[3])
float r_cent[3])
{ {
float total_area = 0.0f; float total_area = 0.0f;
float v1[3], v2[3], v3[3], normal[3], tri_cent[3]; float v1[3], v2[3], v3[3], tri_cent[3];
const float3 normal = blender::bke::mesh::poly_normal_calc(positions, poly_loops);
copy_v3_v3(v1, positions[poly_loops[0].v]);
copy_v3_v3(v2, positions[poly_loops[1].v]);
BKE_mesh_calc_poly_normal(poly, loopstart, positions, normal);
copy_v3_v3(v1, positions[loopstart[0].v]);
copy_v3_v3(v2, positions[loopstart[1].v]);
zero_v3(r_cent); zero_v3(r_cent);
for (int i = 2; i < poly->totloop; i++) { for (int i = 2; i < poly_loops.size(); i++) {
copy_v3_v3(v3, positions[loopstart[i].v]); copy_v3_v3(v3, positions[poly_loops[i].v]);
float tri_area = area_tri_signed_v3(v1, v2, v3, normal); float tri_area = area_tri_signed_v3(v1, v2, v3, normal);
total_area += tri_area; total_area += tri_area;
@ -217,24 +234,23 @@ static float mesh_calc_poly_area_centroid(const MPoly *poly,
return total_area; return total_area;
} }
void BKE_mesh_calc_poly_angles(const MPoly *poly, void poly_angles_calc(const Span<float3> vert_positions,
const MLoop *loopstart, const Span<MLoop> poly_loops,
const float (*vert_positions)[3], MutableSpan<float> angles)
float angles[])
{ {
float nor_prev[3]; float nor_prev[3];
float nor_next[3]; float nor_next[3];
int i_this = poly->totloop - 1; int i_this = poly_loops.size() - 1;
int i_next = 0; int i_next = 0;
sub_v3_v3v3( sub_v3_v3v3(
nor_prev, vert_positions[loopstart[i_this - 1].v], vert_positions[loopstart[i_this].v]); nor_prev, vert_positions[poly_loops[i_this - 1].v], vert_positions[poly_loops[i_this].v]);
normalize_v3(nor_prev); normalize_v3(nor_prev);
while (i_next < poly->totloop) { while (i_next < poly_loops.size()) {
sub_v3_v3v3( sub_v3_v3v3(
nor_next, vert_positions[loopstart[i_this].v], vert_positions[loopstart[i_next].v]); nor_next, vert_positions[poly_loops[i_this].v], vert_positions[poly_loops[i_next].v]);
normalize_v3(nor_next); normalize_v3(nor_next);
angles[i_this] = angle_normalized_v3v3(nor_prev, nor_next); angles[i_this] = angle_normalized_v3v3(nor_prev, nor_next);
@ -245,6 +261,8 @@ void BKE_mesh_calc_poly_angles(const MPoly *poly,
} }
} }
} // namespace blender::bke::mesh
void BKE_mesh_poly_edgehash_insert(EdgeHash *ehash, const MPoly *poly, const MLoop *mloop) void BKE_mesh_poly_edgehash_insert(EdgeHash *ehash, const MPoly *poly, const MLoop *mloop)
{ {
const MLoop *ml, *ml_next; const MLoop *ml, *ml_next;
@ -332,7 +350,7 @@ bool BKE_mesh_center_of_surface(const Mesh *me, float r_cent[3])
float poly_area; float poly_area;
float total_area = 0.0f; float total_area = 0.0f;
float poly_cent[3]; float poly_cent[3];
const float(*positions)[3] = BKE_mesh_vert_positions(me); const Span<float3> positions = me->vert_positions();
const blender::Span<MPoly> polys = me->polys(); const blender::Span<MPoly> polys = me->polys();
const blender::Span<MLoop> loops = me->loops(); const blender::Span<MLoop> loops = me->loops();
@ -340,8 +358,8 @@ bool BKE_mesh_center_of_surface(const Mesh *me, float r_cent[3])
/* calculate a weighted average of polygon centroids */ /* calculate a weighted average of polygon centroids */
for (const int i : polys.index_range()) { for (const int i : polys.index_range()) {
poly_area = mesh_calc_poly_area_centroid( poly_area = blender::bke::mesh::poly_area_centroid_calc(
&polys[i], &loops[polys[i].loopstart], positions, poly_cent); positions, loops.slice(polys[i].loopstart, polys[i].totloop), poly_cent);
madd_v3_v3fl(r_cent, poly_cent, poly_area); madd_v3_v3fl(r_cent, poly_cent, poly_area);
total_area += poly_area; total_area += poly_area;
@ -376,8 +394,8 @@ bool BKE_mesh_center_of_volume(const Mesh *me, float r_cent[3])
/* calculate a weighted average of polyhedron centroids */ /* calculate a weighted average of polyhedron centroids */
for (const int i : polys.index_range()) { for (const int i : polys.index_range()) {
poly_volume = mesh_calc_poly_volume_centroid_with_reference_center( poly_volume = blender::bke::mesh::mesh_calc_poly_volume_centroid_with_reference_center(
&polys[i], &loops[polys[i].loopstart], positions, init_cent, poly_cent); positions, loops.slice(polys[i].loopstart, polys[i].totloop), init_cent, poly_cent);
/* poly_cent is already volume-weighted, so no need to multiply by the volume */ /* poly_cent is already volume-weighted, so no need to multiply by the volume */
add_v3_v3(r_cent, poly_cent); add_v3_v3(r_cent, poly_cent);

View File

@ -16,7 +16,7 @@
#include "BKE_lib_id.h" #include "BKE_lib_id.h"
#include "BKE_lib_query.h" #include "BKE_lib_query.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_fair.h" #include "BKE_mesh_fair.h"
#include "BKE_mesh_mapping.h" #include "BKE_mesh_mapping.h"

View File

@ -12,7 +12,7 @@
#include "BKE_customdata.h" #include "BKE_customdata.h"
#include "BKE_editmesh.h" #include "BKE_editmesh.h"
#include "BKE_editmesh_cache.h" #include "BKE_editmesh_cache.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_iterators.h" #include "BKE_mesh_iterators.h"
#include "BLI_bitmap.h" #include "BLI_bitmap.h"
@ -233,6 +233,7 @@ void BKE_mesh_foreach_mapped_face_center(
void *userData, void *userData,
MeshForeachFlag flag) MeshForeachFlag flag)
{ {
using namespace blender;
if (mesh->edit_mesh != nullptr && mesh->runtime->edit_data != nullptr) { if (mesh->edit_mesh != nullptr && mesh->runtime->edit_data != nullptr) {
BMEditMesh *em = mesh->edit_mesh; BMEditMesh *em = mesh->edit_mesh;
BMesh *bm = em->bm; BMesh *bm = em->bm;
@ -267,11 +268,9 @@ void BKE_mesh_foreach_mapped_face_center(
} }
} }
else { else {
const float(*positions)[3] = BKE_mesh_vert_positions(mesh); const blender::Span<float3> positions = mesh->vert_positions();
const blender::Span<MPoly> polys = mesh->polys(); const blender::Span<MPoly> polys = mesh->polys();
const blender::Span<MLoop> loops = mesh->loops(); const blender::Span<MLoop> loops = mesh->loops();
float _no_buf[3];
float *no = (flag & MESH_FOREACH_USE_NORMAL) ? _no_buf : nullptr;
const int *index = static_cast<const int *>(CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX)); const int *index = static_cast<const int *>(CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX));
if (index) { if (index) {
@ -280,22 +279,28 @@ void BKE_mesh_foreach_mapped_face_center(
if (orig == ORIGINDEX_NONE) { if (orig == ORIGINDEX_NONE) {
continue; continue;
} }
float cent[3]; const Span<MLoop> poly_loops = loops.slice(polys[i].loopstart, polys[i].totloop);
BKE_mesh_calc_poly_center(&polys[i], &loops[polys[i].loopstart], positions, cent); const float3 center = bke::mesh::poly_center_calc(positions, poly_loops);
if (flag & MESH_FOREACH_USE_NORMAL) { if (flag & MESH_FOREACH_USE_NORMAL) {
BKE_mesh_calc_poly_normal(&polys[i], &loops[polys[i].loopstart], positions, no); const float3 normal = bke::mesh::poly_normal_calc(positions, poly_loops);
func(userData, orig, center, normal);
}
else {
func(userData, orig, center, nullptr);
} }
func(userData, orig, cent, no);
} }
} }
else { else {
for (const int i : polys.index_range()) { for (const int i : polys.index_range()) {
float cent[3]; const Span<MLoop> poly_loops = loops.slice(polys[i].loopstart, polys[i].totloop);
BKE_mesh_calc_poly_center(&polys[i], &loops[polys[i].loopstart], positions, cent); const float3 center = bke::mesh::poly_center_calc(positions, poly_loops);
if (flag & MESH_FOREACH_USE_NORMAL) { if (flag & MESH_FOREACH_USE_NORMAL) {
BKE_mesh_calc_poly_normal(&polys[i], &loops[polys[i].loopstart], positions, no); const float3 normal = bke::mesh::poly_normal_calc(positions, poly_loops);
func(userData, i, center, normal);
}
else {
func(userData, i, center, nullptr);
} }
func(userData, i, cent, no);
} }
} }
} }

View File

@ -27,7 +27,7 @@
#include "BKE_attribute.hh" #include "BKE_attribute.hh"
#include "BKE_customdata.h" #include "BKE_customdata.h"
#include "BKE_global.h" #include "BKE_global.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_legacy_convert.h" #include "BKE_mesh_legacy_convert.h"
#include "BKE_multires.h" #include "BKE_multires.h"

View File

@ -15,7 +15,7 @@
#include "BLI_utildefines.h" #include "BLI_utildefines.h"
#include "BKE_customdata.h" #include "BKE_customdata.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_mapping.h" #include "BKE_mesh_mapping.h"
#include "BLI_memarena.h" #include "BLI_memarena.h"

View File

@ -5,6 +5,7 @@
* \ingroup bke * \ingroup bke
*/ */
#include "BLI_array.hh"
#include "BLI_math.h" #include "BLI_math.h"
#include "DNA_mesh_types.h" #include "DNA_mesh_types.h"
@ -14,7 +15,7 @@
#include "BKE_deform.h" #include "BKE_deform.h"
#include "BKE_lib_id.h" #include "BKE_lib_id.h"
#include "BKE_lib_query.h" #include "BKE_lib_query.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_mirror.h" #include "BKE_mesh_mirror.h"
#include "BKE_modifier.h" #include "BKE_modifier.h"
@ -372,8 +373,7 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
/* handle custom split normals */ /* handle custom split normals */
if (ob->type == OB_MESH && (((Mesh *)ob->data)->flag & ME_AUTOSMOOTH) && if (ob->type == OB_MESH && (((Mesh *)ob->data)->flag & ME_AUTOSMOOTH) &&
CustomData_has_layer(&result->ldata, CD_CUSTOMLOOPNORMAL) && result->totpoly > 0) { CustomData_has_layer(&result->ldata, CD_CUSTOMLOOPNORMAL) && result->totpoly > 0) {
float(*loop_normals)[3] = static_cast<float(*)[3]>( blender::Array<blender::float3> loop_normals(result_loops.size());
MEM_calloc_arrayN(size_t(result->totloop), sizeof(*loop_normals), __func__));
CustomData *ldata = &result->ldata; CustomData *ldata = &result->ldata;
short(*clnors)[2] = static_cast<short(*)[2]>( short(*clnors)[2] = static_cast<short(*)[2]>(
CustomData_get_layer_for_write(ldata, CD_CUSTOMLOOPNORMAL, result->totloop)); CustomData_get_layer_for_write(ldata, CD_CUSTOMLOOPNORMAL, result->totloop));
@ -391,24 +391,20 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
CustomData_get_layer_named(&result->edata, CD_PROP_BOOL, "sharp_edge")); CustomData_get_layer_named(&result->edata, CD_PROP_BOOL, "sharp_edge"));
const bool *sharp_faces = static_cast<const bool *>( const bool *sharp_faces = static_cast<const bool *>(
CustomData_get_layer_named(&result->pdata, CD_PROP_BOOL, "sharp_face")); CustomData_get_layer_named(&result->pdata, CD_PROP_BOOL, "sharp_face"));
BKE_mesh_normals_loop_split(BKE_mesh_vert_positions(result), blender::bke::mesh::normals_calc_loop(result->vert_positions(),
BKE_mesh_vert_normals_ensure(result), result_edges,
result->totvert, result_polys,
result_edges.data(), result_loops,
result_edges.size(), {},
result_loops.data(), result->vert_normals(),
loop_normals, result->poly_normals(),
result_loops.size(), sharp_edges,
result_polys.data(), sharp_faces,
BKE_mesh_poly_normals_ensure(result), true,
result_polys.size(), result->smoothresh,
true, clnors,
result->smoothresh, &lnors_spacearr,
sharp_edges, loop_normals);
sharp_faces,
nullptr,
&lnors_spacearr,
clnors);
/* mirroring has to account for loops being reversed in polys in second half */ /* mirroring has to account for loops being reversed in polys in second half */
for (const int i : src_polys.index_range()) { for (const int i : src_polys.index_range()) {
@ -427,7 +423,6 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
} }
} }
MEM_freeN(loop_normals);
BKE_lnor_spacearr_free(&lnors_spacearr); BKE_lnor_spacearr_free(&lnors_spacearr);
} }

View File

@ -21,7 +21,7 @@
#include "BLI_linklist.h" #include "BLI_linklist.h"
#include "BLI_linklist_stack.h" #include "BLI_linklist_stack.h"
#include "BLI_math.h" #include "BLI_math.h"
#include "BLI_math_vector_types.hh" #include "BLI_math_vector.hh"
#include "BLI_memarena.h" #include "BLI_memarena.h"
#include "BLI_span.hh" #include "BLI_span.hh"
#include "BLI_stack.h" #include "BLI_stack.h"
@ -34,7 +34,7 @@
#include "BKE_customdata.h" #include "BKE_customdata.h"
#include "BKE_editmesh_cache.h" #include "BKE_editmesh_cache.h"
#include "BKE_global.h" #include "BKE_global.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_mapping.h" #include "BKE_mesh_mapping.h"
#include "atomic_ops.h" #include "atomic_ops.h"
@ -158,6 +158,8 @@ bool BKE_mesh_poly_normals_are_dirty(const Mesh *mesh)
/** \name Mesh Normal Calculation (Polygons) /** \name Mesh Normal Calculation (Polygons)
* \{ */ * \{ */
namespace blender::bke::mesh {
/* /*
* COMPUTE POLY NORMAL * COMPUTE POLY NORMAL
* *
@ -165,88 +167,77 @@ bool BKE_mesh_poly_normals_are_dirty(const Mesh *mesh)
* polygon See Graphics Gems for * polygon See Graphics Gems for
* computing newell normal. * computing newell normal.
*/ */
static void mesh_calc_ngon_normal(const MPoly *poly, static float3 normal_calc_ngon(const Span<float3> vert_positions, const Span<MLoop> poly_loops)
const MLoop *loopstart,
const float (*positions)[3],
float r_normal[3])
{ {
const int nverts = poly->totloop; float3 normal(0);
const float *v_prev = positions[loopstart[nverts - 1].v];
const float *v_curr;
zero_v3(r_normal);
/* Newell's Method */ /* Newell's Method */
for (int i = 0; i < nverts; i++) { const float *v_prev = vert_positions[poly_loops.last().v];
v_curr = positions[loopstart[i].v]; for (const int i : poly_loops.index_range()) {
add_newell_cross_v3_v3v3(r_normal, v_prev, v_curr); const float *v_curr = vert_positions[poly_loops[i].v];
add_newell_cross_v3_v3v3(normal, v_prev, v_curr);
v_prev = v_curr; v_prev = v_curr;
} }
if (UNLIKELY(normalize_v3(r_normal) == 0.0f)) { if (UNLIKELY(normalize_v3(normal) == 0.0f)) {
r_normal[2] = 1.0f; /* other axis set to 0.0 */ normal[2] = 1.0f; /* other axis set to 0.0 */
} }
return normal;
} }
void BKE_mesh_calc_poly_normal(const MPoly *poly, float3 poly_normal_calc(const Span<float3> vert_positions, const Span<MLoop> poly_loops)
const MLoop *loopstart, {
if (poly_loops.size() > 4) {
return normal_calc_ngon(vert_positions, poly_loops);
}
if (poly_loops.size() == 3) {
return math::normal_tri(vert_positions[poly_loops[0].v],
vert_positions[poly_loops[1].v],
vert_positions[poly_loops[2].v]);
}
if (poly_loops.size() == 4) {
float3 normal;
normal_quad_v3(normal,
vert_positions[poly_loops[0].v],
vert_positions[poly_loops[1].v],
vert_positions[poly_loops[2].v],
vert_positions[poly_loops[3].v]);
return normal;
}
/* horrible, two sided face! */
return float3(0);
}
} // namespace blender::bke::mesh
void BKE_mesh_calc_poly_normal(const MLoop *poly_loops,
const int poly_size,
const float (*vert_positions)[3], const float (*vert_positions)[3],
const int verts_num,
float r_no[3]) float r_no[3])
{ {
if (poly->totloop > 4) { copy_v3_v3(r_no,
mesh_calc_ngon_normal(poly, loopstart, vert_positions, r_no); blender::bke::mesh::poly_normal_calc(
} {reinterpret_cast<const blender::float3 *>(vert_positions), verts_num},
else if (poly->totloop == 3) { {poly_loops, poly_size}));
normal_tri_v3(r_no,
vert_positions[loopstart[0].v],
vert_positions[loopstart[1].v],
vert_positions[loopstart[2].v]);
}
else if (poly->totloop == 4) {
normal_quad_v3(r_no,
vert_positions[loopstart[0].v],
vert_positions[loopstart[1].v],
vert_positions[loopstart[2].v],
vert_positions[loopstart[3].v]);
}
else { /* horrible, two sided face! */
r_no[0] = 0.0;
r_no[1] = 0.0;
r_no[2] = 1.0;
}
} }
static void calculate_normals_poly(const Span<float3> positions, namespace blender::bke::mesh {
const Span<MPoly> polys,
const Span<MLoop> loops, void normals_calc_polys(const Span<float3> positions,
MutableSpan<float3> poly_normals) const Span<MPoly> polys,
const Span<MLoop> loops,
MutableSpan<float3> poly_normals)
{ {
using namespace blender;
threading::parallel_for(polys.index_range(), 1024, [&](const IndexRange range) { threading::parallel_for(polys.index_range(), 1024, [&](const IndexRange range) {
for (const int poly_i : range) { for (const int i : range) {
const MPoly &poly = polys[poly_i]; const MPoly &poly = polys[i];
BKE_mesh_calc_poly_normal(&poly, poly_normals[i] = poly_normal_calc(positions, loops.slice(poly.loopstart, poly.totloop));
&loops[poly.loopstart],
reinterpret_cast<const float(*)[3]>(positions.data()),
poly_normals[poly_i]);
} }
}); });
} }
void BKE_mesh_calc_normals_poly(const float (*vert_positions)[3],
const int verts_num,
const MLoop *mloop,
const int mloop_len,
const MPoly *polys,
int polys_len,
float (*r_poly_normals)[3])
{
calculate_normals_poly({reinterpret_cast<const float3 *>(vert_positions), verts_num},
{polys, polys_len},
{mloop, mloop_len},
{reinterpret_cast<float3 *>(r_poly_normals), polys_len});
}
/** \} */ /** \} */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
@ -256,13 +247,12 @@ void BKE_mesh_calc_normals_poly(const float (*vert_positions)[3],
* meshes can slow down high-poly meshes. For details on performance, see D11993. * meshes can slow down high-poly meshes. For details on performance, see D11993.
* \{ */ * \{ */
static void calculate_normals_poly_and_vert(const Span<float3> positions, void normals_calc_poly_vert(const Span<float3> positions,
const Span<MPoly> polys, const Span<MPoly> polys,
const Span<MLoop> loops, const Span<MLoop> loops,
MutableSpan<float3> poly_normals, MutableSpan<float3> poly_normals,
MutableSpan<float3> vert_normals) MutableSpan<float3> vert_normals)
{ {
using namespace blender;
/* Zero the vertex normal array for accumulation. */ /* Zero the vertex normal array for accumulation. */
{ {
@ -281,7 +271,7 @@ static void calculate_normals_poly_and_vert(const Span<float3> positions,
const int i_end = poly.totloop - 1; const int i_end = poly.totloop - 1;
/* Polygon Normal and edge-vector. */ /* Polygon Normal and edge-vector. */
/* Inline version of #BKE_mesh_calc_poly_normal, also does edge-vectors. */ /* Inline version of #poly_normal_calc, also does edge-vectors. */
{ {
zero_v3(pnor); zero_v3(pnor);
/* Newell's Method */ /* Newell's Method */
@ -346,21 +336,7 @@ static void calculate_normals_poly_and_vert(const Span<float3> positions,
} }
} }
void BKE_mesh_calc_normals_poly_and_vertex(const float (*vert_positions)[3], } // namespace blender::bke::mesh
const int mvert_len,
const MLoop *mloop,
const int mloop_len,
const MPoly *polys,
const int polys_len,
float (*r_poly_normals)[3],
float (*r_vert_normals)[3])
{
calculate_normals_poly_and_vert({reinterpret_cast<const float3 *>(vert_positions), mvert_len},
{polys, polys_len},
{mloop, mloop_len},
{reinterpret_cast<float3 *>(r_poly_normals), polys_len},
{reinterpret_cast<float3 *>(r_vert_normals), mvert_len});
}
/** \} */ /** \} */
@ -397,15 +373,12 @@ const float (*BKE_mesh_vert_normals_ensure(const Mesh *mesh))[3]
vert_normals = BKE_mesh_vert_normals_for_write(&mesh_mutable); vert_normals = BKE_mesh_vert_normals_for_write(&mesh_mutable);
poly_normals = BKE_mesh_poly_normals_for_write(&mesh_mutable); poly_normals = BKE_mesh_poly_normals_for_write(&mesh_mutable);
blender::bke::mesh::normals_calc_poly_vert(
BKE_mesh_calc_normals_poly_and_vertex(reinterpret_cast<const float(*)[3]>(positions.data()), positions,
positions.size(), polys,
loops.data(), loops,
loops.size(), {reinterpret_cast<float3 *>(poly_normals), mesh->totpoly},
polys.data(), {reinterpret_cast<float3 *>(vert_normals), mesh->totvert});
polys.size(),
poly_normals,
vert_normals);
BKE_mesh_vert_normals_clear_dirty(&mesh_mutable); BKE_mesh_vert_normals_clear_dirty(&mesh_mutable);
BKE_mesh_poly_normals_clear_dirty(&mesh_mutable); BKE_mesh_poly_normals_clear_dirty(&mesh_mutable);
@ -441,14 +414,8 @@ const float (*BKE_mesh_poly_normals_ensure(const Mesh *mesh))[3]
const Span<MLoop> loops = mesh_mutable.loops(); const Span<MLoop> loops = mesh_mutable.loops();
poly_normals = BKE_mesh_poly_normals_for_write(&mesh_mutable); poly_normals = BKE_mesh_poly_normals_for_write(&mesh_mutable);
blender::bke::mesh::normals_calc_polys(
BKE_mesh_calc_normals_poly(reinterpret_cast<const float(*)[3]>(positions.data()), positions, polys, loops, {reinterpret_cast<float3 *>(poly_normals), mesh->totvert});
positions.size(),
loops.data(),
loops.size(),
polys.data(),
polys.size(),
poly_normals);
BKE_mesh_poly_normals_clear_dirty(&mesh_mutable); BKE_mesh_poly_normals_clear_dirty(&mesh_mutable);
}); });
@ -788,6 +755,8 @@ struct LoopSplitTaskDataCommon {
/* See comment about edge_to_loops below. */ /* See comment about edge_to_loops below. */
#define IS_EDGE_SHARP(_e2l) ELEM((_e2l)[1], INDEX_UNSET, INDEX_INVALID) #define IS_EDGE_SHARP(_e2l) ELEM((_e2l)[1], INDEX_UNSET, INDEX_INVALID)
namespace blender::bke::mesh {
static void mesh_edges_sharp_tag(const Span<MPoly> polys, static void mesh_edges_sharp_tag(const Span<MPoly> polys,
const Span<MLoop> loops, const Span<MLoop> loops,
const Span<int> loop_to_poly_map, const Span<int> loop_to_poly_map,
@ -799,7 +768,6 @@ static void mesh_edges_sharp_tag(const Span<MPoly> polys,
MutableSpan<int2> edge_to_loops, MutableSpan<int2> edge_to_loops,
MutableSpan<bool> r_sharp_edges) MutableSpan<bool> r_sharp_edges)
{ {
using namespace blender;
const float split_angle_cos = check_angle ? cosf(split_angle) : -1.0f; const float split_angle_cos = check_angle ? cosf(split_angle) : -1.0f;
auto poly_is_smooth = [&](const int poly_i) { auto poly_is_smooth = [&](const int poly_i) {
return sharp_faces.is_empty() || !sharp_faces[poly_i]; return sharp_faces.is_empty() || !sharp_faces[poly_i];
@ -860,40 +828,34 @@ static void mesh_edges_sharp_tag(const Span<MPoly> polys,
} }
} }
void BKE_edges_sharp_from_angle_set(const int numEdges, void edges_sharp_from_angle_set(const Span<MPoly> polys,
const MLoop *mloops, const Span<MLoop> loops,
const int numLoops, const Span<float3> poly_normals,
const MPoly *polys, const bool *sharp_faces,
const float (*poly_normals)[3], const float split_angle,
const bool *sharp_faces, MutableSpan<bool> sharp_edges)
const int numPolys,
const float split_angle,
bool *sharp_edges)
{ {
using namespace blender;
using namespace blender::bke;
if (split_angle >= float(M_PI)) { if (split_angle >= float(M_PI)) {
/* Nothing to do! */ /* Nothing to do! */
return; return;
} }
/* Mapping edge -> loops. See #BKE_mesh_normals_loop_split for details. */ /* Mapping edge -> loops. See #bke::mesh::normals_calc_loop for details. */
Array<int2> edge_to_loops(numEdges, int2(0)); Array<int2> edge_to_loops(sharp_edges.size(), int2(0));
/* Simple mapping from a loop to its polygon index. */ /* Simple mapping from a loop to its polygon index. */
const Array<int> loop_to_poly = mesh_topology::build_loop_to_poly_map({polys, numPolys}, const Array<int> loop_to_poly = mesh_topology::build_loop_to_poly_map(polys, loops.size());
numLoops);
mesh_edges_sharp_tag({polys, numPolys}, mesh_edges_sharp_tag(polys,
{mloops, numLoops}, loops,
loop_to_poly, loop_to_poly,
{reinterpret_cast<const float3 *>(poly_normals), numPolys}, poly_normals,
Span<bool>(sharp_faces, sharp_faces ? numPolys : 0), Span<bool>(sharp_faces, sharp_faces ? polys.size() : 0),
Span<bool>(sharp_edges, numEdges), sharp_edges,
true, true,
split_angle, split_angle,
edge_to_loops, edge_to_loops,
{sharp_edges, numEdges}); sharp_edges);
} }
static void loop_manifold_fan_around_vert_next(const Span<MLoop> loops, static void loop_manifold_fan_around_vert_next(const Span<MLoop> loops,
@ -1304,8 +1266,6 @@ static bool loop_split_generator_check_cyclic_smooth_fan(const Span<MLoop> mloop
static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common_data) static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common_data)
{ {
using namespace blender;
using namespace blender::bke;
MLoopNorSpaceArray *lnors_spacearr = common_data->lnors_spacearr; MLoopNorSpaceArray *lnors_spacearr = common_data->lnors_spacearr;
const Span<MLoop> loops = common_data->loops; const Span<MLoop> loops = common_data->loops;
@ -1440,27 +1400,21 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common
} }
} }
void BKE_mesh_normals_loop_split(const float (*vert_positions)[3], void normals_calc_loop(const Span<float3> vert_positions,
const float (*vert_normals)[3], const Span<MEdge> edges,
const int numVerts, const Span<MPoly> polys,
const MEdge *edges, const Span<MLoop> loops,
const int numEdges, const Span<int> loop_to_poly_map,
const MLoop *mloops, const Span<float3> vert_normals,
float (*r_loop_normals)[3], const Span<float3> poly_normals,
const int numLoops, const bool *sharp_edges,
const MPoly *polys, const bool *sharp_faces,
const float (*poly_normals)[3], bool use_split_normals,
const int numPolys, float split_angle,
const bool use_split_normals, short (*clnors_data)[2],
const float split_angle, MLoopNorSpaceArray *r_lnors_spacearr,
const bool *sharp_edges, MutableSpan<float3> r_loop_normals)
const bool *sharp_faces,
const int *loop_to_poly_map,
MLoopNorSpaceArray *r_lnors_spacearr,
short (*clnors_data)[2])
{ {
using namespace blender;
using namespace blender::bke;
/* For now this is not supported. /* For now this is not supported.
* If we do not use split normals, we do not generate anything fancy! */ * If we do not use split normals, we do not generate anything fancy! */
BLI_assert(use_split_normals || !(r_lnors_spacearr)); BLI_assert(use_split_normals || !(r_lnors_spacearr));
@ -1472,12 +1426,10 @@ void BKE_mesh_normals_loop_split(const float (*vert_positions)[3],
* since we may want to use loop_normals even when mesh's 'autosmooth' is disabled * since we may want to use loop_normals even when mesh's 'autosmooth' is disabled
* (see e.g. mesh mapping code). As usual, we could handle that on case-by-case basis, * (see e.g. mesh mapping code). As usual, we could handle that on case-by-case basis,
* but simpler to keep it well confined here. */ * but simpler to keep it well confined here. */
int poly_index; for (const int poly_index : polys.index_range()) {
const MPoly *poly = &polys[poly_index];
for (poly_index = 0; poly_index < numPolys; poly_index++) { int ml_index = poly->loopstart;
const MPoly &poly = polys[poly_index]; const int ml_index_end = ml_index + poly->totloop;
int ml_index = poly.loopstart;
const int ml_index_end = ml_index + poly.totloop;
const bool is_poly_flat = sharp_faces && sharp_faces[poly_index]; const bool is_poly_flat = sharp_faces && sharp_faces[poly_index];
for (; ml_index < ml_index_end; ml_index++) { for (; ml_index < ml_index_end; ml_index++) {
@ -1485,7 +1437,7 @@ void BKE_mesh_normals_loop_split(const float (*vert_positions)[3],
copy_v3_v3(r_loop_normals[ml_index], poly_normals[poly_index]); copy_v3_v3(r_loop_normals[ml_index], poly_normals[poly_index]);
} }
else { else {
copy_v3_v3(r_loop_normals[ml_index], vert_normals[mloops[ml_index].v]); copy_v3_v3(r_loop_normals[ml_index], vert_normals[loops[ml_index].v]);
} }
} }
} }
@ -1506,17 +1458,17 @@ void BKE_mesh_normals_loop_split(const float (*vert_positions)[3],
* However, if needed, we can store the negated value of loop index instead of INDEX_INVALID * However, if needed, we can store the negated value of loop index instead of INDEX_INVALID
* to retrieve the real value later in code). * to retrieve the real value later in code).
* Note also that loose edges always have both values set to 0! */ * Note also that loose edges always have both values set to 0! */
Array<int2> edge_to_loops(numEdges, int2(0)); Array<int2> edge_to_loops(edges.size(), int2(0));
/* Simple mapping from a loop to its polygon index. */ /* Simple mapping from a loop to its polygon index. */
Span<int> loop_to_poly; Span<int> loop_to_poly;
Array<int> local_loop_to_poly_map; Array<int> local_loop_to_poly_map;
if (loop_to_poly_map) { if (loop_to_poly_map.is_empty()) {
loop_to_poly = {loop_to_poly_map, numLoops}; local_loop_to_poly_map = mesh_topology::build_loop_to_poly_map(polys, loops.size());
loop_to_poly = local_loop_to_poly_map;
} }
else { else {
local_loop_to_poly_map = mesh_topology::build_loop_to_poly_map({polys, numPolys}, numLoops); loop_to_poly = loop_to_poly_map;
loop_to_poly = local_loop_to_poly_map;
} }
/* When using custom loop normals, disable the angle feature! */ /* When using custom loop normals, disable the angle feature! */
@ -1533,28 +1485,27 @@ void BKE_mesh_normals_loop_split(const float (*vert_positions)[3],
r_lnors_spacearr = &_lnors_spacearr; r_lnors_spacearr = &_lnors_spacearr;
} }
if (r_lnors_spacearr) { if (r_lnors_spacearr) {
BKE_lnor_spacearr_init(r_lnors_spacearr, numLoops, MLNOR_SPACEARR_LOOP_INDEX); BKE_lnor_spacearr_init(r_lnors_spacearr, loops.size(), MLNOR_SPACEARR_LOOP_INDEX);
} }
const Span<MLoop> loops(mloops, numLoops);
/* Init data common to all tasks. */ /* Init data common to all tasks. */
LoopSplitTaskDataCommon common_data; LoopSplitTaskDataCommon common_data;
common_data.lnors_spacearr = r_lnors_spacearr; common_data.lnors_spacearr = r_lnors_spacearr;
common_data.loop_normals = {reinterpret_cast<float3 *>(r_loop_normals), numLoops}; common_data.loop_normals = r_loop_normals;
common_data.clnors_data = {reinterpret_cast<short2 *>(clnors_data), clnors_data ? numLoops : 0}; common_data.clnors_data = {reinterpret_cast<short2 *>(clnors_data),
common_data.positions = {reinterpret_cast<const float3 *>(vert_positions), numVerts}; clnors_data ? loops.size() : 0};
common_data.edges = {edges, numEdges}; common_data.positions = vert_positions;
common_data.polys = {polys, numPolys}; common_data.edges = edges;
common_data.polys = polys;
common_data.loops = loops; common_data.loops = loops;
common_data.edge_to_loops = edge_to_loops; common_data.edge_to_loops = edge_to_loops;
common_data.loop_to_poly = loop_to_poly; common_data.loop_to_poly = loop_to_poly;
common_data.poly_normals = {reinterpret_cast<const float3 *>(poly_normals), numPolys}; common_data.poly_normals = poly_normals;
common_data.vert_normals = {reinterpret_cast<const float3 *>(vert_normals), numVerts}; common_data.vert_normals = vert_normals;
/* Pre-populate all loop normals as if their verts were all smooth. /* Pre-populate all loop normals as if their verts were all smooth.
* This way we don't have to compute those later! */ * This way we don't have to compute those later! */
threading::parallel_for(IndexRange(numPolys), 1024, [&](const IndexRange range) { threading::parallel_for(polys.index_range(), 1024, [&](const IndexRange range) {
for (const int poly_i : range) { for (const int poly_i : range) {
const MPoly &poly = polys[poly_i]; const MPoly &poly = polys[poly_i];
for (const int loop_i : IndexRange(poly.loopstart, poly.totloop)) { for (const int loop_i : IndexRange(poly.loopstart, poly.totloop)) {
@ -1564,18 +1515,18 @@ void BKE_mesh_normals_loop_split(const float (*vert_positions)[3],
}); });
/* This first loop check which edges are actually smooth, and compute edge vectors. */ /* This first loop check which edges are actually smooth, and compute edge vectors. */
mesh_edges_sharp_tag({polys, numPolys}, mesh_edges_sharp_tag(polys,
loops, loops,
loop_to_poly, loop_to_poly,
{reinterpret_cast<const float3 *>(poly_normals), numPolys}, poly_normals,
Span<bool>(sharp_faces, sharp_faces ? numPolys : 0), Span<bool>(sharp_faces, sharp_faces ? polys.size() : 0),
Span<bool>(sharp_edges, sharp_edges ? numEdges : 0), Span<bool>(sharp_edges, sharp_edges ? edges.size() : 0),
check_angle, check_angle,
split_angle, split_angle,
edge_to_loops, edge_to_loops,
{}); {});
if (numLoops < LOOP_SPLIT_TASK_BLOCK_SIZE * 8) { if (loops.size() < LOOP_SPLIT_TASK_BLOCK_SIZE * 8) {
/* Not enough loops to be worth the whole threading overhead. */ /* Not enough loops to be worth the whole threading overhead. */
loop_split_generator(nullptr, &common_data); loop_split_generator(nullptr, &common_data);
} }
@ -1609,36 +1560,28 @@ void BKE_mesh_normals_loop_split(const float (*vert_positions)[3],
* r_custom_loop_normals is expected to have normalized normals, or zero ones, * r_custom_loop_normals is expected to have normalized normals, or zero ones,
* in which case they will be replaced by default loop/vertex normal. * in which case they will be replaced by default loop/vertex normal.
*/ */
static void mesh_normals_loop_custom_set(const float (*positions)[3],
const float (*vert_normals)[3], static void mesh_normals_loop_custom_set(Span<float3> positions,
const int numVerts, Span<MEdge> edges,
const MEdge *edges, Span<MPoly> polys,
const int numEdges, Span<MLoop> loops,
const MLoop *mloops, Span<float3> vert_normals,
float (*r_custom_loop_normals)[3], Span<float3> poly_normals,
const int numLoops,
const MPoly *polys,
const float (*poly_normals)[3],
const bool *sharp_faces, const bool *sharp_faces,
const int numPolys, const bool use_vertices,
MutableSpan<float3> r_custom_loop_normals,
MutableSpan<bool> sharp_edges, MutableSpan<bool> sharp_edges,
short (*r_clnors_data)[2], short (*r_clnors_data)[2])
const bool use_vertices)
{ {
using namespace blender; /* We *may* make that poor #bke::mesh::normals_calc_loop() even more complex by making it
using namespace blender::bke; * handling that feature too, would probably be more efficient in absolute. However, this
/* We *may* make that poor #BKE_mesh_normals_loop_split() even more complex by making it handling * function *is not* performance-critical, since it is mostly expected to be called by io add-ons
* that feature too, would probably be more efficient in absolute. * when importing custom normals, and modifier (and perhaps from some editing tools later?). So
* However, this function *is not* performance-critical, since it is mostly expected to be called * better to keep some simplicity here, and just call #bke::mesh::normals_calc_loop() twice! */
* by io add-ons when importing custom normals, and modifier
* (and perhaps from some editing tools later?).
* So better to keep some simplicity here, and just call #BKE_mesh_normals_loop_split() twice! */
MLoopNorSpaceArray lnors_spacearr = {nullptr}; MLoopNorSpaceArray lnors_spacearr = {nullptr};
BitVector<> done_loops(numLoops, false); BitVector<> done_loops(loops.size(), false);
float(*loop_normals)[3] = (float(*)[3])MEM_calloc_arrayN( Array<float3> loop_normals(loops.size());
size_t(numLoops), sizeof(*loop_normals), __func__); const Array<int> loop_to_poly = mesh_topology::build_loop_to_poly_map(polys, loops.size());
const Array<int> loop_to_poly = mesh_topology::build_loop_to_poly_map({polys, numPolys},
numLoops);
/* In this case we always consider split nors as ON, /* In this case we always consider split nors as ON,
* and do not want to use angle to define smooth fans! */ * and do not want to use angle to define smooth fans! */
const bool use_split_normals = true; const bool use_split_normals = true;
@ -1647,35 +1590,31 @@ static void mesh_normals_loop_custom_set(const float (*positions)[3],
BLI_SMALLSTACK_DECLARE(clnors_data, short *); BLI_SMALLSTACK_DECLARE(clnors_data, short *);
/* Compute current lnor spacearr. */ /* Compute current lnor spacearr. */
BKE_mesh_normals_loop_split(positions, normals_calc_loop(positions,
vert_normals, edges,
numVerts, polys,
edges, loops,
numEdges, loop_to_poly,
mloops, vert_normals,
loop_normals, poly_normals,
numLoops, sharp_edges.data(),
polys, sharp_faces,
poly_normals, use_split_normals,
numPolys, split_angle,
use_split_normals, r_clnors_data,
split_angle, &lnors_spacearr,
sharp_edges.data(), loop_normals);
sharp_faces,
loop_to_poly.data(),
&lnors_spacearr,
nullptr);
/* Set all given zero vectors to their default value. */ /* Set all given zero vectors to their default value. */
if (use_vertices) { if (use_vertices) {
for (int i = 0; i < numVerts; i++) { for (const int i : positions.index_range()) {
if (is_zero_v3(r_custom_loop_normals[i])) { if (is_zero_v3(r_custom_loop_normals[i])) {
copy_v3_v3(r_custom_loop_normals[i], vert_normals[i]); copy_v3_v3(r_custom_loop_normals[i], vert_normals[i]);
} }
} }
} }
else { else {
for (int i = 0; i < numLoops; i++) { for (const int i : loops.index_range()) {
if (is_zero_v3(r_custom_loop_normals[i])) { if (is_zero_v3(r_custom_loop_normals[i])) {
copy_v3_v3(r_custom_loop_normals[i], loop_normals[i]); copy_v3_v3(r_custom_loop_normals[i], loop_normals[i]);
} }
@ -1686,7 +1625,7 @@ static void mesh_normals_loop_custom_set(const float (*positions)[3],
/* Now, check each current smooth fan (one lnor space per smooth fan!), /* Now, check each current smooth fan (one lnor space per smooth fan!),
* and if all its matching custom loop_normals are not (enough) equal, add sharp edges as needed. * and if all its matching custom loop_normals are not (enough) equal, add sharp edges as needed.
* This way, next time we run BKE_mesh_normals_loop_split(), we'll get lnor spacearr/smooth fans * This way, next time we run bke::mesh::normals_calc_loop(), we'll get lnor spacearr/smooth fans
* matching given custom loop_normals. * matching given custom loop_normals.
* Note this code *will never* unsharp edges! And quite obviously, * Note this code *will never* unsharp edges! And quite obviously,
* when we set custom normals per vertices, running this is absolutely useless. */ * when we set custom normals per vertices, running this is absolutely useless. */
@ -1694,7 +1633,7 @@ static void mesh_normals_loop_custom_set(const float (*positions)[3],
done_loops.fill(true); done_loops.fill(true);
} }
else { else {
for (int i = 0; i < numLoops; i++) { for (const int i : loops.index_range()) {
if (!lnors_spacearr.lspacearr[i]) { if (!lnors_spacearr.lspacearr[i]) {
/* This should not happen in theory, but in some rare case (probably ugly geometry) /* This should not happen in theory, but in some rare case (probably ugly geometry)
* we can get some nullptr loopspacearr at this point. :/ * we can get some nullptr loopspacearr at this point. :/
@ -1712,7 +1651,7 @@ static void mesh_normals_loop_custom_set(const float (*positions)[3],
/* Notes: /* Notes:
* - In case of mono-loop smooth fan, we have nothing to do. * - In case of mono-loop smooth fan, we have nothing to do.
* - Loops in this linklist are ordered (in reversed order compared to how they were * - Loops in this linklist are ordered (in reversed order compared to how they were
* discovered by BKE_mesh_normals_loop_split(), but this is not a problem). * discovered by bke::mesh::normals_calc_loop(), but this is not a problem).
* Which means if we find a mismatching clnor, * Which means if we find a mismatching clnor,
* we know all remaining loops will have to be in a new, different smooth fan/lnor space. * we know all remaining loops will have to be in a new, different smooth fan/lnor space.
* - In smooth fan case, we compare each clnor against a ref one, * - In smooth fan case, we compare each clnor against a ref one,
@ -1723,13 +1662,13 @@ static void mesh_normals_loop_custom_set(const float (*positions)[3],
continue; continue;
} }
LinkNode *loops = lnors_spacearr.lspacearr[i]->loops; LinkNode *loop_link = lnors_spacearr.lspacearr[i]->loops;
const MLoop *prev_ml = nullptr; const MLoop *prev_ml = nullptr;
const float *org_nor = nullptr; const float *org_nor = nullptr;
while (loops) { while (loop_link) {
const int lidx = POINTER_AS_INT(loops->link); const int lidx = POINTER_AS_INT(loop_link->link);
const MLoop *ml = &mloops[lidx]; const MLoop *ml = &loops[lidx];
const int nidx = lidx; const int nidx = lidx;
float *nor = r_custom_loop_normals[nidx]; float *nor = r_custom_loop_normals[nidx];
@ -1743,14 +1682,14 @@ static void mesh_normals_loop_custom_set(const float (*positions)[3],
* since we do not allow reversed winding in a same smooth fan. */ * since we do not allow reversed winding in a same smooth fan. */
const MPoly &poly = polys[loop_to_poly[lidx]]; const MPoly &poly = polys[loop_to_poly[lidx]];
const MLoop *mlp = const MLoop *mlp =
&mloops[(lidx == poly.loopstart) ? poly.loopstart + poly.totloop - 1 : lidx - 1]; &loops[(lidx == poly.loopstart) ? poly.loopstart + poly.totloop - 1 : lidx - 1];
sharp_edges[(prev_ml->e == mlp->e) ? prev_ml->e : ml->e] = true; sharp_edges[(prev_ml->e == mlp->e) ? prev_ml->e : ml->e] = true;
org_nor = nor; org_nor = nor;
} }
prev_ml = ml; prev_ml = ml;
loops = loops->next; loop_link = loop_link->next;
done_loops[lidx].set(); done_loops[lidx].set();
} }
@ -1758,17 +1697,17 @@ static void mesh_normals_loop_custom_set(const float (*positions)[3],
* otherwise we may miss some sharp edges here! * otherwise we may miss some sharp edges here!
* This is just a simplified version of above while loop. * This is just a simplified version of above while loop.
* See #45984. */ * See #45984. */
loops = lnors_spacearr.lspacearr[i]->loops; loop_link = lnors_spacearr.lspacearr[i]->loops;
if (loops && org_nor) { if (loop_link && org_nor) {
const int lidx = POINTER_AS_INT(loops->link); const int lidx = POINTER_AS_INT(loop_link->link);
const MLoop *ml = &mloops[lidx]; const MLoop *ml = &loops[lidx];
const int nidx = lidx; const int nidx = lidx;
float *nor = r_custom_loop_normals[nidx]; float *nor = r_custom_loop_normals[nidx];
if (dot_v3v3(org_nor, nor) < LNOR_SPACE_TRIGO_THRESHOLD) { if (dot_v3v3(org_nor, nor) < LNOR_SPACE_TRIGO_THRESHOLD) {
const MPoly &poly = polys[loop_to_poly[lidx]]; const MPoly &poly = polys[loop_to_poly[lidx]];
const MLoop *mlp = const MLoop *mlp =
&mloops[(lidx == poly.loopstart) ? poly.loopstart + poly.totloop - 1 : lidx - 1]; &loops[(lidx == poly.loopstart) ? poly.loopstart + poly.totloop - 1 : lidx - 1];
sharp_edges[(prev_ml->e == mlp->e) ? prev_ml->e : ml->e] = true; sharp_edges[(prev_ml->e == mlp->e) ? prev_ml->e : ml->e] = true;
} }
} }
@ -1776,29 +1715,25 @@ static void mesh_normals_loop_custom_set(const float (*positions)[3],
/* And now, recompute our new auto `loop_normals` and lnor spacearr! */ /* And now, recompute our new auto `loop_normals` and lnor spacearr! */
BKE_lnor_spacearr_clear(&lnors_spacearr); BKE_lnor_spacearr_clear(&lnors_spacearr);
BKE_mesh_normals_loop_split(positions, normals_calc_loop(positions,
vert_normals, edges,
numVerts, polys,
edges, loops,
numEdges, loop_to_poly,
mloops, vert_normals,
loop_normals, poly_normals,
numLoops, sharp_edges.data(),
polys, sharp_faces,
poly_normals, use_split_normals,
numPolys, split_angle,
use_split_normals, r_clnors_data,
split_angle, &lnors_spacearr,
sharp_edges.data(), loop_normals);
sharp_faces,
loop_to_poly.data(),
&lnors_spacearr,
nullptr);
} }
/* And we just have to convert plain object-space custom normals to our /* And we just have to convert plain object-space custom normals to our
* lnor space-encoded ones. */ * lnor space-encoded ones. */
for (int i = 0; i < numLoops; i++) { for (const int i : loops.index_range()) {
if (!lnors_spacearr.lspacearr[i]) { if (!lnors_spacearr.lspacearr[i]) {
done_loops[i].reset(); done_loops[i].reset();
if (G.debug & G_DEBUG) { if (G.debug & G_DEBUG) {
@ -1812,10 +1747,10 @@ static void mesh_normals_loop_custom_set(const float (*positions)[3],
/* Note we accumulate and average all custom normals in current smooth fan, /* Note we accumulate and average all custom normals in current smooth fan,
* to avoid getting different clnors data (tiny differences in plain custom normals can * to avoid getting different clnors data (tiny differences in plain custom normals can
* give rather huge differences in computed 2D factors). */ * give rather huge differences in computed 2D factors). */
LinkNode *loops = lnors_spacearr.lspacearr[i]->loops; LinkNode *loop_link = lnors_spacearr.lspacearr[i]->loops;
if (lnors_spacearr.lspacearr[i]->flags & MLNOR_SPACE_IS_SINGLE) { if (lnors_spacearr.lspacearr[i]->flags & MLNOR_SPACE_IS_SINGLE) {
BLI_assert(POINTER_AS_INT(loops) == i); BLI_assert(POINTER_AS_INT(loop_link) == i);
const int nidx = use_vertices ? int(mloops[i].v) : i; const int nidx = use_vertices ? int(loops[i].v) : i;
float *nor = r_custom_loop_normals[nidx]; float *nor = r_custom_loop_normals[nidx];
BKE_lnor_space_custom_normal_to_data(lnors_spacearr.lspacearr[i], nor, r_clnors_data[i]); BKE_lnor_space_custom_normal_to_data(lnors_spacearr.lspacearr[i], nor, r_clnors_data[i]);
@ -1827,16 +1762,16 @@ static void mesh_normals_loop_custom_set(const float (*positions)[3],
short clnor_data_tmp[2], *clnor_data; short clnor_data_tmp[2], *clnor_data;
zero_v3(avg_nor); zero_v3(avg_nor);
while (loops) { while (loop_link) {
const int lidx = POINTER_AS_INT(loops->link); const int lidx = POINTER_AS_INT(loop_link->link);
const int nidx = use_vertices ? int(mloops[lidx].v) : lidx; const int nidx = use_vertices ? int(loops[lidx].v) : lidx;
float *nor = r_custom_loop_normals[nidx]; float *nor = r_custom_loop_normals[nidx];
avg_nor_count++; avg_nor_count++;
add_v3_v3(avg_nor, nor); add_v3_v3(avg_nor, nor);
BLI_SMALLSTACK_PUSH(clnors_data, (short *)r_clnors_data[lidx]); BLI_SMALLSTACK_PUSH(clnors_data, (short *)r_clnors_data[lidx]);
loops = loops->next; loop_link = loop_link->next;
done_loops[lidx].reset(); done_loops[lidx].reset();
} }
@ -1851,78 +1786,59 @@ static void mesh_normals_loop_custom_set(const float (*positions)[3],
} }
} }
MEM_freeN(loop_normals);
BKE_lnor_spacearr_free(&lnors_spacearr); BKE_lnor_spacearr_free(&lnors_spacearr);
} }
void BKE_mesh_normals_loop_custom_set(const float (*vert_positions)[3], void normals_loop_custom_set(const Span<float3> vert_positions,
const float (*vert_normals)[3], const Span<MEdge> edges,
const int numVerts, const Span<MPoly> polys,
const MEdge *edges, const Span<MLoop> loops,
const int numEdges, const Span<float3> vert_normals,
const MLoop *mloops, const Span<float3> poly_normals,
float (*r_custom_loop_normals)[3], const bool *sharp_faces,
const int numLoops, MutableSpan<bool> sharp_edges,
const MPoly *polys, MutableSpan<float3> r_custom_loop_normals,
const float (*poly_normals)[3], short (*r_clnors_data)[2])
const bool *sharp_faces,
const int numPolys,
bool *sharp_edges,
short (*r_clnors_data)[2])
{ {
mesh_normals_loop_custom_set(vert_positions, mesh_normals_loop_custom_set(vert_positions,
vert_normals,
numVerts,
edges, edges,
numEdges,
mloops,
r_custom_loop_normals,
numLoops,
polys, polys,
loops,
vert_normals,
poly_normals, poly_normals,
sharp_faces, sharp_faces,
numPolys, false,
{sharp_edges, numEdges}, r_custom_loop_normals,
r_clnors_data, sharp_edges,
false); r_clnors_data);
} }
void BKE_mesh_normals_loop_custom_from_verts_set(const float (*vert_positions)[3], void normals_loop_custom_set_from_verts(const Span<float3> vert_positions,
const float (*vert_normals)[3], const Span<MEdge> edges,
float (*r_custom_vert_normals)[3], const Span<MPoly> polys,
const int numVerts, const Span<MLoop> loops,
const MEdge *edges, const Span<float3> vert_normals,
const int numEdges, const Span<float3> poly_normals,
const MLoop *mloops, const bool *sharp_faces,
const int numLoops, MutableSpan<bool> sharp_edges,
const MPoly *polys, MutableSpan<float3> r_custom_vert_normals,
const float (*poly_normals)[3], short (*r_clnors_data)[2])
const bool *sharp_faces,
const int numPolys,
bool *sharp_edges,
short (*r_clnors_data)[2])
{ {
mesh_normals_loop_custom_set(vert_positions, mesh_normals_loop_custom_set(vert_positions,
vert_normals,
numVerts,
edges, edges,
numEdges,
mloops,
r_custom_vert_normals,
numLoops,
polys, polys,
loops,
vert_normals,
poly_normals, poly_normals,
sharp_faces, sharp_faces,
numPolys, true,
{sharp_edges, numEdges}, r_custom_vert_normals,
r_clnors_data, sharp_edges,
true); r_clnors_data);
} }
static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const bool use_vertices) static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const bool use_vertices)
{ {
using namespace blender;
using namespace blender::bke;
short(*clnors)[2]; short(*clnors)[2];
const int numloops = mesh->totloop; const int numloops = mesh->totloop;
@ -1935,41 +1851,38 @@ static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const
clnors = (short(*)[2])CustomData_add_layer( clnors = (short(*)[2])CustomData_add_layer(
&mesh->ldata, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, nullptr, numloops); &mesh->ldata, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, nullptr, numloops);
} }
const Span<float3> positions = mesh->vert_positions();
MutableSpan<MEdge> edges = mesh->edges_for_write();
const Span<MPoly> polys = mesh->polys();
const Span<MLoop> loops = mesh->loops();
MutableAttributeAccessor attributes = mesh->attributes_for_write(); MutableAttributeAccessor attributes = mesh->attributes_for_write();
SpanAttributeWriter<bool> sharp_edges = attributes.lookup_or_add_for_write_span<bool>( SpanAttributeWriter<bool> sharp_edges = attributes.lookup_or_add_for_write_span<bool>(
"sharp_edge", ATTR_DOMAIN_EDGE); "sharp_edge", ATTR_DOMAIN_EDGE);
const bool *sharp_faces = static_cast<const bool *>( const bool *sharp_faces = static_cast<const bool *>(
CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, "sharp_face")); CustomData_get_layer_named(&mesh->pdata, CD_PROP_BOOL, "sharp_face"));
mesh_normals_loop_custom_set(reinterpret_cast<const float(*)[3]>(positions.data()),
BKE_mesh_vert_normals_ensure(mesh), mesh_normals_loop_custom_set(mesh->vert_positions(),
positions.size(), mesh->edges(),
edges.data(), mesh->polys(),
edges.size(), mesh->loops(),
loops.data(), mesh->vert_normals(),
r_custom_nors, mesh->poly_normals(),
loops.size(),
polys.data(),
BKE_mesh_poly_normals_ensure(mesh),
sharp_faces, sharp_faces,
polys.size(), use_vertices,
{reinterpret_cast<blender::float3 *>(r_custom_nors),
use_vertices ? mesh->totvert : mesh->totloop},
sharp_edges.span, sharp_edges.span,
clnors, clnors);
use_vertices);
sharp_edges.finish(); sharp_edges.finish();
} }
} // namespace blender::bke::mesh
void BKE_mesh_set_custom_normals(Mesh *mesh, float (*r_custom_loop_normals)[3]) void BKE_mesh_set_custom_normals(Mesh *mesh, float (*r_custom_loop_normals)[3])
{ {
mesh_set_custom_normals(mesh, r_custom_loop_normals, false); blender::bke::mesh::mesh_set_custom_normals(mesh, r_custom_loop_normals, false);
} }
void BKE_mesh_set_custom_normals_from_verts(Mesh *mesh, float (*r_custom_vert_normals)[3]) void BKE_mesh_set_custom_normals_from_verts(Mesh *mesh, float (*r_custom_vert_normals)[3])
{ {
mesh_set_custom_normals(mesh, r_custom_vert_normals, true); blender::bke::mesh::mesh_set_custom_normals(mesh, r_custom_vert_normals, true);
} }
void BKE_mesh_normals_loop_to_vertex(const int numVerts, void BKE_mesh_normals_loop_to_vertex(const int numVerts,

View File

@ -26,7 +26,7 @@
#include "BKE_bvhutils.h" #include "BKE_bvhutils.h"
#include "BKE_customdata.h" #include "BKE_customdata.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_mapping.h" #include "BKE_mesh_mapping.h"
#include "BKE_mesh_remap.h" /* own include */ #include "BKE_mesh_remap.h" /* own include */
#include "BKE_mesh_runtime.h" #include "BKE_mesh_runtime.h"
@ -1043,9 +1043,9 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode,
static void mesh_island_to_astar_graph_edge_process(MeshIslandStore *islands, static void mesh_island_to_astar_graph_edge_process(MeshIslandStore *islands,
const int island_index, const int island_index,
BLI_AStarGraph *as_graph, BLI_AStarGraph *as_graph,
const float (*positions)[3], const blender::Span<blender::float3> positions,
const MPoly *polys, const blender::Span<MPoly> polys,
const MLoop *loops, const blender::Span<MLoop> loops,
const int edge_idx, const int edge_idx,
BLI_bitmap *done_edges, BLI_bitmap *done_edges,
MeshElemMap *edge_to_poly_map, MeshElemMap *edge_to_poly_map,
@ -1075,7 +1075,9 @@ static void mesh_island_to_astar_graph_edge_process(MeshIslandStore *islands,
} }
if (poly_status[pidx_isld] == POLY_UNSET) { if (poly_status[pidx_isld] == POLY_UNSET) {
BKE_mesh_calc_poly_center(&poly, &loops[poly.loopstart], positions, poly_centers[pidx_isld]); copy_v3_v3(poly_centers[pidx_isld],
blender::bke::mesh::poly_center_calc(positions,
loops.slice(poly.loopstart, poly.totloop)));
BLI_astar_node_init(as_graph, pidx_isld, poly_centers[pidx_isld]); BLI_astar_node_init(as_graph, pidx_isld, poly_centers[pidx_isld]);
poly_status[pidx_isld] = POLY_CENTER_INIT; poly_status[pidx_isld] = POLY_CENTER_INIT;
} }
@ -1100,11 +1102,11 @@ static void mesh_island_to_astar_graph_edge_process(MeshIslandStore *islands,
static void mesh_island_to_astar_graph(MeshIslandStore *islands, static void mesh_island_to_astar_graph(MeshIslandStore *islands,
const int island_index, const int island_index,
const float (*positions)[3], const blender::Span<blender::float3> positions,
MeshElemMap *edge_to_poly_map, MeshElemMap *edge_to_poly_map,
const int numedges, const int numedges,
const MLoop *loops, const blender::Span<MPoly> polys,
const MPoly *polys, const blender::Span<MLoop> loops,
const int numpolys, const int numpolys,
BLI_AStarGraph *r_as_graph) BLI_AStarGraph *r_as_graph)
{ {
@ -1289,7 +1291,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
const float(*poly_nors_dst)[3] = nullptr; const float(*poly_nors_dst)[3] = nullptr;
float(*loop_nors_dst)[3] = nullptr; float(*loop_nors_dst)[3] = nullptr;
float(*poly_cents_src)[3] = nullptr; blender::Array<blender::float3> poly_cents_src;
MeshElemMap *vert_to_loop_map_src = nullptr; MeshElemMap *vert_to_loop_map_src = nullptr;
int *vert_to_loop_map_src_buff = nullptr; int *vert_to_loop_map_src_buff = nullptr;
@ -1303,7 +1305,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
/* Unlike above, those are one-to-one mappings, simpler! */ /* Unlike above, those are one-to-one mappings, simpler! */
int *loop_to_poly_map_src = nullptr; int *loop_to_poly_map_src = nullptr;
const float(*positions_src)[3] = BKE_mesh_vert_positions(me_src); const blender::Span<blender::float3> positions_src = me_src->vert_positions();
const int num_verts_src = me_src->totvert; const int num_verts_src = me_src->totvert;
float(*vcos_src)[3] = nullptr; float(*vcos_src)[3] = nullptr;
const blender::Span<MEdge> edges_src = me_src->edges(); const blender::Span<MEdge> edges_src = me_src->edges();
@ -1363,24 +1365,21 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
CustomData_get_layer_named(&mesh_dst->edata, CD_PROP_BOOL, "sharp_edge")); CustomData_get_layer_named(&mesh_dst->edata, CD_PROP_BOOL, "sharp_edge"));
const bool *sharp_faces = static_cast<const bool *>( const bool *sharp_faces = static_cast<const bool *>(
CustomData_get_layer_named(&mesh_dst->pdata, CD_PROP_BOOL, "sharp_face")); CustomData_get_layer_named(&mesh_dst->pdata, CD_PROP_BOOL, "sharp_face"));
BKE_mesh_normals_loop_split(vert_positions_dst, blender::bke::mesh::normals_calc_loop(
BKE_mesh_vert_normals_ensure(mesh_dst), {reinterpret_cast<const blender::float3 *>(vert_positions_dst), numverts_dst},
numverts_dst, {edges_dst, numedges_dst},
edges_dst, {polys_dst, numpolys_dst},
numedges_dst, {loops_dst, numloops_dst},
loops_dst, {},
loop_nors_dst, mesh_dst->vert_normals(),
numloops_dst, mesh_dst->poly_normals(),
polys_dst, sharp_edges,
poly_nors_dst, sharp_faces,
numpolys_dst, use_split_nors_dst,
use_split_nors_dst, split_angle_dst,
split_angle_dst, custom_nors_dst,
sharp_edges, nullptr,
sharp_faces, {reinterpret_cast<blender::float3 *>(loop_nors_dst), numloops_dst});
nullptr,
nullptr,
custom_nors_dst);
} }
} }
if (need_pnors_src || need_lnors_src) { if (need_pnors_src || need_lnors_src) {
@ -1425,8 +1424,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
if (use_from_vert) { if (use_from_vert) {
loop_to_poly_map_src = static_cast<int *>( loop_to_poly_map_src = static_cast<int *>(
MEM_mallocN(sizeof(*loop_to_poly_map_src) * size_t(loops_src.size()), __func__)); MEM_mallocN(sizeof(*loop_to_poly_map_src) * size_t(loops_src.size()), __func__));
poly_cents_src = static_cast<float(*)[3]>( poly_cents_src.reinitialize(polys_src.size());
MEM_mallocN(sizeof(*poly_cents_src) * size_t(polys_src.size()), __func__));
for (pidx_src = 0; pidx_src < polys_src.size(); pidx_src++) { for (pidx_src = 0; pidx_src < polys_src.size(); pidx_src++) {
const MPoly &poly = polys_src[pidx_src]; const MPoly &poly = polys_src[pidx_src];
ml_src = &loops_src[poly.loopstart]; ml_src = &loops_src[poly.loopstart];
@ -1434,7 +1432,8 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
plidx_src++, lidx_src++) { plidx_src++, lidx_src++) {
loop_to_poly_map_src[lidx_src] = pidx_src; loop_to_poly_map_src[lidx_src] = pidx_src;
} }
BKE_mesh_calc_poly_center(&poly, ml_src, positions_src, poly_cents_src[pidx_src]); poly_cents_src[pidx_src] = blender::bke::mesh::poly_center_calc(
positions_src, loops_src.slice(poly.loopstart, poly.totloop));
} }
} }
@ -1449,7 +1448,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
if (gen_islands_src) { if (gen_islands_src) {
const bool *uv_seams = static_cast<const bool *>( const bool *uv_seams = static_cast<const bool *>(
CustomData_get_layer_named(&me_src->edata, CD_PROP_BOOL, ".uv_seam")); CustomData_get_layer_named(&me_src->edata, CD_PROP_BOOL, ".uv_seam"));
use_islands = gen_islands_src(positions_src, use_islands = gen_islands_src(reinterpret_cast<const float(*)[3]>(positions_src.data()),
num_verts_src, num_verts_src,
edges_src.data(), edges_src.data(),
int(edges_src.size()), int(edges_src.size()),
@ -1493,8 +1492,8 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
positions_src, positions_src,
edge_to_poly_map_src, edge_to_poly_map_src,
int(edges_src.size()), int(edges_src.size()),
loops_src.data(), polys_src,
polys_src.data(), loops_src,
int(polys_src.size()), int(polys_src.size()),
&as_graphdata[tindex]); &as_graphdata[tindex]);
} }
@ -1520,7 +1519,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
} }
} }
bvhtree_from_mesh_verts_ex(&treedata[tindex], bvhtree_from_mesh_verts_ex(&treedata[tindex],
positions_src, reinterpret_cast<const float(*)[3]>(positions_src.data()),
num_verts_src, num_verts_src,
verts_active, verts_active,
num_verts_active, num_verts_active,
@ -1550,7 +1549,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
} }
} }
bvhtree_from_mesh_looptri_ex(&treedata[tindex], bvhtree_from_mesh_looptri_ex(&treedata[tindex],
positions_src, reinterpret_cast<const float(*)[3]>(positions_src.data()),
loops_src.data(), loops_src.data(),
looptris_src.data(), looptris_src.data(),
int(looptris_src.size()), int(looptris_src.size()),
@ -1580,7 +1579,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
/* Only in use_from_vert case, we may need polys' centers as fallback /* Only in use_from_vert case, we may need polys' centers as fallback
* in case we cannot decide which corner to use from normals only. */ * in case we cannot decide which corner to use from normals only. */
float pcent_dst[3]; blender::float3 pcent_dst;
bool pcent_dst_valid = false; bool pcent_dst_valid = false;
if (mode == MREMAP_MODE_LOOP_NEAREST_POLYNOR) { if (mode == MREMAP_MODE_LOOP_NEAREST_POLYNOR) {
@ -1668,8 +1667,10 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
ml_src = &loops_src[poly.loopstart]; ml_src = &loops_src[poly.loopstart];
if (!pcent_dst_valid) { if (!pcent_dst_valid) {
BKE_mesh_calc_poly_center( pcent_dst = blender::bke::mesh::poly_center_calc(
mp_dst, &loops_dst[mp_dst->loopstart], vert_positions_dst, pcent_dst); {reinterpret_cast<const blender::float3 *>(vert_positions_dst),
numverts_dst},
{&loops_dst[mp_dst->loopstart], mp_dst->totloop});
pcent_dst_valid = true; pcent_dst_valid = true;
} }
pcent_src = poly_cents_src[pidx_src]; pcent_src = poly_cents_src[pidx_src];
@ -2139,9 +2140,6 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
if (loop_to_poly_map_src) { if (loop_to_poly_map_src) {
MEM_freeN(loop_to_poly_map_src); MEM_freeN(loop_to_poly_map_src);
} }
if (poly_cents_src) {
MEM_freeN(poly_cents_src);
}
if (vcos_interp) { if (vcos_interp) {
MEM_freeN(vcos_interp); MEM_freeN(vcos_interp);
} }
@ -2160,6 +2158,7 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode,
const float ray_radius, const float ray_radius,
const Mesh *mesh_dst, const Mesh *mesh_dst,
const float (*vert_positions_dst)[3], const float (*vert_positions_dst)[3],
const int numverts_dst,
const MLoop *loops_dst, const MLoop *loops_dst,
const MPoly *polys_dst, const MPoly *polys_dst,
const int numpolys_dst, const int numpolys_dst,
@ -2169,7 +2168,7 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode,
const float full_weight = 1.0f; const float full_weight = 1.0f;
const float max_dist_sq = max_dist * max_dist; const float max_dist_sq = max_dist * max_dist;
const float(*poly_nors_dst)[3] = nullptr; const float(*poly_nors_dst)[3] = nullptr;
float tmp_co[3], tmp_no[3]; blender::float3 tmp_co, tmp_no;
int i; int i;
BLI_assert(mode & MREMAP_MODE_POLY); BLI_assert(mode & MREMAP_MODE_POLY);
@ -2199,8 +2198,9 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode,
for (i = 0; i < numpolys_dst; i++) { for (i = 0; i < numpolys_dst; i++) {
const MPoly &poly = polys_dst[i]; const MPoly &poly = polys_dst[i];
tmp_co = blender::bke::mesh::poly_center_calc(
BKE_mesh_calc_poly_center(&poly, &loops_dst[poly.loopstart], vert_positions_dst, tmp_co); {reinterpret_cast<const blender::float3 *>(vert_positions_dst), numverts_dst},
{&loops_dst[poly.loopstart], poly.totloop});
/* Convert the vertex to tree coordinates, if needed. */ /* Convert the vertex to tree coordinates, if needed. */
if (space_transform) { if (space_transform) {
@ -2225,7 +2225,9 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode,
for (i = 0; i < numpolys_dst; i++) { for (i = 0; i < numpolys_dst; i++) {
const MPoly &poly = polys_dst[i]; const MPoly &poly = polys_dst[i];
BKE_mesh_calc_poly_center(&poly, &loops_dst[poly.loopstart], vert_positions_dst, tmp_co); tmp_co = blender::bke::mesh::poly_center_calc(
{reinterpret_cast<const blender::float3 *>(vert_positions_dst), numverts_dst},
{&loops_dst[poly.loopstart], poly.totloop});
copy_v3_v3(tmp_no, poly_nors_dst[i]); copy_v3_v3(tmp_no, poly_nors_dst[i]);
/* Convert the vertex to tree coordinates, if needed. */ /* Convert the vertex to tree coordinates, if needed. */
@ -2277,7 +2279,7 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode,
int tot_rays, done_rays = 0; int tot_rays, done_rays = 0;
float poly_area_2d_inv, done_area = 0.0f; float poly_area_2d_inv, done_area = 0.0f;
float pcent_dst[3]; blender::float3 pcent_dst;
float to_pnor_2d_mat[3][3], from_pnor_2d_mat[3][3]; float to_pnor_2d_mat[3][3], from_pnor_2d_mat[3][3];
float poly_dst_2d_min[2], poly_dst_2d_max[2], poly_dst_2d_z; float poly_dst_2d_min[2], poly_dst_2d_max[2], poly_dst_2d_z;
float poly_dst_2d_size[2]; float poly_dst_2d_size[2];
@ -2288,8 +2290,10 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode,
const int tris_num = poly.totloop - 2; const int tris_num = poly.totloop - 2;
int j; int j;
BKE_mesh_calc_poly_center( pcent_dst = blender::bke::mesh::poly_center_calc(
&poly, &loops_dst[poly.loopstart], vert_positions_dst, pcent_dst); {reinterpret_cast<const blender::float3 *>(vert_positions_dst), numverts_dst},
{&loops_dst[poly.loopstart], poly.totloop});
copy_v3_v3(tmp_no, poly_nors_dst[i]); copy_v3_v3(tmp_no, poly_nors_dst[i]);
/* We do our transform here, else it'd be redone by raycast helper for each ray, ugh! */ /* We do our transform here, else it'd be redone by raycast helper for each ray, ugh! */

View File

@ -30,7 +30,7 @@
#include "BKE_customdata.h" #include "BKE_customdata.h"
#include "BKE_editmesh.h" #include "BKE_editmesh.h"
#include "BKE_lib_id.h" #include "BKE_lib_id.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_mapping.h" #include "BKE_mesh_mapping.h"
#include "BKE_mesh_remesh_voxel.h" /* own include */ #include "BKE_mesh_remesh_voxel.h" /* own include */
#include "BKE_mesh_runtime.h" #include "BKE_mesh_runtime.h"
@ -338,15 +338,12 @@ void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, const Mesh *source)
blender::threading::parallel_for(IndexRange(target->totpoly), 2048, [&](const IndexRange range) { blender::threading::parallel_for(IndexRange(target->totpoly), 2048, [&](const IndexRange range) {
for (const int i : range) { for (const int i : range) {
float from_co[3];
BVHTreeNearest nearest; BVHTreeNearest nearest;
nearest.index = -1; nearest.index = -1;
nearest.dist_sq = FLT_MAX; nearest.dist_sq = FLT_MAX;
const MPoly &poly = target_polys[i]; const MPoly &poly = target_polys[i];
BKE_mesh_calc_poly_center(&poly, const float3 from_co = mesh::poly_center_calc(
&target_loops[poly.loopstart], target_positions, target_loops.slice(poly.loopstart, poly.totloop));
reinterpret_cast<const float(*)[3]>(target_positions.data()),
from_co);
BLI_bvhtree_find_nearest( BLI_bvhtree_find_nearest(
bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree); bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree);
if (nearest.index != -1) { if (nearest.index != -1) {

View File

@ -20,7 +20,7 @@
#include "BKE_bvhutils.h" #include "BKE_bvhutils.h"
#include "BKE_editmesh_cache.h" #include "BKE_editmesh_cache.h"
#include "BKE_lib_id.h" #include "BKE_lib_id.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_runtime.h" #include "BKE_mesh_runtime.h"
#include "BKE_shrinkwrap.h" #include "BKE_shrinkwrap.h"
#include "BKE_subdiv_ccg.h" #include "BKE_subdiv_ccg.h"
@ -152,21 +152,11 @@ blender::Span<MLoopTri> Mesh::looptris() const
r_data.reinitialize(poly_to_tri_count(polys.size(), loops.size())); r_data.reinitialize(poly_to_tri_count(polys.size(), loops.size()));
if (BKE_mesh_poly_normals_are_dirty(this)) { if (BKE_mesh_poly_normals_are_dirty(this)) {
BKE_mesh_recalc_looptri(loops.data(), blender::bke::mesh::looptris_calc(positions, polys, loops, r_data);
polys.data(),
reinterpret_cast<const float(*)[3]>(positions.data()),
loops.size(),
polys.size(),
r_data.data());
} }
else { else {
BKE_mesh_recalc_looptri_with_normals(loops.data(), blender::bke::mesh::looptris_calc_with_normals(
polys.data(), positions, polys, loops, this->poly_normals(), r_data);
reinterpret_cast<const float(*)[3]>(positions.data()),
loops.size(),
polys.size(),
r_data.data(),
BKE_mesh_poly_normals_ensure(this));
} }
}); });

View File

@ -2,7 +2,7 @@
#include "BKE_attribute_math.hh" #include "BKE_attribute_math.hh"
#include "BKE_bvhutils.h" #include "BKE_bvhutils.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_runtime.h" #include "BKE_mesh_runtime.h"
#include "BKE_mesh_sample.hh" #include "BKE_mesh_sample.hh"

View File

@ -20,7 +20,7 @@
#include "BKE_attribute.hh" #include "BKE_attribute.hh"
#include "BKE_customdata.h" #include "BKE_customdata.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_runtime.h" #include "BKE_mesh_runtime.h"
#include "BKE_mesh_tangent.h" #include "BKE_mesh_tangent.h"
#include "BKE_report.h" #include "BKE_report.h"

View File

@ -10,24 +10,18 @@
* \see bmesh_mesh_tessellate.c for the #BMesh equivalent of this file. * \see bmesh_mesh_tessellate.c for the #BMesh equivalent of this file.
*/ */
#include <climits> #include "BLI_enumerable_thread_specific.hh"
#include "MEM_guardedalloc.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "BLI_math.h" #include "BLI_math.h"
#include "BLI_memarena.h" #include "BLI_memarena.h"
#include "BLI_polyfill_2d.h" #include "BLI_polyfill_2d.h"
#include "BLI_task.h" #include "BLI_task.h"
#include "BLI_utildefines.h"
#include "BKE_customdata.h" #include "BKE_mesh.hh"
#include "BKE_mesh.h" /* Own include. */
#include "BLI_strict_flags.h" #include "BLI_strict_flags.h"
namespace blender::bke::mesh {
/** Compared against total loops. */ /** Compared against total loops. */
#define MESH_FACE_TESSELLATE_THREADED_LIMIT 4096 #define MESH_FACE_TESSELLATE_THREADED_LIMIT 4096
@ -40,9 +34,9 @@
/** /**
* \param face_normal: This will be optimized out as a constant. * \param face_normal: This will be optimized out as a constant.
*/ */
BLI_INLINE void mesh_calc_tessellation_for_face_impl(const MLoop *mloop, BLI_INLINE void mesh_calc_tessellation_for_face_impl(const Span<MLoop> mloop,
const MPoly *polys, const Span<MPoly> polys,
const float (*positions)[3], const Span<float3> positions,
uint poly_index, uint poly_index,
MLoopTri *mlt, MLoopTri *mlt,
MemArena **pf_arena_p, MemArena **pf_arena_p,
@ -101,7 +95,7 @@ BLI_INLINE void mesh_calc_tessellation_for_face_impl(const MLoop *mloop,
zero_v3(normal); zero_v3(normal);
/* Calc normal, flipped: to get a positive 2D cross product. */ /* Calc normal, flipped: to get a positive 2D cross product. */
ml = mloop + mp_loopstart; ml = mloop.data() + mp_loopstart;
co_prev = positions[ml[mp_totloop - 1].v]; co_prev = positions[ml[mp_totloop - 1].v];
for (uint j = 0; j < mp_totloop; j++, ml++) { for (uint j = 0; j < mp_totloop; j++, ml++) {
co_curr = positions[ml->v]; co_curr = positions[ml->v];
@ -129,7 +123,7 @@ BLI_INLINE void mesh_calc_tessellation_for_face_impl(const MLoop *mloop,
float(*projverts)[2] = static_cast<float(*)[2]>( float(*projverts)[2] = static_cast<float(*)[2]>(
BLI_memarena_alloc(pf_arena, sizeof(*projverts) * size_t(mp_totloop))); BLI_memarena_alloc(pf_arena, sizeof(*projverts) * size_t(mp_totloop)));
ml = mloop + mp_loopstart; ml = mloop.data() + mp_loopstart;
for (uint j = 0; j < mp_totloop; j++, ml++) { for (uint j = 0; j < mp_totloop; j++, ml++) {
mul_v2_m3v3(projverts[j], axis_mat, positions[ml->v]); mul_v2_m3v3(projverts[j], axis_mat, positions[ml->v]);
} }
@ -150,9 +144,9 @@ BLI_INLINE void mesh_calc_tessellation_for_face_impl(const MLoop *mloop,
#undef ML_TO_MLT #undef ML_TO_MLT
} }
static void mesh_calc_tessellation_for_face(const MLoop *mloop, static void mesh_calc_tessellation_for_face(const Span<MLoop> mloop,
const MPoly *polys, const Span<MPoly> polys,
const float (*positions)[3], const Span<float3> positions,
uint poly_index, uint poly_index,
MLoopTri *mlt, MLoopTri *mlt,
MemArena **pf_arena_p) MemArena **pf_arena_p)
@ -161,9 +155,9 @@ static void mesh_calc_tessellation_for_face(const MLoop *mloop,
mloop, polys, positions, poly_index, mlt, pf_arena_p, false, nullptr); mloop, polys, positions, poly_index, mlt, pf_arena_p, false, nullptr);
} }
static void mesh_calc_tessellation_for_face_with_normal(const MLoop *mloop, static void mesh_calc_tessellation_for_face_with_normal(const Span<MLoop> mloop,
const MPoly *polys, const Span<MPoly> polys,
const float (*positions)[3], const Span<float3> positions,
uint poly_index, uint poly_index,
MLoopTri *mlt, MLoopTri *mlt,
MemArena **pf_arena_p, MemArena **pf_arena_p,
@ -173,16 +167,16 @@ static void mesh_calc_tessellation_for_face_with_normal(const MLoop *mloop,
mloop, polys, positions, poly_index, mlt, pf_arena_p, true, normal_precalc); mloop, polys, positions, poly_index, mlt, pf_arena_p, true, normal_precalc);
} }
static void mesh_recalc_looptri__single_threaded(const MLoop *mloop, static void mesh_recalc_looptri__single_threaded(const Span<MLoop> mloop,
const MPoly *polys, const Span<MPoly> polys,
const float (*positions)[3], const Span<float3> positions,
int totloop, int totloop,
int totpoly, int totpoly,
MLoopTri *mlooptri, MLoopTri *mlooptri,
const float (*poly_normals)[3]) const float (*poly_normals)[3])
{ {
MemArena *pf_arena = nullptr; MemArena *pf_arena = nullptr;
const MPoly *poly = polys; const MPoly *poly = polys.data();
uint tri_index = 0; uint tri_index = 0;
if (poly_normals != nullptr) { if (poly_normals != nullptr) {
@ -214,12 +208,12 @@ static void mesh_recalc_looptri__single_threaded(const MLoop *mloop,
} }
struct TessellationUserData { struct TessellationUserData {
const MLoop *mloop; Span<MLoop> mloop;
const MPoly *polys; Span<MPoly> polys;
const float (*positions)[3]; Span<float3> positions;
/** Output array. */ /** Output array. */
MLoopTri *mlooptri; MutableSpan<MLoopTri> mlooptri;
/** Optional pre-calculated polygon normals array. */ /** Optional pre-calculated polygon normals array. */
const float (*poly_normals)[3]; const float (*poly_normals)[3];
@ -272,23 +266,31 @@ static void mesh_calc_tessellation_for_face_free_fn(const void *__restrict /*use
} }
} }
static void mesh_recalc_looptri__multi_threaded(const MLoop *mloop, static void looptris_calc_all(const Span<float3> positions,
const MPoly *polys, const Span<MPoly> polys,
const float (*positions)[3], const Span<MLoop> loops,
int /*totloop*/, const Span<float3> poly_normals,
int totpoly, MutableSpan<MLoopTri> looptris)
MLoopTri *mlooptri,
const float (*poly_normals)[3])
{ {
if (loops.size() < MESH_FACE_TESSELLATE_THREADED_LIMIT) {
mesh_recalc_looptri__single_threaded(loops,
polys,
positions,
int(loops.size()),
int(polys.size()),
looptris.data(),
reinterpret_cast<const float(*)[3]>(poly_normals.data()));
return;
}
struct TessellationUserTLS tls_data_dummy = {nullptr}; struct TessellationUserTLS tls_data_dummy = {nullptr};
struct TessellationUserData data { struct TessellationUserData data {
}; };
data.mloop = mloop; data.mloop = loops;
data.polys = polys; data.polys = polys;
data.positions = positions; data.positions = positions;
data.mlooptri = mlooptri; data.mlooptri = looptris;
data.poly_normals = poly_normals; data.poly_normals = reinterpret_cast<const float(*)[3]>(poly_normals.data());
TaskParallelSettings settings; TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings); BLI_parallel_range_settings_defaults(&settings);
@ -299,47 +301,46 @@ static void mesh_recalc_looptri__multi_threaded(const MLoop *mloop,
settings.func_free = mesh_calc_tessellation_for_face_free_fn; settings.func_free = mesh_calc_tessellation_for_face_free_fn;
BLI_task_parallel_range(0, BLI_task_parallel_range(0,
totpoly, int(polys.size()),
&data, &data,
poly_normals ? mesh_calc_tessellation_for_face_with_normal_fn : data.poly_normals ? mesh_calc_tessellation_for_face_with_normal_fn :
mesh_calc_tessellation_for_face_fn, mesh_calc_tessellation_for_face_fn,
&settings); &settings);
} }
void looptris_calc(const Span<float3> vert_positions,
const Span<MPoly> polys,
const Span<MLoop> loops,
MutableSpan<MLoopTri> looptris)
{
looptris_calc_all(vert_positions, polys, loops, {}, looptris);
}
void looptris_calc_with_normals(const Span<float3> vert_positions,
const Span<MPoly> polys,
const Span<MLoop> loops,
const Span<float3> poly_normals,
MutableSpan<MLoopTri> looptris)
{
BLI_assert(!poly_normals.is_empty());
looptris_calc_all(vert_positions, polys, loops, poly_normals, looptris);
}
} // namespace blender::bke::mesh
void BKE_mesh_recalc_looptri(const MLoop *mloop, void BKE_mesh_recalc_looptri(const MLoop *mloop,
const MPoly *polys, const MPoly *polys,
const float (*vert_positions)[3], const float (*vert_positions)[3],
int totvert,
int totloop, int totloop,
int totpoly, int totpoly,
MLoopTri *mlooptri) MLoopTri *mlooptri)
{ {
if (totloop < MESH_FACE_TESSELLATE_THREADED_LIMIT) { blender::bke::mesh::looptris_calc(
mesh_recalc_looptri__single_threaded( {reinterpret_cast<const blender::float3 *>(vert_positions), totvert},
mloop, polys, vert_positions, totloop, totpoly, mlooptri, nullptr); {polys, totpoly},
} {mloop, totloop},
else { {mlooptri, poly_to_tri_count(totpoly, totloop)});
mesh_recalc_looptri__multi_threaded(
mloop, polys, vert_positions, totloop, totpoly, mlooptri, nullptr);
}
}
void BKE_mesh_recalc_looptri_with_normals(const MLoop *mloop,
const MPoly *polys,
const float (*vert_positions)[3],
int totloop,
int totpoly,
MLoopTri *mlooptri,
const float (*poly_normals)[3])
{
BLI_assert(poly_normals != nullptr);
if (totloop < MESH_FACE_TESSELLATE_THREADED_LIMIT) {
mesh_recalc_looptri__single_threaded(
mloop, polys, vert_positions, totloop, totpoly, mlooptri, poly_normals);
}
else {
mesh_recalc_looptri__multi_threaded(
mloop, polys, vert_positions, totloop, totpoly, mlooptri, poly_normals);
}
} }
/** \} */ /** \} */

View File

@ -27,7 +27,7 @@
#include "BKE_attribute.hh" #include "BKE_attribute.hh"
#include "BKE_customdata.h" #include "BKE_customdata.h"
#include "BKE_deform.h" #include "BKE_deform.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "DEG_depsgraph.h" #include "DEG_depsgraph.h"

View File

@ -34,7 +34,7 @@
#include "BKE_editmesh.h" #include "BKE_editmesh.h"
#include "BKE_editmesh_cache.h" #include "BKE_editmesh_cache.h"
#include "BKE_lib_id.h" #include "BKE_lib_id.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_runtime.h" #include "BKE_mesh_runtime.h"
#include "BKE_mesh_wrapper.h" #include "BKE_mesh_wrapper.h"
#include "BKE_modifier.h" #include "BKE_modifier.h"

View File

@ -54,7 +54,7 @@
#include "BKE_key.h" #include "BKE_key.h"
#include "BKE_lib_id.h" #include "BKE_lib_id.h"
#include "BKE_lib_query.h" #include "BKE_lib_query.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_wrapper.h" #include "BKE_mesh_wrapper.h"
#include "BKE_multires.h" #include "BKE_multires.h"
#include "BKE_object.h" #include "BKE_object.h"

View File

@ -24,7 +24,7 @@
#include "BKE_ccg.h" #include "BKE_ccg.h"
#include "BKE_cdderivedmesh.h" #include "BKE_cdderivedmesh.h"
#include "BKE_editmesh.h" #include "BKE_editmesh.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_mapping.h" #include "BKE_mesh_mapping.h"
#include "BKE_mesh_runtime.h" #include "BKE_mesh_runtime.h"
#include "BKE_modifier.h" #include "BKE_modifier.h"

View File

@ -14,7 +14,7 @@
#include "BKE_customdata.h" #include "BKE_customdata.h"
#include "BKE_lib_id.h" #include "BKE_lib_id.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_runtime.h" #include "BKE_mesh_runtime.h"
#include "BKE_modifier.h" #include "BKE_modifier.h"
#include "BKE_multires.h" #include "BKE_multires.h"

View File

@ -19,7 +19,7 @@
#include "BKE_customdata.h" #include "BKE_customdata.h"
#include "BKE_lib_id.h" #include "BKE_lib_id.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_mapping.h" #include "BKE_mesh_mapping.h"
#include "BKE_mesh_runtime.h" #include "BKE_mesh_runtime.h"
#include "BKE_multires.h" #include "BKE_multires.h"
@ -114,16 +114,10 @@ void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape
/* Find normal. */ /* Find normal. */
for (int j = 0; j < pmap[i].count; j++) { for (int j = 0; j < pmap[i].count; j++) {
const MPoly &poly = reshape_context->base_polys[pmap[i].indices[j]]; const MPoly &poly = reshape_context->base_polys[pmap[i].indices[j]];
MPoly fake_poly;
float no[3];
/* Set up poly, loops, and coords in order to call BKE_mesh_calc_poly_normal(). */ /* Set up poly, loops, and coords in order to call #bke::mesh::poly_normal_calc(). */
fake_poly.totloop = poly.totloop; blender::Array<MLoop> fake_loops(poly.totloop);
fake_poly.loopstart = 0; blender::Array<blender::float3> fake_co(poly.totloop);
MLoop *fake_loops = static_cast<MLoop *>(
MEM_malloc_arrayN(poly.totloop, sizeof(MLoop), __func__));
float(*fake_co)[3] = static_cast<float(*)[3]>(
MEM_malloc_arrayN(poly.totloop, sizeof(float[3]), __func__));
for (int k = 0; k < poly.totloop; k++) { for (int k = 0; k < poly.totloop; k++) {
const int vndx = reshape_context->base_loops[poly.loopstart + k].v; const int vndx = reshape_context->base_loops[poly.loopstart + k].v;
@ -138,10 +132,7 @@ void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape
} }
} }
BKE_mesh_calc_poly_normal(&fake_poly, fake_loops, (const float(*)[3])fake_co, no); const blender::float3 no = blender::bke::mesh::poly_normal_calc(fake_co, fake_loops);
MEM_freeN(fake_loops);
MEM_freeN(fake_co);
add_v3_v3(avg_no, no); add_v3_v3(avg_no, no);
} }
normalize_v3(avg_no); normalize_v3(avg_no);

View File

@ -14,7 +14,7 @@
#include "BKE_customdata.h" #include "BKE_customdata.h"
#include "BKE_lib_id.h" #include "BKE_lib_id.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_runtime.h" #include "BKE_mesh_runtime.h"
#include "BKE_modifier.h" #include "BKE_modifier.h"
#include "BKE_multires.h" #include "BKE_multires.h"
@ -28,7 +28,9 @@
static void multires_subdivide_create_object_space_linear_grids(Mesh *mesh) static void multires_subdivide_create_object_space_linear_grids(Mesh *mesh)
{ {
const float(*positions)[3] = BKE_mesh_vert_positions(mesh); using namespace blender;
using namespace blender::bke;
const Span<float3> positions = mesh->vert_positions();
const blender::Span<MPoly> polys = mesh->polys(); const blender::Span<MPoly> polys = mesh->polys();
const blender::Span<MLoop> loops = mesh->loops(); const blender::Span<MLoop> loops = mesh->loops();
@ -36,8 +38,8 @@ static void multires_subdivide_create_object_space_linear_grids(Mesh *mesh)
CustomData_get_layer_for_write(&mesh->ldata, CD_MDISPS, mesh->totloop)); CustomData_get_layer_for_write(&mesh->ldata, CD_MDISPS, mesh->totloop));
for (const int p : polys.index_range()) { for (const int p : polys.index_range()) {
const MPoly &poly = polys[p]; const MPoly &poly = polys[p];
float poly_center[3]; const float3 poly_center = mesh::poly_center_calc(positions,
BKE_mesh_calc_poly_center(&poly, &loops[poly.loopstart], positions, poly_center); loops.slice(poly.loopstart, poly.totloop));
for (int l = 0; l < poly.totloop; l++) { for (int l = 0; l < poly.totloop; l++) {
const int loop_index = poly.loopstart + l; const int loop_index = poly.loopstart + l;

View File

@ -18,7 +18,7 @@
#include "BLI_task.h" #include "BLI_task.h"
#include "BKE_customdata.h" #include "BKE_customdata.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_runtime.h" #include "BKE_mesh_runtime.h"
#include "BKE_multires.h" #include "BKE_multires.h"
#include "BKE_subdiv.h" #include "BKE_subdiv.h"

View File

@ -12,7 +12,7 @@
#include "BLI_utildefines.h" #include "BLI_utildefines.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_modifier.h" #include "BKE_modifier.h"
#include "BKE_multires.h" #include "BKE_multires.h"
#include "BKE_subdiv.h" #include "BKE_subdiv.h"

View File

@ -20,7 +20,7 @@
#include "BKE_customdata.h" #include "BKE_customdata.h"
#include "BKE_lib_id.h" #include "BKE_lib_id.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_runtime.h" #include "BKE_mesh_runtime.h"
#include "BKE_modifier.h" #include "BKE_modifier.h"
#include "BKE_multires.h" #include "BKE_multires.h"

View File

@ -105,7 +105,7 @@
#include "BKE_main.h" #include "BKE_main.h"
#include "BKE_material.h" #include "BKE_material.h"
#include "BKE_mball.h" #include "BKE_mball.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_wrapper.h" #include "BKE_mesh_wrapper.h"
#include "BKE_modifier.h" #include "BKE_modifier.h"
#include "BKE_multires.h" #include "BKE_multires.h"

View File

@ -44,7 +44,7 @@
#include "BKE_instances.hh" #include "BKE_instances.hh"
#include "BKE_lattice.h" #include "BKE_lattice.h"
#include "BKE_main.h" #include "BKE_main.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_iterators.h" #include "BKE_mesh_iterators.h"
#include "BKE_mesh_runtime.h" #include "BKE_mesh_runtime.h"
#include "BKE_modifier.h" #include "BKE_modifier.h"

View File

@ -38,7 +38,7 @@
#include "BKE_light.h" #include "BKE_light.h"
#include "BKE_material.h" #include "BKE_material.h"
#include "BKE_mball.h" #include "BKE_mball.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_object.h" #include "BKE_object.h"
#include "BKE_particle.h" #include "BKE_particle.h"
#include "BKE_pointcache.h" #include "BKE_pointcache.h"

View File

@ -46,7 +46,7 @@
#include "BKE_lib_id.h" #include "BKE_lib_id.h"
#include "BKE_main.h" #include "BKE_main.h"
#include "BKE_material.h" #include "BKE_material.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_mapping.h" #include "BKE_mesh_mapping.h"
#include "BKE_mesh_runtime.h" #include "BKE_mesh_runtime.h"
#include "BKE_modifier.h" #include "BKE_modifier.h"
@ -2188,12 +2188,7 @@ static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform, bool
MLoopTri *looptri = static_cast<MLoopTri *>( MLoopTri *looptri = static_cast<MLoopTri *>(
MEM_malloc_arrayN(looptris_num, sizeof(*looptri), __func__)); MEM_malloc_arrayN(looptris_num, sizeof(*looptri), __func__));
BKE_mesh_recalc_looptri(loops.data(), blender::bke::mesh::looptris_calc(positions, polys, loops, {looptri, looptris_num});
polys.data(),
reinterpret_cast<const float(*)[3]>(positions.data()),
me->totloop,
me->totpoly,
looptri);
BKE_pbvh_build_mesh(pbvh, BKE_pbvh_build_mesh(pbvh,
me, me,

View File

@ -58,7 +58,7 @@
#include "BKE_lib_query.h" #include "BKE_lib_query.h"
#include "BKE_main.h" #include "BKE_main.h"
#include "BKE_material.h" #include "BKE_material.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_legacy_convert.h" #include "BKE_mesh_legacy_convert.h"
#include "BKE_mesh_runtime.h" #include "BKE_mesh_runtime.h"
#include "BKE_modifier.h" #include "BKE_modifier.h"

View File

@ -20,7 +20,7 @@
#include "BKE_attribute.h" #include "BKE_attribute.h"
#include "BKE_ccg.h" #include "BKE_ccg.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_mapping.h" #include "BKE_mesh_mapping.h"
#include "BKE_paint.h" #include "BKE_paint.h"
#include "BKE_pbvh.h" #include "BKE_pbvh.h"
@ -1409,7 +1409,7 @@ static void pbvh_update_normals_accum_task_cb(void *__restrict userdata,
if (node->flag & PBVH_UpdateNormals) { if (node->flag & PBVH_UpdateNormals) {
uint mpoly_prev = UINT_MAX; uint mpoly_prev = UINT_MAX;
float fn[3]; blender::float3 fn;
const int *faces = node->prim_indices; const int *faces = node->prim_indices;
const int totface = node->totprim; const int totface = node->totprim;
@ -1426,7 +1426,9 @@ static void pbvh_update_normals_accum_task_cb(void *__restrict userdata,
/* Face normal and mask */ /* Face normal and mask */
if (lt->poly != mpoly_prev) { if (lt->poly != mpoly_prev) {
const MPoly &poly = pbvh->polys[lt->poly]; const MPoly &poly = pbvh->polys[lt->poly];
BKE_mesh_calc_poly_normal(&poly, &pbvh->mloop[poly.loopstart], pbvh->vert_positions, fn); fn = blender::bke::mesh::poly_normal_calc(
{reinterpret_cast<const blender::float3 *>(pbvh->vert_positions), pbvh->totvert},
{&pbvh->mloop[poly.loopstart], poly.totloop});
mpoly_prev = lt->poly; mpoly_prev = lt->poly;
} }

View File

@ -21,7 +21,7 @@
#include "BKE_attribute.h" #include "BKE_attribute.h"
#include "BKE_ccg.h" #include "BKE_ccg.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_mapping.h" #include "BKE_mesh_mapping.h"
#include "BKE_paint.h" #include "BKE_paint.h"
#include "BKE_pbvh.h" #include "BKE_pbvh.h"

View File

@ -3,7 +3,7 @@
#include "BKE_attribute.hh" #include "BKE_attribute.hh"
#include "BKE_customdata.h" #include "BKE_customdata.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_mapping.h" #include "BKE_mesh_mapping.h"
#include "BKE_pbvh.h" #include "BKE_pbvh.h"
#include "BKE_pbvh_pixels.hh" #include "BKE_pbvh_pixels.hh"

View File

@ -33,7 +33,7 @@
#include "BKE_deform.h" #include "BKE_deform.h"
#include "BKE_editmesh.h" #include "BKE_editmesh.h"
#include "BKE_mesh.h" /* for OMP limits. */ #include "BKE_mesh.hh" /* for OMP limits. */
#include "BKE_mesh_runtime.h" #include "BKE_mesh_runtime.h"
#include "BKE_mesh_wrapper.h" #include "BKE_mesh_wrapper.h"
#include "BKE_subsurf.h" #include "BKE_subsurf.h"

View File

@ -2759,7 +2759,8 @@ static void mesh_faces_to_scratch(Object *ob)
sb->scratch->totface = poly_to_tri_count(me->totpoly, me->totloop); sb->scratch->totface = poly_to_tri_count(me->totpoly, me->totloop);
looptri = lt = MEM_mallocN(sizeof(*looptri) * sb->scratch->totface, __func__); looptri = lt = MEM_mallocN(sizeof(*looptri) * sb->scratch->totface, __func__);
BKE_mesh_recalc_looptri(loops, polys, vert_positions, me->totloop, me->totpoly, looptri); BKE_mesh_recalc_looptri(
loops, polys, vert_positions, me->totvert, me->totloop, me->totpoly, looptri);
bodyface = sb->scratch->bodyface = MEM_mallocN(sizeof(BodyFace) * sb->scratch->totface, bodyface = sb->scratch->bodyface = MEM_mallocN(sizeof(BodyFace) * sb->scratch->totface,
"SB_body_Faces"); "SB_body_Faces");

View File

@ -20,7 +20,7 @@
#include "BKE_DerivedMesh.h" #include "BKE_DerivedMesh.h"
#include "BKE_ccg.h" #include "BKE_ccg.h"
#include "BKE_global.h" #include "BKE_global.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_subdiv.h" #include "BKE_subdiv.h"
#include "BKE_subdiv_eval.h" #include "BKE_subdiv_eval.h"

View File

@ -17,7 +17,7 @@
#include "BLI_utildefines.h" #include "BLI_utildefines.h"
#include "BKE_customdata.h" #include "BKE_customdata.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_subdiv.h" #include "BKE_subdiv.h"
#include "MEM_guardedalloc.h" #include "MEM_guardedalloc.h"

View File

@ -5,7 +5,7 @@
* \ingroup bke * \ingroup bke
*/ */
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_subdiv_ccg.h" #include "BKE_subdiv_ccg.h"
#include "MEM_guardedalloc.h" #include "MEM_guardedalloc.h"

View File

@ -16,7 +16,7 @@
#include "BLI_utildefines.h" #include "BLI_utildefines.h"
#include "BKE_customdata.h" #include "BKE_customdata.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_mapping.h" #include "BKE_mesh_mapping.h"
#include "BKE_subdiv.h" #include "BKE_subdiv.h"

View File

@ -18,7 +18,7 @@
#include "BLI_utildefines.h" #include "BLI_utildefines.h"
#include "BKE_customdata.h" #include "BKE_customdata.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_multires.h" #include "BKE_multires.h"
#include "BKE_subdiv_eval.h" #include "BKE_subdiv_eval.h"

View File

@ -16,7 +16,7 @@
#include "BLI_utildefines.h" #include "BLI_utildefines.h"
#include "BKE_customdata.h" #include "BKE_customdata.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_subdiv.h" #include "BKE_subdiv.h"
#include "MEM_guardedalloc.h" #include "MEM_guardedalloc.h"

View File

@ -18,7 +18,7 @@
#include "BKE_customdata.h" #include "BKE_customdata.h"
#include "BKE_key.h" #include "BKE_key.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_subdiv.h" #include "BKE_subdiv.h"
#include "BKE_subdiv_mesh.hh" #include "BKE_subdiv_mesh.hh"

View File

@ -21,7 +21,7 @@
#include "BKE_customdata.h" #include "BKE_customdata.h"
#include "BKE_key.h" #include "BKE_key.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_mapping.h" #include "BKE_mesh_mapping.h"
#include "BKE_subdiv.h" #include "BKE_subdiv.h"
#include "BKE_subdiv_eval.h" #include "BKE_subdiv_eval.h"

View File

@ -11,7 +11,7 @@
#include "DNA_scene_types.h" #include "DNA_scene_types.h"
#include "DNA_userdef_types.h" #include "DNA_userdef_types.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_modifier.h" #include "BKE_modifier.h"
#include "BKE_subdiv.h" #include "BKE_subdiv.h"

View File

@ -33,7 +33,7 @@
#include "BKE_ccg.h" #include "BKE_ccg.h"
#include "BKE_cdderivedmesh.h" #include "BKE_cdderivedmesh.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_mapping.h" #include "BKE_mesh_mapping.h"
#include "BKE_modifier.h" #include "BKE_modifier.h"
#include "BKE_multires.h" #include "BKE_multires.h"

View File

@ -10,7 +10,7 @@
#include "DNA_meshdata_types.h" #include "DNA_meshdata_types.h"
#include "DNA_volume_types.h" #include "DNA_volume_types.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_volume.h" #include "BKE_volume.h"
#ifdef WITH_OPENVDB #ifdef WITH_OPENVDB

View File

@ -75,7 +75,7 @@
#include "BKE_main.h" /* for Main */ #include "BKE_main.h" /* for Main */
#include "BKE_main_idmap.h" #include "BKE_main_idmap.h"
#include "BKE_material.h" #include "BKE_material.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_modifier.h" #include "BKE_modifier.h"
#include "BKE_node.h" /* for tree type defines */ #include "BKE_node.h" /* for tree type defines */
#include "BKE_object.h" #include "BKE_object.h"

View File

@ -48,7 +48,7 @@
#include "BKE_gpencil.h" #include "BKE_gpencil.h"
#include "BKE_lib_id.h" #include "BKE_lib_id.h"
#include "BKE_main.h" #include "BKE_main.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_multires.h" #include "BKE_multires.h"
#include "BKE_node.h" #include "BKE_node.h"

View File

@ -63,7 +63,7 @@
#include "BKE_lib_override.h" #include "BKE_lib_override.h"
#include "BKE_main.h" #include "BKE_main.h"
#include "BKE_main_namemap.h" #include "BKE_main_namemap.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_modifier.h" #include "BKE_modifier.h"
#include "BKE_node.h" #include "BKE_node.h"
#include "BKE_screen.h" #include "BKE_screen.h"

View File

@ -49,7 +49,7 @@
#include "BKE_main.h" #include "BKE_main.h"
#include "BKE_main_namemap.h" #include "BKE_main_namemap.h"
#include "BKE_material.h" #include "BKE_material.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_node.h" #include "BKE_node.h"
#include "BKE_node_runtime.hh" #include "BKE_node_runtime.hh"
#include "BKE_node_tree_update.h" #include "BKE_node_tree_update.h"

View File

@ -16,7 +16,7 @@
#include "BLI_utildefines.h" #include "BLI_utildefines.h"
#include "BKE_customdata.h" #include "BKE_customdata.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "bmesh.h" #include "bmesh.h"

View File

@ -90,7 +90,7 @@
#include "BKE_attribute.hh" #include "BKE_attribute.hh"
#include "BKE_customdata.h" #include "BKE_customdata.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_runtime.h" #include "BKE_mesh_runtime.h"
#include "BKE_multires.h" #include "BKE_multires.h"

View File

@ -22,7 +22,7 @@
#include "BKE_customdata.h" #include "BKE_customdata.h"
#include "BKE_editmesh.h" #include "BKE_editmesh.h"
#include "BKE_global.h" #include "BKE_global.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "intern/bmesh_private.h" #include "intern/bmesh_private.h"
@ -1053,7 +1053,7 @@ static void bm_mesh_loops_calc_normals_for_vert_without_clnors(
} }
/** /**
* BMesh version of BKE_mesh_normals_loop_split() in `mesh_evaluate.cc` * BMesh version of bke::mesh::normals_calc_loop() in `mesh_evaluate.cc`
* Will use first clnors_data array, and fallback to cd_loop_clnors_offset * Will use first clnors_data array, and fallback to cd_loop_clnors_offset
* (use nullptr and -1 to not use clnors). * (use nullptr and -1 to not use clnors).
* *
@ -1404,7 +1404,7 @@ static bool bm_mesh_loops_split_lnor_fans(BMesh *bm,
/* Notes: /* Notes:
* * In case of mono-loop smooth fan, we have nothing to do. * * In case of mono-loop smooth fan, we have nothing to do.
* * Loops in this linklist are ordered (in reversed order compared to how they were * * Loops in this linklist are ordered (in reversed order compared to how they were
* discovered by BKE_mesh_normals_loop_split(), but this is not a problem). * discovered by bke::mesh::normals_calc_loop(), but this is not a problem).
* Which means if we find a mismatching clnor, * Which means if we find a mismatching clnor,
* we know all remaining loops will have to be in a new, different smooth fan/lnor space. * we know all remaining loops will have to be in a new, different smooth fan/lnor space.
* * In smooth fan case, we compare each clnor against a ref one, * * In smooth fan case, we compare each clnor against a ref one,

View File

@ -75,7 +75,7 @@
#include "BKE_mask.h" #include "BKE_mask.h"
#include "BKE_material.h" #include "BKE_material.h"
#include "BKE_mball.h" #include "BKE_mball.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_modifier.h" #include "BKE_modifier.h"
#include "BKE_movieclip.h" #include "BKE_movieclip.h"
#include "BKE_node.h" #include "BKE_node.h"

View File

@ -15,7 +15,7 @@
#include "BKE_curve.h" #include "BKE_curve.h"
#include "BKE_global.h" #include "BKE_global.h"
#include "BKE_mball.h" #include "BKE_mball.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_modifier.h" #include "BKE_modifier.h"
#include "BKE_movieclip.h" #include "BKE_movieclip.h"
#include "BKE_object.h" #include "BKE_object.h"

View File

@ -17,7 +17,7 @@
#include "BKE_attribute.hh" #include "BKE_attribute.hh"
#include "BKE_editmesh.h" #include "BKE_editmesh.h"
#include "BKE_editmesh_cache.h" #include "BKE_editmesh_cache.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_runtime.h" #include "BKE_mesh_runtime.h"
#include "GPU_batch.h" #include "GPU_batch.h"
@ -363,30 +363,25 @@ void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_
mr->poly_normals = mr->me->poly_normals(); mr->poly_normals = mr->me->poly_normals();
} }
if (((data_flag & MR_DATA_LOOP_NOR) && is_auto_smooth) || (data_flag & MR_DATA_TAN_LOOP_NOR)) { if (((data_flag & MR_DATA_LOOP_NOR) && is_auto_smooth) || (data_flag & MR_DATA_TAN_LOOP_NOR)) {
mr->loop_normals = static_cast<float(*)[3]>( mr->loop_normals.reinitialize(mr->loops.size());
MEM_mallocN(sizeof(*mr->loop_normals) * mr->loop_len, __func__));
short(*clnors)[2] = static_cast<short(*)[2]>( short(*clnors)[2] = static_cast<short(*)[2]>(
CustomData_get_layer_for_write(&mr->me->ldata, CD_CUSTOMLOOPNORMAL, mr->me->totloop)); CustomData_get_layer_for_write(&mr->me->ldata, CD_CUSTOMLOOPNORMAL, mr->me->totloop));
const bool *sharp_edges = static_cast<const bool *>( const bool *sharp_edges = static_cast<const bool *>(
CustomData_get_layer_named(&mr->me->edata, CD_PROP_BOOL, "sharp_edge")); CustomData_get_layer_named(&mr->me->edata, CD_PROP_BOOL, "sharp_edge"));
BKE_mesh_normals_loop_split(reinterpret_cast<const float(*)[3]>(mr->vert_positions.data()), blender::bke::mesh::normals_calc_loop(mr->vert_positions,
reinterpret_cast<const float(*)[3]>(mr->vert_normals.data()), mr->edges,
mr->vert_positions.size(), mr->polys,
mr->edges.data(), mr->loops,
mr->edges.size(), {},
mr->loops.data(), mr->vert_normals,
mr->loop_normals, mr->poly_normals,
mr->loops.size(), sharp_edges,
mr->polys.data(), mr->sharp_faces,
reinterpret_cast<const float(*)[3]>(mr->poly_normals.data()), is_auto_smooth,
mr->polys.size(), split_angle,
is_auto_smooth, clnors,
split_angle, nullptr,
sharp_edges, mr->loop_normals);
mr->sharp_faces,
nullptr,
nullptr,
clnors);
} }
} }
else { else {
@ -406,8 +401,7 @@ void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_
poly_normals = mr->bm_poly_normals; poly_normals = mr->bm_poly_normals;
} }
mr->loop_normals = static_cast<float(*)[3]>( mr->loop_normals.reinitialize(mr->loop_len);
MEM_mallocN(sizeof(*mr->loop_normals) * mr->loop_len, __func__));
const int clnors_offset = CustomData_get_offset(&mr->bm->ldata, CD_CUSTOMLOOPNORMAL); const int clnors_offset = CustomData_get_offset(&mr->bm->ldata, CD_CUSTOMLOOPNORMAL);
BM_loops_calc_normal_vcos(mr->bm, BM_loops_calc_normal_vcos(mr->bm,
vert_coords, vert_coords,
@ -415,7 +409,7 @@ void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_
poly_normals, poly_normals,
is_auto_smooth, is_auto_smooth,
split_angle, split_angle,
mr->loop_normals, reinterpret_cast<float(*)[3]>(mr->loop_normals.data()),
nullptr, nullptr,
nullptr, nullptr,
clnors_offset, clnors_offset,
@ -443,7 +437,7 @@ MeshRenderData *mesh_render_data_create(Object *object,
const bool do_uvedit, const bool do_uvedit,
const ToolSettings *ts) const ToolSettings *ts)
{ {
MeshRenderData *mr = static_cast<MeshRenderData *>(MEM_callocN(sizeof(*mr), __func__)); MeshRenderData *mr = MEM_new<MeshRenderData>(__func__);
mr->toolsettings = ts; mr->toolsettings = ts;
mr->mat_len = mesh_render_mat_len_get(object, me); mr->mat_len = mesh_render_mat_len_get(object, me);
@ -596,13 +590,12 @@ MeshRenderData *mesh_render_data_create(Object *object,
void mesh_render_data_free(MeshRenderData *mr) void mesh_render_data_free(MeshRenderData *mr)
{ {
MEM_SAFE_FREE(mr->loop_normals);
/* Loose geometry are owned by #MeshBufferCache. */ /* Loose geometry are owned by #MeshBufferCache. */
mr->ledges = nullptr; mr->ledges = nullptr;
mr->lverts = nullptr; mr->lverts = nullptr;
MEM_freeN(mr); MEM_delete(mr);
} }
/** \} */ /** \} */

View File

@ -36,7 +36,7 @@
#include "BKE_editmesh.h" #include "BKE_editmesh.h"
#include "BKE_editmesh_cache.h" #include "BKE_editmesh_cache.h"
#include "BKE_editmesh_tangent.h" #include "BKE_editmesh_tangent.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_runtime.h" #include "BKE_mesh_runtime.h"
#include "BKE_mesh_tangent.h" #include "BKE_mesh_tangent.h"
#include "BKE_modifier.h" #include "BKE_modifier.h"

View File

@ -9,7 +9,7 @@
#include "BKE_attribute.hh" #include "BKE_attribute.hh"
#include "BKE_editmesh.h" #include "BKE_editmesh.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_mesh_mapping.h" #include "BKE_mesh_mapping.h"
#include "BKE_modifier.h" #include "BKE_modifier.h"
#include "BKE_object.h" #include "BKE_object.h"

View File

@ -15,7 +15,7 @@
#include "BKE_duplilist.h" #include "BKE_duplilist.h"
#include "BKE_global.h" #include "BKE_global.h"
#include "BKE_image.h" #include "BKE_image.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_object.h" #include "BKE_object.h"
#include "BKE_paint.h" #include "BKE_paint.h"
#include "BKE_pbvh.h" #include "BKE_pbvh.h"

View File

@ -15,7 +15,7 @@
#include "BKE_editmesh.h" #include "BKE_editmesh.h"
#include "BKE_editmesh_cache.h" #include "BKE_editmesh_cache.h"
#include "BKE_global.h" #include "BKE_global.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_unit.h" #include "BKE_unit.h"
#include "DNA_mesh_types.h" #include "DNA_mesh_types.h"

View File

@ -36,7 +36,7 @@
#include "BKE_attribute.h" #include "BKE_attribute.h"
#include "BKE_ccg.h" #include "BKE_ccg.h"
#include "BKE_customdata.h" #include "BKE_customdata.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_paint.h" #include "BKE_paint.h"
#include "BKE_pbvh.h" #include "BKE_pbvh.h"
#include "BKE_subdiv_ccg.h" #include "BKE_subdiv_ccg.h"
@ -345,9 +345,9 @@ struct PBVHBatches {
flat = sharp_faces && sharp_faces[tri->poly]; flat = sharp_faces && sharp_faces[tri->poly];
if (flat) { if (flat) {
const MPoly &poly = args->polys[tri->poly]; const MPoly &poly = args->polys[tri->poly];
float fno[3]; const float3 fno = blender::bke::mesh::poly_normal_calc(
BKE_mesh_calc_poly_normal( {reinterpret_cast<const float3 *>(args->vert_positions), args->mesh_verts_num},
&poly, args->mloop + poly.loopstart, args->vert_positions, fno); {&args->mloop[poly.loopstart], poly.totloop});
normal_float_to_short_v3(no, fno); normal_float_to_short_v3(no, fno);
} }
} }

View File

@ -15,7 +15,7 @@
#include "BKE_fluid.h" #include "BKE_fluid.h"
#include "BKE_global.h" #include "BKE_global.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_modifier.h" #include "BKE_modifier.h"
#include "BKE_volume.h" #include "BKE_volume.h"
#include "BKE_volume_render.h" #include "BKE_volume_render.h"

View File

@ -95,7 +95,7 @@ struct MeshRenderData {
const bool *select_edge; const bool *select_edge;
const bool *select_poly; const bool *select_poly;
const bool *sharp_faces; const bool *sharp_faces;
float (*loop_normals)[3]; blender::Array<blender::float3> loop_normals;
int *lverts, *ledges; int *lverts, *ledges;
const char *active_color_name; const char *active_color_name;

View File

@ -15,7 +15,7 @@
#include "BKE_attribute.h" #include "BKE_attribute.h"
#include "BKE_attribute.hh" #include "BKE_attribute.hh"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "draw_attributes.hh" #include "draw_attributes.hh"
#include "draw_subdivision.h" #include "draw_subdivision.h"

View File

@ -7,7 +7,7 @@
#include "MEM_guardedalloc.h" #include "MEM_guardedalloc.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BLI_math_vector_types.hh" #include "BLI_math_vector_types.hh"

View File

@ -9,7 +9,7 @@
#include "MEM_guardedalloc.h" #include "MEM_guardedalloc.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "extract_mesh.hh" #include "extract_mesh.hh"
@ -77,10 +77,8 @@ static void compute_area_ratio(const MeshRenderData *mr,
const float2 *uv_data = (const float2 *)CustomData_get_layer(&mr->me->ldata, CD_PROP_FLOAT2); const float2 *uv_data = (const float2 *)CustomData_get_layer(&mr->me->ldata, CD_PROP_FLOAT2);
for (int poly_index = 0; poly_index < mr->poly_len; poly_index++) { for (int poly_index = 0; poly_index < mr->poly_len; poly_index++) {
const MPoly &poly = mr->polys[poly_index]; const MPoly &poly = mr->polys[poly_index];
float area = BKE_mesh_calc_poly_area( const float area = bke::mesh::poly_area_calc(mr->vert_positions,
&poly, mr->loops.slice(poly.loopstart, poly.totloop));
&mr->loops[poly.loopstart],
reinterpret_cast<const float(*)[3]>(mr->vert_positions.data()));
float uvarea = area_poly_v2(reinterpret_cast<const float(*)[2]>(&uv_data[poly.loopstart]), float uvarea = area_poly_v2(reinterpret_cast<const float(*)[2]>(&uv_data[poly.loopstart]),
poly.totloop); poly.totloop);
tot_area += area; tot_area += area;

View File

@ -41,7 +41,7 @@ static void extract_lnor_iter_poly_bm(const MeshRenderData *mr,
l_iter = l_first = BM_FACE_FIRST_LOOP(f); l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do { do {
const int l_index = BM_elem_index_get(l_iter); const int l_index = BM_elem_index_get(l_iter);
if (mr->loop_normals) { if (!mr->loop_normals.is_empty()) {
(*(GPUPackedNormal **)data)[l_index] = GPU_normal_convert_i10_v3(mr->loop_normals[l_index]); (*(GPUPackedNormal **)data)[l_index] = GPU_normal_convert_i10_v3(mr->loop_normals[l_index]);
} }
else { else {
@ -68,7 +68,7 @@ static void extract_lnor_iter_poly_mesh(const MeshRenderData *mr,
for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) {
const MLoop *ml = &mr->loops[ml_index]; const MLoop *ml = &mr->loops[ml_index];
GPUPackedNormal *lnor_data = &(*(GPUPackedNormal **)data)[ml_index]; GPUPackedNormal *lnor_data = &(*(GPUPackedNormal **)data)[ml_index];
if (mr->loop_normals) { if (!mr->loop_normals.is_empty()) {
*lnor_data = GPU_normal_convert_i10_v3(mr->loop_normals[ml_index]); *lnor_data = GPU_normal_convert_i10_v3(mr->loop_normals[ml_index]);
} }
else if (mr->sharp_faces && mr->sharp_faces[poly_index]) { else if (mr->sharp_faces && mr->sharp_faces[poly_index]) {
@ -167,7 +167,7 @@ static void extract_lnor_hq_iter_poly_bm(const MeshRenderData *mr,
l_iter = l_first = BM_FACE_FIRST_LOOP(f); l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do { do {
const int l_index = BM_elem_index_get(l_iter); const int l_index = BM_elem_index_get(l_iter);
if (mr->loop_normals) { if (!mr->loop_normals.is_empty()) {
normal_float_to_short_v3(&(*(gpuHQNor **)data)[l_index].x, mr->loop_normals[l_index]); normal_float_to_short_v3(&(*(gpuHQNor **)data)[l_index].x, mr->loop_normals[l_index]);
} }
else { else {
@ -192,7 +192,7 @@ static void extract_lnor_hq_iter_poly_mesh(const MeshRenderData *mr,
for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) { for (int ml_index = poly->loopstart; ml_index < ml_index_end; ml_index += 1) {
const MLoop *ml = &mr->loops[ml_index]; const MLoop *ml = &mr->loops[ml_index];
gpuHQNor *lnor_data = &(*(gpuHQNor **)data)[ml_index]; gpuHQNor *lnor_data = &(*(gpuHQNor **)data)[ml_index];
if (mr->loop_normals) { if (!mr->loop_normals.is_empty()) {
normal_float_to_short_v3(&lnor_data->x, mr->loop_normals[ml_index]); normal_float_to_short_v3(&lnor_data->x, mr->loop_normals[ml_index]);
} }
else if (mr->sharp_faces && mr->sharp_faces[poly_index]) { else if (mr->sharp_faces && mr->sharp_faces[poly_index]) {

View File

@ -9,7 +9,7 @@
#include "BLI_string.h" #include "BLI_string.h"
#include "BKE_mesh.h" #include "BKE_mesh.hh"
#include "BKE_paint.h" #include "BKE_paint.h"
#include "draw_subdivision.h" #include "draw_subdivision.h"

Some files were not shown because too many files have changed in this diff Show More