Blender  V2.93
geometry_set.cc
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 #include "BLI_map.hh"
18 
19 #include "BKE_attribute.h"
20 #include "BKE_attribute_access.hh"
21 #include "BKE_geometry_set.hh"
22 #include "BKE_lib_id.h"
23 #include "BKE_mesh.h"
24 #include "BKE_mesh_wrapper.h"
25 #include "BKE_modifier.h"
26 #include "BKE_pointcloud.h"
27 #include "BKE_volume.h"
28 
29 #include "DNA_collection_types.h"
30 #include "DNA_object_types.h"
31 
32 #include "BLI_rand.hh"
33 
34 #include "MEM_guardedalloc.h"
35 
36 using blender::float3;
37 using blender::float4x4;
38 using blender::Map;
40 using blender::Span;
41 using blender::StringRef;
42 using blender::Vector;
43 
44 /* -------------------------------------------------------------------- */
49 {
50 }
51 
53 {
54  switch (component_type) {
56  return new MeshComponent();
58  return new PointCloudComponent();
60  return new InstancesComponent();
62  return new VolumeComponent();
63  }
65  return nullptr;
66 }
67 
69 {
70  users_.fetch_add(1);
71 }
72 
74 {
75  const int new_users = users_.fetch_sub(1) - 1;
76  if (new_users == 0) {
77  delete this;
78  }
79 }
80 
82 {
83  /* If the item is shared, it is read-only. */
84  /* The user count can be 0, when this is called from the destructor. */
85  return users_ <= 1;
86 }
87 
89 {
90  return type_;
91 }
92 
94 {
95  return false;
96 }
97 
100 /* -------------------------------------------------------------------- */
104 /* This method can only be used when the geometry set is mutable. It returns a mutable geometry
105  * component of the given type.
106  */
108 {
109  return components_.add_or_modify(
110  component_type,
111  [&](GeometryComponentPtr *value_ptr) -> GeometryComponent & {
112  /* If the component did not exist before, create a new one. */
113  new (value_ptr) GeometryComponentPtr(GeometryComponent::create(component_type));
114  return **value_ptr;
115  },
116  [&](GeometryComponentPtr *value_ptr) -> GeometryComponent & {
117  GeometryComponentPtr &value = *value_ptr;
118  if (value->is_mutable()) {
119  /* If the referenced component is already mutable, return it directly. */
120  return *value;
121  }
122  /* If the referenced component is shared, make a copy. The copy is not shared and is
123  * therefore mutable. */
124  GeometryComponent *copied_component = value->copy();
125  value = GeometryComponentPtr{copied_component};
126  return *copied_component;
127  });
128 }
129 
130 /* Get the component of the given type. Might return null if the component does not exist yet. */
132  GeometryComponentType component_type) const
133 {
134  const GeometryComponentPtr *component = components_.lookup_ptr(component_type);
135  if (component != nullptr) {
136  return component->get();
137  }
138  return nullptr;
139 }
140 
141 bool GeometrySet::has(const GeometryComponentType component_type) const
142 {
143  return components_.contains(component_type);
144 }
145 
146 void GeometrySet::remove(const GeometryComponentType component_type)
147 {
148  components_.remove(component_type);
149 }
150 
152 {
153  BLI_assert(!components_.contains(component.type()));
154  component.user_add();
155  GeometryComponentPtr component_ptr{const_cast<GeometryComponent *>(&component)};
156  components_.add_new(component.type(), std::move(component_ptr));
157 }
158 
163 {
165  for (const GeometryComponentPtr &ptr : components_.values()) {
166  components.append(ptr.get());
167  }
168  return components;
169 }
170 
172 {
173  const PointCloud *pointcloud = this->get_pointcloud_for_read();
174  if (pointcloud != nullptr) {
175  BKE_pointcloud_minmax(pointcloud, *r_min, *r_max);
176  }
177  const Mesh *mesh = this->get_mesh_for_read();
178  if (mesh != nullptr) {
179  BKE_mesh_wrapper_minmax(mesh, *r_min, *r_max);
180  }
181  const Volume *volume = this->get_volume_for_read();
182  if (volume != nullptr) {
183  BKE_volume_min_max(volume, *r_min, *r_max);
184  }
185 }
186 
187 std::ostream &operator<<(std::ostream &stream, const GeometrySet &geometry_set)
188 {
189  stream << "<GeometrySet at " << &geometry_set << ", " << geometry_set.components_.size()
190  << " components>";
191  return stream;
192 }
193 
194 /* This generally should not be used. It is necessary currently, so that GeometrySet can by used by
195  * the CPPType system. */
197 {
198  return false;
199 }
200 
201 /* This generally should not be used. It is necessary currently, so that GeometrySet can by used by
202  * the CPPType system. */
204 {
205  return reinterpret_cast<uint64_t>(this);
206 }
207 
208 /* Remove all geometry components from the geometry set. */
210 {
211  components_.clear();
212 }
213 
214 /* Make sure that the geometry can be cached. This does not ensure ownership of object/collection
215  * instances. */
217 {
218  for (GeometryComponentType type : components_.keys()) {
220  if (!component->owns_direct_data()) {
221  GeometryComponent &component_for_write = this->get_component_for_write(type);
222  component_for_write.ensure_owns_direct_data();
223  }
224  }
225 }
226 
227 /* Returns a read-only mesh or null. */
229 {
230  const MeshComponent *component = this->get_component_for_read<MeshComponent>();
231  return (component == nullptr) ? nullptr : component->get_for_read();
232 }
233 
234 /* Returns true when the geometry set has a mesh component that has a mesh. */
236 {
237  const MeshComponent *component = this->get_component_for_read<MeshComponent>();
238  return component != nullptr && component->has_mesh();
239 }
240 
241 /* Returns a read-only point cloud of null. */
243 {
244  const PointCloudComponent *component = this->get_component_for_read<PointCloudComponent>();
245  return (component == nullptr) ? nullptr : component->get_for_read();
246 }
247 
248 /* Returns a read-only volume or null. */
250 {
251  const VolumeComponent *component = this->get_component_for_read<VolumeComponent>();
252  return (component == nullptr) ? nullptr : component->get_for_read();
253 }
254 
255 /* Returns true when the geometry set has a point cloud component that has a point cloud. */
257 {
258  const PointCloudComponent *component = this->get_component_for_read<PointCloudComponent>();
259  return component != nullptr && component->has_pointcloud();
260 }
261 
262 /* Returns true when the geometry set has an instances component that has at least one instance. */
264 {
265  const InstancesComponent *component = this->get_component_for_read<InstancesComponent>();
266  return component != nullptr && component->instances_amount() >= 1;
267 }
268 
269 /* Returns true when the geometry set has a volume component that has a volume. */
271 {
272  const VolumeComponent *component = this->get_component_for_read<VolumeComponent>();
273  return component != nullptr && component->has_volume();
274 }
275 
276 /* Create a new geometry set that only contains the given mesh. */
278 {
279  GeometrySet geometry_set;
281  component.replace(mesh, ownership);
282  return geometry_set;
283 }
284 
285 /* Create a new geometry set that only contains the given point cloud. */
287  GeometryOwnershipType ownership)
288 {
289  GeometrySet geometry_set;
291  component.replace(pointcloud, ownership);
292  return geometry_set;
293 }
294 
295 /* Clear the existing mesh and replace it with the given one. */
297 {
298  MeshComponent &component = this->get_component_for_write<MeshComponent>();
299  component.replace(mesh, ownership);
300 }
301 
302 /* Clear the existing point cloud and replace with the given one. */
304 {
305  PointCloudComponent &pointcloud_component = this->get_component_for_write<PointCloudComponent>();
306  pointcloud_component.replace(pointcloud, ownership);
307 }
308 
309 /* Returns a mutable mesh or null. No ownership is transferred. */
311 {
312  MeshComponent &component = this->get_component_for_write<MeshComponent>();
313  return component.get_for_write();
314 }
315 
316 /* Returns a mutable point cloud or null. No ownership is transferred. */
318 {
319  PointCloudComponent &component = this->get_component_for_write<PointCloudComponent>();
320  return component.get_for_write();
321 }
322 
323 /* Returns a mutable volume or null. No ownership is transferred. */
325 {
326  VolumeComponent &component = this->get_component_for_write<VolumeComponent>();
327  return component.get_for_write();
328 }
329 
332 /* -------------------------------------------------------------------- */
337 {
338  delete geometry_set;
339 }
340 
342 {
343  return geometry_set->get_component_for_read<InstancesComponent>() != nullptr;
344 }
345 
Generic geometry attributes built on CustomData.
GeometryComponentType
@ GEO_COMPONENT_TYPE_MESH
@ GEO_COMPONENT_TYPE_POINT_CLOUD
@ GEO_COMPONENT_TYPE_INSTANCES
@ 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.
void BKE_pointcloud_minmax(const struct PointCloud *pointcloud, float r_min[3], float r_max[3])
Definition: pointcloud.cc:263
Volume datablock.
#define BLI_assert_unreachable()
Definition: BLI_assert.h:96
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define UNUSED(x)
static uint8 component(Color32 c, uint i)
Definition: ColorBlock.cpp:126
Object groups, one object can be in many groups at once.
Object is a sort of wrapper for general info.
_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
Read Guarded memory(de)allocation.
void user_add() const
Definition: geometry_set.cc:68
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
static GeometryComponent * create(GeometryComponentType component_type)
Definition: geometry_set.cc:52
GeometryComponentType type() const
Definition: geometry_set.cc:88
void user_remove() const
Definition: geometry_set.cc:73
bool is_mutable() const
Definition: geometry_set.cc:81
virtual bool owns_direct_data() const =0
void replace(PointCloud *pointcloud, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
void append(const T &value)
Definition: BLI_vector.hh:438
bool BKE_geometry_set_has_instances(const GeometrySet *geometry_set)
void BKE_geometry_set_free(GeometrySet *geometry_set)
std::ostream & operator<<(std::ostream &stream, const GeometrySet &geometry_set)
bool operator==(const GeometrySet &UNUSED(a), const GeometrySet &UNUSED(b))
static unsigned a[3]
Definition: RandGen.cpp:92
unsigned __int64 uint64_t
Definition: stdint.h:93
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)
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)
const GeometryComponent * get_component_for_read(GeometryComponentType component_type) const
Component & get_component_for_write()
PointCloud * get_pointcloud_for_write()
const Mesh * get_mesh_for_read() const
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
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 BKE_volume_min_max(const Volume *volume, float3 &r_min, float3 &r_max)
Definition: volume.cc:900
PointerRNA * ptr
Definition: wm_files.c:3157