Using functions with void*

TobiasW

11-10-2008 23:54:38

Hello,

I'm currently trying to port the Tile Based Terrain to C#/Mogre, and nearly all that's left are some functions using void*, namely SceneManager.SetOption(String, void*) and HardwareVertexBufferSharedPtr.Write(uint, uint, void*, bool).

Examples of the two:
void* bounds = reinterpret_cast<void*>(&this->getBounds());
mSceneManager.SetOption("Size", bounds);


float[] vertices = createVertexBuffers(vbufCount, quality);
HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager.Singleton.CreateVertexBuffer(offset, msh.sharedVertexData.vertexCount, HardwareBuffer.Usage.HBU_STATIC_WRITE_ONLY);
vbuf.WriteData(0, vbuf.SizeInBytes, [b]vertices[/b], true);


How can I port this to C#?

Thanks in advance,
Tobias

Bostich

12-10-2008 13:24:27

Hi TobiasW,

Try it in this way:


float[] vertices = createVertexBuffers(vbufCount, quality);
HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager.Singleton.CreateVertexBuffer(offset, msh.sharedVertexData.vertexCount, HardwareBuffer.Usage.HBU_STATIC_WRITE_ONLY);

unsafe{
void* voidPtr;
fixed(float* floatPtr = vertices)
{
voidPtr = floatPtr;
vbuf.WriteData(0, vbuf.SizeInBytes, voidPtr, true);
}
}


You have to compile your Project as unsafe, otherwise it wont compile :P.

Bostich

TobiasW

12-10-2008 17:29:28

Hi Bostich,

great, thank you! Eliminated all errors except one doing it this way.

The one left is my first example. There I need to cast a AxisAlignedBox to void*.

This doesn't work:
unsafe
{
AxisAlignedBox bounds = getBounds();
fixed (void* boundsPtr = &bounds)
{
mSceneManager.SetOption("Size", boundsPtr);
}
}


The error is, freely translated from german: "It is not possible to declare a pointer for the managed type ("Mogre.AixAlignedBox") or to obtain its address or size."

Any ideas?

- Tobias

Bostich

12-10-2008 20:05:25

Hi Tobais,

Iam not sure about this, but please try this because atm i dont know how to marshal the hole AAB (and have currently no time to look at it more in depth)

But anyway, please try this:


using System.Runtime.InteropServices;
*snip*

AxisAlignedBox bounds = getBounds();
unsafe
{
IntPtr boundsPtr = IntPtr.Zero;
try
{
boundsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(bounds.Size));
Marshal.StructureToPtr(bounds.Size, boundsPtr, false);
mSceneManager.SetOption("Size", (void*)boundsPtr);
}
catch
{
}
finally
{
if (boundsPtr != IntPtr.Zero)
{
Marshal.FreeHGlobal(boundsPtr);
}
}
}


Bostich,

PS: Grüße aus Deutschland 8)

TobiasW

12-10-2008 20:18:53

Hi Bostich,

at least no compile warnings. The corresponding demo program doesn't work yet, so I cannot test if it works at runtime too, but I will post the result later.

It would be great if there was a SetOption(String, Object) version...

Thanks again!
- Tobias

PS: Oh, noch ein Deutscher? Sehr sympatisch! :)

TobiasW

12-10-2008 21:56:23

Umm... I just looked over the code (didn't have enough time when I answered): The AxisAlignedBox bounds isn't used anywhere in it, or is it?

Looking in the MSDN, it seems you meant this?

using System.Runtime.InteropServices;
*snip*

AxisAlignedBox bounds = getBounds();
unsafe
{
IntPtr boundsPtr = IntPtr.Zero;
try
{
boundsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(bounds));
Marshal.StructureToPtr(bounds, boundsPtr, false);
mSceneManager.SetOption("Size", (void*)boundsPtr);
}
catch
{
}
finally
{
if (boundsPtr != IntPtr.Zero)
{
Marshal.FreeHGlobal(boundsPtr);
}
}
}

Bostich

13-10-2008 07:43:48

Hi Tobias,

yes, that would be the perfect way, but:

please make a breakpoint at the and of the catch{}.

You will see that there will be an error!

Thats because Marshal.SizeOf() dont gets a size from the Bounds object. Cause "he" dont know how.

Thats the reason why i only took the size from your aab. if its not enough, one dirty idea would be to take each necessary value from the aab, Marshal it, and summate the values to one pointer. but i dont know if that works...(Iam not very good at this Marshaling shit 8) )

Bostich.

Bekas

13-10-2008 12:35:14

I need to cast a AxisAlignedBox to void*
The easiest and safest way is to use C++/CLI. AxisAlignedBox has a conversion operator to get a Ogre::AxisAlignedBox out of the Mogre one (only usable by C++/CLI). Try creating a C++/CLI assembly with a function to receive a Mogre::AxisAlignedBox^ and a Mogre::SceneManager^, convert them to Ogre::AxisAlignedBox and Ogre::SceneManager* (simply cast them) and call setOption on the Ogre::SceneManager.

You will need to #include the include files from modified Ogre's source and just put [#using "Mogre.dll"] to use the Mogre classes.

Bostich

13-10-2008 13:41:54

Hi Bekas,

in my Opinion it cant be a good solution to create a "wrapper", to be able to use a wrapper.

It must be possible to do that w/o anything modifying. Everything else is just a qick'n dirty hack.

Just my 2 cent 8)

Bostich

Bekas

13-10-2008 15:19:53

it cant be a good solution to create a "wrapper", to be able to use a wrapper.

It must be possible to do that w/o anything modifying. Everything else is just a qick'n dirty hack.

Yeah, I couldn't agree more. The sane thing would be to add a custom Mogre.SceneManager.SetOption method that accepts an AxisAlignedBox.

@TobiasW:
This is from the PLSM2Helper project:
public ref class PLSM2Options abstract sealed
{
public:
[....]
static bool SetOption( Mogre::SceneManager^ sceneMgr, String^ key, Mogre::AxisAlignedBox^ box )
{
Ogre::AxisAlignedBox o_box = (Ogre::AxisAlignedBox) box;

return sceneMgr->SetOption( key, (void*)&o_box );
}
[...]

TobiasW

19-10-2008 20:15:16

Hi,

thanks for all your suggestions!

Since this is not the only problem (another one is fiddling around with some pointers/arrays and I'm quite sure this is not the only problem concerning memory which is left in the code - just too much for a C#/Ogre/Mogre neophyte) I'm thinking of wrapping the whole code instead of porting it. I will read up on this in the next days.

You will need to #include the include files from modified Ogre's source and just put [#using "Mogre.dll"] to use the Mogre classes.
Where do I find this "modified Ogre source"? I read this somewhere else, too, but didn't find it anywhere.

- Tobias