triangle_intersector_pluecker.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. // Copyright 2009-2021 Intel Corporation
  2. // SPDX-License-Identifier: Apache-2.0
  3. #pragma once
  4. #include "triangle.h"
  5. #include "trianglev.h"
  6. #include "trianglev_mb.h"
  7. #include "intersector_epilog.h"
  8. /*! Modified Pluecker ray/triangle intersector. The test first shifts
  9. * the ray origin into the origin of the coordinate system and then
  10. * uses Pluecker coordinates for the intersection. Due to the shift,
  11. * the Pluecker coordinate calculation simplifies and the tests get
  12. * numerically stable. The edge equations are watertight along the
  13. * edge for neighboring triangles. */
  14. namespace embree
  15. {
  16. namespace isa
  17. {
  18. template<int M, typename UVMapper>
  19. struct PlueckerHitM
  20. {
  21. __forceinline PlueckerHitM(const UVMapper& mapUV) : mapUV(mapUV) {}
  22. __forceinline PlueckerHitM(const vbool<M>& valid, const vfloat<M>& U, const vfloat<M>& V, const vfloat<M>& UVW, const vfloat<M>& t, const Vec3vf<M>& Ng, const UVMapper& mapUV)
  23. : U(U), V(V), UVW(UVW), mapUV(mapUV), valid(valid), vt(t), vNg(Ng) {}
  24. __forceinline void finalize()
  25. {
  26. const vbool<M> invalid = abs(UVW) < min_rcp_input;
  27. const vfloat<M> rcpUVW = select(invalid,vfloat<M>(0.0f),rcp(UVW));
  28. vu = min(U * rcpUVW,1.0f);
  29. vv = min(V * rcpUVW,1.0f);
  30. mapUV(vu,vv,vNg);
  31. }
  32. __forceinline Vec2vf<M> uv() const { return Vec2vf<M>(vu,vv); }
  33. __forceinline vfloat<M> t () const { return vt; }
  34. __forceinline Vec3vf<M> Ng() const { return vNg; }
  35. __forceinline Vec2f uv (const size_t i) const { return Vec2f(vu[i],vv[i]); }
  36. __forceinline float t (const size_t i) const { return vt[i]; }
  37. __forceinline Vec3fa Ng(const size_t i) const { return Vec3fa(vNg.x[i],vNg.y[i],vNg.z[i]); }
  38. public:
  39. vfloat<M> U;
  40. vfloat<M> V;
  41. vfloat<M> UVW;
  42. const 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 PlueckerIntersector1
  52. {
  53. __forceinline PlueckerIntersector1() {}
  54. __forceinline PlueckerIntersector1(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_v1,
  60. const Vec3vf<M>& tri_v2,
  61. const UVMapper& mapUV,
  62. PlueckerHitM<M,UVMapper>& hit) const
  63. {
  64. vbool<M> valid = valid0;
  65. /* calculate vertices relative to ray origin */
  66. const Vec3vf<M> O = Vec3vf<M>((Vec3fa)ray.org);
  67. const Vec3vf<M> D = Vec3vf<M>((Vec3fa)ray.dir);
  68. const Vec3vf<M> v0 = tri_v0-O;
  69. const Vec3vf<M> v1 = tri_v1-O;
  70. const Vec3vf<M> v2 = tri_v2-O;
  71. /* calculate triangle edges */
  72. const Vec3vf<M> e0 = v2-v0;
  73. const Vec3vf<M> e1 = v0-v1;
  74. const Vec3vf<M> e2 = v1-v2;
  75. /* perform edge tests */
  76. const vfloat<M> U = dot(cross(e0,v2+v0),D);
  77. const vfloat<M> V = dot(cross(e1,v0+v1),D);
  78. const vfloat<M> W = dot(cross(e2,v1+v2),D);
  79. const vfloat<M> UVW = U+V+W;
  80. const vfloat<M> eps = float(ulp)*abs(UVW);
  81. #if defined(EMBREE_BACKFACE_CULLING)
  82. valid &= max(U,V,W) <= eps;
  83. #else
  84. valid &= (min(U,V,W) >= -eps) | (max(U,V,W) <= eps);
  85. #endif
  86. if (unlikely(early_out && none(valid))) return false;
  87. /* calculate geometry normal and denominator */
  88. const Vec3vf<M> Ng = stable_triangle_normal(e0,e1,e2);
  89. const vfloat<M> den = twice(dot(Ng,D));
  90. /* perform depth test */
  91. const vfloat<M> T = twice(dot(v0,Ng));
  92. const vfloat<M> t = rcp(den)*T;
  93. valid &= vfloat<M>(ray.tnear()) <= t & t <= vfloat<M>(ray.tfar);
  94. valid &= den != vfloat<M>(zero);
  95. if (unlikely(early_out && none(valid))) return false;
  96. /* update hit information */
  97. new (&hit) PlueckerHitM<M,UVMapper>(valid,U,V,UVW,t,Ng,mapUV);
  98. return true;
  99. }
  100. template<typename UVMapper>
  101. __forceinline bool intersectEdge(const vbool<M>& valid,
  102. Ray& ray,
  103. const Vec3vf<M>& tri_v0,
  104. const Vec3vf<M>& tri_v1,
  105. const Vec3vf<M>& tri_v2,
  106. const UVMapper& mapUV,
  107. PlueckerHitM<M,UVMapper>& hit) const
  108. {
  109. return intersect(valid,ray,tri_v0,tri_v1,tri_v2,mapUV,hit);
  110. }
  111. template<typename UVMapper>
  112. __forceinline bool intersectEdge(Ray& ray,
  113. const Vec3vf<M>& tri_v0,
  114. const Vec3vf<M>& tri_v1,
  115. const Vec3vf<M>& tri_v2,
  116. const UVMapper& mapUV,
  117. PlueckerHitM<M,UVMapper>& hit) const
  118. {
  119. vbool<M> valid = true;
  120. return intersect(valid,ray,tri_v0,tri_v1,tri_v2,mapUV,hit);
  121. }
  122. template<typename UVMapper>
  123. __forceinline bool intersect(Ray& ray,
  124. const Vec3vf<M>& tri_v0,
  125. const Vec3vf<M>& tri_v1,
  126. const Vec3vf<M>& tri_v2,
  127. const UVMapper& mapUV,
  128. PlueckerHitM<M,UVMapper>& hit) const
  129. {
  130. return intersectEdge(ray,tri_v0,tri_v1,tri_v2,mapUV,hit);
  131. }
  132. template<typename UVMapper, typename Epilog>
  133. __forceinline bool intersectEdge(Ray& ray,
  134. const Vec3vf<M>& v0,
  135. const Vec3vf<M>& e1,
  136. const Vec3vf<M>& e2,
  137. const UVMapper& mapUV,
  138. const Epilog& epilog) const
  139. {
  140. PlueckerHitM<M,UVMapper> hit(mapUV);
  141. if (likely(intersectEdge(ray,v0,e1,e2,mapUV,hit))) return epilog(hit.valid,hit);
  142. return false;
  143. }
  144. template<typename UVMapper, typename Epilog>
  145. __forceinline bool intersect(Ray& ray,
  146. const Vec3vf<M>& v0,
  147. const Vec3vf<M>& v1,
  148. const Vec3vf<M>& v2,
  149. const UVMapper& mapUV,
  150. const Epilog& epilog) const
  151. {
  152. PlueckerHitM<M,UVMapper> hit(mapUV);
  153. if (likely(intersect(ray,v0,v1,v2,mapUV,hit))) return epilog(hit.valid,hit);
  154. return false;
  155. }
  156. template<typename Epilog>
  157. __forceinline bool intersect(Ray& ray,
  158. const Vec3vf<M>& v0,
  159. const Vec3vf<M>& v1,
  160. const Vec3vf<M>& v2,
  161. const Epilog& epilog) const
  162. {
  163. auto mapUV = UVIdentity<M>();
  164. PlueckerHitM<M,UVIdentity<M>> hit(mapUV);
  165. if (likely(intersect(ray,v0,v1,v2,mapUV,hit))) return epilog(hit.valid,hit);
  166. return false;
  167. }
  168. template<typename UVMapper, typename Epilog>
  169. __forceinline bool intersect(const vbool<M>& valid,
  170. Ray& ray,
  171. const Vec3vf<M>& v0,
  172. const Vec3vf<M>& v1,
  173. const Vec3vf<M>& v2,
  174. const UVMapper& mapUV,
  175. const Epilog& epilog) const
  176. {
  177. PlueckerHitM<M,UVMapper> hit(mapUV);
  178. if (likely(intersect(valid,ray,v0,v1,v2,mapUV,hit))) return epilog(hit.valid,hit);
  179. return false;
  180. }
  181. };
  182. template<int K, typename UVMapper>
  183. struct PlueckerHitK
  184. {
  185. __forceinline PlueckerHitK(const UVMapper& mapUV) : mapUV(mapUV) {}
  186. __forceinline PlueckerHitK(const vfloat<K>& U, const vfloat<K>& V, const vfloat<K>& UVW, const vfloat<K>& t, const Vec3vf<K>& Ng, const UVMapper& mapUV)
  187. : U(U), V(V), UVW(UVW), t(t), Ng(Ng), mapUV(mapUV) {}
  188. __forceinline std::tuple<vfloat<K>,vfloat<K>,vfloat<K>,Vec3vf<K>> operator() () const
  189. {
  190. const vbool<K> invalid = abs(UVW) < min_rcp_input;
  191. const vfloat<K> rcpUVW = select(invalid,vfloat<K>(0.0f),rcp(UVW));
  192. vfloat<K> u = min(U * rcpUVW,1.0f);
  193. vfloat<K> v = min(V * rcpUVW,1.0f);
  194. Vec3vf<K> vNg = Ng;
  195. mapUV(u,v,vNg);
  196. return std::make_tuple(u,v,t,vNg);
  197. }
  198. vfloat<K> U;
  199. vfloat<K> V;
  200. const vfloat<K> UVW;
  201. const vfloat<K> t;
  202. const Vec3vf<K> Ng;
  203. const UVMapper& mapUV;
  204. };
  205. template<int M, int K>
  206. struct PlueckerIntersectorK
  207. {
  208. __forceinline PlueckerIntersectorK() {}
  209. __forceinline PlueckerIntersectorK(const vbool<K>& valid, const RayK<K>& ray) {}
  210. /*! Intersects K rays with one of M triangles. */
  211. template<typename UVMapper>
  212. __forceinline vbool<K> intersectK(const vbool<K>& valid0,
  213. RayK<K>& ray,
  214. const Vec3vf<K>& tri_v0,
  215. const Vec3vf<K>& tri_v1,
  216. const Vec3vf<K>& tri_v2,
  217. const UVMapper& mapUV,
  218. PlueckerHitK<K,UVMapper> &hit) const
  219. {
  220. /* calculate vertices relative to ray origin */
  221. vbool<K> valid = valid0;
  222. const Vec3vf<K> O = ray.org;
  223. const Vec3vf<K> D = ray.dir;
  224. const Vec3vf<K> v0 = tri_v0-O;
  225. const Vec3vf<K> v1 = tri_v1-O;
  226. const Vec3vf<K> v2 = tri_v2-O;
  227. /* calculate triangle edges */
  228. const Vec3vf<K> e0 = v2-v0;
  229. const Vec3vf<K> e1 = v0-v1;
  230. const Vec3vf<K> e2 = v1-v2;
  231. /* perform edge tests */
  232. const vfloat<K> U = dot(Vec3vf<K>(cross(e0,v2+v0)),D);
  233. const vfloat<K> V = dot(Vec3vf<K>(cross(e1,v0+v1)),D);
  234. const vfloat<K> W = dot(Vec3vf<K>(cross(e2,v1+v2)),D);
  235. const vfloat<K> UVW = U+V+W;
  236. const vfloat<K> eps = float(ulp)*abs(UVW);
  237. #if defined(EMBREE_BACKFACE_CULLING)
  238. valid &= max(U,V,W) <= eps;
  239. #else
  240. valid &= (min(U,V,W) >= -eps) | (max(U,V,W) <= eps);
  241. #endif
  242. if (unlikely(none(valid))) return valid;
  243. /* calculate geometry normal and denominator */
  244. const Vec3vf<K> Ng = stable_triangle_normal(e0,e1,e2);
  245. const vfloat<K> den = twice(dot(Vec3vf<K>(Ng),D));
  246. /* perform depth test */
  247. const vfloat<K> T = twice(dot(v0,Vec3vf<K>(Ng)));
  248. const vfloat<K> t = rcp(den)*T;
  249. valid &= ray.tnear() <= t & t <= ray.tfar;
  250. valid &= den != vfloat<K>(zero);
  251. if (unlikely(none(valid))) return valid;
  252. /* calculate hit information */
  253. new (&hit) PlueckerHitK<K,UVMapper>(U,V,UVW,t,Ng,mapUV);
  254. return valid;
  255. }
  256. template<typename Epilog>
  257. __forceinline vbool<K> intersectK(const vbool<K>& valid0,
  258. RayK<K>& ray,
  259. const Vec3vf<K>& tri_v0,
  260. const Vec3vf<K>& tri_v1,
  261. const Vec3vf<K>& tri_v2,
  262. const Epilog& epilog) const
  263. {
  264. UVIdentity<K> mapUV;
  265. PlueckerHitK<K,UVIdentity<K>> hit(mapUV);
  266. const vbool<K> valid = intersectK(valid0,ray,tri_v0,tri_v1,tri_v2,mapUV,hit);
  267. return epilog(valid,hit);
  268. }
  269. template<typename UVMapper, typename Epilog>
  270. __forceinline vbool<K> intersectK(const vbool<K>& valid0,
  271. RayK<K>& ray,
  272. const Vec3vf<K>& tri_v0,
  273. const Vec3vf<K>& tri_v1,
  274. const Vec3vf<K>& tri_v2,
  275. const UVMapper& mapUV,
  276. const Epilog& epilog) const
  277. {
  278. PlueckerHitK<K,UVMapper> hit(mapUV);
  279. const vbool<K> valid = intersectK(valid0,ray,tri_v0,tri_v1,tri_v2,mapUV,hit);
  280. return epilog(valid,hit);
  281. }
  282. /*! Intersect k'th ray from ray packet of size K with M triangles. */
  283. template<typename UVMapper>
  284. __forceinline bool intersect(RayK<K>& ray, size_t k,
  285. const Vec3vf<M>& tri_v0,
  286. const Vec3vf<M>& tri_v1,
  287. const Vec3vf<M>& tri_v2,
  288. const UVMapper& mapUV,
  289. PlueckerHitM<M,UVMapper> &hit) const
  290. {
  291. /* calculate vertices relative to ray origin */
  292. const Vec3vf<M> O = broadcast<vfloat<M>>(ray.org,k);
  293. const Vec3vf<M> D = broadcast<vfloat<M>>(ray.dir,k);
  294. const Vec3vf<M> v0 = tri_v0-O;
  295. const Vec3vf<M> v1 = tri_v1-O;
  296. const Vec3vf<M> v2 = tri_v2-O;
  297. /* calculate triangle edges */
  298. const Vec3vf<M> e0 = v2-v0;
  299. const Vec3vf<M> e1 = v0-v1;
  300. const Vec3vf<M> e2 = v1-v2;
  301. /* perform edge tests */
  302. const vfloat<M> U = dot(cross(e0,v2+v0),D);
  303. const vfloat<M> V = dot(cross(e1,v0+v1),D);
  304. const vfloat<M> W = dot(cross(e2,v1+v2),D);
  305. const vfloat<M> UVW = U+V+W;
  306. const vfloat<M> eps = float(ulp)*abs(UVW);
  307. #if defined(EMBREE_BACKFACE_CULLING)
  308. vbool<M> valid = max(U,V,W) <= eps;
  309. #else
  310. vbool<M> valid = (min(U,V,W) >= -eps) | (max(U,V,W) <= eps);
  311. #endif
  312. if (unlikely(none(valid))) return false;
  313. /* calculate geometry normal and denominator */
  314. const Vec3vf<M> Ng = stable_triangle_normal(e0,e1,e2);
  315. const vfloat<M> den = twice(dot(Ng,D));
  316. /* perform depth test */
  317. const vfloat<M> T = twice(dot(v0,Ng));
  318. const vfloat<M> t = rcp(den)*T;
  319. valid &= vfloat<M>(ray.tnear()[k]) <= t & t <= vfloat<M>(ray.tfar[k]);
  320. if (unlikely(none(valid))) return false;
  321. /* avoid division by 0 */
  322. valid &= den != vfloat<M>(zero);
  323. if (unlikely(none(valid))) return false;
  324. /* update hit information */
  325. new (&hit) PlueckerHitM<M,UVMapper>(valid,U,V,UVW,t,Ng,mapUV);
  326. return true;
  327. }
  328. template<typename UVMapper, typename Epilog>
  329. __forceinline bool intersect(RayK<K>& ray, size_t k,
  330. const Vec3vf<M>& tri_v0,
  331. const Vec3vf<M>& tri_v1,
  332. const Vec3vf<M>& tri_v2,
  333. const UVMapper& mapUV,
  334. const Epilog& epilog) const
  335. {
  336. PlueckerHitM<M,UVMapper> hit(mapUV);
  337. if (intersect(ray,k,tri_v0,tri_v1,tri_v2,mapUV,hit))
  338. return epilog(hit.valid,hit);
  339. return false;
  340. }
  341. template<typename Epilog>
  342. __forceinline bool intersect(RayK<K>& ray, size_t k,
  343. const Vec3vf<M>& tri_v0,
  344. const Vec3vf<M>& tri_v1,
  345. const Vec3vf<M>& tri_v2,
  346. const Epilog& epilog) const
  347. {
  348. UVIdentity<M> mapUV;
  349. PlueckerHitM<M,UVIdentity<M>> hit(mapUV);
  350. if (intersect(ray,k,tri_v0,tri_v1,tri_v2,mapUV,hit))
  351. return epilog(hit.valid,hit);
  352. return false;
  353. }
  354. };
  355. }
  356. }