我正在为我的应用程序开发.obj加载器,为此,我设置了一个索引数组和一个顶点数组,并在运行时初始化它们。
这是结构的定义方式:
typedef struct {
float Position[3];
float Color[4];
float TexCoord[2];
} Vertex;
typedef struct {
GLuint v1;
GLuint v2;
GLuint v3;
} Face3D;
这就是数组在.h文件中的方式:
Vertex* VerticesArr;
Face3D* Faces;
但是当我启动它们时,我在屏幕上看不到任何内容,而不是使用这种方式:
const Vertex Vertices[] = {
{{1, -1, 0}, {1, 0, 0, 1},{0,0}},
{{1, 1, 0}, {0, 1, 0, 1},{0,0}},
{{-1, 1, 0}, {0, 0, 1, 1},{0,0}},
{{-1, -1, 0}, {0, 0, 0, 1},{0,0}}
};
const GLubyte Indices[] = {
0, 1, 2,
2, 3, 0
};
通过使用这些const数组,我得到了屏幕上的绘图。
我的问题是,使用索引和顶点数组是否可行? 我相信它似乎是错误的。
这就是我在前面介绍的两种方式下设置VBO的方法:
- (void)setupVBOs {
GLuint vertexBuffer;
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(VerticesArr), VerticesArr, GL_STATIC_DRAW);
GLuint indexBuffer;
glGenBuffers(1, &indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Faces), Faces, GL_STATIC_DRAW);
}
以及我使用绘图元素的方式:
glDrawElements(GL_POINTS, sizeof(Faces)/sizeof(Faces[0]), GL_UNSIGNED_INT, 0);
我确实检查了两个数组是否应该是init,而且确实如此。
这就是我为他们分配空间的方式:
// Allocate space for the Vertices array
NSLog(@"Size of vertice is: %lu",sizeof(Vertex));
VerticesArr = (Vertex*)(malloc(sizeof(Vertex) * vertexCombinations.count));
// Allocate space for the Faces
NSLog(@"Size of face is: %lu",sizeof(Face3D));
Faces = (Face3D*)(malloc(sizeof(Face3D)*faceCount));
答案 0 :(得分:2)
我看到的第一个问题是代码的这一部分:
- (void)setupVBOs {
GLuint vertexBuffer;
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(VerticesArr), VerticesArr, GL_STATIC_DRAW);
GLuint indexBuffer;
glGenBuffers(1, &indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Faces), Faces, GL_STATIC_DRAW);
}
创建常量数组时sizeof(Faces)
将返回数组的大小,但是当您动态分配它们时,sizeof(Faces)
将是指针的大小(通常为4个字节)。我看到的第二个问题是,在静态分配期间,您的隐私为GLUByte
,但在Face3D
中,它们为GLUInt
。不确定这是否是一个问题,但似乎可能是。
答案 1 :(得分:1)
潜在问题:
1)C不保证结构的紧密包装。所以例如编译器可能会查看你的Face3D
,发现它长12个字节,并决定将其填充到16个字节 - 每个结构在最后都有四个未使用的字节,因为这样做可能会使单个结构更快地读取。同样,它保留在结构中的各个项之间填充的权限。您使用的是原生大小的单位,因此填充不一定是可能的,但您的编译器保留添加它的权利,并依赖于紧密包装意味着依赖于未定义的行为。
2)sizeof(Faces)/sizeof(Faces[0])
- sizeof(struct Face3D)
与sizeof(GLuint)
的数量非常不同,所以即使您的结构紧密包装,这也是两段代码之间的差异。
您可以在运行时检查sizeof(struct Face3D) == sizeof(GLuint)*3
和等效测试。如果是这样,那么您可以将结构直接传递给glBufferData
。如果没有那么你可能只是通过glVertexAttribPointer
传递适当的步幅,具体取决于确切的填充,但更有可能你需要明确地序列化到非结构化数组以获得OpenGL的好处。