Blender  V3.3
geometry_set_instances.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include "BKE_collection.h"
5 #include "BKE_material.h"
6 #include "BKE_mesh.h"
7 #include "BKE_mesh_wrapper.h"
8 #include "BKE_modifier.h"
9 #include "BKE_pointcloud.h"
10 
11 #include "DNA_collection_types.h"
12 #include "DNA_layer_types.h"
13 #include "DNA_mesh_types.h"
14 #include "DNA_meshdata_types.h"
15 #include "DNA_object_types.h"
16 #include "DNA_pointcloud_types.h"
17 
18 namespace blender::bke {
19 
20 static void geometry_set_collect_recursive(const GeometrySet &geometry_set,
21  const float4x4 &transform,
22  Vector<GeometryInstanceGroup> &r_sets);
23 
24 static void geometry_set_collect_recursive_collection(const Collection &collection,
25  const float4x4 &transform,
26  Vector<GeometryInstanceGroup> &r_sets);
27 
28 static void add_final_mesh_as_geometry_component(const Object &object, GeometrySet &geometry_set)
29 {
31  &const_cast<Object &>(object));
32 
33  if (mesh != nullptr) {
36  }
37 }
38 
40 {
41  if (object.type == OB_MESH && object.mode == OB_MODE_EDIT) {
42  GeometrySet geometry_set;
43  if (object.runtime.geometry_set_eval != nullptr) {
44  /* `geometry_set_eval` only contains non-mesh components, see `editbmesh_build_data`. */
45  geometry_set = *object.runtime.geometry_set_eval;
46  }
47  add_final_mesh_as_geometry_component(object, geometry_set);
48  return geometry_set;
49  }
50  if (object.runtime.geometry_set_eval != nullptr) {
51  GeometrySet geometry_set = *object.runtime.geometry_set_eval;
52  /* Ensure that subdivision is performed on the CPU. */
53  if (geometry_set.has_mesh()) {
54  add_final_mesh_as_geometry_component(object, geometry_set);
55  }
56  return geometry_set;
57  }
58 
59  /* Otherwise, construct a new geometry set with the component based on the object type. */
60  if (object.type == OB_MESH) {
61  GeometrySet geometry_set;
62  add_final_mesh_as_geometry_component(object, geometry_set);
63  return geometry_set;
64  }
65  if (object.type == OB_EMPTY && object.instance_collection != nullptr) {
66  GeometrySet geometry_set;
67  Collection &collection = *object.instance_collection;
69  const int handle = instances.add_reference(collection);
70  instances.add_instance(handle, float4x4::identity());
71  return geometry_set;
72  }
73 
74  /* Return by value since there is not always an existing geometry set owned elsewhere to use. */
75  return {};
76 }
77 
79  const Collection &collection, const float4x4 &transform, Vector<GeometryInstanceGroup> &r_sets)
80 {
81  float4x4 offset_matrix = float4x4::identity();
82  sub_v3_v3(offset_matrix.values[3], collection.instance_offset);
83  const float4x4 instance_transform = transform * offset_matrix;
84  geometry_set_collect_recursive_collection(collection, instance_transform, r_sets);
85 }
86 
88  const float4x4 &transform,
90 {
91  GeometrySet instance_geometry_set = object_get_evaluated_geometry_set(object);
92  geometry_set_collect_recursive(instance_geometry_set, transform, r_sets);
93 }
94 
96  const float4x4 &transform,
98 {
99  LISTBASE_FOREACH (const CollectionObject *, collection_object, &collection.gobject) {
100  BLI_assert(collection_object->ob != nullptr);
101  const Object &object = *collection_object->ob;
102  const float4x4 object_transform = transform * object.obmat;
103  geometry_set_collect_recursive_object(object, object_transform, r_sets);
104  }
105  LISTBASE_FOREACH (const CollectionChild *, collection_child, &collection.children) {
106  BLI_assert(collection_child->collection != nullptr);
107  const Collection &collection = *collection_child->collection;
109  }
110 }
111 
112 static void geometry_set_collect_recursive(const GeometrySet &geometry_set,
113  const float4x4 &transform,
115 {
116  r_sets.append({geometry_set, {transform}});
117 
118  if (geometry_set.has_instances()) {
119  const InstancesComponent &instances_component =
121 
122  Span<float4x4> transforms = instances_component.instance_transforms();
123  Span<int> handles = instances_component.instance_reference_handles();
124  Span<InstanceReference> references = instances_component.references();
125  for (const int i : transforms.index_range()) {
126  const InstanceReference &reference = references[handles[i]];
127  const float4x4 instance_transform = transform * transforms[i];
128 
129  switch (reference.type()) {
131  Object &object = reference.object();
132  geometry_set_collect_recursive_object(object, instance_transform, r_sets);
133  break;
134  }
136  Collection &collection = reference.collection();
138  collection, instance_transform, r_sets);
139  break;
140  }
142  const GeometrySet &geometry_set = reference.geometry_set();
143  geometry_set_collect_recursive(geometry_set, instance_transform, r_sets);
144  break;
145  }
147  break;
148  }
149  }
150  }
151  }
152 }
153 
155  Vector<GeometryInstanceGroup> &r_instance_groups)
156 {
157  geometry_set_collect_recursive(geometry_set, float4x4::identity(), r_instance_groups);
158 }
159 
160 } // namespace blender::bke
161 
163  blender::FunctionRef<void(const GeometrySet &geometry_set)> callback) const
164 {
165  using namespace blender::bke;
166  for (const InstanceReference &reference : references_) {
167  switch (reference.type()) {
169  const Object &object = reference.object();
170  const GeometrySet object_geometry_set = object_get_evaluated_geometry_set(object);
171  callback(object_geometry_set);
172  break;
173  }
175  Collection &collection = reference.collection();
176  FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (&collection, object) {
177  const GeometrySet object_geometry_set = object_get_evaluated_geometry_set(*object);
178  callback(object_geometry_set);
179  }
181  break;
182  }
184  const GeometrySet &instance_geometry_set = reference.geometry_set();
185  callback(instance_geometry_set);
186  break;
187  }
189  break;
190  }
191  }
192  }
193 }
194 
196 {
197  using namespace blender;
198  using namespace blender::bke;
199  VectorSet<InstanceReference> new_references;
200  new_references.reserve(references_.size());
201  for (const InstanceReference &reference : references_) {
202  switch (reference.type()) {
205  /* Those references can stay as their were. */
206  new_references.add_new(reference);
207  break;
208  }
210  /* Create a new reference that contains the geometry set of the object. We may want to
211  * treat e.g. lamps and similar object types separately here. */
212  const Object &object = reference.object();
213  GeometrySet object_geometry_set = object_get_evaluated_geometry_set(object);
214  if (object_geometry_set.has_instances()) {
216  object_geometry_set.get_component_for_write<InstancesComponent>();
217  component.ensure_geometry_instances();
218  }
219  new_references.add_new(std::move(object_geometry_set));
220  break;
221  }
223  /* Create a new reference that contains a geometry set that contains all objects from the
224  * collection as instances. */
225  GeometrySet collection_geometry_set;
227  collection_geometry_set.get_component_for_write<InstancesComponent>();
228  Collection &collection = reference.collection();
229  FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (&collection, object) {
230  const int handle = component.add_reference(*object);
231  component.add_instance(handle, object->obmat);
232  float4x4 &transform = component.instance_transforms().last();
233  sub_v3_v3(transform.values[3], collection.instance_offset);
234  }
236  component.ensure_geometry_instances();
237  new_references.add_new(std::move(collection_geometry_set));
238  break;
239  }
240  }
241  }
242  references_ = std::move(new_references);
243 }
#define FOREACH_COLLECTION_OBJECT_RECURSIVE_END
#define FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(_collection, _object)
General operations, lookup, etc. for materials.
void BKE_mesh_wrapper_ensure_mdata(struct Mesh *me)
Definition: mesh_wrapper.cc:94
struct Mesh * BKE_modifier_get_evaluated_mesh_from_evaluated_object(struct Object *ob_eval)
General operations for point clouds.
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
MINLINE void sub_v3_v3(float r[3], const float a[3])
static uint8 component(Color32 c, uint i)
Definition: ColorBlock.cpp:108
Object groups, one object can be in many groups at once.
@ OB_MODE_EDIT
Object is a sort of wrapper for general info.
@ OB_EMPTY
@ OB_MESH
_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]
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
Object & object() const
Collection & collection() const
const GeometrySet & geometry_set() const
blender::Span< int > instance_reference_handles() const
void foreach_referenced_geometry(blender::FunctionRef< void(const GeometrySet &geometry_set)> callback) const
int add_reference(const InstanceReference &reference)
blender::Span< InstanceReference > references() const
void add_instance(int instance_handle, const blender::float4x4 &transform)
blender::MutableSpan< blender::float4x4 > instance_transforms()
void reserve(const int64_t n)
void add_new(const Key &key)
void append(const T &value)
Definition: BLI_vector.hh:433
DEGForeachIDComponentCallback callback
static void add_final_mesh_as_geometry_component(const Object &object, GeometrySet &geometry_set)
void geometry_set_gather_instances(const GeometrySet &geometry_set, Vector< GeometryInstanceGroup > &r_instance_groups)
static void geometry_set_collect_recursive_object(const Object &object, const float4x4 &transform, Vector< GeometryInstanceGroup > &r_sets)
GeometrySet object_get_evaluated_geometry_set(const Object &object)
static void geometry_set_collect_recursive(const GeometrySet &geometry_set, const float4x4 &transform, Vector< GeometryInstanceGroup > &r_sets)
static void geometry_set_collect_recursive_collection_instance(const Collection &collection, const float4x4 &transform, Vector< GeometryInstanceGroup > &r_sets)
static void geometry_set_collect_recursive_collection(const Collection &collection, const float4x4 &transform, Vector< GeometryInstanceGroup > &r_sets)
float instance_offset[3]
void replace_mesh(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
GeometryComponent & get_component_for_write(GeometryComponentType component_type)
const GeometryComponent * get_component_for_read(GeometryComponentType component_type) const
bool has_instances() const
bool has_mesh() const
float values[4][4]
Definition: BLI_float4x4.hh:13
static float4x4 identity()
Definition: BLI_float4x4.hh:80
ParamHandle ** handles