subd_dice.cpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. /*
  2. * Copyright 2011-2013 Blender Foundation
  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. #include "render/camera.h"
  17. #include "render/mesh.h"
  18. #include "subd/subd_dice.h"
  19. #include "subd/subd_patch.h"
  20. CCL_NAMESPACE_BEGIN
  21. /* EdgeDice Base */
  22. EdgeDice::EdgeDice(const SubdParams &params_) : params(params_)
  23. {
  24. mesh_P = NULL;
  25. mesh_N = NULL;
  26. vert_offset = 0;
  27. params.mesh->attributes.add(ATTR_STD_VERTEX_NORMAL);
  28. if (params.ptex) {
  29. params.mesh->attributes.add(ATTR_STD_PTEX_UV);
  30. params.mesh->attributes.add(ATTR_STD_PTEX_FACE_ID);
  31. }
  32. }
  33. void EdgeDice::reserve(int num_verts)
  34. {
  35. Mesh *mesh = params.mesh;
  36. vert_offset = mesh->verts.size();
  37. tri_offset = mesh->num_triangles();
  38. /* todo: optimize so we can reserve in advance, this is like push_back_slow() */
  39. if (vert_offset + num_verts > mesh->verts.capacity()) {
  40. mesh->reserve_mesh(size_t((vert_offset + num_verts) * 1.2), mesh->num_triangles());
  41. }
  42. mesh->resize_mesh(vert_offset + num_verts, tri_offset);
  43. Attribute *attr_vN = mesh->attributes.add(ATTR_STD_VERTEX_NORMAL);
  44. mesh_P = mesh->verts.data();
  45. mesh_N = attr_vN->data_float3();
  46. }
  47. int EdgeDice::add_vert(Patch *patch, float2 uv)
  48. {
  49. float3 P, N;
  50. patch->eval(&P, NULL, NULL, &N, uv.x, uv.y);
  51. assert(vert_offset < params.mesh->verts.size());
  52. mesh_P[vert_offset] = P;
  53. mesh_N[vert_offset] = N;
  54. params.mesh->vert_patch_uv[vert_offset] = make_float2(uv.x, uv.y);
  55. if (params.ptex) {
  56. Attribute *attr_ptex_uv = params.mesh->attributes.add(ATTR_STD_PTEX_UV);
  57. params.mesh->attributes.resize();
  58. float3 *ptex_uv = attr_ptex_uv->data_float3();
  59. ptex_uv[vert_offset] = make_float3(uv.x, uv.y, 0.0f);
  60. }
  61. params.mesh->num_subd_verts++;
  62. return vert_offset++;
  63. }
  64. void EdgeDice::add_triangle(Patch *patch, int v0, int v1, int v2)
  65. {
  66. Mesh *mesh = params.mesh;
  67. /* todo: optimize so we can reserve in advance, this is like push_back_slow() */
  68. if (mesh->triangles.size() == mesh->triangles.capacity())
  69. mesh->reserve_mesh(mesh->verts.size(), size_t(max(mesh->num_triangles() + 1, 1) * 1.2));
  70. mesh->add_triangle(v0, v1, v2, patch->shader, true);
  71. params.mesh->triangle_patch[params.mesh->num_triangles() - 1] = patch->patch_index;
  72. if (params.ptex) {
  73. Attribute *attr_ptex_face_id = params.mesh->attributes.add(ATTR_STD_PTEX_FACE_ID);
  74. params.mesh->attributes.resize();
  75. float *ptex_face_id = attr_ptex_face_id->data_float();
  76. ptex_face_id[tri_offset] = (float)patch->ptex_face_id();
  77. }
  78. tri_offset++;
  79. }
  80. void EdgeDice::stitch_triangles(Patch *patch, vector<int> &outer, vector<int> &inner)
  81. {
  82. if (inner.size() == 0 || outer.size() == 0)
  83. return; // XXX avoid crashes for Mu or Mv == 1, missing polygons
  84. /* stitch together two arrays of verts with triangles. at each step,
  85. * we compare using the next verts on both sides, to find the split
  86. * direction with the smallest diagonal, and use that in order to keep
  87. * the triangle shape reasonable. */
  88. for (size_t i = 0, j = 0; i + 1 < inner.size() || j + 1 < outer.size();) {
  89. int v0, v1, v2;
  90. v0 = inner[i];
  91. v1 = outer[j];
  92. if (j + 1 == outer.size()) {
  93. v2 = inner[++i];
  94. }
  95. else if (i + 1 == inner.size()) {
  96. v2 = outer[++j];
  97. }
  98. else {
  99. /* length of diagonals */
  100. float len1 = len_squared(mesh_P[inner[i]] - mesh_P[outer[j + 1]]);
  101. float len2 = len_squared(mesh_P[outer[j]] - mesh_P[inner[i + 1]]);
  102. /* use smallest diagonal */
  103. if (len1 < len2)
  104. v2 = outer[++j];
  105. else
  106. v2 = inner[++i];
  107. }
  108. add_triangle(patch, v0, v1, v2);
  109. }
  110. }
  111. /* QuadDice */
  112. QuadDice::QuadDice(const SubdParams &params_) : EdgeDice(params_)
  113. {
  114. }
  115. void QuadDice::reserve(EdgeFactors &ef, int Mu, int Mv)
  116. {
  117. /* XXX need to make this also work for edge factor 0 and 1 */
  118. int num_verts = (ef.tu0 + ef.tu1 + ef.tv0 + ef.tv1) + (Mu - 1) * (Mv - 1);
  119. EdgeDice::reserve(num_verts);
  120. }
  121. float2 QuadDice::map_uv(SubPatch &sub, float u, float v)
  122. {
  123. /* map UV from subpatch to patch parametric coordinates */
  124. float2 d0 = interp(sub.P00, sub.P01, v);
  125. float2 d1 = interp(sub.P10, sub.P11, v);
  126. return interp(d0, d1, u);
  127. }
  128. float3 QuadDice::eval_projected(SubPatch &sub, float u, float v)
  129. {
  130. float2 uv = map_uv(sub, u, v);
  131. float3 P;
  132. sub.patch->eval(&P, NULL, NULL, NULL, uv.x, uv.y);
  133. if (params.camera)
  134. P = transform_perspective(&params.camera->worldtoraster, P);
  135. return P;
  136. }
  137. int QuadDice::add_vert(SubPatch &sub, float u, float v)
  138. {
  139. return EdgeDice::add_vert(sub.patch, map_uv(sub, u, v));
  140. }
  141. void QuadDice::add_side_u(SubPatch &sub,
  142. vector<int> &outer,
  143. vector<int> &inner,
  144. int Mu,
  145. int Mv,
  146. int tu,
  147. int side,
  148. int offset)
  149. {
  150. outer.clear();
  151. inner.clear();
  152. /* set verts on the edge of the patch */
  153. outer.push_back(offset + ((side) ? 2 : 0));
  154. for (int i = 1; i < tu; i++) {
  155. float u = i / (float)tu;
  156. float v = (side) ? 1.0f : 0.0f;
  157. outer.push_back(add_vert(sub, u, v));
  158. }
  159. outer.push_back(offset + ((side) ? 3 : 1));
  160. /* set verts on the edge of the inner grid */
  161. for (int i = 0; i < Mu - 1; i++) {
  162. int j = (side) ? Mv - 1 - 1 : 0;
  163. inner.push_back(offset + 4 + i + j * (Mu - 1));
  164. }
  165. }
  166. void QuadDice::add_side_v(SubPatch &sub,
  167. vector<int> &outer,
  168. vector<int> &inner,
  169. int Mu,
  170. int Mv,
  171. int tv,
  172. int side,
  173. int offset)
  174. {
  175. outer.clear();
  176. inner.clear();
  177. /* set verts on the edge of the patch */
  178. outer.push_back(offset + ((side) ? 1 : 0));
  179. for (int j = 1; j < tv; j++) {
  180. float u = (side) ? 1.0f : 0.0f;
  181. float v = j / (float)tv;
  182. outer.push_back(add_vert(sub, u, v));
  183. }
  184. outer.push_back(offset + ((side) ? 3 : 2));
  185. /* set verts on the edge of the inner grid */
  186. for (int j = 0; j < Mv - 1; j++) {
  187. int i = (side) ? Mu - 1 - 1 : 0;
  188. inner.push_back(offset + 4 + i + j * (Mu - 1));
  189. }
  190. }
  191. float QuadDice::quad_area(const float3 &a, const float3 &b, const float3 &c, const float3 &d)
  192. {
  193. return triangle_area(a, b, d) + triangle_area(a, d, c);
  194. }
  195. float QuadDice::scale_factor(SubPatch &sub, EdgeFactors &ef, int Mu, int Mv)
  196. {
  197. /* estimate area as 4x largest of 4 quads */
  198. float3 P[3][3];
  199. for (int i = 0; i < 3; i++)
  200. for (int j = 0; j < 3; j++)
  201. P[i][j] = eval_projected(sub, i * 0.5f, j * 0.5f);
  202. float A1 = quad_area(P[0][0], P[1][0], P[0][1], P[1][1]);
  203. float A2 = quad_area(P[1][0], P[2][0], P[1][1], P[2][1]);
  204. float A3 = quad_area(P[0][1], P[1][1], P[0][2], P[1][2]);
  205. float A4 = quad_area(P[1][1], P[2][1], P[1][2], P[2][2]);
  206. float Apatch = max(A1, max(A2, max(A3, A4))) * 4.0f;
  207. /* solve for scaling factor */
  208. float Atri = params.dicing_rate * params.dicing_rate * 0.5f;
  209. float Ntris = Apatch / Atri;
  210. // XXX does the -sqrt solution matter
  211. // XXX max(D, 0.0) is highly suspicious, need to test cases
  212. // where D goes negative
  213. float N = 0.5f * (Ntris - (ef.tu0 + ef.tu1 + ef.tv0 + ef.tv1));
  214. float D = 4.0f * N * Mu * Mv + (Mu + Mv) * (Mu + Mv);
  215. float S = (Mu + Mv + sqrtf(max(D, 0.0f))) / (2 * Mu * Mv);
  216. return S;
  217. }
  218. void QuadDice::add_corners(SubPatch &sub)
  219. {
  220. /* add verts for patch corners */
  221. add_vert(sub, 0.0f, 0.0f);
  222. add_vert(sub, 1.0f, 0.0f);
  223. add_vert(sub, 0.0f, 1.0f);
  224. add_vert(sub, 1.0f, 1.0f);
  225. }
  226. void QuadDice::add_grid(SubPatch &sub, int Mu, int Mv, int offset)
  227. {
  228. /* create inner grid */
  229. float du = 1.0f / (float)Mu;
  230. float dv = 1.0f / (float)Mv;
  231. for (int j = 1; j < Mv; j++) {
  232. for (int i = 1; i < Mu; i++) {
  233. float u = i * du;
  234. float v = j * dv;
  235. add_vert(sub, u, v);
  236. if (i < Mu - 1 && j < Mv - 1) {
  237. int i1 = offset + 4 + (i - 1) + (j - 1) * (Mu - 1);
  238. int i2 = offset + 4 + i + (j - 1) * (Mu - 1);
  239. int i3 = offset + 4 + i + j * (Mu - 1);
  240. int i4 = offset + 4 + (i - 1) + j * (Mu - 1);
  241. add_triangle(sub.patch, i1, i2, i3);
  242. add_triangle(sub.patch, i1, i3, i4);
  243. }
  244. }
  245. }
  246. }
  247. void QuadDice::dice(SubPatch &sub, EdgeFactors &ef)
  248. {
  249. /* compute inner grid size with scale factor */
  250. int Mu = max(ef.tu0, ef.tu1);
  251. int Mv = max(ef.tv0, ef.tv1);
  252. #if 0 /* Doesn't work very well, especially at grazing angles. */
  253. float S = scale_factor(sub, ef, Mu, Mv);
  254. #else
  255. float S = 1.0f;
  256. #endif
  257. Mu = max((int)ceil(S * Mu), 2); // XXX handle 0 & 1?
  258. Mv = max((int)ceil(S * Mv), 2); // XXX handle 0 & 1?
  259. /* reserve space for new verts */
  260. int offset = params.mesh->verts.size();
  261. reserve(ef, Mu, Mv);
  262. /* corners and inner grid */
  263. add_corners(sub);
  264. add_grid(sub, Mu, Mv, offset);
  265. /* bottom side */
  266. vector<int> outer, inner;
  267. add_side_u(sub, outer, inner, Mu, Mv, ef.tu0, 0, offset);
  268. stitch_triangles(sub.patch, outer, inner);
  269. /* top side */
  270. add_side_u(sub, outer, inner, Mu, Mv, ef.tu1, 1, offset);
  271. stitch_triangles(sub.patch, inner, outer);
  272. /* left side */
  273. add_side_v(sub, outer, inner, Mu, Mv, ef.tv0, 0, offset);
  274. stitch_triangles(sub.patch, inner, outer);
  275. /* right side */
  276. add_side_v(sub, outer, inner, Mu, Mv, ef.tv1, 1, offset);
  277. stitch_triangles(sub.patch, outer, inner);
  278. assert(vert_offset == params.mesh->verts.size());
  279. }
  280. CCL_NAMESPACE_END