Blender  V3.3
geometry_set.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include "BLI_bounds.hh"
4 #include "BLI_map.hh"
5 #include "BLI_task.hh"
6 
7 #include "BLT_translation.h"
8 
9 #include "BKE_attribute.h"
10 #include "BKE_curves.hh"
11 #include "BKE_geometry_fields.hh"
12 #include "BKE_geometry_set.hh"
13 #include "BKE_lib_id.h"
14 #include "BKE_mesh.h"
15 #include "BKE_mesh_wrapper.h"
16 #include "BKE_modifier.h"
17 #include "BKE_pointcloud.h"
18 #include "BKE_volume.h"
19 
20 #include "DNA_collection_types.h"
21 #include "DNA_object_types.h"
22 
23 #include "BLI_rand.hh"
24 
25 #include "MEM_guardedalloc.h"
26 
27 using blender::float3;
28 using blender::float4x4;
29 using blender::Map;
31 using blender::Span;
32 using blender::StringRef;
33 using blender::Vector;
34 
35 /* -------------------------------------------------------------------- */
40 {
41 }
42 
44 {
45  switch (component_type) {
47  return new MeshComponent();
49  return new PointCloudComponent();
51  return new InstancesComponent();
53  return new VolumeComponent();
55  return new CurveComponent();
57  return new GeometryComponentEditData();
58  }
60  return nullptr;
61 }
62 
64 {
65  if (this->is_empty()) {
66  return 0;
67  }
68  const std::optional<blender::bke::AttributeAccessor> attributes = this->attributes();
69  if (attributes.has_value()) {
70  return attributes->domain_size(domain);
71  }
72  return 0;
73 }
74 
75 std::optional<blender::bke::AttributeAccessor> GeometryComponent::attributes() const
76 {
77  return std::nullopt;
78 };
79 std::optional<blender::bke::MutableAttributeAccessor> GeometryComponent::attributes_for_write()
80 {
81  return std::nullopt;
82 }
83 
85 {
86  users_.fetch_add(1);
87 }
88 
90 {
91  const int new_users = users_.fetch_sub(1) - 1;
92  if (new_users == 0) {
93  delete this;
94  }
95 }
96 
98 {
99  /* If the item is shared, it is read-only. */
100  /* The user count can be 0, when this is called from the destructor. */
101  return users_ <= 1;
102 }
103 
105 {
106  return type_;
107 }
108 
110 {
111  return false;
112 }
113 
116 /* -------------------------------------------------------------------- */
120 GeometrySet::GeometrySet() = default;
121 GeometrySet::GeometrySet(const GeometrySet &other) = default;
122 GeometrySet::GeometrySet(GeometrySet &&other) = default;
123 GeometrySet::~GeometrySet() = default;
124 GeometrySet &GeometrySet::operator=(const GeometrySet &other) = default;
126 
128 {
129  GeometryComponentPtr &component_ptr = components_[component_type];
130  if (!component_ptr) {
131  /* If the component did not exist before, create a new one. */
132  component_ptr = GeometryComponent::create(component_type);
133  return *component_ptr;
134  }
135  if (component_ptr->is_mutable()) {
136  /* If the referenced component is already mutable, return it directly. */
137  return *component_ptr;
138  }
139  /* If the referenced component is shared, make a copy. The copy is not shared and is
140  * therefore mutable. */
141  component_ptr = component_ptr->copy();
142  return *component_ptr;
143 }
144 
145 GeometryComponent *GeometrySet::get_component_ptr(GeometryComponentType type)
146 {
147  if (this->has(type)) {
148  return &this->get_component_for_write(type);
149  }
150  return nullptr;
151 }
152 
154  GeometryComponentType component_type) const
155 {
156  return components_[component_type].get();
157 }
158 
159 bool GeometrySet::has(const GeometryComponentType component_type) const
160 {
161  return components_[component_type].has_value();
162 }
163 
164 void GeometrySet::remove(const GeometryComponentType component_type)
165 {
166  components_[component_type].reset();
167 }
168 
170 {
171  for (GeometryComponentPtr &component_ptr : components_) {
172  if (component_ptr) {
173  if (!component_types.contains(component_ptr->type())) {
174  component_ptr.reset();
175  }
176  }
177  }
178 }
179 
181  const blender::Span<GeometryComponentType> component_types)
182 {
183  Vector<GeometryComponentType> extended_types = component_types;
186  this->keep_only(extended_types);
187 }
188 
190 {
191  this->keep_only_during_modify({});
192 }
193 
195 {
196  BLI_assert(!components_[component.type()]);
197  component.user_add();
198  components_[component.type()] = const_cast<GeometryComponent *>(&component);
199 }
200 
202 {
204  for (const GeometryComponentPtr &component_ptr : components_) {
205  if (component_ptr) {
206  components.append(component_ptr.get());
207  }
208  }
209  return components;
210 }
211 
213 {
214  using namespace blender;
215  bool have_minmax = false;
216  if (const PointCloud *pointcloud = this->get_pointcloud_for_read()) {
217  have_minmax |= BKE_pointcloud_minmax(pointcloud, *r_min, *r_max);
218  }
219  if (const Mesh *mesh = this->get_mesh_for_read()) {
220  have_minmax |= BKE_mesh_wrapper_minmax(mesh, *r_min, *r_max);
221  }
222  if (const Volume *volume = this->get_volume_for_read()) {
223  have_minmax |= BKE_volume_min_max(volume, *r_min, *r_max);
224  }
225  if (const Curves *curves_id = this->get_curves_for_read()) {
226  const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id->geometry);
227  /* Using the evaluated positions is somewhat arbitrary, but it is probably expected. */
228  std::optional<bounds::MinMaxResult<float3>> min_max = bounds::min_max(
229  curves.evaluated_positions());
230  if (min_max) {
231  have_minmax = true;
232  *r_min = math::min(*r_min, min_max->min);
233  *r_max = math::max(*r_max, min_max->max);
234  }
235  }
236  return have_minmax;
237 }
238 
239 std::ostream &operator<<(std::ostream &stream, const GeometrySet &geometry_set)
240 {
241  stream << "<GeometrySet at " << &geometry_set << ", " << geometry_set.components_.size()
242  << " components>";
243  return stream;
244 }
245 
247 {
248  for (GeometryComponentPtr &component_ptr : components_) {
249  component_ptr.reset();
250  }
251 }
252 
254 {
255  for (GeometryComponentPtr &component_ptr : components_) {
256  if (!component_ptr) {
257  continue;
258  }
259  if (component_ptr->owns_direct_data()) {
260  continue;
261  }
262  GeometryComponent &component_for_write = this->get_component_for_write(component_ptr->type());
263  component_for_write.ensure_owns_direct_data();
264  }
265 }
266 
268 {
269  for (const GeometryComponentPtr &component_ptr : components_) {
270  if (component_ptr) {
271  if (!component_ptr->owns_direct_data()) {
272  return false;
273  }
274  }
275  }
276  return true;
277 }
278 
280 {
281  const MeshComponent *component = this->get_component_for_read<MeshComponent>();
282  return (component == nullptr) ? nullptr : component->get_for_read();
283 }
284 
286 {
287  const MeshComponent *component = this->get_component_for_read<MeshComponent>();
288  return component != nullptr && component->has_mesh();
289 }
290 
292 {
293  const PointCloudComponent *component = this->get_component_for_read<PointCloudComponent>();
294  return (component == nullptr) ? nullptr : component->get_for_read();
295 }
296 
298 {
299  const VolumeComponent *component = this->get_component_for_read<VolumeComponent>();
300  return (component == nullptr) ? nullptr : component->get_for_read();
301 }
302 
304 {
305  const CurveComponent *component = this->get_component_for_read<CurveComponent>();
306  return (component == nullptr) ? nullptr : component->get_for_read();
307 }
308 
310 {
312  this->get_component_for_read<GeometryComponentEditData>();
313  return (component == nullptr) ? nullptr : component->curves_edit_hints_.get();
314 }
315 
317 {
318  const PointCloudComponent *component = this->get_component_for_read<PointCloudComponent>();
319  return component != nullptr && component->has_pointcloud();
320 }
321 
323 {
324  const InstancesComponent *component = this->get_component_for_read<InstancesComponent>();
325  return component != nullptr && component->instances_num() >= 1;
326 }
327 
329 {
330  const VolumeComponent *component = this->get_component_for_read<VolumeComponent>();
331  return component != nullptr && component->has_volume();
332 }
333 
335 {
336  const CurveComponent *component = this->get_component_for_read<CurveComponent>();
337  return component != nullptr && component->has_curves();
338 }
339 
341 {
342  for (const GeometryComponentPtr &component_ptr : components_) {
343  if (component_ptr) {
344  if (component_ptr->type() != GEO_COMPONENT_TYPE_INSTANCES) {
345  return true;
346  }
347  }
348  }
349  return false;
350 }
351 
353 {
354  return !(this->has_mesh() || this->has_curves() || this->has_pointcloud() ||
355  this->has_volume() || this->has_instances());
356 }
357 
359 {
360  GeometrySet geometry_set;
361  if (mesh != nullptr) {
363  component.replace(mesh, ownership);
364  }
365  return geometry_set;
366 }
367 
369 {
370  GeometrySet geometry_set;
371  if (volume != nullptr) {
373  component.replace(volume, ownership);
374  }
375  return geometry_set;
376 }
377 
379  GeometryOwnershipType ownership)
380 {
381  GeometrySet geometry_set;
382  if (pointcloud != nullptr) {
384  component.replace(pointcloud, ownership);
385  }
386  return geometry_set;
387 }
388 
390 {
391  GeometrySet geometry_set;
392  if (curves != nullptr) {
394  component.replace(curves, ownership);
395  }
396  return geometry_set;
397 }
398 
400 {
401  if (mesh == nullptr) {
402  this->remove<MeshComponent>();
403  return;
404  }
405  if (mesh == this->get_mesh_for_read()) {
406  return;
407  }
408  this->remove<MeshComponent>();
409  MeshComponent &component = this->get_component_for_write<MeshComponent>();
410  component.replace(mesh, ownership);
411 }
412 
414 {
415  if (curves == nullptr) {
416  this->remove<CurveComponent>();
417  return;
418  }
419  if (curves == this->get_curves_for_read()) {
420  return;
421  }
422  this->remove<CurveComponent>();
423  CurveComponent &component = this->get_component_for_write<CurveComponent>();
424  component.replace(curves, ownership);
425 }
426 
428 {
429  if (pointcloud == nullptr) {
430  this->remove<PointCloudComponent>();
431  return;
432  }
433  if (pointcloud == this->get_pointcloud_for_read()) {
434  return;
435  }
436  this->remove<PointCloudComponent>();
437  PointCloudComponent &component = this->get_component_for_write<PointCloudComponent>();
438  component.replace(pointcloud, ownership);
439 }
440 
442 {
443  if (volume == nullptr) {
444  this->remove<VolumeComponent>();
445  return;
446  }
447  if (volume == this->get_volume_for_read()) {
448  return;
449  }
450  this->remove<VolumeComponent>();
451  VolumeComponent &component = this->get_component_for_write<VolumeComponent>();
452  component.replace(volume, ownership);
453 }
454 
456 {
457  MeshComponent *component = this->get_component_ptr<MeshComponent>();
458  return component == nullptr ? nullptr : component->get_for_write();
459 }
460 
462 {
463  PointCloudComponent *component = this->get_component_ptr<PointCloudComponent>();
464  return component == nullptr ? nullptr : component->get_for_write();
465 }
466 
468 {
469  VolumeComponent *component = this->get_component_ptr<VolumeComponent>();
470  return component == nullptr ? nullptr : component->get_for_write();
471 }
472 
474 {
475  CurveComponent *component = this->get_component_ptr<CurveComponent>();
476  return component == nullptr ? nullptr : component->get_for_write();
477 }
478 
480 {
481  if (!this->has<GeometryComponentEditData>()) {
482  return nullptr;
483  }
485  this->get_component_for_write<GeometryComponentEditData>();
486  return component.curves_edit_hints_.get();
487 }
488 
490  const bool include_instances,
492 {
493  using namespace blender;
494  using namespace blender::bke;
495  for (const GeometryComponentType component_type : component_types) {
496  if (!this->has(component_type)) {
497  continue;
498  }
499  const GeometryComponent &component = *this->get_component_for_read(component_type);
500  const std::optional<AttributeAccessor> attributes = component.attributes();
501  if (attributes.has_value()) {
502  attributes->for_all(
503  [&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) {
504  callback(attribute_id, meta_data, component);
505  return true;
506  });
507  }
508  }
509  if (include_instances && this->has_instances()) {
510  const InstancesComponent &instances = *this->get_component_for_read<InstancesComponent>();
511  instances.foreach_referenced_geometry([&](const GeometrySet &instance_geometry_set) {
512  instance_geometry_set.attribute_foreach(component_types, include_instances, callback);
513  });
514  }
515 }
516 
518  const Span<GeometryComponentType> component_types,
519  const GeometryComponentType dst_component_type,
520  bool include_instances,
522 {
523  using namespace blender;
524  using namespace blender::bke;
525  /* Only needed right now to check if an attribute is built-in on this component type.
526  * TODO: Get rid of the dummy component. */
527  const GeometryComponent *dummy_component = GeometryComponent::create(dst_component_type);
528  this->attribute_foreach(
529  component_types,
530  include_instances,
531  [&](const AttributeIDRef &attribute_id,
532  const AttributeMetaData &meta_data,
533  const GeometryComponent &component) {
534  if (component.attributes()->is_builtin(attribute_id)) {
535  if (!dummy_component->attributes()->is_builtin(attribute_id)) {
536  /* Don't propagate built-in attributes that are not built-in on the destination
537  * component. */
538  return;
539  }
540  }
541 
542  if (!attribute_id.should_be_kept()) {
543  return;
544  }
545 
546  eAttrDomain domain = meta_data.domain;
547  if (dst_component_type != GEO_COMPONENT_TYPE_INSTANCES && domain == ATTR_DOMAIN_INSTANCE) {
548  domain = ATTR_DOMAIN_POINT;
549  }
550 
551  auto add_info = [&](AttributeKind *attribute_kind) {
552  attribute_kind->domain = domain;
553  attribute_kind->data_type = meta_data.data_type;
554  };
555  auto modify_info = [&](AttributeKind *attribute_kind) {
556  attribute_kind->domain = bke::attribute_domain_highest_priority(
557  {attribute_kind->domain, domain});
558  attribute_kind->data_type = bke::attribute_data_type_highest_complexity(
559  {attribute_kind->data_type, meta_data.data_type});
560  };
561  r_attributes.add_or_modify(attribute_id, add_info, modify_info);
562  });
563  delete dummy_component;
564 }
565 
566 static void gather_component_types_recursive(const GeometrySet &geometry_set,
567  const bool include_instances,
568  const bool ignore_empty,
570 {
571  for (const GeometryComponent *component : geometry_set.get_components_for_read()) {
572  if (ignore_empty) {
573  if (component->is_empty()) {
574  continue;
575  }
576  }
577  r_types.append_non_duplicates(component->type());
578  }
579  if (!include_instances) {
580  return;
581  }
582  const InstancesComponent *instances = geometry_set.get_component_for_read<InstancesComponent>();
583  if (instances == nullptr) {
584  return;
585  }
586  instances->foreach_referenced_geometry([&](const GeometrySet &instance_geometry_set) {
588  instance_geometry_set, include_instances, ignore_empty, r_types);
589  });
590 }
591 
593  const bool include_instances, bool ignore_empty) const
594 {
596  gather_component_types_recursive(*this, include_instances, ignore_empty, types);
597  return types;
598 }
599 
600 static void gather_mutable_geometry_sets(GeometrySet &geometry_set,
601  Vector<GeometrySet *> &r_geometry_sets)
602 {
603  r_geometry_sets.append(&geometry_set);
604  if (!geometry_set.has_instances()) {
605  return;
606  }
607  /* In the future this can be improved by deduplicating instance references across different
608  * instances. */
609  InstancesComponent &instances_component =
611  instances_component.ensure_geometry_instances();
612  for (const int handle : instances_component.references().index_range()) {
613  if (instances_component.references()[handle].type() == InstanceReference::Type::GeometrySet) {
614  GeometrySet &instance_geometry = instances_component.geometry_set_from_reference(handle);
615  gather_mutable_geometry_sets(instance_geometry, r_geometry_sets);
616  }
617  }
618 }
619 
621 {
622  Vector<GeometrySet *> geometry_sets;
623  gather_mutable_geometry_sets(*this, geometry_sets);
624  if (geometry_sets.size() == 1) {
625  /* Avoid possible overhead and a large call stack when multithreading is pointless. */
626  callback(*geometry_sets.first());
627  }
628  else {
630  geometry_sets, [&](GeometrySet *geometry_set) { callback(*geometry_set); });
631  }
632 }
633 
636 /* -------------------------------------------------------------------- */
640 namespace blender::bke {
641 
642 GVArray NormalFieldInput::get_varray_for_context(const GeometryComponent &component,
643  const eAttrDomain domain,
644  IndexMask mask) const
645 {
646  if (component.type() == GEO_COMPONENT_TYPE_MESH) {
647  const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
648  if (const Mesh *mesh = mesh_component.get_for_read()) {
649  return mesh_normals_varray(mesh_component, *mesh, mask, domain);
650  }
651  }
652  else if (component.type() == GEO_COMPONENT_TYPE_CURVE) {
653  const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
654  return curve_normals_varray(curve_component, domain);
655  }
656  return {};
657 }
658 
659 std::string NormalFieldInput::socket_inspection_name() const
660 {
661  return TIP_("Normal");
662 }
663 
665 {
666  return 213980475983;
667 }
668 
669 bool NormalFieldInput::is_equal_to(const fn::FieldNode &other) const
670 {
671  return dynamic_cast<const NormalFieldInput *>(&other) != nullptr;
672 }
673 
674 } // namespace blender::bke
675 
678 /* -------------------------------------------------------------------- */
683 {
684  delete geometry_set;
685 }
686 
688 {
689  const GeometrySet *geometry_set = ob->runtime.geometry_set_eval;
690  if (geometry_set == nullptr) {
691  return false;
692  }
693  for (const GeometryComponent *component : geometry_set->get_components_for_read()) {
694  if (component->is_empty()) {
695  continue;
696  }
697  const GeometryComponentType type = component->type();
698  bool is_instance = false;
699  switch (type) {
701  is_instance = ob->type != OB_MESH;
702  break;
704  is_instance = ob->type != OB_POINTCLOUD;
705  break;
707  is_instance = true;
708  break;
710  is_instance = ob->type != OB_VOLUME;
711  break;
713  is_instance = !ELEM(ob->type, OB_CURVES_LEGACY, OB_FONT);
714  break;
716  break;
717  }
718  if (is_instance) {
719  return true;
720  }
721  }
722  return false;
723 }
724 
Generic geometry attributes built on CustomData.
eAttrDomain
Definition: BKE_attribute.h:25
@ ATTR_DOMAIN_INSTANCE
Definition: BKE_attribute.h:32
@ ATTR_DOMAIN_POINT
Definition: BKE_attribute.h:27
Low-level operations for curves.
GeometryComponentType
@ GEO_COMPONENT_TYPE_MESH
@ GEO_COMPONENT_TYPE_POINT_CLOUD
@ GEO_COMPONENT_TYPE_INSTANCES
@ GEO_COMPONENT_TYPE_EDIT
@ GEO_COMPONENT_TYPE_CURVE
@ GEO_COMPONENT_TYPE_VOLUME
GeometryOwnershipType
bool BKE_mesh_wrapper_minmax(const struct Mesh *me, float min[3], float max[3])
General operations for point clouds.
bool BKE_pointcloud_minmax(const struct PointCloud *pointcloud, float r_min[3], float r_max[3])
Volume data-block.
#define BLI_assert_unreachable()
Definition: BLI_assert.h:93
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define ELEM(...)
#define TIP_(msgid)
static uint8 component(Color32 c, uint i)
Definition: ColorBlock.cpp:108
Object groups, one object can be in many groups at once.
Object is a sort of wrapper for general info.
@ OB_FONT
@ OB_MESH
@ OB_POINTCLOUD
@ OB_VOLUME
@ OB_CURVES_LEGACY
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
float float4x4[4][4]
Read Guarded memory(de)allocation.
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to curves
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Map
void user_add() const
Definition: geometry_set.cc:84
int attribute_domain_size(eAttrDomain domain) const
Definition: geometry_set.cc:63
virtual bool is_empty() const
virtual void ensure_owns_direct_data()=0
GeometryComponent(GeometryComponentType type)
Definition: geometry_set.cc:39
static GeometryComponent * create(GeometryComponentType component_type)
Definition: geometry_set.cc:43
virtual std::optional< blender::bke::AttributeAccessor > attributes() const
Definition: geometry_set.cc:75
virtual std::optional< blender::bke::MutableAttributeAccessor > attributes_for_write()
Definition: geometry_set.cc:79
GeometryComponentType type() const
void user_remove() const
Definition: geometry_set.cc:89
bool is_mutable() const
Definition: geometry_set.cc:97
void foreach_referenced_geometry(blender::FunctionRef< void(const GeometrySet &geometry_set)> callback) const
GeometrySet & geometry_set_from_reference(int reference_index)
blender::Span< InstanceReference > references() const
const Mesh * get_for_read() const
auto add_or_modify(const Key &key, const CreateValueF &create_value, const ModifyValueF &modify_value) -> decltype(create_value(nullptr))
Definition: BLI_map.hh:436
constexpr bool contains(const T &value) const
Definition: BLI_span.hh:265
int64_t size() const
Definition: BLI_vector.hh:694
void append(const T &value)
Definition: BLI_vector.hh:433
const T & first() const
Definition: BLI_vector.hh:680
void append_non_duplicates(const T &value)
Definition: BLI_vector.hh:472
DEGForeachIDComponentCallback callback
bool BKE_object_has_geometry_set_instances(const Object *ob)
void BKE_geometry_set_free(GeometrySet *geometry_set)
static void gather_component_types_recursive(const GeometrySet &geometry_set, const bool include_instances, const bool ignore_empty, Vector< GeometryComponentType > &r_types)
static void gather_mutable_geometry_sets(GeometrySet &geometry_set, Vector< GeometrySet * > &r_geometry_sets)
static char ** types
Definition: makesdna.c:67
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
Definition: math_float4.h:513
static struct PartialUpdateUser * wrap(PartialUpdateUserImpl *user)
VArray< float3 > curve_normals_varray(const CurveComponent &component, const eAttrDomain domain)
eAttrDomain attribute_domain_highest_priority(Span< eAttrDomain > domains)
eCustomDataType attribute_data_type_highest_complexity(Span< eCustomDataType > data_types)
VArray< float3 > mesh_normals_varray(const MeshComponent &mesh_component, const Mesh &mesh, const IndexMask mask, eAttrDomain domain)
static std::optional< MinMaxResult< T > > min_max(Span< T > values)
Definition: BLI_bounds.hh:26
void parallel_for_each(Range &range, const Function &function)
Definition: BLI_task.hh:39
vec_base< float, 3 > float3
#define hash
Definition: noise.c:153
#define min(a, b)
Definition: sort.c:35
unsigned __int64 uint64_t
Definition: stdint.h:90
const PointCloud * get_pointcloud_for_read() const
bool has_volume() const
void replace_mesh(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
GeometryComponent & get_component_for_write(GeometryComponentType component_type)
static GeometrySet create_with_curves(Curves *curves, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
blender::Vector< const GeometryComponent * > get_components_for_read() const
Curves * get_curves_for_write()
void ensure_owns_direct_data()
const Volume * get_volume_for_read() const
void replace_curves(Curves *curves, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
static GeometrySet create_with_mesh(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
void keep_only_during_modify(const blender::Span< GeometryComponentType > component_types)
GeometrySet & operator=(const GeometrySet &other)
bool has_realized_data() const
blender::Vector< GeometryComponentType > gather_component_types(bool include_instances, bool ignore_empty) const
const GeometryComponent * get_component_for_read(GeometryComponentType component_type) const
void replace_volume(Volume *volume, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
static GeometrySet create_with_volume(Volume *volume, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
Component & get_component_for_write()
PointCloud * get_pointcloud_for_write()
const Mesh * get_mesh_for_read() const
bool owns_direct_data() const
const Curves * get_curves_for_read() const
bool is_empty() const
void attribute_foreach(blender::Span< GeometryComponentType > component_types, bool include_instances, AttributeForeachCallback callback) const
void gather_attributes_for_propagation(blender::Span< GeometryComponentType > component_types, GeometryComponentType dst_component_type, bool include_instances, blender::Map< blender::bke::AttributeIDRef, blender::bke::AttributeKind > &r_attributes) 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
void modify_geometry_sets(ForeachSubGeometryCallback callback)
static GeometrySet create_with_pointcloud(PointCloud *pointcloud, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
void keep_only(const blender::Span< GeometryComponentType > component_types)
bool has_mesh() const
blender::bke::CurvesEditHints * get_curve_edit_hints_for_write()
bool has_curves() const
const blender::bke::CurvesEditHints * get_curve_edit_hints_for_read() const
Volume * get_volume_for_write()
bool compute_boundbox_without_instances(blender::float3 *r_min, blender::float3 *r_max) const
void remove_geometry_during_modify()
void replace_pointcloud(PointCloud *pointcloud, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
const Component * get_component_for_read() const
bool has() const
bool has_pointcloud() const
struct GeometrySet * geometry_set_eval
Object_Runtime runtime
float max
bool BKE_volume_min_max(const Volume *volume, float3 &r_min, float3 &r_max)
Definition: volume.cc:981