This tutorial is part of a Collection: 01. DirectX 9 - Braynzar Soft Tutorials
4118
views
08. Rotation and Projection
This lesson will teach you how you can use matrices to rotate objects in world space. You will also learn how to set up a basic view and projection matrix (which is a basic camera) using D3DXMatrixLookAtLH() and D3DXMatrixPerspectiveFovLH().
After we have our geometry for our scene set up, Direct3D needs to take the 3D geometry and transform it into 2D so it can be displayed on the monitor. The series of operations which take advantage of graphics hardware that does this is called the Rendering Pipeline (or Graphics Pipeline). We've already looked at Model Space, which is the space the triangle that make up the object are in. Now we will look at World Space, which is how the objects are positioned in the 3D world, View Space, which is how the virtual camera inside the 3D world is positioned, and Projection, which is getting a 2D representation of the 3D world geometry. We'll start in the SetupScene() function where we set up our virtual camera and projection. To make things more efficient, Direct3D uses an operation called the View Space Transformation. What this does is takes the position of the camera in the 3D world geometry, and transforms the camera back to 0 where its staring down the positive z-axis. All 3D world Geometry is transformed with it so the camera doesn't see anything different. Projection and other operations are less efficient when the camera is at a random positions. The View Space Matrix takes in three matrices and can be calculated using the following function: D3DXMATRIX *D3DXMatrixLookAtLH( D3DXMATRIX* pOut, CONST D3DXVECTOR3* pEye, CONST D3DXVECTOR3* pAt, CONST D3DXVECTOR3* pUp ); **pOut **- Pointer to recieve the computed matrix. **pEye **- Position of the camera in the 3D world space. **pAt **- Direction camera is pointed. **pUp **- Direction that is up, usually (0,1,0) (pointed in the y direction). First we define each matrix. Then compute the View Space Transformation Matrix. D3DXVECTOR3 pos(0.0f, 0.0f, -2.0f); D3DXVECTOR3 targ(0.0f, 0.0f, 0.0f); D3DXVECTOR3 up(0.0f, 1.0f, 0.0f); D3DXMATRIX View; D3DXMatrixLookAtLH(&View, &pos, &targ, &up); Now we need to set the View Space Transformation Matrix. We do this with the method IDirect3DDevice9:: SetTransform with D3DTS_VIEW as the first parameter. d3dDevice->SetTransform(D3DTS_VIEW, &View); Computer monitors are a flat plane, which is 2D. The Geometry we set up is 3D so we need to transform the 3D world Geometry to 2D Geometry. We do this with the Projection Matrix. There are other ways to compute the projection, but we are going to work with Perspective Projection. Perspective Projection represents the 3D world with a 2D picture. Objects further away will appear smaller than closer objects. We compute the Projection Matrix using D3DXMatrixPerspectiveFovLH(). D3DXMATRIX *D3DXMatrixPerspectiveFovLH( D3DXMATRIX* pOut, FLOAT fovY, FLOAT Aspect, FLOAT zn, FLOAT zf ); **pOut **- Pointer to Projection Matrix **fovY **- Vertical angle of the field of view (in radians). **Aspect **- Aspect Ratio, width / height. **zn **- Distance to near plane that is the start of what we see. **zf **- Distance to the far plane, which is the extent of what we see. D3DXMATRIX proj; D3DXMatrixPerspectiveFovLH( &proj, D3DX_PI * 0.5f, (float)Width / (float)Height, 1.0f, 1000.0f); Now we set the Projection Matrix. d3dDevice->SetTransform(D3DTS_PROJECTION, &proj); We can use the World Matrix to rotate, scale, or translate objects in the 3D world. We'll just cover rotation here, but i think next lesson i'll cover scaling and translating. Go to the RenderScene() function. Lets make a matrix for the rotation around the x-axis and one for the y-axis, then declare two static floats, one for y and one for x. The x and y variable will be used to rotate the object. D3DXMATRIX Rotx, Roty; static float y = 0.0f; static float x = 0.0f; Now we compute the X and Y rotation matrices using D3DXMatrixRotationY() and D3DXMatrixRotationX(). D3DXMatrixRotationY(&Roty, y); D3DXMatrixRotationX(&Rotx, x); Incriment the x and y variables. Then check to see if either one has gone over 2(pi), which is 360 degrees. If one has, change the value back to zero. y += timeDelta; x += timeDelta * 0.5f; if( y >= 6.28f ) y = 0.0f; if( x >= 6.28f ) x = 0.0f; Create a new matrix that holds the rotation information and set the rotation matrix D3DXMATRIX rotate = Rotx * Roty; //Set rotation matrix d3dDevice->SetTransform(D3DTS_WORLD, &rotate); Here's the final code: main.cpp ... ... bool SetupScene(){ //Set up our Scene ... ... D3DXVECTOR3 pos(0.0f, 0.0f, -2.0f);//position of camera in 3d space D3DXVECTOR3 targ(0.0f, 0.0f, 0.0f);//Direction camera is looking D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);//Direction that is up D3DXMATRIX View; //Computer view space tranformation matrix D3DXMatrixLookAtLH(&View, &pos, &targ, &up); d3dDevice->SetTransform(D3DTS_VIEW, &View);//Set the view matrix D3DXMATRIX proj; D3DXMatrixPerspectiveFovLH(//Computer Projection Matrix &proj, //Pointer to returned matrix D3DX_PI * 0.5f,//Vertical Field of view angle in radians (float)Width / (float)Height,//aspect ratio 1.0f,//Near plane distance 1000.0f);//Far plane distance //Set the projection Matrix d3dDevice->SetTransform(D3DTS_PROJECTION, &proj); ... ... } ... ... bool RenderScene(float timeDelta) //Renders a single frame { if( d3dDevice ) { D3DXMATRIX Rotx, Roty; static float y = 0.0f; static float x = 0.0f; D3DXMatrixRotationY(&Roty, y); //Compute y rotation matrix D3DXMatrixRotationX(&Rotx, x); //Compute x rotation matrix y += timeDelta; x += timeDelta * 0.5f; //go back to zero when angle reaches 360 degrees or 2*PI if( y >= 6.28f ) y = 0.0f; if( x >= 6.28f ) x = 0.0f; D3DXMATRIX rotate = Rotx * Roty; //Set rotation matrix d3dDevice->SetTransform(D3DTS_WORLD, &rotate); ... ... }
Sign in to comment