gpt4 book ai didi

c - Md2模型顶点加载问题

转载 作者:行者123 更新时间:2023-11-30 19:14:14 25 4
gpt4 key购买 nike

我正在尝试加载 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 模型。

这是我的着色器(与 crate 和飞机的着色器几乎相同,除了只有一个“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);
}

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

感谢任何帮助。

最佳答案

我通过复制从 tirangles 数据中获取的顶点/uv 解决了这个问题。我不必像许多教程那样翻转“t”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 已经足够好了。如果有人知道更好的方法来完成这一切,请随时发表评论。

怪博士正在放松

enter image description here

关于c - Md2模型顶点加载问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34476278/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com