我从头开始,谈直角三角形和右手法则,已经如何通过循环,通过遍历三角形来判断 gluLookAt() 函数.
直角三角形
不,我不会向你解释。我需要你知道什么是三角形的直角,斜边是什么,哪些相反。以防万一,在你的世界里,你可以使用不同的术语,我在这里就是对着图片来解释下。
我相信,在北美,他们称一个直角三角形为一个点。这个是术语的差异,我想避免这点。让我们进入例子。
我不想再解释这些,我只是提醒你,你在高中数学里学过它们。如果忘记了,那是因为它们不适合你。
任何一方的长度可以算出其他的一方。这很容易:
Hypotenuse: hypotenuse2 = adjacent2 + opposite2
in C: hypoenuse = sqrt(adjacent*adjacent + opposite*opposite);
Adjacent length: cosine (?) * hypotenuse.
in C: adjacent = cos(angleInRadians) * hypotenuse;
Opposite Length: sine(?) * hypotenuse
in C: oppositeLength = sin(angleInRadians) * hypotenuse;
首先要记住的是,在c语言的函数里,我们需要关注的是弧度而不是度数。也不要担心弧度如何计算,只要记住两者的关系和下面的两个宏。
#define DEGREES_TO_RADIANS(__ANGLE) ((__ANGLE) / 180.0 * M_PI)
#define RADIANS_TO_DEGREES(__RADIANS) ((__RADIANS) * 180 / M_PI)
你可以用最简单的方式来记住弧度和度数的关系。我们都知道360度事一个圆,也就是2*pi是一个圆。或者1个pi是一个半圆。
通过GCC数学库, M_PI在math.h文件中被定义为3.14。这不是真正的c标准。C的标准是不允许定义pi的。你应该从你的硬件中读取,这样才更准确。在我多年的编程经历里,我从来没有发现一个,我需要的值,但是没有定义的。
如果你不记得什么是sin(),cos()和tan(),不要担心背后的理论。这就像驾驶一辆车,你不需要知道内燃机是如何工作的,你只需要知道如何使用它。
从这里返回图形编程
记得在过去的教程里,我讨论过如何在3d中移动和旋转。我说这就像画一个圆圈。让我更详细的解释下如何画一个圆圈。
这里是一个具有2圆点图片绘制圆。
你注意到了吗?再仔细看看,如果你还没有看到它。
是的,这是个直角三角形。
因此,我们可以绘制一个知道半径和角度的任意一点。因此,我们现在实际上是画了一个圆圈。我们需要解释的就是x和y.
要绘制一个圆,我们知道斜边长度,因为这是我们圆的半径。结合上面的函数和蓝色的三角形,我们知道了x坐标,就可以简单的知道是相邻的边并且y是对面的边。
当然,相邻边和对角边因为每个像素的移动而变化,但我们并不需要关心。该代码绘制一个圆就是:
for (angle = 0; angle < 2*M_PI; angle += 0.01) {
point[0] = RADIUS * cos(angle);
point[1] = RADIUS * sin(angle);
glDrawArrays(GL_POINTS, 0, 1);
}
需要记得是,sin和cos里面是弧度而不是角度。这里有2*pi的弧度,就是360度。越细的循环,那么将得到更圆滑的圆。在大多数情况下,你可以使用短线来代替。
来到最后的教程
好的。记得我说过,使用glLookAt可以看到3d世界的任意点?我说这就像画一个圆圈。
现在,如果用户执行反时针旋转,那么视图看起来是这样的。
我相信你知道的。直角三角型绘制的一个圆。
所以,如果你还记得。我们是从Look From来看的。我们的起点没有改变,我们只会改变我们看的方向,我们在旋转。
这个代码就是:
facing[0] = position[0] + cos(-TURN_SPEED)*vector[0] -
sin(-TURN_SPEED)*vector[2];
facing[2] = position[2] + sin(-TURN_SPEED)*vector[0] +
cos(-TURN_SPEED)*vector[2];
这个facing的值就是我们看向那里的点。这个点就在这个圆上。这个position的值就是我们观察的起点。它实际上比这个复杂,因为它在一个3d世界里,而不是2d的。我没有计算y的坐标,因为我假设它是固定的。我只计算了x和z的坐标。