feature_adaptive_eval_grid.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  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 "patch.h"
  18. #include "catmullclark_patch.h"
  19. #include "bspline_patch.h"
  20. #include "gregory_patch.h"
  21. #include "tessellation.h"
  22. namespace embree
  23. {
  24. namespace isa
  25. {
  26. struct FeatureAdaptiveEvalGrid
  27. {
  28. typedef CatmullClark1Ring3fa CatmullClarkRing;
  29. typedef CatmullClarkPatch3fa CatmullClarkPatch;
  30. typedef BilinearPatch3fa BilinearPatch;
  31. typedef BSplinePatch3fa BSplinePatch;
  32. typedef BezierPatch3fa BezierPatch;
  33. typedef GregoryPatch3fa GregoryPatch;
  34. private:
  35. const unsigned x0,x1;
  36. const unsigned y0,y1;
  37. const unsigned swidth,sheight;
  38. const float rcp_swidth, rcp_sheight;
  39. float* const Px;
  40. float* const Py;
  41. float* const Pz;
  42. float* const U;
  43. float* const V;
  44. float* const Nx;
  45. float* const Ny;
  46. float* const Nz;
  47. const unsigned dwidth;
  48. //const unsigned dheight;
  49. unsigned count;
  50. public:
  51. FeatureAdaptiveEvalGrid (const GeneralCatmullClarkPatch3fa& patch, unsigned subPatch,
  52. const unsigned x0, const unsigned x1, const unsigned y0, const unsigned y1, const unsigned swidth, const unsigned sheight,
  53. float* Px, float* Py, float* Pz, float* U, float* V,
  54. float* Nx, float* Ny, float* Nz,
  55. const unsigned dwidth, const unsigned dheight)
  56. : x0(x0), x1(x1), y0(y0), y1(y1), swidth(swidth), sheight(sheight), rcp_swidth(1.0f/(swidth-1.0f)), rcp_sheight(1.0f/(sheight-1.0f)),
  57. Px(Px), Py(Py), Pz(Pz), U(U), V(V), Nx(Nx), Ny(Ny), Nz(Nz), dwidth(dwidth), /*dheight(dheight),*/ count(0)
  58. {
  59. assert(swidth < (2<<20) && sheight < (2<<20));
  60. const BBox2f srange(Vec2f(0.0f,0.0f),Vec2f(float(swidth-1),float(sheight-1)));
  61. const BBox2f erange(Vec2f((float)x0,(float)y0),Vec2f((float)x1,(float)y1));
  62. /* convert into standard quad patch if possible */
  63. if (likely(patch.isQuadPatch()))
  64. {
  65. CatmullClarkPatch3fa qpatch; patch.init(qpatch);
  66. eval(qpatch, srange, erange, 0);
  67. assert(count == (x1-x0+1)*(y1-y0+1));
  68. return;
  69. }
  70. /* subdivide patch */
  71. unsigned N;
  72. array_t<CatmullClarkPatch3fa,GeneralCatmullClarkPatch3fa::SIZE> patches;
  73. patch.subdivide(patches,N);
  74. if (N == 4)
  75. {
  76. const Vec2f c = srange.center();
  77. const BBox2f srange0(srange.lower,c);
  78. const BBox2f srange1(Vec2f(c.x,srange.lower.y),Vec2f(srange.upper.x,c.y));
  79. const BBox2f srange2(c,srange.upper);
  80. const BBox2f srange3(Vec2f(srange.lower.x,c.y),Vec2f(c.x,srange.upper.y));
  81. #if PATCH_USE_GREGORY == 2
  82. BezierCurve3fa borders[GeneralCatmullClarkPatch3fa::SIZE]; patch.getLimitBorder(borders);
  83. BezierCurve3fa border0l,border0r; borders[0].subdivide(border0l,border0r);
  84. BezierCurve3fa border1l,border1r; borders[1].subdivide(border1l,border1r);
  85. BezierCurve3fa border2l,border2r; borders[2].subdivide(border2l,border2r);
  86. BezierCurve3fa border3l,border3r; borders[3].subdivide(border3l,border3r);
  87. GeneralCatmullClarkPatch3fa::fix_quad_ring_order(patches);
  88. eval(patches[0],srange0,intersect(srange0,erange),1,&border0l,nullptr,nullptr,&border3r);
  89. eval(patches[1],srange1,intersect(srange1,erange),1,&border0r,&border1l,nullptr,nullptr);
  90. eval(patches[2],srange2,intersect(srange2,erange),1,nullptr,&border1r,&border2l,nullptr);
  91. eval(patches[3],srange3,intersect(srange3,erange),1,nullptr,nullptr,&border2r,&border3l);
  92. #else
  93. GeneralCatmullClarkPatch3fa::fix_quad_ring_order(patches);
  94. eval(patches[0],srange0,intersect(srange0,erange),1);
  95. eval(patches[1],srange1,intersect(srange1,erange),1);
  96. eval(patches[2],srange2,intersect(srange2,erange),1);
  97. eval(patches[3],srange3,intersect(srange3,erange),1);
  98. #endif
  99. }
  100. else
  101. {
  102. assert(subPatch < N);
  103. #if PATCH_USE_GREGORY == 2
  104. BezierCurve3fa borders[2]; patch.getLimitBorder(borders,subPatch);
  105. BezierCurve3fa border0l,border0r; borders[0].subdivide(border0l,border0r);
  106. BezierCurve3fa border2l,border2r; borders[1].subdivide(border2l,border2r);
  107. eval(patches[subPatch], srange, erange, 1, &border0l, nullptr, nullptr, &border2r);
  108. #else
  109. eval(patches[subPatch], srange, erange, 1);
  110. #endif
  111. }
  112. assert(count == (x1-x0+1)*(y1-y0+1));
  113. }
  114. FeatureAdaptiveEvalGrid (const CatmullClarkPatch3fa& patch,
  115. const BBox2f& srange, const BBox2f& erange, const unsigned depth,
  116. const unsigned x0, const unsigned x1, const unsigned y0, const unsigned y1, const unsigned swidth, const unsigned sheight,
  117. float* Px, float* Py, float* Pz, float* U, float* V,
  118. float* Nx, float* Ny, float* Nz,
  119. const unsigned dwidth, const unsigned dheight)
  120. : x0(x0), x1(x1), y0(y0), y1(y1), swidth(swidth), sheight(sheight), rcp_swidth(1.0f/(swidth-1.0f)), rcp_sheight(1.0f/(sheight-1.0f)),
  121. Px(Px), Py(Py), Pz(Pz), U(U), V(V), Nx(Nx), Ny(Ny), Nz(Nz), dwidth(dwidth), /*dheight(dheight),*/ count(0)
  122. {
  123. eval(patch,srange,erange,depth);
  124. }
  125. template<typename Patch>
  126. void evalLocalGrid(const Patch& patch, const BBox2f& srange, const int lx0, const int lx1, const int ly0, const int ly1)
  127. {
  128. const float scale_x = rcp(srange.upper.x-srange.lower.x);
  129. const float scale_y = rcp(srange.upper.y-srange.lower.y);
  130. count += (lx1-lx0)*(ly1-ly0);
  131. #if 0
  132. for (unsigned iy=ly0; iy<ly1; iy++) {
  133. for (unsigned ix=lx0; ix<lx1; ix++) {
  134. const float lu = select(ix == swidth -1, float(1.0f), (float(ix)-srange.lower.x)*scale_x);
  135. const float lv = select(iy == sheight-1, float(1.0f), (float(iy)-srange.lower.y)*scale_y);
  136. const Vec3fa p = patch.eval(lu,lv);
  137. const float u = float(ix)*rcp_swidth;
  138. const float v = float(iy)*rcp_sheight;
  139. const int ofs = (iy-y0)*dwidth+(ix-x0);
  140. Px[ofs] = p.x;
  141. Py[ofs] = p.y;
  142. Pz[ofs] = p.z;
  143. U[ofs] = u;
  144. V[ofs] = v;
  145. }
  146. }
  147. #else
  148. foreach2(lx0,lx1,ly0,ly1,[&](const vboolx& valid, const vintx& ix, const vintx& iy) {
  149. const vfloatx lu = select(ix == swidth -1, vfloatx(1.0f), (vfloatx(ix)-srange.lower.x)*scale_x);
  150. const vfloatx lv = select(iy == sheight-1, vfloatx(1.0f), (vfloatx(iy)-srange.lower.y)*scale_y);
  151. const Vec3<vfloatx> p = patch.eval(lu,lv);
  152. Vec3<vfloatx> n = zero;
  153. if (unlikely(Nx != nullptr)) n = normalize_safe(patch.normal(lu,lv));
  154. const vfloatx u = vfloatx(ix)*rcp_swidth;
  155. const vfloatx v = vfloatx(iy)*rcp_sheight;
  156. const vintx ofs = (iy-y0)*dwidth+(ix-x0);
  157. if (likely(all(valid)) && all(iy==iy[0])) {
  158. const unsigned ofs2 = ofs[0];
  159. vfloatx::storeu(Px+ofs2,p.x);
  160. vfloatx::storeu(Py+ofs2,p.y);
  161. vfloatx::storeu(Pz+ofs2,p.z);
  162. vfloatx::storeu(U+ofs2,u);
  163. vfloatx::storeu(V+ofs2,v);
  164. if (unlikely(Nx != nullptr)) {
  165. vfloatx::storeu(Nx+ofs2,n.x);
  166. vfloatx::storeu(Ny+ofs2,n.y);
  167. vfloatx::storeu(Nz+ofs2,n.z);
  168. }
  169. } else {
  170. foreach_unique_index(valid,iy,[&](const vboolx& valid, const int iy0, const int j) {
  171. const unsigned ofs2 = ofs[j]-j;
  172. vfloatx::storeu(valid,Px+ofs2,p.x);
  173. vfloatx::storeu(valid,Py+ofs2,p.y);
  174. vfloatx::storeu(valid,Pz+ofs2,p.z);
  175. vfloatx::storeu(valid,U+ofs2,u);
  176. vfloatx::storeu(valid,V+ofs2,v);
  177. if (unlikely(Nx != nullptr)) {
  178. vfloatx::storeu(valid,Nx+ofs2,n.x);
  179. vfloatx::storeu(valid,Ny+ofs2,n.y);
  180. vfloatx::storeu(valid,Nz+ofs2,n.z);
  181. }
  182. });
  183. }
  184. });
  185. #endif
  186. }
  187. __forceinline bool final(const CatmullClarkPatch3fa& patch, const CatmullClarkRing::Type type, unsigned depth)
  188. {
  189. const unsigned max_eval_depth = (type & CatmullClarkRing::TYPE_CREASES) ? PATCH_MAX_EVAL_DEPTH_CREASE : PATCH_MAX_EVAL_DEPTH_IRREGULAR;
  190. //#if PATCH_MIN_RESOLUTION
  191. // return patch.isFinalResolution(PATCH_MIN_RESOLUTION) || depth>=max_eval_depth;
  192. //#else
  193. return depth>=max_eval_depth;
  194. //#endif
  195. }
  196. void eval(const CatmullClarkPatch3fa& patch, const BBox2f& srange, const BBox2f& erange, const unsigned depth,
  197. const BezierCurve3fa* border0 = nullptr, const BezierCurve3fa* border1 = nullptr, const BezierCurve3fa* border2 = nullptr, const BezierCurve3fa* border3 = nullptr)
  198. {
  199. if (erange.empty())
  200. return;
  201. int lx0 = (int) ceilf(erange.lower.x);
  202. int lx1 = (int) ceilf(erange.upper.x) + (erange.upper.x == x1 && (srange.lower.x < erange.upper.x || erange.upper.x == 0));
  203. int ly0 = (int) ceilf(erange.lower.y);
  204. int ly1 = (int) ceilf(erange.upper.y) + (erange.upper.y == y1 && (srange.lower.y < erange.upper.y || erange.upper.y == 0));
  205. if (lx0 >= lx1 || ly0 >= ly1) return;
  206. CatmullClarkPatch::Type ty = patch.type();
  207. if (unlikely(final(patch,ty,depth)))
  208. {
  209. if (ty & CatmullClarkRing::TYPE_REGULAR) {
  210. RegularPatch rpatch(patch,border0,border1,border2,border3);
  211. evalLocalGrid(rpatch,srange,lx0,lx1,ly0,ly1);
  212. return;
  213. } else {
  214. IrregularFillPatch ipatch(patch,border0,border1,border2,border3);
  215. evalLocalGrid(ipatch,srange,lx0,lx1,ly0,ly1);
  216. return;
  217. }
  218. }
  219. else if (ty & CatmullClarkRing::TYPE_REGULAR_CREASES) {
  220. assert(depth > 0);
  221. RegularPatch rpatch(patch,border0,border1,border2,border3);
  222. evalLocalGrid(rpatch,srange,lx0,lx1,ly0,ly1);
  223. return;
  224. }
  225. #if PATCH_USE_GREGORY == 2
  226. else if (ty & CatmullClarkRing::TYPE_GREGORY_CREASES) {
  227. assert(depth > 0);
  228. GregoryPatch gpatch(patch,border0,border1,border2,border3);
  229. evalLocalGrid(gpatch,srange,lx0,lx1,ly0,ly1);
  230. }
  231. #endif
  232. else
  233. {
  234. array_t<CatmullClarkPatch3fa,4> patches;
  235. patch.subdivide(patches);
  236. const Vec2f c = srange.center();
  237. const BBox2f srange0(srange.lower,c);
  238. const BBox2f srange1(Vec2f(c.x,srange.lower.y),Vec2f(srange.upper.x,c.y));
  239. const BBox2f srange2(c,srange.upper);
  240. const BBox2f srange3(Vec2f(srange.lower.x,c.y),Vec2f(c.x,srange.upper.y));
  241. eval(patches[0],srange0,intersect(srange0,erange),depth+1);
  242. eval(patches[1],srange1,intersect(srange1,erange),depth+1);
  243. eval(patches[2],srange2,intersect(srange2,erange),depth+1);
  244. eval(patches[3],srange3,intersect(srange3,erange),depth+1);
  245. }
  246. }
  247. };
  248. template<typename Eval, typename Patch>
  249. bool stitch_col(const Patch& patch, int subPatch,
  250. const bool right, const unsigned y0, const unsigned y1, const int fine_y, const int coarse_y,
  251. float* Px, float* Py, float* Pz, float* U, float* V, float* Nx, float* Ny, float* Nz, const unsigned dx0, const unsigned dwidth, const unsigned dheight)
  252. {
  253. assert(coarse_y <= fine_y);
  254. if (likely(fine_y == coarse_y))
  255. return false;
  256. const unsigned y0s = stitch(y0,fine_y,coarse_y);
  257. const unsigned y1s = stitch(y1,fine_y,coarse_y);
  258. const unsigned M = y1s-y0s+1;
  259. dynamic_large_stack_array(float,px,M,64*sizeof(float));
  260. dynamic_large_stack_array(float,py,M,64*sizeof(float));
  261. dynamic_large_stack_array(float,pz,M,64*sizeof(float));
  262. dynamic_large_stack_array(float,u,M,64*sizeof(float));
  263. dynamic_large_stack_array(float,v,M,64*sizeof(float));
  264. dynamic_large_stack_array(float,nx,M,64*sizeof(float));
  265. dynamic_large_stack_array(float,ny,M,64*sizeof(float));
  266. dynamic_large_stack_array(float,nz,M,64*sizeof(float));
  267. const bool has_Nxyz = Nx; assert(!Nx || (Ny && Nz));
  268. Eval(patch,subPatch, right,right, y0s,y1s, 2,coarse_y+1, px,py,pz,u,v,
  269. has_Nxyz ? (float*)nx : nullptr,has_Nxyz ? (float*)ny : nullptr ,has_Nxyz ? (float*)nz : nullptr, 1,4097);
  270. for (unsigned y=y0; y<=y1; y++)
  271. {
  272. const unsigned ys = stitch(y,fine_y,coarse_y)-y0s;
  273. Px[(y-y0)*dwidth+dx0] = px[ys];
  274. Py[(y-y0)*dwidth+dx0] = py[ys];
  275. Pz[(y-y0)*dwidth+dx0] = pz[ys];
  276. U [(y-y0)*dwidth+dx0] = u[ys];
  277. V [(y-y0)*dwidth+dx0] = v[ys];
  278. if (unlikely(has_Nxyz)) {
  279. Nx[(y-y0)*dwidth+dx0] = nx[ys];
  280. Ny[(y-y0)*dwidth+dx0] = ny[ys];
  281. Nz[(y-y0)*dwidth+dx0] = nz[ys];
  282. }
  283. }
  284. return true;
  285. }
  286. template<typename Eval, typename Patch>
  287. bool stitch_row(const Patch& patch, int subPatch,
  288. const bool bottom, const unsigned x0, const unsigned x1, const int fine_x, const int coarse_x,
  289. float* Px, float* Py, float* Pz, float* U, float* V, float* Nx, float* Ny, float* Nz, const unsigned dy0, const unsigned dwidth, const unsigned dheight)
  290. {
  291. assert(coarse_x <= fine_x);
  292. if (likely(fine_x == coarse_x))
  293. return false;
  294. const unsigned x0s = stitch(x0,fine_x,coarse_x);
  295. const unsigned x1s = stitch(x1,fine_x,coarse_x);
  296. const unsigned M = x1s-x0s+1;
  297. dynamic_large_stack_array(float,px,M,64*sizeof(float));
  298. dynamic_large_stack_array(float,py,M,64*sizeof(float));
  299. dynamic_large_stack_array(float,pz,M,64*sizeof(float));
  300. dynamic_large_stack_array(float,u,M,64*sizeof(float));
  301. dynamic_large_stack_array(float,v,M,64*sizeof(float));
  302. dynamic_large_stack_array(float,nx,M,64*sizeof(float));
  303. dynamic_large_stack_array(float,ny,M,64*sizeof(float));
  304. dynamic_large_stack_array(float,nz,M,64*sizeof(float));
  305. const bool has_Nxyz = Nx; assert(!Nx || (Ny && Nz));
  306. Eval(patch,subPatch, x0s,x1s, bottom,bottom, coarse_x+1,2, px,py,pz,u,v,
  307. has_Nxyz ? (float*)nx :nullptr, has_Nxyz ? (float*)ny : nullptr , has_Nxyz ? (float*)nz : nullptr, 4097,1);
  308. for (unsigned x=x0; x<=x1; x++)
  309. {
  310. const unsigned xs = stitch(x,fine_x,coarse_x)-x0s;
  311. Px[dy0*dwidth+x-x0] = px[xs];
  312. Py[dy0*dwidth+x-x0] = py[xs];
  313. Pz[dy0*dwidth+x-x0] = pz[xs];
  314. U [dy0*dwidth+x-x0] = u[xs];
  315. V [dy0*dwidth+x-x0] = v[xs];
  316. if (unlikely(has_Nxyz)) {
  317. Nx[dy0*dwidth+x-x0] = nx[xs];
  318. Ny[dy0*dwidth+x-x0] = ny[xs];
  319. Nz[dy0*dwidth+x-x0] = nz[xs];
  320. }
  321. }
  322. return true;
  323. }
  324. template<typename Eval, typename Patch>
  325. void feature_adaptive_eval_grid (const Patch& patch, unsigned subPatch, const float levels[4],
  326. const unsigned x0, const unsigned x1, const unsigned y0, const unsigned y1, const unsigned swidth, const unsigned sheight,
  327. float* Px, float* Py, float* Pz, float* U, float* V, float* Nx, float* Ny, float* Nz, const unsigned dwidth, const unsigned dheight)
  328. {
  329. bool sl = false, sr = false, st = false, sb = false;
  330. if (levels) {
  331. sl = x0 == 0 && stitch_col<Eval,Patch>(patch,subPatch,0,y0,y1,sheight-1,int(levels[3]), Px,Py,Pz,U,V,Nx,Ny,Nz, 0 ,dwidth,dheight);
  332. sr = x1 == swidth-1 && stitch_col<Eval,Patch>(patch,subPatch,1,y0,y1,sheight-1,int(levels[1]), Px,Py,Pz,U,V,Nx,Ny,Nz, x1-x0,dwidth,dheight);
  333. st = y0 == 0 && stitch_row<Eval,Patch>(patch,subPatch,0,x0,x1,swidth-1,int(levels[0]), Px,Py,Pz,U,V,Nx,Ny,Nz, 0 ,dwidth,dheight);
  334. sb = y1 == sheight-1 && stitch_row<Eval,Patch>(patch,subPatch,1,x0,x1,swidth-1,int(levels[2]), Px,Py,Pz,U,V,Nx,Ny,Nz, y1-y0,dwidth,dheight);
  335. }
  336. const unsigned ofs = st*dwidth+sl;
  337. Eval(patch,subPatch,x0+sl,x1-sr,y0+st,y1-sb, swidth,sheight, Px+ofs,Py+ofs,Pz+ofs,U+ofs,V+ofs,Nx?Nx+ofs:nullptr,Ny?Ny+ofs:nullptr,Nz?Nz+ofs:nullptr, dwidth,dheight);
  338. }
  339. }
  340. }