home | login | register | DMCA | contacts | help | donate |      

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z


my bookshelf | genres | recommend | rating of books | rating of authors | reviews | new | | collections | | | add
fantasy
space fantasy
fantasy is horrors
heroic
prose
  military
  child
  russian
detective
  action
  child
  ironical
  historical
  political
western
adventure
adventure (child)
child's stories
love
religion
antique
Scientific literature
biography
business
home pets
animals
art
history
computers
linguistics
mathematics
religion
home_garden
sport
technique
publicism
philosophy
chemistry
close

Loading...


Matrices

What is a Matrix? Matrices are a pretty advanced mathematics topic, so I will only give you a brief summary. A matrix can be thought of as a grid of numbers that can be applied to the coordinates of a vertex to change their values. You can use matrices in DirectX to translate, rotate and scale objects (vertices). In DirectX, a matrix is a 4x4 grid of numbers. There are three types of matrix: World, View and Projection.


World Matrix

You can use the world matrix to rotate, scale and translate objects in 3D space (World Space) by modifying their vertices. All of these transformations will be performed about the origin (0, 0, 0). You can combine transformations by multiplying them together, but be aware that it is important which order you perform the multiplication. Matrix1 x Matrix2 is not the same as Matrix2 x Matrix1. When you perform a world matrix transformation, all subsequent vertices will be transformed by this matrix. To rotate two objects, one about the x axis and one about the y axis, you must perform the x axis transformation first, then render object 1. Next, perform the y axis transformation, then render object 2.


View Matrix

The view matrix is the camera (or eye). The camera has a position in world space and also has a "look at" position. For example, you can place the camera above an object (camera position) and point it at the centre of the object (look at position). You can also specify which way is up, in our example below we will specify that the positive y axis is up.


Projection Matrix

The projection matrix can be thought of as the camera lens. It specifies the field of view angle, aspect ratio and near/far clipping planes. For the time being at least, we will keep these settings the same throughout our examples.

Here is the code for this tutorial. It's just the same as the code from the last tutorial, except for a few modifications:

#include


LPDIRECT3D8 g_pD3D = NULL;

LPDIRECT3DDEVICE8 g_pD3DDevice = NULL;

LPDIRECT3DVERTEXBUFFER8 g_pVertexBuffer = NULL; // Buffer to hold vertices

struct CUSTOMVERTEX {

FLOAT x, y, z;

DWORD colour;

};


#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)


#define SafeRelease(pObject) if (pObject != NULL) {pObject->Release(); pObject=NULL;}


HRESULT InitialiseD3D(HWND hWnd) {

//First of all, create the main D3D object. If it is created successfully we

//should get a pointer to an IDirect3D8 interface.

g_pD3D = Direct3DCreate8(D3D_SDK_VERSION);

if (g_pD3D == NULL) {

return E_FAIL;

}

//Get the current display mode

D3DDISPLAYMODE d3ddm;

if (FAILED(g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm))) {

return E_FAIL;

}

//Create a structure to hold the settings for our device

D3DPRESENT_PARAMETERS d3dpp;

ZeroMemory(&d3dpp, sizeof(d3dpp));

//Fill the structure.

//We want our program to be windowed, and set the back buffer to a format

//that matches our current display mode

d3dpp.Windowed = TRUE;

d3dpp.SwapEffect = D3DSWAPEFFECT_COPY_VSYNC;

d3dpp.BackBufferFormat = d3ddm.Format;

//Create a Direct3D device.

if (FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pD3DDevice))) {

return E_FAIL;

}

//Turn on back face culling. This is becuase we want to hide the back of our polygons

g_pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);

//Turn off lighting becuase we are specifying that our vertices have colour

g_pD3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE);

return S_OK;

}


HRESULT InitialiseVertexBuffer() {

VOID* pVertices;

//Store each point of the cube together with it's colour

//Make sure that the points of a polygon are specified in a clockwise direction,

//this is because anti-clockwise faces will be culled

//We will use a three triangle strips to render these polygons (Top, Sides, Bottom).

CUSTOMVERTEX cvVertices[] = {

//Top Face

{-5.0f, 5.0f, 5.0f, D3DCOLOR_XRGB(0, 0, 255),}, //Vertex 0 Blue

{-5.0f, 5.0f, 5.0f, D3DCOLOR_XRGB(255, 0, 0),}, //Vertex 1 Red

{5.0f, 5.0f, 5.0f, D3DCOLOR_XRGB(255, 0, 0),}, //Vertex 2 Red

{5.0f, 5.0f, 5.0f, D3DCOLOR_XRGB(0, 255, 0),}, //Vertex 3 Green

//Face 1

{-5.0f, 5.0f, 5.0f, D3DCOLOR_XRGB(255, 0, 0),}, //Vertex 4 Red

{-5.0f, 5.0f, 5.0f, D3DCOLOR_XRGB(0, 0, 255),}, //Vertex 5 Blue

{5.0f, 5.0f, 5.0f, D3DCOLOR_XRGB(0, 255, 0),}, //Vertex 6 Green

{5.0f, 5.0f, 5.0f, D3DCOLOR_XRGB(255, 0, 0),}, //Vertex 7 Red

//Face 2

{5.0f, 5.0f, 5.0f, D3DCOLOR_XRGB(0, 0, 255),}, //Vertex 8 Blue

{5.0f, 5.0f, 5.0f, D3DCOLOR_XRGB(0, 255, 0),}, //Vertex 9 Green

//Face 3

{-5.0f, 5.0f, 5.0f, D3DCOLOR_XRGB(0, 255, 0),}, //Vertex 10 Green

{-5.0f, 5.0f, 5.0f, D3DCOLOR_XRGB(255, 0, 0),}, //Vertex 11 Red

//Face 4

{-5.0f, 5.0f, 5.0f, D3DCOLOR_XRGB(255, 0, 0),}, //Vertex 12 Red

{-5.0f, 5.0f, 5.0f, D3DCOLOR_XRGB(0, 0, 255),}, //Vertex 13 Blue

//Bottom Face

{5.0f, 5.0f, 5.0f, D3DCOLOR_XRGB(0, 255, 0),}, //Vertex 14 Green

{5.0f, 5.0f, 5.0f, D3DCOLOR_XRGB(0, 0, 255),}, //Vertex 15 Blue

{-5.0f, 5.0f, 5.0f, D3DCOLOR_XRGB(255, 0, 0),}, //Vertex 16 Red

{-5.0f, 5.0f, 5.0f, D3DCOLOR_XRGB(0, 255, 0),}, //Vertex 17 Green

};

//Create the vertex buffer from our device.

if (FAILED(g_pD3DDevice->CreateVertexBuffer(18 * sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVertexBuffer))) {

return E_FAIL;

}


//Get a pointer to the vertex buffer vertices and lock the vertex buffer

if (FAILED(g_pVertexBuffer->Lock(0, sizeof(cvVertices), (BYTE**)&pVertices, 0))) {

return E_FAIL;

}

//Copy our stored vertices values into the vertex buffer

memcpy(pVertices, cvVertices, sizeof(cvVertices));

//Unlock the vertex buffer

g_pVertexBuffer->Unlock();

return S_OK;

}


void SetupRotation() {

//Here we will rotate our world around the x, y and z axis.

D3DXMATRIX matWorld, matWorldX, matWorldY, matWorldZ;

//Create the transformation matrices

D3DXMatrixRotationX(&matWorldX, timeGetTime()/400.0f);

D3DXMatrixRotationY(&matWorldY, timeGetTime()/400.0f);

D3DXMatrixRotationZ(&matWorldZ, timeGetTime()/400.0f);

//Combine the transformations by multiplying them together

D3DXMatrixMultiply(&matWorld, &matWorldX, &matWorldY);

D3DXMatrixMultiply(&matWorld, &matWorld, &matWorldZ);

//Apply the transformation

g_pD3DDevice->SetTransform(D3DTS_WORLD, &matWorld);

}


void SetupCamera() {

//Here we will setup the camera.

//The camera has three settings: "Camera Position", "Look at Position" and "Up Direction"

//We have set the following:

//Camera Position: (0, 0, 30)

//Look at Position: (0, 0, 0)

//Up direction: Y-Axis.

D3DXMATRIX matView;

D3DXMatrixLookAtLH(&matView, &D3DXVECTOR3(0.0f, 0.0f,-30.0f), //Camera Position

&D3DXVECTOR3(0.0f, 0.0f, 0.0f), //Look At Position

&D3DXVECTOR3(0.0f, 1.0f, 0.0f)); //Up Direction

g_pD3DDevice->SetTransform(D3DTS_VIEW, &matView);

}


void SetupPerspective() {

//Here we specify the field of view, aspect ration and near and far clipping planes.

D3DXMATRIX matProj;

D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI/4, 1.0f, 1.0f, 500.0f);

g_pD3DDevice->SetTransform(D3DTS_PROJECTION, &matProj);

}


void Render() {

if (g_pD3DDevice == NULL) {

return;

}

//Clear the backbuffer to black

g_pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);

//Begin the scene

g_pD3DDevice->BeginScene();

//Setup the rotation, camera, and perspective matrices

SetupRotation();

SetupCamera();

SetupPerspective();


//Rendering our objects

g_pD3DDevice->SetStreamSource(0, g_pVertexBuffer, sizeof(CUSTOMVERTEX));

g_pD3DDevice->SetVertexShader(D3DFVF_CUSTOMVERTEX);

g_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); //Top

g_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 4, 8); //Sides

g_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 14, 2); //Bottom

//End the scene

g_pD3DDevice->EndScene();

//Filp the back and front buffers so that whatever has been rendered on the back buffer

//will now be visible on screen (front buffer).

g_pD3DDevice->Present(NULL, NULL, NULL, NULL);

}


void CleanUp(){

SafeRelease(g_pVertexBuffer);

SafeRelease(g_pD3DDevice);

SafeRelease(g_pD3D);

}


void GameLoop() {

//Enter the game loop

MSG msg;

BOOL fMessage;

PeekMessage(&msg, NULL, 0U, 0U, PM_NOREMOVE);

while (msg.message != WM_QUIT) {

fMessage = PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE);

if (fMessage) {

//Process message

TranslateMessage(&msg);

DispatchMessage(&msg);

} else {

//No message to process, so render the current scene

Render();

}

}

}


//The windows message handler

LRESULT WINAPI WinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {

switch(msg) {

case WM_DESTROY:

PostQuitMessage(0);

return 0;

break;

case WM_KEYUP:

switch (wParam) {

case VK_ESCAPE:

//User has pressed the escape key, so quit

DestroyWindow(hWnd);

return 0;

break;

}

break;

}

return DefWindowProc(hWnd, msg, wParam, lParam);

}


//Application entry point

INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, INT) {

//Register the window class

WNDCLASSEX wc = {

sizeof(WNDCLASSEX), CS_CLASSDC, WinProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, "DX Project 3", NULL

};

RegisterClassEx(&wc);

//Create the application's window

HWND hWnd = CreateWindow("DX Project 3", "www.andypike.com: Tutorial 3",WS_OVERLAPPEDWINDOW, 50, 50, 500, 500, GetDesktopWindow(), NULL, wc.hInstance, NULL);

//Initialize Direct3D

if (SUCCEEDED(InitialiseD3D(hWnd))) {

//Show our window

ShowWindow(hWnd, SW_SHOWDEFAULT);

UpdateWindow(hWnd);

//Initialize Vertex Buffer

if (SUCCEEDED(InitialiseVertexBuffer())) {

//Start game running: Enter the game loop

GameLoop();

}

}

CleanUp();

UnregisterClass("DX Project 3", wc.hInstance);

return 0;

}

You should finish up with a window with a black background and a multi-coloured cube in the middle rotating (shown below).

DirectX 8 Programming Tutorial

So, what have we added/changed:

Include and lib files

We have a new header file, which replaces the old one. The new header file is:

We also have two new lib files to specify in our project settings (as in tutorial 1). They are: "d3dx8.lib" and "winmm.lib".

CUSTOMVERTEX

We have changed our custom vertex to only include x, y, z and colour values. These will allow us to specify a point in 3D space and a colour.

D3DFVF_CUSTOMVERTEX

To match our custom vertex structure, we have modified our FVF. We now use the flags D3DFVF_XYZ and D3DFVF_DIFFUSE.

InitaliseD3D

We have enabled Backface Culling (explained above). We use the SetRenderState function to do this, notice that we use the D3DCULL_CCW flag to specify that we want DirectX to cull the anti-clockwise faces.

We have also used the SetRenderState function to specify that we want to disable lighting, this is because we have given a colour (light) value to each of our vertices.

InitaliseVertexBuffer

Here we have set the values for our 18 vertices. Each vertex has a comment next to it with it's number, these numbers match the diagrams above (Fig 3.3 and 3.4). The cube is centred about the origin (0, 0, 0) and is 10 units wide/high/deep.

SetupRotation

SetupRotation is a new function. Here we call the functions D3DXMatrixRotationX, D3DXMatrixRotationY and D3DXMatrixRotationZ to generate rotation matrices and store them in three D3DXMATRIX structures. Next, we multiply the three matrices together to form one world matrix, we call the SetTransform function to apply the transformation to our vertices.

SetupCamera

SetupCamera is a new function. Here we setup the camera. We set it's position in 3D space to be (0, 0, 30) and point it at the origin (0,0,0). We have centred our cube around the origin. We also specify that the y axis points up. We use the D3DXMatrixLookAtLH to generate the view matrix and then use the SetTransform function to apply the transformation.

SetupPerspective

SetupPerspective is another new function. Here we setup the camera's lens. We have decided to have a field of view of PI/4 (normal) and an aspect ratio of 1. We have decided to set the near clipping path to 1, this means that polygons closer than one unit to the camera will be cropped. We have also decided to set the far clipping path to 500, this means that polygons more than 500 units away will be cropped.

Render

In the Render function, we call the three new functions SetupRotation, SetupCamera and SetupPerspective. These functions are called before we render the polygons.

We render the polygons by using three triangle strips, one for the top, one for the sides and one for the bottom.


How to make a cube | DirectX 8 Programming Tutorial | Summary







Loading...