Md2模型顶点加载问题

时间:2015-12-26 23:36:15

标签: c opengl md2

我正在尝试加载MD2模型,但我似乎无法正确绘制顶点。我现在没有加载UV或法线,只是想在一个帧中看到模型正确显示然后从那里取出。

这是我的md2结构(主要取自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;
};

这是我的简单加载功能:

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
}

仅传递顶点数据。根据我的理解Header->NumVertices,每帧中的顶点数量。所以我采用任意帧(在这种情况下为帧0)并将其未压缩的顶点数据读入Vertices

现在我在一本书中读到,Quake的y轴和z轴都被翻转了,但是仍然没有太大变化。

以下是我绘制模型的方法:

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

矩阵在CameraUpdate函数中计算,我可以验证它是否正常工作,因为除了MD2模型外,场景中的其他所有内容都可以正确呈现。参见:

enter image description here

黄色的一切都应该是MD2模型。

以下是我的着色器(除了只有一个'in'变量,位置和没有UV)之外,对于板条箱和平面几乎都是相同的着色器:

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

我被困在这里几天了。我进入了加载代码,我似乎得到了有效的值。我不确定是什么问题。我做错了什么/错过了什么?

感谢任何帮助。

1 个答案:

答案 0 :(得分:1)

我通过复制从tirangles数据中获取它们的顶点/ uv来解决问题。我没有必要翻转这个&#39;像许多教程一样的UV坐标。我切换了y和z坐标,因为它们被翻转了。

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

我可能会使用索引数组和glDrawElements。但是对于我的测试目的glDrawArrays已经足够了。如果有人知道更好的方法,可以随意发表评论。

还有Freak chillin博士&#39;

enter image description here