【问题标题】:Assimp loader with a cube of 8 vertices带有 8 个顶点的立方体的 Assimp 加载器
【发布时间】:2017-01-09 04:42:05
【问题描述】:

我正在加载当前使用这些标志的立方体的 .obj 模型:

const aiScene* scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_GenNormals | aiProcess_JoinIdenticalVertices);

该模型仅包含 8 个顶点(立方体的每个 sommet),因此没有重复的顶点来指定 assimp 来绘制所需的所有三角形。 结果,我只画了 3 个三角形。

我相信这是因为我使用:

glDrawArrays(GL_TRIANGLES, 0, vertices.size());

其中 vertices.size() 等于 22(这是 mesh->mNumVertices 的返回值)。

我没有得到这个 22,对我来说它应该是 8 或 6*2*3 = 36(6 个面,每个面有 2 个三角形)。谁能解释它来自哪里?

我虽然使用 GL_TRIANGLE_STRIP 但顶点的顺序不正确(我什至不知道它们是否可以)。我得到更多的三角形,但不是正确的。

所以我的主要问题是:有没有可以添加到 ReadFile 的标志 - 或其他东西 - 为要在 .obj 文件中绘制的每个三角形编写顶点的副本。

PS:我从 Blender 导出了 Wavefront 模型,也许在 Blender 上我可以设置一些东西来导出冗余顶点。

我的 .obj 文件: o 1

  # Vertex list

  v -0.5 -0.5 0.5
  v -0.5 -0.5 -0.5
  v -0.5 0.5 -0.5
  v -0.5 0.5 0.5
  v 0.5 -0.5 0.5
  v 0.5 -0.5 -0.5
  v 0.5 0.5 -0.5
  v 0.5 0.5 0.5

  usemtl Default
  f 4 3 2 1
  f 2 6 5 1
  f 3 7 6 2
  f 8 7 3 4
  f 5 8 4 1
  f 6 7 8 5

编辑:我如何使用 Qt OpenGL 类型(现在使用 EBO)设置网格:

   void setupMesh(QOpenGLShaderProgram* program)
    {
    // Create Vertex Array Object
    if (!VAO->isCreated()) {
        VAO->create();
    }
    VAO->bind();

    VBO.create();
    VBO.bind();

    VBO.setUsagePattern(QOpenGLBuffer::StaticDraw);

    construct_sg_vertex();

    VBO.allocate(this->m_vec.constData(), this->m_vec.size() * sizeof(m_vec.at(0)));


    EBO.create();
    EBO.bind(); //glBindBuffer(GL_ARRAY_BUFFER, ebo);
    EBO.setUsagePattern(QOpenGLBuffer::StaticDraw);
    EBO.allocate(indices.data(),indices.size()*sizeof(GLuint)); 

    // 0 : positions
    program->enableAttributeArray(0);
    program->setAttributeBuffer(0, GL_FLOAT, Vertex::positionOffset(), Vertex::PositionTupleSize, Vertex::stride());

    //1: colors
    program->enableAttributeArray(1);
    program->setAttributeBuffer(1, GL_FLOAT, Vertex::colorOffset(), Vertex::ColorTupleSize, Vertex::stride());

    VBO.release();
    EBO.release();
}

private:

QOpenGLBuffer VBO ;
QOpenGLVertexArrayObject* VAO = new QOpenGLVertexArrayObject();
QOpenGLBuffer EBO ; //New Element Buffer
};

通过添加的索引缓冲区,我将绘制方式更改为: VAO->绑定(); glDrawElements(GL_TRIANGLES, indices.size(),GL_UNSIGNED_INT,0);

结果,什么都没有渲染...

【问题讨论】:

  • 您在这里遗漏了一些基本信息,例如如何设置缓冲区(glBindBuffer、glEnableVertexAttribArray、glVertexAttribPointer)。你的 .obj 是什么样的?是否启用背面剔除?
  • 背面剔除已启用。我实际上将 Qt 用于着色器和 VAO。我正在编辑,以便您可以看到我是如何设置它们的。
  • 只考虑顶点是不够的。您还需要这些面来了解顶点是如何组装的。
  • 是的,但我相信 f x y z t 会在 obj 文件中进行组装,不是吗?
  • 是的,这条线是用来组装的。但是你没有考虑到这一点。此信息存储在mFaces 中。您必须从中构建一个索引缓冲区。

标签: opengl blender assimp


【解决方案1】:

根据您提供的标志,我预计会生成 24 个顶点:一个立方体由 6 个面组成,每个面由 2 个三角形组成。现在生成法线时(按照aiProcess_GenNormals 的要求),立方体的每一侧都有4 个唯一的顶点。注意,这里的顶点是指位置和法线的组合。 4个独特的顶点,6条边,共24个顶点。

现在到绘图问题:由于aiProcess_JoinIdenticalVertices 是请求,assimp 将连接所有相同的顶点,在aiMesh->mVertices 数组中只留下这些唯一的顶点。仅凭这些信息不足以绘制任何东西。此外,还需要有关这些顶点如何组装成三角形的信息,由aiMesh->mFaces 提供。从这些面中,要么必须生成一个索引缓冲区,要么通过以正确的顺序复制顶点来将它们组装成一个新数组。下面的代码展示了如何构造索引缓冲区的数据:

std::vector<unsigned int> indices;
indices.reserve(aimesh->mNumFaces * 3);
for (unsigned int fid = 0; fid < aimesh->mNumFaces; fid++)
{
    auto& face = aimesh->mFaces[fid];
    for (size_t iid = 0; iid < 3; iid++)
        indices.push_back(face.mIndices[iid]);
}

索引数据可以被 OpenGL 使用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-30
    • 2017-02-05
    • 2019-11-02
    • 2016-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多