Blender V5.0
geometry_set_instances.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BKE_collection.hh"
7#include "BKE_instances.hh"
8#include "BKE_lib_id.hh"
9#include "BKE_mesh_wrapper.hh"
10#include "BKE_modifier.hh"
11#include "BKE_object.hh"
12#include "BKE_object_types.hh"
13
15#include "DNA_layer_types.h"
16#include "DNA_object_types.h"
17
19
20namespace blender::bke {
21
23 GeometrySet &geometry_set,
24 const bool apply_subdiv)
25{
26 if (apply_subdiv) {
28 &const_cast<Object &>(object));
29
30 if (mesh != nullptr) {
33 }
34 return;
35 }
37 if (mesh != nullptr) {
39 }
40}
41
42GeometrySet object_get_evaluated_geometry_set(const Object &object, const bool apply_subdiv)
43{
45 return {};
46 }
47
48 if (object.runtime->geometry_set_eval != nullptr) {
49 GeometrySet geometry_set = *object.runtime->geometry_set_eval;
50 /* Ensure that subdivision is performed on the CPU. */
51 if (geometry_set.has_mesh()) {
52 add_final_mesh_as_geometry_component(object, geometry_set, apply_subdiv);
53 }
54 return geometry_set;
55 }
56
57 /* Otherwise, construct a new geometry set with the component based on the object type. */
58 if (object.type == OB_MESH) {
59 GeometrySet geometry_set;
60 add_final_mesh_as_geometry_component(object, geometry_set, apply_subdiv);
61 return geometry_set;
62 }
63 if (object.type == OB_EMPTY && object.instance_collection != nullptr) {
64 Collection &collection = *object.instance_collection;
65 std::unique_ptr<Instances> instances = std::make_unique<Instances>();
66 const int handle = instances->add_reference(collection);
67 instances->add_instance(handle, float4x4::identity());
68 return GeometrySet::from_instances(instances.release());
69 }
70
71 /* Return by value since there is not always an existing geometry set owned elsewhere to use. */
72 return {};
73}
74
76 FunctionRef<void(const GeometrySet &geometry_set)> callback) const
77{
78 for (const InstanceReference &reference : references_) {
79 switch (reference.type()) {
81 const Object &object = reference.object();
82 const GeometrySet object_geometry_set = object_get_evaluated_geometry_set(object);
83 callback(object_geometry_set);
84 break;
85 }
87 Collection &collection = reference.collection();
88 FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (&collection, object) {
89 const GeometrySet object_geometry_set = object_get_evaluated_geometry_set(*object);
90 callback(object_geometry_set);
91 }
93 break;
94 }
96 const GeometrySet &instance_geometry_set = reference.geometry_set();
97 callback(instance_geometry_set);
98 break;
99 }
101 break;
102 }
103 }
104 }
105}
106
108{
109 Vector<InstanceReference> new_references;
110 new_references.reserve(references_.size());
111 for (const InstanceReference &reference : references_) {
112 switch (reference.type()) {
114 new_references.append(InstanceReference(GeometrySet{}));
115 break;
116 }
118 /* Those references can stay as their were. */
119 new_references.append(reference);
120 break;
121 }
123 /* Create a new reference that contains the geometry set of the object. We may want to
124 * treat e.g. lamps and similar object types separately here. */
125 Object &object = reference.object();
126 if (ELEM(object.type, OB_LAMP, OB_CAMERA, OB_SPEAKER, OB_ARMATURE)) {
127 new_references.append(InstanceReference(object));
128 break;
129 }
130 GeometrySet object_geometry_set = object_get_evaluated_geometry_set(object);
131 object_geometry_set.name = BKE_id_name(object.id);
132 if (object_geometry_set.has_instances()) {
133 object_geometry_set.get_instances_for_write()->ensure_geometry_instances();
134 }
135 new_references.append(std::move(object_geometry_set));
136 break;
137 }
139 /* Create a new reference that contains a geometry set that contains all objects from the
140 * collection as instances. */
141 std::unique_ptr<Instances> instances = std::make_unique<Instances>();
142 Collection &collection = reference.collection();
143
144 Vector<Object *, 8> objects;
145 FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (&collection, object) {
146 objects.append(object);
147 }
149
150 instances->resize(objects.size());
151 MutableSpan<int> handles = instances->reference_handles_for_write();
152 MutableSpan<float4x4> transforms = instances->transforms_for_write();
153 for (const int i : objects.index_range()) {
154 handles[i] = instances->add_reference(*objects[i]);
155 transforms[i] = objects[i]->object_to_world();
156 transforms[i].location() -= collection.instance_offset;
157 }
158 instances->ensure_geometry_instances();
159 GeometrySet geometry_set = GeometrySet::from_instances(instances.release());
160 geometry_set.name = BKE_id_name(collection.id);
161 new_references.append(std::move(geometry_set));
162 break;
163 }
164 }
165 }
166 references_ = std::move(new_references);
167}
168
169} // namespace blender::bke
#define FOREACH_COLLECTION_OBJECT_RECURSIVE_END
#define FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(_collection, _object)
const char * BKE_id_name(const ID &id)
void BKE_mesh_wrapper_ensure_mdata(Mesh *mesh)
Mesh * BKE_modifier_get_evaluated_mesh_from_evaluated_object(Object *ob_eval)
General operations, lookup, etc. for blender objects.
Mesh * BKE_object_get_evaluated_mesh_no_subsurf(const Object *object_eval)
#define ELEM(...)
bool DEG_object_geometry_is_evaluated(const Object &object)
Object groups, one object can be in many groups at once.
Object is a sort of wrapper for general info.
@ OB_SPEAKER
@ OB_EMPTY
@ OB_CAMERA
@ OB_ARMATURE
@ OB_LAMP
@ OB_MESH
int64_t size() const
void append(const T &value)
IndexRange index_range() const
void reserve(const int64_t min_capacity)
Span< float4x4 > transforms() const
Definition instances.cc:228
void foreach_referenced_geometry(FunctionRef< void(const GeometrySet &geometry_set)> callback) const
GeometrySet object_get_evaluated_geometry_set(const Object &object, bool apply_subdiv=true)
static void add_final_mesh_as_geometry_component(const Object &object, GeometrySet &geometry_set, const bool apply_subdiv)
static GeometrySet from_instances(Instances *instances, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
Instances * get_instances_for_write()
void replace_mesh(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
i
Definition text_draw.cc:230
ParamHandle ** handles