Axiom






2.14/5 (4 votes)
How to setup an Axiom application

Introduction
This sample will focus on how to setup a resizeable Axiom window as a stand alone control. To do this, most of the setup stuff will be happening behind the scenes. I suggest you first read the Basic Tutorials about Axiom since I won't be covering anything about Axiom other than the setup procedure in the context of the sample application.
Background
Axiom is a C# port of the great Ogre3D engine. This has a number of advantages such as being faster than a wrapper such as MOGRE. However it also means that it takes a lot more work to keep up to date with Ogre3D since everything has got to be written from scratch. For more information on Axiom and Ogre3D, see references below.
Setup
Download Axiom (Full 0.7.3) and extract to C:\Program Files\Axiom, then copy all the debug DLLs in the bin directory into the provided “Axiom DLLs” directory. Also make sure you have a Managed DirectX SDK installed as well.
Sample Application
The sample application has three main components - these are the Axiom Manager, Axiom Window and Test Form. The Axiom Manager is responsible for configuring and initializing Axiom. The Axiom Window is a custom control that can be placed on any Windows Form. Finally, there's the Test form which is the main form of the application.
Axiom Manager
Axiom manager is a singleton class that handles configuration and automatically sets up the engine for use by the AxiomWindow
(the custom control).
Configuration Management
Currently configuration management isn't completed/existing as it only provides some defaults for initializing the engine such as the name of the log file and resource configuration file.
Setup
This part of AxiomManager
is responsible for initializing the engine with the default configuration and loading the resource configuration file.
private void SetupAxiom(Configuration.AxiomConfiguration axiomConfig)
{
// create root element
m_root = new Root(axiomConfig.ConfigFile, axiomConfig.LogFile);
// load resources
SetupAxiomResources(axiomConfig.ConfigFile);
// initialize root
RenderSystem temp = m_root.RenderSystems[ 0 ];
m_root.RenderSystem = temp;
m_root.Initialize(false);
}
Axiom Window (the Custom Control)
The AxiomWindow
control is a user control that is fully resizeable. Axiom window has two main sections - these are Initialization and resize support.
The Initialization section just creates a new RenderWindow
of the same dimensions as the control using the Axiom Manager and the current configuration.
public void Init()
{
// get the manager and configuration
AxiomManager axiomManager = AxiomManager.Instance;
Configuration.AxiomConfiguration axiomConfig = axiomManager.Config.AxiomConfig;
// create a render window of the same size
m_currentSize = new Size(Width, Height);
m_window = axiomManager.Engine.CreateRenderWindow(Name, m_currentSize.Width,
m_currentSize.Height, axiomConfig.ColorDepth, false, 0, 0,
axiomConfig.DepthBuffer, axiomConfig.VSynch, this);
m_initialized = true;
}
The interesting bit is the resize support code which takes place in OnResize
. This updates the camera's aspect ratio if AutoAspectRatio
is turned on (so that if the window's aspect ratio changes, the image still looks good) and then rebuilds the render window if its new size is 15% more or less than the RenderWindows
current size. This means that the image will always look good since it's never more than 15% too small or large.
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
if(m_initialized) {
// update the camera's aspect ratio (so the image doesn't look distorted).
if(Camera != null && AutoAspectRatio) {
Camera.AspectRatio = (float)Width / Height;
}
// Check if the window has grown or shrunk by more than 15%.
if(Width > m_currentSize.Width * 1.15 || Width < m_currentSize.Width * 0.85 ||
Height > m_currentSize.Height * 1.15 ||
Height < m_currentSize.Height * 0.85 ) {
// we need to rebuild renderwindow
// save current size and camera
m_currentSize = Size;
Camera camera = Camera;
// destroy render window
AxiomManager.Instance.Engine.DetachRenderTarget(m_window);
m_window.Dispose();
m_window = null;
m_viewPort = null;
m_initialized = false;
// initialize window
Init();
// update camera
Camera = camera;
}
m_window.Update();
}
}
Test Form
The Test form is the main form of the application and contains one Axiom Window (though it could of course contain more). Most of the work happens in OnLoad
which initializes the axiom window, sets up the example scene, and finally starts the rendering process. Note that the scene code comes straight from one of the Axiom samples.
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
try
{
// initialize window
this.axiomWindow1.Init();
scene = AxiomManager.Instance.Engine.SceneManagers.GetSceneManager(
SceneType.Generic);
// create a camera and initialize its position
camera = scene.CreateCamera( "MainCamera" );
camera.Position = new Vector3( 0, 0, 500 );
camera.LookAt( new Vector3( 0, 0, -300 ) );
// set the near clipping plane to be very close
camera.Near = 5;
// create a new viewport and set it's background color
axiomWindow1.Camera = camera;
// set default mipmap level
TextureManager.Instance.DefaultNumMipMaps = 5;
// call the overridden CreateScene method
// set some ambient light
scene.AmbientLight = new ColorEx( 1.0f, 0.2f, 0.2f, 0.2f );
// create a skydome
scene.SetSkyDome( true, "Examples/CloudySky", 5, 8 );
// create a simple default point light
Light light = scene.CreateLight( "MainLight" );
light.Position = new Vector3( 20, 80, 50 );
// create a plane for the plane mesh
Plane plane = new Plane();
plane.Normal = Vector3.UnitY;
plane.D = 200;
// create a plane mesh
MeshManager.Instance.CreatePlane( "FloorPlane", plane, 200000, 200000, 20,
20, true, 1, 50, 50, Vector3.UnitZ );
// create an entity to reference this mesh
Entity planeEntity = scene.CreateEntity( "Floor", "FloorPlane" );
planeEntity.MaterialName = "Examples/RustySteel";
scene.RootSceneNode.CreateChildSceneNode().AttachObject( planeEntity );
// create an entity to have follow the path
Entity ogreHead = scene.CreateEntity( "OgreHead", "ogrehead.mesh" );
// create a scene node for the entity and attach the entity
headNode = scene.RootSceneNode.CreateChildSceneNode( "OgreHeadNode",
Vector3.Zero, Quaternion.Identity );
headNode.AttachObject( ogreHead );
// retrieve and initialize the input system
axiomWindow1.InitInput(true, true, false, false);
this.Show();
// Start rendering
AxiomManager.Instance.Engine.StartRendering();
}
catch ( System.Reflection.ReflectionTypeLoadException ex )
{
// This catches directx missing (or too old) to log :)
for ( int i = 0; i < ex.LoaderExceptions.Length; i++ )
if ( LogManager.Instance != null )
LogManager.Instance.Write( ex.LoaderExceptions[ i ].Message );
}
catch ( Exception ex )
{
if ( LogManager.Instance != null )
LogManager.Instance.Write( ex.ToString() );
}
}
There are also a few other features, but I'll leave it up to you to find them (let the treasure hunt begin!)
User Challenges
- Improve configuration support by adding the ability to persist the configuration and edit it using a dialog of some kind.
- Add input event handlers.
- Implement a “Example Application” form that provides the same interfaces as the “Example Application” found in the Basic Tutorials on the Axiom site.
- Create a more interesting example scene.
References
History
- 2007-12-08 Initial release