【问题标题】:obj loader not displaying correctly in c++ OpenGLobj loader 在 c++ OpenGL 中无法正确显示
【发布时间】:2014-08-26 14:03:55
【问题描述】:

我的 wavefront .obj 加载程序有问题,它没有显示我希望它显示的内容。我希望它显示一个立方体,但我不断得到这个:

这是我的 obj 文件

# cube.obj
#

g cube

v 0.0 0.0 0.0
v 0.0 0.0 1.0
v 0.0 1.0 0.0
v 0.0 1.0 1.0
v 1.0 0.0 0.0
v 1.0 0.0 1.0
v 1.0 1.0 0.0
v 1.0 1.0 1.0

vn 0.0 0.0 1.0
vn 0.0 0.0 -1.0
vn 0.0 1.0 0.0
vn 0.0 -1.0 0.0
vn 1.0 0.0 0.0
vn -1.0 0.0 0.0

f 1//2 7//2 5//2
f 1//2 3//2 7//2
f 1//6 4//6 3//6
f 1//6 2//6 4//6
f 3//3 8//3 7//3
f 3//3 4//3 8//3
f 5//5 7//5 8//5
f 5//5 8//5 6//5
f 1//4 5//4 6//4
f 1//4 6//4 2//4
f 2//1 6//1 8//1
f 2//1 8//1 4//1

我在我的代码中添加了部分以查​​看是否所有内容都正确存储,顶点和法线是否存储为 GLfloats

显示:

输入:

这是我的绘图功能: 我不太确定 glDrawArrays 中的最后一个参数,它是硬编码的,因为我不太确定索引的数量。

void Draw(void)
{
    glPushMatrix();
    glClearColor(0,0,0,1);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();

    glRotatef( rotate_x, 1.0, 0.0, 0.0 );
    glRotatef( rotate_y, 0.0, 1.0, 0.0 );

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);

    glNormalPointer(GL_FLOAT, 0, normals);
    glVertexPointer(3, GL_FLOAT,0, vertices);

    glDrawArrays(GL_TRIANGLES, 0, (14));

    glTranslatef(0, 0, -3);
    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);


    glFlush();
    glutSwapBuffers();
    glPopMatrix();
}

这也是我的主要内容:

int main(int argc,char** argv)
{
    glutInit(&argc, argv);

    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    glutInitWindowSize(500, 500);

    glutCreateWindow("Object Loader!");

    glEnable(GL_DEPTH_TEST);
    //glEnable(GL_LIGHTING);
    //glEnable(GL_LIGHT0);

    GLfloat posLight0[] = {0.0f, 0.0f, -1.0f, 0.0f};
    GLfloat lightColor[] = {1.0f, 1.0f, 1.0f, 1.0f};

    glLightfv(GL_LIGHT0, GL_POSITION, posLight0);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor);

    setUpArrays();

    glutDisplayFunc(Draw);
    glutSpecialFunc(specialKeys);
    glutReshapeFunc(reshape);

    glutMainLoop();
        return 0;
}

最后一件事是我不允许使用 glDrawElements 或 glBegin() 直接模式。

如果有帮助,这里是我的程序的更多内容: 一开始就设置全局变量

GLfloat* vertices;
GLfloat* normals;
GLint* faces;
int amountOfFaces;
double rotate_y=0;
double rotate_x=0;
Loader* loader = new Loader();

设置顶点、法线和索引的数组:

void setUpArrays()
{
    loader->loadObject("cube.obj");


    vector<GLfloat> temp = loader->getVerticies();
    vertices = new GLfloat[temp.size()];
    int tempSize = 0;
    cout << "vectors: ";
    for(vector<GLfloat>::const_iterator i = temp.begin(); i != temp.end(); ++i)
    {
        vertices[tempSize] = *i;
        cout << vertices[tempSize] << ", ";
        tempSize++;
    }
    cout << endl;
    vector<GLfloat> tempNormal = loader->getNormals();
    normals = new GLfloat[tempNormal.size()];
    tempSize = 0;
    cout << "normals: ";
    for(vector<GLfloat>::const_iterator i = tempNormal.begin(); i != tempNormal.end(); ++i)
    {
        normals[tempSize] = *i;
        cout << normals[tempSize] << ", ";
        tempSize++;
    }
    amountOfFaces = tempSize;
    cout << endl;

    vector<GLint> tempIndices = loader->getFaces();
    faces = new GLint[tempIndices.size()];
    tempSize = 0;
    cout << "Indices: ";
    for(vector<GLint>::const_iterator i = tempIndices.begin(); i != tempIndices.end(); ++i)
    {
        faces[tempSize] = *i;
        cout << faces[tempSize] << ", ";
        tempSize++;
    }
    cout << endl;

    amountOfFaces += tempSize;
}

【问题讨论】:

  • 我认为您没有正确附上问题的输出。

标签: c++ opengl


【解决方案1】:

我很困惑为什么但是 OBJ 格式给出的顶点属性索引从 1 开始,而不是 0。即f 1//2 指的是第一个顶点和第二个法线。您的调试输出在索引中没有显示为零,所以我猜加载器没有考虑到这一点。

有效的顶点索引从 1 开始,并匹配先前定义的顶点列表的相应顶点元素。每个面可以包含三个或更多顶点。 [wikipedia]

希望修复很简单:faces[tempSize] = *i - 1;

[编辑]
您的绘图调用指定了 14 个顶点,但您有 12 个三角形,因此应该绘制 36 个。amountOfFaces 听起来应该是 tempIndices.size()/3

您的向量应该是引用以避免复制,并且使用单个 memcpy 填充 faces 等会更快。例如:memcpy(faces, &amp;tempIndices.front(), sizeof(GLint) * tempIndices.size())

[编辑]
哦,对,当然。现在我因为没有注意到而感到愚蠢。 Faces 索引顶点,因此可以重复使用它们(节省内存和额外处理)。而不是 glDrawArrays 你想要这个:

glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, faces); //replate 36 for things you draw that aren't cubes

如果您想使用glDrawArrays,则必须重新排列顶点数组,以便每个顶点按faces 给出的顺序出现,包括所有重复项。例如,您的新位置数组将是 [0,0,0, 1,1,0 1,0,0 ...] 是向量 0,6,4 形成第一个三角形。 std::vectors 使这种重新排列变得容易编码。

最后一件事。法线数组没有位置数组那么大,但是 OpenGL 不支持混合索引。所以你必须复制一些法线,这样每个顶点都有一个位置和法线。

【讨论】:

  • 您好,感谢您的帮助!我设法让它绘制一个立方体,只是有时当我重新编译和运行时,它会绘制一个立方体,有时它不会。此外,对于 faces[],我实际上并没有在任何地方使用它,我还是 openGL 的新手,我只是想知道我必须把它放在哪里。我知道它在 glDrawElements 中使用,但我只能使用 glDrawArrays
  • 天哪,非常感谢!我设法让它正确显示一个立方体!你是救生员!
  • @LewisTracy 不用担心。很乐意提供帮助。
猜你喜欢
  • 1970-01-01
  • 2012-05-22
  • 2014-05-09
  • 2012-09-13
  • 2012-10-30
  • 2018-02-08
  • 1970-01-01
  • 2015-12-02
  • 1970-01-01
相关资源
最近更新 更多