#ifndef PHYSICS_API_IMPL_H #define PHYSICS_API_IMPL_H #include "../PhysicsAPI.h" #include "Octree.h" #include namespace Oyster { namespace Physics { class API_Impl : public API { public: struct ContactSensorCallback : public btCollisionWorld::ContactResultCallback { ContactSensorCallback(btRigidBody& contactBody, EventAction_ApplyEffect effect, void* args) : btCollisionWorld::ContactResultCallback(), body(contactBody), func(effect), args(args) {} btRigidBody& body; EventAction_ApplyEffect func; void* args; virtual bool needsCollision(btBroadphaseProxy* proxy) const { if(!btCollisionWorld::ContactResultCallback::needsCollision(proxy)) return false; return body.checkCollideWithOverride(static_cast(proxy->m_clientObject)); } virtual btScalar addSingleResult(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0, int partId0, int index0, const btCollisionObjectWrapper* colObj1, int partId1, int index1) { btVector3 pt; if(colObj0->m_collisionObject == &body) { pt = cp.m_localPointA; this->func((ICustomBody*)(colObj1->getCollisionObject()->getUserPointer()), this->args); } else { assert(colObj1->m_collisionObject == &body && "Body does not match either collision object"); pt = cp.m_localPointB; this->func((ICustomBody*)(colObj0->getCollisionObject()->getUserPointer()), this->args); } return 0; } }; API_Impl(); virtual ~API_Impl(); void Init(); bool IsInLimbo( const ICustomBody* objRef ); void MoveToLimbo( const ICustomBody* objRef ); void ReleaseFromLimbo( const ICustomBody* objRef ); void SetGravityPoint(::Oyster::Math::Float3 gravityPoint); void SetGravity(float gravity); // Bullet physics ICustomBody* AddCollisionSphere(float radius, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass, float restitution, float staticFriction, float dynamicFriction); ICustomBody* AddCollisionBox(::Oyster::Math::Float3 halfSize, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass, float restitution, float staticFriction, float dynamicFriction); ICustomBody* AddCollisionCylinder(::Oyster::Math::Float3 halfSize, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass, float restitution, float staticFriction, float dynamicFriction); void SetTimeStep(float timeStep); void UpdateWorld(); void ApplyEffect(Oyster::Collision3D::ICollideable* collideable, void* args, EventAction_ApplyEffect effect); private: btBroadphaseInterface* broadphase; btDefaultCollisionConfiguration* collisionConfiguration; btCollisionDispatcher* dispatcher; btSequentialImpulseConstraintSolver* solver; btDiscreteDynamicsWorld* dynamicsWorld; std::vector customBodies; float timeStep; ::Oyster::Math::Float3 gravityPoint; float gravity; }; namespace Default { void EventAction_Destruction( ::Utility::DynamicMemory::UniquePointer<::Oyster::Physics::ICustomBody> proto ); ::Oyster::Physics::ICustomBody::SubscriptMessage EventAction_BeforeCollisionResponse( const ::Oyster::Physics::ICustomBody *proto, const ::Oyster::Physics::ICustomBody *deuter ); void EventAction_AfterCollisionResponse( const ::Oyster::Physics::ICustomBody *proto, const ::Oyster::Physics::ICustomBody *deuter, ::Oyster::Math::Float kineticEnergyLoss ); void EventAction_Move( const ::Oyster::Physics::ICustomBody *object ); } } } #endif