triangle_intersector_moeller.h 22 KB

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