bspline_patch.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. // Copyright 2009-2021 Intel Corporation
  2. // SPDX-License-Identifier: Apache-2.0
  3. #pragma once
  4. #include "catmullclark_patch.h"
  5. #include "bspline_curve.h"
  6. namespace embree
  7. {
  8. template<typename Vertex, typename Vertex_t = Vertex>
  9. class __aligned(64) BSplinePatchT
  10. {
  11. typedef CatmullClark1RingT<Vertex,Vertex_t> CatmullClarkRing;
  12. typedef CatmullClarkPatchT<Vertex,Vertex_t> CatmullClarkPatch;
  13. public:
  14. __forceinline BSplinePatchT () {}
  15. __forceinline BSplinePatchT (const CatmullClarkPatch& patch) {
  16. init(patch);
  17. }
  18. __forceinline BSplinePatchT(const CatmullClarkPatch& patch,
  19. const BezierCurveT<Vertex>* border0,
  20. const BezierCurveT<Vertex>* border1,
  21. const BezierCurveT<Vertex>* border2,
  22. const BezierCurveT<Vertex>* border3)
  23. {
  24. init(patch);
  25. }
  26. __forceinline BSplinePatchT (const HalfEdge* edge, const char* vertices, size_t stride) {
  27. init(edge,vertices,stride);
  28. }
  29. __forceinline Vertex hard_corner(const Vertex& v01, const Vertex& v02,
  30. const Vertex& v10, const Vertex& v11, const Vertex& v12,
  31. const Vertex& v20, const Vertex& v21, const Vertex& v22)
  32. {
  33. return 4.0f*v11 - 2.0f*(v12+v21) + v22;
  34. }
  35. __forceinline Vertex soft_convex_corner( const Vertex& v01, const Vertex& v02,
  36. const Vertex& v10, const Vertex& v11, const Vertex& v12,
  37. const Vertex& v20, const Vertex& v21, const Vertex& v22)
  38. {
  39. return -8.0f*v11 + 4.0f*(v12+v21) + v22;
  40. }
  41. __forceinline Vertex convex_corner(const float vertex_crease_weight,
  42. const Vertex& v01, const Vertex& v02,
  43. const Vertex& v10, const Vertex& v11, const Vertex& v12,
  44. const Vertex& v20, const Vertex& v21, const Vertex& v22)
  45. {
  46. if (std::isinf(vertex_crease_weight)) return hard_corner(v01,v02,v10,v11,v12,v20,v21,v22);
  47. else return soft_convex_corner(v01,v02,v10,v11,v12,v20,v21,v22);
  48. }
  49. __forceinline Vertex load(const HalfEdge* edge, const char* vertices, size_t stride) {
  50. return Vertex_t::loadu(vertices+edge->getStartVertexIndex()*stride);
  51. }
  52. __forceinline void init_border(const CatmullClarkRing& edge0,
  53. Vertex& v01, Vertex& v02,
  54. const Vertex& v11, const Vertex& v12,
  55. const Vertex& v21, const Vertex& v22)
  56. {
  57. if (likely(edge0.has_opposite_back(0)))
  58. {
  59. v01 = edge0.back(2);
  60. v02 = edge0.back(1);
  61. } else {
  62. v01 = 2.0f*v11-v21;
  63. v02 = 2.0f*v12-v22;
  64. }
  65. }
  66. __forceinline void init_corner(const CatmullClarkRing& edge0,
  67. Vertex& v00, const Vertex& v01, const Vertex& v02,
  68. const Vertex& v10, const Vertex& v11, const Vertex& v12,
  69. const Vertex& v20, const Vertex& v21, const Vertex& v22)
  70. {
  71. const bool MAYBE_UNUSED has_back1 = edge0.has_opposite_back(1);
  72. const bool has_back0 = edge0.has_opposite_back(0);
  73. const bool has_front1 = edge0.has_opposite_front(1);
  74. const bool MAYBE_UNUSED has_front2 = edge0.has_opposite_front(2);
  75. if (likely(has_back0)) {
  76. if (likely(has_front1)) { assert(has_back1 && has_front2); v00 = edge0.back(3); }
  77. else { assert(!has_back1); v00 = 2.0f*v01-v02; }
  78. }
  79. else {
  80. if (likely(has_front1)) { assert(!has_front2); v00 = 2.0f*v10-v20; }
  81. else v00 = convex_corner(edge0.vertex_crease_weight,v01,v02,v10,v11,v12,v20,v21,v22);
  82. }
  83. }
  84. void init(const CatmullClarkPatch& patch)
  85. {
  86. /* fill inner vertices */
  87. const Vertex v11 = v[1][1] = patch.ring[0].vtx;
  88. const Vertex v12 = v[1][2] = patch.ring[1].vtx;
  89. const Vertex v22 = v[2][2] = patch.ring[2].vtx;
  90. const Vertex v21 = v[2][1] = patch.ring[3].vtx;
  91. /* fill border vertices */
  92. init_border(patch.ring[0],v[0][1],v[0][2],v11,v12,v21,v22);
  93. init_border(patch.ring[1],v[1][3],v[2][3],v12,v22,v11,v21);
  94. init_border(patch.ring[2],v[3][2],v[3][1],v22,v21,v12,v11);
  95. init_border(patch.ring[3],v[2][0],v[1][0],v21,v11,v22,v12);
  96. /* fill corner vertices */
  97. init_corner(patch.ring[0],v[0][0],v[0][1],v[0][2],v[1][0],v11,v12,v[2][0],v21,v22);
  98. init_corner(patch.ring[1],v[0][3],v[1][3],v[2][3],v[0][2],v12,v22,v[0][1],v11,v21);
  99. init_corner(patch.ring[2],v[3][3],v[3][2],v[3][1],v[2][3],v22,v21,v[1][3],v12,v11);
  100. init_corner(patch.ring[3],v[3][0],v[2][0],v[1][0],v[3][1],v21,v11,v[3][2],v22,v12);
  101. }
  102. void init_border(const HalfEdge* edge0, const char* vertices, size_t stride,
  103. Vertex& v01, Vertex& v02,
  104. const Vertex& v11, const Vertex& v12,
  105. const Vertex& v21, const Vertex& v22)
  106. {
  107. if (likely(edge0->hasOpposite()))
  108. {
  109. const HalfEdge* e = edge0->opposite()->next()->next();
  110. v01 = load(e,vertices,stride);
  111. v02 = load(e->next(),vertices,stride);
  112. } else {
  113. v01 = 2.0f*v11-v21;
  114. v02 = 2.0f*v12-v22;
  115. }
  116. }
  117. void init_corner(const HalfEdge* edge0, const char* vertices, size_t stride,
  118. Vertex& v00, const Vertex& v01, const Vertex& v02,
  119. const Vertex& v10, const Vertex& v11, const Vertex& v12,
  120. const Vertex& v20, const Vertex& v21, const Vertex& v22)
  121. {
  122. const bool has_back0 = edge0->hasOpposite();
  123. const bool has_front1 = edge0->prev()->hasOpposite();
  124. if (likely(has_back0))
  125. {
  126. const HalfEdge* e = edge0->opposite()->next();
  127. if (likely(has_front1))
  128. {
  129. assert(e->hasOpposite());
  130. assert(edge0->prev()->opposite()->prev()->hasOpposite());
  131. v00 = load(e->opposite()->prev(),vertices,stride);
  132. }
  133. else {
  134. assert(!e->hasOpposite());
  135. v00 = 2.0f*v01-v02;
  136. }
  137. }
  138. else
  139. {
  140. if (likely(has_front1)) {
  141. assert(!edge0->prev()->opposite()->prev()->hasOpposite());
  142. v00 = 2.0f*v10-v20;
  143. }
  144. else {
  145. assert(edge0->vertex_crease_weight == 0.0f || std::isinf(edge0->vertex_crease_weight));
  146. v00 = convex_corner(edge0->vertex_crease_weight,v01,v02,v10,v11,v12,v20,v21,v22);
  147. }
  148. }
  149. }
  150. void init(const HalfEdge* edge0, const char* vertices, size_t stride)
  151. {
  152. assert( edge0->isRegularFace() );
  153. /* fill inner vertices */
  154. const Vertex v11 = v[1][1] = load(edge0,vertices,stride); const HalfEdge* edge1 = edge0->next();
  155. const Vertex v12 = v[1][2] = load(edge1,vertices,stride); const HalfEdge* edge2 = edge1->next();
  156. const Vertex v22 = v[2][2] = load(edge2,vertices,stride); const HalfEdge* edge3 = edge2->next();
  157. const Vertex v21 = v[2][1] = load(edge3,vertices,stride); assert(edge0 == edge3->next());
  158. /* fill border vertices */
  159. init_border(edge0,vertices,stride,v[0][1],v[0][2],v11,v12,v21,v22);
  160. init_border(edge1,vertices,stride,v[1][3],v[2][3],v12,v22,v11,v21);
  161. init_border(edge2,vertices,stride,v[3][2],v[3][1],v22,v21,v12,v11);
  162. init_border(edge3,vertices,stride,v[2][0],v[1][0],v21,v11,v22,v12);
  163. /* fill corner vertices */
  164. init_corner(edge0,vertices,stride,v[0][0],v[0][1],v[0][2],v[1][0],v11,v12,v[2][0],v21,v22);
  165. init_corner(edge1,vertices,stride,v[0][3],v[1][3],v[2][3],v[0][2],v12,v22,v[0][1],v11,v21);
  166. init_corner(edge2,vertices,stride,v[3][3],v[3][2],v[3][1],v[2][3],v22,v21,v[1][3],v12,v11);
  167. init_corner(edge3,vertices,stride,v[3][0],v[2][0],v[1][0],v[3][1],v21,v11,v[3][2],v22,v12);
  168. }
  169. __forceinline BBox<Vertex> bounds() const
  170. {
  171. const Vertex* const cv = &v[0][0];
  172. BBox<Vertex> bounds (cv[0]);
  173. for (size_t i=1; i<16 ; i++)
  174. bounds.extend( cv[i] );
  175. return bounds;
  176. }
  177. __forceinline Vertex eval(const float uu, const float vv) const
  178. {
  179. const Vec4f v_n = BSplineBasis::eval(vv);
  180. const Vertex_t curve0 = madd(v_n[0],v[0][0],madd(v_n[1],v[1][0],madd(v_n[2],v[2][0],v_n[3] * v[3][0])));
  181. const Vertex_t curve1 = madd(v_n[0],v[0][1],madd(v_n[1],v[1][1],madd(v_n[2],v[2][1],v_n[3] * v[3][1])));
  182. const Vertex_t curve2 = madd(v_n[0],v[0][2],madd(v_n[1],v[1][2],madd(v_n[2],v[2][2],v_n[3] * v[3][2])));
  183. const Vertex_t curve3 = madd(v_n[0],v[0][3],madd(v_n[1],v[1][3],madd(v_n[2],v[2][3],v_n[3] * v[3][3])));
  184. const Vec4f u_n = BSplineBasis::eval(uu);
  185. return madd(u_n[0],curve0,madd(u_n[1],curve1,madd(u_n[2],curve2,u_n[3] * curve3)));
  186. }
  187. __forceinline Vertex eval_du(const float uu, const float vv) const
  188. {
  189. const Vec4f v_n = BSplineBasis::eval(vv);
  190. const Vertex_t curve0 = madd(v_n[0],v[0][0],madd(v_n[1],v[1][0],madd(v_n[2],v[2][0],v_n[3] * v[3][0])));
  191. const Vertex_t curve1 = madd(v_n[0],v[0][1],madd(v_n[1],v[1][1],madd(v_n[2],v[2][1],v_n[3] * v[3][1])));
  192. const Vertex_t curve2 = madd(v_n[0],v[0][2],madd(v_n[1],v[1][2],madd(v_n[2],v[2][2],v_n[3] * v[3][2])));
  193. const Vertex_t curve3 = madd(v_n[0],v[0][3],madd(v_n[1],v[1][3],madd(v_n[2],v[2][3],v_n[3] * v[3][3])));
  194. const Vec4f u_n = BSplineBasis::derivative(uu);
  195. return madd(u_n[0],curve0,madd(u_n[1],curve1,madd(u_n[2],curve2,u_n[3] * curve3)));
  196. }
  197. __forceinline Vertex eval_dv(const float uu, const float vv) const
  198. {
  199. const Vec4f v_n = BSplineBasis::derivative(vv);
  200. const Vertex_t curve0 = madd(v_n[0],v[0][0],madd(v_n[1],v[1][0],madd(v_n[2],v[2][0],v_n[3] * v[3][0])));
  201. const Vertex_t curve1 = madd(v_n[0],v[0][1],madd(v_n[1],v[1][1],madd(v_n[2],v[2][1],v_n[3] * v[3][1])));
  202. const Vertex_t curve2 = madd(v_n[0],v[0][2],madd(v_n[1],v[1][2],madd(v_n[2],v[2][2],v_n[3] * v[3][2])));
  203. const Vertex_t curve3 = madd(v_n[0],v[0][3],madd(v_n[1],v[1][3],madd(v_n[2],v[2][3],v_n[3] * v[3][3])));
  204. const Vec4f u_n = BSplineBasis::eval(uu);
  205. return madd(u_n[0],curve0,madd(u_n[1],curve1,madd(u_n[2],curve2,u_n[3] * curve3)));
  206. }
  207. __forceinline Vertex eval_dudu(const float uu, const float vv) const
  208. {
  209. const Vec4f v_n = BSplineBasis::eval(vv);
  210. const Vertex_t curve0 = madd(v_n[0],v[0][0],madd(v_n[1],v[1][0],madd(v_n[2],v[2][0],v_n[3] * v[3][0])));
  211. const Vertex_t curve1 = madd(v_n[0],v[0][1],madd(v_n[1],v[1][1],madd(v_n[2],v[2][1],v_n[3] * v[3][1])));
  212. const Vertex_t curve2 = madd(v_n[0],v[0][2],madd(v_n[1],v[1][2],madd(v_n[2],v[2][2],v_n[3] * v[3][2])));
  213. const Vertex_t curve3 = madd(v_n[0],v[0][3],madd(v_n[1],v[1][3],madd(v_n[2],v[2][3],v_n[3] * v[3][3])));
  214. const Vec4f u_n = BSplineBasis::derivative2(uu);
  215. return madd(u_n[0],curve0,madd(u_n[1],curve1,madd(u_n[2],curve2,u_n[3] * curve3)));
  216. }
  217. __forceinline Vertex eval_dvdv(const float uu, const float vv) const
  218. {
  219. const Vec4f v_n = BSplineBasis::derivative2(vv);
  220. const Vertex_t curve0 = madd(v_n[0],v[0][0],madd(v_n[1],v[1][0],madd(v_n[2],v[2][0],v_n[3] * v[3][0])));
  221. const Vertex_t curve1 = madd(v_n[0],v[0][1],madd(v_n[1],v[1][1],madd(v_n[2],v[2][1],v_n[3] * v[3][1])));
  222. const Vertex_t curve2 = madd(v_n[0],v[0][2],madd(v_n[1],v[1][2],madd(v_n[2],v[2][2],v_n[3] * v[3][2])));
  223. const Vertex_t curve3 = madd(v_n[0],v[0][3],madd(v_n[1],v[1][3],madd(v_n[2],v[2][3],v_n[3] * v[3][3])));
  224. const Vec4f u_n = BSplineBasis::eval(uu);
  225. return madd(u_n[0],curve0,madd(u_n[1],curve1,madd(u_n[2],curve2,u_n[3] * curve3)));
  226. }
  227. __forceinline Vertex eval_dudv(const float uu, const float vv) const
  228. {
  229. const Vec4f v_n = BSplineBasis::derivative(vv);
  230. const Vertex_t curve0 = madd(v_n[0],v[0][0],madd(v_n[1],v[1][0],madd(v_n[2],v[2][0],v_n[3] * v[3][0])));
  231. const Vertex_t curve1 = madd(v_n[0],v[0][1],madd(v_n[1],v[1][1],madd(v_n[2],v[2][1],v_n[3] * v[3][1])));
  232. const Vertex_t curve2 = madd(v_n[0],v[0][2],madd(v_n[1],v[1][2],madd(v_n[2],v[2][2],v_n[3] * v[3][2])));
  233. const Vertex_t curve3 = madd(v_n[0],v[0][3],madd(v_n[1],v[1][3],madd(v_n[2],v[2][3],v_n[3] * v[3][3])));
  234. const Vec4f u_n = BSplineBasis::derivative(uu);
  235. return madd(u_n[0],curve0,madd(u_n[1],curve1,madd(u_n[2],curve2,u_n[3] * curve3)));
  236. }
  237. __forceinline Vertex normal(const float uu, const float vv) const
  238. {
  239. const Vertex tu = eval_du(uu,vv);
  240. const Vertex tv = eval_dv(uu,vv);
  241. return cross(tu,tv);
  242. }
  243. template<typename T>
  244. __forceinline Vec3<T> eval(const T& uu, const T& vv, const Vec4<T>& u_n, const Vec4<T>& v_n) const
  245. {
  246. const T curve0_x = madd(v_n[0],T(v[0][0].x),madd(v_n[1],T(v[1][0].x),madd(v_n[2],T(v[2][0].x),v_n[3] * T(v[3][0].x))));
  247. const T curve1_x = madd(v_n[0],T(v[0][1].x),madd(v_n[1],T(v[1][1].x),madd(v_n[2],T(v[2][1].x),v_n[3] * T(v[3][1].x))));
  248. const T curve2_x = madd(v_n[0],T(v[0][2].x),madd(v_n[1],T(v[1][2].x),madd(v_n[2],T(v[2][2].x),v_n[3] * T(v[3][2].x))));
  249. const T curve3_x = madd(v_n[0],T(v[0][3].x),madd(v_n[1],T(v[1][3].x),madd(v_n[2],T(v[2][3].x),v_n[3] * T(v[3][3].x))));
  250. const T x = madd(u_n[0],curve0_x,madd(u_n[1],curve1_x,madd(u_n[2],curve2_x,u_n[3] * curve3_x)));
  251. const T curve0_y = madd(v_n[0],T(v[0][0].y),madd(v_n[1],T(v[1][0].y),madd(v_n[2],T(v[2][0].y),v_n[3] * T(v[3][0].y))));
  252. const T curve1_y = madd(v_n[0],T(v[0][1].y),madd(v_n[1],T(v[1][1].y),madd(v_n[2],T(v[2][1].y),v_n[3] * T(v[3][1].y))));
  253. const T curve2_y = madd(v_n[0],T(v[0][2].y),madd(v_n[1],T(v[1][2].y),madd(v_n[2],T(v[2][2].y),v_n[3] * T(v[3][2].y))));
  254. const T curve3_y = madd(v_n[0],T(v[0][3].y),madd(v_n[1],T(v[1][3].y),madd(v_n[2],T(v[2][3].y),v_n[3] * T(v[3][3].y))));
  255. const T y = madd(u_n[0],curve0_y,madd(u_n[1],curve1_y,madd(u_n[2],curve2_y,u_n[3] * curve3_y)));
  256. const T curve0_z = madd(v_n[0],T(v[0][0].z),madd(v_n[1],T(v[1][0].z),madd(v_n[2],T(v[2][0].z),v_n[3] * T(v[3][0].z))));
  257. const T curve1_z = madd(v_n[0],T(v[0][1].z),madd(v_n[1],T(v[1][1].z),madd(v_n[2],T(v[2][1].z),v_n[3] * T(v[3][1].z))));
  258. const T curve2_z = madd(v_n[0],T(v[0][2].z),madd(v_n[1],T(v[1][2].z),madd(v_n[2],T(v[2][2].z),v_n[3] * T(v[3][2].z))));
  259. const T curve3_z = madd(v_n[0],T(v[0][3].z),madd(v_n[1],T(v[1][3].z),madd(v_n[2],T(v[2][3].z),v_n[3] * T(v[3][3].z))));
  260. const T z = madd(u_n[0],curve0_z,madd(u_n[1],curve1_z,madd(u_n[2],curve2_z,u_n[3] * curve3_z)));
  261. return Vec3<T>(x,y,z);
  262. }
  263. template<typename T>
  264. __forceinline Vec3<T> eval(const T& uu, const T& vv) const
  265. {
  266. const Vec4<T> u_n = BSplineBasis::eval(uu);
  267. const Vec4<T> v_n = BSplineBasis::eval(vv);
  268. return eval(uu,vv,u_n,v_n);
  269. }
  270. template<typename T>
  271. __forceinline Vec3<T> eval_du(const T& uu, const T& vv) const
  272. {
  273. const Vec4<T> u_n = BSplineBasis::derivative(uu);
  274. const Vec4<T> v_n = BSplineBasis::eval(vv);
  275. return eval(uu,vv,u_n,v_n);
  276. }
  277. template<typename T>
  278. __forceinline Vec3<T> eval_dv(const T& uu, const T& vv) const
  279. {
  280. const Vec4<T> u_n = BSplineBasis::eval(uu);
  281. const Vec4<T> v_n = BSplineBasis::derivative(vv);
  282. return eval(uu,vv,u_n,v_n);
  283. }
  284. template<typename T>
  285. __forceinline Vec3<T> eval_dudu(const T& uu, const T& vv) const
  286. {
  287. const Vec4<T> u_n = BSplineBasis::derivative2(uu);
  288. const Vec4<T> v_n = BSplineBasis::eval(vv);
  289. return eval(uu,vv,u_n,v_n);
  290. }
  291. template<typename T>
  292. __forceinline Vec3<T> eval_dvdv(const T& uu, const T& vv) const
  293. {
  294. const Vec4<T> u_n = BSplineBasis::eval(uu);
  295. const Vec4<T> v_n = BSplineBasis::derivative2(vv);
  296. return eval(uu,vv,u_n,v_n);
  297. }
  298. template<typename T>
  299. __forceinline Vec3<T> eval_dudv(const T& uu, const T& vv) const
  300. {
  301. const Vec4<T> u_n = BSplineBasis::derivative(uu);
  302. const Vec4<T> v_n = BSplineBasis::derivative(vv);
  303. return eval(uu,vv,u_n,v_n);
  304. }
  305. template<typename T>
  306. __forceinline Vec3<T> normal(const T& uu, const T& vv) const {
  307. return cross(eval_du(uu,vv),eval_dv(uu,vv));
  308. }
  309. void eval(const float u, const float v,
  310. Vertex* P, Vertex* dPdu, Vertex* dPdv, Vertex* ddPdudu, Vertex* ddPdvdv, Vertex* ddPdudv,
  311. const float dscale = 1.0f) const
  312. {
  313. if (P) {
  314. *P = eval(u,v);
  315. }
  316. if (dPdu) {
  317. assert(dPdu); *dPdu = eval_du(u,v)*dscale;
  318. assert(dPdv); *dPdv = eval_dv(u,v)*dscale;
  319. }
  320. if (ddPdudu) {
  321. assert(ddPdudu); *ddPdudu = eval_dudu(u,v)*sqr(dscale);
  322. assert(ddPdvdv); *ddPdvdv = eval_dvdv(u,v)*sqr(dscale);
  323. assert(ddPdudv); *ddPdudv = eval_dudv(u,v)*sqr(dscale);
  324. }
  325. }
  326. template<class vfloat>
  327. __forceinline vfloat eval(const size_t i, const vfloat& uu, const vfloat& vv, const Vec4<vfloat>& u_n, const Vec4<vfloat>& v_n) const
  328. {
  329. const vfloat curve0_x = madd(v_n[0],vfloat(v[0][0][i]),madd(v_n[1],vfloat(v[1][0][i]),madd(v_n[2],vfloat(v[2][0][i]),v_n[3] * vfloat(v[3][0][i]))));
  330. const vfloat curve1_x = madd(v_n[0],vfloat(v[0][1][i]),madd(v_n[1],vfloat(v[1][1][i]),madd(v_n[2],vfloat(v[2][1][i]),v_n[3] * vfloat(v[3][1][i]))));
  331. const vfloat curve2_x = madd(v_n[0],vfloat(v[0][2][i]),madd(v_n[1],vfloat(v[1][2][i]),madd(v_n[2],vfloat(v[2][2][i]),v_n[3] * vfloat(v[3][2][i]))));
  332. const vfloat curve3_x = madd(v_n[0],vfloat(v[0][3][i]),madd(v_n[1],vfloat(v[1][3][i]),madd(v_n[2],vfloat(v[2][3][i]),v_n[3] * vfloat(v[3][3][i]))));
  333. return madd(u_n[0],curve0_x,madd(u_n[1],curve1_x,madd(u_n[2],curve2_x,u_n[3] * curve3_x)));
  334. }
  335. template<typename vbool, typename vfloat>
  336. void eval(const vbool& valid, const vfloat& uu, const vfloat& vv,
  337. float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv,
  338. const float dscale, const size_t dstride, const size_t N) const
  339. {
  340. if (P) {
  341. const Vec4<vfloat> u_n = BSplineBasis::eval(uu);
  342. const Vec4<vfloat> v_n = BSplineBasis::eval(vv);
  343. for (size_t i=0; i<N; i++) vfloat::store(valid,P+i*dstride,eval(i,uu,vv,u_n,v_n));
  344. }
  345. if (dPdu)
  346. {
  347. {
  348. assert(dPdu);
  349. const Vec4<vfloat> u_n = BSplineBasis::derivative(uu);
  350. const Vec4<vfloat> v_n = BSplineBasis::eval(vv);
  351. for (size_t i=0; i<N; i++) vfloat::store(valid,dPdu+i*dstride,eval(i,uu,vv,u_n,v_n)*dscale);
  352. }
  353. {
  354. assert(dPdv);
  355. const Vec4<vfloat> u_n = BSplineBasis::eval(uu);
  356. const Vec4<vfloat> v_n = BSplineBasis::derivative(vv);
  357. for (size_t i=0; i<N; i++) vfloat::store(valid,dPdv+i*dstride,eval(i,uu,vv,u_n,v_n)*dscale);
  358. }
  359. }
  360. if (ddPdudu)
  361. {
  362. {
  363. assert(ddPdudu);
  364. const Vec4<vfloat> u_n = BSplineBasis::derivative2(uu);
  365. const Vec4<vfloat> v_n = BSplineBasis::eval(vv);
  366. for (size_t i=0; i<N; i++) vfloat::store(valid,ddPdudu+i*dstride,eval(i,uu,vv,u_n,v_n)*sqr(dscale));
  367. }
  368. {
  369. assert(ddPdvdv);
  370. const Vec4<vfloat> u_n = BSplineBasis::eval(uu);
  371. const Vec4<vfloat> v_n = BSplineBasis::derivative2(vv);
  372. for (size_t i=0; i<N; i++) vfloat::store(valid,ddPdvdv+i*dstride,eval(i,uu,vv,u_n,v_n)*sqr(dscale));
  373. }
  374. {
  375. assert(ddPdudv);
  376. const Vec4<vfloat> u_n = BSplineBasis::derivative(uu);
  377. const Vec4<vfloat> v_n = BSplineBasis::derivative(vv);
  378. for (size_t i=0; i<N; i++) vfloat::store(valid,ddPdudv+i*dstride,eval(i,uu,vv,u_n,v_n)*sqr(dscale));
  379. }
  380. }
  381. }
  382. friend __forceinline embree_ostream operator<<(embree_ostream o, const BSplinePatchT& p)
  383. {
  384. for (size_t y=0; y<4; y++)
  385. for (size_t x=0; x<4; x++)
  386. o << "[" << y << "][" << x << "] " << p.v[y][x] << embree_endl;
  387. return o;
  388. }
  389. public:
  390. Vertex v[4][4];
  391. };
  392. typedef BSplinePatchT<Vec3fa,Vec3fa_t> BSplinePatch3fa;
  393. }