Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/embree/kernels/geometry/intersector_epilog.h
9905 views
1
// Copyright 2009-2021 Intel Corporation
2
// SPDX-License-Identifier: Apache-2.0
3
4
#pragma once
5
6
#include "../common/ray.h"
7
#include "../common/context.h"
8
#include "filter.h"
9
10
namespace embree
11
{
12
namespace isa
13
{
14
template<int M>
15
struct UVIdentity {
16
__forceinline void operator() (vfloat<M>& u, vfloat<M>& v, Vec3vf<M>& Ng) const {}
17
};
18
19
20
template<bool filter>
21
struct Intersect1Epilog1
22
{
23
RayHit& ray;
24
RayQueryContext* context;
25
const unsigned int geomID;
26
const unsigned int primID;
27
28
__forceinline Intersect1Epilog1(RayHit& ray,
29
RayQueryContext* context,
30
const unsigned int geomID,
31
const unsigned int primID)
32
: ray(ray), context(context), geomID(geomID), primID(primID) {}
33
34
template<typename Hit>
35
__forceinline bool operator() (Hit& hit) const
36
{
37
/* ray mask test */
38
Scene* scene MAYBE_UNUSED = context->scene;
39
Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
40
#if defined(EMBREE_RAY_MASK)
41
if ((geometry->mask & ray.mask) == 0) return false;
42
#endif
43
hit.finalize();
44
45
/* intersection filter test */
46
#if defined(EMBREE_FILTER_FUNCTION)
47
if (filter) {
48
if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {
49
HitK<1> h(context->user,geomID,primID,hit.u,hit.v,hit.Ng);
50
const float old_t = ray.tfar;
51
ray.tfar = hit.t;
52
bool found = runIntersectionFilter1(geometry,ray,context,h);
53
if (!found) ray.tfar = old_t;
54
return found;
55
}
56
}
57
#endif
58
59
/* update hit information */
60
ray.tfar = hit.t;
61
ray.Ng = hit.Ng;
62
ray.u = hit.u;
63
ray.v = hit.v;
64
ray.primID = primID;
65
ray.geomID = geomID;
66
instance_id_stack::copy_UU(context->user->instID, ray.instID);
67
#if defined(RTC_GEOMETRY_INSTANCE_ARRAY)
68
instance_id_stack::copy_UU(context->user->instPrimID, ray.instPrimID);
69
#endif
70
return true;
71
}
72
};
73
74
template<bool filter>
75
struct Occluded1Epilog1
76
{
77
Ray& ray;
78
RayQueryContext* context;
79
const unsigned int geomID;
80
const unsigned int primID;
81
82
__forceinline Occluded1Epilog1(Ray& ray,
83
RayQueryContext* context,
84
const unsigned int geomID,
85
const unsigned int primID)
86
: ray(ray), context(context), geomID(geomID), primID(primID) {}
87
88
template<typename Hit>
89
__forceinline bool operator() (Hit& hit) const
90
{
91
/* ray mask test */
92
Scene* scene MAYBE_UNUSED = context->scene;
93
Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
94
95
96
#if defined(EMBREE_RAY_MASK)
97
if ((geometry->mask & ray.mask) == 0) return false;
98
#endif
99
hit.finalize();
100
101
/* intersection filter test */
102
#if defined(EMBREE_FILTER_FUNCTION)
103
if (filter) {
104
if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter())) {
105
HitK<1> h(context->user,geomID,primID,hit.u,hit.v,hit.Ng);
106
const float old_t = ray.tfar;
107
ray.tfar = hit.t;
108
const bool found = runOcclusionFilter1(geometry,ray,context,h);
109
if (!found) ray.tfar = old_t;
110
return found;
111
}
112
}
113
#endif
114
return true;
115
}
116
};
117
118
template<int K, bool filter>
119
struct Intersect1KEpilog1
120
{
121
RayHitK<K>& ray;
122
size_t k;
123
RayQueryContext* context;
124
const unsigned int geomID;
125
const unsigned int primID;
126
127
__forceinline Intersect1KEpilog1(RayHitK<K>& ray, size_t k,
128
RayQueryContext* context,
129
const unsigned int geomID,
130
const unsigned int primID)
131
: ray(ray), k(k), context(context), geomID(geomID), primID(primID) {}
132
133
template<typename Hit>
134
__forceinline bool operator() (Hit& hit) const
135
{
136
/* ray mask test */
137
Scene* scene MAYBE_UNUSED = context->scene;
138
Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
139
#if defined(EMBREE_RAY_MASK)
140
if ((geometry->mask & ray.mask[k]) == 0)
141
return false;
142
#endif
143
hit.finalize();
144
145
/* intersection filter test */
146
#if defined(EMBREE_FILTER_FUNCTION)
147
if (filter) {
148
if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {
149
HitK<K> h(context->user,geomID,primID,hit.u,hit.v,hit.Ng);
150
const float old_t = ray.tfar[k];
151
ray.tfar[k] = hit.t;
152
const bool found = any(runIntersectionFilter(vbool<K>(1<<k),geometry,ray,context,h));
153
if (!found) ray.tfar[k] = old_t;
154
return found;
155
}
156
}
157
#endif
158
159
/* update hit information */
160
ray.tfar[k] = hit.t;
161
ray.Ng.x[k] = hit.Ng.x;
162
ray.Ng.y[k] = hit.Ng.y;
163
ray.Ng.z[k] = hit.Ng.z;
164
ray.u[k] = hit.u;
165
ray.v[k] = hit.v;
166
ray.primID[k] = primID;
167
ray.geomID[k] = geomID;
168
instance_id_stack::copy_UV<K>(context->user->instID, ray.instID, k);
169
#if defined(RTC_GEOMETRY_INSTANCE_ARRAY)
170
instance_id_stack::copy_UV<K>(context->user->instPrimID, ray.instPrimID, k);
171
#endif
172
return true;
173
}
174
};
175
176
template<int K, bool filter>
177
struct Occluded1KEpilog1
178
{
179
RayK<K>& ray;
180
size_t k;
181
RayQueryContext* context;
182
const unsigned int geomID;
183
const unsigned int primID;
184
185
__forceinline Occluded1KEpilog1(RayK<K>& ray, size_t k,
186
RayQueryContext* context,
187
const unsigned int geomID,
188
const unsigned int primID)
189
: ray(ray), k(k), context(context), geomID(geomID), primID(primID) {}
190
191
template<typename Hit>
192
__forceinline bool operator() (Hit& hit) const
193
{
194
/* ray mask test */
195
Scene* scene MAYBE_UNUSED = context->scene;
196
Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
197
#if defined(EMBREE_RAY_MASK)
198
if ((geometry->mask & ray.mask[k]) == 0)
199
return false;
200
#endif
201
202
/* intersection filter test */
203
#if defined(EMBREE_FILTER_FUNCTION)
204
if (filter) {
205
if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter())) {
206
hit.finalize();
207
HitK<K> h(context->user,geomID,primID,hit.u,hit.v,hit.Ng);
208
const float old_t = ray.tfar[k];
209
ray.tfar[k] = hit.t;
210
const bool found = any(runOcclusionFilter(vbool<K>(1<<k),geometry,ray,context,h));
211
if (!found) ray.tfar[k] = old_t;
212
return found;
213
}
214
}
215
#endif
216
return true;
217
}
218
};
219
220
template<int M, bool filter>
221
struct Intersect1EpilogM
222
{
223
RayHit& ray;
224
RayQueryContext* context;
225
const vuint<M>& geomIDs;
226
const vuint<M>& primIDs;
227
228
__forceinline Intersect1EpilogM(RayHit& ray,
229
RayQueryContext* context,
230
const vuint<M>& geomIDs,
231
const vuint<M>& primIDs)
232
: ray(ray), context(context), geomIDs(geomIDs), primIDs(primIDs) {}
233
234
template<typename Hit>
235
__forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const
236
{
237
Scene* scene MAYBE_UNUSED = context->scene;
238
vbool<M> valid = valid_i;
239
hit.finalize();
240
size_t i = select_min(valid,hit.vt);
241
unsigned int geomID = geomIDs[i];
242
243
/* intersection filter test */
244
#if defined(EMBREE_FILTER_FUNCTION) || defined(EMBREE_RAY_MASK)
245
bool foundhit = false;
246
goto entry;
247
while (true)
248
{
249
if (unlikely(none(valid))) return foundhit;
250
i = select_min(valid,hit.vt);
251
252
geomID = geomIDs[i];
253
entry:
254
Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
255
256
#if defined(EMBREE_RAY_MASK)
257
/* goto next hit if mask test fails */
258
if ((geometry->mask & ray.mask) == 0) {
259
clear(valid,i);
260
continue;
261
}
262
#endif
263
264
#if defined(EMBREE_FILTER_FUNCTION)
265
/* call intersection filter function */
266
if (filter) {
267
if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {
268
const Vec2f uv = hit.uv(i);
269
HitK<1> h(context->user,geomID,primIDs[i],uv.x,uv.y,hit.Ng(i));
270
const float old_t = ray.tfar;
271
ray.tfar = hit.t(i);
272
const bool found = runIntersectionFilter1(geometry,ray,context,h);
273
if (!found) ray.tfar = old_t;
274
foundhit |= found;
275
clear(valid,i);
276
valid &= hit.vt <= ray.tfar; // intersection filters may modify tfar value
277
continue;
278
}
279
}
280
#endif
281
break;
282
}
283
#endif
284
285
/* update hit information */
286
const Vec2f uv = hit.uv(i);
287
ray.tfar = hit.vt[i];
288
ray.Ng.x = hit.vNg.x[i];
289
ray.Ng.y = hit.vNg.y[i];
290
ray.Ng.z = hit.vNg.z[i];
291
ray.u = uv.x;
292
ray.v = uv.y;
293
ray.primID = primIDs[i];
294
ray.geomID = geomID;
295
instance_id_stack::copy_UU(context->user->instID, ray.instID);
296
#if defined(RTC_GEOMETRY_INSTANCE_ARRAY)
297
instance_id_stack::copy_UU(context->user->instPrimID, ray.instPrimID);
298
#endif
299
return true;
300
301
}
302
};
303
304
template<int M, bool filter>
305
struct Occluded1EpilogM
306
{
307
Ray& ray;
308
RayQueryContext* context;
309
const vuint<M>& geomIDs;
310
const vuint<M>& primIDs;
311
312
__forceinline Occluded1EpilogM(Ray& ray,
313
RayQueryContext* context,
314
const vuint<M>& geomIDs,
315
const vuint<M>& primIDs)
316
: ray(ray), context(context), geomIDs(geomIDs), primIDs(primIDs) {}
317
318
template<typename Hit>
319
__forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const
320
{
321
Scene* scene MAYBE_UNUSED = context->scene;
322
/* intersection filter test */
323
#if defined(EMBREE_FILTER_FUNCTION) || defined(EMBREE_RAY_MASK)
324
if (unlikely(filter))
325
hit.finalize(); /* called only once */
326
327
vbool<M> valid = valid_i;
328
size_t m=movemask(valid);
329
goto entry;
330
while (true)
331
{
332
if (unlikely(m == 0)) return false;
333
entry:
334
size_t i=bsf(m);
335
336
const unsigned int geomID = geomIDs[i];
337
Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
338
339
#if defined(EMBREE_RAY_MASK)
340
/* goto next hit if mask test fails */
341
if ((geometry->mask & ray.mask) == 0) {
342
m=btc(m,i);
343
continue;
344
}
345
#endif
346
347
#if defined(EMBREE_FILTER_FUNCTION)
348
/* if we have no filter then the test passed */
349
if (filter) {
350
if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter()))
351
{
352
const Vec2f uv = hit.uv(i);
353
HitK<1> h(context->user,geomID,primIDs[i],uv.x,uv.y,hit.Ng(i));
354
const float old_t = ray.tfar;
355
ray.tfar = hit.t(i);
356
if (runOcclusionFilter1(geometry,ray,context,h)) return true;
357
ray.tfar = old_t;
358
m=btc(m,i);
359
continue;
360
}
361
}
362
#endif
363
break;
364
}
365
#endif
366
367
return true;
368
}
369
};
370
371
template<int M, bool filter>
372
struct Intersect1EpilogMU
373
{
374
RayHit& ray;
375
RayQueryContext* context;
376
const unsigned int geomID;
377
const unsigned int primID;
378
379
__forceinline Intersect1EpilogMU(RayHit& ray,
380
RayQueryContext* context,
381
const unsigned int geomID,
382
const unsigned int primID)
383
: ray(ray), context(context), geomID(geomID), primID(primID) {}
384
385
template<typename Hit>
386
__forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const
387
{
388
/* ray mask test */
389
Scene* scene MAYBE_UNUSED = context->scene;
390
Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
391
#if defined(EMBREE_RAY_MASK)
392
if ((geometry->mask & ray.mask) == 0) return false;
393
#endif
394
395
vbool<M> valid = valid_i;
396
hit.finalize();
397
398
size_t i = select_min(valid,hit.vt);
399
400
/* intersection filter test */
401
#if defined(EMBREE_FILTER_FUNCTION)
402
if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter()))
403
{
404
bool foundhit = false;
405
while (true)
406
{
407
/* call intersection filter function */
408
Vec2f uv = hit.uv(i);
409
const float old_t = ray.tfar;
410
ray.tfar = hit.t(i);
411
HitK<1> h(context->user,geomID,primID,uv.x,uv.y,hit.Ng(i));
412
const bool found = runIntersectionFilter1(geometry,ray,context,h);
413
if (!found) ray.tfar = old_t;
414
foundhit |= found;
415
clear(valid,i);
416
valid &= hit.vt <= ray.tfar; // intersection filters may modify tfar value
417
if (unlikely(none(valid))) break;
418
i = select_min(valid,hit.vt);
419
}
420
return foundhit;
421
}
422
#endif
423
424
/* update hit information */
425
const Vec2f uv = hit.uv(i);
426
const Vec3fa Ng = hit.Ng(i);
427
ray.tfar = hit.t(i);
428
ray.Ng.x = Ng.x;
429
ray.Ng.y = Ng.y;
430
ray.Ng.z = Ng.z;
431
ray.u = uv.x;
432
ray.v = uv.y;
433
ray.primID = primID;
434
ray.geomID = geomID;
435
instance_id_stack::copy_UU(context->user->instID, ray.instID);
436
#if defined(RTC_GEOMETRY_INSTANCE_ARRAY)
437
instance_id_stack::copy_UU(context->user->instPrimID, ray.instPrimID);
438
#endif
439
return true;
440
}
441
};
442
443
template<int M, bool filter>
444
struct Occluded1EpilogMU
445
{
446
Ray& ray;
447
RayQueryContext* context;
448
const unsigned int geomID;
449
const unsigned int primID;
450
451
__forceinline Occluded1EpilogMU(Ray& ray,
452
RayQueryContext* context,
453
const unsigned int geomID,
454
const unsigned int primID)
455
: ray(ray), context(context), geomID(geomID), primID(primID) {}
456
457
template<typename Hit>
458
__forceinline bool operator() (const vbool<M>& valid, Hit& hit) const
459
{
460
/* ray mask test */
461
Scene* scene MAYBE_UNUSED = context->scene;
462
Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
463
#if defined(EMBREE_RAY_MASK)
464
if ((geometry->mask & ray.mask) == 0) return false;
465
#endif
466
467
/* intersection filter test */
468
#if defined(EMBREE_FILTER_FUNCTION)
469
if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter()))
470
{
471
hit.finalize();
472
for (size_t m=movemask(valid), i=bsf(m); m!=0; m=btc(m,i), i=bsf(m))
473
{
474
const Vec2f uv = hit.uv(i);
475
const float old_t = ray.tfar;
476
ray.tfar = hit.t(i);
477
HitK<1> h(context->user,geomID,primID,uv.x,uv.y,hit.Ng(i));
478
if (runOcclusionFilter1(geometry,ray,context,h)) return true;
479
ray.tfar = old_t;
480
}
481
return false;
482
}
483
#endif
484
return true;
485
}
486
};
487
488
template<int M, int K, bool filter>
489
struct IntersectKEpilogM
490
{
491
RayHitK<K>& ray;
492
RayQueryContext* context;
493
const vuint<M>& geomIDs;
494
const vuint<M>& primIDs;
495
const size_t i;
496
497
__forceinline IntersectKEpilogM(RayHitK<K>& ray,
498
RayQueryContext* context,
499
const vuint<M>& geomIDs,
500
const vuint<M>& primIDs,
501
size_t i)
502
: ray(ray), context(context), geomIDs(geomIDs), primIDs(primIDs), i(i) {}
503
504
template<typename Hit>
505
__forceinline vbool<K> operator() (const vbool<K>& valid_i, const Hit& hit) const
506
{
507
Scene* scene MAYBE_UNUSED = context->scene;
508
509
vfloat<K> u, v, t;
510
Vec3vf<K> Ng;
511
vbool<K> valid = valid_i;
512
513
std::tie(u,v,t,Ng) = hit();
514
515
const unsigned int geomID = geomIDs[i];
516
const unsigned int primID = primIDs[i];
517
Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
518
519
/* ray masking test */
520
#if defined(EMBREE_RAY_MASK)
521
valid &= (geometry->mask & ray.mask) != 0;
522
if (unlikely(none(valid))) return false;
523
#endif
524
525
/* occlusion filter test */
526
#if defined(EMBREE_FILTER_FUNCTION)
527
if (filter) {
528
if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {
529
HitK<K> h(context->user,geomID,primID,u,v,Ng);
530
const vfloat<K> old_t = ray.tfar;
531
ray.tfar = select(valid,t,ray.tfar);
532
const vbool<K> m_accept = runIntersectionFilter(valid,geometry,ray,context,h);
533
ray.tfar = select(m_accept,ray.tfar,old_t);
534
return m_accept;
535
}
536
}
537
#endif
538
539
/* update hit information */
540
vfloat<K>::store(valid,&ray.tfar,t);
541
vfloat<K>::store(valid,&ray.Ng.x,Ng.x);
542
vfloat<K>::store(valid,&ray.Ng.y,Ng.y);
543
vfloat<K>::store(valid,&ray.Ng.z,Ng.z);
544
vfloat<K>::store(valid,&ray.u,u);
545
vfloat<K>::store(valid,&ray.v,v);
546
vuint<K>::store(valid,&ray.primID,primID);
547
vuint<K>::store(valid,&ray.geomID,geomID);
548
instance_id_stack::copy_UV<K>(context->user->instID, ray.instID, valid);
549
#if defined(RTC_GEOMETRY_INSTANCE_ARRAY)
550
instance_id_stack::copy_UV<K>(context->user->instPrimID, ray.instPrimID, valid);
551
#endif
552
return valid;
553
}
554
};
555
556
template<int M, int K, bool filter>
557
struct OccludedKEpilogM
558
{
559
vbool<K>& valid0;
560
RayK<K>& ray;
561
RayQueryContext* context;
562
const vuint<M>& geomIDs;
563
const vuint<M>& primIDs;
564
const size_t i;
565
566
__forceinline OccludedKEpilogM(vbool<K>& valid0,
567
RayK<K>& ray,
568
RayQueryContext* context,
569
const vuint<M>& geomIDs,
570
const vuint<M>& primIDs,
571
size_t i)
572
: valid0(valid0), ray(ray), context(context), geomIDs(geomIDs), primIDs(primIDs), i(i) {}
573
574
template<typename Hit>
575
__forceinline vbool<K> operator() (const vbool<K>& valid_i, const Hit& hit) const
576
{
577
vbool<K> valid = valid_i;
578
579
/* ray masking test */
580
Scene* scene MAYBE_UNUSED = context->scene;
581
const unsigned int geomID MAYBE_UNUSED = geomIDs[i];
582
const unsigned int primID MAYBE_UNUSED = primIDs[i];
583
Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
584
#if defined(EMBREE_RAY_MASK)
585
valid &= (geometry->mask & ray.mask) != 0;
586
if (unlikely(none(valid))) return valid;
587
#endif
588
589
/* intersection filter test */
590
#if defined(EMBREE_FILTER_FUNCTION)
591
if (filter) {
592
if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter()))
593
{
594
vfloat<K> u, v, t;
595
Vec3vf<K> Ng;
596
std::tie(u,v,t,Ng) = hit();
597
HitK<K> h(context->user,geomID,primID,u,v,Ng);
598
const vfloat<K> old_t = ray.tfar;
599
ray.tfar = select(valid,t,ray.tfar);
600
valid = runOcclusionFilter(valid,geometry,ray,context,h);
601
ray.tfar = select(valid,ray.tfar,old_t);
602
}
603
}
604
#endif
605
606
/* update occlusion */
607
valid0 = valid0 & !valid;
608
return valid;
609
}
610
};
611
612
template<int M, int K, bool filter>
613
struct IntersectKEpilogMU
614
{
615
RayHitK<K>& ray;
616
RayQueryContext* context;
617
const unsigned int geomID;
618
const unsigned int primID;
619
620
__forceinline IntersectKEpilogMU(RayHitK<K>& ray,
621
RayQueryContext* context,
622
const unsigned int geomID,
623
const unsigned int primID)
624
: ray(ray), context(context), geomID(geomID), primID(primID) {}
625
626
template<typename Hit>
627
__forceinline vbool<K> operator() (const vbool<K>& valid_org, const Hit& hit) const
628
{
629
vbool<K> valid = valid_org;
630
vfloat<K> u, v, t;
631
Vec3vf<K> Ng;
632
std::tie(u,v,t,Ng) = hit();
633
634
Scene* scene MAYBE_UNUSED = context->scene;
635
Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
636
637
/* ray masking test */
638
#if defined(EMBREE_RAY_MASK)
639
valid &= (geometry->mask & ray.mask) != 0;
640
if (unlikely(none(valid))) return false;
641
#endif
642
643
/* intersection filter test */
644
#if defined(EMBREE_FILTER_FUNCTION)
645
if (filter) {
646
if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {
647
HitK<K> h(context->user,geomID,primID,u,v,Ng);
648
const vfloat<K> old_t = ray.tfar;
649
ray.tfar = select(valid,t,ray.tfar);
650
const vbool<K> m_accept = runIntersectionFilter(valid,geometry,ray,context,h);
651
ray.tfar = select(m_accept,ray.tfar,old_t);
652
return m_accept;
653
}
654
}
655
#endif
656
657
/* update hit information */
658
vfloat<K>::store(valid,&ray.tfar,t);
659
vfloat<K>::store(valid,&ray.Ng.x,Ng.x);
660
vfloat<K>::store(valid,&ray.Ng.y,Ng.y);
661
vfloat<K>::store(valid,&ray.Ng.z,Ng.z);
662
vfloat<K>::store(valid,&ray.u,u);
663
vfloat<K>::store(valid,&ray.v,v);
664
vuint<K>::store(valid,&ray.primID,primID);
665
vuint<K>::store(valid,&ray.geomID,geomID);
666
instance_id_stack::copy_UV<K>(context->user->instID, ray.instID, valid);
667
#if defined(RTC_GEOMETRY_INSTANCE_ARRAY)
668
instance_id_stack::copy_UV<K>(context->user->instPrimID, ray.instPrimID, valid);
669
#endif
670
return valid;
671
}
672
};
673
674
template<int M, int K, bool filter>
675
struct OccludedKEpilogMU
676
{
677
vbool<K>& valid0;
678
RayK<K>& ray;
679
RayQueryContext* context;
680
const unsigned int geomID;
681
const unsigned int primID;
682
683
__forceinline OccludedKEpilogMU(vbool<K>& valid0,
684
RayK<K>& ray,
685
RayQueryContext* context,
686
const unsigned int geomID,
687
const unsigned int primID)
688
: valid0(valid0), ray(ray), context(context), geomID(geomID), primID(primID) {}
689
690
template<typename Hit>
691
__forceinline vbool<K> operator() (const vbool<K>& valid_i, const Hit& hit) const
692
{
693
vbool<K> valid = valid_i;
694
Scene* scene MAYBE_UNUSED = context->scene;
695
Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
696
697
#if defined(EMBREE_RAY_MASK)
698
valid &= (geometry->mask & ray.mask) != 0;
699
if (unlikely(none(valid))) return false;
700
#endif
701
702
/* occlusion filter test */
703
#if defined(EMBREE_FILTER_FUNCTION)
704
if (filter) {
705
if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter()))
706
{
707
vfloat<K> u, v, t;
708
Vec3vf<K> Ng;
709
std::tie(u,v,t,Ng) = hit();
710
HitK<K> h(context->user,geomID,primID,u,v,Ng);
711
const vfloat<K> old_t = ray.tfar;
712
ray.tfar = select(valid,t,ray.tfar);
713
valid = runOcclusionFilter(valid,geometry,ray,context,h);
714
ray.tfar = select(valid,ray.tfar,old_t);
715
}
716
}
717
#endif
718
719
/* update occlusion */
720
valid0 = valid0 & !valid;
721
return valid;
722
}
723
};
724
725
template<int M, int K, bool filter>
726
struct Intersect1KEpilogM
727
{
728
RayHitK<K>& ray;
729
size_t k;
730
RayQueryContext* context;
731
const vuint<M>& geomIDs;
732
const vuint<M>& primIDs;
733
734
__forceinline Intersect1KEpilogM(RayHitK<K>& ray, size_t k,
735
RayQueryContext* context,
736
const vuint<M>& geomIDs,
737
const vuint<M>& primIDs)
738
: ray(ray), k(k), context(context), geomIDs(geomIDs), primIDs(primIDs) {}
739
740
template<typename Hit>
741
__forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const
742
{
743
Scene* scene MAYBE_UNUSED = context->scene;
744
vbool<M> valid = valid_i;
745
hit.finalize();
746
size_t i = select_min(valid,hit.vt);
747
assert(i<M);
748
unsigned int geomID = geomIDs[i];
749
750
/* intersection filter test */
751
#if defined(EMBREE_FILTER_FUNCTION) || defined(EMBREE_RAY_MASK)
752
bool foundhit = false;
753
goto entry;
754
while (true)
755
{
756
if (unlikely(none(valid))) return foundhit;
757
i = select_min(valid,hit.vt);
758
assert(i<M);
759
geomID = geomIDs[i];
760
entry:
761
Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
762
763
#if defined(EMBREE_RAY_MASK)
764
/* goto next hit if mask test fails */
765
if ((geometry->mask & ray.mask[k]) == 0) {
766
clear(valid,i);
767
continue;
768
}
769
#endif
770
771
#if defined(EMBREE_FILTER_FUNCTION)
772
/* call intersection filter function */
773
if (filter) {
774
if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter())) {
775
assert(i<M);
776
const Vec2f uv = hit.uv(i);
777
HitK<K> h(context->user,geomID,primIDs[i],uv.x,uv.y,hit.Ng(i));
778
const float old_t = ray.tfar[k];
779
ray.tfar[k] = hit.t(i);
780
const bool found = any(runIntersectionFilter(vbool<K>(1<<k),geometry,ray,context,h));
781
if (!found) ray.tfar[k] = old_t;
782
foundhit = foundhit | found;
783
clear(valid,i);
784
valid &= hit.vt <= ray.tfar[k]; // intersection filters may modify tfar value
785
continue;
786
}
787
}
788
#endif
789
break;
790
}
791
#endif
792
assert(i<M);
793
/* update hit information */
794
const Vec2f uv = hit.uv(i);
795
ray.tfar[k] = hit.t(i);
796
ray.Ng.x[k] = hit.vNg.x[i];
797
ray.Ng.y[k] = hit.vNg.y[i];
798
ray.Ng.z[k] = hit.vNg.z[i];
799
ray.u[k] = uv.x;
800
ray.v[k] = uv.y;
801
ray.primID[k] = primIDs[i];
802
ray.geomID[k] = geomID;
803
instance_id_stack::copy_UV<K>(context->user->instID, ray.instID, k);
804
#if defined(RTC_GEOMETRY_INSTANCE_ARRAY)
805
instance_id_stack::copy_UV<K>(context->user->instPrimID, ray.instPrimID, k);
806
#endif
807
return true;
808
}
809
};
810
811
template<int M, int K, bool filter>
812
struct Occluded1KEpilogM
813
{
814
RayK<K>& ray;
815
size_t k;
816
RayQueryContext* context;
817
const vuint<M>& geomIDs;
818
const vuint<M>& primIDs;
819
820
__forceinline Occluded1KEpilogM(RayK<K>& ray, size_t k,
821
RayQueryContext* context,
822
const vuint<M>& geomIDs,
823
const vuint<M>& primIDs)
824
: ray(ray), k(k), context(context), geomIDs(geomIDs), primIDs(primIDs) {}
825
826
template<typename Hit>
827
__forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const
828
{
829
Scene* scene MAYBE_UNUSED = context->scene;
830
831
/* intersection filter test */
832
#if defined(EMBREE_FILTER_FUNCTION) || defined(EMBREE_RAY_MASK)
833
if (unlikely(filter))
834
hit.finalize(); /* called only once */
835
836
vbool<M> valid = valid_i;
837
size_t m=movemask(valid);
838
goto entry;
839
while (true)
840
{
841
if (unlikely(m == 0)) return false;
842
entry:
843
size_t i=bsf(m);
844
845
const unsigned int geomID = geomIDs[i];
846
Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
847
848
#if defined(EMBREE_RAY_MASK)
849
/* goto next hit if mask test fails */
850
if ((geometry->mask & ray.mask[k]) == 0) {
851
m=btc(m,i);
852
continue;
853
}
854
#endif
855
856
#if defined(EMBREE_FILTER_FUNCTION)
857
/* execute occlusion filer */
858
if (filter) {
859
if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter()))
860
{
861
const Vec2f uv = hit.uv(i);
862
const float old_t = ray.tfar[k];
863
ray.tfar[k] = hit.t(i);
864
HitK<K> h(context->user,geomID,primIDs[i],uv.x,uv.y,hit.Ng(i));
865
if (any(runOcclusionFilter(vbool<K>(1<<k),geometry,ray,context,h))) return true;
866
ray.tfar[k] = old_t;
867
m=btc(m,i);
868
continue;
869
}
870
}
871
#endif
872
break;
873
}
874
#endif
875
return true;
876
}
877
};
878
879
template<int M, int K, bool filter>
880
struct Intersect1KEpilogMU
881
{
882
RayHitK<K>& ray;
883
size_t k;
884
RayQueryContext* context;
885
const unsigned int geomID;
886
const unsigned int primID;
887
888
__forceinline Intersect1KEpilogMU(RayHitK<K>& ray, size_t k,
889
RayQueryContext* context,
890
const unsigned int geomID,
891
const unsigned int primID)
892
: ray(ray), k(k), context(context), geomID(geomID), primID(primID) {}
893
894
template<typename Hit>
895
__forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const
896
{
897
Scene* scene MAYBE_UNUSED = context->scene;
898
Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
899
#if defined(EMBREE_RAY_MASK)
900
/* ray mask test */
901
if ((geometry->mask & ray.mask[k]) == 0)
902
return false;
903
#endif
904
905
/* finalize hit calculation */
906
vbool<M> valid = valid_i;
907
hit.finalize();
908
size_t i = select_min(valid,hit.vt);
909
910
/* intersection filter test */
911
#if defined(EMBREE_FILTER_FUNCTION)
912
if (filter) {
913
if (unlikely(context->hasContextFilter() || geometry->hasIntersectionFilter()))
914
{
915
bool foundhit = false;
916
while (true)
917
{
918
const Vec2f uv = hit.uv(i);
919
const float old_t = ray.tfar[k];
920
ray.tfar[k] = hit.t(i);
921
HitK<K> h(context->user,geomID,primID,uv.x,uv.y,hit.Ng(i));
922
const bool found = any(runIntersectionFilter(vbool<K>(1<<k),geometry,ray,context,h));
923
if (!found) ray.tfar[k] = old_t;
924
foundhit = foundhit | found;
925
clear(valid,i);
926
valid &= hit.vt <= ray.tfar[k]; // intersection filters may modify tfar value
927
if (unlikely(none(valid))) break;
928
i = select_min(valid,hit.vt);
929
}
930
return foundhit;
931
}
932
}
933
#endif
934
935
/* update hit information */
936
const Vec2f uv = hit.uv(i);
937
const Vec3fa Ng = hit.Ng(i);
938
ray.tfar[k] = hit.t(i);
939
ray.Ng.x[k] = Ng.x;
940
ray.Ng.y[k] = Ng.y;
941
ray.Ng.z[k] = Ng.z;
942
ray.u[k] = uv.x;
943
ray.v[k] = uv.y;
944
ray.primID[k] = primID;
945
ray.geomID[k] = geomID;
946
instance_id_stack::copy_UV<K>(context->user->instID, ray.instID, k);
947
#if defined(RTC_GEOMETRY_INSTANCE_ARRAY)
948
instance_id_stack::copy_UV<K>(context->user->instPrimID, ray.instPrimID, k);
949
#endif
950
return true;
951
}
952
};
953
954
template<int M, int K, bool filter>
955
struct Occluded1KEpilogMU
956
{
957
RayK<K>& ray;
958
size_t k;
959
RayQueryContext* context;
960
const unsigned int geomID;
961
const unsigned int primID;
962
963
__forceinline Occluded1KEpilogMU(RayK<K>& ray, size_t k,
964
RayQueryContext* context,
965
const unsigned int geomID,
966
const unsigned int primID)
967
: ray(ray), k(k), context(context), geomID(geomID), primID(primID) {}
968
969
template<typename Hit>
970
__forceinline bool operator() (const vbool<M>& valid_i, Hit& hit) const
971
{
972
Scene* scene MAYBE_UNUSED = context->scene;
973
Geometry* geometry MAYBE_UNUSED = scene->get(geomID);
974
#if defined(EMBREE_RAY_MASK)
975
/* ray mask test */
976
if ((geometry->mask & ray.mask[k]) == 0)
977
return false;
978
#endif
979
980
/* intersection filter test */
981
#if defined(EMBREE_FILTER_FUNCTION)
982
if (filter) {
983
if (unlikely(context->hasContextFilter() || geometry->hasOcclusionFilter()))
984
{
985
hit.finalize();
986
for (size_t m=movemask(valid_i), i=bsf(m); m!=0; m=btc(m,i), i=bsf(m))
987
{
988
const Vec2f uv = hit.uv(i);
989
const float old_t = ray.tfar[k];
990
ray.tfar[k] = hit.t(i);
991
HitK<K> h(context->user,geomID,primID,uv.x,uv.y,hit.Ng(i));
992
if (any(runOcclusionFilter(vbool<K>(1<<k),geometry,ray,context,h))) return true;
993
ray.tfar[k] = old_t;
994
}
995
return false;
996
}
997
}
998
#endif
999
return true;
1000
}
1001
};
1002
}
1003
}
1004
1005