我最近编写了一个与C ++集成的.obj模型加载器。到目前为止,我已经成功地设法调整文件中的数据,获取其四种属性类型(v,vn,vt和f),以便为IBO结构设置顶点和索引。问题是,顶点位置似乎不止一次交叉,导致一组顶点散布在模型的形式内。
(示范显示在下面的图片链接中。)
Click me to view the current result!
我已经多次彻底调试,仍然无法确定这个问题。 请记住我将每个法线和纹理坐标值设置为零(暂时)以进行测试。此外,剔除被禁用,因此根本不能成为正常的问题。
无论如何,到达代码 - 我首先有一个Vertex结构存储位置,法线和tex-coords的所有属性数据:
struct Vertex
{
CBfloat v1, v2, v3;
CBfloat vn1, vn2, vn3;
CBfloat vt1, vt2;
Vertex(vec3 _position, vec3 _normal, vec2 _texCoord)
{
v1 = _position[0];
v2 = _position[1];
v3 = _position[2];
vn1 = _normal[0];
vn2 = _normal[1];
vn3 = _normal[2];
vt1 = _texCoord[0];
vt2 = _texCoord[1];
}
};
我使用这些容器来收集呈现IBO所需的所有数据:
std::vector <Vertex> _vertices;
std::vector <CBuint> _indices;
然后,在我的loadOBJ函数中,我从.obj中检索数据并将其分配给包含顶点位置,顶点法线和顶点纹理坐标的四个临时矢量列表:
// Assign vertex data
std::vector <vec3> _v;
std::vector <vec3> _vn;
std::vector <vec2> _vt;
std::vector <Face> _f;
for (unsigned int i = 0; i < line.size(); i++)
{
switch ((line[i])[0])
{
case '#':
continue;
case '\0':
continue;
case 'm':
char mtl_url[128];
sscanf_s((&line[i])[0].c_str(), "mtllib %s", mtl_url, sizeof(mtl_url));
_mtl_url = mtl_url;
_materialised = true;
break;
case 'v':
float x, y, z;
if ((line[i])[1] == 'n')
{
sscanf_s((&line[i])[0].c_str(), "vn %f %f %f", &x, &y, &z);
_vn.push_back(vec3(x, y, z));
}
if ((line[i])[1] == 't')
{
sscanf_s((&line[i])[0].c_str(), "vt %f %f", &x, &y);
_vt.push_back(vec2(x, y));
}
else if ((line[i])[1] == ' ')
{
sscanf_s((&line[i])[0].c_str(), "v %f %f %f", &x, &y, &z);
_v.push_back(vec3(x, y, z));
}
break;
case 'u':
char material_element[128];
sscanf_s((&line[i])[0].c_str(), "usemtl %s", &material_element, sizeof(material_element));
// Assign new material to element
if (_material_element.size() > 1)
_f[_f.size() - 1].mat_id = _material_element.size();
_material_element.push_back(material_element);
break;
case 'f':
CBuint v_i[3];
CBuint vn_i[3];
CBuint vt_i[3];
sscanf_s((&line[i])[0].c_str(), "f %d/%d/%d %d/%d/%d %d/%d/%d", &v_i[0], &vt_i[0], &vn_i[0], &v_i[1], &vt_i[1], &vn_i[1], &v_i[2], &vt_i[2], &vn_i[2]);
// Faces (IGNORE!)
_f.push_back(Face(v_i[0], vt_i[0], vn_i[0], v_i[1], vt_i[1], vn_i[1], v_i[2], vt_i[2], vn_i[2]));
// Indices
_indices.push_back(v_i[0] - 1);
_indices.push_back(vt_i[0] - 1);
_indices.push_back(vn_i[0] - 1);
_indices.push_back(v_i[1] - 1);
_indices.push_back(vt_i[1] - 1);
_indices.push_back(vn_i[1] - 1);
_indices.push_back(v_i[2] - 1);
_indices.push_back(vt_i[2] - 1);
_indices.push_back(vn_i[2] - 1);
break;
}
}
接下来,我根据顶点位置的数量分配顶点(用于测试目的的临时方法):
// Optimise vertices (TEMP!!)
for (CBuint i = 0; i < _v.size(); i++)
{
if (i <= _vn.size() - 1 && i <= _vt.size() - 1)
_vertices.push_back(Vertex(_v[i], _vn[i], _vt[i]));
else if (i > _vn.size() - 1 && i <= _vt.size() - 1)
_vertices.push_back(Vertex(_v[i], vec3(0.0f, 0.0f, 0.0f), _vt[i]));
else
_vertices.push_back(Vertex(_v[i], vec3(0.0f, 0.0f, 0.0f), vec2(0.0f, 0.0f)));
}
最后,缓冲区。我首先定义&#34; BUFFER_OFFSET&#34;为:
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
然后按如下方式设置其他所有内容:
glGenVertexArrays(1, &_vao);
glBindVertexArray(_vao);
// Generate
glGenBuffers(1, &vbo);
glGenBuffers(1, &ebo);
// Bind
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
// Buffer
glBufferData(GL_ARRAY_BUFFER, _vertices.size() * sizeof(Vertex), &_vertices[0], GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, _indices.size() * sizeof(CBuint), &_indices[0], GL_STATIC_DRAW);
// Set attribs
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(0));
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(sizeof(CBfloat) * 3));
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(sizeof(CBfloat) * 6));
// Enable attribs
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
// Clean up
glBindVertexArray(0);
然后当然导致渲染阶段:
virtual void render()
{
glUniformMatrix4fv(_u_model, 1, GL_FALSE, _model);
_materials[0]->bind();
glBindVertexArray(_vao);
glDrawElements(GL_TRIANGLES, _indices.size(), GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
}
为了好奇,我正在测试的cube.obj文件包含以下来源:
v -0.5000 -0.5000 0.5000
v -0.5000 -0.5000 -0.5000
v 0.5000 -0.5000 -0.5000
v 0.5000 -0.5000 0.5000
v -0.5000 0.5000 0.5000
v 0.5000 0.5000 0.5000
v 0.5000 0.5000 -0.5000
v -0.5000 0.5000 -0.5000
# 8 vertices
vn 0.0000 -1.0000 -0.0000
vn 0.0000 1.0000 -0.0000
vn 0.0000 0.0000 1.0000
vn 1.0000 0.0000 -0.0000
vn 0.0000 0.0000 -1.0000
vn -1.0000 0.0000 -0.0000
# 6 vertex normals
vt 1.0000 0.0000 0.0000
vt 1.0000 1.0000 0.0000
vt 0.0000 1.0000 0.0000
vt 0.0000 0.0000 0.0000
# 4 texture coords
g Box001
s 2
f 1/1/1 2/2/1 3/3/1
f 3/3/1 4/4/1 1/1/1
s 4
f 5/4/2 6/1/2 7/2/2
f 7/2/2 8/3/2 5/4/2
s 8
f 1/4/3 4/1/3 6/2/3
f 6/2/3 5/3/3 1/4/3
s 16
f 4/4/4 3/1/4 7/2/4
f 7/2/4 6/3/4 4/4/4
s 32
f 3/4/5 2/1/5 8/2/5
f 8/2/5 7/3/5 3/4/5
s 64
f 2/4/6 1/1/6 5/2/6
f 5/2/6 8/3/6 2/4/6
# 12 faces
如果有人对导致此顶点/索引渲染错误的内容有任何想法,我非常感谢您的启发。
谢谢你, 威廉。