Некорректная текстура при загрузке 3d модели с использованием ASSIMP и OpenGL - PullRequest
8 голосов
/ 30 октября 2011

Я пытаюсь изменить пример кода для загрузки 3d-модели, включенной в образец кода ASSIMP , используя GLUT вместо WGL. Однако у меня возникла проблема с текстурой, как показано ниже:

loaded 3d model

в то время как предполагается, как показано ниже:

original 3d model

и код для отрисовки 3d модели, указанной ниже:

void recursive_render (const struct aiScene *sc, const struct aiNode* nd, float scale){
unsigned int i;
unsigned int n=0, t;
struct aiMatrix4x4 m = nd->mTransformation;
m.Scaling(aiVector3D(scale, scale, scale), m);
// update transform
m.Transpose();
glPushMatrix();
glMultMatrixf((float*)&m);
// draw all meshes assigned to this node
for (; n < nd->mNumMeshes; ++n){
    const struct aiMesh* mesh = scene->mMeshes[nd->mMeshes[n]];
    apply_material(sc->mMaterials[mesh->mMaterialIndex]);
    if(mesh->mNormals == NULL){
        glDisable(GL_LIGHTING);
    }
    else {
        glEnable(GL_LIGHTING);
    }
    if(mesh->mColors[0] != NULL) {
        glEnable(GL_COLOR_MATERIAL);
    }
    else {
        glDisable(GL_COLOR_MATERIAL);
    }

    for (t = 0; t < mesh->mNumFaces; ++t) {
        const struct aiFace* face = &mesh->mFaces[t];
        GLenum face_mode;
        switch(face->mNumIndices) {
            case 1: face_mode = GL_POINTS; break;
            case 2: face_mode = GL_LINES; break;
            case 3: face_mode = GL_TRIANGLES; break;
            default: face_mode = GL_POLYGON; break;
        }
        glBegin(face_mode);
        for(i = 0; i < face->mNumIndices; i++){
            int vertexIndex = face->mIndices[i];    // get group index for current index
            if(mesh->mColors[0] != NULL)
                Color4f(&mesh->mColors[0][vertexIndex]); 
            if(mesh->mNormals != NULL)
                if(mesh->HasTextureCoords(0)){  
                    glTexCoord2f(mesh->mTextureCoords[0][vertexIndex].x, 1- mesh->mTextureCoords[0][vertexIndex].y);                    
                }
                glNormal3fv(&mesh->mNormals[vertexIndex].x);
                glVertex3fv(&mesh->mVertices[vertexIndex].x);
        }
        glEnd();
    }
}
// draw all children
for (n = 0; n < nd->mNumChildren; ++n)  {
    recursive_render(sc, nd->mChildren[n], scale);
}
glPopMatrix();

}

функция apply_material, почти такая же, как в примере, предоставленном ASSIMP

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;
unsigned int max;   // changed: to unsigned
int texIndex = 0;
aiString texPath;   //contains filename of texture
if(AI_SUCCESS == mtl->GetTexture(aiTextureType_DIFFUSE, texIndex, &texPath))    {
    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.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_SPECULAR, &specular))
    color4_to_float4(&specular, c);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, 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);
}

, а также функция loadGLtextures, я не думаю, что это связано с жестким отбраковкой.

int LoadGLTextures(const aiScene* scene) {
ILboolean success;
/* initialization of DevIL */
ilInit(); 
/* scan scene's materials for textures */
for (unsigned int m=0; m<scene->mNumMaterials; ++m) {
    int texIndex = 0;
    aiString path;  // filename
    aiReturn texFound = scene->mMaterials[m]->GetTexture(aiTextureType_DIFFUSE, texIndex, &path);
    while (texFound == AI_SUCCESS) {
        //fill map with textures, OpenGL image ids set to 0
        textureIdMap[path.data] = 0; 
        // more textures?
        texIndex++;
        texFound = scene->mMaterials[m]->GetTexture(aiTextureType_DIFFUSE, texIndex, &path);
    }
}

int numTextures = textureIdMap.size();
/* create and fill array with DevIL texture ids */
ILuint* imageIds = new ILuint[numTextures];
ilGenImages(numTextures, imageIds); 
/* create and fill array with GL texture ids */
GLuint* textureIds = new GLuint[numTextures];
glGenTextures(numTextures, textureIds); /* Texture name generation */

/* get iterator */
std::map<std::string, GLuint>::iterator itr = textureIdMap.begin();
printf("TextureIDMap Begin %i\n", textureIdMap.begin());
int i=0;
for (; itr != textureIdMap.end(); ++i, ++itr) {
    //save IL image ID
    std::string filename = (*itr).first;  // get filename
    (*itr).second = textureIds[i];    // save texture id for filename in map
    printf("Texture loaded: %s\n",filename.c_str());
    printf("Texture ID Map End: %i\n",textureIdMap.end());
    ilBindImage(imageIds[i]); /* Binding of DevIL image name */
    ilEnable(IL_ORIGIN_SET);
    ilOriginFunc(IL_ORIGIN_LOWER_LEFT); 
    success = ilLoadImage((ILstring)filename.c_str());

    if (success) {
        /* Convert image to RGBA */
        ilConvertImage(IL_RGBA, IL_UNSIGNED_BYTE); 

        /* Create and load textures to OpenGL */
        glBindTexture(GL_TEXTURE_2D, textureIds[i]); 
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ilGetInteger(IL_IMAGE_WIDTH),
            ilGetInteger(IL_IMAGE_HEIGHT), 0, GL_RGBA, GL_UNSIGNED_BYTE,
            ilGetData()); 
    }
    else 
        printf("Couldn't load Image: %s\n", filename.c_str());
}
/* Because we have already copied image data into texture data  we can release memory used by image. */
ilDeleteImages(numTextures, imageIds); 
//Cleanup
delete [] imageIds;
delete [] textureIds;
//return success;
return true;
}

Lighthouse 3D предоставил пример для этого, однако в настоящее время я не могу внедрить GLSL и VAO в свою программу. Любое решение? Заранее спасибо.

Ответы [ 3 ]

8 голосов
/ 02 ноября 2011

Я нашел обходной путь. Я изменил способ доступа к текстурам в функции recursive_render, используя следующий код:

glTexCoord2f(mesh->mTextureCoords[0][vertexIndex].x,  mesh->mTextureCoords[0][vertexIndex].y);

вместо:

glTexCoord2f(mesh->mTextureCoords[0][vertexIndex].x,  1-mesh->mTextureCoords[0][vertexIndex].y);
2 голосов
/ 30 октября 2011

Это не проблема с текстурами. Ваша проблема исходит от отбраковки задних стенок (по крайней мере, так кажется, поскольку вы можете как-то видеть это внутри утки). Либо ваши многоугольники намотаны в неправильном порядке, либо неправильно выбран ваш задник. Если вы опубликуете код, в котором вы установили выборку задней стороны, мы точно увидим, что не так.

Возможно также, что некоторые из ваших нормалей обращены внутрь (что также может быть результатом намотки многоугольника). Это объясняет, почему клюв вашей утки абсолютно черный.

1 голос
/ 15 августа 2012

Я почти уверен, что проблема в том, что текстура «переворачивается» вдоль оси Y.Вот почему ваш «1-й» работает.Это можно исправить, переворачивая текстуру вдоль Y во время загрузки.Хотя я еще не уверен, почему, потому что сегодня столкнулся с этой проблемой.

...