diff --git a/include/Nazara/Physics3D/PhysWorld3D.hpp b/include/Nazara/Physics3D/PhysWorld3D.hpp index 427aaeb69..411d3d4e7 100644 --- a/include/Nazara/Physics3D/PhysWorld3D.hpp +++ b/include/Nazara/Physics3D/PhysWorld3D.hpp @@ -13,7 +13,9 @@ #include #include +class NewtonBody; class NewtonJoint; +class NewtonMaterial; class NewtonWorld; namespace Nz @@ -23,6 +25,7 @@ namespace Nz class NAZARA_PHYSICS3D_API PhysWorld3D { public: + using AABBOverlapCallback = std::function; using CollisionCallback = std::function; PhysWorld3D(); @@ -41,7 +44,12 @@ namespace Nz void SetSolverModel(unsigned int model); void SetStepSize(float stepSize); - void SetMaterialCollisionCallback(int firstMaterial, int secondMaterial, CollisionCallback callback); + void SetMaterialCollisionCallback(int firstMaterial, int secondMaterial, AABBOverlapCallback aabbOverlapCallback, CollisionCallback collisionCallback); + void SetMaterialDefaultCollidable(int firstMaterial, int secondMaterial, bool collidable); + void SetMaterialDefaultElasticity(int firstMaterial, int secondMaterial, float elasticCoef); + void SetMaterialDefaultFriction(int firstMaterial, int secondMaterial, float staticFriction, float kineticFriction); + void SetMaterialDefaultSoftness(int firstMaterial, int secondMaterial, float softness); + void SetMaterialSurfaceThickness(int firstMaterial, int secondMaterial, float thickness); void Step(float timestep); @@ -51,9 +59,11 @@ namespace Nz private: struct Callback { + AABBOverlapCallback aabbOverlapCallback; CollisionCallback collisionCallback; }; + static int OnAABBOverlap(const NewtonMaterial* const material, const NewtonBody* const body0, const NewtonBody* const body1, int threadIndex); static void ProcessContact(const NewtonJoint* const contact, float timestep, int threadIndex); std::unordered_map> m_callbacks; diff --git a/src/Nazara/Physics3D/PhysWorld3D.cpp b/src/Nazara/Physics3D/PhysWorld3D.cpp index 0b2634be1..4613b7f32 100644 --- a/src/Nazara/Physics3D/PhysWorld3D.cpp +++ b/src/Nazara/Physics3D/PhysWorld3D.cpp @@ -74,14 +74,15 @@ namespace Nz m_stepSize = stepSize; } - void PhysWorld3D::SetMaterialCollisionCallback(int firstMaterial, int secondMaterial, CollisionCallback callback) + void PhysWorld3D::SetMaterialCollisionCallback(int firstMaterial, int secondMaterial, AABBOverlapCallback aabbOverlapCallback, CollisionCallback collisionCallback) { static_assert(sizeof(Nz::UInt64) >= 2 * sizeof(int), "Oops"); auto callbackPtr = std::make_unique(); - callbackPtr->collisionCallback = std::move(callback); + callbackPtr->aabbOverlapCallback = std::move(aabbOverlapCallback); + callbackPtr->collisionCallback = std::move(collisionCallback); - NewtonMaterialSetCollisionCallback(m_world, firstMaterial, secondMaterial, callbackPtr.get(), nullptr, ProcessContact); + NewtonMaterialSetCollisionCallback(m_world, firstMaterial, secondMaterial, callbackPtr.get(), (callbackPtr->aabbOverlapCallback) ? OnAABBOverlap : nullptr, (callbackPtr->collisionCallback) ? ProcessContact : nullptr); Nz::UInt64 firstMaterialId(firstMaterial); Nz::UInt64 secondMaterialId(secondMaterial); @@ -90,6 +91,31 @@ namespace Nz m_callbacks[callbackIndex] = std::move(callbackPtr); } + void PhysWorld3D::SetMaterialDefaultCollidable(int firstMaterial, int secondMaterial, bool collidable) + { + NewtonMaterialSetDefaultCollidable(m_world, firstMaterial, secondMaterial, collidable); + } + + void PhysWorld3D::SetMaterialDefaultElasticity(int firstMaterial, int secondMaterial, float elasticCoef) + { + NewtonMaterialSetDefaultElasticity(m_world, firstMaterial, secondMaterial, elasticCoef); + } + + void PhysWorld3D::SetMaterialDefaultFriction(int firstMaterial, int secondMaterial, float staticFriction, float kineticFriction) + { + NewtonMaterialSetDefaultFriction(m_world, firstMaterial, secondMaterial, staticFriction, kineticFriction); + } + + void PhysWorld3D::SetMaterialDefaultSoftness(int firstMaterial, int secondMaterial, float softness) + { + NewtonMaterialSetDefaultSoftness(m_world, firstMaterial, secondMaterial, softness); + } + + void PhysWorld3D::SetMaterialSurfaceThickness(int firstMaterial, int secondMaterial, float thickness) + { + NewtonMaterialSetSurfaceThickness(m_world, firstMaterial, secondMaterial, thickness); + } + void PhysWorld3D::Step(float timestep) { m_timestepAccumulator += timestep; @@ -101,6 +127,19 @@ namespace Nz } } + int PhysWorld3D::OnAABBOverlap(const NewtonMaterial* const material, const NewtonBody* const body0, const NewtonBody* const body1, int threadIndex) + { + Nz::RigidBody3D* bodyA = static_cast(NewtonBodyGetUserData(body0)); + Nz::RigidBody3D* bodyB = static_cast(NewtonBodyGetUserData(body1)); + assert(bodyA && bodyB); + + Callback* callbackData = static_cast(NewtonMaterialGetMaterialPairUserData(material)); + assert(callbackData); + assert(callbackData->aabbOverlapCallback); + + return callbackData->aabbOverlapCallback(*bodyA, *bodyB); + } + void PhysWorld3D::ProcessContact(const NewtonJoint* const contactJoint, float timestep, int threadIndex) { Nz::RigidBody3D* bodyA = static_cast(NewtonBodyGetUserData(NewtonJointGetBody0(contactJoint))); @@ -123,6 +162,7 @@ namespace Nz NewtonMaterial* material = NewtonContactGetMaterial(contact); Callback* callbackData = static_cast(NewtonMaterialGetMaterialPairUserData(material)); assert(callbackData); + assert(callbackData->collisionCallback); if (!callbackData->collisionCallback(*bodyA, *bodyB)) NewtonContactJointRemoveContact(contactJoint, contact);