# Graphics rotation and projection matrix-3

The second operation of game101; Web GL implementation

THREEJS is used as the basic framework to build various matrices, customize matrix operations, and finally complete

1. Build model matrix correctly
2. Construct perspective projection matrix correctly
3. See the transformed triangle
4. Triangles can be rotated by pressing A and D
5. According to Q and E, triangles can rotate around any vector passing through the origin

Final effect

## Introduction above

In the second chapter of rotation and projection matrix, the principle of three-dimensional transformation is explained in detail, and the concepts of view matrix, canonical cube, projection matrix and perspective projection matrix parameters are explained in detail. Three dimensional transformation is divided into scaling transformation, translation transformation and rotation transformation; The view matrix describes the position and rotation angle of the current camera; The canonical cube describes that by default, elements should be in the [- 1. 1] ^ 3 cube; The projection matrix describes the conversion of the human eye angle into the standard camera angle, which is located at the origin, lookAt is (0, 0, - 1), and up is (0, 1, 0); Perspective projection parameters describe the known fov, aspct, near and far, so as to deduce other parameters.

The theoretical basis has been explained. This chapter mainly focuses on code implementation and lists the process quantities

## Construct perspective projection matrix

The construction of perspective projection matrix requires four parameters, fov, aspct, near and far. The top, right, bottom and left are deduced according to the four parameters. Converting a perspective camera to a standard camera requires two steps:

1. The perspective projection is transformed into orthogonal projection to obtain the transformation matrix
2. The orthogonal projection is transformed into a standard camera to obtain the orthogonal camera matrix

$M_{persp} =M_{ortho} \times M_{persp \rightarrow ortho}$

code implementation

// Construct a perspective projection matrix,
function perspMatrix(fov, aspect, near, far){
fov = Math.PI*fov/180;
const top = Math.tan(fov/2) * Math.abs(near);
const right = aspect * top;
const bottom = -top;
const left = -right;

const ortho = new THREE.Matrix4()
.scale(new THREE.Vector3(2/(right-left), 2/(top-bottom), 2/(near-far)))
.multiply(new THREE.Matrix4().setPosition(-(right+left)/2, -(top+bottom)/2, -(near+far)/2));

const perseToOrtho = new THREE.Matrix4().set(
near, 0, 0, 0,
0, near, 0, 0,
0, 0, near+far, -1*near*far,
0, 0,1, 0
)
return ortho.clone().multiply(perseToOrtho);
}


Set fov to 90, aspect to 1, near to - 3 and far to - 9

const per = perspMatrix(90, 1, -3, -9);


$M_{persp}= \left[ \begin{matrix} -1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & -2 & -9 \\ 0 & 0 & 1 & 0 \end{matrix} \right]$

## Rotation transformation matrix around arbitrary vector

The theoretical basis of the rotation transformation matrix about any axis passing through the origin is as follows, which represents the counterclockwise rotation of the n vector around the origin θ Transformation matrix of angle

$R(n, \theta) = \cos(\theta) \times I + (1-\cos(\theta)) \times n \times n^T + \sin(\theta) \times \left[ \begin{matrix} 0 & -n_z & n_y \\ n_z & 0 & -n_x \\ -n_y & n_x & 0 \end{matrix} \right] \\ n_x, n_y, n_z \: are the x,y,z values of the vector \: \ overrightarrow{n} \:$

How is the vector around any point calculated? As mentioned in the previous article, first move to the origin for calculation, and then move back inversely

The code is as follows

// Rotation transformation matrix about any axis passing through the origin
function getAnyRotation(axis, angle){
const cosTheta = Math.cos(angle);
const matrix1 = new THREE.Matrix3().multiplyScalar(cosTheta);
const matrix2 = getSelfMul(axis).multiplyScalar(1-cosTheta);
const matrix3 = new THREE.Matrix3();
matrix3.set(
0, -axis.z, axis.y,
axis.z, 0, -axis.x,
-axis.y, axis.x, 0
);
matrix3.multiplyScalar(Math.sin(angle));

return new THREE.Matrix4().setFromMatrix3(result);
}


## Set model matrix

The initial values of the three vertex coordinates of the triangle have been fixed. If you want to rotate it, the first method is to change the vertex coordinates through matrix operation. The matrix that changes the position information of the model is called model matrix. The theoretical basis is as follows

$R_x(\theta)= \left[ \begin{matrix} 1 & 0 & 0 & 0 \\ 0 & \cos(\theta) & -\sin(\theta) & 0 \\ 0 & \sin(\theta) & \cos(\theta) & 0 \\ 0 & 0 & 0 & 1 \end{matrix} \right] \\ \\ R_z(\theta)= \left[ \begin{matrix} \cos(\theta) & -\sin(\theta) & 0 & 0 \\ \sin(\theta) & \cos(\theta) & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{matrix} \right] \\ \\ R_y(\theta)= \left[ \begin{matrix} \cos(\theta) & 0 & \sin(\theta) & 0 \\ 0 & 1 & 0 & 0 \\ -\sin(\theta) & 0 & \cos(\theta) & 0 \\ 0 & 0 & 0 & 1 \end{matrix} \right]$

Here, a model matrix rotating counterclockwise around the z axis is constructed

// Equivalent to makerotationz model makeRotationZ(rotation);
function rotateZ(model, rotate){
model.set(
Math.cos(rotate), -Math.sin(rotate), 0, 0,
Math.sin(rotate), Math.cos(rotate), 0, 0,
0, 0,1, 0,
0, 0, 0, 1
)
}


## Add interactive event

Call the corresponding function

window.addEventListener('keydown', ev => {
if(ev.key === "a" ){
rotation += 0.2;
rotateZ(model, rotation)
return;
}
if ( ev.key === 'd'){
rotation -= 0.2;
rotateZ(model, rotation);
return;
}
if ( ev.key === 'q'){
angle -= 0.2;
uniforms.anyRotate.value = getAnyRotation(vec, angle);
return;
}
if ( ev.key === 'e'){
angle += 0.2;
uniforms.anyRotate.value = getAnyRotation(vec, angle);
}
})


## summary

So far, the second operation of games101 has been completed and displayed in the form of web. It is regarded as some innovation. Interested partners can discuss it together and come on

Added by Phairest on Sat, 01 Jan 2022 19:30:15 +0200