The following animation was created in Maya 3D. It consists of 2 meshes and was successfully exported to DirectX. Being my first animated model, it is extremely basic…It can be downloaded below.

Maya Gun Animation

Maya Gun Animation 2

DirectX Gun Animation

DirectX Gun Animation 2

The files for the Gun and Bullet can be downloaded here.

VN:F [1.8.8_1072]
Rating: 0.0/10 (0 votes cast)
VN:F [1.8.8_1072]
Rating: 0 (from 0 votes)

Chapter 1

1.1 Introduction

Titled “Dundonia”, this is a 3D platform based adventure game. The user takes control of the main character, Tiny, taken from the DirectX Samples, and guides her through the level towards the finish. She is able to walk and jump. The user must find the skull and avoid all spheres. Tiny has only 3 lives, and a timer is available for personal scores. Two different camera types are available, 1st and 3rd person. A background track is playing which can be toggled on or off.
The special feature that is utilised is the terrain. Not all of the terrain is used in the demo due to its large scale.

The key mappings are tabulated below:

Dundonia Key Mappings


1.2 Project Brief

The project brief as provided at the beginning of this project, January 2008:
You are to produce a 3D computer game incorporating the following features:
a) Keyboard and mouse interaction
b) Audio
c) Simple physics (collision detection)
d) Use of an effects file

In addition, your game (or its production) must incorporate knowledge or techniques gained from researching one of following areas:
1) Scripting engines
2) Psychoacoustics
3) Advanced physics (such as rigid body dynamics)
4) Terrain generation
5) Any other “advanced” area that has been agreed with LDN

Chapter 2

2.1 Structure

The application primarily utilises an object-oriented structure. All features are encapsulated within their own classes. This aids readability and allows easy access to all methods giving greater flexibility in designing the feature set of the application. Dundonia’s architecture is based on Frank Luna’s Framework. [ A ]

The overall program consists of 56 files which are made up of 26 header files, 23 main files and 7 effects files. The majority of the files contain only one class but with a few exceptions.

The overall application has been divided into an engine with separate game specific files. Titled the Contagious Engine, it is mainly an integrated collection of the sample files available with [ A ]. It provides the following features:

  • Audio
  • Camera
  • Effects
  • Entities
  • Input Devices
  • Physics
  • Animated Meshes
  • Static Meshes
  • Terrain
  • DirectX Specific Utilities
  • Sky
  • Water

The game specific files consist of the main level itself, the game logic and the splash screens.

2.2 Code Organisation

2.2.1 Contagious Engine:

The purpose and implementation of each feature of the Contagious Engine is described below.

A. Utilities

As Direct3D is a low-level graphics API, a general application framework is required in order to access the available functions. The Utilities section of the engine contains 8 files: d3dApp.h/.cpp, d3dUtil.h/.cpp, GfxStats.h/.cpp and Vertex.h/.cpp.
The d3dApp class is the base Direct3D application class, which provides functions for creating the main application window, running the application message loop, handling window messages, initialising Direct3D, handling lost devices and enabling full-screen mode. Five virtual functions are consistently overwritten in the other files.

  • CheckDeviceCaps
  • onLostDevice
  • onResetDevice
  • updateScene
  • drawScene

The benefit of this structure is that the d3dApp class will handle all of the auxiliary processes mentioned above.

The d3dUtil files contain utility code that many files access. This consists of extra debugging builds, global parameters, extended structures for colour, materials, light and bounding volumes.

The GfxStats class keeps track of and displays the frames rendered per second, milliseconds per frame, and vertex and triangle counts. It also displays all screen messages and the player’s statistics.

The Vertex.h/.cpp files contain vertex structures and declarations that are required by the following classes

  • PSystem
  • UnitCube
  • PlayerCharacter
  • StaticMesh
  • Level1
  • Terrain
  • SkinnedMesh
  • SolarSphere

B. Audio

CAudio.h, CSound.h, SoundGlobals.h, CAudio.cpp and CSound.cpp handle the audio capabilities of the application.
The CAudio class is created to initialise and manage the DirectX audio objects. Creating an object of this class automatically initialises all audio components.
SoundGlobals.h contains the DirectX and audio class headers. The main audio object is declared extern for use in all source code files.
CAudio.h defines the CAudio class. It has a constructor which calls InitAudio() to initialise DirectXAudio. The default directory is set which contains the audio files. The destructor calls KillAudio() which releases all interfaces. Two private objects are declared. The performance object handles the playback related features. The loader object is responsible for loading sound files. SetMasterVolume alters the volume of the application.
The constructor in CAudio.cpp sets the performance and the object loader to Null and then calls InitAudio(). As DXAudio is all COM, it must be initialised first otherwise any other function will fail. To get the performance and loader objects CoCreateInstance() is used. The first parameter is the class identifier, CLSID, of the object to be retrieved. The fourth parameter contains a reference to the identifier and the last one is the address of the variable that receives the object. Then the performance object is used to initialise the performance by calling InitAudio(). Null is passed to the first two parameters, IDirectMusic and IDirectSound objects. A handle to our window is passed in the next parameter. A default audio path is created and 64 channels are allocated to it. DMUS_AUDIOF_ALL enables all audio features and the last parameter means that default values are used for the synthesizer.
CSound.h holds one sound represented by the IDirectMusicSegment8 data type. Member functions manage playback and change the behaviour of the sound file. Pointers to the performance and loader objects are taken from the CAudio class because they are essential for loading and playback of the sound. The constructor is responsible for loading and the destructor unloads the sound from memory.
The segment is created using CoCreateInstance() in CSound.cpp. The filename has to be converted to wide char. The loader object is needed to load a sound from a file. The band data is downloaded to the performance. The destructor unloads the data from the performance so that the segment can be released from memory. The performance is used to play the segment and it is played on the default audio path.

C. Camera

The 1st person camera is implemented in the Camera.h/.cpp files. The 3rd person camera is implemented in the PlayerCharacter class as it follows the character and the relevant matrices are used for other calculations.
Four camera vectors are used to define a local coordinate system for the camera relative to the world coordinate system: right vector, up vector, look vector and position vector. To implement movement in the look vector and right vector, the camera must be translated along those axes respectively. For the up and down movement, the look and up vectors must be rotated around the right vector. For the left and right movement, all the basis vectors are rotated around the world y-axis.

Most of the methods in the main class file are trivial as they are simply for accessing values. The update function updates the camera and builds the relevant view matrices. This is done by calling buildView(). As the mouse input is not required for this demo, the sensitivity of the mouse was greatly decreased. buildView() calculates all the required matrices. The camera’s height is affected by the terrain’s height. The terrain class calculates the correct height of the camera by determining the height of the cell that the camera is currently in. This value then updates the camera.

The Level1 class calls setLens each time the device is reset. This setLens function calculates the aspect ratio of the scene.

For the 3rd person camera, the update function in the Level1 class gets the characters current direction that she is facing. The camera’s lookAt vector is then set to always face the characters position.

D. Direct Input

DirectInput.h defines the class which handles the mouse and keyboard input for the application. This works directly with the input drivers via IDirectInputDevice8. It is used to obtain pointers to the IDirectInputDevice8 objects. Initialising the keyboard and mouse is done by creating the device, setting the data format, setting the cooperative level and acquiring the devices. The devices are polled by using the GetDeviceState method. This returns the current state of the keyboard or mouse in relation to how they have changed since the last time they were checked.

E. Physics

A particle system is utilised in the creation of the fire ring. PSystem.h defines the abstract class which handles the generic work required by the particle system. Any new particle system can be derived from this class. The constructor and destructor primarily do memory allocation work. The constructor automatically allocates enough memory for the maximum number of particles meaning that no extra memory is required at run-time. A time function and world matrices are set. Dead particles are reinitialised when more are needed. The update function increments the time depending on how much has passed between frames. It checks each particle to determine whether or not it is dead and adds it to the appropriate list. The virtual draw() function draws the particle system.


Random particles are generated on the ring in its local space. A random z-coordinate is generated at some interval for each particle to add depth. The size, initial colour and initial velocity are randomised to add variation to the system. The particle is assigned according to time, mTime. mTime increments and the age of the particle can be determined by computing the difference of mTime – particle.initialTime. The random velocity assigned ensures that the particles do not fly of the ring.


The motion of the particles, such as the rotation and the physics calculations, and other adjustments, such as the color fade and size ramp are performed by the vertex shader thus freeing the CPU.

F. Sky

An environment map is used to texture the sky sphere. This sphere surrounds the entire scene with an image of the sky with distant mountains painted on it. The sphere is centred about the camera in world space which gives the illusion that is infinitely far away.


The sky is assigned the maximum depth buffer values and is never clipped.

G. Water

The water is implemented using normal maps. A triangle mesh grid on the xz-plane represents the water’s surface. By using two normal maps, the normals of high frequency waves can be captured. These normal maps are scrolled over the water surface at different rates and directions. Each pixel is sampled and the average value is rendered. As different rates and directions are used, this gives the illusion of new waves forming and dispersing continuously.


The water reflects the sky’s surface by using an environment map. To simulate ripples and distortion in the reflection, the look up vector of the environment map is perturbed by the net normal. As the net normal varies, this produces the ripple effect.

H. Static Meshes

d3dUtil.h/.cpp contains a function to facilitate loading .X files. The StaticMesh class actually loads the .X files.
The constructor loads the files, calculates the relevant world matrices and bounding boxes. The bounding boxes are calculated by locking the vertex buffer, recording the minimum and maximum vertices of the mesh and then releasing the buffer. These values are then stored in pBBMeshes. pBBMeshes then calls the getWorldAABB() which calculates the minimum and maximum points in each of the axes. The getWorldAABB() then returns the coordinates of the bounding box.
The destructor releases the meshes and textures. The drawScene() function contains the actual rendering code. It applies Phong Shading to the meshes.


The vertex normals are interpolated across the face of the triangle during rasterization and then the lighting calculations are performed per pixel. Per pixel lighting gives better results than per vertex lighting.

I. Skinned Mesh

The main character, Tiny, contains a hierarchy of bones and a skinned mesh. To animate the character, vertex blending is performed. This animates a particular part of the mesh with respect to the other connected parts.
SkinnedMesh.h defines the class which facilitates the loading and animating of the skinned mesh. The D3DXFRAME structure is used to represent the bones of the character. D3DXMESHCONTAINER specifies what type of mesh it is. The ID3DXAnimationController interface is responsible for animation.
AllocMeshHierarchy.h/cpp contains 4 abstract methods which implement an ID3DXAllocateHierarchy interface. This is required in order to create and destroy a mesh hierarchy using the D3DX functions.
D3DXLoadMeshHierarchyFromX loads the animated character mesh data from the .X file. The bones and vertices which are attached are defined in this file. The hierarchy is searched for the frame that contains the skin data. The vertex format of the mesh is converted using the ConvertToIndexedBlendedMesh method. An array of pointers to the to-root transformation matrices of the bones is constructed.
For drawing the mesh, the position of every bone is recalculated and the transformation matrix is applied to every vertex and its corresponding bones. To show the steps of the animation, the transformation is interpolated between the normal position of the bone and the animated position of the bone, using the time elapsed from the beginning of the animation.


The shader performs vertex blending with a maximum of two bone influences per vertex. Only one vertex weight is required for this calculation.

J. Entities


The spheres provide the obstacles for the character. They are created by animating a mesh hierarchy and the positions are stored in an array in the Level1 class. The outer spheres are children of the centre, and so they rotate about the centre.


The crates form an indicator of the location of the skull. They are created by constructing unit cubes and are detailed via texture mapping. Once the texture is loaded, it is set as an effect parameter so that it can be used in a pixel shader.


After the texture coordinates are output for each vertex, they are interpolated during rasterisation. These are then sent to the pixel shader. The diffuse, combined with ambient, and specular properties are passed independently as specular material is not wanted.
This class contains the main character’s code. This class calls the SkinnedMesh class, and the Level1 class calls functions in this class.
The character’s mesh is loaded and the world position and scale is set in the constructor. These are calculated in separate functions. Tiny’s world position, world matrix, yaw, facing, translation, acceleration and jump vectors are calculated. The net directional vector is calculated. The character is then rendered in the drawScene() method.

2.2.2 Game Specific Files:

The game specific files provide the following functionality.

A. SplashScreen and MenuScreen

These classes render the splash-screens and menu respectively. The images are 2D sprites and is accessed from the ID3DXSprite interface.

B. PlayerStats

This file contains extern declared functions for the player’s lives, time and whether or not the player has collected the skull.

C. Level1






Chapter 3

3.1 Terrain Generation

The terrain generated begins with a flat grid. The heights are adjusted at various points and a texture is applied.

3.2 HeightMaps:

A heightmap is created which is used to describe the hills and valleys in the terrain. Using Luna’s heightmap as a base, Terragen was used to modify the map. The format used for this is 8-bit RAW.
A Heightmap class was created to handle the map. This loads the .raw file and filters the image.

3.3 Grid Geometry:

The terrains grid geometry is created by generating the vertices row by row in a top-down fashion. The y-coordinate is modified by setting it to the corresponding heightmap entry. D3DXCreateMesh is used to store the grid which allows the use of the D3DX mesh optimization and utility functions.

3.4 Sub – Grid Culling:

In order to reduce the frame rate by not drawing sections of the terrain, frustum culling was introduced. The terrain was divided into sub grids, and for each sub-grid an AABB was constructed. If no part of the sub-grid’s AABB is visible, then the sub-grid will not be rendered at all.
In order to determine whether an AABB intersects the frustum, six planes of the frustum are required. These planes can be extracted from the projection matrix.

3.5 Textures:

The texture is created by combining several maps to form a net texture. These textures are tiled over the terrain to increase the resolution. A blend map is then used which controls how much of the corresponding texture shows up in the final image.

3.6 Terrain.fx:

This contains the shader used to light the terrain. Specular lighting calculations are removed as the terrain is a mostly diffuse surface.
Fog calculations are also performed.

Chapter 4

4.1 Appraisal

4.1.1 Code Organisation

The code has been separated into many different class files. This is the most optimal approach for large programs. However as the entire program has been put together piece by piece, in comparison to a program that has been designed completely, there are inconsistencies in places. The variable names do not follow a particular convention, specifically between the audio code and the rest of the application. A state manager should have been implemented, providing greater flexibility.

Member variables should not be public, however for a few cases I required access to these parameters. The correct approach would be to create a function that returns these values.

4.1.2 Collision Detection

The collision detection employed in the application is not entirely accurate. This is due to the meshes not being to scale. All meshes were sourced from the internet and the DirectX samples. As the bounding box computes its size according to the size of the original mesh, I applied the same scaling vector on the bounding box. This only worked satisfactorily in some cases.
A more suitable approach is to integrate PhysX. This was my original intention but there were issues with the terrain. I succeeded with the collision detection for the meshes and tiny. As tiny is a skinned mesh, this was not straight forward. This issue was averted by placing a bounding sphere at her feet which provided realistic detections. Regardless of what was tried, importing the terrain into PhysX was fruitless.

4.1.3 Static Meshes

The mesh loading feature of the application could be streamlined. In its current state, each mesh has to be defined individually. Instead of this, the same method could be used for each mesh.

4.1.4 Animation

The main character utilises only one animation. Due to time constraints, it was not possible to research the appropriate functions in order to extract the other animations.

4.1.5 Effects Files

As many calculations are passed to the vertex and pixel shader, this frees the CPU. The .fx files are executed on the graphics card’s GPU. Future designs could endeavour to send more calculations to the pixel shader.

4.2 Evaluation

The mesh fulfils the requirements of the application. Before choosing this type of terrain, I researched the Fractional Brownian Motion terrain provided with the course notes. Whilst it would have been adequate for this project, the current terrain looks more realistic.

The effect file for the terrain also contains fog calculations. It is set quite small but the effect is still noticeable.

4.3 Conclusions

This demo covers a vertical slice of the gameplay of a 3rd person adventure game. It contains a variety of techniques used to render special effects, vertex blending, character animation, terrain rendering, multi-texturing, particle systems, reflections and stencilling using shaders.
A simple game engine has been created which could be adapted to other genres of games. Whilst I did not write the engine from the beginning, I now have an in-depth knowledge of the minimum requirements of an engine, and the issues facing DirectX programmers.
For a novice considering a similar task, I would recommend adding one feature at a time and using a similar implementation method. However if the person is experienced, there is no substitute for perfect design. My next game will be designed completely before any files are created.

4.3.1 Frame Rate

The frame rate is currently running at 38fps. The meshes in the world have consumed too many frames. A more efficient strategy would have been to import all meshes into a 3D modelling package and reduce the polygon count of each one before importing into DirectX.

4.3.2 Debugging

The DirectX Console was used as the program gained in size. Whilst there were no errors in the code, on many occasions’ breaks occurred. The detailed output proved to be a useful tool.

4.3.3 MSDN

I personally found the information available in books, 3rd party websites and forums easier to read than the enormous MSDN. Searching for a specific topic can become quite tedious due to the sheer scale of the forums.

4.3.4 Implementation Method

Being my first game, the majority of the features were new to me. Each new feature was first implemented separately in another project and so if errors occurred which were ambiguous, the original project was used as a guide to rectify the problem.

4.3.5 DirectX SDK Version

The project is not compatible with the March 2008 version without modifications to the audio files. This issue did not really affect me as I had access to the August 2007 version, but I feel that this is a problem that Microsoft has overlooked.

Chapter 5

5.1 References

[ 1 ] Ingmar Rötzler,
[ 2 ] Keith Ditchburn,

5.2 Bibliography

[ A ] Luna, F. D. 2006, Introduction to 3D Game Programming with DirectX 9.0c : A Shader Approach, Wordware Publishing, Texas.
[ B ] Natanson, Dr. L. 2007, Games Programming Course and Laboratory Notes, University of Abertay, Dundee.

VN:F [1.8.8_1072]
Rating: 0.0/10 (0 votes cast)
VN:F [1.8.8_1072]
Rating: 0 (from 0 votes)


The overall program contains 10 header files and 8 main files. These cover all of the following features: Textures, Materials, Lighting, Stencil and Depth buffering, World, View and Projection transformations and Meshes (loading and animating).

The files are baseplane.h, camera.h, d3dUtil.h, d3dUtility.h, ExtendStructure.h, MeshHierarchy.h, pSystem.h, structures.h, unitcube.h, XFileEntity.h, baseplane.cpp, d3dUtility.cpp, unitcube.cpp, MeshHierarchy.cpp, pSystem.cpp, camera.cpp, XFileEntity.cpp and main.cpp.

d3dUtil.h, ExtendStructure.h, MeshHierarchy.h, structures.h, XFileEntity.h, MeshHierarchy.cpp and XFileEntity.cpp primarily deal with the animation. The others deal with achieving the effects performed.

The general structure follows that of the programs found in [ A ] but with a few exceptions. The majority of the programs deal with one specific area.

Description of Code Organisation

The main file performs the following actions:

Initialises Global Variables.

Initialises the Lights.

Initialises the Materials.

Initialises the Camera. Specifies Land.

Updates the Camera.

Initialises the Stencil Buffer.

The Setup Function setup’s up the various objects:

Snow System

Static Mesh. This mesh object stores the mesh data.

- Materials for the Mesh

- Optimises the Mesh



Animation This is set on animation 2.





Stencil Buffer

It then cleans up



Static Mesh

Snow System

The display function displays the relevant data onto the screen. All objects have to be applied to the world transform.




Materials For the House


Snow System – The snow system must be rendered last.

baseplane.h and baseplane.cpp deal with rendering the baseplane. Unitcube.h and unitcube.cpp deal with rendering the cube. These were given in the labs.

Camera.h and camera.cpp deal with the camera functionality. Psystem.h and psystem.cpp deal with the snow systems functionality. These can be found in [ A ].


Four camera vectors are used to define a local coordinate system for the camera relative to the world coordinate system: right vector, up vector, look vector and position vector.

The camera can perform the following operations:

  • Rotate around the right vector (pitch)
  • Rotate around the up vector (yaw)
  • Rotate around the look vector (roll)
  • Strafe along the right vector
  • Fly along the up vector
  • Move along the look vector

The camera can support 2 types of models: LANDOBJECT or AIRCRAFT. The air model allows more freedom but the land model is more suitable for the purposes of this program. The view space transformation must transform the geometry in the world so that the camera is centred at the origin and the axis aligned with the other coordinate axes. To find this, a translation that takes the camera position to the origin and a rotation that aligns the camera vectors with the world’s axes is required. The Camera::getViewMatrix method performs this operation.


The following effects are present:

Textures, Lighting, Shadow, Particle System – Snowflakes. There are 2 meshes present, animated and static.


This is taken from the cube shadow program from [ C ]. The light and baseplane positions are used as inputs. The D3DXMatrixShadow() function flattens the world matrix and the object is rendered into the plane. The textures must be removed and alpha blending is enabled. The depth buffer must be disabled to avoid issues in the z-axis. The stencil buffer is enabled to ensure that only one layer is rendered. A semi transparent material is added to give the resulting shadow.


There are 2 main lights, one us attached to the camera whilst the other is the main light.

The steps involved in creating the lights

1. Enable lighting.

2. Create a material for each object and set the material before rendering

the corresponding object.

3. Create one or more light sources, set the light sources, and enable


4. Enable any additional lighting states, such as specular highlights.

In camera.cpp, a light is attached. In main.cpp, the other light is set up and both are initialised here.

Particle System – Snowflakes:

In pSystem.h, the Snow system’s class is defined. In pSystem.cpp, the constructor takes a pointer to a bounding box structure and the number of particles the system will have. The bounding box describes the volume that the snowflakes will fall in. All snowflakes outside of this volume are killed and respawned. This keeps the number of active particles the same at all times.

The size of the vertex buffer, the batch size, and the starting offset must all be defined. The resetParticle method creates snowflakes with random x- and z-coordinate positions inside the bounding box and sets the y-coordinate to be equal to the top of the bounding box. It then gives the snowflakes a velocity so that the snowflakes fall downward and

slightly toward the left. The snowflakes are white in colour.

The update method updates the position of the particle and then tests if the particle has gone outside the system’s bounding box. If it has gone outside the bounding box, it is respawned.

This method is then called from the main file.


There are 2 types of meshes rendered, static and animated. The static mesh was derived using Luna’s methods whilst the animation was created using [ D ].

Static Mesh – House:

An ID3DXMesh object is created and the geometric data of the XFile loads into it. As the texture is not embedded but rather the filename, it is automatically loaded with the .X file.

The mesh is loaded such that each entry point has a corresponding subset and this loops until all entries have been rendered. The setup, display, render and cleanup functions are all implemented.

Animated Mesh – Skeleton:

For animation a model hierarchy must be implemented. ID3DXAllocateHierarchy is created for the frame and mesh data. This class defines the following functions:

1. CreateFrame – requests allocation of a frame object

2. CreateMeshContainer – requests allocation of a mesh container object

3. DestroyFrame – deallocation of frame object

4. DestroyMeshContainer – deallocation of mesh container object

The main method for loading animation data, skin info and hierarchy is D3DXLoadMeshHierarchyFromX. The hierarchy is loaded as a frame and mesh data tree. There is a pointer to the animation controller and to the top of the frame hierarchy. The trees are traversed and the meshes data is rendered accordingly.

Skinning is then performed which takes data in a mesh-skeleton hierarchy and applies geometry blending to transform the mesh vertices. Each bone is positioned to its parent via a local bone matrix. exFrameCombinedMatrixPointer contains pointers to the correct frames combined matrix. A bone offset matrix is used to wrap the mesh skin around the bones. These 2 matrices are combined resulting in a matrix which is inputted into the UpdateSkinnedMesh function. This alters the vertices based on the input and a set of weights which carries out the skinning.

Software skinning is used to render the mesh. The animation itself contains 4 different scenes.


[ A ] Frank D. Luna (2003) Introduction to 3D Programming with DirectX 9.0, Wordware Publishing, ISBN : 1-55622-913-5

[ B ] Frank D. Luna (2006) Introduction to 3D Programming with DirectX 9.0c, A Shader Approach, Wordware Publishing, ISBN -13: 978-1-59822-016-2

[ C ] Dr. Louis Natanson (2007) Games Programming Course and Laboratory Notes, University of Abertay, Dundee.

[ D ] Keith Ditchburn,

VN:F [1.8.8_1072]
Rating: 0.0/10 (0 votes cast)
VN:F [1.8.8_1072]
Rating: +1 (from 1 vote)