欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-05-28 12:53:28
...

目录

介绍

使用代码

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

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

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

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


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

(您需要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代表它:

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

要在此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圆。

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

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

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

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

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

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)

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

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

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

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)

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

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

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

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点相乘,以便能够根据相机角度移动对象(通过鼠标移动进行修改)。

相关标签: CSharp.NET