Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/BKE_geometry_set.hh')
-rw-r--r--source/blender/blenkernel/BKE_geometry_set.hh353
1 files changed, 219 insertions, 134 deletions
diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh
index d94b2e7902b..3b3856f11ab 100644
--- a/source/blender/blenkernel/BKE_geometry_set.hh
+++ b/source/blender/blenkernel/BKE_geometry_set.hh
@@ -25,11 +25,11 @@
#include "BLI_float3.hh"
#include "BLI_float4x4.hh"
-#include "BLI_function_ref.hh"
#include "BLI_hash.hh"
#include "BLI_map.hh"
#include "BLI_set.hh"
#include "BLI_user_counter.hh"
+#include "BLI_vector_set.hh"
#include "BKE_attribute_access.hh"
#include "BKE_geometry_set.h"
@@ -39,6 +39,7 @@ struct Mesh;
struct Object;
struct PointCloud;
struct Volume;
+class CurveEval;
enum class GeometryOwnershipType {
/* The geometry is owned. This implies that it can be changed. */
@@ -56,74 +57,6 @@ class ComponentAttributeProviders;
class GeometryComponent;
/**
- * An #OutputAttributePtr wraps a #WriteAttributePtr that might not be stored in its final
- * destination yet. Therefore, once the attribute has been filled with data, the #save method has
- * to be called, to store the attribute where it belongs (possibly by replacing an existing
- * attribute with the same name).
- *
- * This is useful for example in the Attribute Color Ramp node, when the same attribute name is
- * used as input and output. Typically the input is a float attribute, and the output is a color.
- * Those two attributes cannot exist at the same time, due to a name collision. To handle this
- * situation well, first the output colors have to be computed before the input floats are deleted.
- * Therefore, the outputs have to be written to a temporary buffer that replaces the existing
- * attribute once all computations are done.
- */
-class OutputAttributePtr {
- private:
- blender::bke::WriteAttributePtr attribute_;
-
- public:
- OutputAttributePtr() = default;
- OutputAttributePtr(blender::bke::WriteAttributePtr attribute);
- OutputAttributePtr(GeometryComponent &component,
- AttributeDomain domain,
- std::string name,
- CustomDataType data_type);
-
- ~OutputAttributePtr();
-
- /* Returns false, when this wrapper is empty. */
- operator bool() const
- {
- return static_cast<bool>(attribute_);
- }
-
- /* Get a reference to the underlying #WriteAttribute. */
- blender::bke::WriteAttribute &get()
- {
- BLI_assert(attribute_);
- return *attribute_;
- }
-
- blender::bke::WriteAttribute &operator*()
- {
- return *attribute_;
- }
-
- blender::bke::WriteAttribute *operator->()
- {
- return attribute_.get();
- }
-
- void save();
- void apply_span_and_save();
-};
-
-/**
- * Contains information about an attribute in a geometry component.
- * More information can be added in the future. E.g. whether the attribute is builtin and how it is
- * stored (uv map, vertex group, ...).
- */
-struct AttributeMetaData {
- AttributeDomain domain;
- CustomDataType data_type;
-};
-
-/* Returns false when the iteration should be stopped. */
-using AttributeForeachCallback = blender::FunctionRef<bool(blender::StringRefNull attribute_name,
- const AttributeMetaData &meta_data)>;
-
-/**
* This is the base class for specialized geometry component types.
*/
class GeometryComponent {
@@ -156,26 +89,34 @@ class GeometryComponent {
/* Return true when any attribute with this name exists, including built in attributes. */
bool attribute_exists(const blender::StringRef attribute_name) const;
+ /* Return the data type and domain of an attribute with the given name if it exists. */
+ std::optional<AttributeMetaData> attribute_get_meta_data(
+ const blender::StringRef attribute_name) const;
+
/* Returns true when the geometry component supports this attribute domain. */
bool attribute_domain_supported(const AttributeDomain domain) const;
/* Can only be used with supported domain types. */
virtual int attribute_domain_size(const AttributeDomain domain) const;
+ bool attribute_is_builtin(const blender::StringRef attribute_name) const;
+
/* Get read-only access to the highest priority attribute with the given name.
* Returns null if the attribute does not exist. */
- blender::bke::ReadAttributePtr attribute_try_get_for_read(
+ blender::bke::ReadAttributeLookup attribute_try_get_for_read(
const blender::StringRef attribute_name) const;
/* Get read and write access to the highest priority attribute with the given name.
* Returns null if the attribute does not exist. */
- blender::bke::WriteAttributePtr attribute_try_get_for_write(
+ blender::bke::WriteAttributeLookup attribute_try_get_for_write(
const blender::StringRef attribute_name);
/* 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 blender::bke::ReadAttributePtr attribute_try_adapt_domain(
- blender::bke::ReadAttributePtr attribute, const AttributeDomain new_domain) const;
+ 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;
/* Returns true when the attribute has been deleted. */
bool attribute_try_delete(const blender::StringRef attribute_name);
@@ -183,82 +124,104 @@ class GeometryComponent {
/* Returns true when the attribute has been created. */
bool attribute_try_create(const blender::StringRef attribute_name,
const AttributeDomain domain,
- const CustomDataType data_type);
+ const CustomDataType data_type,
+ const AttributeInit &initializer);
+
+ /* Try to create the builtin attribute with the given name. No data type or domain has to be
+ * provided, because those are fixed for builtin attributes. */
+ bool attribute_try_create_builtin(const blender::StringRef attribute_name,
+ const AttributeInit &initializer);
blender::Set<std::string> attribute_names() const;
bool attribute_foreach(const AttributeForeachCallback callback) const;
virtual bool is_empty() const;
- /* Get a read-only attribute for the given domain and data type.
- * Returns null when it does not exist. */
- blender::bke::ReadAttributePtr attribute_try_get_for_read(
+ /* 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::StringRef attribute_name,
const AttributeDomain domain,
const CustomDataType data_type) const;
- /* Get a read-only attribute interpolated to the input domain, leaving the data type unchanged.
- * Returns null when the attribute does not exist. */
- blender::bke::ReadAttributePtr attribute_try_get_for_read(
+ /* 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::StringRef attribute_name, const AttributeDomain domain) const;
- /* Get a read-only attribute for the given domain and data type.
- * Returns a constant attribute based on the default value if the attribute does not exist.
- * Never returns null. */
- blender::bke::ReadAttributePtr attribute_get_for_read(const blender::StringRef attribute_name,
- const AttributeDomain domain,
- const CustomDataType data_type,
- const void *default_value) 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
+ * requested data type. */
+ blender::bke::ReadAttributeLookup attribute_try_get_for_read(
+ const blender::StringRef attribute_name, const CustomDataType data_type) const;
- /* Get a typed read-only attribute for the given domain and type. */
- template<typename T>
- blender::bke::TypedReadAttribute<T> attribute_get_for_read(
+ /* 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::StringRef attribute_name,
const AttributeDomain domain,
- const T &default_value) const
+ 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::StringRef attribute_name,
+ 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);
- return this->attribute_get_for_read(attribute_name, domain, type, &default_value);
+ std::unique_ptr varray = this->attribute_get_for_read(
+ attribute_name, domain, type, &default_value);
+ return blender::fn::GVArray_Typed<T>(std::move(varray));
}
- /* Get a read-only dummy attribute that always returns the same value. */
- blender::bke::ReadAttributePtr attribute_get_constant_for_read(const AttributeDomain domain,
- const CustomDataType data_type,
- const void *value) const;
+ /**
+ * Returns an "output attribute", which is essentially a mutable virtual array with some commonly
+ * used convince features. The returned output attribute might be empty if requested attribute
+ * cannot exist on the geometry.
+ *
+ * The included convenience features are:
+ * - Implicit type conversion when writing to builtin attributes.
+ * - If the attribute name exists already, but has a different type/domain, a temporary attribute
+ * is created that will overwrite the existing attribute in the end.
+ */
+ blender::bke::OutputAttribute attribute_try_get_for_output(
+ const blender::StringRef attribute_name,
+ const AttributeDomain domain,
+ const CustomDataType data_type,
+ const void *default_value = nullptr);
- /* Create a read-only dummy attribute that always returns the same value.
- * The given value is converted to the correct type if necessary. */
- blender::bke::ReadAttributePtr attribute_get_constant_for_read_converted(
+ /* Same as attribute_try_get_for_output, but should be used when the original values in the
+ * attributes are not read, i.e. the attribute is used only for output. Since values are not read
+ * from this attribute, no default value is necessary. */
+ blender::bke::OutputAttribute attribute_try_get_for_output_only(
+ const blender::StringRef attribute_name,
const AttributeDomain domain,
- const CustomDataType in_data_type,
- const CustomDataType out_data_type,
- const void *value) const;
+ const CustomDataType data_type);
- /* Get a read-only dummy attribute that always returns the same value. */
+ /* Statically typed method corresponding to the equally named generic one. */
template<typename T>
- blender::bke::TypedReadAttribute<T> attribute_get_constant_for_read(const AttributeDomain domain,
- const T &value) const
+ blender::bke::OutputAttribute_Typed<T> attribute_try_get_for_output(
+ const blender::StringRef attribute_name, const AttributeDomain domain, const T default_value)
{
const blender::fn::CPPType &cpp_type = blender::fn::CPPType::get<T>();
- const CustomDataType type = blender::bke::cpp_type_to_custom_data_type(cpp_type);
- return this->attribute_get_constant_for_read(domain, type, &value);
+ const CustomDataType data_type = blender::bke::cpp_type_to_custom_data_type(cpp_type);
+ return this->attribute_try_get_for_output(attribute_name, domain, data_type, &default_value);
}
- /**
- * If an attribute with the given params exist, it is returned.
- * If no attribute with the given name exists, create it and
- * fill it with the default value if it is provided.
- * If an attribute with the given name but different domain or type exists, a temporary attribute
- * is created that has to be saved after the output has been computed. This avoids deleting
- * another attribute, before a computation is finished.
- *
- * This might return no attribute when the attribute cannot exist on the component.
- */
- OutputAttributePtr attribute_try_get_for_output(const blender::StringRef attribute_name,
- const AttributeDomain domain,
- const CustomDataType data_type,
- const void *default_value = nullptr);
+ /* Statically typed method corresponding to the equally named generic one. */
+ template<typename T>
+ blender::bke::OutputAttribute_Typed<T> attribute_try_get_for_output_only(
+ const blender::StringRef attribute_name, const AttributeDomain domain)
+ {
+ const blender::fn::CPPType &cpp_type = blender::fn::CPPType::get<T>();
+ const CustomDataType data_type = blender::bke::cpp_type_to_custom_data_type(cpp_type);
+ return this->attribute_try_get_for_output_only(attribute_name, domain, data_type);
+ }
private:
virtual const blender::bke::ComponentAttributeProviders *get_attribute_providers() const;
@@ -328,23 +291,34 @@ struct GeometrySet {
Mesh *mesh, GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
static GeometrySet create_with_pointcloud(
PointCloud *pointcloud, GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
+ static GeometrySet create_with_curve(
+ CurveEval *curve, GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
/* Utility methods for access. */
bool has_mesh() const;
bool has_pointcloud() const;
bool has_instances() const;
bool has_volume() const;
+ bool has_curve() const;
+
const Mesh *get_mesh_for_read() const;
const PointCloud *get_pointcloud_for_read() const;
const Volume *get_volume_for_read() const;
+ const CurveEval *get_curve_for_read() const;
+
Mesh *get_mesh_for_write();
PointCloud *get_pointcloud_for_write();
Volume *get_volume_for_write();
+ CurveEval *get_curve_for_write();
/* Utility methods for replacement. */
void replace_mesh(Mesh *mesh, GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
void replace_pointcloud(PointCloud *pointcloud,
GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
+ void replace_volume(Volume *volume,
+ GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
+ void replace_curve(CurveEval *curve,
+ GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
};
/** A geometry component that can store a mesh. */
@@ -377,8 +351,10 @@ class MeshComponent : public GeometryComponent {
Mesh *get_for_write();
int attribute_domain_size(const AttributeDomain domain) const final;
- blender::bke::ReadAttributePtr attribute_try_adapt_domain(
- blender::bke::ReadAttributePtr attribute, const AttributeDomain new_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;
@@ -424,12 +400,113 @@ class PointCloudComponent : public GeometryComponent {
const blender::bke::ComponentAttributeProviders *get_attribute_providers() const final;
};
+/** A geometry component that stores curve data, in other words, a group of splines. */
+class CurveComponent : public GeometryComponent {
+ private:
+ CurveEval *curve_ = nullptr;
+ GeometryOwnershipType ownership_ = GeometryOwnershipType::Owned;
+
+ public:
+ CurveComponent();
+ ~CurveComponent();
+ GeometryComponent *copy() const override;
+
+ void clear();
+ bool has_curve() const;
+ void replace(CurveEval *curve, GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
+ CurveEval *release();
+
+ const CurveEval *get_for_read() const;
+ CurveEval *get_for_write();
+
+ int attribute_domain_size(const AttributeDomain domain) const final;
+
+ bool is_empty() const final;
+
+ bool owns_direct_data() const override;
+ void ensure_owns_direct_data() override;
+
+ static constexpr inline GeometryComponentType static_type = GEO_COMPONENT_TYPE_CURVE;
+
+ private:
+ const blender::bke::ComponentAttributeProviders *get_attribute_providers() const final;
+};
+
+class InstanceReference {
+ public:
+ enum class Type {
+ /**
+ * An empty instance. This allows an `InstanceReference` to be default constructed without
+ * being in an invalid state. There might also be other use cases that we haven't explored much
+ * yet (such as changing the instance later on, and "disabling" some instances).
+ */
+ None,
+ Object,
+ Collection,
+ };
+
+ private:
+ Type type_ = Type::None;
+ /** Depending on the type this is either null, an Object or Collection pointer. */
+ void *data_ = nullptr;
+
+ public:
+ InstanceReference() = default;
+
+ InstanceReference(Object &object) : type_(Type::Object), data_(&object)
+ {
+ }
+
+ InstanceReference(Collection &collection) : type_(Type::Collection), data_(&collection)
+ {
+ }
+
+ Type type() const
+ {
+ return type_;
+ }
+
+ Object &object() const
+ {
+ BLI_assert(type_ == Type::Object);
+ return *(Object *)data_;
+ }
+
+ Collection &collection() const
+ {
+ BLI_assert(type_ == Type::Collection);
+ return *(Collection *)data_;
+ }
+
+ uint64_t hash() const
+ {
+ return blender::get_default_hash(data_);
+ }
+
+ friend bool operator==(const InstanceReference &a, const InstanceReference &b)
+ {
+ return a.data_ == b.data_;
+ }
+};
+
/** A geometry component that stores instances. */
class InstancesComponent : public GeometryComponent {
private:
- blender::Vector<blender::float4x4> transforms_;
- blender::Vector<int> ids_;
- blender::Vector<InstancedData> instanced_data_;
+ /**
+ * Indexed set containing information about the data that is instanced.
+ * Actual instances store an index ("handle") into this set.
+ */
+ blender::VectorSet<InstanceReference> references_;
+
+ /** Index into `references_`. Determines what data is instanced. */
+ blender::Vector<int> instance_reference_handles_;
+ /** Transformation of the instances. */
+ blender::Vector<blender::float4x4> instance_transforms_;
+ /**
+ * IDs of the instances. They are used for consistency over multiple frames for things like
+ * motion blur.
+ */
+ blender::Vector<int> instance_ids_;
/* These almost unique ids are generated based on `ids_`, which might not contain unique ids at
* all. They are *almost* unique, because under certain very unlikely circumstances, they are not
@@ -444,14 +521,22 @@ class InstancesComponent : public GeometryComponent {
GeometryComponent *copy() const override;
void clear();
- void add_instance(Object *object, blender::float4x4 transform, const int id = -1);
- void add_instance(Collection *collection, blender::float4x4 transform, const int id = -1);
- void add_instance(InstancedData data, blender::float4x4 transform, const int id = -1);
-
- blender::Span<InstancedData> instanced_data() const;
- blender::Span<blender::float4x4> transforms() const;
- blender::Span<int> ids() const;
- blender::MutableSpan<blender::float4x4> transforms();
+
+ void reserve(int min_capacity);
+ void resize(int capacity);
+
+ int add_reference(InstanceReference reference);
+ void add_instance(int instance_handle, const blender::float4x4 &transform, const int id = -1);
+
+ blender::Span<InstanceReference> references() const;
+
+ blender::Span<int> instance_reference_handles() const;
+ blender::MutableSpan<int> instance_reference_handles();
+ blender::MutableSpan<blender::float4x4> instance_transforms();
+ blender::Span<blender::float4x4> instance_transforms() const;
+ blender::MutableSpan<int> instance_ids();
+ blender::Span<int> instance_ids() const;
+
int instances_amount() const;
blender::Span<int> almost_unique_ids() const;