Life is a Space Odyssey: Final Report
From EQUIS Lab Wiki
Project Description
Our project is the conversion of Life is a Village (LIAV) into a martian lander simulator. The player will attempt to land a martian lander on a target located on a 3d terrain. They must navigate the terrain to locate the target and avoid crashing while monitoring their fuel usage. The player must be careful to control their speed in order to land on the target at a reasonable speed to prevent crashing. The lander will be subject to gravitational forces, as well as forces exerted by the engines. The user will control the forces exerted by the engines in order to pilot the lander.
Team Members
- Jason Kurczak
- John Bolton
- Cheryl Savery
Changes to the User Interface
The user interface for Life is a Space Odyssey is radically different in appearance from LIAV. The LIAV terrain has been replaced by a Martian terrain, complete with mountains, plains, and deep craters. The regular skybox has also been replaced with a skybox showing a view out into space. All trees and villagers are gone. The robot avatar has been replaced with a lunar lander model from the Google 3d Warehouse and the HUD has changed to show the the current fuel available and the height above the surface.
Particle effects are used to indicate when the engines are being fired and which engine(s) are being fired. Particle effects were also used to create a spectacular effect when the lander crashes on the martian terrain.
Sound was also added for ambiance and to simulate the sound of the engines firing.
Project Milestones & Schedule
Initial Stages of Development
Initially we planned a four stage development process as indicated below:
Stage 1 | Stage 2 | Stage 3 | Stage 4 |
---|---|---|---|
ODE physics engine | Add HUD | Transition from deep space to planet surface | Add obstacles |
New terrain | Thrusters to handle ship rotation | Collision detection with airborne objects | |
Lander model | Sound HUD |
Integration of the ODE physics engine with the LIAV software was identified as a key technical issue. As such it was tackled in the first stage so that if unforeseen problems arose there was still adequate time to revise the project. Using an actual lunar lander model was also considered to be crucial to the success of the game. Thus, determining how to convert existing Google SketchUp models to work with Ogre was also completed in the first stage.
Revised Stages of Development
At the mid-point of the term we reviewed and adjusted our initial plan. It was decided the transitioning from deep space to the martian surface would not greatly enhance the game play and this was eliminated from the project. The items in stage 4 of the initial plan were always considered optional extras and these were replaced with features such as joystick controls and particle and sound effects for the lander engines. The revised project plan is shown below.
Stage 1 | Stage 2 - March 10th | Stage 3 - March 16th | Stage 4 - March 19th |
---|---|---|---|
ODE physics engine | Physics model for lander | Keyboard control for in-game thrusters | Basically complete! Fun to play? Game-like? |
New terrain | Camera behaviour | Interactive sound with real sounds | Crash landings |
Lander model | Integrate terrain with OGRE | Landing target | Joystick controls |
Working sound in-game | HUD for fuel and height | Jet thruster flames |
As of March 19th, the project was essentially complete.
Technology
Sound in LIAV
The sound in LIAV is handled by the CAXSoundManager and CAXSoundSource classes. These provide a C++ wrapper for OpenAL and the ALUT toolkit, including object representations of sound sources and a sound listener, simplified loading of sound files, and compatibility with some Ogre classes such as vectors.
In simplified terms, sounds are associated with places, and as the user moves through them they are "rendered" to the correct speakers to provide 3D sound. To do this, sound files are loaded into OpenAL sound buffers, which are then tied to a certain location in space where the sound will originate from (a CAXSoundSource). Sound sources are not directional, and will decrease in apparent volume as the user moves away from them in any direction.
The user is represented by a Listener embodied within the CAXSoundManager, which contains a position and an orientation. This represents the user or avatar's "virtual ears" in the space, and so must be kept synchronized with the avatar's position and orientation. It is important to note that orientation includes both a "forward" direction vector and an "up" direction vector, up being required to resolve the ambiguity of an avatar that might be able to perform rolls about the forward axis. In LIAV up is always simply (0, 1, 0); however, in a flying or underwater game this would have to be calculated in each frame.
The only significant work required to get the sound running was to update the CAXGameState's UpdateAvatar method with calls to CAXSoundManager, to update the Listener's position and orientation to match the avatar's. Further information about the fix is available Getting Sound Working In LIAV.
3D sound is not required for Life is a Space Odyssey. The only sources of sound are the rocket engines (location is the same as the avatar, so the sound never changes in relative position) and background music which is not located spatially within the actual game.
OgreODE
In order to add proper physics, we chose to use OgreODE, an Open Dynamics Engine (ODE) wrapper. This physics wrapper supports all ODE primitives and adds prefabricated objects like vehicles, as well as providing rag doll support. The OgreODE download contains three tutorials/demoes, a simple scene that shows all the functions inside OgreODE ( primitives, collisions, joints, rag-doll physics, a car), a landscape showing use of the terrain scene manager in OgreODE, and finally a racing demo.
New Variables
In order to properly incorporate OgreODE into our project we created three new variables.
OgreOde::World *mWorld; OgreOde::Space *mSpace; OgreOde::StepHandler *mStepper;
The world is OgreODE’s topmost object, which is comparable to the root in Ogre. Every object is added to that world and must follow that the world’s rules (physics).
Defining the Physics
To define the physics of the world, several parameters are set.
mWorld->setGravity(Vector3(0,-9.8,0); mWorld->setCFM(10e-5); mWorld->setERP(0.8); mWorld->setAutoSleep(true); mWorld->setContactCorrectionVelocity(1.0);
The Space
The space (or collision space) is a collection of all the objects or geometries. Objects can collide within their space, with objects from other spaces, or not collide with anything at all.
The StepHandler
The StepHandler handles the time in the world and is used to update events. It runs every now and then (e.g. once per frame) and determines which body moves where and what collides with what.
There are several options available for how the calculations are done by the StepHandler. The default used in the OgreOde demos was the OgreOde::ForwardFixedStepHandler. Using this step handler with the default time step of 0.5 seconds resulted in visible shaking of the lander and the terrain. Decreasing the size of the time step reduced the shaking, but did not entirely eliminate it. Also as the size of the time step was decreased, it began to impact the frame rate. Changing the stepper choice to OgreOde::ExactVariableStepHandler completely eliminated the shaking problem and allowed us to set the time step back to 0.5 seconds.
CAXWorldODEObject & CAXAvatar
In order to use OgreODE a new class, CAXWorldODEObject, was created to replace CAXWorldObject. As a result, entities now have a mass and geometry. The mass object contains the total mass of the object and the centre of gravity within the body frame, given as a Vector3. The geometry of an object can be one of several types, box, sphere, cylinder, or triangular mesh. If a box geometry is used it must be passed as 3d vector.
The class CAXAvatar now inherits from CAXWorldODEObject, instead of CAXWorldObject. The mass and geometry for the avatar are passed in the constructor. The constructor creates an OgreODE::Body, applies the mass and geometry, and attaches the body to the scene node. CAXWorldODEObject also includes methods to access the OgreODE::Body and apply forces to the body.
FrameListener & Terrain
The StepHandler is included as part of the FrameListener, to update the ODE world’s time steps. The CollisionListener checks for contact between two bodies and applies the appropriate forces as a result of contact. It can set the level of bounciness as well as the friction.
The terrain is added to the world and space objects, which enables collision detection between the lander and the terrain.
Google SketchUp & Ogre
Google SketchUp is a free 3d modeling tool provided by Google. Google SketchUp has access to a large repository of free 3d models through the Google 3d Warehouse. In order to use SketchUp models with Ogre, a SketchUp to Ogre Exporter was installed. This consisted of a ruby based script for exporting a selection from a SketchUp scene to an Ogre .mesh xml file and an Ogre .material file. Following this export, the OgreXML convertor was used to generate an Ogre binary .mesh file which can be used in LIAV.
Changes to LIAV to Use SketchUp Models
In order to use SketchUp models in LIAV several small changes must be made. Most notably, if the default robot avatar is being replaced all animation for the avatar must be removed. The lunar lander model we used is static, does not contain bones, and will not change in-game, making animation unnecessary. As well, we found that the scaling and placement of the origin for the lunar lander model was not consistent between LIAV and SketchUp. As such, the model must be scaled up several times in LIAV and the model must be translated in SketchUp such that the base is at the global SketchUp origin, as expected by LIAV.
Terrain Generation
A custom terrain was necessary for our project to create an appropriate martian landscape. Using existing data available from Google Maps, we were able to create a custom height map based on real Mars mapping data. We generated this height map in Adobe Photoshop. We cropped our initial image to 513 pixels on each side, changed it to a grayscale image, and applied a slight gaussian blur to smooth out the rough transitions the terrain height map would result in. We were easily able to modify the maximum and minimum heights by changing the brightness and contrast values, as well as editing terrain.cfg to change the maximum height. Our resulting image was a grayscale height map useable by Ogre, that when combined with our texture map gave us a nice Martian terrain.
Implementing A Custom Skydome
Our project also required a custom space skydome, giving the users a view of the stars when playing. In order to do this, we first found an appropriate high resolution jpeg image to display on the skydome and created a custom material in the sky.material file in the include directory. To create the custom material we used the following code.
material CAX/SpaceSkyBox { technique { pass { lighting off depth_write off texture_unit { texture space.jpg } } } }
In order to apply our material to the skydome, we modified CAXApplication. First, we removed the fog, as this was obscuring the visibility of the skydome. Following this, we set the current skydome to our material and tweaked the parameters to ensure it properly wrapped the skydome and tiled the space jpeg image an appropriate number of times.
Particle Effects
Particle effects were added to the lander object in order to give the player a visual indication of when the lander engines were being fired. The effects used were based on two jet engine sample effects that came with Ogre. The particle file used is shown below.
particle_system Examples/JetEngine3 { material Examples/Flare particle_width 15 particle_height 15 cull_each false quota 200 billboard_type point emitter Point { angle 2 emission_rate 100 time_to_live 1 direction 0 -1 0 velocity_min 350 velocity_max 400 colour_range_start 1 1 0.5 colour_range_end 1 0.8 0.3 } affector ColourFader { red -0.25 green -1 blue -1 } }
Four instances of the particle effect were attached to the lander scene node. When the engines were fired, the particle effects associated with the engine(s) are set to visible and the emitters are enabled.
A second particle effect was created for when the lander crashes on the martian surface.
Architecture
Workspace Architecture
Below is a conceptual-level Workspace Model schematic of the game architecture used in the Life is a Space Odyssey game.
In Life is a Space Odyssey, the bicycle used in LIAV has been replaced by the mouse and keyboard. The joystick is an optional alternative to the mouse and keyboard. The A/I component from LIAV is no longer required and the basic physics used in LIAV has been upgraded to use the OgreOde physics engine.
Implemented Game Design UML
This very high level diagram shows which components own which others. It also shows which namespace a module may be found in. On each frame, the game object gets passed control. It calls its input manager to poll the various game devices being used, tells its various managers to update their sub-objects, and moves the lunar lander and camera inside the OGRE scene.
"World ODE Objects"
The CAXWorldObject class in LIAV has been replaced by the class CAXWorldODEObject.
The original CAXWorldObject stored the following information about each object in the game world
- position, direction, and scale
- references an ogre mesh object
- when the object or person is moved, the corresponding mesh object moves in the game world, too
- actual data owned by the object is hidden in an OGRE-independent data source (CAXWorldObjectData)
In addition to all of the features from the original CAXWorldObject class, the new class CAXWorldODEObject contains attributes and methods to support the use of OgreOde physics on the objects. The new attributes include:
- mass
- geometry
Additional methods were also added to the class CAXWorldODEObject to allow forces to be applied to an object.
In Life is a Space Odyssey, there is only one type of object that inherits from CAXWorldODEObject. The class name of Avatar continues to be used. However, it now represents the lunar lander instead of the robot from LIAV.
Input Manager
The input manager is responsible for:
- polling the input devices (mouse, keyboard and joystick).
- mapping the device inputs to the appropriate game control actions
- apply force to lander
- camera pitch and rotation
- restart game
- program exit
Sound Manager
The CAXSoundManager and CAXSoundSource classes are used to run the sound in LIASO
CAXSoundManager manages:
- creation of OpenAL sound buffers from .wav files
- creation of OpenAL sound sources and their mapping to CAXSoundSources
- movement and orientation of the OpenAL sound listener
Each CAXSoundSource manages (through a mapping to an OpenAL sound source):
- the location of its sound in the audio space
- the playback of its sound buffer (play, pause, stop, looping, etc.)
- the volume and pitch of its sound buffer
Sound Engine UML
Interaction With Other Groups
Our interaction with other groups has been limited to providing documentation on:
- Getting sound working in Ogre;
- Using OgreODE; and
- Using the Google SketchUp Ogre Exporter.
This documentation consisted of step-by-step installation, configuration, and building instructions. Links to this documentation can be found on the Main page of the CISC 877 - Equis Lab Wiki and are also provided below:
Who Did What
Jason:
- Sound
- Adding ODE properties to the Lander
- HUD for Fuel and height
- Joystick Controls
- Control for restarting game
John:
- Graphics for all game objects: Lander Module, Landing Target and Tower
- Terrain and Skybox
- Camera behavior
Cheryl:
- Compilation of Ogre Ode source files and demos and integration of Ogre Ode with LIAV
- Adding ODE properties to the Lander
- Keyboard control for thrusters on Lander
- Particle effects for thrusters and crash landings
Lessons Learned
Overall, the entire project went well. We were able to divide the work into areas with as little overlap as possible. This allowed each of us to work on a separate section of the project and there was little difficulty in recombining versions of the code.
To some extent we were able to leverage each person's technical background to our best advantage. John's experience with graphics enabled us to use existing Google SketchUp models for the lunar lander and for the landing target. Jason's experience with sound engines was helpful for tracking down the bugs with the sound in the original LIAV software and for adding sound to the Life is a Space Odyssey game.
We had identified integrating OgreOde with LIAV as one of the key technical issues for the project. Thus, we tackled the integration of OgreOde early on, ensuring that it would not become a show stopper late in the project. By the mid-point of the term, we had a playable demo and all features added since then have merely improved upon the game experience.
If we repeated this project, there are no major changes that we would make to the development process.