patch_eval_grid.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  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 "feature_adaptive_eval_grid.h"
  19. namespace embree
  20. {
  21. namespace isa
  22. {
  23. struct PatchEvalGrid
  24. {
  25. typedef Patch3fa Patch;
  26. typedef Patch::Ref Ref;
  27. typedef GeneralCatmullClarkPatch3fa GeneralCatmullClarkPatch;
  28. typedef CatmullClarkPatch3fa CatmullClarkPatch;
  29. typedef BSplinePatch3fa BSplinePatch;
  30. typedef BezierPatch3fa BezierPatch;
  31. typedef GregoryPatch3fa GregoryPatch;
  32. typedef BilinearPatch3fa BilinearPatch;
  33. private:
  34. const unsigned x0,x1;
  35. const unsigned y0,y1;
  36. const unsigned swidth,sheight;
  37. const float rcp_swidth, rcp_sheight;
  38. float* const Px;
  39. float* const Py;
  40. float* const Pz;
  41. float* const U;
  42. float* const V;
  43. float* const Nx;
  44. float* const Ny;
  45. float* const Nz;
  46. const unsigned dwidth,dheight;
  47. unsigned count;
  48. public:
  49. PatchEvalGrid (Ref patch, unsigned subPatch,
  50. const unsigned x0, const unsigned x1, const unsigned y0, const unsigned y1, const unsigned swidth, const unsigned sheight,
  51. float* Px, float* Py, float* Pz, float* U, float* V,
  52. float* Nx, float* Ny, float* Nz,
  53. const unsigned dwidth, const unsigned dheight)
  54. : 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)),
  55. Px(Px), Py(Py), Pz(Pz), U(U), V(V), Nx(Nx), Ny(Ny), Nz(Nz), dwidth(dwidth), dheight(dheight), count(0)
  56. {
  57. assert(swidth < (2<<20) && sheight < (2<<20));
  58. const BBox2f srange(Vec2f(0.0f,0.0f),Vec2f(float(swidth-1),float(sheight-1)));
  59. const BBox2f erange(Vec2f(float(x0),float(y0)),Vec2f((float)x1,(float)y1));
  60. bool done MAYBE_UNUSED = eval(patch,subPatch,srange,erange);
  61. assert(done);
  62. assert(count == (x1-x0+1)*(y1-y0+1));
  63. }
  64. template<typename Patch>
  65. __forceinline void evalLocalGrid(const Patch* patch, const BBox2f& srange, const int lx0, const int lx1, const int ly0, const int ly1)
  66. {
  67. const float scale_x = rcp(srange.upper.x-srange.lower.x);
  68. const float scale_y = rcp(srange.upper.y-srange.lower.y);
  69. count += (lx1-lx0)*(ly1-ly0);
  70. #if 0
  71. for (unsigned iy=ly0; iy<ly1; iy++) {
  72. for (unsigned ix=lx0; ix<lx1; ix++) {
  73. const float lu = select(ix == swidth -1, float(1.0f), (float(ix)-srange.lower.x)*scale_x);
  74. const float lv = select(iy == sheight-1, float(1.0f), (float(iy)-srange.lower.y)*scale_y);
  75. const Vec3fa p = patch->patch.eval(lu,lv);
  76. const float u = float(ix)*rcp_swidth;
  77. const float v = float(iy)*rcp_sheight;
  78. const int ofs = (iy-y0)*dwidth+(ix-x0);
  79. Px[ofs] = p.x;
  80. Py[ofs] = p.y;
  81. Pz[ofs] = p.z;
  82. U[ofs] = u;
  83. V[ofs] = v;
  84. }
  85. }
  86. #else
  87. foreach2(lx0,lx1,ly0,ly1,[&](const vboolx& valid, const vintx& ix, const vintx& iy) {
  88. const vfloatx lu = select(ix == swidth -1, vfloatx(1.0f), (vfloatx(ix)-srange.lower.x)*scale_x);
  89. const vfloatx lv = select(iy == sheight-1, vfloatx(1.0f), (vfloatx(iy)-srange.lower.y)*scale_y);
  90. const Vec3<vfloatx> p = patch->patch.eval(lu,lv);
  91. Vec3<vfloatx> n = zero;
  92. if (unlikely(Nx != nullptr)) n = normalize_safe(patch->patch.normal(lu,lv));
  93. const vfloatx u = vfloatx(ix)*rcp_swidth;
  94. const vfloatx v = vfloatx(iy)*rcp_sheight;
  95. const vintx ofs = (iy-y0)*dwidth+(ix-x0);
  96. if (likely(all(valid)) && all(iy==iy[0])) {
  97. const unsigned ofs2 = ofs[0];
  98. vfloatx::storeu(Px+ofs2,p.x);
  99. vfloatx::storeu(Py+ofs2,p.y);
  100. vfloatx::storeu(Pz+ofs2,p.z);
  101. vfloatx::storeu(U+ofs2,u);
  102. vfloatx::storeu(V+ofs2,v);
  103. if (unlikely(Nx != nullptr)) {
  104. vfloatx::storeu(Nx+ofs2,n.x);
  105. vfloatx::storeu(Ny+ofs2,n.y);
  106. vfloatx::storeu(Nz+ofs2,n.z);
  107. }
  108. } else {
  109. foreach_unique_index(valid,iy,[&](const vboolx& valid, const int iy0, const int j) {
  110. const unsigned ofs2 = ofs[j]-j;
  111. vfloatx::storeu(valid,Px+ofs2,p.x);
  112. vfloatx::storeu(valid,Py+ofs2,p.y);
  113. vfloatx::storeu(valid,Pz+ofs2,p.z);
  114. vfloatx::storeu(valid,U+ofs2,u);
  115. vfloatx::storeu(valid,V+ofs2,v);
  116. if (unlikely(Nx != nullptr)) {
  117. vfloatx::storeu(valid,Nx+ofs2,n.x);
  118. vfloatx::storeu(valid,Ny+ofs2,n.y);
  119. vfloatx::storeu(valid,Nz+ofs2,n.z);
  120. }
  121. });
  122. }
  123. });
  124. #endif
  125. }
  126. bool eval(Ref This, const BBox2f& srange, const BBox2f& erange, const unsigned depth)
  127. {
  128. if (erange.empty())
  129. return true;
  130. const int lx0 = (int) ceilf(erange.lower.x);
  131. const int lx1 = (int) ceilf(erange.upper.x) + (erange.upper.x == x1 && (srange.lower.x < erange.upper.x || erange.upper.x == 0));
  132. const int ly0 = (int) ceilf(erange.lower.y);
  133. const int ly1 = (int) ceilf(erange.upper.y) + (erange.upper.y == y1 && (srange.lower.y < erange.upper.y || erange.upper.y == 0));
  134. if (lx0 >= lx1 || ly0 >= ly1)
  135. return true;
  136. if (!This)
  137. return false;
  138. switch (This.type())
  139. {
  140. case Patch::BILINEAR_PATCH: {
  141. evalLocalGrid((Patch::BilinearPatch*)This.object(),srange,lx0,lx1,ly0,ly1);
  142. return true;
  143. }
  144. case Patch::BSPLINE_PATCH: {
  145. evalLocalGrid((Patch::BSplinePatch*)This.object(),srange,lx0,lx1,ly0,ly1);
  146. return true;
  147. }
  148. case Patch::BEZIER_PATCH: {
  149. evalLocalGrid((Patch::BezierPatch*)This.object(),srange,lx0,lx1,ly0,ly1);
  150. return true;
  151. }
  152. case Patch::GREGORY_PATCH: {
  153. evalLocalGrid((Patch::GregoryPatch*)This.object(),srange,lx0,lx1,ly0,ly1);
  154. return true;
  155. }
  156. case Patch::SUBDIVIDED_QUAD_PATCH:
  157. {
  158. const Vec2f c = srange.center();
  159. const BBox2f srange0(srange.lower,c);
  160. const BBox2f srange1(Vec2f(c.x,srange.lower.y),Vec2f(srange.upper.x,c.y));
  161. const BBox2f srange2(c,srange.upper);
  162. const BBox2f srange3(Vec2f(srange.lower.x,c.y),Vec2f(c.x,srange.upper.y));
  163. Patch::SubdividedQuadPatch* patch = (Patch::SubdividedQuadPatch*)This.object();
  164. eval(patch->child[0],srange0,intersect(srange0,erange),depth+1);
  165. eval(patch->child[1],srange1,intersect(srange1,erange),depth+1);
  166. eval(patch->child[2],srange2,intersect(srange2,erange),depth+1);
  167. eval(patch->child[3],srange3,intersect(srange3,erange),depth+1);
  168. return true;
  169. }
  170. case Patch::EVAL_PATCH: {
  171. CatmullClarkPatch patch; patch.deserialize(This.object());
  172. FeatureAdaptiveEvalGrid(patch,srange,erange,depth,x0,x1,y0,y1,swidth,sheight,Px,Py,Pz,U,V,Nx,Ny,Nz,dwidth,dheight);
  173. count += (lx1-lx0)*(ly1-ly0);
  174. return true;
  175. }
  176. default:
  177. assert(false);
  178. return false;
  179. }
  180. }
  181. bool eval(Ref This, unsigned subPatch, const BBox2f& srange, const BBox2f& erange)
  182. {
  183. if (!This)
  184. return false;
  185. switch (This.type())
  186. {
  187. case Patch::SUBDIVIDED_GENERAL_PATCH: {
  188. Patch::SubdividedGeneralPatch* patch = (Patch::SubdividedGeneralPatch*)This.object();
  189. assert(subPatch < patch->N);
  190. return eval(patch->child[subPatch],srange,erange,1);
  191. }
  192. default:
  193. assert(subPatch == 0);
  194. return eval(This,srange,erange,0);
  195. }
  196. }
  197. };
  198. __forceinline unsigned patch_eval_subdivision_count (const HalfEdge* h)
  199. {
  200. const unsigned N = h->numEdges();
  201. if (N == 4) return 1;
  202. else return N;
  203. }
  204. template<typename Tessellator>
  205. inline void patch_eval_subdivision (const HalfEdge* h, Tessellator tessellator)
  206. {
  207. const unsigned N = h->numEdges();
  208. int neighborSubdiv[GeneralCatmullClarkPatch3fa::SIZE]; // FIXME: use array_t
  209. float levels[GeneralCatmullClarkPatch3fa::SIZE];
  210. for (unsigned i=0; i<N; i++) {
  211. assert(i<GeneralCatmullClarkPatch3fa::SIZE);
  212. neighborSubdiv[i] = h->hasOpposite() ? h->opposite()->numEdges() != 4 : 0;
  213. levels[i] = h->edge_level;
  214. h = h->next();
  215. }
  216. if (N == 4)
  217. {
  218. const Vec2f uv[4] = { Vec2f(0.0f,0.0f), Vec2f(1.0f,0.0f), Vec2f(1.0f,1.0f), Vec2f(0.0f,1.0f) };
  219. tessellator(uv,neighborSubdiv,levels,0);
  220. }
  221. else
  222. {
  223. for (unsigned i=0; i<N; i++)
  224. {
  225. assert(i<MAX_PATCH_VALENCE);
  226. static_assert(MAX_PATCH_VALENCE <= 16, "MAX_PATCH_VALENCE > 16");
  227. const int h = (i >> 2) & 3, l = i & 3;
  228. const Vec2f base((float)l,(float)h);
  229. const Vec2f uv[4] = { (1.0f/4.0f) * (base + Vec2f(0.0f,0.0f)),
  230. (1.0f/4.0f) * (base + Vec2f(0.5f,0.0f)),
  231. (1.0f/4.0f) * (base + Vec2f(0.5f,0.5f)),
  232. (1.0f/4.0f) * (base + Vec2f(0.0f,0.5f)) };
  233. const int neighborSubdiv1[4] = { 0,0,0,0 };
  234. const float levels1[4] = { 0.5f*levels[(i+0)%N], 0.5f*levels[(i+0)%N], 0.5f*levels[(i-1)%N], 0.5f*levels[(i-1)%N] };
  235. tessellator(uv,neighborSubdiv1,levels1,i);
  236. }
  237. }
  238. }
  239. }
  240. }