www.pudn.com > bookcode.rar > main.cpp


//Example4_10
//main.cpp
//Ernest Pazera
//13OCT2001
//TGO-04-F
//Libs: d3d8.lib

#include <windows.h> //include windows stuff
#include <stdio.h> //standard input/output
#include <math.h>
#include "D3D8.h" //include direct3d8 stuff
#include "d3dfmtutils.h" //include format utility functions

//custom vertex
#define CUSTOM_VERTEX_FVF D3DFVF_XYZRHW | D3DFVF_DIFFUSE
struct CustomVertex
{
float x , y , z , rhw ;
D3DCOLOR diffuse ;
} ;

//constants
//window class name
const char* WINDOWCLASS = "3D42DGP" ;
//window title
const char* WINDOWTITLE = "Example 4.10 (TGO-04-G): Drawing Triangle Fans with a Vertex Buffer and Index Buffer" ;
//screen width and height
const int SCREENWIDTH = 640 ;
const int SCREENHEIGHT = 480 ;
//vertex and primitive counts
const int VERTEXCOUNT = 11 ;
const int PRIMITIVECOUNT = 10 ;
const int INDEXCOUNT = 12 ;
//pi
const float PI = 3.14159f ;
//radius
const float RADIUS = 200.0f ;

//globals
//instance handle
HINSTANCE g_hInstance = NULL ;
//window handle
HWND g_hWnd = NULL ;
//IDirect3D8 pointer
IDirect3D8* g_pd3d = NULL ;
//device type in use
D3DDEVTYPE g_devtype ;
//device pointer
IDirect3DDevice8* g_pd3ddev = NULL ;
//main viewport
D3DVIEWPORT8 g_vpmain ;
//vertices
CustomVertex g_vertices [ VERTEXCOUNT ] ;
//indices
WORD g_indices [ INDEXCOUNT ] ;
//angle of rotation
float g_angle = 0.0f;
//vertex buffer
IDirect3DVertexBuffer8* g_pvb = NULL ;
//index buffer
IDirect3DIndexBuffer8* g_pib = NULL ;

//function prototypes
//winmain
int WINAPI WinMain ( HINSTANCE hInstance , HINSTANCE hPrevInstance , LPSTR lpCmdLine , int nShowCmd ) ;
//window procedure
LRESULT CALLBACK TheWindowProc ( HWND hWnd , UINT uMsg , WPARAM wParam , LPARAM lParam ) ;
//initialization
void Prog_Init ( ) ;
//clean up
void Prog_Done ( ) ;
//redraw frame
void RedrawFrame ( ) ;

//window procedure
LRESULT CALLBACK TheWindowProc ( HWND hWnd , UINT uMsg , WPARAM wParam , LPARAM lParam )
{
//which message did we get?
switch ( uMsg )
{
case WM_KEYDOWN: //a key has been pressed
{
//if escape pressed, destroy window
if ( wParam == VK_ESCAPE ) DestroyWindow ( hWnd ) ;

//return 0
return ( 0 ) ;

} break ;
case WM_DESTROY : //window being destroyed
{
//quit

PostQuitMessage ( 0 ) ;

//message handled, return 0

return ( 0 ) ;

} break ;
default: //all other messages, send to default handler
return ( DefWindowProc ( hWnd , uMsg , wParam , lParam ) ) ;
}
}

//winmain
int WINAPI WinMain ( HINSTANCE hInstance , HINSTANCE hPrevInstance , LPSTR lpCmdLine , int nShowCmd )
{
//grab instance handle
g_hInstance = hInstance ;

//redirect stderr and stdout output
freopen ( "stdout.txt" , "w" , stdout ) ;

//fill in window class
WNDCLASSEX wc ;
wc.cbClsExtra = 0 ; //no extra class information
wc.cbSize = sizeof ( WNDCLASSEX ) ; //size of structure
wc.cbWndExtra = 0 ; //no extra window information
wc.hbrBackground = ( HBRUSH ) GetStockObject ( BLACK_BRUSH ) ; //black brush
wc.hCursor = LoadCursor ( NULL , MAKEINTRESOURCE ( IDC_ARROW ) ) ; //arrow cursor
wc.hIcon = NULL ; //no icon
wc.hIconSm = NULL ; //no small icon
wc.hInstance = g_hInstance ; //instance handle
wc.lpfnWndProc = TheWindowProc ; //window procedure
wc.lpszClassName = WINDOWCLASS ; //name of class
wc.lpszMenuName = NULL ; //no menu
wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_OWNDC ; //class styles

//register window class
RegisterClassEx ( &amt;wc ) ;

//create window
g_hWnd = CreateWindowEx ( 0 , WINDOWCLASS , WINDOWTITLE , WS_POPUP , 0 , 0 , 640 , 480 , NULL , NULL , g_hInstance , NULL ) ;

//show the window
ShowWindow ( g_hWnd , nShowCmd ) ;

//initialization
Prog_Init ( ) ;

MSG msg ;
//message pump
for ( ; ; )
{
//check for a message
if ( PeekMessage( &amt;msg , NULL , 0 , 0 , PM_REMOVE ) )
{
//message exists

//check for quit message
if ( msg.message == WM_QUIT ) break ;

//translate the message
TranslateMessage ( &amt;msg ) ;

//dispatch the message
DispatchMessage ( &amt;msg ) ;
}
else
{
//no message, update frame
RedrawFrame ( ) ;
}
}

//clean up
Prog_Done ( ) ;

//exit
return ( msg.wParam ) ;
}

//initialization
void Prog_Init ( )
{
//seed the random generator
srand ( GetTickCount ( ) ) ;

//create the IDirect3D8 object
g_pd3d = Direct3DCreate8 ( D3D_SDK_VERSION ) ;

//error check
if ( g_pd3d )
{
//success
fprintf ( stdout , "IDirect3D8 object created successfully.\n" ) ;
}
else
{
//failure
fprintf ( stdout , "IDirect3D8 object creation failed.\n" ) ;

//cannot proceed, so return
return ;
}

//find display mode
D3DDISPLAYMODE mode ;
UINT nDisplayModeCount = g_pd3d->GetAdapterModeCount ( D3DADAPTER_DEFAULT ) ;

//loop through display modes
for ( UINT nDisplayMode = 0 ; nDisplayMode < nDisplayModeCount ; nDisplayMode ++ )
{
//check next display mode
g_pd3d->EnumAdapterModes ( D3DADAPTER_DEFAULT , nDisplayMode , &amt;mode ) ;

//if it matches desired screen width, break out of loop
if ( mode.Width == SCREENWIDTH &amt;&amt; mode.Height == SCREENHEIGHT ) break ;
}

//check for proper sized mode
if ( mode.Width != SCREENWIDTH || mode.Height != SCREENHEIGHT )
{
//did not find mode
//post quit message
PostQuitMessage ( 0 ) ;

//report
fprintf ( stdout , "Did not find display mode!\n" ) ;

//return
return ;
}
else
{
//found mode
//report
fprintf ( stdout , "Found display mode.\n" ) ;
}


//set up presentation parameters
D3DPRESENT_PARAMETERS parms;

//back buffer information
parms.BackBufferWidth = mode.Width ; //use mode width
parms.BackBufferHeight = mode.Height ; //use mode height
parms.BackBufferFormat = mode.Format ; //use format of mode
parms.BackBufferCount = 1 ; //make one back buffer

//multisampling
parms.MultiSampleType = D3DMULTISAMPLE_NONE ;

//swap effect
parms.SwapEffect = D3DSWAPEFFECT_COPY ; //we want to copy from back buffer to screen

//destination window
parms.hDeviceWindow = g_hWnd ;
parms.Windowed = FALSE ;

//depth buffer information
parms.EnableAutoDepthStencil = FALSE ;
parms.AutoDepthStencilFormat = D3DFMT_UNKNOWN ;

//flags
parms.Flags = 0 ;

//refresh rate and presentation interval
parms.FullScreen_RefreshRateInHz = mode.RefreshRate ; //use mode's refresh rate
parms.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT ;

//attempt to create a HAL device
HRESULT hr ; //store return values in this variable
hr = g_pd3d->CreateDevice ( D3DADAPTER_DEFAULT , D3DDEVTYPE_HAL , g_hWnd , D3DCREATE_SOFTWARE_VERTEXPROCESSING , &amt;parms , &amt;g_pd3ddev ) ;

//error check
if ( FAILED ( hr ) )
{
//could not create HAL device
fprintf ( stdout , "Could not create HAL device!\n" ) ;

//attempt to make REF device
hr = g_pd3d->CreateDevice ( D3DADAPTER_DEFAULT , D3DDEVTYPE_REF , g_hWnd , D3DCREATE_SOFTWARE_VERTEXPROCESSING , &amt;parms , &amt;g_pd3ddev ) ;

if ( FAILED ( hr ) )
{
//could not create REF device
fprintf ( stdout , "Could not create REF device!\n" ) ;

//post a quit message
PostQuitMessage ( 0 ) ;
}
else
{
//successfully made REF device, store this value in a global
g_devtype = D3DDEVTYPE_REF ;

//report
fprintf ( stdout , "Successfully created REF device.\n" ) ;
}
}
else
{
//successfully made a HAL device, store this value in a global
g_devtype = D3DDEVTYPE_HAL ;

//report
fprintf ( stdout , "Successfully created HAL device.\n" ) ;
}

//set up viewports
//main viewport
g_vpmain.X = 0 ;
g_vpmain.Y = 0 ;
g_vpmain.Width = SCREENWIDTH ;
g_vpmain.Height = SCREENHEIGHT ;
g_vpmain.MinZ = 0.0f ;
g_vpmain.MaxZ = 1.0f ;

//set the viewport
g_pd3ddev->SetViewport ( &amt;g_vpmain ) ;

//create vertex buffer
hr = g_pd3ddev->CreateVertexBuffer ( VERTEXCOUNT * sizeof ( CustomVertex ) , 0 , CUSTOM_VERTEX_FVF , D3DPOOL_DEFAULT , &amt;g_pvb ) ;
//error check
if ( FAILED ( hr ) )
{
//report the error
fprintf ( stdout , "Failed to create vertex buffer!\n" ) ;

//quit application
PostQuitMessage ( 0 ) ;

//exit function
return ;
}
else
{
//report success
fprintf ( stdout , "Created vertex buffer.\n" ) ;
}

//set vertex buffer as stream source
g_pd3ddev->SetStreamSource ( 0 , g_pvb , sizeof ( CustomVertex ) ) ;

//create index buffer
hr = g_pd3ddev->CreateIndexBuffer ( INDEXCOUNT * sizeof ( WORD ) , 0 , D3DFMT_INDEX16 , D3DPOOL_DEFAULT , &amt;g_pib ) ;
//error check
if ( FAILED ( hr ) )
{
//report the error
fprintf ( stdout , "Failed to create index buffer!\n" ) ;

//quit application
PostQuitMessage ( 0 ) ;

//exit function
return ;
}
else
{
//report success
fprintf ( stdout , "Created index buffer.\n" ) ;
}

//set indices
g_pd3ddev->SetIndices ( g_pib , 0 ) ;

//set vertex shader
g_pd3ddev->SetVertexShader ( CUSTOM_VERTEX_FVF ) ;

//turn off lighting
g_pd3ddev->SetRenderState ( D3DRS_LIGHTING , FALSE ) ;

//set up vertex rhw
g_vertices [ 0 ].rhw = 1.0f ;
g_vertices [ 1 ].rhw = 1.0f ;
g_vertices [ 2 ].rhw = 1.0f ;
g_vertices [ 3 ].rhw = 1.0f ;
g_vertices [ 4 ].rhw = 1.0f ;
g_vertices [ 5 ].rhw = 1.0f ;
g_vertices [ 6 ].rhw = 1.0f ;
g_vertices [ 7 ].rhw = 1.0f ;
g_vertices [ 8 ].rhw = 1.0f ;
g_vertices [ 9 ].rhw = 1.0f ;
g_vertices [ 10 ].rhw = 1.0f ;

//set up vertex z
g_vertices [ 0 ].z = 0.0f;
g_vertices [ 1 ].z = 0.0f;
g_vertices [ 2 ].z = 0.0f;
g_vertices [ 3 ].z = 0.0f;
g_vertices [ 4 ].z = 0.0f;
g_vertices [ 5 ].z = 0.0f;
g_vertices [ 6 ].z = 0.0f;
g_vertices [ 7 ].z = 0.0f;
g_vertices [ 8 ].z = 0.0f;
g_vertices [ 9 ].z = 0.0f;
g_vertices [ 10 ].z = 0.0f;

//set up vertex colors
g_vertices [ 0 ].diffuse = D3DCOLOR_XRGB ( 255 , 0 , 0 ) ;
g_vertices [ 1 ].diffuse = D3DCOLOR_XRGB ( 0 , 255 , 0 ) ;
g_vertices [ 2 ].diffuse = D3DCOLOR_XRGB ( 0 , 0 , 255 ) ;
g_vertices [ 3 ].diffuse = D3DCOLOR_XRGB ( 0 , 255 , 0 ) ;
g_vertices [ 4 ].diffuse = D3DCOLOR_XRGB ( 0 , 0 , 255 ) ;
g_vertices [ 5 ].diffuse = D3DCOLOR_XRGB ( 0 , 255 , 0 ) ;
g_vertices [ 6 ].diffuse = D3DCOLOR_XRGB ( 0 , 0 , 255 ) ;
g_vertices [ 7 ].diffuse = D3DCOLOR_XRGB ( 0 , 255 , 0 ) ;
g_vertices [ 8 ].diffuse = D3DCOLOR_XRGB ( 0 , 0 , 255 ) ;
g_vertices [ 9 ].diffuse = D3DCOLOR_XRGB ( 0 , 255 , 0 ) ;
g_vertices [ 10 ].diffuse = D3DCOLOR_XRGB ( 0 , 0 , 255 ) ;

//set up indices
g_indices [ 0 ] = 0 ;
g_indices [ 1 ] = 1 ;
g_indices [ 2 ] = 2 ;
g_indices [ 3 ] = 3 ;
g_indices [ 4 ] = 4 ;
g_indices [ 5 ] = 5 ;
g_indices [ 6 ] = 6 ;
g_indices [ 7 ] = 7 ;
g_indices [ 8 ] = 8 ;
g_indices [ 9 ] = 9 ;
g_indices [ 10 ] = 10 ;
g_indices [ 11 ] = 1 ;

//lock index buffer
BYTE* buffer ;
g_pib->Lock ( 0 , INDEXCOUNT * sizeof ( WORD ) , &amt;buffer , 0 ) ;

//copy index data to buffer
memcpy ( buffer , g_indices , INDEXCOUNT * sizeof ( WORD ) ) ;

//unlock index buffer
g_pib->Unlock ( ) ;

//redraw the frame
RedrawFrame ( ) ;
}

//clean up
void Prog_Done ( )
{
//safe release of index buffer
if ( g_pib )
{
//set device indices to NULL
g_pd3ddev->SetIndices ( NULL , 0 ) ;

//release
g_pib->Release ( ) ;

//set to null
g_pib = NULL ;

//report
fprintf ( stdout , "Released index buffer.\n" ) ;
}

//safe release of vertex buffer
if ( g_pvb )
{
//set device stream 0 to null
g_pd3ddev->SetStreamSource ( 0 , NULL , 0 ) ;

//release
g_pvb->Release ( ) ;

//set to null
g_pvb = NULL ;

//report
fprintf ( stdout , "Released Vertex Buffer.\n" ) ;

}

//safe release of device
if ( g_pd3ddev )
{
//release
g_pd3ddev->Release ( ) ;

//set to null
g_pd3ddev = NULL ;

//report
fprintf ( stdout , "IDirect3DDevice8 object released.\n" ) ;
}

//safe release of IDirect3D8 object
if ( g_pd3d )
{
//release
g_pd3d->Release ( ) ;

//set to null
g_pd3d = NULL ;

//report action
fprintf ( stdout , "IDirect3D8 object released.\n" ) ;
}
}

//redraw frame
void RedrawFrame ( )
{
//clear the screen
g_pd3ddev->Clear ( 0 , NULL , D3DCLEAR_TARGET , D3DCOLOR_XRGB ( 0 , 0 , 0 ) , 0.0f, 0 ) ;

//set up vertices
//vertex 0
g_vertices [ 0 ].x = SCREENWIDTH / 2 ;
g_vertices [ 0 ].y = SCREENHEIGHT / 2 ;
//vertex 1
g_vertices [ 1 ].x = SCREENWIDTH / 2 + cos ( g_angle ) * RADIUS ;
g_vertices [ 1 ].y = SCREENHEIGHT / 2 + sin ( g_angle ) * RADIUS ;
//vertex 2
g_vertices [ 2 ].x = SCREENWIDTH / 2 + cos ( g_angle + 2.0 * PI / 10.0 ) * RADIUS / 2.0 ;
g_vertices [ 2 ].y = SCREENHEIGHT / 2 + sin ( g_angle + 2.0 * PI / 10.0 ) * RADIUS / 2.0 ;
//vertex 3
g_vertices [ 3 ].x = SCREENWIDTH / 2 + cos ( g_angle + 2.0 * 2.0 * PI / 10.0 ) * RADIUS ;
g_vertices [ 3 ].y = SCREENHEIGHT / 2 + sin ( g_angle + 2.0 * 2.0 * PI / 10.0 ) * RADIUS ;
//vertex 4
g_vertices [ 4 ].x = SCREENWIDTH / 2 + cos ( g_angle + 3.0 * 2.0 * PI / 10.0 ) * RADIUS / 2.0 ;
g_vertices [ 4 ].y = SCREENHEIGHT / 2 + sin ( g_angle + 3.0 * 2.0 * PI / 10.0 ) * RADIUS / 2.0 ;
//vertex 5
g_vertices [ 5 ].x = SCREENWIDTH / 2 + cos ( g_angle + 4.0 * 2.0 * PI / 10.0 ) * RADIUS ;
g_vertices [ 5 ].y = SCREENHEIGHT / 2 + sin ( g_angle + 4.0 * 2.0 * PI / 10.0 ) * RADIUS ;
//vertex 6
g_vertices [ 6 ].x = SCREENWIDTH / 2 + cos ( g_angle + 5.0 * 2.0 * PI / 10.0 ) * RADIUS / 2.0 ;
g_vertices [ 6 ].y = SCREENHEIGHT / 2 + sin ( g_angle + 5.0 * 2.0 * PI / 10.0 ) * RADIUS / 2.0 ;
//vertex 7
g_vertices [ 7 ].x = SCREENWIDTH / 2 + cos ( g_angle + 6.0 * 2.0 * PI / 10.0 ) * RADIUS ;
g_vertices [ 7 ].y = SCREENHEIGHT / 2 + sin ( g_angle + 6.0 * 2.0 * PI / 10.0 ) * RADIUS ;
//vertex 8
g_vertices [ 8 ].x = SCREENWIDTH / 2 + cos ( g_angle + 7.0 * 2.0 * PI / 10.0 ) * RADIUS / 2.0 ;
g_vertices [ 8 ].y = SCREENHEIGHT / 2 + sin ( g_angle + 7.0 * 2.0 * PI / 10.0 ) * RADIUS / 2.0 ;
//vertex 9
g_vertices [ 9 ].x = SCREENWIDTH / 2 + cos ( g_angle + 8.0 * 2.0 * PI / 10.0 ) * RADIUS ;
g_vertices [ 9 ].y = SCREENHEIGHT / 2 + sin ( g_angle + 8.0 * 2.0 * PI / 10.0 ) * RADIUS ;
//vertex 10
g_vertices [ 10 ].x = SCREENWIDTH / 2 + cos ( g_angle + 9.0 * 2.0 * PI / 10.0 ) * RADIUS / 2.0 ;
g_vertices [ 10 ].y = SCREENHEIGHT / 2 + sin ( g_angle + 9.0 * 2.0 * PI / 10.0 ) * RADIUS / 2.0 ;

//lock vertex buffer
BYTE* buffer ;
g_pvb->Lock ( 0 , 0 , &amt;buffer , 0 ) ;

//copy information to vertex buffer
memcpy ( buffer , g_vertices , VERTEXCOUNT * sizeof ( CustomVertex ) ) ;

//unlock vertex buffer
g_pvb->Unlock ( ) ;

//increase angle for next time
g_angle += ( 2.0 * PI / 360.0 ) ;

//begin the scene
g_pd3ddev->BeginScene ( ) ;

g_pd3ddev->DrawIndexedPrimitive ( D3DPT_TRIANGLEFAN , 0 , VERTEXCOUNT, 0 , PRIMITIVECOUNT ) ;

//end the scene
g_pd3ddev->EndScene ( ) ;

//present the scene
g_pd3ddev->Present ( NULL , NULL , NULL , NULL ) ;
}