如何在 glVertexPointer / glColorPointer / glNormalPointer 中使用自己的类
我有一个表示顶点的类,如下所示:
class Vertex
{
public:
Vertex(void);
~Vertex(void);
GLfloat x;
GLfloat y;
GLfloat z;
GLfloat r;
GLfloat g;
GLfloat b;
GLfloat nx;
GLfloat ny;
GLfloat nz;
Vertex getCoords();
Vertex crossProd(Vertex& b);
void normalize();
Vertex operator-(Vertex& b);
Vertex& operator+=(const Vertex& b);
bool operator==(const Vertex& b) const;
};
我按如下方式初始化我的 VBO:
glGenBuffers(2, buffers);
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glBufferData(GL_ARRAY_BUFFER, fVertices.size()*sizeof(Vertex), &(fVertices[0].x), GL_STATIC_DRAW);
glVertexPointer(3, GL_UNSIGNED_BYTE, sizeof(Vertex), BUFFER_OFFSET(0));
glColorPointer(3, GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(6*sizeof(GL_FLOAT)));
glNormalPointer( GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(3*sizeof(GL_FLOAT)));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[2]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, fIndices.size()*sizeof(GLushort), &fIndices[0], GL_STATIC_DRAW);
glIndexPointer(GL_UNSIGNED_SHORT, 0, BUFFER_OFFSET(0));
但是在绘制时,这一切都搞砸了。我认为这可能是因为我传递了错误的步幅和/或缓冲区偏移量。
奇怪的是,我正在尝试使用指针来查看地址是否匹配,试图自己弄清楚,我遇到了一些奇怪的事情:
如果我这样做:
GLfloat *test = &(fVertices[0]).x;
GLfloat *test2 = &(fVertices[0]).y;
那么
test + sizeof(GLfloat) != test2;
fVertices 是一个 std::vector 顺便说一句。
希望任何人都可以启发我有关传递给 gl*pointer 调用的内容。
I have a class representing a vertex as follows:
class Vertex
{
public:
Vertex(void);
~Vertex(void);
GLfloat x;
GLfloat y;
GLfloat z;
GLfloat r;
GLfloat g;
GLfloat b;
GLfloat nx;
GLfloat ny;
GLfloat nz;
Vertex getCoords();
Vertex crossProd(Vertex& b);
void normalize();
Vertex operator-(Vertex& b);
Vertex& operator+=(const Vertex& b);
bool operator==(const Vertex& b) const;
};
I initialize my VBO's as follows:
glGenBuffers(2, buffers);
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glBufferData(GL_ARRAY_BUFFER, fVertices.size()*sizeof(Vertex), &(fVertices[0].x), GL_STATIC_DRAW);
glVertexPointer(3, GL_UNSIGNED_BYTE, sizeof(Vertex), BUFFER_OFFSET(0));
glColorPointer(3, GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(6*sizeof(GL_FLOAT)));
glNormalPointer( GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(3*sizeof(GL_FLOAT)));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[2]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, fIndices.size()*sizeof(GLushort), &fIndices[0], GL_STATIC_DRAW);
glIndexPointer(GL_UNSIGNED_SHORT, 0, BUFFER_OFFSET(0));
But when drawing this is all messed up. It's probably because I pass the wrong stride and/or buffer offset I presume.
The strange thing is, I was experimenting with pointer to see if the adresses match, trying to figure it out myself, I encountered something odd:
If I do:
GLfloat *test = &(fVertices[0]).x;
GLfloat *test2 = &(fVertices[0]).y;
then
test + sizeof(GLfloat) != test2;
fVertices is a std::vector btw.
Hope that anyone can enlighten me about what to pass on to the gl*pointer calls.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
仅当该类是普通旧数据 (POD) 类型时,才能保证结构/类中数据的字节排列(C++ 认为它们相同)。在 C++0x 之前,POD 类型的规则非常严格。该类不能有任何类型的构造函数或析构函数。它也不能容纳非 POD 类型。它不能有虚函数。等等。
所以你需要删除构造函数和析构函数。
其次,你的偏移量是错误的。你的颜色是距离前面 3 个浮点,而不是 6 个。你似乎已经切换了你的颜色和法线。
This:
是指针算术。如果您有一个指向某种类型
T
的指针,则向该指针加 1 不会向该地址加 1。基本上,它的工作原理类似于数组访问。所以这是正确的:因此,如果您想在
test
之后获取浮点数,请向其添加 one,而不是浮点数的大小。就个人而言,我一直不明白为什么这么多 OpenGL 程序员喜欢将这些小顶点格式结构放在一起。顶点保存一定的数据排列。它们在当时看起来总是一个好主意,但当你必须改变它们时,一切都会崩溃。
从长远来看,完全不用为显式的“顶点”对象而烦恼要容易得多。只需拥有网格,其中包含它们所拥有的任何顶点数据。一切都应该在具有属性字节偏移量的内存线性数组中完成。这样,如果您需要插入另一个纹理坐标或需要法线或其他东西,则不必从根本上更改代码。只需修改字节偏移量,一切就可以了。
The byte arrangement of data in structs/classes (C++ considers them the same) is only guaranteed if that class is a plain-old-data (POD) type. Before C++0x, the rules for POD types were very strict. The class could not have constructors or destructors, of any kind. It also couldn't hold non-POD types. It cannot have virtual functions. And so on.
So you need to remove the constructor and destructor.
Secondly, your offsets are wrong. Your colors are 3 floats from the front, not 6. You seem to have switched your colors and normals.
This:
is pointer arithmetic. If you have a pointer to some type
T
, adding 1 to this pointer does not add 1 to the address. Basically, it works like array access. So this is true:So if you want to get the float after
test
, you add one to it, not the size of a float.On a personal note, I've never understood why so many OpenGL programmers love to put together these little vertex format structs. Where a vertex holds a certain arrangement of data. They always seem like a good idea at the time, but the moment you have to change them, everything breaks.
It's much easier in the long run not to bother with having explicit "vertex" objects at all. Simply have meshes, which have whatever vertex data they have. Everything should be done in a linear array of memory with byte offsets for the attributes. That way, if you need to insert another texture coordinate or need a normal or something, you don't have to radically alter code. Just modify the byte offsets, and everything works.