MagicPhysX
MagicPhysX copied to clipboard
No way to attach PxSimulationEventCallback / PxSimulationEventCallback
There is any way to implement PxSimulationEventCallback
/ PxSimulationEventCallback
interfaces in c# to receive events / callbaks ?
I understand is not an easy task, I tried myself to rebuild the v-tables for PxContactModifyCallback
/ PxSimulationEventCallback
interfaces without success (nothing is called back, no exceptions).
This what i've done so far:
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
delegate void OnContactModifyDelegate(PxContactModifyPair* pairs, uint count);
_handler = (PxContactModifyCallback*)Marshal.AllocHGlobal(sizeof(PxSimulationEventCallback));
_handler->vtable_ = (void*)Marshal.AllocHGlobal(4 * sizeof(nint));
//first qword is 0, second is a pointer to the typeinfo, following the virtual functions.
//No idea how to recover typeinfo descriptor pointer
((nint*)_handler->vtable_)[2] = Marshal.GetFunctionPointerForDelegate((OnContactModifyDelegate)OnContactModify);
((nint*)_handler->vtable_)[3] = Marshal.GetFunctionPointerForDelegate((VoidDelegate)Distructor);
I've been having the same issue, found out that the function PxSimulationFilterShader must also be set. However a variable sent to that function seems to be incorrectly set.
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate PxFilterFlags PxSimulationFilterShader(uint attributes0, PxFilterData filterData0, uint attributes1, PxFilterData filterData1, ref PxPairFlags pairFlags, IntPtr constantBlock, uint constantBlockSize);
static PxFilterFlags CustomFilterShader(uint attributes0, PxFilterData filterData0, uint attributes1, PxFilterData filterData1, ref PxPairFlags pairFlags, IntPtr constantBlock, uint constantBlockSize)
{
return PxFilterFlags.Kill;
}
How the original physx version works is that you decide based on the attributes and filterdata what the PxPairFlags should be, in this case however pairFlags is a broken memory address.
Unfortunately we have to use a custom filter shader to properly assign the pairflags which if properly set calls the simulation event callback.
I have been at it for a while now, and still haven't been able to figure it out.
This is where I got the filter idea from NVIDIA Filter
You can enable the use of this contact modification callback by raising the flag PxPairFlag::eMODIFY_CONTACTS in the filter shader/callback (see PxSimulationFilterShader) for a pair of rigid body objects.
EDIT: The error i get with the pairflags variable is CORDBG_E_BAD_REFERENCE_VALUE
Potential solution? https://github.com/EmbarkStudios/physx-rs/issues/145
Would have to make this in rust however, change the default there which would be sub optimal.
Found it. I have On Contact working.
(small code dump about what I did) Creating the callbacks:
var simcallback = new SimulationEventCallbackInfo();
simcallback.collision_callback = (delegate* unmanaged[Cdecl]<void*, PxContactPairHeader*, PxContactPair*, uint, void>)Marshal.GetFunctionPointerForDelegate<CollisionCallback>(OnContactDelegateInstance).ToPointer();
var callbackinfoithink = create_simulation_event_callbacks(&simcallback);
sceneDesc.simulationEventCallback = callbackinfoithink;
var thing = (delegate* unmanaged[Cdecl]<FilterShaderCallbackInfo*, PxFilterFlags>)Marshal.GetFunctionPointerForDelegate<CustomFilterShaderDelegate>(CustomFilterShaderInstance).ToPointer();
enable_custom_filter_shader(&sceneDesc, thing, (uint)1);
And the actual callbacks:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void CustomFilterShaderDelegate(FilterShaderCallbackInfo* callbackInfo, PxFilterFlags filterFlags);
static void CustomFilterShader(FilterShaderCallbackInfo* callbackInfo, PxFilterFlags filterFlags)
{
PxPairFlags flags = PxPairFlags.ContactDefault | PxPairFlags.NotifyTouchFound;
callbackInfo->pairFlags[0] = flags;
}
public CustomFilterShaderDelegate CustomFilterShaderInstance = CustomFilterShader; // Assign the managed delegate to the unmanaged delegate instance
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
// public delegate*unmanaged[Cdecl]<void*, PxContactPairHeader*, PxContactPair*, uint, void> OnContactDelegate;
public delegate void CollisionCallback(IntPtr userData, PxContactPairHeader pairHeader, PxContactPair contacts, uint flags);
static void OnContact(IntPtr userData, PxContactPairHeader pairHeader, PxContactPair contacts, uint flags)
{
// On Contact...
// This took 7~ hours to get working.
Console.WriteLine("OnContact");
}
public CollisionCallback OnContactDelegateInstance = OnContact; // Assign the managed delegate to the unmanaged delegate instance
This is all based on the rust post from earlier, translated to C#. The 7 hours includes the hours before I found this issue.