我应该以什么顺序将我的顶点发送到OpenGL以进行剔除

ult*_*tus 27 c++ opengl sdl

我正在学习一个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);
Run Code Online (Sandbox Code Playgroud)

然而,这绝对是错误的,因为当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;

}
Run Code Online (Sandbox Code Playgroud)

gen*_*ult 109

默认情况下?按逆时针顺序.

考虑面向相机的三角形:

A
|\
| \
|  \
B---C
Run Code Online (Sandbox Code Playgroud)

A-> B-> C将是正面(逆时针顺序),A-> C-> B将是朝后的(顺时针顺序).

您可以通过以下方式更改OpenGL认为"面向前方"的方式glFrontFace():

多边形到窗口坐标的投影被称为顺时针缠绕,如果一个假想的对象跟随从其第一个顶点,第二个顶点等到其最后一个顶点的路径,最后回到它的第一个顶点,则移动到围绕多边形内部的顺时针方向.如果跟随相同路径的假想物体围绕多边形内部沿逆时针方向移动,则称多边形的绕组是逆时针方向. glFrontFace指定窗口坐标中顺时针缠绕的多边形或窗口坐标中的逆时针缠绕是否为正面.传递GL_CCWmode选择逆时针多边形为面向前方的; GL_CW选择顺时针多边形作为正面.

默认情况下,逆时针多边形被视为面向前方.

要订购顶点,请考虑理想的立方体:

  6---7
 /|  /|
2---3 |
| 4-|-5
|/  |/ 
0---1
Run Code Online (Sandbox Code Playgroud)

对于每张脸,在心理上旋转它以面向相机(你的大脑):

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
Run Code Online (Sandbox Code Playgroud)

然后你可以用右眼逆时针顺序读取四边形或三角形对:

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
Run Code Online (Sandbox Code Playgroud)

  • 它是否必须从特定的顶点开始? (2认同)

小智 6

我学会了另一个经验法则(字面意思)来确定被称为"右手规则"的顶点顺序.
想象一下你的开放手(右)在立方体内,拇指指向立方体的中心.如果然后将手握成拳头,手指将以正确的顺序通过顶点.因为你正在使用你的右手,所以它被称为"右手规则".

相反,如果您从左手开始并将拇指指向远离立方体的中心,您的手指将再次以正确的顺序扫描顶点.这被称为"左手规则"(惊喜).

这两种方法都可以为您提供逆时针排序.对于顺时针排序,只需使用相反的手.

  • 这是一个陈旧的答案,但称这是右手规则可能会引起很大的混乱.在处理3D欧几里德几何时,右手规则几乎总是指使用右手拇指,食指和中指来记住RH坐标系中轴的配置,例如数学和OpenGL中的典型. (2认同)