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)
{
m_root = new Root(axiomConfig.ConfigFile, axiomConfig.LogFile);
SetupAxiomResources(axiomConfig.ConfigFile);
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()
{
AxiomManager axiomManager = AxiomManager.Instance;
Configuration.AxiomConfiguration axiomConfig = axiomManager.Config.AxiomConfig;
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) {
if(Camera != null && AutoAspectRatio) {
Camera.AspectRatio = (float)Width / Height;
}
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 ) {
m_currentSize = Size;
Camera camera = Camera;
AxiomManager.Instance.Engine.DetachRenderTarget(m_window);
m_window.Dispose();
m_window = null;
m_viewPort = null;
m_initialized = false;
Init();
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
{
this.axiomWindow1.Init();
scene = AxiomManager.Instance.Engine.SceneManagers.GetSceneManager(
SceneType.Generic);
camera = scene.CreateCamera( "MainCamera" );
camera.Position = new Vector3( 0, 0, 500 );
camera.LookAt( new Vector3( 0, 0, -300 ) );
camera.Near = 5;
axiomWindow1.Camera = camera;
TextureManager.Instance.DefaultNumMipMaps = 5;
scene.AmbientLight = new ColorEx( 1.0f, 0.2f, 0.2f, 0.2f );
scene.SetSkyDome( true, "Examples/CloudySky", 5, 8 );
Light light = scene.CreateLight( "MainLight" );
light.Position = new Vector3( 20, 80, 50 );
Plane plane = new Plane();
plane.Normal = Vector3.UnitY;
plane.D = 200;
MeshManager.Instance.CreatePlane( "FloorPlane", plane, 200000, 200000, 20,
20, true, 1, 50, 50, Vector3.UnitZ );
Entity planeEntity = scene.CreateEntity( "Floor", "FloorPlane" );
planeEntity.MaterialName = "Examples/RustySteel";
scene.RootSceneNode.CreateChildSceneNode().AttachObject( planeEntity );
Entity ogreHead = scene.CreateEntity( "OgreHead", "ogrehead.mesh" );
headNode = scene.RootSceneNode.CreateChildSceneNode( "OgreHeadNode",
Vector3.Zero, Quaternion.Identity );
headNode.AttachObject( ogreHead );
axiomWindow1.InitInput(true, true, false, false);
this.Show();
AxiomManager.Instance.Engine.StartRendering();
}
catch ( System.Reflection.ReflectionTypeLoadException ex )
{
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