curve_intersector_ribbon.h 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. // Copyright 2009-2021 Intel Corporation
  2. // SPDX-License-Identifier: Apache-2.0
  3. #pragma once
  4. #include "../common/ray.h"
  5. #include "quad_intersector.h"
  6. #include "curve_intersector_precalculations.h"
  7. #define Bezier1Intersector1 RibbonCurve1Intersector1
  8. #define Bezier1IntersectorK RibbonCurve1IntersectorK
  9. namespace embree
  10. {
  11. namespace isa
  12. {
  13. template<typename NativeCurve3ff, int M>
  14. struct RibbonHit
  15. {
  16. __forceinline RibbonHit() {}
  17. __forceinline RibbonHit(const vbool<M>& valid, const vfloat<M>& U, const vfloat<M>& V, const vfloat<M>& T, const int i, const int N,
  18. const NativeCurve3ff& curve3D)
  19. : U(U), V(V), T(T), i(i), N(N), curve3D(curve3D), valid(valid) {}
  20. __forceinline void finalize()
  21. {
  22. vu = (vfloat<M>(step)+U+vfloat<M>(float(i)))*(1.0f/float(N));
  23. vv = V;
  24. vt = T;
  25. }
  26. __forceinline Vec2f uv (const size_t i) const { return Vec2f(vu[i],vv[i]); }
  27. __forceinline float t (const size_t i) const { return vt[i]; }
  28. __forceinline Vec3fa Ng(const size_t i) const { return curve3D.eval_du(vu[i]); }
  29. __forceinline Vec2vf<M> uv() const { return Vec2vf<M>(vu,vv); }
  30. __forceinline vfloat<M> t () const { return vt; }
  31. __forceinline Vec3vf<M> Ng() const { return (Vec3vf<M>) curve3D.template veval_du<M>(vu); }
  32. public:
  33. vfloat<M> U;
  34. vfloat<M> V;
  35. vfloat<M> T;
  36. int i, N;
  37. NativeCurve3ff curve3D;
  38. public:
  39. vbool<M> valid;
  40. vfloat<M> vu;
  41. vfloat<M> vv;
  42. vfloat<M> vt;
  43. };
  44. /* calculate squared distance of point p0 to line p1->p2 */
  45. template<int M>
  46. __forceinline std::pair<vfloat<M>,vfloat<M>> sqr_point_line_distance(const Vec2vf<M>& p0, const Vec2vf<M>& p1, const Vec2vf<M>& p2)
  47. {
  48. const vfloat<M> num = det(p2-p1,p1-p0);
  49. const vfloat<M> den2 = dot(p2-p1,p2-p1);
  50. return std::make_pair(num*num,den2);
  51. }
  52. /* performs culling against a cylinder */
  53. template<int M>
  54. __forceinline vbool<M> cylinder_culling_test(const Vec2vf<M>& p0, const Vec2vf<M>& p1, const Vec2vf<M>& p2, const vfloat<M>& r)
  55. {
  56. const std::pair<vfloat<M>,vfloat<M>> d = sqr_point_line_distance<M>(p0,p1,p2);
  57. return d.first <= r*r*d.second;
  58. }
  59. template<int M = VSIZEX, typename NativeCurve3ff, typename Epilog>
  60. __forceinline bool intersect_ribbon(const Vec3fa& ray_org, const Vec3fa& ray_dir, const float ray_tnear, const float& ray_tfar,
  61. const LinearSpace3fa& ray_space, const float& depth_scale,
  62. const NativeCurve3ff& curve3D, const int N,
  63. const Epilog& epilog)
  64. {
  65. /* transform control points into ray space */
  66. const NativeCurve3ff curve2D = curve3D.xfm_pr(ray_space,ray_org);
  67. float eps = 4.0f*float(ulp)*reduce_max(max(abs(curve2D.v0),abs(curve2D.v1),abs(curve2D.v2),abs(curve2D.v3)));
  68. int i=0;
  69. bool ishit = false;
  70. #if !defined(__SYCL_DEVICE_ONLY__)
  71. {
  72. /* evaluate the bezier curve */
  73. vbool<M> valid = vfloat<M>(step) < vfloat<M>(float(N));
  74. const Vec4vf<M> p0 = curve2D.template eval0<M>(0,N);
  75. const Vec4vf<M> p1 = curve2D.template eval1<M>(0,N);
  76. valid &= cylinder_culling_test<M>(zero,Vec2vf<M>(p0.x,p0.y),Vec2vf<M>(p1.x,p1.y),max(p0.w,p1.w));
  77. if (any(valid))
  78. {
  79. Vec3vf<M> dp0dt = curve2D.template derivative0<M>(0,N);
  80. Vec3vf<M> dp1dt = curve2D.template derivative1<M>(0,N);
  81. dp0dt = select(reduce_max(abs(dp0dt)) < vfloat<M>(eps),Vec3vf<M>(p1-p0),dp0dt);
  82. dp1dt = select(reduce_max(abs(dp1dt)) < vfloat<M>(eps),Vec3vf<M>(p1-p0),dp1dt);
  83. const Vec3vf<M> n0(dp0dt.y,-dp0dt.x,0.0f);
  84. const Vec3vf<M> n1(dp1dt.y,-dp1dt.x,0.0f);
  85. const Vec3vf<M> nn0 = normalize(n0);
  86. const Vec3vf<M> nn1 = normalize(n1);
  87. const Vec3vf<M> lp0 = madd(p0.w,nn0,Vec3vf<M>(p0));
  88. const Vec3vf<M> lp1 = madd(p1.w,nn1,Vec3vf<M>(p1));
  89. const Vec3vf<M> up0 = nmadd(p0.w,nn0,Vec3vf<M>(p0));
  90. const Vec3vf<M> up1 = nmadd(p1.w,nn1,Vec3vf<M>(p1));
  91. vfloat<M> vu,vv,vt;
  92. vbool<M> valid0 = intersect_quad_backface_culling<M>(valid,zero,Vec3fa(0,0,1),ray_tnear,ray_tfar,lp0,lp1,up1,up0,vu,vv,vt);
  93. if (any(valid0))
  94. {
  95. /* ignore self intersections */
  96. if (EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR != 0.0f) {
  97. vfloat<M> r = lerp(p0.w, p1.w, vu);
  98. valid0 &= vt > float(EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR)*r*depth_scale;
  99. }
  100. if (any(valid0))
  101. {
  102. vv = madd(2.0f,vv,vfloat<M>(-1.0f));
  103. RibbonHit<NativeCurve3ff,M> bhit(valid0,vu,vv,vt,0,N,curve3D);
  104. ishit |= epilog(bhit.valid,bhit);
  105. }
  106. }
  107. }
  108. i += M;
  109. }
  110. if (unlikely(i < N))
  111. #endif
  112. {
  113. /* process SIMD-size many segments per iteration */
  114. for (; i<N; i+=M)
  115. {
  116. /* evaluate the bezier curve */
  117. vbool<M> valid = vint<M>(i)+vint<M>(step) < vint<M>(N);
  118. const Vec4vf<M> p0 = curve2D.template eval0<M>(i,N);
  119. const Vec4vf<M> p1 = curve2D.template eval1<M>(i,N);
  120. valid &= cylinder_culling_test<M>(zero,Vec2vf<M>(p0.x,p0.y),Vec2vf<M>(p1.x,p1.y),max(p0.w,p1.w));
  121. if (none(valid)) continue;
  122. Vec3vf<M> dp0dt = curve2D.template derivative0<M>(i,N);
  123. Vec3vf<M> dp1dt = curve2D.template derivative1<M>(i,N);
  124. dp0dt = select(reduce_max(abs(dp0dt)) < vfloat<M>(eps),Vec3vf<M>(p1-p0),dp0dt);
  125. dp1dt = select(reduce_max(abs(dp1dt)) < vfloat<M>(eps),Vec3vf<M>(p1-p0),dp1dt);
  126. const Vec3vf<M> n0(dp0dt.y,-dp0dt.x,0.0f);
  127. const Vec3vf<M> n1(dp1dt.y,-dp1dt.x,0.0f);
  128. const Vec3vf<M> nn0 = normalize(n0);
  129. const Vec3vf<M> nn1 = normalize(n1);
  130. const Vec3vf<M> lp0 = madd(p0.w,nn0,Vec3vf<M>(p0));
  131. const Vec3vf<M> lp1 = madd(p1.w,nn1,Vec3vf<M>(p1));
  132. const Vec3vf<M> up0 = nmadd(p0.w,nn0,Vec3vf<M>(p0));
  133. const Vec3vf<M> up1 = nmadd(p1.w,nn1,Vec3vf<M>(p1));
  134. vfloat<M> vu,vv,vt;
  135. vbool<M> valid0 = intersect_quad_backface_culling<M>(valid,zero,Vec3fa(0,0,1),ray_tnear,ray_tfar,lp0,lp1,up1,up0,vu,vv,vt);
  136. if (any(valid0))
  137. {
  138. /* ignore self intersections */
  139. if (EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR != 0.0f) {
  140. vfloat<M> r = lerp(p0.w, p1.w, vu);
  141. valid0 &= vt > float(EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR)*r*depth_scale;
  142. }
  143. if (any(valid0))
  144. {
  145. vv = madd(2.0f,vv,vfloat<M>(-1.0f));
  146. RibbonHit<NativeCurve3ff,M> bhit(valid0,vu,vv,vt,i,N,curve3D);
  147. ishit |= epilog(bhit.valid,bhit);
  148. }
  149. }
  150. }
  151. }
  152. return ishit;
  153. }
  154. template<template<typename Ty> class NativeCurve, int M = VSIZEX>
  155. struct RibbonCurve1Intersector1
  156. {
  157. typedef NativeCurve<Vec3ff> NativeCurve3ff;
  158. template<typename Ray, typename Epilog>
  159. __forceinline bool intersect(const CurvePrecalculations1& pre, Ray& ray,
  160. RayQueryContext* context,
  161. const CurveGeometry* geom, const unsigned int primID,
  162. const Vec3ff& v0, const Vec3ff& v1, const Vec3ff& v2, const Vec3ff& v3,
  163. const Epilog& epilog)
  164. {
  165. const int N = geom->tessellationRate;
  166. NativeCurve3ff curve(v0,v1,v2,v3);
  167. curve = enlargeRadiusToMinWidth(context,geom,ray.org,curve);
  168. return intersect_ribbon<M,NativeCurve3ff>(ray.org,ray.dir,ray.tnear(),ray.tfar,
  169. pre.ray_space,pre.depth_scale,
  170. curve,N,
  171. epilog);
  172. }
  173. };
  174. template<template<typename Ty> class NativeCurve, int K, int M = VSIZEX>
  175. struct RibbonCurve1IntersectorK
  176. {
  177. typedef NativeCurve<Vec3ff> NativeCurve3ff;
  178. template<typename Epilog>
  179. __forceinline bool intersect(const CurvePrecalculationsK<K>& pre, RayK<K>& ray, size_t k,
  180. RayQueryContext* context,
  181. const CurveGeometry* geom, const unsigned int primID,
  182. const Vec3ff& v0, const Vec3ff& v1, const Vec3ff& v2, const Vec3ff& v3,
  183. const Epilog& epilog)
  184. {
  185. const int N = geom->tessellationRate;
  186. const Vec3fa ray_org(ray.org.x[k],ray.org.y[k],ray.org.z[k]);
  187. const Vec3fa ray_dir(ray.dir.x[k],ray.dir.y[k],ray.dir.z[k]);
  188. NativeCurve3ff curve(v0,v1,v2,v3);
  189. curve = enlargeRadiusToMinWidth(context,geom,ray_org,curve);
  190. return intersect_ribbon<M,NativeCurve3ff>(ray_org,ray_dir,ray.tnear()[k],ray.tfar[k],
  191. pre.ray_space[k],pre.depth_scale[k],
  192. curve,N,
  193. epilog);
  194. }
  195. };
  196. }
  197. }