Blender V2.61 - r43446

subd_build.cpp

Go to the documentation of this file.
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