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

CatmullClark.cpp

Go to the documentation of this file.
00001 #include "CatmullClark.h"
00002 
00003 #include <math.h>
00004 #include <gmVec3.h>
00005 
00006 #include "Implicit.h"  // M_PI
00007 
00008 #include "meshBase.h"
00009 
00010 
00011 void CatmullClarkSubdivision::divideFace(indexFace *face)
00012 {
00013         gmVector3 average (0.0, 0.0, 0.0);
00014 
00015         U32 total_vertices = face->getVertexCount ();
00016 
00017         // part of tangent term
00018         double A_N = 1.0 + cos (2.0 * M_PI / total_vertices) +
00019                                            cos (          M_PI / total_vertices) * 
00020                                            sqrt (2.0 * (9.0 + cos (2.0 * M_PI / total_vertices)));
00021 
00022         gmVector3 tan0,
00023                           tan1;
00024 
00025         for (U32 i = 0; i < total_vertices; i++)
00026         {
00027                 average += face->getVertex (i);
00028         }
00029 
00030         average /= double (total_vertices);
00031 
00032         face->setArbitraryIndex (m_mesh.addVertex (average));
00033 }
00034 
00035 void CatmullClarkSubdivision::divideEdge(indexEdge  *edge, 
00036                                                                                  indexFace  *face)
00037 {
00038         gmVector3 average;
00039 
00040         indexFace adj_face;
00041 
00042         // check for boundary vertices
00043         if (edge->getNumberOfAdjFaces () == 2)
00044         {
00045                 adj_face = edge->getFace (0);
00046                 average = m_mesh.getVertex (adj_face.getArbitraryIndex ());
00047                 
00048                 adj_face = edge->getFace (1);
00049                 average += m_mesh.getVertex (adj_face.getArbitraryIndex ());
00050 
00051                 average += edge->getVertexA ();
00052                 average += edge->getVertexB ();
00053 
00054                 average /= 4.0;
00055         }
00056         else
00057         {
00058                 average = 0.5 * edge->getVertexA () +
00059                                   0.5 * edge->getVertexB ();
00060         }
00061 
00062         edge->setArbitraryIndex (m_mesh.addVertex (average));
00063 }
00064 
00065 void CatmullClarkSubdivision::buildVertex (indexVertex *vertex)
00066 {
00067         gmVector3 avg_face (0.0, 0.0, 0.0),
00068                           avg_edge (0.0, 0.0, 0.0),
00069                           avg_vert,
00070                           average;
00071 
00072         U32 total = vertex->getValence ();
00073 
00074         indexEdge adj_edge;
00075 
00076         // test for boundary and corner vertices
00077         if (total > 2)
00078         {
00079                 double inv_total2 = 1.0 / (double) (total * total);
00080 
00081                 for (U32 i = 0; i < total; i++)
00082                 {
00083                         indexFace adj_face;
00084         
00085                         adj_face = vertex->getAdjacentFace (i);
00086 
00087                         avg_face += m_mesh.getVertex (adj_face.getArbitraryIndex ());
00088                 }
00089                 avg_face *= inv_total2; 
00090         
00091                 for (U32 i = 0; i < total; i++)
00092                 {
00093                         adj_edge = vertex->getEdge (i);
00094 
00095                         if (vertex->getVertexIndex () != adj_edge.getVertexIndexA ())
00096                         {
00097                                 avg_edge += adj_edge.getVertexA ();
00098                         }
00099                         else 
00100                         {
00101                                 avg_edge += adj_edge.getVertexB ();
00102                         }
00103                 }
00104                 avg_edge *= inv_total2;
00105 
00106                 avg_vert = (((double) total - 2.0) / (double) total) * 
00107                                           m_mesh.getVertex (vertex->getVertexIndex ());
00108 
00109                 average = avg_vert + avg_edge + avg_face;
00110         }
00111         else
00112         {
00113                 // assuming no dangling edges
00114                 adj_edge = vertex->getEdge (0);         
00115                 if (vertex->getVertexIndex () != adj_edge.getVertexIndexA ())
00116                 {
00117                         avg_edge += adj_edge.getVertexA ();
00118                 }
00119                 else 
00120                 {
00121                         avg_edge += adj_edge.getVertexB ();
00122                 }
00123 
00124                 adj_edge = vertex->getEdge (1);
00125                 if (vertex->getVertexIndex () != adj_edge.getVertexIndexA ())
00126                 {
00127                         avg_edge += adj_edge.getVertexA ();
00128                 }
00129                 else 
00130                 {
00131                         avg_edge += adj_edge.getVertexB ();
00132                 }
00133                 avg_edge *= 0.125;
00134 
00135                 average = avg_edge + 0.75 * m_mesh.getVertex (vertex->getVertexIndex ());
00136         }
00137 
00138         vertex->setArbitraryIndex (m_mesh.addVertex (average));
00139 }
00140 
00141 void CatmullClarkSubdivision::subdivide(U32 base_group)
00142 {
00143         // create a new mesh group and acquire its id number
00144         U32 group;
00145         group = m_mesh.addGroup ();
00146 
00147         // acquire the mesh group to be subdivided
00148         MeshGroup &base_mesh = m_mesh.getGroup (base_group);
00149 
00150         // cycle through the faces, building a new
00151         // face vertex for each
00152         base_mesh.rewindFaceList ();
00153         while (indexFace *p_face = base_mesh.facePostIncrement ())
00154         {       
00155                 divideFace (p_face);
00156         }
00157         
00158         // cycle through the faces, building new 
00159         // vertices for each edge
00160         base_mesh.rewindFaceList ();
00161         while (indexFace *p_face = base_mesh.facePostIncrement ())
00162         {
00163                 U32 edge_count = p_face->getEdgeCount ();
00164                 for (U32 i = 0; i < edge_count; i++)
00165                 {
00166                         indexEdge &p_edge = p_face->getEdge (i);
00167 
00168                         // build new edge point if necessary
00169                         if (!p_edge.hasArbitraryIndex ())
00170                         {
00171                                 divideEdge(&p_edge, p_face);
00172                         }
00173                 }
00174         }
00175 
00176         // cycle through the faces, offsetting all
00177         // original vertices
00178         base_mesh.rewindFaceList ();
00179         while (indexFace *p_face = base_mesh.facePostIncrement ())
00180         {
00181                 U32 vertex_count = p_face->getVertexCount ();
00182 
00183                 for (U32 i = 0; i < vertex_count; i++)
00184                 {
00185                         U32 base_vertex = p_face->getVertexIndex (i);
00186 
00187                         indexVertex &curr_vertex = m_mesh.getIndexVertex (base_vertex);
00188 
00189                         if (!curr_vertex.hasArbitraryIndex ())
00190                         {
00191                                 buildVertex (&curr_vertex);
00192                         }
00193                 }
00194         }
00195 
00196         // build new faces from the new vertices
00197         base_mesh.rewindFaceList ();
00198         while (U32 *p_face_index = base_mesh.faceIndexPostIncrement ())
00199         {
00200                 indexFace *p_face = &m_mesh.getFace (*p_face_index);
00201 
00202                 U32 vertex_count = p_face->getVertexCount ();
00203 
00204                 U32 *new_vert           = new U32[vertex_count], 
00205                         *new_edge               = new U32[vertex_count],
00206                         *new_vert_norm  = new U32[vertex_count],
00207                         *new_edge_norm  = new U32[vertex_count];
00208 
00209                 // acquire the offset and new edge vertices
00210                 for (U32 i = 0; i < vertex_count; i++)
00211                 {
00212                         U32 base = p_face->getVertexIndex (i);
00213 
00214                         indexVertex &p_vertex = m_mesh.getIndexVertex (base);
00215                         indexEdge &p_edge = p_face->getEdge (i);
00216 
00217                         new_vert[i] = p_vertex.getArbitraryIndex ();
00218                         new_edge[i] = p_edge.getArbitraryIndex ();
00219 
00220                         new_vert_norm[i] = m_mesh.getIndexVertex 
00221                                                                 (new_vert[i]).getNormalIndex (); 
00222                         new_edge_norm[i] = m_mesh.getIndexVertex 
00223                                                                 (new_edge[i]).getNormalIndex (); 
00224                 }
00225 
00226                 U32 new_face_vert = p_face->getArbitraryIndex ();
00227                 U32 new_face_norm = m_mesh.getIndexVertex 
00228                                                                 (new_face_vert).getNormalIndex (); 
00229 
00230                 // enumerate the new faces (number of
00231                 // new faces equal to number of prior
00232                 // vertices)
00233                 indexFace *new_face;
00234 
00235                 for (U32 i = 0; i < (vertex_count - 1); i++)
00236                 {
00237                         new_face = new indexFace;
00238 
00239                         new_face->addVertex (new_face_vert, new_face_norm);
00240                         new_face->addVertex (new_edge[i],   new_edge_norm[i]);
00241                         new_face->addVertex (new_vert[i+1], new_vert_norm[i+1]);
00242                         new_face->addVertex (new_edge[i],   new_edge_norm[i]);
00243 
00244                         m_mesh.addFace (*new_face);
00245 
00246                         delete new_face;
00247                 }
00248                 // enumerate final new face (wrap around indices)
00249                 new_face = new indexFace;
00250 
00251                 new_face->addVertex (new_face_vert, new_face_norm);
00252                 new_face->addVertex (new_edge    [vertex_count - 1],   
00253                                                          new_edge_norm[vertex_count - 1]);
00254                 new_face->addVertex (new_vert[0], new_vert_norm[0]);
00255                 new_face->addVertex (new_edge[0], new_edge_norm[0]);
00256 
00257                 m_mesh.addFace (*new_face);
00258 
00259                 delete new_face;
00260 
00261                 delete [] new_vert;
00262                 delete [] new_edge;
00263                 delete [] new_vert_norm;
00264                 delete [] new_edge_norm;
00265         }
00266 }
00267 
00268 void CatmullClarkSubdivision::compute(int n)
00269 {
00270         U32 base = 0;
00271 
00272         // Step through the levels currently in the mesh
00273         m_mesh.rewindGroupList();
00274         while (m_mesh.groupPostIncrement()) 
00275                 base++;
00276 
00277         // Subdivide until desired level is reached
00278         for(U32 i = base; i < U32 (n); i++) 
00279         {
00280                 // Subdivide the mesh using level i as the base for one step
00281                 subdivide (i);
00282         }
00283 
00284 }
00285 
00286 int CatmullClarkSubdivision::matrix(int *n, double *s)
00287 {       
00288         return 0; 
00289 }

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