Blender  V2.93
bvh_embree.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2018, Blender Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /* This class implements a ray accelerator for Cycles using Intel's Embree library.
18  * It supports triangles, curves, object and deformation blur and instancing.
19  *
20  * Since Embree allows object to be either curves or triangles but not both, Cycles object IDs are
21  * mapped to Embree IDs by multiplying by two and adding one for curves.
22  *
23  * This implementation shares RTCDevices between Cycles instances. Eventually each instance should
24  * get a separate RTCDevice to correctly keep track of memory usage.
25  *
26  * Vertex and index buffers are duplicated between Cycles device arrays and Embree. These could be
27  * merged, which would require changes to intersection refinement, shader setup, mesh light
28  * sampling and a few other places in Cycles where direct access to vertex data is required.
29  */
30 
31 #ifdef WITH_EMBREE
32 
33 # include <embree3/rtcore_geometry.h>
34 
35 # include "bvh/bvh_embree.h"
36 
37 /* Kernel includes are necessary so that the filter function for Embree can access the packed BVH.
38  */
39 # include "kernel/bvh/bvh_embree.h"
41 # include "kernel/kernel_globals.h"
42 # include "kernel/kernel_random.h"
44 
45 # include "render/hair.h"
46 # include "render/mesh.h"
47 # include "render/object.h"
48 
49 # include "util/util_foreach.h"
50 # include "util/util_logging.h"
51 # include "util/util_progress.h"
52 # include "util/util_stats.h"
53 
55 
56 static_assert(Object::MAX_MOTION_STEPS <= RTC_MAX_TIME_STEP_COUNT,
57  "Object and Embree max motion steps inconsistent");
59  "Object and Geometry max motion steps inconsistent");
60 
61 # define IS_HAIR(x) (x & 1)
62 
63 /* This gets called by Embree at every valid ray/object intersection.
64  * Things like recording subsurface or shadow hits for later evaluation
65  * as well as filtering for volume objects happen here.
66  * Cycles' own BVH does that directly inside the traversal calls.
67  */
68 static void rtc_filter_occluded_func(const RTCFilterFunctionNArguments *args)
69 {
70  /* Current implementation in Cycles assumes only single-ray intersection queries. */
71  assert(args->N == 1);
72 
73  const RTCRay *ray = (RTCRay *)args->ray;
74  RTCHit *hit = (RTCHit *)args->hit;
75  CCLIntersectContext *ctx = ((IntersectContext *)args->context)->userRayExt;
76  KernelGlobals *kg = ctx->kg;
77 
78  switch (ctx->type) {
80  /* Append the intersection to the end of the array. */
81  if (ctx->num_hits < ctx->max_hits) {
82  Intersection current_isect;
83  kernel_embree_convert_hit(kg, ray, hit, &current_isect);
84  for (size_t i = 0; i < ctx->max_hits; ++i) {
85  if (current_isect.object == ctx->isect_s[i].object &&
86  current_isect.prim == ctx->isect_s[i].prim && current_isect.t == ctx->isect_s[i].t) {
87  /* This intersection was already recorded, skip it. */
88  *args->valid = 0;
89  break;
90  }
91  }
92  Intersection *isect = &ctx->isect_s[ctx->num_hits];
93  ++ctx->num_hits;
94  *isect = current_isect;
95  int prim = kernel_tex_fetch(__prim_index, isect->prim);
96  int shader = 0;
97  if (kernel_tex_fetch(__prim_type, isect->prim) & PRIMITIVE_ALL_TRIANGLE) {
98  shader = kernel_tex_fetch(__tri_shader, prim);
99  }
100  else {
101  float4 str = kernel_tex_fetch(__curves, prim);
103  }
104  int flag = kernel_tex_fetch(__shaders, shader & SHADER_MASK).flags;
105  /* If no transparent shadows, all light is blocked. */
106  if (flag & (SD_HAS_TRANSPARENT_SHADOW)) {
107  /* This tells Embree to continue tracing. */
108  *args->valid = 0;
109  }
110  }
111  else {
112  /* Increase the number of hits beyond ray.max_hits
113  * so that the caller can detect this as opaque. */
114  ++ctx->num_hits;
115  }
116  break;
117  }
120  /* Check if it's hitting the correct object. */
121  Intersection current_isect;
122  if (ctx->type == CCLIntersectContext::RAY_SSS) {
123  kernel_embree_convert_sss_hit(kg, ray, hit, &current_isect, ctx->local_object_id);
124  }
125  else {
126  kernel_embree_convert_hit(kg, ray, hit, &current_isect);
127  int object = (current_isect.object == OBJECT_NONE) ?
128  kernel_tex_fetch(__prim_object, current_isect.prim) :
129  current_isect.object;
130  if (ctx->local_object_id != object) {
131  /* This tells Embree to continue tracing. */
132  *args->valid = 0;
133  break;
134  }
135  }
136 
137  /* No intersection information requested, just return a hit. */
138  if (ctx->max_hits == 0) {
139  break;
140  }
141 
142  /* Ignore curves. */
143  if (IS_HAIR(hit->geomID)) {
144  /* This tells Embree to continue tracing. */
145  *args->valid = 0;
146  break;
147  }
148 
149  /* See triangle_intersect_subsurface() for the native equivalent. */
150  for (int i = min(ctx->max_hits, ctx->local_isect->num_hits) - 1; i >= 0; --i) {
151  if (ctx->local_isect->hits[i].t == ray->tfar) {
152  /* This tells Embree to continue tracing. */
153  *args->valid = 0;
154  break;
155  }
156  }
157 
158  int hit_idx = 0;
159 
160  if (ctx->lcg_state) {
161 
162  ++ctx->local_isect->num_hits;
163  if (ctx->local_isect->num_hits <= ctx->max_hits) {
164  hit_idx = ctx->local_isect->num_hits - 1;
165  }
166  else {
167  /* reservoir sampling: if we are at the maximum number of
168  * hits, randomly replace element or skip it */
169  hit_idx = lcg_step_uint(ctx->lcg_state) % ctx->local_isect->num_hits;
170 
171  if (hit_idx >= ctx->max_hits) {
172  /* This tells Embree to continue tracing. */
173  *args->valid = 0;
174  break;
175  }
176  }
177  }
178  else {
179  ctx->local_isect->num_hits = 1;
180  }
181  /* record intersection */
182  ctx->local_isect->hits[hit_idx] = current_isect;
183  ctx->local_isect->Ng[hit_idx] = normalize(make_float3(hit->Ng_x, hit->Ng_y, hit->Ng_z));
184  /* This tells Embree to continue tracing .*/
185  *args->valid = 0;
186  break;
187  }
189  /* Append the intersection to the end of the array. */
190  if (ctx->num_hits < ctx->max_hits) {
191  Intersection current_isect;
192  kernel_embree_convert_hit(kg, ray, hit, &current_isect);
193  for (size_t i = 0; i < ctx->max_hits; ++i) {
194  if (current_isect.object == ctx->isect_s[i].object &&
195  current_isect.prim == ctx->isect_s[i].prim && current_isect.t == ctx->isect_s[i].t) {
196  /* This intersection was already recorded, skip it. */
197  *args->valid = 0;
198  break;
199  }
200  }
201  Intersection *isect = &ctx->isect_s[ctx->num_hits];
202  ++ctx->num_hits;
203  *isect = current_isect;
204  /* Only primitives from volume object. */
205  uint tri_object = (isect->object == OBJECT_NONE) ?
206  kernel_tex_fetch(__prim_object, isect->prim) :
207  isect->object;
208  int object_flag = kernel_tex_fetch(__object_flag, tri_object);
209  if ((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
210  --ctx->num_hits;
211  }
212  /* This tells Embree to continue tracing. */
213  *args->valid = 0;
214  break;
215  }
216  }
218  default:
219  /* Nothing to do here. */
220  break;
221  }
222 }
223 
224 static void rtc_filter_func_thick_curve(const RTCFilterFunctionNArguments *args)
225 {
226  const RTCRay *ray = (RTCRay *)args->ray;
227  RTCHit *hit = (RTCHit *)args->hit;
228 
229  /* Always ignore backfacing intersections. */
230  if (dot(make_float3(ray->dir_x, ray->dir_y, ray->dir_z),
231  make_float3(hit->Ng_x, hit->Ng_y, hit->Ng_z)) > 0.0f) {
232  *args->valid = 0;
233  return;
234  }
235 }
236 
237 static void rtc_filter_occluded_func_thick_curve(const RTCFilterFunctionNArguments *args)
238 {
239  const RTCRay *ray = (RTCRay *)args->ray;
240  RTCHit *hit = (RTCHit *)args->hit;
241 
242  /* Always ignore backfacing intersections. */
243  if (dot(make_float3(ray->dir_x, ray->dir_y, ray->dir_z),
244  make_float3(hit->Ng_x, hit->Ng_y, hit->Ng_z)) > 0.0f) {
245  *args->valid = 0;
246  return;
247  }
248 
249  rtc_filter_occluded_func(args);
250 }
251 
252 static size_t unaccounted_mem = 0;
253 
254 static bool rtc_memory_monitor_func(void *userPtr, const ssize_t bytes, const bool)
255 {
256  Stats *stats = (Stats *)userPtr;
257  if (stats) {
258  if (bytes > 0) {
259  stats->mem_alloc(bytes);
260  }
261  else {
262  stats->mem_free(-bytes);
263  }
264  }
265  else {
266  /* A stats pointer may not yet be available. Keep track of the memory usage for later. */
267  if (bytes >= 0) {
268  atomic_add_and_fetch_z(&unaccounted_mem, bytes);
269  }
270  else {
271  atomic_sub_and_fetch_z(&unaccounted_mem, -bytes);
272  }
273  }
274  return true;
275 }
276 
277 static void rtc_error_func(void *, enum RTCError, const char *str)
278 {
279  VLOG(1) << str;
280 }
281 
282 static double progress_start_time = 0.0f;
283 
284 static bool rtc_progress_func(void *user_ptr, const double n)
285 {
286  Progress *progress = (Progress *)user_ptr;
287 
288  if (time_dt() - progress_start_time < 0.25) {
289  return true;
290  }
291 
292  string msg = string_printf("Building BVH %.0f%%", n * 100.0);
293  progress->set_substatus(msg);
294  progress_start_time = time_dt();
295 
296  return !progress->get_cancel();
297 }
298 
299 BVHEmbree::BVHEmbree(const BVHParams &params_,
300  const vector<Geometry *> &geometry_,
301  const vector<Object *> &objects_)
302  : BVH(params_, geometry_, objects_),
303  scene(NULL),
304  rtc_device(NULL),
305  build_quality(RTC_BUILD_QUALITY_REFIT)
306 {
308 }
309 
310 BVHEmbree::~BVHEmbree()
311 {
312  if (scene) {
313  rtcReleaseScene(scene);
314  }
315 }
316 
317 void BVHEmbree::build(Progress &progress, Stats *stats, RTCDevice rtc_device_)
318 {
319  rtc_device = rtc_device_;
320  assert(rtc_device);
321 
322  rtcSetDeviceErrorFunction(rtc_device, rtc_error_func, NULL);
323  rtcSetDeviceMemoryMonitorFunction(rtc_device, rtc_memory_monitor_func, stats);
324 
325  progress.set_substatus("Building BVH");
326 
327  if (scene) {
328  rtcReleaseScene(scene);
329  scene = NULL;
330  }
331 
332  const bool dynamic = params.bvh_type == SceneParams::BVH_DYNAMIC;
333 
334  scene = rtcNewScene(rtc_device);
335  const RTCSceneFlags scene_flags = (dynamic ? RTC_SCENE_FLAG_DYNAMIC : RTC_SCENE_FLAG_NONE) |
336  RTC_SCENE_FLAG_COMPACT | RTC_SCENE_FLAG_ROBUST;
337  rtcSetSceneFlags(scene, scene_flags);
338  build_quality = dynamic ? RTC_BUILD_QUALITY_LOW :
339  (params.use_spatial_split ? RTC_BUILD_QUALITY_HIGH :
340  RTC_BUILD_QUALITY_MEDIUM);
341  rtcSetSceneBuildQuality(scene, build_quality);
342 
343  int i = 0;
344  foreach (Object *ob, objects) {
345  if (params.top_level) {
346  if (!ob->is_traceable()) {
347  ++i;
348  continue;
349  }
350  if (!ob->get_geometry()->is_instanced()) {
351  add_object(ob, i);
352  }
353  else {
354  add_instance(ob, i);
355  }
356  }
357  else {
358  add_object(ob, i);
359  }
360  ++i;
361  if (progress.get_cancel())
362  return;
363  }
364 
365  if (progress.get_cancel()) {
366  return;
367  }
368 
369  rtcSetSceneProgressMonitorFunction(scene, rtc_progress_func, &progress);
370  rtcCommitScene(scene);
371 }
372 
373 void BVHEmbree::add_object(Object *ob, int i)
374 {
375  Geometry *geom = ob->get_geometry();
376 
377  if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) {
378  Mesh *mesh = static_cast<Mesh *>(geom);
379  if (mesh->num_triangles() > 0) {
380  add_triangles(ob, mesh, i);
381  }
382  }
383  else if (geom->geometry_type == Geometry::HAIR) {
384  Hair *hair = static_cast<Hair *>(geom);
385  if (hair->num_curves() > 0) {
386  add_curves(ob, hair, i);
387  }
388  }
389 }
390 
391 void BVHEmbree::add_instance(Object *ob, int i)
392 {
393  BVHEmbree *instance_bvh = (BVHEmbree *)(ob->get_geometry()->bvh);
394  assert(instance_bvh != NULL);
395 
396  const size_t num_object_motion_steps = ob->use_motion() ? ob->get_motion().size() : 1;
397  const size_t num_motion_steps = min(num_object_motion_steps, RTC_MAX_TIME_STEP_COUNT);
398  assert(num_object_motion_steps <= RTC_MAX_TIME_STEP_COUNT);
399 
400  RTCGeometry geom_id = rtcNewGeometry(rtc_device, RTC_GEOMETRY_TYPE_INSTANCE);
401  rtcSetGeometryInstancedScene(geom_id, instance_bvh->scene);
402  rtcSetGeometryTimeStepCount(geom_id, num_motion_steps);
403 
404  if (ob->use_motion()) {
405  array<DecomposedTransform> decomp(ob->get_motion().size());
406  transform_motion_decompose(decomp.data(), ob->get_motion().data(), ob->get_motion().size());
407  for (size_t step = 0; step < num_motion_steps; ++step) {
408  RTCQuaternionDecomposition rtc_decomp;
409  rtcInitQuaternionDecomposition(&rtc_decomp);
410  rtcQuaternionDecompositionSetQuaternion(
411  &rtc_decomp, decomp[step].x.w, decomp[step].x.x, decomp[step].x.y, decomp[step].x.z);
412  rtcQuaternionDecompositionSetScale(
413  &rtc_decomp, decomp[step].y.w, decomp[step].z.w, decomp[step].w.w);
414  rtcQuaternionDecompositionSetTranslation(
415  &rtc_decomp, decomp[step].y.x, decomp[step].y.y, decomp[step].y.z);
416  rtcQuaternionDecompositionSetSkew(
417  &rtc_decomp, decomp[step].z.x, decomp[step].z.y, decomp[step].w.x);
418  rtcSetGeometryTransformQuaternion(geom_id, step, &rtc_decomp);
419  }
420  }
421  else {
422  rtcSetGeometryTransform(
423  geom_id, 0, RTC_FORMAT_FLOAT3X4_ROW_MAJOR, (const float *)&ob->get_tfm());
424  }
425 
426  rtcSetGeometryUserData(geom_id, (void *)instance_bvh->scene);
427  rtcSetGeometryMask(geom_id, ob->visibility_for_tracing());
428 
429  rtcCommitGeometry(geom_id);
430  rtcAttachGeometryByID(scene, geom_id, i * 2);
431  rtcReleaseGeometry(geom_id);
432 }
433 
434 void BVHEmbree::add_triangles(const Object *ob, const Mesh *mesh, int i)
435 {
436  size_t prim_offset = mesh->optix_prim_offset;
437 
438  const Attribute *attr_mP = NULL;
439  size_t num_motion_steps = 1;
440  if (mesh->has_motion_blur()) {
442  if (attr_mP) {
443  num_motion_steps = mesh->get_motion_steps();
444  }
445  }
446 
447  assert(num_motion_steps <= RTC_MAX_TIME_STEP_COUNT);
448  num_motion_steps = min(num_motion_steps, RTC_MAX_TIME_STEP_COUNT);
449 
450  const size_t num_triangles = mesh->num_triangles();
451 
452  RTCGeometry geom_id = rtcNewGeometry(rtc_device, RTC_GEOMETRY_TYPE_TRIANGLE);
453  rtcSetGeometryBuildQuality(geom_id, build_quality);
454  rtcSetGeometryTimeStepCount(geom_id, num_motion_steps);
455 
456  unsigned *rtc_indices = (unsigned *)rtcSetNewGeometryBuffer(
457  geom_id, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT3, sizeof(int) * 3, num_triangles);
458  assert(rtc_indices);
459  if (!rtc_indices) {
460  VLOG(1) << "Embree could not create new geometry buffer for mesh " << mesh->name.c_str()
461  << ".\n";
462  return;
463  }
464  for (size_t j = 0; j < num_triangles; ++j) {
466  rtc_indices[j * 3] = t.v[0];
467  rtc_indices[j * 3 + 1] = t.v[1];
468  rtc_indices[j * 3 + 2] = t.v[2];
469  }
470 
471  set_tri_vertex_buffer(geom_id, mesh, false);
472 
473  rtcSetGeometryUserData(geom_id, (void *)prim_offset);
474  rtcSetGeometryOccludedFilterFunction(geom_id, rtc_filter_occluded_func);
475  rtcSetGeometryMask(geom_id, ob->visibility_for_tracing());
476 
477  rtcCommitGeometry(geom_id);
478  rtcAttachGeometryByID(scene, geom_id, i * 2);
479  rtcReleaseGeometry(geom_id);
480 }
481 
482 void BVHEmbree::set_tri_vertex_buffer(RTCGeometry geom_id, const Mesh *mesh, const bool update)
483 {
484  const Attribute *attr_mP = NULL;
485  size_t num_motion_steps = 1;
486  int t_mid = 0;
487  if (mesh->has_motion_blur()) {
489  if (attr_mP) {
490  num_motion_steps = mesh->get_motion_steps();
491  t_mid = (num_motion_steps - 1) / 2;
492  if (num_motion_steps > RTC_MAX_TIME_STEP_COUNT) {
493  assert(0);
494  num_motion_steps = RTC_MAX_TIME_STEP_COUNT;
495  }
496  }
497  }
498  const size_t num_verts = mesh->get_verts().size();
499 
500  for (int t = 0; t < num_motion_steps; ++t) {
501  const float3 *verts;
502  if (t == t_mid) {
503  verts = mesh->get_verts().data();
504  }
505  else {
506  int t_ = (t > t_mid) ? (t - 1) : t;
507  verts = &attr_mP->data_float3()[t_ * num_verts];
508  }
509 
510  float *rtc_verts = (update) ?
511  (float *)rtcGetGeometryBufferData(geom_id, RTC_BUFFER_TYPE_VERTEX, t) :
512  (float *)rtcSetNewGeometryBuffer(geom_id,
513  RTC_BUFFER_TYPE_VERTEX,
514  t,
515  RTC_FORMAT_FLOAT3,
516  sizeof(float) * 3,
517  num_verts + 1);
518 
519  assert(rtc_verts);
520  if (rtc_verts) {
521  for (size_t j = 0; j < num_verts; ++j) {
522  rtc_verts[0] = verts[j].x;
523  rtc_verts[1] = verts[j].y;
524  rtc_verts[2] = verts[j].z;
525  rtc_verts += 3;
526  }
527  }
528 
529  if (update) {
530  rtcUpdateGeometryBuffer(geom_id, RTC_BUFFER_TYPE_VERTEX, t);
531  }
532  }
533 }
534 
535 void BVHEmbree::set_curve_vertex_buffer(RTCGeometry geom_id, const Hair *hair, const bool update)
536 {
537  const Attribute *attr_mP = NULL;
538  size_t num_motion_steps = 1;
539  if (hair->has_motion_blur()) {
541  if (attr_mP) {
542  num_motion_steps = hair->get_motion_steps();
543  }
544  }
545 
546  const size_t num_curves = hair->num_curves();
547  size_t num_keys = 0;
548  for (size_t j = 0; j < num_curves; ++j) {
549  const Hair::Curve c = hair->get_curve(j);
550  num_keys += c.num_keys;
551  }
552 
553  /* Catmull-Rom splines need extra CVs at the beginning and end of each curve. */
554  size_t num_keys_embree = num_keys;
555  num_keys_embree += num_curves * 2;
556 
557  /* Copy the CV data to Embree */
558  const int t_mid = (num_motion_steps - 1) / 2;
559  const float *curve_radius = &hair->get_curve_radius()[0];
560  for (int t = 0; t < num_motion_steps; ++t) {
561  const float3 *verts;
562  if (t == t_mid || attr_mP == NULL) {
563  verts = &hair->get_curve_keys()[0];
564  }
565  else {
566  int t_ = (t > t_mid) ? (t - 1) : t;
567  verts = &attr_mP->data_float3()[t_ * num_keys];
568  }
569 
570  float4 *rtc_verts = (update) ? (float4 *)rtcGetGeometryBufferData(
571  geom_id, RTC_BUFFER_TYPE_VERTEX, t) :
572  (float4 *)rtcSetNewGeometryBuffer(geom_id,
573  RTC_BUFFER_TYPE_VERTEX,
574  t,
575  RTC_FORMAT_FLOAT4,
576  sizeof(float) * 4,
577  num_keys_embree);
578 
579  assert(rtc_verts);
580  if (rtc_verts) {
581  const size_t num_curves = hair->num_curves();
582  for (size_t j = 0; j < num_curves; ++j) {
583  Hair::Curve c = hair->get_curve(j);
584  int fk = c.first_key;
585  int k = 1;
586  for (; k < c.num_keys + 1; ++k, ++fk) {
587  rtc_verts[k] = float3_to_float4(verts[fk]);
588  rtc_verts[k].w = curve_radius[fk];
589  }
590  /* Duplicate Embree's Catmull-Rom spline CVs at the start and end of each curve. */
591  rtc_verts[0] = rtc_verts[1];
592  rtc_verts[k] = rtc_verts[k - 1];
593  rtc_verts += c.num_keys + 2;
594  }
595  }
596 
597  if (update) {
598  rtcUpdateGeometryBuffer(geom_id, RTC_BUFFER_TYPE_VERTEX, t);
599  }
600  }
601 }
602 
603 void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i)
604 {
605  size_t prim_offset = hair->optix_prim_offset;
606 
607  const Attribute *attr_mP = NULL;
608  size_t num_motion_steps = 1;
609  if (hair->has_motion_blur()) {
611  if (attr_mP) {
612  num_motion_steps = hair->get_motion_steps();
613  }
614  }
615 
616  assert(num_motion_steps <= RTC_MAX_TIME_STEP_COUNT);
617  num_motion_steps = min(num_motion_steps, RTC_MAX_TIME_STEP_COUNT);
618 
619  const size_t num_curves = hair->num_curves();
620  size_t num_segments = 0;
621  for (size_t j = 0; j < num_curves; ++j) {
622  Hair::Curve c = hair->get_curve(j);
623  assert(c.num_segments() > 0);
624  num_segments += c.num_segments();
625  }
626 
627  enum RTCGeometryType type = (hair->curve_shape == CURVE_RIBBON ?
628  RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE :
629  RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE);
630 
631  RTCGeometry geom_id = rtcNewGeometry(rtc_device, type);
632  rtcSetGeometryTessellationRate(geom_id, params.curve_subdivisions + 1);
633  unsigned *rtc_indices = (unsigned *)rtcSetNewGeometryBuffer(
634  geom_id, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT, sizeof(int), num_segments);
635  size_t rtc_index = 0;
636  for (size_t j = 0; j < num_curves; ++j) {
637  Hair::Curve c = hair->get_curve(j);
638  for (size_t k = 0; k < c.num_segments(); ++k) {
639  rtc_indices[rtc_index] = c.first_key + k;
640  /* Room for extra CVs at Catmull-Rom splines. */
641  rtc_indices[rtc_index] += j * 2;
642 
643  ++rtc_index;
644  }
645  }
646 
647  rtcSetGeometryBuildQuality(geom_id, build_quality);
648  rtcSetGeometryTimeStepCount(geom_id, num_motion_steps);
649 
650  set_curve_vertex_buffer(geom_id, hair, false);
651 
652  rtcSetGeometryUserData(geom_id, (void *)prim_offset);
653  if (hair->curve_shape == CURVE_RIBBON) {
654  rtcSetGeometryOccludedFilterFunction(geom_id, rtc_filter_occluded_func);
655  }
656  else {
657  rtcSetGeometryIntersectFilterFunction(geom_id, rtc_filter_func_thick_curve);
658  rtcSetGeometryOccludedFilterFunction(geom_id, rtc_filter_occluded_func_thick_curve);
659  }
660  rtcSetGeometryMask(geom_id, ob->visibility_for_tracing());
661 
662  rtcCommitGeometry(geom_id);
663  rtcAttachGeometryByID(scene, geom_id, i * 2 + 1);
664  rtcReleaseGeometry(geom_id);
665 }
666 
667 void BVHEmbree::refit(Progress &progress)
668 {
669  progress.set_substatus("Refitting BVH nodes");
670 
671  /* Update all vertex buffers, then tell Embree to rebuild/-fit the BVHs. */
672  unsigned geom_id = 0;
673  foreach (Object *ob, objects) {
674  if (!params.top_level || (ob->is_traceable() && !ob->get_geometry()->is_instanced())) {
675  Geometry *geom = ob->get_geometry();
676 
677  if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) {
678  Mesh *mesh = static_cast<Mesh *>(geom);
679  if (mesh->num_triangles() > 0) {
680  RTCGeometry geom = rtcGetGeometry(scene, geom_id);
681  set_tri_vertex_buffer(geom, mesh, true);
682  rtcSetGeometryUserData(geom, (void *)mesh->optix_prim_offset);
683  rtcCommitGeometry(geom);
684  }
685  }
686  else if (geom->geometry_type == Geometry::HAIR) {
687  Hair *hair = static_cast<Hair *>(geom);
688  if (hair->num_curves() > 0) {
689  RTCGeometry geom = rtcGetGeometry(scene, geom_id + 1);
690  set_curve_vertex_buffer(geom, hair, true);
691  rtcSetGeometryUserData(geom, (void *)hair->optix_prim_offset);
692  rtcCommitGeometry(geom);
693  }
694  }
695  }
696  geom_id += 2;
697  }
698 
699  rtcCommitScene(scene);
700 }
701 
703 
704 #endif /* WITH_EMBREE */
typedef float(TangentPoint)[2]
unsigned int uint
Definition: BLI_sys_types.h:83
SSIZE_T ssize_t
Definition: BLI_winstuff.h:87
_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 z
_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 y
_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
ATOMIC_INLINE size_t atomic_add_and_fetch_z(size_t *p, size_t x)
ATOMIC_INLINE size_t atomic_sub_and_fetch_z(size_t *p, size_t x)
void refit(btStridingMeshInterface *triangles, const btVector3 &aabbMin, const btVector3 &aabbMax)
void build(btStridingMeshInterface *triangles, bool useQuantizedAabbCompression, const btVector3 &bvhAabbMin, const btVector3 &bvhAabbMax)
Attribute * find(ustring name) const
Definition: attribute.cpp:447
float3 * data_float3()
Definition: attribute.h:86
Definition: bvh/bvh.h:80
Type geometry_type
Definition: geometry.h:78
@ MESH
Definition: geometry.h:73
@ VOLUME
Definition: geometry.h:75
@ HAIR
Definition: geometry.h:74
static const uint MAX_MOTION_STEPS
Definition: geometry.h:97
size_t optix_prim_offset
Definition: geometry.h:103
bool has_motion_blur() const
Definition: geometry.cpp:255
AttributeSet attributes
Definition: geometry.h:81
bool get_cancel()
void set_substatus(const string &substatus_)
@ BVH_DYNAMIC
Definition: scene.h:154
void mem_free(size_t size)
Definition: util_stats.h:42
void mem_alloc(size_t size)
Definition: util_stats.h:36
Scene scene
#define str(s)
static float verts[][3]
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
ccl_device_inline void kernel_embree_convert_sss_hit(KernelGlobals *kg, const RTCRay *ray, const RTCHit *hit, Intersection *isect, int local_object_id)
ccl_device_inline void kernel_embree_convert_hit(KernelGlobals *kg, const RTCRay *ray, const RTCHit *hit, Intersection *isect)
#define kernel_tex_fetch(tex, index)
#define CCL_NAMESPACE_END
#define make_float3(x, y, z)
void KERNEL_FUNCTION_FULL_NAME() shader(KernelGlobals *kg, uint4 *input, float4 *output, int type, int filter, int i, int offset, int sample)
ccl_device uint lcg_step_uint(uint *rng)
@ SD_HAS_TRANSPARENT_SHADOW
Definition: kernel_types.h:871
@ PRIMITIVE_ALL_TRIANGLE
Definition: kernel_types.h:697
@ ATTR_STD_MOTION_VERTEX_POSITION
Definition: kernel_types.h:756
@ CURVE_RIBBON
Definition: kernel_types.h:714
#define OBJECT_NONE
Definition: kernel_types.h:59
@ SHADER_MASK
Definition: kernel_types.h:593
@ SD_OBJECT_HAS_VOLUME
Definition: kernel_types.h:912
static unsigned c
Definition: RandGen.cpp:97
static void update(bNodeTree *ntree)
#define min(a, b)
Definition: sort.c:51
LocalIntersection * local_isect
Curve get_curve(size_t i) const
Definition: hair.h:119
size_t num_curves() const
Definition: hair.h:133
CurveShapeType curve_shape
Definition: hair.h:99
struct Intersection hits[LOCAL_MAX_HITS]
float3 Ng[LOCAL_MAX_HITS]
float size[3]
Triangle get_triangle(size_t i) const
Definition: mesh.h:86
size_t num_triangles() const
Definition: mesh.h:92
ustring name
Definition: node.h:174
bool use_motion() const
Definition: object.cpp:238
static const uint MAX_MOTION_STEPS
Definition: object.h:91
bool is_traceable() const
Definition: object.cpp:261
uint visibility_for_tracing() const
Definition: object.cpp:271
void * data
#define VLOG(severity)
Definition: util_logging.h:50
ccl_device_inline int __float_as_int(float f)
Definition: util_math.h:202
ccl_device_inline float4 float3_to_float4(const float3 a)
Definition: util_math.h:420
ccl_device_inline float2 normalize(const float2 &a)
ccl_device_inline float dot(const float2 &a, const float2 &b)
#define SIMD_SET_FLUSH_TO_ZERO
Definition: util_simd.h:49
CCL_NAMESPACE_BEGIN string string_printf(const char *format,...)
Definition: util_string.cpp:32
CCL_NAMESPACE_BEGIN double time_dt()
Definition: util_time.cpp:48
void transform_motion_decompose(DecomposedTransform *decomp, const Transform *motion, size_t size)