Another .NET wrapper for Ogre (Mogre 0.1.6 released)

Anything and everything that's related to OGRE or the wider graphics field that doesn't fit into the other forums.
Bekas
OGRE Expert User
OGRE Expert User
Posts: 253
Joined: Sat Oct 16, 2004 11:21 pm
x 1

Another .NET wrapper for Ogre (Mogre 0.1.6 released)

Post by Bekas »

I started this thread to post some info for the .NET wrapper that I'm developing. "But why don't you use OgreDotNet", you say. Well, I looked into it but OgreDotNet has too many limitations which mostly come from SWIG's lacking support for C#. Plus, IMO SWIG is just too ugly to be used for wrapping more than simple things for C#.

So, I decided to go with the C++/CLI route. To avoid confusion with ODN let's call this wrapper 'Mogre' (Managed Ogre). C++/CLI is a vast improvement over the awful Managed Extensions, and wrapping Ogre with C++/CLI provides many advanced features/possibilities that are not even available in C#. You have absolute and low-level control of how the wrapping works, giving you the ability to make optimizations and integrate Ogre to the CLR seamlessly.

For example, I wanted the Ogre objects and the wrapping CLR objects to be interconnected so that when you do this:

Code: Select all

Camera cam1 = sceneMgr.CreateCamera("PlayerCam");
Camera cam2 = sceneMgr.GetCamera("PlayerCam");
bool areEqual = (cam1 == cam2);
both cam1 and cam2 should refer to the same CLR object (areEqual should be true). Although there was a way to do it without touching the Ogre code, the most optimized way was to add an extra member (CLRObject) to each of the wrapped Ogre classes and recompile Ogre. The CLRObject acts as the connection between the native Ogre camera and the .NET camera, keeps the .NET camera from getting garbage collected, and returns it to .NET when the native Ogre camera is requested.


The C++/CLI wrapping code is clean and straightforward. For example, once you take care of the various conversions, here's how the individual method wrapping goes:

Code: Select all

Camera^ CreateCamera(String^ name)
{
	DECLARE_OGRE_STRING(oName, name)
	return _native->createCamera(oName);
}

void SetPosition(Real x, Real y, Real z)
{
	_native->setPosition(x, y, z);
}

void SetPosition( Vector3 vec )
{
	_native->setPosition( vec );
}

Vector3 GetPosition(void)
{
	return _native->getPosition();
}
Integration with Windows.Forms is possible, allowing for easy creation of tools. i.e. (C# code):

Code: Select all

root.Initialise(false);
System.Collections.Specialized.NameValueCollection col = new System.Collections.Specialized.NameValueCollection();
// Render on a Panel
col["externalWindowHandle"] = panel1.Handle.ToString();
window = root.CreateRenderWindow("", 0, 0, false, col);
Mogre's major advantage is that the integration works in both ways (managed->native and native->managed), so, for example, Ogre's FrameListener is replaced by a .NET event that you can use in C#:

Code: Select all

public virtual void CreateFrameListener()
{
    _root.FrameStarted += new FrameEventHandler(app_frameStarted);
}

void app_FrameStarted(object sender, FrameEventArgs e)
{
    .........
}
Also, the wrapping classes can be subclassed by other .NET classes, and the native Ogre objects will call the overriding methods. Calling .NET methods from native objects is expensive so Mogre classes automatically locate if and which methods are getting overriden by a subclass and cross the CLR/native boundary only when a native object call these overriden methods (not for all the methods of the class).

The subclassing of Mogre wrapper classes provides many possibilities, for example a custom SceneManager can be implemented using your favourite .NET language and with the help of a "plugin proxy" the SceneManager will be loaded and used by Ogre.

The big disadvantage of Mogre is that it mixes native and managed code, so it can't be used in linux by Mono.

I plan on releasing the Mogre's source once I wrap a decent amount of Ogre's classes, to give back something to this great community.
Last edited by Bekas on Tue Sep 19, 2006 4:49 am, edited 3 times in total.
User avatar
raicuandi
Gargoyle
Posts: 1092
Joined: Wed Nov 09, 2005 12:56 pm
Location: Adelaide, Australia
Contact:

Post by raicuandi »

neat stuff!
can't wait! :wink:
grizzley90
Gnome
Posts: 318
Joined: Wed Jan 18, 2006 7:22 pm
Location: Montreal, Canada

Post by grizzley90 »

ask to start an ogre addon forum :D
User avatar
the_cX
Halfling
Posts: 77
Joined: Fri Mar 25, 2005 7:13 pm

Post by the_cX »

Bekas:

i like the feature of being about to replace ogre frame listeners with .NET ones. in fact, it looks niec in general. i am an OgreDotNet user and i am really happy with it. one of the main reasons that i am happy with it is because every class that i want to work, works. actually almost all of the class have been wrapped thus far. so i guess my question to you is, how long would it take you to wrap all of the ogre classes?

an example of some more less used classes that OgreDotNet has which impressed me: Pass, Technique, TextureUnitState:

Code: Select all

// create the material for the billboard
baseMaterialPtr = new MaterialPtr(MaterialManager.Instance.getByName("MiGraphNodeLabel"));

// clone this material into our own
this.mBillboardMaterial = baseMaterialPtr.Clone("GraphNodeLabel_Material_" + this.mName);

// change the texture on the material
this.mBillboardMaterial.GetTechnique(0).getPass(0).getTextureUnitState(0).setTextureName(
    this.mName.ToLower() + ".png");

// set this material on our billboard set
this.mBillboardSet.SetMaterialName(this.mBillboardMaterial.GetName());
EagleEye
Halfling
Posts: 62
Joined: Sun Nov 21, 2004 6:38 pm
Location: Omaha, Nebraska
Contact:

Post by EagleEye »

Correct me if I'm wrong here, but this MOgre sounds like it's meant to wrap Ogre in to a Managed C++ solution, precluding it from being used with C# or VB.NET. Am I wrong here?

If that's the case, that's fine, I just wanted a better understanding of the purpose. A managed C++ option sounds great for those that need it... as they say, it's "filling a need".
OgreDotNet Developer/Tester/Logistics Coordinator
Vermund MMORPG
Imperil

Post by Imperil »

EagleEye wrote:Correct me if I'm wrong here, but this MOgre sounds like it's meant to wrap Ogre in to a Managed C++ solution, precluding it from being used with C# or VB.NET. Am I wrong here?
Yes totally. All managed .NET code is interoperable with code from any assembly built in .NET. So if you write the wrapper in C++/CLI than it is usable with any of the .NET languages.
Bekas
OGRE Expert User
OGRE Expert User
Posts: 253
Joined: Sat Oct 16, 2004 11:21 pm
x 1

Post by Bekas »

the_cX wrote:so i guess my question to you is, how long would it take you to wrap all of the ogre classes?
It will certainly take quite some time to wrap as many classes as ODN. The plan is to have enough classes wrapped for porting a few of the Ogre demos and be able to get a .NET SceneManager working (I'll probably try to port OctreeSceneManager to C# and make it work through Ogre). Then I'll ask Sinbad if he will allow me to host the source files as an Ogre addon and hopefully others will offer some help too.
User avatar
raicuandi
Gargoyle
Posts: 1092
Joined: Wed Nov 09, 2005 12:56 pm
Location: Adelaide, Australia
Contact:

Post by raicuandi »

I'm currently wrapping OIS by hand. Dunno how much it'll take (OIS is much smaller than OGRE), but when I'm done, maybe I could give you a hand, or two :wink: ... (sory, I don't have more than 2 :P )
Bekas
OGRE Expert User
OGRE Expert User
Posts: 253
Joined: Sat Oct 16, 2004 11:21 pm
x 1

Post by Bekas »

That sounds great. What are you using to wrap OIS, C++/CLI or C# ?
User avatar
raicuandi
Gargoyle
Posts: 1092
Joined: Wed Nov 09, 2005 12:56 pm
Location: Adelaide, Australia
Contact:

Post by raicuandi »

I make the bindings in C++ and the actual wrapper for .NET in C#.

How do you make them?
Bekas
OGRE Expert User
OGRE Expert User
Posts: 253
Joined: Sat Oct 16, 2004 11:21 pm
x 1

Post by Bekas »

I use C++/CLI. Some references are here and here.

Basically, if you know C++ and C#, picking up the C++/CLI syntax is very easy.
User avatar
raicuandi
Gargoyle
Posts: 1092
Joined: Wed Nov 09, 2005 12:56 pm
Location: Adelaide, Australia
Contact:

Post by raicuandi »

And does C++/CLI produce .NET executables? (that can then be used in any .NET language?)
Bekas
OGRE Expert User
OGRE Expert User
Posts: 253
Joined: Sat Oct 16, 2004 11:21 pm
x 1

Post by Bekas »

Yes, of course. You can mix native and managed code and the other .NET languages will only see the managed stuff. For example, suppose you have this native class that you want to wrap:

Code: Select all

class Test
{
	int num;

public:
	Test(int n) : num(n)
	{
	}

	int multiply(int x)
	{
		return num*x;
	}
};
You can wrap it in C++/CLI like this:

Code: Select all

ref class TestWrap
{
	Test* _native;

public:
	TestWrap(int n) : _native(new Test(n))
	{
	}

	!TestWrap() {
		// This is the finalizer, delete the native object.
		if (_native != nullptr) {
			delete _native;
			_native = nullptr;
			}
	}

	~TestWrap() {
		// This is the Dispose method. Call the finalizer.
		this->!TestWrap();
	}

	int Multiply(int x)
	{
		return _native->multiply(x);
	}
};
TestWrap will be usable in C# (and other .NET languages) like this:

Code: Select all

TestWrap test = new TestWrap(5);
int result = test.Multiply(10);
You can even go the other way, wrap .NET classes to be used by native applications, the flexibility is amazing!

The only drawback is that, as I said in the first post, if you mix native and managed code, you can't use the dll on linux. If you don't mind this, then IMO C++/CLI is the best language for using native C++ code with .NET.
User avatar
raicuandi
Gargoyle
Posts: 1092
Joined: Wed Nov 09, 2005 12:56 pm
Location: Adelaide, Australia
Contact:

Post by raicuandi »

Wow, thanks alot Bekas!! :D
Now that I know "the other way", I can tell how you fell about SWIG.

Ok, once I'm done with OIS, I'll help you out wrapping OGRE3D (the one that's in the download section, respectively RC1). In fact, I'll need a good set of libs to work with C# for my own project(s), so its more a necesity.

((I was also thinking after I find/make the necesary parts, I could make a nice game engine for the .NET using OGRE,OIS,BASS(allready has a .NET wrapper) for sounds, and OgreNewt+Newton for pshysics, but thats a story for a later time :wink: ))
User avatar
Praetor
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 3335
Joined: Tue Jun 21, 2005 8:26 pm
Location: Rochester, New York, US
x 3
Contact:

Post by Praetor »

Yes for clarification's sake this is important everyone:

C++/CLI
C#
VN .NET

Are all the SAME as far as .NET is concerned. C++ is no longer the bastard child in .NET, it is a full first-class citizen of the runtime. This means all code compiled with .NET in any of these languages (any and all) is interoperable. It just seems people aren't yet used to C++ being a full member of the .Net framework, and it is.
User avatar
raicuandi
Gargoyle
Posts: 1092
Joined: Wed Nov 09, 2005 12:56 pm
Location: Adelaide, Australia
Contact:

Post by raicuandi »

Ok, thanks for the clarification!
User avatar
raicuandi
Gargoyle
Posts: 1092
Joined: Wed Nov 09, 2005 12:56 pm
Location: Adelaide, Australia
Contact:

Post by raicuandi »

With C++/CLI wrappers go much faster, BUT I can't seem to find out how to use properties (the get/set style from C#) in C++/CLI... :cry:

Can you help me please?
Imperil

Post by Imperil »

Properties are a C# language feature.. in C++ just write getter and setter functions unfortunately. Properties are one of the niceties of sharp.
User avatar
raicuandi
Gargoyle
Posts: 1092
Joined: Wed Nov 09, 2005 12:56 pm
Location: Adelaide, Australia
Contact:

Post by raicuandi »

I searched the MSDN and found this:
http://msdn2.microsoft.com/en-us/librar ... S.80).aspx

Good to know that lots of stuff changed since the 2003 edition :wink:
Bekas
OGRE Expert User
OGRE Expert User
Posts: 253
Joined: Sat Oct 16, 2004 11:21 pm
x 1

Post by Bekas »

Some useful references:
http://msdn2.microsoft.com/en-US/librar ... S.80).aspx
http://blogs.msdn.com/branbray/archive/ ... 41099.aspx

The only thing that I missed from C# is that you cannot call a constructor from another constructor, i.e:

Code: Select all

// C# code
class Test
{
   Test(int x)
   {
   }
   Test() : this(5)
   {
   }
}
but this is considered as a future addition to C++/CLI.
User avatar
Praetor
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 3335
Joined: Tue Jun 21, 2005 8:26 pm
Location: Rochester, New York, US
x 3
Contact:

Post by Praetor »

I'm not sure I want microsoft to take C++/CLI too far away from C++. They keep making little changes that make it NOT C++, and these changes have mostly been good. But you go too far.
User avatar
raicuandi
Gargoyle
Posts: 1092
Joined: Wed Nov 09, 2005 12:56 pm
Location: Adelaide, Australia
Contact:

Post by raicuandi »

The OIS wrapper I'm now making is C++/CLI is suppost to be used at least in C#. My question is how to handle enums? For example, some functions take some enums as parameters, or return an enum. How will I handle these? (especially, how will C# see the enums list?)

Do I have to re-declare the enums like this? :

Code: Select all

namespace OISDotNet {
  public enum class FOO {
    unu,
    doi,
    trei
  }
}
If I must do that, then how to handle passing enums? (since C++/CLI will throw an error regarding OIS::FOO is not OISDotNet::FOO)

I've managed to compile it like this:

Code: Select all

FooC(fooenum1 e1, fooenum2, e2) : _native((OIS::RealEnumWithSameNameAsFooEnum1)e1, (OIS::RealEnumWithSameNameAsFooEnum1)e2) {}
(whereas fooenum1&2 are defined like above - for .NET/CLI)
(also note that is the constructor for the FooC class)
Though I don't know if it will work OK... :cry:
Bekas
OGRE Expert User
OGRE Expert User
Posts: 253
Joined: Sat Oct 16, 2004 11:21 pm
x 1

Post by Bekas »

Yes, you got it right. You redefine the enum in a managed "enum class" and convert it using a plain cast

Code: Select all

(OIS::FOO)managedfooenum
or
(OISDotNet::Foo)nativefooenum
You should definately check out the first link of my previous post, it has links to almost everything you need to know about using C++/CLI (i.e. it has a "How to: Convert Between Managed and Standard Enumerations" link)
RobertIsele
Gnoblar
Posts: 2
Joined: Fri Mar 31, 2006 11:49 pm

Post by RobertIsele »

Properties are a C# language feature.. in C++ just write getter and setter functions unfortunately. Properties are one of the niceties of sharp.
No. Properties are a .Net feature. C# is one of the languages which supports them. Another one is 'managed C++" and it's successor C++/CLI.
The only thing that I missed from C# is that you cannot call a constructor from another constructor, i.e:
Code:

Code: Select all

// C# code
class Test
{
   Test(int x)
   {
   }
   Test() : this(5)
   {
   }
}
but this is considered as a future addition to C++/CLI.
yeah, this sucks, thought you could write this instead:

Code: Select all

class Test
{
   Test(int x)
   {
      Init(x);
   }
   Test()
   {
      Init(5);
   }
   public void Init(int x) { ... }
}
what really sucks is that you cannot define the point in time when the baseconstructor is called (like in Java or D) i.e.

Code: Select all

class Child : Parent
{
   public Child(int x)
   {
      DoSomething1();
      base(x); //Error, but works in other modern languages
      DoSomething2();
   }
}
Imperil

Post by Imperil »

RobertIsele wrote: No. Properties are a .Net feature. C# is one of the languages which supports them. Another one is 'managed C++" and it's successor C++/CLI.
Wow I failed to note the inclusion in CLI/C++. Thank you for correcting that point and my apologies if I mislead anyone.
Locked