Blender V2.61 - r43446
|
00001 /* 00002 * Copyright 2011, Blender Foundation. 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 */ 00018 00019 #include "camera.h" 00020 #include "mesh.h" 00021 00022 #include "subd_dice.h" 00023 #include "subd_patch.h" 00024 00025 #include "util_debug.h" 00026 00027 CCL_NAMESPACE_BEGIN 00028 00029 /* EdgeDice Base */ 00030 00031 EdgeDice::EdgeDice(Mesh *mesh_, int shader_, bool smooth_, float dicing_rate_) 00032 { 00033 mesh = mesh_; 00034 mesh_P = NULL; 00035 mesh_N = NULL; 00036 vert_offset = 0; 00037 dicing_rate = dicing_rate_; 00038 shader = shader_; 00039 smooth = smooth_; 00040 camera = NULL; 00041 00042 mesh->attributes.add(Attribute::STD_VERTEX_NORMAL); 00043 } 00044 00045 void EdgeDice::reserve(int num_verts, int num_tris) 00046 { 00047 vert_offset = mesh->verts.size(); 00048 tri_offset = mesh->triangles.size(); 00049 00050 mesh->reserve(vert_offset + num_verts, tri_offset + num_tris); 00051 00052 Attribute *attr_vN = mesh->attributes.add(Attribute::STD_VERTEX_NORMAL); 00053 00054 mesh_P = &mesh->verts[0]; 00055 mesh_N = attr_vN->data_float3(); 00056 } 00057 00058 int EdgeDice::add_vert(Patch *patch, float2 uv) 00059 { 00060 float3 P, N, dPdu, dPdv; 00061 00062 patch->eval(&P, &dPdu, &dPdv, uv.x, uv.y); 00063 N = normalize(cross(dPdu, dPdv)); 00064 00065 assert(vert_offset < mesh->verts.size()); 00066 00067 mesh_P[vert_offset] = P; 00068 mesh_N[vert_offset] = N; 00069 00070 return vert_offset++; 00071 } 00072 00073 void EdgeDice::add_triangle(int v0, int v1, int v2) 00074 { 00075 mesh->add_triangle(v0, v1, v2, shader, smooth); 00076 } 00077 00078 void EdgeDice::stitch_triangles(vector<int>& outer, vector<int>& inner) 00079 { 00080 if(inner.size() == 0 || outer.size() == 0) 00081 return; // XXX avoid crashes for Mu or Mv == 1, missing polygons 00082 00083 /* stitch together two arrays of verts with triangles. at each step, 00084 we compare using the next verts on both sides, to find the split 00085 direction with the smallest diagonal, and use that in order to keep 00086 the triangle shape reasonable. */ 00087 for(size_t i = 0, j = 0; i+1 < inner.size() || j+1 < outer.size();) { 00088 int v0, v1, v2; 00089 00090 v0 = inner[i]; 00091 v1 = outer[j]; 00092 00093 if(j+1 == outer.size()) { 00094 v2 = inner[++i]; 00095 } 00096 else if(i+1 == inner.size()) { 00097 v2 = outer[++j]; 00098 } 00099 else { 00100 /* length of diagonals */ 00101 float len1 = len(mesh_P[inner[i]] - mesh_P[outer[j+1]]); 00102 float len2 = len(mesh_P[outer[j]] - mesh_P[inner[i+1]]); 00103 00104 /* use smallest diagonal */ 00105 if(len1 < len2) 00106 v2 = outer[++j]; 00107 else 00108 v2 = inner[++i]; 00109 } 00110 00111 add_triangle(v0, v1, v2); 00112 } 00113 } 00114 00115 /* QuadDice */ 00116 00117 QuadDice::QuadDice(Mesh *mesh_, int shader_, bool smooth_, float dicing_rate_) 00118 : EdgeDice(mesh_, shader_, smooth_, dicing_rate_) 00119 { 00120 } 00121 00122 void QuadDice::reserve(EdgeFactors& ef, int Mu, int Mv) 00123 { 00124 /* XXX need to make this also work for edge factor 0 and 1 */ 00125 int num_verts = (ef.tu0 + ef.tu1 + ef.tv0 + ef.tv1) + (Mu - 1)*(Mv - 1); 00126 EdgeDice::reserve(num_verts, 0); 00127 } 00128 00129 float2 QuadDice::map_uv(SubPatch& sub, float u, float v) 00130 { 00131 /* map UV from subpatch to patch parametric coordinates */ 00132 float2 d0 = interp(sub.P00, sub.P01, v); 00133 float2 d1 = interp(sub.P10, sub.P11, v); 00134 return interp(d0, d1, u); 00135 } 00136 00137 float3 QuadDice::eval_projected(SubPatch& sub, float u, float v) 00138 { 00139 float2 uv = map_uv(sub, u, v); 00140 float3 P; 00141 00142 sub.patch->eval(&P, NULL, NULL, uv.x, uv.y); 00143 if(camera) 00144 P = transform(&camera->worldtoraster, P); 00145 00146 return P; 00147 } 00148 00149 int QuadDice::add_vert(SubPatch& sub, float u, float v) 00150 { 00151 return EdgeDice::add_vert(sub.patch, map_uv(sub, u, v)); 00152 } 00153 00154 void QuadDice::add_side_u(SubPatch& sub, 00155 vector<int>& outer, vector<int>& inner, 00156 int Mu, int Mv, int tu, int side, int offset) 00157 { 00158 outer.clear(); 00159 inner.clear(); 00160 00161 /* set verts on the edge of the patch */ 00162 outer.push_back(offset + ((side)? 2: 0)); 00163 00164 for(int i = 1; i < tu; i++) { 00165 float u = i/(float)tu; 00166 float v = (side)? 1.0f: 0.0f; 00167 00168 outer.push_back(add_vert(sub, u, v)); 00169 } 00170 00171 outer.push_back(offset + ((side)? 3: 1)); 00172 00173 /* set verts on the edge of the inner grid */ 00174 for(int i = 0; i < Mu-1; i++) { 00175 int j = (side)? Mv-1-1: 0; 00176 inner.push_back(offset + 4 + i + j*(Mu-1)); 00177 } 00178 } 00179 00180 void QuadDice::add_side_v(SubPatch& sub, 00181 vector<int>& outer, vector<int>& inner, 00182 int Mu, int Mv, int tv, int side, int offset) 00183 { 00184 outer.clear(); 00185 inner.clear(); 00186 00187 /* set verts on the edge of the patch */ 00188 outer.push_back(offset + ((side)? 1: 0)); 00189 00190 for(int j = 1; j < tv; j++) { 00191 float u = (side)? 1.0f: 0.0f; 00192 float v = j/(float)tv; 00193 00194 outer.push_back(add_vert(sub, u, v)); 00195 } 00196 00197 outer.push_back(offset + ((side)? 3: 2)); 00198 00199 /* set verts on the edge of the inner grid */ 00200 for(int j = 0; j < Mv-1; j++) { 00201 int i = (side)? Mu-1-1: 0; 00202 inner.push_back(offset + 4 + i + j*(Mu-1)); 00203 } 00204 } 00205 00206 float QuadDice::quad_area(const float3& a, const float3& b, const float3& c, const float3& d) 00207 { 00208 return triangle_area(a, b, d) + triangle_area(a, d, c); 00209 } 00210 00211 float QuadDice::scale_factor(SubPatch& sub, EdgeFactors& ef, int Mu, int Mv) 00212 { 00213 /* estimate area as 4x largest of 4 quads */ 00214 float3 P[3][3]; 00215 00216 for(int i = 0; i < 3; i++) 00217 for(int j = 0; j < 3; j++) 00218 P[i][j] = eval_projected(sub, i*0.5f, j*0.5f); 00219 00220 float A1 = quad_area(P[0][0], P[1][0], P[0][1], P[1][1]); 00221 float A2 = quad_area(P[1][0], P[2][0], P[1][1], P[2][1]); 00222 float A3 = quad_area(P[0][1], P[1][1], P[0][2], P[1][2]); 00223 float A4 = quad_area(P[1][1], P[2][1], P[1][2], P[2][2]); 00224 float Apatch = max(A1, max(A2, max(A3, A4)))*4.0f; 00225 00226 /* solve for scaling factor */ 00227 float Atri = dicing_rate*dicing_rate*0.5f; 00228 float Ntris = Apatch/Atri; 00229 00230 // XXX does the -sqrt solution matter 00231 // XXX max(D, 0.0) is highly suspicious, need to test cases 00232 // where D goes negative 00233 float N = 0.5f*(Ntris - (ef.tu0 + ef.tu1 + ef.tv0 + ef.tv1)); 00234 float D = 4.0f*N*Mu*Mv + (Mu + Mv)*(Mu + Mv); 00235 float S = (Mu + Mv + sqrtf(max(D, 0.0f)))/(2*Mu*Mv); 00236 00237 return S; 00238 } 00239 00240 void QuadDice::add_corners(SubPatch& sub) 00241 { 00242 /* add verts for patch corners */ 00243 if(sub.patch->is_triangle()) { 00244 add_vert(sub, 0.0f, 0.0f); 00245 add_vert(sub, 1.0f, 0.0f); 00246 add_vert(sub, 0.0f, 1.0f); 00247 } 00248 else { 00249 add_vert(sub, 0.0f, 0.0f); 00250 add_vert(sub, 1.0f, 0.0f); 00251 add_vert(sub, 0.0f, 1.0f); 00252 add_vert(sub, 1.0f, 1.0f); 00253 } 00254 } 00255 00256 void QuadDice::add_grid(SubPatch& sub, int Mu, int Mv, int offset) 00257 { 00258 /* create inner grid */ 00259 float du = 1.0f/(float)Mu; 00260 float dv = 1.0f/(float)Mv; 00261 00262 for(int j = 1; j < Mv; j++) { 00263 for(int i = 1; i < Mu; i++) { 00264 float u = i*du; 00265 float v = j*dv; 00266 00267 add_vert(sub, u, v); 00268 00269 if(i < Mu-1 && j < Mv-1) { 00270 int i1 = offset + 4 + (i-1) + (j-1)*(Mu-1); 00271 int i2 = offset + 4 + i + (j-1)*(Mu-1); 00272 int i3 = offset + 4 + i + j*(Mu-1); 00273 int i4 = offset + 4 + (i-1) + j*(Mu-1); 00274 00275 add_triangle(i1, i2, i3); 00276 add_triangle(i1, i3, i4); 00277 } 00278 } 00279 } 00280 } 00281 00282 void QuadDice::dice(SubPatch& sub, EdgeFactors& ef) 00283 { 00284 /* compute inner grid size with scale factor */ 00285 int Mu = max(ef.tu0, ef.tu1); 00286 int Mv = max(ef.tv0, ef.tv1); 00287 00288 float S = scale_factor(sub, ef, Mu, Mv); 00289 Mu = max((int)ceil(S*Mu), 2); // XXX handle 0 & 1? 00290 Mv = max((int)ceil(S*Mv), 2); // XXX handle 0 & 1? 00291 00292 /* reserve space for new verts */ 00293 int offset = mesh->verts.size(); 00294 reserve(ef, Mu, Mv); 00295 00296 /* corners and inner grid */ 00297 add_corners(sub); 00298 add_grid(sub, Mu, Mv, offset); 00299 00300 /* bottom side */ 00301 vector<int> outer, inner; 00302 00303 add_side_u(sub, outer, inner, Mu, Mv, ef.tu0, 0, offset); 00304 stitch_triangles(outer, inner); 00305 00306 /* top side */ 00307 add_side_u(sub, outer, inner, Mu, Mv, ef.tu1, 1, offset); 00308 stitch_triangles(inner, outer); 00309 00310 /* left side */ 00311 add_side_v(sub, outer, inner, Mu, Mv, ef.tv0, 0, offset); 00312 stitch_triangles(inner, outer); 00313 00314 /* right side */ 00315 add_side_v(sub, outer, inner, Mu, Mv, ef.tv1, 1, offset); 00316 stitch_triangles(outer, inner); 00317 00318 assert(vert_offset == mesh->verts.size()); 00319 } 00320 00321 /* TriangleDice */ 00322 00323 TriangleDice::TriangleDice(Mesh *mesh_, int shader_, bool smooth_, float dicing_rate_) 00324 : EdgeDice(mesh_, shader_, smooth_, dicing_rate_) 00325 { 00326 } 00327 00328 void TriangleDice::reserve(EdgeFactors& ef, int M) 00329 { 00330 int num_verts = ef.tu + ef.tv + ef.tw; 00331 00332 for(int m = M-2; m > 0; m -= 2) 00333 num_verts += 3 + (m-1)*3; 00334 00335 if(!(M & 1)) 00336 num_verts++; 00337 00338 EdgeDice::reserve(num_verts, 0); 00339 } 00340 00341 float2 TriangleDice::map_uv(SubPatch& sub, float2 uv) 00342 { 00343 /* map UV from subpatch to patch parametric coordinates */ 00344 return uv.x*sub.Pu + uv.y*sub.Pv + (1.0f - uv.x - uv.y)*sub.Pw; 00345 } 00346 00347 int TriangleDice::add_vert(SubPatch& sub, float2 uv) 00348 { 00349 return EdgeDice::add_vert(sub.patch, map_uv(sub, uv)); 00350 } 00351 00352 void TriangleDice::add_grid(SubPatch& sub, EdgeFactors& ef, int M) 00353 { 00354 // XXX normals are flipped, why? 00355 00356 /* grid is constructed starting from the outside edges, and adding 00357 progressively smaller inner triangles that connected to the outer 00358 one, until M = 1 or 2, the we fill up the last part. */ 00359 vector<int> outer_u, outer_v, outer_w; 00360 int m; 00361 00362 /* add outer corners vertices */ 00363 { 00364 float2 p_u = make_float2(1.0f, 0.0f); 00365 float2 p_v = make_float2(0.0f, 1.0f); 00366 float2 p_w = make_float2(0.0f, 0.0f); 00367 00368 int corner_u = add_vert(sub, p_u); 00369 int corner_v = add_vert(sub, p_v); 00370 int corner_w = add_vert(sub, p_w); 00371 00372 outer_u.push_back(corner_v); 00373 outer_v.push_back(corner_w); 00374 outer_w.push_back(corner_u); 00375 00376 for(int i = 1; i < ef.tu; i++) 00377 outer_u.push_back(add_vert(sub, interp(p_v, p_w, i/(float)ef.tu))); 00378 for(int i = 1; i < ef.tv; i++) 00379 outer_v.push_back(add_vert(sub, interp(p_w, p_u, i/(float)ef.tv))); 00380 for(int i = 1; i < ef.tw; i++) 00381 outer_w.push_back(add_vert(sub, interp(p_u, p_v, i/(float)ef.tw))); 00382 00383 outer_u.push_back(corner_w); 00384 outer_v.push_back(corner_u); 00385 outer_w.push_back(corner_v); 00386 } 00387 00388 for(m = M-2; m > 0; m -= 2) { 00389 vector<int> inner_u, inner_v, inner_w; 00390 00391 float t = m/(float)M; 00392 float2 center = make_float2(1.0f/3.0f, 1.0f/3.0f); 00393 00394 /* 3 corner vertices */ 00395 float2 p_u = interp(center, make_float2(1.0f, 0.0f), t); 00396 float2 p_v = interp(center, make_float2(0.0f, 1.0f), t); 00397 float2 p_w = interp(center, make_float2(0.0f, 0.0f), t); 00398 00399 int corner_u = add_vert(sub, p_u); 00400 int corner_v = add_vert(sub, p_v); 00401 int corner_w = add_vert(sub, p_w); 00402 00403 /* construct array of vertex indices for each side */ 00404 inner_u.push_back(corner_v); 00405 inner_v.push_back(corner_w); 00406 inner_w.push_back(corner_u); 00407 00408 for(int i = 1; i < m; i++) { 00409 /* add vertices between corners */ 00410 float t = i/(float)m; 00411 00412 inner_u.push_back(add_vert(sub, interp(p_v, p_w, t))); 00413 inner_v.push_back(add_vert(sub, interp(p_w, p_u, t))); 00414 inner_w.push_back(add_vert(sub, interp(p_u, p_v, t))); 00415 } 00416 00417 inner_u.push_back(corner_w); 00418 inner_v.push_back(corner_u); 00419 inner_w.push_back(corner_v); 00420 00421 /* stitch together inner/outer with triangles */ 00422 stitch_triangles(outer_u, inner_u); 00423 stitch_triangles(outer_v, inner_v); 00424 stitch_triangles(outer_w, inner_w); 00425 00426 outer_u = inner_u; 00427 outer_v = inner_v; 00428 outer_w = inner_w; 00429 } 00430 00431 /* fill up last part */ 00432 if(m == -1) { 00433 /* single triangle */ 00434 add_triangle(outer_w[0], outer_u[0], outer_v[0]); 00435 } 00436 else { 00437 /* center vertex + 6 triangles */ 00438 int center = add_vert(sub, make_float2(1.0f/3.0f, 1.0f/3.0f)); 00439 00440 add_triangle(outer_w[0], outer_w[1], center); 00441 add_triangle(outer_w[1], outer_w[2], center); 00442 add_triangle(outer_u[0], outer_u[1], center); 00443 add_triangle(outer_u[1], outer_u[2], center); 00444 add_triangle(outer_v[0], outer_v[1], center); 00445 add_triangle(outer_v[1], outer_v[2], center); 00446 } 00447 } 00448 00449 void TriangleDice::dice(SubPatch& sub, EdgeFactors& ef) 00450 { 00451 /* todo: handle 2 1 1 resolution */ 00452 int M = max(ef.tu, max(ef.tv, ef.tw)); 00453 00454 reserve(ef, M); 00455 add_grid(sub, ef, M); 00456 00457 assert(vert_offset == mesh->verts.size()); 00458 } 00459 00460 CCL_NAMESPACE_END 00461