// g++ genmodel.cpp -Ilib/vectormathlibrary/include/vectormath/scalar/cpp -Ilib/OpenCTM-1.0.3/lib lib/libopenctm.a -o genmodel #include #include #include #include #include #include using namespace std; using namespace Vectormath::Aos; void GenSphere(vector & normals, vector & vertices, vector & indices); int main() { CTMexporter ctm; vector normalData; vector vertexData; vector indexData; GenSphere(vertexData, normalData, indexData); ctm.DefineMesh(&vertexData[0], vertexData.size()/3, &indexData[0], indexData.size()/3, &normalData[0]); // ctm.DefineMesh(&vertexData[0], vertexData.size()/3, &indexData[0], indexData.size()/3, NULL); ctm.Save("model.ctm"); return EXIT_SUCCESS; } struct Edge { int vert1, vert2; int splitToEdge1, splitToEdge2; int splitVertex; Edge(): vert1(0), vert2(0), splitToEdge1(0), splitToEdge2(0), splitVertex(-1) {} Edge(int v1, int v2): vert1(v1), vert2(v2), splitToEdge1(0), splitToEdge2(0), splitVertex(-1) {} Edge(const Edge & rhs): vert1(rhs.vert1), vert2(rhs.vert2), splitToEdge1(rhs.splitToEdge1), splitToEdge2(rhs.splitToEdge2), splitVertex(rhs.splitVertex) {} Edge & operator=(const Edge & rhs) { vert1 = rhs.vert1; vert2 = rhs.vert2; splitToEdge1 = rhs.splitToEdge1; splitToEdge2 = rhs.splitToEdge2; splitVertex = rhs.splitVertex; } bool operator==(const Edge & rhs) const { return (vert1 == rhs.vert1 && vert2 == rhs.vert2) || (vert1 == rhs.vert2 && vert2 == rhs.vert1); } bool IsSplit() const {return splitVertex != -1;} void Split(); int HasVertex(int vert) const {return (vert == vert1) || (vert == vert2);} int OtherVertex(int vert) const {return ((vert == vert2) ? vert1 : vert2);} }; int CommonVertex(const Edge & e1, const Edge & e2) { if(e1.vert1 == e2.vert1) return e1.vert1; if(e1.vert1 == e2.vert2) return e1.vert1; if(e1.vert2 == e2.vert1) return e1.vert2; if(e1.vert2 == e2.vert2) return e1.vert2; return -1; } struct Triangle { int edge1, edge2, edge3; Triangle(int e1, int e2, int e3): edge1(e1), edge2(e2), edge3(e3) {} Triangle(const Triangle & rhs): edge1(rhs.edge1), edge2(rhs.edge2), edge3(rhs.edge3) {} }; vector vertices; vector edges; vector triangles; // This is slow, avoid (generate directly from edges) if you can void MakeTriangle(vector & dsttriangles, int v1, int v2, int v3) { Edge edge1(v3, v1); Edge edge2(v1, v2); Edge edge3(v2, v3); int e1 = -1, e2 = -1, e3 = -1; for(int e = 0; e != edges.size(); ++e) { if(edge1 == edges[e]) { e1 = e; break; } } if(e1 < 0) { e1 = edges.size(); edges.push_back(edge1); } for(int e = 0; e != edges.size(); ++e) { if(edge2 == edges[e]) { e2 = e; break; } } if(e2 < 0) { e2 = edges.size(); edges.push_back(edge2); } for(int e = 0; e != edges.size(); ++e) { if(edge3 == edges[e]) { e3 = e; break; } } if(e3 < 0) { e3 = edges.size(); edges.push_back(edge3); } dsttriangles.push_back(Triangle(e1, e2, e3)); } void Edge::Split() { if(IsSplit()) return; splitVertex = vertices.size(); vertices.push_back((vertices[vert1] + vertices[vert2])*0.5); splitToEdge1 = edges.size(); edges.push_back(Edge(vert1, splitVertex)); splitToEdge2 = edges.size(); edges.push_back(Edge(splitVertex, vert2)); } void SubTriangles(const vector & srctriangles, vector & dsttriangles) { vector::const_iterator tri; for(tri = srctriangles.begin(); tri != srctriangles.end(); ++tri) { // v3 // / \ // e1 e3 // / \ // v1---e2---v2 Edge edge1 = edges[tri->edge1]; Edge edge2 = edges[tri->edge2]; Edge edge3 = edges[tri->edge3]; int v1 = CommonVertex(edge1, edge2); int v2 = CommonVertex(edge2, edge3); int v3 = CommonVertex(edge3, edge1); // cout << v1 << ", " << v2 << ", " << v3 << endl; // split each edge of original triangle edge1.Split(); edge2.Split(); edge3.Split(); int e1a, e1b, e2a, e2b, e3a, e3b; e1a = edge1.splitToEdge1; e1b = edge1.splitToEdge2; e2a = edge2.splitToEdge1; e2b = edge2.splitToEdge2; e3a = edge3.splitToEdge1; e3b = edge3.splitToEdge2; if(!edges[e1b].HasVertex(v1)) swap(e1a, e1b); if(!edges[e2b].HasVertex(v2)) swap(e2a, e2b); if(!edges[e3b].HasVertex(v3)) swap(e3a, e3b); int e12, e23, e31; e12 = edges.size(); edges.push_back(Edge(edge1.splitVertex, edge2.splitVertex)); e23 = edges.size(); edges.push_back(Edge(edge2.splitVertex, edge3.splitVertex)); e31 = edges.size(); edges.push_back(Edge(edge3.splitVertex, edge1.splitVertex)); // cout << "# " << e12 << ", " << e23 << ", " << e31 << endl; dsttriangles.push_back(Triangle(e1b, e2a, e12)); dsttriangles.push_back(Triangle(e2b, e3a, e23)); dsttriangles.push_back(Triangle(e3b, e1a, e31)); dsttriangles.push_back(Triangle(e12, e23, e31)); // dsttriangles.push_back(*tri); } } void MakeTetrahedron() { vertices.push_back(Vector3(-1,-1,-1));// bottom left near vertices.push_back(Vector3( 1, 1,-1));// top right near vertices.push_back(Vector3( 1,-1, 1));// bottom right far vertices.push_back(Vector3(-1, 1, 1));// top left far edges.push_back(Edge(0, 1));// 0: near (BLN-TRN) edges.push_back(Edge(0, 2));// 1: bottom (BLN-BRF) edges.push_back(Edge(0, 3));// 2: left (BLN-TLF) edges.push_back(Edge(1, 2));// 3: right (TRN-BRF) edges.push_back(Edge(1, 3));// 4: top (TRN-TLF) edges.push_back(Edge(2, 3));// 5: far (BRF-TLF) triangles.push_back(Triangle(0, 1, 3)); // BLN, BRF, TRN triangles.push_back(Triangle(0, 4, 2)); // BLN, TRN, TLF triangles.push_back(Triangle(3, 5, 4)); // TRN, BRF, TLF triangles.push_back(Triangle(2, 5, 1)); // BLN, TLF, BRF } void MakeOctahedron() { vertices.push_back(Vector3( 0, 0,-1));// near vertices.push_back(Vector3( 0, 0, 1));// far vertices.push_back(Vector3(-1, 0, 0));// left vertices.push_back(Vector3( 1, 0, 0));// right vertices.push_back(Vector3( 0,-1, 0));// bottom vertices.push_back(Vector3( 0, 1, 0));// top const int n = 0, f = 1, l = 2, r = 3, b = 4, t = 5; MakeTriangle(triangles, n, r, t); MakeTriangle(triangles, r, f, t); MakeTriangle(triangles, f, l, t); MakeTriangle(triangles, l, n, t); MakeTriangle(triangles, b, r, n); MakeTriangle(triangles, b, f, r); MakeTriangle(triangles, b, l, f); MakeTriangle(triangles, b, n, l); } void GenSphere(vector & vertexData, vector & normalData, vector & indexData) { //MakeTetrahedron(); MakeOctahedron(); vector dsttriangles; SubTriangles(triangles, dsttriangles); triangles = dsttriangles; dsttriangles.clear(); SubTriangles(triangles, dsttriangles); triangles = dsttriangles; dsttriangles.clear(); SubTriangles(triangles, dsttriangles); triangles = dsttriangles; dsttriangles.clear(); SubTriangles(triangles, dsttriangles); triangles = dsttriangles; dsttriangles.clear(); cout << "triangles.size(): " << triangles.size() << endl; cout << "vertices.size(): " << vertices.size() << endl; cout << "edges.size(): " << edges.size() << endl; cout << "vertices:" << endl; vector::iterator vert; for(vert = vertices.begin(); vert != vertices.end(); ++vert) { Vector3 v = normalize(*vert); vertexData.push_back(v.getX()); vertexData.push_back(v.getY()); vertexData.push_back(v.getZ()); normalData.push_back(v.getX()); normalData.push_back(v.getY()); normalData.push_back(v.getZ()); // cout << v.getX() << ", " << v.getY() << ", " << v.getZ() << endl; } cout << "end vertices" << endl; cout << "triangles:" << endl; vector::iterator tri; for(tri = triangles.begin(); tri != triangles.end(); ++tri) { int v1 = CommonVertex(edges[tri->edge1], edges[tri->edge2]); int v2 = CommonVertex(edges[tri->edge2], edges[tri->edge3]); int v3 = CommonVertex(edges[tri->edge3], edges[tri->edge1]); if(v1 < 0) v1 = 1; if(v2 < 0) v2 = 1; if(v3 < 0) v3 = 1; if(v1 == v2 || v2 == v3 || v3 == v1) { cout << "degenerate triangle" << endl; continue; } indexData.push_back(v1); indexData.push_back(v2); indexData.push_back(v3); // cout << v1 << ", " << v2 << ", " << v3 << endl; } cout << "end triangles" << endl; }