Mesh: Replace auto smooth with node group #108014

Merged
Hans Goudey merged 149 commits from HooglyBoogly/blender:refactor-mesh-corner-normals-lazy into main 2023-10-20 16:54:20 +02:00
3 changed files with 69 additions and 73 deletions
Showing only changes of commit ca331b969b - Show all commits

View File

@ -301,74 +301,6 @@ void normals_calc_poly_vert(const Span<float3> positions,
/** \name Mesh Normal Calculation
* \{ */
namespace blender::bke {
enum class BoolArrayMix {
None,
AllFalse,
AllTrue,
Mixed,
};
static BoolArrayMix bool_array_mix_calc(const VArray<bool> &varray,
const blender::IndexRange range_to_check)
{
using namespace blender;
if (varray.is_empty()) {
return BoolArrayMix::None;
}
const CommonVArrayInfo info = varray.common_info();
if (info.type == CommonVArrayInfo::Type::Single) {
return *static_cast<const bool *>(info.data) ? BoolArrayMix::AllTrue : BoolArrayMix::AllFalse;
}
if (info.type == CommonVArrayInfo::Type::Span) {
const Span<bool> span(static_cast<const bool *>(info.data), varray.size());
return threading::parallel_reduce(
range_to_check,
4096,
BoolArrayMix::None,
[&](const IndexRange range, const BoolArrayMix init) {
if (init == BoolArrayMix::Mixed) {
return init;
}
const Span<bool> slice = span.slice(range);
const bool first = slice.first();
for (const bool value : slice.drop_front(1)) {
if (value != first) {
return BoolArrayMix::Mixed;
}
}
return first ? BoolArrayMix::AllTrue : BoolArrayMix::AllFalse;
},
[&](BoolArrayMix a, BoolArrayMix b) { return (a == b) ? a : BoolArrayMix::Mixed; });
}
return threading::parallel_reduce(
range_to_check,
2048,
BoolArrayMix::None,
[&](const IndexRange range, const BoolArrayMix init) {
if (init == BoolArrayMix::Mixed) {
return init;
}
/* Alternatively, this could use #materialize to retrieve many values at once. */
const bool first = varray[range.first()];
for (const int64_t i : range.drop_front(1)) {
if (varray[i] != first) {
return BoolArrayMix::Mixed;
}
}
return first ? BoolArrayMix::AllTrue : BoolArrayMix::AllFalse;
},
[&](BoolArrayMix a, BoolArrayMix b) { return (a == b) ? a : BoolArrayMix::Mixed; });
}
static BoolArrayMix bool_array_mix_calc(const VArray<bool> &varray)
{
return bool_array_mix_calc(varray, varray.index_range());
}
} // namespace blender::bke
eAttrDomain Mesh::normal_domain_all_info() const
{
using namespace blender;
@ -385,19 +317,21 @@ eAttrDomain Mesh::normal_domain_all_info() const
const VArray<bool> sharp_faces = *attributes.lookup_or_default<bool>(
"sharp_face", ATTR_DOMAIN_FACE, false);
const BoolArrayMix face_mix = bool_array_mix_calc(sharp_faces);
if (face_mix == BoolArrayMix::AllTrue) {
const array_utils::BoolArrayMix face_mix = array_utils::bool_array_mix_calc(sharp_faces);
if (face_mix == array_utils::BoolArrayMix::AllTrue) {
return ATTR_DOMAIN_FACE;
}
const VArray<bool> sharp_edges = *attributes.lookup_or_default<bool>(
"sharp_edge", ATTR_DOMAIN_EDGE, false);
const BoolArrayMix edge_mix = bool_array_mix_calc(sharp_edges);
if (edge_mix == BoolArrayMix::AllTrue) {
const array_utils::BoolArrayMix edge_mix = array_utils::bool_array_mix_calc(sharp_edges);
if (edge_mix == array_utils::BoolArrayMix::AllTrue) {
return ATTR_DOMAIN_FACE;
}
if (edge_mix == BoolArrayMix::AllFalse && face_mix == BoolArrayMix::AllFalse) {
if (edge_mix == array_utils::BoolArrayMix::AllFalse &&
face_mix == array_utils::BoolArrayMix::AllFalse)
{
return ATTR_DOMAIN_POINT;
}

View File

@ -140,5 +140,16 @@ inline void gather(const VArray<T> &src,
}
void invert_booleans(MutableSpan<bool> span);
enum class BoolArrayMix {
None,
AllFalse,
AllTrue,
Mixed,
};
BoolArrayMix bool_array_mix_calc(const VArray<bool> &varray, const IndexRange range_to_check);
inline BoolArrayMix bool_array_mix_calc(const VArray<bool> &varray)
{
return bool_array_mix_calc(varray, varray.index_range());
}
} // namespace blender::array_utils

View File

@ -52,4 +52,55 @@ void invert_booleans(MutableSpan<bool> span)
});
}
BoolArrayMix bool_array_mix_calc(const VArray<bool> &varray, const IndexRange range_to_check)
{
if (varray.is_empty()) {
return BoolArrayMix::None;
}
const CommonVArrayInfo info = varray.common_info();
if (info.type == CommonVArrayInfo::Type::Single) {
return *static_cast<const bool *>(info.data) ? BoolArrayMix::AllTrue : BoolArrayMix::AllFalse;
}
if (info.type == CommonVArrayInfo::Type::Span) {
const Span<bool> span(static_cast<const bool *>(info.data), varray.size());
return threading::parallel_reduce(
range_to_check,
4096,
BoolArrayMix::None,
[&](const IndexRange range, const BoolArrayMix init) {
if (init == BoolArrayMix::Mixed) {
return init;
}
const Span<bool> slice = span.slice(range);
const bool first = slice.first();
for (const bool value : slice.drop_front(1)) {
if (value != first) {
return BoolArrayMix::Mixed;
}
}
return first ? BoolArrayMix::AllTrue : BoolArrayMix::AllFalse;
},
[&](BoolArrayMix a, BoolArrayMix b) { return (a == b) ? a : BoolArrayMix::Mixed; });
}
return threading::parallel_reduce(
range_to_check,
2048,
BoolArrayMix::None,
[&](const IndexRange range, const BoolArrayMix init) {
if (init == BoolArrayMix::Mixed) {
return init;
}
/* Alternatively, this could use #materialize to retrieve many values at once. */
const bool first = varray[range.first()];
for (const int64_t i : range.drop_front(1)) {
if (varray[i] != first) {
return BoolArrayMix::Mixed;
}
}
return first ? BoolArrayMix::AllTrue : BoolArrayMix::AllFalse;
},
[&](BoolArrayMix a, BoolArrayMix b) { return (a == b) ? a : BoolArrayMix::Mixed; });
}
} // namespace blender::array_utils