2015-12-26 2 views
0

J'essaye de charger un modèle MD2 mais je n'arrive pas à obtenir les vertices pour dessiner correctement. Je ne charge pas les UV ou les normales pour l'instant je veux juste voir le modèle apparaître correctement dans un seul cadre puis le prendre à partir de là.Problèmes de chargement de modèles Md2

Voilà mes structures MD2 (principalement tirées de here):

struct v3 
{ 
    union 
    { 
     struct 
     { 
      union { float x; float r; }; 
      union { float y; float g; }; 
      union { float z; float b; }; 
     }; 
     float At[3]; 
    }; 
}; 

struct md2_header 
{ 
    unsigned int Magic; 
    unsigned int Version; 

    unsigned int TextureWidth; 
    unsigned int TextureHeight; 

    unsigned int FrameSize; 

    unsigned int NumTextures; 
    unsigned int NumVertices; 
    unsigned int NumUVs; 
    unsigned int NumTrigs; 
    unsigned int NumGLCommands; 
    unsigned int NumFrames; 

    unsigned int OffsetTextures; 
    unsigned int OffsetUVs; 
    unsigned int OffsetTrigs; 
    unsigned int OffsetFrames; 
    unsigned int OffsetGLCommands; 
    unsigned int OffsetEnd; 
}; 

struct md2_vertex 
{ 
    unsigned char At[3]; 
    unsigned char NormalIndex; 
}; 

struct md2_frame 
{ 
    float  Scale[3]; 
    float  Translate[3]; 
    char  Name[16]; 
    md2_vertex *Vertices; 
}; 

struct md2_skin 
{ 
    char Name[64]; 
}; 

struct md2_uv 
{ 
    unsigned short u; 
    unsigend short v; 
} 

struct md2_triangle 
{ 
    unsigned short Vertices[3]; 
    unsigned short UVs[3]; 
}; 

struct md2_model 
{ 
    md2_header Header; 
    md2_uv *UVs; 
    md2_triangle *Triangles; 
    md2_frame *Frames; 
    md2_skin *Skins; 
    int *GLCommands; 
    unsigned int Texture; 
    unsigned int VAO, VBO; 
}; 

Et voici ma simple fonction de chargement:

void MD2LoadModel (char *FilePath, md2_model *Model) 
{ 
    FILE *File = fopen (FilePath, "rb"); 
    if (!File) 
    { 
     fprintf (stderr, "Error: couldn't open \"%s\"!\n", FilePath); 
     return; 
    } 

#define FREAD(Dest, Type, Count)\ 
    fread(Dest, sizeof(Type), Count, File) 

#define FSEEK(Offset)\ 
    fseek(File, Offset, SEEK_SET) 

#define ALLOC(Type, Count)\ 
    (Type *)malloc(sizeof(Type) * Count) 

    /* Read Header */ 
    FREAD(&Model->Header, md2_header, 1); 

    if ((Model->Header.Magic != 844121161) || 
     (Model->Header.Version != 8)) 
    { 
     fprintf (stderr, "Error: bad md2 Version or identifier\n"); 
     fclose (File); 
     return; 
    } 

    /* Memory allocations */ 
    Model->Skins = ALLOC(md2_skin, Model->Header.NumTextures); 
    Model->UVs = ALLOC(md2_uv, Model->Header.NumUVs); 
    Model->Triangles = ALLOC(md2_triangle, Model->Header.NumTrigs); 
    Model->Frames = ALLOC(md2_frame, Model->Header.NumFrames); 
    Model->GLCommands = ALLOC(int, Model->Header.NumGLCommands); 

    /* Read model data */ 
    FSEEK(Model->Header.OffsetTextures); 
    FREAD(Model->Skins, md2_skin, Model->Header.NumTextures); 

    FSEEK(Model->Header.OffsetUVs); 
    FREAD(Model->UVs, md2_uv, Model->Header.NumUVs); 

    FSEEK(Model->Header.OffsetTrigs); 
    FREAD(Model->Triangles, md2_triangle, Model->Header.NumTrigs); 

    FSEEK(Model->Header.OffsetGLCommands); 
    FREAD(Model->GLCommands, int, Model->Header.NumGLCommands); 

    /* Read frames */ 
    FSEEK(Model->Header.OffsetFrames); 
    for (int i = 0; i < Model->Header.NumFrames; i++) 
    { 
     /* Memory allocation for vertices of this frame */ 
     Model->Frames[i].Vertices = (md2_vertex *) 
      malloc(sizeof(md2_vertex) * Model->Header.NumVertices); 

     /* Read frame data */ 
     FREAD(&Model->Frames[i].Scale, v3, 1); 
     FREAD(&Model->Frames[i].Translate, v3, 1); 
     FREAD(Model->Frames[i].Name, char, 16); 
     FREAD(Model->Frames[i].Vertices, md2_vertex, Model->Header.NumVertices); 
    } 

    v3 *Vertices = ALLOC(v3, Model->Header.NumVertices); 

    md2_frame *Frame = &Model->Frames[0]; 
    For(u32, i, Model->Header.NumVertices) 
    { 
     Vertices[i] = V3(
      (Frame->Vertices[i].At[0] * Frame->Scale[0]) + Frame->Translate[0], 
      (Frame->Vertices[i].At[1] * Frame->Scale[1]) + Frame->Translate[1], 
      (Frame->Vertices[i].At[2] * Frame->Scale[2]) + Frame->Translate[2]); 
    } 

    glGenBuffers(1, &Model->VBO); 
    glBindBuffer(GL_ARRAY_BUFFER, Model->VBO); 
    glBufferData(GL_ARRAY_BUFFER, Model->Header.NumVertices * sizeof(v3), Vertices, GL_STATIC_DRAW); 

    glGenVertexArrays(1, &Model->VAO); 
    glBindVertexArray(Model->VAO); 
    glEnableVertexAttribArray(0); 
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); 
    glBindVertexArray(0); 
    glBindBuffer(GL_ARRAY_BUFFER, 0); 

    fclose (File); 
    free(Vertices); 

#undef FSEEK 
#undef FREAD 
#undef ALLOC 
} 

ne laissant passer que les informations sur les sommets. Lequel, d'après ma compréhension Header->NumVertices est le nombre de sommets dans chaque trame. Donc, je prends une image arbitraire (l'image 0 dans ce cas) et la lecture de ses données de sommets non compressés en Vertices.

Maintenant, j'ai lu dans un livre que Quake avait leurs axes y et z retournés, mais cela n'a pas beaucoup changé.

Voilà comment je dessine le modèle:

GLuint Shader = Data->Shaders.Md2Test; 
ShaderUse(Shader); 
ShaderSetM4(Shader, "view", &WorldToView); 
ShaderSetM4(Shader, "projection", &ViewToProjection); 

glBindVertexArray(DrFreak.VAO); 
{ 
    ModelToWorld = m4_Identity; 
    ShaderSetM4(Shader, "model", &ModelToWorld); 
    glDrawArrays(GL_TRIANGLES, 0, DrFreak.Header.NumVertices); 
} 
glBindVertexArray(0); 

Les matrices sont calculées en fonction de CameraUpdate que je peux vérifier fonctionne correctement parce que tout le reste dans le rendu de la scène correctement sauf le modèle MD2. Voir:

enter image description here

Tout en jaune est censé être le modèle MD2.

Voici mes shaders (à peu près les mêmes shaders pour les caisses et les avions sauf qu'il n'y a qu'un seul « dans » variable, la position et pas UVs):

#version 330 core 
layout (location = 0) in vec3 position; 

uniform mat4 model; 
uniform mat4 view; 
uniform mat4 projection; 

void main() 
{ 
    gl_Position = projection * view * model * vec4(position, 1.0f); 
} 

#version 330 core 
out vec4 color; 
void main() 
{    
    color = vec4(1, 1, 0, 1); 
} 

Je suis coincé ici pour quelques jours. Je suis entré dans le code de chargement et il me semble obtenir des valeurs valides. Je ne suis pas sûr de quel est le problème. Que fais-je tort/manquant?

Toute aide est appréciée.

+0

Pourquoi downvote? – vexe

Répondre

1

J'ai corrigé le problème en dupliquant les sommets/uvs en les récupérant des données tirangles. Je n'ai pas eu besoin d'inverser les coordonnées UV de 't' comme le font de nombreux didacticiels. J'ai changé les coordonnées y et z car elles sont retournées.

u32 NumVerts = Model->Header.NumTrigs * 3; 
u32 NumUVs = NumVerts; 

v3 *Vertices = ALLOC(v3, NumVerts); 
v2 *UVs = ALLOC(v2, NumUVs); 

md2_frame *Frame = &Model->Frames[0]; // render first frame for testing 

For(u32, i, Model->Header.NumTrigs) 
{ 
    For(u32, j, 3) 
    { 
     u32 VertIndex = Model->Triangles[i].Vertices[j]; 
     Vertices[i * 3 + j] = V3(
      (Frame->Vertices[VertIndex].At[0] * Frame->Scale[0]) + Frame->Translate[0], 
      (Frame->Vertices[VertIndex].At[2] * Frame->Scale[2]) + Frame->Translate[2], 
      (Frame->Vertices[VertIndex].At[1] * Frame->Scale[1]) + Frame->Translate[1]); 

     u32 UVIndex = Model->Triangles[i].UVs[j]; 
     UVs[i * 3 + j] = V2(
      Model->UVs[UVIndex].u/(r32)Model->Header.TextureWidth, 
      Model->UVs[UVIndex].v/(r32)Model->Header.TextureHeight); 
    } 
} 

glGenVertexArrays(1, &Model->VAO); 
glBindVertexArray(Model->VAO); 

glGenBuffers(1, &Model->VBO); 
glBindBuffer(GL_ARRAY_BUFFER, Model->VBO); 
glBufferData(GL_ARRAY_BUFFER, NumVerts * sizeof(v3), Vertices, GL_STATIC_DRAW); 
glEnableVertexAttribArray(0); 
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); 

u32 UVBuffer; 
glGenBuffers(1, &UVBuffer); 
glBindBuffer(GL_ARRAY_BUFFER, UVBuffer); 
glBufferData(GL_ARRAY_BUFFER, NumUVs * sizeof(v2), UVs, GL_STATIC_DRAW); 
glEnableVertexAttribArray(1); 
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0); 

glBindVertexArray(0); 
glBindBuffer(GL_ARRAY_BUFFER, 0); 

Je vais probablement utiliser des tableaux indexés et glDrawElements. Mais pour mes tests, glDrawArrays est assez bon. Si quelqu'un connaît une meilleure façon de faire tout cela, n'hésitez pas à laisser un commentaire.

Et il y a le Dr Freak Chillin'

enter image description here