bspline_curve.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  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 "../common/default.h"
  18. #include "bezier_curve.h"
  19. namespace embree
  20. {
  21. class BSplineBasis2 // FIXME: make compatible with basis from bspline_patch.h
  22. {
  23. public:
  24. template<typename T>
  25. static __forceinline Vec4<T> eval(const T& u)
  26. {
  27. const T t = u;
  28. const T s = T(1.0f) - u;
  29. const T n0 = s*s*s;
  30. const T n1 = (4.0f*(s*s*s)+(t*t*t)) + (12.0f*((s*t)*s) + 6.0f*((t*s)*t));
  31. const T n2 = (4.0f*(t*t*t)+(s*s*s)) + (12.0f*((t*s)*t) + 6.0f*((s*t)*s));
  32. const T n3 = t*t*t;
  33. return T(1.0f/6.0f)*Vec4<T>(n0,n1,n2,n3);
  34. }
  35. template<typename T>
  36. static __forceinline Vec4<T> derivative(const T& u)
  37. {
  38. const T t = u;
  39. const T s = 1.0f - u;
  40. const T n0 = -s*s;
  41. const T n1 = -t*t - 4.0f*(t*s);
  42. const T n2 = s*s + 4.0f*(s*t);
  43. const T n3 = t*t;
  44. return T(0.5f)*Vec4<T>(n0,n1,n2,n3);
  45. }
  46. template<typename T>
  47. static __forceinline Vec4<T> derivative2(const T& u)
  48. {
  49. const T t = u;
  50. const T s = 1.0f - u;
  51. const T n0 = s;
  52. const T n1 = t - 2.0f*s;
  53. const T n2 = s - 2.0f*t;
  54. const T n3 = t;
  55. return Vec4<T>(n0,n1,n2,n3);
  56. }
  57. };
  58. struct PrecomputedBSplineBasis
  59. {
  60. enum { N = 16 };
  61. public:
  62. PrecomputedBSplineBasis() {}
  63. PrecomputedBSplineBasis(int shift);
  64. template<typename T>
  65. __forceinline Vec4<T> eval(const int u, const int size)
  66. {
  67. assert(size <= N);
  68. assert(u <= size);
  69. return Vec4<T>(T::loadu(&c0[size][u]),
  70. T::loadu(&c1[size][u]),
  71. T::loadu(&c2[size][u]),
  72. T::loadu(&c3[size][u]));
  73. }
  74. template<typename T>
  75. __forceinline Vec4<T> derivative(const int u, const int size)
  76. {
  77. assert(size <= N);
  78. assert(u <= size);
  79. return Vec4<T>(T::loadu(&d0[size][u]),
  80. T::loadu(&d1[size][u]),
  81. T::loadu(&d2[size][u]),
  82. T::loadu(&d3[size][u]));
  83. }
  84. /* basis for bspline evaluation */
  85. public:
  86. float c0[N+1][N+1];
  87. float c1[N+1][N+1];
  88. float c2[N+1][N+1];
  89. float c3[N+1][N+1];
  90. /* basis for bspline derivative evaluation */
  91. public:
  92. float d0[N+1][N+1];
  93. float d1[N+1][N+1];
  94. float d2[N+1][N+1];
  95. float d3[N+1][N+1];
  96. };
  97. extern PrecomputedBSplineBasis bspline_basis0;
  98. extern PrecomputedBSplineBasis bspline_basis1;
  99. template<typename Vertex>
  100. struct BSplineCurveT
  101. {
  102. Vertex v0,v1,v2,v3;
  103. __forceinline BSplineCurveT() {}
  104. __forceinline BSplineCurveT(const Vertex& v0, const Vertex& v1, const Vertex& v2, const Vertex& v3)
  105. : v0(v0), v1(v1), v2(v2), v3(v3) {}
  106. __forceinline Vertex begin() const {
  107. return madd(1.0f/6.0f,v0,madd(2.0f/3.0f,v1,1.0f/6.0f*v2));
  108. }
  109. __forceinline Vertex end() const {
  110. return madd(1.0f/6.0f,v1,madd(2.0f/3.0f,v2,1.0f/6.0f*v3));
  111. }
  112. __forceinline Vertex eval(const float t) const
  113. {
  114. const Vec4<float> b = BSplineBasis2::eval(t);
  115. return madd(b.x,v0,madd(b.y,v1,madd(b.z,v2,b.w*v3)));
  116. }
  117. __forceinline Vertex eval_du(const float t) const
  118. {
  119. const Vec4<float> b = BSplineBasis2::derivative(t);
  120. return madd(b.x,v0,madd(b.y,v1,madd(b.z,v2,b.w*v3)));
  121. }
  122. __forceinline Vertex eval_dudu(const float t) const
  123. {
  124. const Vec4<float> b = BSplineBasis2::derivative2(t);
  125. return madd(b.x,v0,madd(b.y,v1,madd(b.z,v2,b.w*v3)));
  126. }
  127. __forceinline void eval(const float t, Vertex& p, Vertex& dp, Vertex& ddp) const
  128. {
  129. p = eval(t);
  130. dp = eval_du(t);
  131. ddp = eval_dudu(t);
  132. }
  133. friend inline std::ostream& operator<<(std::ostream& cout, const BSplineCurveT& curve) {
  134. return cout << "BSplineCurve { v0 = " << curve.v0 << ", v1 = " << curve.v1 << ", v2 = " << curve.v2 << ", v3 = " << curve.v3 << " }";
  135. }
  136. };
  137. template<typename Vertex>
  138. __forceinline void convert(const BezierCurveT<Vertex>& icurve, BezierCurveT<Vertex>& ocurve) {
  139. ocurve = icurve;
  140. }
  141. template<typename Vertex>
  142. __forceinline void convert(const BSplineCurveT<Vertex>& icurve, BSplineCurveT<Vertex>& ocurve) {
  143. ocurve = icurve;
  144. }
  145. template<typename Vertex>
  146. __forceinline void convert(const BezierCurveT<Vertex>& icurve, BSplineCurveT<Vertex>& ocurve)
  147. {
  148. const Vertex v0 = madd(6.0f,icurve.v0,madd(-7.0f,icurve.v1,2.0f*icurve.v2));
  149. const Vertex v1 = msub(2.0f,icurve.v1,icurve.v2);
  150. const Vertex v2 = msub(2.0f,icurve.v2,icurve.v1);
  151. const Vertex v3 = madd(2.0f,icurve.v1,madd(-7.0f,icurve.v2,6.0f*icurve.v3));
  152. ocurve = BSplineCurveT<Vertex>(v0,v1,v2,v3);
  153. }
  154. template<typename Vertex>
  155. __forceinline void convert(const BSplineCurveT<Vertex>& icurve, BezierCurveT<Vertex>& ocurve)
  156. {
  157. const Vertex v0 = madd(1.0f/6.0f,icurve.v0,madd(2.0f/3.0f,icurve.v1,1.0f/6.0f*icurve.v2));
  158. const Vertex v1 = madd(2.0f/3.0f,icurve.v1,1.0f/3.0f*icurve.v2);
  159. const Vertex v2 = madd(1.0f/3.0f,icurve.v1,2.0f/3.0f*icurve.v2);
  160. const Vertex v3 = madd(1.0f/6.0f,icurve.v1,madd(2.0f/3.0f,icurve.v2,1.0f/6.0f*icurve.v3));
  161. ocurve = BezierCurveT<Vertex>(v0,v1,v2,v3);
  162. }
  163. struct BSplineCurve3fa : public BSplineCurveT<Vec3fa>
  164. {
  165. //using BSplineCurveT<Vec3fa>::BSplineCurveT; // FIXME: not supported by VS2010
  166. __forceinline BSplineCurve3fa() {}
  167. __forceinline BSplineCurve3fa(const Vec3fa& v0, const Vec3fa& v1, const Vec3fa& v2, const Vec3fa& v3)
  168. : BSplineCurveT<Vec3fa>(v0,v1,v2,v3) {}
  169. __forceinline Vec4vfx eval_(const vfloatx& t) const
  170. {
  171. const Vec4vfx b = BSplineBasis2::eval(t);
  172. return madd(b.x, Vec4vfx(v0), madd(b.y, Vec4vfx(v1), madd(b.z, Vec4vfx(v2), b.w * Vec4vfx(v3))));
  173. }
  174. __forceinline Vec4vfx derivative(const vfloatx& t) const
  175. {
  176. const Vec4vfx b = BSplineBasis2::derivative(t);
  177. return madd(b.x, Vec4vfx(v0), madd(b.y, Vec4vfx(v1), madd(b.z, Vec4vfx(v2), b.w * Vec4vfx(v3))));
  178. }
  179. __forceinline void evalN(const vfloatx& t, Vec4vfx& p, Vec4vfx& dp) const
  180. {
  181. p = eval_(t);
  182. dp = derivative(t);
  183. }
  184. #if 0
  185. template<int M>
  186. __forceinline Vec4<vfloat<M>> eval0(const int ofs, const int size) const
  187. {
  188. const Vec4<vfloat<M>> b = bspline_basis0.eval<vfloat<M>>(ofs,size);
  189. return madd(b.x, Vec4<vfloat<M>>(v0), madd(b.y, Vec4<vfloat<M>>(v1), madd(b.z, Vec4<vfloat<M>>(v2), b.w * Vec4<vfloat<M>>(v3))));
  190. }
  191. template<int M>
  192. __forceinline Vec4<vfloat<M>> eval1(const int ofs, const int size) const
  193. {
  194. const Vec4<vfloat<M>> b = bspline_basis1.eval<vfloat<M>>(ofs,size);
  195. return madd(b.x, Vec4<vfloat<M>>(v0), madd(b.y, Vec4<vfloat<M>>(v1), madd(b.z, Vec4<vfloat<M>>(v2), b.w * Vec4<vfloat<M>>(v3))));
  196. }
  197. template<int M>
  198. __forceinline Vec4<vfloat<M>> derivative0(const int ofs, const int size) const
  199. {
  200. const Vec4<vfloat<M>> b = bspline_basis0.derivative<vfloat<M>>(ofs,size);
  201. return madd(b.x, Vec4<vfloat<M>>(v0), madd(b.y, Vec4<vfloat<M>>(v1), madd(b.z, Vec4<vfloat<M>>(v2), b.w * Vec4<vfloat<M>>(v3))));
  202. }
  203. template<int M>
  204. __forceinline Vec4<vfloat<M>> derivative1(const int ofs, const int size) const
  205. {
  206. const Vec4<vfloat<M>> b = bspline_basis1.derivative<vfloat<M>>(ofs,size);
  207. return madd(b.x, Vec4<vfloat<M>>(v0), madd(b.y, Vec4<vfloat<M>>(v1), madd(b.z, Vec4<vfloat<M>>(v2), b.w * Vec4<vfloat<M>>(v3))));
  208. }
  209. #else
  210. template<int M>
  211. __forceinline Vec4<vfloat<M>> eval0(const int ofs, const int size) const
  212. {
  213. assert(size <= PrecomputedBSplineBasis::N);
  214. assert(ofs <= size);
  215. return madd(vfloat<M>::loadu(&bspline_basis0.c0[size][ofs]), Vec4<vfloat<M>>(v0),
  216. madd(vfloat<M>::loadu(&bspline_basis0.c1[size][ofs]), Vec4<vfloat<M>>(v1),
  217. madd(vfloat<M>::loadu(&bspline_basis0.c2[size][ofs]), Vec4<vfloat<M>>(v2),
  218. vfloat<M>::loadu(&bspline_basis0.c3[size][ofs]) * Vec4<vfloat<M>>(v3))));
  219. }
  220. template<int M>
  221. __forceinline Vec4<vfloat<M>> eval1(const int ofs, const int size) const
  222. {
  223. assert(size <= PrecomputedBSplineBasis::N);
  224. assert(ofs <= size);
  225. return madd(vfloat<M>::loadu(&bspline_basis1.c0[size][ofs]), Vec4<vfloat<M>>(v0),
  226. madd(vfloat<M>::loadu(&bspline_basis1.c1[size][ofs]), Vec4<vfloat<M>>(v1),
  227. madd(vfloat<M>::loadu(&bspline_basis1.c2[size][ofs]), Vec4<vfloat<M>>(v2),
  228. vfloat<M>::loadu(&bspline_basis1.c3[size][ofs]) * Vec4<vfloat<M>>(v3))));
  229. }
  230. template<int M>
  231. __forceinline Vec4<vfloat<M>> derivative0(const int ofs, const int size) const
  232. {
  233. assert(size <= PrecomputedBSplineBasis::N);
  234. assert(ofs <= size);
  235. return madd(vfloat<M>::loadu(&bspline_basis0.d0[size][ofs]), Vec4<vfloat<M>>(v0),
  236. madd(vfloat<M>::loadu(&bspline_basis0.d1[size][ofs]), Vec4<vfloat<M>>(v1),
  237. madd(vfloat<M>::loadu(&bspline_basis0.d2[size][ofs]), Vec4<vfloat<M>>(v2),
  238. vfloat<M>::loadu(&bspline_basis0.d3[size][ofs]) * Vec4<vfloat<M>>(v3))));
  239. }
  240. template<int M>
  241. __forceinline Vec4<vfloat<M>> derivative1(const int ofs, const int size) const
  242. {
  243. assert(size <= PrecomputedBSplineBasis::N);
  244. assert(ofs <= size);
  245. return madd(vfloat<M>::loadu(&bspline_basis1.d0[size][ofs]), Vec4<vfloat<M>>(v0),
  246. madd(vfloat<M>::loadu(&bspline_basis1.d1[size][ofs]), Vec4<vfloat<M>>(v1),
  247. madd(vfloat<M>::loadu(&bspline_basis1.d2[size][ofs]), Vec4<vfloat<M>>(v2),
  248. vfloat<M>::loadu(&bspline_basis1.d3[size][ofs]) * Vec4<vfloat<M>>(v3))));
  249. }
  250. #endif
  251. /* calculates bounds of bspline curve geometry */
  252. __forceinline BBox3fa accurateBounds() const
  253. {
  254. const int N = 7;
  255. const float scale = 1.0f/(3.0f*(N-1));
  256. Vec4vfx pl(pos_inf), pu(neg_inf);
  257. for (int i=0; i<=N; i+=VSIZEX)
  258. {
  259. vintx vi = vintx(i)+vintx(step);
  260. vboolx valid = vi <= vintx(N);
  261. const Vec4vfx p = eval0<VSIZEX>(i,N);
  262. const Vec4vfx dp = derivative0<VSIZEX>(i,N);
  263. const Vec4vfx pm = p-Vec4vfx(scale)*select(vi!=vintx(0),dp,Vec4vfx(zero));
  264. const Vec4vfx pp = p+Vec4vfx(scale)*select(vi!=vintx(N),dp,Vec4vfx(zero));
  265. pl = select(valid,min(pl,p,pm,pp),pl); // FIXME: use masked min
  266. pu = select(valid,max(pu,p,pm,pp),pu); // FIXME: use masked min
  267. }
  268. const Vec3fa lower(reduce_min(pl.x),reduce_min(pl.y),reduce_min(pl.z));
  269. const Vec3fa upper(reduce_max(pu.x),reduce_max(pu.y),reduce_max(pu.z));
  270. const Vec3fa upper_r = Vec3fa(reduce_max(max(abs(pl.w),abs(pu.w))));
  271. return enlarge(BBox3fa(lower,upper),upper_r);
  272. }
  273. /* calculates bounds when tessellated into N line segments */
  274. __forceinline BBox3fa tessellatedBounds(int N) const
  275. {
  276. if (likely(N == 4))
  277. {
  278. const Vec4vf4 pi = eval0<4>(0,4);
  279. const Vec3fa lower(reduce_min(pi.x),reduce_min(pi.y),reduce_min(pi.z));
  280. const Vec3fa upper(reduce_max(pi.x),reduce_max(pi.y),reduce_max(pi.z));
  281. const Vec3fa upper_r = Vec3fa(reduce_max(abs(pi.w)));
  282. const Vec3fa pe = end();
  283. return enlarge(BBox3fa(min(lower,pe),max(upper,pe)),max(upper_r,Vec3fa(abs(pe.w))));
  284. }
  285. else
  286. {
  287. Vec3vfx pl(pos_inf), pu(neg_inf); vfloatx ru(0.0f);
  288. for (int i=0; i<=N; i+=VSIZEX)
  289. {
  290. vboolx valid = vintx(i)+vintx(step) <= vintx(N);
  291. const Vec4vfx pi = eval0<VSIZEX>(i,N);
  292. pl.x = select(valid,min(pl.x,pi.x),pl.x); // FIXME: use masked min
  293. pl.y = select(valid,min(pl.y,pi.y),pl.y);
  294. pl.z = select(valid,min(pl.z,pi.z),pl.z);
  295. pu.x = select(valid,max(pu.x,pi.x),pu.x); // FIXME: use masked min
  296. pu.y = select(valid,max(pu.y,pi.y),pu.y);
  297. pu.z = select(valid,max(pu.z,pi.z),pu.z);
  298. ru = select(valid,max(ru,abs(pi.w)),ru);
  299. }
  300. const Vec3fa lower(reduce_min(pl.x),reduce_min(pl.y),reduce_min(pl.z));
  301. const Vec3fa upper(reduce_max(pu.x),reduce_max(pu.y),reduce_max(pu.z));
  302. const Vec3fa upper_r(reduce_max(ru));
  303. return enlarge(BBox3fa(lower,upper),upper_r);
  304. }
  305. }
  306. };
  307. #if defined(EMBREE_NATIVE_CURVE_BSPLINE)
  308. #define CurveT BSplineCurveT
  309. typedef BSplineCurve3fa Curve3fa;
  310. #endif
  311. }