Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/geometry_component_instances.cc
| Show First 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | GeometryComponent *InstancesComponent::copy() const | ||||
| new_component->references_ = references_; | new_component->references_ = references_; | ||||
| return new_component; | return new_component; | ||||
| } | } | ||||
| void InstancesComponent::reserve(int min_capacity) | void InstancesComponent::reserve(int min_capacity) | ||||
| { | { | ||||
| instance_reference_handles_.reserve(min_capacity); | instance_reference_handles_.reserve(min_capacity); | ||||
| instance_transforms_.reserve(min_capacity); | instance_transforms_.reserve(min_capacity); | ||||
| instance_ids_.reserve(min_capacity); | |||||
| } | } | ||||
| /** | /** | ||||
| * Resize the transform, handles, and ID vectors to the specified capacity. | * Resize the transform, handles, and ID vectors to the specified capacity. | ||||
| * | * | ||||
| * \note This function should be used carefully, only when it's guaranteed | * \note This function should be used carefully, only when it's guaranteed | ||||
| * that the data will be filled. | * that the data will be filled. | ||||
| */ | */ | ||||
| void InstancesComponent::resize(int capacity) | void InstancesComponent::resize(int capacity) | ||||
| { | { | ||||
| instance_reference_handles_.resize(capacity); | instance_reference_handles_.resize(capacity); | ||||
JacquesLucke: unused variable | |||||
| instance_transforms_.resize(capacity); | instance_transforms_.resize(capacity); | ||||
| instance_ids_.resize(capacity); | |||||
| } | } | ||||
| void InstancesComponent::clear() | void InstancesComponent::clear() | ||||
| { | { | ||||
| instance_reference_handles_.clear(); | instance_reference_handles_.clear(); | ||||
| instance_transforms_.clear(); | instance_transforms_.clear(); | ||||
| instance_ids_.clear(); | instance_ids_.clear(); | ||||
| references_.clear(); | references_.clear(); | ||||
| } | } | ||||
| void InstancesComponent::add_instance(const int instance_handle, | void InstancesComponent::add_instance(const int instance_handle, const float4x4 &transform) | ||||
| const float4x4 &transform, | |||||
| const int id) | |||||
| { | { | ||||
| BLI_assert(instance_handle >= 0); | BLI_assert(instance_handle >= 0); | ||||
| BLI_assert(instance_handle < references_.size()); | BLI_assert(instance_handle < references_.size()); | ||||
| instance_reference_handles_.append(instance_handle); | instance_reference_handles_.append(instance_handle); | ||||
| instance_transforms_.append(transform); | instance_transforms_.append(transform); | ||||
JacquesLuckeUnsubmitted Done Inline ActionsThis has to increase the size of the ids vector, otherwise the sizes go out of sync. JacquesLucke: This has to increase the size of the ids vector, otherwise the sizes go out of sync. | |||||
| } | |||||
| void InstancesComponent::add_instance(const int instance_handle, | |||||
JacquesLuckeUnsubmitted Done Inline ActionsThink we can remove this method now. It doesn't seem to be used. JacquesLucke: Think we can remove this method now. It doesn't seem to be used. | |||||
| const float4x4 &transform, | |||||
| const int id) | |||||
| { | |||||
| /* If the ID array is shorter than the total number of instances, fill the difference with the | |||||
| * default value. */ | |||||
| if (instance_ids_.size() < this->instances_amount()) { | |||||
| instance_ids_.append_n_times(-1, this->instances_amount() - instance_ids_.size()); | |||||
| } | |||||
| instance_ids_.append(id); | instance_ids_.append(id); | ||||
| this->add_instance(instance_handle, transform); | |||||
| } | } | ||||
| blender::Span<int> InstancesComponent::instance_reference_handles() const | blender::Span<int> InstancesComponent::instance_reference_handles() const | ||||
| { | { | ||||
| return instance_reference_handles_; | return instance_reference_handles_; | ||||
| } | } | ||||
| blender::MutableSpan<int> InstancesComponent::instance_reference_handles() | blender::MutableSpan<int> InstancesComponent::instance_reference_handles() | ||||
| Show All 14 Lines | |||||
| { | { | ||||
| return instance_ids_; | return instance_ids_; | ||||
| } | } | ||||
| blender::Span<int> InstancesComponent::instance_ids() const | blender::Span<int> InstancesComponent::instance_ids() const | ||||
| { | { | ||||
| return instance_ids_; | return instance_ids_; | ||||
| } | } | ||||
| blender::MutableSpan<int> InstancesComponent::instance_ids_add() | |||||
| { | |||||
| instance_ids_.resize(this->instances_amount()); | |||||
| 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 | * 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` | * changed. This is a function on the component rather than each reference to ensure `const` | ||||
| * correctness for that reason. | * correctness for that reason. | ||||
| */ | */ | ||||
| GeometrySet &InstancesComponent::geometry_set_from_reference(const int reference_index) | GeometrySet &InstancesComponent::geometry_set_from_reference(const int reference_index) | ||||
| { | { | ||||
| /* If this assert fails, it means #ensure_geometry_instances must be called first or that the | /* If this assert fails, it means #ensure_geometry_instances must be called first or that the | ||||
| ▲ Show 20 Lines • Show All 187 Lines • ▼ Show 20 Lines | static blender::Array<int> generate_unique_instance_ids(Span<int> original_ids) | ||||
| } | } | ||||
| return unique_ids; | return unique_ids; | ||||
| } | } | ||||
| blender::Span<int> InstancesComponent::almost_unique_ids() const | blender::Span<int> InstancesComponent::almost_unique_ids() const | ||||
| { | { | ||||
| std::lock_guard lock(almost_unique_ids_mutex_); | std::lock_guard lock(almost_unique_ids_mutex_); | ||||
| 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()) { | if (almost_unique_ids_.size() != instance_ids_.size()) { | ||||
| almost_unique_ids_ = generate_unique_instance_ids(instance_ids_); | almost_unique_ids_ = generate_unique_instance_ids(instance_ids_); | ||||
| } | } | ||||
| } | |||||
| return almost_unique_ids_; | return almost_unique_ids_; | ||||
| } | } | ||||
| int InstancesComponent::attribute_domain_size(const AttributeDomain domain) const | int InstancesComponent::attribute_domain_size(const AttributeDomain domain) const | ||||
| { | { | ||||
| if (domain != ATTR_DOMAIN_POINT) { | if (domain != ATTR_DOMAIN_POINT) { | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | public: | ||||
| } | } | ||||
| bool exists(const GeometryComponent &UNUSED(component)) const final | bool exists(const GeometryComponent &UNUSED(component)) const final | ||||
| { | { | ||||
| return true; | return true; | ||||
| } | } | ||||
| }; | }; | ||||
| 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_add(); | |||||
| switch (initializer.type) { | |||||
| case AttributeInit::Type::Default: { | |||||
| ids.fill(-1); | |||||
JacquesLuckeUnsubmitted Done Inline ActionsThink we can use the default 0 now. -1 probably doesn't make too much sense in general. Don't remember why we used that originally. JacquesLucke: Think we can use the default 0 now. -1 probably doesn't make too much sense in general. Don't… | |||||
| 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 ComponentAttributeProviders create_attribute_providers_for_instances() | ||||
| { | { | ||||
| static InstancePositionAttributeProvider position; | static InstancePositionAttributeProvider position; | ||||
| static InstanceIDAttributeProvider id; | |||||
| return ComponentAttributeProviders({&position}, {}); | return ComponentAttributeProviders({&position, &id}, {}); | ||||
| } | } | ||||
| } // namespace blender::bke | } // namespace blender::bke | ||||
| const blender::bke::ComponentAttributeProviders *InstancesComponent::get_attribute_providers() | const blender::bke::ComponentAttributeProviders *InstancesComponent::get_attribute_providers() | ||||
| const | const | ||||
| { | { | ||||
| static blender::bke::ComponentAttributeProviders providers = | static blender::bke::ComponentAttributeProviders providers = | ||||
| blender::bke::create_attribute_providers_for_instances(); | blender::bke::create_attribute_providers_for_instances(); | ||||
| return &providers; | return &providers; | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
unused variable