quad_intersector_pluecker.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. // ======================================================================== //
  2. // Copyright 2009-2017 Intel Corporation //
  3. // //
  4. // Licensed under the Apache License, Version 2.0 (the "License"); //
  5. // you may not use this file except in compliance with the License. //
  6. // You may obtain a copy of the License at //
  7. // //
  8. // http://www.apache.org/licenses/LICENSE-2.0 //
  9. // //
  10. // Unless required by applicable law or agreed to in writing, software //
  11. // distributed under the License is distributed on an "AS IS" BASIS, //
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
  13. // See the License for the specific language governing permissions and //
  14. // limitations under the License. //
  15. // ======================================================================== //
  16. #pragma once
  17. #include "quad_intersector_moeller.h"
  18. /*! Modified Pluecker ray/triangle intersector. The test first shifts
  19. * the ray origin into the origin of the coordinate system and then
  20. * uses Pluecker coordinates for the intersection. Due to the shift,
  21. * the Pluecker coordinate calculation simplifies and the tests get
  22. * numerically stable. The edge equations are watertight along the
  23. * edge for neighboring triangles. */
  24. namespace embree
  25. {
  26. namespace isa
  27. {
  28. struct PlueckerIntersectorTriangle1
  29. {
  30. template<int M, typename Epilog>
  31. static __forceinline bool intersect(Ray& ray,
  32. const Vec3<vfloat<M>>& tri_v0,
  33. const Vec3<vfloat<M>>& tri_v1,
  34. const Vec3<vfloat<M>>& tri_v2,
  35. const vbool<M>& flags,
  36. const Epilog& epilog)
  37. {
  38. /* calculate vertices relative to ray origin */
  39. typedef Vec3<vfloat<M>> Vec3vfM;
  40. const Vec3vfM O = Vec3vfM(ray.org);
  41. const Vec3vfM D = Vec3vfM(ray.dir);
  42. const Vec3vfM v0 = tri_v0-O;
  43. const Vec3vfM v1 = tri_v1-O;
  44. const Vec3vfM v2 = tri_v2-O;
  45. /* calculate triangle edges */
  46. const Vec3vfM e0 = v2-v0;
  47. const Vec3vfM e1 = v0-v1;
  48. const Vec3vfM e2 = v1-v2;
  49. /* perform edge tests */
  50. const vfloat<M> U = dot(cross(v2+v0,e0),D);
  51. const vfloat<M> V = dot(cross(v0+v1,e1),D);
  52. const vfloat<M> W = dot(cross(v1+v2,e2),D);
  53. #if defined(EMBREE_BACKFACE_CULLING)
  54. const vfloat<M> maxUVW = max(U,V,W);
  55. vbool<M> valid = maxUVW <= 0.0f;
  56. #else
  57. const vfloat<M> minUVW = min(U,V,W);
  58. const vfloat<M> maxUVW = max(U,V,W);
  59. vbool<M> valid = (maxUVW <= 0.0f) | (minUVW >= 0.0f);
  60. #endif
  61. if (unlikely(none(valid))) return false;
  62. /* calculate geometry normal and denominator */
  63. const Vec3vfM Ng = stable_triangle_normal(e2,e1,e0);
  64. const vfloat<M> den = twice(dot(Ng,D));
  65. const vfloat<M> absDen = abs(den);
  66. const vfloat<M> sgnDen = signmsk(den);
  67. /* perform depth test */
  68. const vfloat<M> T = twice(dot(v0,Ng));
  69. valid &= ((T^sgnDen) >= absDen*vfloat<M>(ray.tnear));
  70. valid &=(absDen*vfloat<M>(ray.tfar) >= (T^sgnDen));
  71. if (unlikely(none(valid))) return false;
  72. /* avoid division by 0 */
  73. valid &= den != vfloat<M>(zero);
  74. if (unlikely(none(valid))) return false;
  75. /* update hit information */
  76. QuadHitM<M> hit(valid,U,V,T,den,Ng,flags);
  77. return epilog(valid,hit);
  78. }
  79. };
  80. /*! Intersects M quads with 1 ray */
  81. template<int M, bool filter>
  82. struct QuadMIntersector1Pluecker
  83. {
  84. __forceinline QuadMIntersector1Pluecker() {}
  85. __forceinline QuadMIntersector1Pluecker(const Ray& ray, const void* ptr) {}
  86. __forceinline void intersect(Ray& ray, IntersectContext* context,
  87. const Vec3<vfloat<M>>& v0, const Vec3<vfloat<M>>& v1, const Vec3<vfloat<M>>& v2, const Vec3<vfloat<M>>& v3,
  88. const vint<M>& geomID, const vint<M>& primID) const
  89. {
  90. Intersect1EpilogM<M,M,filter> epilog(ray,context,geomID,primID);
  91. PlueckerIntersectorTriangle1::intersect(ray,v0,v1,v3,vbool<M>(false),epilog);
  92. PlueckerIntersectorTriangle1::intersect(ray,v2,v3,v1,vbool<M>(true),epilog);
  93. }
  94. __forceinline bool occluded(Ray& ray, IntersectContext* context,
  95. const Vec3<vfloat<M>>& v0, const Vec3<vfloat<M>>& v1, const Vec3<vfloat<M>>& v2, const Vec3<vfloat<M>>& v3,
  96. const vint<M>& geomID, const vint<M>& primID) const
  97. {
  98. Occluded1EpilogM<M,M,filter> epilog(ray,context,geomID,primID);
  99. if (PlueckerIntersectorTriangle1::intersect(ray,v0,v1,v3,vbool<M>(false),epilog)) return true;
  100. if (PlueckerIntersectorTriangle1::intersect(ray,v2,v3,v1,vbool<M>(true ),epilog)) return true;
  101. return false;
  102. }
  103. };
  104. #if defined(__AVX512F__)
  105. /*! Intersects 4 quads with 1 ray using AVX512 */
  106. template<bool filter>
  107. struct QuadMIntersector1Pluecker<4,filter>
  108. {
  109. __forceinline QuadMIntersector1Pluecker() {}
  110. __forceinline QuadMIntersector1Pluecker(const Ray& ray, const void* ptr) {}
  111. template<typename Epilog>
  112. __forceinline bool intersect(Ray& ray, const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const Epilog& epilog) const
  113. {
  114. const Vec3vf16 vtx0(select(0x0f0f,vfloat16(v0.x),vfloat16(v2.x)),
  115. select(0x0f0f,vfloat16(v0.y),vfloat16(v2.y)),
  116. select(0x0f0f,vfloat16(v0.z),vfloat16(v2.z)));
  117. #if !defined(EMBREE_BACKFACE_CULLING)
  118. const Vec3vf16 vtx1(vfloat16(v1.x),vfloat16(v1.y),vfloat16(v1.z));
  119. const Vec3vf16 vtx2(vfloat16(v3.x),vfloat16(v3.y),vfloat16(v3.z));
  120. #else
  121. const Vec3vf16 vtx1(select(0x0f0f,vfloat16(v1.x),vfloat16(v3.x)),
  122. select(0x0f0f,vfloat16(v1.y),vfloat16(v3.y)),
  123. select(0x0f0f,vfloat16(v1.z),vfloat16(v3.z)));
  124. const Vec3vf16 vtx2(select(0x0f0f,vfloat16(v3.x),vfloat16(v1.x)),
  125. select(0x0f0f,vfloat16(v3.y),vfloat16(v1.y)),
  126. select(0x0f0f,vfloat16(v3.z),vfloat16(v1.z)));
  127. #endif
  128. const vbool16 flags(0xf0f0);
  129. return PlueckerIntersectorTriangle1::intersect(ray,vtx0,vtx1,vtx2,flags,epilog);
  130. }
  131. __forceinline bool intersect(Ray& ray, IntersectContext* context,
  132. const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
  133. const vint4& geomID, const vint4& primID) const
  134. {
  135. return intersect(ray,v0,v1,v2,v3,Intersect1EpilogM<8,16,filter>(ray,context,vint8(geomID),vint8(primID)));
  136. }
  137. __forceinline bool occluded(Ray& ray, IntersectContext* context,
  138. const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
  139. const vint4& geomID, const vint4& primID) const
  140. {
  141. return intersect(ray,v0,v1,v2,v3,Occluded1EpilogM<8,16,filter>(ray,context,vint8(geomID),vint8(primID)));
  142. }
  143. };
  144. #elif defined (__AVX__)
  145. /*! Intersects 4 quads with 1 ray using AVX */
  146. template<bool filter>
  147. struct QuadMIntersector1Pluecker<4,filter>
  148. {
  149. __forceinline QuadMIntersector1Pluecker() {}
  150. __forceinline QuadMIntersector1Pluecker(const Ray& ray, const void* ptr) {}
  151. template<typename Epilog>
  152. __forceinline bool intersect(Ray& ray, const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const Epilog& epilog) const
  153. {
  154. const Vec3vf8 vtx0(vfloat8(v0.x,v2.x),vfloat8(v0.y,v2.y),vfloat8(v0.z,v2.z));
  155. #if !defined(EMBREE_BACKFACE_CULLING)
  156. const Vec3vf8 vtx1(vfloat8(v1.x),vfloat8(v1.y),vfloat8(v1.z));
  157. const Vec3vf8 vtx2(vfloat8(v3.x),vfloat8(v3.y),vfloat8(v3.z));
  158. #else
  159. const Vec3vf8 vtx1(vfloat8(v1.x,v3.x),vfloat8(v1.y,v3.y),vfloat8(v1.z,v3.z));
  160. const Vec3vf8 vtx2(vfloat8(v3.x,v1.x),vfloat8(v3.y,v1.y),vfloat8(v3.z,v1.z));
  161. #endif
  162. const vbool8 flags(0,0,0,0,1,1,1,1);
  163. return PlueckerIntersectorTriangle1::intersect(ray,vtx0,vtx1,vtx2,flags,epilog);
  164. }
  165. __forceinline bool intersect(Ray& ray, IntersectContext* context, const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
  166. const vint4& geomID, const vint4& primID) const
  167. {
  168. return intersect(ray,v0,v1,v2,v3,Intersect1EpilogM<8,8,filter>(ray,context,vint8(geomID),vint8(primID)));
  169. }
  170. __forceinline bool occluded(Ray& ray, IntersectContext* context, const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
  171. const vint4& geomID, const vint4& primID) const
  172. {
  173. return intersect(ray,v0,v1,v2,v3,Occluded1EpilogM<8,8,filter>(ray,context,vint8(geomID),vint8(primID)));
  174. }
  175. };
  176. #endif
  177. /* ----------------------------- */
  178. /* -- ray packet intersectors -- */
  179. /* ----------------------------- */
  180. struct PlueckerIntersector1KTriangleM
  181. {
  182. /*! Intersect k'th ray from ray packet of size K with M triangles. */
  183. template<int M, int K, typename Epilog>
  184. static __forceinline bool intersect1(RayK<K>& ray,
  185. size_t k,
  186. const Vec3<vfloat<M>>& tri_v0,
  187. const Vec3<vfloat<M>>& tri_v1,
  188. const Vec3<vfloat<M>>& tri_v2,
  189. const vbool<M>& flags,
  190. const Epilog& epilog)
  191. {
  192. /* calculate vertices relative to ray origin */
  193. typedef Vec3<vfloat<M>> Vec3vfM;
  194. const Vec3vfM O = broadcast<vfloat<M>>(ray.org,k);
  195. const Vec3vfM D = broadcast<vfloat<M>>(ray.dir,k);
  196. const Vec3vfM v0 = tri_v0-O;
  197. const Vec3vfM v1 = tri_v1-O;
  198. const Vec3vfM v2 = tri_v2-O;
  199. /* calculate triangle edges */
  200. const Vec3vfM e0 = v2-v0;
  201. const Vec3vfM e1 = v0-v1;
  202. const Vec3vfM e2 = v1-v2;
  203. /* perform edge tests */
  204. const vfloat<M> U = dot(cross(v2+v0,e0),D);
  205. const vfloat<M> V = dot(cross(v0+v1,e1),D);
  206. const vfloat<M> W = dot(cross(v1+v2,e2),D);
  207. const vfloat<M> minUVW MAYBE_UNUSED = min(U,V,W);
  208. const vfloat<M> maxUVW = max(U,V,W);
  209. #if defined(EMBREE_BACKFACE_CULLING)
  210. vbool<M> valid = maxUVW <= 0.0f;
  211. #else
  212. vbool<M> valid = (minUVW >= 0.0f) | (maxUVW <= 0.0f);
  213. #endif
  214. if (unlikely(none(valid))) return false;
  215. /* calculate geometry normal and denominator */
  216. const Vec3vfM Ng = stable_triangle_normal(e2,e1,e0);
  217. const vfloat<M> den = twice(dot(Ng,D));
  218. const vfloat<M> absDen = abs(den);
  219. const vfloat<M> sgnDen = signmsk(den);
  220. /* perform depth test */
  221. const vfloat<M> T = twice(dot(v0,Ng));
  222. valid &= ((T^sgnDen) >= absDen*vfloat<M>(ray.tnear[k]));
  223. valid &= (absDen*vfloat<M>(ray.tfar[k]) >= (T^sgnDen));
  224. if (unlikely(none(valid))) return false;
  225. /* avoid division by 0 */
  226. valid &= den != vfloat<M>(zero);
  227. if (unlikely(none(valid))) return false;
  228. /* calculate hit information */
  229. QuadHitM<M> hit(valid,U,V,T,den,Ng,flags);
  230. return epilog(valid,hit);
  231. }
  232. };
  233. template<int M, int K, bool filter>
  234. struct QuadMIntersectorKPlueckerBase
  235. {
  236. __forceinline QuadMIntersectorKPlueckerBase(const vbool<K>& valid, const RayK<K>& ray) {}
  237. /*! Intersects K rays with one of M triangles. */
  238. template<typename Epilog>
  239. __forceinline vbool<K> intersectK(const vbool<K>& valid0,
  240. RayK<K>& ray,
  241. const Vec3<vfloat<K>>& tri_v0,
  242. const Vec3<vfloat<K>>& tri_v1,
  243. const Vec3<vfloat<K>>& tri_v2,
  244. const vbool<K>& flags,
  245. const Epilog& epilog) const
  246. {
  247. /* calculate vertices relative to ray origin */
  248. typedef Vec3<vfloat<K>> Vec3vfK;
  249. vbool<K> valid = valid0;
  250. const Vec3vfK O = ray.org;
  251. const Vec3vfK D = ray.dir;
  252. const Vec3vfK v0 = tri_v0-O;
  253. const Vec3vfK v1 = tri_v1-O;
  254. const Vec3vfK v2 = tri_v2-O;
  255. /* calculate triangle edges */
  256. const Vec3vfK e0 = v2-v0;
  257. const Vec3vfK e1 = v0-v1;
  258. const Vec3vfK e2 = v1-v2;
  259. /* perform edge tests */
  260. const vfloat<K> U = dot(Vec3vfK(cross(v2+v0,e0)),D);
  261. const vfloat<K> V = dot(Vec3vfK(cross(v0+v1,e1)),D);
  262. const vfloat<K> W = dot(Vec3vfK(cross(v1+v2,e2)),D);
  263. #if defined(EMBREE_BACKFACE_CULLING)
  264. const vfloat<K> maxUVW = max(U,V,W);
  265. valid &= maxUVW <= 0.0f;
  266. #else
  267. const vfloat<K> minUVW = min(U,V,W);
  268. const vfloat<K> maxUVW = max(U,V,W);
  269. valid &= (maxUVW <= 0.0f) | (minUVW >= 0.0f);
  270. #endif
  271. if (unlikely(none(valid))) return false;
  272. /* calculate geometry normal and denominator */
  273. const Vec3vfK Ng = stable_triangle_normal(e2,e1,e0);
  274. const vfloat<K> den = twice(dot(Vec3vfK(Ng),D));
  275. const vfloat<K> absDen = abs(den);
  276. const vfloat<K> sgnDen = signmsk(den);
  277. /* perform depth test */
  278. const vfloat<K> T = twice(dot(v0,Vec3vfK(Ng)));
  279. valid &= ((T^sgnDen) >= absDen*ray.tnear);
  280. valid &= (absDen*ray.tfar >= (T^sgnDen));
  281. if (unlikely(none(valid))) return false;
  282. /* avoid division by 0 */
  283. valid &= den != vfloat<K>(zero);
  284. if (unlikely(none(valid))) return false;
  285. /* calculate hit information */
  286. QuadHitK<K> hit(U,V,T,den,Ng,flags);
  287. return epilog(valid,hit);
  288. }
  289. /*! Intersects K rays with one of M quads. */
  290. template<typename Epilog>
  291. __forceinline bool intersectK(const vbool<K>& valid0,
  292. RayK<K>& ray,
  293. const Vec3<vfloat<K>>& v0,
  294. const Vec3<vfloat<K>>& v1,
  295. const Vec3<vfloat<K>>& v2,
  296. const Vec3<vfloat<K>>& v3,
  297. const Epilog& epilog) const
  298. {
  299. intersectK(valid0,ray,v0,v1,v3,vbool<K>(false),epilog);
  300. if (none(valid0)) return true;
  301. intersectK(valid0,ray,v2,v3,v1,vbool<K>(true ),epilog);
  302. return none(valid0);
  303. }
  304. };
  305. template<int M, int K, bool filter>
  306. struct QuadMIntersectorKPluecker : public QuadMIntersectorKPlueckerBase<M,K,filter>
  307. {
  308. __forceinline QuadMIntersectorKPluecker(const vbool<K>& valid, const RayK<K>& ray)
  309. : QuadMIntersectorKPlueckerBase<M,K,filter>(valid,ray) {}
  310. __forceinline void intersect1(RayK<K>& ray, size_t k, IntersectContext* context,
  311. const Vec3<vfloat<M>>& v0, const Vec3<vfloat<M>>& v1, const Vec3<vfloat<M>>& v2, const Vec3<vfloat<M>>& v3,
  312. const vint<M>& geomID, const vint<M>& primID) const
  313. {
  314. Intersect1KEpilogM<M,M,K,filter> epilog(ray,k,context,geomID,primID);
  315. PlueckerIntersector1KTriangleM::intersect1(ray,k,v0,v1,v3,vbool<M>(false),epilog);
  316. PlueckerIntersector1KTriangleM::intersect1(ray,k,v2,v3,v1,vbool<M>(true ),epilog);
  317. }
  318. __forceinline bool occluded1(RayK<K>& ray, size_t k, IntersectContext* context,
  319. const Vec3<vfloat<M>>& v0, const Vec3<vfloat<M>>& v1, const Vec3<vfloat<M>>& v2, const Vec3<vfloat<M>>& v3,
  320. const vint<M>& geomID, const vint<M>& primID) const
  321. {
  322. Occluded1KEpilogM<M,M,K,filter> epilog(ray,k,context,geomID,primID);
  323. if (PlueckerIntersector1KTriangleM::intersect1(ray,k,v0,v1,v3,vbool<M>(false),epilog)) return true;
  324. if (PlueckerIntersector1KTriangleM::intersect1(ray,k,v2,v3,v1,vbool<M>(true ),epilog)) return true;
  325. return false;
  326. }
  327. };
  328. #if defined(__AVX512F__)
  329. /*! Intersects 4 quads with 1 ray using AVX512 */
  330. template<int K, bool filter>
  331. struct QuadMIntersectorKPluecker<4,K,filter> : public QuadMIntersectorKPlueckerBase<4,K,filter>
  332. {
  333. __forceinline QuadMIntersectorKPluecker(const vbool<K>& valid, const RayK<K>& ray)
  334. : QuadMIntersectorKPlueckerBase<4,K,filter>(valid,ray) {}
  335. template<typename Epilog>
  336. __forceinline bool intersect1(RayK<K>& ray, size_t k, const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const Epilog& epilog) const
  337. {
  338. const Vec3vf16 vtx0(select(0x0f0f,vfloat16(v0.x),vfloat16(v2.x)),
  339. select(0x0f0f,vfloat16(v0.y),vfloat16(v2.y)),
  340. select(0x0f0f,vfloat16(v0.z),vfloat16(v2.z)));
  341. #if !defined(EMBREE_BACKFACE_CULLING)
  342. const Vec3vf16 vtx1(vfloat16(v1.x),vfloat16(v1.y),vfloat16(v1.z));
  343. const Vec3vf16 vtx2(vfloat16(v3.x),vfloat16(v3.y),vfloat16(v3.z));
  344. #else
  345. const Vec3vf16 vtx1(select(0x0f0f,vfloat16(v1.x),vfloat16(v3.x)),
  346. select(0x0f0f,vfloat16(v1.y),vfloat16(v3.y)),
  347. select(0x0f0f,vfloat16(v1.z),vfloat16(v3.z)));
  348. const Vec3vf16 vtx2(select(0x0f0f,vfloat16(v3.x),vfloat16(v1.x)),
  349. select(0x0f0f,vfloat16(v3.y),vfloat16(v1.y)),
  350. select(0x0f0f,vfloat16(v3.z),vfloat16(v1.z)));
  351. #endif
  352. const vbool16 flags(0xf0f0);
  353. return PlueckerIntersector1KTriangleM::intersect1(ray,k,vtx0,vtx1,vtx2,flags,epilog);
  354. }
  355. __forceinline bool intersect1(RayK<K>& ray, size_t k, IntersectContext* context,
  356. const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
  357. const vint4& geomID, const vint4& primID) const
  358. {
  359. return intersect1(ray,k,v0,v1,v2,v3,Intersect1KEpilogM<8,16,K,filter>(ray,k,context,vint8(geomID),vint8(primID)));
  360. }
  361. __forceinline bool occluded1(RayK<K>& ray, size_t k, IntersectContext* context,
  362. const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
  363. const vint4& geomID, const vint4& primID) const
  364. {
  365. return intersect1(ray,k,v0,v1,v2,v3,Occluded1KEpilogM<8,16,K,filter>(ray,k,context,vint8(geomID),vint8(primID)));
  366. }
  367. };
  368. #elif defined (__AVX__)
  369. /*! Intersects 4 quads with 1 ray using AVX */
  370. template<int K, bool filter>
  371. struct QuadMIntersectorKPluecker<4,K,filter> : public QuadMIntersectorKPlueckerBase<4,K,filter>
  372. {
  373. __forceinline QuadMIntersectorKPluecker(const vbool<K>& valid, const RayK<K>& ray)
  374. : QuadMIntersectorKPlueckerBase<4,K,filter>(valid,ray) {}
  375. template<typename Epilog>
  376. __forceinline bool intersect1(RayK<K>& ray, size_t k, const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3, const Epilog& epilog) const
  377. {
  378. const Vec3vf8 vtx0(vfloat8(v0.x,v2.x),vfloat8(v0.y,v2.y),vfloat8(v0.z,v2.z));
  379. const vbool8 flags(0,0,0,0,1,1,1,1);
  380. #if !defined(EMBREE_BACKFACE_CULLING)
  381. const Vec3vf8 vtx1(vfloat8(v1.x),vfloat8(v1.y),vfloat8(v1.z));
  382. const Vec3vf8 vtx2(vfloat8(v3.x),vfloat8(v3.y),vfloat8(v3.z));
  383. #else
  384. const Vec3vf8 vtx1(vfloat8(v1.x,v3.x),vfloat8(v1.y,v3.y),vfloat8(v1.z,v3.z));
  385. const Vec3vf8 vtx2(vfloat8(v3.x,v1.x),vfloat8(v3.y,v1.y),vfloat8(v3.z,v1.z));
  386. #endif
  387. return PlueckerIntersector1KTriangleM::intersect1(ray,k,vtx0,vtx1,vtx2,flags,epilog);
  388. }
  389. __forceinline bool intersect1(RayK<K>& ray, size_t k, IntersectContext* context,
  390. const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
  391. const vint4& geomID, const vint4& primID) const
  392. {
  393. return intersect1(ray,k,v0,v1,v2,v3,Intersect1KEpilogM<8,8,K,filter>(ray,k,context,vint8(geomID),vint8(primID)));
  394. }
  395. __forceinline bool occluded1(RayK<K>& ray, size_t k, IntersectContext* context,
  396. const Vec3vf4& v0, const Vec3vf4& v1, const Vec3vf4& v2, const Vec3vf4& v3,
  397. const vint4& geomID, const vint4& primID) const
  398. {
  399. return intersect1(ray,k,v0,v1,v2,v3,Occluded1KEpilogM<8,8,K,filter>(ray,k,context,vint8(geomID),vint8(primID)));
  400. }
  401. };
  402. #endif
  403. }
  404. }