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
00015
00016
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
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 }
00055
00056
00057
00058
00059
00060
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
00073
00074
00075
00076
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
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 }
00135
00136 } else {
00137
00138 valid_stencil = false;
00139
00140 }
00141
00142
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
00167
00168
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 }
00191
00192
00193
00194
00195
00196
00197 void ButterflySubdivision::subdivide(Mesh* m, U32 base) {
00198
00199 U32 group;
00200 group = m->addGroup();
00201
00202
00203 MeshGroup &base_mesh = m->getGroup(base);
00204
00205
00206 base_mesh.rewindFaceList();
00207 while (indexFace *face = base_mesh.facePostIncrement()) {
00208
00209 U32 edge_count = face->getEdgeCount();
00210
00211
00212 if (edge_count != 3) {
00213 throw Nexception("ButterflySubdivision: requires triangular mesh!");
00214 }
00215
00216 divideFace(face, m);
00217
00218 }
00219
00220
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
00232 U32 vertex_count = face->getVertexCount();
00233 U32 i;
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
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
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 }
00279
00280 }
00281
00282
00283
00284
00285
00286
00287 void ButterflySubdivision::compute(int n) {
00288
00289 U32 base=0;
00290
00291
00292 m_mesh.rewindGroupList();
00293 while (m_mesh.groupPostIncrement()) base++;
00294
00295
00296 for(U32 i=base; i<n; i++) {
00297
00298
00299 subdivide(&m_mesh, i);
00300
00301 }
00302
00303 }
00304
00305