linear_bezier_patch.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. // Copyright 2009-2021 Intel Corporation
  2. // SPDX-License-Identifier: Apache-2.0
  3. #pragma once
  4. #include "bezier_curve.h"
  5. namespace embree
  6. {
  7. namespace isa
  8. {
  9. template<typename V>
  10. struct TensorLinearQuadraticBezierSurface
  11. {
  12. QuadraticBezierCurve<V> L;
  13. QuadraticBezierCurve<V> R;
  14. __forceinline TensorLinearQuadraticBezierSurface() {}
  15. __forceinline TensorLinearQuadraticBezierSurface(const TensorLinearQuadraticBezierSurface<V>& curve)
  16. : L(curve.L), R(curve.R) {}
  17. __forceinline TensorLinearQuadraticBezierSurface& operator= (const TensorLinearQuadraticBezierSurface& other) {
  18. L = other.L; R = other.R; return *this;
  19. }
  20. __forceinline TensorLinearQuadraticBezierSurface(const QuadraticBezierCurve<V>& L, const QuadraticBezierCurve<V>& R)
  21. : L(L), R(R) {}
  22. __forceinline BBox<V> bounds() const {
  23. return merge(L.bounds(),R.bounds());
  24. }
  25. };
  26. #if !defined(__SYCL_DEVICE_ONLY__)
  27. template<>
  28. struct TensorLinearQuadraticBezierSurface<Vec2fa>
  29. {
  30. QuadraticBezierCurve<vfloat4> LR;
  31. __forceinline TensorLinearQuadraticBezierSurface() {}
  32. __forceinline TensorLinearQuadraticBezierSurface(const TensorLinearQuadraticBezierSurface<Vec2fa>& curve)
  33. : LR(curve.LR) {}
  34. __forceinline TensorLinearQuadraticBezierSurface& operator= (const TensorLinearQuadraticBezierSurface& other) {
  35. LR = other.LR; return *this;
  36. }
  37. __forceinline TensorLinearQuadraticBezierSurface(const QuadraticBezierCurve<vfloat4>& LR)
  38. : LR(LR) {}
  39. __forceinline BBox<Vec2fa> bounds() const
  40. {
  41. const BBox<vfloat4> b = LR.bounds();
  42. const BBox<Vec2fa> bl(Vec2fa(b.lower),Vec2fa(b.upper));
  43. const BBox<Vec2fa> br(Vec2fa(shuffle<2,3,2,3>(b.lower)),Vec2fa(shuffle<2,3,2,3>(b.upper)));
  44. return merge(bl,br);
  45. }
  46. };
  47. #endif
  48. template<typename V>
  49. struct TensorLinearCubicBezierSurface
  50. {
  51. CubicBezierCurve<V> L;
  52. CubicBezierCurve<V> R;
  53. __forceinline TensorLinearCubicBezierSurface() {}
  54. __forceinline TensorLinearCubicBezierSurface(const TensorLinearCubicBezierSurface& curve)
  55. : L(curve.L), R(curve.R) {}
  56. __forceinline TensorLinearCubicBezierSurface& operator= (const TensorLinearCubicBezierSurface& other) {
  57. L = other.L; R = other.R; return *this;
  58. }
  59. __forceinline TensorLinearCubicBezierSurface(const CubicBezierCurve<V>& L, const CubicBezierCurve<V>& R)
  60. : L(L), R(R) {}
  61. template<template<typename T> class SourceCurve>
  62. __forceinline static TensorLinearCubicBezierSurface fromCenterAndNormalCurve(const SourceCurve<Vec3ff>& center, const SourceCurve<Vec3fa>& normal)
  63. {
  64. SourceCurve<Vec3ff> vcurve = center;
  65. SourceCurve<Vec3fa> ncurve = normal;
  66. /* here we construct a patch which follows the curve l(t) =
  67. * p(t) +/- r(t)*normalize(cross(n(t),dp(t))) */
  68. const Vec3ff p0 = vcurve.eval(0.0f);
  69. const Vec3ff dp0 = vcurve.eval_du(0.0f);
  70. //const Vec3ff ddp0 = vcurve.eval_dudu(0.0f); // ddp0 is assumed to be 0
  71. const Vec3fa n0 = ncurve.eval(0.0f);
  72. const Vec3fa dn0 = ncurve.eval_du(0.0f);
  73. const Vec3ff p1 = vcurve.eval(1.0f);
  74. const Vec3ff dp1 = vcurve.eval_du(1.0f);
  75. //const Vec3ff ddp1 = vcurve.eval_dudu(1.0f); // ddp1 is assumed to be 0
  76. const Vec3fa n1 = ncurve.eval(1.0f);
  77. const Vec3fa dn1 = ncurve.eval_du(1.0f);
  78. const Vec3fa bt0 = cross(n0,dp0);
  79. const Vec3fa dbt0 = cross(dn0,dp0);// + cross(n0,ddp0);
  80. const Vec3fa bt1 = cross(n1,dp1);
  81. const Vec3fa dbt1 = cross(dn1,dp1);// + cross(n1,ddp1);
  82. const Vec3fa k0 = normalize(bt0);
  83. const Vec3fa dk0 = dnormalize(bt0,dbt0);
  84. const Vec3fa k1 = normalize(bt1);
  85. const Vec3fa dk1 = dnormalize(bt1,dbt1);
  86. const Vec3fa l0 = p0 - p0.w*k0;
  87. const Vec3fa dl0 = dp0 - (dp0.w*k0 + p0.w*dk0);
  88. const Vec3fa r0 = p0 + p0.w*k0;
  89. const Vec3fa dr0 = dp0 + (dp0.w*k0 + p0.w*dk0);
  90. const Vec3fa l1 = p1 - p1.w*k1;
  91. const Vec3fa dl1 = dp1 - (dp1.w*k1 + p1.w*dk1);
  92. const Vec3fa r1 = p1 + p1.w*k1;
  93. const Vec3fa dr1 = dp1 + (dp1.w*k1 + p1.w*dk1);
  94. const float scale = 1.0f/3.0f;
  95. CubicBezierCurve<V> L(l0,l0+scale*dl0,l1-scale*dl1,l1);
  96. CubicBezierCurve<V> R(r0,r0+scale*dr0,r1-scale*dr1,r1);
  97. return TensorLinearCubicBezierSurface(L,R);
  98. }
  99. __forceinline BBox<V> bounds() const {
  100. return merge(L.bounds(),R.bounds());
  101. }
  102. __forceinline BBox3fa accurateBounds() const {
  103. return merge(L.accurateBounds(),R.accurateBounds());
  104. }
  105. __forceinline CubicBezierCurve<Interval1f> reduce_v() const {
  106. return merge(CubicBezierCurve<Interval<V>>(L),CubicBezierCurve<Interval<V>>(R));
  107. }
  108. __forceinline LinearBezierCurve<Interval1f> reduce_u() const {
  109. return LinearBezierCurve<Interval1f>(L.bounds(),R.bounds());
  110. }
  111. __forceinline TensorLinearCubicBezierSurface<float> xfm(const V& dx) const {
  112. return TensorLinearCubicBezierSurface<float>(L.xfm(dx),R.xfm(dx));
  113. }
  114. template<int W>
  115. __forceinline TensorLinearCubicBezierSurface<vfloat<W>> vxfm(const V& dx) const {
  116. return TensorLinearCubicBezierSurface<vfloat<W>>(L.template vxfm<W>(dx),R.template vxfm<W>(dx));
  117. }
  118. __forceinline TensorLinearCubicBezierSurface<float> xfm(const V& dx, const V& p) const {
  119. return TensorLinearCubicBezierSurface<float>(L.xfm(dx,p),R.xfm(dx,p));
  120. }
  121. __forceinline TensorLinearCubicBezierSurface<Vec3fa> xfm(const LinearSpace3fa& space) const {
  122. return TensorLinearCubicBezierSurface(L.xfm(space),R.xfm(space));
  123. }
  124. __forceinline TensorLinearCubicBezierSurface<Vec3fa> xfm(const LinearSpace3fa& space, const Vec3fa& p) const {
  125. return TensorLinearCubicBezierSurface(L.xfm(space,p),R.xfm(space,p));
  126. }
  127. __forceinline TensorLinearCubicBezierSurface<Vec3fa> xfm(const LinearSpace3fa& space, const Vec3fa& p, const float s) const {
  128. return TensorLinearCubicBezierSurface(L.xfm(space,p,s),R.xfm(space,p,s));
  129. }
  130. __forceinline TensorLinearCubicBezierSurface clip_u(const Interval1f& u) const {
  131. return TensorLinearCubicBezierSurface(L.clip(u),R.clip(u));
  132. }
  133. __forceinline TensorLinearCubicBezierSurface clip_v(const Interval1f& v) const {
  134. return TensorLinearCubicBezierSurface(clerp(L,R,V(v.lower)),clerp(L,R,V(v.upper)));
  135. }
  136. __forceinline TensorLinearCubicBezierSurface clip(const Interval1f& u, const Interval1f& v) const {
  137. return clip_v(v).clip_u(u);
  138. }
  139. __forceinline void split_u(TensorLinearCubicBezierSurface& left, TensorLinearCubicBezierSurface& right, const float u = 0.5f) const
  140. {
  141. CubicBezierCurve<V> L0,L1; L.split(L0,L1,u);
  142. CubicBezierCurve<V> R0,R1; R.split(R0,R1,u);
  143. new (&left ) TensorLinearCubicBezierSurface(L0,R0);
  144. new (&right) TensorLinearCubicBezierSurface(L1,R1);
  145. }
  146. __forceinline TensorLinearCubicBezierSurface<Vec2vfx> vsplit_u(vboolx& valid, const BBox1f& u) const {
  147. valid = true; clear(valid,VSIZEX-1);
  148. return TensorLinearCubicBezierSurface<Vec2vfx>(L.split(u),R.split(u));
  149. }
  150. template<int W>
  151. __forceinline TensorLinearCubicBezierSurface<Vec2vf<W>> vsplit_u(vbool<W>& valid, const BBox1f& u, int& i, int N) const
  152. {
  153. valid = true; clear(valid,W-1);
  154. auto r = TensorLinearCubicBezierSurface<Vec2vf<W>>(L.template split<W>(u,i,N),R.template split<W>(u,i,N));
  155. i += W-1;
  156. return r;
  157. }
  158. __forceinline V eval(const float u, const float v) const {
  159. return clerp(L,R,V(v)).eval(u);
  160. }
  161. __forceinline V eval_du(const float u, const float v) const {
  162. return clerp(L,R,V(v)).eval_dt(u);
  163. }
  164. __forceinline V eval_dv(const float u, const float v) const {
  165. return (R-L).eval(u);
  166. }
  167. __forceinline void eval(const float u, const float v, V& p, V& dpdu, V& dpdv) const
  168. {
  169. V p0, dp0du; L.eval(u,p0,dp0du);
  170. V p1, dp1du; R.eval(u,p1,dp1du);
  171. p = lerp(p0,p1,v);
  172. dpdu = lerp(dp0du,dp1du,v);
  173. dpdv = p1-p0;
  174. }
  175. __forceinline TensorLinearQuadraticBezierSurface<V> derivative_u() const {
  176. return TensorLinearQuadraticBezierSurface<V>(L.derivative(),R.derivative());
  177. }
  178. __forceinline CubicBezierCurve<V> derivative_v() const {
  179. return R-L;
  180. }
  181. __forceinline V axis_u() const {
  182. return (L.end()-L.begin())+(R.end()-R.begin());
  183. }
  184. __forceinline V axis_v() const {
  185. return (R.begin()-L.begin())+(R.end()-L.end());
  186. }
  187. friend embree_ostream operator<<(embree_ostream cout, const TensorLinearCubicBezierSurface& a)
  188. {
  189. return cout << "TensorLinearCubicBezierSurface" << embree_endl
  190. << "{" << embree_endl
  191. << " L = " << a.L << ", " << embree_endl
  192. << " R = " << a.R << embree_endl
  193. << "}";
  194. }
  195. friend __forceinline TensorLinearCubicBezierSurface clerp(const TensorLinearCubicBezierSurface& a, const TensorLinearCubicBezierSurface& b, const float t) {
  196. return TensorLinearCubicBezierSurface(clerp(a.L,b.L,V(t)), clerp(a.R,b.R,V(t)));
  197. }
  198. };
  199. #if !defined(__SYCL_DEVICE_ONLY__)
  200. template<>
  201. struct TensorLinearCubicBezierSurface<Vec2fa>
  202. {
  203. CubicBezierCurve<vfloat4> LR;
  204. __forceinline TensorLinearCubicBezierSurface() {}
  205. __forceinline TensorLinearCubicBezierSurface(const TensorLinearCubicBezierSurface& curve)
  206. : LR(curve.LR) {}
  207. __forceinline TensorLinearCubicBezierSurface& operator= (const TensorLinearCubicBezierSurface& other) {
  208. LR = other.LR; return *this;
  209. }
  210. __forceinline TensorLinearCubicBezierSurface(const CubicBezierCurve<vfloat4>& LR)
  211. : LR(LR) {}
  212. __forceinline TensorLinearCubicBezierSurface(const CubicBezierCurve<Vec2fa>& L, const CubicBezierCurve<Vec2fa>& R)
  213. : LR(shuffle<0,1,0,1>(vfloat4(L.v0),vfloat4(R.v0)),shuffle<0,1,0,1>(vfloat4(L.v1),vfloat4(R.v1)),shuffle<0,1,0,1>(vfloat4(L.v2),vfloat4(R.v2)),shuffle<0,1,0,1>(vfloat4(L.v3),vfloat4(R.v3))) {}
  214. __forceinline CubicBezierCurve<Vec2fa> getL() const {
  215. return CubicBezierCurve<Vec2fa>(Vec2fa(LR.v0),Vec2fa(LR.v1),Vec2fa(LR.v2),Vec2fa(LR.v3));
  216. }
  217. __forceinline CubicBezierCurve<Vec2fa> getR() const {
  218. return CubicBezierCurve<Vec2fa>(Vec2fa(shuffle<2,3,2,3>(LR.v0)),Vec2fa(shuffle<2,3,2,3>(LR.v1)),Vec2fa(shuffle<2,3,2,3>(LR.v2)),Vec2fa(shuffle<2,3,2,3>(LR.v3)));
  219. }
  220. __forceinline BBox<Vec2fa> bounds() const
  221. {
  222. const BBox<vfloat4> b = LR.bounds();
  223. const BBox<Vec2fa> bl(Vec2fa(b.lower),Vec2fa(b.upper));
  224. const BBox<Vec2fa> br(Vec2fa(shuffle<2,3,2,3>(b.lower)),Vec2fa(shuffle<2,3,2,3>(b.upper)));
  225. return merge(bl,br);
  226. }
  227. __forceinline BBox1f bounds(const Vec2fa& axis) const
  228. {
  229. const CubicBezierCurve<vfloat4> LRx = LR;
  230. const CubicBezierCurve<vfloat4> LRy(shuffle<1,0,3,2>(LR.v0),shuffle<1,0,3,2>(LR.v1),shuffle<1,0,3,2>(LR.v2),shuffle<1,0,3,2>(LR.v3));
  231. const CubicBezierCurve<vfloat4> LRa = cmadd(shuffle<0>(vfloat4(axis)),LRx,shuffle<1>(vfloat4(axis))*LRy);
  232. const BBox<vfloat4> Lb = LRa.bounds();
  233. const BBox<vfloat4> Rb(shuffle<3>(Lb.lower),shuffle<3>(Lb.upper));
  234. const BBox<vfloat4> b = merge(Lb,Rb);
  235. return BBox1f(b.lower[0],b.upper[0]);
  236. }
  237. __forceinline TensorLinearCubicBezierSurface<float> xfm(const Vec2fa& dx) const
  238. {
  239. const CubicBezierCurve<vfloat4> LRx = LR;
  240. const CubicBezierCurve<vfloat4> LRy(shuffle<1,0,3,2>(LR.v0),shuffle<1,0,3,2>(LR.v1),shuffle<1,0,3,2>(LR.v2),shuffle<1,0,3,2>(LR.v3));
  241. const CubicBezierCurve<vfloat4> LRa = cmadd(shuffle<0>(vfloat4(dx)),LRx,shuffle<1>(vfloat4(dx))*LRy);
  242. return TensorLinearCubicBezierSurface<float>(CubicBezierCurve<float>(LRa.v0[0],LRa.v1[0],LRa.v2[0],LRa.v3[0]),
  243. CubicBezierCurve<float>(LRa.v0[2],LRa.v1[2],LRa.v2[2],LRa.v3[2]));
  244. }
  245. __forceinline TensorLinearCubicBezierSurface<float> xfm(const Vec2fa& dx, const Vec2fa& p) const
  246. {
  247. const vfloat4 pxyxy = shuffle<0,1,0,1>(vfloat4(p));
  248. const CubicBezierCurve<vfloat4> LRx = LR-pxyxy;
  249. const CubicBezierCurve<vfloat4> LRy(shuffle<1,0,3,2>(LR.v0),shuffle<1,0,3,2>(LR.v1),shuffle<1,0,3,2>(LR.v2),shuffle<1,0,3,2>(LR.v3));
  250. const CubicBezierCurve<vfloat4> LRa = cmadd(shuffle<0>(vfloat4(dx)),LRx,shuffle<1>(vfloat4(dx))*LRy);
  251. return TensorLinearCubicBezierSurface<float>(CubicBezierCurve<float>(LRa.v0[0],LRa.v1[0],LRa.v2[0],LRa.v3[0]),
  252. CubicBezierCurve<float>(LRa.v0[2],LRa.v1[2],LRa.v2[2],LRa.v3[2]));
  253. }
  254. __forceinline TensorLinearCubicBezierSurface clip_u(const Interval1f& u) const {
  255. return TensorLinearCubicBezierSurface(LR.clip(u));
  256. }
  257. __forceinline TensorLinearCubicBezierSurface clip_v(const Interval1f& v) const
  258. {
  259. const CubicBezierCurve<vfloat4> LL(shuffle<0,1,0,1>(LR.v0),shuffle<0,1,0,1>(LR.v1),shuffle<0,1,0,1>(LR.v2),shuffle<0,1,0,1>(LR.v3));
  260. const CubicBezierCurve<vfloat4> RR(shuffle<2,3,2,3>(LR.v0),shuffle<2,3,2,3>(LR.v1),shuffle<2,3,2,3>(LR.v2),shuffle<2,3,2,3>(LR.v3));
  261. return TensorLinearCubicBezierSurface(clerp(LL,RR,vfloat4(v.lower,v.lower,v.upper,v.upper)));
  262. }
  263. __forceinline TensorLinearCubicBezierSurface clip(const Interval1f& u, const Interval1f& v) const {
  264. return clip_v(v).clip_u(u);
  265. }
  266. __forceinline void split_u(TensorLinearCubicBezierSurface& left, TensorLinearCubicBezierSurface& right, const float u = 0.5f) const
  267. {
  268. CubicBezierCurve<vfloat4> LR0,LR1; LR.split(LR0,LR1,u);
  269. new (&left ) TensorLinearCubicBezierSurface(LR0);
  270. new (&right) TensorLinearCubicBezierSurface(LR1);
  271. }
  272. __forceinline TensorLinearCubicBezierSurface<Vec2vfx> vsplit_u(vboolx& valid, const BBox1f& u) const {
  273. valid = true; clear(valid,VSIZEX-1);
  274. return TensorLinearCubicBezierSurface<Vec2vfx>(getL().split(u),getR().split(u));
  275. }
  276. template<int W>
  277. __forceinline TensorLinearCubicBezierSurface<Vec2vf<W>> vsplit_u(vbool<W>& valid, const BBox1f& u, int& i, int N) const {
  278. valid = true; clear(valid,W-1);
  279. auto r = TensorLinearCubicBezierSurface<Vec2vf<W>>(getL().split<W>(u,i,N),getR().split<W>(u,i,N));
  280. i += W-1;
  281. return r;
  282. }
  283. __forceinline Vec2fa eval(const float u, const float v) const
  284. {
  285. const vfloat4 p = LR.eval(u);
  286. return Vec2fa(lerp(shuffle<0,1,0,1>(p),shuffle<2,3,2,3>(p),v));
  287. }
  288. __forceinline Vec2fa eval_du(const float u, const float v) const
  289. {
  290. const vfloat4 dpdu = LR.eval_dt(u);
  291. return Vec2fa(lerp(shuffle<0,1,0,1>(dpdu),shuffle<2,3,2,3>(dpdu),v));
  292. }
  293. __forceinline Vec2fa eval_dv(const float u, const float v) const
  294. {
  295. const vfloat4 p = LR.eval(u);
  296. return Vec2fa(shuffle<2,3,2,3>(p)-shuffle<0,1,0,1>(p));
  297. }
  298. __forceinline void eval(const float u, const float v, Vec2fa& p, Vec2fa& dpdu, Vec2fa& dpdv) const
  299. {
  300. vfloat4 p0, dp0du; LR.eval(u,p0,dp0du);
  301. p = Vec2fa(lerp(shuffle<0,1,0,1>(p0),shuffle<2,3,2,3>(p0),v));
  302. dpdu = Vec2fa(lerp(shuffle<0,1,0,1>(dp0du),shuffle<2,3,2,3>(dp0du),v));
  303. dpdv = Vec2fa(shuffle<2,3,2,3>(p0)-shuffle<0,1,0,1>(p0));
  304. }
  305. __forceinline TensorLinearQuadraticBezierSurface<Vec2fa> derivative_u() const {
  306. return TensorLinearQuadraticBezierSurface<Vec2fa>(LR.derivative());
  307. }
  308. __forceinline CubicBezierCurve<Vec2fa> derivative_v() const {
  309. return getR()-getL();
  310. }
  311. __forceinline Vec2fa axis_u() const
  312. {
  313. const CubicBezierCurve<Vec2fa> L = getL();
  314. const CubicBezierCurve<Vec2fa> R = getR();
  315. return (L.end()-L.begin())+(R.end()-R.begin());
  316. }
  317. __forceinline Vec2fa axis_v() const
  318. {
  319. const CubicBezierCurve<Vec2fa> L = getL();
  320. const CubicBezierCurve<Vec2fa> R = getR();
  321. return (R.begin()-L.begin())+(R.end()-L.end());
  322. }
  323. friend embree_ostream operator<<(embree_ostream cout, const TensorLinearCubicBezierSurface& a)
  324. {
  325. return cout << "TensorLinearCubicBezierSurface" << embree_endl
  326. << "{" << embree_endl
  327. << " L = " << a.getL() << ", " << embree_endl
  328. << " R = " << a.getR() << embree_endl
  329. << "}";
  330. }
  331. };
  332. template<>
  333. __forceinline TensorLinearCubicBezierSurface<Vec2f> TensorLinearCubicBezierSurface<Vec2fa>::vsplit_u<1>(bool& valid, const BBox1f& u, int& i, int N) const {
  334. auto r = TensorLinearCubicBezierSurface<Vec2f>(getL().split1(u,i,N),getR().split1(u,i,N));
  335. valid = true; i += 1;
  336. return r;
  337. }
  338. #else
  339. template<> template<>
  340. __forceinline TensorLinearCubicBezierSurface<Vec2f> TensorLinearCubicBezierSurface<Vec2fa>::vsplit_u<1>(bool& valid, const BBox1f& u, int& i, int N) const {
  341. auto r = TensorLinearCubicBezierSurface<Vec2f>(L.split1(u,i,N),R.split1(u,i,N));
  342. valid = true; i += 1;
  343. return r;
  344. }
  345. #endif
  346. typedef TensorLinearCubicBezierSurface<float> TensorLinearCubicBezierSurface1f;
  347. typedef TensorLinearCubicBezierSurface<Vec2fa> TensorLinearCubicBezierSurface2fa;
  348. typedef TensorLinearCubicBezierSurface<Vec3fa> TensorLinearCubicBezierSurface3fa;
  349. }
  350. }