Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Axiom

0.00/5 (No votes)
8 Dec 2007 4  
How to setup an Axiom application
Screenshot -

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

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here