学习3D图形引擎中使用的基本数学

目录

介绍

使用代码

X旋转矩阵(XY平面旋转矩阵)

Y旋转矩阵(YZ平面旋转矩阵)

Z旋转矩阵(XZ平面旋转矩阵)

XYZ旋转矩阵(XY YZ XZ平面旋转矩阵)


(您需要Visual Studio来编译项目。)

介绍

本文将通过删除GPU层抽象并仅使用CPU来帮助您了解3D引擎中使用的3D数学。

而且,为什么不呢,要制作一个基于体素(voxel)3D引擎。

体素(voxel)只是空间中的一个点,就像构成材料的原子一样,这是我自己的定义,对于其他引擎,体素(voxel)定义为像素体积,就像在Minecraft/Roblox中一样,但我不使用此定义。

使用代码

首先,我们需要先问几个问题:

  • 什么是空间(space)
  • 什么是轴(axis)
  • 什么是维(dimension)
  • 什么是平面(plane)
  • 什么是三角函数(trigonometric functions)
  • 什么是向量(vector)
  • 什么是旋转矩阵(rotation matrix)
  • 什么是旋转(rotation)和平移(translation)

现在让我们为这些问题提供答案:

space是由点定义的,数学上由构成空间尺寸的唯一dimensions中的若干axes定域(plane2=2D空间形成)。

Trigonometric functionssin(θ)cos(θ)等函数,其中θ表示围绕轴的角度并在2D平面中绘制一个圆。

rotation matrix是由trigonometric functions组成的一组方程 

vector是空间中的方向(类似于GPS),是点通过rotation matrix转换(算术运算符)的结果。
该点由旋转矩阵驱动到空间中,以便到达trigo函数内部的角度所指定的方向。

1D space用一个方向上的单线axis表示:----------------------------

要在此轴上移动对象,公式为:

x'=Dot.x + x 向右移动

x'=Dot.x-x 向左移动

-3  -2  -1   0  +1  +2  +3
X--|---|---|---|---|---|---|--

translation在一行,1D空间中完成,因此我们可能在X-axis<font color="#007000" face=""Segoe UI",Arial,Sans-Serif">.</font>1  translation

2D space只是1D space另一条线在X-axis90°方向上,Y代表它:

要在此2D space中添加一个对象,我们需要为该对象的每个点设置2个坐标,然后移动该对象,我们像以前一样在x-axis上对translate添加了一个对象。

但是我们也可以围绕2 axis的中心旋转对象,为此,添加是不够的,我们需要调用专门用于rotation计算的数学运算符。

rotation是在平面2D space内完成的,因此,我们有1rotation可能围绕两个axis中心。

这些数学运算符被称为三角函数:sin()cos()占用两条线之间的角度:[中心,对象的点]x-axiscos() y-axissin()

在视觉上,我们在一个点0°x = 1y = 0),我们用+90°+逆时针的, -表示顺时针)rotation中心,结果是x = 0y = 1 

找到这个结果的演算是:

x' = x.cos(90) - y.sin(90)
y' = x.sin(90) + y.cos(90)

从头开始检索该方程式非常容易,这就是我所做的,而且令人惊讶的是,我已经看到该方程式是Z旋转矩阵的线性形式。

这是我的操作方式:

  • 我们有一个直径为82D XY圆。

  • 我们设置1个点,旋转它,然后尝试检索其新位置的方程式,一旦我们对几个不同的XY组合进行运算,我们将找到最终方程式。
  • 让我们从一个红点P(4,0)开始:

  • 现在我们旋转+ 90°(θ)的这一点,并尝试找到其新位置的方程,在视觉上找到的结果为P(0, 4)

X = sin(θ) = 1 ❌
X = cos(θ) = 0 ✔

Y = cos(θ) = 0 ❌
Y = sin(θ) = 1 ❌✔
Y = 4 × sin(θ) = 4 ✔
  • 因此,对于P(4, 0)θ= 90,我们有:
X = cos(θ)
Y = 4 × sin(θ)
  • 尝试对P(4, 0)的任何其他角度以及Y为零的不同X值(对此使用mathsisfun),您会发现相同的方程式,对于X4x,但不会改变最终方程式:
X' = 4 × cos(θ) = X × cos(θ)
Y' = 4 × sin(θ) = X × sin(θ)
  • 现在我们将红点设置为P(0, 4)

  • 我们将此点旋转+ 90°,在视觉上结果为P(-4, 0)

X = cos(θ) = 0 ❌
X = sin(θ) = 1 ❌✔
X = 4 × -sin(θ) = -4 ✔

Y = sin(θ) = 1 ❌
Y = cos(θ) = 0 ✔
  • 因此,对于P(0, 4)θ= 90,我们有:
X = 4 × -sin(θ)
Y = cos(θ)
  • 尝试使用P(0, 4)的任何其他角度以及X值为零的不同Y值,您会发现相同的方程式,其中Y的角度为,但不会改变最终方程式:
X = 4 × -sin(θ) = Y × -sin(θ)
Y = 4 ×  cos(θ) = Y ×  cos(θ)
  • 现在让我们总结一下:
_____ ________________ ________________
|     |                |                |
|     |     P(X, 0)    |     P(0, Y)    |
|_____|________________|________________|
|     |                |                |
|  θ  | X = X × cos(θ) | X = Y × -sin(θ)|
|     | Y = X × sin(θ) | Y = Y ×  cos(θ)|
|_____|________________|________________|

如我们所见,不同的XY组合生成不同的方程式,因此让我们对设置为0以上的XY进行操作:

  • 因此,我们将红点设置为P(2, 4×√3/2)

  • 现在我们将这个点旋转+ 30°,在视觉上找到的结果是P(0, 4)

X = sin(θ) = 0.5  ❌
X = cos(θ) = √3/2 ❌

Y = sin(θ) = 0.5  ❌
Y = cos(θ) = √3/2 ❌

我们有一个问题,三角函数都不起作用,因此我们需要在仍然使用sin()cos()的同时找到解决方案。

让我们回顾一下之前找到的等式:

_____ ________________ ________________
|     |                |                |
|     |     P(X, 0)    |     P(0, Y)    |
|_____|________________|________________|
|     |                |                |
|  θ  | X = X × cos(θ) | X = Y × -sin(θ)|
|     | Y = X × sin(θ) | Y = Y ×  cos(θ)|
|_____|________________|________________|

这些是我们拥有的奇特方程,如果我们有P(X, Y),它应该是两个方程的混合:

X' = X × cos(θ) X = Y × -sin(θ)
Y' = X × sin(θ) Y = Y ×  cos(θ)

X' = X × cos(θ)     Y × -sin(θ)
Y' = X × sin(θ)     Y ×  cos(θ)

让我们看看添加是否有效:

X' = X × cos(θ) + Y × -sin(θ)
     X × cos(θ) - Y ×  sin(θ)
Y' = X × sin(θ) + Y ×  cos(θ)

X = 2 × cos(θ) - 4×√3/2 × sin(θ) = 0 ✔
Y = 2 × sin(θ) + 4×√3/2 × cos(θ) = 4 ✔

完美,此方程式有效,因此最后,XY平面上的最终方程式为:

X' = X × cos(θ) - Y × sin(θ)
Y' = X × sin(θ) + Y × cos(θ)

但是,让我们消除对P(X, 0)P(0, Y)的疑问:

  • 对于P(4, 0),我们应用+ 90°旋转,在视觉上找到的结果为P(0, 4)
X' = 4 × cos(θ) - 0 ×  sin(θ) = 0 ✔
Y' = 4 × sin(θ) + 0 ×  cos(θ) = 4 ✔
  • 对于P(0, 4),我们应用+ 90°旋转,在视觉上找到的结果是P(-4, 0)
X' = 0 × cos(θ) - 4 ×  sin(θ) = -4 ✔
Y' = 0 × sin(θ) + 4 ×  cos(θ) =  0 ✔

很好,一切正常,您可以使用自己的XY和角度值测试此方程式,以验证其是否正常运行。

这个方程是还令人惊讶地(如前面所述)的只是线性形式Z旋转(XZ平面旋转矩阵) 矩阵,乘以点叫vector,其中Z是两者axis的中心)

Rotation matrix on z:                                 Vector:
 _______________ _______________ _______________       _______________
|               |               |               |     |               |
|    cos(θz)    |   -sin(θz)    |       0       |     |       x       |
|_______________|_______________|_______________|     |_______________|
|               |               |               |     |               |
|    sin(θz)    |    cos(θz)    |       0       |  ×  |       y       |
|_______________|_______________|_______________|     |_______________|
|               |               |               |     |               |
|       0       |       0       |       1       |     |       z       |
|_______________|_______________|_______________|     |_______________|

3D space2D space与另一个叫Z轴,并在XY计平面90°上。

可能的移动是translation(加法方程)rotation(sincos)

但现在rotations的次数是3,围绕Z,围绕X和围绕Y

因为如前所述,旋转是在2D平面上进行的,但是现在我们混合使用3x 2D space/plane

  • X/YY/ZZ/X

因此,我们需要收集所有rotation矩阵并使用它们。

X旋转矩阵(XY平面旋转矩阵)

_______________ _______________ _______________
|               |               |               |
|       1       |       0       |       0       |
|_______________|_______________|_______________|
|               |               |               |
|       0       |    cos(θx)    |   -sin(θx)    |
|_______________|_______________|_______________|
|               |               |               |
|       0       |    sin(θx)    |    cos(θx)    |
|_______________|_______________|_______________|

Y旋转矩阵(YZ平面旋转矩阵)

_______________ _______________ _______________
|               |               |               |
|    cos(θy)    |       0       |   -sin(θy)    |
|_______________|_______________|_______________|
|               |               |               |
|       0       |       1       |       0       |
|_______________|_______________|_______________|
|               |               |               |
|    sin(θy)    |       0       |    cos(θy)    |
|_______________|_______________|_______________|

Z旋转矩阵(XZ平面旋转矩阵)

_______________ _______________ _______________
|               |               |               |
|    cos(θz)    |   -sin(θz)    |       0       |
|_______________|_______________|_______________|
|               |               |               |
|    sin(θz)    |    cos(θz)    |       0       |
|_______________|_______________|_______________|
|               |               |               |
|       0       |       0       |       1       |
|_______________|_______________|_______________|

但是我们有一个问题,如果这样做,我们将无法一起围绕XYZ axis旋转一个对象,它是一个axis 上的rotation ,其他角度设置为,因为它们不在所选矩阵中。

为了解决这个问题,我们需要通过将XYZ矩阵相乘来形成1个单个矩阵(mul的顺序问题)。

XYZ旋转矩阵(XY YZ XZ平面旋转矩阵)

______________________________ ______________________________ ____________________
|                              |                              |                    |
|      cos(θy) × cos(θz)       |      cos(θy) × -sin(θz)      |      -sin(θy)      |
|______________________________|______________________________|____________________|
|                              |                              |                    |
| -sin(θx) × sin(θy) × cos(θz) | sin(θx) × sin(θy) × sin(θz)  | -sin(θx) × cos(θy) |
|    + cos(θx) × sin(θz)       |     + cos(θx) × cos(θz)      |                    |
|______________________________|______________________________|____________________|
|                              |                              |                    |
| cos(θx) × sin(θy) × cos(θz)  | cos(θx) × sin(θy) × -sin(θz) | cos(θx) × cos(θy)  |
|    + sin(θx) × sin(θz)       |    + sin(θx) × cos(θz)       |                    |
|______________________________|______________________________|____________________|

现在,我们只需要将这个rotation matrix(基于对象的角度)乘以物体的vector点,就可以在XYZ axes周围对物体进行rotate

Obj Vec:    Rotation Matrix:
 _____     ______________________________ ______________________________ ____________________
|     |   |                              |                              |                    |
|  x  |   |      cos(θy) × cos(θz)       |      cos(θy) × -sin(θz)      |      -sin(θy)      |
|_____|   |______________________________|______________________________|____________________|
|     |   |                              |                              |                    |
|  y  | × | -sin(θx) × sin(θy) × cos(θz) | sin(θx) × sin(θy) × sin(θz)  | -sin(θx) × cos(θy) |
|     |   |    + cos(θx) × sin(θz)       |     + cos(θx) × cos(θz)      |                    |
|_____|   |______________________________|______________________________|____________________|
|     |   |                              |                              |                    |
|  z  |   | cos(θx) × sin(θy) × cos(θz)  | cos(θx) × sin(θy) × -sin(θz) | cos(θx) × cos(θy)  |
|     |   |    + sin(θx) × sin(θz)       |    + sin(θx) × cos(θz)       |                    |
|_____|   |______________________________|______________________________|____________________|

现在快要完成了,我们需要创建一个摄像机以能够导航到场景中。

相机由3 vectors定义:ForwardRight Up

X  Y  Z
Right/Left       (1, 0, 0)
Up/Down          (0, 1, 0)
Forward/Backward (0, 0,-1)

然后,将这3vectors分别乘以rotation matrix(基于相机的角度),因为我们需要它们中的每一个都能够移动相机Forward/Backward/Right/Left/Up/Down

并且,将结果添加到对象向量。

例如:如果按W,使用Forward vector
        如果按S,使用-Forward vector
        如果按D,使用Right   vector

Object Vector:           Forward Vector:    
 __________________       __________________
|                  |     |                  |
|         x        |     |         x        |
|__________________|     |__________________|
|                  |     |                  |
|         y        |  +  |         y        |
|__________________|     |__________________|
|                  |     |                  |
|         z        |     |         z        |
|__________________|     |__________________|

Object Vector:           Forward Vector:         
 __________________       __________________
|                  |     |                  |
|         x        |     |         x        |
|__________________|     |__________________|
|                  |     |                  |
|         y        |  -  |         y        |
|__________________|     |__________________|
|                  |     |                  |
|         z        |     |         z        |
|__________________|     |__________________|

Object Vector:           Right Vector:
 __________________       __________________
|                  |     |                  |
|         x        |     |         x        |
|__________________|     |__________________|
|                  |     |                  |
|         y        |  +  |         y        |
|__________________|     |__________________|
|                  |     |                  |
|         z        |     |         z        |
|__________________|     |__________________|

最后,我们将另一个rotation matrix(基于相机的角度)与来自对象的每个vector点相乘,以便能够根据相机角度移动对象(通过鼠标移动进行修改)。

发布了69 篇原创文章 · 获赞 139 · 访问量 45万+

猜你喜欢

转载自blog.csdn.net/mzl87/article/details/104407393