cylinder.h 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. // Copyright 2009-2021 Intel Corporation
  2. // SPDX-License-Identifier: Apache-2.0
  3. #pragma once
  4. #include "../common/ray.h"
  5. namespace embree
  6. {
  7. namespace isa
  8. {
  9. struct Cylinder
  10. {
  11. const Vec3fa p0; //!< start location
  12. const Vec3fa p1; //!< end position
  13. const float rr; //!< squared radius of cylinder
  14. __forceinline Cylinder(const Vec3fa& p0, const Vec3fa& p1, const float r)
  15. : p0(p0), p1(p1), rr(sqr(r)) {}
  16. __forceinline Cylinder(const Vec3fa& p0, const Vec3fa& p1, const float rr, bool)
  17. : p0(p0), p1(p1), rr(rr) {}
  18. __forceinline bool intersect(const Vec3fa& org,
  19. const Vec3fa& dir,
  20. BBox1f& t_o,
  21. float& u0_o, Vec3fa& Ng0_o,
  22. float& u1_o, Vec3fa& Ng1_o) const
  23. {
  24. /* calculate quadratic equation to solve */
  25. const float rl = rcp_length(p1-p0);
  26. const Vec3fa P0 = p0, dP = (p1-p0)*rl;
  27. const Vec3fa O = org-P0, dO = dir;
  28. const float dOdO = dot(dO,dO);
  29. const float OdO = dot(dO,O);
  30. const float OO = dot(O,O);
  31. const float dOz = dot(dP,dO);
  32. const float Oz = dot(dP,O);
  33. const float A = dOdO - sqr(dOz);
  34. const float B = 2.0f * (OdO - dOz*Oz);
  35. const float C = OO - sqr(Oz) - rr;
  36. /* we miss the cylinder if determinant is smaller than zero */
  37. const float D = B*B - 4.0f*A*C;
  38. if (D < 0.0f) {
  39. t_o = BBox1f(pos_inf,neg_inf);
  40. return false;
  41. }
  42. /* special case for rays that are parallel to the cylinder */
  43. const float eps = 16.0f*float(ulp)*max(abs(dOdO),abs(sqr(dOz)));
  44. if (abs(A) < eps)
  45. {
  46. if (C <= 0.0f) {
  47. t_o = BBox1f(neg_inf,pos_inf);
  48. return true;
  49. } else {
  50. t_o = BBox1f(pos_inf,neg_inf);
  51. return false;
  52. }
  53. }
  54. /* standard case for rays that are not parallel to the cylinder */
  55. const float Q = sqrt(D);
  56. const float rcp_2A = rcp(2.0f*A);
  57. const float t0 = (-B-Q)*rcp_2A;
  58. const float t1 = (-B+Q)*rcp_2A;
  59. /* calculates u and Ng for near hit */
  60. {
  61. u0_o = madd(t0,dOz,Oz)*rl;
  62. const Vec3fa Pr = t0*dir;
  63. const Vec3fa Pl = madd(u0_o,p1-p0,p0);
  64. Ng0_o = Pr-Pl;
  65. }
  66. /* calculates u and Ng for far hit */
  67. {
  68. u1_o = madd(t1,dOz,Oz)*rl;
  69. const Vec3fa Pr = t1*dir;
  70. const Vec3fa Pl = madd(u1_o,p1-p0,p0);
  71. Ng1_o = Pr-Pl;
  72. }
  73. t_o.lower = t0;
  74. t_o.upper = t1;
  75. return true;
  76. }
  77. __forceinline bool intersect(const Vec3fa& org_i, const Vec3fa& dir, BBox1f& t_o) const
  78. {
  79. float u0_o; Vec3fa Ng0_o;
  80. float u1_o; Vec3fa Ng1_o;
  81. return intersect(org_i,dir,t_o,u0_o,Ng0_o,u1_o,Ng1_o);
  82. }
  83. static bool verify(const size_t id, const Cylinder& cylinder, const RayHit& ray, bool shouldhit, const float t0, const float t1)
  84. {
  85. float eps = 0.001f;
  86. BBox1f t; bool hit;
  87. hit = cylinder.intersect(ray.org,ray.dir,t);
  88. bool failed = hit != shouldhit;
  89. if (shouldhit) failed |= std::isinf(t0) ? t0 != t.lower : abs(t0-t.lower) > eps;
  90. if (shouldhit) failed |= std::isinf(t1) ? t1 != t.upper : abs(t1-t.upper) > eps;
  91. if (!failed) return true;
  92. embree_cout << "Cylinder test " << id << " failed: cylinder = " << cylinder << ", ray = " << ray << ", hit = " << hit << ", t = " << t << embree_endl;
  93. return false;
  94. }
  95. /* verify cylinder class */
  96. static bool verify()
  97. {
  98. bool passed = true;
  99. const Cylinder cylinder(Vec3fa(0.0f,0.0f,0.0f),Vec3fa(1.0f,0.0f,0.0f),1.0f);
  100. passed &= verify(0,cylinder,RayHit(Vec3fa(-2.0f,1.0f,0.0f),Vec3fa( 0.0f,-1.0f,+0.0f),0.0f,float(inf)),true,0.0f,2.0f);
  101. passed &= verify(1,cylinder,RayHit(Vec3fa(+2.0f,1.0f,0.0f),Vec3fa( 0.0f,-1.0f,+0.0f),0.0f,float(inf)),true,0.0f,2.0f);
  102. passed &= verify(2,cylinder,RayHit(Vec3fa(+2.0f,1.0f,2.0f),Vec3fa( 0.0f,-1.0f,+0.0f),0.0f,float(inf)),false,0.0f,0.0f);
  103. passed &= verify(3,cylinder,RayHit(Vec3fa(+0.0f,0.0f,0.0f),Vec3fa( 1.0f, 0.0f,+0.0f),0.0f,float(inf)),true,neg_inf,pos_inf);
  104. passed &= verify(4,cylinder,RayHit(Vec3fa(+0.0f,0.0f,0.0f),Vec3fa(-1.0f, 0.0f,+0.0f),0.0f,float(inf)),true,neg_inf,pos_inf);
  105. passed &= verify(5,cylinder,RayHit(Vec3fa(+0.0f,2.0f,0.0f),Vec3fa( 1.0f, 0.0f,+0.0f),0.0f,float(inf)),false,pos_inf,neg_inf);
  106. passed &= verify(6,cylinder,RayHit(Vec3fa(+0.0f,2.0f,0.0f),Vec3fa(-1.0f, 0.0f,+0.0f),0.0f,float(inf)),false,pos_inf,neg_inf);
  107. return passed;
  108. }
  109. /*! output operator */
  110. friend __forceinline embree_ostream operator<<(embree_ostream cout, const Cylinder& c) {
  111. return cout << "Cylinder { p0 = " << c.p0 << ", p1 = " << c.p1 << ", r = " << sqrtf(c.rr) << "}";
  112. }
  113. };
  114. template<int N>
  115. struct CylinderN
  116. {
  117. const Vec3vf<N> p0; //!< start location
  118. const Vec3vf<N> p1; //!< end position
  119. const vfloat<N> rr; //!< squared radius of cylinder
  120. __forceinline CylinderN(const Vec3vf<N>& p0, const Vec3vf<N>& p1, const vfloat<N>& r)
  121. : p0(p0), p1(p1), rr(sqr(r)) {}
  122. __forceinline CylinderN(const Vec3vf<N>& p0, const Vec3vf<N>& p1, const vfloat<N>& rr, bool)
  123. : p0(p0), p1(p1), rr(rr) {}
  124. __forceinline vbool<N> intersect(const Vec3fa& org, const Vec3fa& dir,
  125. BBox<vfloat<N>>& t_o,
  126. vfloat<N>& u0_o, Vec3vf<N>& Ng0_o,
  127. vfloat<N>& u1_o, Vec3vf<N>& Ng1_o) const
  128. {
  129. /* calculate quadratic equation to solve */
  130. const vfloat<N> rl = rcp_length(p1-p0);
  131. const Vec3vf<N> P0 = p0, dP = (p1-p0)*rl;
  132. const Vec3vf<N> O = Vec3vf<N>(org)-P0, dO = dir;
  133. const vfloat<N> dOdO = dot(dO,dO);
  134. const vfloat<N> OdO = dot(dO,O);
  135. const vfloat<N> OO = dot(O,O);
  136. const vfloat<N> dOz = dot(dP,dO);
  137. const vfloat<N> Oz = dot(dP,O);
  138. const vfloat<N> A = dOdO - sqr(dOz);
  139. const vfloat<N> B = 2.0f * (OdO - dOz*Oz);
  140. const vfloat<N> C = OO - sqr(Oz) - rr;
  141. /* we miss the cylinder if determinant is smaller than zero */
  142. const vfloat<N> D = B*B - 4.0f*A*C;
  143. vbool<N> valid = D >= 0.0f;
  144. if (none(valid)) {
  145. t_o = BBox<vfloat<N>>(empty);
  146. return valid;
  147. }
  148. /* standard case for rays that are not parallel to the cylinder */
  149. const vfloat<N> Q = sqrt(D);
  150. const vfloat<N> rcp_2A = rcp(2.0f*A);
  151. const vfloat<N> t0 = (-B-Q)*rcp_2A;
  152. const vfloat<N> t1 = (-B+Q)*rcp_2A;
  153. /* calculates u and Ng for near hit */
  154. {
  155. u0_o = madd(t0,dOz,Oz)*rl;
  156. const Vec3vf<N> Pr = t0*Vec3vf<N>(dir);
  157. const Vec3vf<N> Pl = madd(u0_o,p1-p0,p0);
  158. Ng0_o = Pr-Pl;
  159. }
  160. /* calculates u and Ng for far hit */
  161. {
  162. u1_o = madd(t1,dOz,Oz)*rl;
  163. const Vec3vf<N> Pr = t1*Vec3vf<N>(dir);
  164. const Vec3vf<N> Pl = madd(u1_o,p1-p0,p0);
  165. Ng1_o = Pr-Pl;
  166. }
  167. t_o.lower = select(valid, t0, vfloat<N>(pos_inf));
  168. t_o.upper = select(valid, t1, vfloat<N>(neg_inf));
  169. /* special case for rays that are parallel to the cylinder */
  170. const vfloat<N> eps = 16.0f*float(ulp)*max(abs(dOdO),abs(sqr(dOz)));
  171. vbool<N> validt = valid & (abs(A) < eps);
  172. if (unlikely(any(validt)))
  173. {
  174. vbool<N> inside = C <= 0.0f;
  175. t_o.lower = select(validt,select(inside,vfloat<N>(neg_inf),vfloat<N>(pos_inf)),t_o.lower);
  176. t_o.upper = select(validt,select(inside,vfloat<N>(pos_inf),vfloat<N>(neg_inf)),t_o.upper);
  177. valid &= !validt | inside;
  178. }
  179. return valid;
  180. }
  181. __forceinline vbool<N> intersect(const Vec3fa& org_i, const Vec3fa& dir, BBox<vfloat<N>>& t_o) const
  182. {
  183. vfloat<N> u0_o; Vec3vf<N> Ng0_o;
  184. vfloat<N> u1_o; Vec3vf<N> Ng1_o;
  185. return intersect(org_i,dir,t_o,u0_o,Ng0_o,u1_o,Ng1_o);
  186. }
  187. };
  188. }
  189. }