2023-08-16 00:20:26 +10:00
|
|
|
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
2023-05-31 16:19:06 +02:00
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
2021-03-08 11:41:23 -05:00
|
|
|
|
2021-09-27 10:16:38 +02:00
|
|
|
#include <mutex>
|
|
|
|
|
|
2021-12-29 11:31:58 -06:00
|
|
|
#include "BLI_index_mask.hh"
|
2021-03-08 11:41:23 -05:00
|
|
|
#include "BLI_map.hh"
|
2023-02-06 21:25:45 +01:00
|
|
|
#include "BLI_math_matrix_types.hh"
|
2021-03-08 11:41:23 -05:00
|
|
|
#include "BLI_rand.hh"
|
|
|
|
|
#include "BLI_set.hh"
|
|
|
|
|
#include "BLI_span.hh"
|
2021-09-27 10:16:38 +02:00
|
|
|
#include "BLI_task.hh"
|
2021-03-08 11:41:23 -05:00
|
|
|
#include "BLI_vector.hh"
|
|
|
|
|
|
|
|
|
|
#include "DNA_collection_types.h"
|
|
|
|
|
|
2021-12-29 11:31:58 -06:00
|
|
|
#include "BKE_attribute_math.hh"
|
2021-03-08 11:41:23 -05:00
|
|
|
#include "BKE_geometry_set.hh"
|
2021-09-21 14:20:54 -05:00
|
|
|
#include "BKE_geometry_set_instances.hh"
|
2022-10-17 11:39:40 +02:00
|
|
|
#include "BKE_instances.hh"
|
2021-03-08 11:41:23 -05:00
|
|
|
|
2021-09-20 12:49:11 +02:00
|
|
|
#include "attribute_access_intern.hh"
|
|
|
|
|
|
2022-03-18 10:57:45 +01:00
|
|
|
#include "BLI_cpp_type_make.hh"
|
2021-12-15 09:34:13 -06:00
|
|
|
|
2023-06-15 22:18:28 +02:00
|
|
|
namespace blender::bke {
|
|
|
|
|
|
2021-03-08 11:41:23 -05:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Geometry Component Implementation
|
|
|
|
|
* \{ */
|
|
|
|
|
|
2023-06-15 22:18:28 +02:00
|
|
|
InstancesComponent::InstancesComponent() : GeometryComponent(Type::Instance) {}
|
2021-03-08 11:41:23 -05:00
|
|
|
|
2022-10-17 11:39:40 +02:00
|
|
|
InstancesComponent::~InstancesComponent()
|
2021-03-08 11:41:23 -05:00
|
|
|
{
|
2022-10-17 11:39:40 +02:00
|
|
|
this->clear();
|
2021-03-08 11:41:23 -05:00
|
|
|
}
|
|
|
|
|
|
2022-10-17 11:39:40 +02:00
|
|
|
GeometryComponent *InstancesComponent::copy() const
|
2021-05-08 23:57:36 -05:00
|
|
|
{
|
2022-10-17 11:39:40 +02:00
|
|
|
InstancesComponent *new_component = new InstancesComponent();
|
|
|
|
|
if (instances_ != nullptr) {
|
2023-06-15 22:18:28 +02:00
|
|
|
new_component->instances_ = new Instances(*instances_);
|
2022-10-17 11:39:40 +02:00
|
|
|
new_component->ownership_ = GeometryOwnershipType::Owned;
|
|
|
|
|
}
|
|
|
|
|
return new_component;
|
2021-05-08 23:57:36 -05:00
|
|
|
}
|
|
|
|
|
|
2021-05-04 10:16:24 +02:00
|
|
|
void InstancesComponent::clear()
|
2021-03-08 11:41:23 -05:00
|
|
|
{
|
BLI: support weak users and version in implicit sharing info
The main goal of these changes is to support checking if some data has
been changed over time. This is used by the WIP simulation nodes during
baking to detect which attributes have to be stored in every frame because
they have changed.
By using a combination of a weak user count and a version counter, it is
possible to detect that an attribute (or any data controlled by implicit
sharing) has not been changed with O(1) memory and time. It's still
possible that the data has been changed multiple times and is the same
in the end and beginning of course. That wouldn't be detected using this
mechanism.
The `ImplicitSharingInfo` struct has a new weak user count. A weak
reference is one that does not keep the referenced data alive, but makes sure
that the `ImplicitSharingInfo` itself is not deleted. If some piece of
data has one strong and multiple weak users, it is still mutable. If the
strong user count goes down to zero, the referenced data is freed.
Remaining weak users can check for this condition using `is_expired`.
This is a bit similar to `std::weak_ptr` but there is an important difference:
a weak user can not become a strong user while one can create a `shared_ptr`
from a `weak_ptr`. This restriction is necessary, because some code might
be changing the referenced data assuming that it is the only owner. If
another thread suddenly adds a new owner, the data would be shared again
and the first thread would not have been allowed to modify the data in
the first place.
There is also a new integer version counter in `ImplicitSharingInfo`.
It is incremented whenever some code wants to modify the referenced data.
Obviously, this can only be done when the data is not shared because then
it would be immutable. By comparing an old and new version number of the
same sharing info, one can check if the data has been modified. One has
to keep a weak reference to the sharing info together with the old version
number to ensure that the new sharing info is still the same as the old one.
Without this, it can happen that the sharing info was freed and a new
one was allocated at the same pointer address. Using a strong reference
for this purpose does not work, because then the data would never be
modified because it's shared.
2023-04-28 12:03:42 +02:00
|
|
|
BLI_assert(this->is_mutable() || this->is_expired());
|
2022-10-17 11:39:40 +02:00
|
|
|
if (ownership_ == GeometryOwnershipType::Owned) {
|
|
|
|
|
delete instances_;
|
2021-12-29 11:31:58 -06:00
|
|
|
}
|
2022-10-17 11:39:40 +02:00
|
|
|
instances_ = nullptr;
|
2021-12-29 11:31:58 -06:00
|
|
|
}
|
|
|
|
|
|
2022-10-17 11:39:40 +02:00
|
|
|
bool InstancesComponent::is_empty() const
|
2021-09-27 10:16:38 +02:00
|
|
|
{
|
2022-10-17 11:39:40 +02:00
|
|
|
if (instances_ != nullptr) {
|
|
|
|
|
if (instances_->instances_num() > 0) {
|
|
|
|
|
return false;
|
2021-09-27 10:16:38 +02:00
|
|
|
}
|
|
|
|
|
}
|
2022-10-17 11:39:40 +02:00
|
|
|
return true;
|
2021-03-08 11:41:23 -05:00
|
|
|
}
|
|
|
|
|
|
2021-04-08 17:35:06 +02:00
|
|
|
bool InstancesComponent::owns_direct_data() const
|
|
|
|
|
{
|
2022-10-17 11:39:40 +02:00
|
|
|
if (instances_ != nullptr) {
|
|
|
|
|
return instances_->owns_direct_data();
|
2021-09-06 18:22:24 +02:00
|
|
|
}
|
2021-04-08 17:35:06 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void InstancesComponent::ensure_owns_direct_data()
|
|
|
|
|
{
|
2022-10-17 11:39:40 +02:00
|
|
|
if (instances_ != nullptr) {
|
|
|
|
|
instances_->ensure_owns_direct_data();
|
2021-09-06 18:22:24 +02:00
|
|
|
}
|
2021-04-08 17:35:06 +02:00
|
|
|
}
|
|
|
|
|
|
2023-08-03 17:09:18 +02:00
|
|
|
const Instances *InstancesComponent::get() const
|
2021-03-08 11:41:23 -05:00
|
|
|
{
|
2022-10-17 11:39:40 +02:00
|
|
|
return instances_;
|
2021-03-08 11:41:23 -05:00
|
|
|
}
|
|
|
|
|
|
2023-06-15 22:18:28 +02:00
|
|
|
Instances *InstancesComponent::get_for_write()
|
2021-03-08 11:41:23 -05:00
|
|
|
{
|
2022-10-17 11:39:40 +02:00
|
|
|
BLI_assert(this->is_mutable());
|
|
|
|
|
if (ownership_ == GeometryOwnershipType::ReadOnly) {
|
2023-06-15 22:18:28 +02:00
|
|
|
instances_ = new Instances(*instances_);
|
2022-10-17 11:39:40 +02:00
|
|
|
ownership_ = GeometryOwnershipType::Owned;
|
2021-03-08 11:41:23 -05:00
|
|
|
}
|
2022-10-17 11:39:40 +02:00
|
|
|
return instances_;
|
2021-03-08 11:41:23 -05:00
|
|
|
}
|
|
|
|
|
|
2023-06-15 22:18:28 +02:00
|
|
|
void InstancesComponent::replace(Instances *instances, GeometryOwnershipType ownership)
|
2021-11-19 17:53:48 +01:00
|
|
|
{
|
2022-10-17 11:39:40 +02:00
|
|
|
BLI_assert(this->is_mutable());
|
|
|
|
|
this->clear();
|
|
|
|
|
instances_ = instances;
|
|
|
|
|
ownership_ = ownership;
|
2021-11-19 17:53:48 +01:00
|
|
|
}
|
|
|
|
|
|
2021-09-20 12:49:11 +02:00
|
|
|
static float3 get_transform_position(const float4x4 &transform)
|
|
|
|
|
{
|
2023-02-06 21:25:45 +01:00
|
|
|
return transform.location();
|
2021-09-20 12:49:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void set_transform_position(float4x4 &transform, const float3 position)
|
|
|
|
|
{
|
2023-02-06 21:25:45 +01:00
|
|
|
transform.location() = position;
|
2021-09-20 12:49:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class InstancePositionAttributeProvider final : public BuiltinAttributeProvider {
|
|
|
|
|
public:
|
|
|
|
|
InstancePositionAttributeProvider()
|
|
|
|
|
: BuiltinAttributeProvider(
|
2023-02-20 11:51:16 +01:00
|
|
|
"position", ATTR_DOMAIN_INSTANCE, CD_PROP_FLOAT3, NonCreatable, NonDeletable)
|
2021-09-20 12:49:11 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-19 11:21:06 +02:00
|
|
|
GAttributeReader try_get_for_read(const void *owner) const final
|
2021-09-20 12:49:11 +02:00
|
|
|
{
|
2022-10-17 11:39:40 +02:00
|
|
|
const Instances *instances = static_cast<const Instances *>(owner);
|
|
|
|
|
if (instances == nullptr) {
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
Span<float4x4> transforms = instances->transforms();
|
2023-04-19 11:21:06 +02:00
|
|
|
return {VArray<float3>::ForDerivedSpan<float4x4, get_transform_position>(transforms),
|
|
|
|
|
domain_,
|
|
|
|
|
nullptr};
|
2021-09-20 12:49:11 +02:00
|
|
|
}
|
|
|
|
|
|
Geometry Nodes: new geometry attribute API
Currently, there are two attribute API. The first, defined in `BKE_attribute.h` is
accessible from RNA and C code. The second is implemented with `GeometryComponent`
and is only accessible in C++ code. The second is widely used, but only being
accessible through the `GeometrySet` API makes it awkward to use, and even impossible
for types that don't correspond directly to a geometry component like `CurvesGeometry`.
This patch adds a new attribute API, designed to replace the `GeometryComponent`
attribute API now, and to eventually replace or be the basis of the other one.
The basic idea is that there is an `AttributeAccessor` class that allows code to
interact with a set of attributes owned by some geometry. The accessor itself has
no ownership. `AttributeAccessor` is a simple type that can be passed around by
value. That makes it easy to return it from functions and to store it in containers.
For const-correctness, there is also a `MutableAttributeAccessor` that allows
changing individual and can add or remove attributes.
Currently, `AttributeAccessor` is composed of two pointers. The first is a pointer
to the owner of the attribute data. The second is a pointer to a struct with
function pointers, that is similar to a virtual function table. The functions
know how to access attributes on the owner.
The actual attribute access for geometries is still implemented with the `AttributeProvider`
pattern, which makes it easy to support different sources of attributes on a
geometry and simplifies dealing with built-in attributes.
There are different ways to get an attribute accessor for a geometry:
* `GeometryComponent.attributes()`
* `CurvesGeometry.attributes()`
* `bke::mesh_attributes(const Mesh &)`
* `bke::pointcloud_attributes(const PointCloud &)`
All of these also have a `_for_write` variant that returns a `MutabelAttributeAccessor`.
Differential Revision: https://developer.blender.org/D15280
2022-07-08 16:16:56 +02:00
|
|
|
GAttributeWriter try_get_for_write(void *owner) const final
|
2021-09-20 12:49:11 +02:00
|
|
|
{
|
2022-10-17 11:39:40 +02:00
|
|
|
Instances *instances = static_cast<Instances *>(owner);
|
|
|
|
|
if (instances == nullptr) {
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
MutableSpan<float4x4> transforms = instances->transforms();
|
Geometry Nodes: refactor virtual array system
Goals of this refactor:
* Simplify creating virtual arrays.
* Simplify passing virtual arrays around.
* Simplify converting between typed and generic virtual arrays.
* Reduce memory allocations.
As a quick reminder, a virtual arrays is a data structure that behaves like an
array (i.e. it can be accessed using an index). However, it may not actually
be stored as array internally. The two most important implementations
of virtual arrays are those that correspond to an actual plain array and those
that have the same value for every index. However, many more
implementations exist for various reasons (interfacing with legacy attributes,
unified iterator over all points in multiple splines, ...).
With this refactor the core types (`VArray`, `GVArray`, `VMutableArray` and
`GVMutableArray`) can be used like "normal values". They typically live
on the stack. Before, they were usually inside a `std::unique_ptr`. This makes
passing them around much easier. Creation of new virtual arrays is also
much simpler now due to some constructors. Memory allocations are
reduced by making use of small object optimization inside the core types.
Previously, `VArray` was a class with virtual methods that had to be overridden
to change the behavior of a the virtual array. Now,`VArray` has a fixed size
and has no virtual methods. Instead it contains a `VArrayImpl` that is
similar to the old `VArray`. `VArrayImpl` should rarely ever be used directly,
unless a new virtual array implementation is added.
To support the small object optimization for many `VArrayImpl` classes,
a new `blender::Any` type is added. It is similar to `std::any` with two
additional features. It has an adjustable inline buffer size and alignment.
The inline buffer size of `std::any` can't be relied on and is usually too
small for our use case here. Furthermore, `blender::Any` can store
additional user-defined type information without increasing the
stack size.
Differential Revision: https://developer.blender.org/D12986
2021-11-16 10:15:51 +01:00
|
|
|
return {VMutableArray<float3>::ForDerivedSpan<float4x4,
|
|
|
|
|
get_transform_position,
|
|
|
|
|
set_transform_position>(transforms),
|
|
|
|
|
domain_};
|
2021-09-20 12:49:11 +02:00
|
|
|
}
|
|
|
|
|
|
2022-10-03 17:37:25 -05:00
|
|
|
bool try_delete(void * /*owner*/) const final
|
2021-09-20 12:49:11 +02:00
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-03 17:37:25 -05:00
|
|
|
bool try_create(void * /*owner*/, const AttributeInit & /*initializer*/) const final
|
2021-09-20 12:49:11 +02:00
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-03 17:37:25 -05:00
|
|
|
bool exists(const void * /*owner*/) const final
|
2021-09-20 12:49:11 +02:00
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static ComponentAttributeProviders create_attribute_providers_for_instances()
|
|
|
|
|
{
|
|
|
|
|
static InstancePositionAttributeProvider position;
|
2021-11-19 17:53:48 +01:00
|
|
|
static CustomDataAccessInfo instance_custom_data_access = {
|
Geometry Nodes: new geometry attribute API
Currently, there are two attribute API. The first, defined in `BKE_attribute.h` is
accessible from RNA and C code. The second is implemented with `GeometryComponent`
and is only accessible in C++ code. The second is widely used, but only being
accessible through the `GeometrySet` API makes it awkward to use, and even impossible
for types that don't correspond directly to a geometry component like `CurvesGeometry`.
This patch adds a new attribute API, designed to replace the `GeometryComponent`
attribute API now, and to eventually replace or be the basis of the other one.
The basic idea is that there is an `AttributeAccessor` class that allows code to
interact with a set of attributes owned by some geometry. The accessor itself has
no ownership. `AttributeAccessor` is a simple type that can be passed around by
value. That makes it easy to return it from functions and to store it in containers.
For const-correctness, there is also a `MutableAttributeAccessor` that allows
changing individual and can add or remove attributes.
Currently, `AttributeAccessor` is composed of two pointers. The first is a pointer
to the owner of the attribute data. The second is a pointer to a struct with
function pointers, that is similar to a virtual function table. The functions
know how to access attributes on the owner.
The actual attribute access for geometries is still implemented with the `AttributeProvider`
pattern, which makes it easy to support different sources of attributes on a
geometry and simplifies dealing with built-in attributes.
There are different ways to get an attribute accessor for a geometry:
* `GeometryComponent.attributes()`
* `CurvesGeometry.attributes()`
* `bke::mesh_attributes(const Mesh &)`
* `bke::pointcloud_attributes(const PointCloud &)`
All of these also have a `_for_write` variant that returns a `MutabelAttributeAccessor`.
Differential Revision: https://developer.blender.org/D15280
2022-07-08 16:16:56 +02:00
|
|
|
[](void *owner) -> CustomData * {
|
2022-10-17 11:39:40 +02:00
|
|
|
Instances *instances = static_cast<Instances *>(owner);
|
2023-10-16 16:39:39 +02:00
|
|
|
return &instances->custom_data_attributes();
|
Geometry Nodes: new geometry attribute API
Currently, there are two attribute API. The first, defined in `BKE_attribute.h` is
accessible from RNA and C code. The second is implemented with `GeometryComponent`
and is only accessible in C++ code. The second is widely used, but only being
accessible through the `GeometrySet` API makes it awkward to use, and even impossible
for types that don't correspond directly to a geometry component like `CurvesGeometry`.
This patch adds a new attribute API, designed to replace the `GeometryComponent`
attribute API now, and to eventually replace or be the basis of the other one.
The basic idea is that there is an `AttributeAccessor` class that allows code to
interact with a set of attributes owned by some geometry. The accessor itself has
no ownership. `AttributeAccessor` is a simple type that can be passed around by
value. That makes it easy to return it from functions and to store it in containers.
For const-correctness, there is also a `MutableAttributeAccessor` that allows
changing individual and can add or remove attributes.
Currently, `AttributeAccessor` is composed of two pointers. The first is a pointer
to the owner of the attribute data. The second is a pointer to a struct with
function pointers, that is similar to a virtual function table. The functions
know how to access attributes on the owner.
The actual attribute access for geometries is still implemented with the `AttributeProvider`
pattern, which makes it easy to support different sources of attributes on a
geometry and simplifies dealing with built-in attributes.
There are different ways to get an attribute accessor for a geometry:
* `GeometryComponent.attributes()`
* `CurvesGeometry.attributes()`
* `bke::mesh_attributes(const Mesh &)`
* `bke::pointcloud_attributes(const PointCloud &)`
All of these also have a `_for_write` variant that returns a `MutabelAttributeAccessor`.
Differential Revision: https://developer.blender.org/D15280
2022-07-08 16:16:56 +02:00
|
|
|
},
|
|
|
|
|
[](const void *owner) -> const CustomData * {
|
2022-10-17 11:39:40 +02:00
|
|
|
const Instances *instances = static_cast<const Instances *>(owner);
|
2023-10-16 16:39:39 +02:00
|
|
|
return &instances->custom_data_attributes();
|
2021-11-19 17:53:48 +01:00
|
|
|
},
|
Geometry Nodes: new geometry attribute API
Currently, there are two attribute API. The first, defined in `BKE_attribute.h` is
accessible from RNA and C code. The second is implemented with `GeometryComponent`
and is only accessible in C++ code. The second is widely used, but only being
accessible through the `GeometrySet` API makes it awkward to use, and even impossible
for types that don't correspond directly to a geometry component like `CurvesGeometry`.
This patch adds a new attribute API, designed to replace the `GeometryComponent`
attribute API now, and to eventually replace or be the basis of the other one.
The basic idea is that there is an `AttributeAccessor` class that allows code to
interact with a set of attributes owned by some geometry. The accessor itself has
no ownership. `AttributeAccessor` is a simple type that can be passed around by
value. That makes it easy to return it from functions and to store it in containers.
For const-correctness, there is also a `MutableAttributeAccessor` that allows
changing individual and can add or remove attributes.
Currently, `AttributeAccessor` is composed of two pointers. The first is a pointer
to the owner of the attribute data. The second is a pointer to a struct with
function pointers, that is similar to a virtual function table. The functions
know how to access attributes on the owner.
The actual attribute access for geometries is still implemented with the `AttributeProvider`
pattern, which makes it easy to support different sources of attributes on a
geometry and simplifies dealing with built-in attributes.
There are different ways to get an attribute accessor for a geometry:
* `GeometryComponent.attributes()`
* `CurvesGeometry.attributes()`
* `bke::mesh_attributes(const Mesh &)`
* `bke::pointcloud_attributes(const PointCloud &)`
All of these also have a `_for_write` variant that returns a `MutabelAttributeAccessor`.
Differential Revision: https://developer.blender.org/D15280
2022-07-08 16:16:56 +02:00
|
|
|
[](const void *owner) -> int {
|
2022-10-17 11:39:40 +02:00
|
|
|
const Instances *instances = static_cast<const Instances *>(owner);
|
|
|
|
|
return instances->instances_num();
|
2022-09-06 09:43:32 -05:00
|
|
|
}};
|
2021-11-19 17:53:48 +01:00
|
|
|
|
2021-12-01 09:27:27 -05:00
|
|
|
/**
|
|
|
|
|
* IDs of the instances. They are used for consistency over multiple frames for things like
|
|
|
|
|
* 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.
|
|
|
|
|
*/
|
|
|
|
|
static BuiltinCustomDataLayerProvider id("id",
|
|
|
|
|
ATTR_DOMAIN_INSTANCE,
|
|
|
|
|
CD_PROP_INT32,
|
|
|
|
|
CD_PROP_INT32,
|
|
|
|
|
BuiltinAttributeProvider::Creatable,
|
|
|
|
|
BuiltinAttributeProvider::Deletable,
|
|
|
|
|
instance_custom_data_access,
|
|
|
|
|
nullptr);
|
|
|
|
|
|
2021-11-19 17:53:48 +01:00
|
|
|
static CustomDataAttributeProvider instance_custom_data(ATTR_DOMAIN_INSTANCE,
|
|
|
|
|
instance_custom_data_access);
|
|
|
|
|
|
|
|
|
|
return ComponentAttributeProviders({&position, &id}, {&instance_custom_data});
|
2021-09-20 12:49:11 +02:00
|
|
|
}
|
Geometry Nodes: new geometry attribute API
Currently, there are two attribute API. The first, defined in `BKE_attribute.h` is
accessible from RNA and C code. The second is implemented with `GeometryComponent`
and is only accessible in C++ code. The second is widely used, but only being
accessible through the `GeometrySet` API makes it awkward to use, and even impossible
for types that don't correspond directly to a geometry component like `CurvesGeometry`.
This patch adds a new attribute API, designed to replace the `GeometryComponent`
attribute API now, and to eventually replace or be the basis of the other one.
The basic idea is that there is an `AttributeAccessor` class that allows code to
interact with a set of attributes owned by some geometry. The accessor itself has
no ownership. `AttributeAccessor` is a simple type that can be passed around by
value. That makes it easy to return it from functions and to store it in containers.
For const-correctness, there is also a `MutableAttributeAccessor` that allows
changing individual and can add or remove attributes.
Currently, `AttributeAccessor` is composed of two pointers. The first is a pointer
to the owner of the attribute data. The second is a pointer to a struct with
function pointers, that is similar to a virtual function table. The functions
know how to access attributes on the owner.
The actual attribute access for geometries is still implemented with the `AttributeProvider`
pattern, which makes it easy to support different sources of attributes on a
geometry and simplifies dealing with built-in attributes.
There are different ways to get an attribute accessor for a geometry:
* `GeometryComponent.attributes()`
* `CurvesGeometry.attributes()`
* `bke::mesh_attributes(const Mesh &)`
* `bke::pointcloud_attributes(const PointCloud &)`
All of these also have a `_for_write` variant that returns a `MutabelAttributeAccessor`.
Differential Revision: https://developer.blender.org/D15280
2022-07-08 16:16:56 +02:00
|
|
|
|
|
|
|
|
static AttributeAccessorFunctions get_instances_accessor_functions()
|
|
|
|
|
{
|
|
|
|
|
static const ComponentAttributeProviders providers = create_attribute_providers_for_instances();
|
|
|
|
|
AttributeAccessorFunctions fn =
|
|
|
|
|
attribute_accessor_functions::accessor_functions_for_providers<providers>();
|
|
|
|
|
fn.domain_size = [](const void *owner, const eAttrDomain domain) {
|
|
|
|
|
if (owner == nullptr) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2022-10-17 11:39:40 +02:00
|
|
|
const Instances *instances = static_cast<const Instances *>(owner);
|
Geometry Nodes: new geometry attribute API
Currently, there are two attribute API. The first, defined in `BKE_attribute.h` is
accessible from RNA and C code. The second is implemented with `GeometryComponent`
and is only accessible in C++ code. The second is widely used, but only being
accessible through the `GeometrySet` API makes it awkward to use, and even impossible
for types that don't correspond directly to a geometry component like `CurvesGeometry`.
This patch adds a new attribute API, designed to replace the `GeometryComponent`
attribute API now, and to eventually replace or be the basis of the other one.
The basic idea is that there is an `AttributeAccessor` class that allows code to
interact with a set of attributes owned by some geometry. The accessor itself has
no ownership. `AttributeAccessor` is a simple type that can be passed around by
value. That makes it easy to return it from functions and to store it in containers.
For const-correctness, there is also a `MutableAttributeAccessor` that allows
changing individual and can add or remove attributes.
Currently, `AttributeAccessor` is composed of two pointers. The first is a pointer
to the owner of the attribute data. The second is a pointer to a struct with
function pointers, that is similar to a virtual function table. The functions
know how to access attributes on the owner.
The actual attribute access for geometries is still implemented with the `AttributeProvider`
pattern, which makes it easy to support different sources of attributes on a
geometry and simplifies dealing with built-in attributes.
There are different ways to get an attribute accessor for a geometry:
* `GeometryComponent.attributes()`
* `CurvesGeometry.attributes()`
* `bke::mesh_attributes(const Mesh &)`
* `bke::pointcloud_attributes(const PointCloud &)`
All of these also have a `_for_write` variant that returns a `MutabelAttributeAccessor`.
Differential Revision: https://developer.blender.org/D15280
2022-07-08 16:16:56 +02:00
|
|
|
switch (domain) {
|
|
|
|
|
case ATTR_DOMAIN_INSTANCE:
|
2022-10-17 11:39:40 +02:00
|
|
|
return instances->instances_num();
|
Geometry Nodes: new geometry attribute API
Currently, there are two attribute API. The first, defined in `BKE_attribute.h` is
accessible from RNA and C code. The second is implemented with `GeometryComponent`
and is only accessible in C++ code. The second is widely used, but only being
accessible through the `GeometrySet` API makes it awkward to use, and even impossible
for types that don't correspond directly to a geometry component like `CurvesGeometry`.
This patch adds a new attribute API, designed to replace the `GeometryComponent`
attribute API now, and to eventually replace or be the basis of the other one.
The basic idea is that there is an `AttributeAccessor` class that allows code to
interact with a set of attributes owned by some geometry. The accessor itself has
no ownership. `AttributeAccessor` is a simple type that can be passed around by
value. That makes it easy to return it from functions and to store it in containers.
For const-correctness, there is also a `MutableAttributeAccessor` that allows
changing individual and can add or remove attributes.
Currently, `AttributeAccessor` is composed of two pointers. The first is a pointer
to the owner of the attribute data. The second is a pointer to a struct with
function pointers, that is similar to a virtual function table. The functions
know how to access attributes on the owner.
The actual attribute access for geometries is still implemented with the `AttributeProvider`
pattern, which makes it easy to support different sources of attributes on a
geometry and simplifies dealing with built-in attributes.
There are different ways to get an attribute accessor for a geometry:
* `GeometryComponent.attributes()`
* `CurvesGeometry.attributes()`
* `bke::mesh_attributes(const Mesh &)`
* `bke::pointcloud_attributes(const PointCloud &)`
All of these also have a `_for_write` variant that returns a `MutabelAttributeAccessor`.
Differential Revision: https://developer.blender.org/D15280
2022-07-08 16:16:56 +02:00
|
|
|
default:
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
};
|
2022-10-03 17:37:25 -05:00
|
|
|
fn.domain_supported = [](const void * /*owner*/, const eAttrDomain domain) {
|
Geometry Nodes: new geometry attribute API
Currently, there are two attribute API. The first, defined in `BKE_attribute.h` is
accessible from RNA and C code. The second is implemented with `GeometryComponent`
and is only accessible in C++ code. The second is widely used, but only being
accessible through the `GeometrySet` API makes it awkward to use, and even impossible
for types that don't correspond directly to a geometry component like `CurvesGeometry`.
This patch adds a new attribute API, designed to replace the `GeometryComponent`
attribute API now, and to eventually replace or be the basis of the other one.
The basic idea is that there is an `AttributeAccessor` class that allows code to
interact with a set of attributes owned by some geometry. The accessor itself has
no ownership. `AttributeAccessor` is a simple type that can be passed around by
value. That makes it easy to return it from functions and to store it in containers.
For const-correctness, there is also a `MutableAttributeAccessor` that allows
changing individual and can add or remove attributes.
Currently, `AttributeAccessor` is composed of two pointers. The first is a pointer
to the owner of the attribute data. The second is a pointer to a struct with
function pointers, that is similar to a virtual function table. The functions
know how to access attributes on the owner.
The actual attribute access for geometries is still implemented with the `AttributeProvider`
pattern, which makes it easy to support different sources of attributes on a
geometry and simplifies dealing with built-in attributes.
There are different ways to get an attribute accessor for a geometry:
* `GeometryComponent.attributes()`
* `CurvesGeometry.attributes()`
* `bke::mesh_attributes(const Mesh &)`
* `bke::pointcloud_attributes(const PointCloud &)`
All of these also have a `_for_write` variant that returns a `MutabelAttributeAccessor`.
Differential Revision: https://developer.blender.org/D15280
2022-07-08 16:16:56 +02:00
|
|
|
return domain == ATTR_DOMAIN_INSTANCE;
|
|
|
|
|
};
|
2022-10-03 17:37:25 -05:00
|
|
|
fn.adapt_domain = [](const void * /*owner*/,
|
2023-06-08 08:29:15 -04:00
|
|
|
const GVArray &varray,
|
Geometry Nodes: new geometry attribute API
Currently, there are two attribute API. The first, defined in `BKE_attribute.h` is
accessible from RNA and C code. The second is implemented with `GeometryComponent`
and is only accessible in C++ code. The second is widely used, but only being
accessible through the `GeometrySet` API makes it awkward to use, and even impossible
for types that don't correspond directly to a geometry component like `CurvesGeometry`.
This patch adds a new attribute API, designed to replace the `GeometryComponent`
attribute API now, and to eventually replace or be the basis of the other one.
The basic idea is that there is an `AttributeAccessor` class that allows code to
interact with a set of attributes owned by some geometry. The accessor itself has
no ownership. `AttributeAccessor` is a simple type that can be passed around by
value. That makes it easy to return it from functions and to store it in containers.
For const-correctness, there is also a `MutableAttributeAccessor` that allows
changing individual and can add or remove attributes.
Currently, `AttributeAccessor` is composed of two pointers. The first is a pointer
to the owner of the attribute data. The second is a pointer to a struct with
function pointers, that is similar to a virtual function table. The functions
know how to access attributes on the owner.
The actual attribute access for geometries is still implemented with the `AttributeProvider`
pattern, which makes it easy to support different sources of attributes on a
geometry and simplifies dealing with built-in attributes.
There are different ways to get an attribute accessor for a geometry:
* `GeometryComponent.attributes()`
* `CurvesGeometry.attributes()`
* `bke::mesh_attributes(const Mesh &)`
* `bke::pointcloud_attributes(const PointCloud &)`
All of these also have a `_for_write` variant that returns a `MutabelAttributeAccessor`.
Differential Revision: https://developer.blender.org/D15280
2022-07-08 16:16:56 +02:00
|
|
|
const eAttrDomain from_domain,
|
|
|
|
|
const eAttrDomain to_domain) {
|
|
|
|
|
if (from_domain == to_domain && from_domain == ATTR_DOMAIN_INSTANCE) {
|
|
|
|
|
return varray;
|
|
|
|
|
}
|
2023-06-08 08:29:15 -04:00
|
|
|
return GVArray{};
|
Geometry Nodes: new geometry attribute API
Currently, there are two attribute API. The first, defined in `BKE_attribute.h` is
accessible from RNA and C code. The second is implemented with `GeometryComponent`
and is only accessible in C++ code. The second is widely used, but only being
accessible through the `GeometrySet` API makes it awkward to use, and even impossible
for types that don't correspond directly to a geometry component like `CurvesGeometry`.
This patch adds a new attribute API, designed to replace the `GeometryComponent`
attribute API now, and to eventually replace or be the basis of the other one.
The basic idea is that there is an `AttributeAccessor` class that allows code to
interact with a set of attributes owned by some geometry. The accessor itself has
no ownership. `AttributeAccessor` is a simple type that can be passed around by
value. That makes it easy to return it from functions and to store it in containers.
For const-correctness, there is also a `MutableAttributeAccessor` that allows
changing individual and can add or remove attributes.
Currently, `AttributeAccessor` is composed of two pointers. The first is a pointer
to the owner of the attribute data. The second is a pointer to a struct with
function pointers, that is similar to a virtual function table. The functions
know how to access attributes on the owner.
The actual attribute access for geometries is still implemented with the `AttributeProvider`
pattern, which makes it easy to support different sources of attributes on a
geometry and simplifies dealing with built-in attributes.
There are different ways to get an attribute accessor for a geometry:
* `GeometryComponent.attributes()`
* `CurvesGeometry.attributes()`
* `bke::mesh_attributes(const Mesh &)`
* `bke::pointcloud_attributes(const PointCloud &)`
All of these also have a `_for_write` variant that returns a `MutabelAttributeAccessor`.
Differential Revision: https://developer.blender.org/D15280
2022-07-08 16:16:56 +02:00
|
|
|
};
|
|
|
|
|
return fn;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const AttributeAccessorFunctions &get_instances_accessor_functions_ref()
|
|
|
|
|
{
|
|
|
|
|
static const AttributeAccessorFunctions fn = get_instances_accessor_functions();
|
|
|
|
|
return fn;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-15 22:18:28 +02:00
|
|
|
AttributeAccessor Instances::attributes() const
|
2022-10-17 11:39:40 +02:00
|
|
|
{
|
2023-06-15 22:18:28 +02:00
|
|
|
return AttributeAccessor(this, get_instances_accessor_functions_ref());
|
2022-10-17 11:39:40 +02:00
|
|
|
}
|
|
|
|
|
|
2023-06-15 22:18:28 +02:00
|
|
|
MutableAttributeAccessor Instances::attributes_for_write()
|
2022-10-17 11:39:40 +02:00
|
|
|
{
|
2023-06-15 22:18:28 +02:00
|
|
|
return MutableAttributeAccessor(this, get_instances_accessor_functions_ref());
|
2022-10-17 11:39:40 +02:00
|
|
|
}
|
|
|
|
|
|
2023-06-15 22:18:28 +02:00
|
|
|
std::optional<AttributeAccessor> InstancesComponent::attributes() const
|
Geometry Nodes: new geometry attribute API
Currently, there are two attribute API. The first, defined in `BKE_attribute.h` is
accessible from RNA and C code. The second is implemented with `GeometryComponent`
and is only accessible in C++ code. The second is widely used, but only being
accessible through the `GeometrySet` API makes it awkward to use, and even impossible
for types that don't correspond directly to a geometry component like `CurvesGeometry`.
This patch adds a new attribute API, designed to replace the `GeometryComponent`
attribute API now, and to eventually replace or be the basis of the other one.
The basic idea is that there is an `AttributeAccessor` class that allows code to
interact with a set of attributes owned by some geometry. The accessor itself has
no ownership. `AttributeAccessor` is a simple type that can be passed around by
value. That makes it easy to return it from functions and to store it in containers.
For const-correctness, there is also a `MutableAttributeAccessor` that allows
changing individual and can add or remove attributes.
Currently, `AttributeAccessor` is composed of two pointers. The first is a pointer
to the owner of the attribute data. The second is a pointer to a struct with
function pointers, that is similar to a virtual function table. The functions
know how to access attributes on the owner.
The actual attribute access for geometries is still implemented with the `AttributeProvider`
pattern, which makes it easy to support different sources of attributes on a
geometry and simplifies dealing with built-in attributes.
There are different ways to get an attribute accessor for a geometry:
* `GeometryComponent.attributes()`
* `CurvesGeometry.attributes()`
* `bke::mesh_attributes(const Mesh &)`
* `bke::pointcloud_attributes(const PointCloud &)`
All of these also have a `_for_write` variant that returns a `MutabelAttributeAccessor`.
Differential Revision: https://developer.blender.org/D15280
2022-07-08 16:16:56 +02:00
|
|
|
{
|
2023-06-15 22:18:28 +02:00
|
|
|
return AttributeAccessor(instances_, get_instances_accessor_functions_ref());
|
Geometry Nodes: new geometry attribute API
Currently, there are two attribute API. The first, defined in `BKE_attribute.h` is
accessible from RNA and C code. The second is implemented with `GeometryComponent`
and is only accessible in C++ code. The second is widely used, but only being
accessible through the `GeometrySet` API makes it awkward to use, and even impossible
for types that don't correspond directly to a geometry component like `CurvesGeometry`.
This patch adds a new attribute API, designed to replace the `GeometryComponent`
attribute API now, and to eventually replace or be the basis of the other one.
The basic idea is that there is an `AttributeAccessor` class that allows code to
interact with a set of attributes owned by some geometry. The accessor itself has
no ownership. `AttributeAccessor` is a simple type that can be passed around by
value. That makes it easy to return it from functions and to store it in containers.
For const-correctness, there is also a `MutableAttributeAccessor` that allows
changing individual and can add or remove attributes.
Currently, `AttributeAccessor` is composed of two pointers. The first is a pointer
to the owner of the attribute data. The second is a pointer to a struct with
function pointers, that is similar to a virtual function table. The functions
know how to access attributes on the owner.
The actual attribute access for geometries is still implemented with the `AttributeProvider`
pattern, which makes it easy to support different sources of attributes on a
geometry and simplifies dealing with built-in attributes.
There are different ways to get an attribute accessor for a geometry:
* `GeometryComponent.attributes()`
* `CurvesGeometry.attributes()`
* `bke::mesh_attributes(const Mesh &)`
* `bke::pointcloud_attributes(const PointCloud &)`
All of these also have a `_for_write` variant that returns a `MutabelAttributeAccessor`.
Differential Revision: https://developer.blender.org/D15280
2022-07-08 16:16:56 +02:00
|
|
|
}
|
|
|
|
|
|
2023-06-15 22:18:28 +02:00
|
|
|
std::optional<MutableAttributeAccessor> InstancesComponent::attributes_for_write()
|
2021-09-20 12:49:11 +02:00
|
|
|
{
|
2023-06-15 22:18:28 +02:00
|
|
|
return MutableAttributeAccessor(instances_, get_instances_accessor_functions_ref());
|
2021-09-20 12:49:11 +02:00
|
|
|
}
|
|
|
|
|
|
2021-03-08 11:41:23 -05:00
|
|
|
/** \} */
|
2023-06-15 22:18:28 +02:00
|
|
|
|
|
|
|
|
} // namespace blender::bke
|