//------------------------------------------------------------------------------ // Creates an Hbr mesh // // see hbr_tutorial_0 and hbr_tutorial_1 for more details // Hmesh * createMesh() { // Pyramid geometry from catmark_pyramid.h static float verts[5][3] = {{ 0.0f, 0.0f, 2.0f}, { 0.0f, -2.0f, 0.0f}, { 2.0f, 0.0f, 0.0f}, { 0.0f, 2.0f, 0.0f}, {-2.0f, 0.0f, 0.0f}}; static int nverts = 5, nfaces = 5; static int facenverts[5] = { 3, 3, 3, 3, 4 }; static int faceverts[16] = { 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 1, 4, 3, 2, 1 }; OpenSubdiv::HbrCatmarkSubdivision<Vertex> * catmark = new OpenSubdiv::HbrCatmarkSubdivision<Vertex>(); Hmesh * hmesh = new Hmesh(catmark); // Populate the vertices Vertex v; for (int i=0; i<nverts; ++i) { v.SetPosition(verts[i][0], verts[i][1], verts[i][2]); hmesh->NewVertex(i, v); } // Create the topology int * fv = faceverts; for (int i=0; i<nfaces; ++i) { int nv = facenverts[i]; bool valid = true; for(int j=0;j<nv;j++) { Hvertex const * origin = hmesh->GetVertex(fv[j]), * destination = hmesh->GetVertex(fv[(j+1)%nv]); Hhalfedge const * opposite = destination->GetEdge(origin); // Make sure that the vertices exist in the mesh if (origin==NULL or destination==NULL) { printf(" An edge was specified that connected a nonexistent vertex\n"); valid=false; break; } // Check for a degenerate edge if (origin == destination) { printf(" An edge was specified that connected a vertex to itself\n"); valid=false; break; } // Check that no more than 2 faces are adjacent to the edge if (opposite and opposite->GetOpposite() ) { printf(" A non-manifold edge incident to more than 2 faces was found\n"); valid=false; break; } // Check that the edge is unique and oriented properly if (origin->GetEdge(destination)) { printf(" An edge connecting two vertices was specified more than once." " It's likely that an incident face was flipped\n"); valid=false; break; } } if (valid) { hmesh->NewFace(nv, fv, 0); } else { printf(" Skipped face %d\n", i); } fv+=nv; } hmesh->SetInterpolateBoundaryMethod(Hmesh::k_InterpolateBoundaryEdgeOnly); hmesh->Finish(); return hmesh; }
Mesh::Mesh(const char* filename) :_vertices() ,_triangles() { fstream fileStream; fileStream.open(filename, fstream::in | iostream::binary); if( fileStream.is_open() ) { unsigned short chunkId; unsigned long chunkLength; unsigned short chunkQuantity; // Get file length fileStream.seekg(0, ios::end); int fileLength = fileStream.tellg(); fileStream.seekg(0, ios::beg); // Loop through chunk structure while( fileStream.tellg() < fileLength ) { fileStream.read((char*)&chunkId, 2); fileStream.read((char*)&chunkLength, 4); switch( chunkId ) { case 0x4d4d: // Main chunk break; case 0x3d3d: // 3D editor chunk break; case 0x4000: // Object block { char name[20]; // Read object name for( int count = 0; count < 20; ++count ) { fileStream.read(&name[count], 1); if( name[count] == '\0' ) { break; } } } break; case 0x4100: // Triangular mesh break; case 0x4110: // Vertices list fileStream.read((char*)&chunkQuantity, 2); for( unsigned short i = 0; i < chunkQuantity; ++i ) { Vertex* vertex = new Vertex(); if( vertex ) { Vector3f nativePos; this->_vertices.push_back(vertex); for( int j = 0; j < 3; ++j ) { fileStream.read((char*)(&nativePos[j]), 4); } // Convert from 3ds coordinates to opengl coordinates. vertex->SetPosition(nativePos.x, nativePos.z, -nativePos.y); } } break; case 0x4120: // Faces description fileStream.read((char*)&chunkQuantity, 2); for( unsigned short i = 0; i < chunkQuantity; ++i ) { Triangle* triangle = new Triangle(); if( triangle ) { this->_triangles.push_back(triangle); unsigned short vertIndex; for( int j = 0; j < 3; ++j ) { fileStream.read((char*)&vertIndex, 2); triangle->SetVertex(j, this->_vertices.at((unsigned int)vertIndex)); } fileStream.read((char*)&vertIndex, 2); // Extra data } } break; case 0x4140: // Mapping coordinates list fileStream.read((char*)&chunkQuantity, 2); for( unsigned short i = 0; i < chunkQuantity; ++i ) { Vertex* vertex = this->_vertices.at((unsigned int)i); if( vertex ) { for( int j = 0; j < 2; ++j ) { fileStream.read((char*)(&vertex->TextureCoords()[j]), 4); } } } break; default: // Skip chunk fileStream.seekg(chunkLength-6, ios_base::cur); } } fileStream.close(); this->CalculateVertexNormals(); this->Update(); } }