Mesh: Reduce custom normal calculation memory usage #107592
|
@ -50,6 +50,35 @@ void poly_angles_calc(Span<float3> vert_positions,
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \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,
|
||||
OffsetIndices<int> polys,
|
||||
Span<int> corner_verts,
|
||||
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,
|
||||
OffsetIndices<int> polys,
|
||||
Span<int> corner_verts,
|
||||
MutableSpan<float3> poly_normals,
|
||||
MutableSpan<float3> vert_normals);
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Face Corner Normal Calculation
|
||||
* \{ */
|
||||
|
@ -60,20 +89,20 @@ void poly_angles_calc(Span<float3> vert_positions,
|
|||
* a regular #float3 format.
|
||||
*/
|
||||
struct NormalFanSpace {
|
||||
/** Reference vector, orthogonal to vec_lnor. */
|
||||
/** Reference vector, orthogonal to corner normal. */
|
||||
float3 vec_ref;
|
||||
/** Third vector, orthogonal to vec_lnor and vec_ref. */
|
||||
/** Third vector, orthogonal to corner normal and #vec_ref. */
|
||||
float3 vec_ortho;
|
||||
/** Reference angle, around vec_ortho, in [0, pi] range (0.0 marks that space as invalid). */
|
||||
/** Reference angle around #vec_ortho, in [0, pi] range (0.0 marks space as invalid). */
|
||||
float ref_alpha;
|
||||
/** Reference angle, around vec_lnor, in [0, 2pi] range (0.0 marks that space as invalid). */
|
||||
/** Reference angle around corner normal, in [0, 2pi] range (0.0 marks space as invalid). */
|
||||
float ref_beta;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
* Storage for coordinate spaces and connection information during normal calculation.
|
||||
*/
|
||||
struct MeshNormalFanSpaces {
|
||||
struct NormalFanSpaces {
|
||||
Campbell Barton
commented
The names The names `NormalFanSpaces` & `NormalFanSpace` are too similar, the old suffix "Array" wasn't exactly accurate either (as it's not just an array) but at least it was easily distinguishable.
|
||||
/**
|
||||
* The normal coordinate spaces, potentially shared between multiple face corners in a smooth fan
|
||||
* connected to a vertex. Depending on the mesh (the amount of sharing / number of sharp edges /
|
||||
|
@ -115,38 +144,9 @@ void normals_calc_loop(Span<float3> vert_positions,
|
|||
bool use_split_normals,
|
||||
float split_angle,
|
||||
short2 *clnors_data,
|
||||
MeshNormalFanSpaces *r_lnors_spacearr,
|
||||
NormalFanSpaces *r_lnors_spacearr,
|
||||
MutableSpan<float3> r_loop_normals);
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \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,
|
||||
OffsetIndices<int> polys,
|
||||
Span<int> corner_verts,
|
||||
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,
|
||||
OffsetIndices<int> polys,
|
||||
Span<int> corner_verts,
|
||||
MutableSpan<float3> poly_normals,
|
||||
MutableSpan<float3> vert_normals);
|
||||
|
||||
void normals_loop_custom_set(Span<float3> vert_positions,
|
||||
Span<int2> edges,
|
||||
OffsetIndices<int> polys,
|
||||
|
|
|
@ -390,7 +390,7 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
|
|||
CustomData *ldata = &result->ldata;
|
||||
blender::short2 *clnors = static_cast<blender::short2 *>(
|
||||
CustomData_get_layer_for_write(ldata, CD_CUSTOMLOOPNORMAL, result->totloop));
|
||||
blender::bke::mesh::MeshNormalFanSpaces lnors_spacearr;
|
||||
blender::bke::mesh::NormalFanSpaces lnors_spacearr;
|
||||
|
||||
/* The transform matrix of a normal must be
|
||||
* the transpose of inverse of transform matrix of the geometry... */
|
||||
|
|
|
@ -709,7 +709,7 @@ struct LoopSplitTaskDataCommon {
|
|||
/* Read/write.
|
||||
* Note we do not need to protect it, though, since two different tasks will *always* affect
|
||||
* different elements in the arrays. */
|
||||
MeshNormalFanSpaces *lnors_spacearr;
|
||||
NormalFanSpaces *lnors_spacearr;
|
||||
MutableSpan<float3> loop_normals;
|
||||
MutableSpan<short2> clnors_data;
|
||||
|
||||
|
@ -889,7 +889,7 @@ static void lnor_space_for_single_fan(LoopSplitTaskDataCommon *common_data,
|
|||
|
||||
loop_normals[ml_curr_index] = poly_normals[loop_to_poly[ml_curr_index]];
|
||||
|
||||
if (MeshNormalFanSpaces *lnors_spacearr = common_data->lnors_spacearr) {
|
||||
if (NormalFanSpaces *lnors_spacearr = common_data->lnors_spacearr) {
|
||||
const Span<float3> positions = common_data->positions;
|
||||
const Span<int2> edges = common_data->edges;
|
||||
const OffsetIndices polys = common_data->polys;
|
||||
|
@ -930,7 +930,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data,
|
|||
const int space_index,
|
||||
Vector<float3> *edge_vectors)
|
||||
{
|
||||
MeshNormalFanSpaces *lnors_spacearr = common_data->lnors_spacearr;
|
||||
NormalFanSpaces *lnors_spacearr = common_data->lnors_spacearr;
|
||||
MutableSpan<float3> loop_normals = common_data->loop_normals;
|
||||
MutableSpan<short2> clnors_data = common_data->clnors_data;
|
||||
|
||||
|
@ -1270,7 +1270,7 @@ void normals_calc_loop(const Span<float3> vert_positions,
|
|||
bool use_split_normals,
|
||||
float split_angle,
|
||||
short2 *clnors_data,
|
||||
MeshNormalFanSpaces *r_lnors_spacearr,
|
||||
NormalFanSpaces *r_lnors_spacearr,
|
||||
MutableSpan<float3> r_loop_normals)
|
||||
{
|
||||
/* For now this is not supported.
|
||||
|
@ -1328,7 +1328,7 @@ void normals_calc_loop(const Span<float3> vert_positions,
|
|||
/* When using custom loop normals, disable the angle feature! */
|
||||
const bool check_angle = (split_angle < float(M_PI)) && (clnors_data == nullptr);
|
||||
|
||||
MeshNormalFanSpaces _lnors_spacearr;
|
||||
NormalFanSpaces _lnors_spacearr;
|
||||
|
||||
#ifdef DEBUG_TIME
|
||||
SCOPED_TIMER_AVERAGED(__func__);
|
||||
|
@ -1457,7 +1457,7 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
|
|||
* function *is not* performance-critical, since it is mostly expected to be called 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_calc_loop() twice! */
|
||||
MeshNormalFanSpaces lnors_spacearr;
|
||||
NormalFanSpaces lnors_spacearr;
|
||||
BitVector<> done_loops(corner_verts.size(), false);
|
||||
Array<float3> loop_normals(corner_verts.size());
|
||||
const Array<int> loop_to_poly = mesh_topology::build_loop_to_poly_map(polys);
|
||||
|
|
|
@ -205,7 +205,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd,
|
|||
|
||||
const bool has_clnors = wn_data->has_clnors;
|
||||
const float split_angle = wn_data->split_angle;
|
||||
bke::mesh::MeshNormalFanSpaces lnors_spacearr;
|
||||
bke::mesh::NormalFanSpaces lnors_spacearr;
|
||||
|
||||
const bool keep_sharp = (wnmd->flag & MOD_WEIGHTEDNORMAL_KEEP_SHARP) != 0;
|
||||
const bool use_face_influence = (wnmd->flag & MOD_WEIGHTEDNORMAL_FACE_INFLUENCE) != 0 &&
|
||||
|
|
Loading…
Reference in New Issue
Worth mentioning some things that might seem obvious, that this stores normal data for an entire mesh.