Blender  V2.93
BKE_geometry_set.hh
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
17 #pragma once
18 
23 #include <atomic>
24 #include <iostream>
25 
26 #include "BLI_float3.hh"
27 #include "BLI_float4x4.hh"
28 #include "BLI_function_ref.hh"
29 #include "BLI_hash.hh"
30 #include "BLI_map.hh"
31 #include "BLI_set.hh"
32 #include "BLI_user_counter.hh"
33 
34 #include "BKE_attribute_access.hh"
35 #include "BKE_geometry_set.h"
36 
37 struct Collection;
38 struct Mesh;
39 struct Object;
40 struct PointCloud;
41 struct Volume;
42 
44  /* The geometry is owned. This implies that it can be changed. */
45  Owned = 0,
46  /* The geometry can be changed, but someone else is responsible for freeing it. */
47  Editable = 1,
48  /* The geometry cannot be changed and someone else is responsible for freeing it. */
49  ReadOnly = 2,
50 };
51 
52 namespace blender::bke {
53 class ComponentAttributeProviders;
54 }
55 
56 class GeometryComponent;
57 
72  private:
74 
75  public:
76  OutputAttributePtr() = default;
79  AttributeDomain domain,
80  std::string name,
81  CustomDataType data_type);
82 
84 
85  /* Returns false, when this wrapper is empty. */
86  operator bool() const
87  {
88  return static_cast<bool>(attribute_);
89  }
90 
91  /* Get a reference to the underlying #WriteAttribute. */
93  {
94  BLI_assert(attribute_);
95  return *attribute_;
96  }
97 
99  {
100  return *attribute_;
101  }
102 
104  {
105  return attribute_.get();
106  }
107 
108  void save();
109  void apply_span_and_save();
110 };
111 
120 };
121 
122 /* Returns false when the iteration should be stopped. */
124  const AttributeMetaData &meta_data)>;
125 
130  private:
131  /* The reference count has two purposes. When it becomes zero, the component is freed. When it is
132  * larger than one, the component becomes immutable. */
133  mutable std::atomic<int> users_ = 1;
134  GeometryComponentType type_;
135 
136  public:
138  virtual ~GeometryComponent() = default;
139  static GeometryComponent *create(GeometryComponentType component_type);
140 
141  /* The returned component should be of the same type as the type this is called on. */
142  virtual GeometryComponent *copy() const = 0;
143 
144  /* Direct data is everything except for instances of objects/collections.
145  * If this returns true, the geometry set can be cached and is still valid after e.g. modifier
146  * evaluation ends. Instances can only be valid as long as the data they instance is valid. */
147  virtual bool owns_direct_data() const = 0;
148  virtual void ensure_owns_direct_data() = 0;
149 
150  void user_add() const;
151  void user_remove() const;
152  bool is_mutable() const;
153 
154  GeometryComponentType type() const;
155 
156  /* Return true when any attribute with this name exists, including built in attributes. */
157  bool attribute_exists(const blender::StringRef attribute_name) const;
158 
159  /* Returns true when the geometry component supports this attribute domain. */
160  bool attribute_domain_supported(const AttributeDomain domain) const;
161  /* Can only be used with supported domain types. */
162  virtual int attribute_domain_size(const AttributeDomain domain) const;
163 
164  /* Get read-only access to the highest priority attribute with the given name.
165  * Returns null if the attribute does not exist. */
167  const blender::StringRef attribute_name) const;
168 
169  /* Get read and write access to the highest priority attribute with the given name.
170  * Returns null if the attribute does not exist. */
172  const blender::StringRef attribute_name);
173 
174  /* Get a read-only attribute for the domain based on the given attribute. This can be used to
175  * interpolate from one domain to another.
176  * Returns null if the interpolation is not implemented. */
178  blender::bke::ReadAttributePtr attribute, const AttributeDomain new_domain) const;
179 
180  /* Returns true when the attribute has been deleted. */
181  bool attribute_try_delete(const blender::StringRef attribute_name);
182 
183  /* Returns true when the attribute has been created. */
184  bool attribute_try_create(const blender::StringRef attribute_name,
185  const AttributeDomain domain,
186  const CustomDataType data_type);
187 
190 
191  virtual bool is_empty() const;
192 
193  /* Get a read-only attribute for the given domain and data type.
194  * Returns null when it does not exist. */
196  const blender::StringRef attribute_name,
197  const AttributeDomain domain,
198  const CustomDataType data_type) const;
199 
200  /* Get a read-only attribute interpolated to the input domain, leaving the data type unchanged.
201  * Returns null when the attribute does not exist. */
203  const blender::StringRef attribute_name, const AttributeDomain domain) const;
204 
205  /* Get a read-only attribute for the given domain and data type.
206  * Returns a constant attribute based on the default value if the attribute does not exist.
207  * Never returns null. */
209  const AttributeDomain domain,
210  const CustomDataType data_type,
211  const void *default_value) const;
212 
213  /* Get a typed read-only attribute for the given domain and type. */
214  template<typename T>
216  const blender::StringRef attribute_name,
217  const AttributeDomain domain,
218  const T &default_value) const
219  {
220  const blender::fn::CPPType &cpp_type = blender::fn::CPPType::get<T>();
222  return this->attribute_get_for_read(attribute_name, domain, type, &default_value);
223  }
224 
225  /* Get a read-only dummy attribute that always returns the same value. */
227  const CustomDataType data_type,
228  const void *value) const;
229 
230  /* Create a read-only dummy attribute that always returns the same value.
231  * The given value is converted to the correct type if necessary. */
233  const AttributeDomain domain,
234  const CustomDataType in_data_type,
235  const CustomDataType out_data_type,
236  const void *value) const;
237 
238  /* Get a read-only dummy attribute that always returns the same value. */
239  template<typename T>
241  const T &value) const
242  {
243  const blender::fn::CPPType &cpp_type = blender::fn::CPPType::get<T>();
245  return this->attribute_get_constant_for_read(domain, type, &value);
246  }
247 
259  const AttributeDomain domain,
260  const CustomDataType data_type,
261  const void *default_value = nullptr);
262 
263  private:
264  virtual const blender::bke::ComponentAttributeProviders *get_attribute_providers() const;
265 };
266 
267 template<typename T>
268 inline constexpr bool is_geometry_component_v = std::is_base_of_v<GeometryComponent, T>;
269 
278 struct GeometrySet {
279  private:
282 
283  public:
285  template<typename Component> Component &get_component_for_write()
286  {
287  BLI_STATIC_ASSERT(is_geometry_component_v<Component>, "");
288  return static_cast<Component &>(this->get_component_for_write(Component::static_type));
289  }
290 
292  template<typename Component> const Component *get_component_for_read() const
293  {
294  BLI_STATIC_ASSERT(is_geometry_component_v<Component>, "");
295  return static_cast<const Component *>(get_component_for_read(Component::static_type));
296  }
297 
298  bool has(const GeometryComponentType component_type) const;
299  template<typename Component> bool has() const
300  {
301  BLI_STATIC_ASSERT(is_geometry_component_v<Component>, "");
302  return this->has(Component::static_type);
303  }
304 
305  void remove(const GeometryComponentType component_type);
306  template<typename Component> void remove()
307  {
308  BLI_STATIC_ASSERT(is_geometry_component_v<Component>, "");
309  return this->remove(Component::static_type);
310  }
311 
312  void add(const GeometryComponent &component);
313 
315 
317 
318  friend std::ostream &operator<<(std::ostream &stream, const GeometrySet &geometry_set);
319  friend bool operator==(const GeometrySet &a, const GeometrySet &b);
320  uint64_t hash() const;
321 
322  void clear();
323 
325 
326  /* Utility methods for creation. */
331 
332  /* Utility methods for access. */
333  bool has_mesh() const;
334  bool has_pointcloud() const;
335  bool has_instances() const;
336  bool has_volume() const;
337  const Mesh *get_mesh_for_read() const;
338  const PointCloud *get_pointcloud_for_read() const;
339  const Volume *get_volume_for_read() const;
343 
344  /* Utility methods for replacement. */
346  void replace_pointcloud(PointCloud *pointcloud,
348 };
349 
352  private:
353  Mesh *mesh_ = nullptr;
355  /* Due to historical design choices, vertex group data is stored in the mesh, but the vertex
356  * group names are stored on an object. Since we don't have an object here, we copy over the
357  * names into this map. */
358  blender::Map<std::string, int> vertex_group_names_;
359 
360  public:
361  MeshComponent();
362  ~MeshComponent();
363  GeometryComponent *copy() const override;
364 
365  void clear();
366  bool has_mesh() const;
370  Mesh *release();
371 
372  void copy_vertex_group_names_from_object(const struct Object &object);
375 
376  const Mesh *get_for_read() const;
377  Mesh *get_for_write();
378 
379  int attribute_domain_size(const AttributeDomain domain) const final;
381  blender::bke::ReadAttributePtr attribute, const AttributeDomain new_domain) const final;
382 
383  bool is_empty() const final;
384 
385  bool owns_direct_data() const override;
386  void ensure_owns_direct_data() override;
387 
389 
390  private:
391  const blender::bke::ComponentAttributeProviders *get_attribute_providers() const final;
392 };
393 
396  private:
397  PointCloud *pointcloud_ = nullptr;
399 
400  public:
403  GeometryComponent *copy() const override;
404 
405  void clear();
406  bool has_pointcloud() const;
407  void replace(PointCloud *pointcloud,
409  PointCloud *release();
410 
411  const PointCloud *get_for_read() const;
413 
414  int attribute_domain_size(const AttributeDomain domain) const final;
415 
416  bool is_empty() const final;
417 
418  bool owns_direct_data() const override;
419  void ensure_owns_direct_data() override;
420 
422 
423  private:
424  const blender::bke::ComponentAttributeProviders *get_attribute_providers() const final;
425 };
426 
429  private:
432  blender::Vector<InstancedData> instanced_data_;
433 
434  /* These almost unique ids are generated based on `ids_`, which might not contain unique ids at
435  * all. They are *almost* unique, because under certain very unlikely circumstances, they are not
436  * unique. Code using these ids should not crash when they are not unique but can generally
437  * expect them to be unique. */
438  mutable std::mutex almost_unique_ids_mutex_;
439  mutable blender::Array<int> almost_unique_ids_;
440 
441  public:
443  ~InstancesComponent() = default;
444  GeometryComponent *copy() const override;
445 
446  void clear();
447  void add_instance(Object *object, blender::float4x4 transform, const int id = -1);
448  void add_instance(Collection *collection, blender::float4x4 transform, const int id = -1);
449  void add_instance(InstancedData data, blender::float4x4 transform, const int id = -1);
450 
451  blender::Span<InstancedData> instanced_data() const;
452  blender::Span<blender::float4x4> transforms() const;
453  blender::Span<int> ids() const;
455  int instances_amount() const;
456 
457  blender::Span<int> almost_unique_ids() const;
458 
459  bool is_empty() const final;
460 
461  bool owns_direct_data() const override;
463 
465 };
466 
469  private:
470  Volume *volume_ = nullptr;
472 
473  public:
474  VolumeComponent();
475  ~VolumeComponent();
476  GeometryComponent *copy() const override;
477 
478  void clear();
479  bool has_volume() const;
481  Volume *release();
482 
483  const Volume *get_for_read() const;
485 
486  bool owns_direct_data() const override;
487  void ensure_owns_direct_data() override;
488 
490 };
AttributeDomain
Definition: BKE_attribute.h:41
GeometryComponentType
@ GEO_COMPONENT_TYPE_MESH
@ GEO_COMPONENT_TYPE_POINT_CLOUD
@ GEO_COMPONENT_TYPE_INSTANCES
@ GEO_COMPONENT_TYPE_VOLUME
GeometryOwnershipType
constexpr bool is_geometry_component_v
#define BLI_STATIC_ASSERT(a, msg)
Definition: BLI_assert.h:86
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define final(a, b, c)
Definition: BLI_hash.h:35
ThreadMutex mutex
static uint8 component(Color32 c, uint i)
Definition: ColorBlock.cpp:126
CustomDataType
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
virtual blender::bke::ReadAttributePtr attribute_try_adapt_domain(blender::bke::ReadAttributePtr attribute, const AttributeDomain new_domain) const
void user_add() const
Definition: geometry_set.cc:68
virtual int attribute_domain_size(const AttributeDomain domain) const
virtual bool is_empty() const
Definition: geometry_set.cc:93
virtual void ensure_owns_direct_data()=0
GeometryComponent(GeometryComponentType type)
Definition: geometry_set.cc:48
blender::bke::WriteAttributePtr attribute_try_get_for_write(const blender::StringRef attribute_name)
bool attribute_exists(const blender::StringRef attribute_name) const
blender::bke::ReadAttributePtr attribute_get_constant_for_read(const AttributeDomain domain, const CustomDataType data_type, const void *value) const
virtual ~GeometryComponent()=default
blender::Set< std::string > attribute_names() const
static GeometryComponent * create(GeometryComponentType component_type)
Definition: geometry_set.cc:52
bool attribute_try_delete(const blender::StringRef attribute_name)
blender::bke::ReadAttributePtr attribute_try_get_for_read(const blender::StringRef attribute_name) const
OutputAttributePtr attribute_try_get_for_output(const blender::StringRef attribute_name, const AttributeDomain domain, const CustomDataType data_type, const void *default_value=nullptr)
bool attribute_foreach(const AttributeForeachCallback callback) const
blender::bke::TypedReadAttribute< T > attribute_get_for_read(const blender::StringRef attribute_name, const AttributeDomain domain, const T &default_value) const
GeometryComponentType type() const
Definition: geometry_set.cc:88
blender::bke::ReadAttributePtr attribute_get_constant_for_read_converted(const AttributeDomain domain, const CustomDataType in_data_type, const CustomDataType out_data_type, const void *value) const
void user_remove() const
Definition: geometry_set.cc:73
blender::bke::TypedReadAttribute< T > attribute_get_constant_for_read(const AttributeDomain domain, const T &value) const
blender::bke::ReadAttributePtr attribute_get_for_read(const blender::StringRef attribute_name, const AttributeDomain domain, const CustomDataType data_type, const void *default_value) const
bool is_mutable() const
Definition: geometry_set.cc:81
virtual GeometryComponent * copy() const =0
virtual bool owns_direct_data() const =0
bool attribute_try_create(const blender::StringRef attribute_name, const AttributeDomain domain, const CustomDataType data_type)
bool attribute_domain_supported(const AttributeDomain domain) const
~InstancesComponent()=default
const Mesh * get_for_read() const
void replace_mesh_but_keep_vertex_group_names(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
bool is_empty() const final
void replace(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
void copy_vertex_group_names_from_object(const struct Object &object)
GeometryComponent * copy() const override
bool owns_direct_data() const override
void ensure_owns_direct_data() override
static constexpr GeometryComponentType static_type
blender::bke::ReadAttributePtr attribute_try_adapt_domain(blender::bke::ReadAttributePtr attribute, const AttributeDomain new_domain) const final
const blender::Map< std::string, int > & vertex_group_names() const
int attribute_domain_size(const AttributeDomain domain) const final
blender::bke::WriteAttribute * operator->()
OutputAttributePtr()=default
OutputAttributePtr(blender::bke::WriteAttributePtr attribute)
blender::bke::WriteAttribute & get()
blender::bke::WriteAttribute & operator*()
void get(const int64_t index, void *r_value) const
DEGForeachIDComponentCallback callback
#define T
static unsigned a[3]
Definition: RandGen.cpp:92
CustomDataType cpp_type_to_custom_data_type(const CPPType &type)
std::unique_ptr< WriteAttribute > WriteAttributePtr
std::unique_ptr< ReadAttribute > ReadAttributePtr
Set< ID * > ids_
unsigned __int64 uint64_t
Definition: stdint.h:93
CustomDataType data_type
AttributeDomain domain
const PointCloud * get_pointcloud_for_read() const
bool has_volume() const
void replace_mesh(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
blender::Vector< const GeometryComponent * > get_components_for_read() const
void compute_boundbox_without_instances(blender::float3 *r_min, blender::float3 *r_max) const
void ensure_owns_direct_data()
const Volume * get_volume_for_read() const
static GeometrySet create_with_mesh(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
Component & get_component_for_write()
PointCloud * get_pointcloud_for_write()
const Mesh * get_mesh_for_read() const
friend std::ostream & operator<<(std::ostream &stream, const GeometrySet &geometry_set)
Mesh * get_mesh_for_write()
void add(const GeometryComponent &component)
bool has_instances() const
static GeometrySet create_with_pointcloud(PointCloud *pointcloud, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
bool has_mesh() const
friend bool operator==(const GeometrySet &a, const GeometrySet &b)
Volume * get_volume_for_write()
void replace_pointcloud(PointCloud *pointcloud, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
const Component * get_component_for_read() const
bool has() const
uint64_t hash() const
bool has_pointcloud() const
bool override
Definition: wm_files.c:854