在 openGL 中加载 obj 文件

Loading obj files in openGL

我是 OpenGL 的新手,我正在尝试将 obj 文件加载到我的代码中。我有一个简单的动画立方体代码。当我如下声明顶点和索引时,它可以正常工作:

GLfloat cube_vertices[] = {
// front
    -1.0, -1.0, 1.0,
    1.0, -1.0, 1.0,
    1.0, 1.0, 1.0,
    -1.0, 1.0, 1.0,
    // back
    -1.0, -1.0, -1.0,
    1.0, -1.0, -1.0,
    1.0, 1.0, -1.0,
    -1.0, 1.0, -1.0,
};
GLushort cube_elements[] = {
    // front
    0, 1, 2,
    2, 3, 0,
    // top
    1, 5, 6,
    6, 2, 1,
    // back
    7, 6, 5,
    5, 4, 7,
    // bottom
    4, 0, 3,
    3, 7, 4,
    // left
    4, 5, 1,
    1, 0, 4,
    // right
    3, 2, 6,
    6, 7, 3,
};

但是,当我尝试从文件中获取相似的数字时,程序运行时没有错误,但在 window 中什么也没有显示。这是我加载 obj 文件的代码:

vector<GLfloat> vertices;
vector<GLushort> elements;

ifstream in("cube.obj", ios::in);
if (!in)
{
    cerr << "Cannot open " << "sample.obj" << endl; exit(1);
}

string line;
while (getline(in, line))
{
    if (line.substr(0, 2) == "v ")
    {
        istringstream s(line.substr(2));
        GLfloat v;
        s >> v; vertices.push_back(v);
        s >> v; vertices.push_back(v);
        s >> v; vertices.push_back(v);

    }
    else if (line.substr(0, 2) == "f ")
    {
        istringstream s(line.substr(2));
        GLushort a, b, c;
        s >> a; s >> b; s >> c;
        elements.push_back(a); elements.push_back(b); elements.push_back(c);
    }
}

cube.obj文件保存如下:

o cube
v -1.0 -1.0 1.0
v 1.0 -1.0 1.0
v 1.0 1.0 1.0
v -1.0 1.0 1.0
v -1.0 -1.0 -1.0
v 1.0 -1.0 -1.0
v 1.0 1.0 -1.0
v -1.0 1.0 -1.0
f 0 1 2
f 2 3 0
f 1 5 6
f 6 2 1
f 7 6 5
f 5 4 7
f 4 0 3
f 3 7 4
f 4 5 1
f 1 0 4
f 3 2 6
f 6 7 3

我只是在输出中得到一个空白 window。你知道加载器为什么不工作吗?

我这样上传数据

glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices, GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), &elements, GL_STATIC_DRAW);

当我没有在 verticeselements 之前放置 & 运算符时,它给出了 "no suitable conversion".

的编译错误

您 post 编辑的代码可以很好地加载顶点和面,因此您需要 post 您的渲染代码才能获得特定答案。

不过根据您 post 的内容,我有一些建议:

  • 您在指定多维数据集时使用了 cube_vertices 和 cube_elements,但在从文件加载时使用了不同的变量。您是否尝试从程序中的空数组进行渲染?
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices, GL_STATIC_DRAW);

glBufferData 需要原始数据而不是直接的向量,而且数据的大小也应该正确给出。您在这里所做的是传递 vector 本身的大小,而不是它包含的数据。

A vector 是一个数据结构,一个容器,具有元数据,例如指向它要保存的数据的指针和一个变量来保存它所保存的元素的数量。当你做 sizeof(vector) 时,它总是 return 一个常数,不管它包含多少元素;这个尺寸是sizeof(pointer-to-data) + sizeof(variable-holding-count)。这个数据不是你想要的。

此外,当您传递 &vertices 时,您传递的是向量本身的地址,而不是它包含的数据的地址。 vector::data() 给出其中包含的数据的地址。

改为这样做:

glBufferData(GL_ARRAY_BUFFER,
             vertices.size() * sizeof(GLfloat),
             vertices.data(),
             GL_STATIC_DRAW);

应该这样做。元素数组缓冲区也是如此。

glBufferData(GL_ELEMENT_ARRAY_BUFFER,
             elements.size() * sizeof(GLushort),
             elements.data(),
             GL_STATIC_DRAW);

vector::size() 给出了它包含的元素的数量,乘以一个元素的大小给出了包含的数据的正确大小。

一边

line.substr(0, 2) == "v "
line.substr(0, 2) == "f "

这会不必要地创建两个子字符串,相反您可以这样做来检查相同的东西

line[0] == 'v'
line[0] == 'f'