From Axiom
' This file was created from ExampleApplication.h (Ogle v1.2.3) by trejs
' for use with Axiom's tutorials.
'
' It still has some flaws. See the "// TODO" lines to begin with.
' But better that than no tutorials at all :)
'
' 2006-12-26: Fixed the mouse button issue, code now compatible with 0.7.1.0-RC2. / trejs
' 2007-08-17: Updated for compatibility with 0.7.2.0 / borrillis
' 2009-01-19: Translated to VB / wleader
#Region " Namespace Declaration "
Imports System
Imports System.Data
Imports System.Collections.Generic
Imports Axiom
Imports Axiom.Core
Imports Axiom.Graphics
Imports Axiom.Configuration
Imports Axiom.Math
Imports Axiom.Overlays
Imports Axiom.Input
#End Region
Namespace ExampleApplication
Public Class ExampleApplication
#Region " Configure Console "
' Code originally from the command-line demo launcher. Mostly rewritten.
'
' If you only want the configuration menu, just copy this class into your application.
' See how it's used in ExampleApplication.Configure().
Private Class ConfigureConsole
#Region " Types "
Public Enum DialogResult
[Continue]
Run
[Exit]
End Enum
#End Region
#Region " Private Fields "
' Currently selected system
Private m_currentSystem As RenderSystem
' Holds the list of possible rendersystems
Private m_renderSystems As ConfigOption
' Menu items
Private m_currentMenuItems As New List(Of ConfigOption)
' Currently selected item
Private m_currentOption As ConfigOption
' Options for the currently selected system
Private m_currentSystemOptions As New List(Of ConfigOption)
#End Region
#Region " Properties "
''' <summary>
''' Gets the selected rendersystem (and all the values of options set for it)
''' </summary>
Public ReadOnly Property RenderSystem() As RenderSystem
Get
Return m_currentSystem
End Get
End Property
#End Region
#Region " Constructor "
Public Sub New()
' Set current RenderSystem to first in list
m_currentSystem = Root.Instance.RenderSystems(0)
' Create rendersystem option and get possible values
m_renderSystems = New ConfigOption("Render System", m_currentSystem.Name, False)
Dim R As RenderSystem
For Each R In Root.Instance.RenderSystems
m_renderSystems.PossibleValues.Add(R.ToString)
Next
BuildCurrentSystemOptions()
End Sub
#End Region
#Region " Public Methods "
Public Function Show() As DialogResult
While True
' Clear menu buffer
m_currentMenuItems.Clear()
' Build menu
If IsNothing(m_currentOption) Then 'Main Menu
' Build menu from m_currentOptions
Dim C As ConfigOption
For Each C In m_currentSystemOptions
m_currentMenuItems.Add(C)
Next
Else 'option menu
' Add possible values for this option
Dim value As Object
For Each value In m_currentOption.PossibleValues
m_currentMenuItems.Add(New ConfigOption(value.ToString, String.Empty, False))
Next
End If
' Display menu
DisplayOptions()
' Handle next keypress (waits for user input)
Dim Result As DialogResult = HandleNextKeyPress()
' Check if we're exiting the configure console
If Result <> DialogResult.Continue Then
Console.Clear()
Return Result
End If
End While
End Function
#End Region
#Region " Private Methods "
Private Sub BuildCurrentSystemOptions()
' Make sure its empty
m_currentSystemOptions.Clear()
' Add RenderSystem options to the list.
m_currentSystemOptions.Add(m_renderSystems)
' Browse and add options of current rendersystem
Dim C As ConfigOption
For Each C In m_currentSystem.ConfigOptions
m_currentSystemOptions.Add(C)
Next
End Sub
Private Function IsDigit(ByRef digit As Integer, ByVal Key As ConsoleKey)
Dim Str As String = Key.ToString
If Str.Length = 2 And Char.IsDigit(Str.Substring(1)) Then
digit = Integer.Parse(Str.Substring(1)) ' Numbers are returend like "D5"
Return True
End If
Return False
End Function
Private Function HandleNextKeyPress() As DialogResult
' Wait for key and then read it without echo to the console
Dim Key As ConsoleKey = Console.ReadKey(True).Key
' if the currentoption.Name is null, then we're in the main menu.
If IsNothing(m_currentOption) Then
'Escape exits, Enter Runs
If Key = ConsoleKey.Escape Then
Return ConfigureConsole.DialogResult.Exit
ElseIf Key = ConsoleKey.Enter Then
' Save options for current system.
For I As Integer = 0 To m_currentSystemOptions.Count - 1
Dim Opt As ConfigOption = m_currentSystemOptions(I)
m_currentSystem.ConfigOptions(Opt.Name) = Opt
Next
Return ConfigureConsole.DialogResult.Run
Else
' Check for selection
Dim selection As Integer = 0
If IsDigit(selection, Key) And selection < m_currentMenuItems.Count Then
m_currentOption = m_currentMenuItems(selection)
End If
End If
Else
' Esc: Return to main menu
If Key = ConsoleKey.Escape Then
m_currentOption = Nothing
End If
' Check if the current key is a digit, and if that digit is within the possible values
Dim selection As Integer = 0
If IsDigit(selection, Key) And selection < m_currentMenuItems.Count Then
' Check if we're about to change render system
If m_currentOption.Name = "Render System" Then
m_currentSystem = Root.Instance.RenderSystems(selection)
m_renderSystems = m_currentOption
BuildCurrentSystemOptions()
m_currentOption = Nothing ' Reset current option (to show main-menu)
Else
m_currentOption.Value = m_currentOption.PossibleValues(selection)
' Set the selected value
For I As Integer = 0 To m_currentSystemOptions.Count - 1
If m_currentSystemOptions(I).Name = m_currentOption.Name Then
m_currentSystemOptions(I) = m_currentOption
End If
Next
m_currentOption = Nothing ' Reset current option (to show main-menu)
End If
End If
End If
Return ConfigureConsole.DialogResult.Continue
End Function
Private Sub DisplayOptions()
Console.Clear()
Console.WriteLine("Axiom Engine Configuration")
Console.WriteLine("==========================")
If Not IsNothing(m_currentOption) AndAlso Not IsNothing(m_currentOption.Name) Then
Console.WriteLine("Available settings for {0}.\n", m_currentOption.Name)
End If
' Load Render Subsystem Options
Dim i As Integer = 0
For Each C As ConfigOption In m_currentMenuItems
' If this is a possible-value of an option (and not a list of options in the main-menu)
' we need to display it's name but not the current value (it doesn't have any).
If IsNothing(m_currentOption) OrElse IsNothing(m_currentOption.Name) Then
Console.WriteLine("{0} | {1}", i + 1, C.ToString)
Else
Console.WriteLine("{0} | {1}", i + 1, C.Name)
End If
i += 1
Next
If IsNothing(m_currentOption) OrElse IsNothing(m_currentOption.Name) Then
Console.WriteLine()
Console.WriteLine("Enter | Saves changes.")
Console.WriteLine("ESC | Exits.")
End If
Console.Write("\nSelect option: ")
End Sub
#End Region
End Class
#End Region
#Region " Private Fields "
Private m_configFile As String = "EngineConfig.xml"
Private m_logFile As String = "AxiomExample.log"
Private m_lastOverlayUpdate As Long = -1000
Private m_moveScale As Single = 0
Private m_rotScale As Single = 0
Private m_moveSpeed As Single = 100
Private m_rotateSpeed As Single = 36
Private m_rotateVector As New Vector2(0, 0)
Private m_translateVector As New Vector3(0, 0, 0)
Private m_root As Root
Private m_camera As Camera
Private m_sceneManager As SceneManager
Private m_renderWindow As RenderWindow
Private m_inputReader As InputReader
#End Region
#Region " Protected Properties"
''' <summary>
''' Root (Axiom.Core.Root)
''' </summary>
Protected Property Root() As Root
Get
Return m_root
End Get
Set(ByVal value As Root)
m_root = value
End Set
End Property
''' <summary>
''' Camera (Axiom.Core.Camera)
''' </summary>
Protected Property Camera() As Camera
Get
Return m_camera
End Get
Set(ByVal value As Camera)
m_camera = value
End Set
End Property
''' <summary>
''' SceneManager (Axiom.Core.SceneManager)
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Protected Property SceneManager() As SceneManager
Get
Return m_sceneManager
End Get
Set(ByVal value As SceneManager)
m_sceneManager = value
End Set
End Property
''' <summary>
''' RenderWindow (Axiom.Graphics.RenderWindow)
''' </summary>
Protected Property RenderWindow() As RenderWindow
Get
Return m_renderWindow
End Get
Set(ByVal value As RenderWindow)
m_renderWindow = value
End Set
End Property
''' <summary>
''' InputReader (Axiom.Input.InputReader)
''' </summary>
Protected Property InputReader() As InputReader
Get
Return m_inputReader
End Get
Set(ByVal value As InputReader)
m_inputReader = value
End Set
End Property
#End Region
#Region " Public Properties "
''' <summary>
''' Gets or set the config file name and path
''' </summary>
Public Property ConfigFile() As String
Get
Return m_configFile
End Get
Set(ByVal value As String)
m_configFile = value
End Set
End Property
''' <summary>
''' Gets or sets the config file name and path
''' </summary>
Public Property LogFile() As String
Get
Return m_logFile
End Get
Set(ByVal value As String)
m_logFile = value
End Set
End Property
#End Region
#Region " Init Methods "
''' <summary>
''' Starts the example
''' </summary>
Public Overridable Sub Run()
Try
If Setup() Then
m_root.StartRendering()
End If
Catch ex As System.Reflection.ReflectionTypeLoadException
' This catches directx missing (or too old) to log :)
For I As Integer = 0 To ex.LoaderExceptions.Length - 1
If Not IsNothing(LogManager.Instance) Then
LogManager.Instance.Write(ex.LoaderExceptions(I).Message)
End If
Next
Catch Ex As Exception
If Not IsNothing(LogManager.Instance) Then
LogManager.Instance.Write(Ex.ToString)
End If
End Try
' TODO: Memory cleanup here..
End Sub
''' <summary>
''' Initalizes the application
''' </summary>
''' <returns>True if successfull, False to exit the application</returns>
''' <remarks></remarks>
Protected Overridable Function Setup() As Boolean
m_root = New Root(ConfigFile, LogFile)
SetupResources()
' Run config utility, exit program if it returns false
If Not Configure() Then
Return False
Else
m_renderWindow = Root.Instance.Initialize(True)
End If
' Initalize input
m_inputReader = PlatformManager.Instance.CreateInputReader()
m_inputReader.Initialize(m_renderWindow, True, True, False, True)
ChooseSceneManager()
CreateCamera()
CreateViewports()
' Set default mipmap level (NB some APIs ignore this)
TextureManager.Instance.DefaultNumMipMaps = 5
' Create any resource listeners (for loading screens)
CreateResourceListener()
' Add some event handlers
RegisterEventHandlers()
' Lastly, create the scene
CreateScene()
Return True
End Function
''' <summary>
''' Adds the searchpaths from "EngineConfig.xml" to resources
''' </summary>
Protected Overridable Sub SetupResources()
Dim config As New EngineConfig()
config.ReadXml(ConfigFile)
For Each row As EngineConfig.FilePathRow In config.FilePath
ResourceManager.AddCommonArchive(row.src, row.type)
Next
End Sub
''' <summary>
''' Configures the application
''' </summary>
''' <returns>True if successfull, False to exit the application</returns>
Protected Overridable Function Configure() As Boolean
Dim cc As ConfigureConsole = New ConfigureConsole
If cc.Show = ConfigureConsole.DialogResult.Exit Then
Return False
End If
' Set selected rendersystem
m_root.RenderSystem = cc.RenderSystem
Return True
End Function
''' <summary>
''' Chooses scene manager (SceneType.Generic)
''' </summary>
Protected Overridable Sub ChooseSceneManager()
' Create a generic scene manager
m_sceneManager = m_root.SceneManagers.GetSceneManager(SceneType.Generic)
End Sub
''' <summary>
''' Creates a camera at 500 in the Z direction that looks at -300 in the Z direction
''' </summary>
Protected Overridable Sub CreateCamera()
' Create the camera
m_camera = m_sceneManager.CreateCamera("PlayerCam")
' Position it at 500 in the Z direction
m_camera.Position = New Vector3(0, 0, 500)
' Look back along -Z
m_camera.LookAt(New Vector3(0, 0, -300))
m_camera.Near = 5
End Sub
''' <summary>
''' Creates a viewport using mCamera
''' </summary>
''' <remarks></remarks>
Protected Overridable Sub CreateViewports()
' Create one viewport, entire window
Dim vp As Viewport = m_renderWindow.AddViewport(m_camera)
vp.BackgroundColor = ColorEx.Black
' Alter the camera aspect ratio to match the viewport
m_camera.AspectRatio = vp.ActualWidth / vp.ActualHeight
End Sub
''' <summary>
''' Optional override method where you can create resource listeners (e.g. for loading screens)
''' </summary>
''' <remarks></remarks>
Protected Overridable Sub CreateResourceListener()
End Sub
''' <summary>
''' Registers event handlers and calls InitOverlay()
''' </summary>
Protected Overridable Sub RegisterEventHandlers()
AddHandler m_root.FrameStarted, AddressOf UpdateInput
AddHandler m_root.FrameStarted, AddressOf UpdateOverlay
AddHandler m_root.FrameStarted, AddressOf FrameStarted
AddHandler m_root.FrameEnded, AddressOf FrameEnded
' Create debug overlay
InitOverlay()
End Sub
''' <summary>
''' Initalizes the debug overlay (fps, etc..)
''' </summary>
''' <remarks></remarks>
Protected Overridable Sub InitOverlay()
Dim o As Overlay = OverlayManager.Instance.GetByName("Core/DebugOverlay")
If IsNothing(o) Then
Throw New Exception("Could not find overlay named 'Core/DebugOverlay'.")
End If
o.Show()
End Sub
''' <summary>
''' Creates the Scene
''' </summary>
Protected Overridable Sub CreateScene()
End Sub
#End Region
#Region " Event Handlers "
''' <summary>
''' This is run before each frame.
''' </summary>
Protected Overridable Sub FrameStarted(ByVal source As Object, ByVal e As FrameEventArgs)
End Sub
''' <summary>
''' This is run after each frame
''' </summary>
Protected Overridable Sub FrameEnded(ByVal source As Object, ByVal e As FrameEventArgs)
End Sub
''' <summary>
''' Checks for input and handles it.
''' </summary>
Protected Overridable Sub UpdateInput(ByVal source As Object, ByVal e As FrameEventArgs)
m_inputReader.Capture()
' Reset vectors
m_rotateVector.x = 0
m_translateVector.x = 0
m_rotateVector.y = 0
m_translateVector.y = 0
m_translateVector.z = 0
' Move
m_moveScale = m_moveSpeed * e.TimeSinceLastFrame
' Rotate
m_rotScale = m_rotateSpeed * e.TimeSinceLastFrame
' Move forward and back
If m_inputReader.IsKeyPressed(KeyCodes.W) Or m_inputReader.IsKeyPressed(KeyCodes.Up) Then
m_translateVector.z = -m_moveScale
ElseIf m_inputReader.IsKeyPressed(KeyCodes.S) Or m_inputReader.IsKeyPressed(KeyCodes.Down) Then
m_translateVector.z = m_moveScale
End If
' Move left and right
If m_inputReader.IsKeyPressed(KeyCodes.A) Then
m_translateVector.x = -m_moveScale
ElseIf m_inputReader.IsKeyPressed(KeyCodes.D) Then
m_translateVector.x = m_moveScale
End If
' Move up and down
If m_inputReader.IsKeyPressed(KeyCodes.PageUp) Then
m_translateVector.y = m_moveScale
ElseIf m_inputReader.IsKeyPressed(KeyCodes.PageDown) Then
m_translateVector.y = -m_moveScale
End If
' Rotate left and right
If m_inputReader.IsKeyPressed(KeyCodes.Left) Then
m_rotateVector.x = -m_rotScale
ElseIf m_inputReader.IsKeyPressed(KeyCodes.Right) Then
m_rotateVector.x = m_rotScale
End If
' Right mouse button pressed
If m_inputReader.IsMousePressed(MouseButtons.Right) Then
' Translate
m_translateVector.x += m_inputReader.RelativeMouseX * 0.13F
m_translateVector.y -= m_inputReader.RelativeMouseY * 0.13F
ElseIf m_inputReader.IsMousePressed(MouseButtons.Left) Then
' Apply mouse rotation
m_rotateVector.x += m_inputReader.RelativeMouseX * 0.13F
m_rotateVector.y += m_inputReader.RelativeMouseY * 0.13F
End If
' Apply changes
m_camera.Yaw(-m_rotateVector.x)
m_camera.Pitch(-m_rotateVector.y)
m_camera.MoveRelative(m_translateVector)
' TODO: what about window-closing-event?
If m_inputReader.IsKeyPressed(KeyCodes.Escape) Then
Root.Instance.QueueEndRendering()
' TODO: Find a better way
If IsNothing(m_root) Then
' remove event handlers
' engine.FrameStarted -= new FrameEvent( OnFrameStarted );
' engine.FrameEnded -= new FrameEvent( OnFrameEnded );
m_root.Dispose()
End If
m_sceneManager.RemoveAllCameras()
m_sceneManager.RemoveCamera(m_camera)
m_camera = Nothing
Root.Instance.RenderSystem.DetachRenderTarget(m_renderWindow)
m_renderWindow.Dispose()
End If
End Sub
''' <summary>
''' Updates the debug overlay
''' </summary>
Protected Overridable Sub UpdateOverlay(ByVal source As Object, ByVal e As FrameEventArgs)
If (Root.Instance.Timer.Milliseconds - m_lastOverlayUpdate >= 1000) Then
m_lastOverlayUpdate = Root.Instance.Timer.Milliseconds
Dim element As OverlayElement = OverlayElementManager.Instance.GetElement("Core/DebugText")
element.Text = m_renderWindow.DebugText
element = OverlayElementManager.Instance.GetElement("Core/CurrFps")
element.Text = String.Format("Current FPS: {0}", Root.Instance.CurrentFPS)
element = OverlayElementManager.Instance.GetElement("Core/BestFps")
element.Text = String.Format("Best FPS: {0}", Root.Instance.BestFPS)
element = OverlayElementManager.Instance.GetElement("Core/WorstFps")
element.Text = String.Format("Worst FPS: {0}", Root.Instance.WorstFPS)
element = OverlayElementManager.Instance.GetElement("Core/AverageFps")
element.Text = String.Format("Average FPS: {0}", Root.Instance.AverageFPS)
element = OverlayElementManager.Instance.GetElement("Core/NumTris")
element.Text = String.Format("Triangle Count: {0}", m_sceneManager.TargetRenderSystem.FacesRendered)
End If
End Sub
#End Region
End Class
End Namespace