我正在学习 3d opengl,进展相当顺利,目前我有一个很好的移动相机和一些简单的立方体对象。目前使用顶点数组,但我在这里很快就切换到 VBO。我只是想启用剔除,但是我不确定应该以什么顺序指定我的顶点,现在这就是我正在做的:
void cube::update_verts(){
GLushort cur=0;
///back face
verts[cur++]=x; verts[cur++]=y; verts[cur++]=z;
verts[cur++]=x+sx; verts[cur++]=y; verts[cur++]=z;
verts[cur++]=x+sx; verts[cur++]=y+sy; verts[cur++]=z;
verts[cur++]=x; verts[cur++]=y+sy; verts[cur++]=z;
///right face
verts[cur++]=x+sx; verts[cur++]=y+sy; verts[cur++]=z;
verts[cur++]=x+sx; verts[cur++]=y; verts[cur++]=z;
verts[cur++]=x+sx; verts[cur++]=y; verts[cur++]=z+sz;
verts[cur++]=x+sx; verts[cur++]=y+sy; verts[cur++]=z+sz;
///top face
verts[cur++]=x+sx; verts[cur++]=y+sy; verts[cur++]=z;
verts[cur++]=x; verts[cur++]=y+sy; verts[cur++]=z;
verts[cur++]=x; verts[cur++]=y+sy; verts[cur++]=z+sz;
verts[cur++]=x+sx; verts[cur++]=y+sy; verts[cur++]=z+sz;
///front face
verts[cur++]=x; verts[cur++]=y; verts[cur++]=z+sz;
verts[cur++]=x+sx; verts[cur++]=y; verts[cur++]=z+sz;
verts[cur++]=x+sx; verts[cur++]=y+sy; verts[cur++]=z+sz;
verts[cur++]=x; verts[cur++]=y+sy; verts[cur++]=z+sz;
///bottom face
verts[cur++]=x+sx; verts[cur++]=y; verts[cur++]=z;
verts[cur++]=x; verts[cur++]=y; verts[cur++]=z;
verts[cur++]=x; verts[cur++]=y; verts[cur++]=z+sz;
verts[cur++]=x+sx; verts[cur++]=y; verts[cur++]=z+sz;
///left face
verts[cur++]=x; verts[cur++]=y+sy; verts[cur++]=z;
verts[cur++]=x; verts[cur++]=y; verts[cur++]=z;
verts[cur++]=x; verts[cur++]=y; verts[cur++]=z+sz;
verts[cur++]=x; verts[cur++]=y+sy; verts[cur++]=z+sz;
}
///Drawing Code:
glVertexPointer(3,GL_FLOAT,0,object.verts);
glColorPointer(3,GL_UNSIGNED_BYTE,0,object.colors);
glDrawArrays(GL_QUADS,0,6*4);
但这绝对是错误的,因为当我
glEnable(GL_CULL_FACE);
时,我的立方体没有显示正确的面(如下所示)。
正常
问题儿童
这两个图像都启用了剔除功能。
我应该按什么顺序指定顶点?
(编辑)更新的工作功能:
void cube::update_verts(){
GLushort cur=0;
///top face
verts[cur++]=x; verts[cur++]=y+sy; verts[cur++]=z;
verts[cur++]=x; verts[cur++]=y+sy; verts[cur++]=z+sz;
verts[cur++]=x+sx; verts[cur++]=y+sy; verts[cur++]=z+sz;
verts[cur++]=x+sx; verts[cur++]=y+sy; verts[cur++]=z;
///bottom face
verts[cur++]=x; verts[cur++]=y; verts[cur++]=z;
verts[cur++]=x+sx; verts[cur++]=y; verts[cur++]=z;
verts[cur++]=x+sx; verts[cur++]=y; verts[cur++]=z+sz;
verts[cur++]=x; verts[cur++]=y; verts[cur++]=z+sz;
///left face
verts[cur++]=x; verts[cur++]=y; verts[cur++]=z;
verts[cur++]=x; verts[cur++]=y; verts[cur++]=z+sz;
verts[cur++]=x; verts[cur++]=y+sy; verts[cur++]=z+sz;
verts[cur++]=x; verts[cur++]=y+sy; verts[cur++]=z;
///right face
verts[cur++]=x+sx; verts[cur++]=y; verts[cur++]=z;
verts[cur++]=x+sx; verts[cur++]=y+sy; verts[cur++]=z;
verts[cur++]=x+sx; verts[cur++]=y+sy; verts[cur++]=z+sz;
verts[cur++]=x+sx; verts[cur++]=y; verts[cur++]=z+sz;
///front face
verts[cur++]=x; verts[cur++]=y; verts[cur++]=z+sz;
verts[cur++]=x+sx; verts[cur++]=y; verts[cur++]=z+sz;
verts[cur++]=x+sx; verts[cur++]=y+sy; verts[cur++]=z+sz;
verts[cur++]=x; verts[cur++]=y+sy; verts[cur++]=z+sz;
///back face
verts[cur++]=x; verts[cur++]=y; verts[cur++]=z;
verts[cur++]=x; verts[cur++]=y+sy; verts[cur++]=z;
verts[cur++]=x+sx; verts[cur++]=y+sy; verts[cur++]=z;
verts[cur++]=x+sx; verts[cur++]=y; verts[cur++]=z;
}
默认?按逆时针顺序。
考虑一个面向相机的三角形:
A
|\
| \
| \
B---C
A->B->C 为正面(逆时针顺序),A->C->B 为背面(顺时针顺序)。
glFrontFace()
: 更改 OpenGL 考虑“正面”的方式
据说多边形到窗口坐标的投影有 顺时针缠绕,如果一个假想的物体沿着从它的路径开始的路径 第一个顶点,第二个顶点,依此类推,直到最后一个顶点,并且 最后回到第一个顶点,沿顺时针方向移动约 多边形的内部。多边形的缠绕据说是 如果假想的物体沿着相同的路径移动,则逆时针移动 以围绕多边形内部的逆时针方向。
指定多边形是否顺时针缠绕 窗口坐标,或在窗口坐标中逆时针缠绕, 被认为是正面的。将glFrontFace
传递到GL_CCW
选择 逆时针多边形为正面;mode
选择顺时针方向 多边形作为正面。GL_CW
默认情况下,逆时针多边形被视为正面。
为了对顶点进行排序,请考虑一个理想的立方体:
6---7
/| /|
2---3 |
| 4-|-5
|/ |/
0---1
对于每张脸,在心里旋转它以面对相机(你的心灵之眼):
Sides:
2---3 3---7 7---6 6---2
| | | | | | | |
| | | | | | | |
0---1 1---5 5---4 4---0
Bottom/Top:
0---1 6---7
| | | |
| | | |
4---5 2---3
然后您可以按正确的逆时针顺序直观地读出四边形或三角形对:
2---3 3 2---3
| | becomes /| and | /
| | / | |/
0---1 0---1 0
Triangles 0-1-3 and 0-3-2
Quad 0-1-3-2
从哪个顶点开始三角形/四边形并不重要,例如第一个三角形
0-1-3
、1-3-0
和 3-0-1
都是同样有效的正面三角形。
我学到了另一个确定顶点顺序的经验法则(字面意思),称为“右手法则”。
想象一下你张开的手(右)在立方体内部,拇指指向立方体的中心。如果您随后将手握成拳头,您的手指将以正确的顺序经过顶点。由于您使用的是右手,因此称为“右手法则”。
相反,如果您从左手开始并将拇指远离立方体的中心,您的手指将再次以正确的顺序扫过顶点。这被称为“左手法则”(惊喜)。
这两种方法都可以为您提供逆时针顺序。对于顺时针顺序,只需使用另一只手即可。
这是一个嵌套的立方体。使用 @genpfault 对立方体面进行编号的内部立方体和外部立方体。数据采用 *.ply(3D 点云)格式,还包含 RGB 颜色数据。
如果复制并粘贴到文件中,请务必检查每行的换行符终止符。我在这里添加了 2 个空格,因为这是显示新行所需的。
层数 格式 ascii 1.0
元素顶点 16
属性 float32 x
属性 float32 y
属性 float32 z
属性 uchar 红
房产 uchar 绿色
属性 uchar 蓝色
元素面24
属性列表 uint8 int32 vertex_indices
结束标题
-4.00 -4.00 4.00 255 0 0
4.00 -4.00 4.00 255 0 0
4.00 4.00 4.00 255 0 0
-4.00 4.00 4.00 255 0 0
-4.00 -4.00 -4.00 255 0 0
4.00 -4.00 -4.00 255 0 0
-4.00 4.00 -4.00 255 0 0
4.00 4.00 -4.00 255 0 0
-6.00 -6.00 6.00 255 255 255
6.00 -6.00 6.00 255 255 255
-6.00 6.00 6.00 255 255 255
6.00 6.00 6.00 255 255 255
-6.00 -6.00 -6.00 255 255 255
6.00 -6.00 -6.00 255 255 255
-6.00 6.00 -6.00 255 255 255
6.00 6.00 -6.00 255 255 255
3 0 1 2
3 1 3 2
3 1 5 3
3 5 7 3
3 5 4 7
3 4 6 7
3 4 0 6
3 0 2 6
3 4 5 0
3 5 1 0
3 2 3 6
3 3 7 6
3 8 9 10
3 9 11 10
3 9 13 11
3 13 15 11
3 13 12 15
3 12 14 15
3 12 8 14
3 8 10 14
3 12 13 8
3 13 9 8
3 10 11 14
3 11 15 14