Blender V2.61 - r43446
|
00001 /* 00002 * Copyright 2006, NVIDIA Corporation Ignacio Castano <icastano@nvidia.com> 00003 * 00004 * Modifications copyright (c) 2011, Blender Foundation. All rights reserved. 00005 * 00006 * Permission is hereby granted, free of charge, to any person obtaining a copy 00007 * of this software and associated documentation files (the "Software"), to deal 00008 * in the Software without restriction, including without limitation the rights 00009 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00010 * copies of the Software, and to permit persons to whom the Software is 00011 * furnished to do so, subject to the following conditions: 00012 * 00013 * The above copyright notice and this permission notice shall be included in 00014 * all copies or substantial portions of the Software. 00015 * 00016 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00017 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00018 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00019 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00020 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00021 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00022 * THE SOFTWARE. 00023 */ 00024 00025 #include "subd_build.h" 00026 #include "subd_edge.h" 00027 #include "subd_face.h" 00028 #include "subd_ring.h" 00029 #include "subd_mesh.h" 00030 #include "subd_patch.h" 00031 #include "subd_stencil.h" 00032 #include "subd_vert.h" 00033 00034 #include "util_algorithm.h" 00035 #include "util_debug.h" 00036 #include "util_math.h" 00037 #include "util_string.h" 00038 00039 CCL_NAMESPACE_BEGIN 00040 00041 /* Subd Builder */ 00042 00043 SubdBuilder *SubdBuilder::create(bool linear) 00044 { 00045 if(linear) 00046 return new SubdLinearBuilder(); 00047 else 00048 return new SubdAccBuilder(); 00049 } 00050 00051 /* Gregory ACC Stencil */ 00052 00053 class GregoryAccStencil { 00054 public: 00055 SubdFaceRing *ring; 00056 StencilMask stencil[20]; 00057 00058 GregoryAccStencil(SubdFaceRing *ring_) 00059 { 00060 ring = ring_; 00061 00062 for(int i = 0; i < 20; i++) 00063 stencil[i].resize(ring->num_verts()); 00064 } 00065 00066 StencilMask& get(int i) 00067 { 00068 assert(i < 20); 00069 return stencil[i]; 00070 } 00071 00072 float& get(int i, SubdVert *vert) 00073 { 00074 assert(i < 20); 00075 return stencil[i][ring->vert_index(vert)]; 00076 } 00077 }; 00078 00079 static float pseudoValence(SubdVert *vert) 00080 { 00081 float valence = (float)vert->valence(); 00082 00083 if(vert->is_boundary()) { 00084 /* we treat boundary verts as being half a closed mesh. corners are 00085 special case. n = 4 for corners and n = 2*(n-1) for boundaries. */ 00086 if(valence == 2) return 4; 00087 return (valence - 1)*2; 00088 } 00089 00090 return valence; 00091 } 00092 00093 /* Subd ACC Builder */ 00094 00095 SubdAccBuilder::SubdAccBuilder() 00096 { 00097 } 00098 00099 SubdAccBuilder::~SubdAccBuilder() 00100 { 00101 } 00102 00103 Patch *SubdAccBuilder::run(SubdFace *face) 00104 { 00105 SubdFaceRing ring(face, face->edge); 00106 GregoryAccStencil stencil(&ring); 00107 float3 position[20]; 00108 00109 computeCornerStencil(&ring, &stencil); 00110 computeEdgeStencil(&ring, &stencil); 00111 computeInteriorStencil(&ring, &stencil); 00112 00113 ring.evaluate_stencils(position, stencil.stencil, 20); 00114 00115 if(face->num_edges() == 3) { 00116 GregoryTrianglePatch *patch = new GregoryTrianglePatch(); 00117 memcpy(patch->hull, position, sizeof(float3)*20); 00118 return patch; 00119 } 00120 else if(face->num_edges() == 4) { 00121 GregoryQuadPatch *patch = new GregoryQuadPatch(); 00122 memcpy(patch->hull, position, sizeof(float3)*20); 00123 return patch; 00124 } 00125 00126 assert(0); /* n-gons should have been split already */ 00127 return NULL; 00128 } 00129 00130 /* Gregory Patch */ 00131 00132 void SubdAccBuilder::computeCornerStencil(SubdFaceRing *ring, GregoryAccStencil *stencil) 00133 { 00134 const int cornerIndices[7] = {8, 11, 19, 16, 6, 9, 12}; 00135 int primitiveOffset = ring->is_quad()? 0: 4; 00136 00137 SubdEdge *firstEdge = ring->firstEdge(); 00138 00139 /* compute corner control points */ 00140 int v = 0; 00141 00142 for(SubdFace::EdgeIterator it(firstEdge); !it.isDone(); it.advance(), v++) { 00143 SubdVert *vert = it.current()->from(); 00144 int valence = vert->valence(); 00145 int cid = cornerIndices[primitiveOffset+v]; 00146 00147 if(vert->is_boundary()) { 00148 /* compute vertex limit position */ 00149 SubdEdge *edge0 = vert->edge; 00150 SubdEdge *edge1 = vert->edge->prev; 00151 00152 assert(edge0->face == NULL); 00153 assert(edge0->to() != vert); 00154 assert(edge1->face == NULL); 00155 assert(edge1->from() != vert); 00156 00157 stencil->get(cid, vert) = 2.0f/3.0f; 00158 stencil->get(cid, edge0->to()) = 1.0f/6.0f; 00159 stencil->get(cid, edge1->from()) = 1.0f/6.0f; 00160 00161 assert(stencil->get(cid).is_normalized()); 00162 } 00163 else { 00164 stencil->get(cid, vert) = 3.0f*valence*valence; 00165 00166 for(SubdVert::EdgeIterator eit(vert->edge); !eit.isDone(); eit.advance()) { 00167 SubdEdge *edge = eit.current(); 00168 assert(vert->co == edge->from()->co); 00169 00170 stencil->get(cid, edge->to()) = 12.0f; 00171 00172 if(SubdFaceRing::is_triangle(edge->face)) { 00173 /* distribute weight to all verts */ 00174 stencil->get(cid, vert) += 1.0f; 00175 stencil->get(cid, edge->to()) += 1.0f; 00176 stencil->get(cid, edge->next->to()) += 1.0f; 00177 } 00178 else 00179 stencil->get(cid, edge->next->to()) = 3.0f; 00180 } 00181 00182 /* normalize stencil. */ 00183 stencil->get(cid).normalize(); 00184 } 00185 } 00186 } 00187 00188 void SubdAccBuilder::computeEdgeStencil(SubdFaceRing *ring, GregoryAccStencil *stencil) 00189 { 00190 const int cornerIndices[7] = {8, 11, 19, 16, 6, 9, 12}; 00191 const int edge1Indices[7] = {9, 13, 18, 14, 7, 10, 13}; 00192 const int edge2Indices[7] = {12, 10, 15, 17, 14, 8, 11}; 00193 int primitiveOffset = ring->is_quad()? 0: 4; 00194 00195 float tangentScales[14] = { 00196 0.0f, 0.0f, 0.0f, 0.667791f, 1.0f, 00197 1.11268f, 1.1284f, 1.10289f, 1.06062f, 00198 1.01262f, 0.963949f, 0.916926f, 0.872541f, 0.831134f 00199 }; 00200 00201 SubdEdge *firstEdge = ring->firstEdge(); 00202 00203 /* compute corner / edge control points */ 00204 int v = 0; 00205 00206 for(SubdFace::EdgeIterator it(firstEdge); !it.isDone(); it.advance(), v++) { 00207 SubdVert *vert = it.current()->from(); 00208 int valence = vert->valence(); 00209 int cid = cornerIndices[primitiveOffset+v]; 00210 00211 int i1 = 0, i2 = 0, j = 0; 00212 00213 for(SubdVert::EdgeIterator eit(vert->edge); !eit.isDone(); eit.advance(), j++) { 00214 SubdEdge *edge = eit.current(); 00215 00216 /* find index of "our" edge for edge control points */ 00217 if(edge == it.current()) 00218 i1 = j; 00219 if(edge == it.current()->prev->pair) 00220 i2 = j; 00221 } 00222 00223 if(vert->is_boundary()) { 00224 int num_verts = ring->num_verts(); 00225 StencilMask r0(num_verts); 00226 StencilMask r1(num_verts); 00227 00228 computeBoundaryTangentStencils(ring, vert, r0, r1); 00229 00230 int k = valence - 1; 00231 float omega = M_PI_F / k; 00232 00233 int eid1 = edge1Indices[primitiveOffset + v]; 00234 int eid2 = edge2Indices[primitiveOffset + v]; 00235 00236 if(it.current()->is_boundary()) { 00237 assert(it.current()->from() == vert); 00238 00239 stencil->get(eid1, vert) = 2.0f / 3.0f; 00240 stencil->get(eid1, it.current()->to()) = 1.0f / 3.0f; 00241 00242 assert(stencil->get(eid1).is_normalized()); 00243 00244 if(valence == 2) { 00245 for(int i = 0; i < num_verts; i++) 00246 stencil->get(eid1)[i] += r0[i] * 0.0001f; 00247 } 00248 } 00249 else { 00250 stencil->get(eid1) = stencil->get(cid); 00251 00252 /* compute index of it.current() around vert */ 00253 int idx = 0; 00254 00255 for(SubdVert::EdgeIterator eit(vert->edges()); !eit.isDone(); eit.advance(), idx++) 00256 if(eit.current() == it.current()) 00257 break; 00258 00259 assert(idx != valence); 00260 00261 float c = cosf(idx * omega); 00262 float s = sinf(idx * omega); 00263 00264 for(int i = 0; i < num_verts; i++) 00265 stencil->get(eid1)[i] += (r0[i] * s + r1[i] * c) / 3.0f; 00266 } 00267 00268 if(it.current()->prev->is_boundary()) { 00269 assert(it.current()->prev->pair->from() == vert); 00270 00271 stencil->get(eid2, vert) = 2.0f / 3.0f; 00272 stencil->get(eid2, it.current()->prev->pair->to()) = 1.0f / 3.0f; 00273 00274 assert(stencil->get(eid2).is_normalized()); 00275 00276 if(valence == 2) { 00277 for(int i = 0; i < num_verts; i++) 00278 stencil->get(eid2)[i] += r0[i] * 0.0001f; 00279 } 00280 } 00281 else { 00282 stencil->get(eid2) = stencil->get(cid); 00283 00284 /* compute index of it.current() around vert */ 00285 int idx = 0; 00286 00287 for(SubdVert::EdgeIterator eit(vert->edges()); !eit.isDone(); eit.advance(), idx++) 00288 if(eit.current() == it.current()->prev->pair) 00289 break; 00290 00291 assert(idx != valence); 00292 00293 float c = cosf(idx * omega); 00294 float s = sinf(idx * omega); 00295 00296 for(int i = 0; i < num_verts; i++) 00297 stencil->get(eid2)[i] += (r0[i] * s + r1[i] * c) / 3; 00298 } 00299 } 00300 else { 00301 float costerm = cosf(M_PI_F / valence); 00302 float sqrtterm = sqrtf(4.0f + costerm*costerm); 00303 00304 /* float tangentScale = 1.0f; */ 00305 float tangentScale = tangentScales[min(valence, 13U)]; 00306 00307 float alpha = (1.0f + costerm / sqrtterm) / (3.0f * valence) * tangentScale; 00308 float beta = 1.0f / (3.0f * valence * sqrtterm) * tangentScale; 00309 00310 00311 int eid1 = edge1Indices[primitiveOffset + v]; 00312 int eid2 = edge2Indices[primitiveOffset + v]; 00313 00314 stencil->get(eid1) = stencil->get(cid); 00315 stencil->get(eid2) = stencil->get(cid); 00316 00317 int j = 0; 00318 for(SubdVert::EdgeIterator eit(vert->edges()); !eit.isDone(); eit.advance(), j++) { 00319 SubdEdge *edge = eit.current(); 00320 assert(vert->co == edge->from()->co); 00321 00322 float costerm1_a = cosf(M_PI_F * 2 * (j-i1) / valence); 00323 float costerm1_b = cosf(M_PI_F * (2 * (j-i1)-1) / valence); /* -1 instead of +1 b/c of edge->next->to() */ 00324 00325 float costerm2_a = cosf(M_PI_F * 2 * (j-i2) / valence); 00326 float costerm2_b = cosf(M_PI_F * (2 * (j-i2)-1) / valence); /* -1 instead of +1 b/c of edge->next->to() */ 00327 00328 00329 stencil->get(eid1, edge->to()) += alpha * costerm1_a; 00330 stencil->get(eid2, edge->to()) += alpha * costerm2_a; 00331 00332 if(SubdFaceRing::is_triangle(edge->face)) { 00333 /* @@ this probably does not provide watertight results!! (1/3 + 1/3 + 1/3 != 1) */ 00334 00335 /* distribute weight to all verts */ 00336 stencil->get(eid1, vert) += beta * costerm1_b / 3.0f; 00337 stencil->get(eid1, edge->to()) += beta * costerm1_b / 3.0f; 00338 stencil->get(eid1, edge->next->to()) += beta * costerm1_b / 3.0f; 00339 00340 stencil->get(eid2, vert) += beta * costerm2_b / 3.0f; 00341 stencil->get(eid2, edge->to()) += beta * costerm2_b / 3.0f; 00342 stencil->get(eid2, edge->next->to()) += beta * costerm2_b / 3.0f; 00343 } 00344 else { 00345 stencil->get(eid1, edge->next->to()) += beta * costerm1_b; 00346 stencil->get(eid2, edge->next->to()) += beta * costerm2_b; 00347 } 00348 } 00349 } 00350 } 00351 } 00352 00353 void SubdAccBuilder::computeInteriorStencil(SubdFaceRing *ring, GregoryAccStencil *stencil) 00354 { 00355 static int corner1Indices[7] = {8, 11, 19, 16, 6, 9, 12}; 00356 static int corner2Indices[7] = {11, 19, 16, 8, 9, 12, 6}; 00357 static int edge1Indices[7] = {9, 13, 18, 14, 7, 10, 13}; 00358 static int edge2Indices[7] = {10, 15, 17, 12, 8, 11, 14}; 00359 static int interior1Indices[7] = {1, 3, 6, 4, 1, 3, 5}; 00360 static int interior2Indices[7] = {2, 7, 5, 0, 2, 4, 0}; 00361 00362 int primitiveOffset = ring->is_quad()? 0: 4; 00363 00364 SubdFace * face = ring->face(); 00365 SubdEdge *firstEdge = ring->firstEdge(); 00366 00367 /* interior control points */ 00368 int v = 0; 00369 for(SubdFace::EdgeIterator it(firstEdge); !it.isDone(); it.advance(), v++) { 00370 SubdEdge *edge = it.current(); 00371 00372 if(edge->is_boundary()) { 00373 float valence1 = pseudoValence(edge->from()); 00374 float valence2 = pseudoValence(edge->to()); 00375 00376 float weights1[4]; 00377 float weights2[4]; 00378 00379 if(ring->is_quad()) { 00380 weights1[0] = 3 * valence1; 00381 weights1[1] = 6; 00382 weights1[2] = 3; 00383 weights1[3] = 6; 00384 00385 weights2[0] = 6; 00386 weights2[1] = 3 * valence2; 00387 weights2[2] = 6; 00388 weights2[3] = 3; 00389 } 00390 else { 00391 assert(ring->is_triangle()); 00392 weights1[0] = 3 * valence1 + 1; 00393 weights1[1] = 7; 00394 weights1[2] = 7; 00395 00396 weights2[0] = 7; 00397 weights2[1] = 3 * valence2 + 1; 00398 weights2[2] = 7; 00399 } 00400 00401 int idx1 = interior1Indices[primitiveOffset+v]; 00402 int idx2 = interior2Indices[primitiveOffset+v]; 00403 00404 int i = 0; 00405 for(SubdFace::EdgeIterator it(face->edges(edge)); !it.isDone(); it.advance(), i++) { 00406 SubdVert *vert = it.current()->from(); 00407 stencil->get(idx1, vert) += weights1[i]; 00408 stencil->get(idx2, vert) += weights2[i]; 00409 } 00410 00411 stencil->get(idx1).normalize(); 00412 stencil->get(idx2).normalize(); 00413 } 00414 else { 00415 SubdVert *e0 = edge->from(); 00416 float costerm0 = cosf(2.0f * M_PI_F / pseudoValence(e0)); 00417 00418 SubdVert *f0 = edge->to(); 00419 float costerm1 = cosf(2.0f * M_PI_F / pseudoValence(f0)); 00420 00421 /* p0 +------+ q0 00422 * | | 00423 * f0 +======+ e0 <=== current edge 00424 * | | 00425 * p1 +------+ q1 00426 */ 00427 00428 SubdVert *q0 = edge->next->to(); 00429 SubdVert *p0 = edge->prev->from(); 00430 00431 SubdVert *p1 = edge->pair->next->to(); 00432 SubdVert *q1 = edge->pair->prev->from(); 00433 00434 00435 StencilMask x(ring->num_verts()); 00436 StencilMask y(ring->num_verts()); 00437 00438 for(int i = 0; i < ring->num_verts(); i++) { 00439 x[i] = 00440 (costerm1 * stencil->get(corner1Indices[primitiveOffset+v])[i] - 00441 (2*costerm0 + costerm1) * stencil->get(edge1Indices[primitiveOffset+v])[i] + 00442 2*costerm0 * stencil->get(edge2Indices[primitiveOffset+v])[i]) / 3.0f; 00443 } 00444 00445 /* y = (2*( midedgeA1 - midedgeB1) + 4*(centroidA - centroidB))/18.0f; */ 00446 y[ring->vert_index(p0)] = 1; 00447 y[ring->vert_index(p1)] = -1; 00448 00449 /* add centroidA */ 00450 if(ring->is_triangle()) { 00451 y[ring->vert_index(p0)] += 4.0f / 3.0f; 00452 y[ring->vert_index(e0)] += 4.0f / 3.0f; 00453 y[ring->vert_index(f0)] += 4.0f / 3.0f; 00454 } 00455 else { 00456 y[ring->vert_index(p0)] += 1; 00457 y[ring->vert_index(q0)] += 1; 00458 y[ring->vert_index(e0)] += 1; 00459 y[ring->vert_index(f0)] += 1; 00460 } 00461 00462 /* sub centroidB */ 00463 if(SubdFaceRing::is_triangle(edge->pair->face)) { 00464 y[ring->vert_index(p1)] -= 4.0f / 3.0f; 00465 y[ring->vert_index(e0)] -= 4.0f / 3.0f; 00466 y[ring->vert_index(f0)] -= 4.0f / 3.0f; 00467 00468 } 00469 else { 00470 y[ring->vert_index(p1)] -= 1; 00471 y[ring->vert_index(q1)] -= 1; 00472 y[ring->vert_index(e0)] -= 1; 00473 y[ring->vert_index(f0)] -= 1; 00474 } 00475 00476 y /= 18.0f; 00477 00478 if(ring->is_triangle()) { 00479 x *= 3.0f / 4.0f; 00480 y *= 3.0f / 4.0f; 00481 } 00482 00483 /* this change makes the triangle boundaries smoother, but distorts the quads next to them */ 00484 /*if(ring->is_triangle() || SubdFaceRing::is_triangle(edge->pair->face)) 00485 { 00486 y *= 4.0f / 3.0f; 00487 }*/ 00488 00489 stencil->get(interior1Indices[primitiveOffset+v]) = stencil->get(edge1Indices[primitiveOffset+v]); 00490 stencil->get(interior1Indices[primitiveOffset+v]) += x; 00491 stencil->get(interior1Indices[primitiveOffset+v]) += y; 00492 00493 for(int i = 0; i < ring->num_verts(); i++) { 00494 x[i] = 00495 (costerm0 * stencil->get(corner2Indices[primitiveOffset+v])[i] - 00496 (2*costerm1 + costerm0) * stencil->get(edge2Indices[primitiveOffset+v])[i] + 00497 2*costerm1 * stencil->get(edge1Indices[primitiveOffset+v])[i]) / 3.0f; 00498 } 00499 00500 /* y = (2*( midedgeA2 - midedgeB2) + 4*(centroidA - centroidB))/18.0f; */ 00501 y = 0.0f; 00502 00503 /* (2*( midedgeA2 - midedgeB2) */ 00504 y[ring->vert_index(q0)] = 1; 00505 y[ring->vert_index(q1)] = -1; 00506 00507 /* add centroidA */ 00508 if(ring->is_triangle()) { 00509 y[ring->vert_index(p0)] += 4.0f / 3.0f; 00510 y[ring->vert_index(e0)] += 4.0f / 3.0f; 00511 y[ring->vert_index(f0)] += 4.0f / 3.0f; 00512 } 00513 else { 00514 y[ring->vert_index(p0)] += 1; 00515 y[ring->vert_index(q0)] += 1; 00516 y[ring->vert_index(e0)] += 1; 00517 y[ring->vert_index(f0)] += 1; 00518 } 00519 00520 /* sub centroidB */ 00521 if(SubdFaceRing::is_triangle(edge->pair->face)) { 00522 y[ring->vert_index(p1)] -= 4.0f / 3.0f; 00523 y[ring->vert_index(e0)] -= 4.0f / 3.0f; 00524 y[ring->vert_index(f0)] -= 4.0f / 3.0f; 00525 00526 } 00527 else { 00528 y[ring->vert_index(p1)] -= 1; 00529 y[ring->vert_index(q1)] -= 1; 00530 y[ring->vert_index(e0)] -= 1; 00531 y[ring->vert_index(f0)] -= 1; 00532 } 00533 00534 y /= 18.0f; 00535 00536 if(ring->is_triangle()) { 00537 x *= 3.0f / 4.0f; 00538 y *= 3.0f / 4.0f; 00539 } 00540 00541 /* this change makes the triangle boundaries smoother, but distorts the quads next to them. */ 00542 /*if(ring->is_triangle() || SubdFaceRing::is_triangle(edge->pair->face)) 00543 y *= 4.0f / 3.0f;*/ 00544 00545 stencil->get(interior2Indices[primitiveOffset+v]) = stencil->get(edge2Indices[primitiveOffset+v]); 00546 stencil->get(interior2Indices[primitiveOffset+v]) += x; 00547 stencil->get(interior2Indices[primitiveOffset+v]) += y; 00548 } 00549 } 00550 } 00551 00552 void SubdAccBuilder::computeBoundaryTangentStencils(SubdFaceRing *ring, SubdVert *vert, StencilMask & r0, StencilMask & r1) 00553 { 00554 assert(vert->is_boundary()); 00555 assert(r0.size() == ring->num_verts()); 00556 assert(r1.size() == ring->num_verts()); 00557 00558 SubdEdge *edge0 = vert->edge; 00559 assert(edge0->face == NULL); 00560 assert(edge0->to() != vert); 00561 00562 SubdEdge *edgek = vert->edge->prev; 00563 assert(edgek->face == NULL); 00564 assert(edgek->from() != vert); 00565 00566 int valence = vert->valence(); 00567 00568 int k = valence - 1; 00569 float omega = M_PI_F / k; 00570 float s = sinf(omega); 00571 float c = cosf(omega); 00572 00573 float factor = 1.0f / (3 * k + c); 00574 00575 float gamma = -4 * s * factor; 00576 r0[ring->vert_index(vert)] = gamma; 00577 /* r1[ring->vert_index(vert)] = 0; */ 00578 00579 float salpha0 = -((1 + 2 * c) * sqrtf(1 + c)) * factor / sqrtf(1 - c); 00580 float calpha0 = 1.0f / 2.0f; 00581 00582 r0[ring->vert_index(edge0->to())] = salpha0; 00583 r1[ring->vert_index(edge0->to())] = calpha0; 00584 00585 float salphak = salpha0; 00586 float calphak = -1.0f / 2.0f; 00587 00588 r0[ring->vert_index(edgek->from())] = salphak; 00589 r1[ring->vert_index(edgek->from())] = calphak; 00590 00591 int j = 0; 00592 for(SubdVert::EdgeIterator it(vert->edges()); !it.isDone(); it.advance(), j++) { 00593 SubdEdge *edge = it.current(); 00594 00595 if(j == k) break; 00596 00597 SubdVert *p = edge->to(); 00598 SubdVert *q = edge->pair->prev->from(); 00599 00600 float alphaj = 4 * sinf(j * omega) * factor; 00601 float betaj = (sinf(j * omega) + sinf((j + 1) * omega)) * factor; 00602 00603 if(j != 0) 00604 r0[ring->vert_index(p)] += alphaj; 00605 00606 if(edge->pair->prev->prev->prev == edge->pair) { 00607 r0[ring->vert_index(vert)] += betaj / 3.0f; 00608 r0[ring->vert_index(edge->pair->from())] += betaj / 3.0f; 00609 r0[ring->vert_index(q)] += betaj / 3.0f; 00610 } 00611 else 00612 r0[ring->vert_index(q)] += betaj; 00613 } 00614 00615 if(valence == 2) { 00616 /* r0 perpendicular to r1 */ 00617 r0[ring->vert_index(vert)] = -4.0f / 3.0f; 00618 r0[ring->vert_index(edgek->from())] = 1.0f / 2.0f; 00619 r0[ring->vert_index(edge0->to())] = 1.0f / 2.0f; 00620 r0[ring->vert_index(edge0->next->to())] = 1.0f / 3.0f; 00621 } 00622 } 00623 00624 /* Subd Linear Builder */ 00625 00626 SubdLinearBuilder::SubdLinearBuilder() 00627 { 00628 } 00629 00630 SubdLinearBuilder::~SubdLinearBuilder() 00631 { 00632 } 00633 00634 Patch *SubdLinearBuilder::run(SubdFace *face) 00635 { 00636 Patch *patch; 00637 float3 *hull; 00638 00639 if(face->num_edges() == 3) { 00640 LinearTrianglePatch *lpatch = new LinearTrianglePatch(); 00641 hull = lpatch->hull; 00642 patch = lpatch; 00643 } 00644 else if(face->num_edges() == 4) { 00645 LinearQuadPatch *lpatch = new LinearQuadPatch(); 00646 hull = lpatch->hull; 00647 patch = lpatch; 00648 } 00649 else { 00650 assert(0); /* n-gons should have been split already */ 00651 return NULL; 00652 } 00653 00654 int i = 0; 00655 00656 for(SubdFace::EdgeIterator it(face->edge); !it.isDone(); it.advance()) 00657 hull[i++] = it.current()->from()->co; 00658 00659 if(face->num_edges() == 4) 00660 swap(hull[2], hull[3]); 00661 00662 return patch; 00663 } 00664 00665 CCL_NAMESPACE_END 00666