Original address: http://blog.csdn.net/vagrxie/article/details/5016143
Copyright NOTICE: This work is created by nine days Goose Ling, using the Creative Commons Attribution-NonCommercial Use 4.0 International License Agreement license. Http://www.jtianling.com
Directory (?) [+]
Write by nine days Goose Feather (jtianling)--Blog.csdn.net/vagrxie
Discussion of newsgroups and documents
Starting here, is the real knowledge of 3D graphics programming, the first two sections can only be considered pure mathematics.
Translation matrix
To translate the vectors (x, y, Z, 1) along the x-axis, translate along the y-axis, and shift units along the z-axis, we only need to multiply the vector with the following matrix.
N (P) =
It can be seen that the n41,n42,n43 of 4*4 matrix n controls its translation units on the z-axis of the x-axis, respectively.
is the unit matrix, which we already know, multiplied by other matrices equal to the guy without multiplication. This matrix is slightly down from the unit matrix and has more than a few values for the 4th row. We first look at the contribution to the final result, when Vector m (x,y,z,1) is multiplied by the matrix N (p), the last x-coordinate value (that is, the value of the Matrix M11) is x*1 + y*0 + z*0 + 1*px = x + px. (Set the formula for multiplying the rectangle)
Y,z the same formula, it's not much to say. As can be seen here, for the implementation of the matrix translation calculation, the original vector (3-D) is required to expand the one-dimensional (generally denoted by W) set to 1, otherwise, the above x-coordinate =x*1 + y*0 + z*0 + 0*px=x, that is, the original matrix will not change at all.
The GNU Octave (MATLAB) verifies that:
> P = [1,0,0,0;0,1,0,0;0,0,1,0;2,3,4,1]p = 1 0 0 0 0 1 0 0 0 0 1 0 2 3 4 1octave-3.2.3.exe:6:d:/octave/3.2.3_gcc-> xx = 1 2 3 1octave-3.2.3.exe:7:d:/octave/3.2.3_gcc-> x * pans = 3 5 7 1octave-3.2.3.exe:8:d:/octave/ 3.2.3_gcc- |
x = 2 + 1 = 3, and so on, the result is correct.
In Irrlicht, the code of the translation matrix is directly lazy ..... Using the derivation of the above formula, the converted X-value is x+px .... Sweat-_-!, the theory and the actual actually still has the disparity. But think about it, so to say, an addition can be done by the translation, why do you want the entire matrix multiplication to complete? The existence of this formula makes people depressed ... Is it simply because of the need to calculate with a matrix ...
Template <class t>inline void Cmatrix4<t>::translatevect (vector3df& vect) const{ vect. X = Vect. X+M[12]; Vect. Y = Vect. Y+M[13]; Vect. Z = Vect. Z+M[14];}
Using Functions in D3D:
Build a matrix which translates by (x, Y, z) d3dxmatrix* WINAPI d3dxmatrixtranslation (D3dxmatrix *pout, FLOAT x, F Loat y, FLOAT z);
Realize the translation of the Matrix, the specific way unknown.
Scaling matrix
We scaled the X-fold of the one-unit matrix X-times, the y-axis to Y-times, and the z-axis by Z, which multiplies the vectors by the following matrices.
Deduced by formula: X (M11) coordinate value is x*x+y*0+z*0+0*0=x*x
The derivation of y,z is similar.
GNU Octave (MATLAB):
> x = [1,2,3,0]x = 1 2 3 0octave-3.2.3.exe:6:f:> pp = 2 0 0 0 0 3 0 0 0 0 4 0 0 0 0 1octave-3.2.3.exe:7:f:> x * pans = 2 6 0 |
The results are correct. Actually looked at the realization of the source code will also find that this formula is still nothing to look for, in fact, directly take more convenient AH.
The following implementation is used to construct a scaling matrix in Irrlicht:
Template <class t> inline cmatrix4<t>& cmatrix4<t>::setscale (const vector3d<t> & scale) { m[0] = scale. X; M[5] = scale. Y; M[10] = scale. Z; #if defined (use_matrix_test) definitelyidentitymatrix=false; #endif return *this; }
D3D using the following implementation to complete the scaling operation, the direct multiplication is good ...
D3dxinline d3dxvector3* d3dxvec3scale (D3dxvector3 *pout, CONST D3dxvector3 *PV, FLOAT s) {#ifdef d3dx_debug if ( !pout | | !PV) return NULL, #endif pout->x = pv->x * s; Pout->y = Pv->y * s; Pout->z = Pv->z * s; return pOut;}
Rotation matrix:
A rotation matrix is a matrix that has the effect of changing the direction of the vector but not changing the size when multiplied by a vector. The rotation matrix does not include inversion, it can change the right-handed coordinate system into a left-handed coordinate system or vice versa. All rotations plus inversion form a set of orthogonal matrices. It should be noted that the method of extending the 3-D vector is to make the w=0 when the rotation transformation is performed;
We can use the following 3 matrices to rotate a component clockwise around the x, Y, Z axis of θ.
X (θ) =
Y (θ) =
Z (θ) =
Or the first formula, after the vector m (x,y,z,0) is multiplied by the matrix X (θ), the last X (M11) coordinate value is x*1+y*0+z*0+0*0=x,y (M12) The coordinate value is x*0+y*cosθ+z* (-sinθ) +0*0 = y*cosθ+ Z * (- sinθθ), the Z (M13) coordinate value is x*0+y*sinθ+z*cosθ+0*0 = y*sinθ+ z*cosθ,w (m14) coordinates are x*0+y*0+z*0+0*1 = 0.
This is complicated ..... Not very good intuitive to see the results of the verification, we will receive 2 dimensions to see the results.
We use the GNU Octave (MATLAB) Compass command to visually display vector x = [1, tan (PI/3), 0, 0] in 2-dimensional space (actually shown in the X, y plane)
When we use it to rotate 30 degrees clockwise around the z axis, the way is multiplied by the above matrix of θ 30, the result is as follows:
> A = PI/6 > P = [cos (a), sin (a), 0,0;-sin (a), cos (a), 0,0;0,0,1,0;0,0,0,1]p = 0.86603 0.50000 0.00000 0.00000 -0.50000 0.86603 0.00000 0.00000 0.00000 0.00000 1.00000 0.00000 0.00000 0.00000 0.00000 1.00000octave-3.2.3.exe:26:f:/octave/3.2.3_gcc-4.4.0/bin> x = [1, Tan (pi /3), 0, 0]x = 1.00000 1.73205 0.00000 0.00000octave-3.2.3.exe:27:f:/octave/3.2.3_gcc-4.4.0/ bin> x2 = x * px2 = 0.00000 2.00000 0.00000 0.00000octave-3.2.3.exe:28:f:/octave/3.2.3_ Gcc-4.4.0/bin> |
Accuracy of 30 degrees.
It is learned to set the rotation matrix in Irrlicht:
Template <class t> inline cmatrix4<t>& cmatrix4<t>::setrotationradians (const vector3d< t>& rotation) { const F64 cr = cos (rotation. X); Const F64 sr = sin (rotation. X); CONST F64 CP = cos (rotation. Y); Const F64 SP = sin (rotation. Y); Const F64 cy = cos (rotation. Z); Const F64 sy = sin (rotation. Z); M[0] = (T) (cp*cy); M[1] = (T) (cp*sy); M[2] = (T) (-SP); Const F64 SRSP = SR*SP; Const F64 CRSP = CR*SP; M[4] = (T) (srsp*cy-cr*sy); M[5] = (T) (srsp*sy+cr*cy); M[6] = (T) (SR*CP); M[8] = (T) (crsp*cy+sr*sy); M[9] = (T) (crsp*sy-sr*cy); M[10] = (T) (CR*CP), #if defined (use_matrix_test) definitelyidentitymatrix=false; #endif return *this; }
To explain how this function works, look at the following procedures:
#include "irrlicht.h" #include <math.h> #pragma comment (lib, "Irrlicht.lib") using namespace Irr;using namespace Irr::core;int _tmain (int argc, _tchar* argv[]) { F32 a = +; F32 m[16] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; MATRIX4 MT; Mt.setm (M); VECTOR3DF VEC (0.0, 0.0, PI/6); Mt.setrotationradians (VEC); for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { printf ("%.6f/t", MT (I, j)); } printf ("/n"); } return 0;}
The result of the operation is:
0.866025 0.500000 -0.000000 0.000000-0.500000 0.866025 0.000000 0.0000000.000000 0.000000 1.000000 0.0000000.000000 0.000000 0.000000 1.000000 |
See what it is? Yes, the matrix in the GNU Octave (MATLAB) Example:
p = [cos (a), sin (a), 0,0;-sin (a), cos (a), 0,0;0,0,1,0;0,0,0,1]
In fact, the VEC in the above program does not revolve around the x, Y axis, rotate pi/6 around the z axis, the actual function is to construct the above matrix p.
The above matrix is applied by the following member function to use the generated matrix, which is actually the multiplication-_-!
template <class t>inline void Cmatrix4<t>::rotatevect (vector3df& vect ) const{VECTOR3DF tmp = Vect; Vect. X = tmp. X*M[0] + tmp. Y*M[4] + tmp. Z*M[8]; Vect. Y = tmp. X*M[1] + tmp. Y*M[5] + tmp. Z*M[9]; Vect. Z = tmp. X*M[2] + tmp. Y*M[6] + tmp. Z*M[10];} //! An alternate transform vector method, writing into a second vectortemplate <class t>inline void cmatrix4<t>::r Otatevect (core::vector3df& out, const core::vector3df& in) const{out. X = in. X*m[0] + in. Y*M[4] + in. Z*M[8]; Out. Y = in. X*M[1] + in. Y*M[5] + in. Z*M[9]; Out. Z = in. X*M[2] + in. Y*M[6] + in. Z*M[10];} //! An alternate transform vector method, writing to an array of 3 floatstemplate <class t>inline void CMATRIX4<T&G T;::rotatevect (T *out, const core::vector3df& in) const{out[0] = in. X*m[0] + in. Y*M[4] + in. Z*M[8]; OUT[1] = in. X*M[1] + in. Y*M[5] + in. Z*M[9]; OUT[2] = in. X*M[2] + in. Y*M[6] + in. Z*M[10];}
The above program is followed by the following sentences, using the matrix just generated above:
VECTOR3DF x (1.0, Tan (PI/3), 0.0), Mt.rotatevect (x);p rintf ("x = [%f,%f,%f]/n", x.x, x.y, x.z);
Output Result:
x = [-0.000000, 2.000000, 0.000000] |
As with the GNU Octave (MATLAB), the exact 30 degree rotation is achieved.
There are several functions of the vector related to rotation:
//! Rotates the vector by a specified number of degrees around the Y axis and the specified center./**/param degrees number O F degrees to rotate around the Y Axis./param Center the center of the rotation. */void Rotatexzby (f64 degrees, const vector3d<t>& center=vector3d<t> ()) {degrees *= DEGTORAD64; F64 cs = cos (degrees); f64 sn = sin (degrees); X-= center. X Z-= center. Z Set ((t) (X*CS-Z*SN), Y, (t) (X*SN + Z*cs)); X + = center. X Z + = center. Z;} //! Rotates the vector by a specified number of degrees around the Z axis and the specified center./**/param degrees:number of degrees to rotate around the Z Axis./param center:the Center of the rotation. */void rotatexyby (f64 degrees, const vector3d<t>& center=vector3d<t> ()) {degrees *= DEGTORAD64; F64 cs = cos (degrees); f64 sn = sin (degrees); X-= center. X Y-= center. Y Set ((t) (X*CS-Y*SN), (t) (X*SN + Y*cs), Z); X + = center. X Y + = center. Y;} //! Rotates the vector by a specified number of degrees around the X axis and the specified center./**/param degrees:number of degrees To rotate around the X Axis./param center:the Center of the rotation. */void Rotateyzby (f64 degrees, const vector3d<t>& center=vector3d<t> ()) {degrees *= DEGTORAD64; F64 cs = cos (degrees); f64 sn = sin (degrees); Z-= center. Z Y-= center. Y Set (X, (t) (Y*CS-Z*SN), (t) (Y*SN + Z*cs)); Z + = center. Z Y + = center. Y;}
In fact, these functions are the first two steps of the implementation, the actual use of the above formula to deduce the final result, you can compare.
such as the following code:
VECTOR3DF x (1.0, Tan (PI/3), 0.0), X.rotatexyby (;p rintf ("x = [%f,%f,%f]/n", x.x, x.y, x.z);
Output:
x = [-0.000000, 2.000000, 0.000000] |
Is the result of two steps ahead. The above Irrlicht code needs to be noted that the parameter is degree is the unit is the number of degrees, other times the default is radians.
D3D uses the following functions to achieve rotation, without implementing the source code, there is not much to say.
Build a matrix which rotates around the X axisd3dxmatrix* WINAPI d3dxmatrixrotationx (D3dxmatrix *pout, FLOAT Angl e);//Build a matrix which rotates around the Y axisd3dxmatrix* WINAPI d3dxmatrixrotationy (D3dxmatrix *pout, FLOAT Angle)//Build a matrix which rotates around the Z axisd3dxmatrix* WINAPI D3DXMatrixRotationZ (D3dxmatrix *pout, FL OAT Angle);
Original article author retention copyright reprint please indicate the original author and give the link
Write by nine days Goose Feather (jtianling)--Blog.csdn.net/vagrxie
(reprint) Mathematical basis for 3D graphics programming (3) Basic transformation of matrix