Geometry Nodes: refactor virtual array system
Goals of this refactor: * Simplify creating virtual arrays. * Simplify passing virtual arrays around. * Simplify converting between typed and generic virtual arrays. * Reduce memory allocations. As a quick reminder, a virtual arrays is a data structure that behaves like an array (i.e. it can be accessed using an index). However, it may not actually be stored as array internally. The two most important implementations of virtual arrays are those that correspond to an actual plain array and those that have the same value for every index. However, many more implementations exist for various reasons (interfacing with legacy attributes, unified iterator over all points in multiple splines, ...). With this refactor the core types (`VArray`, `GVArray`, `VMutableArray` and `GVMutableArray`) can be used like "normal values". They typically live on the stack. Before, they were usually inside a `std::unique_ptr`. This makes passing them around much easier. Creation of new virtual arrays is also much simpler now due to some constructors. Memory allocations are reduced by making use of small object optimization inside the core types. Previously, `VArray` was a class with virtual methods that had to be overridden to change the behavior of a the virtual array. Now,`VArray` has a fixed size and has no virtual methods. Instead it contains a `VArrayImpl` that is similar to the old `VArray`. `VArrayImpl` should rarely ever be used directly, unless a new virtual array implementation is added. To support the small object optimization for many `VArrayImpl` classes, a new `blender::Any` type is added. It is similar to `std::any` with two additional features. It has an adjustable inline buffer size and alignment. The inline buffer size of `std::any` can't be relied on and is usually too small for our use case here. Furthermore, `blender::Any` can store additional user-defined type information without increasing the stack size. Differential Revision: https://developer.blender.org/D12986
This commit is contained in:
@@ -115,10 +115,10 @@ struct AttributeInitDefault : public AttributeInit {
|
||||
* Note that this can be used to fill the new attribute with the default
|
||||
*/
|
||||
struct AttributeInitVArray : public AttributeInit {
|
||||
const blender::fn::GVArray *varray;
|
||||
blender::fn::GVArray varray;
|
||||
|
||||
AttributeInitVArray(const blender::fn::GVArray *varray)
|
||||
: AttributeInit(Type::VArray), varray(varray)
|
||||
AttributeInitVArray(blender::fn::GVArray varray)
|
||||
: AttributeInit(Type::VArray), varray(std::move(varray))
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -150,9 +150,7 @@ namespace blender::bke {
|
||||
|
||||
using fn::CPPType;
|
||||
using fn::GVArray;
|
||||
using fn::GVArrayPtr;
|
||||
using fn::GVMutableArray;
|
||||
using fn::GVMutableArrayPtr;
|
||||
|
||||
const CPPType *custom_data_type_to_cpp_type(const CustomDataType type);
|
||||
CustomDataType cpp_type_to_custom_data_type(const CPPType &type);
|
||||
@@ -164,14 +162,14 @@ AttributeDomain attribute_domain_highest_priority(Span<AttributeDomain> domains)
|
||||
*/
|
||||
struct ReadAttributeLookup {
|
||||
/* The virtual array that is used to read from this attribute. */
|
||||
GVArrayPtr varray;
|
||||
GVArray varray;
|
||||
/* Domain the attribute lives on in the geometry. */
|
||||
AttributeDomain domain;
|
||||
|
||||
/* Convenience function to check if the attribute has been found. */
|
||||
operator bool() const
|
||||
{
|
||||
return this->varray.get() != nullptr;
|
||||
return this->varray;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -180,7 +178,7 @@ struct ReadAttributeLookup {
|
||||
*/
|
||||
struct WriteAttributeLookup {
|
||||
/* The virtual array that is used to read from and write to the attribute. */
|
||||
GVMutableArrayPtr varray;
|
||||
GVMutableArray varray;
|
||||
/* Domain the attributes lives on in the geometry. */
|
||||
AttributeDomain domain;
|
||||
/* Call this after changing the attribute to invalidate caches that depend on this attribute. */
|
||||
@@ -189,7 +187,7 @@ struct WriteAttributeLookup {
|
||||
/* Convenience function to check if the attribute has been found. */
|
||||
operator bool() const
|
||||
{
|
||||
return this->varray.get() != nullptr;
|
||||
return this->varray;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -209,7 +207,7 @@ class OutputAttribute {
|
||||
using SaveFn = std::function<void(OutputAttribute &)>;
|
||||
|
||||
private:
|
||||
GVMutableArrayPtr varray_;
|
||||
GVMutableArray varray_;
|
||||
AttributeDomain domain_ = ATTR_DOMAIN_AUTO;
|
||||
SaveFn save_;
|
||||
std::unique_ptr<fn::GVMutableArray_GSpan> optional_span_varray_;
|
||||
@@ -219,7 +217,7 @@ class OutputAttribute {
|
||||
public:
|
||||
OutputAttribute();
|
||||
OutputAttribute(OutputAttribute &&other);
|
||||
OutputAttribute(GVMutableArrayPtr varray,
|
||||
OutputAttribute(GVMutableArray varray,
|
||||
AttributeDomain domain,
|
||||
SaveFn save,
|
||||
const bool ignore_old_values);
|
||||
@@ -229,7 +227,7 @@ class OutputAttribute {
|
||||
operator bool() const;
|
||||
|
||||
GVMutableArray &operator*();
|
||||
GVMutableArray *operator->();
|
||||
fn::GVMutableArray *operator->();
|
||||
GVMutableArray &varray();
|
||||
AttributeDomain domain() const;
|
||||
const CPPType &cpp_type() const;
|
||||
@@ -247,16 +245,14 @@ class OutputAttribute {
|
||||
template<typename T> class OutputAttribute_Typed {
|
||||
private:
|
||||
OutputAttribute attribute_;
|
||||
std::unique_ptr<fn::GVMutableArray_Typed<T>> optional_varray_;
|
||||
VMutableArray<T> *varray_ = nullptr;
|
||||
VMutableArray<T> varray_;
|
||||
|
||||
public:
|
||||
OutputAttribute_Typed();
|
||||
OutputAttribute_Typed(OutputAttribute attribute) : attribute_(std::move(attribute))
|
||||
{
|
||||
if (attribute_) {
|
||||
optional_varray_ = std::make_unique<fn::GVMutableArray_Typed<T>>(attribute_.varray());
|
||||
varray_ = &**optional_varray_;
|
||||
varray_ = attribute_.varray().template typed<T>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,22 +271,22 @@ template<typename T> class OutputAttribute_Typed {
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return varray_ != nullptr;
|
||||
return varray_;
|
||||
}
|
||||
|
||||
VMutableArray<T> &operator*()
|
||||
{
|
||||
return *varray_;
|
||||
return varray_;
|
||||
}
|
||||
|
||||
VMutableArray<T> *operator->()
|
||||
{
|
||||
return varray_;
|
||||
return &varray_;
|
||||
}
|
||||
|
||||
VMutableArray<T> &varray()
|
||||
{
|
||||
return *varray_;
|
||||
return varray_;
|
||||
}
|
||||
|
||||
AttributeDomain domain() const
|
||||
@@ -351,18 +347,17 @@ class CustomDataAttributes {
|
||||
|
||||
std::optional<blender::fn::GSpan> get_for_read(const AttributeIDRef &attribute_id) const;
|
||||
|
||||
blender::fn::GVArrayPtr get_for_read(const AttributeIDRef &attribute_id,
|
||||
const CustomDataType data_type,
|
||||
const void *default_value) const;
|
||||
blender::fn::GVArray get_for_read(const AttributeIDRef &attribute_id,
|
||||
const CustomDataType data_type,
|
||||
const void *default_value) const;
|
||||
|
||||
template<typename T>
|
||||
blender::fn::GVArray_Typed<T> get_for_read(const AttributeIDRef &attribute_id,
|
||||
const T &default_value) const
|
||||
blender::VArray<T> get_for_read(const AttributeIDRef &attribute_id, const T &default_value) const
|
||||
{
|
||||
const blender::fn::CPPType &cpp_type = blender::fn::CPPType::get<T>();
|
||||
const CustomDataType type = blender::bke::cpp_type_to_custom_data_type(cpp_type);
|
||||
GVArrayPtr varray = this->get_for_read(attribute_id, type, &default_value);
|
||||
return blender::fn::GVArray_Typed<T>(std::move(varray));
|
||||
GVArray varray = this->get_for_read(attribute_id, type, &default_value);
|
||||
return varray.typed<T>();
|
||||
}
|
||||
|
||||
std::optional<blender::fn::GMutableSpan> get_for_write(const AttributeIDRef &attribute_id);
|
||||
@@ -465,7 +460,7 @@ inline bool AttributeIDRef::should_be_kept() const
|
||||
inline OutputAttribute::OutputAttribute() = default;
|
||||
inline OutputAttribute::OutputAttribute(OutputAttribute &&other) = default;
|
||||
|
||||
inline OutputAttribute::OutputAttribute(GVMutableArrayPtr varray,
|
||||
inline OutputAttribute::OutputAttribute(GVMutableArray varray,
|
||||
AttributeDomain domain,
|
||||
SaveFn save,
|
||||
const bool ignore_old_values)
|
||||
@@ -478,22 +473,22 @@ inline OutputAttribute::OutputAttribute(GVMutableArrayPtr varray,
|
||||
|
||||
inline OutputAttribute::operator bool() const
|
||||
{
|
||||
return varray_.get() != nullptr;
|
||||
return varray_;
|
||||
}
|
||||
|
||||
inline GVMutableArray &OutputAttribute::operator*()
|
||||
{
|
||||
return *varray_;
|
||||
return varray_;
|
||||
}
|
||||
|
||||
inline GVMutableArray *OutputAttribute::operator->()
|
||||
inline fn::GVMutableArray *OutputAttribute::operator->()
|
||||
{
|
||||
return varray_.get();
|
||||
return &varray_;
|
||||
}
|
||||
|
||||
inline GVMutableArray &OutputAttribute::varray()
|
||||
{
|
||||
return *varray_;
|
||||
return varray_;
|
||||
}
|
||||
|
||||
inline AttributeDomain OutputAttribute::domain() const
|
||||
@@ -503,7 +498,7 @@ inline AttributeDomain OutputAttribute::domain() const
|
||||
|
||||
inline const CPPType &OutputAttribute::cpp_type() const
|
||||
{
|
||||
return varray_->type();
|
||||
return varray_.type();
|
||||
}
|
||||
|
||||
inline CustomDataType OutputAttribute::custom_data_type() const
|
||||
|
||||
@@ -119,10 +119,21 @@ class GeometryComponent {
|
||||
/* Get a read-only attribute for the domain based on the given attribute. This can be used to
|
||||
* interpolate from one domain to another.
|
||||
* Returns null if the interpolation is not implemented. */
|
||||
virtual std::unique_ptr<blender::fn::GVArray> attribute_try_adapt_domain(
|
||||
std::unique_ptr<blender::fn::GVArray> varray,
|
||||
const AttributeDomain from_domain,
|
||||
const AttributeDomain to_domain) const;
|
||||
blender::fn::GVArray attribute_try_adapt_domain(const blender::fn::GVArray &varray,
|
||||
const AttributeDomain from_domain,
|
||||
const AttributeDomain to_domain) const
|
||||
{
|
||||
return this->attribute_try_adapt_domain_impl(varray, from_domain, to_domain);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
blender::VArray<T> attribute_try_adapt_domain(const blender::VArray<T> &varray,
|
||||
const AttributeDomain from_domain,
|
||||
const AttributeDomain to_domain) const
|
||||
{
|
||||
return this->attribute_try_adapt_domain_impl(varray, from_domain, to_domain)
|
||||
.template typed<T>();
|
||||
}
|
||||
|
||||
/* Returns true when the attribute has been deleted. */
|
||||
bool attribute_try_delete(const blender::bke::AttributeIDRef &attribute_id);
|
||||
@@ -146,16 +157,15 @@ class GeometryComponent {
|
||||
/* Get a virtual array to read the data of an attribute on the given domain and data type.
|
||||
* Returns null when the attribute does not exist or cannot be converted to the requested domain
|
||||
* and data type. */
|
||||
std::unique_ptr<blender::fn::GVArray> attribute_try_get_for_read(
|
||||
const blender::bke::AttributeIDRef &attribute_id,
|
||||
const AttributeDomain domain,
|
||||
const CustomDataType data_type) const;
|
||||
blender::fn::GVArray attribute_try_get_for_read(const blender::bke::AttributeIDRef &attribute_id,
|
||||
const AttributeDomain domain,
|
||||
const CustomDataType data_type) const;
|
||||
|
||||
/* Get a virtual array to read the data of an attribute on the given domain. The data type is
|
||||
* left unchanged. Returns null when the attribute does not exist or cannot be adapted to the
|
||||
* requested domain. */
|
||||
std::unique_ptr<blender::fn::GVArray> attribute_try_get_for_read(
|
||||
const blender::bke::AttributeIDRef &attribute_id, const AttributeDomain domain) const;
|
||||
blender::fn::GVArray attribute_try_get_for_read(const blender::bke::AttributeIDRef &attribute_id,
|
||||
const AttributeDomain domain) const;
|
||||
|
||||
/* Get a virtual array to read data of an attribute with the given data type. The domain is
|
||||
* left unchanged. Returns null when the attribute does not exist or cannot be converted to the
|
||||
@@ -165,25 +175,22 @@ class GeometryComponent {
|
||||
|
||||
/* Get a virtual array to read the data of an attribute. If that is not possible, the returned
|
||||
* virtual array will contain a default value. This never returns null. */
|
||||
std::unique_ptr<blender::fn::GVArray> attribute_get_for_read(
|
||||
const blender::bke::AttributeIDRef &attribute_id,
|
||||
const AttributeDomain domain,
|
||||
const CustomDataType data_type,
|
||||
const void *default_value = nullptr) const;
|
||||
blender::fn::GVArray attribute_get_for_read(const blender::bke::AttributeIDRef &attribute_id,
|
||||
const AttributeDomain domain,
|
||||
const CustomDataType data_type,
|
||||
const void *default_value = nullptr) const;
|
||||
|
||||
/* Should be used instead of the method above when the requested data type is known at compile
|
||||
* time for better type safety. */
|
||||
template<typename T>
|
||||
blender::fn::GVArray_Typed<T> attribute_get_for_read(
|
||||
const blender::bke::AttributeIDRef &attribute_id,
|
||||
const AttributeDomain domain,
|
||||
const T &default_value) const
|
||||
blender::VArray<T> attribute_get_for_read(const blender::bke::AttributeIDRef &attribute_id,
|
||||
const AttributeDomain domain,
|
||||
const T &default_value) const
|
||||
{
|
||||
const blender::fn::CPPType &cpp_type = blender::fn::CPPType::get<T>();
|
||||
const CustomDataType type = blender::bke::cpp_type_to_custom_data_type(cpp_type);
|
||||
std::unique_ptr varray = this->attribute_get_for_read(
|
||||
attribute_id, domain, type, &default_value);
|
||||
return blender::fn::GVArray_Typed<T>(std::move(varray));
|
||||
return this->attribute_get_for_read(attribute_id, domain, type, &default_value)
|
||||
.template typed<T>();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -234,6 +241,11 @@ class GeometryComponent {
|
||||
|
||||
private:
|
||||
virtual const blender::bke::ComponentAttributeProviders *get_attribute_providers() const;
|
||||
|
||||
virtual blender::fn::GVArray attribute_try_adapt_domain_impl(
|
||||
const blender::fn::GVArray &varray,
|
||||
const AttributeDomain from_domain,
|
||||
const AttributeDomain to_domain) const;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
@@ -391,10 +403,6 @@ class MeshComponent : public GeometryComponent {
|
||||
Mesh *get_for_write();
|
||||
|
||||
int attribute_domain_size(const AttributeDomain domain) const final;
|
||||
std::unique_ptr<blender::fn::GVArray> attribute_try_adapt_domain(
|
||||
std::unique_ptr<blender::fn::GVArray> varray,
|
||||
const AttributeDomain from_domain,
|
||||
const AttributeDomain to_domain) const final;
|
||||
|
||||
bool is_empty() const final;
|
||||
|
||||
@@ -405,6 +413,11 @@ class MeshComponent : public GeometryComponent {
|
||||
|
||||
private:
|
||||
const blender::bke::ComponentAttributeProviders *get_attribute_providers() const final;
|
||||
|
||||
blender::fn::GVArray attribute_try_adapt_domain_impl(
|
||||
const blender::fn::GVArray &varray,
|
||||
const AttributeDomain from_domain,
|
||||
const AttributeDomain to_domain) const final;
|
||||
};
|
||||
|
||||
/** A geometry component that stores a point cloud. */
|
||||
@@ -469,10 +482,6 @@ class CurveComponent : public GeometryComponent {
|
||||
CurveEval *get_for_write();
|
||||
|
||||
int attribute_domain_size(const AttributeDomain domain) const final;
|
||||
std::unique_ptr<blender::fn::GVArray> attribute_try_adapt_domain(
|
||||
std::unique_ptr<blender::fn::GVArray> varray,
|
||||
const AttributeDomain from_domain,
|
||||
const AttributeDomain to_domain) const final;
|
||||
|
||||
bool is_empty() const final;
|
||||
|
||||
@@ -485,6 +494,11 @@ class CurveComponent : public GeometryComponent {
|
||||
|
||||
private:
|
||||
const blender::bke::ComponentAttributeProviders *get_attribute_providers() const final;
|
||||
|
||||
blender::fn::GVArray attribute_try_adapt_domain_impl(
|
||||
const blender::fn::GVArray &varray,
|
||||
const AttributeDomain from_domain,
|
||||
const AttributeDomain to_domain) const final;
|
||||
};
|
||||
|
||||
class InstanceReference {
|
||||
@@ -759,9 +773,9 @@ class AttributeFieldInput : public fn::FieldInput {
|
||||
return name_;
|
||||
}
|
||||
|
||||
const GVArray *get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const override;
|
||||
GVArray get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const override;
|
||||
|
||||
std::string socket_inspection_name() const override;
|
||||
|
||||
@@ -776,9 +790,9 @@ class IDAttributeFieldInput : public fn::FieldInput {
|
||||
category_ = Category::Generated;
|
||||
}
|
||||
|
||||
const GVArray *get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const override;
|
||||
GVArray get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const override;
|
||||
|
||||
std::string socket_inspection_name() const override;
|
||||
|
||||
@@ -815,9 +829,9 @@ class AnonymousAttributeFieldInput : public fn::FieldInput {
|
||||
return fn::Field<T>{field_input};
|
||||
}
|
||||
|
||||
const GVArray *get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const override;
|
||||
GVArray get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const override;
|
||||
|
||||
std::string socket_inspection_name() const override;
|
||||
|
||||
|
||||
@@ -187,14 +187,14 @@ class Spline {
|
||||
blender::MutableSpan<T> dst) const
|
||||
{
|
||||
this->sample_with_index_factors(
|
||||
blender::fn::GVArray_For_VArray(src), index_factors, blender::fn::GMutableSpan(dst));
|
||||
blender::fn::GVArray(src), index_factors, blender::fn::GMutableSpan(dst));
|
||||
}
|
||||
template<typename T>
|
||||
void sample_with_index_factors(blender::Span<T> src,
|
||||
blender::Span<float> index_factors,
|
||||
blender::MutableSpan<T> dst) const
|
||||
{
|
||||
this->sample_with_index_factors(blender::VArray_For_Span(src), index_factors, dst);
|
||||
this->sample_with_index_factors(blender::VArray<T>::ForSpan(src), index_factors, dst);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -202,13 +202,11 @@ class Spline {
|
||||
* evaluated points. For poly splines, the lifetime of the returned virtual array must not
|
||||
* exceed the lifetime of the input data.
|
||||
*/
|
||||
virtual blender::fn::GVArrayPtr interpolate_to_evaluated(
|
||||
const blender::fn::GVArray &src) const = 0;
|
||||
blender::fn::GVArrayPtr interpolate_to_evaluated(blender::fn::GSpan data) const;
|
||||
template<typename T>
|
||||
blender::fn::GVArray_Typed<T> interpolate_to_evaluated(blender::Span<T> data) const
|
||||
virtual blender::fn::GVArray interpolate_to_evaluated(const blender::fn::GVArray &src) const = 0;
|
||||
blender::fn::GVArray interpolate_to_evaluated(blender::fn::GSpan data) const;
|
||||
template<typename T> blender::VArray<T> interpolate_to_evaluated(blender::Span<T> data) const
|
||||
{
|
||||
return blender::fn::GVArray_Typed<T>(this->interpolate_to_evaluated(blender::fn::GSpan(data)));
|
||||
return this->interpolate_to_evaluated(blender::fn::GSpan(data)).typed<T>();
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -350,7 +348,7 @@ class BezierSpline final : public Spline {
|
||||
};
|
||||
InterpolationData interpolation_data_from_index_factor(const float index_factor) const;
|
||||
|
||||
virtual blender::fn::GVArrayPtr interpolate_to_evaluated(
|
||||
virtual blender::fn::GVArray interpolate_to_evaluated(
|
||||
const blender::fn::GVArray &src) const override;
|
||||
|
||||
void evaluate_segment(const int index,
|
||||
@@ -487,7 +485,7 @@ class NURBSpline final : public Spline {
|
||||
|
||||
blender::Span<blender::float3> evaluated_positions() const final;
|
||||
|
||||
blender::fn::GVArrayPtr interpolate_to_evaluated(const blender::fn::GVArray &src) const final;
|
||||
blender::fn::GVArray interpolate_to_evaluated(const blender::fn::GVArray &src) const final;
|
||||
|
||||
protected:
|
||||
void correct_end_tangents() const final;
|
||||
@@ -538,7 +536,7 @@ class PolySpline final : public Spline {
|
||||
|
||||
blender::Span<blender::float3> evaluated_positions() const final;
|
||||
|
||||
blender::fn::GVArrayPtr interpolate_to_evaluated(const blender::fn::GVArray &src) const final;
|
||||
blender::fn::GVArray interpolate_to_evaluated(const blender::fn::GVArray &src) const final;
|
||||
|
||||
protected:
|
||||
void correct_end_tangents() const final;
|
||||
|
||||
@@ -50,9 +50,7 @@ using blender::bke::AttributeIDRef;
|
||||
using blender::bke::OutputAttribute;
|
||||
using blender::fn::GMutableSpan;
|
||||
using blender::fn::GSpan;
|
||||
using blender::fn::GVArray_For_GSpan;
|
||||
using blender::fn::GVArray_For_SingleValue;
|
||||
using blender::fn::GVMutableArray_For_GMutableSpan;
|
||||
using blender::fn::GVMutableArrayImpl_For_GMutableSpan;
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
@@ -207,7 +205,7 @@ fn::GMutableSpan OutputAttribute::as_span()
|
||||
{
|
||||
if (!optional_span_varray_) {
|
||||
const bool materialize_old_values = !ignore_old_values_;
|
||||
optional_span_varray_ = std::make_unique<fn::GVMutableArray_GSpan>(*varray_,
|
||||
optional_span_varray_ = std::make_unique<fn::GVMutableArray_GSpan>(varray_,
|
||||
materialize_old_values);
|
||||
}
|
||||
fn::GVMutableArray_GSpan &span_varray = *optional_span_varray_;
|
||||
@@ -257,8 +255,8 @@ static bool add_builtin_type_custom_data_layer_from_init(CustomData &custom_data
|
||||
if (data == nullptr) {
|
||||
return false;
|
||||
}
|
||||
const GVArray *varray = static_cast<const AttributeInitVArray &>(initializer).varray;
|
||||
varray->materialize_to_uninitialized(IndexRange(varray->size()), data);
|
||||
const GVArray &varray = static_cast<const AttributeInitVArray &>(initializer).varray;
|
||||
varray.materialize_to_uninitialized(varray.index_range(), data);
|
||||
return true;
|
||||
}
|
||||
case AttributeInit::Type::MoveArray: {
|
||||
@@ -313,8 +311,8 @@ static bool add_custom_data_layer_from_attribute_init(const AttributeIDRef &attr
|
||||
if (data == nullptr) {
|
||||
return false;
|
||||
}
|
||||
const GVArray *varray = static_cast<const AttributeInitVArray &>(initializer).varray;
|
||||
varray->materialize_to_uninitialized(IndexRange(varray->size()), data);
|
||||
const GVArray &varray = static_cast<const AttributeInitVArray &>(initializer).varray;
|
||||
varray.materialize_to_uninitialized(varray.index_range(), data);
|
||||
return true;
|
||||
}
|
||||
case AttributeInit::Type::MoveArray: {
|
||||
@@ -345,8 +343,7 @@ static bool custom_data_layer_matches_attribute_id(const CustomDataLayer &layer,
|
||||
return layer.name == attribute_id.name();
|
||||
}
|
||||
|
||||
GVArrayPtr BuiltinCustomDataLayerProvider::try_get_for_read(
|
||||
const GeometryComponent &component) const
|
||||
GVArray BuiltinCustomDataLayerProvider::try_get_for_read(const GeometryComponent &component) const
|
||||
{
|
||||
const CustomData *custom_data = custom_data_access_.get_const_custom_data(component);
|
||||
if (custom_data == nullptr) {
|
||||
@@ -511,7 +508,7 @@ ReadAttributeLookup CustomDataAttributeProvider::try_get_for_read(
|
||||
continue;
|
||||
}
|
||||
GSpan data{*type, layer.data, domain_size};
|
||||
return {std::make_unique<GVArray_For_GSpan>(data), domain_};
|
||||
return {GVArray::ForSpan(data), domain_};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
@@ -541,7 +538,7 @@ WriteAttributeLookup CustomDataAttributeProvider::try_get_for_write(
|
||||
continue;
|
||||
}
|
||||
GMutableSpan data{*type, layer.data, domain_size};
|
||||
return {std::make_unique<GVMutableArray_For_GMutableSpan>(data), domain_};
|
||||
return {GVMutableArray::ForSpan(data), domain_};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
@@ -751,25 +748,25 @@ std::optional<GSpan> CustomDataAttributes::get_for_read(const AttributeIDRef &at
|
||||
* 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 AttributeIDRef &attribute_id,
|
||||
const CustomDataType data_type,
|
||||
const void *default_value) const
|
||||
GVArray CustomDataAttributes::get_for_read(const AttributeIDRef &attribute_id,
|
||||
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(attribute_id);
|
||||
if (!attribute) {
|
||||
const int domain_size = this->size_;
|
||||
return std::make_unique<GVArray_For_SingleValue>(
|
||||
return GVArray::ForSingle(
|
||||
*type, domain_size, (default_value == nullptr) ? type->default_value() : default_value);
|
||||
}
|
||||
|
||||
if (attribute->type() == *type) {
|
||||
return std::make_unique<GVArray_For_GSpan>(*attribute);
|
||||
return GVArray::ForSpan(*attribute);
|
||||
}
|
||||
const blender::nodes::DataTypeConversions &conversions =
|
||||
blender::nodes::get_implicit_type_conversions();
|
||||
return conversions.try_convert(std::make_unique<GVArray_For_GSpan>(*attribute), *type);
|
||||
return conversions.try_convert(GVArray::ForSpan(*attribute), *type);
|
||||
}
|
||||
|
||||
std::optional<GMutableSpan> CustomDataAttributes::get_for_write(const AttributeIDRef &attribute_id)
|
||||
@@ -922,8 +919,8 @@ blender::bke::ReadAttributeLookup GeometryComponent::attribute_try_get_for_read(
|
||||
return {};
|
||||
}
|
||||
|
||||
std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_adapt_domain(
|
||||
std::unique_ptr<blender::fn::GVArray> varray,
|
||||
blender::fn::GVArray GeometryComponent::attribute_try_adapt_domain_impl(
|
||||
const blender::fn::GVArray &varray,
|
||||
const AttributeDomain from_domain,
|
||||
const AttributeDomain to_domain) const
|
||||
{
|
||||
@@ -1110,15 +1107,15 @@ std::optional<AttributeMetaData> GeometryComponent::attribute_get_meta_data(
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::unique_ptr<blender::fn::GVArray> try_adapt_data_type(
|
||||
std::unique_ptr<blender::fn::GVArray> varray, const blender::fn::CPPType &to_type)
|
||||
static blender::fn::GVArray try_adapt_data_type(blender::fn::GVArray varray,
|
||||
const blender::fn::CPPType &to_type)
|
||||
{
|
||||
const blender::nodes::DataTypeConversions &conversions =
|
||||
blender::nodes::get_implicit_type_conversions();
|
||||
return conversions.try_convert(std::move(varray), to_type);
|
||||
}
|
||||
|
||||
std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_get_for_read(
|
||||
blender::fn::GVArray GeometryComponent::attribute_try_get_for_read(
|
||||
const AttributeIDRef &attribute_id,
|
||||
const AttributeDomain domain,
|
||||
const CustomDataType data_type) const
|
||||
@@ -1128,7 +1125,7 @@ std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_get_for_r
|
||||
return {};
|
||||
}
|
||||
|
||||
std::unique_ptr<blender::fn::GVArray> varray = std::move(attribute.varray);
|
||||
blender::fn::GVArray varray = std::move(attribute.varray);
|
||||
if (!ELEM(domain, ATTR_DOMAIN_AUTO, attribute.domain)) {
|
||||
varray = this->attribute_try_adapt_domain(std::move(varray), attribute.domain, domain);
|
||||
if (!varray) {
|
||||
@@ -1138,7 +1135,7 @@ std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_get_for_r
|
||||
|
||||
const blender::fn::CPPType *cpp_type = blender::bke::custom_data_type_to_cpp_type(data_type);
|
||||
BLI_assert(cpp_type != nullptr);
|
||||
if (varray->type() != *cpp_type) {
|
||||
if (varray.type() != *cpp_type) {
|
||||
varray = try_adapt_data_type(std::move(varray), *cpp_type);
|
||||
if (!varray) {
|
||||
return {};
|
||||
@@ -1148,7 +1145,7 @@ std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_get_for_r
|
||||
return varray;
|
||||
}
|
||||
|
||||
std::unique_ptr<blender::bke::GVArray> GeometryComponent::attribute_try_get_for_read(
|
||||
blender::fn::GVArray GeometryComponent::attribute_try_get_for_read(
|
||||
const AttributeIDRef &attribute_id, const AttributeDomain domain) const
|
||||
{
|
||||
if (!this->attribute_domain_supported(domain)) {
|
||||
@@ -1176,7 +1173,7 @@ blender::bke::ReadAttributeLookup GeometryComponent::attribute_try_get_for_read(
|
||||
}
|
||||
const blender::fn::CPPType *type = blender::bke::custom_data_type_to_cpp_type(data_type);
|
||||
BLI_assert(type != nullptr);
|
||||
if (attribute.varray->type() == *type) {
|
||||
if (attribute.varray.type() == *type) {
|
||||
return attribute;
|
||||
}
|
||||
const blender::nodes::DataTypeConversions &conversions =
|
||||
@@ -1184,14 +1181,12 @@ blender::bke::ReadAttributeLookup GeometryComponent::attribute_try_get_for_read(
|
||||
return {conversions.try_convert(std::move(attribute.varray), *type), attribute.domain};
|
||||
}
|
||||
|
||||
std::unique_ptr<blender::bke::GVArray> GeometryComponent::attribute_get_for_read(
|
||||
const AttributeIDRef &attribute_id,
|
||||
const AttributeDomain domain,
|
||||
const CustomDataType data_type,
|
||||
const void *default_value) const
|
||||
blender::fn::GVArray GeometryComponent::attribute_get_for_read(const AttributeIDRef &attribute_id,
|
||||
const AttributeDomain domain,
|
||||
const CustomDataType data_type,
|
||||
const void *default_value) const
|
||||
{
|
||||
std::unique_ptr<blender::bke::GVArray> varray = this->attribute_try_get_for_read(
|
||||
attribute_id, domain, data_type);
|
||||
blender::fn::GVArray varray = this->attribute_try_get_for_read(attribute_id, domain, data_type);
|
||||
if (varray) {
|
||||
return varray;
|
||||
}
|
||||
@@ -1200,11 +1195,11 @@ std::unique_ptr<blender::bke::GVArray> GeometryComponent::attribute_get_for_read
|
||||
default_value = type->default_value();
|
||||
}
|
||||
const int domain_size = this->attribute_domain_size(domain);
|
||||
return std::make_unique<blender::fn::GVArray_For_SingleValue>(*type, domain_size, default_value);
|
||||
return blender::fn::GVArray::ForSingle(*type, domain_size, default_value);
|
||||
}
|
||||
|
||||
class GVMutableAttribute_For_OutputAttribute
|
||||
: public blender::fn::GVMutableArray_For_GMutableSpan {
|
||||
: public blender::fn::GVMutableArrayImpl_For_GMutableSpan {
|
||||
public:
|
||||
GeometryComponent *component;
|
||||
std::string attribute_name;
|
||||
@@ -1213,7 +1208,7 @@ class GVMutableAttribute_For_OutputAttribute
|
||||
GVMutableAttribute_For_OutputAttribute(GMutableSpan data,
|
||||
GeometryComponent &component,
|
||||
const AttributeIDRef &attribute_id)
|
||||
: blender::fn::GVMutableArray_For_GMutableSpan(data), component(&component)
|
||||
: blender::fn::GVMutableArrayImpl_For_GMutableSpan(data), component(&component)
|
||||
{
|
||||
if (attribute_id.is_named()) {
|
||||
this->attribute_name = attribute_id.name();
|
||||
@@ -1239,7 +1234,8 @@ static void save_output_attribute(OutputAttribute &output_attribute)
|
||||
using namespace blender::bke;
|
||||
|
||||
GVMutableAttribute_For_OutputAttribute &varray =
|
||||
dynamic_cast<GVMutableAttribute_For_OutputAttribute &>(output_attribute.varray());
|
||||
dynamic_cast<GVMutableAttribute_For_OutputAttribute &>(
|
||||
*output_attribute.varray().get_implementation());
|
||||
|
||||
GeometryComponent &component = *varray.component;
|
||||
AttributeIDRef attribute_id;
|
||||
@@ -1267,7 +1263,7 @@ static void save_output_attribute(OutputAttribute &output_attribute)
|
||||
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);
|
||||
write_attribute.varray.set_by_relocate(i, buffer);
|
||||
}
|
||||
if (write_attribute.tag_modified_fn) {
|
||||
write_attribute.tag_modified_fn();
|
||||
@@ -1310,9 +1306,9 @@ static OutputAttribute create_output_attribute(GeometryComponent &component,
|
||||
if (!attribute) {
|
||||
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));
|
||||
component.attribute_try_create_builtin(
|
||||
attribute_name,
|
||||
AttributeInitVArray(GVArray::ForSingleRef(*cpp_type, domain_size, default_value)));
|
||||
}
|
||||
else {
|
||||
component.attribute_try_create_builtin(attribute_name, AttributeInitDefault());
|
||||
@@ -1327,9 +1323,8 @@ static OutputAttribute create_output_attribute(GeometryComponent &component,
|
||||
/* Builtin attribute is on different domain. */
|
||||
return {};
|
||||
}
|
||||
|
||||
GVMutableArrayPtr varray = std::move(attribute.varray);
|
||||
if (varray->type() == *cpp_type) {
|
||||
GVMutableArray varray = std::move(attribute.varray);
|
||||
if (varray.type() == *cpp_type) {
|
||||
/* Builtin attribute matches exactly. */
|
||||
return OutputAttribute(std::move(varray),
|
||||
domain,
|
||||
@@ -1349,9 +1344,11 @@ static OutputAttribute create_output_attribute(GeometryComponent &component,
|
||||
WriteAttributeLookup attribute = component.attribute_try_get_for_write(attribute_id);
|
||||
if (!attribute) {
|
||||
if (default_value) {
|
||||
const GVArray_For_SingleValueRef default_varray{*cpp_type, domain_size, default_value};
|
||||
component.attribute_try_create(
|
||||
attribute_id, domain, data_type, AttributeInitVArray(&default_varray));
|
||||
attribute_id,
|
||||
domain,
|
||||
data_type,
|
||||
AttributeInitVArray(GVArray::ForSingleRef(*cpp_type, domain_size, default_value)));
|
||||
}
|
||||
else {
|
||||
component.attribute_try_create(attribute_id, domain, data_type, AttributeInitDefault());
|
||||
@@ -1363,7 +1360,7 @@ static OutputAttribute create_output_attribute(GeometryComponent &component,
|
||||
return {};
|
||||
}
|
||||
}
|
||||
if (attribute.domain == domain && attribute.varray->type() == *cpp_type) {
|
||||
if (attribute.domain == domain && attribute.varray.type() == *cpp_type) {
|
||||
/* Existing generic attribute matches exactly. */
|
||||
|
||||
return OutputAttribute(std::move(attribute.varray),
|
||||
@@ -1382,11 +1379,11 @@ static OutputAttribute create_output_attribute(GeometryComponent &component,
|
||||
}
|
||||
else {
|
||||
/* Fill the temporary array with values from the existing attribute. */
|
||||
GVArrayPtr old_varray = component.attribute_get_for_read(
|
||||
GVArray old_varray = component.attribute_get_for_read(
|
||||
attribute_id, domain, data_type, default_value);
|
||||
old_varray->materialize_to_uninitialized(IndexRange(domain_size), data);
|
||||
old_varray.materialize_to_uninitialized(IndexRange(domain_size), data);
|
||||
}
|
||||
GVMutableArrayPtr varray = std::make_unique<GVMutableAttribute_For_OutputAttribute>(
|
||||
GVMutableArray varray = GVMutableArray::For<GVMutableAttribute_For_OutputAttribute>(
|
||||
GMutableSpan{*cpp_type, data, domain_size}, component, attribute_id);
|
||||
|
||||
return OutputAttribute(std::move(varray), domain, save_output_attribute, true);
|
||||
@@ -1410,21 +1407,21 @@ OutputAttribute GeometryComponent::attribute_try_get_for_output_only(
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
const GVArray *AttributeFieldInput::get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask UNUSED(mask),
|
||||
ResourceScope &scope) const
|
||||
GVArray AttributeFieldInput::get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask UNUSED(mask),
|
||||
ResourceScope &UNUSED(scope)) const
|
||||
{
|
||||
if (const GeometryComponentFieldContext *geometry_context =
|
||||
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
|
||||
const GeometryComponent &component = geometry_context->geometry_component();
|
||||
const AttributeDomain domain = geometry_context->domain();
|
||||
const CustomDataType data_type = cpp_type_to_custom_data_type(*type_);
|
||||
GVArrayPtr attribute = component.attribute_try_get_for_read(name_, domain, data_type);
|
||||
GVArray attribute = component.attribute_try_get_for_read(name_, domain, data_type);
|
||||
if (attribute) {
|
||||
return scope.add(std::move(attribute));
|
||||
return attribute;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string AttributeFieldInput::socket_inspection_name() const
|
||||
@@ -1457,25 +1454,25 @@ static StringRef get_random_id_attribute_name(const AttributeDomain domain)
|
||||
}
|
||||
}
|
||||
|
||||
const GVArray *IDAttributeFieldInput::get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const
|
||||
GVArray IDAttributeFieldInput::get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const
|
||||
{
|
||||
if (const GeometryComponentFieldContext *geometry_context =
|
||||
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
|
||||
const GeometryComponent &component = geometry_context->geometry_component();
|
||||
const AttributeDomain domain = geometry_context->domain();
|
||||
const StringRef name = get_random_id_attribute_name(domain);
|
||||
GVArrayPtr attribute = component.attribute_try_get_for_read(name, domain, CD_PROP_INT32);
|
||||
GVArray attribute = component.attribute_try_get_for_read(name, domain, CD_PROP_INT32);
|
||||
if (attribute) {
|
||||
BLI_assert(attribute->size() == component.attribute_domain_size(domain));
|
||||
return scope.add(std::move(attribute));
|
||||
BLI_assert(attribute.size() == component.attribute_domain_size(domain));
|
||||
return attribute;
|
||||
}
|
||||
|
||||
/* Use the index as the fallback if no random ID attribute exists. */
|
||||
return fn::IndexFieldInput::get_index_varray(mask, scope);
|
||||
}
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string IDAttributeFieldInput::socket_inspection_name() const
|
||||
@@ -1495,19 +1492,20 @@ bool IDAttributeFieldInput::is_equal_to(const fn::FieldNode &other) const
|
||||
return dynamic_cast<const IDAttributeFieldInput *>(&other) != nullptr;
|
||||
}
|
||||
|
||||
const GVArray *AnonymousAttributeFieldInput::get_varray_for_context(
|
||||
const fn::FieldContext &context, IndexMask UNUSED(mask), ResourceScope &scope) const
|
||||
GVArray AnonymousAttributeFieldInput::get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask UNUSED(mask),
|
||||
ResourceScope &UNUSED(scope)) const
|
||||
{
|
||||
if (const GeometryComponentFieldContext *geometry_context =
|
||||
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
|
||||
const GeometryComponent &component = geometry_context->geometry_component();
|
||||
const AttributeDomain domain = geometry_context->domain();
|
||||
const CustomDataType data_type = cpp_type_to_custom_data_type(*type_);
|
||||
GVArrayPtr attribute = component.attribute_try_get_for_read(
|
||||
GVArray attribute = component.attribute_try_get_for_read(
|
||||
anonymous_id_.get(), domain, data_type);
|
||||
return scope.add(std::move(attribute));
|
||||
return attribute;
|
||||
}
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string AnonymousAttributeFieldInput::socket_inspection_name() const
|
||||
|
||||
@@ -24,9 +24,6 @@
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
using fn::GVArrayPtr;
|
||||
using fn::GVMutableArrayPtr;
|
||||
|
||||
/**
|
||||
* Utility to group together multiple functions that are used to access custom data on geometry
|
||||
* components in a generic way.
|
||||
@@ -86,7 +83,7 @@ class BuiltinAttributeProvider {
|
||||
{
|
||||
}
|
||||
|
||||
virtual GVArrayPtr try_get_for_read(const GeometryComponent &component) const = 0;
|
||||
virtual GVArray try_get_for_read(const GeometryComponent &component) const = 0;
|
||||
virtual WriteAttributeLookup try_get_for_write(GeometryComponent &component) const = 0;
|
||||
virtual bool try_delete(GeometryComponent &component) const = 0;
|
||||
virtual bool try_create(GeometryComponent &UNUSED(component),
|
||||
@@ -188,8 +185,8 @@ class CustomDataAttributeProvider final : public DynamicAttributesProvider {
|
||||
*/
|
||||
class NamedLegacyCustomDataProvider final : public DynamicAttributesProvider {
|
||||
private:
|
||||
using AsReadAttribute = GVArrayPtr (*)(const void *data, const int domain_size);
|
||||
using AsWriteAttribute = GVMutableArrayPtr (*)(void *data, const int domain_size);
|
||||
using AsReadAttribute = GVArray (*)(const void *data, const int domain_size);
|
||||
using AsWriteAttribute = GVMutableArray (*)(void *data, const int domain_size);
|
||||
const AttributeDomain domain_;
|
||||
const CustomDataType attribute_type_;
|
||||
const CustomDataType stored_type_;
|
||||
@@ -232,8 +229,8 @@ class NamedLegacyCustomDataProvider final : public DynamicAttributesProvider {
|
||||
* if the stored type is the same as the attribute type.
|
||||
*/
|
||||
class BuiltinCustomDataLayerProvider final : public BuiltinAttributeProvider {
|
||||
using AsReadAttribute = GVArrayPtr (*)(const void *data, const int domain_size);
|
||||
using AsWriteAttribute = GVMutableArrayPtr (*)(void *data, const int domain_size);
|
||||
using AsReadAttribute = GVArray (*)(const void *data, const int domain_size);
|
||||
using AsWriteAttribute = GVMutableArray (*)(void *data, const int domain_size);
|
||||
using UpdateOnRead = void (*)(const GeometryComponent &component);
|
||||
using UpdateOnWrite = void (*)(GeometryComponent &component);
|
||||
const CustomDataType stored_type_;
|
||||
@@ -266,7 +263,7 @@ class BuiltinCustomDataLayerProvider final : public BuiltinAttributeProvider {
|
||||
{
|
||||
}
|
||||
|
||||
GVArrayPtr try_get_for_read(const GeometryComponent &component) const final;
|
||||
GVArray try_get_for_read(const GeometryComponent &component) const final;
|
||||
WriteAttributeLookup try_get_for_write(GeometryComponent &component) const final;
|
||||
bool try_delete(GeometryComponent &component) const final;
|
||||
bool try_create(GeometryComponent &component, const AttributeInit &initializer) const final;
|
||||
|
||||
@@ -32,8 +32,6 @@
|
||||
|
||||
using blender::fn::GMutableSpan;
|
||||
using blender::fn::GSpan;
|
||||
using blender::fn::GVArray_Typed;
|
||||
using blender::fn::GVArrayPtr;
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
@@ -76,7 +74,7 @@ static void vert_extrude_to_mesh_data(const Spline &spline,
|
||||
Span<float3> positions = spline.evaluated_positions();
|
||||
Span<float3> tangents = spline.evaluated_tangents();
|
||||
Span<float3> normals = spline.evaluated_normals();
|
||||
GVArray_Typed<float> radii = spline.interpolate_to_evaluated(spline.radii());
|
||||
VArray<float> radii = spline.interpolate_to_evaluated(spline.radii());
|
||||
for (const int i : IndexRange(eval_size)) {
|
||||
float4x4 point_matrix = float4x4::from_normalized_axis_data(
|
||||
positions[i], normals[i], tangents[i]);
|
||||
@@ -227,7 +225,7 @@ static void spline_extrude_to_mesh_data(const ResultInfo &info,
|
||||
Span<float3> normals = spline.evaluated_normals();
|
||||
Span<float3> profile_positions = profile.evaluated_positions();
|
||||
|
||||
GVArray_Typed<float> radii = spline.interpolate_to_evaluated(spline.radii());
|
||||
VArray<float> radii = spline.interpolate_to_evaluated(spline.radii());
|
||||
for (const int i_ring : IndexRange(info.spline_vert_len)) {
|
||||
float4x4 point_matrix = float4x4::from_normalized_axis_data(
|
||||
positions[i_ring], normals[i_ring], tangents[i_ring]);
|
||||
@@ -495,8 +493,8 @@ static void copy_curve_point_attribute_to_mesh(const GSpan src,
|
||||
const ResultInfo &info,
|
||||
ResultAttributeData &dst)
|
||||
{
|
||||
GVArrayPtr interpolated_gvarray = info.spline.interpolate_to_evaluated(src);
|
||||
GSpan interpolated = interpolated_gvarray->get_internal_span();
|
||||
GVArray interpolated_gvarray = info.spline.interpolate_to_evaluated(src);
|
||||
GSpan interpolated = interpolated_gvarray.get_internal_span();
|
||||
|
||||
attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
@@ -561,8 +559,8 @@ static void copy_profile_point_attribute_to_mesh(const GSpan src,
|
||||
const ResultInfo &info,
|
||||
ResultAttributeData &dst)
|
||||
{
|
||||
GVArrayPtr interpolated_gvarray = info.profile.interpolate_to_evaluated(src);
|
||||
GSpan interpolated = interpolated_gvarray->get_internal_span();
|
||||
GVArray interpolated_gvarray = info.profile.interpolate_to_evaluated(src);
|
||||
GSpan interpolated = interpolated_gvarray.get_internal_span();
|
||||
|
||||
attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
|
||||
@@ -28,10 +28,8 @@
|
||||
|
||||
using blender::fn::GMutableSpan;
|
||||
using blender::fn::GSpan;
|
||||
using blender::fn::GVArray_For_GSpan;
|
||||
using blender::fn::GVArray;
|
||||
using blender::fn::GVArray_GSpan;
|
||||
using blender::fn::GVArrayPtr;
|
||||
using blender::fn::GVMutableArray_For_GMutableSpan;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Geometry Component Implementation
|
||||
@@ -253,15 +251,15 @@ void adapt_curve_domain_point_to_spline_impl(const CurveEval &curve,
|
||||
}
|
||||
}
|
||||
|
||||
static GVArrayPtr adapt_curve_domain_point_to_spline(const CurveEval &curve, GVArrayPtr varray)
|
||||
static GVArray adapt_curve_domain_point_to_spline(const CurveEval &curve, GVArray varray)
|
||||
{
|
||||
GVArrayPtr new_varray;
|
||||
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
|
||||
GVArray new_varray;
|
||||
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
|
||||
Array<T> values(curve.splines().size());
|
||||
adapt_curve_domain_point_to_spline_impl<T>(curve, varray->typed<T>(), values);
|
||||
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
|
||||
adapt_curve_domain_point_to_spline_impl<T>(curve, varray.typed<T>(), values);
|
||||
new_varray = VArray<T>::ForContainer(std::move(values));
|
||||
}
|
||||
});
|
||||
return new_varray;
|
||||
@@ -272,29 +270,29 @@ static GVArrayPtr adapt_curve_domain_point_to_spline(const CurveEval &curve, GVA
|
||||
* attributes. The goal is to avoid copying the spline value for every one of its control points
|
||||
* unless it is necessary (in that case the materialize functions will be called).
|
||||
*/
|
||||
template<typename T> class VArray_For_SplineToPoint final : public VArray<T> {
|
||||
GVArrayPtr original_varray_;
|
||||
template<typename T> class VArray_For_SplineToPoint final : public VArrayImpl<T> {
|
||||
GVArray original_varray_;
|
||||
/* Store existing data materialized if it was not already a span. This is expected
|
||||
* to be worth it because a single spline's value will likely be accessed many times. */
|
||||
fn::GVArray_Span<T> original_data_;
|
||||
VArray_Span<T> original_data_;
|
||||
Array<int> offsets_;
|
||||
|
||||
public:
|
||||
VArray_For_SplineToPoint(GVArrayPtr original_varray, Array<int> offsets)
|
||||
: VArray<T>(offsets.last()),
|
||||
VArray_For_SplineToPoint(GVArray original_varray, Array<int> offsets)
|
||||
: VArrayImpl<T>(offsets.last()),
|
||||
original_varray_(std::move(original_varray)),
|
||||
original_data_(*original_varray_),
|
||||
original_data_(original_varray_.typed<T>()),
|
||||
offsets_(std::move(offsets))
|
||||
{
|
||||
}
|
||||
|
||||
T get_impl(const int64_t index) const final
|
||||
T get(const int64_t index) const final
|
||||
{
|
||||
const PointIndices indices = lookup_point_indices(offsets_, index);
|
||||
return original_data_[indices.spline_index];
|
||||
}
|
||||
|
||||
void materialize_impl(const IndexMask mask, MutableSpan<T> r_span) const final
|
||||
void materialize(const IndexMask mask, MutableSpan<T> r_span) const final
|
||||
{
|
||||
const int total_size = offsets_.last();
|
||||
if (mask.is_range() && mask.as_range() == IndexRange(total_size)) {
|
||||
@@ -315,7 +313,7 @@ template<typename T> class VArray_For_SplineToPoint final : public VArray<T> {
|
||||
}
|
||||
}
|
||||
|
||||
void materialize_to_uninitialized_impl(const IndexMask mask, MutableSpan<T> r_span) const final
|
||||
void materialize_to_uninitialized(const IndexMask mask, MutableSpan<T> r_span) const final
|
||||
{
|
||||
T *dst = r_span.data();
|
||||
const int total_size = offsets_.last();
|
||||
@@ -338,29 +336,29 @@ template<typename T> class VArray_For_SplineToPoint final : public VArray<T> {
|
||||
}
|
||||
};
|
||||
|
||||
static GVArrayPtr adapt_curve_domain_spline_to_point(const CurveEval &curve, GVArrayPtr varray)
|
||||
static GVArray adapt_curve_domain_spline_to_point(const CurveEval &curve, GVArray varray)
|
||||
{
|
||||
GVArrayPtr new_varray;
|
||||
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
|
||||
GVArray new_varray;
|
||||
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
|
||||
Array<int> offsets = curve.control_point_offsets();
|
||||
new_varray = std::make_unique<fn::GVArray_For_EmbeddedVArray<T, VArray_For_SplineToPoint<T>>>(
|
||||
offsets.last(), std::move(varray), std::move(offsets));
|
||||
new_varray = VArray<T>::template For<VArray_For_SplineToPoint<T>>(std::move(varray),
|
||||
std::move(offsets));
|
||||
});
|
||||
return new_varray;
|
||||
}
|
||||
|
||||
} // namespace blender::bke
|
||||
|
||||
GVArrayPtr CurveComponent::attribute_try_adapt_domain(GVArrayPtr varray,
|
||||
const AttributeDomain from_domain,
|
||||
const AttributeDomain to_domain) const
|
||||
GVArray CurveComponent::attribute_try_adapt_domain_impl(const GVArray &varray,
|
||||
const AttributeDomain from_domain,
|
||||
const AttributeDomain to_domain) const
|
||||
{
|
||||
if (!varray) {
|
||||
return {};
|
||||
}
|
||||
if (varray->size() == 0) {
|
||||
if (varray.is_empty()) {
|
||||
return {};
|
||||
}
|
||||
if (from_domain == to_domain) {
|
||||
@@ -402,8 +400,8 @@ static const CurveEval *get_curve_from_component_for_read(const GeometryComponen
|
||||
namespace blender::bke {
|
||||
|
||||
class BuiltinSplineAttributeProvider final : public BuiltinAttributeProvider {
|
||||
using AsReadAttribute = GVArrayPtr (*)(const CurveEval &data);
|
||||
using AsWriteAttribute = GVMutableArrayPtr (*)(CurveEval &data);
|
||||
using AsReadAttribute = GVArray (*)(const CurveEval &data);
|
||||
using AsWriteAttribute = GVMutableArray (*)(CurveEval &data);
|
||||
const AsReadAttribute as_read_attribute_;
|
||||
const AsWriteAttribute as_write_attribute_;
|
||||
|
||||
@@ -424,7 +422,7 @@ class BuiltinSplineAttributeProvider final : public BuiltinAttributeProvider {
|
||||
{
|
||||
}
|
||||
|
||||
GVArrayPtr try_get_for_read(const GeometryComponent &component) const final
|
||||
GVArray try_get_for_read(const GeometryComponent &component) const final
|
||||
{
|
||||
const CurveEval *curve = get_curve_from_component_for_read(component);
|
||||
if (curve == nullptr) {
|
||||
@@ -483,19 +481,15 @@ static void set_spline_resolution(SplinePtr &spline, const int resolution)
|
||||
}
|
||||
}
|
||||
|
||||
static GVArrayPtr make_resolution_read_attribute(const CurveEval &curve)
|
||||
static GVArray make_resolution_read_attribute(const CurveEval &curve)
|
||||
{
|
||||
return std::make_unique<fn::GVArray_For_DerivedSpan<SplinePtr, int, get_spline_resolution>>(
|
||||
curve.splines());
|
||||
return VArray<int>::ForDerivedSpan<SplinePtr, get_spline_resolution>(curve.splines());
|
||||
}
|
||||
|
||||
static GVMutableArrayPtr make_resolution_write_attribute(CurveEval &curve)
|
||||
static GVMutableArray make_resolution_write_attribute(CurveEval &curve)
|
||||
{
|
||||
return std::make_unique<fn::GVMutableArray_For_DerivedSpan<SplinePtr,
|
||||
int,
|
||||
get_spline_resolution,
|
||||
set_spline_resolution>>(
|
||||
curve.splines());
|
||||
return VMutableArray<int>::
|
||||
ForDerivedSpan<SplinePtr, get_spline_resolution, set_spline_resolution>(curve.splines());
|
||||
}
|
||||
|
||||
static bool get_cyclic_value(const SplinePtr &spline)
|
||||
@@ -511,16 +505,14 @@ static void set_cyclic_value(SplinePtr &spline, const bool value)
|
||||
}
|
||||
}
|
||||
|
||||
static GVArrayPtr make_cyclic_read_attribute(const CurveEval &curve)
|
||||
static GVArray make_cyclic_read_attribute(const CurveEval &curve)
|
||||
{
|
||||
return std::make_unique<fn::GVArray_For_DerivedSpan<SplinePtr, bool, get_cyclic_value>>(
|
||||
curve.splines());
|
||||
return VArray<bool>::ForDerivedSpan<SplinePtr, get_cyclic_value>(curve.splines());
|
||||
}
|
||||
|
||||
static GVMutableArrayPtr make_cyclic_write_attribute(CurveEval &curve)
|
||||
static GVMutableArray make_cyclic_write_attribute(CurveEval &curve)
|
||||
{
|
||||
return std::make_unique<
|
||||
fn::GVMutableArray_For_DerivedSpan<SplinePtr, bool, get_cyclic_value, set_cyclic_value>>(
|
||||
return VMutableArray<bool>::ForDerivedSpan<SplinePtr, get_cyclic_value, set_cyclic_value>(
|
||||
curve.splines());
|
||||
}
|
||||
|
||||
@@ -623,9 +615,9 @@ static void point_attribute_materialize_to_uninitialized(Span<Span<T>> data,
|
||||
}
|
||||
}
|
||||
|
||||
static GVArrayPtr varray_from_initializer(const AttributeInit &initializer,
|
||||
const CustomDataType data_type,
|
||||
const Span<SplinePtr> splines)
|
||||
static GVArray varray_from_initializer(const AttributeInit &initializer,
|
||||
const CustomDataType data_type,
|
||||
const Span<SplinePtr> splines)
|
||||
{
|
||||
switch (initializer.type) {
|
||||
case AttributeInit::Type::Default:
|
||||
@@ -634,16 +626,15 @@ static GVArrayPtr varray_from_initializer(const AttributeInit &initializer,
|
||||
BLI_assert_unreachable();
|
||||
return {};
|
||||
case AttributeInit::Type::VArray:
|
||||
return static_cast<const AttributeInitVArray &>(initializer).varray->shallow_copy();
|
||||
return static_cast<const AttributeInitVArray &>(initializer).varray;
|
||||
case AttributeInit::Type::MoveArray:
|
||||
int total_size = 0;
|
||||
for (const SplinePtr &spline : splines) {
|
||||
total_size += spline->size();
|
||||
}
|
||||
return std::make_unique<fn::GVArray_For_GSpan>(
|
||||
GSpan(*bke::custom_data_type_to_cpp_type(data_type),
|
||||
static_cast<const AttributeInitMove &>(initializer).data,
|
||||
total_size));
|
||||
return GVArray::ForSpan(GSpan(*bke::custom_data_type_to_cpp_type(data_type),
|
||||
static_cast<const AttributeInitMove &>(initializer).data,
|
||||
total_size));
|
||||
}
|
||||
BLI_assert_unreachable();
|
||||
return {};
|
||||
@@ -691,11 +682,11 @@ static bool create_point_attribute(GeometryComponent &component,
|
||||
/* We just created the attribute, it should exist. */
|
||||
BLI_assert(write_attribute);
|
||||
|
||||
GVArrayPtr source_varray = varray_from_initializer(initializer, data_type, splines);
|
||||
GVArray source_varray = varray_from_initializer(initializer, data_type, splines);
|
||||
/* TODO: When we can call a variant of #set_all with a virtual array argument,
|
||||
* this theoretically unnecessary materialize step could be removed. */
|
||||
GVArray_GSpan source_varray_span{*source_varray};
|
||||
write_attribute.varray->set_all(source_varray_span.data());
|
||||
GVArray_GSpan source_varray_span{source_varray};
|
||||
write_attribute.varray.set_all(source_varray_span.data());
|
||||
|
||||
if (initializer.type == AttributeInit::Type::MoveArray) {
|
||||
MEM_freeN(static_cast<const AttributeInitMove &>(initializer).data);
|
||||
@@ -723,29 +714,29 @@ static bool remove_point_attribute(GeometryComponent &component,
|
||||
/**
|
||||
* Virtual array for any control point data accessed with spans and an offset array.
|
||||
*/
|
||||
template<typename T> class VArray_For_SplinePoints : public VArray<T> {
|
||||
template<typename T> class VArray_For_SplinePoints : public VArrayImpl<T> {
|
||||
private:
|
||||
const Array<Span<T>> data_;
|
||||
Array<int> offsets_;
|
||||
|
||||
public:
|
||||
VArray_For_SplinePoints(Array<Span<T>> data, Array<int> offsets)
|
||||
: VArray<T>(offsets.last()), data_(std::move(data)), offsets_(std::move(offsets))
|
||||
: VArrayImpl<T>(offsets.last()), data_(std::move(data)), offsets_(std::move(offsets))
|
||||
{
|
||||
}
|
||||
|
||||
T get_impl(const int64_t index) const final
|
||||
T get(const int64_t index) const final
|
||||
{
|
||||
const PointIndices indices = lookup_point_indices(offsets_, index);
|
||||
return data_[indices.spline_index][indices.point_index];
|
||||
}
|
||||
|
||||
void materialize_impl(const IndexMask mask, MutableSpan<T> r_span) const final
|
||||
void materialize(const IndexMask mask, MutableSpan<T> r_span) const final
|
||||
{
|
||||
point_attribute_materialize(data_.as_span(), offsets_, mask, r_span);
|
||||
}
|
||||
|
||||
void materialize_to_uninitialized_impl(const IndexMask mask, MutableSpan<T> r_span) const final
|
||||
void materialize_to_uninitialized(const IndexMask mask, MutableSpan<T> r_span) const final
|
||||
{
|
||||
point_attribute_materialize_to_uninitialized(data_.as_span(), offsets_, mask, r_span);
|
||||
}
|
||||
@@ -754,30 +745,30 @@ template<typename T> class VArray_For_SplinePoints : public VArray<T> {
|
||||
/**
|
||||
* Mutable virtual array for any control point data accessed with spans and an offset array.
|
||||
*/
|
||||
template<typename T> class VMutableArray_For_SplinePoints final : public VMutableArray<T> {
|
||||
template<typename T> class VMutableArray_For_SplinePoints final : public VMutableArrayImpl<T> {
|
||||
private:
|
||||
Array<MutableSpan<T>> data_;
|
||||
Array<int> offsets_;
|
||||
|
||||
public:
|
||||
VMutableArray_For_SplinePoints(Array<MutableSpan<T>> data, Array<int> offsets)
|
||||
: VMutableArray<T>(offsets.last()), data_(std::move(data)), offsets_(std::move(offsets))
|
||||
: VMutableArrayImpl<T>(offsets.last()), data_(std::move(data)), offsets_(std::move(offsets))
|
||||
{
|
||||
}
|
||||
|
||||
T get_impl(const int64_t index) const final
|
||||
T get(const int64_t index) const final
|
||||
{
|
||||
const PointIndices indices = lookup_point_indices(offsets_, index);
|
||||
return data_[indices.spline_index][indices.point_index];
|
||||
}
|
||||
|
||||
void set_impl(const int64_t index, T value) final
|
||||
void set(const int64_t index, T value) final
|
||||
{
|
||||
const PointIndices indices = lookup_point_indices(offsets_, index);
|
||||
data_[indices.spline_index][indices.point_index] = value;
|
||||
}
|
||||
|
||||
void set_all_impl(Span<T> src) final
|
||||
void set_all(Span<T> src) final
|
||||
{
|
||||
for (const int spline_index : data_.index_range()) {
|
||||
const int offset = offsets_[spline_index];
|
||||
@@ -786,30 +777,28 @@ template<typename T> class VMutableArray_For_SplinePoints final : public VMutabl
|
||||
}
|
||||
}
|
||||
|
||||
void materialize_impl(const IndexMask mask, MutableSpan<T> r_span) const final
|
||||
void materialize(const IndexMask mask, MutableSpan<T> r_span) const final
|
||||
{
|
||||
point_attribute_materialize({(Span<T> *)data_.data(), data_.size()}, offsets_, mask, r_span);
|
||||
}
|
||||
|
||||
void materialize_to_uninitialized_impl(const IndexMask mask, MutableSpan<T> r_span) const final
|
||||
void materialize_to_uninitialized(const IndexMask mask, MutableSpan<T> r_span) const final
|
||||
{
|
||||
point_attribute_materialize_to_uninitialized(
|
||||
{(Span<T> *)data_.data(), data_.size()}, offsets_, mask, r_span);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T> GVArrayPtr point_data_gvarray(Array<Span<T>> spans, Array<int> offsets)
|
||||
template<typename T> VArray<T> point_data_varray(Array<Span<T>> spans, Array<int> offsets)
|
||||
{
|
||||
return std::make_unique<fn::GVArray_For_EmbeddedVArray<T, VArray_For_SplinePoints<T>>>(
|
||||
offsets.last(), std::move(spans), std::move(offsets));
|
||||
return VArray<T>::template For<VArray_For_SplinePoints<T>>(std::move(spans), std::move(offsets));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
GVMutableArrayPtr point_data_gvarray(Array<MutableSpan<T>> spans, Array<int> offsets)
|
||||
VMutableArray<T> point_data_varray(Array<MutableSpan<T>> spans, Array<int> offsets)
|
||||
{
|
||||
return std::make_unique<
|
||||
fn::GVMutableArray_For_EmbeddedVMutableArray<T, VMutableArray_For_SplinePoints<T>>>(
|
||||
offsets.last(), std::move(spans), std::move(offsets));
|
||||
return VMutableArray<T>::template For<VMutableArray_For_SplinePoints<T>>(std::move(spans),
|
||||
std::move(offsets));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -820,24 +809,24 @@ GVMutableArrayPtr point_data_gvarray(Array<MutableSpan<T>> spans, Array<int> off
|
||||
* \note There is no need to check the handle type to avoid changing auto handles, since
|
||||
* retrieving write access to the position data will mark them for recomputation anyway.
|
||||
*/
|
||||
class VMutableArray_For_SplinePosition final : public VMutableArray<float3> {
|
||||
class VMutableArray_For_SplinePosition final : public VMutableArrayImpl<float3> {
|
||||
private:
|
||||
MutableSpan<SplinePtr> splines_;
|
||||
Array<int> offsets_;
|
||||
|
||||
public:
|
||||
VMutableArray_For_SplinePosition(MutableSpan<SplinePtr> splines, Array<int> offsets)
|
||||
: VMutableArray<float3>(offsets.last()), splines_(splines), offsets_(std::move(offsets))
|
||||
: VMutableArrayImpl<float3>(offsets.last()), splines_(splines), offsets_(std::move(offsets))
|
||||
{
|
||||
}
|
||||
|
||||
float3 get_impl(const int64_t index) const final
|
||||
float3 get(const int64_t index) const final
|
||||
{
|
||||
const PointIndices indices = lookup_point_indices(offsets_, index);
|
||||
return splines_[indices.spline_index]->positions()[indices.point_index];
|
||||
}
|
||||
|
||||
void set_impl(const int64_t index, float3 value) final
|
||||
void set(const int64_t index, float3 value) final
|
||||
{
|
||||
const PointIndices indices = lookup_point_indices(offsets_, index);
|
||||
Spline &spline = *splines_[indices.spline_index];
|
||||
@@ -852,7 +841,7 @@ class VMutableArray_For_SplinePosition final : public VMutableArray<float3> {
|
||||
}
|
||||
}
|
||||
|
||||
void set_all_impl(Span<float3> src) final
|
||||
void set_all(Span<float3> src) final
|
||||
{
|
||||
for (const int spline_index : splines_.index_range()) {
|
||||
Spline &spline = *splines_[spline_index];
|
||||
@@ -885,21 +874,20 @@ class VMutableArray_For_SplinePosition final : public VMutableArray<float3> {
|
||||
return spans;
|
||||
}
|
||||
|
||||
void materialize_impl(const IndexMask mask, MutableSpan<float3> r_span) const final
|
||||
void materialize(const IndexMask mask, MutableSpan<float3> r_span) const final
|
||||
{
|
||||
Array<Span<float3>> spans = this->get_position_spans();
|
||||
point_attribute_materialize(spans.as_span(), offsets_, mask, r_span);
|
||||
}
|
||||
|
||||
void materialize_to_uninitialized_impl(const IndexMask mask,
|
||||
MutableSpan<float3> r_span) const final
|
||||
void materialize_to_uninitialized(const IndexMask mask, MutableSpan<float3> r_span) const final
|
||||
{
|
||||
Array<Span<float3>> spans = this->get_position_spans();
|
||||
point_attribute_materialize_to_uninitialized(spans.as_span(), offsets_, mask, r_span);
|
||||
}
|
||||
};
|
||||
|
||||
class VArray_For_BezierHandle final : public VArray<float3> {
|
||||
class VArray_For_BezierHandle final : public VArrayImpl<float3> {
|
||||
private:
|
||||
Span<SplinePtr> splines_;
|
||||
Array<int> offsets_;
|
||||
@@ -907,7 +895,7 @@ class VArray_For_BezierHandle final : public VArray<float3> {
|
||||
|
||||
public:
|
||||
VArray_For_BezierHandle(Span<SplinePtr> splines, Array<int> offsets, const bool is_right)
|
||||
: VArray<float3>(offsets.last()),
|
||||
: VArrayImpl<float3>(offsets.last()),
|
||||
splines_(std::move(splines)),
|
||||
offsets_(std::move(offsets)),
|
||||
is_right_(is_right)
|
||||
@@ -929,7 +917,7 @@ class VArray_For_BezierHandle final : public VArray<float3> {
|
||||
return float3(0);
|
||||
}
|
||||
|
||||
float3 get_impl(const int64_t index) const final
|
||||
float3 get(const int64_t index) const final
|
||||
{
|
||||
return get_internal(index, splines_, offsets_, is_right_);
|
||||
}
|
||||
@@ -976,19 +964,18 @@ class VArray_For_BezierHandle final : public VArray<float3> {
|
||||
point_attribute_materialize_to_uninitialized(spans.as_span(), offsets, mask, r_span);
|
||||
}
|
||||
|
||||
void materialize_impl(const IndexMask mask, MutableSpan<float3> r_span) const final
|
||||
void materialize(const IndexMask mask, MutableSpan<float3> r_span) const final
|
||||
{
|
||||
materialize_internal(mask, splines_, offsets_, is_right_, r_span);
|
||||
}
|
||||
|
||||
void materialize_to_uninitialized_impl(const IndexMask mask,
|
||||
MutableSpan<float3> r_span) const final
|
||||
void materialize_to_uninitialized(const IndexMask mask, MutableSpan<float3> r_span) const final
|
||||
{
|
||||
materialize_to_uninitialized_internal(mask, splines_, offsets_, is_right_, r_span);
|
||||
}
|
||||
};
|
||||
|
||||
class VMutableArray_For_BezierHandles final : public VMutableArray<float3> {
|
||||
class VMutableArray_For_BezierHandles final : public VMutableArrayImpl<float3> {
|
||||
private:
|
||||
MutableSpan<SplinePtr> splines_;
|
||||
Array<int> offsets_;
|
||||
@@ -998,19 +985,19 @@ class VMutableArray_For_BezierHandles final : public VMutableArray<float3> {
|
||||
VMutableArray_For_BezierHandles(MutableSpan<SplinePtr> splines,
|
||||
Array<int> offsets,
|
||||
const bool is_right)
|
||||
: VMutableArray<float3>(offsets.last()),
|
||||
: VMutableArrayImpl<float3>(offsets.last()),
|
||||
splines_(splines),
|
||||
offsets_(std::move(offsets)),
|
||||
is_right_(is_right)
|
||||
{
|
||||
}
|
||||
|
||||
float3 get_impl(const int64_t index) const final
|
||||
float3 get(const int64_t index) const final
|
||||
{
|
||||
return VArray_For_BezierHandle::get_internal(index, splines_, offsets_, is_right_);
|
||||
}
|
||||
|
||||
void set_impl(const int64_t index, float3 value) final
|
||||
void set(const int64_t index, float3 value) final
|
||||
{
|
||||
const PointIndices indices = lookup_point_indices(offsets_, index);
|
||||
Spline &spline = *splines_[indices.spline_index];
|
||||
@@ -1026,7 +1013,7 @@ class VMutableArray_For_BezierHandles final : public VMutableArray<float3> {
|
||||
}
|
||||
}
|
||||
|
||||
void set_all_impl(Span<float3> src) final
|
||||
void set_all(Span<float3> src) final
|
||||
{
|
||||
for (const int spline_index : splines_.index_range()) {
|
||||
Spline &spline = *splines_[spline_index];
|
||||
@@ -1049,13 +1036,12 @@ class VMutableArray_For_BezierHandles final : public VMutableArray<float3> {
|
||||
}
|
||||
}
|
||||
|
||||
void materialize_impl(const IndexMask mask, MutableSpan<float3> r_span) const final
|
||||
void materialize(const IndexMask mask, MutableSpan<float3> r_span) const final
|
||||
{
|
||||
VArray_For_BezierHandle::materialize_internal(mask, splines_, offsets_, is_right_, r_span);
|
||||
}
|
||||
|
||||
void materialize_to_uninitialized_impl(const IndexMask mask,
|
||||
MutableSpan<float3> r_span) const final
|
||||
void materialize_to_uninitialized(const IndexMask mask, MutableSpan<float3> r_span) const final
|
||||
{
|
||||
VArray_For_BezierHandle::materialize_to_uninitialized_internal(
|
||||
mask, splines_, offsets_, is_right_, r_span);
|
||||
@@ -1097,7 +1083,7 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu
|
||||
{
|
||||
}
|
||||
|
||||
GVArrayPtr try_get_for_read(const GeometryComponent &component) const override
|
||||
GVArray try_get_for_read(const GeometryComponent &component) const override
|
||||
{
|
||||
const CurveEval *curve = get_curve_from_component_for_read(component);
|
||||
if (curve == nullptr) {
|
||||
@@ -1110,7 +1096,7 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu
|
||||
|
||||
Span<SplinePtr> splines = curve->splines();
|
||||
if (splines.size() == 1) {
|
||||
return std::make_unique<fn::GVArray_For_GSpan>(get_span_(*splines.first()));
|
||||
return GVArray::ForSpan(get_span_(*splines.first()));
|
||||
}
|
||||
|
||||
Array<int> offsets = curve->control_point_offsets();
|
||||
@@ -1119,7 +1105,7 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu
|
||||
spans[i] = get_span_(*splines[i]);
|
||||
}
|
||||
|
||||
return point_data_gvarray(spans, offsets);
|
||||
return point_data_varray(spans, offsets);
|
||||
}
|
||||
|
||||
WriteAttributeLookup try_get_for_write(GeometryComponent &component) const override
|
||||
@@ -1144,8 +1130,7 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu
|
||||
|
||||
MutableSpan<SplinePtr> splines = curve->splines();
|
||||
if (splines.size() == 1) {
|
||||
return {std::make_unique<fn::GVMutableArray_For_GMutableSpan>(
|
||||
get_mutable_span_(*splines.first())),
|
||||
return {GVMutableArray::ForSpan(get_mutable_span_(*splines.first())),
|
||||
domain_,
|
||||
std::move(tag_modified_fn)};
|
||||
}
|
||||
@@ -1156,7 +1141,7 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu
|
||||
spans[i] = get_mutable_span_(*splines[i]);
|
||||
}
|
||||
|
||||
return {point_data_gvarray(spans, offsets), domain_, tag_modified_fn};
|
||||
return {point_data_varray(spans, offsets), domain_, tag_modified_fn};
|
||||
}
|
||||
|
||||
bool try_delete(GeometryComponent &component) const final
|
||||
@@ -1248,10 +1233,8 @@ class PositionAttributeProvider final : public BuiltinPointAttributeProvider<flo
|
||||
};
|
||||
|
||||
Array<int> offsets = curve->control_point_offsets();
|
||||
return {std::make_unique<
|
||||
fn::GVMutableArray_For_EmbeddedVMutableArray<float3,
|
||||
VMutableArray_For_SplinePosition>>(
|
||||
offsets.last(), curve->splines(), std::move(offsets)),
|
||||
return {VMutableArray<float3>::For<VMutableArray_For_SplinePosition>(curve->splines(),
|
||||
std::move(offsets)),
|
||||
domain_,
|
||||
tag_modified_fn};
|
||||
}
|
||||
@@ -1273,7 +1256,7 @@ class BezierHandleAttributeProvider : public BuiltinAttributeProvider {
|
||||
{
|
||||
}
|
||||
|
||||
GVArrayPtr try_get_for_read(const GeometryComponent &component) const override
|
||||
GVArray try_get_for_read(const GeometryComponent &component) const override
|
||||
{
|
||||
const CurveEval *curve = get_curve_from_component_for_read(component);
|
||||
if (curve == nullptr) {
|
||||
@@ -1285,8 +1268,8 @@ class BezierHandleAttributeProvider : public BuiltinAttributeProvider {
|
||||
}
|
||||
|
||||
Array<int> offsets = curve->control_point_offsets();
|
||||
return std::make_unique<fn::GVArray_For_EmbeddedVArray<float3, VArray_For_BezierHandle>>(
|
||||
offsets.last(), curve->splines(), std::move(offsets), is_right_);
|
||||
return VArray<float3>::For<VArray_For_BezierHandle>(
|
||||
curve->splines(), std::move(offsets), is_right_);
|
||||
}
|
||||
|
||||
WriteAttributeLookup try_get_for_write(GeometryComponent &component) const override
|
||||
@@ -1303,12 +1286,10 @@ class BezierHandleAttributeProvider : public BuiltinAttributeProvider {
|
||||
auto tag_modified_fn = [curve]() { curve->mark_cache_invalid(); };
|
||||
|
||||
Array<int> offsets = curve->control_point_offsets();
|
||||
return {
|
||||
std::make_unique<
|
||||
fn::GVMutableArray_For_EmbeddedVMutableArray<float3, VMutableArray_For_BezierHandles>>(
|
||||
offsets.last(), curve->splines(), std::move(offsets), is_right_),
|
||||
domain_,
|
||||
tag_modified_fn};
|
||||
return {VMutableArray<float3>::For<VMutableArray_For_BezierHandles>(
|
||||
curve->splines(), std::move(offsets), is_right_),
|
||||
domain_,
|
||||
tag_modified_fn};
|
||||
}
|
||||
|
||||
bool try_delete(GeometryComponent &UNUSED(component)) const final
|
||||
@@ -1387,7 +1368,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider {
|
||||
|
||||
/* First check for the simpler situation when we can return a simpler span virtual array. */
|
||||
if (spans.size() == 1) {
|
||||
return {std::make_unique<GVArray_For_GSpan>(spans.first()), ATTR_DOMAIN_POINT};
|
||||
return {GVArray::ForSpan(spans.first()), ATTR_DOMAIN_POINT};
|
||||
}
|
||||
|
||||
ReadAttributeLookup attribute = {};
|
||||
@@ -1399,7 +1380,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider {
|
||||
data[i] = spans[i].typed<T>();
|
||||
BLI_assert(data[i].data() != nullptr);
|
||||
}
|
||||
attribute = {point_data_gvarray(data, offsets), ATTR_DOMAIN_POINT};
|
||||
attribute = {point_data_varray(data, offsets), ATTR_DOMAIN_POINT};
|
||||
});
|
||||
return attribute;
|
||||
}
|
||||
@@ -1440,7 +1421,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider {
|
||||
|
||||
/* First check for the simpler situation when we can return a simpler span virtual array. */
|
||||
if (spans.size() == 1) {
|
||||
return {std::make_unique<GVMutableArray_For_GMutableSpan>(spans.first()), ATTR_DOMAIN_POINT};
|
||||
return {GVMutableArray::ForSpan(spans.first()), ATTR_DOMAIN_POINT};
|
||||
}
|
||||
|
||||
WriteAttributeLookup attribute = {};
|
||||
@@ -1452,7 +1433,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider {
|
||||
data[i] = spans[i].typed<T>();
|
||||
BLI_assert(data[i].data() != nullptr);
|
||||
}
|
||||
attribute = {point_data_gvarray(data, offsets), ATTR_DOMAIN_POINT};
|
||||
attribute = {point_data_varray(data, offsets), ATTR_DOMAIN_POINT};
|
||||
});
|
||||
return attribute;
|
||||
}
|
||||
|
||||
@@ -389,25 +389,22 @@ class InstancePositionAttributeProvider final : public BuiltinAttributeProvider
|
||||
{
|
||||
}
|
||||
|
||||
GVArrayPtr try_get_for_read(const GeometryComponent &component) const final
|
||||
GVArray try_get_for_read(const GeometryComponent &component) const final
|
||||
{
|
||||
const InstancesComponent &instances_component = static_cast<const InstancesComponent &>(
|
||||
component);
|
||||
Span<float4x4> transforms = instances_component.instance_transforms();
|
||||
return std::make_unique<fn::GVArray_For_DerivedSpan<float4x4, float3, get_transform_position>>(
|
||||
transforms);
|
||||
return VArray<float3>::ForDerivedSpan<float4x4, get_transform_position>(transforms);
|
||||
}
|
||||
|
||||
WriteAttributeLookup try_get_for_write(GeometryComponent &component) const final
|
||||
{
|
||||
InstancesComponent &instances_component = static_cast<InstancesComponent &>(component);
|
||||
MutableSpan<float4x4> transforms = instances_component.instance_transforms();
|
||||
return {
|
||||
std::make_unique<fn::GVMutableArray_For_DerivedSpan<float4x4,
|
||||
float3,
|
||||
get_transform_position,
|
||||
set_transform_position>>(transforms),
|
||||
domain_};
|
||||
return {VMutableArray<float3>::ForDerivedSpan<float4x4,
|
||||
get_transform_position,
|
||||
set_transform_position>(transforms),
|
||||
domain_};
|
||||
}
|
||||
|
||||
bool try_delete(GeometryComponent &UNUSED(component)) const final
|
||||
@@ -435,13 +432,13 @@ class InstanceIDAttributeProvider final : public BuiltinAttributeProvider {
|
||||
{
|
||||
}
|
||||
|
||||
GVArrayPtr try_get_for_read(const GeometryComponent &component) const final
|
||||
GVArray try_get_for_read(const GeometryComponent &component) const final
|
||||
{
|
||||
const InstancesComponent &instances = static_cast<const InstancesComponent &>(component);
|
||||
if (instances.instance_ids().is_empty()) {
|
||||
return {};
|
||||
}
|
||||
return std::make_unique<fn::GVArray_For_Span<int>>(instances.instance_ids());
|
||||
return VArray<int>::ForSpan(instances.instance_ids());
|
||||
}
|
||||
|
||||
WriteAttributeLookup try_get_for_write(GeometryComponent &component) const final
|
||||
@@ -450,8 +447,7 @@ class InstanceIDAttributeProvider final : public BuiltinAttributeProvider {
|
||||
if (instances.instance_ids().is_empty()) {
|
||||
return {};
|
||||
}
|
||||
return {std::make_unique<fn::GVMutableArray_For_MutableSpan<int>>(instances.instance_ids()),
|
||||
domain_};
|
||||
return {VMutableArray<int>::ForSpan(instances.instance_ids()), domain_};
|
||||
}
|
||||
|
||||
bool try_delete(GeometryComponent &component) const final
|
||||
@@ -477,8 +473,8 @@ class InstanceIDAttributeProvider final : public BuiltinAttributeProvider {
|
||||
break;
|
||||
}
|
||||
case AttributeInit::Type::VArray: {
|
||||
const GVArray *varray = static_cast<const AttributeInitVArray &>(initializer).varray;
|
||||
varray->materialize_to_uninitialized(IndexRange(varray->size()), ids.data());
|
||||
const GVArray &varray = static_cast<const AttributeInitVArray &>(initializer).varray;
|
||||
varray.materialize_to_uninitialized(varray.index_range(), ids.data());
|
||||
break;
|
||||
}
|
||||
case AttributeInit::Type::MoveArray: {
|
||||
|
||||
@@ -32,8 +32,6 @@
|
||||
/* Can't include BKE_object_deform.h right now, due to an enum forward declaration. */
|
||||
extern "C" MDeformVert *BKE_object_defgroup_data_create(ID *id);
|
||||
|
||||
using blender::fn::GVArray;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Geometry Component Implementation
|
||||
* \{ */
|
||||
@@ -203,17 +201,17 @@ void adapt_mesh_domain_corner_to_point_impl(const Mesh &mesh,
|
||||
}
|
||||
}
|
||||
|
||||
static GVArrayPtr adapt_mesh_domain_corner_to_point(const Mesh &mesh, GVArrayPtr varray)
|
||||
static GVArray adapt_mesh_domain_corner_to_point(const Mesh &mesh, const GVArray &varray)
|
||||
{
|
||||
GVArrayPtr new_varray;
|
||||
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
|
||||
GVArray new_varray;
|
||||
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
|
||||
/* We compute all interpolated values at once, because for this interpolation, one has to
|
||||
* iterate over all loops anyway. */
|
||||
Array<T> values(mesh.totvert);
|
||||
adapt_mesh_domain_corner_to_point_impl<T>(mesh, varray->typed<T>(), values);
|
||||
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
|
||||
adapt_mesh_domain_corner_to_point_impl<T>(mesh, varray.typed<T>(), values);
|
||||
new_varray = VArray<T>::ForContainer(std::move(values));
|
||||
}
|
||||
});
|
||||
return new_varray;
|
||||
@@ -239,14 +237,14 @@ static void adapt_mesh_domain_point_to_corner_impl(const Mesh &mesh,
|
||||
}
|
||||
}
|
||||
|
||||
static GVArrayPtr adapt_mesh_domain_point_to_corner(const Mesh &mesh, GVArrayPtr varray)
|
||||
static GVArray adapt_mesh_domain_point_to_corner(const Mesh &mesh, const GVArray &varray)
|
||||
{
|
||||
GVArrayPtr new_varray;
|
||||
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
|
||||
GVArray new_varray;
|
||||
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
Array<T> values(mesh.totloop);
|
||||
adapt_mesh_domain_point_to_corner_impl<T>(mesh, varray->typed<T>(), values);
|
||||
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
|
||||
adapt_mesh_domain_point_to_corner_impl<T>(mesh, varray.typed<T>(), values);
|
||||
new_varray = VArray<T>::ForContainer(std::move(values));
|
||||
});
|
||||
return new_varray;
|
||||
}
|
||||
@@ -295,15 +293,15 @@ void adapt_mesh_domain_corner_to_face_impl(const Mesh &mesh,
|
||||
}
|
||||
}
|
||||
|
||||
static GVArrayPtr adapt_mesh_domain_corner_to_face(const Mesh &mesh, GVArrayPtr varray)
|
||||
static GVArray adapt_mesh_domain_corner_to_face(const Mesh &mesh, const GVArray &varray)
|
||||
{
|
||||
GVArrayPtr new_varray;
|
||||
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
|
||||
GVArray new_varray;
|
||||
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
|
||||
Array<T> values(mesh.totpoly);
|
||||
adapt_mesh_domain_corner_to_face_impl<T>(mesh, varray->typed<T>(), values);
|
||||
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
|
||||
adapt_mesh_domain_corner_to_face_impl<T>(mesh, varray.typed<T>(), values);
|
||||
new_varray = VArray<T>::ForContainer(std::move(values));
|
||||
}
|
||||
});
|
||||
return new_varray;
|
||||
@@ -368,15 +366,15 @@ void adapt_mesh_domain_corner_to_edge_impl(const Mesh &mesh,
|
||||
}
|
||||
}
|
||||
|
||||
static GVArrayPtr adapt_mesh_domain_corner_to_edge(const Mesh &mesh, GVArrayPtr varray)
|
||||
static GVArray adapt_mesh_domain_corner_to_edge(const Mesh &mesh, const GVArray &varray)
|
||||
{
|
||||
GVArrayPtr new_varray;
|
||||
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
|
||||
GVArray new_varray;
|
||||
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
|
||||
Array<T> values(mesh.totedge);
|
||||
adapt_mesh_domain_corner_to_edge_impl<T>(mesh, varray->typed<T>(), values);
|
||||
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
|
||||
adapt_mesh_domain_corner_to_edge_impl<T>(mesh, varray.typed<T>(), values);
|
||||
new_varray = VArray<T>::ForContainer(std::move(values));
|
||||
}
|
||||
});
|
||||
return new_varray;
|
||||
@@ -424,15 +422,15 @@ void adapt_mesh_domain_face_to_point_impl(const Mesh &mesh,
|
||||
}
|
||||
}
|
||||
|
||||
static GVArrayPtr adapt_mesh_domain_face_to_point(const Mesh &mesh, GVArrayPtr varray)
|
||||
static GVArray adapt_mesh_domain_face_to_point(const Mesh &mesh, const GVArray &varray)
|
||||
{
|
||||
GVArrayPtr new_varray;
|
||||
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
|
||||
GVArray new_varray;
|
||||
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
|
||||
Array<T> values(mesh.totvert);
|
||||
adapt_mesh_domain_face_to_point_impl<T>(mesh, varray->typed<T>(), values);
|
||||
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
|
||||
adapt_mesh_domain_face_to_point_impl<T>(mesh, varray.typed<T>(), values);
|
||||
new_varray = VArray<T>::ForContainer(std::move(values));
|
||||
}
|
||||
});
|
||||
return new_varray;
|
||||
@@ -453,15 +451,15 @@ void adapt_mesh_domain_face_to_corner_impl(const Mesh &mesh,
|
||||
}
|
||||
}
|
||||
|
||||
static GVArrayPtr adapt_mesh_domain_face_to_corner(const Mesh &mesh, GVArrayPtr varray)
|
||||
static GVArray adapt_mesh_domain_face_to_corner(const Mesh &mesh, const GVArray &varray)
|
||||
{
|
||||
GVArrayPtr new_varray;
|
||||
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
|
||||
GVArray new_varray;
|
||||
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
|
||||
Array<T> values(mesh.totloop);
|
||||
adapt_mesh_domain_face_to_corner_impl<T>(mesh, varray->typed<T>(), values);
|
||||
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
|
||||
adapt_mesh_domain_face_to_corner_impl<T>(mesh, varray.typed<T>(), values);
|
||||
new_varray = VArray<T>::ForContainer(std::move(values));
|
||||
}
|
||||
});
|
||||
return new_varray;
|
||||
@@ -507,15 +505,15 @@ void adapt_mesh_domain_face_to_edge_impl(const Mesh &mesh,
|
||||
}
|
||||
}
|
||||
|
||||
static GVArrayPtr adapt_mesh_domain_face_to_edge(const Mesh &mesh, GVArrayPtr varray)
|
||||
static GVArray adapt_mesh_domain_face_to_edge(const Mesh &mesh, const GVArray &varray)
|
||||
{
|
||||
GVArrayPtr new_varray;
|
||||
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
|
||||
GVArray new_varray;
|
||||
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
|
||||
Array<T> values(mesh.totedge);
|
||||
adapt_mesh_domain_face_to_edge_impl<T>(mesh, varray->typed<T>(), values);
|
||||
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
|
||||
adapt_mesh_domain_face_to_edge_impl<T>(mesh, varray.typed<T>(), values);
|
||||
new_varray = VArray<T>::ForContainer(std::move(values));
|
||||
}
|
||||
});
|
||||
return new_varray;
|
||||
@@ -567,15 +565,15 @@ void adapt_mesh_domain_point_to_face_impl(const Mesh &mesh,
|
||||
}
|
||||
}
|
||||
|
||||
static GVArrayPtr adapt_mesh_domain_point_to_face(const Mesh &mesh, GVArrayPtr varray)
|
||||
static GVArray adapt_mesh_domain_point_to_face(const Mesh &mesh, const GVArray &varray)
|
||||
{
|
||||
GVArrayPtr new_varray;
|
||||
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
|
||||
GVArray new_varray;
|
||||
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
|
||||
Array<T> values(mesh.totpoly);
|
||||
adapt_mesh_domain_point_to_face_impl<T>(mesh, varray->typed<T>(), values);
|
||||
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
|
||||
adapt_mesh_domain_point_to_face_impl<T>(mesh, varray.typed<T>(), values);
|
||||
new_varray = VArray<T>::ForContainer(std::move(values));
|
||||
}
|
||||
});
|
||||
return new_varray;
|
||||
@@ -617,15 +615,15 @@ void adapt_mesh_domain_point_to_edge_impl(const Mesh &mesh,
|
||||
}
|
||||
}
|
||||
|
||||
static GVArrayPtr adapt_mesh_domain_point_to_edge(const Mesh &mesh, GVArrayPtr varray)
|
||||
static GVArray adapt_mesh_domain_point_to_edge(const Mesh &mesh, const GVArray &varray)
|
||||
{
|
||||
GVArrayPtr new_varray;
|
||||
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
|
||||
GVArray new_varray;
|
||||
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
|
||||
Array<T> values(mesh.totedge);
|
||||
adapt_mesh_domain_point_to_edge_impl<T>(mesh, varray->typed<T>(), values);
|
||||
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
|
||||
adapt_mesh_domain_point_to_edge_impl<T>(mesh, varray.typed<T>(), values);
|
||||
new_varray = VArray<T>::ForContainer(std::move(values));
|
||||
}
|
||||
});
|
||||
return new_varray;
|
||||
@@ -678,15 +676,15 @@ void adapt_mesh_domain_edge_to_corner_impl(const Mesh &mesh,
|
||||
}
|
||||
}
|
||||
|
||||
static GVArrayPtr adapt_mesh_domain_edge_to_corner(const Mesh &mesh, GVArrayPtr varray)
|
||||
static GVArray adapt_mesh_domain_edge_to_corner(const Mesh &mesh, const GVArray &varray)
|
||||
{
|
||||
GVArrayPtr new_varray;
|
||||
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
|
||||
GVArray new_varray;
|
||||
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
|
||||
Array<T> values(mesh.totloop);
|
||||
adapt_mesh_domain_edge_to_corner_impl<T>(mesh, varray->typed<T>(), values);
|
||||
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
|
||||
adapt_mesh_domain_edge_to_corner_impl<T>(mesh, varray.typed<T>(), values);
|
||||
new_varray = VArray<T>::ForContainer(std::move(values));
|
||||
}
|
||||
});
|
||||
return new_varray;
|
||||
@@ -728,15 +726,15 @@ void adapt_mesh_domain_edge_to_point_impl(const Mesh &mesh,
|
||||
}
|
||||
}
|
||||
|
||||
static GVArrayPtr adapt_mesh_domain_edge_to_point(const Mesh &mesh, GVArrayPtr varray)
|
||||
static GVArray adapt_mesh_domain_edge_to_point(const Mesh &mesh, const GVArray &varray)
|
||||
{
|
||||
GVArrayPtr new_varray;
|
||||
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
|
||||
GVArray new_varray;
|
||||
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
|
||||
Array<T> values(mesh.totvert);
|
||||
adapt_mesh_domain_edge_to_point_impl<T>(mesh, varray->typed<T>(), values);
|
||||
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
|
||||
adapt_mesh_domain_edge_to_point_impl<T>(mesh, varray.typed<T>(), values);
|
||||
new_varray = VArray<T>::ForContainer(std::move(values));
|
||||
}
|
||||
});
|
||||
return new_varray;
|
||||
@@ -788,15 +786,15 @@ void adapt_mesh_domain_edge_to_face_impl(const Mesh &mesh,
|
||||
}
|
||||
}
|
||||
|
||||
static GVArrayPtr adapt_mesh_domain_edge_to_face(const Mesh &mesh, GVArrayPtr varray)
|
||||
static GVArray adapt_mesh_domain_edge_to_face(const Mesh &mesh, const GVArray &varray)
|
||||
{
|
||||
GVArrayPtr new_varray;
|
||||
attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) {
|
||||
GVArray new_varray;
|
||||
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
|
||||
Array<T> values(mesh.totpoly);
|
||||
adapt_mesh_domain_edge_to_face_impl<T>(mesh, varray->typed<T>(), values);
|
||||
new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
|
||||
adapt_mesh_domain_edge_to_face_impl<T>(mesh, varray.typed<T>(), values);
|
||||
new_varray = VArray<T>::ForContainer(std::move(values));
|
||||
}
|
||||
});
|
||||
return new_varray;
|
||||
@@ -804,15 +802,15 @@ static GVArrayPtr adapt_mesh_domain_edge_to_face(const Mesh &mesh, GVArrayPtr va
|
||||
|
||||
} // namespace blender::bke
|
||||
|
||||
blender::fn::GVArrayPtr MeshComponent::attribute_try_adapt_domain(
|
||||
blender::fn::GVArrayPtr varray,
|
||||
blender::fn::GVArray MeshComponent::attribute_try_adapt_domain_impl(
|
||||
const blender::fn::GVArray &varray,
|
||||
const AttributeDomain from_domain,
|
||||
const AttributeDomain to_domain) const
|
||||
{
|
||||
if (!varray) {
|
||||
return {};
|
||||
}
|
||||
if (varray->size() == 0) {
|
||||
if (varray.size() == 0) {
|
||||
return {};
|
||||
}
|
||||
if (from_domain == to_domain) {
|
||||
@@ -823,11 +821,11 @@ blender::fn::GVArrayPtr MeshComponent::attribute_try_adapt_domain(
|
||||
case ATTR_DOMAIN_CORNER: {
|
||||
switch (to_domain) {
|
||||
case ATTR_DOMAIN_POINT:
|
||||
return blender::bke::adapt_mesh_domain_corner_to_point(*mesh_, std::move(varray));
|
||||
return blender::bke::adapt_mesh_domain_corner_to_point(*mesh_, varray);
|
||||
case ATTR_DOMAIN_FACE:
|
||||
return blender::bke::adapt_mesh_domain_corner_to_face(*mesh_, std::move(varray));
|
||||
return blender::bke::adapt_mesh_domain_corner_to_face(*mesh_, varray);
|
||||
case ATTR_DOMAIN_EDGE:
|
||||
return blender::bke::adapt_mesh_domain_corner_to_edge(*mesh_, std::move(varray));
|
||||
return blender::bke::adapt_mesh_domain_corner_to_edge(*mesh_, varray);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -836,11 +834,11 @@ blender::fn::GVArrayPtr MeshComponent::attribute_try_adapt_domain(
|
||||
case ATTR_DOMAIN_POINT: {
|
||||
switch (to_domain) {
|
||||
case ATTR_DOMAIN_CORNER:
|
||||
return blender::bke::adapt_mesh_domain_point_to_corner(*mesh_, std::move(varray));
|
||||
return blender::bke::adapt_mesh_domain_point_to_corner(*mesh_, varray);
|
||||
case ATTR_DOMAIN_FACE:
|
||||
return blender::bke::adapt_mesh_domain_point_to_face(*mesh_, std::move(varray));
|
||||
return blender::bke::adapt_mesh_domain_point_to_face(*mesh_, varray);
|
||||
case ATTR_DOMAIN_EDGE:
|
||||
return blender::bke::adapt_mesh_domain_point_to_edge(*mesh_, std::move(varray));
|
||||
return blender::bke::adapt_mesh_domain_point_to_edge(*mesh_, varray);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -849,11 +847,11 @@ blender::fn::GVArrayPtr MeshComponent::attribute_try_adapt_domain(
|
||||
case ATTR_DOMAIN_FACE: {
|
||||
switch (to_domain) {
|
||||
case ATTR_DOMAIN_POINT:
|
||||
return blender::bke::adapt_mesh_domain_face_to_point(*mesh_, std::move(varray));
|
||||
return blender::bke::adapt_mesh_domain_face_to_point(*mesh_, varray);
|
||||
case ATTR_DOMAIN_CORNER:
|
||||
return blender::bke::adapt_mesh_domain_face_to_corner(*mesh_, std::move(varray));
|
||||
return blender::bke::adapt_mesh_domain_face_to_corner(*mesh_, varray);
|
||||
case ATTR_DOMAIN_EDGE:
|
||||
return blender::bke::adapt_mesh_domain_face_to_edge(*mesh_, std::move(varray));
|
||||
return blender::bke::adapt_mesh_domain_face_to_edge(*mesh_, varray);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -862,11 +860,11 @@ blender::fn::GVArrayPtr MeshComponent::attribute_try_adapt_domain(
|
||||
case ATTR_DOMAIN_EDGE: {
|
||||
switch (to_domain) {
|
||||
case ATTR_DOMAIN_CORNER:
|
||||
return blender::bke::adapt_mesh_domain_edge_to_corner(*mesh_, std::move(varray));
|
||||
return blender::bke::adapt_mesh_domain_edge_to_corner(*mesh_, varray);
|
||||
case ATTR_DOMAIN_POINT:
|
||||
return blender::bke::adapt_mesh_domain_edge_to_point(*mesh_, std::move(varray));
|
||||
return blender::bke::adapt_mesh_domain_edge_to_point(*mesh_, varray);
|
||||
case ATTR_DOMAIN_FACE:
|
||||
return blender::bke::adapt_mesh_domain_edge_to_face(*mesh_, std::move(varray));
|
||||
return blender::bke::adapt_mesh_domain_edge_to_face(*mesh_, varray);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -896,9 +894,9 @@ static const Mesh *get_mesh_from_component_for_read(const GeometryComponent &com
|
||||
namespace blender::bke {
|
||||
|
||||
template<typename StructT, typename ElemT, ElemT (*GetFunc)(const StructT &)>
|
||||
static GVArrayPtr make_derived_read_attribute(const void *data, const int domain_size)
|
||||
static GVArray make_derived_read_attribute(const void *data, const int domain_size)
|
||||
{
|
||||
return std::make_unique<fn::GVArray_For_DerivedSpan<StructT, ElemT, GetFunc>>(
|
||||
return VArray<ElemT>::template ForDerivedSpan<StructT, GetFunc>(
|
||||
Span<StructT>((const StructT *)data, domain_size));
|
||||
}
|
||||
|
||||
@@ -906,23 +904,22 @@ template<typename StructT,
|
||||
typename ElemT,
|
||||
ElemT (*GetFunc)(const StructT &),
|
||||
void (*SetFunc)(StructT &, ElemT)>
|
||||
static GVMutableArrayPtr make_derived_write_attribute(void *data, const int domain_size)
|
||||
static GVMutableArray make_derived_write_attribute(void *data, const int domain_size)
|
||||
{
|
||||
return std::make_unique<fn::GVMutableArray_For_DerivedSpan<StructT, ElemT, GetFunc, SetFunc>>(
|
||||
return VMutableArray<ElemT>::template ForDerivedSpan<StructT, GetFunc, SetFunc>(
|
||||
MutableSpan<StructT>((StructT *)data, domain_size));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static GVArrayPtr make_array_read_attribute(const void *data, const int domain_size)
|
||||
static GVArray make_array_read_attribute(const void *data, const int domain_size)
|
||||
{
|
||||
return std::make_unique<fn::GVArray_For_Span<T>>(Span<T>((const T *)data, domain_size));
|
||||
return VArray<T>::ForSpan(Span<T>((const T *)data, domain_size));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static GVMutableArrayPtr make_array_write_attribute(void *data, const int domain_size)
|
||||
static GVMutableArray make_array_write_attribute(void *data, const int domain_size)
|
||||
{
|
||||
return std::make_unique<fn::GVMutableArray_For_MutableSpan<T>>(
|
||||
MutableSpan<T>((T *)data, domain_size));
|
||||
return VMutableArray<T>::ForSpan(MutableSpan<T>((T *)data, domain_size));
|
||||
}
|
||||
|
||||
static float3 get_vertex_position(const MVert &vert)
|
||||
@@ -999,23 +996,23 @@ static void set_crease(MEdge &edge, float value)
|
||||
edge.crease = round_fl_to_uchar_clamp(value * 255.0f);
|
||||
}
|
||||
|
||||
class VMutableArray_For_VertexWeights final : public VMutableArray<float> {
|
||||
class VMutableArray_For_VertexWeights final : public VMutableArrayImpl<float> {
|
||||
private:
|
||||
MDeformVert *dverts_;
|
||||
const int dvert_index_;
|
||||
|
||||
public:
|
||||
VMutableArray_For_VertexWeights(MDeformVert *dverts, const int totvert, const int dvert_index)
|
||||
: VMutableArray<float>(totvert), dverts_(dverts), dvert_index_(dvert_index)
|
||||
: VMutableArrayImpl<float>(totvert), dverts_(dverts), dvert_index_(dvert_index)
|
||||
{
|
||||
}
|
||||
|
||||
float get_impl(const int64_t index) const override
|
||||
float get(const int64_t index) const override
|
||||
{
|
||||
return get_internal(dverts_, dvert_index_, index);
|
||||
}
|
||||
|
||||
void set_impl(const int64_t index, const float value) override
|
||||
void set(const int64_t index, const float value) override
|
||||
{
|
||||
MDeformWeight *weight = BKE_defvert_ensure_index(&dverts_[index], dvert_index_);
|
||||
weight->weight = value;
|
||||
@@ -1036,18 +1033,18 @@ class VMutableArray_For_VertexWeights final : public VMutableArray<float> {
|
||||
}
|
||||
};
|
||||
|
||||
class VArray_For_VertexWeights final : public VArray<float> {
|
||||
class VArray_For_VertexWeights final : public VArrayImpl<float> {
|
||||
private:
|
||||
const MDeformVert *dverts_;
|
||||
const int dvert_index_;
|
||||
|
||||
public:
|
||||
VArray_For_VertexWeights(const MDeformVert *dverts, const int totvert, const int dvert_index)
|
||||
: VArray<float>(totvert), dverts_(dverts), dvert_index_(dvert_index)
|
||||
: VArrayImpl<float>(totvert), dverts_(dverts), dvert_index_(dvert_index)
|
||||
{
|
||||
}
|
||||
|
||||
float get_impl(const int64_t index) const override
|
||||
float get(const int64_t index) const override
|
||||
{
|
||||
return VMutableArray_For_VertexWeights::get_internal(dverts_, dvert_index_, index);
|
||||
}
|
||||
@@ -1078,12 +1075,10 @@ class VertexGroupsAttributeProvider final : public DynamicAttributesProvider {
|
||||
}
|
||||
if (mesh->dvert == nullptr) {
|
||||
static const float default_value = 0.0f;
|
||||
return {std::make_unique<fn::GVArray_For_SingleValueRef>(
|
||||
CPPType::get<float>(), mesh->totvert, &default_value),
|
||||
ATTR_DOMAIN_POINT};
|
||||
return {VArray<float>::ForSingle(default_value, mesh->totvert), ATTR_DOMAIN_POINT};
|
||||
}
|
||||
return {std::make_unique<fn::GVArray_For_EmbeddedVArray<float, VArray_For_VertexWeights>>(
|
||||
mesh->totvert, mesh->dvert, mesh->totvert, vertex_group_index),
|
||||
return {VArray<float>::For<VArray_For_VertexWeights>(
|
||||
mesh->dvert, mesh->totvert, vertex_group_index),
|
||||
ATTR_DOMAIN_POINT};
|
||||
}
|
||||
|
||||
@@ -1114,11 +1109,9 @@ class VertexGroupsAttributeProvider final : public DynamicAttributesProvider {
|
||||
mesh->dvert = (MDeformVert *)CustomData_duplicate_referenced_layer(
|
||||
&mesh->vdata, CD_MDEFORMVERT, mesh->totvert);
|
||||
}
|
||||
return {
|
||||
std::make_unique<
|
||||
fn::GVMutableArray_For_EmbeddedVMutableArray<float, VMutableArray_For_VertexWeights>>(
|
||||
mesh->totvert, mesh->dvert, mesh->totvert, vertex_group_index),
|
||||
ATTR_DOMAIN_POINT};
|
||||
return {VMutableArray<float>::For<VMutableArray_For_VertexWeights>(
|
||||
mesh->dvert, mesh->totvert, vertex_group_index),
|
||||
ATTR_DOMAIN_POINT};
|
||||
}
|
||||
|
||||
bool try_delete(GeometryComponent &component, const AttributeIDRef &attribute_id) const final
|
||||
@@ -1184,7 +1177,7 @@ class NormalAttributeProvider final : public BuiltinAttributeProvider {
|
||||
{
|
||||
}
|
||||
|
||||
GVArrayPtr try_get_for_read(const GeometryComponent &component) const final
|
||||
GVArray try_get_for_read(const GeometryComponent &component) const final
|
||||
{
|
||||
const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
|
||||
const Mesh *mesh = mesh_component.get_for_read();
|
||||
@@ -1197,8 +1190,7 @@ class NormalAttributeProvider final : public BuiltinAttributeProvider {
|
||||
CustomData_has_layer(&mesh->pdata, CD_NORMAL)) {
|
||||
const void *data = CustomData_get_layer(&mesh->pdata, CD_NORMAL);
|
||||
|
||||
return std::make_unique<fn::GVArray_For_Span<float3>>(
|
||||
Span<float3>((const float3 *)data, mesh->totpoly));
|
||||
return VArray<float3>::ForSpan(Span<float3>((const float3 *)data, mesh->totpoly));
|
||||
}
|
||||
|
||||
Array<float3> normals(mesh->totpoly);
|
||||
@@ -1207,7 +1199,7 @@ class NormalAttributeProvider final : public BuiltinAttributeProvider {
|
||||
BKE_mesh_calc_poly_normal(poly, &mesh->mloop[poly->loopstart], mesh->mvert, normals[i]);
|
||||
}
|
||||
|
||||
return std::make_unique<fn::GVArray_For_ArrayContainer<Array<float3>>>(std::move(normals));
|
||||
return VArray<float3>::ForContainer(std::move(normals));
|
||||
}
|
||||
|
||||
WriteAttributeLookup try_get_for_write(GeometryComponent &UNUSED(component)) const final
|
||||
|
||||
@@ -141,16 +141,15 @@ int PointCloudComponent::attribute_domain_size(const AttributeDomain domain) con
|
||||
namespace blender::bke {
|
||||
|
||||
template<typename T>
|
||||
static GVArrayPtr make_array_read_attribute(const void *data, const int domain_size)
|
||||
static GVArray make_array_read_attribute(const void *data, const int domain_size)
|
||||
{
|
||||
return std::make_unique<fn::GVArray_For_Span<T>>(Span<T>((const T *)data, domain_size));
|
||||
return VArray<T>::ForSpan(Span<T>((const T *)data, domain_size));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static GVMutableArrayPtr make_array_write_attribute(void *data, const int domain_size)
|
||||
static GVMutableArray make_array_write_attribute(void *data, const int domain_size)
|
||||
{
|
||||
return std::make_unique<fn::GVMutableArray_For_MutableSpan<T>>(
|
||||
MutableSpan<T>((T *)data, domain_size));
|
||||
return VMutableArray<T>::ForSpan(MutableSpan<T>((T *)data, domain_size));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -360,12 +360,12 @@ static void join_attributes(Span<GeometryInstanceGroup> set_groups,
|
||||
result.attribute_try_create(
|
||||
entry.key, domain_output, data_type_output, AttributeInitDefault());
|
||||
WriteAttributeLookup write_attribute = result.attribute_try_get_for_write(attribute_id);
|
||||
if (!write_attribute || &write_attribute.varray->type() != cpp_type ||
|
||||
if (!write_attribute || &write_attribute.varray.type() != cpp_type ||
|
||||
write_attribute.domain != domain_output) {
|
||||
continue;
|
||||
}
|
||||
|
||||
fn::GVMutableArray_GSpan dst_span{*write_attribute.varray};
|
||||
fn::GVMutableArray_GSpan dst_span{write_attribute.varray};
|
||||
|
||||
int offset = 0;
|
||||
for (const GeometryInstanceGroup &set_group : set_groups) {
|
||||
@@ -377,11 +377,11 @@ static void join_attributes(Span<GeometryInstanceGroup> set_groups,
|
||||
if (domain_size == 0) {
|
||||
continue; /* Domain size is 0, so no need to increment the offset. */
|
||||
}
|
||||
GVArrayPtr source_attribute = component.attribute_try_get_for_read(
|
||||
GVArray source_attribute = component.attribute_try_get_for_read(
|
||||
attribute_id, domain_output, data_type_output);
|
||||
|
||||
if (source_attribute) {
|
||||
fn::GVArray_GSpan src_span{*source_attribute};
|
||||
fn::GVArray_GSpan src_span{source_attribute};
|
||||
const void *src_buffer = src_span.data();
|
||||
for (const int UNUSED(i) : set_group.transforms.index_range()) {
|
||||
void *dst_buffer = dst_span[offset];
|
||||
|
||||
@@ -269,7 +269,7 @@ void MeshAttributeInterpolator::sample_attribute(const ReadAttributeLookup &src_
|
||||
eAttributeMapMode mode)
|
||||
{
|
||||
if (src_attribute && dst_attribute) {
|
||||
this->sample_data(*src_attribute.varray, src_attribute.domain, mode, dst_attribute.as_span());
|
||||
this->sample_data(src_attribute.varray, src_attribute.domain, mode, dst_attribute.as_span());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,14 +30,12 @@ using blender::float3;
|
||||
using blender::IndexRange;
|
||||
using blender::MutableSpan;
|
||||
using blender::Span;
|
||||
using blender::VArray;
|
||||
using blender::attribute_math::convert_to_static_type;
|
||||
using blender::bke::AttributeIDRef;
|
||||
using blender::fn::GMutableSpan;
|
||||
using blender::fn::GSpan;
|
||||
using blender::fn::GVArray;
|
||||
using blender::fn::GVArray_For_GSpan;
|
||||
using blender::fn::GVArray_Typed;
|
||||
using blender::fn::GVArrayPtr;
|
||||
|
||||
Spline::Type Spline::type() const
|
||||
{
|
||||
@@ -416,7 +414,7 @@ Span<float3> Spline::evaluated_normals() const
|
||||
}
|
||||
|
||||
/* Rotate the generated normals with the interpolated tilt data. */
|
||||
GVArray_Typed<float> tilts = this->interpolate_to_evaluated(this->tilts());
|
||||
VArray<float> tilts = this->interpolate_to_evaluated(this->tilts());
|
||||
for (const int i : normals.index_range()) {
|
||||
normals[i] = rotate_direction_around_axis(normals[i], tangents[i], tilts[i]);
|
||||
}
|
||||
@@ -529,9 +527,9 @@ void Spline::bounds_min_max(float3 &min, float3 &max, const bool use_evaluated)
|
||||
}
|
||||
}
|
||||
|
||||
GVArrayPtr Spline::interpolate_to_evaluated(GSpan data) const
|
||||
GVArray Spline::interpolate_to_evaluated(GSpan data) const
|
||||
{
|
||||
return this->interpolate_to_evaluated(GVArray_For_GSpan(data));
|
||||
return this->interpolate_to_evaluated(GVArray::ForSpan(data));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -547,7 +545,7 @@ void Spline::sample_with_index_factors(const GVArray &src,
|
||||
|
||||
blender::attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
const GVArray_Typed<T> src_typed = src.typed<T>();
|
||||
const VArray<T> src_typed = src.typed<T>();
|
||||
MutableSpan<T> dst_typed = dst.typed<T>();
|
||||
if (src.size() == 1) {
|
||||
dst_typed.fill(src_typed[0]);
|
||||
|
||||
@@ -25,9 +25,8 @@ using blender::float3;
|
||||
using blender::IndexRange;
|
||||
using blender::MutableSpan;
|
||||
using blender::Span;
|
||||
using blender::VArray;
|
||||
using blender::fn::GVArray;
|
||||
using blender::fn::GVArray_For_ArrayContainer;
|
||||
using blender::fn::GVArrayPtr;
|
||||
|
||||
void BezierSpline::copy_settings(Spline &dst) const
|
||||
{
|
||||
@@ -702,26 +701,26 @@ static void interpolate_to_evaluated_impl(const BezierSpline &spline,
|
||||
}
|
||||
}
|
||||
|
||||
GVArrayPtr BezierSpline::interpolate_to_evaluated(const GVArray &src) const
|
||||
GVArray BezierSpline::interpolate_to_evaluated(const GVArray &src) const
|
||||
{
|
||||
BLI_assert(src.size() == this->size());
|
||||
|
||||
if (src.is_single()) {
|
||||
return src.shallow_copy();
|
||||
return src;
|
||||
}
|
||||
|
||||
const int eval_size = this->evaluated_points_size();
|
||||
if (eval_size == 1) {
|
||||
return src.shallow_copy();
|
||||
return src;
|
||||
}
|
||||
|
||||
GVArrayPtr new_varray;
|
||||
GVArray new_varray;
|
||||
blender::attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<blender::attribute_math::DefaultMixer<T>>) {
|
||||
Array<T> values(eval_size);
|
||||
interpolate_to_evaluated_impl<T>(*this, src.typed<T>(), values);
|
||||
new_varray = std::make_unique<GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
|
||||
new_varray = VArray<T>::ForContainer(std::move(values));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -26,10 +26,8 @@ using blender::float3;
|
||||
using blender::IndexRange;
|
||||
using blender::MutableSpan;
|
||||
using blender::Span;
|
||||
using blender::VArray;
|
||||
using blender::fn::GVArray;
|
||||
using blender::fn::GVArray_For_ArrayContainer;
|
||||
using blender::fn::GVArray_Typed;
|
||||
using blender::fn::GVArrayPtr;
|
||||
|
||||
void NURBSpline::copy_settings(Spline &dst) const
|
||||
{
|
||||
@@ -410,23 +408,23 @@ void interpolate_to_evaluated_impl(Span<NURBSpline::BasisCache> weights,
|
||||
mixer.finalize();
|
||||
}
|
||||
|
||||
GVArrayPtr NURBSpline::interpolate_to_evaluated(const GVArray &src) const
|
||||
GVArray NURBSpline::interpolate_to_evaluated(const GVArray &src) const
|
||||
{
|
||||
BLI_assert(src.size() == this->size());
|
||||
|
||||
if (src.is_single()) {
|
||||
return src.shallow_copy();
|
||||
return src;
|
||||
}
|
||||
|
||||
Span<BasisCache> basis_cache = this->calculate_basis_cache();
|
||||
|
||||
GVArrayPtr new_varray;
|
||||
GVArray new_varray;
|
||||
blender::attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
if constexpr (!std::is_void_v<blender::attribute_math::DefaultMixer<T>>) {
|
||||
Array<T> values(this->evaluated_points_size());
|
||||
interpolate_to_evaluated_impl<T>(basis_cache, src.typed<T>(), values);
|
||||
new_varray = std::make_unique<GVArray_For_ArrayContainer<Array<T>>>(std::move(values));
|
||||
new_varray = VArray<T>::ForContainer(std::move(values));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -448,8 +446,8 @@ Span<float3> NURBSpline::evaluated_positions() const
|
||||
evaluated_position_cache_.resize(eval_size);
|
||||
|
||||
/* TODO: Avoid copying the evaluated data from the temporary array. */
|
||||
GVArray_Typed<float3> evaluated = Spline::interpolate_to_evaluated(positions_.as_span());
|
||||
evaluated->materialize(evaluated_position_cache_);
|
||||
VArray<float3> evaluated = Spline::interpolate_to_evaluated(positions_.as_span());
|
||||
evaluated.materialize(evaluated_position_cache_);
|
||||
|
||||
position_cache_dirty_ = false;
|
||||
return evaluated_position_cache_;
|
||||
|
||||
@@ -23,7 +23,6 @@ using blender::float3;
|
||||
using blender::MutableSpan;
|
||||
using blender::Span;
|
||||
using blender::fn::GVArray;
|
||||
using blender::fn::GVArrayPtr;
|
||||
|
||||
void PolySpline::copy_settings(Spline &UNUSED(dst)) const
|
||||
{
|
||||
@@ -122,9 +121,8 @@ Span<float3> PolySpline::evaluated_positions() const
|
||||
* the original data. Therefore the lifetime of the returned virtual array must not be longer than
|
||||
* the source data.
|
||||
*/
|
||||
GVArrayPtr PolySpline::interpolate_to_evaluated(const GVArray &src) const
|
||||
GVArray PolySpline::interpolate_to_evaluated(const GVArray &src) const
|
||||
{
|
||||
BLI_assert(src.size() == this->size());
|
||||
|
||||
return src.shallow_copy();
|
||||
return src;
|
||||
}
|
||||
|
||||
319
source/blender/blenlib/BLI_any.hh
Normal file
319
source/blender/blenlib/BLI_any.hh
Normal file
@@ -0,0 +1,319 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/** \file
|
||||
* \ingroup bli
|
||||
*
|
||||
* A #blender::Any is a type-safe container for single values of any copy constructible type.
|
||||
* It is similar to #std::any but provides the following two additional features:
|
||||
* - Adjustable inline buffer capacity and alignment. #std::any has a small inline buffer in most
|
||||
* implementations as well, but its size is not guaranteed.
|
||||
* - Can store additional user-defined type information without increasing the stack size of #Any.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
#include "BLI_memory_utils.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
namespace detail {
|
||||
|
||||
/**
|
||||
* Contains function pointers that manage the memory in an #Any.
|
||||
* Additional type specific #ExtraInfo can be embedded here as well.
|
||||
*/
|
||||
template<typename ExtraInfo> struct AnyTypeInfo {
|
||||
void (*copy_construct)(void *dst, const void *src);
|
||||
void (*move_construct)(void *dst, void *src);
|
||||
void (*destruct)(void *src);
|
||||
const void *(*get)(const void *src);
|
||||
ExtraInfo extra_info;
|
||||
|
||||
/**
|
||||
* Used when #T is stored directly in the inline buffer of the #Any.
|
||||
*/
|
||||
template<typename T> static const AnyTypeInfo &get_for_inline()
|
||||
{
|
||||
static AnyTypeInfo funcs = {[](void *dst, const void *src) { new (dst) T(*(const T *)src); },
|
||||
[](void *dst, void *src) { new (dst) T(std::move(*(T *)src)); },
|
||||
[](void *src) { ((T *)src)->~T(); },
|
||||
[](const void *src) { return src; },
|
||||
ExtraInfo::template get<T>()};
|
||||
return funcs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when #T can't be stored directly in the inline buffer and is stored in a #std::unique_ptr
|
||||
* instead. In this scenario, the #std::unique_ptr is stored in the inline buffer.
|
||||
*/
|
||||
template<typename T> static const AnyTypeInfo &get_for_unique_ptr()
|
||||
{
|
||||
using Ptr = std::unique_ptr<T>;
|
||||
static AnyTypeInfo funcs = {
|
||||
[](void *dst, const void *src) { new (dst) Ptr(new T(**(const Ptr *)src)); },
|
||||
[](void *dst, void *src) { new (dst) Ptr(new T(std::move(**(Ptr *)src))); },
|
||||
[](void *src) { ((Ptr *)src)->~Ptr(); },
|
||||
[](const void *src) -> const void * { return &**(const Ptr *)src; },
|
||||
ExtraInfo::template get<T>()};
|
||||
return funcs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when the #Any does not contain any type currently.
|
||||
*/
|
||||
static const AnyTypeInfo &get_for_empty()
|
||||
{
|
||||
static AnyTypeInfo funcs = {[](void *UNUSED(dst), const void *UNUSED(src)) {},
|
||||
[](void *UNUSED(dst), void *UNUSED(src)) {},
|
||||
[](void *UNUSED(src)) {},
|
||||
[](const void *UNUSED(src)) -> const void * { return nullptr; },
|
||||
ExtraInfo{}};
|
||||
return funcs;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Dummy extra info that is used when no additional type information should be stored in the #Any.
|
||||
*/
|
||||
struct NoExtraInfo {
|
||||
template<typename T> static NoExtraInfo get()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<
|
||||
/**
|
||||
* Either void or a struct that contains data members for additional type information.
|
||||
* The struct has to have a static `ExtraInfo get<T>()` method that initializes the struct
|
||||
* based on a type.
|
||||
*/
|
||||
typename ExtraInfo = void,
|
||||
/**
|
||||
* Size of the inline buffer. This allows types that are small enough to be stored directly
|
||||
* inside the #Any without an additional allocation.
|
||||
*/
|
||||
size_t InlineBufferCapacity = 8,
|
||||
/**
|
||||
* Required minimum alignment of the inline buffer. If this is smaller than the alignment
|
||||
* requirement of a used type, a separate allocation is necessary.
|
||||
*/
|
||||
size_t Alignment = 8>
|
||||
class Any {
|
||||
private:
|
||||
/* Makes it possible to use void in the template parameters. */
|
||||
using RealExtraInfo =
|
||||
std::conditional_t<std::is_void_v<ExtraInfo>, detail::NoExtraInfo, ExtraInfo>;
|
||||
using Info = detail::AnyTypeInfo<RealExtraInfo>;
|
||||
|
||||
/**
|
||||
* Inline buffer that either contains nothing, the stored value directly, or a #std::unique_ptr
|
||||
* to the value.
|
||||
*/
|
||||
AlignedBuffer<std::max(InlineBufferCapacity, sizeof(std::unique_ptr<int>)), Alignment> buffer_{};
|
||||
|
||||
/**
|
||||
* Information about the type that is currently stored.
|
||||
*/
|
||||
const Info *info_ = &Info::get_for_empty();
|
||||
|
||||
public:
|
||||
/** Only copy constructible types can be stored in #Any. */
|
||||
template<typename T> static constexpr inline bool is_allowed_v = std::is_copy_constructible_v<T>;
|
||||
|
||||
/**
|
||||
* Checks if the type will be stored in the inline buffer or if it requires a separate
|
||||
* allocation.
|
||||
*/
|
||||
template<typename T>
|
||||
static constexpr inline bool is_inline_v = std::is_nothrow_move_constructible_v<T> &&
|
||||
sizeof(T) <= InlineBufferCapacity &&
|
||||
alignof(T) <= Alignment;
|
||||
|
||||
/**
|
||||
* Checks if #T is the same type as this #Any, because in this case the behavior of e.g. the
|
||||
* assignment operator is different.
|
||||
*/
|
||||
template<typename T>
|
||||
static constexpr inline bool is_same_any_v = std::is_same_v<std::decay_t<T>, Any>;
|
||||
|
||||
private:
|
||||
template<typename T> const Info &get_info() const
|
||||
{
|
||||
using DecayT = std::decay_t<T>;
|
||||
static_assert(is_allowed_v<DecayT>);
|
||||
if constexpr (is_inline_v<DecayT>) {
|
||||
return Info::template get_for_inline<DecayT>();
|
||||
}
|
||||
else {
|
||||
return Info::template get_for_unique_ptr<DecayT>();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
Any() = default;
|
||||
|
||||
Any(const Any &other) : info_(other.info_)
|
||||
{
|
||||
info_->copy_construct(&buffer_, &other.buffer_);
|
||||
}
|
||||
|
||||
/**
|
||||
* \note The #other #Any will not be empty afterwards if it was not before. Just its value is in
|
||||
* a moved-from state.
|
||||
*/
|
||||
Any(Any &&other) noexcept : info_(other.info_)
|
||||
{
|
||||
info_->move_construct(&buffer_, &other.buffer_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new #Any that contains the given type #T from #args. The #std::in_place_type_t is
|
||||
* used to disambiguate this and the copy/move constructors.
|
||||
*/
|
||||
template<typename T, typename... Args> explicit Any(std::in_place_type_t<T>, Args &&...args)
|
||||
{
|
||||
using DecayT = std::decay_t<T>;
|
||||
static_assert(is_allowed_v<DecayT>);
|
||||
info_ = &this->template get_info<DecayT>();
|
||||
if constexpr (is_inline_v<DecayT>) {
|
||||
/* Construct the value directly in the inline buffer. */
|
||||
new (&buffer_) DecayT(std::forward<Args>(args)...);
|
||||
}
|
||||
else {
|
||||
/* Construct the value in a new allocation and store a #std::unique_ptr to it in the inline
|
||||
* buffer. */
|
||||
new (&buffer_) std::unique_ptr<DecayT>(new DecayT(std::forward<Args>(args)...));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new #Any that contains the given value.
|
||||
*/
|
||||
template<typename T, typename X = std::enable_if_t<!is_same_any_v<T>, void>>
|
||||
Any(T &&value) : Any(std::in_place_type<T>, std::forward<T>(value))
|
||||
{
|
||||
}
|
||||
|
||||
~Any()
|
||||
{
|
||||
info_->destruct(&buffer_);
|
||||
}
|
||||
|
||||
/**
|
||||
* \note: Only needed because the template below does not count as copy assignment operator.
|
||||
*/
|
||||
Any &operator=(const Any &other)
|
||||
{
|
||||
if (this == &other) {
|
||||
return *this;
|
||||
}
|
||||
this->~Any();
|
||||
new (this) Any(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Assign any value to the #Any. */
|
||||
template<typename T> Any &operator=(T &&other)
|
||||
{
|
||||
if constexpr (is_same_any_v<T>) {
|
||||
if (this == &other) {
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
this->~Any();
|
||||
new (this) Any(std::forward<T>(other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Destruct any existing value to make it empty. */
|
||||
void reset()
|
||||
{
|
||||
info_->destruct(&buffer_);
|
||||
info_ = &Info::get_for_empty();
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return this->has_value();
|
||||
}
|
||||
|
||||
bool has_value() const
|
||||
{
|
||||
return info_ != &Info::get_for_empty();
|
||||
}
|
||||
|
||||
template<typename T, typename... Args> std::decay_t<T> &emplace(Args &&...args)
|
||||
{
|
||||
this->~Any();
|
||||
new (this) Any(std::in_place_type<T>, std::forward<Args>(args)...);
|
||||
return this->get<T>();
|
||||
}
|
||||
|
||||
/** Return true when the value that is currently stored is a #T. */
|
||||
template<typename T> bool is() const
|
||||
{
|
||||
return info_ == &this->template get_info<T>();
|
||||
}
|
||||
|
||||
/** Get a pointer to the stored value. */
|
||||
void *get()
|
||||
{
|
||||
return const_cast<void *>(info_->get(&buffer_));
|
||||
}
|
||||
|
||||
/** Get a pointer to the stored value. */
|
||||
const void *get() const
|
||||
{
|
||||
return info_->get(&buffer_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a reference to the stored value. This invokes undefined behavior when #T does not have the
|
||||
* correct type.
|
||||
*/
|
||||
template<typename T> std::decay_t<T> &get()
|
||||
{
|
||||
BLI_assert(this->is<T>());
|
||||
return *static_cast<std::decay_t<T> *>(this->get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a reference to the stored value. This invokes undefined behavior when #T does not have the
|
||||
* correct type.
|
||||
*/
|
||||
template<typename T> const std::decay_t<T> &get() const
|
||||
{
|
||||
BLI_assert(this->is<T>());
|
||||
return *static_cast<const std::decay_t<T> *>(this->get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get extra information that has been stored for the contained type.
|
||||
*/
|
||||
const RealExtraInfo &extra_info() const
|
||||
{
|
||||
return info_->extra_info;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace blender
|
||||
File diff suppressed because it is too large
Load Diff
@@ -165,6 +165,7 @@ set(SRC
|
||||
|
||||
BLI_alloca.h
|
||||
BLI_allocator.hh
|
||||
BLI_any.hh
|
||||
BLI_args.h
|
||||
BLI_array.h
|
||||
BLI_array.hh
|
||||
@@ -411,6 +412,7 @@ blender_add_lib(bf_blenlib "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
||||
|
||||
if(WITH_GTESTS)
|
||||
set(TEST_SRC
|
||||
tests/BLI_any_test.cc
|
||||
tests/BLI_array_store_test.cc
|
||||
tests/BLI_array_test.cc
|
||||
tests/BLI_array_utils_test.cc
|
||||
|
||||
108
source/blender/blenlib/tests/BLI_any_test.cc
Normal file
108
source/blender/blenlib/tests/BLI_any_test.cc
Normal file
@@ -0,0 +1,108 @@
|
||||
/* Apache License, Version 2.0 */
|
||||
|
||||
#include "BLI_any.hh"
|
||||
#include "BLI_map.hh"
|
||||
|
||||
#include "testing/testing.h"
|
||||
|
||||
namespace blender::tests {
|
||||
|
||||
TEST(any, DefaultConstructor)
|
||||
{
|
||||
Any a;
|
||||
EXPECT_FALSE(a.has_value());
|
||||
}
|
||||
|
||||
TEST(any, AssignInt)
|
||||
{
|
||||
Any<> a = 5;
|
||||
EXPECT_TRUE(a.has_value());
|
||||
EXPECT_TRUE(a.is<int>());
|
||||
EXPECT_FALSE(a.is<float>());
|
||||
const int &value = a.get<int>();
|
||||
EXPECT_EQ(value, 5);
|
||||
a = 10;
|
||||
EXPECT_EQ(value, 10);
|
||||
|
||||
Any b = a;
|
||||
EXPECT_TRUE(b.has_value());
|
||||
EXPECT_EQ(b.get<int>(), 10);
|
||||
|
||||
Any c = std::move(a);
|
||||
EXPECT_TRUE(c);
|
||||
EXPECT_EQ(c.get<int>(), 10);
|
||||
|
||||
EXPECT_EQ(a.get<int>(), 10); /* NOLINT: bugprone-use-after-move */
|
||||
|
||||
a.reset();
|
||||
EXPECT_FALSE(a);
|
||||
}
|
||||
|
||||
TEST(any, AssignMap)
|
||||
{
|
||||
Any<> a = Map<int, int>();
|
||||
EXPECT_TRUE(a.has_value());
|
||||
EXPECT_TRUE((a.is<Map<int, int>>()));
|
||||
EXPECT_FALSE((a.is<Map<int, float>>()));
|
||||
Map<int, int> &map = a.get<Map<int, int>>();
|
||||
map.add(4, 2);
|
||||
EXPECT_EQ((a.get<Map<int, int>>().lookup(4)), 2);
|
||||
|
||||
Any b = a;
|
||||
EXPECT_TRUE(b);
|
||||
EXPECT_EQ((b.get<Map<int, int>>().lookup(4)), 2);
|
||||
|
||||
Any c = std::move(a);
|
||||
c = c;
|
||||
EXPECT_TRUE(b);
|
||||
EXPECT_EQ((c.get<Map<int, int>>().lookup(4)), 2);
|
||||
|
||||
EXPECT_TRUE((a.get<Map<int, int>>().is_empty())); /* NOLINT: bugprone-use-after-move */
|
||||
}
|
||||
|
||||
TEST(any, AssignAny)
|
||||
{
|
||||
Any<> a = 5;
|
||||
Any<> b = std::string("hello");
|
||||
Any c;
|
||||
|
||||
Any z;
|
||||
EXPECT_FALSE(z.has_value());
|
||||
|
||||
z = a;
|
||||
EXPECT_TRUE(z.has_value());
|
||||
EXPECT_EQ(z.get<int>(), 5);
|
||||
|
||||
z = b;
|
||||
EXPECT_EQ(z.get<std::string>(), "hello");
|
||||
|
||||
z = c;
|
||||
EXPECT_FALSE(z.has_value());
|
||||
|
||||
z = Any(std::in_place_type<Any<>>, a);
|
||||
EXPECT_FALSE(z.is<int>());
|
||||
EXPECT_TRUE(z.is<Any<>>());
|
||||
EXPECT_EQ(z.get<Any<>>().get<int>(), 5);
|
||||
}
|
||||
|
||||
struct ExtraSizeInfo {
|
||||
size_t size;
|
||||
|
||||
template<typename T> static ExtraSizeInfo get()
|
||||
{
|
||||
return {sizeof(T)};
|
||||
}
|
||||
};
|
||||
|
||||
TEST(any, ExtraInfo)
|
||||
{
|
||||
using MyAny = Any<ExtraSizeInfo>;
|
||||
|
||||
MyAny a = 5;
|
||||
EXPECT_EQ(a.extra_info().size, sizeof(int));
|
||||
|
||||
a = std::string("hello");
|
||||
EXPECT_EQ(a.extra_info().size, sizeof(std::string));
|
||||
}
|
||||
|
||||
} // namespace blender::tests
|
||||
@@ -12,7 +12,7 @@ namespace blender::tests {
|
||||
TEST(virtual_array, Span)
|
||||
{
|
||||
std::array<int, 5> data = {3, 4, 5, 6, 7};
|
||||
VArray_For_Span<int> varray{data};
|
||||
VArray<int> varray = VArray<int>::ForSpan(data);
|
||||
EXPECT_EQ(varray.size(), 5);
|
||||
EXPECT_EQ(varray.get(0), 3);
|
||||
EXPECT_EQ(varray.get(4), 7);
|
||||
@@ -23,7 +23,7 @@ TEST(virtual_array, Span)
|
||||
|
||||
TEST(virtual_array, Single)
|
||||
{
|
||||
VArray_For_Single<int> varray{10, 4};
|
||||
VArray<int> varray = VArray<int>::ForSingle(10, 4);
|
||||
EXPECT_EQ(varray.size(), 4);
|
||||
EXPECT_EQ(varray.get(0), 10);
|
||||
EXPECT_EQ(varray.get(3), 10);
|
||||
@@ -35,7 +35,7 @@ TEST(virtual_array, Array)
|
||||
{
|
||||
Array<int> array = {1, 2, 3, 5, 8};
|
||||
{
|
||||
VArray_For_ArrayContainer varray{array};
|
||||
VArray<int> varray = VArray<int>::ForContainer(array);
|
||||
EXPECT_EQ(varray.size(), 5);
|
||||
EXPECT_EQ(varray[0], 1);
|
||||
EXPECT_EQ(varray[2], 3);
|
||||
@@ -43,7 +43,7 @@ TEST(virtual_array, Array)
|
||||
EXPECT_TRUE(varray.is_span());
|
||||
}
|
||||
{
|
||||
VArray_For_ArrayContainer varray{std::move(array)};
|
||||
VArray<int> varray = VArray<int>::ForContainer(std::move(array));
|
||||
EXPECT_EQ(varray.size(), 5);
|
||||
EXPECT_EQ(varray[0], 1);
|
||||
EXPECT_EQ(varray[2], 3);
|
||||
@@ -51,7 +51,7 @@ TEST(virtual_array, Array)
|
||||
EXPECT_TRUE(varray.is_span());
|
||||
}
|
||||
{
|
||||
VArray_For_ArrayContainer varray{array}; /* NOLINT: bugprone-use-after-move */
|
||||
VArray<int> varray = VArray<int>::ForContainer(array); /* NOLINT: bugprone-use-after-move */
|
||||
EXPECT_TRUE(varray.is_empty());
|
||||
}
|
||||
}
|
||||
@@ -59,7 +59,7 @@ TEST(virtual_array, Array)
|
||||
TEST(virtual_array, Vector)
|
||||
{
|
||||
Vector<int> vector = {9, 8, 7, 6};
|
||||
VArray_For_ArrayContainer varray{std::move(vector)};
|
||||
VArray<int> varray = VArray<int>::ForContainer(std::move(vector));
|
||||
EXPECT_EQ(varray.size(), 4);
|
||||
EXPECT_EQ(varray[0], 9);
|
||||
EXPECT_EQ(varray[3], 6);
|
||||
@@ -68,7 +68,7 @@ TEST(virtual_array, Vector)
|
||||
TEST(virtual_array, StdVector)
|
||||
{
|
||||
std::vector<int> vector = {5, 6, 7, 8};
|
||||
VArray_For_ArrayContainer varray{std::move(vector)};
|
||||
VArray<int> varray = VArray<int>::ForContainer(std::move(vector));
|
||||
EXPECT_EQ(varray.size(), 4);
|
||||
EXPECT_EQ(varray[0], 5);
|
||||
EXPECT_EQ(varray[1], 6);
|
||||
@@ -77,7 +77,7 @@ TEST(virtual_array, StdVector)
|
||||
TEST(virtual_array, StdArray)
|
||||
{
|
||||
std::array<int, 4> array = {2, 3, 4, 5};
|
||||
VArray_For_ArrayContainer varray{array};
|
||||
VArray<int> varray = VArray<int>::ForContainer(std::move(array));
|
||||
EXPECT_EQ(varray.size(), 4);
|
||||
EXPECT_EQ(varray[0], 2);
|
||||
EXPECT_EQ(varray[1], 3);
|
||||
@@ -86,7 +86,7 @@ TEST(virtual_array, StdArray)
|
||||
TEST(virtual_array, VectorSet)
|
||||
{
|
||||
VectorSet<int> vector_set = {5, 3, 7, 3, 3, 5, 1};
|
||||
VArray_For_ArrayContainer varray{std::move(vector_set)};
|
||||
VArray<int> varray = VArray<int>::ForContainer(std::move(vector_set));
|
||||
EXPECT_TRUE(vector_set.is_empty()); /* NOLINT: bugprone-use-after-move. */
|
||||
EXPECT_EQ(varray.size(), 4);
|
||||
EXPECT_EQ(varray[0], 5);
|
||||
@@ -98,7 +98,7 @@ TEST(virtual_array, VectorSet)
|
||||
TEST(virtual_array, Func)
|
||||
{
|
||||
auto func = [](int64_t index) { return (int)(index * index); };
|
||||
VArray_For_Func<int, decltype(func)> varray{10, func};
|
||||
VArray<int> varray = VArray<int>::ForFunc(10, func);
|
||||
EXPECT_EQ(varray.size(), 10);
|
||||
EXPECT_EQ(varray[0], 0);
|
||||
EXPECT_EQ(varray[3], 9);
|
||||
@@ -108,7 +108,7 @@ TEST(virtual_array, Func)
|
||||
TEST(virtual_array, AsSpan)
|
||||
{
|
||||
auto func = [](int64_t index) { return (int)(10 * index); };
|
||||
VArray_For_Func<int, decltype(func)> func_varray{10, func};
|
||||
VArray<int> func_varray = VArray<int>::ForFunc(10, func);
|
||||
VArray_Span span_varray{func_varray};
|
||||
EXPECT_EQ(span_varray.size(), 10);
|
||||
Span<int> span = span_varray;
|
||||
@@ -134,13 +134,14 @@ TEST(virtual_array, DerivedSpan)
|
||||
vector.append({3, 4, 5});
|
||||
vector.append({1, 1, 1});
|
||||
{
|
||||
VArray_For_DerivedSpan<std::array<int, 3>, int, get_x> varray{vector};
|
||||
VArray<int> varray = VArray<int>::ForDerivedSpan<std::array<int, 3>, get_x>(vector);
|
||||
EXPECT_EQ(varray.size(), 2);
|
||||
EXPECT_EQ(varray[0], 3);
|
||||
EXPECT_EQ(varray[1], 1);
|
||||
}
|
||||
{
|
||||
VMutableArray_For_DerivedSpan<std::array<int, 3>, int, get_x, set_x> varray{vector};
|
||||
VMutableArray<int> varray =
|
||||
VMutableArray<int>::ForDerivedSpan<std::array<int, 3>, get_x, set_x>(vector);
|
||||
EXPECT_EQ(varray.size(), 2);
|
||||
EXPECT_EQ(varray[0], 3);
|
||||
EXPECT_EQ(varray[1], 1);
|
||||
@@ -151,4 +152,32 @@ TEST(virtual_array, DerivedSpan)
|
||||
}
|
||||
}
|
||||
|
||||
TEST(virtual_array, MutableToImmutable)
|
||||
{
|
||||
std::array<int, 4> array = {4, 2, 6, 4};
|
||||
{
|
||||
VMutableArray<int> mutable_varray = VMutableArray<int>::ForSpan(array);
|
||||
VArray<int> varray = mutable_varray;
|
||||
EXPECT_TRUE(varray.is_span());
|
||||
EXPECT_EQ(varray.size(), 4);
|
||||
EXPECT_EQ(varray[1], 2);
|
||||
EXPECT_EQ(mutable_varray.size(), 4);
|
||||
}
|
||||
{
|
||||
VMutableArray<int> mutable_varray = VMutableArray<int>::ForSpan(array);
|
||||
EXPECT_EQ(mutable_varray.size(), 4);
|
||||
VArray<int> varray = std::move(mutable_varray);
|
||||
EXPECT_TRUE(varray.is_span());
|
||||
EXPECT_EQ(varray.size(), 4);
|
||||
EXPECT_EQ(varray[1], 2);
|
||||
EXPECT_EQ(mutable_varray.size(), 0);
|
||||
}
|
||||
{
|
||||
VArray<int> varray = VMutableArray<int>::ForSpan(array);
|
||||
EXPECT_TRUE(varray.is_span());
|
||||
EXPECT_EQ(varray.size(), 4);
|
||||
EXPECT_EQ(varray[1], 2);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace blender::tests
|
||||
|
||||
@@ -78,7 +78,7 @@ static std::optional<eSpreadsheetColumnValueType> cpp_type_to_column_value_type(
|
||||
void ExtraColumns::foreach_default_column_ids(
|
||||
FunctionRef<void(const SpreadsheetColumnID &, bool is_extra)> fn) const
|
||||
{
|
||||
for (const auto &item : columns_.items()) {
|
||||
for (const auto item : columns_.items()) {
|
||||
SpreadsheetColumnID column_id;
|
||||
column_id.name = (char *)item.key.c_str();
|
||||
fn(column_id, true);
|
||||
@@ -168,12 +168,12 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
|
||||
if (!attribute) {
|
||||
return {};
|
||||
}
|
||||
const fn::GVArray *varray = scope_.add(std::move(attribute.varray));
|
||||
fn::GVArray varray = std::move(attribute.varray);
|
||||
if (attribute.domain != domain_) {
|
||||
return {};
|
||||
}
|
||||
int domain_size = varray->size();
|
||||
const CustomDataType type = bke::cpp_type_to_custom_data_type(varray->type());
|
||||
int domain_size = varray.size();
|
||||
const CustomDataType type = bke::cpp_type_to_custom_data_type(varray.type());
|
||||
switch (type) {
|
||||
case CD_PROP_FLOAT:
|
||||
return column_values_from_function(SPREADSHEET_VALUE_TYPE_FLOAT,
|
||||
@@ -181,7 +181,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
|
||||
domain_size,
|
||||
[varray](int index, CellValue &r_cell_value) {
|
||||
float value;
|
||||
varray->get(index, &value);
|
||||
varray.get(index, &value);
|
||||
r_cell_value.value_float = value;
|
||||
});
|
||||
case CD_PROP_INT32:
|
||||
@@ -191,7 +191,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
|
||||
domain_size,
|
||||
[varray](int index, CellValue &r_cell_value) {
|
||||
int value;
|
||||
varray->get(index, &value);
|
||||
varray.get(index, &value);
|
||||
r_cell_value.value_int = value;
|
||||
},
|
||||
STREQ(column_id.name, "id") ? 5.5f : 0.0f);
|
||||
@@ -201,7 +201,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
|
||||
domain_size,
|
||||
[varray](int index, CellValue &r_cell_value) {
|
||||
bool value;
|
||||
varray->get(index, &value);
|
||||
varray.get(index, &value);
|
||||
r_cell_value.value_bool = value;
|
||||
});
|
||||
case CD_PROP_FLOAT2: {
|
||||
@@ -210,7 +210,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
|
||||
domain_size,
|
||||
[varray](int index, CellValue &r_cell_value) {
|
||||
float2 value;
|
||||
varray->get(index, &value);
|
||||
varray.get(index, &value);
|
||||
r_cell_value.value_float2 = value;
|
||||
});
|
||||
}
|
||||
@@ -220,7 +220,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
|
||||
domain_size,
|
||||
[varray](int index, CellValue &r_cell_value) {
|
||||
float3 value;
|
||||
varray->get(index, &value);
|
||||
varray.get(index, &value);
|
||||
r_cell_value.value_float3 = value;
|
||||
});
|
||||
}
|
||||
@@ -230,7 +230,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
|
||||
domain_size,
|
||||
[varray](int index, CellValue &r_cell_value) {
|
||||
ColorGeometry4f value;
|
||||
varray->get(index, &value);
|
||||
varray.get(index, &value);
|
||||
r_cell_value.value_color = value;
|
||||
});
|
||||
}
|
||||
@@ -738,7 +738,7 @@ static void add_fields_as_extra_columns(SpaceSpreadsheet *sspreadsheet,
|
||||
|
||||
const AttributeDomain domain = (AttributeDomain)sspreadsheet->attribute_domain;
|
||||
const int domain_size = component.attribute_domain_size(domain);
|
||||
for (const auto &item : fields_to_show.items()) {
|
||||
for (const auto item : fields_to_show.items()) {
|
||||
StringRef name = item.key;
|
||||
const GField &field = item.value;
|
||||
|
||||
|
||||
@@ -248,9 +248,9 @@ class FieldInput : public FieldNode {
|
||||
* Get the value of this specific input based on the given context. The returned virtual array,
|
||||
* should live at least as long as the passed in #scope. May return null.
|
||||
*/
|
||||
virtual const GVArray *get_varray_for_context(const FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const = 0;
|
||||
virtual GVArray get_varray_for_context(const FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const = 0;
|
||||
|
||||
virtual std::string socket_inspection_name() const;
|
||||
blender::StringRef debug_name() const;
|
||||
@@ -268,9 +268,9 @@ class FieldContext {
|
||||
public:
|
||||
~FieldContext() = default;
|
||||
|
||||
virtual const GVArray *get_varray_for_input(const FieldInput &field_input,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const;
|
||||
virtual GVArray get_varray_for_input(const FieldInput &field_input,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -289,8 +289,8 @@ class FieldEvaluator : NonMovable, NonCopyable {
|
||||
const FieldContext &context_;
|
||||
const IndexMask mask_;
|
||||
Vector<GField> fields_to_evaluate_;
|
||||
Vector<GVMutableArray *> dst_varrays_;
|
||||
Vector<const GVArray *> evaluated_varrays_;
|
||||
Vector<GVMutableArray> dst_varrays_;
|
||||
Vector<GVArray> evaluated_varrays_;
|
||||
Vector<OutputPointerInfo> output_pointer_infos_;
|
||||
bool is_evaluated_ = false;
|
||||
|
||||
@@ -317,13 +317,12 @@ class FieldEvaluator : NonMovable, NonCopyable {
|
||||
* \param field: Field to add to the evaluator.
|
||||
* \param dst: Mutable virtual array that the evaluated result for this field is be written into.
|
||||
*/
|
||||
int add_with_destination(GField field, GVMutableArray &dst);
|
||||
int add_with_destination(GField field, GVMutableArray dst);
|
||||
|
||||
/** Same as #add_with_destination but typed. */
|
||||
template<typename T> int add_with_destination(Field<T> field, VMutableArray<T> &dst)
|
||||
template<typename T> int add_with_destination(Field<T> field, VMutableArray<T> dst)
|
||||
{
|
||||
GVMutableArray &varray = scope_.construct<GVMutableArray_For_VMutableArray<T>>(dst);
|
||||
return this->add_with_destination(GField(std::move(field)), varray);
|
||||
return this->add_with_destination(GField(std::move(field)), GVMutableArray(std::move(dst)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -342,11 +341,10 @@ class FieldEvaluator : NonMovable, NonCopyable {
|
||||
*/
|
||||
template<typename T> int add_with_destination(Field<T> field, MutableSpan<T> dst)
|
||||
{
|
||||
GVMutableArray &varray = scope_.construct<GVMutableArray_For_MutableSpan<T>>(dst);
|
||||
return this->add_with_destination(std::move(field), varray);
|
||||
return this->add_with_destination(std::move(field), VMutableArray<T>::ForSpan(dst));
|
||||
}
|
||||
|
||||
int add(GField field, const GVArray **varray_ptr);
|
||||
int add(GField field, GVArray *varray_ptr);
|
||||
|
||||
/**
|
||||
* \param field: Field to add to the evaluator.
|
||||
@@ -354,14 +352,14 @@ class FieldEvaluator : NonMovable, NonCopyable {
|
||||
* assigned to the given position.
|
||||
* \return Index of the field in the evaluator which can be used in the #get_evaluated methods.
|
||||
*/
|
||||
template<typename T> int add(Field<T> field, const VArray<T> **varray_ptr)
|
||||
template<typename T> int add(Field<T> field, VArray<T> *varray_ptr)
|
||||
{
|
||||
const int field_index = fields_to_evaluate_.append_and_get_index(std::move(field));
|
||||
dst_varrays_.append(nullptr);
|
||||
output_pointer_infos_.append(
|
||||
OutputPointerInfo{varray_ptr, [](void *dst, const GVArray &varray, ResourceScope &scope) {
|
||||
*(const VArray<T> **)dst = &*scope.construct<GVArray_Typed<T>>(varray);
|
||||
}});
|
||||
dst_varrays_.append({});
|
||||
output_pointer_infos_.append(OutputPointerInfo{
|
||||
varray_ptr, [](void *dst, const GVArray &varray, ResourceScope &UNUSED(scope)) {
|
||||
*(VArray<T> *)dst = varray.typed<T>();
|
||||
}});
|
||||
return field_index;
|
||||
}
|
||||
|
||||
@@ -378,14 +376,12 @@ class FieldEvaluator : NonMovable, NonCopyable {
|
||||
const GVArray &get_evaluated(const int field_index) const
|
||||
{
|
||||
BLI_assert(is_evaluated_);
|
||||
return *evaluated_varrays_[field_index];
|
||||
return evaluated_varrays_[field_index];
|
||||
}
|
||||
|
||||
template<typename T> const VArray<T> &get_evaluated(const int field_index)
|
||||
template<typename T> VArray<T> get_evaluated(const int field_index)
|
||||
{
|
||||
const GVArray &varray = this->get_evaluated(field_index);
|
||||
GVArray_Typed<T> &typed_varray = scope_.construct<GVArray_Typed<T>>(varray);
|
||||
return *typed_varray;
|
||||
return this->get_evaluated(field_index).typed<T>();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -396,11 +392,11 @@ class FieldEvaluator : NonMovable, NonCopyable {
|
||||
IndexMask get_evaluated_as_mask(const int field_index);
|
||||
};
|
||||
|
||||
Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
|
||||
Span<GFieldRef> fields_to_evaluate,
|
||||
IndexMask mask,
|
||||
const FieldContext &context,
|
||||
Span<GVMutableArray *> dst_varrays = {});
|
||||
Vector<GVArray> evaluate_fields(ResourceScope &scope,
|
||||
Span<GFieldRef> fields_to_evaluate,
|
||||
IndexMask mask,
|
||||
const FieldContext &context,
|
||||
Span<GVMutableArray> dst_varrays = {});
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Utility functions for simple field creation and evaluation
|
||||
@@ -429,11 +425,11 @@ class IndexFieldInput final : public FieldInput {
|
||||
public:
|
||||
IndexFieldInput();
|
||||
|
||||
static GVArray *get_index_varray(IndexMask mask, ResourceScope &scope);
|
||||
static GVArray get_index_varray(IndexMask mask, ResourceScope &scope);
|
||||
|
||||
const GVArray *get_varray_for_context(const FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const final;
|
||||
GVArray get_varray_for_context(const FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const final;
|
||||
|
||||
uint64_t hash() const override;
|
||||
bool is_equal_to(const fn::FieldNode &other) const override;
|
||||
|
||||
@@ -125,8 +125,7 @@ template<typename T> class GVectorArray_TypedMutableRef {
|
||||
|
||||
void extend(const int64_t index, const VArray<T> &values)
|
||||
{
|
||||
GVArray_For_VArray<T> array{values};
|
||||
this->extend(index, array);
|
||||
vector_array_->extend(index, values);
|
||||
}
|
||||
|
||||
MutableSpan<T> operator[](const int64_t index)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -100,31 +100,31 @@ class GVVectorArray {
|
||||
}
|
||||
};
|
||||
|
||||
class GVArray_For_GVVectorArrayIndex : public GVArray {
|
||||
class GVArray_For_GVVectorArrayIndex : public GVArrayImpl {
|
||||
private:
|
||||
const GVVectorArray &vector_array_;
|
||||
const int64_t index_;
|
||||
|
||||
public:
|
||||
GVArray_For_GVVectorArrayIndex(const GVVectorArray &vector_array, const int64_t index)
|
||||
: GVArray(vector_array.type(), vector_array.get_vector_size(index)),
|
||||
: GVArrayImpl(vector_array.type(), vector_array.get_vector_size(index)),
|
||||
vector_array_(vector_array),
|
||||
index_(index)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
void get_impl(const int64_t index_in_vector, void *r_value) const override;
|
||||
void get_to_uninitialized_impl(const int64_t index_in_vector, void *r_value) const override;
|
||||
void get(const int64_t index_in_vector, void *r_value) const override;
|
||||
void get_to_uninitialized(const int64_t index_in_vector, void *r_value) const override;
|
||||
};
|
||||
|
||||
class GVVectorArray_For_SingleGVArray : public GVVectorArray {
|
||||
private:
|
||||
const GVArray &array_;
|
||||
GVArray varray_;
|
||||
|
||||
public:
|
||||
GVVectorArray_For_SingleGVArray(const GVArray &array, const int64_t size)
|
||||
: GVVectorArray(array.type(), size), array_(array)
|
||||
GVVectorArray_For_SingleGVArray(GVArray varray, const int64_t size)
|
||||
: GVVectorArray(varray.type(), size), varray_(std::move(varray))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ class MFParamsBuilder {
|
||||
const MFSignature *signature_;
|
||||
IndexMask mask_;
|
||||
int64_t min_array_size_;
|
||||
Vector<const GVArray *> virtual_arrays_;
|
||||
Vector<GVArray> virtual_arrays_;
|
||||
Vector<GMutableSpan> mutable_spans_;
|
||||
Vector<const GVVectorArray *> virtual_vector_arrays_;
|
||||
Vector<GVectorArray *> vector_arrays_;
|
||||
@@ -68,24 +68,22 @@ class MFParamsBuilder {
|
||||
template<typename T> void add_readonly_single_input(const T *value, StringRef expected_name = "")
|
||||
{
|
||||
this->add_readonly_single_input(
|
||||
scope_.construct<GVArray_For_SingleValueRef>(CPPType::get<T>(), min_array_size_, value),
|
||||
expected_name);
|
||||
GVArray::ForSingleRef(CPPType::get<T>(), min_array_size_, value), expected_name);
|
||||
}
|
||||
void add_readonly_single_input(const GSpan span, StringRef expected_name = "")
|
||||
{
|
||||
this->add_readonly_single_input(scope_.construct<GVArray_For_GSpan>(span), expected_name);
|
||||
this->add_readonly_single_input(GVArray::ForSpan(span), expected_name);
|
||||
}
|
||||
void add_readonly_single_input(GPointer value, StringRef expected_name = "")
|
||||
{
|
||||
this->add_readonly_single_input(
|
||||
scope_.construct<GVArray_For_SingleValueRef>(*value.type(), min_array_size_, value.get()),
|
||||
expected_name);
|
||||
GVArray::ForSingleRef(*value.type(), min_array_size_, value.get()), expected_name);
|
||||
}
|
||||
void add_readonly_single_input(const GVArray &ref, StringRef expected_name = "")
|
||||
void add_readonly_single_input(GVArray varray, StringRef expected_name = "")
|
||||
{
|
||||
this->assert_current_param_type(MFParamType::ForSingleInput(ref.type()), expected_name);
|
||||
BLI_assert(ref.size() >= min_array_size_);
|
||||
virtual_arrays_.append(&ref);
|
||||
this->assert_current_param_type(MFParamType::ForSingleInput(varray.type()), expected_name);
|
||||
BLI_assert(varray.size() >= min_array_size_);
|
||||
virtual_arrays_.append(varray);
|
||||
}
|
||||
|
||||
void add_readonly_vector_input(const GVectorArray &vector_array, StringRef expected_name = "")
|
||||
@@ -221,16 +219,16 @@ class MFParams {
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T> const VArray<T> &readonly_single_input(int param_index, StringRef name = "")
|
||||
template<typename T> VArray<T> readonly_single_input(int param_index, StringRef name = "")
|
||||
{
|
||||
const GVArray &array = this->readonly_single_input(param_index, name);
|
||||
return builder_->scope_.construct<GVArray_Typed<T>>(array);
|
||||
const GVArray &varray = this->readonly_single_input(param_index, name);
|
||||
return varray.typed<T>();
|
||||
}
|
||||
const GVArray &readonly_single_input(int param_index, StringRef name = "")
|
||||
{
|
||||
this->assert_correct_param(param_index, name, MFParamType::SingleInput);
|
||||
int data_index = builder_->signature_->data_index(param_index);
|
||||
return *builder_->virtual_arrays_[data_index];
|
||||
return builder_->virtual_arrays_[data_index];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -81,19 +81,18 @@ static FieldTreeInfo preprocess_field_tree(Span<GFieldRef> entry_fields)
|
||||
/**
|
||||
* Retrieves the data from the context that is passed as input into the field.
|
||||
*/
|
||||
static Vector<const GVArray *> get_field_context_inputs(
|
||||
static Vector<GVArray> get_field_context_inputs(
|
||||
ResourceScope &scope,
|
||||
const IndexMask mask,
|
||||
const FieldContext &context,
|
||||
const Span<std::reference_wrapper<const FieldInput>> field_inputs)
|
||||
{
|
||||
Vector<const GVArray *> field_context_inputs;
|
||||
Vector<GVArray> field_context_inputs;
|
||||
for (const FieldInput &field_input : field_inputs) {
|
||||
const GVArray *varray = context.get_varray_for_input(field_input, mask, scope);
|
||||
if (varray == nullptr) {
|
||||
GVArray varray = context.get_varray_for_input(field_input, mask, scope);
|
||||
if (!varray) {
|
||||
const CPPType &type = field_input.cpp_type();
|
||||
varray = &scope.construct<GVArray_For_SingleValueRef>(
|
||||
type, mask.min_array_size(), type.default_value());
|
||||
varray = GVArray::ForSingleDefault(type, mask.min_array_size());
|
||||
}
|
||||
field_context_inputs.append(varray);
|
||||
}
|
||||
@@ -105,7 +104,7 @@ static Vector<const GVArray *> get_field_context_inputs(
|
||||
* for different indices.
|
||||
*/
|
||||
static Set<GFieldRef> find_varying_fields(const FieldTreeInfo &field_tree_info,
|
||||
Span<const GVArray *> field_context_inputs)
|
||||
Span<GVArray> field_context_inputs)
|
||||
{
|
||||
Set<GFieldRef> found_fields;
|
||||
Stack<GFieldRef> fields_to_check;
|
||||
@@ -114,8 +113,8 @@ static Set<GFieldRef> find_varying_fields(const FieldTreeInfo &field_tree_info,
|
||||
* start the tree search at the non-constant input fields and traverse through all fields that
|
||||
* depend on them. */
|
||||
for (const int i : field_context_inputs.index_range()) {
|
||||
const GVArray *varray = field_context_inputs[i];
|
||||
if (varray->is_single()) {
|
||||
const GVArray &varray = field_context_inputs[i];
|
||||
if (varray.is_single()) {
|
||||
continue;
|
||||
}
|
||||
const FieldInput &field_input = field_tree_info.deduplicated_field_inputs[i];
|
||||
@@ -278,29 +277,42 @@ static void build_multi_function_procedure_for_fields(MFProcedure &procedure,
|
||||
* \return The computed virtual arrays for each provided field. If #dst_varrays is passed, the
|
||||
* provided virtual arrays are returned.
|
||||
*/
|
||||
Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
|
||||
Span<GFieldRef> fields_to_evaluate,
|
||||
IndexMask mask,
|
||||
const FieldContext &context,
|
||||
Span<GVMutableArray *> dst_varrays)
|
||||
Vector<GVArray> evaluate_fields(ResourceScope &scope,
|
||||
Span<GFieldRef> fields_to_evaluate,
|
||||
IndexMask mask,
|
||||
const FieldContext &context,
|
||||
Span<GVMutableArray> dst_varrays)
|
||||
{
|
||||
Vector<const GVArray *> r_varrays(fields_to_evaluate.size(), nullptr);
|
||||
Vector<GVArray> r_varrays(fields_to_evaluate.size());
|
||||
Array<bool> is_output_written_to_dst(fields_to_evaluate.size(), false);
|
||||
const int array_size = mask.min_array_size();
|
||||
|
||||
/* Destination arrays are optional. Create a small utility method to access them. */
|
||||
auto get_dst_varray_if_available = [&](int index) -> GVMutableArray * {
|
||||
if (dst_varrays.is_empty()) {
|
||||
return nullptr;
|
||||
if (mask.is_empty()) {
|
||||
for (const int i : fields_to_evaluate.index_range()) {
|
||||
const CPPType &type = fields_to_evaluate[i].cpp_type();
|
||||
r_varrays[i] = GVArray::ForEmpty(type);
|
||||
}
|
||||
BLI_assert(dst_varrays[index] == nullptr || dst_varrays[index]->size() >= array_size);
|
||||
return dst_varrays[index];
|
||||
return r_varrays;
|
||||
}
|
||||
|
||||
/* Destination arrays are optional. Create a small utility method to access them. */
|
||||
auto get_dst_varray = [&](int index) -> GVMutableArray {
|
||||
if (dst_varrays.is_empty()) {
|
||||
return {};
|
||||
}
|
||||
const GVMutableArray &varray = dst_varrays[index];
|
||||
if (!varray) {
|
||||
return {};
|
||||
}
|
||||
BLI_assert(varray.size() >= array_size);
|
||||
return varray;
|
||||
};
|
||||
|
||||
/* Traverse the field tree and prepare some data that is used in later steps. */
|
||||
FieldTreeInfo field_tree_info = preprocess_field_tree(fields_to_evaluate);
|
||||
|
||||
/* Get inputs that will be passed into the field when evaluated. */
|
||||
Vector<const GVArray *> field_context_inputs = get_field_context_inputs(
|
||||
Vector<GVArray> field_context_inputs = get_field_context_inputs(
|
||||
scope, mask, context, field_tree_info.deduplicated_field_inputs);
|
||||
|
||||
/* Finish fields that output an input varray directly. For those we don't have to do any further
|
||||
@@ -312,7 +324,7 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
|
||||
}
|
||||
const FieldInput &field_input = static_cast<const FieldInput &>(field.node());
|
||||
const int field_input_index = field_tree_info.deduplicated_field_inputs.index_of(field_input);
|
||||
const GVArray *varray = field_context_inputs[field_input_index];
|
||||
const GVArray &varray = field_context_inputs[field_input_index];
|
||||
r_varrays[out_index] = varray;
|
||||
}
|
||||
|
||||
@@ -325,7 +337,7 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
|
||||
Vector<GFieldRef> constant_fields_to_evaluate;
|
||||
Vector<int> constant_field_indices;
|
||||
for (const int i : fields_to_evaluate.index_range()) {
|
||||
if (r_varrays[i] != nullptr) {
|
||||
if (r_varrays[i]) {
|
||||
/* Already done. */
|
||||
continue;
|
||||
}
|
||||
@@ -357,8 +369,8 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
|
||||
MFContextBuilder mf_context;
|
||||
|
||||
/* Provide inputs to the procedure executor. */
|
||||
for (const GVArray *varray : field_context_inputs) {
|
||||
mf_params.add_readonly_single_input(*varray);
|
||||
for (const GVArray &varray : field_context_inputs) {
|
||||
mf_params.add_readonly_single_input(varray);
|
||||
}
|
||||
|
||||
for (const int i : varying_fields_to_evaluate.index_range()) {
|
||||
@@ -367,9 +379,9 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
|
||||
const int out_index = varying_field_indices[i];
|
||||
|
||||
/* Try to get an existing virtual array that the result should be written into. */
|
||||
GVMutableArray *output_varray = get_dst_varray_if_available(out_index);
|
||||
GVMutableArray dst_varray = get_dst_varray(out_index);
|
||||
void *buffer;
|
||||
if (output_varray == nullptr || !output_varray->is_span()) {
|
||||
if (!dst_varray || !dst_varray.is_span()) {
|
||||
/* Allocate a new buffer for the computed result. */
|
||||
buffer = scope.linear_allocator().allocate(type.size() * array_size, type.alignment());
|
||||
|
||||
@@ -379,14 +391,14 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
|
||||
[buffer, mask, &type]() { type.destruct_indices(buffer, mask); });
|
||||
}
|
||||
|
||||
r_varrays[out_index] = &scope.construct<GVArray_For_GSpan>(
|
||||
GSpan{type, buffer, array_size});
|
||||
r_varrays[out_index] = GVArray::ForSpan({type, buffer, array_size});
|
||||
}
|
||||
else {
|
||||
/* Write the result into the existing span. */
|
||||
buffer = output_varray->get_internal_span().data();
|
||||
buffer = dst_varray.get_internal_span().data();
|
||||
|
||||
r_varrays[out_index] = output_varray;
|
||||
r_varrays[out_index] = dst_varray;
|
||||
is_output_written_to_dst[out_index] = true;
|
||||
}
|
||||
|
||||
/* Pass output buffer to the procedure executor. */
|
||||
@@ -404,15 +416,12 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
|
||||
build_multi_function_procedure_for_fields(
|
||||
procedure, scope, field_tree_info, constant_fields_to_evaluate);
|
||||
MFProcedureExecutor procedure_executor{"Procedure", procedure};
|
||||
/* Run the code below even when the mask is empty, so that outputs are properly prepared.
|
||||
* Higher level code can detect this as well and just skip evaluating the field. */
|
||||
const int mask_size = mask.is_empty() ? 0 : 1;
|
||||
MFParamsBuilder mf_params{procedure_executor, mask_size};
|
||||
MFParamsBuilder mf_params{procedure_executor, 1};
|
||||
MFContextBuilder mf_context;
|
||||
|
||||
/* Provide inputs to the procedure executor. */
|
||||
for (const GVArray *varray : field_context_inputs) {
|
||||
mf_params.add_readonly_single_input(*varray);
|
||||
for (const GVArray &varray : field_context_inputs) {
|
||||
mf_params.add_readonly_single_input(varray);
|
||||
}
|
||||
|
||||
for (const int i : constant_fields_to_evaluate.index_range()) {
|
||||
@@ -421,55 +430,52 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope,
|
||||
/* Allocate memory where the computed value will be stored in. */
|
||||
void *buffer = scope.linear_allocator().allocate(type.size(), type.alignment());
|
||||
|
||||
if (!type.is_trivially_destructible() && mask_size > 0) {
|
||||
BLI_assert(mask_size == 1);
|
||||
if (!type.is_trivially_destructible()) {
|
||||
/* Destruct value in the end. */
|
||||
scope.add_destruct_call([buffer, &type]() { type.destruct(buffer); });
|
||||
}
|
||||
|
||||
/* Pass output buffer to the procedure executor. */
|
||||
mf_params.add_uninitialized_single_output({type, buffer, mask_size});
|
||||
mf_params.add_uninitialized_single_output({type, buffer, 1});
|
||||
|
||||
/* Create virtual array that can be used after the procedure has been executed below. */
|
||||
const int out_index = constant_field_indices[i];
|
||||
r_varrays[out_index] = &scope.construct<GVArray_For_SingleValueRef>(
|
||||
type, array_size, buffer);
|
||||
r_varrays[out_index] = GVArray::ForSingleRef(type, array_size, buffer);
|
||||
}
|
||||
|
||||
procedure_executor.call(IndexRange(mask_size), mf_params, mf_context);
|
||||
procedure_executor.call(IndexRange(1), mf_params, mf_context);
|
||||
}
|
||||
|
||||
/* Copy data to supplied destination arrays if necessary. In some cases the evaluation above has
|
||||
* written the computed data in the right place already. */
|
||||
/* Copy data to supplied destination arrays if necessary. In some cases the evaluation above
|
||||
* has written the computed data in the right place already. */
|
||||
if (!dst_varrays.is_empty()) {
|
||||
for (const int out_index : fields_to_evaluate.index_range()) {
|
||||
GVMutableArray *output_varray = get_dst_varray_if_available(out_index);
|
||||
if (output_varray == nullptr) {
|
||||
GVMutableArray dst_varray = get_dst_varray(out_index);
|
||||
if (!dst_varray) {
|
||||
/* Caller did not provide a destination for this output. */
|
||||
continue;
|
||||
}
|
||||
const GVArray *computed_varray = r_varrays[out_index];
|
||||
BLI_assert(computed_varray->type() == output_varray->type());
|
||||
if (output_varray == computed_varray) {
|
||||
const GVArray &computed_varray = r_varrays[out_index];
|
||||
BLI_assert(computed_varray.type() == dst_varray.type());
|
||||
if (is_output_written_to_dst[out_index]) {
|
||||
/* The result has been written into the destination provided by the caller already. */
|
||||
continue;
|
||||
}
|
||||
/* Still have to copy over the data in the destination provided by the caller. */
|
||||
if (output_varray->is_span()) {
|
||||
if (dst_varray.is_span()) {
|
||||
/* Materialize into a span. */
|
||||
computed_varray->materialize_to_uninitialized(mask,
|
||||
output_varray->get_internal_span().data());
|
||||
computed_varray.materialize_to_uninitialized(mask, dst_varray.get_internal_span().data());
|
||||
}
|
||||
else {
|
||||
/* Slower materialize into a different structure. */
|
||||
const CPPType &type = computed_varray->type();
|
||||
const CPPType &type = computed_varray.type();
|
||||
BUFFER_FOR_CPP_TYPE_VALUE(type, buffer);
|
||||
for (const int i : mask) {
|
||||
computed_varray->get_to_uninitialized(i, buffer);
|
||||
output_varray->set_by_relocate(i, buffer);
|
||||
computed_varray.get_to_uninitialized(i, buffer);
|
||||
dst_varray.set_by_relocate(i, buffer);
|
||||
}
|
||||
}
|
||||
r_varrays[out_index] = output_varray;
|
||||
r_varrays[out_index] = dst_varray;
|
||||
}
|
||||
}
|
||||
return r_varrays;
|
||||
@@ -485,8 +491,8 @@ void evaluate_constant_field(const GField &field, void *r_value)
|
||||
|
||||
ResourceScope scope;
|
||||
FieldContext context;
|
||||
Vector<const GVArray *> varrays = evaluate_fields(scope, {field}, IndexRange(1), context);
|
||||
varrays[0]->get_to_uninitialized(0, r_value);
|
||||
Vector<GVArray> varrays = evaluate_fields(scope, {field}, IndexRange(1), context);
|
||||
varrays[0].get_to_uninitialized(0, r_value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -512,9 +518,9 @@ GField make_field_constant_if_possible(GField field)
|
||||
return GField{operation, 0};
|
||||
}
|
||||
|
||||
const GVArray *FieldContext::get_varray_for_input(const FieldInput &field_input,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const
|
||||
GVArray FieldContext::get_varray_for_input(const FieldInput &field_input,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const
|
||||
{
|
||||
/* By default ask the field input to create the varray. Another field context might overwrite
|
||||
* the context here. */
|
||||
@@ -526,17 +532,15 @@ IndexFieldInput::IndexFieldInput() : FieldInput(CPPType::get<int>(), "Index")
|
||||
category_ = Category::Generated;
|
||||
}
|
||||
|
||||
GVArray *IndexFieldInput::get_index_varray(IndexMask mask, ResourceScope &scope)
|
||||
GVArray IndexFieldInput::get_index_varray(IndexMask mask, ResourceScope &UNUSED(scope))
|
||||
{
|
||||
auto index_func = [](int i) { return i; };
|
||||
return &scope.construct<
|
||||
fn::GVArray_For_EmbeddedVArray<int, VArray_For_Func<int, decltype(index_func)>>>(
|
||||
mask.min_array_size(), mask.min_array_size(), index_func);
|
||||
return VArray<int>::ForFunc(mask.min_array_size(), index_func);
|
||||
}
|
||||
|
||||
const GVArray *IndexFieldInput::get_varray_for_context(const fn::FieldContext &UNUSED(context),
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const
|
||||
GVArray IndexFieldInput::get_varray_for_context(const fn::FieldContext &UNUSED(context),
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const
|
||||
{
|
||||
/* TODO: Investigate a similar method to IndexRange::as_span() */
|
||||
return get_index_varray(mask, scope);
|
||||
@@ -631,27 +635,26 @@ static Vector<int64_t> indices_from_selection(const VArray<bool> &selection)
|
||||
return indices;
|
||||
}
|
||||
|
||||
int FieldEvaluator::add_with_destination(GField field, GVMutableArray &dst)
|
||||
int FieldEvaluator::add_with_destination(GField field, GVMutableArray dst)
|
||||
{
|
||||
const int field_index = fields_to_evaluate_.append_and_get_index(std::move(field));
|
||||
dst_varrays_.append(&dst);
|
||||
dst_varrays_.append(dst);
|
||||
output_pointer_infos_.append({});
|
||||
return field_index;
|
||||
}
|
||||
|
||||
int FieldEvaluator::add_with_destination(GField field, GMutableSpan dst)
|
||||
{
|
||||
GVMutableArray &varray = scope_.construct<GVMutableArray_For_GMutableSpan>(dst);
|
||||
return this->add_with_destination(std::move(field), varray);
|
||||
return this->add_with_destination(std::move(field), GVMutableArray::ForSpan(dst));
|
||||
}
|
||||
|
||||
int FieldEvaluator::add(GField field, const GVArray **varray_ptr)
|
||||
int FieldEvaluator::add(GField field, GVArray *varray_ptr)
|
||||
{
|
||||
const int field_index = fields_to_evaluate_.append_and_get_index(std::move(field));
|
||||
dst_varrays_.append(nullptr);
|
||||
output_pointer_infos_.append(OutputPointerInfo{
|
||||
varray_ptr, [](void *dst, const GVArray &varray, ResourceScope &UNUSED(scope)) {
|
||||
*(const GVArray **)dst = &varray;
|
||||
*(GVArray *)dst = varray;
|
||||
}});
|
||||
return field_index;
|
||||
}
|
||||
@@ -676,7 +679,7 @@ void FieldEvaluator::evaluate()
|
||||
for (const int i : fields_to_evaluate_.index_range()) {
|
||||
OutputPointerInfo &info = output_pointer_infos_[i];
|
||||
if (info.dst != nullptr) {
|
||||
info.set(info.dst, *evaluated_varrays_[i], scope_);
|
||||
info.set(info.dst, evaluated_varrays_[i], scope_);
|
||||
}
|
||||
}
|
||||
is_evaluated_ = true;
|
||||
@@ -684,17 +687,16 @@ void FieldEvaluator::evaluate()
|
||||
|
||||
IndexMask FieldEvaluator::get_evaluated_as_mask(const int field_index)
|
||||
{
|
||||
const GVArray &varray = this->get_evaluated(field_index);
|
||||
GVArray_Typed<bool> typed_varray{varray};
|
||||
VArray<bool> varray = this->get_evaluated(field_index).typed<bool>();
|
||||
|
||||
if (typed_varray->is_single()) {
|
||||
if (typed_varray->get_internal_single()) {
|
||||
return IndexRange(typed_varray.size());
|
||||
if (varray.is_single()) {
|
||||
if (varray.get_internal_single()) {
|
||||
return IndexRange(varray.size());
|
||||
}
|
||||
return IndexRange(0);
|
||||
}
|
||||
|
||||
return scope_.add_value(indices_from_selection(*typed_varray)).as_span();
|
||||
return scope_.add_value(indices_from_selection(varray)).as_span();
|
||||
}
|
||||
|
||||
} // namespace blender::fn
|
||||
|
||||
@@ -60,15 +60,14 @@ void GVectorArray::extend(const int64_t index, const GVArray &values)
|
||||
|
||||
void GVectorArray::extend(const int64_t index, const GSpan values)
|
||||
{
|
||||
GVArray_For_GSpan varray{values};
|
||||
this->extend(index, varray);
|
||||
this->extend(index, GVArray::ForSpan(values));
|
||||
}
|
||||
|
||||
void GVectorArray::extend(IndexMask mask, const GVVectorArray &values)
|
||||
{
|
||||
for (const int i : mask) {
|
||||
GVArray_For_GVVectorArrayIndex array{values, i};
|
||||
this->extend(i, array);
|
||||
this->extend(i, GVArray(&array));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,52 +19,10 @@
|
||||
namespace blender::fn {
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #GVArray_For_ShallowCopy
|
||||
/** \name #GVArrayImpl
|
||||
* \{ */
|
||||
|
||||
class GVArray_For_ShallowCopy : public GVArray {
|
||||
private:
|
||||
const GVArray &varray_;
|
||||
|
||||
public:
|
||||
GVArray_For_ShallowCopy(const GVArray &varray)
|
||||
: GVArray(varray.type(), varray.size()), varray_(varray)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
void get_impl(const int64_t index, void *r_value) const override
|
||||
{
|
||||
varray_.get(index, r_value);
|
||||
}
|
||||
|
||||
void get_to_uninitialized_impl(const int64_t index, void *r_value) const override
|
||||
{
|
||||
varray_.get_to_uninitialized(index, r_value);
|
||||
}
|
||||
|
||||
void materialize_to_uninitialized_impl(const IndexMask mask, void *dst) const override
|
||||
{
|
||||
varray_.materialize_to_uninitialized(mask, dst);
|
||||
}
|
||||
};
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #GVArray
|
||||
* \{ */
|
||||
|
||||
void GVArray::materialize(void *dst) const
|
||||
{
|
||||
this->materialize(IndexMask(size_), dst);
|
||||
}
|
||||
|
||||
void GVArray::materialize(const IndexMask mask, void *dst) const
|
||||
{
|
||||
this->materialize_impl(mask, dst);
|
||||
}
|
||||
|
||||
void GVArray::materialize_impl(const IndexMask mask, void *dst) const
|
||||
void GVArrayImpl::materialize(const IndexMask mask, void *dst) const
|
||||
{
|
||||
for (const int64_t i : mask) {
|
||||
void *elem_dst = POINTER_OFFSET(dst, type_->size() * i);
|
||||
@@ -72,18 +30,7 @@ void GVArray::materialize_impl(const IndexMask mask, void *dst) const
|
||||
}
|
||||
}
|
||||
|
||||
void GVArray::materialize_to_uninitialized(void *dst) const
|
||||
{
|
||||
this->materialize_to_uninitialized(IndexMask(size_), dst);
|
||||
}
|
||||
|
||||
void GVArray::materialize_to_uninitialized(const IndexMask mask, void *dst) const
|
||||
{
|
||||
BLI_assert(mask.min_array_size() <= size_);
|
||||
this->materialize_to_uninitialized_impl(mask, dst);
|
||||
}
|
||||
|
||||
void GVArray::materialize_to_uninitialized_impl(const IndexMask mask, void *dst) const
|
||||
void GVArrayImpl::materialize_to_uninitialized(const IndexMask mask, void *dst) const
|
||||
{
|
||||
for (const int64_t i : mask) {
|
||||
void *elem_dst = POINTER_OFFSET(dst, type_->size() * i);
|
||||
@@ -91,83 +38,75 @@ void GVArray::materialize_to_uninitialized_impl(const IndexMask mask, void *dst)
|
||||
}
|
||||
}
|
||||
|
||||
void GVArray::get_impl(const int64_t index, void *r_value) const
|
||||
void GVArrayImpl::get(const int64_t index, void *r_value) const
|
||||
{
|
||||
type_->destruct(r_value);
|
||||
this->get_to_uninitialized_impl(index, r_value);
|
||||
this->get_to_uninitialized(index, r_value);
|
||||
}
|
||||
|
||||
bool GVArray::is_span_impl() const
|
||||
bool GVArrayImpl::is_span() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
GSpan GVArray::get_internal_span_impl() const
|
||||
GSpan GVArrayImpl::get_internal_span() const
|
||||
{
|
||||
BLI_assert(false);
|
||||
return GSpan(*type_);
|
||||
}
|
||||
|
||||
bool GVArray::is_single_impl() const
|
||||
bool GVArrayImpl::is_single() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void GVArray::get_internal_single_impl(void *UNUSED(r_value)) const
|
||||
void GVArrayImpl::get_internal_single(void *UNUSED(r_value)) const
|
||||
{
|
||||
BLI_assert(false);
|
||||
}
|
||||
|
||||
const void *GVArray::try_get_internal_varray_impl() const
|
||||
bool GVArrayImpl::try_assign_VArray(void *UNUSED(varray)) const
|
||||
{
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new `std::unique_ptr<GVArray>` based on this `GVArray`.
|
||||
* The lifetime of the returned virtual array must not be longer than the lifetime of this virtual
|
||||
* array.
|
||||
*/
|
||||
GVArrayPtr GVArray::shallow_copy() const
|
||||
bool GVArrayImpl::may_have_ownership() const
|
||||
{
|
||||
if (this->is_span()) {
|
||||
return std::make_unique<GVArray_For_GSpan>(this->get_internal_span());
|
||||
}
|
||||
if (this->is_single()) {
|
||||
BUFFER_FOR_CPP_TYPE_VALUE(*type_, buffer);
|
||||
this->get_internal_single(buffer);
|
||||
std::unique_ptr new_varray = std::make_unique<GVArray_For_SingleValue>(*type_, size_, buffer);
|
||||
type_->destruct(buffer);
|
||||
return new_varray;
|
||||
}
|
||||
return std::make_unique<GVArray_For_ShallowCopy>(*this);
|
||||
/* Use true as default to avoid accidentally creating subclasses that have this set to false but
|
||||
* actually own data. Subclasses should set the to false instead. */
|
||||
return true;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #GVMutableArray
|
||||
/** \name #GVMutableArrayImpl
|
||||
* \{ */
|
||||
|
||||
void GVMutableArray::set_by_copy_impl(const int64_t index, const void *value)
|
||||
GVMutableArrayImpl::GVMutableArrayImpl(const CPPType &type, const int64_t size)
|
||||
: GVArrayImpl(type, size)
|
||||
{
|
||||
}
|
||||
|
||||
void GVMutableArrayImpl::set_by_copy(const int64_t index, const void *value)
|
||||
{
|
||||
BUFFER_FOR_CPP_TYPE_VALUE(*type_, buffer);
|
||||
type_->copy_construct(value, buffer);
|
||||
this->set_by_move_impl(index, buffer);
|
||||
this->set_by_move(index, buffer);
|
||||
type_->destruct(buffer);
|
||||
}
|
||||
|
||||
void GVMutableArray::set_by_relocate_impl(const int64_t index, void *value)
|
||||
void GVMutableArrayImpl::set_by_relocate(const int64_t index, void *value)
|
||||
{
|
||||
this->set_by_move_impl(index, value);
|
||||
this->set_by_move(index, value);
|
||||
type_->destruct(value);
|
||||
}
|
||||
|
||||
void GVMutableArray::set_all_impl(const void *src)
|
||||
void GVMutableArrayImpl::set_all(const void *src)
|
||||
{
|
||||
if (this->is_span()) {
|
||||
const GMutableSpan span = this->get_internal_span();
|
||||
type_->copy_assign_n(src, span.data(), size_);
|
||||
const GSpan span = this->get_internal_span();
|
||||
type_->copy_assign_n(src, const_cast<void *>(span.data()), size_);
|
||||
}
|
||||
else {
|
||||
for (int64_t i : IndexRange(size_)) {
|
||||
@@ -176,149 +115,224 @@ void GVMutableArray::set_all_impl(const void *src)
|
||||
}
|
||||
}
|
||||
|
||||
void *GVMutableArray::try_get_internal_mutable_varray_impl()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void GVMutableArray::fill(const void *value)
|
||||
{
|
||||
if (this->is_span()) {
|
||||
const GMutableSpan span = this->get_internal_span();
|
||||
type_->fill_assign_n(value, span.data(), size_);
|
||||
const GSpan span = this->get_internal_span();
|
||||
this->type().fill_assign_n(value, const_cast<void *>(span.data()), this->size());
|
||||
}
|
||||
else {
|
||||
for (int64_t i : IndexRange(size_)) {
|
||||
for (int64_t i : IndexRange(this->size())) {
|
||||
this->set_by_copy(i, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool GVMutableArrayImpl::try_assign_VMutableArray(void *UNUSED(varray)) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #GVArray_For_GSpan
|
||||
/** \name #GVArrayImpl_For_GSpan
|
||||
* \{ */
|
||||
|
||||
void GVArray_For_GSpan::get_impl(const int64_t index, void *r_value) const
|
||||
GVArrayImpl_For_GSpan::GVArrayImpl_For_GSpan(const GSpan span)
|
||||
: GVArrayImpl(span.type(), span.size()), data_(span.data()), element_size_(span.type().size())
|
||||
{
|
||||
}
|
||||
|
||||
GVArrayImpl_For_GSpan::GVArrayImpl_For_GSpan(const CPPType &type, const int64_t size)
|
||||
: GVArrayImpl(type, size), element_size_(type.size())
|
||||
{
|
||||
}
|
||||
|
||||
void GVArrayImpl_For_GSpan::get(const int64_t index, void *r_value) const
|
||||
{
|
||||
type_->copy_assign(POINTER_OFFSET(data_, element_size_ * index), r_value);
|
||||
}
|
||||
|
||||
void GVArray_For_GSpan::get_to_uninitialized_impl(const int64_t index, void *r_value) const
|
||||
void GVArrayImpl_For_GSpan::get_to_uninitialized(const int64_t index, void *r_value) const
|
||||
{
|
||||
type_->copy_construct(POINTER_OFFSET(data_, element_size_ * index), r_value);
|
||||
}
|
||||
|
||||
bool GVArray_For_GSpan::is_span_impl() const
|
||||
bool GVArrayImpl_For_GSpan::is_span() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
GSpan GVArray_For_GSpan::get_internal_span_impl() const
|
||||
GSpan GVArrayImpl_For_GSpan::get_internal_span() const
|
||||
{
|
||||
return GSpan(*type_, data_, size_);
|
||||
}
|
||||
|
||||
/** See #VArrayImpl_For_Span_final. */
|
||||
class GVArrayImpl_For_GSpan_final final : public GVArrayImpl_For_GSpan {
|
||||
public:
|
||||
using GVArrayImpl_For_GSpan::GVArrayImpl_For_GSpan;
|
||||
|
||||
private:
|
||||
bool may_have_ownership() const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #GVMutableArray_For_GMutableSpan
|
||||
/** \name #GVMutableArrayImpl_For_GMutableSpan
|
||||
* \{ */
|
||||
|
||||
void GVMutableArray_For_GMutableSpan::get_impl(const int64_t index, void *r_value) const
|
||||
GVMutableArrayImpl_For_GMutableSpan::GVMutableArrayImpl_For_GMutableSpan(const GMutableSpan span)
|
||||
: GVMutableArrayImpl(span.type(), span.size()),
|
||||
data_(span.data()),
|
||||
element_size_(span.type().size())
|
||||
{
|
||||
}
|
||||
|
||||
GVMutableArrayImpl_For_GMutableSpan::GVMutableArrayImpl_For_GMutableSpan(const CPPType &type,
|
||||
const int64_t size)
|
||||
: GVMutableArrayImpl(type, size), element_size_(type.size())
|
||||
{
|
||||
}
|
||||
|
||||
void GVMutableArrayImpl_For_GMutableSpan::get(const int64_t index, void *r_value) const
|
||||
{
|
||||
type_->copy_assign(POINTER_OFFSET(data_, element_size_ * index), r_value);
|
||||
}
|
||||
|
||||
void GVMutableArray_For_GMutableSpan::get_to_uninitialized_impl(const int64_t index,
|
||||
void *r_value) const
|
||||
void GVMutableArrayImpl_For_GMutableSpan::get_to_uninitialized(const int64_t index,
|
||||
void *r_value) const
|
||||
{
|
||||
type_->copy_construct(POINTER_OFFSET(data_, element_size_ * index), r_value);
|
||||
}
|
||||
|
||||
void GVMutableArray_For_GMutableSpan::set_by_copy_impl(const int64_t index, const void *value)
|
||||
void GVMutableArrayImpl_For_GMutableSpan::set_by_copy(const int64_t index, const void *value)
|
||||
{
|
||||
type_->copy_assign(value, POINTER_OFFSET(data_, element_size_ * index));
|
||||
}
|
||||
|
||||
void GVMutableArray_For_GMutableSpan::set_by_move_impl(const int64_t index, void *value)
|
||||
void GVMutableArrayImpl_For_GMutableSpan::set_by_move(const int64_t index, void *value)
|
||||
{
|
||||
type_->move_construct(value, POINTER_OFFSET(data_, element_size_ * index));
|
||||
}
|
||||
|
||||
void GVMutableArray_For_GMutableSpan::set_by_relocate_impl(const int64_t index, void *value)
|
||||
void GVMutableArrayImpl_For_GMutableSpan::set_by_relocate(const int64_t index, void *value)
|
||||
{
|
||||
type_->relocate_assign(value, POINTER_OFFSET(data_, element_size_ * index));
|
||||
}
|
||||
|
||||
bool GVMutableArray_For_GMutableSpan::is_span_impl() const
|
||||
bool GVMutableArrayImpl_For_GMutableSpan::is_span() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
GSpan GVMutableArray_For_GMutableSpan::get_internal_span_impl() const
|
||||
GSpan GVMutableArrayImpl_For_GMutableSpan::get_internal_span() const
|
||||
{
|
||||
return GSpan(*type_, data_, size_);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
class GVMutableArrayImpl_For_GMutableSpan_final final
|
||||
: public GVMutableArrayImpl_For_GMutableSpan {
|
||||
public:
|
||||
using GVMutableArrayImpl_For_GMutableSpan::GVMutableArrayImpl_For_GMutableSpan;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #GVArray_For_SingleValueRef
|
||||
* \{ */
|
||||
|
||||
void GVArray_For_SingleValueRef::get_impl(const int64_t UNUSED(index), void *r_value) const
|
||||
{
|
||||
type_->copy_assign(value_, r_value);
|
||||
}
|
||||
|
||||
void GVArray_For_SingleValueRef::get_to_uninitialized_impl(const int64_t UNUSED(index),
|
||||
void *r_value) const
|
||||
{
|
||||
type_->copy_construct(value_, r_value);
|
||||
}
|
||||
|
||||
bool GVArray_For_SingleValueRef::is_span_impl() const
|
||||
{
|
||||
return size_ == 1;
|
||||
}
|
||||
|
||||
GSpan GVArray_For_SingleValueRef::get_internal_span_impl() const
|
||||
{
|
||||
return GSpan{*type_, value_, 1};
|
||||
}
|
||||
|
||||
bool GVArray_For_SingleValueRef::is_single_impl() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void GVArray_For_SingleValueRef::get_internal_single_impl(void *r_value) const
|
||||
{
|
||||
type_->copy_assign(value_, r_value);
|
||||
}
|
||||
private:
|
||||
bool may_have_ownership() const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #GVArray_For_SingleValue
|
||||
/** \name #GVArrayImpl_For_SingleValueRef
|
||||
* \{ */
|
||||
|
||||
GVArray_For_SingleValue::GVArray_For_SingleValue(const CPPType &type,
|
||||
const int64_t size,
|
||||
const void *value)
|
||||
: GVArray_For_SingleValueRef(type, size)
|
||||
{
|
||||
value_ = MEM_mallocN_aligned(type.size(), type.alignment(), __func__);
|
||||
type.copy_construct(value, (void *)value_);
|
||||
}
|
||||
/* Generic virtual array where each element has the same value. The value is not owned. */
|
||||
class GVArrayImpl_For_SingleValueRef : public GVArrayImpl {
|
||||
protected:
|
||||
const void *value_ = nullptr;
|
||||
|
||||
GVArray_For_SingleValue::~GVArray_For_SingleValue()
|
||||
{
|
||||
type_->destruct((void *)value_);
|
||||
MEM_freeN((void *)value_);
|
||||
}
|
||||
public:
|
||||
GVArrayImpl_For_SingleValueRef(const CPPType &type, const int64_t size, const void *value)
|
||||
: GVArrayImpl(type, size), value_(value)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
GVArrayImpl_For_SingleValueRef(const CPPType &type, const int64_t size) : GVArrayImpl(type, size)
|
||||
{
|
||||
}
|
||||
|
||||
void get(const int64_t UNUSED(index), void *r_value) const override
|
||||
{
|
||||
type_->copy_assign(value_, r_value);
|
||||
}
|
||||
void get_to_uninitialized(const int64_t UNUSED(index), void *r_value) const override
|
||||
{
|
||||
type_->copy_construct(value_, r_value);
|
||||
}
|
||||
|
||||
bool is_span() const override
|
||||
{
|
||||
return size_ == 1;
|
||||
}
|
||||
GSpan get_internal_span() const override
|
||||
{
|
||||
return GSpan{*type_, value_, 1};
|
||||
}
|
||||
|
||||
bool is_single() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
void get_internal_single(void *r_value) const override
|
||||
{
|
||||
type_->copy_assign(value_, r_value);
|
||||
}
|
||||
};
|
||||
|
||||
class GVArrayImpl_For_SingleValueRef_final final : public GVArrayImpl_For_SingleValueRef {
|
||||
public:
|
||||
using GVArrayImpl_For_SingleValueRef::GVArrayImpl_For_SingleValueRef;
|
||||
|
||||
private:
|
||||
bool may_have_ownership() const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #GVArrayImpl_For_SingleValue
|
||||
* \{ */
|
||||
|
||||
/* Same as GVArrayImpl_For_SingleValueRef, but the value is owned. */
|
||||
class GVArrayImpl_For_SingleValue : public GVArrayImpl_For_SingleValueRef,
|
||||
NonCopyable,
|
||||
NonMovable {
|
||||
public:
|
||||
GVArrayImpl_For_SingleValue(const CPPType &type, const int64_t size, const void *value)
|
||||
: GVArrayImpl_For_SingleValueRef(type, size)
|
||||
{
|
||||
value_ = MEM_mallocN_aligned(type.size(), type.alignment(), __func__);
|
||||
type.copy_construct(value, (void *)value_);
|
||||
}
|
||||
|
||||
~GVArrayImpl_For_SingleValue() override
|
||||
{
|
||||
type_->destruct((void *)value_);
|
||||
MEM_freeN((void *)value_);
|
||||
}
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
@@ -326,7 +340,7 @@ GVArray_For_SingleValue::~GVArray_For_SingleValue()
|
||||
/** \name #GVArray_GSpan
|
||||
* \{ */
|
||||
|
||||
GVArray_GSpan::GVArray_GSpan(const GVArray &varray) : GSpan(varray.type()), varray_(varray)
|
||||
GVArray_GSpan::GVArray_GSpan(GVArray varray) : GSpan(varray.type()), varray_(std::move(varray))
|
||||
{
|
||||
size_ = varray_.size();
|
||||
if (varray_.is_span()) {
|
||||
@@ -353,8 +367,8 @@ GVArray_GSpan::~GVArray_GSpan()
|
||||
/** \name #GVMutableArray_GSpan
|
||||
* \{ */
|
||||
|
||||
GVMutableArray_GSpan::GVMutableArray_GSpan(GVMutableArray &varray, const bool copy_values_to_span)
|
||||
: GMutableSpan(varray.type()), varray_(varray)
|
||||
GVMutableArray_GSpan::GVMutableArray_GSpan(GVMutableArray varray, const bool copy_values_to_span)
|
||||
: GMutableSpan(varray.type()), varray_(std::move(varray))
|
||||
{
|
||||
size_ = varray_.size();
|
||||
if (varray_.is_span()) {
|
||||
@@ -405,48 +419,314 @@ void GVMutableArray_GSpan::disable_not_applied_warning()
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #GVArray_For_SlicedGVArray
|
||||
/** \name #GVArrayImpl_For_SlicedGVArray
|
||||
* \{ */
|
||||
|
||||
void GVArray_For_SlicedGVArray::get_impl(const int64_t index, void *r_value) const
|
||||
class GVArrayImpl_For_SlicedGVArray : public GVArrayImpl {
|
||||
protected:
|
||||
GVArray varray_;
|
||||
int64_t offset_;
|
||||
|
||||
public:
|
||||
GVArrayImpl_For_SlicedGVArray(GVArray varray, const IndexRange slice)
|
||||
: GVArrayImpl(varray.type(), slice.size()),
|
||||
varray_(std::move(varray)),
|
||||
offset_(slice.start())
|
||||
{
|
||||
BLI_assert(slice.one_after_last() <= varray_.size());
|
||||
}
|
||||
|
||||
void get(const int64_t index, void *r_value) const override
|
||||
{
|
||||
varray_.get(index + offset_, r_value);
|
||||
}
|
||||
|
||||
void get_to_uninitialized(const int64_t index, void *r_value) const override
|
||||
{
|
||||
varray_.get_to_uninitialized(index + offset_, r_value);
|
||||
}
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #GVArrayCommon
|
||||
* \{ */
|
||||
|
||||
GVArrayCommon::GVArrayCommon() = default;
|
||||
|
||||
GVArrayCommon::GVArrayCommon(const GVArrayCommon &other) : storage_(other.storage_)
|
||||
{
|
||||
varray_.get(index + offset_, r_value);
|
||||
impl_ = this->impl_from_storage();
|
||||
}
|
||||
|
||||
void GVArray_For_SlicedGVArray::get_to_uninitialized_impl(const int64_t index, void *r_value) const
|
||||
GVArrayCommon::GVArrayCommon(GVArrayCommon &&other) noexcept : storage_(std::move(other.storage_))
|
||||
{
|
||||
varray_.get_to_uninitialized(index + offset_, r_value);
|
||||
impl_ = this->impl_from_storage();
|
||||
other.storage_.reset();
|
||||
other.impl_ = nullptr;
|
||||
}
|
||||
|
||||
GVArrayCommon::GVArrayCommon(const GVArrayImpl *impl) : impl_(impl)
|
||||
{
|
||||
storage_ = impl_;
|
||||
}
|
||||
|
||||
GVArrayCommon::GVArrayCommon(std::shared_ptr<const GVArrayImpl> impl) : impl_(impl.get())
|
||||
{
|
||||
if (impl) {
|
||||
storage_ = std::move(impl);
|
||||
}
|
||||
}
|
||||
|
||||
GVArrayCommon::~GVArrayCommon() = default;
|
||||
|
||||
void GVArrayCommon::materialize(void *dst) const
|
||||
{
|
||||
this->materialize(IndexMask(impl_->size()), dst);
|
||||
}
|
||||
|
||||
void GVArrayCommon::materialize(const IndexMask mask, void *dst) const
|
||||
{
|
||||
impl_->materialize(mask, dst);
|
||||
}
|
||||
|
||||
void GVArrayCommon::materialize_to_uninitialized(void *dst) const
|
||||
{
|
||||
this->materialize_to_uninitialized(IndexMask(impl_->size()), dst);
|
||||
}
|
||||
|
||||
void GVArrayCommon::materialize_to_uninitialized(const IndexMask mask, void *dst) const
|
||||
{
|
||||
BLI_assert(mask.min_array_size() <= impl_->size());
|
||||
impl_->materialize_to_uninitialized(mask, dst);
|
||||
}
|
||||
|
||||
bool GVArrayCommon::may_have_ownership() const
|
||||
{
|
||||
return impl_->may_have_ownership();
|
||||
}
|
||||
|
||||
void GVArrayCommon::copy_from(const GVArrayCommon &other)
|
||||
{
|
||||
if (this == &other) {
|
||||
return;
|
||||
}
|
||||
storage_ = other.storage_;
|
||||
impl_ = this->impl_from_storage();
|
||||
}
|
||||
|
||||
void GVArrayCommon::move_from(GVArrayCommon &&other) noexcept
|
||||
{
|
||||
if (this == &other) {
|
||||
return;
|
||||
}
|
||||
storage_ = std::move(other.storage_);
|
||||
impl_ = this->impl_from_storage();
|
||||
other.storage_.reset();
|
||||
other.impl_ = nullptr;
|
||||
}
|
||||
|
||||
/* Returns true when the virtual array is stored as a span internally. */
|
||||
bool GVArrayCommon::is_span() const
|
||||
{
|
||||
if (this->is_empty()) {
|
||||
return true;
|
||||
}
|
||||
return impl_->is_span();
|
||||
}
|
||||
|
||||
/* Returns the internally used span of the virtual array. This invokes undefined behavior is the
|
||||
* virtual array is not stored as a span internally. */
|
||||
GSpan GVArrayCommon::get_internal_span() const
|
||||
{
|
||||
BLI_assert(this->is_span());
|
||||
if (this->is_empty()) {
|
||||
return GSpan(impl_->type());
|
||||
}
|
||||
return impl_->get_internal_span();
|
||||
}
|
||||
|
||||
/* Returns true when the virtual array returns the same value for every index. */
|
||||
bool GVArrayCommon::is_single() const
|
||||
{
|
||||
if (impl_->size() == 1) {
|
||||
return true;
|
||||
}
|
||||
return impl_->is_single();
|
||||
}
|
||||
|
||||
/* Copies the value that is used for every element into `r_value`, which is expected to point to
|
||||
* initialized memory. This invokes undefined behavior if the virtual array would not return the
|
||||
* same value for every index. */
|
||||
void GVArrayCommon::get_internal_single(void *r_value) const
|
||||
{
|
||||
BLI_assert(this->is_single());
|
||||
if (impl_->size() == 1) {
|
||||
impl_->get(0, r_value);
|
||||
return;
|
||||
}
|
||||
impl_->get_internal_single(r_value);
|
||||
}
|
||||
|
||||
/* Same as `get_internal_single`, but `r_value` points to initialized memory. */
|
||||
void GVArrayCommon::get_internal_single_to_uninitialized(void *r_value) const
|
||||
{
|
||||
impl_->type().default_construct(r_value);
|
||||
this->get_internal_single(r_value);
|
||||
}
|
||||
|
||||
const GVArrayImpl *GVArrayCommon::impl_from_storage() const
|
||||
{
|
||||
return storage_.extra_info().get_varray(storage_.get());
|
||||
}
|
||||
|
||||
IndexRange GVArrayCommon::index_range() const
|
||||
{
|
||||
return IndexRange(this->size());
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #GVArray_Slice
|
||||
/** \name #GVArray
|
||||
* \{ */
|
||||
|
||||
GVArray_Slice::GVArray_Slice(const GVArray &varray, const IndexRange slice)
|
||||
GVArray::GVArray(const GVArray &other) = default;
|
||||
|
||||
GVArray::GVArray(GVArray &&other) noexcept = default;
|
||||
|
||||
GVArray::GVArray(const GVArrayImpl *impl) : GVArrayCommon(impl)
|
||||
{
|
||||
if (varray.is_span()) {
|
||||
/* Create a new virtual for the sliced span. */
|
||||
const GSpan span = varray.get_internal_span();
|
||||
const GSpan sliced_span = span.slice(slice.start(), slice.size());
|
||||
varray_span_.emplace(sliced_span);
|
||||
varray_ = &*varray_span_;
|
||||
}
|
||||
else if (varray.is_single()) {
|
||||
/* Can just use the existing virtual array, because it's the same value for the indices in the
|
||||
* slice anyway. */
|
||||
varray_ = &varray;
|
||||
}
|
||||
else {
|
||||
/* Generic version when none of the above method works.
|
||||
* We don't necessarily want to materialize the input varray because there might be
|
||||
* large distances between the required indices. Then we would materialize many elements that
|
||||
* are not accessed later on.
|
||||
*/
|
||||
varray_any_.emplace(varray, slice);
|
||||
varray_ = &*varray_any_;
|
||||
}
|
||||
|
||||
GVArray::GVArray(std::shared_ptr<const GVArrayImpl> impl) : GVArrayCommon(std::move(impl))
|
||||
{
|
||||
}
|
||||
|
||||
GVArray GVArray::ForSingle(const CPPType &type, const int64_t size, const void *value)
|
||||
{
|
||||
return GVArray::For<GVArrayImpl_For_SingleValue>(type, size, value);
|
||||
}
|
||||
|
||||
GVArray GVArray::ForSingleRef(const CPPType &type, const int64_t size, const void *value)
|
||||
{
|
||||
return GVArray::For<GVArrayImpl_For_SingleValueRef_final>(type, size, value);
|
||||
}
|
||||
|
||||
GVArray GVArray::ForSingleDefault(const CPPType &type, const int64_t size)
|
||||
{
|
||||
return GVArray::ForSingleRef(type, size, type.default_value());
|
||||
}
|
||||
|
||||
GVArray GVArray::ForSpan(GSpan span)
|
||||
{
|
||||
return GVArray::For<GVArrayImpl_For_GSpan_final>(span);
|
||||
}
|
||||
|
||||
class GVArrayImpl_For_GArray : public GVArrayImpl_For_GSpan {
|
||||
protected:
|
||||
GArray<> array_;
|
||||
|
||||
public:
|
||||
GVArrayImpl_For_GArray(GArray<> array)
|
||||
: GVArrayImpl_For_GSpan(array.as_span()), array_(std::move(array))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
GVArray GVArray::ForGArray(GArray<> array)
|
||||
{
|
||||
return GVArray::For<GVArrayImpl_For_GArray>(array);
|
||||
}
|
||||
|
||||
GVArray GVArray::ForEmpty(const CPPType &type)
|
||||
{
|
||||
return GVArray::ForSpan(GSpan(type));
|
||||
}
|
||||
|
||||
GVArray GVArray::slice(IndexRange slice) const
|
||||
{
|
||||
return GVArray::For<GVArrayImpl_For_SlicedGVArray>(*this, slice);
|
||||
}
|
||||
|
||||
GVArray &GVArray::operator=(const GVArray &other)
|
||||
{
|
||||
this->copy_from(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
GVArray &GVArray::operator=(GVArray &&other) noexcept
|
||||
{
|
||||
this->move_from(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #GVMutableArray
|
||||
* \{ */
|
||||
|
||||
GVMutableArray::GVMutableArray(const GVMutableArray &other) = default;
|
||||
GVMutableArray::GVMutableArray(GVMutableArray &&other) noexcept = default;
|
||||
|
||||
GVMutableArray::GVMutableArray(GVMutableArrayImpl *impl) : GVArrayCommon(impl)
|
||||
{
|
||||
}
|
||||
|
||||
GVMutableArray::GVMutableArray(std::shared_ptr<GVMutableArrayImpl> impl)
|
||||
: GVArrayCommon(std::move(impl))
|
||||
{
|
||||
}
|
||||
|
||||
GVMutableArray GVMutableArray::ForSpan(GMutableSpan span)
|
||||
{
|
||||
return GVMutableArray::For<GVMutableArrayImpl_For_GMutableSpan_final>(span);
|
||||
}
|
||||
|
||||
GVMutableArray::operator GVArray() const &
|
||||
{
|
||||
GVArray varray;
|
||||
varray.copy_from(*this);
|
||||
return varray;
|
||||
}
|
||||
|
||||
GVMutableArray::operator GVArray() &&noexcept
|
||||
{
|
||||
GVArray varray;
|
||||
varray.move_from(std::move(*this));
|
||||
return varray;
|
||||
}
|
||||
|
||||
GVMutableArray &GVMutableArray::operator=(const GVMutableArray &other)
|
||||
{
|
||||
this->copy_from(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
GVMutableArray &GVMutableArray::operator=(GVMutableArray &&other) noexcept
|
||||
{
|
||||
this->move_from(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
GVMutableArrayImpl *GVMutableArray::get_implementation() const
|
||||
{
|
||||
return this->get_impl();
|
||||
}
|
||||
|
||||
/* Copy the values from the source buffer to all elements in the virtual array. */
|
||||
void GVMutableArray::set_all(const void *src)
|
||||
{
|
||||
this->get_impl()->set_all(src);
|
||||
}
|
||||
|
||||
GMutableSpan GVMutableArray::get_internal_span() const
|
||||
{
|
||||
BLI_assert(this->is_span());
|
||||
const GSpan span = impl_->get_internal_span();
|
||||
return GMutableSpan(span.type(), const_cast<void *>(span.data()), span.size());
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
@@ -18,13 +18,13 @@
|
||||
|
||||
namespace blender::fn {
|
||||
|
||||
void GVArray_For_GVVectorArrayIndex::get_impl(const int64_t index_in_vector, void *r_value) const
|
||||
void GVArray_For_GVVectorArrayIndex::get(const int64_t index_in_vector, void *r_value) const
|
||||
{
|
||||
vector_array_.get_vector_element(index_, index_in_vector, r_value);
|
||||
}
|
||||
|
||||
void GVArray_For_GVVectorArrayIndex::get_to_uninitialized_impl(const int64_t index_in_vector,
|
||||
void *r_value) const
|
||||
void GVArray_For_GVVectorArrayIndex::get_to_uninitialized(const int64_t index_in_vector,
|
||||
void *r_value) const
|
||||
{
|
||||
type_->default_construct(r_value);
|
||||
vector_array_.get_vector_element(index_, index_in_vector, r_value);
|
||||
@@ -32,14 +32,14 @@ void GVArray_For_GVVectorArrayIndex::get_to_uninitialized_impl(const int64_t ind
|
||||
|
||||
int64_t GVVectorArray_For_SingleGVArray::get_vector_size_impl(const int64_t UNUSED(index)) const
|
||||
{
|
||||
return array_.size();
|
||||
return varray_.size();
|
||||
}
|
||||
|
||||
void GVVectorArray_For_SingleGVArray::get_vector_element_impl(const int64_t UNUSED(index),
|
||||
const int64_t index_in_vector,
|
||||
void *r_value) const
|
||||
{
|
||||
array_.get(index_in_vector, r_value);
|
||||
varray_.get(index_in_vector, r_value);
|
||||
}
|
||||
|
||||
bool GVVectorArray_For_SingleGVArray::is_single_vector_impl() const
|
||||
|
||||
@@ -54,7 +54,6 @@ void ParallelMultiFunction::call(IndexMask full_mask, MFParams params, MFContext
|
||||
const IndexRange input_slice_range{input_slice_start, input_slice_size};
|
||||
|
||||
MFParamsBuilder sub_params{fn_, sub_mask.min_array_size()};
|
||||
ResourceScope &scope = sub_params.resource_scope();
|
||||
|
||||
/* All parameters are sliced so that the wrapped multi-function does not have to take care of
|
||||
* the index offset. */
|
||||
@@ -63,8 +62,7 @@ void ParallelMultiFunction::call(IndexMask full_mask, MFParams params, MFContext
|
||||
switch (param_type.category()) {
|
||||
case MFParamType::SingleInput: {
|
||||
const GVArray &varray = params.readonly_single_input(param_index);
|
||||
const GVArray &sliced_varray = scope.construct<GVArray_Slice>(varray, input_slice_range);
|
||||
sub_params.add_readonly_single_input(sliced_varray);
|
||||
sub_params.add_readonly_single_input(varray.slice(input_slice_range));
|
||||
break;
|
||||
}
|
||||
case MFParamType::SingleMutable: {
|
||||
|
||||
@@ -66,6 +66,7 @@ struct VariableValue_GVArray : public VariableValue {
|
||||
|
||||
VariableValue_GVArray(const GVArray &data) : VariableValue(static_type), data(data)
|
||||
{
|
||||
BLI_assert(data);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -756,7 +757,7 @@ class VariableState : NonCopyable, NonMovable {
|
||||
|
||||
switch (value_->type) {
|
||||
case ValueType::GVArray: {
|
||||
const GVArray_Typed<bool> varray{this->value_as<VariableValue_GVArray>()->data};
|
||||
const VArray<bool> varray = this->value_as<VariableValue_GVArray>()->data.typed<bool>();
|
||||
for (const int i : mask) {
|
||||
r_indices[varray[i]].append(i);
|
||||
}
|
||||
|
||||
@@ -34,14 +34,12 @@ class IndexFieldInput final : public FieldInput {
|
||||
{
|
||||
}
|
||||
|
||||
const GVArray *get_varray_for_context(const FieldContext &UNUSED(context),
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const final
|
||||
GVArray get_varray_for_context(const FieldContext &UNUSED(context),
|
||||
IndexMask mask,
|
||||
ResourceScope &UNUSED(scope)) const final
|
||||
{
|
||||
auto index_func = [](int i) { return i; };
|
||||
return &scope.construct<
|
||||
GVArray_For_EmbeddedVArray<int, VArray_For_Func<int, decltype(index_func)>>>(
|
||||
mask.min_array_size(), mask.min_array_size(), index_func);
|
||||
return VArray<int>::ForFunc(mask.min_array_size(), index_func);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -240,20 +238,20 @@ TEST(field, TwoFunctionsTwoOutputs)
|
||||
|
||||
FieldContext field_context;
|
||||
FieldEvaluator field_evaluator{field_context, &mask};
|
||||
const VArray<int> *result_1 = nullptr;
|
||||
const VArray<int> *result_2 = nullptr;
|
||||
VArray<int> result_1;
|
||||
VArray<int> result_2;
|
||||
field_evaluator.add(result_field_1, &result_1);
|
||||
field_evaluator.add(result_field_2, &result_2);
|
||||
field_evaluator.evaluate();
|
||||
|
||||
EXPECT_EQ(result_1->get(2), 4);
|
||||
EXPECT_EQ(result_1->get(4), 8);
|
||||
EXPECT_EQ(result_1->get(6), 12);
|
||||
EXPECT_EQ(result_1->get(8), 16);
|
||||
EXPECT_EQ(result_2->get(2), 24);
|
||||
EXPECT_EQ(result_2->get(4), 28);
|
||||
EXPECT_EQ(result_2->get(6), 32);
|
||||
EXPECT_EQ(result_2->get(8), 36);
|
||||
EXPECT_EQ(result_1.get(2), 4);
|
||||
EXPECT_EQ(result_1.get(4), 8);
|
||||
EXPECT_EQ(result_1.get(6), 12);
|
||||
EXPECT_EQ(result_1.get(8), 16);
|
||||
EXPECT_EQ(result_2.get(2), 24);
|
||||
EXPECT_EQ(result_2.get(4), 28);
|
||||
EXPECT_EQ(result_2.get(6), 32);
|
||||
EXPECT_EQ(result_2.get(8), 36);
|
||||
}
|
||||
|
||||
TEST(field, SameFieldTwice)
|
||||
@@ -264,16 +262,16 @@ TEST(field, SameFieldTwice)
|
||||
FieldContext field_context;
|
||||
IndexMask mask{IndexRange(2)};
|
||||
ResourceScope scope;
|
||||
Vector<const GVArray *> results = evaluate_fields(
|
||||
Vector<GVArray> results = evaluate_fields(
|
||||
scope, {constant_field, constant_field}, mask, field_context);
|
||||
|
||||
GVArray_Typed<int> varray1{*results[0]};
|
||||
GVArray_Typed<int> varray2{*results[1]};
|
||||
VArray<int> varray1 = results[0].typed<int>();
|
||||
VArray<int> varray2 = results[1].typed<int>();
|
||||
|
||||
EXPECT_EQ(varray1->get(0), 10);
|
||||
EXPECT_EQ(varray1->get(1), 10);
|
||||
EXPECT_EQ(varray2->get(0), 10);
|
||||
EXPECT_EQ(varray2->get(1), 10);
|
||||
EXPECT_EQ(varray1.get(0), 10);
|
||||
EXPECT_EQ(varray1.get(1), 10);
|
||||
EXPECT_EQ(varray2.get(0), 10);
|
||||
EXPECT_EQ(varray2.get(1), 10);
|
||||
}
|
||||
|
||||
TEST(field, IgnoredOutput)
|
||||
@@ -283,12 +281,12 @@ TEST(field, IgnoredOutput)
|
||||
|
||||
FieldContext field_context;
|
||||
FieldEvaluator field_evaluator{field_context, 10};
|
||||
const VArray<int> *results = nullptr;
|
||||
VArray<int> results;
|
||||
field_evaluator.add(field, &results);
|
||||
field_evaluator.evaluate();
|
||||
|
||||
EXPECT_EQ(results->get(0), 5);
|
||||
EXPECT_EQ(results->get(3), 5);
|
||||
EXPECT_EQ(results.get(0), 5);
|
||||
EXPECT_EQ(results.get(3), 5);
|
||||
}
|
||||
|
||||
} // namespace blender::fn::tests
|
||||
|
||||
@@ -9,6 +9,43 @@
|
||||
|
||||
namespace blender::fn::tests {
|
||||
|
||||
TEST(multi_function_procedure, ConstantOutput)
|
||||
{
|
||||
/**
|
||||
* procedure(int *var2) {
|
||||
* var1 = 5;
|
||||
* var2 = var1 + var1;
|
||||
* }
|
||||
*/
|
||||
|
||||
CustomMF_Constant<int> constant_fn{5};
|
||||
CustomMF_SI_SI_SO<int, int, int> add_fn{"Add", [](int a, int b) { return a + b; }};
|
||||
|
||||
MFProcedure procedure;
|
||||
MFProcedureBuilder builder{procedure};
|
||||
|
||||
auto [var1] = builder.add_call<1>(constant_fn);
|
||||
auto [var2] = builder.add_call<1>(add_fn, {var1, var1});
|
||||
builder.add_destruct(*var1);
|
||||
builder.add_return();
|
||||
builder.add_output_parameter(*var2);
|
||||
|
||||
EXPECT_TRUE(procedure.validate());
|
||||
|
||||
MFProcedureExecutor executor{"My Procedure", procedure};
|
||||
|
||||
MFParamsBuilder params{executor, 2};
|
||||
MFContextBuilder context;
|
||||
|
||||
Array<int> output_array(2);
|
||||
params.add_uninitialized_single_output(output_array.as_mutable_span());
|
||||
|
||||
executor.call(IndexRange(2), params, context);
|
||||
|
||||
EXPECT_EQ(output_array[0], 10);
|
||||
EXPECT_EQ(output_array[1], 10);
|
||||
}
|
||||
|
||||
TEST(multi_function_procedure, SimpleTest)
|
||||
{
|
||||
/**
|
||||
|
||||
@@ -50,23 +50,23 @@ static void copy_attributes_to_points(CurveEval &curve,
|
||||
|
||||
/* Copy builtin control point attributes. */
|
||||
if (source_attribute_ids.contains("tilt")) {
|
||||
const fn::GVArray_Typed<float> tilt_attribute = mesh_component.attribute_get_for_read<float>(
|
||||
const VArray<float> tilt_attribute = mesh_component.attribute_get_for_read<float>(
|
||||
"tilt", ATTR_DOMAIN_POINT, 0.0f);
|
||||
threading::parallel_for(splines.index_range(), 256, [&](IndexRange range) {
|
||||
for (const int i : range) {
|
||||
copy_attribute_to_points<float>(
|
||||
*tilt_attribute, point_to_vert_maps[i], splines[i]->tilts());
|
||||
tilt_attribute, point_to_vert_maps[i], splines[i]->tilts());
|
||||
}
|
||||
});
|
||||
source_attribute_ids.remove_contained("tilt");
|
||||
}
|
||||
if (source_attribute_ids.contains("radius")) {
|
||||
const fn::GVArray_Typed<float> radius_attribute = mesh_component.attribute_get_for_read<float>(
|
||||
const VArray<float> radius_attribute = mesh_component.attribute_get_for_read<float>(
|
||||
"radius", ATTR_DOMAIN_POINT, 1.0f);
|
||||
threading::parallel_for(splines.index_range(), 256, [&](IndexRange range) {
|
||||
for (const int i : range) {
|
||||
copy_attribute_to_points<float>(
|
||||
*radius_attribute, point_to_vert_maps[i], splines[i]->radii());
|
||||
radius_attribute, point_to_vert_maps[i], splines[i]->radii());
|
||||
}
|
||||
});
|
||||
source_attribute_ids.remove_contained("radius");
|
||||
@@ -82,7 +82,7 @@ static void copy_attributes_to_points(CurveEval &curve,
|
||||
continue;
|
||||
}
|
||||
|
||||
const fn::GVArrayPtr mesh_attribute = mesh_component.attribute_try_get_for_read(
|
||||
const fn::GVArray mesh_attribute = mesh_component.attribute_try_get_for_read(
|
||||
attribute_id, ATTR_DOMAIN_POINT);
|
||||
/* Some attributes might not exist if they were builtin attribute on domains that don't
|
||||
* have any elements, i.e. a face attribute on the output of the line primitive node. */
|
||||
@@ -90,7 +90,7 @@ static void copy_attributes_to_points(CurveEval &curve,
|
||||
continue;
|
||||
}
|
||||
|
||||
const CustomDataType data_type = bke::cpp_type_to_custom_data_type(mesh_attribute->type());
|
||||
const CustomDataType data_type = bke::cpp_type_to_custom_data_type(mesh_attribute.type());
|
||||
|
||||
threading::parallel_for(splines.index_range(), 128, [&](IndexRange range) {
|
||||
for (const int i : range) {
|
||||
@@ -101,10 +101,10 @@ static void copy_attributes_to_points(CurveEval &curve,
|
||||
BLI_assert(spline_attribute);
|
||||
|
||||
/* Copy attribute based on the map for this spline. */
|
||||
attribute_math::convert_to_static_type(mesh_attribute->type(), [&](auto dummy) {
|
||||
attribute_math::convert_to_static_type(mesh_attribute.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
copy_attribute_to_points<T>(
|
||||
mesh_attribute->typed<T>(), point_to_vert_maps[i], spline_attribute->typed<T>());
|
||||
mesh_attribute.typed<T>(), point_to_vert_maps[i], spline_attribute->typed<T>());
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -57,13 +57,8 @@ using fn::GPointer;
|
||||
using fn::GSpan;
|
||||
using fn::GVArray;
|
||||
using fn::GVArray_GSpan;
|
||||
using fn::GVArray_Span;
|
||||
using fn::GVArray_Typed;
|
||||
using fn::GVArrayPtr;
|
||||
using fn::GVMutableArray;
|
||||
using fn::GVMutableArray_GSpan;
|
||||
using fn::GVMutableArray_Typed;
|
||||
using fn::GVMutableArrayPtr;
|
||||
using geometry_nodes_eval_log::NodeWarningType;
|
||||
|
||||
/**
|
||||
@@ -316,21 +311,21 @@ class GeoNodeExecParams {
|
||||
* \note This will add an error message if the string socket is active and
|
||||
* the input attribute does not exist.
|
||||
*/
|
||||
GVArrayPtr get_input_attribute(const StringRef name,
|
||||
const GeometryComponent &component,
|
||||
const AttributeDomain domain,
|
||||
const CustomDataType type,
|
||||
const void *default_value) const;
|
||||
GVArray get_input_attribute(const StringRef name,
|
||||
const GeometryComponent &component,
|
||||
const AttributeDomain domain,
|
||||
const CustomDataType type,
|
||||
const void *default_value) const;
|
||||
|
||||
template<typename T>
|
||||
GVArray_Typed<T> get_input_attribute(const StringRef name,
|
||||
const GeometryComponent &component,
|
||||
const AttributeDomain domain,
|
||||
const T &default_value) const
|
||||
VArray<T> get_input_attribute(const StringRef name,
|
||||
const GeometryComponent &component,
|
||||
const AttributeDomain domain,
|
||||
const T &default_value) const
|
||||
{
|
||||
const CustomDataType type = bke::cpp_type_to_custom_data_type(CPPType::get<T>());
|
||||
GVArrayPtr varray = this->get_input_attribute(name, component, domain, type, &default_value);
|
||||
return GVArray_Typed<T>(std::move(varray));
|
||||
GVArray varray = this->get_input_attribute(name, component, domain, type, &default_value);
|
||||
return varray.typed<T>();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
namespace blender::nodes {
|
||||
|
||||
using fn::CPPType;
|
||||
using fn::GVArray;
|
||||
|
||||
struct ConversionFunctions {
|
||||
const fn::MultiFunction *multi_function;
|
||||
@@ -73,9 +72,9 @@ class DataTypeConversions {
|
||||
const void *from_value,
|
||||
void *to_value) const;
|
||||
|
||||
fn::GVArrayPtr try_convert(fn::GVArrayPtr varray, const CPPType &to_type) const;
|
||||
fn::GVArray try_convert(fn::GVArray varray, const CPPType &to_type) const;
|
||||
|
||||
fn::GVMutableArrayPtr try_convert(fn::GVMutableArrayPtr varray, const CPPType &to_type) const;
|
||||
fn::GVMutableArray try_convert(fn::GVMutableArray varray, const CPPType &to_type) const;
|
||||
};
|
||||
|
||||
const DataTypeConversions &get_implicit_type_conversions();
|
||||
|
||||
@@ -179,9 +179,9 @@ static void align_rotations_on_component(GeometryComponent &component,
|
||||
return;
|
||||
}
|
||||
|
||||
GVArray_Typed<float> factors = params.get_input_attribute<float>(
|
||||
VArray<float> factors = params.get_input_attribute<float>(
|
||||
"Factor", component, ATTR_DOMAIN_POINT, 1.0f);
|
||||
GVArray_Typed<float3> vectors = params.get_input_attribute<float3>(
|
||||
VArray<float3> vectors = params.get_input_attribute<float3>(
|
||||
"Vector", component, ATTR_DOMAIN_POINT, {0, 0, 1});
|
||||
|
||||
float3 local_main_axis{0, 0, 0};
|
||||
|
||||
@@ -156,7 +156,7 @@ static void clamp_attribute(GeometryComponent &component, const GeoNodeExecParam
|
||||
const AttributeDomain domain = get_result_domain(component, attribute_name, result_name);
|
||||
const int operation = static_cast<int>(storage.operation);
|
||||
|
||||
GVArrayPtr attribute_input = component.attribute_try_get_for_read(
|
||||
GVArray attribute_input = component.attribute_try_get_for_read(
|
||||
attribute_name, domain, data_type);
|
||||
|
||||
OutputAttribute attribute_result = component.attribute_try_get_for_output_only(
|
||||
@@ -185,7 +185,7 @@ static void clamp_attribute(GeometryComponent &component, const GeoNodeExecParam
|
||||
}
|
||||
}
|
||||
MutableSpan<float3> results = attribute_result.as_span<float3>();
|
||||
clamp_attribute<float3>(attribute_input->typed<float3>(), results, min, max);
|
||||
clamp_attribute<float3>(attribute_input.typed<float3>(), results, min, max);
|
||||
break;
|
||||
}
|
||||
case CD_PROP_FLOAT: {
|
||||
@@ -193,10 +193,10 @@ static void clamp_attribute(GeometryComponent &component, const GeoNodeExecParam
|
||||
const float max = params.get_input<float>("Max_001");
|
||||
MutableSpan<float> results = attribute_result.as_span<float>();
|
||||
if (operation == NODE_CLAMP_RANGE && min > max) {
|
||||
clamp_attribute<float>(attribute_input->typed<float>(), results, max, min);
|
||||
clamp_attribute<float>(attribute_input.typed<float>(), results, max, min);
|
||||
}
|
||||
else {
|
||||
clamp_attribute<float>(attribute_input->typed<float>(), results, min, max);
|
||||
clamp_attribute<float>(attribute_input.typed<float>(), results, min, max);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -205,10 +205,10 @@ static void clamp_attribute(GeometryComponent &component, const GeoNodeExecParam
|
||||
const int max = params.get_input<int>("Max_002");
|
||||
MutableSpan<int> results = attribute_result.as_span<int>();
|
||||
if (operation == NODE_CLAMP_RANGE && min > max) {
|
||||
clamp_attribute<int>(attribute_input->typed<int>(), results, max, min);
|
||||
clamp_attribute<int>(attribute_input.typed<int>(), results, max, min);
|
||||
}
|
||||
else {
|
||||
clamp_attribute<int>(attribute_input->typed<int>(), results, min, max);
|
||||
clamp_attribute<int>(attribute_input.typed<int>(), results, min, max);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -231,7 +231,7 @@ static void clamp_attribute(GeometryComponent &component, const GeoNodeExecParam
|
||||
}
|
||||
MutableSpan<ColorGeometry4f> results = attribute_result.as_span<ColorGeometry4f>();
|
||||
clamp_attribute<ColorGeometry4f>(
|
||||
attribute_input->typed<ColorGeometry4f>(), results, min, max);
|
||||
attribute_input.typed<ColorGeometry4f>(), results, min, max);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
||||
@@ -85,7 +85,7 @@ static void execute_on_component(const GeoNodeExecParams ¶ms, GeometryCompon
|
||||
return;
|
||||
}
|
||||
|
||||
GVArray_Typed<float> attribute_in = component.attribute_get_for_read<float>(
|
||||
VArray<float> attribute_in = component.attribute_get_for_read<float>(
|
||||
input_name, result_domain, 0.0f);
|
||||
|
||||
MutableSpan<ColorGeometry4f> results = attribute_result.as_span();
|
||||
|
||||
@@ -95,11 +95,11 @@ static void combine_attributes(GeometryComponent &component, const GeoNodeExecPa
|
||||
if (!attribute_result) {
|
||||
return;
|
||||
}
|
||||
GVArray_Typed<float> attribute_x = params.get_input_attribute<float>(
|
||||
VArray<float> attribute_x = params.get_input_attribute<float>(
|
||||
"X", component, result_domain, 0.0f);
|
||||
GVArray_Typed<float> attribute_y = params.get_input_attribute<float>(
|
||||
VArray<float> attribute_y = params.get_input_attribute<float>(
|
||||
"Y", component, result_domain, 0.0f);
|
||||
GVArray_Typed<float> attribute_z = params.get_input_attribute<float>(
|
||||
VArray<float> attribute_z = params.get_input_attribute<float>(
|
||||
"Z", component, result_domain, 0.0f);
|
||||
|
||||
for (const int i : IndexRange(attribute_result->size())) {
|
||||
|
||||
@@ -257,9 +257,9 @@ static void attribute_compare_calc(GeometryComponent &component, const GeoNodeEx
|
||||
|
||||
const CustomDataType input_data_type = get_data_type(component, params, *node_storage);
|
||||
|
||||
GVArrayPtr attribute_a = params.get_input_attribute(
|
||||
GVArray attribute_a = params.get_input_attribute(
|
||||
"A", component, result_domain, input_data_type, nullptr);
|
||||
GVArrayPtr attribute_b = params.get_input_attribute(
|
||||
GVArray attribute_b = params.get_input_attribute(
|
||||
"B", component, result_domain, input_data_type, nullptr);
|
||||
|
||||
if (!attribute_a || !attribute_b) {
|
||||
@@ -276,47 +276,47 @@ static void attribute_compare_calc(GeometryComponent &component, const GeoNodeEx
|
||||
if (operation == NODE_FLOAT_COMPARE_EQUAL) {
|
||||
if (input_data_type == CD_PROP_FLOAT) {
|
||||
do_equal_operation_float(
|
||||
attribute_a->typed<float>(), attribute_b->typed<float>(), threshold, result_span);
|
||||
attribute_a.typed<float>(), attribute_b.typed<float>(), threshold, result_span);
|
||||
}
|
||||
else if (input_data_type == CD_PROP_FLOAT3) {
|
||||
do_equal_operation_float3(
|
||||
attribute_a->typed<float3>(), attribute_b->typed<float3>(), threshold, result_span);
|
||||
attribute_a.typed<float3>(), attribute_b.typed<float3>(), threshold, result_span);
|
||||
}
|
||||
else if (input_data_type == CD_PROP_COLOR) {
|
||||
do_equal_operation_color4f(attribute_a->typed<ColorGeometry4f>(),
|
||||
attribute_b->typed<ColorGeometry4f>(),
|
||||
do_equal_operation_color4f(attribute_a.typed<ColorGeometry4f>(),
|
||||
attribute_b.typed<ColorGeometry4f>(),
|
||||
threshold,
|
||||
result_span);
|
||||
}
|
||||
else if (input_data_type == CD_PROP_BOOL) {
|
||||
do_equal_operation_bool(
|
||||
attribute_a->typed<bool>(), attribute_b->typed<bool>(), threshold, result_span);
|
||||
attribute_a.typed<bool>(), attribute_b.typed<bool>(), threshold, result_span);
|
||||
}
|
||||
}
|
||||
else if (operation == NODE_FLOAT_COMPARE_NOT_EQUAL) {
|
||||
if (input_data_type == CD_PROP_FLOAT) {
|
||||
do_not_equal_operation_float(
|
||||
attribute_a->typed<float>(), attribute_b->typed<float>(), threshold, result_span);
|
||||
attribute_a.typed<float>(), attribute_b.typed<float>(), threshold, result_span);
|
||||
}
|
||||
else if (input_data_type == CD_PROP_FLOAT3) {
|
||||
do_not_equal_operation_float3(
|
||||
attribute_a->typed<float3>(), attribute_b->typed<float3>(), threshold, result_span);
|
||||
attribute_a.typed<float3>(), attribute_b.typed<float3>(), threshold, result_span);
|
||||
}
|
||||
else if (input_data_type == CD_PROP_COLOR) {
|
||||
do_not_equal_operation_color4f(attribute_a->typed<ColorGeometry4f>(),
|
||||
attribute_b->typed<ColorGeometry4f>(),
|
||||
do_not_equal_operation_color4f(attribute_a.typed<ColorGeometry4f>(),
|
||||
attribute_b.typed<ColorGeometry4f>(),
|
||||
threshold,
|
||||
result_span);
|
||||
}
|
||||
else if (input_data_type == CD_PROP_BOOL) {
|
||||
do_not_equal_operation_bool(
|
||||
attribute_a->typed<bool>(), attribute_b->typed<bool>(), threshold, result_span);
|
||||
attribute_a.typed<bool>(), attribute_b.typed<bool>(), threshold, result_span);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
do_math_operation(
|
||||
attribute_a->typed<float>(), attribute_b->typed<float>(), operation, result_span);
|
||||
attribute_a.typed<float>(), attribute_b.typed<float>(), operation, result_span);
|
||||
}
|
||||
|
||||
attribute_result.save();
|
||||
|
||||
@@ -104,7 +104,7 @@ static void attribute_convert_calc(GeometryComponent &component,
|
||||
return;
|
||||
}
|
||||
|
||||
GVArrayPtr source_attribute = component.attribute_try_get_for_read(
|
||||
GVArray source_attribute = component.attribute_try_get_for_read(
|
||||
source_name, result_domain, result_type);
|
||||
if (!source_attribute) {
|
||||
params.error_message_add(NodeWarningType::Error,
|
||||
@@ -118,7 +118,7 @@ static void attribute_convert_calc(GeometryComponent &component,
|
||||
return;
|
||||
}
|
||||
|
||||
GVArray_GSpan source_span{*source_attribute};
|
||||
GVArray_GSpan source_span{source_attribute};
|
||||
GMutableSpan result_span = result_attribute.as_span();
|
||||
|
||||
BLI_assert(source_span.size() == result_span.size());
|
||||
|
||||
@@ -136,10 +136,10 @@ static void execute_on_component(const GeoNodeExecParams ¶ms, GeometryCompon
|
||||
switch (result_type) {
|
||||
case CD_PROP_FLOAT: {
|
||||
const CurveMapping *cumap = (CurveMapping *)node_storage.curve_vec;
|
||||
GVArray_Typed<float> attribute_in = component.attribute_get_for_read<float>(
|
||||
VArray<float> attribute_in = component.attribute_get_for_read<float>(
|
||||
input_name, result_domain, float(0.0f));
|
||||
MutableSpan<float> results = attribute_result.as_span<float>();
|
||||
threading::parallel_for(IndexRange(attribute_in.size()), 512, [&](IndexRange range) {
|
||||
threading::parallel_for(attribute_in.index_range(), 512, [&](IndexRange range) {
|
||||
for (const int i : range) {
|
||||
results[i] = BKE_curvemapping_evaluateF(cumap, 3, attribute_in[i]);
|
||||
}
|
||||
@@ -148,10 +148,10 @@ static void execute_on_component(const GeoNodeExecParams ¶ms, GeometryCompon
|
||||
}
|
||||
case CD_PROP_FLOAT3: {
|
||||
const CurveMapping *cumap = (CurveMapping *)node_storage.curve_vec;
|
||||
GVArray_Typed<float3> attribute_in = component.attribute_get_for_read<float3>(
|
||||
VArray<float3> attribute_in = component.attribute_get_for_read<float3>(
|
||||
input_name, result_domain, float3(0.0f));
|
||||
MutableSpan<float3> results = attribute_result.as_span<float3>();
|
||||
threading::parallel_for(IndexRange(attribute_in.size()), 512, [&](IndexRange range) {
|
||||
threading::parallel_for(attribute_in.index_range(), 512, [&](IndexRange range) {
|
||||
for (const int i : range) {
|
||||
BKE_curvemapping_evaluate3F(cumap, results[i], attribute_in[i]);
|
||||
}
|
||||
@@ -160,11 +160,10 @@ static void execute_on_component(const GeoNodeExecParams ¶ms, GeometryCompon
|
||||
}
|
||||
case CD_PROP_COLOR: {
|
||||
const CurveMapping *cumap = (CurveMapping *)node_storage.curve_rgb;
|
||||
GVArray_Typed<ColorGeometry4f> attribute_in =
|
||||
component.attribute_get_for_read<ColorGeometry4f>(
|
||||
input_name, result_domain, ColorGeometry4f(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
VArray<ColorGeometry4f> attribute_in = component.attribute_get_for_read<ColorGeometry4f>(
|
||||
input_name, result_domain, ColorGeometry4f(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
MutableSpan<ColorGeometry4f> results = attribute_result.as_span<ColorGeometry4f>();
|
||||
threading::parallel_for(IndexRange(attribute_in.size()), 512, [&](IndexRange range) {
|
||||
threading::parallel_for(attribute_in.index_range(), 512, [&](IndexRange range) {
|
||||
for (const int i : range) {
|
||||
BKE_curvemapping_evaluateRGBF(cumap, results[i], attribute_in[i]);
|
||||
}
|
||||
|
||||
@@ -362,7 +362,7 @@ static void map_range_attribute(GeometryComponent &component, const GeoNodeExecP
|
||||
|
||||
const AttributeDomain domain = get_result_domain(component, input_name, result_name);
|
||||
|
||||
GVArrayPtr attribute_input = component.attribute_try_get_for_read(input_name, domain, data_type);
|
||||
GVArray attribute_input = component.attribute_try_get_for_read(input_name, domain, data_type);
|
||||
|
||||
if (!attribute_input) {
|
||||
params.error_message_add(NodeWarningType::Error,
|
||||
@@ -381,12 +381,12 @@ static void map_range_attribute(GeometryComponent &component, const GeoNodeExecP
|
||||
|
||||
switch (data_type) {
|
||||
case CD_PROP_FLOAT: {
|
||||
map_range_float(attribute_input->typed<float>(), attribute_result.as_span<float>(), params);
|
||||
map_range_float(attribute_input.typed<float>(), attribute_result.as_span<float>(), params);
|
||||
break;
|
||||
}
|
||||
case CD_PROP_FLOAT3: {
|
||||
map_range_float3(
|
||||
attribute_input->typed<float3>(), attribute_result.as_span<float3>(), params);
|
||||
attribute_input.typed<float3>(), attribute_result.as_span<float3>(), params);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
||||
@@ -250,7 +250,7 @@ static void attribute_math_calc(GeometryComponent &component, const GeoNodeExecP
|
||||
return;
|
||||
}
|
||||
|
||||
GVArray_Typed<float> attribute_a = params.get_input_attribute<float>(
|
||||
VArray<float> attribute_a = params.get_input_attribute<float>(
|
||||
"A", component, result_domain, 0.0f);
|
||||
|
||||
MutableSpan<float> result_span = attribute_result.as_span();
|
||||
@@ -258,10 +258,10 @@ static void attribute_math_calc(GeometryComponent &component, const GeoNodeExecP
|
||||
/* Note that passing the data with `get_internal_span<float>()` works
|
||||
* because the attributes were accessed with #CD_PROP_FLOAT. */
|
||||
if (operation_use_input_b(operation)) {
|
||||
GVArray_Typed<float> attribute_b = params.get_input_attribute<float>(
|
||||
VArray<float> attribute_b = params.get_input_attribute<float>(
|
||||
"B", component, result_domain, 0.0f);
|
||||
if (operation_use_input_c(operation)) {
|
||||
GVArray_Typed<float> attribute_c = params.get_input_attribute<float>(
|
||||
VArray<float> attribute_c = params.get_input_attribute<float>(
|
||||
"C", component, result_domain, 0.0f);
|
||||
do_math_operation(attribute_a, attribute_b, attribute_c, result_span, operation);
|
||||
}
|
||||
|
||||
@@ -144,25 +144,28 @@ static void do_mix_operation(const CustomDataType result_type,
|
||||
GVMutableArray &attribute_result)
|
||||
{
|
||||
if (result_type == CD_PROP_FLOAT) {
|
||||
VMutableArray<float> result = attribute_result.typed<float>();
|
||||
do_mix_operation_float(blend_mode,
|
||||
attribute_factor,
|
||||
attribute_a.typed<float>(),
|
||||
attribute_b.typed<float>(),
|
||||
attribute_result.typed<float>());
|
||||
result);
|
||||
}
|
||||
else if (result_type == CD_PROP_FLOAT3) {
|
||||
VMutableArray<float3> result = attribute_result.typed<float3>();
|
||||
do_mix_operation_float3(blend_mode,
|
||||
attribute_factor,
|
||||
attribute_a.typed<float3>(),
|
||||
attribute_b.typed<float3>(),
|
||||
attribute_result.typed<float3>());
|
||||
result);
|
||||
}
|
||||
else if (result_type == CD_PROP_COLOR) {
|
||||
VMutableArray<ColorGeometry4f> result = attribute_result.typed<ColorGeometry4f>();
|
||||
do_mix_operation_color4f(blend_mode,
|
||||
attribute_factor,
|
||||
attribute_a.typed<ColorGeometry4f>(),
|
||||
attribute_b.typed<ColorGeometry4f>(),
|
||||
attribute_result.typed<ColorGeometry4f>());
|
||||
result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,19 +206,19 @@ static void attribute_mix_calc(GeometryComponent &component, const GeoNodeExecPa
|
||||
return;
|
||||
}
|
||||
|
||||
GVArray_Typed<float> attribute_factor = params.get_input_attribute<float>(
|
||||
VArray<float> attribute_factor = params.get_input_attribute<float>(
|
||||
"Factor", component, result_domain, 0.5f);
|
||||
GVArrayPtr attribute_a = params.get_input_attribute(
|
||||
GVArray attribute_a = params.get_input_attribute(
|
||||
"A", component, result_domain, result_type, nullptr);
|
||||
GVArrayPtr attribute_b = params.get_input_attribute(
|
||||
GVArray attribute_b = params.get_input_attribute(
|
||||
"B", component, result_domain, result_type, nullptr);
|
||||
|
||||
do_mix_operation(result_type,
|
||||
node_storage->blend_type,
|
||||
attribute_factor,
|
||||
*attribute_a,
|
||||
*attribute_b,
|
||||
*attribute_result);
|
||||
attribute_a,
|
||||
attribute_b,
|
||||
attribute_result.varray());
|
||||
attribute_result.save();
|
||||
}
|
||||
|
||||
|
||||
@@ -153,7 +153,7 @@ static void attribute_calc_proximity(GeometryComponent &component,
|
||||
if (!position_attribute || (!distance_attribute && !location_attribute)) {
|
||||
return;
|
||||
}
|
||||
GVArray_Typed<float3> positions{*position_attribute.varray};
|
||||
VArray<float3> positions = position_attribute.varray.typed<float3>();
|
||||
const NodeGeometryAttributeProximity &storage =
|
||||
*(const NodeGeometryAttributeProximity *)params.node().storage;
|
||||
|
||||
|
||||
@@ -180,13 +180,13 @@ Array<uint32_t> get_geometry_element_ids_as_uints(const GeometryComponent &compo
|
||||
const int domain_size = component.attribute_domain_size(domain);
|
||||
|
||||
/* Hash the reserved name attribute "id" as a (hopefully) stable seed for each point. */
|
||||
GVArrayPtr hash_attribute = component.attribute_try_get_for_read("id", domain);
|
||||
GVArray hash_attribute = component.attribute_try_get_for_read("id", domain);
|
||||
Array<uint32_t> hashes(domain_size);
|
||||
if (hash_attribute) {
|
||||
BLI_assert(hashes.size() == hash_attribute->size());
|
||||
const CPPType &cpp_type = hash_attribute->type();
|
||||
BLI_assert(hashes.size() == hash_attribute.size());
|
||||
const CPPType &cpp_type = hash_attribute.type();
|
||||
BLI_assert(cpp_type.is_hashable());
|
||||
GVArray_GSpan items{*hash_attribute};
|
||||
GVArray_GSpan items{hash_attribute};
|
||||
threading::parallel_for(hashes.index_range(), 512, [&](IndexRange range) {
|
||||
for (const int i : range) {
|
||||
hashes[i] = cpp_type.hash(items[i]);
|
||||
|
||||
@@ -82,7 +82,7 @@ static void execute_on_component(GeometryComponent &component, const GeoNodeExec
|
||||
return;
|
||||
}
|
||||
|
||||
GVArray_Typed<float3> mapping_attribute = component.attribute_get_for_read<float3>(
|
||||
VArray<float3> mapping_attribute = component.attribute_get_for_read<float3>(
|
||||
mapping_name, result_domain, {0, 0, 0});
|
||||
|
||||
MutableSpan<ColorGeometry4f> colors = attribute_out.as_span();
|
||||
|
||||
@@ -106,9 +106,9 @@ static void separate_attribute(GeometryComponent &component, const GeoNodeExecPa
|
||||
const AttributeDomain result_domain = get_result_domain(
|
||||
component, params, result_name_x, result_name_y, result_name_z);
|
||||
|
||||
GVArray_Typed<float3> attribute_input = params.get_input_attribute<float3>(
|
||||
VArray<float3> attribute_input = params.get_input_attribute<float3>(
|
||||
"Vector", component, result_domain, {0, 0, 0});
|
||||
VArray_Span<float3> input_span{*attribute_input};
|
||||
VArray_Span<float3> input_span{attribute_input};
|
||||
|
||||
OutputAttribute_Typed<float> attribute_result_x =
|
||||
component.attribute_try_get_for_output_only<float>(result_name_x, result_domain);
|
||||
|
||||
@@ -407,13 +407,13 @@ static void transfer_attribute_nearest(const GeometrySet &src_geometry,
|
||||
if (pointcloud_distances_sq[i] < mesh_distances_sq[i]) {
|
||||
/* Point-cloud point is closer. */
|
||||
const int index = pointcloud_indices[i];
|
||||
pointcloud_src_attribute.varray->get(index, buffer);
|
||||
pointcloud_src_attribute.varray.get(index, buffer);
|
||||
dst_attribute->set_by_relocate(i, buffer);
|
||||
}
|
||||
else {
|
||||
/* Mesh element is closer. */
|
||||
const int index = mesh_indices[i];
|
||||
mesh_src_attribute.varray->get(index, buffer);
|
||||
mesh_src_attribute.varray.get(index, buffer);
|
||||
dst_attribute->set_by_relocate(i, buffer);
|
||||
}
|
||||
}
|
||||
@@ -424,7 +424,7 @@ static void transfer_attribute_nearest(const GeometrySet &src_geometry,
|
||||
src_name, data_type);
|
||||
for (const int i : IndexRange(tot_samples)) {
|
||||
const int index = pointcloud_indices[i];
|
||||
src_attribute.varray->get(index, buffer);
|
||||
src_attribute.varray.get(index, buffer);
|
||||
dst_attribute->set_by_relocate(i, buffer);
|
||||
}
|
||||
}
|
||||
@@ -434,7 +434,7 @@ static void transfer_attribute_nearest(const GeometrySet &src_geometry,
|
||||
data_type);
|
||||
for (const int i : IndexRange(tot_samples)) {
|
||||
const int index = mesh_indices[i];
|
||||
src_attribute.varray->get(index, buffer);
|
||||
src_attribute.varray.get(index, buffer);
|
||||
dst_attribute->set_by_relocate(i, buffer);
|
||||
}
|
||||
}
|
||||
@@ -460,7 +460,7 @@ static void transfer_attribute(const GeoNodeExecParams ¶ms,
|
||||
const AttributeDomain dst_domain = (input_domain == ATTR_DOMAIN_AUTO) ? auto_domain :
|
||||
input_domain;
|
||||
|
||||
GVArray_Typed<float3> dst_positions = dst_component.attribute_get_for_read<float3>(
|
||||
VArray<float3> dst_positions = dst_component.attribute_get_for_read<float3>(
|
||||
"position", dst_domain, {0, 0, 0});
|
||||
|
||||
switch (mapping) {
|
||||
|
||||
@@ -187,7 +187,7 @@ static void geo_node_attribute_vector_math_update(bNodeTree *UNUSED(ntree), bNod
|
||||
|
||||
static void do_math_operation_fl3_fl3_to_fl3(const VArray<float3> &input_a,
|
||||
const VArray<float3> &input_b,
|
||||
VMutableArray<float3> &result,
|
||||
const VMutableArray<float3> &result,
|
||||
const NodeVectorMathOperation operation)
|
||||
{
|
||||
const int size = input_a.size();
|
||||
@@ -218,7 +218,7 @@ static void do_math_operation_fl3_fl3_to_fl3(const VArray<float3> &input_a,
|
||||
static void do_math_operation_fl3_fl3_fl3_to_fl3(const VArray<float3> &input_a,
|
||||
const VArray<float3> &input_b,
|
||||
const VArray<float3> &input_c,
|
||||
VMutableArray<float3> &result,
|
||||
const VMutableArray<float3> &result,
|
||||
const NodeVectorMathOperation operation)
|
||||
{
|
||||
const int size = input_a.size();
|
||||
@@ -251,7 +251,7 @@ static void do_math_operation_fl3_fl3_fl3_to_fl3(const VArray<float3> &input_a,
|
||||
static void do_math_operation_fl3_fl3_fl_to_fl3(const VArray<float3> &input_a,
|
||||
const VArray<float3> &input_b,
|
||||
const VArray<float> &input_c,
|
||||
VMutableArray<float3> &result,
|
||||
const VMutableArray<float3> &result,
|
||||
const NodeVectorMathOperation operation)
|
||||
{
|
||||
const int size = input_a.size();
|
||||
@@ -283,7 +283,7 @@ static void do_math_operation_fl3_fl3_fl_to_fl3(const VArray<float3> &input_a,
|
||||
|
||||
static void do_math_operation_fl3_fl3_to_fl(const VArray<float3> &input_a,
|
||||
const VArray<float3> &input_b,
|
||||
VMutableArray<float> &result,
|
||||
const VMutableArray<float> &result,
|
||||
const NodeVectorMathOperation operation)
|
||||
{
|
||||
const int size = input_a.size();
|
||||
@@ -313,7 +313,7 @@ static void do_math_operation_fl3_fl3_to_fl(const VArray<float3> &input_a,
|
||||
|
||||
static void do_math_operation_fl3_fl_to_fl3(const VArray<float3> &input_a,
|
||||
const VArray<float> &input_b,
|
||||
VMutableArray<float3> &result,
|
||||
const VMutableArray<float3> &result,
|
||||
const NodeVectorMathOperation operation)
|
||||
{
|
||||
const int size = input_a.size();
|
||||
@@ -342,7 +342,7 @@ static void do_math_operation_fl3_fl_to_fl3(const VArray<float3> &input_a,
|
||||
}
|
||||
|
||||
static void do_math_operation_fl3_to_fl3(const VArray<float3> &input_a,
|
||||
VMutableArray<float3> &result,
|
||||
const VMutableArray<float3> &result,
|
||||
const NodeVectorMathOperation operation)
|
||||
{
|
||||
const int size = input_a.size();
|
||||
@@ -369,7 +369,7 @@ static void do_math_operation_fl3_to_fl3(const VArray<float3> &input_a,
|
||||
}
|
||||
|
||||
static void do_math_operation_fl3_to_fl(const VArray<float3> &input_a,
|
||||
VMutableArray<float> &result,
|
||||
const VMutableArray<float> &result,
|
||||
const NodeVectorMathOperation operation)
|
||||
{
|
||||
const int size = input_a.size();
|
||||
@@ -437,13 +437,13 @@ static void attribute_vector_math_calc(GeometryComponent &component,
|
||||
const AttributeDomain result_domain = get_result_domain(
|
||||
component, params, operation, result_name);
|
||||
|
||||
GVArrayPtr attribute_a = params.get_input_attribute(
|
||||
GVArray attribute_a = params.get_input_attribute(
|
||||
"A", component, result_domain, read_type_a, nullptr);
|
||||
if (!attribute_a) {
|
||||
return;
|
||||
}
|
||||
GVArrayPtr attribute_b;
|
||||
GVArrayPtr attribute_c;
|
||||
GVArray attribute_b;
|
||||
GVArray attribute_c;
|
||||
if (use_input_b) {
|
||||
attribute_b = params.get_input_attribute("B", component, result_domain, read_type_b, nullptr);
|
||||
if (!attribute_b) {
|
||||
@@ -476,26 +476,26 @@ static void attribute_vector_math_calc(GeometryComponent &component,
|
||||
case NODE_VECTOR_MATH_MODULO:
|
||||
case NODE_VECTOR_MATH_MINIMUM:
|
||||
case NODE_VECTOR_MATH_MAXIMUM:
|
||||
do_math_operation_fl3_fl3_to_fl3(attribute_a->typed<float3>(),
|
||||
attribute_b->typed<float3>(),
|
||||
attribute_result->typed<float3>(),
|
||||
do_math_operation_fl3_fl3_to_fl3(attribute_a.typed<float3>(),
|
||||
attribute_b.typed<float3>(),
|
||||
attribute_result.varray().typed<float3>(),
|
||||
operation);
|
||||
break;
|
||||
case NODE_VECTOR_MATH_DOT_PRODUCT:
|
||||
case NODE_VECTOR_MATH_DISTANCE:
|
||||
do_math_operation_fl3_fl3_to_fl(attribute_a->typed<float3>(),
|
||||
attribute_b->typed<float3>(),
|
||||
attribute_result->typed<float>(),
|
||||
do_math_operation_fl3_fl3_to_fl(attribute_a.typed<float3>(),
|
||||
attribute_b.typed<float3>(),
|
||||
attribute_result.varray().typed<float>(),
|
||||
operation);
|
||||
break;
|
||||
case NODE_VECTOR_MATH_LENGTH:
|
||||
do_math_operation_fl3_to_fl(
|
||||
attribute_a->typed<float3>(), attribute_result->typed<float>(), operation);
|
||||
attribute_a.typed<float3>(), attribute_result.varray().typed<float>(), operation);
|
||||
break;
|
||||
case NODE_VECTOR_MATH_SCALE:
|
||||
do_math_operation_fl3_fl_to_fl3(attribute_a->typed<float3>(),
|
||||
attribute_b->typed<float>(),
|
||||
attribute_result->typed<float3>(),
|
||||
do_math_operation_fl3_fl_to_fl3(attribute_a.typed<float3>(),
|
||||
attribute_b.typed<float>(),
|
||||
attribute_result.varray().typed<float3>(),
|
||||
operation);
|
||||
break;
|
||||
case NODE_VECTOR_MATH_NORMALIZE:
|
||||
@@ -507,22 +507,22 @@ static void attribute_vector_math_calc(GeometryComponent &component,
|
||||
case NODE_VECTOR_MATH_COSINE:
|
||||
case NODE_VECTOR_MATH_TANGENT:
|
||||
do_math_operation_fl3_to_fl3(
|
||||
attribute_a->typed<float3>(), attribute_result->typed<float3>(), operation);
|
||||
attribute_a.typed<float3>(), attribute_result.varray().typed<float3>(), operation);
|
||||
break;
|
||||
case NODE_VECTOR_MATH_WRAP:
|
||||
case NODE_VECTOR_MATH_FACEFORWARD:
|
||||
case NODE_VECTOR_MATH_MULTIPLY_ADD:
|
||||
do_math_operation_fl3_fl3_fl3_to_fl3(attribute_a->typed<float3>(),
|
||||
attribute_b->typed<float3>(),
|
||||
attribute_c->typed<float3>(),
|
||||
attribute_result->typed<float3>(),
|
||||
do_math_operation_fl3_fl3_fl3_to_fl3(attribute_a.typed<float3>(),
|
||||
attribute_b.typed<float3>(),
|
||||
attribute_c.typed<float3>(),
|
||||
attribute_result.varray().typed<float3>(),
|
||||
operation);
|
||||
break;
|
||||
case NODE_VECTOR_MATH_REFRACT:
|
||||
do_math_operation_fl3_fl3_fl_to_fl3(attribute_a->typed<float3>(),
|
||||
attribute_b->typed<float3>(),
|
||||
attribute_c->typed<float>(),
|
||||
attribute_result->typed<float3>(),
|
||||
do_math_operation_fl3_fl3_fl_to_fl3(attribute_a.typed<float3>(),
|
||||
attribute_b.typed<float3>(),
|
||||
attribute_c.typed<float>(),
|
||||
attribute_result.varray().typed<float3>(),
|
||||
operation);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -220,12 +220,12 @@ static void execute_on_component(const GeoNodeExecParams ¶ms, GeometryCompon
|
||||
const AttributeDomain result_domain = get_result_domain(component, params, result_name);
|
||||
const bool invert = params.get_input<bool>("Invert");
|
||||
|
||||
GVArrayPtr attribute_vector = params.get_input_attribute(
|
||||
GVArray attribute_vector = params.get_input_attribute(
|
||||
"Vector", component, result_domain, CD_PROP_FLOAT3, nullptr);
|
||||
if (!attribute_vector) {
|
||||
return;
|
||||
}
|
||||
GVArrayPtr attribute_center = params.get_input_attribute(
|
||||
GVArray attribute_center = params.get_input_attribute(
|
||||
"Center", component, result_domain, CD_PROP_FLOAT3, nullptr);
|
||||
if (!attribute_center) {
|
||||
return;
|
||||
@@ -238,21 +238,21 @@ static void execute_on_component(const GeoNodeExecParams ¶ms, GeometryCompon
|
||||
}
|
||||
|
||||
if (mode == GEO_NODE_VECTOR_ROTATE_TYPE_EULER_XYZ) {
|
||||
GVArrayPtr attribute_rotation = params.get_input_attribute(
|
||||
GVArray attribute_rotation = params.get_input_attribute(
|
||||
"Rotation", component, result_domain, CD_PROP_FLOAT3, nullptr);
|
||||
if (!attribute_rotation) {
|
||||
return;
|
||||
}
|
||||
do_vector_rotate_euler(attribute_vector->typed<float3>(),
|
||||
attribute_center->typed<float3>(),
|
||||
attribute_rotation->typed<float3>(),
|
||||
do_vector_rotate_euler(attribute_vector.typed<float3>(),
|
||||
attribute_center.typed<float3>(),
|
||||
attribute_rotation.typed<float3>(),
|
||||
attribute_result.as_span<float3>(),
|
||||
invert);
|
||||
attribute_result.save();
|
||||
return;
|
||||
}
|
||||
|
||||
GVArrayPtr attribute_angle = params.get_input_attribute(
|
||||
GVArray attribute_angle = params.get_input_attribute(
|
||||
"Angle", component, result_domain, CD_PROP_FLOAT, nullptr);
|
||||
if (!attribute_angle) {
|
||||
return;
|
||||
@@ -260,40 +260,40 @@ static void execute_on_component(const GeoNodeExecParams ¶ms, GeometryCompon
|
||||
|
||||
switch (mode) {
|
||||
case GEO_NODE_VECTOR_ROTATE_TYPE_AXIS: {
|
||||
GVArrayPtr attribute_axis = params.get_input_attribute(
|
||||
GVArray attribute_axis = params.get_input_attribute(
|
||||
"Axis", component, result_domain, CD_PROP_FLOAT3, nullptr);
|
||||
if (!attribute_axis) {
|
||||
return;
|
||||
}
|
||||
do_vector_rotate_around_axis(attribute_vector->typed<float3>(),
|
||||
attribute_center->typed<float3>(),
|
||||
attribute_axis->typed<float3>(),
|
||||
attribute_angle->typed<float>(),
|
||||
do_vector_rotate_around_axis(attribute_vector.typed<float3>(),
|
||||
attribute_center.typed<float3>(),
|
||||
attribute_axis.typed<float3>(),
|
||||
attribute_angle.typed<float>(),
|
||||
attribute_result.as_span<float3>(),
|
||||
invert);
|
||||
} break;
|
||||
case GEO_NODE_VECTOR_ROTATE_TYPE_AXIS_X:
|
||||
do_vector_rotate_around_fixed_axis(attribute_vector->typed<float3>(),
|
||||
attribute_center->typed<float3>(),
|
||||
do_vector_rotate_around_fixed_axis(attribute_vector.typed<float3>(),
|
||||
attribute_center.typed<float3>(),
|
||||
float3(1.0f, 0.0f, 0.0f),
|
||||
attribute_angle->typed<float>(),
|
||||
attribute_angle.typed<float>(),
|
||||
attribute_result.as_span<float3>(),
|
||||
invert);
|
||||
break;
|
||||
case GEO_NODE_VECTOR_ROTATE_TYPE_AXIS_Y:
|
||||
do_vector_rotate_around_fixed_axis(attribute_vector->typed<float3>(),
|
||||
attribute_center->typed<float3>(),
|
||||
do_vector_rotate_around_fixed_axis(attribute_vector.typed<float3>(),
|
||||
attribute_center.typed<float3>(),
|
||||
float3(0.0f, 1.0f, 0.0f),
|
||||
attribute_angle->typed<float>(),
|
||||
attribute_angle.typed<float>(),
|
||||
attribute_result.as_span<float3>(),
|
||||
invert);
|
||||
|
||||
break;
|
||||
case GEO_NODE_VECTOR_ROTATE_TYPE_AXIS_Z:
|
||||
do_vector_rotate_around_fixed_axis(attribute_vector->typed<float3>(),
|
||||
attribute_center->typed<float3>(),
|
||||
do_vector_rotate_around_fixed_axis(attribute_vector.typed<float3>(),
|
||||
attribute_center.typed<float3>(),
|
||||
float3(0.0f, 0.0f, 1.0f),
|
||||
attribute_angle->typed<float>(),
|
||||
attribute_angle.typed<float>(),
|
||||
attribute_result.as_span<float3>(),
|
||||
invert);
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ static void copy_spline_domain_attributes(const CurveComponent &curve_component,
|
||||
if (meta_data.domain != ATTR_DOMAIN_CURVE) {
|
||||
return true;
|
||||
}
|
||||
GVArrayPtr spline_attribute = curve_component.attribute_get_for_read(
|
||||
GVArray spline_attribute = curve_component.attribute_get_for_read(
|
||||
attribute_id, ATTR_DOMAIN_CURVE, meta_data.data_type);
|
||||
|
||||
OutputAttribute result_attribute = points.attribute_try_get_for_output_only(
|
||||
@@ -70,7 +70,7 @@ static void copy_spline_domain_attributes(const CurveComponent &curve_component,
|
||||
|
||||
/* Only copy the attributes of splines in the offsets. */
|
||||
for (const int i : offsets.index_range()) {
|
||||
spline_attribute->get(offsets[i], result[i]);
|
||||
spline_attribute.get(offsets[i], result[i]);
|
||||
}
|
||||
|
||||
result_attribute.save();
|
||||
@@ -130,7 +130,7 @@ static void copy_endpoint_attributes(Span<SplinePtr> splines,
|
||||
|
||||
BLI_assert(spline.attributes.get_for_read(attribute_id));
|
||||
GSpan spline_span = *spline.attributes.get_for_read(attribute_id);
|
||||
blender::fn::GVArray_For_GSpan(spline_span).get(0, point_span[i]);
|
||||
spline_span.type().copy_assign(spline_span[0], point_span[i]);
|
||||
}
|
||||
|
||||
for (const auto item : end_data.point_attributes.items()) {
|
||||
@@ -139,7 +139,7 @@ static void copy_endpoint_attributes(Span<SplinePtr> splines,
|
||||
|
||||
BLI_assert(spline.attributes.get_for_read(attribute_id));
|
||||
GSpan spline_span = *spline.attributes.get_for_read(attribute_id);
|
||||
blender::fn::GVArray_For_GSpan(spline_span).get(spline.size() - 1, point_span[i]);
|
||||
spline_span.type().copy_assign(spline_span[spline.size() - 1], point_span[i]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -44,7 +44,7 @@ static void geo_node_curve_reverse_exec(GeoNodeExecParams params)
|
||||
MutableSpan<SplinePtr> splines = curve.splines();
|
||||
|
||||
const std::string selection_name = params.extract_input<std::string>("Selection");
|
||||
GVArray_Typed<bool> selection = curve_component.attribute_get_for_read(
|
||||
VArray<bool> selection = curve_component.attribute_get_for_read(
|
||||
selection_name, ATTR_DOMAIN_CURVE, true);
|
||||
|
||||
threading::parallel_for(splines.index_range(), 128, [&](IndexRange range) {
|
||||
|
||||
@@ -84,7 +84,7 @@ static void geo_node_curve_set_handles_exec(GeoNodeExecParams params)
|
||||
MutableSpan<SplinePtr> splines = curve.splines();
|
||||
|
||||
const std::string selection_name = params.extract_input<std::string>("Selection");
|
||||
GVArray_Typed<bool> selection = curve_component.attribute_get_for_read(
|
||||
VArray<bool> selection = curve_component.attribute_get_for_read(
|
||||
selection_name, ATTR_DOMAIN_POINT, true);
|
||||
|
||||
const BezierSpline::HandleType new_handle_type = handle_type_from_input_type(type);
|
||||
|
||||
@@ -255,7 +255,7 @@ static void geo_node_legacy_curve_spline_type_exec(GeoNodeExecParams params)
|
||||
const CurveEval &curve = *curve_component->get_for_read();
|
||||
|
||||
const std::string selection_name = params.extract_input<std::string>("Selection");
|
||||
GVArray_Typed<bool> selection = curve_component->attribute_get_for_read(
|
||||
VArray<bool> selection = curve_component->attribute_get_for_read(
|
||||
selection_name, ATTR_DOMAIN_CURVE, true);
|
||||
|
||||
std::unique_ptr<CurveEval> new_curve = std::make_unique<CurveEval>();
|
||||
|
||||
@@ -25,10 +25,6 @@
|
||||
|
||||
#include "node_geometry_util.hh"
|
||||
|
||||
using blender::fn::GVArray_For_GSpan;
|
||||
using blender::fn::GVArray_For_Span;
|
||||
using blender::fn::GVArray_Typed;
|
||||
|
||||
namespace blender::nodes {
|
||||
|
||||
static void geo_node_curve_subdivide_declare(NodeDeclarationBuilder &b)
|
||||
@@ -363,14 +359,13 @@ static void geo_node_subdivide_exec(GeoNodeExecParams params)
|
||||
}
|
||||
|
||||
const CurveComponent &component = *geometry_set.get_component_for_read<CurveComponent>();
|
||||
GVArray_Typed<int> cuts = params.get_input_attribute<int>(
|
||||
"Cuts", component, ATTR_DOMAIN_POINT, 0);
|
||||
if (cuts->is_single() && cuts->get_internal_single() < 1) {
|
||||
VArray<int> cuts = params.get_input_attribute<int>("Cuts", component, ATTR_DOMAIN_POINT, 0);
|
||||
if (cuts.is_single() && cuts.get_internal_single() < 1) {
|
||||
params.set_output("Geometry", geometry_set);
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_ptr<CurveEval> output_curve = subdivide_curve(*component.get_for_read(), *cuts);
|
||||
std::unique_ptr<CurveEval> output_curve = subdivide_curve(*component.get_for_read(), cuts);
|
||||
|
||||
params.set_output("Geometry", GeometrySet::create_with_curve(output_curve.release()));
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ static GMutableSpan create_attribute_and_retrieve_span(PointCloudComponent &poin
|
||||
points.attribute_try_create(attribute_id, ATTR_DOMAIN_POINT, data_type, AttributeInitDefault());
|
||||
WriteAttributeLookup attribute = points.attribute_try_get_for_write(attribute_id);
|
||||
BLI_assert(attribute);
|
||||
return attribute.varray->get_internal_span();
|
||||
return attribute.varray.get_internal_span();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -177,8 +177,8 @@ static void copy_evaluated_point_attributes(Span<SplinePtr> splines,
|
||||
const int size = offsets[i + 1] - offsets[i];
|
||||
|
||||
data.positions.slice(offset, size).copy_from(spline.evaluated_positions());
|
||||
spline.interpolate_to_evaluated(spline.radii())->materialize(data.radii.slice(offset, size));
|
||||
spline.interpolate_to_evaluated(spline.tilts())->materialize(data.tilts.slice(offset, size));
|
||||
spline.interpolate_to_evaluated(spline.radii()).materialize(data.radii.slice(offset, size));
|
||||
spline.interpolate_to_evaluated(spline.tilts()).materialize(data.tilts.slice(offset, size));
|
||||
|
||||
for (const Map<AttributeIDRef, GMutableSpan>::Item item : data.point_attributes.items()) {
|
||||
const AttributeIDRef attribute_id = item.key;
|
||||
@@ -188,7 +188,7 @@ static void copy_evaluated_point_attributes(Span<SplinePtr> splines,
|
||||
GSpan spline_span = *spline.attributes.get_for_read(attribute_id);
|
||||
|
||||
spline.interpolate_to_evaluated(spline_span)
|
||||
->materialize(point_span.slice(offset, size).data());
|
||||
.materialize(point_span.slice(offset, size).data());
|
||||
}
|
||||
|
||||
data.tangents.slice(offset, size).copy_from(spline.evaluated_tangents());
|
||||
@@ -230,7 +230,7 @@ static void copy_uniform_sample_point_attributes(Span<SplinePtr> splines,
|
||||
BLI_assert(spline.attributes.get_for_read(attribute_id));
|
||||
GSpan spline_span = *spline.attributes.get_for_read(attribute_id);
|
||||
|
||||
spline.sample_with_index_factors(*spline.interpolate_to_evaluated(spline_span),
|
||||
spline.sample_with_index_factors(spline.interpolate_to_evaluated(spline_span),
|
||||
uniform_samples,
|
||||
point_span.slice(offset, size));
|
||||
}
|
||||
@@ -263,20 +263,20 @@ static void copy_spline_domain_attributes(const CurveComponent &curve_component,
|
||||
if (meta_data.domain != ATTR_DOMAIN_CURVE) {
|
||||
return true;
|
||||
}
|
||||
GVArrayPtr spline_attribute = curve_component.attribute_get_for_read(
|
||||
GVArray spline_attribute = curve_component.attribute_get_for_read(
|
||||
attribute_id, ATTR_DOMAIN_CURVE, meta_data.data_type);
|
||||
const CPPType &type = spline_attribute->type();
|
||||
const CPPType &type = spline_attribute.type();
|
||||
|
||||
OutputAttribute result_attribute = points.attribute_try_get_for_output_only(
|
||||
attribute_id, ATTR_DOMAIN_POINT, meta_data.data_type);
|
||||
GMutableSpan result = result_attribute.as_span();
|
||||
|
||||
for (const int i : IndexRange(spline_attribute->size())) {
|
||||
for (const int i : spline_attribute.index_range()) {
|
||||
const int offset = offsets[i];
|
||||
const int size = offsets[i + 1] - offsets[i];
|
||||
if (size != 0) {
|
||||
BUFFER_FOR_CPP_TYPE_VALUE(type, buffer);
|
||||
spline_attribute->get(i, buffer);
|
||||
spline_attribute.get(i, buffer);
|
||||
type.fill_assign_n(buffer, result[offset], size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ static std::unique_ptr<CurveEval> curve_delete(const CurveEval &input_curve,
|
||||
Vector<int64_t> copied_splines;
|
||||
|
||||
if (input_curve.attributes.get_for_read(name)) {
|
||||
GVArray_Typed<bool> selection = input_curve.attributes.get_for_read<bool>(name, false);
|
||||
VArray<bool> selection = input_curve.attributes.get_for_read<bool>(name, false);
|
||||
for (const int i : input_splines.index_range()) {
|
||||
if (selection[i] == invert) {
|
||||
output_curve->add_spline(input_splines[i]->copy());
|
||||
@@ -151,7 +151,7 @@ static std::unique_ptr<CurveEval> curve_delete(const CurveEval &input_curve,
|
||||
|
||||
for (const int i : input_splines.index_range()) {
|
||||
const Spline &spline = *input_splines[i];
|
||||
GVArray_Typed<bool> selection = spline.attributes.get_for_read<bool>(name, false);
|
||||
VArray<bool> selection = spline.attributes.get_for_read<bool>(name, false);
|
||||
|
||||
indices_to_copy.clear();
|
||||
for (const int i_point : IndexRange(spline.size())) {
|
||||
@@ -202,7 +202,7 @@ static void delete_point_cloud_selection(const PointCloudComponent &in_component
|
||||
const StringRef selection_name,
|
||||
const bool invert)
|
||||
{
|
||||
const GVArray_Typed<bool> selection_attribute = in_component.attribute_get_for_read<bool>(
|
||||
const VArray<bool> selection_attribute = in_component.attribute_get_for_read<bool>(
|
||||
selection_name, ATTR_DOMAIN_POINT, false);
|
||||
VArray_Span<bool> selection{selection_attribute};
|
||||
|
||||
@@ -590,7 +590,7 @@ static void delete_mesh_selection(MeshComponent &component,
|
||||
const AttributeDomain selection_domain = get_mesh_selection_domain(component, selection_name);
|
||||
|
||||
/* This already checks if the attribute exists, and displays a warning in that case. */
|
||||
GVArray_Typed<bool> selection = component.attribute_get_for_read<bool>(
|
||||
VArray<bool> selection = component.attribute_get_for_read<bool>(
|
||||
selection_name, selection_domain, false);
|
||||
|
||||
/* Check if there is anything to delete. */
|
||||
|
||||
@@ -72,7 +72,7 @@ static void geo_node_legacy_material_assign_exec(GeoNodeExecParams params)
|
||||
MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>();
|
||||
Mesh *mesh = mesh_component.get_for_write();
|
||||
if (mesh != nullptr) {
|
||||
GVArray_Typed<bool> face_mask = mesh_component.attribute_get_for_read<bool>(
|
||||
VArray<bool> face_mask = mesh_component.attribute_get_for_read<bool>(
|
||||
mask_name, ATTR_DOMAIN_FACE, true);
|
||||
assign_material_to_faces(*mesh, face_mask, material);
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ static void geo_node_legacy_mesh_to_curve_exec(GeoNodeExecParams params)
|
||||
params.error_message_add(NodeWarningType::Error,
|
||||
TIP_("No attribute with name \"") + selection_name + "\"");
|
||||
}
|
||||
GVArray_Typed<bool> selection = component.attribute_get_for_read<bool>(
|
||||
VArray<bool> selection = component.attribute_get_for_read<bool>(
|
||||
selection_name, ATTR_DOMAIN_EDGE, true);
|
||||
|
||||
Vector<int64_t> selected_edge_indices;
|
||||
|
||||
@@ -106,9 +106,9 @@ static void sample_mesh_surface(const Mesh &mesh,
|
||||
|
||||
float looptri_density_factor = 1.0f;
|
||||
if (density_factors != nullptr) {
|
||||
const float v0_density_factor = std::max(0.0f, density_factors->get(v0_loop));
|
||||
const float v1_density_factor = std::max(0.0f, density_factors->get(v1_loop));
|
||||
const float v2_density_factor = std::max(0.0f, density_factors->get(v2_loop));
|
||||
const float v0_density_factor = std::max(0.0f, (*density_factors)[v0_loop]);
|
||||
const float v1_density_factor = std::max(0.0f, (*density_factors)[v1_loop]);
|
||||
const float v2_density_factor = std::max(0.0f, (*density_factors)[v2_loop]);
|
||||
looptri_density_factor = (v0_density_factor + v1_density_factor + v2_density_factor) / 3.0f;
|
||||
}
|
||||
const float area = area_tri_v3(v0_pos, v1_pos, v2_pos);
|
||||
@@ -315,7 +315,7 @@ BLI_NOINLINE static void interpolate_existing_attributes(
|
||||
}
|
||||
|
||||
const AttributeDomain source_domain = attribute_info->domain;
|
||||
GVArrayPtr source_attribute = source_component.attribute_get_for_read(
|
||||
GVArray source_attribute = source_component.attribute_get_for_read(
|
||||
attribute_id, source_domain, output_data_type, nullptr);
|
||||
if (!source_attribute) {
|
||||
i_instance += set_group.transforms.size();
|
||||
@@ -329,7 +329,7 @@ BLI_NOINLINE static void interpolate_existing_attributes(
|
||||
|
||||
GMutableSpan instance_span = out_span.slice(offset, bary_coords.size());
|
||||
interpolate_attribute(
|
||||
mesh, bary_coords, looptri_indices, source_domain, *source_attribute, instance_span);
|
||||
mesh, bary_coords, looptri_indices, source_domain, source_attribute, instance_span);
|
||||
|
||||
i_instance++;
|
||||
}
|
||||
@@ -337,7 +337,7 @@ BLI_NOINLINE static void interpolate_existing_attributes(
|
||||
attribute_math::convert_to_static_type(output_data_type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
|
||||
GVArray_Span<T> source_span{*source_attribute};
|
||||
VArray_Span source_span{source_attribute.typed<T>()};
|
||||
});
|
||||
}
|
||||
|
||||
@@ -445,7 +445,7 @@ static void distribute_points_random(Span<GeometryInstanceGroup> set_groups,
|
||||
for (const GeometryInstanceGroup &set_group : set_groups) {
|
||||
const GeometrySet &set = set_group.geometry_set;
|
||||
const MeshComponent &component = *set.get_component_for_read<MeshComponent>();
|
||||
GVArray_Typed<float> density_factors = component.attribute_get_for_read<float>(
|
||||
VArray<float> density_factors = component.attribute_get_for_read<float>(
|
||||
density_attribute_name, ATTR_DOMAIN_CORNER, use_one_default ? 1.0f : 0.0f);
|
||||
const Mesh &mesh = *component.get_for_read();
|
||||
for (const float4x4 &transform : set_group.transforms) {
|
||||
@@ -455,7 +455,7 @@ static void distribute_points_random(Span<GeometryInstanceGroup> set_groups,
|
||||
sample_mesh_surface(mesh,
|
||||
transform,
|
||||
density,
|
||||
&*density_factors,
|
||||
&density_factors,
|
||||
seed,
|
||||
positions,
|
||||
bary_coords,
|
||||
@@ -514,7 +514,7 @@ static void distribute_points_poisson_disk(Span<GeometryInstanceGroup> set_group
|
||||
const GeometrySet &set = set_group.geometry_set;
|
||||
const MeshComponent &component = *set.get_component_for_read<MeshComponent>();
|
||||
const Mesh &mesh = *component.get_for_read();
|
||||
const GVArray_Typed<float> density_factors = component.attribute_get_for_read<float>(
|
||||
const VArray<float> density_factors = component.attribute_get_for_read<float>(
|
||||
density_attribute_name, ATTR_DOMAIN_CORNER, use_one_default ? 1.0f : 0.0f);
|
||||
|
||||
for (const int UNUSED(i_set_instance) : set_group.transforms.index_range()) {
|
||||
|
||||
@@ -171,13 +171,12 @@ static void add_instances_from_component(InstancesComponent &instances,
|
||||
|
||||
const int domain_size = src_geometry.attribute_domain_size(domain);
|
||||
|
||||
GVArray_Typed<float3> positions = src_geometry.attribute_get_for_read<float3>(
|
||||
VArray<float3> positions = src_geometry.attribute_get_for_read<float3>(
|
||||
"position", domain, {0, 0, 0});
|
||||
GVArray_Typed<float3> rotations = src_geometry.attribute_get_for_read<float3>(
|
||||
VArray<float3> rotations = src_geometry.attribute_get_for_read<float3>(
|
||||
"rotation", domain, {0, 0, 0});
|
||||
GVArray_Typed<float3> scales = src_geometry.attribute_get_for_read<float3>(
|
||||
"scale", domain, {1, 1, 1});
|
||||
GVArray_Typed<int> id_attribute = src_geometry.attribute_get_for_read<int>("id", domain, -1);
|
||||
VArray<float3> scales = src_geometry.attribute_get_for_read<float3>("scale", domain, {1, 1, 1});
|
||||
VArray<int> id_attribute = src_geometry.attribute_get_for_read<int>("id", domain, -1);
|
||||
|
||||
/* The initial size of the component might be non-zero if there are two component types. */
|
||||
const int start_len = instances.instances_amount();
|
||||
|
||||
@@ -169,9 +169,9 @@ static void point_rotate_on_component(GeometryComponent &component,
|
||||
const int domain_size = rotations.size();
|
||||
|
||||
if (storage.type == GEO_NODE_POINT_ROTATE_TYPE_AXIS_ANGLE) {
|
||||
GVArray_Typed<float3> axis = params.get_input_attribute<float3>(
|
||||
VArray<float3> axis = params.get_input_attribute<float3>(
|
||||
"Axis", component, ATTR_DOMAIN_POINT, {0, 0, 1});
|
||||
GVArray_Typed<float> angles = params.get_input_attribute<float>(
|
||||
VArray<float> angles = params.get_input_attribute<float>(
|
||||
"Angle", component, ATTR_DOMAIN_POINT, 0);
|
||||
|
||||
if (storage.space == GEO_NODE_POINT_ROTATE_SPACE_OBJECT) {
|
||||
@@ -182,7 +182,7 @@ static void point_rotate_on_component(GeometryComponent &component,
|
||||
}
|
||||
}
|
||||
else {
|
||||
GVArray_Typed<float3> eulers = params.get_input_attribute<float3>(
|
||||
VArray<float3> eulers = params.get_input_attribute<float3>(
|
||||
"Rotation", component, ATTR_DOMAIN_POINT, {0, 0, 0});
|
||||
|
||||
if (storage.space == GEO_NODE_POINT_ROTATE_SPACE_OBJECT) {
|
||||
|
||||
@@ -78,7 +78,7 @@ static void execute_on_component(GeoNodeExecParams params, GeometryComponent &co
|
||||
const CustomDataType data_type = (input_type == GEO_NODE_ATTRIBUTE_INPUT_FLOAT) ? CD_PROP_FLOAT :
|
||||
CD_PROP_FLOAT3;
|
||||
|
||||
GVArrayPtr attribute = params.get_input_attribute(
|
||||
GVArray attribute = params.get_input_attribute(
|
||||
"Factor", component, ATTR_DOMAIN_POINT, data_type, nullptr);
|
||||
if (!attribute) {
|
||||
return;
|
||||
@@ -86,13 +86,13 @@ static void execute_on_component(GeoNodeExecParams params, GeometryComponent &co
|
||||
|
||||
MutableSpan<float3> scale_span = scale_attribute.as_span();
|
||||
if (data_type == CD_PROP_FLOAT) {
|
||||
GVArray_Typed<float> factors{*attribute};
|
||||
VArray<float> factors = attribute.typed<float>();
|
||||
for (const int i : scale_span.index_range()) {
|
||||
scale_span[i] = scale_span[i] * factors[i];
|
||||
}
|
||||
}
|
||||
else if (data_type == CD_PROP_FLOAT3) {
|
||||
GVArray_Typed<float3> factors{*attribute};
|
||||
VArray<float3> factors = attribute.typed<float3>();
|
||||
for (const int i : scale_span.index_range()) {
|
||||
scale_span[i] = scale_span[i] * factors[i];
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ void copy_point_attributes_based_on_mask(const GeometryComponent &in_component,
|
||||
{
|
||||
for (const AttributeIDRef &attribute_id : in_component.attribute_ids()) {
|
||||
ReadAttributeLookup attribute = in_component.attribute_try_get_for_read(attribute_id);
|
||||
const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray->type());
|
||||
const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type());
|
||||
|
||||
/* Only copy point attributes. Theoretically this could interpolate attributes on other
|
||||
* domains to the point domain, but that would conflict with attributes that are built-in
|
||||
@@ -69,7 +69,7 @@ void copy_point_attributes_based_on_mask(const GeometryComponent &in_component,
|
||||
|
||||
attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
GVArray_Span<T> span{*attribute.varray};
|
||||
VArray_Span span{attribute.varray.typed<T>()};
|
||||
MutableSpan<T> out_span = result_attribute.as_span<T>();
|
||||
copy_data_based_on_mask(span, masks, invert, out_span);
|
||||
});
|
||||
@@ -103,7 +103,7 @@ static void separate_points_from_component(const GeometryComponent &in_component
|
||||
return;
|
||||
}
|
||||
|
||||
const GVArray_Typed<bool> mask_attribute = in_component.attribute_get_for_read<bool>(
|
||||
const VArray<bool> mask_attribute = in_component.attribute_get_for_read<bool>(
|
||||
mask_name, ATTR_DOMAIN_POINT, false);
|
||||
VArray_Span<bool> masks{mask_attribute};
|
||||
|
||||
|
||||
@@ -43,10 +43,10 @@ static void execute_on_component(GeoNodeExecParams params, GeometryComponent &co
|
||||
if (!position_attribute) {
|
||||
return;
|
||||
}
|
||||
GVArray_Typed<float3> attribute = params.get_input_attribute<float3>(
|
||||
VArray<float3> attribute = params.get_input_attribute<float3>(
|
||||
"Translation", component, ATTR_DOMAIN_POINT, {0, 0, 0});
|
||||
|
||||
for (const int i : IndexRange(attribute.size())) {
|
||||
for (const int i : attribute.index_range()) {
|
||||
position_attribute->set(i, position_attribute->get(i) + attribute[i]);
|
||||
}
|
||||
|
||||
|
||||
@@ -172,12 +172,12 @@ static void gather_point_data_from_component(const GeoNodeExecParams ¶ms,
|
||||
Vector<float3> &r_positions,
|
||||
Vector<float> &r_radii)
|
||||
{
|
||||
GVArray_Typed<float3> positions = component.attribute_get_for_read<float3>(
|
||||
VArray<float3> positions = component.attribute_get_for_read<float3>(
|
||||
"position", ATTR_DOMAIN_POINT, {0, 0, 0});
|
||||
GVArray_Typed<float> radii = params.get_input_attribute<float>(
|
||||
VArray<float> radii = params.get_input_attribute<float>(
|
||||
"Radius", component, ATTR_DOMAIN_POINT, 0.0f);
|
||||
|
||||
for (const int i : IndexRange(positions.size())) {
|
||||
for (const int i : positions.index_range()) {
|
||||
r_positions.append(positions[i]);
|
||||
r_radii.append(radii[i]);
|
||||
}
|
||||
|
||||
@@ -197,11 +197,11 @@ static void raycast_from_points(const GeoNodeExecParams ¶ms,
|
||||
(GeometryNodeRaycastMapMode)storage.mapping);
|
||||
const AttributeDomain result_domain = ATTR_DOMAIN_POINT;
|
||||
|
||||
GVArray_Typed<float3> ray_origins = dst_component.attribute_get_for_read<float3>(
|
||||
VArray<float3> ray_origins = dst_component.attribute_get_for_read<float3>(
|
||||
"position", result_domain, {0, 0, 0});
|
||||
GVArray_Typed<float3> ray_directions = params.get_input_attribute<float3>(
|
||||
VArray<float3> ray_directions = params.get_input_attribute<float3>(
|
||||
"Ray Direction", dst_component, result_domain, {0, 0, 0});
|
||||
GVArray_Typed<float> ray_lengths = params.get_input_attribute<float>(
|
||||
VArray<float> ray_lengths = params.get_input_attribute<float>(
|
||||
"Ray Length", dst_component, result_domain, 0);
|
||||
|
||||
OutputAttribute_Typed<bool> hit_attribute =
|
||||
@@ -218,10 +218,10 @@ static void raycast_from_points(const GeoNodeExecParams ¶ms,
|
||||
Array<int> hit_indices;
|
||||
Array<float3> hit_positions_internal;
|
||||
if (!hit_attribute_names.is_empty()) {
|
||||
hit_indices.reinitialize(ray_origins->size());
|
||||
hit_indices.reinitialize(ray_origins.size());
|
||||
|
||||
if (!hit_position_attribute) {
|
||||
hit_positions_internal.reinitialize(ray_origins->size());
|
||||
hit_positions_internal.reinitialize(ray_origins.size());
|
||||
}
|
||||
}
|
||||
const MutableSpan<bool> is_hit = hit_attribute ? hit_attribute.as_span() : MutableSpan<bool>();
|
||||
|
||||
@@ -169,10 +169,10 @@ static Mesh *compute_hull(const GeometrySet &geometry_set)
|
||||
span_count++;
|
||||
const PointCloudComponent *component =
|
||||
geometry_set.get_component_for_read<PointCloudComponent>();
|
||||
GVArray_Typed<float3> varray = component->attribute_get_for_read<float3>(
|
||||
VArray<float3> varray = component->attribute_get_for_read<float3>(
|
||||
"position", ATTR_DOMAIN_POINT, {0, 0, 0});
|
||||
total_size += varray->size();
|
||||
positions_span = varray->get_internal_span();
|
||||
total_size += varray.size();
|
||||
positions_span = varray.get_internal_span();
|
||||
}
|
||||
|
||||
if (geometry_set.has_curve()) {
|
||||
@@ -200,18 +200,18 @@ static Mesh *compute_hull(const GeometrySet &geometry_set)
|
||||
|
||||
if (geometry_set.has_mesh()) {
|
||||
const MeshComponent *component = geometry_set.get_component_for_read<MeshComponent>();
|
||||
GVArray_Typed<float3> varray = component->attribute_get_for_read<float3>(
|
||||
VArray<float3> varray = component->attribute_get_for_read<float3>(
|
||||
"position", ATTR_DOMAIN_POINT, {0, 0, 0});
|
||||
varray->materialize(positions.as_mutable_span().slice(offset, varray.size()));
|
||||
varray.materialize(positions.as_mutable_span().slice(offset, varray.size()));
|
||||
offset += varray.size();
|
||||
}
|
||||
|
||||
if (geometry_set.has_pointcloud()) {
|
||||
const PointCloudComponent *component =
|
||||
geometry_set.get_component_for_read<PointCloudComponent>();
|
||||
GVArray_Typed<float3> varray = component->attribute_get_for_read<float3>(
|
||||
VArray<float3> varray = component->attribute_get_for_read<float3>(
|
||||
"position", ATTR_DOMAIN_POINT, {0, 0, 0});
|
||||
varray->materialize(positions.as_mutable_span().slice(offset, varray.size()));
|
||||
varray.materialize(positions.as_mutable_span().slice(offset, varray.size()));
|
||||
offset += varray.size();
|
||||
}
|
||||
|
||||
@@ -235,16 +235,16 @@ static void read_positions(const GeometryComponent &component,
|
||||
Span<float4x4> transforms,
|
||||
Vector<float3> *r_coords)
|
||||
{
|
||||
GVArray_Typed<float3> positions = component.attribute_get_for_read<float3>(
|
||||
VArray<float3> positions = component.attribute_get_for_read<float3>(
|
||||
"position", ATTR_DOMAIN_POINT, {0, 0, 0});
|
||||
|
||||
/* NOTE: could use convex hull operation here to
|
||||
* cut out some vertices, before accumulating,
|
||||
* but can also be done by the user beforehand. */
|
||||
|
||||
r_coords->reserve(r_coords->size() + positions.size() * transforms.size());
|
||||
r_coords->reserve(r_coords->size() + positions->size() * transforms.size());
|
||||
for (const float4x4 &transform : transforms) {
|
||||
for (const int i : positions.index_range()) {
|
||||
for (const int i : positions->index_range()) {
|
||||
const float3 position = positions[i];
|
||||
const float3 transformed_position = transform * position;
|
||||
r_coords->append(transformed_position);
|
||||
|
||||
@@ -64,9 +64,9 @@ class EndpointFieldInput final : public fn::FieldInput {
|
||||
category_ = Category::Generated;
|
||||
}
|
||||
|
||||
const GVArray *get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask UNUSED(mask),
|
||||
ResourceScope &scope) const final
|
||||
GVArray get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask UNUSED(mask),
|
||||
ResourceScope &UNUSED(scope)) const final
|
||||
{
|
||||
if (const GeometryComponentFieldContext *geometry_context =
|
||||
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
|
||||
@@ -111,9 +111,9 @@ class EndpointFieldInput final : public fn::FieldInput {
|
||||
}
|
||||
current_point += spline->size();
|
||||
}
|
||||
return &scope.construct<fn::GVArray_For_ArrayContainer<Array<bool>>>(std::move(selection));
|
||||
return VArray<bool>::ForContainer(std::move(selection));
|
||||
}
|
||||
return nullptr;
|
||||
return {};
|
||||
};
|
||||
|
||||
uint64_t hash() const override
|
||||
|
||||
@@ -59,10 +59,10 @@ struct FilletParam {
|
||||
GeometryNodeCurveFilletMode mode;
|
||||
|
||||
/* Number of points to be added. */
|
||||
const VArray<int> *counts;
|
||||
VArray<int> counts;
|
||||
|
||||
/* Radii for fillet arc at all vertices. */
|
||||
const VArray<float> *radii;
|
||||
VArray<float> radii;
|
||||
|
||||
/* Whether or not fillets are allowed to overlap. */
|
||||
bool limit_radius;
|
||||
@@ -160,7 +160,7 @@ static Array<int> calculate_counts(const FilletParam &fillet_param,
|
||||
Array<int> counts(size, 1);
|
||||
if (fillet_param.mode == GEO_NODE_CURVE_FILLET_POLY) {
|
||||
for (const int i : IndexRange(size)) {
|
||||
counts[i] = (*fillet_param.counts)[spline_offset + i];
|
||||
counts[i] = fillet_param.counts[spline_offset + i];
|
||||
}
|
||||
}
|
||||
if (!cyclic) {
|
||||
@@ -178,12 +178,12 @@ static Array<float> calculate_radii(const FilletParam &fillet_param,
|
||||
Array<float> radii(size, 0.0f);
|
||||
if (fillet_param.limit_radius) {
|
||||
for (const int i : IndexRange(size)) {
|
||||
radii[i] = std::max((*fillet_param.radii)[spline_offset + i], 0.0f);
|
||||
radii[i] = std::max(fillet_param.radii[spline_offset + i], 0.0f);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (const int i : IndexRange(size)) {
|
||||
radii[i] = (*fillet_param.radii)[spline_offset + i];
|
||||
radii[i] = fillet_param.radii[spline_offset + i];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -590,13 +590,13 @@ static void calculate_curve_fillet(GeometrySet &geometry_set,
|
||||
|
||||
field_evaluator.evaluate();
|
||||
|
||||
fillet_param.radii = &field_evaluator.get_evaluated<float>(0);
|
||||
if (fillet_param.radii->is_single() && fillet_param.radii->get_internal_single() < 0.0f) {
|
||||
fillet_param.radii = field_evaluator.get_evaluated<float>(0);
|
||||
if (fillet_param.radii.is_single() && fillet_param.radii.get_internal_single() < 0.0f) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode == GEO_NODE_CURVE_FILLET_POLY) {
|
||||
fillet_param.counts = &field_evaluator.get_evaluated<int>(1);
|
||||
fillet_param.counts = field_evaluator.get_evaluated<int>(1);
|
||||
}
|
||||
|
||||
fillet_param.limit_radius = limit_radius;
|
||||
|
||||
@@ -96,9 +96,9 @@ class HandleTypeFieldInput final : public fn::FieldInput {
|
||||
category_ = Category::Generated;
|
||||
}
|
||||
|
||||
const GVArray *get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const final
|
||||
GVArray get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &UNUSED(scope)) const final
|
||||
{
|
||||
if (const GeometryComponentFieldContext *geometry_context =
|
||||
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
|
||||
@@ -106,22 +106,22 @@ class HandleTypeFieldInput final : public fn::FieldInput {
|
||||
const GeometryComponent &component = geometry_context->geometry_component();
|
||||
const AttributeDomain domain = geometry_context->domain();
|
||||
if (component.type() != GEO_COMPONENT_TYPE_CURVE) {
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
|
||||
const CurveEval *curve = curve_component.get_for_read();
|
||||
if (curve == nullptr) {
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
if (domain == ATTR_DOMAIN_POINT) {
|
||||
Array<bool> selection(mask.min_array_size());
|
||||
select_by_handle_type(*curve, type_, mode_, selection);
|
||||
return &scope.construct<fn::GVArray_For_ArrayContainer<Array<bool>>>(std::move(selection));
|
||||
return VArray<bool>::ForContainer(std::move(selection));
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
return {};
|
||||
};
|
||||
|
||||
uint64_t hash() const override
|
||||
|
||||
@@ -129,10 +129,9 @@ static Array<float> curve_length_point_domain(const CurveEval &curve)
|
||||
return lengths;
|
||||
}
|
||||
|
||||
static const GVArray *construct_curve_parameter_gvarray(const CurveEval &curve,
|
||||
const IndexMask mask,
|
||||
const AttributeDomain domain,
|
||||
ResourceScope &scope)
|
||||
static VArray<float> construct_curve_parameter_varray(const CurveEval &curve,
|
||||
const IndexMask mask,
|
||||
const AttributeDomain domain)
|
||||
{
|
||||
if (domain == ATTR_DOMAIN_POINT) {
|
||||
Span<SplinePtr> splines = curve.splines();
|
||||
@@ -147,7 +146,7 @@ static const GVArray *construct_curve_parameter_gvarray(const CurveEval &curve,
|
||||
values[offsets[i_spline] + i] *= spline_length_inv;
|
||||
}
|
||||
}
|
||||
return &scope.construct<fn::GVArray_For_ArrayContainer<Array<float>>>(std::move(values));
|
||||
return VArray<float>::ForContainer(std::move(values));
|
||||
}
|
||||
|
||||
if (domain == ATTR_DOMAIN_CURVE) {
|
||||
@@ -156,32 +155,31 @@ static const GVArray *construct_curve_parameter_gvarray(const CurveEval &curve,
|
||||
for (const int i : mask) {
|
||||
values[i] *= total_length_inv;
|
||||
}
|
||||
return &scope.construct<fn::GVArray_For_ArrayContainer<Array<float>>>(std::move(values));
|
||||
return VArray<float>::ForContainer(std::move(values));
|
||||
}
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
static const GVArray *construct_curve_length_gvarray(const CurveEval &curve,
|
||||
const IndexMask mask,
|
||||
const AttributeDomain domain,
|
||||
ResourceScope &scope)
|
||||
static VArray<float> construct_curve_length_varray(const CurveEval &curve,
|
||||
const IndexMask mask,
|
||||
const AttributeDomain domain)
|
||||
{
|
||||
if (domain == ATTR_DOMAIN_POINT) {
|
||||
Array<float> lengths = curve_length_point_domain(curve);
|
||||
return &scope.construct<fn::GVArray_For_ArrayContainer<Array<float>>>(std::move(lengths));
|
||||
return VArray<float>::ForContainer(std::move(lengths));
|
||||
}
|
||||
|
||||
if (domain == ATTR_DOMAIN_CURVE) {
|
||||
if (curve.splines().size() == 1) {
|
||||
Array<float> lengths(1, 0.0f);
|
||||
return &scope.construct<fn::GVArray_For_ArrayContainer<Array<float>>>(std::move(lengths));
|
||||
return VArray<float>::ForContainer(std::move(lengths));
|
||||
}
|
||||
|
||||
Array<float> lengths = curve_length_spline_domain(curve, mask);
|
||||
return &scope.construct<fn::GVArray_For_ArrayContainer<Array<float>>>(std::move(lengths));
|
||||
return VArray<float>::ForContainer(std::move(lengths));
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
class CurveParameterFieldInput final : public fn::FieldInput {
|
||||
@@ -191,9 +189,9 @@ class CurveParameterFieldInput final : public fn::FieldInput {
|
||||
category_ = Category::Generated;
|
||||
}
|
||||
|
||||
const GVArray *get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const final
|
||||
GVArray get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &UNUSED(scope)) const final
|
||||
{
|
||||
if (const GeometryComponentFieldContext *geometry_context =
|
||||
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
|
||||
@@ -205,11 +203,11 @@ class CurveParameterFieldInput final : public fn::FieldInput {
|
||||
const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
|
||||
const CurveEval *curve = curve_component.get_for_read();
|
||||
if (curve) {
|
||||
return construct_curve_parameter_gvarray(*curve, mask, domain, scope);
|
||||
return construct_curve_parameter_varray(*curve, mask, domain);
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
uint64_t hash() const override
|
||||
@@ -231,9 +229,9 @@ class CurveLengthFieldInput final : public fn::FieldInput {
|
||||
category_ = Category::Generated;
|
||||
}
|
||||
|
||||
const GVArray *get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const final
|
||||
GVArray get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &UNUSED(scope)) const final
|
||||
{
|
||||
if (const GeometryComponentFieldContext *geometry_context =
|
||||
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
|
||||
@@ -244,11 +242,11 @@ class CurveLengthFieldInput final : public fn::FieldInput {
|
||||
const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
|
||||
const CurveEval *curve = curve_component.get_for_read();
|
||||
if (curve) {
|
||||
return construct_curve_length_gvarray(*curve, mask, domain, scope);
|
||||
return construct_curve_length_varray(*curve, mask, domain);
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
uint64_t hash() const override
|
||||
|
||||
@@ -26,10 +26,6 @@
|
||||
|
||||
#include "node_geometry_util.hh"
|
||||
|
||||
using blender::fn::GVArray_For_GSpan;
|
||||
using blender::fn::GVArray_For_Span;
|
||||
using blender::fn::GVArray_Typed;
|
||||
|
||||
namespace blender::nodes {
|
||||
|
||||
static void geo_node_curve_resample_declare(NodeDeclarationBuilder &b)
|
||||
@@ -124,7 +120,7 @@ static SplinePtr resample_spline(const Spline &src, const int count)
|
||||
std::optional<GMutableSpan> output_attribute = dst->attributes.get_for_write(
|
||||
attribute_id);
|
||||
if (output_attribute) {
|
||||
src.sample_with_index_factors(*src.interpolate_to_evaluated(*input_attribute),
|
||||
src.sample_with_index_factors(src.interpolate_to_evaluated(*input_attribute),
|
||||
uniform_samples,
|
||||
*output_attribute);
|
||||
return true;
|
||||
@@ -147,8 +143,8 @@ static SplinePtr resample_spline_evaluated(const Spline &src)
|
||||
|
||||
dst->positions().copy_from(src.evaluated_positions());
|
||||
dst->positions().copy_from(src.evaluated_positions());
|
||||
src.interpolate_to_evaluated(src.radii())->materialize(dst->radii());
|
||||
src.interpolate_to_evaluated(src.tilts())->materialize(dst->tilts());
|
||||
src.interpolate_to_evaluated(src.radii()).materialize(dst->radii());
|
||||
src.interpolate_to_evaluated(src.tilts()).materialize(dst->tilts());
|
||||
|
||||
src.attributes.foreach_attribute(
|
||||
[&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) {
|
||||
@@ -156,7 +152,7 @@ static SplinePtr resample_spline_evaluated(const Spline &src)
|
||||
if (dst->attributes.create(attribute_id, meta_data.data_type)) {
|
||||
std::optional<GMutableSpan> dst_attribute = dst->attributes.get_for_write(attribute_id);
|
||||
if (dst_attribute) {
|
||||
src.interpolate_to_evaluated(*src_attribute)->materialize(dst_attribute->data());
|
||||
src.interpolate_to_evaluated(*src_attribute).materialize(dst_attribute->data());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,10 +25,6 @@
|
||||
|
||||
#include "node_geometry_util.hh"
|
||||
|
||||
using blender::fn::GVArray_For_GSpan;
|
||||
using blender::fn::GVArray_For_Span;
|
||||
using blender::fn::GVArray_Typed;
|
||||
|
||||
namespace blender::nodes {
|
||||
|
||||
static void geo_node_curve_subdivide_declare(NodeDeclarationBuilder &b)
|
||||
|
||||
@@ -113,7 +113,7 @@ static GMutableSpan ensure_point_attribute(PointCloudComponent &points,
|
||||
points.attribute_try_create(attribute_id, ATTR_DOMAIN_POINT, data_type, AttributeInitDefault());
|
||||
WriteAttributeLookup attribute = points.attribute_try_get_for_write(attribute_id);
|
||||
BLI_assert(attribute);
|
||||
return attribute.varray->get_internal_span();
|
||||
return attribute.varray.get_internal_span();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -194,7 +194,7 @@ static void copy_evaluated_point_attributes(const Span<SplinePtr> splines,
|
||||
const int size = offsets[i + 1] - offsets[i];
|
||||
|
||||
data.positions.slice(offset, size).copy_from(spline.evaluated_positions());
|
||||
spline.interpolate_to_evaluated(spline.radii())->materialize(data.radii.slice(offset, size));
|
||||
spline.interpolate_to_evaluated(spline.radii()).materialize(data.radii.slice(offset, size));
|
||||
|
||||
for (const Map<AttributeIDRef, GMutableSpan>::Item item : data.point_attributes.items()) {
|
||||
const AttributeIDRef attribute_id = item.key;
|
||||
@@ -203,7 +203,7 @@ static void copy_evaluated_point_attributes(const Span<SplinePtr> splines,
|
||||
BLI_assert(spline.attributes.get_for_read(attribute_id));
|
||||
GSpan spline_span = *spline.attributes.get_for_read(attribute_id);
|
||||
|
||||
spline.interpolate_to_evaluated(spline_span)->materialize(dst.slice(offset, size).data());
|
||||
spline.interpolate_to_evaluated(spline_span).materialize(dst.slice(offset, size).data());
|
||||
}
|
||||
|
||||
if (!data.tangents.is_empty()) {
|
||||
@@ -233,7 +233,7 @@ static void copy_uniform_sample_point_attributes(const Span<SplinePtr> splines,
|
||||
|
||||
spline.sample_with_index_factors<float3>(
|
||||
spline.evaluated_positions(), uniform_samples, data.positions.slice(offset, size));
|
||||
spline.sample_with_index_factors<float>(*spline.interpolate_to_evaluated(spline.radii()),
|
||||
spline.sample_with_index_factors<float>(spline.interpolate_to_evaluated(spline.radii()),
|
||||
uniform_samples,
|
||||
data.radii.slice(offset, size));
|
||||
|
||||
@@ -244,7 +244,7 @@ static void copy_uniform_sample_point_attributes(const Span<SplinePtr> splines,
|
||||
BLI_assert(spline.attributes.get_for_read(attribute_id));
|
||||
GSpan spline_span = *spline.attributes.get_for_read(attribute_id);
|
||||
|
||||
spline.sample_with_index_factors(*spline.interpolate_to_evaluated(spline_span),
|
||||
spline.sample_with_index_factors(spline.interpolate_to_evaluated(spline_span),
|
||||
uniform_samples,
|
||||
dst.slice(offset, size));
|
||||
}
|
||||
|
||||
@@ -216,9 +216,9 @@ static PolySpline trim_nurbs_spline(const Spline &spline,
|
||||
|
||||
attribute_math::convert_to_static_type(src->type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
GVArray_Typed<T> eval_data = spline.interpolate_to_evaluated<T>(src->typed<T>());
|
||||
VArray<T> eval_data = spline.interpolate_to_evaluated<T>(src->typed<T>());
|
||||
linear_trim_to_output_data<T>(
|
||||
start, end, eval_data->get_internal_span(), dst->typed<T>());
|
||||
start, end, eval_data.get_internal_span(), dst->typed<T>());
|
||||
});
|
||||
return true;
|
||||
},
|
||||
@@ -227,13 +227,13 @@ static PolySpline trim_nurbs_spline(const Spline &spline,
|
||||
linear_trim_to_output_data<float3>(
|
||||
start, end, spline.evaluated_positions(), new_spline.positions());
|
||||
|
||||
GVArray_Typed<float> evaluated_radii = spline.interpolate_to_evaluated(spline.radii());
|
||||
VArray<float> evaluated_radii = spline.interpolate_to_evaluated(spline.radii());
|
||||
linear_trim_to_output_data<float>(
|
||||
start, end, evaluated_radii->get_internal_span(), new_spline.radii());
|
||||
start, end, evaluated_radii.get_internal_span(), new_spline.radii());
|
||||
|
||||
GVArray_Typed<float> evaluated_tilts = spline.interpolate_to_evaluated(spline.tilts());
|
||||
VArray<float> evaluated_tilts = spline.interpolate_to_evaluated(spline.tilts());
|
||||
linear_trim_to_output_data<float>(
|
||||
start, end, evaluated_tilts->get_internal_span(), new_spline.tilts());
|
||||
start, end, evaluated_tilts.get_internal_span(), new_spline.tilts());
|
||||
|
||||
return new_spline;
|
||||
}
|
||||
@@ -427,8 +427,8 @@ static PolySpline to_single_point_nurbs(const Spline &spline, const Spline::Look
|
||||
std::optional<GMutableSpan> dst = new_spline.attributes.get_for_write(attribute_id);
|
||||
attribute_math::convert_to_static_type(src->type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
GVArray_Typed<T> eval_data = spline.interpolate_to_evaluated<T>(src->typed<T>());
|
||||
to_single_point_data<T>(trim, eval_data->get_internal_span(), dst->typed<T>());
|
||||
VArray<T> eval_data = spline.interpolate_to_evaluated<T>(src->typed<T>());
|
||||
to_single_point_data<T>(trim, eval_data.get_internal_span(), dst->typed<T>());
|
||||
});
|
||||
return true;
|
||||
},
|
||||
@@ -436,11 +436,11 @@ static PolySpline to_single_point_nurbs(const Spline &spline, const Spline::Look
|
||||
|
||||
to_single_point_data<float3>(trim, spline.evaluated_positions(), new_spline.positions());
|
||||
|
||||
GVArray_Typed<float> evaluated_radii = spline.interpolate_to_evaluated(spline.radii());
|
||||
to_single_point_data<float>(trim, evaluated_radii->get_internal_span(), new_spline.radii());
|
||||
VArray<float> evaluated_radii = spline.interpolate_to_evaluated(spline.radii());
|
||||
to_single_point_data<float>(trim, evaluated_radii.get_internal_span(), new_spline.radii());
|
||||
|
||||
GVArray_Typed<float> evaluated_tilts = spline.interpolate_to_evaluated(spline.tilts());
|
||||
to_single_point_data<float>(trim, evaluated_tilts->get_internal_span(), new_spline.tilts());
|
||||
VArray<float> evaluated_tilts = spline.interpolate_to_evaluated(spline.tilts());
|
||||
to_single_point_data<float>(trim, evaluated_tilts.get_internal_span(), new_spline.tilts());
|
||||
|
||||
return new_spline;
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ static void copy_attributes(const Map<AttributeIDRef, AttributeKind> &attributes
|
||||
if (!domains.contains(attribute.domain)) {
|
||||
continue;
|
||||
}
|
||||
const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray->type());
|
||||
const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type());
|
||||
|
||||
OutputAttribute result_attribute = result_component.attribute_try_get_for_output_only(
|
||||
attribute_id, attribute.domain, data_type);
|
||||
@@ -149,7 +149,7 @@ static void copy_attributes(const Map<AttributeIDRef, AttributeKind> &attributes
|
||||
|
||||
attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
GVArray_Span<T> span{*attribute.varray};
|
||||
VArray_Span<T> span{attribute.varray.typed<T>()};
|
||||
MutableSpan<T> out_span = result_attribute.as_span<T>();
|
||||
out_span.copy_from(span);
|
||||
});
|
||||
@@ -178,7 +178,7 @@ static void copy_attributes_based_on_mask(const Map<AttributeIDRef, AttributeKin
|
||||
if (domain != attribute.domain) {
|
||||
continue;
|
||||
}
|
||||
const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray->type());
|
||||
const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type());
|
||||
|
||||
OutputAttribute result_attribute = result_component.attribute_try_get_for_output_only(
|
||||
attribute_id, attribute.domain, data_type);
|
||||
@@ -189,7 +189,7 @@ static void copy_attributes_based_on_mask(const Map<AttributeIDRef, AttributeKin
|
||||
|
||||
attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
GVArray_Span<T> span{*attribute.varray};
|
||||
VArray_Span<T> span{attribute.varray.typed<T>()};
|
||||
MutableSpan<T> out_span = result_attribute.as_span<T>();
|
||||
copy_data(span, out_span, mask);
|
||||
});
|
||||
|
||||
@@ -313,7 +313,7 @@ BLI_NOINLINE static void propagate_existing_attributes(
|
||||
bary_coords,
|
||||
looptri_indices,
|
||||
source_attribute.domain,
|
||||
*source_attribute.varray,
|
||||
source_attribute.varray,
|
||||
out_span);
|
||||
attribute_out.save();
|
||||
}
|
||||
|
||||
@@ -31,19 +31,18 @@ static void geo_node_input_normal_declare(NodeDeclarationBuilder &b)
|
||||
b.add_output<decl::Vector>(N_("Normal")).field_source();
|
||||
}
|
||||
|
||||
static GVArrayPtr mesh_face_normals(const Mesh &mesh,
|
||||
const Span<MVert> verts,
|
||||
const Span<MPoly> polys,
|
||||
const Span<MLoop> loops,
|
||||
const IndexMask mask)
|
||||
static VArray<float3> mesh_face_normals(const Mesh &mesh,
|
||||
const Span<MVert> verts,
|
||||
const Span<MPoly> polys,
|
||||
const Span<MLoop> loops,
|
||||
const IndexMask mask)
|
||||
{
|
||||
/* Use existing normals to avoid unnecessarily recalculating them, if possible. */
|
||||
if (!(mesh.runtime.cd_dirty_poly & CD_MASK_NORMAL) &&
|
||||
CustomData_has_layer(&mesh.pdata, CD_NORMAL)) {
|
||||
const void *data = CustomData_get_layer(&mesh.pdata, CD_NORMAL);
|
||||
|
||||
return std::make_unique<fn::GVArray_For_Span<float3>>(
|
||||
Span<float3>((const float3 *)data, polys.size()));
|
||||
return VArray<float3>::ForSpan({(const float3 *)data, polys.size()});
|
||||
}
|
||||
|
||||
auto normal_fn = [verts, polys, loops](const int i) -> float3 {
|
||||
@@ -53,24 +52,21 @@ static GVArrayPtr mesh_face_normals(const Mesh &mesh,
|
||||
return normal;
|
||||
};
|
||||
|
||||
return std::make_unique<
|
||||
fn::GVArray_For_EmbeddedVArray<float3, VArray_For_Func<float3, decltype(normal_fn)>>>(
|
||||
mask.min_array_size(), mask.min_array_size(), normal_fn);
|
||||
return VArray<float3>::ForFunc(mask.min_array_size(), normal_fn);
|
||||
}
|
||||
|
||||
static GVArrayPtr mesh_vertex_normals(const Mesh &mesh,
|
||||
const Span<MVert> verts,
|
||||
const Span<MPoly> polys,
|
||||
const Span<MLoop> loops,
|
||||
const IndexMask mask)
|
||||
static VArray<float3> mesh_vertex_normals(const Mesh &mesh,
|
||||
const Span<MVert> verts,
|
||||
const Span<MPoly> polys,
|
||||
const Span<MLoop> loops,
|
||||
const IndexMask mask)
|
||||
{
|
||||
/* Use existing normals to avoid unnecessarily recalculating them, if possible. */
|
||||
if (!(mesh.runtime.cd_dirty_vert & CD_MASK_NORMAL) &&
|
||||
CustomData_has_layer(&mesh.vdata, CD_NORMAL)) {
|
||||
const void *data = CustomData_get_layer(&mesh.pdata, CD_NORMAL);
|
||||
|
||||
return std::make_unique<fn::GVArray_For_Span<float3>>(
|
||||
Span<float3>((const float3 *)data, mesh.totvert));
|
||||
return VArray<float3>::ForSpan({(const float3 *)data, mesh.totvert});
|
||||
}
|
||||
|
||||
/* If the normals are dirty, they must be recalculated for the output of this node's field
|
||||
@@ -91,14 +87,14 @@ static GVArrayPtr mesh_vertex_normals(const Mesh &mesh,
|
||||
nullptr,
|
||||
(float(*)[3])normals.data());
|
||||
|
||||
return std::make_unique<fn::GVArray_For_ArrayContainer<Array<float3>>>(std::move(normals));
|
||||
return VArray<float3>::ForContainer(std::move(normals));
|
||||
}
|
||||
|
||||
static const GVArray *construct_mesh_normals_gvarray(const MeshComponent &mesh_component,
|
||||
static VArray<float3> construct_mesh_normals_gvarray(const MeshComponent &mesh_component,
|
||||
const Mesh &mesh,
|
||||
const IndexMask mask,
|
||||
const AttributeDomain domain,
|
||||
ResourceScope &scope)
|
||||
ResourceScope &UNUSED(scope))
|
||||
{
|
||||
Span<MVert> verts{mesh.mvert, mesh.totvert};
|
||||
Span<MEdge> edges{mesh.medge, mesh.totedge};
|
||||
@@ -107,18 +103,18 @@ static const GVArray *construct_mesh_normals_gvarray(const MeshComponent &mesh_c
|
||||
|
||||
switch (domain) {
|
||||
case ATTR_DOMAIN_FACE: {
|
||||
return scope.add_value(mesh_face_normals(mesh, verts, polys, loops, mask)).get();
|
||||
return mesh_face_normals(mesh, verts, polys, loops, mask);
|
||||
}
|
||||
case ATTR_DOMAIN_POINT: {
|
||||
return scope.add_value(mesh_vertex_normals(mesh, verts, polys, loops, mask)).get();
|
||||
return mesh_vertex_normals(mesh, verts, polys, loops, mask);
|
||||
}
|
||||
case ATTR_DOMAIN_EDGE: {
|
||||
/* In this case, start with vertex normals and convert to the edge domain, since the
|
||||
* conversion from edges to vertices is very simple. Use the full mask since the edges
|
||||
* might use the vertex normal from any index. */
|
||||
GVArrayPtr vert_normals = mesh_vertex_normals(
|
||||
GVArray vert_normals = mesh_vertex_normals(
|
||||
mesh, verts, polys, loops, IndexRange(verts.size()));
|
||||
Span<float3> vert_normals_span = vert_normals->get_internal_span().typed<float3>();
|
||||
Span<float3> vert_normals_span = vert_normals.get_internal_span().typed<float3>();
|
||||
Array<float3> edge_normals(mask.min_array_size());
|
||||
|
||||
/* Use "manual" domain interpolation instead of the GeometryComponent API to avoid
|
||||
@@ -130,23 +126,21 @@ static const GVArray *construct_mesh_normals_gvarray(const MeshComponent &mesh_c
|
||||
.normalized();
|
||||
}
|
||||
|
||||
return &scope.construct<fn::GVArray_For_ArrayContainer<Array<float3>>>(
|
||||
std::move(edge_normals));
|
||||
return VArray<float3>::ForContainer(std::move(edge_normals));
|
||||
}
|
||||
case ATTR_DOMAIN_CORNER: {
|
||||
/* The normals on corners are just the mesh's face normals, so start with the face normal
|
||||
* array and copy the face normal for each of its corners. */
|
||||
GVArrayPtr face_normals = mesh_face_normals(
|
||||
VArray<float3> face_normals = mesh_face_normals(
|
||||
mesh, verts, polys, loops, IndexRange(polys.size()));
|
||||
|
||||
/* In this case using the mesh component's generic domain interpolation is fine, the data
|
||||
* will still be normalized, since the face normal is just copied to every corner. */
|
||||
GVArrayPtr loop_normals = mesh_component.attribute_try_adapt_domain(
|
||||
return mesh_component.attribute_try_adapt_domain<float3>(
|
||||
std::move(face_normals), ATTR_DOMAIN_FACE, ATTR_DOMAIN_CORNER);
|
||||
return scope.add_value(std::move(loop_normals)).get();
|
||||
}
|
||||
default:
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,9 +198,9 @@ static Array<float3> curve_normal_point_domain(const CurveEval &curve)
|
||||
return normals;
|
||||
}
|
||||
|
||||
static const GVArray *construct_curve_normal_gvarray(const CurveComponent &component,
|
||||
static VArray<float3> construct_curve_normal_gvarray(const CurveComponent &component,
|
||||
const AttributeDomain domain,
|
||||
ResourceScope &scope)
|
||||
ResourceScope &UNUSED(scope))
|
||||
{
|
||||
const CurveEval *curve = component.get_for_read();
|
||||
if (curve == nullptr) {
|
||||
@@ -220,20 +214,18 @@ static const GVArray *construct_curve_normal_gvarray(const CurveComponent &compo
|
||||
* This is only possible when there is only one poly spline. */
|
||||
if (splines.size() == 1 && splines.first()->type() == Spline::Type::Poly) {
|
||||
const PolySpline &spline = static_cast<PolySpline &>(*splines.first());
|
||||
return &scope.construct<fn::GVArray_For_Span<float3>>(spline.evaluated_normals());
|
||||
return VArray<float3>::ForSpan(spline.evaluated_normals());
|
||||
}
|
||||
|
||||
Array<float3> normals = curve_normal_point_domain(*curve);
|
||||
return &scope.construct<fn::GVArray_For_ArrayContainer<Array<float3>>>(std::move(normals));
|
||||
return VArray<float3>::ForContainer(std::move(normals));
|
||||
}
|
||||
|
||||
if (domain == ATTR_DOMAIN_CURVE) {
|
||||
Array<float3> point_normals = curve_normal_point_domain(*curve);
|
||||
GVArrayPtr gvarray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<float3>>>(
|
||||
std::move(point_normals));
|
||||
GVArrayPtr spline_normals = component.attribute_try_adapt_domain(
|
||||
std::move(gvarray), ATTR_DOMAIN_POINT, ATTR_DOMAIN_CURVE);
|
||||
return scope.add_value(std::move(spline_normals)).get();
|
||||
VArray<float3> varray = VArray<float3>::ForContainer(std::move(point_normals));
|
||||
return component.attribute_try_adapt_domain<float3>(
|
||||
std::move(varray), ATTR_DOMAIN_POINT, ATTR_DOMAIN_CURVE);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
@@ -246,9 +238,9 @@ class NormalFieldInput final : public fn::FieldInput {
|
||||
category_ = Category::Generated;
|
||||
}
|
||||
|
||||
const GVArray *get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const final
|
||||
GVArray get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const final
|
||||
{
|
||||
if (const GeometryComponentFieldContext *geometry_context =
|
||||
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
|
||||
@@ -260,7 +252,7 @@ class NormalFieldInput final : public fn::FieldInput {
|
||||
const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
|
||||
const Mesh *mesh = mesh_component.get_for_read();
|
||||
if (mesh == nullptr) {
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
return construct_mesh_normals_gvarray(mesh_component, *mesh, mask, domain, scope);
|
||||
@@ -270,7 +262,7 @@ class NormalFieldInput final : public fn::FieldInput {
|
||||
return construct_curve_normal_gvarray(curve_component, domain, scope);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
uint64_t hash() const override
|
||||
|
||||
@@ -25,31 +25,25 @@ static void geo_node_input_spline_length_declare(NodeDeclarationBuilder &b)
|
||||
b.add_output<decl::Float>(N_("Length")).field_source();
|
||||
}
|
||||
|
||||
static const GVArray *construct_spline_length_gvarray(const CurveComponent &component,
|
||||
const AttributeDomain domain,
|
||||
ResourceScope &scope)
|
||||
static VArray<float> construct_spline_length_gvarray(const CurveComponent &component,
|
||||
const AttributeDomain domain,
|
||||
ResourceScope &UNUSED(scope))
|
||||
{
|
||||
const CurveEval *curve = component.get_for_read();
|
||||
if (curve == nullptr) {
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
Span<SplinePtr> splines = curve->splines();
|
||||
auto length_fn = [splines](int i) { return splines[i]->length(); };
|
||||
|
||||
if (domain == ATTR_DOMAIN_CURVE) {
|
||||
return &scope.construct<
|
||||
fn::GVArray_For_EmbeddedVArray<float, VArray_For_Func<float, decltype(length_fn)>>>(
|
||||
splines.size(), splines.size(), length_fn);
|
||||
return VArray<float>::ForFunc(splines.size(), length_fn);
|
||||
}
|
||||
if (domain == ATTR_DOMAIN_POINT) {
|
||||
GVArrayPtr length = std::make_unique<
|
||||
fn::GVArray_For_EmbeddedVArray<float, VArray_For_Func<float, decltype(length_fn)>>>(
|
||||
splines.size(), splines.size(), length_fn);
|
||||
return scope
|
||||
.add_value(component.attribute_try_adapt_domain(
|
||||
std::move(length), ATTR_DOMAIN_CURVE, ATTR_DOMAIN_POINT))
|
||||
.get();
|
||||
VArray<float> length = VArray<float>::ForFunc(splines.size(), length_fn);
|
||||
return component.attribute_try_adapt_domain<float>(
|
||||
std::move(length), ATTR_DOMAIN_CURVE, ATTR_DOMAIN_POINT);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
@@ -62,9 +56,9 @@ class SplineLengthFieldInput final : public fn::FieldInput {
|
||||
category_ = Category::Generated;
|
||||
}
|
||||
|
||||
const GVArray *get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask UNUSED(mask),
|
||||
ResourceScope &scope) const final
|
||||
GVArray get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask UNUSED(mask),
|
||||
ResourceScope &scope) const final
|
||||
{
|
||||
if (const GeometryComponentFieldContext *geometry_context =
|
||||
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
|
||||
@@ -76,7 +70,7 @@ class SplineLengthFieldInput final : public fn::FieldInput {
|
||||
return construct_spline_length_gvarray(curve_component, domain, scope);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
uint64_t hash() const override
|
||||
|
||||
@@ -84,9 +84,9 @@ static Array<float3> curve_tangent_point_domain(const CurveEval &curve)
|
||||
return tangents;
|
||||
}
|
||||
|
||||
static const GVArray *construct_curve_tangent_gvarray(const CurveComponent &component,
|
||||
static VArray<float3> construct_curve_tangent_gvarray(const CurveComponent &component,
|
||||
const AttributeDomain domain,
|
||||
ResourceScope &scope)
|
||||
ResourceScope &UNUSED(scope))
|
||||
{
|
||||
const CurveEval *curve = component.get_for_read();
|
||||
if (curve == nullptr) {
|
||||
@@ -100,20 +100,19 @@ static const GVArray *construct_curve_tangent_gvarray(const CurveComponent &comp
|
||||
* This is only possible when there is only one poly spline. */
|
||||
if (splines.size() == 1 && splines.first()->type() == Spline::Type::Poly) {
|
||||
const PolySpline &spline = static_cast<PolySpline &>(*splines.first());
|
||||
return &scope.construct<fn::GVArray_For_Span<float3>>(spline.evaluated_tangents());
|
||||
return VArray<float3>::ForSpan(spline.evaluated_tangents());
|
||||
}
|
||||
|
||||
Array<float3> tangents = curve_tangent_point_domain(*curve);
|
||||
return &scope.construct<fn::GVArray_For_ArrayContainer<Array<float3>>>(std::move(tangents));
|
||||
return VArray<float3>::ForContainer(std::move(tangents));
|
||||
}
|
||||
|
||||
if (domain == ATTR_DOMAIN_CURVE) {
|
||||
Array<float3> point_tangents = curve_tangent_point_domain(*curve);
|
||||
GVArrayPtr gvarray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<float3>>>(
|
||||
std::move(point_tangents));
|
||||
GVArrayPtr spline_tangents = component.attribute_try_adapt_domain(
|
||||
std::move(gvarray), ATTR_DOMAIN_POINT, ATTR_DOMAIN_CURVE);
|
||||
return scope.add_value(std::move(spline_tangents)).get();
|
||||
return component.attribute_try_adapt_domain<float3>(
|
||||
VArray<float3>::ForContainer(std::move(point_tangents)),
|
||||
ATTR_DOMAIN_POINT,
|
||||
ATTR_DOMAIN_CURVE);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
@@ -126,9 +125,9 @@ class TangentFieldInput final : public fn::FieldInput {
|
||||
category_ = Category::Generated;
|
||||
}
|
||||
|
||||
const GVArray *get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask UNUSED(mask),
|
||||
ResourceScope &scope) const final
|
||||
GVArray get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask UNUSED(mask),
|
||||
ResourceScope &scope) const final
|
||||
{
|
||||
if (const GeometryComponentFieldContext *geometry_context =
|
||||
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
|
||||
@@ -141,7 +140,7 @@ class TangentFieldInput final : public fn::FieldInput {
|
||||
return construct_curve_tangent_gvarray(curve_component, domain, scope);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
uint64_t hash() const override
|
||||
|
||||
@@ -80,10 +80,10 @@ static void add_instances_from_component(InstancesComponent &dst_component,
|
||||
select_len);
|
||||
|
||||
FieldEvaluator field_evaluator{field_context, domain_size};
|
||||
const VArray<bool> *pick_instance = nullptr;
|
||||
const VArray<int> *indices = nullptr;
|
||||
const VArray<float3> *rotations = nullptr;
|
||||
const VArray<float3> *scales = nullptr;
|
||||
VArray<bool> pick_instance;
|
||||
VArray<int> indices;
|
||||
VArray<float3> rotations;
|
||||
VArray<float3> scales;
|
||||
/* The evaluator could use the component's stable IDs as a destination directly, but only the
|
||||
* selected indices should be copied. */
|
||||
field_evaluator.add(params.get_input<Field<bool>>("Pick Instance"), &pick_instance);
|
||||
@@ -92,7 +92,7 @@ static void add_instances_from_component(InstancesComponent &dst_component,
|
||||
field_evaluator.add(params.get_input<Field<float3>>("Scale"), &scales);
|
||||
field_evaluator.evaluate();
|
||||
|
||||
GVArray_Typed<float3> positions = src_component.attribute_get_for_read<float3>(
|
||||
VArray<float3> positions = src_component.attribute_get_for_read<float3>(
|
||||
"position", domain, {0, 0, 0});
|
||||
|
||||
const InstancesComponent *src_instances = instance.get_component_for_read<InstancesComponent>();
|
||||
@@ -101,7 +101,7 @@ static void add_instances_from_component(InstancesComponent &dst_component,
|
||||
Array<int> handle_mapping;
|
||||
/* Only fill #handle_mapping when it may be used below. */
|
||||
if (src_instances != nullptr &&
|
||||
(!pick_instance->is_single() || pick_instance->get_internal_single())) {
|
||||
(!pick_instance.is_single() || pick_instance.get_internal_single())) {
|
||||
Span<InstanceReference> src_references = src_instances->references();
|
||||
handle_mapping.reinitialize(src_references.size());
|
||||
for (const int src_instance_handle : src_references.index_range()) {
|
||||
@@ -121,17 +121,16 @@ static void add_instances_from_component(InstancesComponent &dst_component,
|
||||
|
||||
/* Compute base transform for every instances. */
|
||||
float4x4 &dst_transform = dst_transforms[range_i];
|
||||
dst_transform = float4x4::from_loc_eul_scale(
|
||||
positions[i], rotations->get(i), scales->get(i));
|
||||
dst_transform = float4x4::from_loc_eul_scale(positions[i], rotations[i], scales[i]);
|
||||
|
||||
/* Reference that will be used by this new instance. */
|
||||
int dst_handle = empty_reference_handle;
|
||||
|
||||
const bool use_individual_instance = pick_instance->get(i);
|
||||
const bool use_individual_instance = pick_instance[i];
|
||||
if (use_individual_instance) {
|
||||
if (src_instances != nullptr) {
|
||||
const int src_instances_amount = src_instances->instances_amount();
|
||||
const int original_index = indices->get(i);
|
||||
const int original_index = indices[i];
|
||||
/* Use #mod_i instead of `%` to get the desirable wrap around behavior where -1
|
||||
* refers to the last element. */
|
||||
const int index = mod_i(original_index, std::max(src_instances_amount, 1));
|
||||
@@ -155,10 +154,10 @@ static void add_instances_from_component(InstancesComponent &dst_component,
|
||||
}
|
||||
});
|
||||
|
||||
GVArrayPtr id_attribute = src_component.attribute_try_get_for_read(
|
||||
"id", ATTR_DOMAIN_POINT, CD_PROP_INT32);
|
||||
if (id_attribute) {
|
||||
GVArray_Typed<int> ids{*id_attribute};
|
||||
VArray<int> ids = src_component
|
||||
.attribute_try_get_for_read("id", ATTR_DOMAIN_POINT, CD_PROP_INT32)
|
||||
.typed<int>();
|
||||
if (ids) {
|
||||
VArray_Span<int> ids_span{ids};
|
||||
MutableSpan<int> dst_ids = dst_component.instance_ids_ensure();
|
||||
for (const int64_t i : selection.index_range()) {
|
||||
@@ -166,8 +165,8 @@ static void add_instances_from_component(InstancesComponent &dst_component,
|
||||
}
|
||||
}
|
||||
|
||||
if (pick_instance->is_single()) {
|
||||
if (pick_instance->get_internal_single()) {
|
||||
if (pick_instance.is_single()) {
|
||||
if (pick_instance.get_internal_single()) {
|
||||
if (instance.has_realized_data()) {
|
||||
params.error_message_add(
|
||||
NodeWarningType::Info,
|
||||
|
||||
@@ -27,8 +27,6 @@
|
||||
|
||||
#include "node_geometry_util.hh"
|
||||
|
||||
using blender::fn::GVArray_For_GSpan;
|
||||
|
||||
namespace blender::nodes {
|
||||
|
||||
static void geo_node_join_geometry_declare(NodeDeclarationBuilder &b)
|
||||
@@ -190,10 +188,10 @@ static void fill_new_attribute(Span<const GeometryComponent *> src_components,
|
||||
if (domain_size == 0) {
|
||||
continue;
|
||||
}
|
||||
GVArrayPtr read_attribute = component->attribute_get_for_read(
|
||||
GVArray read_attribute = component->attribute_get_for_read(
|
||||
attribute_id, domain, data_type, nullptr);
|
||||
|
||||
GVArray_GSpan src_span{*read_attribute};
|
||||
GVArray_GSpan src_span{read_attribute};
|
||||
const void *src_buffer = src_span.data();
|
||||
void *dst_buffer = dst_span[offset];
|
||||
cpp_type->copy_assign_n(src_buffer, dst_buffer, domain_size);
|
||||
@@ -319,8 +317,7 @@ static void ensure_control_point_attribute(const AttributeIDRef &attribute_id,
|
||||
spline->size() * type.size(), type.alignment(), __func__);
|
||||
|
||||
const DataTypeConversions &conversions = blender::nodes::get_implicit_type_conversions();
|
||||
conversions.try_convert(std::make_unique<GVArray_For_GSpan>(*attribute), type)
|
||||
->materialize(converted_buffer);
|
||||
conversions.try_convert(GVArray::ForSpan(*attribute), type).materialize(converted_buffer);
|
||||
|
||||
spline->attributes.remove(attribute_id);
|
||||
spline->attributes.create_by_move(attribute_id, data_type, converted_buffer);
|
||||
@@ -333,14 +330,14 @@ static void ensure_control_point_attribute(const AttributeIDRef &attribute_id,
|
||||
/* In this case the attribute did not exist, but there is a spline domain attribute
|
||||
* we can retrieve a value from, as a spline to point domain conversion. So fill the
|
||||
* new attribute with the value for this spline. */
|
||||
GVArrayPtr current_curve_attribute = current_curve->attributes.get_for_read(
|
||||
GVArray current_curve_attribute = current_curve->attributes.get_for_read(
|
||||
attribute_id, data_type, nullptr);
|
||||
|
||||
BLI_assert(spline->attributes.get_for_read(attribute_id));
|
||||
std::optional<GMutableSpan> new_attribute = spline->attributes.get_for_write(attribute_id);
|
||||
|
||||
BUFFER_FOR_CPP_TYPE_VALUE(type, buffer);
|
||||
current_curve_attribute->get(spline_index_in_component, buffer);
|
||||
current_curve_attribute.get(spline_index_in_component, buffer);
|
||||
type.fill_assign_n(buffer, new_attribute->data(), new_attribute->size());
|
||||
}
|
||||
}
|
||||
@@ -397,8 +394,8 @@ static void ensure_spline_attribute(const AttributeIDRef &attribute_id,
|
||||
if (size == 0) {
|
||||
continue;
|
||||
}
|
||||
GVArrayPtr read_attribute = curve.attributes.get_for_read(attribute_id, data_type, nullptr);
|
||||
GVArray_GSpan src_span{*read_attribute};
|
||||
GVArray read_attribute = curve.attributes.get_for_read(attribute_id, data_type, nullptr);
|
||||
GVArray_GSpan src_span{read_attribute};
|
||||
|
||||
const void *src_buffer = src_span.data();
|
||||
type.copy_assign_n(src_buffer, result_attribute[offset], size);
|
||||
|
||||
@@ -64,36 +64,33 @@ class MaterialSelectionFieldInput final : public fn::FieldInput {
|
||||
category_ = Category::Generated;
|
||||
}
|
||||
|
||||
const GVArray *get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &scope) const final
|
||||
GVArray get_varray_for_context(const fn::FieldContext &context,
|
||||
IndexMask mask,
|
||||
ResourceScope &UNUSED(scope)) const final
|
||||
{
|
||||
if (const GeometryComponentFieldContext *geometry_context =
|
||||
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
|
||||
const GeometryComponent &component = geometry_context->geometry_component();
|
||||
const AttributeDomain domain = geometry_context->domain();
|
||||
if (component.type() != GEO_COMPONENT_TYPE_MESH) {
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
|
||||
const Mesh *mesh = mesh_component.get_for_read();
|
||||
if (mesh == nullptr) {
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
if (domain == ATTR_DOMAIN_FACE) {
|
||||
Array<bool> selection(mask.min_array_size());
|
||||
select_mesh_by_material(*mesh, material_, mask, selection);
|
||||
return &scope.construct<fn::GVArray_For_ArrayContainer<Array<bool>>>(std::move(selection));
|
||||
return VArray<bool>::ForContainer(std::move(selection));
|
||||
}
|
||||
|
||||
Array<bool> selection(mesh->totpoly);
|
||||
select_mesh_by_material(*mesh, material_, IndexMask(mesh->totpoly), selection);
|
||||
GVArrayPtr face_selection = std::make_unique<fn::GVArray_For_ArrayContainer<Array<bool>>>(
|
||||
std::move(selection));
|
||||
GVArrayPtr final_selection = mesh_component.attribute_try_adapt_domain(
|
||||
std::move(face_selection), ATTR_DOMAIN_FACE, domain);
|
||||
return scope.add_value(std::move(final_selection)).get();
|
||||
return mesh_component.attribute_try_adapt_domain<bool>(
|
||||
VArray<bool>::ForContainer(std::move(selection)), ATTR_DOMAIN_FACE, domain);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
||||
@@ -113,14 +113,14 @@ static void geometry_set_mesh_to_points(GeometrySet &geometry_set,
|
||||
for (Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) {
|
||||
const AttributeIDRef attribute_id = entry.key;
|
||||
const CustomDataType data_type = entry.value.data_type;
|
||||
GVArrayPtr src = mesh_component->attribute_get_for_read(attribute_id, domain, data_type);
|
||||
GVArray src = mesh_component->attribute_get_for_read(attribute_id, domain, data_type);
|
||||
OutputAttribute dst = point_component.attribute_try_get_for_output_only(
|
||||
attribute_id, ATTR_DOMAIN_POINT, data_type);
|
||||
if (dst && src) {
|
||||
attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
GVArray_Typed<T> src_typed{*src};
|
||||
copy_attribute_to_points(*src_typed, selection, dst.as_span().typed<T>());
|
||||
VArray<T> src_typed = src.typed<T>();
|
||||
copy_attribute_to_points(src_typed, selection, dst.as_span().typed<T>());
|
||||
});
|
||||
dst.save();
|
||||
}
|
||||
|
||||
@@ -74,15 +74,15 @@ static void geometry_set_points_to_vertices(GeometrySet &geometry_set,
|
||||
for (Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) {
|
||||
const AttributeIDRef attribute_id = entry.key;
|
||||
const CustomDataType data_type = entry.value.data_type;
|
||||
GVArrayPtr src = point_component->attribute_get_for_read(
|
||||
GVArray src = point_component->attribute_get_for_read(
|
||||
attribute_id, ATTR_DOMAIN_POINT, data_type);
|
||||
OutputAttribute dst = mesh_component.attribute_try_get_for_output_only(
|
||||
attribute_id, ATTR_DOMAIN_POINT, data_type);
|
||||
if (dst && src) {
|
||||
attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
GVArray_Typed<T> src_typed{*src};
|
||||
VArray_Span<T> src_typed_span{*src_typed};
|
||||
VArray<T> src_typed = src.typed<T>();
|
||||
VArray_Span<T> src_typed_span{src_typed};
|
||||
copy_attribute_to_vertices(src_typed_span, selection, dst.as_span().typed<T>());
|
||||
});
|
||||
dst.save();
|
||||
|
||||
@@ -165,7 +165,7 @@ static void gather_point_data_from_component(GeoNodeExecParams ¶ms,
|
||||
Vector<float3> &r_positions,
|
||||
Vector<float> &r_radii)
|
||||
{
|
||||
GVArray_Typed<float3> positions = component.attribute_get_for_read<float3>(
|
||||
VArray<float3> positions = component.attribute_get_for_read<float3>(
|
||||
"position", ATTR_DOMAIN_POINT, {0, 0, 0});
|
||||
|
||||
Field<float> radius_field = params.get_input<Field<float>>("Radius");
|
||||
@@ -173,7 +173,7 @@ static void gather_point_data_from_component(GeoNodeExecParams ¶ms,
|
||||
const int domain_size = component.attribute_domain_size(ATTR_DOMAIN_POINT);
|
||||
|
||||
r_positions.resize(r_positions.size() + domain_size);
|
||||
positions->materialize(r_positions.as_mutable_span().take_back(domain_size));
|
||||
positions.materialize(r_positions.as_mutable_span().take_back(domain_size));
|
||||
|
||||
r_radii.resize(r_radii.size() + domain_size);
|
||||
fn::FieldEvaluator evaluator{field_context, domain_size};
|
||||
|
||||
@@ -541,10 +541,10 @@ class NearestTransferFunction : public fn::MultiFunction {
|
||||
attribute_math::convert_to_static_type(dst.type(), [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
if (use_mesh_ && use_points_) {
|
||||
GVArray_Typed<T> src_mesh{*mesh_data_};
|
||||
GVArray_Typed<T> src_point{*point_data_};
|
||||
copy_with_indices_and_comparison(*src_mesh,
|
||||
*src_point,
|
||||
VArray<T> src_mesh = mesh_data_->typed<T>();
|
||||
VArray<T> src_point = point_data_->typed<T>();
|
||||
copy_with_indices_and_comparison(src_mesh,
|
||||
src_point,
|
||||
mesh_distances,
|
||||
point_distances,
|
||||
mask,
|
||||
@@ -553,12 +553,12 @@ class NearestTransferFunction : public fn::MultiFunction {
|
||||
dst.typed<T>());
|
||||
}
|
||||
else if (use_points_) {
|
||||
GVArray_Typed<T> src_point{*point_data_};
|
||||
copy_with_indices(*src_point, mask, point_indices, dst.typed<T>());
|
||||
VArray<T> src_point = point_data_->typed<T>();
|
||||
copy_with_indices(src_point, mask, point_indices, dst.typed<T>());
|
||||
}
|
||||
else if (use_mesh_) {
|
||||
GVArray_Typed<T> src_mesh{*mesh_data_};
|
||||
copy_with_indices(*src_mesh, mask, mesh_indices, dst.typed<T>());
|
||||
VArray<T> src_mesh = mesh_data_->typed<T>();
|
||||
copy_with_indices(src_mesh, mask, mesh_indices, dst.typed<T>());
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -667,8 +667,7 @@ class IndexTransferFunction : public fn::MultiFunction {
|
||||
|
||||
attribute_math::convert_to_static_type(type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
GVArray_Typed<T> src{*src_data_};
|
||||
copy_with_indices_clamped(*src, mask, indices, dst.typed<T>());
|
||||
copy_with_indices_clamped(src_data_->typed<T>(), mask, indices, dst.typed<T>());
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -113,11 +113,11 @@ const bNodeSocket *GeoNodeExecParams::find_available_socket(const StringRef name
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GVArrayPtr GeoNodeExecParams::get_input_attribute(const StringRef name,
|
||||
const GeometryComponent &component,
|
||||
const AttributeDomain domain,
|
||||
const CustomDataType type,
|
||||
const void *default_value) const
|
||||
GVArray GeoNodeExecParams::get_input_attribute(const StringRef name,
|
||||
const GeometryComponent &component,
|
||||
const AttributeDomain domain,
|
||||
const CustomDataType type,
|
||||
const void *default_value) const
|
||||
{
|
||||
const bNodeSocket *found_socket = this->find_available_socket(name);
|
||||
BLI_assert(found_socket != nullptr); /* There should always be available socket for the name. */
|
||||
@@ -129,13 +129,13 @@ GVArrayPtr GeoNodeExecParams::get_input_attribute(const StringRef name,
|
||||
}
|
||||
|
||||
if (found_socket == nullptr) {
|
||||
return std::make_unique<fn::GVArray_For_SingleValue>(*cpp_type, domain_size, default_value);
|
||||
return GVArray::ForSingle(*cpp_type, domain_size, default_value);
|
||||
}
|
||||
|
||||
if (found_socket->type == SOCK_STRING) {
|
||||
const std::string name = this->get_input<std::string>(found_socket->identifier);
|
||||
/* Try getting the attribute without the default value. */
|
||||
GVArrayPtr attribute = component.attribute_try_get_for_read(name, domain, type);
|
||||
GVArray attribute = component.attribute_try_get_for_read(name, domain, type);
|
||||
if (attribute) {
|
||||
return attribute;
|
||||
}
|
||||
@@ -147,36 +147,36 @@ GVArrayPtr GeoNodeExecParams::get_input_attribute(const StringRef name,
|
||||
this->error_message_add(NodeWarningType::Error,
|
||||
TIP_("No attribute with name \"") + name + "\"");
|
||||
}
|
||||
return std::make_unique<fn::GVArray_For_SingleValue>(*cpp_type, domain_size, default_value);
|
||||
return GVArray::ForSingle(*cpp_type, domain_size, default_value);
|
||||
}
|
||||
const DataTypeConversions &conversions = get_implicit_type_conversions();
|
||||
if (found_socket->type == SOCK_FLOAT) {
|
||||
const float value = this->get_input<float>(found_socket->identifier);
|
||||
BUFFER_FOR_CPP_TYPE_VALUE(*cpp_type, buffer);
|
||||
conversions.convert_to_uninitialized(CPPType::get<float>(), *cpp_type, &value, buffer);
|
||||
return std::make_unique<fn::GVArray_For_SingleValue>(*cpp_type, domain_size, buffer);
|
||||
return GVArray::ForSingle(*cpp_type, domain_size, buffer);
|
||||
}
|
||||
if (found_socket->type == SOCK_INT) {
|
||||
const int value = this->get_input<int>(found_socket->identifier);
|
||||
BUFFER_FOR_CPP_TYPE_VALUE(*cpp_type, buffer);
|
||||
conversions.convert_to_uninitialized(CPPType::get<int>(), *cpp_type, &value, buffer);
|
||||
return std::make_unique<fn::GVArray_For_SingleValue>(*cpp_type, domain_size, buffer);
|
||||
return GVArray::ForSingle(*cpp_type, domain_size, buffer);
|
||||
}
|
||||
if (found_socket->type == SOCK_VECTOR) {
|
||||
const float3 value = this->get_input<float3>(found_socket->identifier);
|
||||
BUFFER_FOR_CPP_TYPE_VALUE(*cpp_type, buffer);
|
||||
conversions.convert_to_uninitialized(CPPType::get<float3>(), *cpp_type, &value, buffer);
|
||||
return std::make_unique<fn::GVArray_For_SingleValue>(*cpp_type, domain_size, buffer);
|
||||
return GVArray::ForSingle(*cpp_type, domain_size, buffer);
|
||||
}
|
||||
if (found_socket->type == SOCK_RGBA) {
|
||||
const ColorGeometry4f value = this->get_input<ColorGeometry4f>(found_socket->identifier);
|
||||
BUFFER_FOR_CPP_TYPE_VALUE(*cpp_type, buffer);
|
||||
conversions.convert_to_uninitialized(
|
||||
CPPType::get<ColorGeometry4f>(), *cpp_type, &value, buffer);
|
||||
return std::make_unique<fn::GVArray_For_SingleValue>(*cpp_type, domain_size, buffer);
|
||||
return GVArray::ForSingle(*cpp_type, domain_size, buffer);
|
||||
}
|
||||
BLI_assert(false);
|
||||
return std::make_unique<fn::GVArray_For_SingleValue>(*cpp_type, domain_size, default_value);
|
||||
return GVArray::ForSingle(*cpp_type, domain_size, default_value);
|
||||
}
|
||||
|
||||
CustomDataType GeoNodeExecParams::get_input_attribute_data_type(
|
||||
|
||||
@@ -24,9 +24,6 @@
|
||||
|
||||
namespace blender::nodes {
|
||||
|
||||
using fn::GVArrayPtr;
|
||||
using fn::GVMutableArray;
|
||||
using fn::GVMutableArrayPtr;
|
||||
using fn::MFDataType;
|
||||
|
||||
template<typename From, typename To, To (*ConversionF)(const From &)>
|
||||
@@ -242,107 +239,108 @@ void DataTypeConversions::convert_to_uninitialized(const CPPType &from_type,
|
||||
functions->convert_single_to_uninitialized(from_value, to_value);
|
||||
}
|
||||
|
||||
class GVArray_For_ConvertedGVArray : public GVArray {
|
||||
class GVArray_For_ConvertedGVArray : public fn::GVArrayImpl {
|
||||
private:
|
||||
GVArrayPtr varray_;
|
||||
fn::GVArray varray_;
|
||||
const CPPType &from_type_;
|
||||
ConversionFunctions old_to_new_conversions_;
|
||||
|
||||
public:
|
||||
GVArray_For_ConvertedGVArray(GVArrayPtr varray,
|
||||
GVArray_For_ConvertedGVArray(fn::GVArray varray,
|
||||
const CPPType &to_type,
|
||||
const DataTypeConversions &conversions)
|
||||
: GVArray(to_type, varray->size()), varray_(std::move(varray)), from_type_(varray_->type())
|
||||
: fn::GVArrayImpl(to_type, varray.size()),
|
||||
varray_(std::move(varray)),
|
||||
from_type_(varray_.type())
|
||||
{
|
||||
old_to_new_conversions_ = *conversions.get_conversion_functions(from_type_, to_type);
|
||||
}
|
||||
|
||||
private:
|
||||
void get_impl(const int64_t index, void *r_value) const override
|
||||
void get(const int64_t index, void *r_value) const override
|
||||
{
|
||||
BUFFER_FOR_CPP_TYPE_VALUE(from_type_, buffer);
|
||||
varray_->get(index, buffer);
|
||||
varray_.get(index, buffer);
|
||||
old_to_new_conversions_.convert_single_to_initialized(buffer, r_value);
|
||||
from_type_.destruct(buffer);
|
||||
}
|
||||
|
||||
void get_to_uninitialized_impl(const int64_t index, void *r_value) const override
|
||||
void get_to_uninitialized(const int64_t index, void *r_value) const override
|
||||
{
|
||||
BUFFER_FOR_CPP_TYPE_VALUE(from_type_, buffer);
|
||||
varray_->get(index, buffer);
|
||||
varray_.get(index, buffer);
|
||||
old_to_new_conversions_.convert_single_to_uninitialized(buffer, r_value);
|
||||
from_type_.destruct(buffer);
|
||||
}
|
||||
};
|
||||
|
||||
class GVMutableArray_For_ConvertedGVMutableArray : public GVMutableArray {
|
||||
class GVMutableArray_For_ConvertedGVMutableArray : public fn::GVMutableArrayImpl {
|
||||
private:
|
||||
GVMutableArrayPtr varray_;
|
||||
fn::GVMutableArray varray_;
|
||||
const CPPType &from_type_;
|
||||
ConversionFunctions old_to_new_conversions_;
|
||||
ConversionFunctions new_to_old_conversions_;
|
||||
|
||||
public:
|
||||
GVMutableArray_For_ConvertedGVMutableArray(GVMutableArrayPtr varray,
|
||||
GVMutableArray_For_ConvertedGVMutableArray(fn::GVMutableArray varray,
|
||||
const CPPType &to_type,
|
||||
const DataTypeConversions &conversions)
|
||||
: GVMutableArray(to_type, varray->size()),
|
||||
: fn::GVMutableArrayImpl(to_type, varray.size()),
|
||||
varray_(std::move(varray)),
|
||||
from_type_(varray_->type())
|
||||
from_type_(varray_.type())
|
||||
{
|
||||
old_to_new_conversions_ = *conversions.get_conversion_functions(from_type_, to_type);
|
||||
new_to_old_conversions_ = *conversions.get_conversion_functions(to_type, from_type_);
|
||||
}
|
||||
|
||||
private:
|
||||
void get_impl(const int64_t index, void *r_value) const override
|
||||
void get(const int64_t index, void *r_value) const override
|
||||
{
|
||||
BUFFER_FOR_CPP_TYPE_VALUE(from_type_, buffer);
|
||||
varray_->get(index, buffer);
|
||||
varray_.get(index, buffer);
|
||||
old_to_new_conversions_.convert_single_to_initialized(buffer, r_value);
|
||||
from_type_.destruct(buffer);
|
||||
}
|
||||
|
||||
void get_to_uninitialized_impl(const int64_t index, void *r_value) const override
|
||||
void get_to_uninitialized(const int64_t index, void *r_value) const override
|
||||
{
|
||||
BUFFER_FOR_CPP_TYPE_VALUE(from_type_, buffer);
|
||||
varray_->get(index, buffer);
|
||||
varray_.get(index, buffer);
|
||||
old_to_new_conversions_.convert_single_to_uninitialized(buffer, r_value);
|
||||
from_type_.destruct(buffer);
|
||||
}
|
||||
|
||||
void set_by_move_impl(const int64_t index, void *value) override
|
||||
void set_by_move(const int64_t index, void *value) override
|
||||
{
|
||||
BUFFER_FOR_CPP_TYPE_VALUE(from_type_, buffer);
|
||||
new_to_old_conversions_.convert_single_to_uninitialized(value, buffer);
|
||||
varray_->set_by_relocate(index, buffer);
|
||||
varray_.set_by_relocate(index, buffer);
|
||||
}
|
||||
};
|
||||
|
||||
fn::GVArrayPtr DataTypeConversions::try_convert(fn::GVArrayPtr varray,
|
||||
const CPPType &to_type) const
|
||||
fn::GVArray DataTypeConversions::try_convert(fn::GVArray varray, const CPPType &to_type) const
|
||||
{
|
||||
const CPPType &from_type = varray->type();
|
||||
const CPPType &from_type = varray.type();
|
||||
if (from_type == to_type) {
|
||||
return varray;
|
||||
}
|
||||
if (!this->is_convertible(from_type, to_type)) {
|
||||
return {};
|
||||
}
|
||||
return std::make_unique<GVArray_For_ConvertedGVArray>(std::move(varray), to_type, *this);
|
||||
return fn::GVArray::For<GVArray_For_ConvertedGVArray>(std::move(varray), to_type, *this);
|
||||
}
|
||||
|
||||
fn::GVMutableArrayPtr DataTypeConversions::try_convert(fn::GVMutableArrayPtr varray,
|
||||
const CPPType &to_type) const
|
||||
fn::GVMutableArray DataTypeConversions::try_convert(fn::GVMutableArray varray,
|
||||
const CPPType &to_type) const
|
||||
{
|
||||
const CPPType &from_type = varray->type();
|
||||
const CPPType &from_type = varray.type();
|
||||
if (from_type == to_type) {
|
||||
return varray;
|
||||
}
|
||||
if (!this->is_convertible(from_type, to_type)) {
|
||||
return {};
|
||||
}
|
||||
return std::make_unique<GVMutableArray_For_ConvertedGVMutableArray>(
|
||||
return fn::GVMutableArray::For<GVMutableArray_For_ConvertedGVMutableArray>(
|
||||
std::move(varray), to_type, *this);
|
||||
}
|
||||
|
||||
|
||||
@@ -199,28 +199,28 @@ class MusgraveFunction : public fn::MultiFunction {
|
||||
|
||||
void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
|
||||
{
|
||||
auto get_vector = [&](int param_index) -> const VArray<float3> & {
|
||||
auto get_vector = [&](int param_index) -> VArray<float3> {
|
||||
return params.readonly_single_input<float3>(param_index, "Vector");
|
||||
};
|
||||
auto get_w = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_w = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "W");
|
||||
};
|
||||
auto get_scale = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_scale = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "Scale");
|
||||
};
|
||||
auto get_detail = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_detail = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "Detail");
|
||||
};
|
||||
auto get_dimension = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_dimension = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "Dimension");
|
||||
};
|
||||
auto get_lacunarity = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_lacunarity = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "Lacunarity");
|
||||
};
|
||||
auto get_offset = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_offset = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "Offset");
|
||||
};
|
||||
auto get_gain = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_gain = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "Gain");
|
||||
};
|
||||
|
||||
|
||||
@@ -220,22 +220,22 @@ class VoronoiMinowskiFunction : public fn::MultiFunction {
|
||||
|
||||
void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
|
||||
{
|
||||
auto get_vector = [&](int param_index) -> const VArray<float3> & {
|
||||
auto get_vector = [&](int param_index) -> VArray<float3> {
|
||||
return params.readonly_single_input<float3>(param_index, "Vector");
|
||||
};
|
||||
auto get_w = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_w = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "W");
|
||||
};
|
||||
auto get_scale = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_scale = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "Scale");
|
||||
};
|
||||
auto get_smoothness = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_smoothness = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "Smoothness");
|
||||
};
|
||||
auto get_exponent = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_exponent = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "Exponent");
|
||||
};
|
||||
auto get_randomness = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_randomness = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "Randomness");
|
||||
};
|
||||
auto get_r_distance = [&](int param_index) -> MutableSpan<float> {
|
||||
@@ -651,19 +651,19 @@ class VoronoiMetricFunction : public fn::MultiFunction {
|
||||
|
||||
void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
|
||||
{
|
||||
auto get_vector = [&](int param_index) -> const VArray<float3> & {
|
||||
auto get_vector = [&](int param_index) -> VArray<float3> {
|
||||
return params.readonly_single_input<float3>(param_index, "Vector");
|
||||
};
|
||||
auto get_w = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_w = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "W");
|
||||
};
|
||||
auto get_scale = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_scale = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "Scale");
|
||||
};
|
||||
auto get_smoothness = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_smoothness = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "Smoothness");
|
||||
};
|
||||
auto get_randomness = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_randomness = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "Randomness");
|
||||
};
|
||||
auto get_r_distance = [&](int param_index) -> MutableSpan<float> {
|
||||
@@ -1153,16 +1153,16 @@ class VoronoiEdgeFunction : public fn::MultiFunction {
|
||||
|
||||
void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
|
||||
{
|
||||
auto get_vector = [&](int param_index) -> const VArray<float3> & {
|
||||
auto get_vector = [&](int param_index) -> VArray<float3> {
|
||||
return params.readonly_single_input<float3>(param_index, "Vector");
|
||||
};
|
||||
auto get_w = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_w = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "W");
|
||||
};
|
||||
auto get_scale = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_scale = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "Scale");
|
||||
};
|
||||
auto get_randomness = [&](int param_index) -> const VArray<float> & {
|
||||
auto get_randomness = [&](int param_index) -> VArray<float> {
|
||||
return params.readonly_single_input<float>(param_index, "Randomness");
|
||||
};
|
||||
auto get_r_distance = [&](int param_index) -> MutableSpan<float> {
|
||||
|
||||
Reference in New Issue
Block a user