Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/BKE_geometry_set.hh5
-rw-r--r--source/blender/blenkernel/intern/geometry_component_instances.cc60
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc32
3 files changed, 96 insertions, 1 deletions
diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh
index 8e36bda84ce..0f9c2c1062b 100644
--- a/source/blender/blenkernel/BKE_geometry_set.hh
+++ b/source/blender/blenkernel/BKE_geometry_set.hh
@@ -922,6 +922,11 @@ class InstancesComponent : public GeometryComponent {
int instances_amount() const;
int references_amount() const;
+ /**
+ * Remove the indices in the selection mask and remove unused instance references afterwards.
+ */
+ void remove_instances(const blender::IndexMask selection);
+
blender::Span<int> almost_unique_ids() const;
blender::bke::CustomDataAttributes &attributes();
diff --git a/source/blender/blenkernel/intern/geometry_component_instances.cc b/source/blender/blenkernel/intern/geometry_component_instances.cc
index 93a7646fed0..a7e3c5b60dc 100644
--- a/source/blender/blenkernel/intern/geometry_component_instances.cc
+++ b/source/blender/blenkernel/intern/geometry_component_instances.cc
@@ -17,6 +17,7 @@
#include <mutex>
#include "BLI_float4x4.hh"
+#include "BLI_index_mask.hh"
#include "BLI_map.hh"
#include "BLI_rand.hh"
#include "BLI_set.hh"
@@ -26,6 +27,8 @@
#include "DNA_collection_types.h"
+#include "BKE_attribute_access.hh"
+#include "BKE_attribute_math.hh"
#include "BKE_geometry_set.hh"
#include "BKE_geometry_set_instances.hh"
@@ -34,6 +37,7 @@
#include "FN_cpp_type_make.hh"
using blender::float4x4;
+using blender::IndexMask;
using blender::Map;
using blender::MutableSpan;
using blender::Set;
@@ -132,6 +136,62 @@ blender::Span<InstanceReference> InstancesComponent::references() const
return references_;
}
+template<typename T>
+static void copy_data_based_on_mask(Span<T> src, MutableSpan<T> dst, IndexMask mask)
+{
+ BLI_assert(src.data() != dst.data());
+ using namespace blender;
+ threading::parallel_for(mask.index_range(), 1024, [&](IndexRange range) {
+ for (const int i : range) {
+ dst[i] = src[mask[i]];
+ }
+ });
+}
+
+void InstancesComponent::remove_instances(const IndexMask selection)
+{
+ using namespace blender;
+ if (selection.is_range() && selection.index_range().first() == 0) {
+ /* Deleting from the end of the array can be much faster since no data has to be shifted. */
+ this->resize(selection.size());
+ this->remove_unused_references();
+ return;
+ }
+
+ Vector<int> new_handles(selection.size());
+ copy_data_based_on_mask<int>(this->instance_reference_handles(), new_handles, selection);
+ instance_reference_handles_ = std::move(new_handles);
+ Vector<float4x4> new_transforms(selection.size());
+ copy_data_based_on_mask<float4x4>(this->instance_transforms(), new_transforms, selection);
+ instance_transforms_ = std::move(new_transforms);
+
+ const bke::CustomDataAttributes &src_attributes = attributes_;
+
+ bke::CustomDataAttributes dst_attributes;
+ dst_attributes.reallocate(selection.size());
+
+ src_attributes.foreach_attribute(
+ [&](const bke::AttributeIDRef &id, const AttributeMetaData &meta_data) {
+ if (!id.should_be_kept()) {
+ return true;
+ }
+
+ GSpan src = *src_attributes.get_for_read(id);
+ dst_attributes.create(id, meta_data.data_type);
+ fn::GMutableSpan dst = *dst_attributes.get_for_write(id);
+
+ attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
+ using T = decltype(dummy);
+ copy_data_based_on_mask<T>(src.typed<T>(), dst.typed<T>(), selection);
+ });
+ return true;
+ },
+ ATTR_DOMAIN_INSTANCE);
+
+ attributes_ = std::move(dst_attributes);
+ this->remove_unused_references();
+}
+
void InstancesComponent::remove_unused_references()
{
using namespace blender;
diff --git a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc
index a5197b23adb..7d41242b8bc 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc
@@ -529,6 +529,30 @@ static void separate_point_cloud_selection(GeometrySet &geometry_set,
geometry_set.replace_pointcloud(pointcloud);
}
+static void separate_instance_selection(GeometrySet &geometry_set,
+ const Field<bool> &selection_field,
+ const bool invert)
+{
+ InstancesComponent &instances = geometry_set.get_component_for_write<InstancesComponent>();
+ GeometryComponentFieldContext field_context{instances, ATTR_DOMAIN_INSTANCE};
+
+ const int domain_size = instances.attribute_domain_size(ATTR_DOMAIN_INSTANCE);
+ fn::FieldEvaluator evaluator{field_context, domain_size};
+ evaluator.add(selection_field);
+ evaluator.evaluate();
+ const VArray_Span<bool> &selection = evaluator.get_evaluated<bool>(0);
+
+ Vector<int64_t> indices;
+ const IndexMask mask = index_mask_indices(selection, invert, indices);
+
+ if (mask.size() == 0) {
+ geometry_set.remove<InstancesComponent>();
+ return;
+ }
+
+ instances.remove_instances(mask);
+}
+
static void compute_selected_vertices_from_vertex_selection(const Span<bool> vertex_selection,
const bool invert,
MutableSpan<int> r_vertex_map,
@@ -1261,7 +1285,7 @@ void separate_geometry(GeometrySet &geometry_set,
}
}
if (geometry_set.has_mesh()) {
- if (domain != ATTR_DOMAIN_CURVE) {
+ if (ELEM(domain, ATTR_DOMAIN_POINT, ATTR_DOMAIN_EDGE, ATTR_DOMAIN_FACE, ATTR_DOMAIN_CORNER)) {
separate_mesh_selection(geometry_set, selection_field, domain, mode, invert);
some_valid_domain = true;
}
@@ -1272,6 +1296,12 @@ void separate_geometry(GeometrySet &geometry_set,
some_valid_domain = true;
}
}
+ if (geometry_set.has_instances()) {
+ if (domain == ATTR_DOMAIN_INSTANCE) {
+ separate_instance_selection(geometry_set, selection_field, invert);
+ some_valid_domain = true;
+ }
+ }
r_is_error = !some_valid_domain && geometry_set.has_realized_data();
}