2011-10-30 10 views
7

Próbuję zmodyfikować przykładowy kod do ładowania modelu 3D zawartego w ASSIMP o numerze sample code, używając polecenia GLUT zamiast WGL. Jednak mam problem z fakturą, jak pokazano poniżej:Niepoprawna tekstura w ładowaniu modelu 3D przy użyciu ASSIMP i OpenGL

loaded 3d model

gdy jest to miało być, jak pokazano poniżej:

original 3d model

i kod do rysowania modelu 3d poniżej:

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 funkcja, niemal dokładnie taka sama jak ASSIMP umieszczono próbkę

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); 
} 

a także funkcję LoadGLTextures, nie sądzę, jest to związane z ubojem trudne.

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 dał an example dla tej operacji, jednak w tej chwili nie mogę realizować GLSL i vào do mojego programu. Jakieś rozwiązanie? Z góry dziękuję.

+0

Mogę się mylić, ale może problem nie dotyczy tekstury, ale materiałów. –

+0

Czy masz pojęcie, co może spowodować problem z materiałem? dzięki .. – snowball147

+0

Próbowałem już tutorialu latarni morskiej 3D, ale nie mogę go załadować modelu – SpicyWeenie

Odpowiedz

8

Znalazłem obejście. Zmieniłem sposób dostępu tekstur recursive_render funkcji za pomocą następującego kodu:

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

zamiast:

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

Używam Assimp z GLSL, tekstura UV z modeli, które dostarczam do Assimp działa tylko wtedy, gdy używam 'glTexCoord2f (mesh-> mTextureCoords [0] [vertexIndex] .x, 1- (mesh-> mTextureCoords [0] [ vertexIndex] .y)); ' Inaczej dostaję dziwne zachowanie z teksturami.Myślę, że 1-y jest potrzebne tylko dla kilku modeli – 2am

2

To nie jest problem z teksturami. Twój problem pochodzi z uboju z tyłu (przynajmniej wydaje się, że możesz zobaczyć wewnątrz kaczki). Albo twoje wielokąty są nawijane w niewłaściwej kolejności, albo twój ubiór jest nieprawidłowo ustawiony. Jeśli opublikujesz kod, w którym ustawiłeś utylizację backface, widzimy dokładnie, co jest nie tak.

Może być również możliwe, że niektóre z normalnych będą skierowane do wewnątrz (co może również wynikać z uzwojenia wielokąta). To wyjaśniałoby, dlaczego dziób twojej kaczki jest czarny jak smoła.

+0

Dziękuję za odpowiedź. Włączanie/wyłączanie uboju jest ustawiane na końcu funkcji 'apply_material'. Nie jestem pewien, czy problem dotyczy uboju, ponieważ nawet jeśli wyłączyłem uboju, tekstura nie załaduje się poprawnie. (CMIIW). Edytowałem kod. – snowball147

+0

Czy próbowałeś całkowicie wyłączyć utylizację? To znaczy. usunięcie instrukcji if i po prostu wstawienie glDisable (GL_CULL_FACE)? – NickLH

+0

Mam, ale to nie zadziałało. – snowball147

1

Jestem całkiem pewien, że problemem jest struktura jest „odwrócenie” wzdłuż osi y. Dlatego twoja "1-y" działa. Można go naprawić, przewijając teksturę wzdłuż Y podczas ładowania. Chociaż nie jestem jeszcze pewien, dlaczego właśnie dziś natknąłem się na ten problem.

Powiązane problemy