Mesh: Reduce custom normal calculation memory usage #107592
|
@ -92,9 +92,10 @@ struct MeshNormalFanSpaces {
|
|||
Array<int> corner_group_lists;
|
||||
};
|
||||
|
||||
short2 fan_space_custom_normal_to_data(const NormalFanSpace *space,
|
||||
float3 corner_normal_no_custom,
|
||||
float3 custom_lnor);
|
||||
void fan_space_custom_normal_to_data(const NormalFanSpace *lnor_space,
|
||||
const float3 lnor_no_custom,
|
||||
const float custom_lnor[3],
|
||||
short r_clnor_data[2]);
|
||||
|
||||
/**
|
||||
* Compute split normals, i.e. vertex normals associated with each poly (hence 'loop normals').
|
||||
|
@ -104,8 +105,8 @@ short2 fan_space_custom_normal_to_data(const NormalFanSpace *space,
|
|||
* \param loop_to_poly_map: Optional pre-created map from corners to their polygon.
|
||||
|
||||
* \param sharp_edges: Optional array of sharp edge tags, used to split the evaluated normals on
|
||||
* each side of the edge.
|
||||
* \param r_lnors_spacearr: Optional return data filled with information about the custom normals
|
||||
* spaces for each grouped fan of face corners.
|
||||
* \param r_lnors_spacearr: Optional return data filled with information about the custom
|
||||
* normals spaces for each grouped fan of face corners.
|
||||
*/
|
||||
void normals_calc_loop(Span<float3> vert_positions,
|
||||
Span<int2> edges,
|
||||
Campbell Barton
commented
Worth mentioning this array isn't aligned to geometry and must be accessed via Worth mentioning this array isn't aligned to geometry and must be accessed via `corner_space_indices`.
|
||||
|
|
|
@ -432,10 +432,10 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
|
|||
mul_m4_v3(mtx_nor, loop_normals[mirrorj]);
|
||||
|
||||
const int space_index = lnors_spacearr.corner_space_indices[mirrorj];
|
||||
const blender::bke::mesh::NormalFanSpace &space = lnors_spacearr.spaces[space_index];
|
||||
|
||||
clnors[mirrorj] = blender::bke::mesh::fan_space_custom_normal_to_data(
|
||||
&space, loop_normals[mirrorj], loop_normals[mirrorj]);
|
||||
blender::bke::mesh::fan_space_custom_normal_to_data(&lnors_spacearr.spaces[space_index],
|
||||
loop_normals[mirrorj],
|
||||
loop_normals[mirrorj],
|
||||
clnors[mirrorj]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -468,12 +468,12 @@ MLoopNorSpace *BKE_lnor_space_create(MLoopNorSpaceArray *lnors_spacearr)
|
|||
#define LNOR_SPACE_TRIGO_THRESHOLD (1.0f - 1e-4f)
|
||||
|
||||
namespace blender::bke::mesh {
|
||||
static NormalFanSpace normal_fan_space_define(const float lnor[3],
|
||||
float vec_ref[3],
|
||||
float vec_other[3],
|
||||
const Span<float3> edge_vectors)
|
||||
static void normal_fan_space_define(NormalFanSpace *lnor_space,
|
||||
const float lnor[3],
|
||||
float vec_ref[3],
|
||||
float vec_other[3],
|
||||
const blender::Span<blender::float3> edge_vectors)
|
||||
{
|
||||
NormalFanSpace lnor_space{};
|
||||
const float pi2 = float(M_PI) * 2.0f;
|
||||
float tvec[3], dtp;
|
||||
const float dtp_ref = dot_v3v3(vec_ref, lnor);
|
||||
|
@ -483,14 +483,14 @@ static NormalFanSpace normal_fan_space_define(const float lnor[3],
|
|||
fabsf(dtp_other) >= LNOR_SPACE_TRIGO_THRESHOLD)) {
|
||||
/* If vec_ref or vec_other are too much aligned with lnor, we can't build lnor space,
|
||||
* tag it as invalid and abort. */
|
||||
lnor_space.ref_alpha = lnor_space.ref_beta = 0.0f;
|
||||
return lnor_space;
|
||||
lnor_space->ref_alpha = lnor_space->ref_beta = 0.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Compute ref alpha, average angle of all available edge vectors to lnor. */
|
||||
if (!edge_vectors.is_empty()) {
|
||||
float alpha = 0.0f;
|
||||
for (const float3 &vec : edge_vectors) {
|
||||
for (const blender::float3 &vec : edge_vectors) {
|
||||
alpha += saacosf(dot_v3v3(vec, lnor));
|
||||
}
|
||||
/* This piece of code shall only be called for more than one loop. */
|
||||
|
@ -499,21 +499,21 @@ static NormalFanSpace normal_fan_space_define(const float lnor[3],
|
|||
* a smooth vertex with only two edges and two faces (our Monkey's nose has that, e.g.).
|
||||
*/
|
||||
BLI_assert(edge_vectors.size() >= 2);
|
||||
lnor_space.ref_alpha = alpha / float(edge_vectors.size());
|
||||
lnor_space->ref_alpha = alpha / float(edge_vectors.size());
|
||||
}
|
||||
else {
|
||||
lnor_space.ref_alpha = (saacosf(dot_v3v3(vec_ref, lnor)) +
|
||||
saacosf(dot_v3v3(vec_other, lnor))) /
|
||||
2.0f;
|
||||
lnor_space->ref_alpha = (saacosf(dot_v3v3(vec_ref, lnor)) +
|
||||
saacosf(dot_v3v3(vec_other, lnor))) /
|
||||
2.0f;
|
||||
}
|
||||
|
||||
/* Project vec_ref on lnor's ortho plane. */
|
||||
mul_v3_v3fl(tvec, lnor, dtp_ref);
|
||||
sub_v3_v3(vec_ref, tvec);
|
||||
normalize_v3_v3(lnor_space.vec_ref, vec_ref);
|
||||
normalize_v3_v3(lnor_space->vec_ref, vec_ref);
|
||||
|
||||
cross_v3_v3v3(tvec, lnor, lnor_space.vec_ref);
|
||||
normalize_v3_v3(lnor_space.vec_ortho, tvec);
|
||||
cross_v3_v3v3(tvec, lnor, lnor_space->vec_ref);
|
||||
normalize_v3_v3(lnor_space->vec_ortho, tvec);
|
||||
|
||||
/* Project vec_other on lnor's ortho plane. */
|
||||
mul_v3_v3fl(tvec, lnor, dtp_other);
|
||||
|
@ -521,16 +521,14 @@ static NormalFanSpace normal_fan_space_define(const float lnor[3],
|
|||
normalize_v3(vec_other);
|
||||
|
||||
/* Beta is angle between ref_vec and other_vec, around lnor. */
|
||||
dtp = dot_v3v3(lnor_space.vec_ref, vec_other);
|
||||
dtp = dot_v3v3(lnor_space->vec_ref, vec_other);
|
||||
if (LIKELY(dtp < LNOR_SPACE_TRIGO_THRESHOLD)) {
|
||||
const float beta = saacos(dtp);
|
||||
lnor_space.ref_beta = (dot_v3v3(lnor_space.vec_ortho, vec_other) < 0.0f) ? pi2 - beta : beta;
|
||||
lnor_space->ref_beta = (dot_v3v3(lnor_space->vec_ortho, vec_other) < 0.0f) ? pi2 - beta : beta;
|
||||
}
|
||||
else {
|
||||
lnor_space.ref_beta = pi2;
|
||||
lnor_space->ref_beta = pi2;
|
||||
}
|
||||
|
||||
return lnor_space;
|
||||
}
|
||||
} // namespace blender::bke::mesh
|
||||
|
||||
|
@ -541,7 +539,8 @@ void BKE_lnor_space_define(MLoopNorSpace *lnor_space,
|
|||
const blender::Span<blender::float3> edge_vectors)
|
||||
{
|
||||
using namespace blender::bke::mesh;
|
||||
const NormalFanSpace space = normal_fan_space_define(lnor, vec_ref, vec_other, edge_vectors);
|
||||
NormalFanSpace space{};
|
||||
normal_fan_space_define(&space, lnor, vec_ref, vec_other, edge_vectors);
|
||||
copy_v3_v3(lnor_space->vec_lnor, lnor);
|
||||
copy_v3_v3(lnor_space->vec_ref, space.vec_ref);
|
||||
copy_v3_v3(lnor_space->vec_ortho, space.vec_ortho);
|
||||
|
@ -549,16 +548,6 @@ void BKE_lnor_space_define(MLoopNorSpace *lnor_space,
|
|||
lnor_space->ref_beta = space.ref_beta;
|
||||
}
|
||||
|
||||
namespace blender::bke::mesh {
|
||||
static void fan_space_add_corners(MeshNormalFanSpaces &fan_spaces, const Span<int> corners)
|
||||
{
|
||||
for (const int i : corners.index_range().drop_back(1)) {
|
||||
fan_spaces.corner_group_lists[corners[i]] = corners[i + 1];
|
||||
}
|
||||
fan_spaces.corner_group_lists[corners.last()] = -1;
|
||||
}
|
||||
} // namespace blender::bke::mesh
|
||||
|
||||
void BKE_lnor_space_add_loop(MLoopNorSpaceArray *lnors_spacearr,
|
||||
MLoopNorSpace *lnor_space,
|
||||
const int ml_index,
|
||||
|
@ -595,41 +584,40 @@ MINLINE short unit_float_to_short(const float val)
|
|||
}
|
||||
|
||||
namespace blender::bke::mesh {
|
||||
static float3 fan_space_custom_data_to_normal(const NormalFanSpace *lnor_space,
|
||||
const float3 lnor_no_custom,
|
||||
const short2 clnor_data)
|
||||
static void fan_space_custom_data_to_normal(const NormalFanSpace *lnor_space,
|
||||
const float3 lnor_no_custom,
|
||||
Campbell Barton
commented
Prefer old name (can remove the BKE prefix). Prefer old name (can remove the BKE prefix).
|
||||
const short clnor_data[2],
|
||||
float r_custom_lnor[3])
|
||||
{
|
||||
/* NOP custom normal data or invalid lnor space, return. */
|
||||
if (clnor_data[0] == 0 || lnor_space->ref_alpha == 0.0f || lnor_space->ref_beta == 0.0f) {
|
||||
return lnor_no_custom;
|
||||
copy_v3_v3(r_custom_lnor, lnor_no_custom);
|
||||
return;
|
||||
}
|
||||
|
||||
float3 r_custom_lnor(0.0f);
|
||||
{
|
||||
/* TODO: Check whether using #sincosf() gives any noticeable benefit
|
||||
* (could not even get it working under linux though)! */
|
||||
const float pi2 = float(M_PI * 2.0);
|
||||
const float alphafac = unit_short_to_float(clnor_data[0]);
|
||||
const float alpha = (alphafac > 0.0f ? lnor_space->ref_alpha : pi2 - lnor_space->ref_alpha) *
|
||||
alphafac;
|
||||
const float betafac = unit_short_to_float(clnor_data[1]);
|
||||
|
||||
/* TODO: Check whether using #sincosf() gives any noticeable benefit
|
||||
* (could not even get it working under linux though)! */
|
||||
const float pi2 = float(M_PI * 2.0);
|
||||
const float alphafac = unit_short_to_float(clnor_data[0]);
|
||||
const float alpha = (alphafac > 0.0f ? lnor_space->ref_alpha : pi2 - lnor_space->ref_alpha) *
|
||||
alphafac;
|
||||
const float betafac = unit_short_to_float(clnor_data[1]);
|
||||
mul_v3_v3fl(r_custom_lnor, lnor_no_custom, cosf(alpha));
|
||||
|
||||
mul_v3_v3fl(r_custom_lnor, lnor_no_custom, cosf(alpha));
|
||||
|
||||
if (betafac == 0.0f) {
|
||||
madd_v3_v3fl(r_custom_lnor, lnor_space->vec_ref, sinf(alpha));
|
||||
if (betafac == 0.0f) {
|
||||
madd_v3_v3fl(r_custom_lnor, lnor_space->vec_ref, sinf(alpha));
|
||||
}
|
||||
else {
|
||||
const float sinalpha = sinf(alpha);
|
||||
const float beta = (betafac > 0.0f ? lnor_space->ref_beta : pi2 - lnor_space->ref_beta) *
|
||||
betafac;
|
||||
madd_v3_v3fl(r_custom_lnor, lnor_space->vec_ref, sinalpha * cosf(beta));
|
||||
madd_v3_v3fl(r_custom_lnor, lnor_space->vec_ortho, sinalpha * sinf(beta));
|
||||
}
|
||||
}
|
||||
else {
|
||||
const float sinalpha = sinf(alpha);
|
||||
const float beta = (betafac > 0.0f ? lnor_space->ref_beta : pi2 - lnor_space->ref_beta) *
|
||||
betafac;
|
||||
madd_v3_v3fl(r_custom_lnor, lnor_space->vec_ref, sinalpha * cosf(beta));
|
||||
madd_v3_v3fl(r_custom_lnor, lnor_space->vec_ortho, sinalpha * sinf(beta));
|
||||
}
|
||||
|
||||
return r_custom_lnor;
|
||||
}
|
||||
|
||||
} // namespace blender::bke::mesh
|
||||
|
||||
void BKE_lnor_space_custom_data_to_normal(const MLoopNorSpace *lnor_space,
|
||||
|
@ -642,63 +630,62 @@ void BKE_lnor_space_custom_data_to_normal(const MLoopNorSpace *lnor_space,
|
|||
space.vec_ortho = lnor_space->vec_ortho;
|
||||
space.ref_alpha = lnor_space->ref_alpha;
|
||||
space.ref_beta = lnor_space->ref_beta;
|
||||
copy_v3_v3(r_custom_lnor,
|
||||
fan_space_custom_data_to_normal(&space, lnor_space->vec_lnor, clnor_data));
|
||||
fan_space_custom_data_to_normal(&space, lnor_space->vec_lnor, clnor_data, r_custom_lnor);
|
||||
}
|
||||
|
||||
namespace blender::bke::mesh {
|
||||
short2 fan_space_custom_normal_to_data(const NormalFanSpace *lnor_space,
|
||||
const float3 lnor_no_custom,
|
||||
const float3 custom_lnor)
|
||||
void fan_space_custom_normal_to_data(const NormalFanSpace *lnor_space,
|
||||
const float3 lnor_no_custom,
|
||||
const float custom_lnor[3],
|
||||
short r_clnor_data[2])
|
||||
{
|
||||
/* We use nullptr vector as NOP custom normal (can be simpler than giving auto-computed `lnor`).
|
||||
*/
|
||||
if (is_zero_v3(custom_lnor) || compare_v3v3(lnor_no_custom, custom_lnor, 1e-4f)) {
|
||||
return short2(0, 0);
|
||||
r_clnor_data[0] = r_clnor_data[1] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
const float pi2 = float(M_PI * 2.0);
|
||||
const float cos_alpha = dot_v3v3(lnor_no_custom, custom_lnor);
|
||||
float vec[3], cos_beta;
|
||||
float alpha;
|
||||
{
|
||||
const float pi2 = float(M_PI * 2.0);
|
||||
const float cos_alpha = dot_v3v3(lnor_no_custom, custom_lnor);
|
||||
float vec[3], cos_beta;
|
||||
float alpha;
|
||||
|
||||
short2 r_clnor_data;
|
||||
|
||||
alpha = saacosf(cos_alpha);
|
||||
if (alpha > lnor_space->ref_alpha) {
|
||||
/* Note we could stick to [0, pi] range here,
|
||||
* but makes decoding more complex, not worth it. */
|
||||
r_clnor_data[0] = unit_float_to_short(-(pi2 - alpha) / (pi2 - lnor_space->ref_alpha));
|
||||
}
|
||||
else {
|
||||
r_clnor_data[0] = unit_float_to_short(alpha / lnor_space->ref_alpha);
|
||||
}
|
||||
|
||||
/* Project custom lnor on (vec_ref, vec_ortho) plane. */
|
||||
mul_v3_v3fl(vec, lnor_no_custom, -cos_alpha);
|
||||
add_v3_v3(vec, custom_lnor);
|
||||
normalize_v3(vec);
|
||||
|
||||
cos_beta = dot_v3v3(lnor_space->vec_ref, vec);
|
||||
|
||||
if (cos_beta < LNOR_SPACE_TRIGO_THRESHOLD) {
|
||||
float beta = saacosf(cos_beta);
|
||||
if (dot_v3v3(lnor_space->vec_ortho, vec) < 0.0f) {
|
||||
beta = pi2 - beta;
|
||||
}
|
||||
|
||||
if (beta > lnor_space->ref_beta) {
|
||||
r_clnor_data[1] = unit_float_to_short(-(pi2 - beta) / (pi2 - lnor_space->ref_beta));
|
||||
alpha = saacosf(cos_alpha);
|
||||
if (alpha > lnor_space->ref_alpha) {
|
||||
/* Note we could stick to [0, pi] range here,
|
||||
* but makes decoding more complex, not worth it. */
|
||||
r_clnor_data[0] = unit_float_to_short(-(pi2 - alpha) / (pi2 - lnor_space->ref_alpha));
|
||||
}
|
||||
else {
|
||||
r_clnor_data[1] = unit_float_to_short(beta / lnor_space->ref_beta);
|
||||
r_clnor_data[0] = unit_float_to_short(alpha / lnor_space->ref_alpha);
|
||||
}
|
||||
|
||||
/* Project custom lnor on (vec_ref, vec_ortho) plane. */
|
||||
mul_v3_v3fl(vec, lnor_no_custom, -cos_alpha);
|
||||
add_v3_v3(vec, custom_lnor);
|
||||
normalize_v3(vec);
|
||||
|
||||
cos_beta = dot_v3v3(lnor_space->vec_ref, vec);
|
||||
|
||||
if (cos_beta < LNOR_SPACE_TRIGO_THRESHOLD) {
|
||||
float beta = saacosf(cos_beta);
|
||||
if (dot_v3v3(lnor_space->vec_ortho, vec) < 0.0f) {
|
||||
beta = pi2 - beta;
|
||||
}
|
||||
|
||||
if (beta > lnor_space->ref_beta) {
|
||||
r_clnor_data[1] = unit_float_to_short(-(pi2 - beta) / (pi2 - lnor_space->ref_beta));
|
||||
}
|
||||
else {
|
||||
r_clnor_data[1] = unit_float_to_short(beta / lnor_space->ref_beta);
|
||||
}
|
||||
}
|
||||
else {
|
||||
r_clnor_data[1] = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
r_clnor_data[1] = 0;
|
||||
}
|
||||
|
||||
return r_clnor_data;
|
||||
}
|
||||
} // namespace blender::bke::mesh
|
||||
|
||||
|
@ -712,8 +699,7 @@ void BKE_lnor_space_custom_normal_to_data(const MLoopNorSpace *lnor_space,
|
|||
space.vec_ortho = lnor_space->vec_ortho;
|
||||
space.ref_alpha = lnor_space->ref_alpha;
|
||||
space.ref_beta = lnor_space->ref_beta;
|
||||
copy_v2_v2_short(r_clnor_data,
|
||||
fan_space_custom_normal_to_data(&space, lnor_space->vec_lnor, custom_lnor));
|
||||
fan_space_custom_normal_to_data(&space, lnor_space->vec_lnor, custom_lnor, r_clnor_data);
|
||||
}
|
||||
|
||||
namespace blender::bke::mesh {
|
||||
|
@ -890,9 +876,20 @@ static void loop_manifold_fan_around_vert_next(const Span<int> corner_verts,
|
|||
}
|
||||
}
|
||||
|
||||
static void fan_space_add_corners(MeshNormalFanSpaces &fan_spaces,
|
||||
const Span<int> corners,
|
||||
const int space_index)
|
||||
{
|
||||
for (const int i : corners.index_range().drop_back(1)) {
|
||||
fan_spaces.corner_group_lists[corners[i]] = corners[i + 1];
|
||||
}
|
||||
fan_spaces.corner_group_lists[corners.last()] = -1;
|
||||
fan_spaces.corner_space_indices.as_mutable_span().fill_indices(corners, space_index);
|
||||
}
|
||||
|
||||
static void lnor_space_for_single_fan(LoopSplitTaskDataCommon *common_data,
|
||||
const int ml_curr_index,
|
||||
NormalFanSpace *lnor_space)
|
||||
const int space_index)
|
||||
{
|
||||
const Span<int> loop_to_poly = common_data->loop_to_poly;
|
||||
const Span<float3> poly_normals = common_data->poly_normals;
|
||||
|
@ -900,7 +897,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 (lnor_space) {
|
||||
if (MeshNormalFanSpaces *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;
|
||||
|
@ -922,20 +919,23 @@ static void lnor_space_for_single_fan(LoopSplitTaskDataCommon *common_data,
|
|||
sub_v3_v3v3(vec_prev, positions[vert_3], positions[vert_pivot]);
|
||||
normalize_v3(vec_prev);
|
||||
|
||||
*lnor_space = normal_fan_space_define(loop_normals[ml_curr_index], vec_curr, vec_prev, {});
|
||||
NormalFanSpace *lnor_space = &lnors_spacearr->spaces[space_index];
|
||||
normal_fan_space_define(lnor_space, loop_normals[ml_curr_index], vec_curr, vec_prev, {});
|
||||
/* We know there is only one loop in this space, no need to create a link-list in this case. */
|
||||
fan_space_add_corners(*lnors_spacearr, {ml_curr_index}, space_index);
|
||||
|
||||
if (!clnors_data.is_empty()) {
|
||||
loop_normals[ml_curr_index] = fan_space_custom_data_to_normal(
|
||||
lnor_space, loop_normals[ml_curr_index], clnors_data[ml_curr_index]);
|
||||
fan_space_custom_data_to_normal(lnor_space,
|
||||
loop_normals[ml_curr_index],
|
||||
clnors_data[ml_curr_index],
|
||||
loop_normals[ml_curr_index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data,
|
||||
const int ml_curr_index,
|
||||
Vector<int, 8> &processed_corners,
|
||||
NormalFanSpace *lnor_space,
|
||||
const int space_index,
|
||||
Vector<float3> *edge_vectors)
|
||||
{
|
||||
MeshNormalFanSpaces *lnors_spacearr = common_data->lnors_spacearr;
|
||||
|
@ -974,6 +974,8 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data,
|
|||
int clnors_count = 0;
|
||||
bool clnors_invalid = false;
|
||||
|
||||
Vector<int, 8> processed_corners;
|
||||
|
||||
/* `mlfan_vert_index` the loop of our current edge might not be the loop of our current vertex!
|
||||
*/
|
||||
int mlfan_curr_index = ml_prev_index;
|
||||
|
@ -1071,15 +1073,15 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data,
|
|||
* and optionally compute final lnor from custom data too!
|
||||
*/
|
||||
if (lnors_spacearr) {
|
||||
processed_corners.as_mutable_span().reverse();
|
||||
fan_space_add_corners(*lnors_spacearr, processed_corners);
|
||||
fan_space_add_corners(*lnors_spacearr, processed_corners, space_index);
|
||||
if (UNLIKELY(lnor_len == 0.0f)) {
|
||||
/* Use vertex normal as fallback! */
|
||||
copy_v3_v3(lnor, loop_normals[mlfan_vert_index]);
|
||||
lnor_len = 1.0f;
|
||||
}
|
||||
|
||||
*lnor_space = normal_fan_space_define(lnor, vec_org, vec_curr, *edge_vectors);
|
||||
NormalFanSpace *lnor_space = &lnors_spacearr->spaces[space_index];
|
||||
normal_fan_space_define(lnor_space, lnor, vec_org, vec_curr, *edge_vectors);
|
||||
edge_vectors->clear();
|
||||
|
||||
if (!clnors_data.is_empty()) {
|
||||
|
@ -1097,7 +1099,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data,
|
|||
/* Extra bonus: since small-stack is local to this function,
|
||||
* no more need to empty it at all cost! */
|
||||
|
||||
lnor = fan_space_custom_data_to_normal(lnor_space, lnor, *clnor_ref);
|
||||
fan_space_custom_data_to_normal(lnor_space, lnor, *clnor_ref, lnor);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1388,31 +1390,16 @@ void normals_calc_loop(const Span<float3> vert_positions,
|
|||
threading::parallel_for(single_corners.index_range(), 1024, [&](const IndexRange range) {
|
||||
for (const int i : range) {
|
||||
const int corner = single_corners[i];
|
||||
lnor_space_for_single_fan(
|
||||
&common_data, corner, r_lnors_spacearr ? &r_lnors_spacearr->spaces[i] : nullptr);
|
||||
if (r_lnors_spacearr) {
|
||||
r_lnors_spacearr->corner_space_indices[corner] = i;
|
||||
r_lnors_spacearr->corner_group_lists[corner] = -1;
|
||||
}
|
||||
lnor_space_for_single_fan(&common_data, corner, i);
|
||||
}
|
||||
});
|
||||
|
||||
threading::parallel_for(fan_corners.index_range(), 1024, [&](const IndexRange range) {
|
||||
Vector<int, 8> processed_corners;
|
||||
Vector<float3> edge_vectors;
|
||||
for (const int i : range) {
|
||||
const int corner = fan_corners[i];
|
||||
const int space_index = single_corners.size() + i;
|
||||
split_loop_nor_fan_do(&common_data,
|
||||
corner,
|
||||
processed_corners,
|
||||
r_lnors_spacearr ? &r_lnors_spacearr->spaces[space_index] : nullptr,
|
||||
&edge_vectors);
|
||||
if (r_lnors_spacearr) {
|
||||
r_lnors_spacearr->corner_space_indices.as_mutable_span().fill_indices(
|
||||
processed_corners.as_span(), space_index);
|
||||
}
|
||||
processed_corners.clear();
|
||||
split_loop_nor_fan_do(&common_data, corner, space_index, &edge_vectors);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1539,8 +1526,8 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
|
|||
* - In smooth fan case, we compare each clnor against a ref one,
|
||||
* to avoid small differences adding up into a real big one in the end!
|
||||
*/
|
||||
int corner_link = lnors_spacearr.corner_group_lists[i];
|
||||
if (corner_link == -1) {
|
||||
int loop_link = lnors_spacearr.corner_group_lists[i];
|
||||
if (loop_link == -1) {
|
||||
done_loops[i].set();
|
||||
continue;
|
||||
}
|
||||
|
@ -1548,8 +1535,8 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
|
|||
int prev_corner = -1;
|
||||
const float *org_nor = nullptr;
|
||||
|
||||
while (corner_link != -1) {
|
||||
const int lidx = corner_link;
|
||||
while (loop_link != -1) {
|
||||
const int lidx = loop_link;
|
||||
float *nor = r_custom_loop_normals[lidx];
|
||||
|
||||
if (!org_nor) {
|
||||
|
@ -1571,7 +1558,7 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
|
|||
}
|
||||
|
||||
prev_corner = lidx;
|
||||
corner_link = lnors_spacearr.corner_group_lists[corner_link];
|
||||
loop_link = lnors_spacearr.corner_group_lists[loop_link];
|
||||
done_loops[lidx].set();
|
||||
}
|
||||
|
||||
|
@ -1579,9 +1566,9 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
|
|||
* otherwise we may miss some sharp edges here!
|
||||
* This is just a simplified version of above while loop.
|
||||
* See #45984. */
|
||||
corner_link = lnors_spacearr.corner_group_lists[i];
|
||||
if (corner_link != -1 && org_nor) {
|
||||
const int lidx = corner_link;
|
||||
loop_link = lnors_spacearr.corner_group_lists[i];
|
||||
if (loop_link != -1 && org_nor) {
|
||||
const int lidx = loop_link;
|
||||
float *nor = r_custom_loop_normals[lidx];
|
||||
|
||||
if (dot_v3v3(org_nor, nor) < LNOR_SPACE_TRIGO_THRESHOLD) {
|
||||
|
@ -1632,21 +1619,21 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
|
|||
/* Note we accumulate and average all custom normals in current smooth fan,
|
||||
Campbell Barton
commented
These names read as generic face-corner information when they are quite spesific and only useful when used together. That these values are referenced by the space index would make this clearer, e.g. These names read as generic face-corner information when they are quite spesific and only useful when used together.
That these values are referenced by the space index would make this clearer, e.g.
`fan_corners_from_space_data`
`fan_corners_from_space_offset_indices`
|
||||
* to avoid getting different clnors data (tiny differences in plain custom normals can
|
||||
* give rather huge differences in computed 2D factors). */
|
||||
int corner_link = lnors_spacearr.corner_group_lists[i];
|
||||
if (corner_link == -1) {
|
||||
int loop_link = lnors_spacearr.corner_group_lists[i];
|
||||
if (loop_link == -1) {
|
||||
const int nidx = use_vertices ? corner_verts[i] : i;
|
||||
float *nor = r_custom_loop_normals[nidx];
|
||||
|
||||
const int space_index = lnors_spacearr.corner_space_indices[i];
|
||||
r_clnors_data[i] = fan_space_custom_normal_to_data(
|
||||
&lnors_spacearr.spaces[space_index], loop_normals[i], nor);
|
||||
fan_space_custom_normal_to_data(
|
||||
&lnors_spacearr.spaces[space_index], loop_normals[i], nor, r_clnors_data[i]);
|
||||
done_loops[i].reset();
|
||||
}
|
||||
else {
|
||||
int avg_nor_count = 0;
|
||||
float3 avg_nor(0.0f);
|
||||
while (corner_link != -1) {
|
||||
const int lidx = corner_link;
|
||||
while (loop_link != -1) {
|
||||
const int lidx = loop_link;
|
||||
const int nidx = use_vertices ? corner_verts[lidx] : lidx;
|
||||
float *nor = r_custom_loop_normals[nidx];
|
||||
|
||||
|
@ -1654,14 +1641,15 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
|
|||
add_v3_v3(avg_nor, nor);
|
||||
processed_corners.append(lidx);
|
||||
|
||||
corner_link = lnors_spacearr.corner_group_lists[corner_link];
|
||||
loop_link = lnors_spacearr.corner_group_lists[loop_link];
|
||||
done_loops[lidx].reset();
|
||||
}
|
||||
|
||||
mul_v3_fl(avg_nor, 1.0f / float(avg_nor_count));
|
||||
short2 clnor_data_tmp;
|
||||
const int space_index = lnors_spacearr.corner_space_indices[i];
|
||||
const short2 clnor_data_tmp = fan_space_custom_normal_to_data(
|
||||
&lnors_spacearr.spaces[space_index], loop_normals[i], avg_nor);
|
||||
fan_space_custom_normal_to_data(
|
||||
&lnors_spacearr.spaces[space_index], loop_normals[i], avg_nor, clnor_data_tmp);
|
||||
|
||||
r_clnors_data.fill_indices(processed_corners.as_span(), clnor_data_tmp);
|
||||
processed_corners.clear();
|
||||
|
|
Loading…
Reference in New Issue
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.