Problem building with TerrainSceneManager support


11-09-2006 20:09:08

I've started with a very basic wrap of TerrainSceneManager, TerrainSceneManager.i:

#include "OgreTerrainSceneManager.h"

I also added an %include directive for this in ogre.i. Now when I try to build I get these 2 errors:

c:\development\libraries\ogrenew\plugins\octreescenemanager\include\OgreTerrainRenderable.h(286) : error C3083: 'Ogre': the symbol to the left of a '::' must be a type

c:\development\libraries\ogrenew\plugins\octreescenemanager\include\OgreTerrainRenderable.h(286) : error C3083: '{ctor}': the symbol to the left of a '::' must be a type

The errors both refer to the 2nd of these lines in TerrainRenderable.h:

void _updateCustomGpuParameter(
const GpuProgramParameters::AutoConstantEntry& constantEntry,
GpuProgramParameters* params) const;

I have no clue what the first error is trying to tell me since 'Ogre' doesn't even appear on that line. GpuProgramParameters and GpuProgramParameters::AutoConstantEntry are both defined in OgreGpuProgram.h which is included in OgreTerrainRenderable.h by way of OgreRenderable.h - so it should be found. The errors don't appear when I try to compile ogre itself which makes me think this is swig related. I'm a complete swig newb.

I'm working with: ogre 1.2.1 release, swigwin 1.3.29, pyogre from svn (a few weeks old), and I tried both VS.NET 7.1 (pro) and 8.0 (express), all on XP Pro. I can compile pyogre fine without modifications.

Any ideas?


14-09-2006 21:02:39

From browsing the SWIG mailing list archives it appears that this may be a shortcoming of SWIG wrt nested namespaces/classes. I'm working on it. Any advice would still be appreciated.


17-09-2006 18:57:28

Update on my progress

I've made progress by developing the OctreeSceneManager plugin as a separate SWIG project - the compile time errors have magically gone away when the main .i file is stripped down. One hair pulling problem I ran into, for future reference, was missing export directives in OctreeSceneManager and OctreeSceneManagerFactory that caused missing symbols during linking. Grr.

Now here's the problem that I have to work around. The OctreeSceneManager plugin is built into _octree.pyd, separate from _ogre.pyd, and for python it's a module contained within pyogre as pyogre.octree. But if I request an OctreeSceneManager or TerrainSceneManager from the Ogre core then, naturally, I get one that isn't wrapped (i.e. doesn't expose the extra functions of the octree and terrain scenemanagers). I only get a properly wrapped instance if I create it manually from the pyogre.octree module. That of course isn't how Ogre is supposed to work so I need to find a way to glue pyogre.ogre and pyogre.octree together in parallel to the way plugins work within the Ogre C++ core. I'm investigating the guts of Ogre, and more advanced SWIG features, to figure out the best way to do this without radical changes.

Essentially I'm working on the same issue as in this message, only in python instead of java:


18-09-2006 21:57:01

Perhaps look into how boost::python handles that as it re-links separate instances perfectly. (Hint, it uses types).


19-09-2006 22:33:34

Maybe this can help: ... highlight=

I have made a (half finished) plsm2 wrapper/proxy based on the same technique, so I might be able to answer questions if you have any and dermont doesn't answer.


20-09-2006 22:09:38

OvermindDL1: Thanks for the response, but I didn't have much luck hunting through the boost::python docs/wiki/mailing lists. It sounds like you might know specifically where to look, any advice?

viblo2: Yes I found that and it seems like a good alternative. I was hoping for the C++ to Python port to be as seamless as possible in terms of the API, but if that's not possible I'll use whatever technique works.

The other possibility I considered is extending Root.createSceneManager in the pyogre binding so it dynamically loads python modules if possible, and falls back on the C++ code if not. I just hope there are no thorny cross-dll issues.


20-09-2006 23:33:58

Sorry for the short answer last time, did not have time to elaborate. Boost::python uses the usual typemaps built into the compiler (RTTI has to be on) to identify classes. It does it in a manner that is portable (look at the source, the documentation does not define how this works as it is unnecessary, the source is clear if you know C++ 'well'). Everything boost::python builds into the python module, is, well, let me describe with an example. You have a class called OctreeSceneManager in C++. When you wrap it to expose it to python (you would not need to put it in a separate module like you are currently doing if you used boost::python) it adds the RTTI info in a compiler independent fashion to the new-style class that is exposed to python (yes, boost::python use new-style classes so it can only be used in 2.2.2 and higher effectively, faster, more capabilities, etc...). Anytime you pass a class to python through a wrapped function, it checks the RTTI of the type and wraps the appropriate python class around it according to the internal registry of wrapped classes. Doing that cross modules would require a little more finageling in that you'd have to write a function to handle that.

Although, since I've thought about it since yesterday, since you are not using boost::python, just go the cheap way and write your own wrapper function around ogre's createscenemanager() and if the string is of a type you wrapped in another module, have it call it from that module then correctly register it in ogre.

As I recall though, you should not need to even wrap those, just the base class. The base class for scenemanager's have a function where you can pass in and get data as strings and blank pointers, which could be wrapped into python. Just wrapping that should be fine to just get it working...

The reason it would work with boost::python though is its internal registry combined across all loaded instances, which swig does not do. You may even think about emulating that functionality...


21-09-2006 15:26:04

Thanks Overmind, that clears up a lot. I'll go with the createSceneManager wrapping method for now - although I'm comfortable with C++ I'll avoid digging through the boost source if I can.

More updates to come as progress warrants...


21-09-2006 19:53:18

Do note, since you are just going to wrap the creation function, you will need to access python's module's built-in and see what is loaded, if Octree isn't loaded when it is asked to be created, you will need to load it. Once loaded, get the module handle and instant a new octree class out of it, then extract the C++ pointer out of that python handler and register it manually with the Ogre engine. It would also be smart at that point to override the instance octree class __del__ method to override it so when it is deleted then it will automatically be dereference in Ogre (to help pythonize it). If you are still going to force them to be able to only delete it using the normal Ogre delete scene manager method, make sure to override it too so that it is removed from Ogre, but that Ogre does *not* delete it, as the python engine will need to delete it itself. You can then force a delete though by calling the function "del" with the parameter of the passed in handle for the scenemanager that python handles. Remember to let all other scenemanagers (everything but octree in other words, unless you handle others as well) pass through normally so that Ogre creates and deletes them itself.


21-09-2006 20:01:49

Wow, thanks a lot. I had considered those issues but not to that depth. I've worked with python dynamic module loading so for that part at least I have some useful code around to reuse, the rest will be a learning experience.


22-09-2006 21:20:13

Yea, most documentation about Python is *for* Python, not binding it with other things. I am embedding Python in my app (instead of Python being my app and binding other languages to it), and that was a *tremendous* learning experience. From that research, testing, experimentation, and much breaking, I now have a nice PythonEngine class that encapsulates most of what I've learned, from proper error handling (including making errors readable) to embedding (of course), to bringing in modules from source's other then files, to being able to serialize out an entire module to send to another computer on a network to unserialize and load up as if it was a native module, to many other things. It is a bit of pain (due to utter lack of documentation) for doing that, but it was well worth it. I now have a scripting engine similar to UTScript yet far more powerful.

Now that Python 2.5 Final is out, I need to update my source.