OgreDotNet.EventHandler and Windows Forms

leep

26-08-2006 07:30:39

I just worked through all the OgreDotNet tutorials in the wiki (converting them all the VB.NET as I went). I wanted to try to get one of the tutorials (I picked the MultiViewportApp) to run in a panel on a Windows Form and I ran into a problem. The application crashes with "This application has requested the Runtime to terminate it in an unusual way." when it tries to create an instance of OgreDotNet.EventHandler.

I'll post my entire code below. It's not too big, it's mostly the MultiViewportApp turtorial modified slightly to make it work with a windows form (exposed mRoot and mRenderWindow as readonly properties from the base class, and modified the main class' main to create the form and loop through rendering frames). The form (form1) is just a blank form with a panel (panel1) on it. No code added to the form at all. I removed all the xml comments to shorten it here.

BTW, if I comment out the contents of the CreateEventHandler Sub in the base class then it runs fine in the panel on the form. Of course it won't respond to any events, but it runs.

I've single stepped into the mEventHandler = New OgreDotNet.EventHandler(mRoot, mRenderWindow) line and it goes to public EventHandler(Root root, RenderWindow renderwindow) : this(OgreBindingsPINVOKE.new_EventHandler__SWIG_1(Root.getCPtr(root), RenderWindow.getCPtr(renderwindow)), true) { } in EventHandler.h. Single stepping into that takes it through Root's getCPtr and the RenderWindow's getCPtr fine, then once RenderWindow.getCptr returns the next "step into" causes the "This application has requested the Runtime to terminate it in an unusual way." error.


Imports System
Imports System.IO
Imports System.Drawing
Imports Math3D
Imports OgreDotNet

Namespace OgreDotNetTutorial
Public MustInherit Class MultiViewportFramework
Implements IDisposable
Protected mRoot As Root = Nothing
Protected mRenderWindow As RenderWindow = Nothing
Protected mSceneManager As SceneManager = Nothing
Protected mMainCamera As Camera = Nothing
Protected mSecondCamera As Camera = Nothing
Protected mMainViewport As Viewport = Nothing
Protected mSecondViewport As Viewport = Nothing
Protected mEventHandler As OgreDotNet.EventHandler = Nothing

Protected mDeltaTime As Single = 0.0F
Protected mDone As Boolean = False

Protected mDebugOverlayVisible As Boolean = True
Protected mWireFrame As Boolean = False
Protected mFilter As TextureFilterOptions = TextureFilterOptions.TfoBilinear
Protected mAnisotropy As UInt32 = 1

Protected mMoveVehicle As Integer = 0
Protected mTurnVehicle As Integer = 0
Protected mMoveScale As Single = 150.0F
Protected mRotateScale As Single = 1.0F
Protected mScreenShotCount As Integer = 0

Public ReadOnly Property Root() As Root
Get
Return mRoot
End Get
End Property

Public ReadOnly Property RenderWindow() As RenderWindow
Get
Return mRenderWindow
End Get
End Property

Public Sub New(ByVal ctl As Windows.Forms.Control)
Setup(ctl)
End Sub

Protected Overridable Function Setup(ByVal ctl As Windows.Forms.Control) As Boolean
mRoot = New Root()

SetupResources("resources.cfg")

If Not mRoot.ShowConfigDialog() Then
Return False
End If

If ctl Is Nothing Then
mRenderWindow = mRoot.Initialise(True, "Kewl App")
Else
mRenderWindow = mRoot.Initialise(ctl)
End If

CreateSceneManager()

CreateCameras()

CreateViewPorts()

TextureManager.Instance.SetDefaultNumMipmaps(5)

LoadResources()

CreateEventHandler()

MaterialManager.Instance.SetDefaultTextureFiltering(mFilter)
MaterialManager.Instance.SetDefaultAnisotropy(mAnisotropy)

CreateScene()
Return True
End Function

Protected Sub SetupResources(ByVal sFileName As String)
'Initialiser.SetupResources(sFileName);
Using sr As New StreamReader(sFileName)
Dim secName As String = ""
Dim sLocType As String
Dim sarchName As String
Dim line As String

line = sr.ReadLine()
While line IsNot Nothing
Dim x As Integer = line.IndexOf("#")
If x > -1 Then
line = line.Substring(0, x)
End If
line = line.Trim()
If line.Length > 0 Then
If line(0) = "["c Then
secName = line.Substring(1, line.Length - 2)
ElseIf secName.Length > 0 Then
x = line.IndexOf("=")
If x <= 0 Then
Throw New Exception("Invalid line in resource file " + sFileName)
End If
sLocType = line.Substring(0, x)
sarchName = line.Substring(x + 1)
ResourceGroupManager.getSingleton().addResourceLocation(sarchName, sLocType, secName)
End If
End If
line = sr.ReadLine()
End While
End Using
End Sub

Protected Overridable Sub Start()
mRoot.StartRendering()
End Sub

Protected Overridable Sub CreateSceneManager()
mSceneManager = mRoot.CreateSceneManager(CUShort(SceneType.ExteriorClose))
End Sub

Protected Overridable Sub CreateCameras()
mMainCamera = mSceneManager.CreateCamera("MainCamera")
mSecondCamera = mSceneManager.CreateCamera("SecondCamera")

' Position it at 50,50, 500
mMainCamera.SetPosition(New Vector3(1000, 8000, 1000))
' Look at 0,0,0
mMainCamera.LookAt = New Vector3(32000, 5000, 32000)
mMainCamera.SetNearClipDistance(5)

' Position it at 50,50,500
mSecondCamera.SetPosition(New Vector3(1000, 8000, 1000))
' Look at 0,0,0
mSecondCamera.LookAt = New Vector3(32000, 5000, 32000)
mSecondCamera.SetNearClipDistance(5)
End Sub

Protected Overridable Sub CreateViewPorts()
' Create main viewport full width, full height
' Camera Name, Z-Order, Left, Top, Width, Height);
mMainViewport = mRenderWindow.AddViewport(mMainCamera, 0, 0.0F, 0.0F, 1.0F, 1.0F)

' Set background color
mMainViewport.SetBackgroundColour(Color.Black)

' The aspect ratio should be 4/3
mMainCamera.SetAspectRatio(CSng(mMainViewport.ActualHeight) / CSng(mMainViewport.ActualWidth))

' Create second viewport, 1/3 size window, bottom, left side
' Camera Name, Z-Order, Left, Top, Width, Height,);
mSecondViewport = mRenderWindow.AddViewport(mSecondCamera, 1, 0.0F, 0.66F, 0.33F, 0.33F)

' Set background color
mSecondViewport.SetBackgroundColour(Color.Black)

' Alter the camera aspect ratio to match the viewport
mSecondCamera.SetAspectRatio(CSng(mSecondViewport.ActualHeight) / CSng(mSecondViewport.ActualWidth))
End Sub

Protected Overridable Sub LoadResources()
ResourceGroupManager.getSingleton().initialiseAllResourceGroups()
End Sub

Protected Overridable Sub CreateEventHandler()
mEventHandler = New OgreDotNet.EventHandler(mRoot, mRenderWindow)
mEventHandler.SubscribeEvents()
AddHandler mEventHandler.FrameStarted, AddressOf FrameStarted
AddHandler mEventHandler.FrameEnded, AddressOf FrameEnded
AddHandler mEventHandler.KeyClicked, AddressOf KeyClicked
AddHandler mEventHandler.KeyPressed, AddressOf KeyPressed
AddHandler mEventHandler.KeyReleased, AddressOf KeyReleased
AddHandler mEventHandler.MouseMoved, AddressOf MouseMotion
AddHandler mEventHandler.MouseClicked, AddressOf MouseClick
AddHandler mEventHandler.MousePressed, AddressOf MousePressed
AddHandler mEventHandler.MouseReleased, AddressOf MouseReleased
AddHandler mEventHandler.MouseDragged, AddressOf MouseDragged
End Sub

Protected MustOverride Sub CreateScene()

Protected Overridable Function FrameStarted(ByVal e As FrameEvent) As Boolean
If mRenderWindow.Closed Or mDone Then
Return False
End If
mDeltaTime = e.TimeSinceLastFrame

If mMoveVehicle > 0 Then
'mMoveCam bits: 1=forward, 2=backward, 4=up, 8=down
Dim vCamMove As Vector3 = Vector3.Zero
Dim mvscale As Single = mMoveScale * e.TimeSinceLastFrame

If (mMoveVehicle And 1) > 0 Then
vCamMove += Vector3.NegativeUnitZ
End If
If (mMoveVehicle And 2) > 0 Then
vCamMove += Vector3.UnitZ
End If
If (mMoveVehicle And 4) > 0 Then
vCamMove += Vector3.UnitY
End If
If (mMoveVehicle And 8) > 0 Then
vCamMove += Vector3.NegativeUnitY
End If

vCamMove *= mvscale
mMainCamera.MoveRelative(vCamMove)
mSecondCamera.SetPosition(mMainCamera.GetPosition())
End If

'mTurnVehicle bits: 1=left , 2=right
If (mTurnVehicle And 1) > 0 Then
mMainCamera.Yaw(New Radian(mRotateScale * 1.0F * e.TimeSinceLastFrame))
mSecondCamera.Yaw(New Radian(mRotateScale * 1.0F * e.TimeSinceLastFrame))
End If
If (mTurnVehicle And 2) > 0 Then
mMainCamera.Yaw(New Radian(mRotateScale * -1.0F * e.TimeSinceLastFrame))
mSecondCamera.Yaw(New Radian(mRotateScale * -1.0F * e.TimeSinceLastFrame))
End If

Return True
End Function

Protected Overridable Function FrameEnded(ByVal e As FrameEvent) As Boolean
Return True
End Function

Protected Overridable Sub MouseMotion(ByVal e As MouseMotionEvent)
mSecondCamera.Pitch(New Radian(-e.DeltaY * mDeltaTime * 500.0F))
mSecondCamera.Yaw(New Radian(-e.DeltaX * mDeltaTime * 500.0F))
End Sub

Protected Overridable Sub MouseDragged(ByVal e As MouseMotionEvent)
Me.MouseMotion(e)
End Sub

Protected Overridable Sub MouseClick(ByVal e As MouseEvent)

End Sub

Protected Overridable Sub MousePressed(ByVal e As MouseEvent)
End Sub


Protected Overridable Sub MouseReleased(ByVal e As MouseEvent)
End Sub

Protected Overridable Sub KeyClicked(ByVal e As KeyEvent)
Select Case e.KeyCode
Case KeyCode.Home
mMainCamera.SetOrientation(Quaternion.Identity)
mSecondCamera.SetOrientation(Quaternion.Identity)
Case KeyCode.Escape
mDone = True
Case KeyCode.R
mWireFrame = Not mWireFrame
If mWireFrame Then
mMainCamera.DetailLevel = PolygonMode.PMWireframe
mSecondCamera.DetailLevel = PolygonMode.PMWireframe
Else
mMainCamera.DetailLevel = PolygonMode.PMSolid
mSecondCamera.DetailLevel = PolygonMode.PMSolid
End If
Case KeyCode.T
Select Case mFilter
Case TextureFilterOptions.TfoBilinear
mFilter = TextureFilterOptions.TfoTrilinear
mAnisotropy = 1
Case TextureFilterOptions.TfoTrilinear
mFilter = TextureFilterOptions.TfoAnisotropic
mAnisotropy = 8
Case TextureFilterOptions.TfoAnisotropic
mFilter = TextureFilterOptions.TfoBilinear
mAnisotropy = 1
End Select
MaterialManager.Instance.SetDefaultTextureFiltering(mFilter)
MaterialManager.Instance.DefaultAnisotropy = mAnisotropy
Case KeyCode.SYSRQ
mRenderWindow.WriteContentsToFile(String.Format("ScreenShot{0}.png", mScreenShotCount))
mScreenShotCount += 1
End Select
End Sub

Protected Overridable Sub KeyPressed(ByVal e As KeyEvent)
Select Case e.KeyCode
Case KeyCode.W, KeyCode.Up
mMoveVehicle = mMoveVehicle Or 1
Case KeyCode.S, KeyCode.Down
mMoveVehicle = mMoveVehicle Or 2
Case KeyCode.PageUp, KeyCode.E
mMoveVehicle = mMoveVehicle Or 4
Case KeyCode.PageDown, KeyCode.Q
mMoveVehicle = mMoveVehicle Or 8
Case KeyCode.A, KeyCode.Left
mTurnVehicle = mTurnVehicle Or 1
Case KeyCode.D, KeyCode.Right
mTurnVehicle = mTurnVehicle Or 2
End Select
End Sub

Protected Overridable Sub KeyReleased(ByVal e As KeyEvent)
Select Case e.KeyCode
Case KeyCode.W, KeyCode.Up
mMoveVehicle = mMoveVehicle And Not 1
Case KeyCode.S, KeyCode.Down
mMoveVehicle = mMoveVehicle And Not 2
Case KeyCode.PageUp, KeyCode.E
mMoveVehicle = mMoveVehicle And Not 4
Case KeyCode.PageDown, KeyCode.Q
mMoveVehicle = mMoveVehicle And Not 8
Case KeyCode.A, KeyCode.Left
mTurnVehicle = mTurnVehicle And Not 1
Case KeyCode.D, KeyCode.Right
mTurnVehicle = mTurnVehicle And Not 2
End Select
End Sub

Private disposedValue As Boolean = False ' To detect redundant calls

' IDisposable
Protected Overridable Sub Dispose(ByVal disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
' TODO: free unmanaged resources when explicitly called
mRoot.Dispose()
End If

' TODO: free shared unmanaged resources
End If
Me.disposedValue = True
End Sub

#Region " IDisposable Support "
' This code added by Visual Basic to correctly implement the disposable pattern.
Public Sub Dispose() Implements IDisposable.Dispose
' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above.
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
End Class
End Namespace



Imports System
Imports System.Drawing
Imports OgreDotNet
Imports Math3D

Namespace OgreDotNetTutorial

Class MultipleViewportApp
Inherits MultiViewportFramework

Public Sub New(ByVal ctl As Windows.Forms.Control)
MyBase.New(ctl)
End Sub

Protected Overrides Sub CreateScene()
mSceneManager.SetAmbientLight(Color.FromArgb(127, 127, 127))
mSceneManager.SetWorldGeometry("terrain.cfg")
End Sub

Shared Sub Main(ByVal args() As String)
'Using app As New MultipleViewportApp(Nothing)
' app.Start()
'End Using
Using frmForm As New Form1
frmForm.Show()
Using app As New MultipleViewportApp(frmForm.Panel1)
While frmForm.Created()
app.Root.RenderOneFrame()
app.RenderWindow.Update()
Windows.Forms.Application.DoEvents()
End While
End Using
End Using

End Sub
End Class
End Namespace

leep

29-08-2006 16:09:48

I've moved away from using Ogre's events in favor of using Ogre just for rendering and handling all input myself (either using the Form/UserControl's mouse/keyboard events, or eventualy DirectInput probably) and calling RenderOneFrame directly as needed. But I'm still curious why I can't create an instance of the OgreDotNet.EventHandler if I called Root.Initialize(Control) instead of Root.Initialize(True, "Window Title"). Anyone have any idea?

GermanDZ

10-05-2007 16:35:09

Hi People,

this is my first message in the forum. We are evaluating OgreDotNet. We need to integrate a "3d Viewport" on a WinForms App.

I have the same problem (app explode!) with CreateEventHandler.

Solutions?

I am trying to compile (an swig generate) the C# sources and inspect the code.

Leep: How you capture the events on winform and "forward" the events to Ogre?


Thanks in advance,


German DZ

jacmoe

11-05-2007 21:25:43

Look into MOGRE instead, as it's actively developed.

GermanDZ

12-05-2007 20:12:47

I was reading into source codes: SWIG interfaces, Win32 API, Ogre code and Direct3D input... I discovered the crash, it is related to the "ActiveWindow". So I change the initialisation procedures of my App, Forms, OgreRoot, etc. Now is working ok.


About MOGRE (Off topic). ¿Is active? I read that "beka" is leaving the project, the army call for he!!! Please give me an advise.

I am on a 3 months project to evaluate OGRE as base to build a 3D virtual world (we are a company experienced en software development, another company will give us the 3D models). And I was in a team that developed a really nice good Virtual World during DotCom Bubble. So, please dont say me that developing a virtual world is hard.. I know that, we expend more than 3 Millions on that.

jacmoe

13-05-2007 14:22:42

MOGRE is more actively used, and while Bekas is away, he will most probably return to it.
So, I'd advise you to check out MOGRE. :wink: