That's a different approach to what I've to in NxOgre. I realise that Ogre and NxOgre are very different things, but the style of C++ API between the two is very similar. Anyway, this is what I have in NxOgre for the World Object (like Ogre's Root).
Code: Select all
#if NXOGRE_C_API == 1
extern "C"
{
struct NXC_WorldDescription
{
int assertion_policy;
unsigned int cooker_thread_mask;
unsigned int hardware_maximum_convex;
unsigned int hardware_page_size;
unsigned int hardware_maximum_page;
int no_hardware;
int per_scene_batching;
unsigned int gpu_heap_size;
unsigned int mesh_cache_size;
};
NXOGRE_C_FUNCTION void* NXC_WorldCreate(NXC_WorldDescription* d)
{
NxOgre::WorldDescription desc;
desc.mAssertionPolicy = (NxOgre::Enums::PhysXAssertionPolicy) d->assertion_policy;
desc.mCookerThreadMask = d->cooker_thread_mask;
desc.mGPUHeapSize = d->gpu_heap_size;
desc.mHardwareMaximumConvex = d->hardware_maximum_convex;
desc.mHardwareMaximumPage = d->hardware_maximum_page;
desc.mHardwarePageSize = d->hardware_page_size;
desc.mMeshCacheSize = d->mesh_cache_size;
desc.mNoHardware = d->no_hardware;
desc.mPerSceneBatching = d->per_scene_batching;
return NxOgre::World::createWorld(desc);
}
NXOGRE_C_FUNCTION void NXC_WorldDestroy()
{
NxOgre::World::destroyWorld();
}
NXOGRE_C_FUNCTION NXC_WorldDescription* NXC_WorldDescriptionNew()
{
NXC_WorldDescription* desc = new NXC_WorldDescription();
desc->assertion_policy = NxOgre::Enums::PhysXAssertionPolicy_Continue;
desc->cooker_thread_mask = 0;
desc->gpu_heap_size = 32;
desc->hardware_maximum_convex = 2048;
desc->hardware_maximum_page = 256;
desc->hardware_page_size = 65536;
desc->mesh_cache_size = 0xffffffff;
desc->no_hardware = true;
desc->per_scene_batching = true;
return desc;
}
NXOGRE_C_FUNCTION void NXC_WorldDescriptionReset(NXC_WorldDescription* desc)
{
std::cout << "Reseting\n";
desc->assertion_policy = NxOgre::Enums::PhysXAssertionPolicy_Continue;
desc->cooker_thread_mask = 0;
desc->gpu_heap_size = 32;
desc->hardware_maximum_convex = 2048;
desc->hardware_maximum_page = 256;
desc->hardware_page_size = 65536;
desc->mesh_cache_size = 0xffffffff;
desc->no_hardware = true;
desc->per_scene_batching = true;
}
NXOGRE_C_FUNCTION void NXC_WorldDescriptionDelete(NXC_WorldDescription* desc)
{
if (desc)
delete desc;
}
NXOGRE_C_FUNCTION void NXC_WorldAdvance(NxOgre::World* world, float time)
{
world->advance(time);
}
NXOGRE_C_FUNCTION NxOgre::World* NXC_WorldSingleton()
{
return NxOgre::World::getSingleton();
}
NXOGRE_C_FUNCTION void NXC_WorldSetAssertionPolicy(NxOgre::World* world, int policy)
{
world->setPhysXAssertionPolicy((NxOgre::Enums::PhysXAssertionPolicy) policy);
}
NXOGRE_C_FUNCTION int NXC_WorldGetAssertionPolicy(NxOgre::World* world)
{
return world->getPhysXAssertionPolicy();
}
}
#endif
I suppose my way is more of a direct wrapper, each function represents a classes method, which the first argument is a pointer to that method. The differences though, is that I'm using an int for a boolean value and enums. I've also mirrored the WorldDescription class which has constructors/destructors and methods to an aggregate struct called NXC_WorldDescription.
The second part is particularity useful as, I can duplicate the struct in Ruby code and just pass the pointer of that instance directly into NxOgre. My Ruby wrapping of the code is quite straight forward, it just turns the C API back into a Ruby OO API.
Code: Select all
require 'ffi'
module NxOgreLib
extend FFI::Library
ffi_lib 'NxOgreDebug.dll'
ffi_convention :stdcall
attach_function 'NXC_WorldCreate', [:pointer], :pointer
attach_function 'NXC_WorldDestroy', [], :void
attach_function 'NXC_WorldAdvance', [:pointer, :float], :void
attach_function 'NXC_WorldSetAssertionPolicy', [:pointer, :int], :void
attach_function 'NXC_WorldGetAssertionPolicy', [:pointer], :int
attach_function 'NXC_WorldDescriptionNew', [], :pointer
attach_function 'NXC_WorldDescriptionReset', [:pointer], :void
attach_function 'NXC_WorldDescriptionDelete', [:pointer], :void
class Enums
PHYSXASSERTIONPOLICY_CONTINUE = 0
PHYSXASSERTIONPOLICY_IGNORE = 1
PHYSXASSERTIONPOLICY_BREAKPOINT = 2
PHYSXASSERTIONPOLICY_EXCEPTION = 3
end
class WorldDescription < FFI::Struct
layout :assertion_policy, :int,
:cooker_thread_mask, :uint,
:hardware_maximum_convex, :uint,
:hardware_page_size, :uint,
:hardware_maximum_page, :uint,
:no_hardware, :int,
:per_scene_batching, :int,
:gpu_heap_size, :uint,
:mesh_cache_size, :uint
def initialize
self[:assertion_policy] = Enums::PHYSXASSERTIONPOLICY_CONTINUE
self[:cooker_thread_mask] = 0
self[:gpu_heap_size] = 32
self[:hardware_maximum_convex] = 2048
self[:hardware_maximum_page] = 256
self[:hardware_page_size] = 65536
self[:mesh_cache_size] = -1
self[:no_hardware] = 1
self[:per_scene_batching] = 1
end
end
class World
def self.createWorld!(world_desc)
@@singleton = World.new(world_desc)
return @@singleton
end
def self.destroyWorld!
@@singleton.shutdown
end
def self.instance
return @@singleton
end
def advance(deltaTime = 0.16667)
NxOgreLib.NXC_WorldAdvance(@world, deltaTime.to_f)
end
def initialize(world_desc)
@world = NxOgreLib.NXC_WorldCreate(world_desc)
end
def shutdown
NxOgreLib.NXC_WorldDestroy
end
def setAssertionPolicy(policy)
if policy == :continue
NxOgreLib.NXC_WorldSetAssertionPolicy(@world, Enums::PHYSXASSERTIONPOLICY_CONTINUE)
elsif policy == :ignore
NxOgreLib.NXC_WorldSetAssertionPolicy(@world, Enums::PHYSXASSERTIONPOLICY_IGNORE)
elsif policy == :breakpoint
NxOgreLib.NXC_WorldSetAssertionPolicy(@world, Enums::PHYSXASSERTIONPOLICY_BREAKPOINT)
elsif policy == :exception
NxOgreLib.NXC_WorldSetAssertionPolicy(@world, Enums::PHYSXASSERTIONPOLICY_EXCEPTION)
end
end
def getAssertionPolicy()
policy = NxOgreLib.NXC_WorldGetAssertionPolicy(@world)
if policy == Enums::PHYSXASSERTIONPOLICY_CONTINUE
return :continue
elsif policy == Enums::PHYSXASSERTIONPOLICY_IGNORE
return :ignore
elsif policy == Enums::PHYSXASSERTIONPOLICY_BREAKPOINT
return :breakpoint
elsif policy == :exception
return :exception
end
return :continue
end
end
end
In the end the NxOgre Ruby API is quite similar to NxOgre's, except I'm using symbols instead of enumeration values. I'd like to automate this somehow, perhaps make some sort of meta-language to generate the C and Ruby wrapping code for me.
I do like your approach though, it's different to what I first imagined, I thought you was going to do it like mine. How are you going to handle pointers and accessing objects? Multiple SceneManagers?