This tutorial is part of a Collection: 01. DirectX 9 - Braynzar Soft Tutorials
2355
views
09. Transformations
This lessons will cover how to translate and scale objects in 3D space. We will learn about translation, scaling, and rotation matrices.
Transformations in Direct3D use a 4x4 Matrix. Thats because they use 4 dimensions, 3 spacial, x, y, z, and 1 change, which is represented by the letter w. w is usually equal to a one(1) or a zero(0). I don't want to get into too much math, so if you don't know much about matrices, you should learn a little more if this gets confusing. When you want to transform an object, you take its 3D vector, v=[x, y, z], add in the w so it can be multiplied by a 4x4 Matrix, so it looks like v=[x, y, z, 1]. you set w to one because that means it will be transformed. Then you multiply v by the 4x4 Matrix which we will call M. the outcome of vM will be v'. vM=v'. [M11,M12,M13,M14] v'[x', y', z', 1]=v[x, y, z, 1] x M[M21,M22,M23,M24] [M31,M32,M33,M34] [M41,M42,M43,M44] x'=(x*M11) + (y*M21) + (z*M31) + (1*M41) y'=(x*M12) + (y*M22) + (z*M32) + (1*M42) z'=(x*M13) + (y*M23) + (z*M33) + (1*M43) Scaling Matrices will scale the size of an object in 3D space. Direct3D has functions that will compute transformations for us. the Scaling Matrix can be computed with the following method. D3DXMATRIX *D3DXMatrixScaling( D3DXMATRIX* pOut, // Pointer to recieve computed matrix FLOAT sx, // x=axis scale FLOAT sy, // y-axis scale FLOAT sz // z-axis scale ); The 4x4 scaling matrix looks like this. [S1, 0, 0, 0] S = [ 0,S2, 0, 0] [ 0, 0,S3, 0] [ 0, 0, 0, 1] Rotation Matrices are used to rotate an object in 3D space. There are 3 different matrices for rotating around each of the x, y, and z-axis's. Here are the three methods to create each of the rotation matrices, and what the 4x4 translation matrix looks like. Where r is the angle in radians. [ 1, 0, 0, 0] Rx = [ 0, cos(r),sin(r), 0] [ 0,-sin(r),cos(r), 0] [ 0, 0, 0, 1] D3DXMATRIX *D3DXMatrixRotationX( D3DXMATRIX* pOut, // Pointer to returned matrix FLOAT Angle // Rotation angle in radians ); [cos(r), 0,-sin(r), 0] Ry = [ 0, 1, 0, 0] [sin(r), 0, cos(r), 0] [ 0, 0, 0, 1] D3DXMATRIX *D3DXMatrixRotationY( D3DXMATRIX* pOut, // Pointer to store result in FLOAT Angle // Rotation angle in radians ); [ cos(r),sin(r), 0, 0] Rz = [-sin(r),cos(r), 0, 0] [ 0, 0, 1, 0] [ 0, 0, 0, 1] D3DXMATRIX *D3DXMatrixRotationZ( D3DXMATRIX* pOut, // Pointer to store resulting matrix in FLOAT Angle // Rotation angle in radians ); Translation Formations are used to move an object in 3D space. If you wanted to take and object positioned at [1,2,0] and move it over on the x-axis 3 units, the outcome would look like [4,2,0]. Below is how the Translation matrix looks and what the function to create it is. mx is the units translated on the x-axis, my is the units translated on the y=axis, and mz is the units translated on the z-axis. [ 1, 0, 0, 0] T = [ 0, 1, 0, 0] [ 0, 0, 1, 0] [mx,my,mz, 1] D3DXMATRIX *D3DXMatrixTranslation( D3DXMATRIX* pOut, // Pointer to matrix to store result in FLOAT x, // Units translated on the x-axis FLOAT y, // Units translated on the y-axis FLOAT z // Units translated on the z-axis ); We can combine multiple transformation matrices into one matrice. We do this by multiplying each one together. We have to do it in order to get the desired outcome. We have a scaling matrix called 'S', a rotation matrix called 'R', and a translation matrix called 'T'. our outcome is 'O'. O = S * R * T. Thats the order we must do it in. If we were to put the translation matrix first, 0 = T * S * R, our object would be rotating around where it was originally, not where it is now. It would create more of an orbit effect instead of a spinning effect. First think you'll see is the GetAsyncKeyState() function. What this does is see if a virtual key is down at the time the function is called. We test to see if the arrow keys are pressed. If one is, then the function returns true and does what it needs to do. Left and right translate the object on the x-axis, and up and down scale the objects size. The object may look like its going down the z-axis, but its really just getting smaller. if( GetAsyncKeyState(VK_LEFT) & 0x8000f ) transx -= 3.0f * timeDelta; if( GetAsyncKeyState(VK_RIGHT) & 0x8000f ) transx += 3.0f * timeDelta; if( GetAsyncKeyState(VK_UP) & 0x8000f ) scale -= 0.5f * timeDelta; if( GetAsyncKeyState(VK_DOWN) & 0x8000f ) scale += 0.5f * timeDelta; Next is just declaring the rotation, translation, and scaling variables and matrices. D3DXMATRIX Rotx, Roty, T, S; static float y = 0.0f; static float x = 0.0f; static float transx = 0.0f; static float scale = 1.0f; Compute the Translation, Scaling and Rotation matrices with their right functions using the variables we defined. D3DXMatrixTranslation(&T, transx, 0.0f, 0.0f); D3DXMatrixScaling(&S, scale, scale, scale); D3DXMatrixRotationY(&Roty, y); D3DXMatrixRotationX(&Rotx, x); Multiply all the Matrices into one matrix called 'A'. Then just set the World Matrix to 'A'. D3DXMATRIX A = S * Rotx * Roty * T; d3dDevice->SetTransform(D3DTS_WORLD, &A); Thats the end of this lesson. I really hope you learned something this time, cause there was more to learn here instead of just computer code. Thank you for reading, and come again! Here's the final code: main.cpp ... ... ... ... bool RenderScene(float timeDelta) //Renders a single frame { if( d3dDevice ) { // create x/y-rotation variables to hold angle data static float y = 0.0f; static float x = 0.0f; //Translation data for X-axis static float transx = 0.0f; //Scaling data for all-axis static float scale = 1.0f; //Check for keyboard input if( GetAsyncKeyState(VK_LEFT) & 0x8000f ) transx -= 3.0f * timeDelta; if( GetAsyncKeyState(VK_RIGHT) & 0x8000f ) transx += 3.0f * timeDelta; if( GetAsyncKeyState(VK_UP) & 0x8000f ) scale -= 0.5f * timeDelta; if( GetAsyncKeyState(VK_DOWN) & 0x8000f ) scale += 0.5f * timeDelta; D3DXMATRIX Rotx, Roty, T, S; //Compute a Translation Matrix D3DXMatrixTranslation(&T, transx, 0.0f, 0.0f); //Compute a Scaling Matrix D3DXMatrixScaling(&S, scale, scale, scale); D3DXMatrixRotationY(&Roty, y); //Compute y rotation matrix D3DXMatrixRotationX(&Rotx, x); //Compute x rotation matrix //Increment x/y rotation angles y += timeDelta; x += timeDelta * 0.5f; // reset angle to zero when angle reaches 2*PI if( y >= 6.28f ) y = 0.0f; if( x >= 6.28f ) x = 0.0f; D3DXMATRIX A = S * Rotx * Roty * T; //Put matrices into one d3dDevice->SetTransform(D3DTS_WORLD, &A); //Set rotation matrix ... ... } ... ...
Sign in to comment