美文网首页
OpenGL ES 点、顶点、三角形

OpenGL ES 点、顶点、三角形

作者: Visitor | 来源:发表于2017-07-29 10:43 被阅读450次

点或顶点

3D图像的最小单位称为点(point)或者顶点(vertex)。它们代表三维空间中的一个点并用来建造更复杂的物体。多边形就是由点构成,而物体是由多个多边形组成。尽管通常OpenGL支持多种多边形,但OpenGL ES只支持三边形(即三角形)

如果你回忆高中学过的几何学,你可能会记得所谓的笛卡尔坐标。基本概念是在空间中任选一点,称作原点。然后你可以通过参照原点并使用三个代表三维的数值指定空间中的任意一点,坐标是由三个想象的通过原点线表示。从左至右的想象直线叫x-轴。沿着x-轴从左至右数值变大,向左移动数值变小。原点左方x为负值,右边为正直。另外两轴同理。沿y轴向上,y值增加,向下y值减小。原点上方y为正,原点下方为负。对于z轴,当物体离开观察者,数值变小,向观察者移动(或超出观察者),数值变大。原点前方z值为正,原点之后为负。见下图

image.png

iPhone上另一种绘图框架Core Graphics 使用了稍微不同的坐标系统,当向屏幕上方移动时y值减小,而向下移动y值增加。

沿各轴增加或减小的数值是以任意刻度进行的,他们不代表任何真实单位,如英尺,英寸或米等。你可以选择任何对你的程序有意义的刻度。如果你想设计的游戏以英尺为单位,你可以那样做。如果你希望单位为毫米,同样可行。OpenGL不管它对最终用户代表什么,只是将它作为单位处理,保证它们具有相同的距离。

由于任何物体在三维空间中的方位可以由三个数值表示,物体的位置通常在OpenGL中由使用一个三维数组的三个GLfloat变量表示,数组中的第一项(索引0)为x位置,第二项(索引1)为y位置,第三项(索引2)为z位置。下面是一个创建OpenGL ES顶点的简单例子:

GLfloat vertex[3];
vertex[0] = 10.0;    // x
vertex[1] = 20.29;  // y
vertex[2] = -112.02 // z

在OpenGL ES中,通常将场景中所有构成所有或部分物体的提交为顶点数组。一个顶点数组是包括场景中部分或所有顶点数据的简单数组。我将在系列的下一篇教程中讨论,有关顶点数组要记住的是它们的大小是基于呈现的顶点数乘以三(三维空间绘图)或二(二维空间绘图)。所以一个包含六个三维空间的三角形的顶点数组由54个GLfloat组成,因为每个三角形有三个顶点,而每个顶点有三个坐标,即: 6 * 3 * 3 = 54。

处理所有这些GLfloat是很痛苦是事情。幸运的是,有一个容易的方法。我们可以定义一个数据结构来保存多个顶点,像这样:

typedef struct {
GLfloat x;
GLfloat y;
GLfloat z;
} Vertex3D;

通过这样做,我们的代码可读性更强:

Vertex3D vertex;
vertex.x = 10.0;
vertex.y = 23.99;
vertex.z = -22.32;

现在由于Vertex3D由三个GLfloat组成,向Vertex3D传递指针与传递一个包含三个GLfloat的数组的指针完全一样。对于电脑而言毫无分别:两者具有同样的尺寸和同样的字节数以及OpenGL需要的同样的顺序。将数据分组到数据结构只是让程序感到更容易。还有一个内联函数用于创建单个顶点:

static inline vertex3D Vertex3DMake (CGFloat inX, CGFloat inY, CGFloat inZ) {
Vertex3D ret;
ret.x = inX;
ret.y = inY;
ret.z = inZ;
return ret;
}

如果你回忆起几何学的内容,你会知道空间中两点间的举例是使用线面公式计算的:


image.png

我们可以在一个简单的内联函数中实现这个公式来计算三维空间中任何两点间的直线距离:

static inline GLfloat Vertex3DCalculateDistanceBetweenVertices(Vertex3D first, Vertex3D second) {
GLfloat detaX = second.x - first.x;
GLfloat deltaY = second.y - first.y;
GLfloat deltaZ = second.z - first.z;
return sqrtf(deltaX*deltaX + deltaY*deltaY + deltaZ * deltaZ);
};

三角形

由于OpenGL ES进支持三角形,因此我们可以通过创建一个数据结构将三个顶点组合成一个三角形物体。

typedef struct {
Vertex3D v1;
Vertex3D v2;
Vertex3D v3;
} Triangle3D;

一个Triangle3D实际上与一个九个GLfloat构成的数组是完全一样的,因为我们通过顶点和三角形而不是GLfloat数组来构建物体,所以它能帮助我们更容易地处理我们的代码。
然而关于三角形你需要知道更多的事情。在OpenGL 中由一个概念叫卷绕(winding),它表示顶点绘制的次序是重要的。不像真实世界中的物体,OpenGL中的多边形通常都不会有两面。它们只有一面,被当做front face(前面),三角形只有其front face面对观察者时才可见。可以设置OpenGL将多边形作为两面处理,但默认状态下,三角形只有一个可见面。通过知道哪一个面是多边形的前面或可见面,才能使OpenGL只做一半的计算。
尽管有时多边形也可以独立存在,需要绘制其背面,但通常三角形是一个大物体的一部分,其面对物体内部的一面永远也不可见。不被绘制的一面称为backface(背面),OpenGL 是通过观察顶点的绘制次序来确定front face 和 backface的。以反时针次序绘制顶点的构成的面是frontface(默认,可以改变)。

由于OpenGL可以很容易确定哪个三角形对用户可见,所以它使用了一种称为Backface Culling(隐面消除)的技术来避免绘制视窗中多边形的不可见面。

image.png

上图中,左边青色的三角形是backface,因此将不可见。而右方的三角形是frontface,所以将被绘制。

本文参考了《OpenGL ES从零开始系列》一书

相关文章

网友评论

      本文标题:OpenGL ES 点、顶点、三角形

      本文链接:https://www.haomeiwen.com/subject/ikqqlxtx.html