Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages

ButterflySubdivision.cpp

Go to the documentation of this file.
00001 
00002 #include "Subdiv/ButterflySubdivision.h"
00003 
00004 #include "mesh/meshGroup.h"
00005 #include "mesh/indexVertex.h"
00006 
00007 ButterflySubdivision::ButterflySubdivision(double w) {
00008 
00009   weight = w;
00010 
00011 }
00012 
00013 /*****
00014  * getOpposingVertex(gmVector3&, gmVector3&, indexFace*, indexEdge*, int)
00015  *
00016  * returns info for the far vertex on the opposing face of this edge
00017  */
00018 int ButterflySubdivision::getOpposingVertexInfo(gmVector3 &vertex,
00019                                                 gmVector3 &normal,
00020                                                 indexEdge* edge, 
00021                                                 indexFace* face,
00022                                                 U32 i) {
00023 
00024   if (edge->getNumberOfAdjFaces() == 2) {
00025 
00026     indexFace other_face;
00027 
00028     // don't grab the same face!
00029     if(face->getIndex() != edge->getFaceIndex(0)) {
00030       other_face = edge->getFace(0);
00031     } else {
00032       other_face = edge->getFace(1);
00033     }
00034 
00035     if (other_face.getVertexCount() != 3) {
00036       throw Nexception("ButterflySubdivision: requires triangular mesh!");
00037     }
00038 
00039     for(int j=0; j < 3; j++) {
00040       if (edge->getVertexA() != other_face.getVertex(j) &&
00041           edge->getVertexB() != other_face.getVertex(j)) {
00042 
00043         vertex = other_face.getVertex(j);
00044         normal = other_face.getNormal(j);
00045         return 1;
00046 
00047       }
00048     }
00049 
00050   }
00051 
00052   return 0;
00053 
00054 } // end getOpposingVertex
00055 
00056 
00057 /*****
00058  * divideEdge(indexEdge*, indexFace*, int)
00059  *
00060  * Returns a vertex which subdivides this edge using the standard scheme
00061  */
00062 void ButterflySubdivision::divideEdge(gmVector3& vertex,
00063                                       gmVector3& normal,
00064                                       indexEdge* edge, 
00065                                       indexFace* face, 
00066                                       U32 i) {
00067   gmVector3 a,b,c,d,e,f,g,h;
00068   gmVector3 na,nb,nc,nd,ne,nf,ng,nh;
00069 
00070   bool valid_stencil = true;
00071 
00072   /* c---d---e
00073    *  \ / \ /
00074    *   a-->b
00075    *  / \ / \
00076    * f---g---h
00077    */
00078 
00079   a = edge->getVertexA(); na = edge->getNormalA();
00080   b = edge->getVertexB(); nb = edge->getNormalB();
00081 
00082   g = face->getVertex((i+2)%3); ng = face->getNormal((i+2)%3);
00083  
00084   if (!getOpposingVertexInfo(h, nh, &(face->getEdge((i+1)%3)), face, (i+1)%3))
00085     valid_stencil = false;
00086     
00087   if (!getOpposingVertexInfo(f, nf, &(face->getEdge((i+2)%3)), face, (i+2)%3))
00088     valid_stencil = false;
00089   
00090   // Now, move to the top
00091   
00092   getOpposingVertexInfo(d, nd, edge, face, i);
00093 
00094   if (edge->getNumberOfAdjFaces() == 2) {
00095 
00096     indexFace* top_face;
00097 
00098     if (face->getIndex() != edge->getFaceIndex(0)) {
00099       top_face = &(edge->getFace(0));
00100     } else {
00101       top_face = &(edge->getFace(1));
00102     }
00103 
00104     if (top_face->getVertexCount() != 3) {
00105       throw Nexception("ButterflySubdivision: requires triangular mesh!");
00106     }
00107 
00108     for(int k=0; k < 3; k++) {
00109 
00110       if ((edge->getVertexA() == top_face->getEdge(k).getVertexA()) &&
00111           (edge->getVertexB() == top_face->getEdge(k).getVertexB())) {
00112 
00113         if(!getOpposingVertexInfo(e, ne, &(top_face->getEdge((k+1)%3)), 
00114                               top_face, (k+1)%3))
00115           valid_stencil = false;
00116 
00117         if(!getOpposingVertexInfo(c, nc, &(top_face->getEdge((k+2)%3)), 
00118                               top_face, (k+2)%3))
00119           valid_stencil = false;
00120 
00121       } else if ((edge->getVertexA() == top_face->getEdge(k).getVertexB()) &&
00122                  (edge->getVertexB() == top_face->getEdge(k).getVertexA())) {
00123 
00124         if(!getOpposingVertexInfo(c, nc, &(top_face->getEdge((k+1)%3)), 
00125                               top_face, (k+1)%3))
00126           valid_stencil = false;
00127 
00128         if(!getOpposingVertexInfo(e, ne, &(top_face->getEdge((k+2)%3)), 
00129                               top_face, (k+2)%3))
00130           valid_stencil = false;
00131 
00132       }                                                                  
00133 
00134     } // end loop
00135 
00136   } else {
00137     
00138     valid_stencil = false;
00139 
00140   }
00141 
00142   // Now, all the vertices should be ready
00143 
00144   if (valid_stencil) {
00145     
00146     vertex =
00147       (a + b)*0.5 + 
00148       (d + g)*(0.125 + 2.0*weight) - 
00149       (c + e + f + h)*(0.0625 - weight);
00150 
00151     normal =
00152       (na + nb)*0.5 +
00153       (nd + ng)*(0.125 + 2.0*weight) -
00154       (nc + ne + nf + nh)*(0.0625 - weight);
00155 
00156   } else {
00157     
00158     vertex = (a + b)*0.5;
00159     normal = (na + nb)*0.5;
00160 
00161   }
00162 
00163 }
00164 
00165 /*****
00166  * divideFace(indexFace*, Mesh*)
00167  *
00168  * Subdivides a single face
00169  */
00170 void ButterflySubdivision::divideFace(indexFace* face, Mesh* m) {
00171 
00172   gmVector3 vertex;
00173   gmVector3 normal;
00174 
00175   for (U32 i=0; i < 3; i++) {
00176 
00177     indexEdge &edge = face->getEdge(i);
00178 
00179     if(!edge.hasArbitraryIndex()) {
00180 
00181       divideEdge(vertex, normal, &edge, face, i);
00182       edge.setArbitraryIndex(m->addVertex(vertex));
00183       indexVertex &v = m->getIndexVertex(edge.getArbitraryIndex());
00184       v.setNormalIndex(m->addNormal(normal));
00185 
00186     }
00187 
00188   }
00189 
00190 } // end divideFace
00191 
00192 /*****
00193  * subdivide (Mesh*, U32)
00194  *
00195  * Does one subdivision step on the entire mesh level defined by base
00196  */
00197 void ButterflySubdivision::subdivide(Mesh* m, U32 base) {
00198 
00199   U32 group;
00200   group = m->addGroup();
00201 
00202   // Extract the group (level) to be subdivided
00203   MeshGroup &base_mesh = m->getGroup(base);
00204 
00205   // Loop through faces to subdivide
00206   base_mesh.rewindFaceList();
00207   while (indexFace *face = base_mesh.facePostIncrement()) {
00208 
00209     U32 edge_count = face->getEdgeCount();
00210 
00211     // Assuming triangular mesh
00212     if (edge_count != 3) {
00213       throw Nexception("ButterflySubdivision: requires triangular mesh!");
00214     } 
00215 
00216     divideFace(face, m);
00217 
00218   } // end while
00219 
00220   // Loop through faces to compose new mesh
00221   base_mesh.rewindFaceList();
00222   while(U32 *findex = base_mesh.faceIndexPostIncrement()) {
00223 
00224     indexFace* face = &m->getFace(*findex);
00225 
00226     U32 new_vertices[3];
00227     U32 old_vertices[3];
00228     U32 new_normals[3];
00229     U32 old_normals[3];
00230 
00231     // Get "old" vertices
00232     U32 vertex_count = face->getVertexCount();
00233         U32 i; // VC++ wants declarator in only the first for loop
00234     for (i=0; i < vertex_count; i++) {
00235 
00236       old_vertices[i] = face->getVertexIndex(i);
00237       old_normals[i] = face->getNormalIndex(i);
00238 
00239     }
00240 
00241     // Get new vertices
00242     U32 edge_count = face->getEdgeCount();
00243     for(i=0; i < edge_count; i++) {
00244 
00245       indexEdge &edge = face->getEdge(i);
00246       new_vertices[i] = edge.getArbitraryIndex();
00247       new_normals[i] = m->getIndexVertex(edge.getArbitraryIndex()).getNormalIndex();
00248       
00249     }      
00250 
00251     // Stich 'em in
00252 
00253     indexFace face0;
00254     face0.addVertex(old_vertices[0], old_normals[0]);
00255     face0.addVertex(new_vertices[0], new_normals[0]);
00256     face0.addVertex(new_vertices[2], new_normals[2]);
00257 
00258     indexFace face1;
00259     face1.addVertex(old_vertices[1], old_normals[1]);
00260     face1.addVertex(new_vertices[1], new_normals[1]);
00261     face1.addVertex(new_vertices[0], new_normals[0]);
00262 
00263     indexFace face2;
00264     face2.addVertex(old_vertices[2], old_normals[2]);
00265     face2.addVertex(new_vertices[2], new_normals[2]);
00266     face2.addVertex(new_vertices[1], new_normals[1]);
00267 
00268     indexFace face3;
00269     face3.addVertex(new_vertices[0], new_normals[0]);
00270     face3.addVertex(new_vertices[1], new_normals[1]);
00271     face3.addVertex(new_vertices[2], new_normals[2]);
00272     
00273     m->addFace(face0);
00274     m->addFace(face1);
00275     m->addFace(face2);
00276     m->addFace(face3);
00277 
00278   } // end while
00279 
00280 } // end subdivide
00281 
00282 /*****
00283  * compute(int)
00284  *
00285  * Computes subdivision to the nth level from the base
00286  */
00287 void ButterflySubdivision::compute(int n) {
00288 
00289   U32 base=0;
00290 
00291   // Step through the levels currently in the mesh
00292   m_mesh.rewindGroupList();
00293   while (m_mesh.groupPostIncrement()) base++;
00294 
00295   // Subdivide until desired level is reached
00296   for(U32 i=base; i<n; i++) {
00297 
00298     // Subdivide the mesh using level i as the base for one step
00299     subdivide(&m_mesh, i);
00300 
00301   }
00302 
00303 } // end compute
00304 
00305 

Generated on Mon Jun 28 14:58:13 2004 for Advanced Surface Library by doxygen 1.3.4