Ejemplo n.º 1
0
//------------------------------------------------------------------------------
// 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();
	}
}