bezier_patch.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  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 "bezier_curve.h"
  19. namespace embree
  20. {
  21. template<class T, class S>
  22. static __forceinline T deCasteljau(const S& uu, const T& v0, const T& v1, const T& v2, const T& v3)
  23. {
  24. const T v0_1 = lerp(v0,v1,uu);
  25. const T v1_1 = lerp(v1,v2,uu);
  26. const T v2_1 = lerp(v2,v3,uu);
  27. const T v0_2 = lerp(v0_1,v1_1,uu);
  28. const T v1_2 = lerp(v1_1,v2_1,uu);
  29. const T v0_3 = lerp(v0_2,v1_2,uu);
  30. return v0_3;
  31. }
  32. template<class T, class S>
  33. static __forceinline T deCasteljau_tangent(const S& uu, const T& v0, const T& v1, const T& v2, const T& v3)
  34. {
  35. const T v0_1 = lerp(v0,v1,uu);
  36. const T v1_1 = lerp(v1,v2,uu);
  37. const T v2_1 = lerp(v2,v3,uu);
  38. const T v0_2 = lerp(v0_1,v1_1,uu);
  39. const T v1_2 = lerp(v1_1,v2_1,uu);
  40. return S(3.0f)*(v1_2-v0_2);
  41. }
  42. template<typename Vertex>
  43. __forceinline Vertex computeInnerBezierControlPoint(const Vertex v[4][4], const size_t y, const size_t x) {
  44. return 1.0f / 36.0f * (16.0f * v[y][x] + 4.0f * (v[y-1][x] + v[y+1][x] + v[y][x-1] + v[y][x+1]) + (v[y-1][x-1] + v[y+1][x+1] + v[y-1][x+1] + v[y+1][x-1]));
  45. }
  46. template<typename Vertex>
  47. __forceinline Vertex computeTopEdgeBezierControlPoint(const Vertex v[4][4], const size_t y, const size_t x) {
  48. return 1.0f / 18.0f * (8.0f * v[y][x] + 4.0f * v[y-1][x] + 2.0f * (v[y][x-1] + v[y][x+1]) + (v[y-1][x-1] + v[y-1][x+1]));
  49. }
  50. template<typename Vertex>
  51. __forceinline Vertex computeBottomEdgeBezierControlPoint(const Vertex v[4][4], const size_t y, const size_t x) {
  52. return 1.0f / 18.0f * (8.0f * v[y][x] + 4.0f * v[y+1][x] + 2.0f * (v[y][x-1] + v[y][x+1]) + v[y+1][x-1] + v[y+1][x+1]);
  53. }
  54. template<typename Vertex>
  55. __forceinline Vertex computeLeftEdgeBezierControlPoint(const Vertex v[4][4], const size_t y, const size_t x) {
  56. return 1.0f / 18.0f * (8.0f * v[y][x] + 4.0f * v[y][x-1] + 2.0f * (v[y-1][x] + v[y+1][x]) + v[y-1][x-1] + v[y+1][x-1]);
  57. }
  58. template<typename Vertex>
  59. __forceinline Vertex computeRightEdgeBezierControlPoint(const Vertex v[4][4], const size_t y, const size_t x) {
  60. return 1.0f / 18.0f * (8.0f * v[y][x] + 4.0f * v[y][x+1] + 2.0f * (v[y-1][x] + v[y+1][x]) + v[y-1][x+1] + v[y+1][x+1]);
  61. }
  62. template<typename Vertex>
  63. __forceinline Vertex computeCornerBezierControlPoint(const Vertex v[4][4], const size_t y, const size_t x, const ssize_t delta_y, const ssize_t delta_x)
  64. {
  65. return 1.0f / 9.0f * (4.0f * v[y][x] + 2.0f * (v[y+delta_y][x] + v[y][x+delta_x]) + v[y+delta_y][x+delta_x]);
  66. }
  67. template<typename Vertex, typename Vertex_t>
  68. class __aligned(64) BezierPatchT
  69. {
  70. public:
  71. Vertex matrix[4][4];
  72. public:
  73. __forceinline BezierPatchT() {}
  74. __forceinline BezierPatchT (const HalfEdge* edge, const char* vertices, size_t stride);
  75. __forceinline BezierPatchT(const CatmullClarkPatchT<Vertex,Vertex_t>& patch);
  76. __forceinline BezierPatchT(const CatmullClarkPatchT<Vertex,Vertex_t>& patch,
  77. const BezierCurveT<Vertex>* border0,
  78. const BezierCurveT<Vertex>* border1,
  79. const BezierCurveT<Vertex>* border2,
  80. const BezierCurveT<Vertex>* border3);
  81. __forceinline BezierPatchT(const BSplinePatchT<Vertex,Vertex_t>& source)
  82. {
  83. /* compute inner bezier control points */
  84. matrix[0][0] = computeInnerBezierControlPoint(source.v,1,1);
  85. matrix[0][3] = computeInnerBezierControlPoint(source.v,1,2);
  86. matrix[3][3] = computeInnerBezierControlPoint(source.v,2,2);
  87. matrix[3][0] = computeInnerBezierControlPoint(source.v,2,1);
  88. /* compute top edge control points */
  89. matrix[0][1] = computeRightEdgeBezierControlPoint(source.v,1,1);
  90. matrix[0][2] = computeLeftEdgeBezierControlPoint(source.v,1,2);
  91. /* compute buttom edge control points */
  92. matrix[3][1] = computeRightEdgeBezierControlPoint(source.v,2,1);
  93. matrix[3][2] = computeLeftEdgeBezierControlPoint(source.v,2,2);
  94. /* compute left edge control points */
  95. matrix[1][0] = computeBottomEdgeBezierControlPoint(source.v,1,1);
  96. matrix[2][0] = computeTopEdgeBezierControlPoint(source.v,2,1);
  97. /* compute right edge control points */
  98. matrix[1][3] = computeBottomEdgeBezierControlPoint(source.v,1,2);
  99. matrix[2][3] = computeTopEdgeBezierControlPoint(source.v,2,2);
  100. /* compute corner control points */
  101. matrix[1][1] = computeCornerBezierControlPoint(source.v,1,1, 1, 1);
  102. matrix[1][2] = computeCornerBezierControlPoint(source.v,1,2, 1,-1);
  103. matrix[2][2] = computeCornerBezierControlPoint(source.v,2,2,-1,-1);
  104. matrix[2][1] = computeCornerBezierControlPoint(source.v,2,1,-1, 1);
  105. }
  106. static __forceinline Vertex_t bilinear(const Vec4f Bu, const Vertex matrix[4][4], const Vec4f Bv)
  107. {
  108. const Vertex_t M0 = madd(Bu.x,matrix[0][0],madd(Bu.y,matrix[0][1],madd(Bu.z,matrix[0][2],Bu.w * matrix[0][3])));
  109. const Vertex_t M1 = madd(Bu.x,matrix[1][0],madd(Bu.y,matrix[1][1],madd(Bu.z,matrix[1][2],Bu.w * matrix[1][3])));
  110. const Vertex_t M2 = madd(Bu.x,matrix[2][0],madd(Bu.y,matrix[2][1],madd(Bu.z,matrix[2][2],Bu.w * matrix[2][3])));
  111. const Vertex_t M3 = madd(Bu.x,matrix[3][0],madd(Bu.y,matrix[3][1],madd(Bu.z,matrix[3][2],Bu.w * matrix[3][3])));
  112. return madd(Bv.x,M0,madd(Bv.y,M1,madd(Bv.z,M2,Bv.w*M3)));
  113. }
  114. static __forceinline Vertex_t eval(const Vertex matrix[4][4], const float uu, const float vv)
  115. {
  116. const Vec4f Bu = BezierBasis::eval(uu);
  117. const Vec4f Bv = BezierBasis::eval(vv);
  118. return bilinear(Bu,matrix,Bv);
  119. }
  120. static __forceinline Vertex_t eval_du(const Vertex matrix[4][4], const float uu, const float vv)
  121. {
  122. const Vec4f Bu = BezierBasis::derivative(uu);
  123. const Vec4f Bv = BezierBasis::eval(vv);
  124. return bilinear(Bu,matrix,Bv);
  125. }
  126. static __forceinline Vertex_t eval_dv(const Vertex matrix[4][4], const float uu, const float vv)
  127. {
  128. const Vec4f Bu = BezierBasis::eval(uu);
  129. const Vec4f Bv = BezierBasis::derivative(vv);
  130. return bilinear(Bu,matrix,Bv);
  131. }
  132. static __forceinline Vertex_t eval_dudu(const Vertex matrix[4][4], const float uu, const float vv)
  133. {
  134. const Vec4f Bu = BezierBasis::derivative2(uu);
  135. const Vec4f Bv = BezierBasis::eval(vv);
  136. return bilinear(Bu,matrix,Bv);
  137. }
  138. static __forceinline Vertex_t eval_dvdv(const Vertex matrix[4][4], const float uu, const float vv)
  139. {
  140. const Vec4f Bu = BezierBasis::eval(uu);
  141. const Vec4f Bv = BezierBasis::derivative2(vv);
  142. return bilinear(Bu,matrix,Bv);
  143. }
  144. static __forceinline Vertex_t eval_dudv(const Vertex matrix[4][4], const float uu, const float vv)
  145. {
  146. const Vec4f Bu = BezierBasis::derivative(uu);
  147. const Vec4f Bv = BezierBasis::derivative(vv);
  148. return bilinear(Bu,matrix,Bv);
  149. }
  150. static __forceinline Vertex_t normal(const Vertex matrix[4][4], const float uu, const float vv)
  151. {
  152. const Vertex_t dPdu = eval_du(matrix,uu,vv);
  153. const Vertex_t dPdv = eval_dv(matrix,uu,vv);
  154. return cross(dPdv,dPdu);
  155. }
  156. __forceinline Vertex_t normal(const float uu, const float vv)
  157. {
  158. const Vertex_t dPdu = eval_du(matrix,uu,vv);
  159. const Vertex_t dPdv = eval_dv(matrix,uu,vv);
  160. return cross(dPdv,dPdu);
  161. }
  162. __forceinline Vertex_t eval(const float uu, const float vv) const {
  163. return eval(matrix,uu,vv);
  164. }
  165. __forceinline Vertex_t eval_du(const float uu, const float vv) const {
  166. return eval_du(matrix,uu,vv);
  167. }
  168. __forceinline Vertex_t eval_dv(const float uu, const float vv) const {
  169. return eval_dv(matrix,uu,vv);
  170. }
  171. __forceinline Vertex_t eval_dudu(const float uu, const float vv) const {
  172. return eval_dudu(matrix,uu,vv);
  173. }
  174. __forceinline Vertex_t eval_dvdv(const float uu, const float vv) const {
  175. return eval_dvdv(matrix,uu,vv);
  176. }
  177. __forceinline Vertex_t eval_dudv(const float uu, const float vv) const {
  178. return eval_dudv(matrix,uu,vv);
  179. }
  180. __forceinline void eval(const float u, const float v, Vertex* P, Vertex* dPdu, Vertex* dPdv, Vertex* ddPdudu, Vertex* ddPdvdv, Vertex* ddPdudv, const float dscale = 1.0f) const
  181. {
  182. if (P) {
  183. *P = eval(u,v);
  184. }
  185. if (dPdu) {
  186. assert(dPdu); *dPdu = eval_du(u,v)*dscale;
  187. assert(dPdv); *dPdv = eval_dv(u,v)*dscale;
  188. }
  189. if (ddPdudu) {
  190. assert(ddPdudu); *ddPdudu = eval_dudu(u,v)*sqr(dscale);
  191. assert(ddPdvdv); *ddPdvdv = eval_dvdv(u,v)*sqr(dscale);
  192. assert(ddPdudv); *ddPdudv = eval_dudv(u,v)*sqr(dscale);
  193. }
  194. }
  195. template<class vfloat>
  196. __forceinline vfloat eval(const size_t i, const vfloat& uu, const vfloat& vv, const Vec4<vfloat>& u_n, const Vec4<vfloat>& v_n) const
  197. {
  198. const vfloat curve0_x = v_n[0] * vfloat(matrix[0][0][i]) + v_n[1] * vfloat(matrix[1][0][i]) + v_n[2] * vfloat(matrix[2][0][i]) + v_n[3] * vfloat(matrix[3][0][i]);
  199. const vfloat curve1_x = v_n[0] * vfloat(matrix[0][1][i]) + v_n[1] * vfloat(matrix[1][1][i]) + v_n[2] * vfloat(matrix[2][1][i]) + v_n[3] * vfloat(matrix[3][1][i]);
  200. const vfloat curve2_x = v_n[0] * vfloat(matrix[0][2][i]) + v_n[1] * vfloat(matrix[1][2][i]) + v_n[2] * vfloat(matrix[2][2][i]) + v_n[3] * vfloat(matrix[3][2][i]);
  201. const vfloat curve3_x = v_n[0] * vfloat(matrix[0][3][i]) + v_n[1] * vfloat(matrix[1][3][i]) + v_n[2] * vfloat(matrix[2][3][i]) + v_n[3] * vfloat(matrix[3][3][i]);
  202. return u_n[0] * curve0_x + u_n[1] * curve1_x + u_n[2] * curve2_x + u_n[3] * curve3_x;
  203. }
  204. template<typename vbool, typename vfloat>
  205. __forceinline void eval(const vbool& valid, const vfloat& uu, const vfloat& vv,
  206. float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv,
  207. const float dscale, const size_t dstride, const size_t N) const
  208. {
  209. if (P) {
  210. const Vec4<vfloat> u_n = BezierBasis::eval(uu);
  211. const Vec4<vfloat> v_n = BezierBasis::eval(vv);
  212. for (size_t i=0; i<N; i++) vfloat::store(valid,P+i*dstride,eval(i,uu,vv,u_n,v_n));
  213. }
  214. if (dPdu)
  215. {
  216. {
  217. assert(dPdu);
  218. const Vec4<vfloat> u_n = BezierBasis::derivative(uu);
  219. const Vec4<vfloat> v_n = BezierBasis::eval(vv);
  220. for (size_t i=0; i<N; i++) vfloat::store(valid,dPdu+i*dstride,eval(i,uu,vv,u_n,v_n)*dscale);
  221. }
  222. {
  223. assert(dPdv);
  224. const Vec4<vfloat> u_n = BezierBasis::eval(uu);
  225. const Vec4<vfloat> v_n = BezierBasis::derivative(vv);
  226. for (size_t i=0; i<N; i++) vfloat::store(valid,dPdv+i*dstride,eval(i,uu,vv,u_n,v_n)*dscale);
  227. }
  228. }
  229. if (ddPdudu)
  230. {
  231. {
  232. assert(ddPdudu);
  233. const Vec4<vfloat> u_n = BezierBasis::derivative2(uu);
  234. const Vec4<vfloat> v_n = BezierBasis::eval(vv);
  235. for (size_t i=0; i<N; i++) vfloat::store(valid,ddPdudu+i*dstride,eval(i,uu,vv,u_n,v_n)*sqr(dscale));
  236. }
  237. {
  238. assert(ddPdvdv);
  239. const Vec4<vfloat> u_n = BezierBasis::eval(uu);
  240. const Vec4<vfloat> v_n = BezierBasis::derivative2(vv);
  241. for (size_t i=0; i<N; i++) vfloat::store(valid,ddPdvdv+i*dstride,eval(i,uu,vv,u_n,v_n)*sqr(dscale));
  242. }
  243. {
  244. assert(ddPdudv);
  245. const Vec4<vfloat> u_n = BezierBasis::derivative(uu);
  246. const Vec4<vfloat> v_n = BezierBasis::derivative(vv);
  247. for (size_t i=0; i<N; i++) vfloat::store(valid,ddPdudv+i*dstride,eval(i,uu,vv,u_n,v_n)*sqr(dscale));
  248. }
  249. }
  250. }
  251. template<typename T>
  252. static __forceinline Vec3<T> eval(const Vertex matrix[4][4], const T& uu, const T& vv)
  253. {
  254. const T one_minus_uu = 1.0f - uu;
  255. const T one_minus_vv = 1.0f - vv;
  256. const T B0_u = one_minus_uu * one_minus_uu * one_minus_uu;
  257. const T B0_v = one_minus_vv * one_minus_vv * one_minus_vv;
  258. const T B1_u = 3.0f * (one_minus_uu * uu * one_minus_uu);
  259. const T B1_v = 3.0f * (one_minus_vv * vv * one_minus_vv);
  260. const T B2_u = 3.0f * (uu * one_minus_uu * uu);
  261. const T B2_v = 3.0f * (vv * one_minus_vv * vv);
  262. const T B3_u = uu * uu * uu;
  263. const T B3_v = vv * vv * vv;
  264. const T x =
  265. madd(B0_v,madd(B0_u,matrix[0][0].x,madd(B1_u,matrix[0][1].x,madd(B2_u,matrix[0][2].x,B3_u*matrix[0][3].x))),
  266. madd(B1_v,madd(B0_u,matrix[1][0].x,madd(B1_u,matrix[1][1].x,madd(B2_u,matrix[1][2].x,B3_u*matrix[1][3].x))),
  267. madd(B2_v,madd(B0_u,matrix[2][0].x,madd(B1_u,matrix[2][1].x,madd(B2_u,matrix[2][2].x,B3_u*matrix[2][3].x))),
  268. B3_v*madd(B0_u,matrix[3][0].x,madd(B1_u,matrix[3][1].x,madd(B2_u,matrix[3][2].x,B3_u*matrix[3][3].x))))));
  269. const T y =
  270. madd(B0_v,madd(B0_u,matrix[0][0].y,madd(B1_u,matrix[0][1].y,madd(B2_u,matrix[0][2].y,B3_u*matrix[0][3].y))),
  271. madd(B1_v,madd(B0_u,matrix[1][0].y,madd(B1_u,matrix[1][1].y,madd(B2_u,matrix[1][2].y,B3_u*matrix[1][3].y))),
  272. madd(B2_v,madd(B0_u,matrix[2][0].y,madd(B1_u,matrix[2][1].y,madd(B2_u,matrix[2][2].y,B3_u*matrix[2][3].y))),
  273. B3_v*madd(B0_u,matrix[3][0].y,madd(B1_u,matrix[3][1].y,madd(B2_u,matrix[3][2].y,B3_u*matrix[3][3].y))))));
  274. const T z =
  275. madd(B0_v,madd(B0_u,matrix[0][0].z,madd(B1_u,matrix[0][1].z,madd(B2_u,matrix[0][2].z,B3_u*matrix[0][3].z))),
  276. madd(B1_v,madd(B0_u,matrix[1][0].z,madd(B1_u,matrix[1][1].z,madd(B2_u,matrix[1][2].z,B3_u*matrix[1][3].z))),
  277. madd(B2_v,madd(B0_u,matrix[2][0].z,madd(B1_u,matrix[2][1].z,madd(B2_u,matrix[2][2].z,B3_u*matrix[2][3].z))),
  278. B3_v*madd(B0_u,matrix[3][0].z,madd(B1_u,matrix[3][1].z,madd(B2_u,matrix[3][2].z,B3_u*matrix[3][3].z))))));
  279. return Vec3<T>(x,y,z);
  280. }
  281. template<typename vfloat>
  282. __forceinline Vec3<vfloat> eval(const vfloat& uu, const vfloat& vv) const {
  283. return eval(matrix,uu,vv);
  284. }
  285. template<class T>
  286. static __forceinline Vec3<T> normal(const Vertex matrix[4][4], const T& uu, const T& vv)
  287. {
  288. const Vec3<T> matrix_00 = Vec3<T>(matrix[0][0].x,matrix[0][0].y,matrix[0][0].z);
  289. const Vec3<T> matrix_01 = Vec3<T>(matrix[0][1].x,matrix[0][1].y,matrix[0][1].z);
  290. const Vec3<T> matrix_02 = Vec3<T>(matrix[0][2].x,matrix[0][2].y,matrix[0][2].z);
  291. const Vec3<T> matrix_03 = Vec3<T>(matrix[0][3].x,matrix[0][3].y,matrix[0][3].z);
  292. const Vec3<T> matrix_10 = Vec3<T>(matrix[1][0].x,matrix[1][0].y,matrix[1][0].z);
  293. const Vec3<T> matrix_11 = Vec3<T>(matrix[1][1].x,matrix[1][1].y,matrix[1][1].z);
  294. const Vec3<T> matrix_12 = Vec3<T>(matrix[1][2].x,matrix[1][2].y,matrix[1][2].z);
  295. const Vec3<T> matrix_13 = Vec3<T>(matrix[1][3].x,matrix[1][3].y,matrix[1][3].z);
  296. const Vec3<T> matrix_20 = Vec3<T>(matrix[2][0].x,matrix[2][0].y,matrix[2][0].z);
  297. const Vec3<T> matrix_21 = Vec3<T>(matrix[2][1].x,matrix[2][1].y,matrix[2][1].z);
  298. const Vec3<T> matrix_22 = Vec3<T>(matrix[2][2].x,matrix[2][2].y,matrix[2][2].z);
  299. const Vec3<T> matrix_23 = Vec3<T>(matrix[2][3].x,matrix[2][3].y,matrix[2][3].z);
  300. const Vec3<T> matrix_30 = Vec3<T>(matrix[3][0].x,matrix[3][0].y,matrix[3][0].z);
  301. const Vec3<T> matrix_31 = Vec3<T>(matrix[3][1].x,matrix[3][1].y,matrix[3][1].z);
  302. const Vec3<T> matrix_32 = Vec3<T>(matrix[3][2].x,matrix[3][2].y,matrix[3][2].z);
  303. const Vec3<T> matrix_33 = Vec3<T>(matrix[3][3].x,matrix[3][3].y,matrix[3][3].z);
  304. /* tangentU */
  305. const Vec3<T> col0 = deCasteljau(vv, matrix_00, matrix_10, matrix_20, matrix_30);
  306. const Vec3<T> col1 = deCasteljau(vv, matrix_01, matrix_11, matrix_21, matrix_31);
  307. const Vec3<T> col2 = deCasteljau(vv, matrix_02, matrix_12, matrix_22, matrix_32);
  308. const Vec3<T> col3 = deCasteljau(vv, matrix_03, matrix_13, matrix_23, matrix_33);
  309. const Vec3<T> tangentU = deCasteljau_tangent(uu, col0, col1, col2, col3);
  310. /* tangentV */
  311. const Vec3<T> row0 = deCasteljau(uu, matrix_00, matrix_01, matrix_02, matrix_03);
  312. const Vec3<T> row1 = deCasteljau(uu, matrix_10, matrix_11, matrix_12, matrix_13);
  313. const Vec3<T> row2 = deCasteljau(uu, matrix_20, matrix_21, matrix_22, matrix_23);
  314. const Vec3<T> row3 = deCasteljau(uu, matrix_30, matrix_31, matrix_32, matrix_33);
  315. const Vec3<T> tangentV = deCasteljau_tangent(vv, row0, row1, row2, row3);
  316. /* normal = tangentU x tangentV */
  317. const Vec3<T> n = cross(tangentV,tangentU);
  318. return n;
  319. }
  320. template<typename vfloat>
  321. __forceinline Vec3<vfloat> normal(const vfloat& uu, const vfloat& vv) const {
  322. return normal(matrix,uu,vv);
  323. }
  324. };
  325. typedef BezierPatchT<Vec3fa,Vec3fa_t> BezierPatch3fa;
  326. }