catmullclark_patch.h 23 KB

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