catmullclark_patch.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  1. // Copyright 2009-2021 Intel Corporation
  2. // SPDX-License-Identifier: Apache-2.0
  3. #pragma once
  4. #include "catmullclark_ring.h"
  5. #include "bezier_curve.h"
  6. namespace embree
  7. {
  8. template<typename Vertex, typename Vertex_t = Vertex>
  9. class __aligned(64) CatmullClarkPatchT
  10. {
  11. public:
  12. typedef CatmullClark1RingT<Vertex,Vertex_t> CatmullClark1Ring;
  13. typedef typename CatmullClark1Ring::Type Type;
  14. array_t<CatmullClark1RingT<Vertex,Vertex_t>,4> ring;
  15. public:
  16. __forceinline CatmullClarkPatchT () {}
  17. __forceinline CatmullClarkPatchT (const HalfEdge* first_half_edge, const char* vertices, size_t stride) {
  18. init(first_half_edge,vertices,stride);
  19. }
  20. __forceinline CatmullClarkPatchT (const HalfEdge* first_half_edge, const BufferView<Vec3fa>& vertices) {
  21. init(first_half_edge,vertices.getPtr(),vertices.getStride());
  22. }
  23. __forceinline void init (const HalfEdge* first_half_edge, const char* vertices, size_t stride)
  24. {
  25. for (unsigned i=0; i<4; i++)
  26. ring[i].init(first_half_edge+i,vertices,stride);
  27. assert(verify());
  28. }
  29. __forceinline size_t bytes() const {
  30. return ring[0].bytes()+ring[1].bytes()+ring[2].bytes()+ring[3].bytes();
  31. }
  32. __forceinline void serialize(void* ptr, size_t& ofs) const
  33. {
  34. for (size_t i=0; i<4; i++)
  35. ring[i].serialize((char*)ptr,ofs);
  36. }
  37. __forceinline void deserialize(void* ptr)
  38. {
  39. size_t ofs = 0;
  40. for (size_t i=0; i<4; i++)
  41. ring[i].deserialize((char*)ptr,ofs);
  42. }
  43. __forceinline BBox3fa bounds() const
  44. {
  45. BBox3fa bounds (ring[0].bounds());
  46. for (size_t i=1; i<4; i++)
  47. bounds.extend(ring[i].bounds());
  48. return bounds;
  49. }
  50. __forceinline Type type() const
  51. {
  52. const int ty0 = ring[0].type() ^ CatmullClark1Ring::TYPE_CREASES;
  53. const int ty1 = ring[1].type() ^ CatmullClark1Ring::TYPE_CREASES;
  54. const int ty2 = ring[2].type() ^ CatmullClark1Ring::TYPE_CREASES;
  55. const int ty3 = ring[3].type() ^ CatmullClark1Ring::TYPE_CREASES;
  56. return (Type) ((ty0 & ty1 & ty2 & ty3) ^ CatmullClark1Ring::TYPE_CREASES);
  57. }
  58. __forceinline bool isFinalResolution(float res) const {
  59. return ring[0].isFinalResolution(res) && ring[1].isFinalResolution(res) && ring[2].isFinalResolution(res) && ring[3].isFinalResolution(res);
  60. }
  61. static __forceinline void init_regular(const CatmullClark1RingT<Vertex,Vertex_t>& p0,
  62. const CatmullClark1RingT<Vertex,Vertex_t>& p1,
  63. CatmullClark1RingT<Vertex,Vertex_t>& dest0,
  64. CatmullClark1RingT<Vertex,Vertex_t>& dest1)
  65. {
  66. assert(p1.face_valence > 2);
  67. dest1.vertex_level = dest0.vertex_level = p0.edge_level;
  68. dest1.face_valence = dest0.face_valence = 4;
  69. dest1.edge_valence = dest0.edge_valence = 8;
  70. dest1.border_index = dest0.border_index = -1;
  71. dest1.vtx = dest0.vtx = (Vertex_t)p0.ring[0];
  72. dest1.vertex_crease_weight = dest0.vertex_crease_weight = 0.0f;
  73. dest1.ring[2] = dest0.ring[0] = (Vertex_t)p0.ring[1];
  74. dest1.ring[1] = dest0.ring[7] = (Vertex_t)p1.ring[0];
  75. dest1.ring[0] = dest0.ring[6] = (Vertex_t)p1.vtx;
  76. dest1.ring[7] = dest0.ring[5] = (Vertex_t)p1.ring[4];
  77. dest1.ring[6] = dest0.ring[4] = (Vertex_t)p0.ring[p0.edge_valence-1];
  78. dest1.ring[5] = dest0.ring[3] = (Vertex_t)p0.ring[p0.edge_valence-2];
  79. dest1.ring[4] = dest0.ring[2] = (Vertex_t)p0.vtx;
  80. dest1.ring[3] = dest0.ring[1] = (Vertex_t)p0.ring[2];
  81. dest1.crease_weight[1] = dest0.crease_weight[0] = 0.0f;
  82. dest1.crease_weight[0] = dest0.crease_weight[3] = p1.crease_weight[1];
  83. dest1.crease_weight[3] = dest0.crease_weight[2] = 0.0f;
  84. dest1.crease_weight[2] = dest0.crease_weight[1] = p0.crease_weight[0];
  85. if (p0.eval_unique_identifier <= p1.eval_unique_identifier)
  86. {
  87. dest0.eval_start_index = 3;
  88. dest1.eval_start_index = 0;
  89. dest0.eval_unique_identifier = p0.eval_unique_identifier;
  90. dest1.eval_unique_identifier = p0.eval_unique_identifier;
  91. }
  92. else
  93. {
  94. dest0.eval_start_index = 1;
  95. dest1.eval_start_index = 2;
  96. dest0.eval_unique_identifier = p1.eval_unique_identifier;
  97. dest1.eval_unique_identifier = p1.eval_unique_identifier;
  98. }
  99. }
  100. static __forceinline void init_border(const CatmullClark1RingT<Vertex,Vertex_t> &p0,
  101. const CatmullClark1RingT<Vertex,Vertex_t> &p1,
  102. CatmullClark1RingT<Vertex,Vertex_t> &dest0,
  103. CatmullClark1RingT<Vertex,Vertex_t> &dest1)
  104. {
  105. dest1.vertex_level = dest0.vertex_level = p0.edge_level;
  106. dest1.face_valence = dest0.face_valence = 3;
  107. dest1.edge_valence = dest0.edge_valence = 6;
  108. dest0.border_index = 2;
  109. dest1.border_index = 4;
  110. dest1.vtx = dest0.vtx = (Vertex_t)p0.ring[0];
  111. dest1.vertex_crease_weight = dest0.vertex_crease_weight = 0.0f;
  112. dest1.ring[2] = dest0.ring[0] = (Vertex_t)p0.ring[1];
  113. dest1.ring[1] = dest0.ring[5] = (Vertex_t)p1.ring[0];
  114. dest1.ring[0] = dest0.ring[4] = (Vertex_t)p1.vtx;
  115. dest1.ring[5] = dest0.ring[3] = (Vertex_t)p0.ring[p0.border_index+1]; // dummy
  116. dest1.ring[4] = dest0.ring[2] = (Vertex_t)p0.vtx;
  117. dest1.ring[3] = dest0.ring[1] = (Vertex_t)p0.ring[2];
  118. dest1.crease_weight[1] = dest0.crease_weight[0] = 0.0f;
  119. dest1.crease_weight[0] = dest0.crease_weight[2] = p1.crease_weight[1];
  120. dest1.crease_weight[2] = dest0.crease_weight[1] = p0.crease_weight[0];
  121. if (p0.eval_unique_identifier <= p1.eval_unique_identifier)
  122. {
  123. dest0.eval_start_index = 1;
  124. dest1.eval_start_index = 2;
  125. dest0.eval_unique_identifier = p0.eval_unique_identifier;
  126. dest1.eval_unique_identifier = p0.eval_unique_identifier;
  127. }
  128. else
  129. {
  130. dest0.eval_start_index = 2;
  131. dest1.eval_start_index = 0;
  132. dest0.eval_unique_identifier = p1.eval_unique_identifier;
  133. dest1.eval_unique_identifier = p1.eval_unique_identifier;
  134. }
  135. }
  136. static __forceinline void init_regular(const Vertex_t &center, const Vertex_t center_ring[8], const unsigned int offset, CatmullClark1RingT<Vertex,Vertex_t> &dest)
  137. {
  138. dest.vertex_level = 0.0f;
  139. dest.face_valence = 4;
  140. dest.edge_valence = 8;
  141. dest.border_index = -1;
  142. dest.vtx = (Vertex_t)center;
  143. dest.vertex_crease_weight = 0.0f;
  144. for (size_t i=0; i<8; i++)
  145. dest.ring[i] = (Vertex_t)center_ring[(offset+i)%8];
  146. for (size_t i=0; i<4; i++)
  147. dest.crease_weight[i] = 0.0f;
  148. dest.eval_start_index = (8-offset)>>1;
  149. if (dest.eval_start_index >= dest.face_valence) dest.eval_start_index -= dest.face_valence;
  150. assert( dest.eval_start_index < dest.face_valence );
  151. dest.eval_unique_identifier = 0;
  152. }
  153. __noinline void subdivide(array_t<CatmullClarkPatchT,4>& patch) const
  154. {
  155. ring[0].subdivide(patch[0].ring[0]);
  156. ring[1].subdivide(patch[1].ring[1]);
  157. ring[2].subdivide(patch[2].ring[2]);
  158. ring[3].subdivide(patch[3].ring[3]);
  159. patch[0].ring[0].edge_level = 0.5f*ring[0].edge_level;
  160. patch[0].ring[1].edge_level = 0.25f*(ring[1].edge_level+ring[3].edge_level);
  161. patch[0].ring[2].edge_level = 0.25f*(ring[0].edge_level+ring[2].edge_level);
  162. patch[0].ring[3].edge_level = 0.5f*ring[3].edge_level;
  163. patch[1].ring[0].edge_level = 0.5f*ring[0].edge_level;
  164. patch[1].ring[1].edge_level = 0.5f*ring[1].edge_level;
  165. patch[1].ring[2].edge_level = 0.25f*(ring[0].edge_level+ring[2].edge_level);
  166. patch[1].ring[3].edge_level = 0.25f*(ring[1].edge_level+ring[3].edge_level);
  167. patch[2].ring[0].edge_level = 0.25f*(ring[0].edge_level+ring[2].edge_level);
  168. patch[2].ring[1].edge_level = 0.5f*ring[1].edge_level;
  169. patch[2].ring[2].edge_level = 0.5f*ring[2].edge_level;
  170. patch[2].ring[3].edge_level = 0.25f*(ring[1].edge_level+ring[3].edge_level);
  171. patch[3].ring[0].edge_level = 0.25f*(ring[0].edge_level+ring[2].edge_level);
  172. patch[3].ring[1].edge_level = 0.25f*(ring[1].edge_level+ring[3].edge_level);
  173. patch[3].ring[2].edge_level = 0.5f*ring[2].edge_level;
  174. patch[3].ring[3].edge_level = 0.5f*ring[3].edge_level;
  175. const bool regular0 = ring[0].has_last_face() && ring[1].face_valence > 2;
  176. if (likely(regular0))
  177. init_regular(patch[0].ring[0],patch[1].ring[1],patch[0].ring[1],patch[1].ring[0]);
  178. else
  179. init_border(patch[0].ring[0],patch[1].ring[1],patch[0].ring[1],patch[1].ring[0]);
  180. const bool regular1 = ring[1].has_last_face() && ring[2].face_valence > 2;
  181. if (likely(regular1))
  182. init_regular(patch[1].ring[1],patch[2].ring[2],patch[1].ring[2],patch[2].ring[1]);
  183. else
  184. init_border(patch[1].ring[1],patch[2].ring[2],patch[1].ring[2],patch[2].ring[1]);
  185. const bool regular2 = ring[2].has_last_face() && ring[3].face_valence > 2;
  186. if (likely(regular2))
  187. init_regular(patch[2].ring[2],patch[3].ring[3],patch[2].ring[3],patch[3].ring[2]);
  188. else
  189. init_border(patch[2].ring[2],patch[3].ring[3],patch[2].ring[3],patch[3].ring[2]);
  190. const bool regular3 = ring[3].has_last_face() && ring[0].face_valence > 2;
  191. if (likely(regular3))
  192. init_regular(patch[3].ring[3],patch[0].ring[0],patch[3].ring[0],patch[0].ring[3]);
  193. else
  194. init_border(patch[3].ring[3],patch[0].ring[0],patch[3].ring[0],patch[0].ring[3]);
  195. Vertex_t center = (ring[0].vtx + ring[1].vtx + ring[2].vtx + ring[3].vtx) * 0.25f;
  196. Vertex_t center_ring[8];
  197. center_ring[0] = (Vertex_t)patch[3].ring[3].ring[0];
  198. center_ring[7] = (Vertex_t)patch[3].ring[3].vtx;
  199. center_ring[6] = (Vertex_t)patch[2].ring[2].ring[0];
  200. center_ring[5] = (Vertex_t)patch[2].ring[2].vtx;
  201. center_ring[4] = (Vertex_t)patch[1].ring[1].ring[0];
  202. center_ring[3] = (Vertex_t)patch[1].ring[1].vtx;
  203. center_ring[2] = (Vertex_t)patch[0].ring[0].ring[0];
  204. center_ring[1] = (Vertex_t)patch[0].ring[0].vtx;
  205. init_regular(center,center_ring,0,patch[0].ring[2]);
  206. init_regular(center,center_ring,2,patch[1].ring[3]);
  207. init_regular(center,center_ring,4,patch[2].ring[0]);
  208. init_regular(center,center_ring,6,patch[3].ring[1]);
  209. assert(patch[0].verify());
  210. assert(patch[1].verify());
  211. assert(patch[2].verify());
  212. assert(patch[3].verify());
  213. }
  214. bool verify() const {
  215. return ring[0].hasValidPositions() && ring[1].hasValidPositions() && ring[2].hasValidPositions() && ring[3].hasValidPositions();
  216. }
  217. __forceinline void init( FinalQuad& quad ) const
  218. {
  219. quad.vtx[0] = (Vertex_t)ring[0].vtx;
  220. quad.vtx[1] = (Vertex_t)ring[1].vtx;
  221. quad.vtx[2] = (Vertex_t)ring[2].vtx;
  222. quad.vtx[3] = (Vertex_t)ring[3].vtx;
  223. };
  224. friend __forceinline embree_ostream operator<<(embree_ostream o, const CatmullClarkPatchT &p)
  225. {
  226. o << "CatmullClarkPatch { " << embree_endl;
  227. for (size_t i=0; i<4; i++)
  228. o << "ring" << i << ": " << p.ring[i] << embree_endl;
  229. o << "}" << embree_endl;
  230. return o;
  231. }
  232. };
  233. typedef CatmullClarkPatchT<Vec3fa,Vec3fa_t> CatmullClarkPatch3fa;
  234. template<typename Vertex, typename Vertex_t = Vertex>
  235. class __aligned(64) GeneralCatmullClarkPatchT
  236. {
  237. public:
  238. typedef CatmullClarkPatchT<Vertex,Vertex_t> CatmullClarkPatch;
  239. typedef CatmullClark1RingT<Vertex,Vertex_t> CatmullClark1Ring;
  240. typedef BezierCurveT<Vertex> BezierCurve;
  241. static const unsigned SIZE = MAX_PATCH_VALENCE;
  242. DynamicStackArray<GeneralCatmullClark1RingT<Vertex,Vertex_t>,8,SIZE> ring;
  243. unsigned N;
  244. __forceinline GeneralCatmullClarkPatchT ()
  245. : N(0) {}
  246. GeneralCatmullClarkPatchT (const HalfEdge* h, const char* vertices, size_t stride) {
  247. init(h,vertices,stride);
  248. }
  249. __forceinline GeneralCatmullClarkPatchT (const HalfEdge* first_half_edge, const BufferView<Vec3fa>& vertices) {
  250. init(first_half_edge,vertices.getPtr(),vertices.getStride());
  251. }
  252. __forceinline void init (const HalfEdge* h, const char* vertices, size_t stride)
  253. {
  254. unsigned int i = 0;
  255. const HalfEdge* edge = h;
  256. do {
  257. ring[i].init(edge,vertices,stride);
  258. edge = edge->next();
  259. i++;
  260. } while ((edge != h) && (i < SIZE));
  261. N = i;
  262. }
  263. __forceinline unsigned size() const {
  264. return N;
  265. }
  266. __forceinline bool isQuadPatch() const {
  267. return (N == 4) && ring[0].only_quads && ring[1].only_quads && ring[2].only_quads && ring[3].only_quads;
  268. }
  269. static __forceinline void init_regular(const CatmullClark1RingT<Vertex,Vertex_t>& p0,
  270. const CatmullClark1RingT<Vertex,Vertex_t>& p1,
  271. CatmullClark1RingT<Vertex,Vertex_t>& dest0,
  272. CatmullClark1RingT<Vertex,Vertex_t>& dest1)
  273. {
  274. assert(p1.face_valence > 2);
  275. dest1.vertex_level = dest0.vertex_level = p0.edge_level;
  276. dest1.face_valence = dest0.face_valence = 4;
  277. dest1.edge_valence = dest0.edge_valence = 8;
  278. dest1.border_index = dest0.border_index = -1;
  279. dest1.vtx = dest0.vtx = (Vertex_t)p0.ring[0];
  280. dest1.vertex_crease_weight = dest0.vertex_crease_weight = 0.0f;
  281. dest1.ring[2] = dest0.ring[0] = (Vertex_t)p0.ring[1];
  282. dest1.ring[1] = dest0.ring[7] = (Vertex_t)p1.ring[0];
  283. dest1.ring[0] = dest0.ring[6] = (Vertex_t)p1.vtx;
  284. dest1.ring[7] = dest0.ring[5] = (Vertex_t)p1.ring[4];
  285. dest1.ring[6] = dest0.ring[4] = (Vertex_t)p0.ring[p0.edge_valence-1];
  286. dest1.ring[5] = dest0.ring[3] = (Vertex_t)p0.ring[p0.edge_valence-2];
  287. dest1.ring[4] = dest0.ring[2] = (Vertex_t)p0.vtx;
  288. dest1.ring[3] = dest0.ring[1] = (Vertex_t)p0.ring[2];
  289. dest1.crease_weight[1] = dest0.crease_weight[0] = 0.0f;
  290. dest1.crease_weight[0] = dest0.crease_weight[3] = p1.crease_weight[1];
  291. dest1.crease_weight[3] = dest0.crease_weight[2] = 0.0f;
  292. dest1.crease_weight[2] = dest0.crease_weight[1] = p0.crease_weight[0];
  293. if (p0.eval_unique_identifier <= p1.eval_unique_identifier)
  294. {
  295. dest0.eval_start_index = 3;
  296. dest1.eval_start_index = 0;
  297. dest0.eval_unique_identifier = p0.eval_unique_identifier;
  298. dest1.eval_unique_identifier = p0.eval_unique_identifier;
  299. }
  300. else
  301. {
  302. dest0.eval_start_index = 1;
  303. dest1.eval_start_index = 2;
  304. dest0.eval_unique_identifier = p1.eval_unique_identifier;
  305. dest1.eval_unique_identifier = p1.eval_unique_identifier;
  306. }
  307. }
  308. static __forceinline void init_border(const CatmullClark1RingT<Vertex,Vertex_t> &p0,
  309. const CatmullClark1RingT<Vertex,Vertex_t> &p1,
  310. CatmullClark1RingT<Vertex,Vertex_t> &dest0,
  311. CatmullClark1RingT<Vertex,Vertex_t> &dest1)
  312. {
  313. dest1.vertex_level = dest0.vertex_level = p0.edge_level;
  314. dest1.face_valence = dest0.face_valence = 3;
  315. dest1.edge_valence = dest0.edge_valence = 6;
  316. dest0.border_index = 2;
  317. dest1.border_index = 4;
  318. dest1.vtx = dest0.vtx = (Vertex_t)p0.ring[0];
  319. dest1.vertex_crease_weight = dest0.vertex_crease_weight = 0.0f;
  320. dest1.ring[2] = dest0.ring[0] = (Vertex_t)p0.ring[1];
  321. dest1.ring[1] = dest0.ring[5] = (Vertex_t)p1.ring[0];
  322. dest1.ring[0] = dest0.ring[4] = (Vertex_t)p1.vtx;
  323. dest1.ring[5] = dest0.ring[3] = (Vertex_t)p0.ring[p0.border_index+1]; // dummy
  324. dest1.ring[4] = dest0.ring[2] = (Vertex_t)p0.vtx;
  325. dest1.ring[3] = dest0.ring[1] = (Vertex_t)p0.ring[2];
  326. dest1.crease_weight[1] = dest0.crease_weight[0] = 0.0f;
  327. dest1.crease_weight[0] = dest0.crease_weight[2] = p1.crease_weight[1];
  328. dest1.crease_weight[2] = dest0.crease_weight[1] = p0.crease_weight[0];
  329. if (p0.eval_unique_identifier <= p1.eval_unique_identifier)
  330. {
  331. dest0.eval_start_index = 1;
  332. dest1.eval_start_index = 2;
  333. dest0.eval_unique_identifier = p0.eval_unique_identifier;
  334. dest1.eval_unique_identifier = p0.eval_unique_identifier;
  335. }
  336. else
  337. {
  338. dest0.eval_start_index = 2;
  339. dest1.eval_start_index = 0;
  340. dest0.eval_unique_identifier = p1.eval_unique_identifier;
  341. dest1.eval_unique_identifier = p1.eval_unique_identifier;
  342. }
  343. }
  344. static __forceinline void init_regular(const Vertex_t &center, const array_t<Vertex_t,2*SIZE>& center_ring, const float vertex_level, const unsigned int N, const unsigned int offset, CatmullClark1RingT<Vertex,Vertex_t> &dest)
  345. {
  346. assert(N<(MAX_RING_FACE_VALENCE));
  347. assert(2*N<(MAX_RING_EDGE_VALENCE));
  348. dest.vertex_level = vertex_level;
  349. dest.face_valence = N;
  350. dest.edge_valence = 2*N;
  351. dest.border_index = -1;
  352. dest.vtx = (Vertex_t)center;
  353. dest.vertex_crease_weight = 0.0f;
  354. for (unsigned i=0; i<2*N; i++) {
  355. dest.ring[i] = (Vertex_t)center_ring[(2*N+offset+i-1)%(2*N)];
  356. assert(isvalid(dest.ring[i]));
  357. }
  358. for (unsigned i=0; i<N; i++)
  359. dest.crease_weight[i] = 0.0f;
  360. assert(offset <= 2*N);
  361. dest.eval_start_index = (2*N-offset)>>1;
  362. if (dest.eval_start_index >= dest.face_valence) dest.eval_start_index -= dest.face_valence;
  363. assert( dest.eval_start_index < dest.face_valence );
  364. dest.eval_unique_identifier = 0;
  365. }
  366. __noinline void subdivide(array_t<CatmullClarkPatch,SIZE>& patch, unsigned& N_o) const
  367. {
  368. N_o = N;
  369. assert( N );
  370. for (unsigned i=0; i<N; i++) {
  371. unsigned ip1 = (i+1)%N; // FIXME: %
  372. ring[i].subdivide(patch[i].ring[0]);
  373. patch[i] .ring[0].edge_level = 0.5f*ring[i].edge_level;
  374. patch[ip1].ring[3].edge_level = 0.5f*ring[i].edge_level;
  375. assert( patch[i].ring[0].hasValidPositions() );
  376. }
  377. assert(N < 2*SIZE);
  378. Vertex_t center = Vertex_t(0.0f);
  379. array_t<Vertex_t,2*SIZE> center_ring;
  380. float center_vertex_level = 2.0f; // guarantees that irregular vertices get always isolated also for non-quads
  381. for (unsigned i=0; i<N; i++)
  382. {
  383. unsigned ip1 = (i+1)%N; // FIXME: %
  384. unsigned im1 = (i+N-1)%N; // FIXME: %
  385. bool regular = ring[i].has_last_face() && ring[ip1].face_valence > 2;
  386. if (likely(regular)) init_regular(patch[i].ring[0],patch[ip1].ring[0],patch[i].ring[1],patch[ip1].ring[3]);
  387. else init_border (patch[i].ring[0],patch[ip1].ring[0],patch[i].ring[1],patch[ip1].ring[3]);
  388. assert( patch[i].ring[1].hasValidPositions() );
  389. assert( patch[ip1].ring[3].hasValidPositions() );
  390. float level = 0.25f*(ring[im1].edge_level+ring[ip1].edge_level);
  391. patch[i].ring[1].edge_level = patch[ip1].ring[2].edge_level = level;
  392. center_vertex_level = max(center_vertex_level,level);
  393. center += ring[i].vtx;
  394. center_ring[2*i+0] = (Vertex_t)patch[i].ring[0].vtx;
  395. center_ring[2*i+1] = (Vertex_t)patch[i].ring[0].ring[0];
  396. }
  397. center /= float(N);
  398. for (unsigned int i=0; i<N; i++) {
  399. init_regular(center,center_ring,center_vertex_level,N,2*i,patch[i].ring[2]);
  400. assert( patch[i].ring[2].hasValidPositions() );
  401. }
  402. }
  403. void init(CatmullClarkPatch& patch) const
  404. {
  405. assert(size() == 4);
  406. ring[0].convert(patch.ring[0]);
  407. ring[1].convert(patch.ring[1]);
  408. ring[2].convert(patch.ring[2]);
  409. ring[3].convert(patch.ring[3]);
  410. }
  411. static void fix_quad_ring_order (array_t<CatmullClarkPatch,GeneralCatmullClarkPatchT::SIZE>& patches)
  412. {
  413. CatmullClark1Ring patches1ring1 = patches[1].ring[1];
  414. patches[1].ring[1] = patches[1].ring[0]; // FIXME: optimize these assignments
  415. patches[1].ring[0] = patches[1].ring[3];
  416. patches[1].ring[3] = patches[1].ring[2];
  417. patches[1].ring[2] = patches1ring1;
  418. CatmullClark1Ring patches2ring2 = patches[2].ring[2];
  419. patches[2].ring[2] = patches[2].ring[0];
  420. patches[2].ring[0] = patches2ring2;
  421. CatmullClark1Ring patches2ring3 = patches[2].ring[3];
  422. patches[2].ring[3] = patches[2].ring[1];
  423. patches[2].ring[1] = patches2ring3;
  424. CatmullClark1Ring patches3ring3 = patches[3].ring[3];
  425. patches[3].ring[3] = patches[3].ring[0];
  426. patches[3].ring[0] = patches[3].ring[1];
  427. patches[3].ring[1] = patches[3].ring[2];
  428. patches[3].ring[2] = patches3ring3;
  429. }
  430. __forceinline void getLimitBorder(BezierCurve curves[GeneralCatmullClarkPatchT::SIZE]) const
  431. {
  432. Vertex P0 = ring[0].getLimitVertex();
  433. for (unsigned i=0; i<N; i++)
  434. {
  435. const unsigned i0 = i, i1 = i+1==N ? 0 : i+1;
  436. const Vertex P1 = madd(1.0f/3.0f,ring[i0].getLimitTangent(),P0);
  437. const Vertex P3 = ring[i1].getLimitVertex();
  438. const Vertex P2 = madd(1.0f/3.0f,ring[i1].getSecondLimitTangent(),P3);
  439. new (&curves[i]) BezierCurve(P0,P1,P2,P3);
  440. P0 = P3;
  441. }
  442. }
  443. __forceinline void getLimitBorder(BezierCurve curves[2], const unsigned subPatch) const
  444. {
  445. const unsigned i0 = subPatch;
  446. const Vertex t0_p = ring[i0].getLimitTangent();
  447. const Vertex t0_m = ring[i0].getSecondLimitTangent();
  448. const unsigned i1 = subPatch+1 == N ? 0 : subPatch+1;
  449. const Vertex t1_p = ring[i1].getLimitTangent();
  450. const Vertex t1_m = ring[i1].getSecondLimitTangent();
  451. const unsigned i2 = subPatch == 0 ? N-1 : subPatch-1;
  452. const Vertex t2_p = ring[i2].getLimitTangent();
  453. const Vertex t2_m = ring[i2].getSecondLimitTangent();
  454. const Vertex b00 = ring[i0].getLimitVertex();
  455. const Vertex b03 = ring[i1].getLimitVertex();
  456. const Vertex b33 = ring[i2].getLimitVertex();
  457. const Vertex b01 = madd(1.0/3.0f,t0_p,b00);
  458. const Vertex b11 = madd(1.0/3.0f,t0_m,b00);
  459. //const Vertex b13 = madd(1.0/3.0f,t1_p,b03);
  460. const Vertex b02 = madd(1.0/3.0f,t1_m,b03);
  461. const Vertex b22 = madd(1.0/3.0f,t2_p,b33);
  462. const Vertex b23 = madd(1.0/3.0f,t2_m,b33);
  463. new (&curves[0]) BezierCurve(b00,b01,b02,b03);
  464. new (&curves[1]) BezierCurve(b33,b22,b11,b00);
  465. }
  466. friend __forceinline embree_ostream operator<<(embree_ostream o, const GeneralCatmullClarkPatchT &p)
  467. {
  468. o << "GeneralCatmullClarkPatch { " << embree_endl;
  469. for (unsigned i=0; i<p.N; i++)
  470. o << "ring" << i << ": " << p.ring[i] << embree_endl;
  471. o << "}" << embree_endl;
  472. return o;
  473. }
  474. };
  475. typedef GeneralCatmullClarkPatchT<Vec3fa,Vec3fa_t> GeneralCatmullClarkPatch3fa;
  476. }