00001 #include "CatmullClark.h"
00002
00003 #include <math.h>
00004 #include <gmVec3.h>
00005
00006 #include "Implicit.h"
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
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
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
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
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
00144 U32 group;
00145 group = m_mesh.addGroup ();
00146
00147
00148 MeshGroup &base_mesh = m_mesh.getGroup (base_group);
00149
00150
00151
00152 base_mesh.rewindFaceList ();
00153 while (indexFace *p_face = base_mesh.facePostIncrement ())
00154 {
00155 divideFace (p_face);
00156 }
00157
00158
00159
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
00169 if (!p_edge.hasArbitraryIndex ())
00170 {
00171 divideEdge(&p_edge, p_face);
00172 }
00173 }
00174 }
00175
00176
00177
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
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
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
00231
00232
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
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
00273 m_mesh.rewindGroupList();
00274 while (m_mesh.groupPostIncrement())
00275 base++;
00276
00277
00278 for(U32 i = base; i < U32 (n); i++)
00279 {
00280
00281 subdivide (i);
00282 }
00283
00284 }
00285
00286 int CatmullClarkSubdivision::matrix(int *n, double *s)
00287 {
00288 return 0;
00289 }