Rotating our Square with Direct3D

Back to Direct3D Tutorial Index

Welcome once again to another installment to my Direct 3D tutorials. Here I am
going to show you how to achieve simple rotation. This rotation will rotate
your objects on only 1 axis. I will be showing you in the next how to rotate
on more than 1 axis at once.

-------------------------------------------------------------------------------
Section 1: Headers, Libraries, Global Variables

Because this tutorial will be building off of the previous, we only need to add
one item to this section. And that will be the variable which holds are
angle of rotation.

This will be a float type variable which I will call Angle. To achieve this, I
have simply placed the following line under our #define for our custom vertex
information:

float Angle;

-------------------------------------------------------------------------------
Section 2: Rotation

The next thing for us to do, is create our Rotation code. I have placed this
inside a function in which I have called Rotation.

void Rotation (void)
{

To rotate our scene, I need to create a Matrix, which I have called matWorld,
and this will hold our rotation information.
D3DXMATRIXA16 matWorld;

Next I am going to increase my angle of rotation by 0.1. This will keep increasing
and when it reaches 360, it will keep increasing, but Direct 3D will treat 361 as
if it were 1 degree. Therefore 1081 degrees would be treated as 1 again. Anyway
an increment of 0.1 on my system gives me a nice animation, while an increment of
1 is too fast and looks patchy. I will talk in a later tutorial on how to do this
so that it works the same on each system using a time based increment.
Angle+=0.1;

Now for the code that will set our rotation. The call:
D3DXMatrixRotationX
will give us a rotation on the X axis. There are also:
D3DXMatrixRotationY
D3DXMatrixRotationZ

Which cause rotations on the Y and Z axis respectively. So this call takes our
matWorld matrix and rotates it according to our Angle variable.
D3DXMatrixRotationX( &matWorld, Angle );
Next we need to transform our world according to our matWorld matrix.
g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
}

----------------------------------------------------------------------------------
Section 3: Rendering

Now all I have to do is call our rotation function from within our Render
function. So just before our drawing code, and after our Projection call,
I have added the line:
Rotation();

----------------------------------------------------------------------------------
And that is all there is to it. This will rotate your scene according to the
Angle variable.

If you have any questions, just email me at swiftless@gmail.com

#include <dx/d3dx9.h>
#include <dx/d3d9.h>

#pragma comment(lib,"d3d9.lib")
#pragma comment(lib,"d3dx9.lib")

LPDIRECT3D9 g_pD3D = NULL;
LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;
LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL;

struct CUSTOMVERTEX
{
float x, y, z;
DWORD color;
};

#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)

float Angle;

void init( HWND hWnd )
{

g_pD3D = Direct3DCreate9( D3D_SDK_VERSION );

D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof(d3dpp) );
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;

g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice );

g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );

g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );

}

void initVBuffer (void)
{
CUSTOMVERTEX Square[] =
{
{ -1, 1, 0, D3DCOLOR_XRGB(255,0,0), },
{ -1, -1, 0, D3DCOLOR_XRGB(0,0,255), },

{ 1, 1, 0, D3DCOLOR_XRGB(255,255,0), },
{ 1, -1, 0, 0xff00ff00, },
};

g_pd3dDevice->CreateVertexBuffer( 4*sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL );

void* pVertices;
g_pVB->Lock( 0, sizeof(Square), (void**)&pVertices, 0 );

memcpy( pVertices, Square, sizeof(Square) );

g_pVB->Unlock();
}

void Rotation (void)
{
D3DXMATRIXA16 matWorld;

fAngle+=0.1;

D3DXMatrixRotationX( &matWorld, fAngle );
g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
}

void Eye (void)
{
D3DXVECTOR3 EyePoint( 0, 0,-5 );
D3DXVECTOR3 LookatPoint( 0, 0, 0 );
D3DXVECTOR3 UpVector( 0, 1, 0 );

D3DXMATRIXA16 mView;
D3DXMatrixLookAtLH( &mView, &EyePoint, &LookatPoint, &UpVector );
g_pd3dDevice->SetTransform( D3DTS_VIEW, &mView );
}

void Perspective (void)
{
D3DXMATRIXA16 mProjection;
D3DXMatrixPerspectiveFovLH( &mProjection, D3DX_PI/4, 1, 0.1, 100 );
g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &mProjection );
}

void Cleanup (void)
{

if( g_pVB != NULL )
{
g_pVB->Release();
}

if( g_pd3dDevice != NULL)
{
g_pd3dDevice->Release();
}

if( g_pD3D != NULL)
{
g_pD3D->Release();
}
}

void Render (void)
{
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1, 0 );

g_pd3dDevice->BeginScene();

Eye();

Perspective();

Rotation();

g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) );

g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );

g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );

g_pd3dDevice->EndScene();

g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}

LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_DESTROY:
Cleanup();
PostQuitMessage( 0 );
return 0;

case WM_PAINT:
Render();
ValidateRect( hWnd, NULL );
return 0;
}

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

INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
{
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, "A Basic Window", NULL };
RegisterClassEx( &wc );

HWND hWnd = CreateWindow( "A Basic Window", "A Basic Window", WS_OVERLAPPEDWINDOW, 100, 100, 500, 500, NULL, NULL, wc.hInstance, NULL );

init( hWnd );

initVBuffer();

ShowWindow( hWnd, SW_SHOWDEFAULT );
UpdateWindow( hWnd );

MSG msg;
ZeroMemory( &msg, sizeof(msg) );
while( msg.message!=WM_QUIT )
{
if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
else
Render();
}

UnregisterClass( "A Basic Window", wc.hInstance );
return 0;
}

Download C++ Source Code for this Tutorial

     

 

Copyright 2008, Donald Urquhart
Proudly supported by http://www.cdadc.com