Topic : Direct3D 7 Frame Programming
Author : Wolfgang Engel
Page : 1 Next >>
Go to page :


Direct3D 7 IM
Framework Programming

by Wolfgang Engel (Last modified: 22.06.00)



Preface


With the advent of DirectX 7 two new interfaces have been added as part of Direct3D: IDirect3D7 and IDirect3Ddevice7. These objects provide several new features over their counterparts from previous versions of Direct3D. To mention a few: Hardware-accelerated transformation and lighting, Environment mapping with cubic environment maps, Geometry Blending, Device-state blocks, the texture manager can handle texture priorities etc. .

This tutorial serie at www.direct3d.net focuses on using the new Direct3D features with the Direct3D IM Framework provided by Microsoft. Since its advent in DirectX 6, the Direct3D IM Framework has changed dramatically. It’s easier to use and easier to code ... that’s great work.
There’s also a new Utility Library Direct3DX, which sits on Top of Direct3D IM (Tutorial: http://www.icon.fi/~solar/dxtut.html). It provides helper functionality for enumerating device configurations, setting up a device, running full-screen or windowed mode uniformly, running resizing operations, calculating vector and matrix operations, and simplifying image file loading and texture creation. In addition, it provides functions for drawing simple shapes, sprites, and cube maps. However, Direct3DX does not provide a scene hierarchy or support X Files. This way the whole complexity of Direct3D IM is encapsulated. There’s one big drawback ... we haven’t received the source of this library. I recommend on doing your own Utility Library. There are a lot of open source libraries to learn from.

A good place to start diving into Direct3D is the DirectX Software Development Kit (SDK). All the D3D samples use the Direct3D IM Framework. This common framework gives you a common ground on which you can implement your individual features. As a beginner, you avoid a lot of basic mistakes. The framework code is fast and very well tested. You can concentrate your energy on learning. As a mediate and professional programmer, you have a good testing platform. Perhaps a professional programmer will write his own framework, which suits his needs better, by looking in the Direct3D IM Framework Source.

For example ATI has a slightly modified version of this framework. NVIDIA has built a complete new framework.
The SDK HTML Help is the primary resource for understanding DirectX in general and D3D specifically. You can find it online in the msdn library. Sample code is the next best vehicle for learning Direct3D. The Direct3D Immediate Mode sample code lives in \mssdk\samples\multimedia\d3dim. Beneath \d3dim are \bin, \include, \lib, \media, and \src. All samples in ready-to-build form can be found in \src, depend on \include and \lib, and use art content in \media. The SDK installer plants prebuilt executables in \bin. Play around with the examples in the bin directory. Microsoft provides an discussion forum and a faq for like-minded developers to share information. They provide an an excellent article on starting with the framework at http://msdn.microsoft.com/voices/directx05152000.asp .
The only problem with Direct3D IM is that there are simply no good books on the material. In the moment, there's one exception: "3D Game Programming with C++" from John De Goes. I have known John from his time as an administrator of the Game Programming Forum at Compuserve. The Direct3D coverage is simply the best I found. The book is a must have for any Direct3D game programmer.


Compiling The Source

Get the source here:
http://www.directxgraphics.net/tutorials/tutorial1/tex7_1.zip

In our first example, we will take a look at the basic functionality provided by the framework and on one of the most simplified programms I can think of to use it. We will see a texture thrown at the back of a window and a timer, which shows the frames per seconds. This little programm will work windowed and fullscreen. Press Alt-F4 to switch between these modes. F1 will show you the about box. F2 will give you a selection of useable drivers and ESC will shutdown the app.

First let’s talk about the files you need to compile the programm. The best place to copy the files is in your Direct3D Immediate Mode source file Directory of the DirectX 7 SDK, which has to be installed. On my computer that would be for tex1: D:\mssdk\samples\Multimedia\D3DIM\src\tex7_1.

There are only four programm files:

tex1.cpp: the main file
winmain.rc: the resource file (Menu, Accelerator, Icon information etc.)
resource.h: header of winmain.rc
directx.ico: the icon you can see if the programm is minimized or if maximized in the left corner of the title of the window.

To compile the whole stuff, you should link it with the following *.lib files:
ddraw.lib dxguid.lib ..\..\lib\d3dframe.lib kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib shell32.lib uuid.lib winmm.lib

The d3dframe.lib is the static library, which holds the Direct3D 7 Framework. You can find the Framework source in the D3Dframe directory in D:\mssdk\samples\Multimedia\D3DIM\src\D3DFrame. We will walk now through a high-level view of the Framework to understand and use the Direct3D 7 Framework. The Framework consists of seven *.cpp files. These files encapsulates the basic functionality you need, to start programming a Direct3D game.

d3dapp.cpp exposes the application interface used for samples
d3dframe.cpp provides the framework that the application interface (in tex1.cpp) uses "under the covers"
d3denum.cpp contains enumeration support for drivers, devices, and modes
d3dtextr.cpp supplies texture support
d3dfile.cpp furnishes x-file support
d3dmath.cpp delivers math utility functions
d3dutil.cpp is a catchall for whatever miscellaneous useful functions remain
d3dApp.cpp module contains the class CD3DApplication. This class publishes the interface for sample programs, in the file D3Dapp.h. It provides seven functions:

  
    virtual HRESULT OneTimeSceneInit()     { return S_OK; }
    virtual HRESULT InitDeviceObjects()    { return S_OK; }
    virtual HRESULT DeleteDeviceObjects()  { return S_OK; }
    virtual HRESULT Render()               { return S_OK; }
    virtual HRESULT FrameMove( FLOAT )     { return S_OK; }
    virtual HRESULT RestoreSurfaces()      { return S_OK; }
    virtual HRESULT FinalCleanup()         { return S_OK; }


These are the functions we'll use in tex1.cpp to create our D3D app. They could be called the "public interface" for the Direct3D IM Framework. Now, let's dive into the source:

The Application class
The application class in tex1.cpp:


class CMyD3DApplication : public CD3DApplication
{
    D3DTLVERTEX m_Background[4];           // Vertices used to render the backdrop
    FLOAT       m_fStartTimeKey;           // Time reference for calculations

    static HRESULT ConfirmDevice( DDCAPS* pddDriverCaps,
                                  D3DDEVICEDESC7* pd3dDeviceDesc );

protected:
    HRESULT OneTimeSceneInit();
    HRESULT InitDeviceObjects();
    HRESULT DeleteDeviceObjects();
    HRESULT Render();
    HRESULT FrameMove( FLOAT fTimeKey );
    HRESULT FinalCleanup();

public:
    CMyD3DApplication();
};


The first two variables hold the vertices used to render the background and the reference for calculating the time. The method ConfirmDevice() checks the device for some minimum set of capabilities.
If you like to use only devices, which really support multiple textures, you can use the following code in this method:


if( pd3dDeviceDesc->wMaxTextureBlendStages > 1 )
if( pd3dDeviceDesc->wMaxSimultaneousTextures > 1 )
if( pd3dDeviceDesc->dwTextureOpCaps & D3DTEXOPCAPS_MODULATE )
return S_OK;


For the permanent initialization the function OneTimeSceneInit() is invoked once per application execution cycle. You can load textures and x-files, setup calculated values etc.. Basically any one-time resource allocation should be performed here. InitDeviceObjects() is used to initialize per-device objects such as loading texture bits onto a device surface, setting matrices and populating vertex buffers. The method DeleteDeviceObjects() is called when the app exits, or the device is being changed. It deletes any device dependant objects, which are intialized in InitDeviceObjects().

These two functions are matched pairs; be sure your device-specific resource allocations are matched with deletions, or you will be leaking memory every time a device change happens.

The Render() method is self-explaining. It is called once per frame and is the entry point for 3d rendering. It could set up render states, clear the viewport, and render a scene. In an animated programm, the method FrameMove() is used to hold the whole animation code such as updating matrices, texture coordinates, object coordinates, and other time-varying activities. This example doesn’t use any animation ... just a texture, which is thrown at the background. So it’s not used really. Well ... FinalCleanup() as the last protected method destroys for example the allocated memory for the textures, deletes the file objects etc. .

It's the counterpart to OneTimeSceneInit() and destroys any per-application objects. Watch out for memory leaks.

OneTimeSceneInit()


The first method, which is exported by the framework is OneTimeSceneInit():

HRESULT CMyD3DApplication::OneTimeSceneInit()
{
    // Initializes vertices used to render the background
    D3DVECTOR vFar =


Page : 1 Next >>