B
brian0102
Guest
3-d-third-person-camera-tutorial
GM Version: Studio
Target Platform: Windows
Download Editable Example:https://drive.google.com/open?id=0B2TkWVm2bJT0ZE9Zd1hTU2NuQ2M
Controls :" WASD - to move camera, Q and E to roll camera"
Links:
http://planning.cs.uiuc.edu/node102.html
http://ncalculators.com/matrix/3x3-matrix-multiplication-calculator.htm
Summary:
When i was reading about matrices i made a 3rd person camera using a rotation matrix. This example is pretty straight forward but i'll explain step by step what's supposed to be happening.
Tutorial:
In the Create event :
Okay in the Create event 3d mode is being turned on
then i am going to create a 3x3 Matrix using the Create 3x3 Matrix in the Matrix Functions found in the Step Event of the Editable Example
In the Draw event :
In the draw event we are simply drawing the cameras projection from cam_Position to cam_LookAt using cam_Roll as the Up vector, "xyz(0,0,1) is up in this example". Remember we are using d3d_set_projection_ext(xfrom, yfrom, zfrom, xto, yto, zto, xup, yup, zup, angle, aspect, znear, zfar)
In the Step event :
In this event the camera is going to be rotated in a very specific order, first Roll, then Yaw, and then Pitch. In X, Y, Z terms, first we rotate the X-Axis, then we rotate the Y-Axis, and then finally the Z-Axis.
In rotation of these terms a X-Axis rotation is gathered by manipulating only the Y and Z coordinates of a (x,y,z)Position. A Y-Axis rotation is gathered by manipulating only the X and Z coordinates of a (x,y,z)Position. And a Z-Axis rotation is gathered by manipulating only the X and Y coordinates of a (x,y,z)Position.
This is the code that rotates the cam_Position(x,y,z) first by the X-Axis, then by the Y-Axis, and then by the Z-Axis. Now let's start the X axis rotation
This is the most important code to remember, this is where the Rotation Matrix is created, the order of sin and cos is the exact order for a counter clock-wise x-axis rotation. When a rotation matrix is multiplied with a (x,y,z)Position matrix an estimated (x,y,z)Position is created if the given (x,y,z)Position was rotated (theta) angles - for example rotateX is a 0 to 360 degree angle.
Let's continue.
This is Matrix B, or the Up Vector (0,0,1) in 3x3 Matrix form
Now we are going to multiply the Up Vector by the X-Axis Rotation Matrix using a 3x3 Matrix Multiplication Formula.
Right here all you have to do is plug the 'a' matrix and the 'b' matrix into the 3x3 Multiplication Syntax.
Then we will finally update the Camera.
Next we are going to rotate the cam_Position on the Y Axis.
Notice the order of sin and cos is different in this matrix, that is because this is the Y Axis Rotation Matrix.
This isn't the matrix form of the Up vector but the X vector, if you're confused maybe look up how vectors work but basically a vector a is a 3-D line drawn from point(0,0,0) to point(x,y,z) , usually vectors are normalized meaning the highest number in point(x,y,z) is brought down to 1 and all other points are brought down using the same ratio i.e. point(10 , 5 , 0) normalized is point(1 , 0.5 , 0). Vectors are usually used for direction for example the X Vector would be (1,0,0), the Y Vector would be (0,1,0) and the Up Vector would be (0,0,1).
Plug and play
Then we will finally update the Camera.
And finally we are going to rotate the cam_Position on the Z Axis.
Notice the order of sin and cos is different in this matrix, that is because this is the Z Axis Rotation Matrix.
This time we are multiplying the already Y Axis rotated cam_Position by the Z Axis, This will work in conjunction with one another due to the order of rotations, using the right hand grid and right hand rotation visualization with your actual hand might help if you don't understand.
The X axis is not being used with the Y or Z axis rotations and that is because the X Axis rotation is the cam_Roll and is used only as the Up Vector in d3d_set_projection_ext.
Plug and play
Then we will finally update the Camera.
GM Version: Studio
Target Platform: Windows
Download Editable Example:https://drive.google.com/open?id=0B2TkWVm2bJT0ZE9Zd1hTU2NuQ2M
Controls :" WASD - to move camera, Q and E to roll camera"
Links:
http://planning.cs.uiuc.edu/node102.html
http://ncalculators.com/matrix/3x3-matrix-multiplication-calculator.htm
Summary:
When i was reading about matrices i made a 3rd person camera using a rotation matrix. This example is pretty straight forward but i'll explain step by step what's supposed to be happening.
Tutorial:
In the Create event :
Okay in the Create event 3d mode is being turned on
Code:
//Initialize
d3d_start();
d3d_set_perspective(true);
d3d_set_lighting(false);
draw_set_color(c_white);
d3d_set_fog(true,c_black,1,128);
d3d_set_culling(false);
d3d_set_shading(false);
texture_set_interpolation(true);
Code:
cam_Roll=0;
cam_Position=0;
cam_LookAt=0;
cam_Distance=75;
//Set Rotation
rotateX = 0;
rotateY = 0;
rotateZ = 0;
//Create 3x3 Matrix - m
// | m0 m1 m2 | X
// | m3 m4 m5 | Y
// | m6 m7 m8 | Z
//------------- Create Matrix - Camera Position Matrix
cam_Position[0] = 0;
cam_Position[1] = 0;
cam_Position[2] = 0;
cam_Position[3] = 0;
cam_Position[4] = 0;
cam_Position[5] = 0;
cam_Position[6] = 0;
cam_Position[7] = 0;
cam_Position[8] = 0;
//------------- Create Matrix - Camera LookAt Matrix
cam_LookAt[0] = 0;
cam_LookAt[1] = 0;
cam_LookAt[2] = 0;
cam_LookAt[3] = 0;
cam_LookAt[4] = 0;
cam_LookAt[5] = 0;
cam_LookAt[6] = 0;
cam_LookAt[7] = 0;
cam_LookAt[8] = 0;
//------------- Create Matrix - Camera Roll Matrix
cam_Roll[0] = 0;
cam_Roll[1] = 0;
cam_Roll[2] = 0;
cam_Roll[3] = 0;
cam_Roll[4] = 0;
cam_Roll[5] = 1;
cam_Roll[6] = 1;
cam_Roll[7] = 1;
cam_Roll[8] = 0;
In the Draw event :
In the draw event we are simply drawing the cameras projection from cam_Position to cam_LookAt using cam_Roll as the Up vector, "xyz(0,0,1) is up in this example". Remember we are using d3d_set_projection_ext(xfrom, yfrom, zfrom, xto, yto, zto, xup, yup, zup, angle, aspect, znear, zfar)
Code:
d3d_set_projection_ext(cam_Position[0],cam_Position[3],cam_Position[6],
cam_LookAt[0],cam_LookAt[3],cam_LookAt[6],
cam_Roll[0],cam_Roll[3],cam_Roll[6], 60,1.33,1,256);
d3d_draw_ellipsoid(x-1,y-1,z,x+1,y+1,2+z,background_get_texture(bac_tex),2,1,24);
d3d_draw_floor(-128,-128,0,128,128,0,background_get_texture(bac_tex2),32,16);
In this event the camera is going to be rotated in a very specific order, first Roll, then Yaw, and then Pitch. In X, Y, Z terms, first we rotate the X-Axis, then we rotate the Y-Axis, and then finally the Z-Axis.
In rotation of these terms a X-Axis rotation is gathered by manipulating only the Y and Z coordinates of a (x,y,z)Position. A Y-Axis rotation is gathered by manipulating only the X and Z coordinates of a (x,y,z)Position. And a Z-Axis rotation is gathered by manipulating only the X and Y coordinates of a (x,y,z)Position.
This is the code that rotates the cam_Position(x,y,z) first by the X-Axis, then by the Y-Axis, and then by the Z-Axis. Now let's start the X axis rotation
Code:
//-----------------------------------Rotate X
var theta, a, b, c, d, e;
theta = degtorad(rotateX);//angle of rotation
//----------------------------------------Rotate(theta) on the X axis
//------------Create matrix - a
//Create 3x3 Matrix - m
// | m0 m1 m2 |
// | m3 m4 m5 |
// | m6 m7 m8 |
// | 1 0 0 | X
// | 0 cos -sin | Y
// | 0 sin cos | Z
// plug in values
a[0] = 1;
a[1] = 0;
a[2] = 0;
a[3] = 0;
a[4] = cos(theta);
a[5] = -sin(theta);
a[6] = 0;
a[7] = sin(theta);
a[8] = cos(theta);
Let's continue.
Code:
//------------Create matrix - b
//Create 3x3 Matrix - m
// | m0 m1 m2 |
// | m3 m4 m5 |
// | m6 m7 m8 |
// plug in values
b[0] = 0;
b[1] = 0;
b[2] = 0;
b[3] = 0;
b[4] = 0;
b[5] = 0;
b[6] = 1;
b[7] = 1;
b[8] = 1;
// X Y Z
// | 0 0 1 |
// | 0 0 1 |
// | 0 0 1 |
Now we are going to multiply the Up Vector by the X-Axis Rotation Matrix using a 3x3 Matrix Multiplication Formula.
Code:
// 3x3 Multiplication Syntax
// | d0 d1 d2 |
// | d3 d4 d5 |
// | d6 d7 d8 |
// | d0 =(a0*b0 + a1*b3 + a2*b6) d1 =(a0*b1 + a1*b4 + a2*b7) d2 =(a0*b2 + a1*b5 + a2*b8)|
// | d3 =(a3*b0 + a4*b3 + a5*b6) d4 =(a3*b1 + a4*b4 + a5*b7) d5 =(a3*b2 + a4*b5 + a5*b8)|
// | d6 =(a6*b0 + a7*b3 + a8*b6) d7 =(a6*b1 + a7*b4 + a8*b7) d8 =(a6*b2 + a7*b5 + a8*b8)|
d[0] = (a[0] * b[0]) + (a[1] * b[3]) + (a[2] * b[6]);
d[1] = (a[0] * b[1]) + (a[1] * b[4]) + (a[2] * b[7]);
d[2] = (a[0] * b[2]) + (a[1] * b[5]) + (a[2] * b[8]);
d[3] = (a[3] * b[0]) + (a[4] * b[3]) + (a[5] * b[6]);
d[4] = (a[3] * b[1]) + (a[4] * b[4]) + (a[5] * b[7]);
d[5] = (a[3] * b[2]) + (a[4] * b[5]) + (a[5] * b[8]);
d[6] = (a[6] * b[0]) + (a[7] * b[3]) + (a[8] * b[6]);
d[7] = (a[6] * b[1]) + (a[7] * b[4]) + (a[8] * b[7]);
d[8] = (a[6] * b[2]) + (a[7] * b[5]) + (a[8] * b[8]);
Then we will finally update the Camera.
Code:
//Camera Update
cam_Roll[0] = d[0];
cam_Roll[1] = d[1];
cam_Roll[2] = d[2];
cam_Roll[3] = d[3];
cam_Roll[4] = d[4];
cam_Roll[5] = d[5];
cam_Roll[6] = d[6];
cam_Roll[7] = d[7];
cam_Roll[8] = d[8];
Code:
//-------------------------------Rotate Y
//Camera Limitation
var theta, a, b, c, d, e;
if(rotateY>89)rotateY = 89;
if(rotateY<1)rotateY = 1;
theta = -degtorad(rotateY);//angle of rotation
//----------------------------------------Rotate(theta) on the Y axis
//------------Create matrix - a
//Create 3x3 Matrix - m
// | m0 m1 m2 |
// | m3 m4 m5 |
// | m6 m7 m8 |
// | cos 0 sin | X
// | 0 1 0 | Y
// |-sin 0 cos | Z
// plug in values
a[0] = cos(theta);
a[1] = 0;
a[2] = sin(theta);
a[3] = 0;
a[4] = 1;
a[5] = 0;
a[6] = -sin(theta);
a[7] = 0;
a[8] = cos(theta);
Code:
//------------Create matrix - b
//Create 3x3 Matrix - m
// | m0 m1 m2 |
// | m3 m4 m5 |
// | m6 m7 m8 |
// plug in values
b[0] = cam_Distance;
b[1] = cam_Distance;
b[2] = cam_Distance;
b[3] = 0;
b[4] = 0;
b[5] = 0;
b[6] = 0;
b[7] = 0;
b[8] = 0;
Plug and play
Code:
//------------Rotation
// Multiply camera position matrix * rotation matrix
// 3x3 Multiplication Syntax
// | d0 d1 d2 |
// | d3 d4 d5 |
// | d6 d7 d8 |
// | d0 =(a0*b0 + a1*b3 + a2*b6) d1 =(a0*b1 + a1*b4 + a2*b7) d2 =(a0*b2 + a1*b5 + a2*b8)|
// | d3 =(a3*b0 + a4*b3 + a5*b6) d4 =(a3*b1 + a4*b4 + a5*b7) d5 =(a3*b2 + a4*b5 + a5*b8)|
// | d6 =(a6*b0 + a7*b3 + a8*b6) d7 =(a6*b1 + a7*b4 + a8*b7) d8 =(a6*b2 + a7*b5 + a8*b8)|
d[0] = (a[0] * b[0]) + (a[1] * b[3]) + (a[2] * b[6]);
d[1] = (a[0] * b[1]) + (a[1] * b[4]) + (a[2] * b[7]);
d[2] = (a[0] * b[2]) + (a[1] * b[5]) + (a[2] * b[8]);
d[3] = (a[3] * b[0]) + (a[4] * b[3]) + (a[5] * b[6]);
d[4] = (a[3] * b[1]) + (a[4] * b[4]) + (a[5] * b[7]);
d[5] = (a[3] * b[2]) + (a[4] * b[5]) + (a[5] * b[8]);
d[6] = (a[6] * b[0]) + (a[7] * b[3]) + (a[8] * b[6]);
d[7] = (a[6] * b[1]) + (a[7] * b[4]) + (a[8] * b[7]);
d[8] = (a[6] * b[2]) + (a[7] * b[5]) + (a[8] * b[8]);
Code:
//Camera Update
cam_Position[0] = d[0];
cam_Position[1] = d[1];
cam_Position[2] = d[2];
cam_Position[3] = d[3];
cam_Position[4] = d[4];
cam_Position[5] = d[5];
cam_Position[6] = d[6];
cam_Position[7] = d[7];
cam_Position[8] = d[8];
Code:
//------------------------------Rotate Z
theta = degtorad(rotateZ);//angle of rotation
//----------------------------------------Rotate(theta) on the Z axis
//------------Create matrix - a
//Create 3x3 Matrix - m
// | m0 m1 m2 |
// | m3 m4 m5 |
// | m6 m7 m8 |
// | cos -sin 0 | X
// | sin cos 0 | Y
// | 0 0 1 | Z
// plug in values
a[0] = cos(theta);
a[1] = -sin(theta);
a[2] = 0;
a[3] = sin(theta);
a[4] = cos(theta);
a[5] = 0;
a[6] = 0;
a[7] = 0;
a[8] = 1;
Code:
//------------Create matrix - b
//Create 3x3 Matrix - m
// | m0 m1 m2 |
// | m3 m4 m5 |
// | m6 m7 m8 |
// plug in values
b[0] = cam_Position[0];
b[1] = cam_Position[1];
b[2] = cam_Position[2];
b[3] = cam_Position[3];
b[4] = cam_Position[4];
b[5] = cam_Position[5];
b[6] = cam_Position[6];
b[7] = cam_Position[7];
b[8] = cam_Position[8];
The X axis is not being used with the Y or Z axis rotations and that is because the X Axis rotation is the cam_Roll and is used only as the Up Vector in d3d_set_projection_ext.
Plug and play
Code:
//------------Rotation
// Multiply camera position matrix * rotation matrix
// 3x3 Multiplication Syntax
// | d0 d1 d2 |
// | d3 d4 d5 |
// | d6 d7 d8 |
// | d0 =(a0*b0 + a1*b3 + a2*b6) d1 =(a0*b1 + a1*b4 + a2*b7) d2 =(a0*b2 + a1*b5 + a2*b8)|
// | d3 =(a3*b0 + a4*b3 + a5*b6) d4 =(a3*b1 + a4*b4 + a5*b7) d5 =(a3*b2 + a4*b5 + a5*b8)|
// | d6 =(a6*b0 + a7*b3 + a8*b6) d7 =(a6*b1 + a7*b4 + a8*b7) d8 =(a6*b2 + a7*b5 + a8*b8)|
d[0] = (a[0] * b[0]) + (a[1] * b[3]) + (a[2] * b[6]);
d[1] = (a[0] * b[1]) + (a[1] * b[4]) + (a[2] * b[7]);
d[2] = (a[0] * b[2]) + (a[1] * b[5]) + (a[2] * b[8]);
d[3] = (a[3] * b[0]) + (a[4] * b[3]) + (a[5] * b[6]);
d[4] = (a[3] * b[1]) + (a[4] * b[4]) + (a[5] * b[7]);
d[5] = (a[3] * b[2]) + (a[4] * b[5]) + (a[5] * b[8]);
d[6] = (a[6] * b[0]) + (a[7] * b[3]) + (a[8] * b[6]);
d[7] = (a[6] * b[1]) + (a[7] * b[4]) + (a[8] * b[7]);
d[8] = (a[6] * b[2]) + (a[7] * b[5]) + (a[8] * b[8]);
Code:
//Camera Update
cam_Position[0] = d[0];
cam_Position[1] = d[1];
cam_Position[2] = d[2];
cam_Position[3] = d[3];
cam_Position[4] = d[4];
cam_Position[5] = d[5];
cam_Position[6] = d[6];
cam_Position[7] = d[7];
cam_Position[8] = d[8];
Last edited by a moderator: