Blender  V3.3
scene/object.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright 2011-2022 Blender Foundation */
3 
4 #include "scene/object.h"
5 #include "device/device.h"
6 #include "scene/camera.h"
7 #include "scene/curves.h"
8 #include "scene/hair.h"
9 #include "scene/integrator.h"
10 #include "scene/light.h"
11 #include "scene/mesh.h"
12 #include "scene/particles.h"
13 #include "scene/pointcloud.h"
14 #include "scene/scene.h"
15 #include "scene/stats.h"
16 #include "scene/volume.h"
17 
18 #include "util/foreach.h"
19 #include "util/log.h"
20 #include "util/map.h"
21 #include "util/murmurhash.h"
22 #include "util/progress.h"
23 #include "util/set.h"
24 #include "util/task.h"
25 #include "util/vector.h"
26 
27 #include "subd/patch_table.h"
28 
30 
31 /* Global state of object transform update. */
32 
34  /* Global state used by device_update_object_transform().
35  * Common for both threaded and non-threaded update.
36  */
37 
38  /* Type of the motion required by the scene settings. */
40 
41  /* Mapping from particle system to a index in packed particle array.
42  * Only used for read.
43  */
44  map<ParticleSystem *, int> particle_offset;
45 
46  /* Motion offsets for each object. */
48 
49  /* Packed object arrays. Those will be filled in. */
56 
57  /* Flags which will be synchronized to Integrator. */
62 
63  /* ** Scheduling queue. ** */
65 
66  /* First unused object index in the queue. */
68 };
69 
70 /* Object */
71 
73 {
74  NodeType *type = NodeType::add("object", create);
75 
76  SOCKET_NODE(geometry, "Geometry", Geometry::get_node_base_type());
77  SOCKET_TRANSFORM(tfm, "Transform", transform_identity());
78  SOCKET_UINT(visibility, "Visibility", ~0);
79  SOCKET_COLOR(color, "Color", zero_float3());
80  SOCKET_FLOAT(alpha, "Alpha", 0.0f);
81  SOCKET_UINT(random_id, "Random ID", 0);
82  SOCKET_INT(pass_id, "Pass ID", 0);
83  SOCKET_BOOLEAN(use_holdout, "Use Holdout", false);
84  SOCKET_BOOLEAN(hide_on_missing_motion, "Hide on Missing Motion", false);
85  SOCKET_POINT(dupli_generated, "Dupli Generated", zero_float3());
86  SOCKET_POINT2(dupli_uv, "Dupli UV", zero_float2());
87  SOCKET_TRANSFORM_ARRAY(motion, "Motion", array<Transform>());
88  SOCKET_FLOAT(shadow_terminator_shading_offset, "Shadow Terminator Shading Offset", 0.0f);
89  SOCKET_FLOAT(shadow_terminator_geometry_offset, "Shadow Terminator Geometry Offset", 0.1f);
90  SOCKET_STRING(asset_name, "Asset Name", ustring());
91 
92  SOCKET_BOOLEAN(is_shadow_catcher, "Shadow Catcher", false);
93 
94  SOCKET_BOOLEAN(is_caustics_caster, "Cast Shadow Caustics", false);
95  SOCKET_BOOLEAN(is_caustics_receiver, "Receive Shadow Caustics", false);
96 
97  SOCKET_NODE(particle_system, "Particle System", ParticleSystem::get_node_type());
98  SOCKET_INT(particle_index, "Particle Index", 0);
99 
100  SOCKET_FLOAT(ao_distance, "AO Distance", 0.0f);
101 
102  SOCKET_STRING(lightgroup, "Light Group", ustring());
103 
104  return type;
105 }
106 
107 Object::Object() : Node(get_node_type())
108 {
109  particle_system = NULL;
110  particle_index = 0;
111  attr_map_offset = 0;
113  intersects_volume = false;
114 }
115 
117 {
118 }
119 
121 {
122  if (!use_motion()) {
123  return;
124  }
125 
126  bool have_motion = false;
127 
128  for (size_t i = 0; i < motion.size(); i++) {
129  if (motion[i] == transform_empty()) {
130  if (hide_on_missing_motion) {
131  /* Hide objects that have no valid previous or next
132  * transform, for example particle that stop existing. It
133  * would be better to handle this in the kernel and make
134  * objects invisible outside certain motion steps. */
135  tfm = transform_empty();
136  motion.clear();
137  return;
138  }
139  else {
140  /* Otherwise just copy center motion. */
141  motion[i] = tfm;
142  }
143  }
144 
145  /* Test if any of the transforms are actually different. */
146  have_motion = have_motion || motion[i] != tfm;
147  }
148 
149  /* Clear motion array if there is no actual motion. */
150  if (!have_motion) {
151  motion.clear();
152  }
153 }
154 
155 void Object::compute_bounds(bool motion_blur)
156 {
157  BoundBox mbounds = geometry->bounds;
158 
159  if (motion_blur && use_motion()) {
160  array<DecomposedTransform> decomp(motion.size());
161  transform_motion_decompose(decomp.data(), motion.data(), motion.size());
162 
164 
165  /* TODO: this is really terrible. according to PBRT there is a better
166  * way to find this iteratively, but did not find implementation yet
167  * or try to implement myself */
168  for (float t = 0.0f; t < 1.0f; t += (1.0f / 128.0f)) {
169  Transform ttfm;
170 
171  transform_motion_array_interpolate(&ttfm, decomp.data(), motion.size(), t);
172  bounds.grow(mbounds.transformed(&ttfm));
173  }
174  }
175  else {
176  /* No motion blur case. */
177  if (geometry->transform_applied) {
178  bounds = mbounds;
179  }
180  else {
181  bounds = mbounds.transformed(&tfm);
182  }
183  }
184 }
185 
186 void Object::apply_transform(bool apply_to_motion)
187 {
188  if (!geometry || tfm == transform_identity())
189  return;
190 
191  geometry->apply_transform(tfm, apply_to_motion);
192 
193  /* we keep normals pointing in same direction on negative scale, notify
194  * geometry about this in it (re)calculates normals */
195  if (transform_negative_scale(tfm))
196  geometry->transform_negative_scaled = true;
197 
198  if (bounds.valid()) {
199  geometry->compute_bounds();
200  compute_bounds(false);
201  }
202 
203  /* tfm is not reset to identity, all code that uses it needs to check the
204  * transform_applied boolean */
205 }
206 
208 {
210 
211  if (is_modified()) {
213 
214  if (use_holdout_is_modified()) {
216  }
217 
218  if (is_shadow_catcher_is_modified()) {
220  }
221  }
222 
223  if (geometry) {
224  if (tfm_is_modified() || motion_is_modified()) {
226  }
227 
228  if (visibility_is_modified()) {
230  }
231 
232  foreach (Node *node, geometry->get_used_shaders()) {
233  Shader *shader = static_cast<Shader *>(node);
234  if (shader->get_use_mis() && shader->has_surface_emission)
236  }
237  }
238 
239  scene->camera->need_flags_update = true;
241 }
242 
243 bool Object::use_motion() const
244 {
245  return (motion.size() > 1);
246 }
247 
248 float Object::motion_time(int step) const
249 {
250  return (use_motion()) ? 2.0f * step / (motion.size() - 1) - 1.0f : 0.0f;
251 }
252 
253 int Object::motion_step(float time) const
254 {
255  if (use_motion()) {
256  for (size_t step = 0; step < motion.size(); step++) {
257  if (time == motion_time(step)) {
258  return step;
259  }
260  }
261  }
262 
263  return -1;
264 }
265 
267 {
268  /* Mesh itself can be empty,can skip all such objects. */
269  if (!bounds.valid() || bounds.size() == zero_float3()) {
270  return false;
271  }
272  /* TODO(sergey): Check for mesh vertices/curves. visibility flags. */
273  return true;
274 }
275 
277 {
278  return SHADOW_CATCHER_OBJECT_VISIBILITY(is_shadow_catcher, visibility & PATH_RAY_ALL_VISIBILITY);
279 }
280 
282 {
283  if (geometry->geometry_type != Geometry::MESH && geometry->geometry_type != Geometry::VOLUME) {
284  return FLT_MAX;
285  }
286 
287  Mesh *mesh = static_cast<Mesh *>(geometry);
288 
289  if (!mesh->has_volume) {
290  return FLT_MAX;
291  }
292 
293  /* Compute step rate from shaders. */
294  float step_rate = FLT_MAX;
295 
296  foreach (Node *node, mesh->get_used_shaders()) {
297  Shader *shader = static_cast<Shader *>(node);
298  if (shader->has_volume) {
299  if ((shader->get_heterogeneous_volume() && shader->has_volume_spatial_varying) ||
301  step_rate = fminf(shader->get_volume_step_rate(), step_rate);
302  }
303  }
304  }
305 
306  if (step_rate == FLT_MAX) {
307  return FLT_MAX;
308  }
309 
310  /* Compute step size from voxel grids. */
311  float step_size = FLT_MAX;
312 
313  if (geometry->geometry_type == Geometry::VOLUME) {
314  Volume *volume = static_cast<Volume *>(geometry);
315 
316  foreach (Attribute &attr, volume->attributes.attributes) {
317  if (attr.element == ATTR_ELEMENT_VOXEL) {
318  ImageHandle &handle = attr.data_voxel();
319  const ImageMetaData &metadata = handle.metadata();
320  if (metadata.width == 0 || metadata.height == 0 || metadata.depth == 0) {
321  continue;
322  }
323 
324  /* User specified step size. */
325  float voxel_step_size = volume->get_step_size();
326 
327  if (voxel_step_size == 0.0f) {
328  /* Auto detect step size. */
329  float3 size = one_float3();
330 #ifdef WITH_NANOVDB
331  /* Dimensions were not applied to image transform with NanoVDB (see image_vdb.cpp) */
332  if (metadata.type != IMAGE_DATA_TYPE_NANOVDB_FLOAT &&
333  metadata.type != IMAGE_DATA_TYPE_NANOVDB_FLOAT3 &&
334  metadata.type != IMAGE_DATA_TYPE_NANOVDB_FPN &&
336 #endif
337  size /= make_float3(metadata.width, metadata.height, metadata.depth);
338 
339  /* Step size is transformed from voxel to world space. */
340  Transform voxel_tfm = tfm;
341  if (metadata.use_transform_3d) {
342  voxel_tfm = tfm * transform_inverse(metadata.transform_3d);
343  }
344  voxel_step_size = reduce_min(fabs(transform_direction(&voxel_tfm, size)));
345  }
346  else if (volume->get_object_space()) {
347  /* User specified step size in object space. */
348  float3 size = make_float3(voxel_step_size, voxel_step_size, voxel_step_size);
349  voxel_step_size = reduce_min(fabs(transform_direction(&tfm, size)));
350  }
351 
352  if (voxel_step_size > 0.0f) {
353  step_size = fminf(voxel_step_size, step_size);
354  }
355  }
356  }
357  }
358 
359  if (step_size == FLT_MAX) {
360  /* Fall back to 1/10th of bounds for procedural volumes. */
361  step_size = 0.1f * average(bounds.size());
362  }
363 
364  step_size *= step_rate;
365 
366  return step_size;
367 }
368 
370 {
371  return index;
372 }
373 
374 /* Object Manager */
375 
377 {
378  update_flags = UPDATE_ALL;
379  need_flags_update = true;
380 }
381 
383 {
384 }
385 
386 static float object_volume_density(const Transform &tfm, Geometry *geom)
387 {
388  if (geom->geometry_type == Geometry::VOLUME) {
389  /* Volume density automatically adjust to object scale. */
390  if (static_cast<Volume *>(geom)->get_object_space()) {
391  const float3 unit = normalize(one_float3());
392  return 1.0f / len(transform_direction(&tfm, unit));
393  }
394  }
395 
396  return 1.0f;
397 }
398 
400  Object *ob,
401  bool update_all,
402  const Scene *scene)
403 {
404  KernelObject &kobject = state->objects[ob->index];
405  Transform *object_motion_pass = state->object_motion_pass;
406 
407  Geometry *geom = ob->geometry;
408  uint flag = 0;
409 
410  /* Compute transformations. */
411  Transform tfm = ob->tfm;
412  Transform itfm = transform_inverse(tfm);
413 
414  float3 color = ob->color;
415  float pass_id = ob->pass_id;
416  float random_number = (float)ob->random_id * (1.0f / (float)0xFFFFFFFF);
417  int particle_index = (ob->particle_system) ?
418  ob->particle_index + state->particle_offset[ob->particle_system] :
419  0;
420 
421  kobject.tfm = tfm;
422  kobject.itfm = itfm;
423  kobject.volume_density = object_volume_density(tfm, geom);
424  kobject.color[0] = color.x;
425  kobject.color[1] = color.y;
426  kobject.color[2] = color.z;
427  kobject.alpha = ob->alpha;
428  kobject.pass_id = pass_id;
429  kobject.random_number = random_number;
430  kobject.particle_index = particle_index;
431  kobject.motion_offset = 0;
432  kobject.ao_distance = ob->ao_distance;
433 
434  if (geom->get_use_motion_blur()) {
435  state->have_motion = true;
436  }
437 
439  /* TODO: why only mesh? */
440  Mesh *mesh = static_cast<Mesh *>(geom);
443  }
444  }
445  else if (geom->is_volume()) {
446  Volume *volume = static_cast<Volume *>(geom);
448  volume->get_velocity_scale() != 0.0f) {
450  kobject.velocity_scale = volume->get_velocity_scale();
451  }
452  }
453 
454  if (state->need_motion == Scene::MOTION_PASS) {
455  /* Clear motion array if there is no actual motion. */
456  ob->update_motion();
457 
458  /* Compute motion transforms. */
459  Transform tfm_pre, tfm_post;
460  if (ob->use_motion()) {
461  tfm_pre = ob->motion[0];
462  tfm_post = ob->motion[ob->motion.size() - 1];
463  }
464  else {
465  tfm_pre = tfm;
466  tfm_post = tfm;
467  }
468 
469  /* Motion transformations, is world/object space depending if mesh
470  * comes with deformed position in object space, or if we transform
471  * the shading point in world space. */
472  if (!(flag & SD_OBJECT_HAS_VERTEX_MOTION)) {
473  tfm_pre = tfm_pre * itfm;
474  tfm_post = tfm_post * itfm;
475  }
476 
477  int motion_pass_offset = ob->index * OBJECT_MOTION_PASS_SIZE;
478  object_motion_pass[motion_pass_offset + 0] = tfm_pre;
479  object_motion_pass[motion_pass_offset + 1] = tfm_post;
480  }
481  else if (state->need_motion == Scene::MOTION_BLUR) {
482  if (ob->use_motion()) {
483  kobject.motion_offset = state->motion_offset[ob->index];
484 
485  /* Decompose transforms for interpolation. */
486  if (ob->tfm_is_modified() || ob->motion_is_modified() || update_all) {
487  DecomposedTransform *decomp = state->object_motion + kobject.motion_offset;
488  transform_motion_decompose(decomp, ob->motion.data(), ob->motion.size());
489  }
490 
491  flag |= SD_OBJECT_MOTION;
492  state->have_motion = true;
493  }
494  }
495 
496  /* Dupli object coords and motion info. */
497  kobject.dupli_generated[0] = ob->dupli_generated[0];
498  kobject.dupli_generated[1] = ob->dupli_generated[1];
499  kobject.dupli_generated[2] = ob->dupli_generated[2];
500  kobject.numkeys = (geom->geometry_type == Geometry::HAIR) ?
501  static_cast<Hair *>(geom)->get_curve_keys().size() :
503  static_cast<PointCloud *>(geom)->num_points() :
504  0;
505  kobject.dupli_uv[0] = ob->dupli_uv[0];
506  kobject.dupli_uv[1] = ob->dupli_uv[1];
507  int totalsteps = geom->get_motion_steps();
508  kobject.numsteps = (totalsteps - 1) / 2;
509  kobject.numverts = (geom->geometry_type == Geometry::MESH ||
510  geom->geometry_type == Geometry::VOLUME) ?
511  static_cast<Mesh *>(geom)->get_verts().size() :
512  0;
513  kobject.patch_map_offset = 0;
514  kobject.attribute_map_offset = 0;
515 
516  if (ob->asset_name_is_modified() || update_all) {
517  uint32_t hash_name = util_murmur_hash3(ob->name.c_str(), ob->name.length(), 0);
518  uint32_t hash_asset = util_murmur_hash3(ob->asset_name.c_str(), ob->asset_name.length(), 0);
519  kobject.cryptomatte_object = util_hash_to_float(hash_name);
520  kobject.cryptomatte_asset = util_hash_to_float(hash_asset);
521  }
522 
523  kobject.shadow_terminator_shading_offset = 1.0f /
524  (1.0f - 0.5f * ob->shadow_terminator_shading_offset);
525  kobject.shadow_terminator_geometry_offset = ob->shadow_terminator_geometry_offset;
526 
527  kobject.visibility = ob->visibility_for_tracing();
528  kobject.primitive_type = geom->primitive_type();
529 
530  /* Object shadow caustics flag */
531  if (ob->is_caustics_caster) {
533  }
534  if (ob->is_caustics_receiver) {
536  }
537 
538  /* Object flag. */
539  if (ob->use_holdout) {
540  flag |= SD_OBJECT_HOLDOUT_MASK;
541  }
542  state->object_flag[ob->index] = flag;
543  state->object_volume_step[ob->index] = FLT_MAX;
544 
545  /* Have curves. */
546  if (geom->geometry_type == Geometry::HAIR) {
547  state->have_curves = true;
548  }
549  if (geom->geometry_type == Geometry::POINTCLOUD) {
550  state->have_points = true;
551  }
552  if (geom->geometry_type == Geometry::VOLUME) {
553  state->have_volumes = true;
554  }
555 
556  /* Light group. */
557  auto it = scene->lightgroups.find(ob->lightgroup);
558  if (it != scene->lightgroups.end()) {
559  kobject.lightgroup = it->second;
560  }
561  else {
562  kobject.lightgroup = LIGHTGROUP_NONE;
563  }
564 }
565 
567 {
568  BVHLayoutMask layout_mask = device->get_bvh_layout_mask();
569  if (layout_mask != BVH_LAYOUT_METAL && layout_mask != BVH_LAYOUT_MULTI_METAL &&
570  layout_mask != BVH_LAYOUT_MULTI_METAL_EMBREE) {
571  return;
572  }
573 
574  /* On MetalRT, primitive / curve segment offsets can't be baked at BVH build time. Intersection
575  * handlers need to apply the offset manually. */
576  uint *object_prim_offset = dscene->object_prim_offset.alloc(scene->objects.size());
577  foreach (Object *ob, scene->objects) {
578  uint32_t prim_offset = 0;
579  if (Geometry *const geom = ob->geometry) {
580  if (geom->geometry_type == Geometry::HAIR) {
581  prim_offset = ((Hair *const)geom)->curve_segment_offset;
582  }
583  else {
584  prim_offset = geom->prim_offset;
585  }
586  }
587  uint obj_index = ob->get_device_index();
588  object_prim_offset[obj_index] = prim_offset;
589  }
590 
593 }
594 
596 {
598  state.need_motion = scene->need_motion();
599  state.have_motion = false;
600  state.have_curves = false;
601  state.have_points = false;
602  state.have_volumes = false;
603  state.scene = scene;
604  state.queue_start_object = 0;
605 
606  state.objects = dscene->objects.alloc(scene->objects.size());
607  state.object_flag = dscene->object_flag.alloc(scene->objects.size());
608  state.object_volume_step = dscene->object_volume_step.alloc(scene->objects.size());
609  state.object_motion = NULL;
610  state.object_motion_pass = NULL;
611 
612  if (state.need_motion == Scene::MOTION_PASS) {
613  state.object_motion_pass = dscene->object_motion_pass.alloc(OBJECT_MOTION_PASS_SIZE *
614  scene->objects.size());
615  }
616  else if (state.need_motion == Scene::MOTION_BLUR) {
617  /* Set object offsets into global object motion array. */
618  uint *motion_offsets = state.motion_offset.resize(scene->objects.size());
619  uint motion_offset = 0;
620 
621  foreach (Object *ob, scene->objects) {
622  *motion_offsets = motion_offset;
623  motion_offsets++;
624 
625  /* Clear motion array if there is no actual motion. */
626  ob->update_motion();
627  motion_offset += ob->motion.size();
628  }
629 
630  state.object_motion = dscene->object_motion.alloc(motion_offset);
631  }
632 
633  /* Particle system device offsets
634  * 0 is dummy particle, index starts at 1.
635  */
636  int numparticles = 1;
637  foreach (ParticleSystem *psys, scene->particle_systems) {
638  state.particle_offset[psys] = numparticles;
639  numparticles += psys->particles.size();
640  }
641 
642  /* as all the arrays are the same size, checking only dscene.objects is sufficient */
643  const bool update_all = dscene->objects.need_realloc();
644 
645  /* Parallel object update, with grain size to avoid too much threading overhead
646  * for individual objects. */
647  static const int OBJECTS_PER_TASK = 32;
648  parallel_for(blocked_range<size_t>(0, scene->objects.size(), OBJECTS_PER_TASK),
649  [&](const blocked_range<size_t> &r) {
650  for (size_t i = r.begin(); i != r.end(); i++) {
651  Object *ob = state.scene->objects[i];
652  device_update_object_transform(&state, ob, update_all, scene);
653  }
654  });
655 
656  if (progress.get_cancel()) {
657  return;
658  }
659 
660  dscene->objects.copy_to_device_if_modified();
661  if (state.need_motion == Scene::MOTION_PASS) {
662  dscene->object_motion_pass.copy_to_device();
663  }
664  else if (state.need_motion == Scene::MOTION_BLUR) {
665  dscene->object_motion.copy_to_device();
666  }
667 
668  dscene->data.bvh.have_motion = state.have_motion;
669  dscene->data.bvh.have_curves = state.have_curves;
670  dscene->data.bvh.have_points = state.have_points;
671  dscene->data.bvh.have_volumes = state.have_volumes;
672 
673  dscene->objects.clear_modified();
674  dscene->object_motion_pass.clear_modified();
675  dscene->object_motion.clear_modified();
676 }
677 
679  DeviceScene *dscene,
680  Scene *scene,
681  Progress &progress)
682 {
683  if (!need_update())
684  return;
685 
686  if (update_flags & (OBJECT_ADDED | OBJECT_REMOVED)) {
687  dscene->objects.tag_realloc();
689  dscene->object_motion.tag_realloc();
690  dscene->object_flag.tag_realloc();
692  }
693 
694  if (update_flags & HOLDOUT_MODIFIED) {
695  dscene->object_flag.tag_modified();
696  }
697 
698  if (update_flags & PARTICLE_MODIFIED) {
699  dscene->objects.tag_modified();
700  }
701 
702  VLOG_INFO << "Total " << scene->objects.size() << " objects.";
703 
704  device_free(device, dscene, false);
705 
706  if (scene->objects.size() == 0)
707  return;
708 
709  {
710  /* Assign object IDs. */
711  scoped_callback_timer timer([scene](double time) {
712  if (scene->update_stats) {
713  scene->update_stats->object.times.add_entry({"device_update (assign index)", time});
714  }
715  });
716 
717  int index = 0;
718  foreach (Object *object, scene->objects) {
719  object->index = index++;
720 
721  /* this is a bit too broad, however a bigger refactor might be needed to properly separate
722  * update each type of data (transform, flags, etc.) */
723  if (object->is_modified()) {
724  dscene->objects.tag_modified();
726  dscene->object_motion.tag_modified();
727  dscene->object_flag.tag_modified();
729  }
730  }
731  }
732 
733  {
734  /* set object transform matrices, before applying static transforms */
735  scoped_callback_timer timer([scene](double time) {
736  if (scene->update_stats) {
737  scene->update_stats->object.times.add_entry(
738  {"device_update (copy objects to device)", time});
739  }
740  });
741 
742  progress.set_status("Updating Objects", "Copying Transformations to device");
743  device_update_transforms(dscene, scene, progress);
744  }
745 
746  if (progress.get_cancel())
747  return;
748 
749  /* prepare for static BVH building */
750  /* todo: do before to support getting object level coords? */
752  scoped_callback_timer timer([scene](double time) {
753  if (scene->update_stats) {
754  scene->update_stats->object.times.add_entry(
755  {"device_update (apply static transforms)", time});
756  }
757  });
758 
759  progress.set_status("Updating Objects", "Applying Static Transformations");
760  apply_static_transforms(dscene, scene, progress);
761  }
762 
763  foreach (Object *object, scene->objects) {
764  object->clear_modified();
765  }
766 }
767 
769  Device *, DeviceScene *dscene, Scene *scene, Progress & /*progress*/, bool bounds_valid)
770 {
771  if (!need_update() && !need_flags_update)
772  return;
773 
774  scoped_callback_timer timer([scene](double time) {
775  if (scene->update_stats) {
776  scene->update_stats->object.times.add_entry({"device_update_flags", time});
777  }
778  });
779 
780  update_flags = UPDATE_NONE;
781  need_flags_update = false;
782 
783  if (scene->objects.size() == 0)
784  return;
785 
786  /* Object info flag. */
787  uint *object_flag = dscene->object_flag.data();
788  float *object_volume_step = dscene->object_volume_step.data();
789 
790  /* Object volume intersection. */
791  vector<Object *> volume_objects;
792  bool has_volume_objects = false;
793  foreach (Object *object, scene->objects) {
794  if (object->geometry->has_volume) {
795  if (bounds_valid) {
796  volume_objects.push_back(object);
797  }
798  has_volume_objects = true;
799  object_volume_step[object->index] = object->compute_volume_step_size();
800  }
801  else {
802  object_volume_step[object->index] = FLT_MAX;
803  }
804  }
805 
806  foreach (Object *object, scene->objects) {
807  if (object->geometry->has_volume) {
808  object_flag[object->index] |= SD_OBJECT_HAS_VOLUME;
809  object_flag[object->index] &= ~SD_OBJECT_HAS_VOLUME_ATTRIBUTES;
810 
811  foreach (Attribute &attr, object->geometry->attributes.attributes) {
812  if (attr.element == ATTR_ELEMENT_VOXEL) {
813  object_flag[object->index] |= SD_OBJECT_HAS_VOLUME_ATTRIBUTES;
814  }
815  }
816  }
817  else {
818  object_flag[object->index] &= ~(SD_OBJECT_HAS_VOLUME | SD_OBJECT_HAS_VOLUME_ATTRIBUTES);
819  }
820 
821  if (object->is_shadow_catcher) {
822  object_flag[object->index] |= SD_OBJECT_SHADOW_CATCHER;
823  }
824  else {
825  object_flag[object->index] &= ~SD_OBJECT_SHADOW_CATCHER;
826  }
827 
828  if (bounds_valid) {
829  object->intersects_volume = false;
830  foreach (Object *volume_object, volume_objects) {
831  if (object == volume_object) {
832  continue;
833  }
834  if (object->bounds.intersects(volume_object->bounds)) {
835  object_flag[object->index] |= SD_OBJECT_INTERSECTS_VOLUME;
836  object->intersects_volume = true;
837  break;
838  }
839  }
840  }
841  else if (has_volume_objects) {
842  /* Not really valid, but can't make more reliable in the case
843  * of bounds not being up to date.
844  */
845  object_flag[object->index] |= SD_OBJECT_INTERSECTS_VOLUME;
846  }
847  }
848 
849  /* Copy object flag. */
850  dscene->object_flag.copy_to_device();
851  dscene->object_volume_step.copy_to_device();
852 
853  dscene->object_flag.clear_modified();
854  dscene->object_volume_step.clear_modified();
855 }
856 
858 {
859  if (dscene->objects.size() == 0) {
860  return;
861  }
862 
863  KernelObject *kobjects = dscene->objects.data();
864 
865  bool update = false;
866 
867  foreach (Object *object, scene->objects) {
868  Geometry *geom = object->geometry;
869 
870  if (geom->geometry_type == Geometry::MESH) {
871  Mesh *mesh = static_cast<Mesh *>(geom);
872  if (mesh->patch_table) {
873  uint patch_map_offset = 2 * (mesh->patch_table_offset + mesh->patch_table->total_size() -
874  mesh->patch_table->num_nodes * PATCH_NODE_SIZE) -
875  mesh->patch_offset;
876 
877  if (kobjects[object->index].patch_map_offset != patch_map_offset) {
878  kobjects[object->index].patch_map_offset = patch_map_offset;
879  update = true;
880  }
881  }
882  }
883 
884  size_t attr_map_offset = object->attr_map_offset;
885 
886  /* An object attribute map cannot have a zero offset because mesh maps come first. */
887  if (attr_map_offset == 0) {
888  attr_map_offset = geom->attr_map_offset;
889  }
890 
891  if (kobjects[object->index].attribute_map_offset != attr_map_offset) {
892  kobjects[object->index].attribute_map_offset = attr_map_offset;
893  update = true;
894  }
895  }
896 
897  if (update) {
898  dscene->objects.copy_to_device();
899  }
900 }
901 
902 void ObjectManager::device_free(Device *, DeviceScene *dscene, bool force_free)
903 {
904  dscene->objects.free_if_need_realloc(force_free);
905  dscene->object_motion_pass.free_if_need_realloc(force_free);
906  dscene->object_motion.free_if_need_realloc(force_free);
907  dscene->object_flag.free_if_need_realloc(force_free);
908  dscene->object_volume_step.free_if_need_realloc(force_free);
909  dscene->object_prim_offset.free_if_need_realloc(force_free);
910 }
911 
913 {
914  /* todo: normals and displacement should be done before applying transform! */
915  /* todo: create objects/geometry in right order! */
916 
917  /* counter geometry users */
918  map<Geometry *, int> geometry_users;
919  Scene::MotionType need_motion = scene->need_motion();
920  bool motion_blur = need_motion == Scene::MOTION_BLUR;
921  bool apply_to_motion = need_motion != Scene::MOTION_PASS;
922  int i = 0;
923 
924  foreach (Object *object, scene->objects) {
925  map<Geometry *, int>::iterator it = geometry_users.find(object->geometry);
926 
927  if (it == geometry_users.end())
928  geometry_users[object->geometry] = 1;
929  else
930  it->second++;
931  }
932 
933  if (progress.get_cancel())
934  return;
935 
936  uint *object_flag = dscene->object_flag.data();
937 
938  /* apply transforms for objects with single user geometry */
939  foreach (Object *object, scene->objects) {
940  /* Annoying feedback loop here: we can't use is_instanced() because
941  * it'll use uninitialized transform_applied flag.
942  *
943  * Could be solved by moving reference counter to Geometry.
944  */
945  Geometry *geom = object->geometry;
946  bool apply = (geometry_users[geom] == 1) && !geom->has_surface_bssrdf &&
947  !geom->has_true_displacement();
948 
949  if (geom->geometry_type == Geometry::MESH) {
950  Mesh *mesh = static_cast<Mesh *>(geom);
951  apply = apply && mesh->get_subdivision_type() == Mesh::SUBDIVISION_NONE;
952  }
953  else if (geom->geometry_type == Geometry::HAIR) {
954  /* Can't apply non-uniform scale to curves, this can't be represented by
955  * control points and radius alone. */
956  float scale;
957  apply = apply && transform_uniform_scale(object->tfm, scale);
958  }
959 
960  if (apply) {
961  if (!(motion_blur && object->use_motion())) {
962  if (!geom->transform_applied) {
963  object->apply_transform(apply_to_motion);
964  geom->transform_applied = true;
965 
966  if (progress.get_cancel())
967  return;
968  }
969 
970  object_flag[i] |= SD_OBJECT_TRANSFORM_APPLIED;
971  if (geom->transform_negative_scaled)
972  object_flag[i] |= SD_OBJECT_NEGATIVE_SCALE_APPLIED;
973  }
974  }
975 
976  i++;
977  }
978 }
979 
981 {
982  update_flags |= flag;
983 
984  /* avoid infinite loops if the geometry manager tagged us for an update */
985  if ((flag & GEOMETRY_MANAGER) == 0) {
987 
988  /* Also notify in case added or removed objects were instances, as no Geometry might have been
989  * added or removed, but the BVH still needs to updated. */
990  if ((flag & (OBJECT_ADDED | OBJECT_REMOVED)) != 0) {
992  }
993 
994  if ((flag & TRANSFORM_MODIFIED) != 0) {
995  geometry_flag |= GeometryManager::TRANSFORM_MODIFIED;
996  }
997 
998  if ((flag & VISIBILITY_MODIFIED) != 0) {
999  geometry_flag |= GeometryManager::VISIBILITY_MODIFIED;
1000  }
1001 
1002  scene->geometry_manager->tag_update(scene, geometry_flag);
1003  }
1004 
1006 
1007  /* Integrator's shadow catcher settings depends on object visibility settings. */
1008  if (flag & (OBJECT_ADDED | OBJECT_REMOVED | OBJECT_MODIFIED)) {
1010  }
1011 }
1012 
1014 {
1015  return update_flags != UPDATE_NONE;
1016 }
1017 
1019 {
1020  string manifest = "{";
1021 
1022  unordered_set<ustring, ustringHash> objects;
1023  foreach (Object *object, scene->objects) {
1024  if (objects.count(object->name)) {
1025  continue;
1026  }
1027  objects.insert(object->name);
1028  uint32_t hash_name = util_murmur_hash3(object->name.c_str(), object->name.length(), 0);
1029  manifest += string_printf("\"%s\":\"%08x\",", object->name.c_str(), hash_name);
1030  }
1031  manifest[manifest.size() - 1] = '}';
1032  return manifest;
1033 }
1034 
1036 {
1037  string manifest = "{";
1038  unordered_set<ustring, ustringHash> assets;
1039  foreach (Object *ob, scene->objects) {
1040  if (assets.count(ob->asset_name)) {
1041  continue;
1042  }
1043  assets.insert(ob->asset_name);
1044  uint32_t hash_asset = util_murmur_hash3(ob->asset_name.c_str(), ob->asset_name.length(), 0);
1045  manifest += string_printf("\"%s\":\"%08x\",", ob->asset_name.c_str(), hash_asset);
1046  }
1047  manifest[manifest.size() - 1] = '}';
1048  return manifest;
1049 }
1050 
typedef float(TangentPoint)[2]
unsigned int uint
Definition: BLI_sys_types.h:67
_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 const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
_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
_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 const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
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 used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a color
__forceinline int reduce_min(const avxi &v)
Definition: avxi.h:688
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
list< Attribute > attributes
Attribute * find(ustring name) const
ImageHandle & data_voxel()
AttributeElement element
device_vector< DecomposedTransform > object_motion
Definition: scene.h:92
device_vector< Transform > object_motion_pass
Definition: scene.h:91
device_vector< float > object_volume_step
Definition: scene.h:94
device_vector< uint > object_prim_offset
Definition: scene.h:95
device_vector< uint > object_flag
Definition: scene.h:93
device_vector< KernelObject > objects
Definition: scene.h:90
virtual BVHLayoutMask get_bvh_layout_mask() const =0
void tag_update(Scene *scene, uint32_t flag)
Type geometry_type
bool transform_applied
bool has_volume
bool has_true_displacement() const
bool is_volume() const
bool has_surface_bssrdf
virtual PrimitiveType primitive_type() const =0
size_t attr_map_offset
AttributeSet attributes
bool transform_negative_scaled
Definition: hair.h:13
ImageMetaData metadata()
ImageDataType type
Transform transform_3d
void tag_update(Scene *scene, uint32_t flag)
Definition: integrator.cpp:291
@ OBJECT_MANAGER
Definition: integrator.h:88
@ EMISSIVE_MESH_MODIFIED
Definition: scene/light.h:88
void tag_update(Scene *scene, uint32_t flag)
string get_cryptomatte_objects(Scene *scene)
void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress)
void tag_update(Scene *scene, uint32_t flag)
void device_update_object_transform(UpdateObjectTransformState *state, Object *ob, bool update_all, const Scene *scene)
void device_free(Device *device, DeviceScene *dscene, bool force_free)
string get_cryptomatte_assets(Scene *scene)
bool need_update() const
void device_update_geom_offsets(Device *device, DeviceScene *dscene, Scene *scene)
void device_update_prim_offsets(Device *device, DeviceScene *dscene, Scene *scene)
void device_update_transforms(DeviceScene *dscene, Scene *scene, Progress &progress)
void apply_static_transforms(DeviceScene *dscene, Scene *scene, Progress &progress)
bool need_flags_update
Definition: scene/object.h:144
void device_update_flags(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress, bool bounds_valid=true)
bool get_cancel() const
Definition: progress.h:90
BVHType bvh_type
Definition: scene.h:148
bool has_volume_attribute_dependency
Definition: scene/shader.h:114
bool has_volume
Definition: scene/shader.h:107
bool has_surface_emission
Definition: scene/shader.h:104
bool has_volume_spatial_varying
Definition: scene/shader.h:113
T * alloc(size_t width, size_t height=0, size_t depth=0)
size_t size() const
void free_if_need_realloc(bool force_free)
#define CCL_NAMESPACE_END
Definition: cuda/compat.h:9
OperationNode * node
double time
Scene scene
int len
Definition: draw_manager.c:108
ccl_device_inline Transform transform_identity()
ccl_device void transform_motion_array_interpolate(ccl_private Transform *tfm, ccl_global const DecomposedTransform *motion, uint numsteps, float time)
ccl_device_inline Transform transform_empty()
ccl_device_inline bool transform_negative_scale(const Transform &tfm)
ccl_device_inline Transform transform_inverse(const Transform tfm)
ccl_device_inline float3 transform_direction(ccl_private const Transform *t, const float3 a)
ccl_device_inline bool transform_uniform_scale(const Transform &tfm, float &scale)
const int state
ccl_device_inline uint particle_index(KernelGlobals kg, int particle)
@ ATTR_STD_VOLUME_VELOCITY
Definition: kernel/types.h:638
@ ATTR_STD_MOTION_VERTEX_POSITION
Definition: kernel/types.h:624
@ PATH_RAY_ALL_VISIBILITY
Definition: kernel/types.h:217
#define OBJECT_MOTION_PASS_SIZE
Definition: kernel/types.h:25
@ SD_OBJECT_MOTION
Definition: kernel/types.h:806
@ SD_OBJECT_HAS_VOLUME_ATTRIBUTES
Definition: kernel/types.h:820
@ SD_OBJECT_HAS_VOLUME
Definition: kernel/types.h:812
@ SD_OBJECT_INTERSECTS_VOLUME
Definition: kernel/types.h:814
@ SD_OBJECT_HOLDOUT_MASK
Definition: kernel/types.h:804
@ SD_OBJECT_HAS_VOLUME_MOTION
Definition: kernel/types.h:826
@ SD_OBJECT_CAUSTICS_RECEIVER
Definition: kernel/types.h:824
@ SD_OBJECT_SHADOW_CATCHER
Definition: kernel/types.h:818
@ SD_OBJECT_TRANSFORM_APPLIED
Definition: kernel/types.h:808
@ SD_OBJECT_HAS_VERTEX_MOTION
Definition: kernel/types.h:816
@ SD_OBJECT_NEGATIVE_SCALE_APPLIED
Definition: kernel/types.h:810
@ SD_OBJECT_CAUSTICS_CASTER
Definition: kernel/types.h:822
@ BVH_LAYOUT_METAL
@ BVH_LAYOUT_MULTI_METAL
@ BVH_LAYOUT_MULTI_METAL_EMBREE
@ ATTR_ELEMENT_VOXEL
Definition: kernel/types.h:609
#define LIGHTGROUP_NONE
Definition: kernel/types.h:45
#define SHADOW_CATCHER_OBJECT_VISIBILITY(is_shadow_catcher, visibility)
Definition: kernel/types.h:310
#define VLOG_INFO
Definition: log.h:77
ccl_device_inline float2 zero_float2()
Definition: math_float2.h:62
ccl_device_inline float average(const float2 &a)
Definition: math_float2.h:170
ccl_device_inline float2 fabs(const float2 &a)
Definition: math_float2.h:222
ccl_device_inline float3 one_float3()
Definition: math_float3.h:89
ccl_device_inline float3 zero_float3()
Definition: math_float3.h:80
#define fminf(x, y)
Definition: metal/compat.h:229
#define make_float3(x, y, z)
Definition: metal/compat.h:204
float util_hash_to_float(uint32_t hash)
Definition: murmurhash.cpp:98
uint32_t util_murmur_hash3(const void *key, int len, uint32_t seed)
Definition: murmurhash.cpp:49
std::unique_ptr< IDProperty, IDPropertyDeleter > create(StringRefNull prop_name, int32_t value)
Allocate a new IDProperty of type IDP_INT, set its name and value.
vec_base< T, Size > normalize(const vec_base< T, Size > &v)
void parallel_for(IndexRange range, int64_t grain_size, const Function &function)
Definition: BLI_task.hh:51
static void update(bNodeTree *ntree)
#define SOCKET_POINT(name, ui_name, default_value,...)
Definition: node_type.h:197
#define SOCKET_FLOAT(name, ui_name, default_value,...)
Definition: node_type.h:191
#define SOCKET_INT(name, ui_name, default_value,...)
Definition: node_type.h:187
#define SOCKET_NODE(name, ui_name, node_type,...)
Definition: node_type.h:220
#define SOCKET_TRANSFORM(name, ui_name, default_value,...)
Definition: node_type.h:205
#define SOCKET_UINT(name, ui_name, default_value,...)
Definition: node_type.h:189
#define SOCKET_COLOR(name, ui_name, default_value,...)
Definition: node_type.h:193
#define SOCKET_TRANSFORM_ARRAY(name, ui_name, default_value,...)
Definition: node_type.h:260
#define SOCKET_BOOLEAN(name, ui_name, default_value,...)
Definition: node_type.h:185
#define SOCKET_POINT2(name, ui_name, default_value,...)
Definition: node_type.h:201
#define SOCKET_STRING(name, ui_name, default_value,...)
Definition: node_type.h:203
int BVHLayoutMask
Definition: params.h:47
@ BVH_TYPE_STATIC
Definition: params.h:37
#define PATCH_NODE_SIZE
Definition: patch_table.h:32
NODE_DEFINE(Object)
static float object_volume_density(const Transform &tfm, Geometry *geom)
unsigned int uint32_t
Definition: stdint.h:80
CCL_NAMESPACE_BEGIN string string_printf(const char *format,...)
Definition: string.cpp:22
BoundBox transformed(const Transform *tfm) const
Definition: boundbox.h:136
@ empty
Definition: boundbox.h:35
__forceinline bool valid() const
Definition: boundbox.h:129
__forceinline float3 size() const
Definition: boundbox.h:124
__forceinline bool intersects(const BoundBox &other)
Definition: boundbox.h:153
__forceinline void grow(const float3 &pt)
Definition: boundbox.h:42
float velocity_scale
Transform tfm
Transform itfm
float dupli_uv[2]
float volume_density
float random_number
float shadow_terminator_geometry_offset
float cryptomatte_asset
float color[3]
uint attribute_map_offset
uint patch_map_offset
float shadow_terminator_shading_offset
float dupli_generated[3]
float cryptomatte_object
float size[3]
@ SUBDIVISION_NONE
Definition: scene/mesh.h:120
static NodeType * add(const char *name, CreateFunc create, Type type=NONE, const NodeType *base=NULL)
ustring name
Definition: graph/node.h:174
bool is_modified() const
Definition: graph/node.cpp:804
void compute_bounds(bool motion_blur)
int motion_step(float time) const
bool use_motion() const
NODE_DECLARE BoundBox bounds
Definition: scene/object.h:43
size_t attr_map_offset
Definition: scene/object.h:115
vector< ParamValue > attributes
Definition: scene/object.h:49
void update_motion()
int get_device_index() const
void apply_transform(bool apply_to_motion)
float compute_volume_step_size() const
bool is_traceable() const
uint visibility_for_tracing() const
void tag_update(Scene *scene)
float color[4]
float motion_time(int step) const
void * data
struct LightgroupMembership * lightgroup
bool intersects_volume
Definition: scene/object.h:72
ParticleData * particles
size_t num_points() const
MotionType need_motion() const
Definition: scene.cpp:387
SceneParams params
Definition: scene.h:243
void tag_shadow_catcher_modified()
Definition: scene.cpp:754
vector< ParticleSystem * > particle_systems
Definition: scene.h:217
vector< Object * > objects
Definition: scene.h:213
ObjectManager * object_manager
Definition: scene.h:226
MotionType
Definition: scene.h:259
@ MOTION_PASS
Definition: scene.h:259
@ MOTION_BLUR
Definition: scene.h:259
Integrator * integrator
Definition: scene.h:210
LightManager * light_manager
Definition: scene.h:223
struct Object * camera
map< ustring, int > lightgroups
Definition: scene.h:201
SceneUpdateStats * update_stats
Definition: scene.h:249
GeometryManager * geometry_manager
Definition: scene.h:225
map< ParticleSystem *, int > particle_offset
DecomposedTransform * object_motion
Scene::MotionType need_motion
void transform_motion_decompose(DecomposedTransform *decomp, const Transform *motion, size_t size)
Definition: transform.cpp:246
@ IMAGE_DATA_TYPE_NANOVDB_FP16
Definition: util/texture.h:41
@ IMAGE_DATA_TYPE_NANOVDB_FLOAT
Definition: util/texture.h:38
@ IMAGE_DATA_TYPE_NANOVDB_FLOAT3
Definition: util/texture.h:39
@ IMAGE_DATA_TYPE_NANOVDB_FPN
Definition: util/texture.h:40