Opengl在.obj加载器中为网格添加了一个额外的顶点

时间:2014-09-30 05:07:38

标签: opengl

enter image description here

我创建了一个.obj加载器,它从在blender 2.66中创建的网格文件中读取,并将数据加载到作为VBO传递给Opengl的std :: vector中。网格文件中的所有顶点都没有(0,0,0)的位置。 那么,网格在中心获得额外顶点的可能原因是什么?由于原始网格只是一个只有四个顶点的三角形平面。

struct Vertex
{
    //Position
    GLfloat m_X;
    GLfloat m_Y;
    GLfloat m_Z;

    //Normal
    GLfloat m_NX;
    GLfloat m_NY;
    GLfloat m_NZ;

    //TexCoords
    GLfloat m_U;
    GLfloat m_V;
};

void Mesh::loadMesh(std::string Filename)
{
  ...

    const unsigned int PositionAttribute = 0;
    const unsigned int NormalAttribute   = 1;
    const unsigned int TexCoordAttribute = 2;

    //Create a new VBO and use the variable id to store the VBO id
    glGenBuffers(1, &MeshVBO);

    //make the new VBO active
    glBindBuffer(GL_ARRAY_BUFFER, MeshVBO);

    //Pass the Mesh's vertex data into the VBO to be transferred to super fast Video RAM
    glBufferData(GL_ARRAY_BUFFER, m_Vertices.size() * sizeof(Vertex), &m_Vertices[0], GL_STATIC_DRAW);

    glEnableVertexAttribArray(PositionAttribute);
    glEnableVertexAttribArray(NormalAttribute);
    glEnableVertexAttribArray(TexCoordAttribute);

    //specifies the location and data of an array of vertex
    glVertexAttribPointer(PositionAttribute, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)0);
    glVertexAttribPointer(NormalAttribute, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)(sizeof(GLfloat) * 3)); //12 byte offset
    glVertexAttribPointer(TexCoordAttribute, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)(sizeof(GLfloat) * 6)); //24 byte offset

    //make the new VBO active
    glBindBuffer(GL_ARRAY_BUFFER, MeshVBO);

    glGenBuffers(1, &MeshIBO);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, MeshIBO);

    glBufferData(GL_ELEMENT_ARRAY_BUFFER, (sizeof(GLushort) * m_IndexList.size()), &m_IndexList[0], GL_STATIC_DRAW); 

    //Cleanup
    delete[] m_VertexArray;
    delete[] m_Indices;
    m_VertexArray = NULL;
    m_Indices = NULL;

    return Success;
}

void Mesh::drawMesh()
{
    glDrawElements(GL_POINTS, (GLsizei)m_IndexList.size() + 1, GL_UNSIGNED_SHORT, 0);
}

Plane.obj

# Blender v2.66 (sub 1) OBJ File: ''
# www.blender.org
mtllib plane.mtl
o Plane
v 0.622129 -0.622129 0.000000
v -0.622129 -0.622129 0.000000
v 0.622129 0.622129 -0.000000
v -0.622129 0.622129 -0.000000
vn 1.000000 0.000000 0.000000
usemtl None
s off
f 2//1 1//1 3//1
f 4//1 2//1 3//1

1 个答案:

答案 0 :(得分:4)

您的主要问题是OBJ文件中的索引是基于1的,而OpenGL使用基于0的索引。这意味着您必须从OBJ文件中读取的索引中减去1。在您阅读解析代码中的索引之后,这是最方便的,因为大多数编程语言和API使用基于0的索引。

如果您希望能够读取更多选择的OBJ文件,则还必须在输入文件中处理负索引值。这似乎并不常用,如果文件来自一个控制良好的源(例如,您总是使用相同的软件自己生成它们),您可以跳过此步骤。如果存在,则负指数相对于到目前为止读取的顶点的末尾。例如。 index -1是最新的顶点读取,-2是最新的顶点读取等。

在发布的代码中,您在绘图调用中添加了1到可用索引的数量:

glDrawElements(GL_POINTS, (GLsizei)m_IndexList.size() + 1, GL_UNSIGNED_SHORT, 0);

我怀疑您可能已经这样做以弥补错误的索引值。获得正确的索引值后,应删除+ 1

有关OBJ格式的更详细文档,维基百科页面(http://en.wikipedia.org/wiki/Wavefront_.obj_file)包含一个很好的概述。我发现的最详细和最全面的定义是:http://www.martinreddy.net/gfx/3d/OBJ.spec。 OBJ格式可以包含相当高级的功能,如NURBS。如果您编写自己的解析器和渲染器,您可能希望找到一个子集。否则你会忙一段时间。

如果您想了解更多有关如何有效地从OBJ文件渲染网格的深入信息,以下是我对早期问题的一些相关答案: