如何在glVertexPointer / glColorPointer / glNormalPointer中使用自己的类

时间:2011-08-19 00:42:47

标签: c++ opengl

我有一个表示顶点的类,如下所示:

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 btw。

希望任何人都能告诉我传递给gl *指针调用的内容。

1 个答案:

答案 0 :(得分:4)

只有当该类是普通旧数据(POD)类型时,才能保证结构/类中数据的字节排列(C ++认为它们相同)。在C ++ 0x之前,POD类型的规则非常严格。该类不能有任何类型的构造函数或析构函数。它也无法容纳非POD类型。它不具备虚拟功能。等等。

所以你需要删除构造函数和析构函数。

其次,你的抵消是错误的。你的颜色是前面的3个花车,而不是6个。你似乎已经改变了你的颜色和法线。


此:

test + sizeof(GLfloat) != test2;

是指针算术。如果您有指向某个类型T的指针,则向该指针添加1不会将1添加到该地址。基本上,它像数组访问一样工作。所以这是真的:

T *p = ...;
&p[1] == p + 1;

因此,如果您希望在test之后获得浮动,则向其添加一个,而不是浮动的大小。


就个人而言,我从未理解为什么这么多OpenGL程序员喜欢将这些小顶点格式结构组合在一起。顶点保持某种数据排列的位置。当时它们似乎总是一个好主意,但是当你必须改变它们时,一切都会破裂。

从长远来看,更容易完全没有明确的“顶点”对象。只需要网格,它们具有任何顶点数据。一切都应该在线性内存数组中完成,并为属性提供字节偏移。这样,如果您需要插入另一个纹理坐标或需要法线或其他东西,您不必从根本上改变代码。只需修改字节偏移量,一切正常。