#include "PxPhysicsAPI.h"
#include <cstdint>
#include "physx_generated.hpp"
PxDefaultAllocator gAllocator;
PxDefaultErrorCallback gErrorCallback;
struct FilterShaderCallbackInfo
{
PxFilterObjectAttributes attributes0;
PxFilterObjectAttributes attributes1;
PxFilterData filterData0;
PxFilterData filterData1;
PxPairFlags *pairFlags;
const void *constantBlock;
PxU32 constantBlockSize;
};
typedef void (*CollisionCallback)(void *, PxContactPairHeader const *, PxContactPair const *, PxU32);
extern "C" typedef PxU16 (*SimulationShaderFilter)(FilterShaderCallbackInfo *);
struct FilterCallbackData {
SimulationShaderFilter filter;
bool call_default_filter_shader_first;
};
PxFilterFlags FilterShaderTrampoline(PxFilterObjectAttributes attributes0,
PxFilterData filterData0,
PxFilterObjectAttributes attributes1,
PxFilterData filterData1,
PxPairFlags &pairFlags,
const void *constantBlock,
PxU32 constantBlockSize)
{
const FilterCallbackData *data = static_cast<const FilterCallbackData *>(constantBlock);
if (data->call_default_filter_shader_first) {
PxDefaultSimulationFilterShader(attributes0, filterData0, attributes1, filterData1, pairFlags, constantBlock,
constantBlockSize);
}
SimulationShaderFilter shaderfilter = data->filter;
FilterShaderCallbackInfo info{attributes0, attributes1, filterData0, filterData1, &pairFlags, nullptr, 0};
return PxFilterFlags{shaderfilter(&info)};
}
using CollisionCallback = void (*)(void *, PxContactPairHeader const *, PxContactPair const *, PxU32);
using TriggerCallback = void (*)(void *, PxTriggerPair const *, PxU32);
using ConstraintBreakCallback = void (*)(void *, PxConstraintInfo const *, PxU32);
using WakeSleepCallback = void (*)(void *, PxActor **const, PxU32, bool);
using AdvanceCallback = void (*)(void *, const PxRigidBody *const *, const PxTransform *const, PxU32);
struct SimulationEventCallbackInfo {
CollisionCallback collisionCallback = nullptr;
void *collisionUserData = nullptr;
TriggerCallback triggerCallback = nullptr;
void *triggerUserData = nullptr;
ConstraintBreakCallback constraintBreakCallback = nullptr;
void *constraintBreakUserData = nullptr;
WakeSleepCallback wakeSleepCallback = nullptr;
void *wakeSleepUserData = nullptr;
AdvanceCallback advanceCallback = nullptr;
void *advanceUserData = nullptr;
};
class SimulationEventTrampoline : public PxSimulationEventCallback
{
public:
SimulationEventTrampoline(const SimulationEventCallbackInfo *callbacks) : mCallbacks(*callbacks) {}
void onContact(const PxContactPairHeader &pairHeader, const PxContactPair *pairs, PxU32 nbPairs) override {
if (mCallbacks.collisionCallback) {
mCallbacks.collisionCallback(mCallbacks.collisionUserData, &pairHeader, pairs, nbPairs);
}
}
void onTrigger(PxTriggerPair *pairs, PxU32 count) override {
if (mCallbacks.triggerCallback) {
mCallbacks.triggerCallback(mCallbacks.triggerUserData, pairs, count);
}
}
void onConstraintBreak(PxConstraintInfo *constraints, PxU32 count) override {
if (mCallbacks.constraintBreakCallback) {
mCallbacks.constraintBreakCallback(mCallbacks.constraintBreakUserData, constraints, count);
}
}
void onWake(PxActor **actors, PxU32 count) override {
if (mCallbacks.wakeSleepCallback) {
mCallbacks.wakeSleepCallback(mCallbacks.wakeSleepUserData, actors, count, true);
}
}
void onSleep(PxActor **actors, PxU32 count) override {
if (mCallbacks.wakeSleepCallback) {
mCallbacks.wakeSleepCallback(mCallbacks.wakeSleepUserData, actors, count, false);
}
}
void onAdvance(const PxRigidBody *const * bodyBuffer, const PxTransform *poseBuffer, const PxU32 count) override {
if (mCallbacks.advanceCallback) {
mCallbacks.advanceCallback(mCallbacks.advanceUserData, bodyBuffer, poseBuffer, count);
}
}
SimulationEventCallbackInfo mCallbacks;
};
class RaycastFilterCallback : public PxQueryFilterCallback
{
public:
explicit RaycastFilterCallback(PxRigidActor *actor) : mActor(actor) {}
PxRigidActor *mActor;
virtual PxQueryHitType::Enum preFilter(const PxFilterData &, const PxShape *shape, const PxRigidActor *actor, PxHitFlags &)
{
if (mActor == actor)
{
return PxQueryHitType::eNONE;
}
else
{
return PxQueryHitType::eBLOCK;
}
}
virtual PxQueryHitType::Enum postFilter(const PxFilterData &, const PxQueryHit &)
{
return PxQueryHitType::eNONE;
}
};
typedef uint32_t (*RaycastHitCallback)(const PxRigidActor *actor, const PxFilterData *filterData, const PxShape *shape, uint32_t hitFlags, const void *userData);
class RaycastFilterTrampoline : public PxQueryFilterCallback
{
public:
RaycastFilterTrampoline(RaycastHitCallback callback, const void *userdata)
: mCallback(callback), mUserData(userdata) {}
RaycastHitCallback mCallback;
const void *mUserData;
virtual PxQueryHitType::Enum preFilter(const PxFilterData &filterData, const PxShape *shape, const PxRigidActor *actor, PxHitFlags &hitFlags)
{
switch (mCallback(actor, &filterData, shape, (uint32_t)hitFlags, mUserData)) {
case 0: return PxQueryHitType::eNONE;
case 1: return PxQueryHitType::eTOUCH;
case 2: return PxQueryHitType::eBLOCK;
default: return PxQueryHitType::eNONE;
}
}
virtual PxQueryHitType::Enum postFilter(const PxFilterData &, const PxQueryHit &)
{
return PxQueryHitType::eNONE;
}
};
typedef void * (*AllocCallback)(uint64_t size, const char *typeName, const char *filename, int line, void *userdata);
typedef void (*DeallocCallback)(void *ptr, void *userdata);
class CustomAllocatorTrampoline : public PxAllocatorCallback {
public:
CustomAllocatorTrampoline(AllocCallback allocCb, DeallocCallback deallocCb, void *userdata)
: mAllocCallback(allocCb), mDeallocCallback(deallocCb), mUserData(userdata) {
}
void *allocate(size_t size, const char* typeName, const char* filename, int line) {
return mAllocCallback((uint64_t)size, typeName, filename, line, mUserData);
}
virtual void deallocate(void* ptr) {
mDeallocCallback(ptr, mUserData);
}
private:
AllocCallback mAllocCallback;
DeallocCallback mDeallocCallback;
public:
void *mUserData;
};
typedef void * (*ZoneStartCallback)(const char *typeName, bool detached, uint64_t context , void *userdata);
typedef void (*ZoneEndCallback)(void* profilerData, const char *typeName, bool detached, uint64_t context , void *userdata);
class CustomProfilerTrampoline : public PxProfilerCallback {
public:
CustomProfilerTrampoline(ZoneStartCallback startCb, ZoneEndCallback endCb, void *userdata)
: mStartCallback(startCb), mEndCallback(endCb), mUserData(userdata) {
}
virtual void* zoneStart(const char* eventName, bool detached, uint64_t contextId) override
{
return mStartCallback(eventName, detached, contextId, mUserData);
}
virtual void zoneEnd(void* profilerData, const char* eventName, bool detached, uint64_t contextId) override
{
return mEndCallback(profilerData, eventName, detached, contextId, mUserData);
}
private:
ZoneStartCallback mStartCallback;
ZoneEndCallback mEndCallback;
public:
void *mUserData;
};
using ErrorCallback = void (*)(int code, const char* message, const char* file, int line, void* userdata);
class ErrorTrampoline : public PxErrorCallback {
public:
ErrorTrampoline(ErrorCallback errorCb, void* userdata)
: mErrorCallback(errorCb), mUserdata(userdata)
{}
void reportError(PxErrorCode::Enum code, const char* message, const char* file, int line) override {
mErrorCallback(code, message, file, line, mUserdata);
}
private:
ErrorCallback mErrorCallback = nullptr;
void* mUserdata = nullptr;
};
using AssertHandler = void (*)(const char* expr, const char* file, int line, bool* should_ignore, void* userdata);
class AssertTrampoline : public PxAssertHandler {
public:
AssertTrampoline(AssertHandler onAssert, void* userdata)
: mAssertHandler(onAssert), mUserdata(userdata)
{}
virtual void operator()(const char* exp, const char* file, int line, bool& ignore) override final {
mAssertHandler(exp, file, line, &ignore, mUserdata);
}
private:
AssertHandler mAssertHandler = nullptr;
void* mUserdata = nullptr;
};
extern "C"
{
PxFoundation *physx_create_foundation()
{
return PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);
}
PxFoundation *physx_create_foundation_with_alloc(PxAllocatorCallback *allocator)
{
return PxCreateFoundation(PX_PHYSICS_VERSION, *allocator, gErrorCallback);
}
PxAllocatorCallback* get_default_allocator()
{
return &gAllocator;
}
PxErrorCallback* get_default_error_callback()
{
return &gErrorCallback;
}
PxPhysics *physx_create_physics(PxFoundation *foundation)
{
return PxCreatePhysics(PX_PHYSICS_VERSION, *foundation, PxTolerancesScale(), true, nullptr);
}
PxQueryFilterCallback *create_raycast_filter_callback(PxRigidActor *actor_to_ignore)
{
return new RaycastFilterCallback(actor_to_ignore);
}
PxQueryFilterCallback *create_raycast_filter_callback_func(RaycastHitCallback callback, void *userData) {
return new RaycastFilterTrampoline(callback, userData);
}
PxAllocatorCallback *create_alloc_callback(
AllocCallback alloc_callback,
DeallocCallback dealloc_callback,
void *userdata
) {
return new CustomAllocatorTrampoline(alloc_callback, dealloc_callback, userdata);
}
void *get_alloc_callback_user_data(PxAllocatorCallback *allocator) {
CustomAllocatorTrampoline *trampoline = static_cast<CustomAllocatorTrampoline *>(allocator);
return trampoline->mUserData;
}
PxProfilerCallback *create_profiler_callback(
ZoneStartCallback zone_start_callback,
ZoneEndCallback zone_end_callback,
void *userdata
) {
return new CustomProfilerTrampoline(zone_start_callback, zone_end_callback, userdata);
}
PxErrorCallback *create_error_callback(
ErrorCallback error_callback,
void* userdata
) {
return new ErrorTrampoline(error_callback, userdata);
}
PxAssertHandler *create_assert_handler(
AssertHandler on_assert,
void* userdata
) {
return new AssertTrampoline(on_assert, userdata);
}
void *get_default_simulation_filter_shader()
{
return (void *)PxDefaultSimulationFilterShader;
}
PxSimulationEventCallback *create_simulation_event_callbacks(const SimulationEventCallbackInfo *callbacks)
{
SimulationEventTrampoline *trampoline = new SimulationEventTrampoline(callbacks);
return static_cast<PxSimulationEventCallback *>(trampoline);
}
SimulationEventCallbackInfo *get_simulation_event_info(PxSimulationEventCallback *callback)
{
SimulationEventTrampoline *trampoline = static_cast<SimulationEventTrampoline *>(callback);
return &trampoline->mCallbacks;
}
void destroy_simulation_event_callbacks(PxSimulationEventCallback *callback)
{
SimulationEventTrampoline *trampoline = static_cast<SimulationEventTrampoline *>(callback);
delete trampoline;
}
void enable_custom_filter_shader(PxSceneDesc *desc, SimulationShaderFilter filter, uint32_t call_default_filter_shader_first)
{
static FilterCallbackData filterShaderData = {
filter,
call_default_filter_shader_first != 0
};
desc->filterShader = FilterShaderTrampoline;
desc->filterShaderData = (void *)&filterShaderData;
desc->filterShaderDataSize = sizeof(FilterCallbackData);
}
void PxAssertHandler_opCall_mut(physx_PxErrorCallback_Pod* self__pod, char const* expr, char const* file, int32_t line, bool* ignore ) {
physx::PxAssertHandler* self_ = reinterpret_cast<physx::PxAssertHandler*>(self__pod);
(*self_)(expr, file, line, *ignore);
};
}