1 | // Copyright 2009-2021 Intel Corporation |
2 | // SPDX-License-Identifier: Apache-2.0 |
3 | |
4 | #pragma once |
5 | |
6 | #include "trianglei.h" |
7 | #include "triangle_intersector_moeller.h" |
8 | #include "triangle_intersector_pluecker.h" |
9 | |
10 | namespace embree |
11 | { |
12 | namespace isa |
13 | { |
14 | /*! Intersects M triangles with 1 ray */ |
15 | template<int M, bool filter> |
16 | struct TriangleMiIntersector1Moeller |
17 | { |
18 | typedef TriangleMi<M> Primitive; |
19 | typedef MoellerTrumboreIntersector1<M> Precalculations; |
20 | |
21 | static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& tri) |
22 | { |
23 | STAT3(normal.trav_prims,1,1,1); |
24 | Vec3vf<M> v0, v1, v2; tri.gather(v0,v1,v2,context->scene); |
25 | pre.intersect(ray,v0,v1,v2,Intersect1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID())); |
26 | } |
27 | |
28 | static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& tri) |
29 | { |
30 | STAT3(shadow.trav_prims,1,1,1); |
31 | Vec3vf<M> v0, v1, v2; tri.gather(v0,v1,v2,context->scene); |
32 | return pre.intersect(ray,v0,v1,v2,Occluded1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID())); |
33 | } |
34 | |
35 | static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri) |
36 | { |
37 | return PrimitivePointQuery1<Primitive>::pointQuery(query, context, tri); |
38 | } |
39 | }; |
40 | |
41 | /*! Intersects M triangles with K rays */ |
42 | template<int M, int K, bool filter> |
43 | struct TriangleMiIntersectorKMoeller |
44 | { |
45 | typedef TriangleMi<M> Primitive; |
46 | typedef MoellerTrumboreIntersectorK<M,K> Precalculations; |
47 | |
48 | static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive& tri) |
49 | { |
50 | const Scene* scene = context->scene; |
51 | for (size_t i=0; i<Primitive::max_size(); i++) |
52 | { |
53 | if (!tri.valid(i)) break; |
54 | STAT3(normal.trav_prims,1,popcnt(valid_i),RayHitK<K>::size()); |
55 | const Vec3vf<K> v0 = tri.template getVertex<0>(i,scene); |
56 | const Vec3vf<K> v1 = tri.template getVertex<1>(i,scene); |
57 | const Vec3vf<K> v2 = tri.template getVertex<2>(i,scene); |
58 | pre.intersectK(valid_i,ray,v0,v1,v2,IntersectKEpilogM<M,K,filter>(ray,context,tri.geomID(),tri.primID(),i)); |
59 | } |
60 | } |
61 | |
62 | static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive& tri) |
63 | { |
64 | vbool<K> valid0 = valid_i; |
65 | const Scene* scene = context->scene; |
66 | |
67 | for (size_t i=0; i<Primitive::max_size(); i++) |
68 | { |
69 | if (!tri.valid(i)) break; |
70 | STAT3(shadow.trav_prims,1,popcnt(valid_i),RayHitK<K>::size()); |
71 | const Vec3vf<K> v0 = tri.template getVertex<0>(i,scene); |
72 | const Vec3vf<K> v1 = tri.template getVertex<1>(i,scene); |
73 | const Vec3vf<K> v2 = tri.template getVertex<2>(i,scene); |
74 | pre.intersectK(valid0,ray,v0,v1,v2,OccludedKEpilogM<M,K,filter>(valid0,ray,context,tri.geomID(),tri.primID(),i)); |
75 | if (none(valid0)) break; |
76 | } |
77 | return !valid0; |
78 | } |
79 | |
80 | static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& tri) |
81 | { |
82 | STAT3(normal.trav_prims,1,1,1); |
83 | Vec3vf<M> v0, v1, v2; tri.gather(v0,v1,v2,context->scene); |
84 | pre.intersect(ray,k,v0,v1,v2,Intersect1KEpilogM<M,K,filter>(ray,k,context,tri.geomID(),tri.primID())); |
85 | } |
86 | |
87 | static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& tri) |
88 | { |
89 | STAT3(shadow.trav_prims,1,1,1); |
90 | Vec3vf<M> v0, v1, v2; tri.gather(v0,v1,v2,context->scene); |
91 | return pre.intersect(ray,k,v0,v1,v2,Occluded1KEpilogM<M,K,filter>(ray,k,context,tri.geomID(),tri.primID())); |
92 | } |
93 | }; |
94 | |
95 | /*! Intersects M triangles with 1 ray */ |
96 | template<int M, bool filter> |
97 | struct TriangleMiIntersector1Pluecker |
98 | { |
99 | typedef TriangleMi<M> Primitive; |
100 | typedef PlueckerIntersector1<M> Precalculations; |
101 | |
102 | static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& tri) |
103 | { |
104 | STAT3(normal.trav_prims,1,1,1); |
105 | Vec3vf<M> v0, v1, v2; tri.gather(v0,v1,v2,context->scene); |
106 | pre.intersect(ray,v0,v1,v2,Intersect1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID())); |
107 | } |
108 | |
109 | static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& tri) |
110 | { |
111 | STAT3(shadow.trav_prims,1,1,1); |
112 | Vec3vf<M> v0, v1, v2; tri.gather(v0,v1,v2,context->scene); |
113 | return pre.intersect(ray,v0,v1,v2,Occluded1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID())); |
114 | } |
115 | |
116 | static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri) |
117 | { |
118 | return PrimitivePointQuery1<Primitive>::pointQuery(query, context, tri); |
119 | } |
120 | }; |
121 | |
122 | /*! Intersects M triangles with K rays */ |
123 | template<int M, int K, bool filter> |
124 | struct TriangleMiIntersectorKPluecker |
125 | { |
126 | typedef TriangleMi<M> Primitive; |
127 | typedef PlueckerIntersectorK<M,K> Precalculations; |
128 | |
129 | static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const Primitive& tri) |
130 | { |
131 | const Scene* scene = context->scene; |
132 | for (size_t i=0; i<Primitive::max_size(); i++) |
133 | { |
134 | if (!tri.valid(i)) break; |
135 | STAT3(normal.trav_prims,1,popcnt(valid_i),RayHitK<K>::size()); |
136 | const Vec3vf<K> v0 = tri.template getVertex<0>(i,scene); |
137 | const Vec3vf<K> v1 = tri.template getVertex<1>(i,scene); |
138 | const Vec3vf<K> v2 = tri.template getVertex<2>(i,scene); |
139 | pre.intersectK(valid_i,ray,v0,v1,v2,IntersectKEpilogM<M,K,filter>(ray,context,tri.geomID(),tri.primID(),i)); |
140 | } |
141 | } |
142 | |
143 | static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const Primitive& tri) |
144 | { |
145 | vbool<K> valid0 = valid_i; |
146 | const Scene* scene = context->scene; |
147 | |
148 | for (size_t i=0; i<Primitive::max_size(); i++) |
149 | { |
150 | if (!tri.valid(i)) break; |
151 | STAT3(shadow.trav_prims,1,popcnt(valid_i),RayHitK<K>::size()); |
152 | const Vec3vf<K> v0 = tri.template getVertex<0>(i,scene); |
153 | const Vec3vf<K> v1 = tri.template getVertex<1>(i,scene); |
154 | const Vec3vf<K> v2 = tri.template getVertex<2>(i,scene); |
155 | pre.intersectK(valid0,ray,v0,v1,v2,OccludedKEpilogM<M,K,filter>(valid0,ray,context,tri.geomID(),tri.primID(),i)); |
156 | if (none(valid0)) break; |
157 | } |
158 | return !valid0; |
159 | } |
160 | |
161 | static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const Primitive& tri) |
162 | { |
163 | STAT3(normal.trav_prims,1,1,1); |
164 | Vec3vf<M> v0, v1, v2; tri.gather(v0,v1,v2,context->scene); |
165 | pre.intersect(ray,k,v0,v1,v2,Intersect1KEpilogM<M,K,filter>(ray,k,context,tri.geomID(),tri.primID())); |
166 | } |
167 | |
168 | static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const Primitive& tri) |
169 | { |
170 | STAT3(shadow.trav_prims,1,1,1); |
171 | Vec3vf<M> v0, v1, v2; tri.gather(v0,v1,v2,context->scene); |
172 | return pre.intersect(ray,k,v0,v1,v2,Occluded1KEpilogM<M,K,filter>(ray,k,context,tri.geomID(),tri.primID())); |
173 | } |
174 | }; |
175 | |
176 | /*! Intersects M motion blur triangles with 1 ray */ |
177 | template<int M, bool filter> |
178 | struct TriangleMiMBIntersector1Moeller |
179 | { |
180 | typedef TriangleMi<M> Primitive; |
181 | typedef MoellerTrumboreIntersector1<M> Precalculations; |
182 | |
183 | /*! Intersect a ray with the M triangles and updates the hit. */ |
184 | static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& tri) |
185 | { |
186 | STAT3(normal.trav_prims,1,1,1); |
187 | Vec3vf<M> v0,v1,v2; tri.gather(v0,v1,v2,context->scene,ray.time()); |
188 | pre.intersect(ray,v0,v1,v2,Intersect1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID())); |
189 | } |
190 | |
191 | /*! Test if the ray is occluded by one of M triangles. */ |
192 | static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& tri) |
193 | { |
194 | STAT3(shadow.trav_prims,1,1,1); |
195 | Vec3vf<M> v0,v1,v2; tri.gather(v0,v1,v2,context->scene,ray.time()); |
196 | return pre.intersect(ray,v0,v1,v2,Occluded1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID())); |
197 | } |
198 | |
199 | static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri) |
200 | { |
201 | return PrimitivePointQuery1<Primitive>::pointQuery(query, context, tri); |
202 | } |
203 | }; |
204 | |
205 | /*! Intersects M motion blur triangles with K rays. */ |
206 | template<int M, int K, bool filter> |
207 | struct TriangleMiMBIntersectorKMoeller |
208 | { |
209 | typedef TriangleMi<M> Primitive; |
210 | typedef MoellerTrumboreIntersectorK<M,K> Precalculations; |
211 | |
212 | /*! Intersects K rays with M triangles. */ |
213 | static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const TriangleMi<M>& tri) |
214 | { |
215 | for (size_t i=0; i<TriangleMi<M>::max_size(); i++) |
216 | { |
217 | if (!tri.valid(i)) break; |
218 | STAT3(normal.trav_prims,1,popcnt(valid_i),K); |
219 | Vec3vf<K> v0,v1,v2; tri.template gather<K>(valid_i,v0,v1,v2,i,context->scene,ray.time()); |
220 | pre.intersectK(valid_i,ray,v0,v1,v2,IntersectKEpilogM<M,K,filter>(ray,context,tri.geomID(),tri.primID(),i)); |
221 | } |
222 | } |
223 | |
224 | /*! Test for K rays if they are occluded by any of the M triangles. */ |
225 | static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const TriangleMi<M>& tri) |
226 | { |
227 | vbool<K> valid0 = valid_i; |
228 | for (size_t i=0; i<TriangleMi<M>::max_size(); i++) |
229 | { |
230 | if (!tri.valid(i)) break; |
231 | STAT3(shadow.trav_prims,1,popcnt(valid0),K); |
232 | Vec3vf<K> v0,v1,v2; tri.template gather<K>(valid_i,v0,v1,v2,i,context->scene,ray.time()); |
233 | pre.intersectK(valid0,ray,v0,v1,v2,OccludedKEpilogM<M,K,filter>(valid0,ray,context,tri.geomID(),tri.primID(),i)); |
234 | if (none(valid0)) break; |
235 | } |
236 | return !valid0; |
237 | } |
238 | |
239 | /*! Intersect a ray with M triangles and updates the hit. */ |
240 | static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const TriangleMi<M>& tri) |
241 | { |
242 | STAT3(normal.trav_prims,1,1,1); |
243 | Vec3vf<M> v0,v1,v2; tri.gather(v0,v1,v2,context->scene,ray.time()[k]); |
244 | pre.intersect(ray,k,v0,v1,v2,Intersect1KEpilogM<M,K,filter>(ray,k,context,tri.geomID(),tri.primID())); |
245 | } |
246 | |
247 | /*! Test if the ray is occluded by one of the M triangles. */ |
248 | static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const TriangleMi<M>& tri) |
249 | { |
250 | STAT3(shadow.trav_prims,1,1,1); |
251 | Vec3vf<M> v0,v1,v2; tri.gather(v0,v1,v2,context->scene,ray.time()[k]); |
252 | return pre.intersect(ray,k,v0,v1,v2,Occluded1KEpilogM<M,K,filter>(ray,k,context,tri.geomID(),tri.primID())); |
253 | } |
254 | }; |
255 | |
256 | /*! Intersects M motion blur triangles with 1 ray */ |
257 | template<int M, bool filter> |
258 | struct TriangleMiMBIntersector1Pluecker |
259 | { |
260 | typedef TriangleMi<M> Primitive; |
261 | typedef PlueckerIntersector1<M> Precalculations; |
262 | |
263 | /*! Intersect a ray with the M triangles and updates the hit. */ |
264 | static __forceinline void intersect(const Precalculations& pre, RayHit& ray, IntersectContext* context, const Primitive& tri) |
265 | { |
266 | STAT3(normal.trav_prims,1,1,1); |
267 | Vec3vf<M> v0,v1,v2; tri.gather(v0,v1,v2,context->scene,ray.time()); |
268 | pre.intersect(ray,v0,v1,v2,Intersect1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID())); |
269 | } |
270 | |
271 | /*! Test if the ray is occluded by one of M triangles. */ |
272 | static __forceinline bool occluded(const Precalculations& pre, Ray& ray, IntersectContext* context, const Primitive& tri) |
273 | { |
274 | STAT3(shadow.trav_prims,1,1,1); |
275 | Vec3vf<M> v0,v1,v2; tri.gather(v0,v1,v2,context->scene,ray.time()); |
276 | return pre.intersect(ray,v0,v1,v2,Occluded1EpilogM<M,filter>(ray,context,tri.geomID(),tri.primID())); |
277 | } |
278 | |
279 | static __forceinline bool pointQuery(PointQuery* query, PointQueryContext* context, const Primitive& tri) |
280 | { |
281 | return PrimitivePointQuery1<Primitive>::pointQuery(query, context, tri); |
282 | } |
283 | }; |
284 | |
285 | /*! Intersects M motion blur triangles with K rays. */ |
286 | template<int M, int K, bool filter> |
287 | struct TriangleMiMBIntersectorKPluecker |
288 | { |
289 | typedef TriangleMi<M> Primitive; |
290 | typedef PlueckerIntersectorK<M,K> Precalculations; |
291 | |
292 | /*! Intersects K rays with M triangles. */ |
293 | static __forceinline void intersect(const vbool<K>& valid_i, Precalculations& pre, RayHitK<K>& ray, IntersectContext* context, const TriangleMi<M>& tri) |
294 | { |
295 | for (size_t i=0; i<TriangleMi<M>::max_size(); i++) |
296 | { |
297 | if (!tri.valid(i)) break; |
298 | STAT3(normal.trav_prims,1,popcnt(valid_i),K); |
299 | Vec3vf<K> v0,v1,v2; tri.template gather<K>(valid_i,v0,v1,v2,i,context->scene,ray.time()); |
300 | pre.intersectK(valid_i,ray,v0,v1,v2,IntersectKEpilogM<M,K,filter>(ray,context,tri.geomID(),tri.primID(),i)); |
301 | } |
302 | } |
303 | |
304 | /*! Test for K rays if they are occluded by any of the M triangles. */ |
305 | static __forceinline vbool<K> occluded(const vbool<K>& valid_i, Precalculations& pre, RayK<K>& ray, IntersectContext* context, const TriangleMi<M>& tri) |
306 | { |
307 | vbool<K> valid0 = valid_i; |
308 | for (size_t i=0; i<TriangleMi<M>::max_size(); i++) |
309 | { |
310 | if (!tri.valid(i)) break; |
311 | STAT3(shadow.trav_prims,1,popcnt(valid0),K); |
312 | Vec3vf<K> v0,v1,v2; tri.template gather<K>(valid_i,v0,v1,v2,i,context->scene,ray.time()); |
313 | pre.intersectK(valid0,ray,v0,v1,v2,OccludedKEpilogM<M,K,filter>(valid0,ray,context,tri.geomID(),tri.primID(),i)); |
314 | if (none(valid0)) break; |
315 | } |
316 | return !valid0; |
317 | } |
318 | |
319 | /*! Intersect a ray with M triangles and updates the hit. */ |
320 | static __forceinline void intersect(Precalculations& pre, RayHitK<K>& ray, size_t k, IntersectContext* context, const TriangleMi<M>& tri) |
321 | { |
322 | STAT3(normal.trav_prims,1,1,1); |
323 | Vec3vf<M> v0,v1,v2; tri.gather(v0,v1,v2,context->scene,ray.time()[k]); |
324 | pre.intersect(ray,k,v0,v1,v2,Intersect1KEpilogM<M,K,filter>(ray,k,context,tri.geomID(),tri.primID())); |
325 | } |
326 | |
327 | /*! Test if the ray is occluded by one of the M triangles. */ |
328 | static __forceinline bool occluded(Precalculations& pre, RayK<K>& ray, size_t k, IntersectContext* context, const TriangleMi<M>& tri) |
329 | { |
330 | STAT3(shadow.trav_prims,1,1,1); |
331 | Vec3vf<M> v0,v1,v2; tri.gather(v0,v1,v2,context->scene,ray.time()[k]); |
332 | return pre.intersect(ray,k,v0,v1,v2,Occluded1KEpilogM<M,K,filter>(ray,k,context,tri.geomID(),tri.primID())); |
333 | } |
334 | }; |
335 | } |
336 | } |
337 | |