Views
Basic Tutorial 5 (The Axiom Startup Sequence)
From Axiom
Congratulations, after this tutorial you'll have graduated from the Basic Tutorials! In basic tutorial 1, we mentioned that TechDemo was not a good basis for a full-blown application. Thus is becomes necessary to have our own version of TechDemo.
Prerequisites
As always:
- This tutorial assumes you have basic knowledge of C#, VB.NET, or Python, or other .NET language, though only the mentioned languages will have sample code.
- This tutorial builds on the previous tutorials, and it assumes you have already worked through them.
Getting Started
In your IDE of choice, browse to where you can create a class and add the following:
class Game
{
public void Run()
{
}
}
Class GamePublic Sub Run()
End Sub End Class
class Game:
def Run():
pass
Overview of the Axiom Startup Process
Once you understand what's going on under the hood, getting Axiom running is actually very easy to do. After finishing this tutorial, you will be able to pick and choose what exactly is needed for your application. Before we dive into this, we'll first take a quick look at how the startup process works at a high level. The basic Axiom life cycle looks like this:
- Create the Root object.
- Define the resources that the application will use.
- Choose and set up the render system (that is, DirectX, OpenGL, etc).
- Create the render window (the window which Axiom will render onto).
- Initialize the resources that you are going to use.
- Create a scene using those resources.
- Set up any third party libraries and plugins.
- Create frame listeners.
- Start the render loop.
We will be going through each one of these in-depth in this tutorial. Note that while you really should do steps 1-4 in order, steps 5 and 6 (initializing resources and creating the scene) can come much later in your startup process if you like. You could initialize third party plugins and create frame listeners before steps 5 and 6 if you so choose, but you really shouldn't do them before finishing step 4. Also, the frame listeners/third party libraries cannot access any game related resources (such as your cameras, entities, etc) until the resources are initialized and the scene has been created. In short, you can do some of these steps out of order if you feel it will be better for your application, but we do not recommend doing so unless you are sure you understand the consequences of what you are doing.
Create the Root Object
The Root object is the core of the Axiom library, and must be created before you can do almost anything with the engine. In your Run method add the following:
Root root = new Root("Game.log");
Dim root as Root = New Root("Game.log")
root = Root("Game.log")
There, that easy. Optionally Root has a parameter less constructor, in which the .log file will simply be called Axiom.log.
Define the Resources
The next thing we have to do is define the resources that the application uses. This includes the textures, models, scripts, and so on. We will not be going over all there is to know about resources in this tutorial. For now, just keep in mind that you must first define all the resources that you might use during the application, then you must initialize the specific resources you need before Axiom can use them. In this step we are defining all resources that our application will possibly use. Thus far we have been using EngineConfig.xml to define Resource paths. But now we'll also show you how to add Resource Locations manually.
Adding a resource location is done with a simple call to the ResourceGroupManager class:
ResourceGroupManager.Instance.AddResourceLocation(location, type, group);
ResourceGroupManager.Instance.AddResourceLocation(location, type, group)
ResourceGroupManager.Instance.AddResourceLocation(location, type, group)
The first parameter of this method is the location of the resource on disk (file/directory name). The second parameter is the type of resource which is generally either "Folder" (for a directory) or "Zip" (for a zip file). The last parameter is the resource group to add the resource to. So we can add a location by saying:
ResourceGroupManager.Instance.AddResourceLocation("Media", "Folder", "General");
ResourceGroupManager.Instance.AddResourceLocation("Media", "Folder", "General")
ResourceGroupManager.Instance.AddResourceLocation("Media", "Folder", "General")
And then repeating this process for each subfolder of "Media". You can see now why a system like EngineConfig was created.
Choose Render System
You select a RenderSystem by writing the following line:
root.RenderSystem = root.RenderSystems["DirectX9"];
root.RenderSystem = root.RenderSystems["DirectX9"]
root.RenderSystem = root.RenderSystems["DirectX9"]
Currently the options are DirectX9, OpenGL, and Xna. The root.RenderSystems list is populated when the Root object is initialized. Axiom automatically searches the Working Directory for Axiom.RenderSystem.*.dll's and adds the name here. After the RenderSystem is chosen, various options can be set like so:
Root.Instance.RenderSystem.ConfigOptions["Video Mode"].Value = "1280 x 720 @ 32-bit color";
Root.Instance.RenderSystem.ConfigOptions["Video Mode"].Value = "1280 x 720 @ 32-bit color"
Root.Instance.RenderSystem.ConfigOptions["Video Mode"].Value = "1280 x 720 @ 32-bit color";
The options and format change based on Rendering System, but here are some more common settings:
| Name | Purpose |
| Video Mode | Sets resolution and color-depth. |
| Full Screen | Sets whether to use the full screen. |
| VSync | Syncs FPS to monitors refresh rate |
| Anti-Aliasing | Gives the appearence of smoother edges. |
| Floating-Point mode | Choice between fastest and precise floating point numbers. |
Options that appear to be boolean are given a "Yes" or a "No", and all options are given as strings.
Create a RenderWindow
Now that we have chosen the RenderSystem, we need a window to render Axiom in. There are actually a lot of options for how to do this, but we will really only cover a couple. The simplest option is to let Axiom create a render window for you. This is very easy to do.
RenderWindow window = root.Initialize(true, "Window Title");
Dim window as RenderWindow = root.Initialize(True, "Window Title")
window= root.Initialize(True, "Window Title")
The Initialize method of the Root object initializes the RenderSystem we set in the previous section. The first parameter is whether or not Axiom should create a render window for you. If it is set to true, the method will return a RenderWindow object. Alternatively, we could have created a window ourselves which we then want to tell Axiom to use. Here is a quick example of how this might be done using Windows.Forms (don't add this code):
RenderWindow window = root.CreateRenderWindow("Axiom Render Window", 800, 600, false);
Dim window as RenderWindow = root.CreateRenderWindow("Axiom Render Window", 800, 600, False)
window = root.CreateRenderWindow("Axiom Render Window", 800, 600, False)
Note that you still have to call Initialize, but the first parameter is set to false. RenderWindows are actually Windows Forms themselves behind the scenes. Check out [this tutorial http://axiom3d.net/wiki/index.php/Embedding_Axiom_On_A_Windows_Form] to see how to embed Axiom into a Windows.Forms project.
Initialize Resources
Now that we have our Root, RenderSystem and RenderWindow objects created and ready to go, we are very close to being ready to create our scene. The only thing left to do is to initialize the resources we are about to use. In a very large game or application, we may have hundreds or even thousands of resources that our game uses - everything from meshes to textures to scripts. At any given time though, we probably will only be using a small subset of these resources. Note that when you initialize a resource group, it parses and loads scripts, but does not actually load the resources (such as models and textures) into memory until the program actually needs to use it. Before we initialize the resources, we should also set the default number of mipmaps that textures use. We must set that before we initialize the resources for it to have any effect. Add the following code to your application:
TextureManager.Instance.DefaultMipmapCount = 5;
ResourceGroupManager.Instance.InitializeAllResourceGroups();
TextureManager.Instance.DefaultMipmapCount = 5ResourceGroupManager.Instance.InitializeAllResourceGroups()
TextureManager.Instance.DefaultMipmapCount = 5ResourceGroupManager.Instance.InitializeAllResourceGroups()
The application now has all resource groups initialized and ready to be used.
Creating a Scene
Next we will create the scene. There are 3 things that must happen before you start adding things to a scene:
1. Creating the SceneManager.
2. Creating a Camera.
3. Creating a Viewport.
Add the following code to your application:
SceneManager scene = root.CreateSceneManager(SceneType.Generic);
Camera camera = scene.CreateCamera("Camera1");
Viewport viewport = window.AddViewport(camera);
Entity ninja = scene.CreateEntity("bob", "ninja.mesh");
SceneNode ninjaNode = scene.RootSceneNode.CreateChildSceneNode(new Vector3(0,0,-200));
ninjaNode.AttachObject(ninja);
Dim scene as SceneManager = root.CreateSceneManager(SceneType.Generic)
Dim camera as Camera = scene.CreateCamera("Camera1")
Dim viewport as Viewport = window.AddViewport(camera)
Dim ninja as Entity = scene.CreateEntity("bob", "ninja.mesh")
Dim ninjaNode as Entity = scene.RootSceneNode.CreateChildSceneNode(New Vector3(0,0,-200))
ninjaNode.AttachObject(ninja)
scene = root.CreateSceneManager(SceneType.Generic)
camera = scene.CreateCamera("Camera1")
viewport = window.AddViewport(camera)
ninja = scene.CreateEntity("bob", "ninja.mesh")
ninjaNode = scene.RootSceneNode.CreateChildSceneNode(Vector3(0,0,-200))
ninjaNode.AttachObject(ninja)
Registering Frame Event Handlers
It is important to place an EventHandler before Rendering is Started. Otherwise they won't be registered in time for the application to use them. Add the following:
root.FrameStarted += new EventHandler<FrameEventArgs>(root_FrameStarted);
root.FrameStarted += New EventHandler<FrameEventArgs>(root_FrameStarted)
root.FrameStarted += root_FrameStarted
be sure to create the method 'root_FrameStarted' in your class:
void root_FrameStarted(object sender, FrameEventArgs e)
{
}
Private Sub root_FrameStarted(sender As Object, e As FrameEventArgs) End Sub
def root_FrameStarted(sender, e):
pass
Start the Render Loop
The easiest way to begin rendering is to use Axiom's built in method:
root.StartRendering()
Alternatively we can implement our own render loop:
while (root.RenderOneFrame())
{
//Do stuff, remembering to break when finished.
}
While (root.RenderOneFrame())
'Do stuff, remembering to break when finished.
End While
while (root.RenderOneFrame()):
#Do stuff, remembering to break when finished.
This gives you more control over the render loop and allows you to perform other incremental actions not dependant on frame listeners.
Full Source Code
using System;
using Axiom.Core;
using Axiom.Math;
using Axiom.Graphics;
namespace Axiom.Demos
{
class Game
{
public void Run()
{
Root root = new Root("Game.log");
root.RenderSystem = root.RenderSystems["DirectX9"];
root.RenderSystem.ConfigOptions["Video Mode"].Value = "1280 x 720 @ 32-bit color";
ResourceGroupManager.Instance.AddResourceLocation("Media", "Folder");
RenderWindow window = root.Initialize(true);
SceneManager scene = root.CreateSceneManager(SceneType.Generic);
Camera camera = scene.CreateCamera("Camera1");
Viewport viewport = window.AddViewport(camera);
TextureManager.Instance.DefaultMipmapCount = 5;
ResourceGroupManager.Instance.InitializeAllResourceGroups();
Entity ninja = scene.CreateEntity("bob", "ninja.mesh");
SceneNode ninjaNode = scene.RootSceneNode.CreateChildSceneNode(new Vector3(0,0,-200));
ninjaNode.AttachObject(ninja);
root.FrameStarted += new EventHandler<FrameEventArgs>(root_FrameStarted);
root.StartRendering();
}
void root_FrameStarted(object sender, FrameEventArgs e)
{
}
}
}
Imports Axiom.Core
Imports Axiom.Math
Imports Axiom.Graphics
Namespace Axiom.Demos
Class Game
Public Sub Run()
Dim root As New Root("Game.log")
root.RenderSystem = root.RenderSystems("DirectX9")
root.RenderSystem.ConfigOptions("Video Mode").Value = "1280 x 720 @ 32-bit color"
ResourceGroupManager.Instance.AddResourceLocation("Media", "Folder")
Dim window As RenderWindow = root.Initialize(True)
Dim scene As SceneManager = root.CreateSceneManager(SceneType.Generic)
Dim camera As Camera = scene.CreateCamera("Camera1")
Dim viewport As Viewport = window.AddViewport(camera)
TextureManager.Instance.DefaultMipmapCount = 5
ResourceGroupManager.Instance.InitializeAllResourceGroups()
Dim ninja As Entity = scene.CreateEntity("bob", "ninja.mesh")
Dim ninjaNode As SceneNode = scene.RootSceneNode.CreateChildSceneNode(New Vector3(0, 0, -200))
ninjaNode.AttachObject(ninja)
root.FrameStarted += New EventHandler(Of FrameEventArgs)(AddressOf root_FrameStarted)
root.StartRendering()
End Sub
Private Sub root_FrameStarted(sender As Object, e As FrameEventArgs)
End Sub
End Class
End Namespace
import clr
clr.AddReferenceByName("Axiom.dll")
from Axiom.Core import *
from Axiom.Math import *
from Axiom.Graphics import *
class Game:
def Run():
root = Root("Game.log")
root.RenderSystem = root.RenderSystems("DirectX9")
root.RenderSystem.ConfigOptions("Video Mode").Value = "1280 x 720 @ 32-bit color"
ResourceGroupManager.Instance.AddResourceLocation("Media", "Folder")
window = root.Initialize(True)
scene = root.CreateSceneManager(SceneType.Generic)
camera = scene.CreateCamera("Camera1")
viewport = window.AddViewport(camera)
TextureManager.Instance.DefaultMipmapCount = 5
ResourceGroupManager.Instance.InitializeAllResourceGroups()
ninja = scene.CreateEntity("bob", "ninja.mesh")
ninjaNode = scene.RootSceneNode.CreateChildSceneNode(Vector3(0, 0, -200))
ninjaNode.AttachObject(ninja)
root.StartRendering()
def root_FrameStarted(sender, e):
pass
if __name__ == '__main__':
game = Game()
game.Run()
Conclusion
So, now what?
In this tutorial we have gone over the basics of getting Axiom started from scratch. By this point you should be able to write your own Axiom application which no longer uses the TechDemo class (we will be continuing to use in following tutorials however).
You should now understand exactly the steps required and the objects involved to get to a rendered scene from scratch.
You may want to try placing each segment of this tutorial in a method, and then implementing each in an inherited class.
If you downloaded the Source, you may have stumbled across a project called Axiom.Framework, which is a Framework meant for large applications, so you may want to give that a try.
You might also considering helping out other users in the forum, or in the IRC. Often the best way to learn is too help out others.
And of course you can continue on to the Intermediate tutorials.



