obj loader在c ++ OpenGL中无法正确显示

时间:2014-08-26 14:03:56

标签: c++ opengl

我的wavefront .obj加载器存在问题,它没有显示我想要显示的内容。我想让它显示一个立方体,但我一直这样: enter image description here

这是我的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

显示:

输入

enter image description here

这是我的绘图功能: 我不太清楚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;
}

1 个答案:

答案 0 :(得分:3)

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

  

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

希望修复程序非常简单:faces[tempSize] = *i - 1;

[修改]
你的绘制调用指定了14个顶点,但你有12个三角形,所以应该绘制36个。amountOfFaces听起来应该是tempIndices.size()/3

您的向量应该是引用以避免副本,并且使用单个faces填充memcpy等会更快。例如:memcpy(faces, &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::vector使这种重新排列变得容易编码。

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