Cleanup: Use short2 for custom normals, simplify access

Use a span instead of a pointer, which allows using `fill_indices`
to set values and using the assign operator in the future.
This commit is contained in:
Hans Goudey 2023-04-28 13:34:15 -04:00
parent 5ce4447f02
commit 82769653f8
11 changed files with 67 additions and 70 deletions

View File

@ -98,7 +98,7 @@ void normals_calc_loop(Span<float3> vert_positions,
const bool *sharp_faces,
bool use_split_normals,
float split_angle,
short (*clnors_data)[2],
short2 *clnors_data,
MLoopNorSpaceArray *r_lnors_spacearr,
MutableSpan<float3> r_loop_normals);
@ -112,7 +112,7 @@ void normals_loop_custom_set(Span<float3> vert_positions,
const bool *sharp_faces,
MutableSpan<bool> sharp_edges,
MutableSpan<float3> r_custom_loop_normals,
short (*r_clnors_data)[2]);
MutableSpan<short2> r_clnors_data);
void normals_loop_custom_set_from_verts(Span<float3> vert_positions,
Span<int2> edges,
@ -124,7 +124,7 @@ void normals_loop_custom_set_from_verts(Span<float3> vert_positions,
const bool *sharp_faces,
MutableSpan<bool> sharp_edges,
MutableSpan<float3> r_custom_vert_normals,
short (*r_clnors_data)[2]);
MutableSpan<short2> r_clnors_data);
/**
* Define sharp edges as needed to mimic 'autosmooth' from angle threshold.

View File

@ -365,7 +365,7 @@ static void data_transfer_dtdata_type_preprocess(const Mesh *me_src,
BLI_assert(CustomData_get_layer(&me_src->ldata, CD_NORMAL) != nullptr);
(void)me_src;
short(*custom_nors_dst)[2] = static_cast<short(*)[2]>(
blender::short2 *custom_nors_dst = static_cast<blender::short2 *>(
CustomData_get_layer_for_write(ldata_dst, CD_CUSTOMLOOPNORMAL, me_dst->totloop));
/* Cache loop nors into a temp CDLayer. */
@ -415,11 +415,11 @@ static void data_transfer_dtdata_type_postprocess(Mesh *me_dst,
blender::float3 *loop_nors_dst = static_cast<blender::float3 *>(
CustomData_get_layer_for_write(ldata_dst, CD_NORMAL, me_dst->totloop));
short(*custom_nors_dst)[2] = static_cast<short(*)[2]>(
blender::short2 *custom_nors_dst = static_cast<blender::short2 *>(
CustomData_get_layer_for_write(ldata_dst, CD_CUSTOMLOOPNORMAL, me_dst->totloop));
if (!custom_nors_dst) {
custom_nors_dst = static_cast<short(*)[2]>(
custom_nors_dst = static_cast<blender::short2 *>(
CustomData_add_layer(ldata_dst, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, me_dst->totloop));
}
@ -439,7 +439,7 @@ static void data_transfer_dtdata_type_postprocess(Mesh *me_dst,
sharp_faces,
sharp_edges.span,
{loop_nors_dst, me_dst->totloop},
custom_nors_dst);
{custom_nors_dst, me_dst->totloop});
sharp_edges.finish();
}
}

View File

@ -2274,8 +2274,8 @@ void BKE_keyblock_mesh_calc_normals(const KeyBlock *kb,
{reinterpret_cast<blender::float3 *>(vert_normals), mesh->totvert});
}
if (loop_normals_needed) {
short(*clnors)[2] = static_cast<short(*)[2]>(CustomData_get_layer_for_write(
&mesh->ldata, CD_CUSTOMLOOPNORMAL, corner_verts.size())); /* May be nullptr. */
blender::short2 *clnors = static_cast<blender::short2 *>(
CustomData_get_layer_for_write(&mesh->ldata, CD_CUSTOMLOOPNORMAL, corner_verts.size()));
const bool *sharp_edges = static_cast<const bool *>(
CustomData_get_layer_named(&mesh->edata, CD_PROP_BOOL, "sharp_edge"));
const bool *sharp_faces = static_cast<const bool *>(

View File

@ -1888,7 +1888,7 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh,
const float split_angle = (mesh->flag & ME_AUTOSMOOTH) != 0 ? mesh->smoothresh : float(M_PI);
/* may be nullptr */
short(*clnors)[2] = (short(*)[2])CustomData_get_layer_for_write(
blender::short2 *clnors = (blender::short2 *)CustomData_get_layer_for_write(
&mesh->ldata, CD_CUSTOMLOOPNORMAL, mesh->totloop);
const bool *sharp_edges = static_cast<const bool *>(
CustomData_get_layer_named(&mesh->edata, CD_PROP_BOOL, "sharp_edge"));

View File

@ -165,10 +165,12 @@ void BKE_mesh_foreach_mapped_loop(Mesh *mesh,
const float(*vertexCos)[3] = mesh->runtime->edit_data->vertexCos;
/* XXX: investigate using EditMesh data. */
const float(*loop_normals)[3] = (flag & MESH_FOREACH_USE_NORMAL) ?
static_cast<const float(*)[3]>(
CustomData_get_layer(&mesh->ldata, CD_NORMAL)) :
nullptr;
blender::Span<blender::float3> corner_normals;
if (flag & MESH_FOREACH_USE_NORMAL) {
corner_normals = {
static_cast<const blender::float3 *>(CustomData_get_layer(&mesh->ldata, CD_NORMAL)),
mesh->totloop};
}
int f_idx;
@ -181,16 +183,19 @@ void BKE_mesh_foreach_mapped_loop(Mesh *mesh,
do {
const BMVert *eve = l_iter->v;
const int v_idx = BM_elem_index_get(eve);
const float *no = loop_normals ? *loop_normals++ : nullptr;
const float *no = corner_normals.is_empty() ? nullptr :
&corner_normals[BM_elem_index_get(l_iter)].x;
func(userData, v_idx, f_idx, vertexCos ? vertexCos[v_idx] : eve->co, no);
} while ((l_iter = l_iter->next) != l_first);
}
}
else {
const float(*loop_normals)[3] = (flag & MESH_FOREACH_USE_NORMAL) ?
static_cast<const float(*)[3]>(
CustomData_get_layer(&mesh->ldata, CD_NORMAL)) :
nullptr;
blender::Span<blender::float3> corner_normals;
if (flag & MESH_FOREACH_USE_NORMAL) {
corner_normals = {
static_cast<const blender::float3 *>(CustomData_get_layer(&mesh->ldata, CD_NORMAL)),
mesh->totloop};
}
const float(*positions)[3] = BKE_mesh_vert_positions(mesh);
const blender::OffsetIndices polys = mesh->polys();
@ -202,10 +207,11 @@ void BKE_mesh_foreach_mapped_loop(Mesh *mesh,
if (v_index || f_index) {
for (const int poly_i : polys.index_range()) {
for (const int vert : corner_verts.slice(polys[poly_i])) {
for (const int corner : polys[poly_i]) {
const int vert = corner_verts[corner];
const int v_idx = v_index ? v_index[vert] : vert;
const int f_idx = f_index ? f_index[poly_i] : poly_i;
const float *no = loop_normals ? *loop_normals++ : nullptr;
const float *no = corner_normals.is_empty() ? nullptr : &corner_normals[corner].x;
if (ELEM(ORIGINDEX_NONE, v_idx, f_idx)) {
continue;
}
@ -215,11 +221,10 @@ void BKE_mesh_foreach_mapped_loop(Mesh *mesh,
}
else {
for (const int poly_i : polys.index_range()) {
for (const int vert : corner_verts.slice(polys[poly_i])) {
const int v_idx = vert;
const int f_idx = poly_i;
const float *no = loop_normals ? *loop_normals++ : nullptr;
func(userData, v_idx, f_idx, positions[vert], no);
for (const int corner : polys[poly_i]) {
const int vert = corner_verts[corner];
const float *no = corner_normals.is_empty() ? nullptr : &corner_normals[corner].x;
func(userData, vert, poly_i, positions[vert], no);
}
}
}

View File

@ -386,7 +386,7 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
CustomData_has_layer(&result->ldata, CD_CUSTOMLOOPNORMAL) && result->totpoly > 0) {
blender::Array<blender::float3> loop_normals(result_corner_verts.size());
CustomData *ldata = &result->ldata;
short(*clnors)[2] = static_cast<short(*)[2]>(
blender::short2 *clnors = static_cast<blender::short2 *>(
CustomData_get_layer_for_write(ldata, CD_CUSTOMLOOPNORMAL, result->totloop));
MLoopNorSpaceArray lnors_spacearr = {nullptr};

View File

@ -1212,7 +1212,7 @@ void normals_calc_loop(const Span<float3> vert_positions,
const bool *sharp_faces,
bool use_split_normals,
float split_angle,
short (*clnors_data)[2],
short2 *clnors_data,
MLoopNorSpaceArray *r_lnors_spacearr,
MutableSpan<float3> r_loop_normals)
{
@ -1379,7 +1379,7 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
const bool use_vertices,
MutableSpan<float3> r_custom_loop_normals,
MutableSpan<bool> sharp_edges,
short (*r_clnors_data)[2])
MutableSpan<short2> r_clnors_data)
{
/* We *may* make that poor #bke::mesh::normals_calc_loop() even more complex by making it
* handling that feature too, would probably be more efficient in absolute. However, this
@ -1395,8 +1395,6 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
const bool use_split_normals = true;
const float split_angle = float(M_PI);
Vector<short *> clnors_data;
/* Compute current lnor spacearr. */
normals_calc_loop(positions,
edges,
@ -1410,7 +1408,7 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
sharp_faces,
use_split_normals,
split_angle,
r_clnors_data,
r_clnors_data.data(),
&lnors_spacearr,
loop_normals);
@ -1536,11 +1534,13 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
sharp_faces,
use_split_normals,
split_angle,
r_clnors_data,
r_clnors_data.data(),
&lnors_spacearr,
loop_normals);
}
Vector<int> processed_corners;
/* And we just have to convert plain object-space custom normals to our
* lnor space-encoded ones. */
for (const int i : corner_verts.index_range()) {
@ -1568,10 +1568,7 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
}
else {
int avg_nor_count = 0;
float avg_nor[3];
short clnor_data_tmp[2];
zero_v3(avg_nor);
float3 avg_nor(0.0f);
while (loop_link) {
const int lidx = POINTER_AS_INT(loop_link->link);
const int nidx = use_vertices ? corner_verts[lidx] : lidx;
@ -1579,20 +1576,18 @@ static void mesh_normals_loop_custom_set(Span<float3> positions,
avg_nor_count++;
add_v3_v3(avg_nor, nor);
clnors_data.append(r_clnors_data[lidx]);
processed_corners.append(lidx);
loop_link = loop_link->next;
done_loops[lidx].reset();
}
mul_v3_fl(avg_nor, 1.0f / float(avg_nor_count));
short2 clnor_data_tmp;
BKE_lnor_space_custom_normal_to_data(lnors_spacearr.lspacearr[i], avg_nor, clnor_data_tmp);
while (!clnors_data.is_empty()) {
short *clnor_data = clnors_data.pop_last();
clnor_data[0] = clnor_data_tmp[0];
clnor_data[1] = clnor_data_tmp[1];
}
r_clnors_data.fill_indices(processed_corners.as_span(), clnor_data_tmp);
processed_corners.clear();
}
}
}
@ -1610,7 +1605,7 @@ void normals_loop_custom_set(const Span<float3> vert_positions,
const bool *sharp_faces,
MutableSpan<bool> sharp_edges,
MutableSpan<float3> r_custom_loop_normals,
short (*r_clnors_data)[2])
MutableSpan<short2> r_clnors_data)
{
mesh_normals_loop_custom_set(vert_positions,
edges,
@ -1636,7 +1631,7 @@ void normals_loop_custom_set_from_verts(const Span<float3> vert_positions,
const bool *sharp_faces,
MutableSpan<bool> sharp_edges,
MutableSpan<float3> r_custom_vert_normals,
short (*r_clnors_data)[2])
MutableSpan<short2> r_clnors_data)
{
mesh_normals_loop_custom_set(vert_positions,
edges,
@ -1654,17 +1649,14 @@ void normals_loop_custom_set_from_verts(const Span<float3> vert_positions,
static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const bool use_vertices)
{
short(*clnors)[2];
const int numloops = mesh->totloop;
clnors = (short(*)[2])CustomData_get_layer_for_write(
&mesh->ldata, CD_CUSTOMLOOPNORMAL, mesh->totloop);
short2 *clnors = static_cast<short2 *>(
CustomData_get_layer_for_write(&mesh->ldata, CD_CUSTOMLOOPNORMAL, mesh->totloop));
if (clnors != nullptr) {
memset(clnors, 0, sizeof(*clnors) * size_t(numloops));
memset(clnors, 0, sizeof(*clnors) * mesh->totloop);
}
else {
clnors = (short(*)[2])CustomData_add_layer(
&mesh->ldata, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, numloops);
clnors = static_cast<short2 *>(
CustomData_add_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, mesh->totloop));
}
MutableAttributeAccessor attributes = mesh->attributes_for_write();
SpanAttributeWriter<bool> sharp_edges = attributes.lookup_or_add_for_write_span<bool>(
@ -1684,7 +1676,7 @@ static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const
use_vertices,
{reinterpret_cast<float3 *>(r_custom_nors), use_vertices ? mesh->totvert : mesh->totloop},
sharp_edges.span,
clnors);
{clnors, mesh->totloop});
sharp_edges.finish();
}

View File

@ -1330,7 +1330,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
poly_normals_dst = mesh_dst->poly_normals();
}
if (need_lnors_dst) {
short(*custom_nors_dst)[2] = static_cast<short(*)[2]>(
blender::short2 *custom_nors_dst = static_cast<blender::short2 *>(
CustomData_get_layer_for_write(ldata_dst, CD_CUSTOMLOOPNORMAL, numloops_dst));
/* Cache loop normals into a temporary custom data layer. */

View File

@ -335,7 +335,7 @@ void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_
}
if (((data_flag & MR_DATA_LOOP_NOR) && is_auto_smooth) || (data_flag & MR_DATA_TAN_LOOP_NOR)) {
mr->loop_normals.reinitialize(mr->corner_verts.size());
short(*clnors)[2] = static_cast<short(*)[2]>(
blender::short2 *clnors = static_cast<blender::short2 *>(
CustomData_get_layer_for_write(&mr->me->ldata, CD_CUSTOMLOOPNORMAL, mr->me->totloop));
const bool *sharp_edges = static_cast<const bool *>(
CustomData_get_layer_named(&mr->me->edata, CD_PROP_BOOL, "sharp_edge"));

View File

@ -222,7 +222,7 @@ static void normalEditModifier_do_radial(NormalEditModifierData *enmd,
const ModifierEvalContext * /*ctx*/,
Object *ob,
Mesh *mesh,
short (*clnors)[2],
blender::MutableSpan<blender::short2> clnors,
blender::MutableSpan<blender::float3> loop_normals,
const short mix_mode,
const float mix_factor,
@ -350,7 +350,7 @@ static void normalEditModifier_do_directional(NormalEditModifierData *enmd,
const ModifierEvalContext * /*ctx*/,
Object *ob,
Mesh *mesh,
short (*clnors)[2],
blender::MutableSpan<blender::short2> clnors,
blender::MutableSpan<blender::float3> loop_normals,
const short mix_mode,
const float mix_factor,
@ -530,10 +530,10 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd,
bke::SpanAttributeWriter<bool> sharp_edges = attributes.lookup_or_add_for_write_span<bool>(
"sharp_edge", ATTR_DOMAIN_EDGE);
short(*clnors)[2] = static_cast<short(*)[2]>(
blender::short2 *clnors = static_cast<blender::short2 *>(
CustomData_get_layer_for_write(ldata, CD_CUSTOMLOOPNORMAL, corner_verts.size()));
if (use_current_clnors) {
clnors = static_cast<short(*)[2]>(
clnors = static_cast<blender::short2 *>(
CustomData_get_layer_for_write(ldata, CD_CUSTOMLOOPNORMAL, corner_verts.size()));
loop_normals.reinitialize(corner_verts.size());
const bool *sharp_faces = static_cast<const bool *>(
@ -556,7 +556,7 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd,
}
if (clnors == nullptr) {
clnors = static_cast<short(*)[2]>(
clnors = static_cast<blender::short2 *>(
CustomData_add_layer(ldata, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, corner_verts.size()));
}
@ -567,7 +567,7 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd,
ctx,
ob,
result,
clnors,
{clnors, result->totloop},
loop_normals,
enmd->mix_mode,
enmd->mix_factor,
@ -587,7 +587,7 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd,
ctx,
ob,
result,
clnors,
{clnors, result->totloop},
loop_normals,
enmd->mix_mode,
enmd->mix_factor,

View File

@ -78,7 +78,7 @@ struct WeightedNormalData {
blender::Span<int> corner_verts;
blender::Span<int> corner_edges;
blender::Span<int> loop_to_poly;
short (*clnors)[2];
blender::MutableSpan<blender::short2> clnors;
bool has_clnors; /* True if clnors already existed, false if we had to create them. */
float split_angle;
@ -191,7 +191,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd,
const blender::Span<int> corner_verts = wn_data->corner_verts;
const blender::Span<int> corner_edges = wn_data->corner_edges;
short(*clnors)[2] = wn_data->clnors;
MutableSpan<short2> clnors = wn_data->clnors;
const blender::Span<int> loop_to_poly = wn_data->loop_to_poly;
const blender::Span<blender::float3> poly_normals = wn_data->poly_normals;
@ -234,7 +234,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd,
wn_data->sharp_faces,
true,
split_angle,
has_clnors ? clnors : nullptr,
has_clnors ? clnors.data() : nullptr,
&lnors_spacearr,
loop_normals);
@ -395,7 +395,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd,
wn_data->sharp_faces,
true,
split_angle,
has_clnors ? clnors : nullptr,
has_clnors ? clnors.data() : nullptr,
nullptr,
loop_normals);
@ -561,14 +561,14 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
}
const float split_angle = mesh->smoothresh;
short(*clnors)[2] = static_cast<short(*)[2]>(
blender::short2 *clnors = static_cast<blender::short2 *>(
CustomData_get_layer_for_write(&result->ldata, CD_CUSTOMLOOPNORMAL, mesh->totloop));
/* Keep info whether we had clnors,
* it helps when generating clnor spaces and default normals. */
const bool has_clnors = clnors != nullptr;
if (!clnors) {
clnors = static_cast<short(*)[2]>(CustomData_add_layer(
clnors = static_cast<blender::short2 *>(CustomData_add_layer(
&result->ldata, CD_CUSTOMLOOPNORMAL, CD_SET_DEFAULT, corner_verts.size()));
}
@ -593,7 +593,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
wn_data.corner_verts = corner_verts;
wn_data.corner_edges = corner_edges;
wn_data.loop_to_poly = loop_to_poly_map;
wn_data.clnors = clnors;
wn_data.clnors = {clnors, mesh->totloop};
wn_data.has_clnors = has_clnors;
wn_data.split_angle = split_angle;