1 | // Copyright 2009-2021 Intel Corporation |
2 | // SPDX-License-Identifier: Apache-2.0 |
3 | |
4 | #pragma once |
5 | |
6 | #include "triangle.h" |
7 | #include "intersector_epilog.h" |
8 | |
9 | /*! This intersector implements a modified version of the Moeller |
10 | * Trumbore intersector from the paper "Fast, Minimum Storage |
11 | * Ray-Triangle Intersection". In contrast to the paper we |
12 | * precalculate some factors and factor the calculations differently |
13 | * to allow precalculating the cross product e1 x e2. The resulting |
14 | * algorithm is similar to the fastest one of the paper "Optimizing |
15 | * Ray-Triangle Intersection via Automated Search". */ |
16 | |
17 | namespace embree |
18 | { |
19 | namespace isa |
20 | { |
21 | template<int M, typename UVMapper> |
22 | struct MoellerTrumboreHitM |
23 | { |
24 | __forceinline MoellerTrumboreHitM(const UVMapper& mapUV) : mapUV(mapUV) {} |
25 | |
26 | __forceinline MoellerTrumboreHitM(const vbool<M>& valid, const vfloat<M>& U, const vfloat<M>& V, const vfloat<M>& T, const vfloat<M>& absDen, const Vec3vf<M>& Ng, const UVMapper& mapUV) |
27 | : U(U), V(V), T(T), absDen(absDen), mapUV(mapUV), valid(valid), vNg(Ng) {} |
28 | |
29 | __forceinline void finalize() |
30 | { |
31 | const vfloat<M> rcpAbsDen = rcp(absDen); |
32 | vt = T * rcpAbsDen; |
33 | vu = U * rcpAbsDen; |
34 | vv = V * rcpAbsDen; |
35 | mapUV(vu,vv,vNg); |
36 | } |
37 | |
38 | __forceinline Vec2vf<M> uv() const { return Vec2vf<M>(vu,vv); } |
39 | __forceinline vfloat<M> t () const { return vt; } |
40 | __forceinline Vec3vf<M> Ng() const { return vNg; } |
41 | |
42 | __forceinline Vec2f uv (const size_t i) const { return Vec2f(vu[i],vv[i]); } |
43 | __forceinline float t (const size_t i) const { return vt[i]; } |
44 | __forceinline Vec3fa Ng(const size_t i) const { return Vec3fa(vNg.x[i],vNg.y[i],vNg.z[i]); } |
45 | |
46 | public: |
47 | vfloat<M> U; |
48 | vfloat<M> V; |
49 | vfloat<M> T; |
50 | vfloat<M> absDen; |
51 | UVMapper mapUV; |
52 | |
53 | public: |
54 | vbool<M> valid; |
55 | vfloat<M> vu; |
56 | vfloat<M> vv; |
57 | vfloat<M> vt; |
58 | Vec3vf<M> vNg; |
59 | }; |
60 | |
61 | template<int M, bool early_out = true> |
62 | struct MoellerTrumboreIntersector1 |
63 | { |
64 | __forceinline MoellerTrumboreIntersector1() {} |
65 | |
66 | __forceinline MoellerTrumboreIntersector1(const Ray& ray, const void* ptr) {} |
67 | |
68 | template<typename UVMapper> |
69 | __forceinline bool intersect(const vbool<M>& valid0, |
70 | Ray& ray, |
71 | const Vec3vf<M>& tri_v0, |
72 | const Vec3vf<M>& tri_e1, |
73 | const Vec3vf<M>& tri_e2, |
74 | const Vec3vf<M>& tri_Ng, |
75 | const UVMapper& mapUV, |
76 | MoellerTrumboreHitM<M,UVMapper>& hit) const |
77 | { |
78 | /* calculate denominator */ |
79 | vbool<M> valid = valid0; |
80 | const Vec3vf<M> O = Vec3vf<M>((Vec3fa)ray.org); |
81 | const Vec3vf<M> D = Vec3vf<M>((Vec3fa)ray.dir); |
82 | const Vec3vf<M> C = Vec3vf<M>(tri_v0) - O; |
83 | const Vec3vf<M> R = cross(C,D); |
84 | const vfloat<M> den = dot(Vec3vf<M>(tri_Ng),D); |
85 | |
86 | const vfloat<M> absDen = abs(den); |
87 | const vfloat<M> sgnDen = signmsk(den); |
88 | |
89 | /* perform edge tests */ |
90 | const vfloat<M> U = dot(R,Vec3vf<M>(tri_e2)) ^ sgnDen; |
91 | const vfloat<M> V = dot(R,Vec3vf<M>(tri_e1)) ^ sgnDen; |
92 | |
93 | /* perform backface culling */ |
94 | #if defined(EMBREE_BACKFACE_CULLING) |
95 | valid &= (den < vfloat<M>(zero)) & (U >= 0.0f) & (V >= 0.0f) & (U+V<=absDen); |
96 | #else |
97 | valid &= (den != vfloat<M>(zero)) & (U >= 0.0f) & (V >= 0.0f) & (U+V<=absDen); |
98 | #endif |
99 | if (likely(early_out && none(valid))) return false; |
100 | |
101 | /* perform depth test */ |
102 | const vfloat<M> T = dot(Vec3vf<M>(tri_Ng),C) ^ sgnDen; |
103 | valid &= (absDen*vfloat<M>(ray.tnear()) < T) & (T <= absDen*vfloat<M>(ray.tfar)); |
104 | if (likely(early_out && none(valid))) return false; |
105 | |
106 | /* update hit information */ |
107 | new (&hit) MoellerTrumboreHitM<M,UVMapper>(valid,U,V,T,absDen,tri_Ng,mapUV); |
108 | |
109 | return true; |
110 | } |
111 | |
112 | template<typename UVMapper> |
113 | __forceinline bool intersectEdge(const vbool<M>& valid, |
114 | Ray& ray, |
115 | const Vec3vf<M>& tri_v0, |
116 | const Vec3vf<M>& tri_e1, |
117 | const Vec3vf<M>& tri_e2, |
118 | const UVMapper& mapUV, |
119 | MoellerTrumboreHitM<M,UVMapper>& hit) const |
120 | { |
121 | const Vec3<vfloat<M>> tri_Ng = cross(tri_e2,tri_e1); |
122 | return intersect(valid,ray,tri_v0,tri_e1,tri_e2,tri_Ng,mapUV,hit); |
123 | } |
124 | |
125 | template<typename UVMapper> |
126 | __forceinline bool intersectEdge(Ray& ray, |
127 | const Vec3vf<M>& tri_v0, |
128 | const Vec3vf<M>& tri_e1, |
129 | const Vec3vf<M>& tri_e2, |
130 | const UVMapper& mapUV, |
131 | MoellerTrumboreHitM<M,UVMapper>& hit) const |
132 | { |
133 | vbool<M> valid = true; |
134 | const Vec3<vfloat<M>> tri_Ng = cross(tri_e2,tri_e1); |
135 | return intersect(valid,ray,tri_v0,tri_e1,tri_e2,tri_Ng,mapUV,hit); |
136 | } |
137 | |
138 | template<typename UVMapper> |
139 | __forceinline bool intersect(Ray& ray, |
140 | const Vec3vf<M>& v0, |
141 | const Vec3vf<M>& v1, |
142 | const Vec3vf<M>& v2, |
143 | const UVMapper& mapUV, |
144 | MoellerTrumboreHitM<M,UVMapper>& hit) const |
145 | { |
146 | const Vec3vf<M> e1 = v0-v1; |
147 | const Vec3vf<M> e2 = v2-v0; |
148 | return intersectEdge(ray,v0,e1,e2,mapUV,hit); |
149 | } |
150 | |
151 | template<typename UVMapper> |
152 | __forceinline bool intersect(const vbool<M>& valid, |
153 | Ray& ray, |
154 | const Vec3vf<M>& v0, |
155 | const Vec3vf<M>& v1, |
156 | const Vec3vf<M>& v2, |
157 | const UVMapper& mapUV, |
158 | MoellerTrumboreHitM<M,UVMapper>& hit) const |
159 | { |
160 | const Vec3vf<M> e1 = v0-v1; |
161 | const Vec3vf<M> e2 = v2-v0; |
162 | return intersectEdge(valid,ray,v0,e1,e2,mapUV,hit); |
163 | } |
164 | |
165 | template<typename UVMapper, typename Epilog> |
166 | __forceinline bool intersectEdge(Ray& ray, |
167 | const Vec3vf<M>& v0, |
168 | const Vec3vf<M>& e1, |
169 | const Vec3vf<M>& e2, |
170 | const UVMapper& mapUV, |
171 | const Epilog& epilog) const |
172 | { |
173 | MoellerTrumboreHitM<M,UVMapper> hit(mapUV); |
174 | if (likely(intersectEdge(ray,v0,e1,e2,mapUV,hit))) return epilog(hit.valid,hit); |
175 | return false; |
176 | } |
177 | |
178 | template<typename UVMapper, typename Epilog> |
179 | __forceinline bool intersect(Ray& ray, |
180 | const Vec3vf<M>& v0, |
181 | const Vec3vf<M>& v1, |
182 | const Vec3vf<M>& v2, |
183 | const UVMapper& mapUV, |
184 | const Epilog& epilog) const |
185 | { |
186 | MoellerTrumboreHitM<M,UVMapper> hit(mapUV); |
187 | if (likely(intersect(ray,v0,v1,v2,mapUV,hit))) return epilog(hit.valid,hit); |
188 | return false; |
189 | } |
190 | |
191 | template<typename Epilog> |
192 | __forceinline bool intersect(Ray& ray, |
193 | const Vec3vf<M>& v0, |
194 | const Vec3vf<M>& v1, |
195 | const Vec3vf<M>& v2, |
196 | const Epilog& epilog) const |
197 | { |
198 | auto mapUV = UVIdentity<M>(); |
199 | MoellerTrumboreHitM<M,UVIdentity<M>> hit(mapUV); |
200 | if (likely(intersect(ray,v0,v1,v2,mapUV,hit))) return epilog(hit.valid,hit); |
201 | return false; |
202 | } |
203 | |
204 | template<typename UVMapper, typename Epilog> |
205 | __forceinline bool intersect(const vbool<M>& valid, |
206 | Ray& ray, |
207 | const Vec3vf<M>& v0, |
208 | const Vec3vf<M>& v1, |
209 | const Vec3vf<M>& v2, |
210 | const UVMapper& mapUV, |
211 | const Epilog& epilog) const |
212 | { |
213 | MoellerTrumboreHitM<M,UVMapper> hit(mapUV); |
214 | if (likely(intersect(valid,ray,v0,v1,v2,mapUV,hit))) return epilog(hit.valid,hit); |
215 | return false; |
216 | } |
217 | }; |
218 | |
219 | template<int K, typename UVMapper> |
220 | struct MoellerTrumboreHitK |
221 | { |
222 | __forceinline MoellerTrumboreHitK(const UVMapper& mapUV) : mapUV(mapUV) {} |
223 | __forceinline MoellerTrumboreHitK(const vfloat<K>& U, const vfloat<K>& V, const vfloat<K>& T, const vfloat<K>& absDen, const Vec3vf<K>& Ng, const UVMapper& mapUV) |
224 | : U(U), V(V), T(T), absDen(absDen), Ng(Ng), mapUV(mapUV) {} |
225 | |
226 | __forceinline std::tuple<vfloat<K>,vfloat<K>,vfloat<K>,Vec3vf<K>> operator() () const |
227 | { |
228 | const vfloat<K> rcpAbsDen = rcp(absDen); |
229 | const vfloat<K> t = T * rcpAbsDen; |
230 | vfloat<K> u = U * rcpAbsDen; |
231 | vfloat<K> v = V * rcpAbsDen; |
232 | Vec3vf<K> vNg = Ng; |
233 | mapUV(u,v,vNg); |
234 | return std::make_tuple(u,v,t,vNg); |
235 | } |
236 | |
237 | vfloat<K> U; |
238 | vfloat<K> V; |
239 | const vfloat<K> T; |
240 | const vfloat<K> absDen; |
241 | const Vec3vf<K> Ng; |
242 | const UVMapper& mapUV; |
243 | }; |
244 | |
245 | template<int M, int K> |
246 | struct MoellerTrumboreIntersectorK |
247 | { |
248 | __forceinline MoellerTrumboreIntersectorK() {} |
249 | __forceinline MoellerTrumboreIntersectorK(const vbool<K>& valid, const RayK<K>& ray) {} |
250 | |
251 | /*! Intersects K rays with one of M triangles. */ |
252 | template<typename UVMapper> |
253 | __forceinline vbool<K> intersectK(const vbool<K>& valid0, |
254 | //RayK<K>& ray, |
255 | const Vec3vf<K>& ray_org, |
256 | const Vec3vf<K>& ray_dir, |
257 | const vfloat<K>& ray_tnear, |
258 | const vfloat<K>& ray_tfar, |
259 | const Vec3vf<K>& tri_v0, |
260 | const Vec3vf<K>& tri_e1, |
261 | const Vec3vf<K>& tri_e2, |
262 | const Vec3vf<K>& tri_Ng, |
263 | const UVMapper& mapUV, |
264 | MoellerTrumboreHitK<K,UVMapper> &hit) const |
265 | { |
266 | /* calculate denominator */ |
267 | vbool<K> valid = valid0; |
268 | const Vec3vf<K> C = tri_v0 - ray_org; |
269 | const Vec3vf<K> R = cross(C,ray_dir); |
270 | const vfloat<K> den = dot(tri_Ng,ray_dir); |
271 | const vfloat<K> absDen = abs(den); |
272 | const vfloat<K> sgnDen = signmsk(den); |
273 | |
274 | /* test against edge p2 p0 */ |
275 | const vfloat<K> U = dot(tri_e2,R) ^ sgnDen; |
276 | valid &= U >= 0.0f; |
277 | if (likely(none(valid))) return false; |
278 | |
279 | /* test against edge p0 p1 */ |
280 | const vfloat<K> V = dot(tri_e1,R) ^ sgnDen; |
281 | valid &= V >= 0.0f; |
282 | if (likely(none(valid))) return false; |
283 | |
284 | /* test against edge p1 p2 */ |
285 | const vfloat<K> W = absDen-U-V; |
286 | valid &= W >= 0.0f; |
287 | if (likely(none(valid))) return false; |
288 | |
289 | /* perform depth test */ |
290 | const vfloat<K> T = dot(tri_Ng,C) ^ sgnDen; |
291 | valid &= (absDen*ray_tnear < T) & (T <= absDen*ray_tfar); |
292 | if (unlikely(none(valid))) return false; |
293 | |
294 | /* perform backface culling */ |
295 | #if defined(EMBREE_BACKFACE_CULLING) |
296 | valid &= den < vfloat<K>(zero); |
297 | if (unlikely(none(valid))) return false; |
298 | #else |
299 | valid &= den != vfloat<K>(zero); |
300 | if (unlikely(none(valid))) return false; |
301 | #endif |
302 | |
303 | /* calculate hit information */ |
304 | new (&hit) MoellerTrumboreHitK<K,UVMapper>(U,V,T,absDen,tri_Ng,mapUV); |
305 | return valid; |
306 | } |
307 | |
308 | /*! Intersects K rays with one of M triangles. */ |
309 | template<typename UVMapper> |
310 | __forceinline vbool<K> intersectK(const vbool<K>& valid0, |
311 | RayK<K>& ray, |
312 | const Vec3vf<K>& tri_v0, |
313 | const Vec3vf<K>& tri_v1, |
314 | const Vec3vf<K>& tri_v2, |
315 | const UVMapper& mapUV, |
316 | MoellerTrumboreHitK<K,UVMapper> &hit) const |
317 | { |
318 | const Vec3vf<K> e1 = tri_v0-tri_v1; |
319 | const Vec3vf<K> e2 = tri_v2-tri_v0; |
320 | const Vec3vf<K> Ng = cross(e2,e1); |
321 | return intersectK(valid0,ray.org,ray.dir,ray.tnear(),ray.tfar,tri_v0,e1,e2,Ng,mapUV,hit); |
322 | } |
323 | |
324 | |
325 | /*! Intersects K rays with one of M triangles. */ |
326 | template<typename UVMapper, typename Epilog> |
327 | __forceinline vbool<K> intersectK(const vbool<K>& valid0, |
328 | RayK<K>& ray, |
329 | const Vec3vf<K>& tri_v0, |
330 | const Vec3vf<K>& tri_v1, |
331 | const Vec3vf<K>& tri_v2, |
332 | const UVMapper& mapUV, |
333 | const Epilog& epilog) const |
334 | { |
335 | MoellerTrumboreHitK<K,UVIdentity<K>> hit(mapUV); |
336 | const Vec3vf<K> e1 = tri_v0-tri_v1; |
337 | const Vec3vf<K> e2 = tri_v2-tri_v0; |
338 | const Vec3vf<K> Ng = cross(e2,e1); |
339 | const vbool<K> valid = intersectK(valid0,ray.org,ray.dir,ray.tnear(),ray.tfar,tri_v0,e1,e2,Ng,mapUV,hit); |
340 | return epilog(valid,hit); |
341 | } |
342 | |
343 | |
344 | |
345 | template<typename Epilog> |
346 | __forceinline vbool<K> intersectK(const vbool<K>& valid0, |
347 | RayK<K>& ray, |
348 | const Vec3vf<K>& tri_v0, |
349 | const Vec3vf<K>& tri_v1, |
350 | const Vec3vf<K>& tri_v2, |
351 | const Epilog& epilog) const |
352 | { |
353 | UVIdentity<K> mapUV; |
354 | MoellerTrumboreHitK<K,UVIdentity<K>> hit(mapUV); |
355 | const Vec3vf<K> e1 = tri_v0-tri_v1; |
356 | const Vec3vf<K> e2 = tri_v2-tri_v0; |
357 | const Vec3vf<K> Ng = cross(e2,e1); |
358 | const vbool<K> valid = intersectK(valid0,ray.org,ray.dir,ray.tnear(),ray.tfar,tri_v0,e1,e2,Ng,mapUV,hit); |
359 | return epilog(valid,hit); |
360 | } |
361 | |
362 | /*! Intersects K rays with one of M triangles. */ |
363 | template<typename UVMapper, typename Epilog> |
364 | __forceinline vbool<K> intersectEdgeK(const vbool<K>& valid0, |
365 | RayK<K>& ray, |
366 | const Vec3vf<K>& tri_v0, |
367 | const Vec3vf<K>& tri_e1, |
368 | const Vec3vf<K>& tri_e2, |
369 | const UVMapper& mapUV, |
370 | const Epilog& epilog) const |
371 | { |
372 | MoellerTrumboreHitK<K,UVIdentity<K>> hit(mapUV); |
373 | const Vec3vf<K> tri_Ng = cross(tri_e2,tri_e1); |
374 | const vbool<K> valid = intersectK(valid0,ray.org,ray.dir,ray.tnear(),ray.tfar,tri_v0,tri_e1,tri_e2,tri_Ng,mapUV,hit); |
375 | return epilog(valid,hit); |
376 | } |
377 | |
378 | /*! Intersect k'th ray from ray packet of size K with M triangles. */ |
379 | template<typename UVMapper> |
380 | __forceinline bool intersectEdge(RayK<K>& ray, |
381 | size_t k, |
382 | const Vec3vf<M>& tri_v0, |
383 | const Vec3vf<M>& tri_e1, |
384 | const Vec3vf<M>& tri_e2, |
385 | const UVMapper& mapUV, |
386 | MoellerTrumboreHitM<M,UVMapper>& hit) const |
387 | { |
388 | /* calculate denominator */ |
389 | typedef Vec3vf<M> Vec3vfM; |
390 | const Vec3vf<M> tri_Ng = cross(tri_e2,tri_e1); |
391 | |
392 | const Vec3vfM O = broadcast<vfloat<M>>(ray.org,k); |
393 | const Vec3vfM D = broadcast<vfloat<M>>(ray.dir,k); |
394 | const Vec3vfM C = Vec3vfM(tri_v0) - O; |
395 | const Vec3vfM R = cross(C,D); |
396 | const vfloat<M> den = dot(Vec3vfM(tri_Ng),D); |
397 | const vfloat<M> absDen = abs(den); |
398 | const vfloat<M> sgnDen = signmsk(den); |
399 | |
400 | /* perform edge tests */ |
401 | const vfloat<M> U = dot(Vec3vf<M>(tri_e2),R) ^ sgnDen; |
402 | const vfloat<M> V = dot(Vec3vf<M>(tri_e1),R) ^ sgnDen; |
403 | |
404 | /* perform backface culling */ |
405 | #if defined(EMBREE_BACKFACE_CULLING) |
406 | vbool<M> valid = (den < vfloat<M>(zero)) & (U >= 0.0f) & (V >= 0.0f) & (U+V<=absDen); |
407 | #else |
408 | vbool<M> valid = (den != vfloat<M>(zero)) & (U >= 0.0f) & (V >= 0.0f) & (U+V<=absDen); |
409 | #endif |
410 | if (likely(none(valid))) return false; |
411 | |
412 | /* perform depth test */ |
413 | const vfloat<M> T = dot(Vec3vf<M>(tri_Ng),C) ^ sgnDen; |
414 | valid &= (absDen*vfloat<M>(ray.tnear()[k]) < T) & (T <= absDen*vfloat<M>(ray.tfar[k])); |
415 | if (likely(none(valid))) return false; |
416 | |
417 | /* calculate hit information */ |
418 | new (&hit) MoellerTrumboreHitM<M,UVMapper>(valid,U,V,T,absDen,tri_Ng,mapUV); |
419 | return true; |
420 | } |
421 | |
422 | template<typename UVMapper> |
423 | __forceinline bool intersectEdge(RayK<K>& ray, |
424 | size_t k, |
425 | const BBox<vfloat<M>>& time_range, |
426 | const Vec3vf<M>& tri_v0, |
427 | const Vec3vf<M>& tri_e1, |
428 | const Vec3vf<M>& tri_e2, |
429 | const UVMapper& mapUV, |
430 | MoellerTrumboreHitM<M,UVMapper>& hit) const |
431 | { |
432 | if (likely(intersect(ray,k,tri_v0,tri_e1,tri_e2,mapUV,hit))) |
433 | { |
434 | hit.valid &= time_range.lower <= vfloat<M>(ray.time[k]); |
435 | hit.valid &= vfloat<M>(ray.time[k]) < time_range.upper; |
436 | return any(hit.valid); |
437 | } |
438 | return false; |
439 | } |
440 | |
441 | template<typename UVMapper> |
442 | __forceinline bool intersect(RayK<K>& ray, |
443 | size_t k, |
444 | const Vec3vf<M>& v0, |
445 | const Vec3vf<M>& v1, |
446 | const Vec3vf<M>& v2, |
447 | const UVMapper& mapUV, |
448 | MoellerTrumboreHitM<M,UVMapper>& hit) const |
449 | { |
450 | const Vec3vf<M> e1 = v0-v1; |
451 | const Vec3vf<M> e2 = v2-v0; |
452 | return intersectEdge(ray,k,v0,e1,e2,mapUV,hit); |
453 | } |
454 | |
455 | template<typename UVMapper, typename Epilog> |
456 | __forceinline bool intersectEdge(RayK<K>& ray, |
457 | size_t k, |
458 | const Vec3vf<M>& tri_v0, |
459 | const Vec3vf<M>& tri_e1, |
460 | const Vec3vf<M>& tri_e2, |
461 | const UVMapper& mapUV, |
462 | const Epilog& epilog) const |
463 | { |
464 | MoellerTrumboreHitM<M,UVMapper> hit(mapUV); |
465 | if (likely(intersectEdge(ray,k,tri_v0,tri_e1,tri_e2,mapUV,hit))) return epilog(hit.valid,hit); |
466 | return false; |
467 | } |
468 | |
469 | template<typename UVMapper, typename Epilog> |
470 | __forceinline bool intersectEdge(RayK<K>& ray, |
471 | size_t k, |
472 | const BBox<vfloat<M>>& time_range, |
473 | const Vec3vf<M>& tri_v0, |
474 | const Vec3vf<M>& tri_e1, |
475 | const Vec3vf<M>& tri_e2, |
476 | const UVMapper& mapUV, |
477 | const Epilog& epilog) const |
478 | { |
479 | MoellerTrumboreHitM<M,UVMapper> hit(mapUV); |
480 | if (likely(intersectEdge(ray,k,time_range,tri_v0,tri_e1,tri_e2,mapUV,hit))) return epilog(hit.valid,hit); |
481 | return false; |
482 | } |
483 | |
484 | template<typename UVMapper, typename Epilog> |
485 | __forceinline bool intersect(RayK<K>& ray, |
486 | size_t k, |
487 | const Vec3vf<M>& v0, |
488 | const Vec3vf<M>& v1, |
489 | const Vec3vf<M>& v2, |
490 | const UVMapper& mapUV, |
491 | const Epilog& epilog) const |
492 | { |
493 | const Vec3vf<M> e1 = v0-v1; |
494 | const Vec3vf<M> e2 = v2-v0; |
495 | return intersectEdge(ray,k,v0,e1,e2,mapUV,epilog); |
496 | } |
497 | |
498 | template<typename Epilog> |
499 | __forceinline bool intersect(RayK<K>& ray, |
500 | size_t k, |
501 | const Vec3vf<M>& v0, |
502 | const Vec3vf<M>& v1, |
503 | const Vec3vf<M>& v2, |
504 | const Epilog& epilog) const |
505 | { |
506 | return intersect(ray,k,v0,v1,v2,UVIdentity<M>(),epilog); |
507 | } |
508 | |
509 | template<typename UVMapper, typename Epilog> |
510 | __forceinline bool intersect(RayK<K>& ray, |
511 | size_t k, |
512 | const BBox<vfloat<M>>& time_range, |
513 | const Vec3vf<M>& v0, |
514 | const Vec3vf<M>& v1, |
515 | const Vec3vf<M>& v2, |
516 | const UVMapper& mapUV, |
517 | const Epilog& epilog) const |
518 | { |
519 | const Vec3vf<M> e1 = v0-v1; |
520 | const Vec3vf<M> e2 = v2-v0; |
521 | return intersectEdge(ray,k,time_range,v0,e1,e2,mapUV,epilog); |
522 | } |
523 | }; |
524 | } |
525 | } |
526 | |