triangle_intersector_moeller.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  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 "triangle.h"
  18. #include "intersector_epilog.h"
  19. /*! This intersector implements a modified version of the Moeller
  20. * Trumbore intersector from the paper "Fast, Minimum Storage
  21. * Ray-Triangle Intersection". In contrast to the paper we
  22. * precalculate some factors and factor the calculations differently
  23. * to allow precalculating the cross product e1 x e2. The resulting
  24. * algorithm is similar to the fastest one of the paper "Optimizing
  25. * Ray-Triangle Intersection via Automated Search". */
  26. namespace embree
  27. {
  28. namespace isa
  29. {
  30. template<int M>
  31. struct MoellerTrumboreHitM
  32. {
  33. __forceinline MoellerTrumboreHitM() {}
  34. __forceinline MoellerTrumboreHitM(const vbool<M>& valid, const vfloat<M>& U, const vfloat<M>& V, const vfloat<M>& T, const vfloat<M>& absDen, const Vec3<vfloat<M>>& Ng)
  35. : U(U), V(V), T(T), absDen(absDen), valid(valid), vNg(Ng) {}
  36. __forceinline void finalize()
  37. {
  38. const vfloat<M> rcpAbsDen = rcp(absDen);
  39. vt = T * rcpAbsDen;
  40. vu = U * rcpAbsDen;
  41. vv = V * rcpAbsDen;
  42. }
  43. __forceinline Vec2f uv (const size_t i) const { return Vec2f(vu[i],vv[i]); }
  44. __forceinline float t (const size_t i) const { return vt[i]; }
  45. __forceinline Vec3fa Ng(const size_t i) const { return Vec3fa(vNg.x[i],vNg.y[i],vNg.z[i]); }
  46. public:
  47. vfloat<M> U;
  48. vfloat<M> V;
  49. vfloat<M> T;
  50. vfloat<M> absDen;
  51. public:
  52. vbool<M> valid;
  53. vfloat<M> vu;
  54. vfloat<M> vv;
  55. vfloat<M> vt;
  56. Vec3<vfloat<M>> vNg;
  57. };
  58. template<int M>
  59. struct MoellerTrumboreIntersector1
  60. {
  61. __forceinline MoellerTrumboreIntersector1() {}
  62. __forceinline MoellerTrumboreIntersector1(const Ray& ray, const void* ptr) {}
  63. __forceinline bool intersect(const vbool<M>& valid0,
  64. Ray& ray,
  65. const Vec3<vfloat<M>>& tri_v0,
  66. const Vec3<vfloat<M>>& tri_e1,
  67. const Vec3<vfloat<M>>& tri_e2,
  68. const Vec3<vfloat<M>>& tri_Ng,
  69. MoellerTrumboreHitM<M>& hit) const
  70. {
  71. /* calculate denominator */
  72. vbool<M> valid = valid0;
  73. typedef Vec3<vfloat<M>> Vec3vfM;
  74. const Vec3vfM O = Vec3vfM(ray.org);
  75. const Vec3vfM D = Vec3vfM(ray.dir);
  76. const Vec3vfM C = Vec3vfM(tri_v0) - O;
  77. const Vec3vfM R = cross(D,C);
  78. const vfloat<M> den = dot(Vec3vfM(tri_Ng),D);
  79. const vfloat<M> absDen = abs(den);
  80. const vfloat<M> sgnDen = signmsk(den);
  81. /* perform edge tests */
  82. const vfloat<M> U = dot(R,Vec3vfM(tri_e2)) ^ sgnDen;
  83. const vfloat<M> V = dot(R,Vec3vfM(tri_e1)) ^ sgnDen;
  84. /* perform backface culling */
  85. #if defined(EMBREE_BACKFACE_CULLING)
  86. valid &= (den < vfloat<M>(zero)) & (U >= 0.0f) & (V >= 0.0f) & (U+V<=absDen);
  87. #else
  88. valid &= (den != vfloat<M>(zero)) & (U >= 0.0f) & (V >= 0.0f) & (U+V<=absDen);
  89. #endif
  90. if (likely(none(valid))) return false;
  91. /* perform depth test */
  92. const vfloat<M> T = dot(Vec3vfM(tri_Ng),C) ^ sgnDen;
  93. valid &= (T > absDen*vfloat<M>(ray.tnear)) & (T < absDen*vfloat<M>(ray.tfar));
  94. if (likely(none(valid))) return false;
  95. /* update hit information */
  96. new (&hit) MoellerTrumboreHitM<M>(valid,U,V,T,absDen,tri_Ng);
  97. return true;
  98. }
  99. __forceinline bool intersect(Ray& ray,
  100. const Vec3<vfloat<M>>& tri_v0,
  101. const Vec3<vfloat<M>>& tri_e1,
  102. const Vec3<vfloat<M>>& tri_e2,
  103. const Vec3<vfloat<M>>& tri_Ng,
  104. MoellerTrumboreHitM<M>& hit) const
  105. {
  106. vbool<M> valid = true;
  107. return intersect(valid,ray,tri_v0,tri_e1,tri_e2,tri_Ng,hit);
  108. }
  109. __forceinline bool intersect(Ray& ray,
  110. const Vec3<vfloat<M>>& v0,
  111. const Vec3<vfloat<M>>& v1,
  112. const Vec3<vfloat<M>>& v2,
  113. MoellerTrumboreHitM<M>& hit) const
  114. {
  115. const Vec3<vfloat<M>> e1 = v0-v1;
  116. const Vec3<vfloat<M>> e2 = v2-v0;
  117. const Vec3<vfloat<M>> Ng = cross(e1,e2);
  118. return intersect(ray,v0,e1,e2,Ng,hit);
  119. }
  120. __forceinline bool intersect(const vbool<M>& valid,
  121. Ray& ray,
  122. const Vec3<vfloat<M>>& v0,
  123. const Vec3<vfloat<M>>& v1,
  124. const Vec3<vfloat<M>>& v2,
  125. MoellerTrumboreHitM<M>& hit) const
  126. {
  127. const Vec3<vfloat<M>> e1 = v0-v1;
  128. const Vec3<vfloat<M>> e2 = v2-v0;
  129. const Vec3<vfloat<M>> Ng = cross(e1,e2);
  130. return intersect(valid,ray,v0,e1,e2,Ng,hit);
  131. }
  132. template<typename Epilog>
  133. __forceinline bool intersect(Ray& ray,
  134. const Vec3<vfloat<M>>& v0,
  135. const Vec3<vfloat<M>>& e1,
  136. const Vec3<vfloat<M>>& e2,
  137. const Vec3<vfloat<M>>& Ng,
  138. const Epilog& epilog) const
  139. {
  140. MoellerTrumboreHitM<M> hit;
  141. if (likely(intersect(ray,v0,e1,e2,Ng,hit))) return epilog(hit.valid,hit);
  142. return false;
  143. }
  144. template<typename Epilog>
  145. __forceinline bool intersect(Ray& ray,
  146. const Vec3<vfloat<M>>& v0,
  147. const Vec3<vfloat<M>>& v1,
  148. const Vec3<vfloat<M>>& v2,
  149. const Epilog& epilog) const
  150. {
  151. MoellerTrumboreHitM<M> hit;
  152. if (likely(intersect(ray,v0,v1,v2,hit))) return epilog(hit.valid,hit);
  153. return false;
  154. }
  155. template<typename Epilog>
  156. __forceinline bool intersect(const vbool<M>& valid,
  157. Ray& ray,
  158. const Vec3<vfloat<M>>& v0,
  159. const Vec3<vfloat<M>>& v1,
  160. const Vec3<vfloat<M>>& v2,
  161. const Epilog& epilog) const
  162. {
  163. MoellerTrumboreHitM<M> hit;
  164. if (likely(intersect(valid,ray,v0,v1,v2,hit))) return epilog(hit.valid,hit);
  165. return false;
  166. }
  167. // ==== new interface for ray streams ====
  168. __forceinline bool intersectN(const Vec3<vfloat<M>>& ray_org,
  169. const Vec3<vfloat<M>>& ray_dir,
  170. const vfloat<M>& ray_tnear,
  171. const vfloat<M>& ray_tfar,
  172. const Vec3<vfloat<M>>& tri_v0,
  173. const Vec3<vfloat<M>>& tri_e1,
  174. const Vec3<vfloat<M>>& tri_e2,
  175. const Vec3<vfloat<M>>& tri_Ng,
  176. MoellerTrumboreHitM<M>& hit) const
  177. {
  178. /* calculate denominator */
  179. typedef Vec3<vfloat<M>> Vec3vfM;
  180. const Vec3vfM &O = ray_org;
  181. const Vec3vfM &D = ray_dir;
  182. const Vec3vfM C = Vec3vfM(tri_v0) - O;
  183. const Vec3vfM R = cross(D,C);
  184. const vfloat<M> den = dot(Vec3vfM(tri_Ng),D);
  185. const vfloat<M> absDen = abs(den);
  186. const vfloat<M> sgnDen = signmsk(den);
  187. /* perform edge tests */
  188. const vfloat<M> U = dot(R,Vec3vfM(tri_e2)) ^ sgnDen;
  189. const vfloat<M> V = dot(R,Vec3vfM(tri_e1)) ^ sgnDen;
  190. /* perform backface culling */
  191. #if defined(EMBREE_BACKFACE_CULLING)
  192. vbool<M> valid = (den < vfloat<M>(zero)) & (U >= 0.0f) & (V >= 0.0f) & (U+V<=absDen);
  193. #else
  194. vbool<M> valid = (den != vfloat<M>(zero)) & (U >= 0.0f) & (V >= 0.0f) & (U+V<=absDen);
  195. #endif
  196. if (likely(none(valid))) return false;
  197. /* perform depth test */
  198. const vfloat<M> T = dot(Vec3vfM(tri_Ng),C) ^ sgnDen;
  199. valid &= (T > absDen*ray_tnear) & (T < absDen*ray_tfar);
  200. if (likely(none(valid))) return false;
  201. /* update hit information */
  202. new (&hit) MoellerTrumboreHitM<M>(valid,U,V,T,absDen,tri_Ng);
  203. return true;
  204. }
  205. template<typename Epilog>
  206. __forceinline bool intersectN(const Vec3<vfloat<M>>& ray_org,
  207. const Vec3<vfloat<M>>& ray_dir,
  208. const vfloat<M>& ray_tnear,
  209. const vfloat<M>& ray_tfar,
  210. const Vec3<vfloat<M>>& v0,
  211. const Vec3<vfloat<M>>& e1,
  212. const Vec3<vfloat<M>>& e2,
  213. const Vec3<vfloat<M>>& Ng,
  214. const Epilog& epilog) const
  215. {
  216. MoellerTrumboreHitM<M> hit;
  217. if (likely(intersectN(ray_org,ray_dir,ray_tnear,ray_tfar,v0,e1,e2,Ng,hit))) return epilog(hit.valid,hit);
  218. return false;
  219. }
  220. };
  221. template<int K>
  222. struct MoellerTrumboreHitK
  223. {
  224. __forceinline MoellerTrumboreHitK(const vfloat<K>& U, const vfloat<K>& V, const vfloat<K>& T, const vfloat<K>& absDen, const Vec3<vfloat<K>>& Ng)
  225. : U(U), V(V), T(T), absDen(absDen), Ng(Ng) {}
  226. __forceinline std::tuple<vfloat<K>,vfloat<K>,vfloat<K>,Vec3<vfloat<K>>> operator() () const
  227. {
  228. const vfloat<K> rcpAbsDen = rcp(absDen);
  229. const vfloat<K> t = T * rcpAbsDen;
  230. const vfloat<K> u = U * rcpAbsDen;
  231. const vfloat<K> v = V * rcpAbsDen;
  232. return std::make_tuple(u,v,t,Ng);
  233. }
  234. private:
  235. const vfloat<K> U;
  236. const vfloat<K> V;
  237. const vfloat<K> T;
  238. const vfloat<K> absDen;
  239. const Vec3<vfloat<K>> Ng;
  240. };
  241. template<int M, int K>
  242. struct MoellerTrumboreIntersectorK
  243. {
  244. __forceinline MoellerTrumboreIntersectorK(const vbool<K>& valid, const RayK<K>& ray) {}
  245. /*! Intersects K rays with one of M triangles. */
  246. template<typename Epilog>
  247. __forceinline vbool<K> intersectK(const vbool<K>& valid0,
  248. //RayK<K>& ray,
  249. const Vec3<vfloat<K>>& ray_org,
  250. const Vec3<vfloat<K>>& ray_dir,
  251. const vfloat<K>& ray_tnear,
  252. const vfloat<K>& ray_tfar,
  253. const Vec3<vfloat<K>>& tri_v0,
  254. const Vec3<vfloat<K>>& tri_e1,
  255. const Vec3<vfloat<K>>& tri_e2,
  256. const Vec3<vfloat<K>>& tri_Ng,
  257. const Epilog& epilog) const
  258. {
  259. /* ray SIMD type shortcuts */
  260. typedef Vec3<vfloat<K>> Vec3vfK;
  261. /* calculate denominator */
  262. vbool<K> valid = valid0;
  263. const Vec3vfK C = tri_v0 - ray_org;
  264. const Vec3vfK R = cross(ray_dir,C);
  265. const vfloat<K> den = dot(tri_Ng,ray_dir);
  266. const vfloat<K> absDen = abs(den);
  267. const vfloat<K> sgnDen = signmsk(den);
  268. /* test against edge p2 p0 */
  269. const vfloat<K> U = dot(R,tri_e2) ^ sgnDen;
  270. valid &= U >= 0.0f;
  271. if (likely(none(valid))) return false;
  272. /* test against edge p0 p1 */
  273. const vfloat<K> V = dot(R,tri_e1) ^ sgnDen;
  274. valid &= V >= 0.0f;
  275. if (likely(none(valid))) return false;
  276. /* test against edge p1 p2 */
  277. const vfloat<K> W = absDen-U-V;
  278. valid &= W >= 0.0f;
  279. if (likely(none(valid))) return false;
  280. /* perform depth test */
  281. const vfloat<K> T = dot(tri_Ng,C) ^ sgnDen;
  282. valid &= (T >= absDen*ray_tnear) & (absDen*ray_tfar >= T);
  283. if (unlikely(none(valid))) return false;
  284. /* perform backface culling */
  285. #if defined(EMBREE_BACKFACE_CULLING)
  286. valid &= den < vfloat<K>(zero);
  287. if (unlikely(none(valid))) return false;
  288. #else
  289. valid &= den != vfloat<K>(zero);
  290. if (unlikely(none(valid))) return false;
  291. #endif
  292. /* calculate hit information */
  293. MoellerTrumboreHitK<K> hit(U,V,T,absDen,tri_Ng);
  294. return epilog(valid,hit);
  295. }
  296. /*! Intersects K rays with one of M triangles. */
  297. template<typename Epilog>
  298. __forceinline vbool<K> intersectK(const vbool<K>& valid0,
  299. RayK<K>& ray,
  300. const Vec3<vfloat<K>>& tri_v0,
  301. const Vec3<vfloat<K>>& tri_v1,
  302. const Vec3<vfloat<K>>& tri_v2,
  303. const Epilog& epilog) const
  304. {
  305. typedef Vec3<vfloat<K>> Vec3vfK;
  306. const Vec3vfK e1 = tri_v0-tri_v1;
  307. const Vec3vfK e2 = tri_v2-tri_v0;
  308. const Vec3vfK Ng = cross(e1,e2);
  309. return intersectK(valid0,ray.org,ray.dir,ray.tnear,ray.tfar,tri_v0,e1,e2,Ng,epilog);
  310. }
  311. /*! Intersects K rays with one of M triangles. */
  312. template<typename Epilog>
  313. __forceinline vbool<K> intersectK(const vbool<K>& valid0,
  314. RayK<K>& ray,
  315. const Vec3<vfloat<K>>& tri_v0,
  316. const Vec3<vfloat<K>>& tri_e1,
  317. const Vec3<vfloat<K>>& tri_e2,
  318. const Vec3<vfloat<K>>& tri_Ng,
  319. const Epilog& epilog) const
  320. {
  321. return intersectK(valid0,ray.org,ray.dir,ray.tnear,ray.tfar,tri_v0,tri_e1,tri_e2,tri_Ng,epilog);
  322. }
  323. /*! Intersect k'th ray from ray packet of size K with M triangles. */
  324. template<typename Epilog>
  325. __forceinline bool intersect(RayK<K>& ray,
  326. size_t k,
  327. const Vec3<vfloat<M>>& tri_v0,
  328. const Vec3<vfloat<M>>& tri_e1,
  329. const Vec3<vfloat<M>>& tri_e2,
  330. const Vec3<vfloat<M>>& tri_Ng,
  331. const Epilog& epilog) const
  332. {
  333. /* calculate denominator */
  334. typedef Vec3<vfloat<M>> Vec3vfM;
  335. const Vec3vfM O = broadcast<vfloat<M>>(ray.org,k);
  336. const Vec3vfM D = broadcast<vfloat<M>>(ray.dir,k);
  337. const Vec3vfM C = Vec3vfM(tri_v0) - O;
  338. const Vec3vfM R = cross(D,C);
  339. const vfloat<M> den = dot(Vec3vfM(tri_Ng),D);
  340. const vfloat<M> absDen = abs(den);
  341. const vfloat<M> sgnDen = signmsk(den);
  342. /* perform edge tests */
  343. const vfloat<M> U = dot(R,Vec3vfM(tri_e2)) ^ sgnDen;
  344. const vfloat<M> V = dot(R,Vec3vfM(tri_e1)) ^ sgnDen;
  345. /* perform backface culling */
  346. #if defined(EMBREE_BACKFACE_CULLING)
  347. vbool<M> valid = (den < vfloat<M>(zero)) & (U >= 0.0f) & (V >= 0.0f) & (U+V<=absDen);
  348. #else
  349. vbool<M> valid = (den != vfloat<M>(zero)) & (U >= 0.0f) & (V >= 0.0f) & (U+V<=absDen);
  350. #endif
  351. if (likely(none(valid))) return false;
  352. /* perform depth test */
  353. const vfloat<M> T = dot(Vec3vfM(tri_Ng),C) ^ sgnDen;
  354. valid &= (T > absDen*vfloat<M>(ray.tnear[k])) & (T < absDen*vfloat<M>(ray.tfar[k]));
  355. if (likely(none(valid))) return false;
  356. /* calculate hit information */
  357. MoellerTrumboreHitM<M> hit(valid,U,V,T,absDen,tri_Ng);
  358. return epilog(valid,hit);
  359. }
  360. template<typename Epilog>
  361. __forceinline bool intersect(RayK<K>& ray,
  362. size_t k,
  363. const Vec3<vfloat<M>>& v0,
  364. const Vec3<vfloat<M>>& v1,
  365. const Vec3<vfloat<M>>& v2,
  366. const Epilog& epilog) const
  367. {
  368. const Vec3<vfloat<M>> e1 = v0-v1;
  369. const Vec3<vfloat<M>> e2 = v2-v0;
  370. const Vec3<vfloat<M>> Ng = cross(e1,e2);
  371. return intersect(ray,k,v0,e1,e2,Ng,epilog);
  372. }
  373. };
  374. }
  375. }