bspline_patch.h 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  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 "catmullclark_patch.h"
  18. #include "bspline_curve.h"
  19. namespace embree
  20. {
  21. class BSplineBasis // FIXME: factor of 1.0f/6.0f should be inside basis
  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 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(3.0f)*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 T(6.0f)*Vec4<T>(n0,n1,n2,n3);
  56. }
  57. };
  58. template<typename Vertex, typename Vertex_t = Vertex>
  59. class __aligned(64) BSplinePatchT
  60. {
  61. typedef CatmullClark1RingT<Vertex,Vertex_t> CatmullClarkRing;
  62. typedef CatmullClarkPatchT<Vertex,Vertex_t> CatmullClarkPatch;
  63. public:
  64. __forceinline BSplinePatchT () {}
  65. __forceinline BSplinePatchT (const CatmullClarkPatch& patch) {
  66. init(patch);
  67. }
  68. __forceinline BSplinePatchT(const CatmullClarkPatch& patch,
  69. const BezierCurveT<Vertex>* border0,
  70. const BezierCurveT<Vertex>* border1,
  71. const BezierCurveT<Vertex>* border2,
  72. const BezierCurveT<Vertex>* border3)
  73. {
  74. init(patch);
  75. }
  76. __forceinline BSplinePatchT (const HalfEdge* edge, const char* vertices, size_t stride) {
  77. init(edge,vertices,stride);
  78. }
  79. __forceinline Vertex hard_corner(const Vertex& v01, const Vertex& v02,
  80. const Vertex& v10, const Vertex& v11, const Vertex& v12,
  81. const Vertex& v20, const Vertex& v21, const Vertex& v22)
  82. {
  83. return 4.0f*v11 - 2.0f*(v12+v21) + v22;
  84. }
  85. __forceinline Vertex soft_convex_corner( const Vertex& v01, const Vertex& v02,
  86. const Vertex& v10, const Vertex& v11, const Vertex& v12,
  87. const Vertex& v20, const Vertex& v21, const Vertex& v22)
  88. {
  89. return -8.0f*v11 + 4.0f*(v12+v21) + v22;
  90. }
  91. __forceinline Vertex convex_corner(const float vertex_crease_weight,
  92. const Vertex& v01, const Vertex& v02,
  93. const Vertex& v10, const Vertex& v11, const Vertex& v12,
  94. const Vertex& v20, const Vertex& v21, const Vertex& v22)
  95. {
  96. if (std::isinf(vertex_crease_weight)) return hard_corner(v01,v02,v10,v11,v12,v20,v21,v22);
  97. else return soft_convex_corner(v01,v02,v10,v11,v12,v20,v21,v22);
  98. }
  99. __forceinline Vertex load(const HalfEdge* edge, const char* vertices, size_t stride) {
  100. return Vertex_t::loadu(vertices+edge->getStartVertexIndex()*stride);
  101. }
  102. __forceinline void init_border(const CatmullClarkRing& edge0,
  103. Vertex& v01, Vertex& v02,
  104. const Vertex& v11, const Vertex& v12,
  105. const Vertex& v21, const Vertex& v22)
  106. {
  107. if (likely(edge0.has_opposite_back(0)))
  108. {
  109. v01 = edge0.back(2);
  110. v02 = edge0.back(1);
  111. } else {
  112. v01 = 2.0f*v11-v21;
  113. v02 = 2.0f*v12-v22;
  114. }
  115. }
  116. __forceinline void init_corner(const CatmullClarkRing& edge0,
  117. Vertex& v00, const Vertex& v01, const Vertex& v02,
  118. const Vertex& v10, const Vertex& v11, const Vertex& v12,
  119. const Vertex& v20, const Vertex& v21, const Vertex& v22)
  120. {
  121. const bool MAYBE_UNUSED has_back1 = edge0.has_opposite_back(1);
  122. const bool has_back0 = edge0.has_opposite_back(0);
  123. const bool has_front1 = edge0.has_opposite_front(1);
  124. const bool MAYBE_UNUSED has_front2 = edge0.has_opposite_front(2);
  125. if (likely(has_back0)) {
  126. if (likely(has_front1)) { assert(has_back1 && has_front2); v00 = edge0.back(3); }
  127. else { assert(!has_back1); v00 = 2.0f*v01-v02; }
  128. }
  129. else {
  130. if (likely(has_front1)) { assert(!has_front2); v00 = 2.0f*v10-v20; }
  131. else v00 = convex_corner(edge0.vertex_crease_weight,v01,v02,v10,v11,v12,v20,v21,v22);
  132. }
  133. }
  134. void init(const CatmullClarkPatch& patch)
  135. {
  136. /* fill inner vertices */
  137. const Vertex v11 = v[1][1] = patch.ring[0].vtx;
  138. const Vertex v12 = v[1][2] = patch.ring[1].vtx;
  139. const Vertex v22 = v[2][2] = patch.ring[2].vtx;
  140. const Vertex v21 = v[2][1] = patch.ring[3].vtx;
  141. /* fill border vertices */
  142. init_border(patch.ring[0],v[0][1],v[0][2],v11,v12,v21,v22);
  143. init_border(patch.ring[1],v[1][3],v[2][3],v12,v22,v11,v21);
  144. init_border(patch.ring[2],v[3][2],v[3][1],v22,v21,v12,v11);
  145. init_border(patch.ring[3],v[2][0],v[1][0],v21,v11,v22,v12);
  146. /* fill corner vertices */
  147. init_corner(patch.ring[0],v[0][0],v[0][1],v[0][2],v[1][0],v11,v12,v[2][0],v21,v22);
  148. init_corner(patch.ring[1],v[0][3],v[1][3],v[2][3],v[0][2],v12,v22,v[0][1],v11,v21);
  149. init_corner(patch.ring[2],v[3][3],v[3][2],v[3][1],v[2][3],v22,v21,v[1][3],v12,v11);
  150. init_corner(patch.ring[3],v[3][0],v[2][0],v[1][0],v[3][1],v21,v11,v[3][2],v22,v12);
  151. }
  152. void init_border(const HalfEdge* edge0, const char* vertices, size_t stride,
  153. Vertex& v01, Vertex& v02,
  154. const Vertex& v11, const Vertex& v12,
  155. const Vertex& v21, const Vertex& v22)
  156. {
  157. if (likely(edge0->hasOpposite()))
  158. {
  159. const HalfEdge* e = edge0->opposite()->next()->next();
  160. v01 = load(e,vertices,stride);
  161. v02 = load(e->next(),vertices,stride);
  162. } else {
  163. v01 = 2.0f*v11-v21;
  164. v02 = 2.0f*v12-v22;
  165. }
  166. }
  167. void init_corner(const HalfEdge* edge0, const char* vertices, size_t stride,
  168. Vertex& v00, const Vertex& v01, const Vertex& v02,
  169. const Vertex& v10, const Vertex& v11, const Vertex& v12,
  170. const Vertex& v20, const Vertex& v21, const Vertex& v22)
  171. {
  172. const bool has_back0 = edge0->hasOpposite();
  173. const bool has_front1 = edge0->prev()->hasOpposite();
  174. if (likely(has_back0))
  175. {
  176. const HalfEdge* e = edge0->opposite()->next();
  177. if (likely(has_front1))
  178. {
  179. assert(e->hasOpposite());
  180. assert(edge0->prev()->opposite()->prev()->hasOpposite());
  181. v00 = load(e->opposite()->prev(),vertices,stride);
  182. }
  183. else {
  184. assert(!e->hasOpposite());
  185. v00 = 2.0f*v01-v02;
  186. }
  187. }
  188. else
  189. {
  190. if (likely(has_front1)) {
  191. assert(!edge0->prev()->opposite()->prev()->hasOpposite());
  192. v00 = 2.0f*v10-v20;
  193. }
  194. else {
  195. assert(edge0->vertex_crease_weight == 0.0f || std::isinf(edge0->vertex_crease_weight));
  196. v00 = convex_corner(edge0->vertex_crease_weight,v01,v02,v10,v11,v12,v20,v21,v22);
  197. }
  198. }
  199. }
  200. void init(const HalfEdge* edge0, const char* vertices, size_t stride)
  201. {
  202. assert( edge0->isRegularFace() );
  203. /* fill inner vertices */
  204. const Vertex v11 = v[1][1] = load(edge0,vertices,stride); const HalfEdge* edge1 = edge0->next();
  205. const Vertex v12 = v[1][2] = load(edge1,vertices,stride); const HalfEdge* edge2 = edge1->next();
  206. const Vertex v22 = v[2][2] = load(edge2,vertices,stride); const HalfEdge* edge3 = edge2->next();
  207. const Vertex v21 = v[2][1] = load(edge3,vertices,stride); assert(edge0 == edge3->next());
  208. /* fill border vertices */
  209. init_border(edge0,vertices,stride,v[0][1],v[0][2],v11,v12,v21,v22);
  210. init_border(edge1,vertices,stride,v[1][3],v[2][3],v12,v22,v11,v21);
  211. init_border(edge2,vertices,stride,v[3][2],v[3][1],v22,v21,v12,v11);
  212. init_border(edge3,vertices,stride,v[2][0],v[1][0],v21,v11,v22,v12);
  213. /* fill corner vertices */
  214. init_corner(edge0,vertices,stride,v[0][0],v[0][1],v[0][2],v[1][0],v11,v12,v[2][0],v21,v22);
  215. init_corner(edge1,vertices,stride,v[0][3],v[1][3],v[2][3],v[0][2],v12,v22,v[0][1],v11,v21);
  216. init_corner(edge2,vertices,stride,v[3][3],v[3][2],v[3][1],v[2][3],v22,v21,v[1][3],v12,v11);
  217. init_corner(edge3,vertices,stride,v[3][0],v[2][0],v[1][0],v[3][1],v21,v11,v[3][2],v22,v12);
  218. }
  219. __forceinline BBox<Vertex> bounds() const
  220. {
  221. const Vertex* const cv = &v[0][0];
  222. BBox<Vertex> bounds (cv[0]);
  223. for (size_t i=1; i<16 ; i++)
  224. bounds.extend( cv[i] );
  225. return bounds;
  226. }
  227. __forceinline Vertex eval(const float uu, const float vv) const
  228. {
  229. const Vec4f v_n = BSplineBasis::eval(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::eval(uu);
  235. return madd(u_n[0],curve0,madd(u_n[1],curve1,madd(u_n[2],curve2,u_n[3] * curve3))) * (1.0f/36.0f);
  236. }
  237. __forceinline Vertex eval_du(const float uu, const float vv) const
  238. {
  239. const Vec4f v_n = BSplineBasis::eval(vv);
  240. 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])));
  241. 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])));
  242. 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])));
  243. 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])));
  244. const Vec4f u_n = BSplineBasis::derivative(uu);
  245. return madd(u_n[0],curve0,madd(u_n[1],curve1,madd(u_n[2],curve2,u_n[3] * curve3))) * (1.0f/36.0f);
  246. }
  247. __forceinline Vertex eval_dv(const float uu, const float vv) const
  248. {
  249. const Vec4f v_n = BSplineBasis::derivative(vv);
  250. 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])));
  251. 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])));
  252. 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])));
  253. 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])));
  254. const Vec4f u_n = BSplineBasis::eval(uu);
  255. return madd(u_n[0],curve0,madd(u_n[1],curve1,madd(u_n[2],curve2,u_n[3] * curve3))) * (1.0f/36.0f);
  256. }
  257. __forceinline Vertex eval_dudu(const float uu, const float vv) const
  258. {
  259. const Vec4f v_n = BSplineBasis::eval(vv);
  260. 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])));
  261. 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])));
  262. 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])));
  263. 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])));
  264. const Vec4f u_n = BSplineBasis::derivative2(uu);
  265. return madd(u_n[0],curve0,madd(u_n[1],curve1,madd(u_n[2],curve2,u_n[3] * curve3))) * (1.0f/36.0f);
  266. }
  267. __forceinline Vertex eval_dvdv(const float uu, const float vv) const
  268. {
  269. const Vec4f v_n = BSplineBasis::derivative2(vv);
  270. 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])));
  271. 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])));
  272. 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])));
  273. 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])));
  274. const Vec4f u_n = BSplineBasis::eval(uu);
  275. return madd(u_n[0],curve0,madd(u_n[1],curve1,madd(u_n[2],curve2,u_n[3] * curve3))) * (1.0f/36.0f);
  276. }
  277. __forceinline Vertex eval_dudv(const float uu, const float vv) const
  278. {
  279. const Vec4f v_n = BSplineBasis::derivative(vv);
  280. 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])));
  281. 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])));
  282. 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])));
  283. 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])));
  284. const Vec4f u_n = BSplineBasis::derivative(uu);
  285. return madd(u_n[0],curve0,madd(u_n[1],curve1,madd(u_n[2],curve2,u_n[3] * curve3))) * (1.0f/36.0f);
  286. }
  287. __forceinline Vertex normal(const float uu, const float vv) const
  288. {
  289. const Vertex tu = eval_du(uu,vv);
  290. const Vertex tv = eval_dv(uu,vv);
  291. return cross(tv,tu);
  292. }
  293. template<typename T>
  294. __forceinline Vec3<T> eval(const T& uu, const T& vv, const Vec4<T>& u_n, const Vec4<T>& v_n) const
  295. {
  296. 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))));
  297. 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))));
  298. 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))));
  299. 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))));
  300. 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))) * T(1.0f/36.0f);
  301. 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))));
  302. 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))));
  303. 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))));
  304. 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))));
  305. 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))) * T(1.0f/36.0f);
  306. 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))));
  307. 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))));
  308. 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))));
  309. 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))));
  310. 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))) * T(1.0f/36.0f);
  311. return Vec3<T>(x,y,z);
  312. }
  313. template<typename T>
  314. __forceinline Vec3<T> eval(const T& uu, const T& vv) const
  315. {
  316. const Vec4<T> u_n = BSplineBasis::eval(uu);
  317. const Vec4<T> v_n = BSplineBasis::eval(vv);
  318. return eval(uu,vv,u_n,v_n);
  319. }
  320. template<typename T>
  321. __forceinline Vec3<T> eval_du(const T& uu, const T& vv) const
  322. {
  323. const Vec4<T> u_n = BSplineBasis::derivative(uu);
  324. const Vec4<T> v_n = BSplineBasis::eval(vv);
  325. return eval(uu,vv,u_n,v_n);
  326. }
  327. template<typename T>
  328. __forceinline Vec3<T> eval_dv(const T& uu, const T& vv) const
  329. {
  330. const Vec4<T> u_n = BSplineBasis::eval(uu);
  331. const Vec4<T> v_n = BSplineBasis::derivative(vv);
  332. return eval(uu,vv,u_n,v_n);
  333. }
  334. template<typename T>
  335. __forceinline Vec3<T> eval_dudu(const T& uu, const T& vv) const
  336. {
  337. const Vec4<T> u_n = BSplineBasis::derivative2(uu);
  338. const Vec4<T> v_n = BSplineBasis::eval(vv);
  339. return eval(uu,vv,u_n,v_n);
  340. }
  341. template<typename T>
  342. __forceinline Vec3<T> eval_dvdv(const T& uu, const T& vv) const
  343. {
  344. const Vec4<T> u_n = BSplineBasis::eval(uu);
  345. const Vec4<T> v_n = BSplineBasis::derivative2(vv);
  346. return eval(uu,vv,u_n,v_n);
  347. }
  348. template<typename T>
  349. __forceinline Vec3<T> eval_dudv(const T& uu, const T& vv) const
  350. {
  351. const Vec4<T> u_n = BSplineBasis::derivative(uu);
  352. const Vec4<T> v_n = BSplineBasis::derivative(vv);
  353. return eval(uu,vv,u_n,v_n);
  354. }
  355. template<typename T>
  356. __forceinline Vec3<T> normal(const T& uu, const T& vv) const {
  357. return cross(eval_dv(uu,vv),eval_du(uu,vv));
  358. }
  359. void eval(const float u, const float v,
  360. Vertex* P, Vertex* dPdu, Vertex* dPdv, Vertex* ddPdudu, Vertex* ddPdvdv, Vertex* ddPdudv,
  361. const float dscale = 1.0f) const
  362. {
  363. if (P) {
  364. *P = eval(u,v);
  365. }
  366. if (dPdu) {
  367. assert(dPdu); *dPdu = eval_du(u,v)*dscale;
  368. assert(dPdv); *dPdv = eval_dv(u,v)*dscale;
  369. }
  370. if (ddPdudu) {
  371. assert(ddPdudu); *ddPdudu = eval_dudu(u,v)*sqr(dscale);
  372. assert(ddPdvdv); *ddPdvdv = eval_dvdv(u,v)*sqr(dscale);
  373. assert(ddPdudv); *ddPdudv = eval_dudv(u,v)*sqr(dscale);
  374. }
  375. }
  376. template<class vfloat>
  377. __forceinline vfloat eval(const size_t i, const vfloat& uu, const vfloat& vv, const Vec4<vfloat>& u_n, const Vec4<vfloat>& v_n) const
  378. {
  379. 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]))));
  380. 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]))));
  381. 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]))));
  382. 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]))));
  383. return madd(u_n[0],curve0_x,madd(u_n[1],curve1_x,madd(u_n[2],curve2_x,u_n[3] * curve3_x))) * vfloat(1.0f/36.0f);
  384. }
  385. template<typename vbool, typename vfloat>
  386. void eval(const vbool& valid, const vfloat& uu, const vfloat& vv,
  387. float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv,
  388. const float dscale, const size_t dstride, const size_t N) const
  389. {
  390. if (P) {
  391. const Vec4<vfloat> u_n = BSplineBasis::eval(uu);
  392. const Vec4<vfloat> v_n = BSplineBasis::eval(vv);
  393. for (size_t i=0; i<N; i++) vfloat::store(valid,P+i*dstride,eval(i,uu,vv,u_n,v_n));
  394. }
  395. if (dPdu)
  396. {
  397. {
  398. assert(dPdu);
  399. const Vec4<vfloat> u_n = BSplineBasis::derivative(uu);
  400. const Vec4<vfloat> v_n = BSplineBasis::eval(vv);
  401. for (size_t i=0; i<N; i++) vfloat::store(valid,dPdu+i*dstride,eval(i,uu,vv,u_n,v_n)*dscale);
  402. }
  403. {
  404. assert(dPdv);
  405. const Vec4<vfloat> u_n = BSplineBasis::eval(uu);
  406. const Vec4<vfloat> v_n = BSplineBasis::derivative(vv);
  407. for (size_t i=0; i<N; i++) vfloat::store(valid,dPdv+i*dstride,eval(i,uu,vv,u_n,v_n)*dscale);
  408. }
  409. }
  410. if (ddPdudu)
  411. {
  412. {
  413. assert(ddPdudu);
  414. const Vec4<vfloat> u_n = BSplineBasis::derivative2(uu);
  415. const Vec4<vfloat> v_n = BSplineBasis::eval(vv);
  416. for (size_t i=0; i<N; i++) vfloat::store(valid,ddPdudu+i*dstride,eval(i,uu,vv,u_n,v_n)*sqr(dscale));
  417. }
  418. {
  419. assert(ddPdvdv);
  420. const Vec4<vfloat> u_n = BSplineBasis::eval(uu);
  421. const Vec4<vfloat> v_n = BSplineBasis::derivative2(vv);
  422. for (size_t i=0; i<N; i++) vfloat::store(valid,ddPdvdv+i*dstride,eval(i,uu,vv,u_n,v_n)*sqr(dscale));
  423. }
  424. {
  425. assert(ddPdudv);
  426. const Vec4<vfloat> u_n = BSplineBasis::derivative(uu);
  427. const Vec4<vfloat> v_n = BSplineBasis::derivative(vv);
  428. for (size_t i=0; i<N; i++) vfloat::store(valid,ddPdudv+i*dstride,eval(i,uu,vv,u_n,v_n)*sqr(dscale));
  429. }
  430. }
  431. }
  432. friend __forceinline std::ostream& operator<<(std::ostream& o, const BSplinePatchT& p)
  433. {
  434. for (size_t y=0; y<4; y++)
  435. for (size_t x=0; x<4; x++)
  436. o << "[" << y << "][" << x << "] " << p.v[y][x] << std::endl;
  437. return o;
  438. }
  439. public:
  440. Vertex v[4][4];
  441. };
  442. typedef BSplinePatchT<Vec3fa,Vec3fa_t> BSplinePatch3fa;
  443. }