14,392,424 members

# Learning Basic Math Used In 3D Graphics Engines

Rate this:
13 Dec 2019CPOL
Math explanation and game engine coding.

(You need Visual Studio to compile the project.)

## Introduction

This article will help you to understand the 3D math used in 3D engines, by removing the GPU layer abstraction and using only the CPU.

And, why not, to make a 3D engine based on voxels.

A voxel is just a point within a space, like an atom that composes the material, it's my own definition, for other engines, voxels are defined as volume of pixels, like in Minecraft/Roblox and I don't use this definition for my engine.

Also, this 3D engine does not use matrices calculations, it uses the linear equation. I do that just because I don't like matrices, it's out of my understanding of math concept.

## Background

This article was possible with my wish (2010) to see a game with texture and object built only with voxel.

## Using the Code

First of all, we need to ask few questions before:

• What is a space?
• What is an axis?
• What is a plane?
• What is a dimension?
• What are trigonometric functions?
• What is a vector?
• What is a matrix?
• What is a rotation and translation?

Now let's give answers to these questions:

A `space` is defined by a number of `axes `in unique directions that form the `dimensions `of the space.

A plane is formed by 2 axes/2D space.

And to form an `axis`, we use mathematical equations as additions and trigonometric functions where each number (X, Y, Z) is visually a coordinate along axes.

A `vector `is a point into the space localized by coordinates.

A 1D `space` is represented by a single line in one direction/`axis`: ----------------------------

To move an object on this axis, the equation is:

x' = vector.x + x

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

By consequence, the object moves within the same line.

A `translation `is done within a line, 1D space, so we have 1 `translation `possible on `X-axis`.

A 2D `space `is just a 1D `space `with another line in a direction at 90° of the `X-axis` where `Y` represents it:

To add an object in this 2D `space`, we need to set 2 coordinates for each point of the object and to move the object, we apply an addition like we did before to `translate` the object on `x``-axis`.

But we can also rotate the object around the center of the 2 `axis`, for doing that, an addition is not enough, we need to call math operators that is designed for `rotation `calculations.

A `rotation `is done within a plane, 2D `space`, so we have 1 `rotation `possible around the center of the two `axis`.

These math operators are called, trigonometric functions: `sin()` and `cos()` that take the angle between the two lines: [center, object's point] and `x-axis` for cos() and `y-axis` for `sin()`.

Visually, we have a point at `0°` (`x = 1`, `y = 0`) and we apply a `rotation `of `+90°` (+ is anticlockwise and - is clockwise) around the center, the result is `x = 0`, `y = 1`.

And the calculus to find this result is:

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

It's quite easy to retrieve this equation from scratch, it's what I did and surprisingly I have seen that this equation was the linear form of the Z rotation matrix.

Here's how I did it:

• We have a 2D XY circle with a diameter of 8.

• We set 1 point, rotate it and try to retrieve the equation of its new locations, we will find the final equation once we have operate on a couple of different XY combinations.
• Let's begin with P(4, 0), a red point:

• Now we rotate this point of +90° (θ) and try to find the equation of its new location, visually the result to find is P(0, 4):

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

Y = cos(θ) = 0 ❌
Y = sin(θ) = 1 ❌✔
Y = 4 × sin(θ) = 4 ✔```
• So for P(4, 0) and θ = 90, we have:
```X = cos(θ)
Y = 4 × sin(θ)```
• Try with any other angles for P(4, 0) and different X value with Y at zero (use mathsisfun for that), you will find the same equations, with 4× for X, but it's not alterate the final equation:
```X' = 4 × cos(θ) = X × cos(θ)
Y' = 4 × sin(θ) = X × sin(θ)```
• Now we set the red point at P(0, 4):

• We rotate this point of +90°, visually the result is P(-4, 0):

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

Y = sin(θ) = 1 ❌
Y = cos(θ) = 0 ✔```
• So for P(0, 4) and θ = 90, we have:
```X = 4 × -sin(θ)
Y = cos(θ)```
• Try with any other angles for P(0, 4) and different Y values with X at zero , you will find the same equations, with 4 × for Y, but it's not alterate the final equation:
```X = 4 × -sin(θ) = Y × -sin(θ)
Y = 4 ×  cos(θ) = Y ×  cos(θ)```
• Now let's summarize:
``` _____ ________________ ________________
|     |                |                |
|     |     P(X, 0)    |     P(0, Y)    |
|_____|________________|________________|
|     |                |                |
|  θ  | X = X × cos(θ) | X = Y × -sin(θ)|
|     | Y = X × sin(θ) | Y = Y ×  cos(θ)|
|_____|________________|________________|```

As we can see, different XY combinations generate different equations, so let's work on X and Y set above 0:

• Hence we set the red point at P(2, 4×√3/2):

• Now we rotate this point of +30°, visually the result to find is P(0, 4):

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

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

We have a problem, none of the trigonometric functions work, so we need to find the solution away while still working with `sin()` and `cos()`.

Let's review the previous equations found:

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

These are strange equations that we have, what if we have P(X, Y), it should be a mix of the both equations:

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

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

Let's see if an addition is working:

```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 ✔```

Perfect, this equation is working, so at the end, the final equations on a XY plane is:

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

But let's remove the doubt about P(X, 0) and P(0, Y):

• For P(4, 0), we apply a rotation of +90°, visually the result to find is P(0, 4):
```X' = 4 × cos(θ) - 0 ×  sin(θ) = 0 ✔
Y' = 4 × sin(θ) + 0 ×  cos(θ) = 4 ✔```
• For P(0, 4), we apply a rotation of +90°, visually the result to find is P(-4, 0):
```X' = 0 × cos(θ) - 4 ×  sin(θ) = -4 ✔
Y' = 0 × sin(θ) + 4 ×  cos(θ) =  0 ✔```

Good, all is working, you can test this equation with your own XY and angle values to verifiy if it's working.

This equation is also surprisingly (as said earlier) just a linear form of the Z rotation (XZ plane rotation matrix)` `matrix, multiplied by the point called `vector`, where `Z` is the center of the both `axis`)

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

And a 3D `space `is 2D `space `with another axis called `Z` and at `90°` of the `XY` plan.

The moves possible are `translation `(addition equation) and `rotation `(`sin `and `cos`).

But now `rotations `are in number of 3, around `Z`, around `X` and around `Y`.

Because as we said before, a rotation is made on a 2D plane, but now we have a mix of 3x 2D `space/plane`:

• `X/Y`, `Y/Z` and `Z/X`.

So we need to gather all the `rotation `matrices and use them.

### X Rotation Matrix (XY Plane Rotation Matrix)

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

### Y Rotation Matrix (YZ Plane Rotation Matrix)

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

### Z Rotation Matrix (XZ Plane Rotation Matrix)

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

But we have a problem, if we are doing that, we will not be able to rotate an object around `XYZ` `axis `together, it's one `rotation `on one `axis `only with other angles set as "zero" because they are not present in the matrix chosen.

To fix that, we need to form 1 single matrix by multiplying `XYZ` matrices together (mul's order matter).

So instead having 3 `rotations `on 3 x 2D plane, we will have only 1 `rotation `for a 3D `space`.

XYZ Rotation Matrix (XY YZ XZ Planes Rotation Matrix)

``` ______________________________ ______________________________ ____________________
|                              |                              |                    |
|      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)       |                    |
|______________________________|______________________________|____________________|```

Now, we just need to multiply this matrix to the `vector `point of the object to be able to `rotate `the object around `XYZ` `axis`.

And the result is:

Now it's almost finished, we need to create a camera to be able to navigate into the scene.

The camera is defined by 3 `vectors`: `Forward`, `Right `and `Up`:

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

Then, we multiply these 3 `vectors `to a `XYZ` matrix separately because we need each of them to be able to move the camera `Forward/Backward/Right/Left/Up/Down`.

Example: If press W, `Forward vector` is used, if press D, `Right vector` is used, ...

Now that we have our 3 camera `vectors`, we just need to add them to each of the points of the object to move, like that:

```Vector Object:           Forward Vector:          Backward Vector:         Right Vector:
__________________       __________________       __________________       __________________
|                  |     |                  |     |                  |     |                  |
|         x        |     |         x        |     |         x        |     |         x        |
|__________________|     |__________________|     |__________________|     |__________________|
|                  |     |                  |     |                  |     |                  |
|         y        |  +  |         y        |  +  |         y        |  +  |         y        |
|__________________|     |__________________|     |__________________|     |__________________|
|                  |     |                  |     |                  |     |                  |
|         z        |     |         z        |     |         z        |     |         z        |
|__________________|     |__________________|     |__________________|     |__________________|```

Finally, we multiply another `XYZ` matrix based on the camera angle with each `vector` point from the object to be able to move the object depending on the camera position and angle.

That's all for now, I hope I will give updates often because this code is not perfect, it has some bugs and does not have all the features of 3D math.

## History

• 14th December, 2019: Code update, GUI improvement
• 10th November, 2019: Code update, added stereocopic display for future VR support
• 12th June, 2018: Initial version

## Share

 France
No Biography provided

 First PrevNext
 Missing sample mesh file? Anand TM21-Nov-19 4:49 Anand TM 21-Nov-19 4:49
 Re: Missing sample mesh file? wqaxs3622-Nov-19 12:37 wqaxs36 22-Nov-19 12:37
 4th image from the top is missing littleGreenDude14-Nov-18 7:58 littleGreenDude 14-Nov-18 7:58
 Re: 4th image from the top is missing wqaxs3614-Nov-18 8:40 wqaxs36 14-Nov-18 8:40
 Re: 4th image from the top is missing littleGreenDude14-Nov-18 9:51 littleGreenDude 14-Nov-18 9:51
 Nice article Kenneth Haugland30-Jul-18 3:51 Kenneth Haugland 30-Jul-18 3:51
 Re: Nice article wqaxs368-Oct-18 12:17 wqaxs36 8-Oct-18 12:17
 Using Matrices Stefan_Lang11-Jul-18 23:26 Stefan_Lang 11-Jul-18 23:26
 Re: Using Matrices wqaxs3623-Sep-19 21:59 wqaxs36 23-Sep-19 21:59
 Re: Using Matrices Stefan_Lang23-Sep-19 23:11 Stefan_Lang 23-Sep-19 23:11
 Re: Using Matrices feanorgem25-Sep-19 9:17 feanorgem 25-Sep-19 9:17
 Re: Using Matrices Bob100025-Sep-19 2:00 Bob1000 25-Sep-19 2:00
 Premultiply feanorgem11-Jul-18 6:30 feanorgem 11-Jul-18 6:30
 Re: Premultiply wqaxs3611-Jul-18 7:04 wqaxs36 11-Jul-18 7:04
 Re: Premultiply Stefan_Lang11-Jul-18 22:44 Stefan_Lang 11-Jul-18 22:44
 Re: Premultiply wqaxs3612-Jul-18 3:45 wqaxs36 12-Jul-18 3:45
 nice BillW336-Jul-18 3:16 BillW33 6-Jul-18 3:16
 Re: nice wqaxs368-Oct-18 12:15 wqaxs36 8-Oct-18 12:15
 Learn 3D Math made by the GPU by Creating a 3D Engine on CPU Doom For Ever18-Jun-18 10:41 Doom For Ever 18-Jun-18 10:41
 Re: Learn 3D Math made by the GPU by Creating a 3D Engine on CPU wqaxs3618-Jun-18 12:39 wqaxs36 18-Jun-18 12:39
 Try this as one of your tables - created in Word davesmills14-Jun-18 4:59 davesmills 14-Jun-18 4:59
 Re: Try this as one of your tables - created in Word wqaxs3614-Jun-18 8:04 wqaxs36 14-Jun-18 8:04
 Last Visit: 15-Dec-19 10:33     Last Update: 15-Dec-19 10:33 Refresh 12 Next »