Problem with SimpleRenderableDirector

leep

31-08-2006 16:55:28

I'm using OgreDotNet and VB.NET (2005). I took the Line3D class that inherits from SimpleRenderableDirector and converted it to VB.NET. I'm creating a single line for a test and it displays fine in PMSolid mode. If I put the camera in PMWireframe mode then there are certain positions/orientations (usualy near the line) that I can position the camera where the line disapears, or, even more strangely, has a second line coming off it's end point stretching off to some other point (usualy off camera, but once it ended on a pixel on the display and "stuck" to that pixel so when I moved the camera the "extra" line segment always ended on that same pixel). Also, in PMPoints mode the line still draws instead of just points. This is actualy the behavior I want, but don't want to rely on it if it's a bug and might be "fixed" in future releases.

I'll post me code here. The OgreRenderableControl just gets dropped on a form and the form calls the OgreRenderableControl's SetupOgre() in it's Load event.

Line3D.vb

edit: Code removed since I'm not using this class anymore. I'm using the OgreDotNet.Line3D class now that I didn't realize existed before. Still having same problems though.


OgreRenderableControl.vb

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

Public Class OgreRenderControl

Protected mRoot As Root = Nothing
Protected mRenderWindow As RenderWindow = Nothing
Protected mSceneManager As SceneManager = Nothing
Protected mCamera As Camera = Nothing
Protected mViewport As Viewport = Nothing
Protected mFilter As TextureFilterOptions = TextureFilterOptions.TfoBilinear
Protected mAnisotropy As UInt32 = 1

Protected mFlags As UInteger = 0
Protected mMouseX As Integer = 0
Protected mMouseY As Integer = 0
Protected mRotateMouse As Integer = 25
Protected mRotateDegrees As Single = 10.0F
Protected mZoomSpeed As Single = 100.0F
Protected mLine As Line3D = Nothing
Protected mUnitsPerSecond As Single = 100.0F
Protected mLastFrameTime As DateTime = Nothing

Public Enum ToggleBits As UInteger
LeftMouseButton = 1
RightMouseButton = 2
MoveForward = 4
MoveBackward = 8
MoveLeft = 16
MoveRight = 32
MoveUp = 64
MoveDown = 128
Moving = MoveForward Or MoveBackward Or MoveLeft Or MoveRight Or MoveUp Or MoveDown
End Enum

Private Sub OgreRenderControl_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
Select Case e.KeyCode
Case Windows.Forms.Keys.W, Windows.Forms.Keys.Up
SetFlag(ToggleBits.MoveForward)
Case Windows.Forms.Keys.S, Windows.Forms.Keys.Down
SetFlag(ToggleBits.MoveBackward)
Case Windows.Forms.Keys.A, Windows.Forms.Keys.Left
SetFlag(ToggleBits.MoveLeft)
Case Windows.Forms.Keys.D, Windows.Forms.Keys.Right
SetFlag(ToggleBits.MoveRight)
Case Windows.Forms.Keys.Q, Windows.Forms.Keys.PageUp
SetFlag(ToggleBits.MoveUp)
Case Windows.Forms.Keys.Z, Windows.Forms.Keys.PageDown
SetFlag(ToggleBits.MoveDown)
Case Windows.Forms.Keys.Space
Select Case mCamera.GetPolygonMode()
Case PolygonMode.PMPoints
mCamera.SetPolygonMode(PolygonMode.PMSolid)
Case PolygonMode.PMSolid
mCamera.SetPolygonMode(PolygonMode.PMWireframe)
Case PolygonMode.PMWireframe
mCamera.SetPolygonMode(PolygonMode.PMPoints)
End Select
UpdateDisplay()
End Select
If FlagIsSet(ToggleBits.Moving) Then
StartAnimation()
End If
End Sub

Protected Overrides Function ProcessCmdKey(ByRef msg As System.Windows.Forms.Message, ByVal keyData As System.Windows.Forms.Keys) As Boolean
Select Case keyData
Case Windows.Forms.Keys.W, Windows.Forms.Keys.Up
SetFlag(ToggleBits.MoveForward)
Case Windows.Forms.Keys.S, Windows.Forms.Keys.Down
SetFlag(ToggleBits.MoveBackward)
Case Windows.Forms.Keys.A, Windows.Forms.Keys.Left
SetFlag(ToggleBits.MoveLeft)
Case Windows.Forms.Keys.D, Windows.Forms.Keys.Right
SetFlag(ToggleBits.MoveRight)
End Select
If FlagIsSet(ToggleBits.Moving) Then
StartAnimation()
End If
Return MyBase.ProcessCmdKey(msg, keyData)
End Function

Private Sub OgreRenderControl_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyUp
Console.WriteLine(e.KeyCode.ToString() & " up")
Select Case e.KeyCode
Case Windows.Forms.Keys.W, Windows.Forms.Keys.Up
ClearFlag(ToggleBits.MoveForward)
Case Windows.Forms.Keys.S, Windows.Forms.Keys.Down
ClearFlag(ToggleBits.MoveBackward)
Case Windows.Forms.Keys.A, Windows.Forms.Keys.Left
ClearFlag(ToggleBits.MoveLeft)
Case Windows.Forms.Keys.D, Windows.Forms.Keys.Right
ClearFlag(ToggleBits.MoveRight)
Case Windows.Forms.Keys.Q, Windows.Forms.Keys.PageUp
ClearFlag(ToggleBits.MoveUp)
Case Windows.Forms.Keys.Z, Windows.Forms.Keys.PageDown
ClearFlag(ToggleBits.MoveDown)
End Select
If Not FlagIsSet(ToggleBits.Moving) Then
StopAnimation()
End If
End Sub

Private Sub MyOgreControl_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
End Sub

Public Function SetupOgre() As Boolean
mRoot = New Root()

SetupResources("resources.cfg")

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

mRenderWindow = mRoot.Initialise(Me)

mSceneManager = mRoot.CreateSceneManager(CUShort(SceneType.ExteriorClose))

mCamera = mSceneManager.CreateCamera("MainCamera")
mCamera.SetPosition(New Vector3(32000, 4000, 32000))
mCamera.LookAt = mCamera.Position + Vector3.UnitX
mCamera.SetNearClipDistance(5)

mViewport = mRenderWindow.AddViewport(mCamera, 0, 0.0F, 0.0F, 1.0F, 1.0F)
mViewport.SetBackgroundColour(Color.Black)
mCamera.AutoAspectRatio = True
mCamera.SetPolygonMode(PolygonMode.PMSolid)

TextureManager.Instance.SetDefaultNumMipmaps(5)

ResourceGroupManager.getSingleton().initialiseAllResourceGroups()

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

mSceneManager.SetAmbientLight(Color.FromArgb(127, 127, 127))
mSceneManager.SetWorldGeometry("terrain.cfg")

Dim ent As Entity

For i As Integer = 0 To 19
Dim headNode As SceneNode = mSceneManager.RootSceneNode.CreateChildSceneNode()
ent = mSceneManager.CreateEntity("head" + i.ToString(), "ogrehead.mesh")
headNode.AttachObject(ent)
Dim angle As New Radian(i * Math.PI / 10)
headNode.SetPosition(200 * Math.Cos(angle.ValueRadians), 0, 200 * Math.Sin(angle.ValueRadians))
headNode.Translate(32000, 4000, 32000, Node.TransformSpace.TS_LOCAL)
Next

mLine = New Line3D()

mLine.addPoint(New Vector3(31900, 3900, 31900))
mLine.addPoint(New Vector3(32100, 3900, 32100))
mLine.drawLines()

Dim lineNode As SceneNode = mSceneManager.RootSceneNode.CreateChildSceneNode("TestLine")
lineNode.AttachObject(mLine)

Return True
End Function

Private 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

Public Sub UpdateDisplay()
If mRoot IsNot Nothing Then
mRoot.RenderOneFrame()
mRenderWindow.Update()
End If
End Sub

Private Sub OgreRenderControl_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown
Me.Capture = True
If e.Button = Windows.Forms.MouseButtons.Right Then
SetFlag(ToggleBits.RightMouseButton)
End If
If e.Button = Windows.Forms.MouseButtons.Left Then
SetFlag(ToggleBits.LeftMouseButton)
End If
End Sub

Private Sub OgreRenderControl_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove
Dim deltaX As Integer = e.X - mMouseX
Dim deltaY As Integer = e.Y - mMouseY

Dim yawRadians As New Radian(New Degree(CSng(-deltaX) / CSng(mRotateMouse) * mRotateDegrees))
Dim pitchRadians As New Radian(New Degree(CSng(-deltaY) / CSng(mRotateMouse) * mRotateDegrees))

If FlagIsSet(ToggleBits.RightMouseButton) Then
mCamera.Yaw(yawRadians)
mCamera.Pitch(pitchRadians)
UpdateDisplay()
End If
mMouseX = e.X
mMouseY = e.Y
End Sub

Private Sub OgreRenderControl_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseUp
Me.Capture = False
If e.Button = Windows.Forms.MouseButtons.Right Then
ClearFlag(ToggleBits.RightMouseButton)
End If
If e.Button = Windows.Forms.MouseButtons.Left Then
ClearFlag(ToggleBits.LeftMouseButton)
End If
mMouseX = e.X
mMouseY = e.Y
End Sub

Private Sub OgreRenderControl_MouseWheel(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseWheel
If e.Delta > 0 Then
mCamera.MoveRelative(Vector3.NegativeUnitZ * mZoomSpeed)
ElseIf e.Delta < 0 Then
mCamera.MoveRelative(Vector3.UnitZ * mZoomSpeed)
End If
UpdateDisplay()
End Sub

Private Sub OgreRenderControl_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
Me.UpdateDisplay()
End Sub

Private Sub OgreRenderControl_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize
If mRenderWindow IsNot Nothing Then
mRenderWindow.WindowMovedOrResized()
UpdateDisplay()
End If
End Sub

Protected Sub SetFlag(ByVal bit As ToggleBits)
mFlags = mFlags Or bit
End Sub

Protected Sub ClearFlag(ByVal bit As ToggleBits)
mFlags = mFlags And (Not bit)
End Sub

Protected Function ToggleFlag(ByVal bit As ToggleBits) As Boolean
mFlags = mFlags Xor bit
Return FlagIsSet(bit)
End Function

Protected Function FlagIsSet(ByVal bit As ToggleBits) As Boolean
Return (mFlags And bit)
End Function

Protected Sub StartAnimation()
If tmrAnimate.Enabled = False Then
mLastFrameTime = DateTime.Now().Subtract(TimeSpan.FromMilliseconds(tmrAnimate.Interval))
tmrAnimate.Enabled = True
End If
End Sub

Protected Sub StopAnimation()
tmrAnimate.Enabled = False
End Sub

Private Sub tmrAnimate_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmrAnimate.Tick
Dim secondsSinceLastTick As Single
If mLastFrameTime.Day <> DateTime.Now().Day Then
secondsSinceLastTick = tmrAnimate.Interval
Else
secondsSinceLastTick = CSng((DateTime.Now() - mLastFrameTime).Milliseconds) / 1000
End If
mLastFrameTime = DateTime.Now()

If mCamera IsNot Nothing AndAlso FlagIsSet(ToggleBits.Moving) Then
If FlagIsSet(ToggleBits.MoveForward) Then
mCamera.MoveRelative(Vector3.UnitZ * (-mUnitsPerSecond * secondsSinceLastTick))
End If
If FlagIsSet(ToggleBits.MoveBackward) Then
mCamera.MoveRelative(Vector3.UnitZ * (mUnitsPerSecond * secondsSinceLastTick))
End If
If FlagIsSet(ToggleBits.MoveLeft) Then
mCamera.MoveRelative(Vector3.UnitX * (-mUnitsPerSecond * secondsSinceLastTick))
End If
If FlagIsSet(ToggleBits.MoveRight) Then
mCamera.MoveRelative(Vector3.UnitX * (mUnitsPerSecond * secondsSinceLastTick))
End If
If FlagIsSet(ToggleBits.MoveDown) Then
mCamera.MoveRelative(Vector3.UnitY * (-mUnitsPerSecond * secondsSinceLastTick))
End If
If FlagIsSet(ToggleBits.MoveUp) Then
mCamera.MoveRelative(Vector3.UnitY * (mUnitsPerSecond * secondsSinceLastTick))
End If
UpdateDisplay()
End If
End Sub
End Class


OgreRenderableControl.Designer.vb

<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class OgreRenderControl
Inherits System.Windows.Forms.UserControl

'UserControl overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
If mLine IsNot Nothing Then
mLine.Dispose()
End If
GC.Collect() ' force collect before root gets Dispose
If mRoot IsNot Nothing Then
mRoot.Dispose()
End If
MyBase.Dispose(disposing)
End Sub

'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
Me.components = New System.ComponentModel.Container
Me.tmrAnimate = New System.Windows.Forms.Timer(Me.components)
Me.SuspendLayout()
'
'tmrAnimate
'
Me.tmrAnimate.Enabled = True
Me.tmrAnimate.Interval = 33
'
'OgreRenderControl
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
Me.Name = "OgreRenderControl"
Me.Size = New System.Drawing.Size(148, 148)
Me.ResumeLayout(False)

End Sub
Friend WithEvents tmrAnimate As System.Windows.Forms.Timer

End Class

leep

01-09-2006 06:35:23

I didn't realize there was a Line3D already in OgreDotNet. But when I use OgreDotNet.Line3D instead of the VB class in my previous post, I have the same problem. Also now I've tried calling updatePoint(index, vertex3) to move the points and then calling drawLines() again and the whole thing disapears! I've read some other posts that suggest Line3D has problems with not updating correctly, and the wiki for Line3D mentions that it's better to use ManualObject. Unfortunately ManualObject isn't implemented in OgreDotNet yet and I don't know anything about using swig to try and generate a wrapper for it.

So... I'm at a slight loss now as to how to proceed. I need to draw a circle made up of line segments on the terrain with each point of the circle "snapped" to the terrain and with "depth_check off" on the line segments so they draw even if they're behind some terrain (like if the circle is at the top of a hill and the back side of the circle (from the camera's perspective) is behind the hill, I still want it to draw and not be "hidden" by the terrain). Line3D doesn't seem to work correctly when updating the points (which I need to do as the mouse is moved so the circle follows the mouse and conforms to the terrain where the mouse is pointing), and ManualObject isn't wrapped yet in OgreDotNet.

Any suggestions?

leep

02-09-2006 17:35:16

Ok, part of the "disapearing Line3D" problem was my fault. The function I wrote to snap a point to the terrain had a bug that made it frequently return Vector3(0,0,0) so all my points were getting snaped to origin. :oops:

But... Now I can move the Line3D circle around the terrain sometimes, but certain ways I turn the camera or certain places I position the camera and the Line3D circle disapears again. I'm logging the vectors now as I update them on the Line3D object and they are valid points (not 0,0,0). But the circle just disapears. If I move the camera slightly and/or turn it slightly, the circle starts displaying again.

BTW, if there's is a better place I should be posting these questions, please let me know. This OgreDotNet forum doesn't seem to get much traffic and I'm not sure if that's because OgreDotNet just isn't being used much, or if the few people posting just aren't asking the right questions. :D I realy do hope that OgreDotNet is popular enough to keep going. I love the fact that I can have a stable well tested/used rendering engine accessible to me, a VB.NET developer, and I hope the developers working on the OgreDotNet project (I believe Maleficus was the OgreDotNet founder) frequent this forum and can help us out. We need you! :D

leep

03-09-2006 17:09:47

I found a older post that made a reference to detaching the Line3D from its parent SceneNode and reattaching it after you call drawLines(). I tried it and that resolved the problem with the Line3D entity disapearing with certain camera positions and/or angles. This obviously isn't the intended behavior of Line3D, so the next natural question is... are the appropriate people (either with OgreDotNet or Ogre3D) aware of this issue and is a fix planned for future releases some time? Or is ManualObject the prefered method now of creating manual entities like this and will eventualy be wrapped in OgreDotNet?