Creating my own Frame and Key Listener class

humantargetjoe

12-06-2006 16:16:45

I'm currently using VS2005 Express, and I'm trying to make my own frame listener class. Before using the CLR, I simply inherited from Ogre::FrameListener and Ogre::KeyListener. Now, however, that does not appear to be an option.

For instance, it looks a lot like this:

#ifndef __BasicFrameListener_H__
#define __BasicFrameListener_H__

ref class BasicFrameListener
{
private:
bool ShutdownRequested;
OgreDotNet::RenderWindow^ mRenderWindow;
OgreDotNet::EventProcessor^ mEventProcessor;
OgreDotNet::InputReader^ mInputDevice;

public:
BasicFrameListener(OgreDotNet::RenderWindow^ win)
{
mRenderWindow = win;
ShutdownRequested = false;

//mEventProcessor = new EventProcessor();
mEventProcessor->initialise(win);
mEventProcessor->startProcessingEvents();
//mEventProcessor->addKeyListener(this);
mInputDevice = mEventProcessor->getInputReader();
}

~BasicFrameListener()
{
//delete mEventProcessor;
}

// Override frameStarted event to process that
bool frameStarted(OgreDotNet::FrameEvent evt)
{
if(ShutdownRequested || mRenderWindow->Closed)
return false;
else
return true;
}

// Override frameEnded event to process that
bool frameEnded(OgreDotNet::FrameEvent evt)
{
return true;
}

void keyPressed(OgreDotNet::KeyEvent^ e)
{
//if(e->KeyCode == KC_ESCAPE)
{
ShutdownRequested = true;
//e->consume();
return;
}

//e->consume();
}

void keyClicked(OgreDotNet::KeyEvent^ e) {}
void keyReleased(OgreDotNet::KeyEvent^ e) {}
};

#endif // __BasicFrameListener_H__


Or, am I forced to use Example Application? Or do I need to write this as a native library and create some kind of wrapper for it?

DigitalCyborg

12-06-2006 16:33:15

you can override the event handling for any event you want.

take a look at ODN basic tutorial 4, and ODN intermediate tutorial 5, 7

humantargetjoe

12-06-2006 20:55:50

The tutorial is in C#, and not C++, however.

DigitalCyborg

13-06-2006 00:24:47

sorry. I haven't dabbled at all with managed C++, but I think you can use the OgreDotNetEventHandler class, which provides the connection to windows events. If you can't use code similar to this,


OgreDotNet.EventHandler mEventHandler;
mEventHandler = new OgreDotNet.EventHandler(mRoot, mRenderWindow);
mEventHandler.SubscribeEvents();
mEventHandler.FrameStarted += new FrameEventDelegate(FrameStarted);
mEventHandler.FrameEnded += new FrameEventDelegate(FrameEnded);


Then you might try inheriting OgreDotNet.EventHandler and see if that gets you what you want.

hope this helps... if not.. sorry.

cheers.

humantargetjoe

13-06-2006 14:49:41

sorry. I haven't dabbled at all with managed C++, but I think you can use the OgreDotNetEventHandler class, which provides the connection to windows events. If you can't use code similar to this,


OgreDotNet.EventHandler mEventHandler;
mEventHandler = new OgreDotNet.EventHandler(mRoot, mRenderWindow);
mEventHandler.SubscribeEvents();
mEventHandler.FrameStarted += new FrameEventDelegate(FrameStarted);
mEventHandler.FrameEnded += new FrameEventDelegate(FrameEnded);


Then you might try inheriting OgreDotNet.EventHandler and see if that gets you what you want.

hope this helps... if not.. sorry.

cheers.


That's almost certainly exactly the function/member I was looking for. If it's not it, it's probably close, thanks!

humantargetjoe

13-06-2006 20:26:02

Ok! So I got my .h all up and running, and I think it should be fine... But now I'm hitting an exception when it attempts to find lightSpecularColor when I run Root::Initialise()

An excerpt from my Ogre.log:
16:15:56: ***************************************
16:15:56: *** D3D9 : Subsystem Initialised OK ***
16:15:56: ***************************************
16:15:56: ResourceBackgroundQueue - threading disabled
16:15:56: Particle Renderer Type 'billboard' registered
16:15:56: Unregistering ResourceManager for type BspLevel
16:15:56: *-*-* OGRE Shutdown
16:15:56: Unregistering ResourceManager for type Compositor
16:15:56: Unregistering ResourceManager for type Font
16:15:56: Unregistering ResourceManager for type Skeleton
16:15:56: Unregistering ResourceManager for type Mesh
16:15:56: Unregistering ResourceManager for type HighLevelGpuProgram
16:15:56: Unloading library .\Plugin_CgProgramManager
16:15:56: Unloading library .\Plugin_OctreeSceneManager
16:15:56: Unloading library .\Plugin_BSPSceneManager
16:15:56: Unloading library .\Plugin_ParticleFX
16:15:56: *** Stopping Win32GL Subsystem ***
16:15:56: Unloading library .\RenderSystem_GL
16:15:56: Render Target 'My Window' Average FPS: 0 Best FPS: 0 Worst FPS: 999
16:15:56: D3D9 : Shutting down cleanly.
16:15:56: Unregistering ResourceManager for type Texture
16:15:56: Unregistering ResourceManager for type GpuProgram
16:15:56: D3D9 : Direct3D9 Rendering Subsystem destroyed.
16:15:56: Unloading library .\RenderSystem_Direct3D9
16:15:56: Unregistering ResourceManager for type Material
16:15:56: Unloading library OgrePlatform.dll


edit: copied from the wrong log file, fixed now

And what my WinMain looks like:


INT WinMain(HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
{
String^ strRenderSystemName = "Direct3D9 Rendering Subsystem";

Root^ mRoot = gcnew Root(/*String^ plugin*/"plugins.cfg",
/*String^ config*/"display.cfg",
/*String^ log*/"log.txt");

// Enumerate available Rendering Systems and select one. Direct X in this case.
RenderSystem^ myRenderSystem;
RenderSystemList^ AvailableRenderingSystems = mRoot->GetAvailableRenderers();
RenderSystemList::RenderSystemListEnumerator^ RenderingEnumerator = AvailableRenderingSystems->GetEnumerator();

while(RenderingEnumerator->MoveNext())
{
myRenderSystem = RenderingEnumerator->Current;

if(myRenderSystem->Name == strRenderSystemName)
{
myRenderSystem->SetConfigOption("Full Screen","No");
myRenderSystem->SetConfigOption("Video Mode","800 x 600 @ 16-bit colour");
mRoot->SetRenderSystem(myRenderSystem);
break;
}
}

// Initialize all these important things.
RenderWindow^ RenderWnd = mRoot->Initialise(true, "My Window");
BasicFrameListener^ myListener = gcnew BasicFrameListener(RenderWnd);
SceneManager^ mSceneMgr = mRoot->CreateSceneManager((unsigned short)SceneType::Generic);

// Setup the Scene
mSceneMgr->SetWorldGeometry("terrain.cfg");
//mSceneMgr->SetAmbientLight(::System::Drawing::Color); ??
mSceneMgr->SetSkyDome(true, "Examples/CloudySky", 5, 8);
SceneNode^ terrainNode = mSceneMgr->GetSceneNode("Terrain");

// Create a Camera and Viewport
Camera^ myCamera = mSceneMgr->GetCamera("PlayerCam");
myCamera->SetPosition( Vector3(100, 100, 500) );
myCamera->SetDirection( Vector3(0,0,500) );
myCamera->LookAt = Vector3(200,200,-300);
myCamera->NearClipDistance = 5;

Viewport^ myView = RenderWnd->AddViewport(myCamera);
//myView->SetBackgroundColour(::System::Drawing::Color); ??

mRoot->StartRendering();

return 0;
}

rastaman

13-06-2006 21:48:47

I don't see the exception text. What exactly does it say?

DigitalCyborg

13-06-2006 22:03:43

I see Error #7 too.

from ogre.txt logifle

Error #: 7
Function: GpuProgramParameters::getParamIndex
Description: Cannot find a parameter named lightSpecularColor.
File: c:\ogre\ogrenew\ogremain\src\ogregpuprogram.cpp
Line: 768
Stack unwinding: <<beginning of stack>>
21:33:25: Error at line 29 of deferred_post_minilight.hlsl.program: Invalid param_named_auto attribute - An exception has been thrown!


I always assumed that my graphics card just doesn't support that property since it doesn't kill the program.

humantargetjoe

14-06-2006 12:18:32

I don't see the exception text. What exactly does it say?

According to the Just In Time Debugging window, it's a "System.ArgumentException", which I presume means that some kind of casting is being called, and then is casted improperly at runtim which causes an exception that the compiler assumed would work.

There's no error in my log, so I'm not sure what's causing it, but when I run through the debugger, it breaks on this function:


SWIGEXPORT void * SWIGSTDCALL CSharp_SceneNode_DetachObject__SWIG_2(void * jarg1, char * jarg2) {
void * jresult ;
Ogre::SceneNode *arg1 = (Ogre::SceneNode *) 0 ;
Ogre::String *arg2 = 0 ;
Ogre::MovableObject *result = 0 ;

arg1 = (Ogre::SceneNode *)jarg1;
if (!jarg2) {
SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "null string", 0);
return 0;
}
std::string arg2_str(jarg2);
arg2 = &arg2_str;
result = (Ogre::MovableObject *)(arg1)->detachObject((Ogre::String const &)*arg2);
jresult = (void *)result;
return jresult;
}


on the if(!jarg2) line.

Before that on the stack is the call to Initialise (and a bunch of assembly in between probably caused by running in release with a [Managed to Native Transition] on several of the lines.).

I still can't really run in debug because of the bad manifest issue, and my compiler is building bad versions of the native Ogre dlls, so I'm still using the precompiled release ones, because they work.

humantargetjoe

14-06-2006 16:02:04

Update:

What I'm getting is this (I've fixed my debug dll issues)

----------------------
Details:
----------------------
Error #: 2
Function: Root::initialise
Description: Cannot initialise - no render system has been selected.

Stepping through it, it's not actually entering the while(RenderingEnumerator->MoveNext()) conditional, because MoveNext() is returning an error, because RenderSystemList is empty...

Have I set this up wrong?

humantargetjoe

14-06-2006 18:48:00

Update:

What I'm getting is this (I've fixed my debug dll issues)

----------------------
Details:
----------------------
Error #: 2
Function: Root::initialise
Description: Cannot initialise - no render system has been selected.

Stepping through it, it's not actually entering the while(RenderingEnumerator->MoveNext()) conditional, because MoveNext() is returning an error, because RenderSystemList is empty...

Have I set this up wrong?


Ok, I fixed this by beating on the execution path for the debugger.

Now I just need to figure out how to get it to load some terrain, but I don't see that in any of the OgreDotNet demos.

DigitalCyborg

14-06-2006 20:10:28

actually its covered in the tutorials on the wiki. (basic 3, intermediate 2,3,4,6) ...

pick the correct scene manager:

mSceneManager = mRoot.CreateSceneManager((ushort)SceneType.ExteriorClose);


tell the scene manager to load a terrain,

mSceneManager.SetWorldGeometry("terrain.cfg");


Compile and run your program. It's that easy. You might want to set the Camera to start in a place that's over the terrain

humantargetjoe

14-06-2006 20:24:11

actually its covered in the tutorials on the wiki. (basic 3, intermediate 2,3,4,6) ...

pick the correct scene manager:

mSceneManager = mRoot.CreateSceneManager((ushort)SceneType.ExteriorClose);


tell the scene manager to load a terrain,

mSceneManager.SetWorldGeometry("terrain.cfg");


Compile and run your program. It's that easy. You might want to set the Camera to start in a place that's over the terrain


Yes, but doing that uses ExampleApplication to do all the work. I actually have put in a function to parse the resource locations file, but it still doesn't want to find my terrain.cfg file (which is located in my SDK folder, the same place that the native terrain demo points to), as it crashes when it attempts to load that.

I already built a camera and a viewport, and I can even load the robot.mesh.... though I can't set the light because it seems as though System::Drawing::Color does not exist as far as my compiler is concerned (doesn't show up in intellisense either).

DigitalCyborg

15-06-2006 00:09:11

those 2 lines of code should be easily translateable...

substitute your SceneManager variable and your Root varaible & put them in your application wherever you select the scenemanager and wherever you create the scene.

DigitalCyborg

15-06-2006 03:16:12

Hi again,
Does terrain.cfg load for you when you use the ExampleApplication framework?

If it does, then we'll need to debug your resource location and parsing, if not, we can probably look at resources.cfg (or your version of it) and see what's going on

humantargetjoe

15-06-2006 12:39:23

Hi again,
Does terrain.cfg load for you when you use the ExampleApplication framework?

If it does, then we'll need to debug your resource location and parsing, if not, we can probably look at resources.cfg (or your version of it) and see what's going on


Not sure... none of the C# demos use a terrain, and all the terrain examples i have are in Native. I'll have to check and see if it's getting added seperately as an additional resource location.

Here's what I have to initialize resources:

void InitializeResources(System::String^ resourceFileName)
{
// Use System namespace locally so that strings don't all need the System:: indirection
using namespace System;
IO::StreamReader^ sr = gcnew IO::StreamReader(resourceFileName);
String ^secName, ^sLocType, ^sarchName, ^line;

while((line = sr->ReadLine()))
{
int i = line->IndexOf("#");

if(i > -1)
line = line->Substring(0, i);

line = line->Trim();

if(line->Length > 0)
{
if(line[0] == '[')
{
secName = line->Substring(1, line->Length - 2);
}
else if(secName->Length > 0)
{
i = line->IndexOf("=");
if(i > 0)
{
sLocType = line->Substring(0, i);
sarchName = line->Substring(i + 1);
ResourceGroupManager::getSingleton()->
addResourceLocation(sarchName, sLocType, secName);
}
}
}// Line Length
}// ReadLine while

ResourceGroupManager::getSingleton()->initialiseAllResourceGroups();
}


and this is my OgreDotNet resouces.cfg file:

# Resource locations to be added to the 'boostrap' path
# This also contains the minimum you need to use the Ogre example framework

[Bootstrap]
Zip=C:\OgreSDK\media\packs\OgreCore.zip

# Resource locations to be added to the default path

[General]

FileSystem=C:\OgreSDK\media
FileSystem=C:\OgreSDK\media\fonts
FileSystem=C:\OgreSDK\media\materials\programs
FileSystem=C:\OgreSDK\media\materials\scripts
FileSystem=C:\OgreSDK\media\materials\textures
FileSystem=C:\OgreSDK\media\models
FileSystem=C:\OgreSDK\media\overlays
FileSystem=C:\OgreSDK\media\particle
FileSystem=C:\OgreSDK\media\gui
FileSystem=C:\OgreSDK\media\DeferredShadingMedia

Zip=C:\OgreSDK\media\packs\cubemap.zip
Zip=C:\OgreSDK\media\packs\cubemapsJS.zip
Zip=C:\OgreSDK\media\packs\dragon.zip
Zip=C:\OgreSDK\media\packs\fresneldemo.zip
Zip=C:\OgreSDK\media\packs\ogretestmap.zip
Zip=C:\OgreSDK\media\packs\skybox.zip

FileSystem=..\..\Samples\Media

#To use GangstaDotNet, correct the path and uncomment the line below
#FileSystem=@GangstaWrapper@\..\Gangsta_Ogre\Samples\Media


The resource file I haven't touched, and if you look at ExampleRefApplication.h you'll see I pretty much lifted the entire method and changed the syntax to match CLR C++.

My directory structure looks like this -

C:\OGRE\ogrenew // Ogre native source
C:\OGRE\ogreaddons\ogredotnet // OgreDotNet
C:\OgreSDK // SDK folder

humantargetjoe

15-06-2006 13:27:43

As an addendum, I can load the robot mesh, and I can load the Examples/Rockwall material to put a robot on a plane... So it's definately parsing some of these correctly. I THINK that it's finding these materials in the SDK folder, since I don't see them in the ogredotnet Media folder... so it by all rights probably ought to be able to find the terrain.cfg file unless there's something whacky I'm missing.

Here's my WinMain function:

String^ strRenderSystemName = "Direct3D9 Rendering Subsystem";
String^ strResourceFileName = "resources.cfg";

Root^ mRoot = gcnew Root("plugins.cfg", "ogre.cfg", "log.txt");

// Enumerate available Rendering Systems and select one. Direct X in this case.
RenderSystem^ myRenderSystem;
RenderSystemList^ AvailableRenderingSystems = mRoot->AvailableRenderers;
RenderSystemList::RenderSystemListEnumerator^ RenderingEnumerator = AvailableRenderingSystems->GetEnumerator();

while(RenderingEnumerator->MoveNext())
{
myRenderSystem = RenderingEnumerator->Current;

if(myRenderSystem->Name == strRenderSystemName)
{
myRenderSystem->SetConfigOption("Full Screen","No");
myRenderSystem->SetConfigOption("Video Mode","800 x 600 @ 16-bit colour");
mRoot->SetRenderSystem(myRenderSystem);
break;
}
}

// Initialize all these important things.
RenderWindow^ RenderWnd = mRoot->Initialise(true, "My Window");
BasicFrameListener^ myListener = gcnew BasicFrameListener(RenderWnd, mRoot);
myListener->InitializeResources(strResourceFileName);
SceneManager^ mSceneMgr = mRoot->CreateSceneManager((unsigned short)SceneType::ExteriorClose);

// Setup the Scene
//mSceneMgr->SetWorldGeometry("terrain.cfg");
//mSceneMgr->SetSkyDome(true, "Examples/CloudySky", 5, 8);
//SceneNode^ terrainNode =
mSceneMgr->GetSceneNode("Terrain");
Entity^ myEnt = mSceneMgr->CreateEntity("Robot1", "robot.mesh");
SceneNode^ robotNode =
mSceneMgr->GetRootSceneNode()->CreateChildSceneNode( Vector3(200, 100, -300), Quaternion(1,0,0,0));
robotNode->AttachObject(myEnt);

Plane^ plane = gcnew Plane( Vector3::UnitY, 0 );

MeshManager::GetSingleton()->CreatePlane("Myplane",
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
plane, 1500, 1500, 20, 20, true, 1, 60, 60,
Vector3::UnitZ);

Entity^ PlaneEnt = mSceneMgr->CreateEntity( "plane", "Myplane" );
PlaneEnt->SetMaterialName("Examples/Rockwall");
PlaneEnt->SetCastShadows(false);
SceneNode^ planeNode =
mSceneMgr->GetRootSceneNode()->CreateChildSceneNode(Vector3(0,99,0));
planeNode->AttachObject(PlaneEnt);

// Create a Camera and Viewport
Camera^ myCamera = mSceneMgr->CreateCamera("PlayerCam");
myCamera->SetPosition( Vector3(100, 300, 200) );
myCamera->SetDirection( Vector3(0,0,500) );
myCamera->LookAt = Vector3(200,200,-300);
myCamera->NearClipDistance = 5;

Viewport^ myView = RenderWnd->AddViewport(myCamera);
//myView->SetBackgroundColour(::System::Drawing::Color); ??

mRoot->StartRendering();

return 0;


I've commented out the terrain loading since it crashes with it in and I've been testing whether or not it grabbed some other things (like the aforementioned mesh and material).

DigitalCyborg

15-06-2006 19:54:34

Rastaman : is this legal?

//SceneNode^ terrainNode = mSceneMgr->GetSceneNode("Terrain")

I didn't think terrains were handled as Nodes.

humantargetjoe

15-06-2006 20:14:58

Rastaman : is this legal?

//SceneNode^ terrainNode = mSceneMgr->GetSceneNode("Terrain")

I didn't think terrains were handled as Nodes.



Even if it's not, my error is in the setWorldGeometry call, in SceneManager.cs

public virtual void SetWorldGeometry(string filename) {
OgreBindingsPINVOKE.SceneManager_SetWorldGeometry__SWIG_0(swigCPtr, filename);
if (OgreBindingsPINVOKE.SWIGPendingException.Pending) throw OgreBindingsPINVOKE.SWIGPendingException.Retrieve();
}

Bekas

16-06-2006 01:36:11

I don't quite see the point of using C++/CLI with OgreDotNet.

-Using C# and OgreDotNet has the benefits of faster compilation, better productivity, portability etc.

-Using C++/CLI and accessing the native Ogre has the benefits that you are using Ogre directly without a wrapper layer and its limitations/quirks.

-Using C++/CLI and OgreDotNet drops all benefits..

humantargetjoe

16-06-2006 11:56:06

Mostly because I have the constraint (since this is in large part due to my workplace) that I need to be using C++/CLI, and there isn't really an all-managed alternative.

Given the choice, I'd just keep using standard C++, but it's not my choice to make.

humantargetjoe

16-06-2006 13:02:04

Ah HA! Success. I changed the initialization to a DataStreamPtr, and this time, when it threw an exception, it made it's way to my log where I recieved:


07:37:41: TerrainSceneManager: Activated PageSource Heightmap
07:37:41: Texture: terrain_texture.jpg: Loading 1 faces(PF_B8G8R8,512x512x1) with hardware generated mipmaps from Image. Internal format is PF_X8R8G8B8,512x512x1.
07:37:41: Texture: terrain_detail.jpg: Loading 1 faces(PF_B8G8R8,256x256x1) with hardware generated mipmaps from Image. Internal format is PF_X8R8G8B8,256x256x1.
07:37:41: An exception has been thrown!

-----------------------------------
Details:
-----------------------------------
Error #: 7
Function: TerrainRenderable::_calculateCFactor
Description: You have not created a camera yet!.
File: c:\ogre\ogrenew\plugins\octreescenemanager\src\ogreterrainrenderable.cpp
Line: 658


Ok, So I moved the line where I set world geometry below where I create the camera and viewport, and now no crash! I don't see the terrain either, but it's probably somewhere outside of my camera's view.