Exemple #1
0
            void apply_material(const aiMaterial *mtl)
            {
                float c[4];
                GLenum fill_mode;
                int ret1, ret2;
                aiColor4D diffuse;
                aiColor4D specular;
                aiColor4D ambient;
                aiColor4D emission;
                float shininess, strength;
                int two_sided;
                int wireframe;
                unsigned int max;

                set_float4(c, 0.8f, 0.8f, 0.8f, 1.0f);
                if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_DIFFUSE, &diffuse))
                    color4_to_float4(&diffuse, c);
                glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, c);

                set_float4(c, 0.0f, 0.0f, 0.0f, 1.0f);
                if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_SPECULAR, &specular))
                    color4_to_float4(&specular, c);
                glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, c);

                set_float4(c, 0.2f, 0.2f, 0.2f, 1.0f);
                if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_AMBIENT, &ambient))
                    color4_to_float4(&ambient, c);
                glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, c);

                set_float4(c, 0.0f, 0.0f, 0.0f, 1.0f);
                if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_EMISSIVE, &emission))
                    color4_to_float4(&emission, c);
                glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, c);

                max = 1;
                ret1 = aiGetMaterialFloatArray(mtl, AI_MATKEY_SHININESS, &shininess, &max);
                max = 1;
                ret2 = aiGetMaterialFloatArray(mtl, AI_MATKEY_SHININESS_STRENGTH, &strength, &max);
                if((ret1 == AI_SUCCESS) && (ret2 == AI_SUCCESS))
                    glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess * strength);
                else
                {
                    glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0f);
                    set_float4(c, 0.0f, 0.0f, 0.0f, 0.0f);
                    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, c);
                }

                max = 1;
                if(AI_SUCCESS == aiGetMaterialIntegerArray(mtl, AI_MATKEY_ENABLE_WIREFRAME, &wireframe, &max))
                    fill_mode = wireframe ? GL_LINE : GL_FILL;
                else
                    fill_mode = GL_FILL;
                glPolygonMode(GL_FRONT_AND_BACK, fill_mode);

                max = 1;
                if((AI_SUCCESS == aiGetMaterialIntegerArray(mtl, AI_MATKEY_TWOSIDED, &two_sided, &max)) && two_sided)
                    glEnable(GL_CULL_FACE);
                else
                    glDisable(GL_CULL_FACE);
            }
Exemple #2
0
void apply_material(const struct aiMaterial *mtl)
{
	float c[4];
    
	GLenum fill_mode;
	int ret1, ret2;
	struct aiColor4D diffuse;
	struct aiColor4D specular;
	struct aiColor4D ambient;
	struct aiColor4D emission;
	float shininess, strength;
	int two_sided;
	int wireframe;
	int max;
    
    int texIndex = 0;
    aiString texPath;	//contains filename of texture
    if(AI_SUCCESS == mtl->GetTexture(aiTextureType_DIFFUSE, texIndex, &texPath))
    {
        //bind texture
        unsigned int texId = *textureIdMap[texPath.data];
        glBindTexture(GL_TEXTURE_2D, texId);
    }
    
	set_float4(c, 0.8f, 0.8f, 0.8f, 1.0f);
	if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_DIFFUSE, &diffuse))
		color4_to_float4(&diffuse, c);
	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, c);
    
	set_float4(c, 0.0f, 0.0f, 0.0f, 1.0f);
	if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_SPECULAR, &specular))
		color4_to_float4(&specular, c);
	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, c);
    
	set_float4(c, 0.2f, 0.2f, 0.2f, 1.0f);
	if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_AMBIENT, &ambient))
		color4_to_float4(&ambient, c);
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, c);
    
	set_float4(c, 0.0f, 0.0f, 0.0f, 1.0f);
	if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_EMISSIVE, &emission))
		color4_to_float4(&emission, c);
	glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, c);
    
	max = 1;
	ret1 = aiGetMaterialFloatArray(mtl, AI_MATKEY_SHININESS, &shininess, (unsigned int *)&max);
	max = 1;
	ret2 = aiGetMaterialFloatArray(mtl, AI_MATKEY_SHININESS_STRENGTH, &strength, (unsigned int *)&max);
	if((ret1 == AI_SUCCESS) && (ret2 == AI_SUCCESS))
		glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess * strength);
	else {
		glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0f);
		set_float4(c, 0.0f, 0.0f, 0.0f, 0.0f);
		glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, c);
	}
    
	max = 1;
	if(AI_SUCCESS == aiGetMaterialIntegerArray(mtl, AI_MATKEY_ENABLE_WIREFRAME, &wireframe, (unsigned int *)&max))
		fill_mode = wireframe ? GL_LINE : GL_FILL;
	else
		fill_mode = GL_FILL;
	glPolygonMode(GL_FRONT_AND_BACK, fill_mode);
    
	max = 1;
	if((AI_SUCCESS == aiGetMaterialIntegerArray(mtl, AI_MATKEY_TWOSIDED, &two_sided, (unsigned int *)&max)) && two_sided)
		glEnable(GL_CULL_FACE);
	else
		glDisable(GL_CULL_FACE);
}
Exemple #3
0
void
VSResModelLib::genVAOsAndUniformBuffer(const struct aiScene *sc) {

    struct MyMesh aMesh;
    struct Material aMat;
    GLuint buffer;
    int totalTris = 0;
    unsigned int *adjFaceArray;

    VSLOG(mLogInfo, "Number of Meshes: %d",sc->mNumMeshes);
    // For each mesh
    for (unsigned int n = 0; n < sc->mNumMeshes; ++n)
    {
        const struct aiMesh* mesh = sc->mMeshes[n];

        if (mesh->mPrimitiveTypes != 4) {
            aMesh.numIndices = 0;
            pMyMeshesAux.push_back(aMesh);
            continue;
        }

        VSLOG(mLogInfo, "Mesh[%d] Triangles %d",n,
              mesh->mNumFaces);
        totalTris += mesh->mNumFaces;
        // create array with faces
        // have to convert from Assimp format to array
        unsigned int *faceArray;
        faceArray = (unsigned int *)malloc(
                        sizeof(unsigned int) * mesh->mNumFaces * 3);
        unsigned int faceIndex = 0;

        for (unsigned int t = 0; t < mesh->mNumFaces; ++t) {
            const struct aiFace* face = &mesh->mFaces[t];

            memcpy(&faceArray[faceIndex], face->mIndices,
                   3 * sizeof(unsigned int));
            faceIndex += 3;
        }

        if (pUseAdjacency) {
            // Create the half edge structure
            std::map<std::pair<unsigned int,unsigned int>, struct HalfEdge *> myEdges;
            struct HalfEdge *edge;

            // fill it up with edges. twin info will be added latter
            edge = (struct HalfEdge *)malloc(sizeof(struct HalfEdge) * mesh->mNumFaces * 3);
            for (unsigned int i = 0; i < mesh->mNumFaces; ++i) {

                edge[i*3].vertex = faceArray[i*3+1];
                edge[i*3+1].vertex = faceArray[i*3+2];
                edge[i*3+2].vertex = faceArray[i*3];

                edge[i*3].next = &edge[i*3+1];
                edge[i*3+1].next = &edge[i*3+2];
                edge[i*3+2].next = &edge[i*3];

                myEdges[std::pair<unsigned int,unsigned int>(faceArray[i*3+2],faceArray[i*3])] = &edge[i*3];
                myEdges[std::pair<unsigned int,unsigned int>(faceArray[i*3],faceArray[i*3+1])] = &edge[i*3+1];
                myEdges[std::pair<unsigned int,unsigned int>(faceArray[i*3+1],faceArray[i*3+2])] = &edge[i*3+2];
            }

            // add twin info
            std::map<std::pair<unsigned int,unsigned int>, struct HalfEdge *>::iterator iter;
            std::pair<unsigned int,unsigned int> edgeIndex, twinIndex;

            iter = myEdges.begin();

            for (; iter != myEdges.end(); ++iter) {

                edgeIndex = iter->first;
                twinIndex = std::pair<unsigned int, unsigned int>(edgeIndex.second, edgeIndex.first);

                if (myEdges.count(twinIndex))
                    iter->second->twin = myEdges[twinIndex];
                else
                    iter->second->twin = NULL;
            }

            adjFaceArray = (unsigned int *)malloc(sizeof(unsigned int) * mesh->mNumFaces * 6);
            for (unsigned int i = 0; i < mesh->mNumFaces; i++) {

                // NOTE: twin may be null
                adjFaceArray[i*6]   = edge[3*i + 0].next->vertex;
                adjFaceArray[i*6+1] = edge[3*i + 0].twin?edge[3*i + 0].twin->vertex:edge[3*i + 0].next->vertex;

                adjFaceArray[i*6+2] = edge[3*i + 1].next->vertex;
                adjFaceArray[i*6+3] = edge[3*i + 1].twin?edge[3*i + 1].twin->vertex:edge[3*i + 1].next->vertex;

                adjFaceArray[i*6+4] = edge[3*i + 2].next->vertex;
                adjFaceArray[i*6+5] = edge[3*i + 2].twin?edge[3*i + 2].twin->vertex:edge[3*i + 2].next->vertex;

            }
        }
        //printf("\n");
        //for (int i = 0; i < mesh->mNumFaces * 3; ++i)
        //	printf("%d ", faceArray[i]);
        //printf("\n");
        //for (int i = 0; i < mesh->mNumFaces * 6; ++i)
        //	printf("%d ", adjFaceArray[i]);
        //printf("\n");

        aMesh.numIndices = sc->mMeshes[n]->mNumFaces * 3;

        // generate Vertex Array for mesh
        glGenVertexArrays(1,&(aMesh.vao));
        glBindVertexArray(aMesh.vao);

        // buffer for faces
        glGenBuffers(1, &buffer);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);

        if (pUseAdjacency) {
            glBufferData(GL_ELEMENT_ARRAY_BUFFER,
                         sizeof(unsigned int) * mesh->mNumFaces * 6,
                         adjFaceArray, GL_STATIC_DRAW);
            free(adjFaceArray);
        }
        else
            glBufferData(GL_ELEMENT_ARRAY_BUFFER,
                         sizeof(unsigned int) * mesh->mNumFaces * 3,
                         faceArray, GL_STATIC_DRAW);

        free(faceArray);

        // buffer for vertex positions
        if (mesh->HasPositions()) {
            glGenBuffers(1, &buffer);
            glBindBuffer(GL_ARRAY_BUFFER, buffer);
            glBufferData(GL_ARRAY_BUFFER,
                         sizeof(float)*3*mesh->mNumVertices,
                         mesh->mVertices, GL_STATIC_DRAW);
            glEnableVertexAttribArray(
                VSShaderLib::VERTEX_COORD_ATTRIB);
            glVertexAttribPointer(VSShaderLib::VERTEX_COORD_ATTRIB,
                                  3, GL_FLOAT, 0, 0, 0);
        }

        // buffer for vertex normals
        if (mesh->HasNormals()) {
            glGenBuffers(1, &buffer);
            glBindBuffer(GL_ARRAY_BUFFER, buffer);
            glBufferData(GL_ARRAY_BUFFER,
                         sizeof(float)*3*mesh->mNumVertices, mesh->mNormals,
                         GL_STATIC_DRAW);
            glEnableVertexAttribArray(VSShaderLib::NORMAL_ATTRIB);
            glVertexAttribPointer(VSShaderLib::NORMAL_ATTRIB,
                                  3, GL_FLOAT, 0, 0, 0);
        }

        // buffer for vertex normals
        if (mesh->HasTangentsAndBitangents()) {
            glGenBuffers(1, &buffer);
            glBindBuffer(GL_ARRAY_BUFFER, buffer);
            glBufferData(GL_ARRAY_BUFFER,
                         sizeof(float)*3*mesh->mNumVertices, mesh->mTangents,
                         GL_STATIC_DRAW);
            glEnableVertexAttribArray(VSShaderLib::TANGENT_ATTRIB);
            glVertexAttribPointer(VSShaderLib::TANGENT_ATTRIB,
                                  3, GL_FLOAT, 0, 0, 0);
        }

        // buffer for vertex normals
        if (mesh->HasTangentsAndBitangents()) {
            glGenBuffers(1, &buffer);
            glBindBuffer(GL_ARRAY_BUFFER, buffer);
            glBufferData(GL_ARRAY_BUFFER,
                         sizeof(float)*3*mesh->mNumVertices, mesh->mBitangents,
                         GL_STATIC_DRAW);
            glEnableVertexAttribArray(VSShaderLib::BITANGENT_ATTRIB);
            glVertexAttribPointer(VSShaderLib::BITANGENT_ATTRIB,
                                  3, GL_FLOAT, 0, 0, 0);
        }

        // buffer for vertex texture coordinates
        if (mesh->HasTextureCoords(0)) {
            float *texCoords = (float *)malloc(
                                   sizeof(float)*2*mesh->mNumVertices);
            for (unsigned int k = 0; k < mesh->mNumVertices; ++k) {

                texCoords[k*2]   = mesh->mTextureCoords[0][k].x;
                texCoords[k*2+1] = mesh->mTextureCoords[0][k].y;

            }
            glGenBuffers(1, &buffer);
            glBindBuffer(GL_ARRAY_BUFFER, buffer);
            glBufferData(GL_ARRAY_BUFFER,
                         sizeof(float)*2*mesh->mNumVertices, texCoords,
                         GL_STATIC_DRAW);
            glEnableVertexAttribArray(
                VSShaderLib::TEXTURE_COORD_ATTRIB);
            glVertexAttribPointer(
                VSShaderLib::TEXTURE_COORD_ATTRIB, 2,
                GL_FLOAT, 0, 0, 0);
            free(texCoords);
        }

        // unbind buffers
        glBindVertexArray(0);
        glBindBuffer(GL_ARRAY_BUFFER,0);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);

        // create material uniform buffer
        struct aiMaterial *mtl =
                sc->mMaterials[mesh->mMaterialIndex];

        aiString texPath;	//contains filename of texture

        for (int j = 0; j < VSResourceLib::MAX_TEXTURES; ++j)
            aMesh.texUnits[j] = 0;

        if(AI_SUCCESS == mtl->GetTexture(aiTextureType_DIFFUSE,
                                         0, &texPath)) {
            //bind texture
            aMesh.texUnits[0] =
                pTextureIdMap[texPath.data];
            aMesh.texTypes[0] = GL_TEXTURE_2D;
            aMat.texCount = 1;
        }
        else {
            aMesh.texUnits[0] = 0;
            aMat.texCount = 0;
        }

        float c[4];
        set_float4(c, 0.8f, 0.8f, 0.8f, 1.0f);
        aiColor4D diffuse;
        if(AI_SUCCESS == aiGetMaterialColor(mtl,
                                            AI_MATKEY_COLOR_DIFFUSE, &diffuse))
            color4_to_float4(&diffuse, c);
        memcpy(aMat.diffuse, c, sizeof(c));

        set_float4(c, 0.2f, 0.2f, 0.2f, 1.0f);
        aiColor4D ambient;
        if(AI_SUCCESS == aiGetMaterialColor(mtl,
                                            AI_MATKEY_COLOR_AMBIENT, &ambient))
            color4_to_float4(&ambient, c);
        memcpy(aMat.ambient, c, sizeof(c));

        set_float4(c, 0.0f, 0.0f, 0.0f, 1.0f);
        aiColor4D specular;
        if(AI_SUCCESS == aiGetMaterialColor(mtl,
                                            AI_MATKEY_COLOR_SPECULAR, &specular))
            color4_to_float4(&specular, c);
        memcpy(aMat.specular, c, sizeof(c));

        set_float4(c, 0.0f, 0.0f, 0.0f, 1.0f);
        aiColor4D emission;
        if(AI_SUCCESS == aiGetMaterialColor(mtl,
                                            AI_MATKEY_COLOR_EMISSIVE, &emission))
            color4_to_float4(&emission, c);
        memcpy(aMat.emissive, c, sizeof(c));

        float shininess = 0.0;
        unsigned int max;
        aiGetMaterialFloatArray(mtl,
                                AI_MATKEY_SHININESS, &shininess, &max);
        aMat.shininess = shininess;

        aMesh.mat = aMat;

        pMyMeshesAux.push_back(aMesh);
    }

    mVSML->loadIdentity(VSMathLib::AUX0);
    recursive_walk_for_matrices(sc, sc->mRootNode);

    pMyMeshesAux.clear();

    VSLOG(mLogInfo, "Total Meshes: %d  | Faces: %d",
          sc->mNumMeshes, totalTris);
}
Exemple #4
0
void Model::genVAOsAndUniformBuffer(const aiScene *sc) {
    checkForErrors();
    
    struct MyMesh aMesh;
    struct MyMaterial aMat;
    GLuint buffer;
    
    // For each mesh
    for (unsigned int n = 0; n < sc->mNumMeshes; ++n)
    {
        const aiMesh* mesh = sc->mMeshes[n];
        
        // create array with faces
        // have to convert from Assimp format to array
        unsigned int *faceArray;
        faceArray = (unsigned int *)malloc(sizeof(unsigned int) * mesh->mNumFaces * 3);
        unsigned int faceIndex = 0;
        
        for (unsigned int t = 0; t < mesh->mNumFaces; ++t) {
            const aiFace* face = &mesh->mFaces[t];
            
            memcpy(&faceArray[faceIndex], face->mIndices,3 * sizeof(unsigned int));
            faceIndex += 3;
        }
        aMesh.numFaces = sc->mMeshes[n]->mNumFaces;
        
        // generate Vertex Array for mesh
        glGenVertexArrays(1,&(aMesh.vao));
        glBindVertexArray(aMesh.vao);
        
        // buffer for faces
        glGenBuffers(1, &buffer);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * mesh->mNumFaces * 3, faceArray, GL_STATIC_DRAW);
        free(faceArray);
        
        // buffer for vertex positions
        if (mesh->HasPositions()) {
            glGenBuffers(1, &buffer);
            glBindBuffer(GL_ARRAY_BUFFER, buffer);
            glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh->mNumVertices, mesh->mVertices, GL_STATIC_DRAW);
            glEnableVertexAttribArray(vertexLoc);
            glVertexAttribPointer(vertexLoc, 3, GL_FLOAT, 0, 0, 0);
        }
        
        // buffer for vertex normals
        if (mesh->HasNormals()) {
            glGenBuffers(1, &buffer);
            glBindBuffer(GL_ARRAY_BUFFER, buffer);
            glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh->mNumVertices, mesh->mNormals, GL_STATIC_DRAW);
            glEnableVertexAttribArray(normalLoc);
            glVertexAttribPointer(normalLoc, 3, GL_FLOAT, 0, 0, 0);
        }
        
        // buffer for vertex texture coordinates
        if (mesh->HasTextureCoords(0)) {
            float *texCoords = (float *)malloc(sizeof(float)*2*mesh->mNumVertices);
            for (unsigned int k = 0; k < mesh->mNumVertices; ++k) {
                
                texCoords[k*2]   = mesh->mTextureCoords[0][k].x;
                texCoords[k*2+1] = mesh->mTextureCoords[0][k].y;
                
            }
            glGenBuffers(1, &buffer);
            glBindBuffer(GL_ARRAY_BUFFER, buffer);
            glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*mesh->mNumVertices, texCoords, GL_STATIC_DRAW);
            glEnableVertexAttribArray(texCoordLoc);
            glVertexAttribPointer(texCoordLoc, 2, GL_FLOAT, 0, 0, 0);
        }
        
        // unbind buffers
        glBindVertexArray(0);
        glBindBuffer(GL_ARRAY_BUFFER,0);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
        
        // create material uniform buffer
        aiMaterial *mtl = sc->mMaterials[mesh->mMaterialIndex];
        
        aiString texPath;   //contains filename of texture
        if(AI_SUCCESS == mtl->GetTexture(aiTextureType_DIFFUSE, 0, &texPath)){
            //bind texture
            unsigned int texId = textureIdMap[texPath.data];
            aMesh.texIndex = texId;
            aMat.texCount = 1;
        }
        else
            aMat.texCount = 0;
        
        float c[4];
        set_float4(c, 0.8f, 0.8f, 0.8f, 1.0f);
        aiColor4D diffuse;
        if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_DIFFUSE, &diffuse))
            color4_to_float4(&diffuse, c);
        memcpy(aMat.diffuse, c, sizeof(c));
        
        set_float4(c, 0.2f, 0.2f, 0.2f, 1.0f);
        aiColor4D ambient;
        if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_AMBIENT, &ambient))
            color4_to_float4(&ambient, c);
        memcpy(aMat.ambient, c, sizeof(c));
        
        set_float4(c, 0.0f, 0.0f, 0.0f, 1.0f);
        aiColor4D specular;
        if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_SPECULAR, &specular))
            color4_to_float4(&specular, c);
        memcpy(aMat.specular, c, sizeof(c));
        
        set_float4(c, 0.0f, 0.0f, 0.0f, 1.0f);
        aiColor4D emission;
        if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_EMISSIVE, &emission))
            color4_to_float4(&emission, c);
        memcpy(aMat.emissive, c, sizeof(c));
        
        float shininess = 0.0;
        unsigned int max;
        aiGetMaterialFloatArray(mtl, AI_MATKEY_SHININESS, &shininess, &max);
        aMat.shininess = shininess;
        
        glGenBuffers(1,&(aMesh.uniformBlockIndex));
        glBindBuffer(GL_UNIFORM_BUFFER,aMesh.uniformBlockIndex);
        glBufferData(GL_UNIFORM_BUFFER, sizeof(aMat), (void *)(&aMat), GL_STATIC_DRAW);
        
        myMeshes.push_back(aMesh);
    }
}
void AssimpModel::applyMaterial(const aiMaterial *mtl)
{
    int texIndex = 0;
    aiString texPath;	//contains filename of texture
    if(AI_SUCCESS == mtl->GetTexture(aiTextureType_DIFFUSE, texIndex, &texPath))
    {
        GLuint& texId = m_textures[texPath.data];
        glBindTexture(GL_TEXTURE_2D, texId);
    }

    float color[4];
    set_float4(color, 0.8f, 0.8f, 0.8f, 1.0f);
    aiColor4D diffuse;
    if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_DIFFUSE, &diffuse))
        color4_to_float4(&diffuse, color);
    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color);

    set_float4(color, 0.0f, 0.0f, 0.0f, 1.0f);
    aiColor4D specular;
    if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_SPECULAR, &specular))
        color4_to_float4(&specular, color);
    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color);

    set_float4(color, 0.2f, 0.2f, 0.2f, 1.0f);
    aiColor4D ambient;
    if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_AMBIENT, &ambient))
        color4_to_float4(&ambient, color);
    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color);

    set_float4(color, 0.0f, 0.0f, 0.0f, 1.0f);
    aiColor4D emission;
    if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_EMISSIVE, &emission))
        color4_to_float4(&emission, color);
    glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, color);

    float shininess, strength;
    unsigned int max = 1;
    if( aiGetMaterialFloatArray(mtl, AI_MATKEY_SHININESS, &shininess, &max) == AI_SUCCESS && 
        aiGetMaterialFloatArray(mtl, AI_MATKEY_SHININESS_STRENGTH, &strength, &max) == AI_SUCCESS)
        glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess * strength);
    else {
        glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0f);
        set_float4(color, 0.0f, 0.0f, 0.0f, 0.0f);
        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color);
    }

    max = 1;
    GLenum fill_mode;
    int wireframe;
    if(AI_SUCCESS == aiGetMaterialIntegerArray(mtl, AI_MATKEY_ENABLE_WIREFRAME, &wireframe, &max)) {
        fill_mode = wireframe ? GL_LINE : GL_FILL;
    } else {
        fill_mode = GL_FILL;
    }

    glPolygonMode(GL_FRONT_AND_BACK, fill_mode);

    max = 1;
    int two_sided;
    if((AI_SUCCESS == aiGetMaterialIntegerArray(mtl, AI_MATKEY_TWOSIDED, &two_sided, &max)) && two_sided) {
        glEnable(GL_CULL_FACE);
    } else {
        glDisable(GL_CULL_FACE);
    }
}