Direct3D 9.0 with Allegro
by Homer Cuevas


ADVERTISEMENT

This article is actually based from an excellent article written by Michael Conway not too long ago. If you haven't read the article then you can click here. This tutorial aims to utilize Direct3D 9 while using Allegro's input and timer functionality instead of writing your own API-based code.

Now, let me tell you a little something about Shawn Hargreave's Allegro Game Programming Library. Allegro, just like SDL, is a cross-platform game library which gives you access to graphics, windowing, audio, timer and input handling without the complexity of touching a single operating system API. If you want to learn more about Allegro you can visit Allegro's Community Site by clicking here or its website here. Now let's get started!

What you Need

  • The DirectX 9.0 SDK which you can get from http://www.microsoft.com
  • The Allegro Game Programming Library which you can get from http://www.talula.demon.co.uk/allegro/. (We'll be using the Stable 4.03 build but later versions may work). If you want to get a precompiled version 4.03 you may get it at http://www.allegro.cc, just click on "Files" section on the upper left hand corner of the site.
  • Microsoft Visual C++ (We'll be using version 6.0 here but other versions may work)

For this tutorial we'll imitate the Mesh example demo from the DirectX 9.0 SDK tutorial.

We will be using the Tiger.X file used by Microsoft in their DX9 tutorial example.

Pseoudocode

Basically, here's what our program will do:

  1. Initialize Allegro
  2. Initialize DirectX
  3. Load Mesh Data (the X file)
  4. Setup Orientation
  5. Render Mesh Data
  6. Upon press of a key, the rendering stops
  7. Then we free all resources
  8. Program Exits

Defines, Includes and Libs

Since we're exposing allegro to some windows specific stuff we'll need to define this before anything else.

#define ALLEGRO_NO_MAGIC_MAIN

Which means we will not be using the allegro int main(void) format but instead we'll use this format as our entrypoint:

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

Then we need to include these:

#include <allegro.h>           //the allegro header
#include <winalleg.h>          //Windows specific allegro header
#include <d3d9.h>              //direct x header
#include <d3dx9.h>             //d3dx utility header

We will then need to link with the files alleg.lib, d3d9.lib and d3dx9.lib or define these as a shortcut:

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

Allegro

In this section we'll be discussing all the Allegro related methods in the demo program.

Since we'll be using the allegro timer routines, we also need to define these:

DWORD g_nCounter = 0;

void my_timer_handler()      {
    g_nCounter++;
}

This will work just like timeGetTime() in the SDK version of the demo; g_nCounter will increment by 1 everytime the handler is called.

Here is our function to initialize allegro. We'll need to initialize allegro before we intitialize DirectX. We'll be using the 800x600 video mode.

int StartAllegro(void) {
    allegro_init();           // start allegro

// create a window which can be used DirectX. If you don't create this the allegro input
// routines won't work
    if (set_gfx_mode(GFX_DIRECTX_WIN, 800, 600, 0, 0) < 0) {
        MessageBox(win_get_window(), allegro_error, "Error setting video mode", MB_OK);
            return 1;
    }
    // by the way you may also use the option GFX_GDI instead of GFX_DIRECTX_WIN

    install_timer();     //we'll be using the allegro routines for our timer so we call this
    install_keyboard();  //we'll also be using the allegro keyboard routines
    install_mouse();     //in order to hide the mouse pointer we'll need to call this first
    show_mouse(NULL);    //then hide the mouse pointer

//we'll call my_timer_handler() every 1 millisecond which would make g_nCounter
//work just like timeGetTime() in the SDK version of the example
    install_int(my_timer_handler, 1);
    return 0;
}

Here is our main program loop:

while(!keypressed())  { //keypressed is an Allegro function similar to kbhit(), returns
                        //true until a key is pressed

    SetupMatrices(); //setup our orientation

    //Clear the backbuffer and the zbuffer
    g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
                        D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );

    //Begin the scene
    if(SUCCEEDED(g_pd3dDevice->BeginScene()))     {

        RenderX(); //Render our model

        // End the scene
        g_pd3dDevice->EndScene();
    }

    // Present the backbuffer contents to the display
    g_pd3dDevice->Present( NULL, NULL, NULL, NULL );

}

DirectX

In this section we'll be discussing all the DirectX related methods in the demo program.

These things are a must for our Example:

LPDIRECT3D9 g_pD3D = NULL;              // Used to create the D3DDevice
LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;  // Our rendering device
LPD3DXMESH g_pMesh = NULL;              // Our mesh object in sysmem
D3DMATERIAL9 *g_pMeshMaterials = NULL;  // Materials for our mesh
LPDIRECT3DTEXTURE9 *g_pMeshTextures  = NULL; // Textures for our mesh
DWORD g_dwNumMaterials = 0L;            // Number of mesh materials

Here is the routine to Initialize Direct X, we'll be using the 800x600 video mode.

int StartDirectX(void)    {
    D3DPRESENT_PARAMETERS d3dpp;

    //creating direct3D object
    g_pD3D = Direct3DCreate9(D3D_SDK_VERSION);
    if    (g_pD3D == NULL)    {
        MessageBox(win_get_window(),"Error Creating Direct3D Object","D3D Object Error",MB_OK);
        return 1;
    }

    //setting parameters that will be needed to created direct3D device
    ZeroMemory(&d3dpp, sizeof(d3dpp));            
    d3dpp.Windowed = false;                        
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.EnableAutoDepthStencil = true;                    
    d3dpp.AutoDepthStencilFormat = D3DFMT_D16;        
    d3dpp.hDeviceWindow = win_get_window();
    d3dpp.BackBufferWidth = 800;                    
    d3dpp.BackBufferHeight = 600;                    
    d3dpp.BackBufferFormat = D3DFMT_R5G6B5;                    
    d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;

    //creating direct3D device
    if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, win_get_window(),
              D3DCREATE_SOFTWARE_VERTEXPROCESSING,&d3dpp, &g_pd3dDevice)))    {
        MessageBox(win_get_window(),"Error Creating Direct3D Device","D3D Device    Error",MB_OK);
        return 1;
    }

   
    // Turn on the zbuffer
    g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );


    // Turn on ambient lighting 
    g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0xffffffff );

    return 0;
}

We used the allegro function win_get_window() in this routine to let DirectX use the window created by Allegro.

This simple routine will be in-charge of loading the .X mesh for us.

int LoadX(char *szFile)        {
    ...
}

This will setup the orientation of our model per frame. There's nothing special about this routine except that we used g_nCounter instead of timeGetTime().

void SetupMatrices(void)     {
    ...
    D3DXMatrixRotationY( &matWorld, g_nCounter/1000.0f );
    ...
}

This routine would free all the resources we used up and stop our program

void EndDirectX(void)          {
    ...
}

You can download the complete demo project here.

I hope this tutorial has helped anyone. To give feedback, complaints or suggestions just shoot me an e-mail at the_temporal@yahoo.com

Acknowledgments

I would like to thank the people of http://www.allegro.cc for all their assistance when I was still beginning to use Allegro. Now I would like to give something back in return.

I would also like to thank the people of Anino Entertainment for letting me experience how it feels like to work for a game development company and for helping me learn DirectX.

Biography

Homer Cuevas is a hobbyist programmer from the Philippines who's interests lie in Graphics, AI and game development in general. He has experience in C/C++, Visual Basic, Java, Allegro, ASP, OpenGL and DirectX.

Discuss this article in the forums


Date this article was posted to GameDev.net: 1/25/2006
(Note that this date does not necessarily correspond to the date the article was written)

See Also:
Direct3D
General
Sweet Snippets

© 1999-2011 Gamedev.net. All rights reserved. Terms of Use Privacy Policy
Comments? Questions? Feedback? Click here!