Blender  V2.93
blender_geometry.cpp
Go to the documentation of this file.
1 
2 /*
3  * Copyright 2011-2013 Blender Foundation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include "render/curves.h"
19 #include "render/hair.h"
20 #include "render/mesh.h"
21 #include "render/object.h"
22 #include "render/volume.h"
23 
24 #include "blender/blender_sync.h"
25 #include "blender/blender_util.h"
26 
27 #include "util/util_foreach.h"
28 #include "util/util_task.h"
29 
31 
32 static Geometry::Type determine_geom_type(BL::Object &b_ob, bool use_particle_hair)
33 {
34  if (b_ob.type() == BL::Object::type_HAIR || use_particle_hair) {
35  return Geometry::HAIR;
36  }
37 
38  if (b_ob.type() == BL::Object::type_VOLUME || object_fluid_gas_domain_find(b_ob)) {
39  return Geometry::VOLUME;
40  }
41 
42  return Geometry::MESH;
43 }
44 
45 array<Node *> BlenderSync::find_used_shaders(BL::Object &b_ob)
46 {
47  BL::Material material_override = view_layer.material_override;
48  Shader *default_shader = (b_ob.type() == BL::Object::type_VOLUME) ? scene->default_volume :
49  scene->default_surface;
50 
51  array<Node *> used_shaders;
52 
53  for (BL::MaterialSlot &b_slot : b_ob.material_slots) {
54  if (material_override) {
55  find_shader(material_override, used_shaders, default_shader);
56  }
57  else {
58  BL::ID b_material(b_slot.material());
59  find_shader(b_material, used_shaders, default_shader);
60  }
61  }
62 
63  if (used_shaders.size() == 0) {
64  if (material_override)
65  find_shader(material_override, used_shaders, default_shader);
66  else
67  used_shaders.push_back_slow(default_shader);
68  }
69 
70  return used_shaders;
71 }
72 
73 Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
74  BL::Object &b_ob,
75  BL::Object &b_ob_instance,
76  bool object_updated,
77  bool use_particle_hair,
79 {
80  /* Test if we can instance or if the object is modified. */
81  BL::ID b_ob_data = b_ob.data();
82  BL::ID b_key_id = (BKE_object_is_modified(b_ob)) ? b_ob_instance : b_ob_data;
83  Geometry::Type geom_type = determine_geom_type(b_ob, use_particle_hair);
84  GeometryKey key(b_key_id.ptr.data, geom_type);
85 
86  /* Find shader indices. */
87  array<Node *> used_shaders = find_used_shaders(b_ob);
88 
89  /* Ensure we only sync instanced geometry once. */
90  Geometry *geom = geometry_map.find(key);
91  if (geom) {
92  if (geometry_synced.find(geom) != geometry_synced.end()) {
93  return geom;
94  }
95  }
96 
97  /* Test if we need to sync. */
98  bool sync = true;
99  if (geom == NULL) {
100  /* Add new geometry if it did not exist yet. */
101  if (geom_type == Geometry::HAIR) {
102  geom = scene->create_node<Hair>();
103  }
104  else if (geom_type == Geometry::VOLUME) {
105  geom = scene->create_node<Volume>();
106  }
107  else {
108  geom = scene->create_node<Mesh>();
109  }
110  geometry_map.add(key, geom);
111  }
112  else {
113  /* Test if we need to update existing geometry. */
114  sync = geometry_map.update(geom, b_key_id);
115  }
116 
117  if (!sync) {
118  /* If transform was applied to geometry, need full update. */
119  if (object_updated && geom->transform_applied) {
120  ;
121  }
122  /* Test if shaders changed, these can be object level so geometry
123  * does not get tagged for recalc. */
124  else if (geom->get_used_shaders() != used_shaders) {
125  ;
126  }
127  else {
128  /* Even if not tagged for recalc, we may need to sync anyway
129  * because the shader needs different geometry attributes. */
130  bool attribute_recalc = false;
131 
132  foreach (Node *node, geom->get_used_shaders()) {
133  Shader *shader = static_cast<Shader *>(node);
134  if (shader->need_update_geometry()) {
135  attribute_recalc = true;
136  }
137  }
138 
139  if (!attribute_recalc) {
140  return geom;
141  }
142  }
143  }
144 
145  geometry_synced.insert(geom);
146 
147  geom->name = ustring(b_ob_data.name().c_str());
148 
149  /* Store the shaders immediately for the object attribute code. */
150  geom->set_used_shaders(used_shaders);
151 
152  auto sync_func = [=]() mutable {
153  if (progress.get_cancel())
154  return;
155 
156  progress.set_sync_status("Synchronizing object", b_ob.name());
157 
158  if (geom_type == Geometry::HAIR) {
159  Hair *hair = static_cast<Hair *>(geom);
160  sync_hair(b_depsgraph, b_ob, hair);
161  }
162  else if (geom_type == Geometry::VOLUME) {
163  Volume *volume = static_cast<Volume *>(geom);
164  sync_volume(b_ob, volume);
165  }
166  else {
167  Mesh *mesh = static_cast<Mesh *>(geom);
168  sync_mesh(b_depsgraph, b_ob, mesh);
169  }
170  };
171 
172  /* Defer the actual geometry sync to the task_pool for multithreading */
173  if (task_pool) {
175  }
176  else {
177  sync_func();
178  }
179 
180  return geom;
181 }
182 
183 void BlenderSync::sync_geometry_motion(BL::Depsgraph &b_depsgraph,
184  BL::Object &b_ob,
185  Object *object,
186  float motion_time,
187  bool use_particle_hair,
189 {
190  /* Ensure we only sync instanced geometry once. */
191  Geometry *geom = object->get_geometry();
192 
193  if (geometry_motion_synced.find(geom) != geometry_motion_synced.end())
194  return;
195 
196  geometry_motion_synced.insert(geom);
197 
198  /* Ensure we only motion sync geometry that also had geometry synced, to avoid
199  * unnecessary work and to ensure that its attributes were clear. */
200  if (geometry_synced.find(geom) == geometry_synced.end())
201  return;
202 
203  /* Find time matching motion step required by geometry. */
204  int motion_step = geom->motion_step(motion_time);
205  if (motion_step < 0) {
206  return;
207  }
208 
209  auto sync_func = [=]() mutable {
210  if (progress.get_cancel())
211  return;
212 
213  if (b_ob.type() == BL::Object::type_HAIR || use_particle_hair) {
214  Hair *hair = static_cast<Hair *>(geom);
215  sync_hair_motion(b_depsgraph, b_ob, hair, motion_step);
216  }
217  else if (b_ob.type() == BL::Object::type_VOLUME || object_fluid_gas_domain_find(b_ob)) {
218  /* No volume motion blur support yet. */
219  }
220  else {
221  Mesh *mesh = static_cast<Mesh *>(geom);
222  sync_mesh_motion(b_depsgraph, b_ob, mesh, motion_step);
223  }
224  };
225 
226  /* Defer the actual geometry sync to the task_pool for multithreading */
227  if (task_pool) {
229  }
230  else {
231  sync_func();
232  }
233 }
234 
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
struct ID ID
struct Material Material
struct Object Object
static CCL_NAMESPACE_BEGIN Geometry::Type determine_geom_type(BL::Object &b_ob, bool use_particle_hair)
static PyObject * sync_func(PyObject *, PyObject *args)
static BL::FluidDomainSettings object_fluid_gas_domain_find(BL::Object &b_ob)
Definition: blender_util.h:555
@ MESH
Definition: geometry.h:73
@ VOLUME
Definition: geometry.h:75
@ HAIR
Definition: geometry.h:74
bool transform_applied
Definition: geometry.h:88
int motion_step(float time) const
Definition: geometry.cpp:150
bool get_cancel()
void set_sync_status(const string &status_, const string &substatus_="")
Definition: shader.h:80
void add(const K &key, T *data)
bool update(T *data, const BL::ID &id)
T * find(const BL::ID &id)
OperationNode * node
TaskPool * task_pool
#define CCL_NAMESPACE_END
void KERNEL_FUNCTION_FULL_NAME() shader(KernelGlobals *kg, uint4 *input, float4 *output, int type, int filter, int i, int offset, int sample)
Definition: node.h:98
ustring name
Definition: node.h:174
T * create_node(Args &&... args)
Definition: scene.h:302
Shader * default_volume
Definition: scene.h:254
Shader * default_surface
Definition: scene.h:253
void push(TaskRunFunction &&task)
Definition: util_task.cpp:36