2020-12-02 13:25:25 +01:00
|
|
|
/*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <utility>
|
|
|
|
|
|
|
|
#include "BKE_attribute_access.hh"
|
2021-02-09 11:44:58 +01:00
|
|
|
#include "BKE_attribute_math.hh"
|
2020-12-02 13:25:25 +01:00
|
|
|
#include "BKE_customdata.h"
|
|
|
|
#include "BKE_deform.h"
|
|
|
|
#include "BKE_geometry_set.hh"
|
|
|
|
#include "BKE_mesh.h"
|
|
|
|
#include "BKE_pointcloud.h"
|
|
|
|
|
|
|
|
#include "DNA_mesh_types.h"
|
|
|
|
#include "DNA_meshdata_types.h"
|
|
|
|
#include "DNA_pointcloud_types.h"
|
|
|
|
|
|
|
|
#include "BLI_color.hh"
|
|
|
|
#include "BLI_float2.hh"
|
|
|
|
#include "BLI_span.hh"
|
|
|
|
|
|
|
|
#include "CLG_log.h"
|
|
|
|
|
2021-04-15 09:35:56 +02:00
|
|
|
#include "NOD_type_conversions.hh"
|
2020-12-02 13:25:25 +01:00
|
|
|
|
2021-03-08 16:31:51 -05:00
|
|
|
#include "attribute_access_intern.hh"
|
|
|
|
|
2020-12-02 13:25:25 +01:00
|
|
|
static CLG_LogRef LOG = {"bke.attribute_access"};
|
|
|
|
|
|
|
|
using blender::float3;
|
|
|
|
using blender::Set;
|
|
|
|
using blender::StringRef;
|
2021-01-14 15:52:08 +01:00
|
|
|
using blender::StringRefNull;
|
|
|
|
using blender::fn::GMutableSpan;
|
2021-05-19 13:22:09 -04:00
|
|
|
using blender::fn::GSpan;
|
2021-06-02 08:24:42 -04:00
|
|
|
using blender::fn::GVArray_For_GSpan;
|
|
|
|
using blender::fn::GVArray_For_SingleValue;
|
2020-12-02 13:25:25 +01:00
|
|
|
|
|
|
|
namespace blender::bke {
|
|
|
|
|
|
|
|
const blender::fn::CPPType *custom_data_type_to_cpp_type(const CustomDataType type)
|
|
|
|
{
|
|
|
|
switch (type) {
|
|
|
|
case CD_PROP_FLOAT:
|
|
|
|
return &CPPType::get<float>();
|
|
|
|
case CD_PROP_FLOAT2:
|
|
|
|
return &CPPType::get<float2>();
|
|
|
|
case CD_PROP_FLOAT3:
|
|
|
|
return &CPPType::get<float3>();
|
|
|
|
case CD_PROP_INT32:
|
|
|
|
return &CPPType::get<int>();
|
|
|
|
case CD_PROP_COLOR:
|
2021-05-25 17:16:35 +02:00
|
|
|
return &CPPType::get<ColorGeometry4f>();
|
2020-12-16 12:33:13 -06:00
|
|
|
case CD_PROP_BOOL:
|
|
|
|
return &CPPType::get<bool>();
|
2020-12-02 13:25:25 +01:00
|
|
|
default:
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
CustomDataType cpp_type_to_custom_data_type(const blender::fn::CPPType &type)
|
|
|
|
{
|
|
|
|
if (type.is<float>()) {
|
|
|
|
return CD_PROP_FLOAT;
|
|
|
|
}
|
|
|
|
if (type.is<float2>()) {
|
|
|
|
return CD_PROP_FLOAT2;
|
|
|
|
}
|
|
|
|
if (type.is<float3>()) {
|
|
|
|
return CD_PROP_FLOAT3;
|
|
|
|
}
|
|
|
|
if (type.is<int>()) {
|
|
|
|
return CD_PROP_INT32;
|
|
|
|
}
|
2021-05-25 17:16:35 +02:00
|
|
|
if (type.is<ColorGeometry4f>()) {
|
2020-12-02 13:25:25 +01:00
|
|
|
return CD_PROP_COLOR;
|
|
|
|
}
|
2020-12-16 12:33:13 -06:00
|
|
|
if (type.is<bool>()) {
|
|
|
|
return CD_PROP_BOOL;
|
|
|
|
}
|
2021-03-08 16:31:51 -05:00
|
|
|
return static_cast<CustomDataType>(-1);
|
2021-02-09 11:24:28 +01:00
|
|
|
}
|
|
|
|
|
2021-03-08 16:31:51 -05:00
|
|
|
static int attribute_data_type_complexity(const CustomDataType data_type)
|
2021-02-09 11:24:28 +01:00
|
|
|
{
|
2021-03-08 16:31:51 -05:00
|
|
|
switch (data_type) {
|
|
|
|
case CD_PROP_BOOL:
|
|
|
|
return 0;
|
|
|
|
case CD_PROP_INT32:
|
|
|
|
return 1;
|
|
|
|
case CD_PROP_FLOAT:
|
|
|
|
return 2;
|
|
|
|
case CD_PROP_FLOAT2:
|
|
|
|
return 3;
|
|
|
|
case CD_PROP_FLOAT3:
|
|
|
|
return 4;
|
|
|
|
case CD_PROP_COLOR:
|
|
|
|
return 5;
|
|
|
|
#if 0 /* These attribute types are not supported yet. */
|
|
|
|
case CD_MLOOPCOL:
|
|
|
|
return 3;
|
|
|
|
case CD_PROP_STRING:
|
|
|
|
return 6;
|
|
|
|
#endif
|
|
|
|
default:
|
|
|
|
/* Only accept "generic" custom data types used by the attribute system. */
|
2021-03-23 16:49:47 +01:00
|
|
|
BLI_assert_unreachable();
|
2021-03-08 16:31:51 -05:00
|
|
|
return 0;
|
|
|
|
}
|
2020-12-02 13:25:25 +01:00
|
|
|
}
|
|
|
|
|
2021-03-08 16:31:51 -05:00
|
|
|
CustomDataType attribute_data_type_highest_complexity(Span<CustomDataType> data_types)
|
2020-12-02 13:25:25 +01:00
|
|
|
{
|
2021-03-08 16:31:51 -05:00
|
|
|
int highest_complexity = INT_MIN;
|
|
|
|
CustomDataType most_complex_type = CD_PROP_COLOR;
|
2020-12-02 13:25:25 +01:00
|
|
|
|
2021-03-08 16:31:51 -05:00
|
|
|
for (const CustomDataType data_type : data_types) {
|
|
|
|
const int complexity = attribute_data_type_complexity(data_type);
|
|
|
|
if (complexity > highest_complexity) {
|
|
|
|
highest_complexity = complexity;
|
|
|
|
most_complex_type = data_type;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return most_complex_type;
|
2020-12-02 13:25:25 +01:00
|
|
|
}
|
|
|
|
|
2021-03-08 16:31:51 -05:00
|
|
|
/**
|
|
|
|
* \note Generally the order should mirror the order of the domains
|
|
|
|
* established in each component's ComponentAttributeProviders.
|
|
|
|
*/
|
|
|
|
static int attribute_domain_priority(const AttributeDomain domain)
|
2021-02-12 11:31:15 +01:00
|
|
|
{
|
2021-03-08 16:31:51 -05:00
|
|
|
switch (domain) {
|
|
|
|
case ATTR_DOMAIN_CURVE:
|
|
|
|
return 0;
|
2021-03-25 12:01:42 +01:00
|
|
|
case ATTR_DOMAIN_FACE:
|
2021-03-08 16:31:51 -05:00
|
|
|
return 1;
|
|
|
|
case ATTR_DOMAIN_EDGE:
|
|
|
|
return 2;
|
|
|
|
case ATTR_DOMAIN_POINT:
|
|
|
|
return 3;
|
|
|
|
case ATTR_DOMAIN_CORNER:
|
|
|
|
return 4;
|
|
|
|
default:
|
|
|
|
/* Domain not supported in nodes yet. */
|
2021-03-23 16:49:47 +01:00
|
|
|
BLI_assert_unreachable();
|
2021-03-08 16:31:51 -05:00
|
|
|
return 0;
|
2021-02-12 11:31:15 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-08 16:31:51 -05:00
|
|
|
/**
|
|
|
|
* Domains with a higher "information density" have a higher priority, in order
|
|
|
|
* to choose a domain that will not lose data through domain conversion.
|
|
|
|
*/
|
|
|
|
AttributeDomain attribute_domain_highest_priority(Span<AttributeDomain> domains)
|
2021-02-17 08:30:15 -06:00
|
|
|
{
|
2021-03-08 16:31:51 -05:00
|
|
|
int highest_priority = INT_MIN;
|
|
|
|
AttributeDomain highest_priority_domain = ATTR_DOMAIN_CORNER;
|
2021-02-17 08:30:15 -06:00
|
|
|
|
2021-03-08 16:31:51 -05:00
|
|
|
for (const AttributeDomain domain : domains) {
|
|
|
|
const int priority = attribute_domain_priority(domain);
|
|
|
|
if (priority > highest_priority) {
|
|
|
|
highest_priority = priority;
|
|
|
|
highest_priority_domain = domain;
|
|
|
|
}
|
|
|
|
}
|
2021-02-17 08:30:15 -06:00
|
|
|
|
2021-03-08 16:31:51 -05:00
|
|
|
return highest_priority_domain;
|
2021-02-17 08:30:15 -06:00
|
|
|
}
|
|
|
|
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
void OutputAttribute::save()
|
|
|
|
{
|
2021-04-23 12:44:59 +02:00
|
|
|
save_has_been_called_ = true;
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
if (optional_span_varray_.has_value()) {
|
|
|
|
optional_span_varray_->save();
|
|
|
|
}
|
|
|
|
if (save_) {
|
|
|
|
save_(*this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-23 12:44:59 +02:00
|
|
|
OutputAttribute::~OutputAttribute()
|
|
|
|
{
|
|
|
|
if (!save_has_been_called_) {
|
|
|
|
if (varray_) {
|
|
|
|
std::cout << "Warning: Call `save()` to make sure that changes persist in all cases.\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
GVArrayPtr BuiltinCustomDataLayerProvider::try_get_for_read(
|
2021-03-08 16:31:51 -05:00
|
|
|
const GeometryComponent &component) const
|
2021-02-17 08:30:15 -06:00
|
|
|
{
|
2021-03-08 16:31:51 -05:00
|
|
|
const CustomData *custom_data = custom_data_access_.get_const_custom_data(component);
|
|
|
|
if (custom_data == nullptr) {
|
|
|
|
return {};
|
|
|
|
}
|
2021-02-17 08:30:15 -06:00
|
|
|
|
2021-03-08 16:31:51 -05:00
|
|
|
const int domain_size = component.attribute_domain_size(domain_);
|
|
|
|
const void *data = CustomData_get_layer(custom_data, stored_type_);
|
|
|
|
if (data == nullptr) {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
return as_read_attribute_(data, domain_size);
|
2021-03-05 15:16:25 -06:00
|
|
|
}
|
|
|
|
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
GVMutableArrayPtr BuiltinCustomDataLayerProvider::try_get_for_write(
|
2021-03-08 16:31:51 -05:00
|
|
|
GeometryComponent &component) const
|
2021-03-05 15:16:25 -06:00
|
|
|
{
|
2021-03-08 16:31:51 -05:00
|
|
|
if (writable_ != Writable) {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
CustomData *custom_data = custom_data_access_.get_custom_data(component);
|
|
|
|
if (custom_data == nullptr) {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
const int domain_size = component.attribute_domain_size(domain_);
|
|
|
|
void *data = CustomData_get_layer(custom_data, stored_type_);
|
|
|
|
if (data == nullptr) {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
void *new_data = CustomData_duplicate_referenced_layer(custom_data, stored_type_, domain_size);
|
|
|
|
if (data != new_data) {
|
|
|
|
custom_data_access_.update_custom_data_pointers(component);
|
|
|
|
data = new_data;
|
|
|
|
}
|
|
|
|
if (update_on_write_ != nullptr) {
|
|
|
|
update_on_write_(component);
|
|
|
|
}
|
|
|
|
return as_write_attribute_(data, domain_size);
|
2021-03-05 15:16:25 -06:00
|
|
|
}
|
|
|
|
|
2021-03-08 16:31:51 -05:00
|
|
|
bool BuiltinCustomDataLayerProvider::try_delete(GeometryComponent &component) const
|
2021-03-05 15:16:25 -06:00
|
|
|
{
|
2021-03-08 16:31:51 -05:00
|
|
|
if (deletable_ != Deletable) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
CustomData *custom_data = custom_data_access_.get_custom_data(component);
|
|
|
|
if (custom_data == nullptr) {
|
|
|
|
return {};
|
2021-03-05 15:16:25 -06:00
|
|
|
}
|
|
|
|
|
2021-03-08 16:31:51 -05:00
|
|
|
const int domain_size = component.attribute_domain_size(domain_);
|
|
|
|
const int layer_index = CustomData_get_layer_index(custom_data, stored_type_);
|
|
|
|
const bool delete_success = CustomData_free_layer(
|
|
|
|
custom_data, stored_type_, domain_size, layer_index);
|
|
|
|
if (delete_success) {
|
|
|
|
custom_data_access_.update_custom_data_pointers(component);
|
2021-03-05 15:16:25 -06:00
|
|
|
}
|
2021-03-08 16:31:51 -05:00
|
|
|
return delete_success;
|
2021-03-05 15:16:25 -06:00
|
|
|
}
|
|
|
|
|
2021-04-22 09:20:03 -05:00
|
|
|
static bool add_custom_data_layer_from_attribute_init(CustomData &custom_data,
|
|
|
|
const CustomDataType data_type,
|
|
|
|
const int domain_size,
|
|
|
|
const AttributeInit &initializer)
|
|
|
|
{
|
|
|
|
switch (initializer.type) {
|
|
|
|
case AttributeInit::Type::Default: {
|
|
|
|
void *data = CustomData_add_layer(&custom_data, data_type, CD_DEFAULT, nullptr, domain_size);
|
|
|
|
return data != nullptr;
|
|
|
|
}
|
|
|
|
case AttributeInit::Type::VArray: {
|
|
|
|
void *data = CustomData_add_layer(&custom_data, data_type, CD_DEFAULT, nullptr, domain_size);
|
|
|
|
if (data == nullptr) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
const GVArray *varray = static_cast<const AttributeInitVArray &>(initializer).varray;
|
|
|
|
varray->materialize_to_uninitialized(IndexRange(varray->size()), data);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
case AttributeInit::Type::MoveArray: {
|
|
|
|
void *source_data = static_cast<const AttributeInitMove &>(initializer).data;
|
|
|
|
void *data = CustomData_add_layer(
|
|
|
|
&custom_data, data_type, CD_ASSIGN, source_data, domain_size);
|
|
|
|
if (data == nullptr) {
|
|
|
|
MEM_freeN(source_data);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BLI_assert_unreachable();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BuiltinCustomDataLayerProvider::try_create(GeometryComponent &component,
|
|
|
|
const AttributeInit &initializer) const
|
2021-02-18 10:24:02 +01:00
|
|
|
{
|
2021-03-08 16:31:51 -05:00
|
|
|
if (createable_ != Creatable) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
CustomData *custom_data = custom_data_access_.get_custom_data(component);
|
|
|
|
if (custom_data == nullptr) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (CustomData_get_layer(custom_data, stored_type_) != nullptr) {
|
|
|
|
/* Exists already. */
|
|
|
|
return false;
|
|
|
|
}
|
2021-04-22 09:20:03 -05:00
|
|
|
|
2021-03-08 16:31:51 -05:00
|
|
|
const int domain_size = component.attribute_domain_size(domain_);
|
2021-04-22 09:20:03 -05:00
|
|
|
const bool success = add_custom_data_layer_from_attribute_init(
|
|
|
|
*custom_data, stored_type_, domain_size, initializer);
|
2021-03-08 16:31:51 -05:00
|
|
|
if (success) {
|
|
|
|
custom_data_access_.update_custom_data_pointers(component);
|
|
|
|
}
|
|
|
|
return success;
|
2021-02-18 10:24:02 +01:00
|
|
|
}
|
|
|
|
|
2021-03-08 16:31:51 -05:00
|
|
|
bool BuiltinCustomDataLayerProvider::exists(const GeometryComponent &component) const
|
2021-02-18 10:24:02 +01:00
|
|
|
{
|
2021-03-08 16:31:51 -05:00
|
|
|
const CustomData *custom_data = custom_data_access_.get_const_custom_data(component);
|
|
|
|
if (custom_data == nullptr) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
const void *data = CustomData_get_layer(custom_data, stored_type_);
|
|
|
|
return data != nullptr;
|
2021-02-18 10:24:02 +01:00
|
|
|
}
|
|
|
|
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
ReadAttributeLookup CustomDataAttributeProvider::try_get_for_read(
|
2021-03-08 16:31:51 -05:00
|
|
|
const GeometryComponent &component, const StringRef attribute_name) const
|
2021-02-18 10:24:02 +01:00
|
|
|
{
|
2021-03-08 16:31:51 -05:00
|
|
|
const CustomData *custom_data = custom_data_access_.get_const_custom_data(component);
|
|
|
|
if (custom_data == nullptr) {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
const int domain_size = component.attribute_domain_size(domain_);
|
|
|
|
for (const CustomDataLayer &layer : Span(custom_data->layers, custom_data->totlayer)) {
|
|
|
|
if (layer.name != attribute_name) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
const CustomDataType data_type = (CustomDataType)layer.type;
|
|
|
|
switch (data_type) {
|
|
|
|
case CD_PROP_FLOAT:
|
|
|
|
return this->layer_to_read_attribute<float>(layer, domain_size);
|
|
|
|
case CD_PROP_FLOAT2:
|
|
|
|
return this->layer_to_read_attribute<float2>(layer, domain_size);
|
|
|
|
case CD_PROP_FLOAT3:
|
|
|
|
return this->layer_to_read_attribute<float3>(layer, domain_size);
|
|
|
|
case CD_PROP_INT32:
|
|
|
|
return this->layer_to_read_attribute<int>(layer, domain_size);
|
|
|
|
case CD_PROP_COLOR:
|
2021-05-25 17:16:35 +02:00
|
|
|
return this->layer_to_read_attribute<ColorGeometry4f>(layer, domain_size);
|
2021-03-08 16:31:51 -05:00
|
|
|
case CD_PROP_BOOL:
|
|
|
|
return this->layer_to_read_attribute<bool>(layer, domain_size);
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return {};
|
2021-02-18 10:24:02 +01:00
|
|
|
}
|
|
|
|
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
WriteAttributeLookup CustomDataAttributeProvider::try_get_for_write(
|
2021-03-08 16:31:51 -05:00
|
|
|
GeometryComponent &component, const StringRef attribute_name) const
|
2021-02-18 10:24:02 +01:00
|
|
|
{
|
2021-03-08 16:31:51 -05:00
|
|
|
CustomData *custom_data = custom_data_access_.get_custom_data(component);
|
|
|
|
if (custom_data == nullptr) {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
const int domain_size = component.attribute_domain_size(domain_);
|
|
|
|
for (CustomDataLayer &layer : MutableSpan(custom_data->layers, custom_data->totlayer)) {
|
|
|
|
if (layer.name != attribute_name) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
CustomData_duplicate_referenced_layer_named(custom_data, layer.type, layer.name, domain_size);
|
|
|
|
const CustomDataType data_type = (CustomDataType)layer.type;
|
|
|
|
switch (data_type) {
|
|
|
|
case CD_PROP_FLOAT:
|
|
|
|
return this->layer_to_write_attribute<float>(layer, domain_size);
|
|
|
|
case CD_PROP_FLOAT2:
|
|
|
|
return this->layer_to_write_attribute<float2>(layer, domain_size);
|
|
|
|
case CD_PROP_FLOAT3:
|
|
|
|
return this->layer_to_write_attribute<float3>(layer, domain_size);
|
|
|
|
case CD_PROP_INT32:
|
|
|
|
return this->layer_to_write_attribute<int>(layer, domain_size);
|
|
|
|
case CD_PROP_COLOR:
|
2021-05-25 17:16:35 +02:00
|
|
|
return this->layer_to_write_attribute<ColorGeometry4f>(layer, domain_size);
|
2021-03-08 16:31:51 -05:00
|
|
|
case CD_PROP_BOOL:
|
|
|
|
return this->layer_to_write_attribute<bool>(layer, domain_size);
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return {};
|
2021-02-18 10:24:02 +01:00
|
|
|
}
|
|
|
|
|
2021-03-08 16:31:51 -05:00
|
|
|
bool CustomDataAttributeProvider::try_delete(GeometryComponent &component,
|
|
|
|
const StringRef attribute_name) const
|
2021-02-18 10:24:02 +01:00
|
|
|
{
|
2021-03-08 16:31:51 -05:00
|
|
|
CustomData *custom_data = custom_data_access_.get_custom_data(component);
|
|
|
|
if (custom_data == nullptr) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
const int domain_size = component.attribute_domain_size(domain_);
|
|
|
|
for (const int i : IndexRange(custom_data->totlayer)) {
|
|
|
|
const CustomDataLayer &layer = custom_data->layers[i];
|
|
|
|
if (this->type_is_supported((CustomDataType)layer.type) && layer.name == attribute_name) {
|
|
|
|
CustomData_free_layer(custom_data, layer.type, domain_size, i);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
2021-02-18 10:24:02 +01:00
|
|
|
}
|
|
|
|
|
2021-04-22 09:20:03 -05:00
|
|
|
static bool add_named_custom_data_layer_from_attribute_init(const StringRef attribute_name,
|
|
|
|
CustomData &custom_data,
|
|
|
|
const CustomDataType data_type,
|
|
|
|
const int domain_size,
|
|
|
|
const AttributeInit &initializer)
|
|
|
|
{
|
|
|
|
char attribute_name_c[MAX_NAME];
|
|
|
|
attribute_name.copy(attribute_name_c);
|
|
|
|
|
|
|
|
switch (initializer.type) {
|
|
|
|
case AttributeInit::Type::Default: {
|
|
|
|
void *data = CustomData_add_layer_named(
|
|
|
|
&custom_data, data_type, CD_DEFAULT, nullptr, domain_size, attribute_name_c);
|
|
|
|
return data != nullptr;
|
|
|
|
}
|
|
|
|
case AttributeInit::Type::VArray: {
|
|
|
|
void *data = CustomData_add_layer_named(
|
|
|
|
&custom_data, data_type, CD_DEFAULT, nullptr, domain_size, attribute_name_c);
|
|
|
|
if (data == nullptr) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
const GVArray *varray = static_cast<const AttributeInitVArray &>(initializer).varray;
|
|
|
|
varray->materialize_to_uninitialized(IndexRange(varray->size()), data);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
case AttributeInit::Type::MoveArray: {
|
|
|
|
void *source_data = static_cast<const AttributeInitMove &>(initializer).data;
|
|
|
|
void *data = CustomData_add_layer_named(
|
|
|
|
&custom_data, data_type, CD_ASSIGN, source_data, domain_size, attribute_name_c);
|
|
|
|
if (data == nullptr) {
|
|
|
|
MEM_freeN(source_data);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BLI_assert_unreachable();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-03-08 16:31:51 -05:00
|
|
|
bool CustomDataAttributeProvider::try_create(GeometryComponent &component,
|
|
|
|
const StringRef attribute_name,
|
|
|
|
const AttributeDomain domain,
|
2021-04-22 09:20:03 -05:00
|
|
|
const CustomDataType data_type,
|
|
|
|
const AttributeInit &initializer) const
|
2021-02-18 10:24:02 +01:00
|
|
|
{
|
2021-03-08 16:31:51 -05:00
|
|
|
if (domain_ != domain) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!this->type_is_supported(data_type)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
CustomData *custom_data = custom_data_access_.get_custom_data(component);
|
|
|
|
if (custom_data == nullptr) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
for (const CustomDataLayer &layer : Span(custom_data->layers, custom_data->totlayer)) {
|
|
|
|
if (layer.name == attribute_name) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const int domain_size = component.attribute_domain_size(domain_);
|
2021-04-22 09:20:03 -05:00
|
|
|
add_named_custom_data_layer_from_attribute_init(
|
|
|
|
attribute_name, *custom_data, data_type, domain_size, initializer);
|
2021-03-08 16:31:51 -05:00
|
|
|
return true;
|
2021-02-18 10:24:02 +01:00
|
|
|
}
|
|
|
|
|
2021-03-08 16:31:51 -05:00
|
|
|
bool CustomDataAttributeProvider::foreach_attribute(const GeometryComponent &component,
|
|
|
|
const AttributeForeachCallback callback) const
|
2021-02-18 10:24:02 +01:00
|
|
|
{
|
2021-03-08 16:31:51 -05:00
|
|
|
const CustomData *custom_data = custom_data_access_.get_const_custom_data(component);
|
|
|
|
if (custom_data == nullptr) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
for (const CustomDataLayer &layer : Span(custom_data->layers, custom_data->totlayer)) {
|
|
|
|
const CustomDataType data_type = (CustomDataType)layer.type;
|
|
|
|
if (this->type_is_supported(data_type)) {
|
|
|
|
AttributeMetaData meta_data{domain_, data_type};
|
|
|
|
if (!callback(layer.name, meta_data)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
2021-02-18 10:24:02 +01:00
|
|
|
}
|
|
|
|
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
ReadAttributeLookup NamedLegacyCustomDataProvider::try_get_for_read(
|
2021-03-08 16:31:51 -05:00
|
|
|
const GeometryComponent &component, const StringRef attribute_name) const
|
2021-02-18 10:24:02 +01:00
|
|
|
{
|
2021-03-08 16:31:51 -05:00
|
|
|
const CustomData *custom_data = custom_data_access_.get_const_custom_data(component);
|
|
|
|
if (custom_data == nullptr) {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
for (const CustomDataLayer &layer : Span(custom_data->layers, custom_data->totlayer)) {
|
|
|
|
if (layer.type == stored_type_) {
|
|
|
|
if (layer.name == attribute_name) {
|
|
|
|
const int domain_size = component.attribute_domain_size(domain_);
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
return {as_read_attribute_(layer.data, domain_size), domain_};
|
2021-03-08 16:31:51 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return {};
|
2021-02-18 10:24:02 +01:00
|
|
|
}
|
|
|
|
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
WriteAttributeLookup NamedLegacyCustomDataProvider::try_get_for_write(
|
2021-03-08 16:31:51 -05:00
|
|
|
GeometryComponent &component, const StringRef attribute_name) const
|
2020-12-02 13:25:25 +01:00
|
|
|
{
|
2021-03-08 16:31:51 -05:00
|
|
|
CustomData *custom_data = custom_data_access_.get_custom_data(component);
|
|
|
|
if (custom_data == nullptr) {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
for (CustomDataLayer &layer : MutableSpan(custom_data->layers, custom_data->totlayer)) {
|
|
|
|
if (layer.type == stored_type_) {
|
|
|
|
if (layer.name == attribute_name) {
|
|
|
|
const int domain_size = component.attribute_domain_size(domain_);
|
|
|
|
void *data_old = layer.data;
|
|
|
|
void *data_new = CustomData_duplicate_referenced_layer_named(
|
|
|
|
custom_data, stored_type_, layer.name, domain_size);
|
|
|
|
if (data_old != data_new) {
|
|
|
|
custom_data_access_.update_custom_data_pointers(component);
|
|
|
|
}
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
return {as_write_attribute_(layer.data, domain_size), domain_};
|
2021-03-08 16:31:51 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return {};
|
2021-02-09 11:24:28 +01:00
|
|
|
}
|
|
|
|
|
2021-03-08 16:31:51 -05:00
|
|
|
bool NamedLegacyCustomDataProvider::try_delete(GeometryComponent &component,
|
|
|
|
const StringRef attribute_name) const
|
2021-02-09 11:24:28 +01:00
|
|
|
{
|
2021-03-08 16:31:51 -05:00
|
|
|
CustomData *custom_data = custom_data_access_.get_custom_data(component);
|
|
|
|
if (custom_data == nullptr) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
for (const int i : IndexRange(custom_data->totlayer)) {
|
|
|
|
const CustomDataLayer &layer = custom_data->layers[i];
|
|
|
|
if (layer.type == stored_type_) {
|
|
|
|
if (layer.name == attribute_name) {
|
|
|
|
const int domain_size = component.attribute_domain_size(domain_);
|
|
|
|
CustomData_free_layer(custom_data, stored_type_, domain_size, i);
|
|
|
|
custom_data_access_.update_custom_data_pointers(component);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
2021-02-09 11:24:28 +01:00
|
|
|
}
|
|
|
|
|
2021-03-08 16:31:51 -05:00
|
|
|
bool NamedLegacyCustomDataProvider::foreach_attribute(
|
|
|
|
const GeometryComponent &component, const AttributeForeachCallback callback) const
|
2021-02-09 11:24:28 +01:00
|
|
|
{
|
2021-03-08 16:31:51 -05:00
|
|
|
const CustomData *custom_data = custom_data_access_.get_const_custom_data(component);
|
|
|
|
if (custom_data == nullptr) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
for (const CustomDataLayer &layer : Span(custom_data->layers, custom_data->totlayer)) {
|
|
|
|
if (layer.type == stored_type_) {
|
|
|
|
AttributeMetaData meta_data{domain_, attribute_type_};
|
|
|
|
if (!callback(layer.name, meta_data)) {
|
|
|
|
return false;
|
|
|
|
}
|
2020-12-02 13:25:25 +01:00
|
|
|
}
|
2021-03-08 16:31:51 -05:00
|
|
|
}
|
|
|
|
return true;
|
2020-12-02 13:25:25 +01:00
|
|
|
}
|
|
|
|
|
2021-03-17 11:50:13 +01:00
|
|
|
void NamedLegacyCustomDataProvider::foreach_domain(
|
|
|
|
const FunctionRef<void(AttributeDomain)> callback) const
|
2020-12-02 13:25:25 +01:00
|
|
|
{
|
2021-03-17 11:50:13 +01:00
|
|
|
callback(domain_);
|
2020-12-02 13:25:25 +01:00
|
|
|
}
|
|
|
|
|
2021-05-19 13:22:09 -04:00
|
|
|
CustomDataAttributes::CustomDataAttributes()
|
|
|
|
{
|
|
|
|
CustomData_reset(&data);
|
|
|
|
size_ = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
CustomDataAttributes::~CustomDataAttributes()
|
|
|
|
{
|
|
|
|
CustomData_free(&data, size_);
|
|
|
|
}
|
|
|
|
|
|
|
|
CustomDataAttributes::CustomDataAttributes(const CustomDataAttributes &other)
|
|
|
|
{
|
|
|
|
size_ = other.size_;
|
|
|
|
CustomData_copy(&other.data, &data, CD_MASK_ALL, CD_DUPLICATE, size_);
|
|
|
|
}
|
|
|
|
|
|
|
|
CustomDataAttributes::CustomDataAttributes(CustomDataAttributes &&other)
|
|
|
|
{
|
|
|
|
size_ = other.size_;
|
|
|
|
data = other.data;
|
|
|
|
CustomData_reset(&other.data);
|
|
|
|
}
|
|
|
|
|
2021-06-09 15:54:26 -05:00
|
|
|
CustomDataAttributes &CustomDataAttributes::operator=(const CustomDataAttributes &other)
|
|
|
|
{
|
|
|
|
if (this != &other) {
|
|
|
|
CustomData_copy(&other.data, &data, CD_MASK_ALL, CD_DUPLICATE, other.size_);
|
|
|
|
size_ = other.size_;
|
|
|
|
}
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2021-05-19 13:22:09 -04:00
|
|
|
std::optional<GSpan> CustomDataAttributes::get_for_read(const StringRef name) const
|
|
|
|
{
|
|
|
|
BLI_assert(size_ != 0);
|
|
|
|
for (const CustomDataLayer &layer : Span(data.layers, data.totlayer)) {
|
|
|
|
if (layer.name == name) {
|
|
|
|
const CPPType *cpp_type = custom_data_type_to_cpp_type((CustomDataType)layer.type);
|
|
|
|
BLI_assert(cpp_type != nullptr);
|
|
|
|
return GSpan(*cpp_type, layer.data, size_);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2021-06-02 08:24:42 -04:00
|
|
|
/**
|
|
|
|
* Return a virtual array for a stored attribute, or a single value virtual array with the default
|
|
|
|
* value if the attribute doesn't exist. If no default value is provided, the default value for the
|
|
|
|
* type will be used.
|
|
|
|
*/
|
|
|
|
GVArrayPtr CustomDataAttributes::get_for_read(const StringRef name,
|
|
|
|
const CustomDataType data_type,
|
|
|
|
const void *default_value) const
|
|
|
|
{
|
|
|
|
const CPPType *type = blender::bke::custom_data_type_to_cpp_type(data_type);
|
|
|
|
|
|
|
|
std::optional<GSpan> attribute = this->get_for_read(name);
|
|
|
|
if (!attribute) {
|
|
|
|
const int domain_size = this->size_;
|
|
|
|
return std::make_unique<GVArray_For_SingleValue>(
|
|
|
|
*type, domain_size, (default_value == nullptr) ? type->default_value() : default_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (attribute->type() == *type) {
|
|
|
|
return std::make_unique<GVArray_For_GSpan>(*attribute);
|
|
|
|
}
|
|
|
|
const blender::nodes::DataTypeConversions &conversions =
|
|
|
|
blender::nodes::get_implicit_type_conversions();
|
|
|
|
return conversions.try_convert(std::make_unique<GVArray_For_GSpan>(*attribute), *type);
|
|
|
|
}
|
|
|
|
|
2021-05-19 13:22:09 -04:00
|
|
|
std::optional<GMutableSpan> CustomDataAttributes::get_for_write(const StringRef name)
|
|
|
|
{
|
2021-06-03 18:06:14 -04:00
|
|
|
/* If this assert hits, it most likely means that #reallocate was not called at some point. */
|
2021-05-19 13:22:09 -04:00
|
|
|
BLI_assert(size_ != 0);
|
|
|
|
for (CustomDataLayer &layer : MutableSpan(data.layers, data.totlayer)) {
|
|
|
|
if (layer.name == name) {
|
|
|
|
const CPPType *cpp_type = custom_data_type_to_cpp_type((CustomDataType)layer.type);
|
|
|
|
BLI_assert(cpp_type != nullptr);
|
|
|
|
return GMutableSpan(*cpp_type, layer.data, size_);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CustomDataAttributes::create(const StringRef name, const CustomDataType data_type)
|
|
|
|
{
|
|
|
|
char name_c[MAX_NAME];
|
|
|
|
name.copy(name_c);
|
|
|
|
void *result = CustomData_add_layer_named(&data, data_type, CD_DEFAULT, nullptr, size_, name_c);
|
|
|
|
return result != nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CustomDataAttributes::create_by_move(const blender::StringRef name,
|
|
|
|
const CustomDataType data_type,
|
|
|
|
void *buffer)
|
|
|
|
{
|
|
|
|
char name_c[MAX_NAME];
|
|
|
|
name.copy(name_c);
|
|
|
|
void *result = CustomData_add_layer_named(&data, data_type, CD_ASSIGN, buffer, size_, name_c);
|
|
|
|
return result != nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CustomDataAttributes::remove(const blender::StringRef name)
|
|
|
|
{
|
|
|
|
bool result = false;
|
|
|
|
for (const int i : IndexRange(data.totlayer)) {
|
|
|
|
const CustomDataLayer &layer = data.layers[i];
|
|
|
|
if (layer.name == name) {
|
|
|
|
CustomData_free_layer(&data, layer.type, size_, i);
|
|
|
|
result = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CustomDataAttributes::reallocate(const int size)
|
|
|
|
{
|
|
|
|
size_ = size;
|
|
|
|
CustomData_realloc(&data, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CustomDataAttributes::foreach_attribute(const AttributeForeachCallback callback,
|
|
|
|
const AttributeDomain domain) const
|
|
|
|
{
|
|
|
|
for (const CustomDataLayer &layer : Span(data.layers, data.totlayer)) {
|
|
|
|
AttributeMetaData meta_data{domain, (CustomDataType)layer.type};
|
|
|
|
if (!callback(layer.name, meta_data)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-02-09 11:24:28 +01:00
|
|
|
} // namespace blender::bke
|
2020-12-02 13:25:25 +01:00
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Geometry Component
|
|
|
|
* \{ */
|
|
|
|
|
2021-02-09 11:24:28 +01:00
|
|
|
const blender::bke::ComponentAttributeProviders *GeometryComponent::get_attribute_providers() const
|
2020-12-02 13:25:25 +01:00
|
|
|
{
|
2021-02-09 11:24:28 +01:00
|
|
|
return nullptr;
|
2020-12-02 13:25:25 +01:00
|
|
|
}
|
|
|
|
|
2021-02-09 11:24:28 +01:00
|
|
|
bool GeometryComponent::attribute_domain_supported(const AttributeDomain domain) const
|
2020-12-02 13:25:25 +01:00
|
|
|
{
|
2021-02-09 11:24:28 +01:00
|
|
|
using namespace blender::bke;
|
|
|
|
const ComponentAttributeProviders *providers = this->get_attribute_providers();
|
|
|
|
if (providers == nullptr) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return providers->supported_domains().contains(domain);
|
2020-12-02 13:25:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int GeometryComponent::attribute_domain_size(const AttributeDomain UNUSED(domain)) const
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
bool GeometryComponent::attribute_is_builtin(const blender::StringRef attribute_name) const
|
|
|
|
{
|
|
|
|
using namespace blender::bke;
|
|
|
|
const ComponentAttributeProviders *providers = this->get_attribute_providers();
|
|
|
|
if (providers == nullptr) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return providers->builtin_attribute_providers().contains_as(attribute_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
blender::bke::ReadAttributeLookup GeometryComponent::attribute_try_get_for_read(
|
2021-02-09 11:24:28 +01:00
|
|
|
const StringRef attribute_name) const
|
2020-12-02 13:25:25 +01:00
|
|
|
{
|
2021-02-09 11:24:28 +01:00
|
|
|
using namespace blender::bke;
|
|
|
|
const ComponentAttributeProviders *providers = this->get_attribute_providers();
|
|
|
|
if (providers == nullptr) {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
const BuiltinAttributeProvider *builtin_provider =
|
|
|
|
providers->builtin_attribute_providers().lookup_default_as(attribute_name, nullptr);
|
|
|
|
if (builtin_provider != nullptr) {
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
return {builtin_provider->try_get_for_read(*this), builtin_provider->domain()};
|
2021-02-09 11:24:28 +01:00
|
|
|
}
|
|
|
|
for (const DynamicAttributesProvider *dynamic_provider :
|
|
|
|
providers->dynamic_attribute_providers()) {
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
ReadAttributeLookup attribute = dynamic_provider->try_get_for_read(*this, attribute_name);
|
2021-02-09 11:24:28 +01:00
|
|
|
if (attribute) {
|
|
|
|
return attribute;
|
|
|
|
}
|
|
|
|
}
|
2020-12-02 13:25:25 +01:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_adapt_domain(
|
|
|
|
std::unique_ptr<blender::fn::GVArray> varray,
|
|
|
|
const AttributeDomain from_domain,
|
|
|
|
const AttributeDomain to_domain) const
|
2020-12-02 13:25:25 +01:00
|
|
|
{
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
if (from_domain == to_domain) {
|
|
|
|
return varray;
|
2020-12-02 13:25:25 +01:00
|
|
|
}
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
blender::bke::WriteAttributeLookup GeometryComponent::attribute_try_get_for_write(
|
|
|
|
const StringRef attribute_name)
|
2020-12-02 13:25:25 +01:00
|
|
|
{
|
2021-02-09 11:24:28 +01:00
|
|
|
using namespace blender::bke;
|
|
|
|
const ComponentAttributeProviders *providers = this->get_attribute_providers();
|
|
|
|
if (providers == nullptr) {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
const BuiltinAttributeProvider *builtin_provider =
|
|
|
|
providers->builtin_attribute_providers().lookup_default_as(attribute_name, nullptr);
|
|
|
|
if (builtin_provider != nullptr) {
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
return {builtin_provider->try_get_for_write(*this), builtin_provider->domain()};
|
2021-02-09 11:24:28 +01:00
|
|
|
}
|
|
|
|
for (const DynamicAttributesProvider *dynamic_provider :
|
|
|
|
providers->dynamic_attribute_providers()) {
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
WriteAttributeLookup attribute = dynamic_provider->try_get_for_write(*this, attribute_name);
|
2021-02-09 11:24:28 +01:00
|
|
|
if (attribute) {
|
|
|
|
return attribute;
|
|
|
|
}
|
|
|
|
}
|
2020-12-02 13:25:25 +01:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2021-02-09 11:24:28 +01:00
|
|
|
bool GeometryComponent::attribute_try_delete(const StringRef attribute_name)
|
2020-12-02 13:25:25 +01:00
|
|
|
{
|
2021-02-09 11:24:28 +01:00
|
|
|
using namespace blender::bke;
|
|
|
|
const ComponentAttributeProviders *providers = this->get_attribute_providers();
|
|
|
|
if (providers == nullptr) {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
const BuiltinAttributeProvider *builtin_provider =
|
|
|
|
providers->builtin_attribute_providers().lookup_default_as(attribute_name, nullptr);
|
|
|
|
if (builtin_provider != nullptr) {
|
|
|
|
return builtin_provider->try_delete(*this);
|
|
|
|
}
|
|
|
|
bool success = false;
|
|
|
|
for (const DynamicAttributesProvider *dynamic_provider :
|
|
|
|
providers->dynamic_attribute_providers()) {
|
|
|
|
success = dynamic_provider->try_delete(*this, attribute_name) || success;
|
|
|
|
}
|
|
|
|
return success;
|
2020-12-02 13:25:25 +01:00
|
|
|
}
|
|
|
|
|
2021-02-09 11:24:28 +01:00
|
|
|
bool GeometryComponent::attribute_try_create(const StringRef attribute_name,
|
|
|
|
const AttributeDomain domain,
|
2021-04-22 09:20:03 -05:00
|
|
|
const CustomDataType data_type,
|
|
|
|
const AttributeInit &initializer)
|
2020-12-02 13:25:25 +01:00
|
|
|
{
|
2021-02-09 11:24:28 +01:00
|
|
|
using namespace blender::bke;
|
2021-02-19 18:08:40 +01:00
|
|
|
if (attribute_name.is_empty()) {
|
|
|
|
return false;
|
|
|
|
}
|
2021-02-09 11:24:28 +01:00
|
|
|
const ComponentAttributeProviders *providers = this->get_attribute_providers();
|
|
|
|
if (providers == nullptr) {
|
2021-02-19 18:08:40 +01:00
|
|
|
return false;
|
2021-02-09 11:24:28 +01:00
|
|
|
}
|
|
|
|
const BuiltinAttributeProvider *builtin_provider =
|
|
|
|
providers->builtin_attribute_providers().lookup_default_as(attribute_name, nullptr);
|
|
|
|
if (builtin_provider != nullptr) {
|
|
|
|
if (builtin_provider->domain() != domain) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (builtin_provider->data_type() != data_type) {
|
|
|
|
return false;
|
|
|
|
}
|
2021-04-22 09:20:03 -05:00
|
|
|
return builtin_provider->try_create(*this, initializer);
|
2021-02-09 11:24:28 +01:00
|
|
|
}
|
|
|
|
for (const DynamicAttributesProvider *dynamic_provider :
|
|
|
|
providers->dynamic_attribute_providers()) {
|
2021-04-22 09:20:03 -05:00
|
|
|
if (dynamic_provider->try_create(*this, attribute_name, domain, data_type, initializer)) {
|
2021-02-09 11:24:28 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2020-12-02 13:25:25 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-04-22 09:20:03 -05:00
|
|
|
bool GeometryComponent::attribute_try_create_builtin(const blender::StringRef attribute_name,
|
|
|
|
const AttributeInit &initializer)
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
{
|
|
|
|
using namespace blender::bke;
|
|
|
|
if (attribute_name.is_empty()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
const ComponentAttributeProviders *providers = this->get_attribute_providers();
|
|
|
|
if (providers == nullptr) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
const BuiltinAttributeProvider *builtin_provider =
|
|
|
|
providers->builtin_attribute_providers().lookup_default_as(attribute_name, nullptr);
|
|
|
|
if (builtin_provider == nullptr) {
|
|
|
|
return false;
|
|
|
|
}
|
2021-04-22 09:20:03 -05:00
|
|
|
return builtin_provider->try_create(*this, initializer);
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
}
|
|
|
|
|
2020-12-02 13:25:25 +01:00
|
|
|
Set<std::string> GeometryComponent::attribute_names() const
|
2021-02-23 15:15:23 +01:00
|
|
|
{
|
|
|
|
Set<std::string> attributes;
|
|
|
|
this->attribute_foreach([&](StringRefNull name, const AttributeMetaData &UNUSED(meta_data)) {
|
|
|
|
attributes.add(name);
|
|
|
|
return true;
|
|
|
|
});
|
|
|
|
return attributes;
|
|
|
|
}
|
|
|
|
|
2021-04-08 12:19:09 -05:00
|
|
|
/**
|
|
|
|
* \return False if the callback explicitly returned false at any point, otherwise true,
|
|
|
|
* meaning the callback made it all the way through.
|
|
|
|
*/
|
|
|
|
bool GeometryComponent::attribute_foreach(const AttributeForeachCallback callback) const
|
2020-12-02 13:25:25 +01:00
|
|
|
{
|
2021-02-09 11:24:28 +01:00
|
|
|
using namespace blender::bke;
|
|
|
|
const ComponentAttributeProviders *providers = this->get_attribute_providers();
|
|
|
|
if (providers == nullptr) {
|
2021-04-08 12:19:09 -05:00
|
|
|
return true;
|
2021-02-09 11:24:28 +01:00
|
|
|
}
|
2021-02-23 15:15:23 +01:00
|
|
|
|
|
|
|
/* Keep track handled attribute names to make sure that we do not return the same name twice. */
|
|
|
|
Set<std::string> handled_attribute_names;
|
|
|
|
|
2021-02-09 11:24:28 +01:00
|
|
|
for (const BuiltinAttributeProvider *provider :
|
|
|
|
providers->builtin_attribute_providers().values()) {
|
|
|
|
if (provider->exists(*this)) {
|
2021-02-23 15:15:23 +01:00
|
|
|
AttributeMetaData meta_data{provider->domain(), provider->data_type()};
|
|
|
|
if (!callback(provider->name(), meta_data)) {
|
2021-04-08 12:19:09 -05:00
|
|
|
return false;
|
2021-02-23 15:15:23 +01:00
|
|
|
}
|
|
|
|
handled_attribute_names.add_new(provider->name());
|
2021-02-09 11:24:28 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
for (const DynamicAttributesProvider *provider : providers->dynamic_attribute_providers()) {
|
2021-02-23 15:15:23 +01:00
|
|
|
const bool continue_loop = provider->foreach_attribute(
|
|
|
|
*this, [&](StringRefNull name, const AttributeMetaData &meta_data) {
|
|
|
|
if (handled_attribute_names.add(name)) {
|
|
|
|
return callback(name, meta_data);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
});
|
|
|
|
if (!continue_loop) {
|
2021-04-08 12:19:09 -05:00
|
|
|
return false;
|
2021-02-23 15:15:23 +01:00
|
|
|
}
|
2021-02-09 11:24:28 +01:00
|
|
|
}
|
2021-04-08 12:19:09 -05:00
|
|
|
|
|
|
|
return true;
|
2020-12-02 13:25:25 +01:00
|
|
|
}
|
|
|
|
|
2020-12-10 10:50:37 -06:00
|
|
|
bool GeometryComponent::attribute_exists(const blender::StringRef attribute_name) const
|
|
|
|
{
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
blender::bke::ReadAttributeLookup attribute = this->attribute_try_get_for_read(attribute_name);
|
2020-12-10 10:50:37 -06:00
|
|
|
if (attribute) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-04-22 08:05:02 -05:00
|
|
|
std::optional<AttributeMetaData> GeometryComponent::attribute_get_meta_data(
|
|
|
|
const StringRef attribute_name) const
|
|
|
|
{
|
|
|
|
std::optional<AttributeMetaData> result{std::nullopt};
|
|
|
|
this->attribute_foreach([&](StringRefNull name, const AttributeMetaData &meta_data) {
|
|
|
|
if (attribute_name == name) {
|
|
|
|
result = meta_data;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
});
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
static std::unique_ptr<blender::fn::GVArray> try_adapt_data_type(
|
|
|
|
std::unique_ptr<blender::fn::GVArray> varray, const blender::fn::CPPType &to_type)
|
2020-12-02 13:25:25 +01:00
|
|
|
{
|
|
|
|
const blender::nodes::DataTypeConversions &conversions =
|
|
|
|
blender::nodes::get_implicit_type_conversions();
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
return conversions.try_convert(std::move(varray), to_type);
|
2020-12-02 13:25:25 +01:00
|
|
|
}
|
|
|
|
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_get_for_read(
|
2020-12-02 13:25:25 +01:00
|
|
|
const StringRef attribute_name,
|
|
|
|
const AttributeDomain domain,
|
|
|
|
const CustomDataType data_type) const
|
|
|
|
{
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
blender::bke::ReadAttributeLookup attribute = this->attribute_try_get_for_read(attribute_name);
|
2020-12-02 13:25:25 +01:00
|
|
|
if (!attribute) {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
std::unique_ptr<blender::fn::GVArray> varray = std::move(attribute.varray);
|
|
|
|
if (domain != ATTR_DOMAIN_AUTO && attribute.domain != domain) {
|
|
|
|
varray = this->attribute_try_adapt_domain(std::move(varray), attribute.domain, domain);
|
|
|
|
if (!varray) {
|
2020-12-02 13:25:25 +01:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const blender::fn::CPPType *cpp_type = blender::bke::custom_data_type_to_cpp_type(data_type);
|
|
|
|
BLI_assert(cpp_type != nullptr);
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
if (varray->type() != *cpp_type) {
|
|
|
|
varray = try_adapt_data_type(std::move(varray), *cpp_type);
|
|
|
|
if (!varray) {
|
2020-12-02 13:25:25 +01:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
return varray;
|
2020-12-02 13:25:25 +01:00
|
|
|
}
|
|
|
|
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
std::unique_ptr<blender::bke::GVArray> GeometryComponent::attribute_try_get_for_read(
|
|
|
|
const StringRef attribute_name, const AttributeDomain domain) const
|
2020-12-17 07:43:31 -06:00
|
|
|
{
|
|
|
|
if (!this->attribute_domain_supported(domain)) {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
blender::bke::ReadAttributeLookup attribute = this->attribute_try_get_for_read(attribute_name);
|
2020-12-17 07:43:31 -06:00
|
|
|
if (!attribute) {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
if (attribute.domain != domain) {
|
|
|
|
return this->attribute_try_adapt_domain(std::move(attribute.varray), attribute.domain, domain);
|
2020-12-17 07:43:31 -06:00
|
|
|
}
|
|
|
|
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
return std::move(attribute.varray);
|
2020-12-17 07:43:31 -06:00
|
|
|
}
|
|
|
|
|
2021-04-21 17:07:00 +02:00
|
|
|
blender::bke::ReadAttributeLookup GeometryComponent::attribute_try_get_for_read(
|
|
|
|
const blender::StringRef attribute_name, const CustomDataType data_type) const
|
|
|
|
{
|
|
|
|
blender::bke::ReadAttributeLookup attribute = this->attribute_try_get_for_read(attribute_name);
|
|
|
|
if (!attribute) {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
const blender::fn::CPPType *type = blender::bke::custom_data_type_to_cpp_type(data_type);
|
|
|
|
BLI_assert(type != nullptr);
|
|
|
|
if (attribute.varray->type() == *type) {
|
|
|
|
return attribute;
|
|
|
|
}
|
|
|
|
const blender::nodes::DataTypeConversions &conversions =
|
|
|
|
blender::nodes::get_implicit_type_conversions();
|
|
|
|
return {conversions.try_convert(std::move(attribute.varray), *type), attribute.domain};
|
|
|
|
}
|
|
|
|
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
std::unique_ptr<blender::bke::GVArray> GeometryComponent::attribute_get_for_read(
|
|
|
|
const StringRef attribute_name,
|
2020-12-09 16:20:48 +01:00
|
|
|
const AttributeDomain domain,
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
const CustomDataType data_type,
|
|
|
|
const void *default_value) const
|
2020-12-09 16:20:48 +01:00
|
|
|
{
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
std::unique_ptr<blender::bke::GVArray> varray = this->attribute_try_get_for_read(
|
|
|
|
attribute_name, domain, data_type);
|
|
|
|
if (varray) {
|
|
|
|
return varray;
|
|
|
|
}
|
|
|
|
const blender::fn::CPPType *type = blender::bke::custom_data_type_to_cpp_type(data_type);
|
|
|
|
if (default_value == nullptr) {
|
|
|
|
default_value = type->default_value();
|
2020-12-09 16:20:48 +01:00
|
|
|
}
|
|
|
|
const int domain_size = this->attribute_domain_size(domain);
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
return std::make_unique<blender::fn::GVArray_For_SingleValue>(*type, domain_size, default_value);
|
2020-12-09 16:20:48 +01:00
|
|
|
}
|
|
|
|
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
class GVMutableAttribute_For_OutputAttribute
|
|
|
|
: public blender::fn::GVMutableArray_For_GMutableSpan {
|
|
|
|
public:
|
|
|
|
GeometryComponent *component;
|
|
|
|
std::string final_name;
|
2021-01-14 15:52:08 +01:00
|
|
|
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
GVMutableAttribute_For_OutputAttribute(GMutableSpan data,
|
|
|
|
GeometryComponent &component,
|
|
|
|
std::string final_name)
|
|
|
|
: blender::fn::GVMutableArray_For_GMutableSpan(data),
|
|
|
|
component(&component),
|
|
|
|
final_name(std::move(final_name))
|
|
|
|
{
|
2020-12-02 13:25:25 +01:00
|
|
|
}
|
|
|
|
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
~GVMutableAttribute_For_OutputAttribute() override
|
|
|
|
{
|
|
|
|
type_->destruct_n(data_, size_);
|
|
|
|
MEM_freeN(data_);
|
2020-12-02 13:25:25 +01:00
|
|
|
}
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
};
|
2021-01-14 15:52:08 +01:00
|
|
|
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
static void save_output_attribute(blender::bke::OutputAttribute &output_attribute)
|
2021-01-14 15:52:08 +01:00
|
|
|
{
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
using namespace blender;
|
|
|
|
using namespace blender::fn;
|
|
|
|
using namespace blender::bke;
|
2021-01-14 15:52:08 +01:00
|
|
|
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
GVMutableAttribute_For_OutputAttribute &varray =
|
|
|
|
dynamic_cast<GVMutableAttribute_For_OutputAttribute &>(output_attribute.varray());
|
2021-01-14 15:52:08 +01:00
|
|
|
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
GeometryComponent &component = *varray.component;
|
|
|
|
const StringRefNull name = varray.final_name;
|
|
|
|
const AttributeDomain domain = output_attribute.domain();
|
|
|
|
const CustomDataType data_type = output_attribute.custom_data_type();
|
|
|
|
const CPPType &cpp_type = output_attribute.cpp_type();
|
2021-01-21 16:55:44 +01:00
|
|
|
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
component.attribute_try_delete(name);
|
2021-04-22 09:20:03 -05:00
|
|
|
if (!component.attribute_try_create(
|
|
|
|
varray.final_name, domain, data_type, AttributeInitDefault())) {
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
CLOG_WARN(&LOG,
|
|
|
|
"Could not create the '%s' attribute with type '%s'.",
|
|
|
|
name.c_str(),
|
|
|
|
cpp_type.name().c_str());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
WriteAttributeLookup write_attribute = component.attribute_try_get_for_write(name);
|
|
|
|
BUFFER_FOR_CPP_TYPE_VALUE(varray.type(), buffer);
|
|
|
|
for (const int i : IndexRange(varray.size())) {
|
|
|
|
varray.get(i, buffer);
|
|
|
|
write_attribute.varray->set_by_relocate(i, buffer);
|
2021-01-21 16:55:44 +01:00
|
|
|
}
|
2021-01-14 15:52:08 +01:00
|
|
|
}
|
|
|
|
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
static blender::bke::OutputAttribute create_output_attribute(
|
|
|
|
GeometryComponent &component,
|
|
|
|
const blender::StringRef attribute_name,
|
|
|
|
const AttributeDomain domain,
|
|
|
|
const CustomDataType data_type,
|
|
|
|
const bool ignore_old_values,
|
|
|
|
const void *default_value)
|
2021-01-14 15:52:08 +01:00
|
|
|
{
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
using namespace blender;
|
|
|
|
using namespace blender::fn;
|
|
|
|
using namespace blender::bke;
|
2021-01-14 15:52:08 +01:00
|
|
|
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
if (attribute_name.is_empty()) {
|
|
|
|
return {};
|
2020-12-02 13:25:25 +01:00
|
|
|
}
|
2021-01-14 15:52:08 +01:00
|
|
|
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
const CPPType *cpp_type = custom_data_type_to_cpp_type(data_type);
|
|
|
|
BLI_assert(cpp_type != nullptr);
|
|
|
|
const nodes::DataTypeConversions &conversions = nodes::get_implicit_type_conversions();
|
2021-01-14 15:52:08 +01:00
|
|
|
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
if (component.attribute_is_builtin(attribute_name)) {
|
|
|
|
WriteAttributeLookup attribute = component.attribute_try_get_for_write(attribute_name);
|
|
|
|
if (!attribute) {
|
2021-04-22 09:20:03 -05:00
|
|
|
if (default_value) {
|
|
|
|
const int64_t domain_size = component.attribute_domain_size(domain);
|
|
|
|
const GVArray_For_SingleValueRef default_varray{*cpp_type, domain_size, default_value};
|
|
|
|
component.attribute_try_create_builtin(attribute_name,
|
|
|
|
AttributeInitVArray(&default_varray));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
component.attribute_try_create_builtin(attribute_name, AttributeInitDefault());
|
|
|
|
}
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
attribute = component.attribute_try_get_for_write(attribute_name);
|
|
|
|
if (!attribute) {
|
|
|
|
/* Builtin attribute does not exist and can't be created. */
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (attribute.domain != domain) {
|
|
|
|
/* Builtin attribute is on different domain. */
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
GVMutableArrayPtr varray = std::move(attribute.varray);
|
|
|
|
if (varray->type() == *cpp_type) {
|
|
|
|
/* Builtin attribute matches exactly. */
|
|
|
|
return OutputAttribute(std::move(varray), domain, {}, ignore_old_values);
|
|
|
|
}
|
|
|
|
/* Builtin attribute is on the same domain but has a different data type. */
|
|
|
|
varray = conversions.try_convert(std::move(varray), *cpp_type);
|
|
|
|
return OutputAttribute(std::move(varray), domain, {}, ignore_old_values);
|
2021-01-14 15:52:08 +01:00
|
|
|
}
|
|
|
|
|
2021-04-22 09:20:03 -05:00
|
|
|
const int domain_size = component.attribute_domain_size(domain);
|
|
|
|
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
WriteAttributeLookup attribute = component.attribute_try_get_for_write(attribute_name);
|
|
|
|
if (!attribute) {
|
2021-04-22 09:20:03 -05:00
|
|
|
if (default_value) {
|
|
|
|
const GVArray_For_SingleValueRef default_varray{*cpp_type, domain_size, default_value};
|
|
|
|
component.attribute_try_create(
|
|
|
|
attribute_name, domain, data_type, AttributeInitVArray(&default_varray));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
component.attribute_try_create(attribute_name, domain, data_type, AttributeInitDefault());
|
|
|
|
}
|
|
|
|
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
attribute = component.attribute_try_get_for_write(attribute_name);
|
|
|
|
if (!attribute) {
|
|
|
|
/* Can't create the attribute. */
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (attribute.domain == domain && attribute.varray->type() == *cpp_type) {
|
|
|
|
/* Existing generic attribute matches exactly. */
|
|
|
|
return OutputAttribute(std::move(attribute.varray), domain, {}, ignore_old_values);
|
|
|
|
}
|
2021-01-14 15:52:08 +01:00
|
|
|
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
/* Allocate a new array that lives next to the existing attribute. It will overwrite the existing
|
|
|
|
* attribute after processing is done. */
|
|
|
|
void *data = MEM_mallocN_aligned(
|
|
|
|
cpp_type->size() * domain_size, cpp_type->alignment(), __func__);
|
|
|
|
if (ignore_old_values) {
|
|
|
|
/* This does nothing for trivially constructible types, but is necessary for correctness. */
|
|
|
|
cpp_type->construct_default_n(data, domain);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* Fill the temporary array with values from the existing attribute. */
|
|
|
|
GVArrayPtr old_varray = component.attribute_get_for_read(
|
|
|
|
attribute_name, domain, data_type, default_value);
|
|
|
|
old_varray->materialize_to_uninitialized(IndexRange(domain_size), data);
|
|
|
|
}
|
|
|
|
GVMutableArrayPtr varray = std::make_unique<GVMutableAttribute_For_OutputAttribute>(
|
|
|
|
GMutableSpan{*cpp_type, data, domain_size}, component, attribute_name);
|
2021-01-14 15:52:08 +01:00
|
|
|
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
return OutputAttribute(std::move(varray), domain, save_output_attribute, true);
|
2021-01-14 15:52:08 +01:00
|
|
|
}
|
|
|
|
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
blender::bke::OutputAttribute GeometryComponent::attribute_try_get_for_output(
|
|
|
|
const StringRef attribute_name,
|
|
|
|
const AttributeDomain domain,
|
|
|
|
const CustomDataType data_type,
|
|
|
|
const void *default_value)
|
2021-01-14 15:52:08 +01:00
|
|
|
{
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
return create_output_attribute(*this, attribute_name, domain, data_type, false, default_value);
|
2021-01-14 15:52:08 +01:00
|
|
|
}
|
|
|
|
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
blender::bke::OutputAttribute GeometryComponent::attribute_try_get_for_output_only(
|
|
|
|
const blender::StringRef attribute_name,
|
|
|
|
const AttributeDomain domain,
|
|
|
|
const CustomDataType data_type)
|
2021-01-14 15:52:08 +01:00
|
|
|
{
|
Geometry Nodes: use virtual arrays in internal attribute api
A virtual array is a data structure that is similar to a normal array
in that its elements can be accessed by an index. However, a virtual
array does not have to be a contiguous array internally. Instead, its
elements can be layed out arbitrarily while element access happens
through a virtual function call. However, the virtual array data
structures are designed so that the virtual function call can be avoided
in cases where it could become a bottleneck.
Most commonly, a virtual array is backed by an actual array/span or
is a single value internally, that is the same for every index.
Besides those, there are many more specialized virtual arrays like the
ones that provides vertex positions based on the `MVert` struct or
vertex group weights.
Not all attributes used by geometry nodes are stored in simple contiguous
arrays. To provide uniform access to all kinds of attributes, the attribute
API has to provide virtual array functionality that hides the implementation
details of attributes.
Before this refactor, the attribute API provided its own virtual array
implementation as part of the `ReadAttribute` and `WriteAttribute` types.
That resulted in unnecessary code duplication with the virtual array system.
Even worse, it bound many algorithms used by geometry nodes to the specifics
of the attribute API, even though they could also use different data sources
(such as data from sockets, default values, later results of expressions, ...).
This refactor removes the `ReadAttribute` and `WriteAttribute` types and
replaces them with `GVArray` and `GVMutableArray` respectively. The `GV`
stands for "generic virtual". The "generic" means that the data type contained
in those virtual arrays is only known at run-time. There are the corresponding
statically typed types `VArray<T>` and `VMutableArray<T>` as well.
No regressions are expected from this refactor. It does come with one
improvement for users. The attribute API can convert the data type
on write now. This is especially useful when writing to builtin attributes
like `material_index` with e.g. the Attribute Math node (which usually
just writes to float attributes, while `material_index` is an integer attribute).
Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
|
|
|
return create_output_attribute(*this, attribute_name, domain, data_type, true, nullptr);
|
2020-12-02 13:25:25 +01:00
|
|
|
}
|