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.hh9
-rw-r--r--source/blender/blenkernel/intern/geometry_component_instances.cc117
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc18
-rw-r--r--source/blender/modifiers/intern/MOD_nodes.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_point_instance.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_instances_to_points.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc5
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc2
9 files changed, 151 insertions, 34 deletions
diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh
index 78ccefaed5c..429c37e9c9b 100644
--- a/source/blender/blenkernel/BKE_geometry_set.hh
+++ b/source/blender/blenkernel/BKE_geometry_set.hh
@@ -621,7 +621,9 @@ class InstancesComponent : public GeometryComponent {
blender::Vector<blender::float4x4> instance_transforms_;
/**
* IDs of the instances. They are used for consistency over multiple frames for things like
- * motion blur.
+ * motion blur. Proper stable ID data that actually helps when rendering can only be generated
+ * in some situations, so this vector is allowed to be empty, in which case the index of each
+ * instance will be used for the final ID.
*/
blender::Vector<int> instance_ids_;
@@ -643,7 +645,7 @@ class InstancesComponent : public GeometryComponent {
void resize(int capacity);
int add_reference(const InstanceReference &reference);
- void add_instance(int instance_handle, const blender::float4x4 &transform, const int id = -1);
+ void add_instance(int instance_handle, const blender::float4x4 &transform);
blender::Span<InstanceReference> references() const;
void remove_unused_references();
@@ -658,6 +660,9 @@ class InstancesComponent : public GeometryComponent {
blender::MutableSpan<int> instance_ids();
blender::Span<int> instance_ids() const;
+ blender::MutableSpan<int> instance_ids_ensure();
+ void instance_ids_clear();
+
int instances_amount() const;
int references_amount() const;
diff --git a/source/blender/blenkernel/intern/geometry_component_instances.cc b/source/blender/blenkernel/intern/geometry_component_instances.cc
index 4204d62e1a7..d02121b44a6 100644
--- a/source/blender/blenkernel/intern/geometry_component_instances.cc
+++ b/source/blender/blenkernel/intern/geometry_component_instances.cc
@@ -60,7 +60,9 @@ void InstancesComponent::reserve(int min_capacity)
{
instance_reference_handles_.reserve(min_capacity);
instance_transforms_.reserve(min_capacity);
- instance_ids_.reserve(min_capacity);
+ if (!instance_ids_.is_empty()) {
+ this->instance_ids_ensure();
+ }
}
/**
@@ -73,7 +75,9 @@ void InstancesComponent::resize(int capacity)
{
instance_reference_handles_.resize(capacity);
instance_transforms_.resize(capacity);
- instance_ids_.resize(capacity);
+ if (!instance_ids_.is_empty()) {
+ this->instance_ids_ensure();
+ }
}
void InstancesComponent::clear()
@@ -85,15 +89,15 @@ void InstancesComponent::clear()
references_.clear();
}
-void InstancesComponent::add_instance(const int instance_handle,
- const float4x4 &transform,
- const int id)
+void InstancesComponent::add_instance(const int instance_handle, const float4x4 &transform)
{
BLI_assert(instance_handle >= 0);
BLI_assert(instance_handle < references_.size());
instance_reference_handles_.append(instance_handle);
instance_transforms_.append(transform);
- instance_ids_.append(id);
+ if (!instance_ids_.is_empty()) {
+ this->instance_ids_ensure();
+ }
}
blender::Span<int> InstancesComponent::instance_reference_handles() const
@@ -125,6 +129,22 @@ blender::Span<int> InstancesComponent::instance_ids() const
}
/**
+ * Make sure the ID storage size matches the number of instances. By directly resizing the
+ * component's vectors internally, it is possible to be in a situation where the IDs are not
+ * empty but they do not have the correct size; this function resolves that.
+ */
+blender::MutableSpan<int> InstancesComponent::instance_ids_ensure()
+{
+ instance_ids_.append_n_times(0, this->instances_amount() - instance_ids_.size());
+ return instance_ids_;
+}
+
+void InstancesComponent::instance_ids_clear()
+{
+ instance_ids_.clear_and_make_inline();
+}
+
+/**
* With write access to the instances component, the data in the instanced geometry sets can be
* changed. This is a function on the component rather than each reference to ensure `const`
* correctness for that reason.
@@ -327,8 +347,16 @@ static blender::Array<int> generate_unique_instance_ids(Span<int> original_ids)
blender::Span<int> InstancesComponent::almost_unique_ids() const
{
std::lock_guard lock(almost_unique_ids_mutex_);
- if (almost_unique_ids_.size() != instance_ids_.size()) {
- almost_unique_ids_ = generate_unique_instance_ids(instance_ids_);
+ if (instance_ids().is_empty()) {
+ almost_unique_ids_.reinitialize(this->instances_amount());
+ for (const int i : almost_unique_ids_.index_range()) {
+ almost_unique_ids_[i] = i;
+ }
+ }
+ else {
+ if (almost_unique_ids_.size() != instance_ids_.size()) {
+ almost_unique_ids_ = generate_unique_instance_ids(instance_ids_);
+ }
}
return almost_unique_ids_;
}
@@ -398,11 +426,82 @@ class InstancePositionAttributeProvider final : public BuiltinAttributeProvider
}
};
+class InstanceIDAttributeProvider final : public BuiltinAttributeProvider {
+ public:
+ InstanceIDAttributeProvider()
+ : BuiltinAttributeProvider(
+ "id", ATTR_DOMAIN_POINT, CD_PROP_INT32, Creatable, Writable, Deletable)
+ {
+ }
+
+ GVArrayPtr try_get_for_read(const GeometryComponent &component) const final
+ {
+ const InstancesComponent &instances = static_cast<const InstancesComponent &>(component);
+ if (instances.instance_ids().is_empty()) {
+ return {};
+ }
+ return std::make_unique<fn::GVArray_For_Span<int>>(instances.instance_ids());
+ }
+
+ GVMutableArrayPtr try_get_for_write(GeometryComponent &component) const final
+ {
+ InstancesComponent &instances = static_cast<InstancesComponent &>(component);
+ if (instances.instance_ids().is_empty()) {
+ return {};
+ }
+ return std::make_unique<fn::GVMutableArray_For_MutableSpan<int>>(instances.instance_ids());
+ }
+
+ bool try_delete(GeometryComponent &component) const final
+ {
+ InstancesComponent &instances = static_cast<InstancesComponent &>(component);
+ if (instances.instance_ids().is_empty()) {
+ return false;
+ }
+ instances.instance_ids_clear();
+ return true;
+ }
+
+ bool try_create(GeometryComponent &component, const AttributeInit &initializer) const final
+ {
+ InstancesComponent &instances = static_cast<InstancesComponent &>(component);
+ if (instances.instances_amount() == 0) {
+ return false;
+ }
+ MutableSpan<int> ids = instances.instance_ids_ensure();
+ switch (initializer.type) {
+ case AttributeInit::Type::Default: {
+ ids.fill(0);
+ break;
+ }
+ case AttributeInit::Type::VArray: {
+ const GVArray *varray = static_cast<const AttributeInitVArray &>(initializer).varray;
+ varray->materialize_to_uninitialized(IndexRange(varray->size()), ids.data());
+ break;
+ }
+ case AttributeInit::Type::MoveArray: {
+ void *source_data = static_cast<const AttributeInitMove &>(initializer).data;
+ ids.copy_from({static_cast<int *>(source_data), instances.instances_amount()});
+ MEM_freeN(source_data);
+ break;
+ }
+ }
+ return true;
+ }
+
+ bool exists(const GeometryComponent &component) const final
+ {
+ const InstancesComponent &instances = static_cast<const InstancesComponent &>(component);
+ return !instances.instance_ids().is_empty();
+ }
+};
+
static ComponentAttributeProviders create_attribute_providers_for_instances()
{
static InstancePositionAttributeProvider position;
+ static InstanceIDAttributeProvider id;
- return ComponentAttributeProviders({&position}, {});
+ return ComponentAttributeProviders({&position, &id}, {});
}
} // namespace blender::bke
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc
index 76e7291d905..f352a5fd0eb 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc
@@ -466,14 +466,16 @@ std::unique_ptr<ColumnValues> InstancesDataSource::get_column_values(
});
}
Span<int> ids = component_->instance_ids();
- if (STREQ(column_id.name, "ID")) {
- /* Make the column a bit wider by default, since the IDs tend to be large numbers. */
- return column_values_from_function(
- SPREADSHEET_VALUE_TYPE_INT32,
- column_id.name,
- size,
- [ids](int index, CellValue &r_cell_value) { r_cell_value.value_int = ids[index]; },
- 5.5f);
+ if (!ids.is_empty()) {
+ if (STREQ(column_id.name, "ID")) {
+ /* Make the column a bit wider by default, since the IDs tend to be large numbers. */
+ return column_values_from_function(
+ SPREADSHEET_VALUE_TYPE_INT32,
+ column_id.name,
+ size,
+ [ids](int index, CellValue &r_cell_value) { r_cell_value.value_int = ids[index]; },
+ 5.5f);
+ }
}
return {};
}
diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc
index e6cc7663c58..292ba04490c 100644
--- a/source/blender/modifiers/intern/MOD_nodes.cc
+++ b/source/blender/modifiers/intern/MOD_nodes.cc
@@ -917,6 +917,10 @@ static void store_output_value_in_geometry(GeometrySet &geometry_set,
CurveComponent &component = geometry_set.get_component_for_write<CurveComponent>();
store_field_on_geometry_component(component, attribute_name, domain, field);
}
+ if (geometry_set.has_instances()) {
+ InstancesComponent &component = geometry_set.get_component_for_write<InstancesComponent>();
+ store_field_on_geometry_component(component, attribute_name, domain, field);
+ }
}
/**
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_instance.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_point_instance.cc
index fb45c22ced4..b68dfe44984 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_instance.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_point_instance.cc
@@ -184,7 +184,7 @@ static void add_instances_from_component(InstancesComponent &instances,
instances.resize(start_len + domain_size);
MutableSpan<int> handles = instances.instance_reference_handles().slice(start_len, domain_size);
MutableSpan<float4x4> transforms = instances.instance_transforms().slice(start_len, domain_size);
- MutableSpan<int> instance_ids = instances.instance_ids().slice(start_len, domain_size);
+ MutableSpan<int> instance_ids = instances.instance_ids_ensure().slice(start_len, domain_size);
/* Skip all of the randomness handling if there is only a single possible instance
* (anything except for collection mode with "Whole Collection" turned off). */
diff --git a/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc b/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc
index 44cad2d38d4..f4a127faf43 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc
@@ -77,7 +77,6 @@ static void add_instances_from_component(InstancesComponent &dst_component,
select_len);
MutableSpan<float4x4> dst_transforms = dst_component.instance_transforms().slice(start_len,
select_len);
- MutableSpan<int> dst_stable_ids = dst_component.instance_ids().slice(start_len, select_len);
FieldEvaluator field_evaluator{field_context, domain_size};
const VArray<bool> *pick_instance = nullptr;
@@ -86,7 +85,6 @@ static void add_instances_from_component(InstancesComponent &dst_component,
const VArray<float3> *scales = nullptr;
/* The evaluator could use the component's stable IDs as a destination directly, but only the
* selected indices should be copied. */
- GVArray_Typed<int> stable_ids = src_component.attribute_get_for_read("id", ATTR_DOMAIN_POINT, 0);
field_evaluator.add(params.get_input<Field<bool>>("Pick Instance"), &pick_instance);
field_evaluator.add(params.get_input<Field<int>>("Instance Index"), &indices);
field_evaluator.add(params.get_input<Field<float3>>("Rotation"), &rotations);
@@ -119,7 +117,6 @@ static void add_instances_from_component(InstancesComponent &dst_component,
threading::parallel_for(selection.index_range(), 1024, [&](IndexRange selection_range) {
for (const int range_i : selection_range) {
const int64_t i = selection[range_i];
- dst_stable_ids[range_i] = (*stable_ids)[i];
/* Compute base transform for every instances. */
float4x4 &dst_transform = dst_transforms[range_i];
@@ -157,6 +154,17 @@ static void add_instances_from_component(InstancesComponent &dst_component,
}
});
+ GVArrayPtr id_attribute = src_component.attribute_try_get_for_read(
+ "id", ATTR_DOMAIN_POINT, CD_PROP_INT32);
+ if (id_attribute) {
+ GVArray_Typed<int> ids{*id_attribute};
+ VArray_Span<int> ids_span{ids};
+ MutableSpan<int> dst_ids = dst_component.instance_ids_ensure();
+ for (const int64_t i : selection.index_range()) {
+ dst_ids[i] = ids_span[selection[i]];
+ }
+ }
+
if (pick_instance->is_single()) {
if (pick_instance->get_internal_single()) {
if (instance.has_realized_data()) {
diff --git a/source/blender/nodes/geometry/nodes/node_geo_instances_to_points.cc b/source/blender/nodes/geometry/nodes/node_geo_instances_to_points.cc
index 63d1f88a442..434fe4a19d7 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_instances_to_points.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_instances_to_points.cc
@@ -77,13 +77,15 @@ static void convert_instances_to_points(GeometrySet &geometry_set,
const VArray<float> &radii = evaluator.get_evaluated<float>(1);
copy_attribute_to_points(radii, selection, {pointcloud->radius, pointcloud->totpoint});
- OutputAttribute_Typed<int> id_attribute = points.attribute_try_get_for_output<int>(
- "id", ATTR_DOMAIN_POINT, 0);
- MutableSpan<int> ids = id_attribute.as_span();
- for (const int i : selection.index_range()) {
- ids[i] = instances.instance_ids()[selection[i]];
+ if (!instances.instance_ids().is_empty()) {
+ OutputAttribute_Typed<int> id_attribute = points.attribute_try_get_for_output<int>(
+ "id", ATTR_DOMAIN_POINT, CD_PROP_INT32);
+ MutableSpan<int> ids = id_attribute.as_span();
+ for (const int i : selection.index_range()) {
+ ids[i] = instances.instance_ids()[selection[i]];
+ }
+ id_attribute.save();
}
- id_attribute.save();
}
static void geo_node_instances_to_points_exec(GeoNodeExecParams params)
diff --git a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc
index b628c5cbab8..bbba8635b88 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc
@@ -270,17 +270,16 @@ static void join_components(Span<const InstancesComponent *> src_components, Geo
}
Span<float4x4> src_transforms = src_component->instance_transforms();
- Span<int> src_ids = src_component->instance_ids();
Span<int> src_reference_handles = src_component->instance_reference_handles();
for (const int i : src_transforms.index_range()) {
const int src_handle = src_reference_handles[i];
const int dst_handle = handle_map[src_handle];
const float4x4 &transform = src_transforms[i];
- const int id = src_ids[i];
- dst_component.add_instance(dst_handle, transform, id);
+ dst_component.add_instance(dst_handle, transform);
}
}
+ join_attributes(to_base_components(src_components), dst_component, {"position"});
}
static void join_components(Span<const VolumeComponent *> src_components, GeometrySet &result)
diff --git a/source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc b/source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc
index ac946540221..83526df3ac2 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc
@@ -242,13 +242,11 @@ static void add_instances_from_handles(InstancesComponent &instances,
instances.resize(positions.size());
MutableSpan<int> handles = instances.instance_reference_handles();
MutableSpan<float4x4> transforms = instances.instance_transforms();
- MutableSpan<int> instance_ids = instances.instance_ids();
threading::parallel_for(IndexRange(positions.size()), 256, [&](IndexRange range) {
for (const int i : range) {
handles[i] = char_handles.lookup(charcodes[i]);
transforms[i] = float4x4::from_location({positions[i].x, positions[i].y, 0});
- instance_ids[i] = i;
}
});
}