我最近尝试在我的 OpenGL 应用程序中导入网格时遇到问题。网格导入成功,但是在渲染时它看起来完全毁容了。在我看来,网格的顶点位置没有正确加载。下面是问题的图像。 注意: 此处导入的 .obj 是 Blender 的默认猴子网格。可以看出,网格的大体轮廓被保留了下来,但是,它完全偏离了目标。
我不能在这里问最好的问题,因为我似乎无法确定代码在哪一点失败。没有构建或运行时错误。然而,我最好的猜测是代码在加载网格时失败了。下面的代码是加载器函数。
bool Loader::LoadObject(
std::string objectFP,
std::vector<glm::vec3>& VBD,
std::vector<glm::vec2>& UVBD,
std::vector<glm::vec3>& NBD,
std::vector<unsigned int>& IBD
)
{
Helpers::Log(LOG, "Loading object (" + objectFP + ")...");
std::vector<glm::vec3> VertexData;
std::vector<glm::vec2> UVData;
std::vector<glm::vec3> NormalData;
FILE* file = fopen(objectFP.c_str(), "r");
if (file == 0)
{
Helpers::Error(ERR, L"Failed to load object.");
return false;
}
else
{
while (true)
{
char lineHeader[128] = { 0 };
int res = fscanf(file, "%s", lineHeader);
/* RUN CHECKS */
// End of File (EOF)
if (res == EOF)
{
break;
}
else
{
if (res <= 0)
{
Helpers::Error(ERR, L"(RES) Failed to load object.");
break;
}
else
{
if (strcmp(lineHeader, "v") == 0)
{
glm::vec3 vertex = glm::vec3(0.0f, 0.0f, 0.0f);
// Return value is not needed here, just to get rid of the warning
int out = fscanf(file, "%f %f %f\n", &vertex.x, &vertex.y, &vertex.z);
VertexData.push_back(vertex);
}
else if (strcmp(lineHeader, "vt") == 0)
{
glm::vec2 uv = glm::vec2(0.0f, 0.0f);
int out = fscanf(file, "%f %f\n", &uv.x, &uv.y);
UVData.push_back(uv);
}
else if (strcmp(lineHeader, "vn") == 0)
{
glm::vec3 normal = glm::vec3(0.0f, 0.0f, 0.0f);
int out = fscanf(file, "%f %f %f\n", &normal.x, &normal.y, &normal.z);
NormalData.push_back(normal);
}
else
{
char fillBuffer[1000];
fgets(fillBuffer, 100, file);
}
VBD.reserve(VertexData.size());
UVBD.reserve(UVData.size());
NBD.reserve(NormalData.size());
for (unsigned int i = 0; i < VertexData.size(); i++)
{
VBD.push_back(VertexData[i]);
}
for (unsigned int i = 0; i < UVData.size(); i++)
{
UVBD.push_back(UVData[i]);
}
for (unsigned int i = 0; i < NormalData.size(); i++)
{
NBD.push_back(NormalData[i]);
}
}
}
}
ComputeIndexBuffer(VBD, IBD);
fclose(file);
return true;
}
}
如果这不是问题。源代码是公开的here.
着色器也可能有问题。
monkey.obj
,正如我所怀疑的那样,你的网格没有被三角化。从搅拌机导出时。选中如下所示的
Triangulated Mesh
框,将网格从多边形转换为三角形,因为您在导入器中将面解释为三角形。在你的
ComputeIndexBuffer()
函数中:
void Loader::ComputeIndexBuffer(std::vector<glm::vec3> VBD, std::vector<unsigned int>& IBD)
{
for (unsigned int i = 0; i < VBD.size() / 3; i++)
{
unsigned int i1 = i * 3;
unsigned int i2 = i * 3 + 1;
unsigned int i3 = i * 3 + 2;
IBD.push_back(i1);
IBD.push_back(i2);
IBD.push_back(i3);
}
}
您假设面是三角形,而 monkey.obj
文件主要包含四边形,因此渲染不正确。为了处理多边形,你要么必须改进你的进口商,要么求助于使用专门的进口商,比如
assimp
编辑:为了进一步澄清,我将显示您的“monkey.obj”中的线条和三角线:在下面的行中:
f 505/553/499 323/353/499 321/349/499 391/427/499
这是monkey.obj
的最后一行,定义了一个面(
f
在行的开头),有4个顶点(即四边形),每个顶点包含关于位置/uv坐标/法线的信息;而三角剖分的人的所有面孔都是这样定义的:
f 505/553/942 323/353/942 321/349/942
如您所见,共有三个 /
组,因此有三个顶点,因此有一个
triangle
.