Mesh: Rewrite split edges algorithm #110661

Merged
Hans Goudey merged 78 commits from HooglyBoogly/blender:split-edges-rewrite-2 into main 2023-08-30 14:23:49 +02:00
4 changed files with 73 additions and 66 deletions
Showing only changes of commit a5cbdd9061 - Show all commits

View File

@ -266,6 +266,9 @@ class NewGeometryNodeGroupTool(Operator):
@classmethod
def poll(cls, context):
if not context.space_data:
# Does not exist if the search menu is called while the cursor is outside the Blender window.
return False
return context.space_data.type == 'NODE_EDITOR' and context.space_data.geometry_nodes_type == 'TOOL'
def execute(self, context):

View File

@ -1033,6 +1033,29 @@ void gather_attributes(const AttributeAccessor src_attributes,
});
}
static bool indices_are_range(const Span<int> indices, const IndexRange range)
{
if (indices.size() != range.size()) {
return false;
}
return threading::parallel_reduce(
range,
4096,
true,
[&](const IndexRange range, const bool init) {
if (!init) {
return false;
}
for (const int i : range) {
if (indices[i] != i) {
return false;
}
}
return true;
},
[](const bool a, const bool b) { return a && b; });
}
void gather_attributes(const AttributeAccessor src_attributes,
const eAttrDomain domain,
const AnonymousAttributePropagationInfo &propagation_info,
@ -1040,26 +1063,31 @@ void gather_attributes(const AttributeAccessor src_attributes,
const Span<int> indices,
MutableAttributeAccessor dst_attributes)
{
src_attributes.for_all([&](const AttributeIDRef &id, const AttributeMetaData meta_data) {
if (meta_data.domain != domain) {
if (indices_are_range(indices, IndexRange(src_attributes.domain_size(domain)))) {
copy_attributes(src_attributes, domain, propagation_info, skip, dst_attributes);
}
else {
src_attributes.for_all([&](const AttributeIDRef &id, const AttributeMetaData meta_data) {
if (meta_data.domain != domain) {
return true;
}
if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) {
return true;
}
if (skip.contains(id.name())) {
return true;
}
const bke::GAttributeReader src = src_attributes.lookup(id, domain);
bke::GSpanAttributeWriter dst = dst_attributes.lookup_or_add_for_write_only_span(
id, domain, meta_data.data_type);
if (!dst) {
return true;
}
attribute_math::gather(src.varray, indices, dst.span);
dst.finish();
return true;
}
if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) {
return true;
}
if (skip.contains(id.name())) {
return true;
}
const bke::GAttributeReader src = src_attributes.lookup(id, domain);
bke::GSpanAttributeWriter dst = dst_attributes.lookup_or_add_for_write_only_span(
id, domain, meta_data.data_type);
if (!dst) {
return true;
}
attribute_math::gather(src.varray, indices, dst.span);
dst.finish();
return true;
});
});
}
}
template<typename T>

View File

@ -653,18 +653,20 @@ static const EnumPropertyItem *bone_collection_enum_items(bContext *C,
PropertyRNA * /*prop*/,
bool *r_free)
{
Object *obpose = ED_pose_object_from_context(C);
bArmature *arm = static_cast<bArmature *>(obpose->data);
EnumPropertyItem *item = nullptr, item_tmp = {0};
int totitem = 0;
int bcoll_index = 0;
LISTBASE_FOREACH_INDEX (BoneCollection *, bcoll, &arm->collections, bcoll_index) {
item_tmp.identifier = bcoll->name;
item_tmp.name = bcoll->name;
item_tmp.value = bcoll_index;
RNA_enum_item_add(&item, &totitem, &item_tmp);
if (C) {
Object *obpose = ED_pose_object_from_context(C);
bArmature *arm = static_cast<bArmature *>(obpose->data);
LISTBASE_FOREACH_INDEX (BoneCollection *, bcoll, &arm->collections, bcoll_index) {
item_tmp.identifier = bcoll->name;
item_tmp.name = bcoll->name;
item_tmp.value = bcoll_index;
RNA_enum_item_add(&item, &totitem, &item_tmp);
}
}
RNA_enum_item_add_separator(&item, &totitem);

View File

@ -20,26 +20,6 @@
namespace blender::geometry {
static bool indices_are_full_ordered_copy(const Span<int> indices)
{
return threading::parallel_reduce(
indices.index_range(),
4096,
true,
[&](const IndexRange range, const bool init) {
if (!init) {
return false;
}
for (const int i : range) {
if (indices[i] != i) {
return false;
}
}
return true;
},
[](const bool a, const bool b) { return a && b; });
}
BLI_NOINLINE bke::CurvesGeometry create_curve_from_vert_indices(
const bke::AttributeAccessor &mesh_attributes,
const Span<int> vert_indices,
@ -58,24 +38,23 @@ BLI_NOINLINE bke::CurvesGeometry create_curve_from_vert_indices(
curves.cyclic_for_write().slice(cyclic_curves).fill(true);
}
const int src_total_points = mesh_attributes.domain_size(ATTR_DOMAIN_POINT);
const bool share_vert_data = vert_indices.size() == src_total_points &&
indices_are_full_ordered_copy(vert_indices);
if (share_vert_data) {
bke::copy_attributes(
mesh_attributes, ATTR_DOMAIN_POINT, propagation_info, {}, curves_attributes);
/* Don't copy attributes that are built-in on meshes but not on curves. */
Set<std::string> skip;
for (const bke::AttributeIDRef &id : mesh_attributes.all_ids()) {
if (mesh_attributes.is_builtin(id) && !curves_attributes.is_builtin(id)) {
skip.add(id.name());
}
}
bke::gather_attributes(
mesh_attributes, ATTR_DOMAIN_POINT, propagation_info, skip, vert_indices, curves_attributes);
mesh_attributes.for_all(
[&](const bke::AttributeIDRef &id, const bke::AttributeMetaData meta_data) {
if (share_vert_data) {
if (meta_data.domain == ATTR_DOMAIN_POINT) {
return true;
}
if (meta_data.domain == ATTR_DOMAIN_POINT) {
return true;
}
if (mesh_attributes.is_builtin(id) && !curves_attributes.is_builtin(id)) {
/* Don't copy attributes that are built-in on meshes but not on curves. */
if (skip.contains(id.name())) {
return true;
}
if (id.is_anonymous() && !propagation_info.propagate(id.anonymous_id())) {
@ -90,12 +69,7 @@ BLI_NOINLINE bke::CurvesGeometry create_curve_from_vert_indices(
}
bke::GSpanAttributeWriter dst = curves_attributes.lookup_or_add_for_write_only_span(
id, ATTR_DOMAIN_POINT, meta_data.data_type);
if (share_vert_data) {
array_utils::copy(*src, dst.span);
}
else {
bke::attribute_math::gather(*src, vert_indices, dst.span);
}
bke::attribute_math::gather(*src, vert_indices, dst.span);
dst.finish();
return true;
});