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
10namespace 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