diff --git a/sources/reactphysics3d/engine/PhysicsEngine.cpp b/sources/reactphysics3d/engine/PhysicsEngine.cpp index 5465a817..4b9d84c8 100644 --- a/sources/reactphysics3d/engine/PhysicsEngine.cpp +++ b/sources/reactphysics3d/engine/PhysicsEngine.cpp @@ -19,6 +19,7 @@ // Libraries #include "PhysicsEngine.h" +#include "../integration/SemiImplicitEuler.h" // We want to use the ReactPhysics3D namespace using namespace reactphysics3d; @@ -31,15 +32,118 @@ PhysicsEngine::PhysicsEngine(PhysicsWorld* world, const Time& timeStep) throw (s // Throw an exception throw std::invalid_argument("Exception in PhysicsEngine constructor : World pointer cannot be NULL"); } -} - -// Copy-constructor -PhysicsEngine::PhysicsEngine(const PhysicsEngine& engine) - :world(engine.world), timer(engine.timer) { + // Creation of the Semi-Implicit Euler integration algorithm + integrationAlgorithm = new SemiImplicitEuler(); } // Destructor PhysicsEngine::~PhysicsEngine() { - + delete integrationAlgorithm; +} + +void PhysicsEngine::update() { + updateCollision(); +} + +// TODO : Delete this method +// Update the physics simulation +void PhysicsEngine::updateDynamic() { + // Check if the physics simulation is running + if (timer.getIsRunning()) { + // While the time accumulator is not empty + while(timer.getAccumulator() >= timer.getTimeStep().getValue()) { + // For each body in the dynamic world + for(std::vector::const_iterator it = world->getBodyListStartIterator(); it != world->getBodyListEndIterator(); ++it) { + // If the body is a RigidBody and if the rigid body motion is enabled + RigidBody* rigidBody = dynamic_cast(*it); + if (rigidBody && rigidBody->getIsMotionEnabled()) { + // Update the state of the rigid body + updateBodyState(rigidBody, timer.getTimeStep()); + } + } + + // Update the timer + timer.update(); + } + + // For each body in the dynamic world + for(std::vector::const_iterator it = world->getBodyListStartIterator(); it != world->getBodyListEndIterator(); ++it) { + // If the body is a RigidBody and if the rigid body motion is enabled + RigidBody* rigidBody = dynamic_cast(*it); + if (rigidBody && rigidBody->getIsMotionEnabled()) { + // Update the interpolation factor of the rigid body + // This one will be used to compute the interpolated state + rigidBody->setInterpolationFactor(timer.getInterpolationFactor()); + } + } + } +} + +// TODO : Delethe this method +// Update the physics simulation +void PhysicsEngine::updateCollision() { + + // While the time accumulator is not empty + while(timer.getAccumulator() >= timer.getTimeStep().getValue()) { + + // Remove all old collision contact constraints + world->removeAllContactConstraints(); + + // Compute the collision detection + if (collisionDetection.computeCollisionDetection(world)) { + + // TODO : Delete this ---------------------------------------------------------- + for (std::vector::const_iterator it = world->getConstraintListStartIterator(); it != world->getConstraintListEndIterator(); ++it) { + RigidBody* rigidBody1 = dynamic_cast((*it)->getBody1()); + RigidBody* rigidBody2 = dynamic_cast((*it)->getBody2()); + rigidBody1->setIsMotionEnabled(false); + rigidBody2->setIsMotionEnabled(false); + } + // ----------------------------------------------------------------------------- + } + + // For each body in the dynamic world + for(std::vector::const_iterator it = world->getBodyListStartIterator(); it != world->getBodyListEndIterator(); ++it) { + // If the body is a RigidBody and if the rigid body motion is enabled + RigidBody* rigidBody = dynamic_cast(*it); + if (rigidBody && rigidBody->getIsMotionEnabled()) { + // Update the state of the rigid body with an entire time step + updateBodyState(rigidBody, timer.getTimeStep()); + } + } + + // Update the timer + timer.update(); + } + + // For each body in the the dynamic world + for(std::vector::const_iterator it = world->getBodyListStartIterator(); it != world->getBodyListEndIterator(); ++it) { + // If the body is a RigidBody and if the rigid body motion is enabled + RigidBody* rigidBody = dynamic_cast(*it); + if (rigidBody && rigidBody->getIsMotionEnabled()) { + // Update the interpolation factor of the rigid body + // This one will be used to compute the interpolated state + rigidBody->setInterpolationFactor(timer.getInterpolationFactor()); + } + } +} + +// Update the state of a rigid body +void PhysicsEngine::updateBodyState(RigidBody* const rigidBody, const Time& timeStep) { + + // If the gravity force is on + if(world->getIsGravityOn()) { + // Apply the current gravity force to the body + rigidBody->getCurrentBodyState().setForce(world->getGravity()); + } + + // The current body state of the body becomes the previous body state + rigidBody->updatePreviousBodyState(); + + // Integrate the current body state at time t to get the next state at time t + dt + integrationAlgorithm->integrate(rigidBody->getCurrentBodyState(), timer.getTime(), timeStep); + + // If the body state has changed, we have to update some informations in the rigid body + rigidBody->update(); } diff --git a/sources/reactphysics3d/engine/PhysicsEngine.h b/sources/reactphysics3d/engine/PhysicsEngine.h index 550b969f..59ca4836 100644 --- a/sources/reactphysics3d/engine/PhysicsEngine.h +++ b/sources/reactphysics3d/engine/PhysicsEngine.h @@ -22,6 +22,9 @@ // Libraries #include "PhysicsWorld.h" +#include "../integration/IntegrationAlgorithm.h" +#include "../collision/CollisionDetection.h" +#include "../body/RigidBody.h" #include "Timer.h" // Namespace ReactPhysics3D @@ -29,23 +32,29 @@ namespace reactphysics3d { /* ------------------------------------------------------------------- Class PhysicsEngine : - This is an abstract class that represents the physics engine + This class represents the physics engine of the library. ------------------------------------------------------------------- */ class PhysicsEngine { protected : - PhysicsWorld* world; // Pointer to the physics world of the physics engine - Timer timer; // Timer of the physics engine + PhysicsWorld* world; // Pointer to the physics world of the physics engine + Timer timer; // Timer of the physics engine + IntegrationAlgorithm* integrationAlgorithm; // Integration algorithm used to solve differential equations of movement + CollisionDetection collisionDetection; // Collision detection + + void updateBodyState(RigidBody* const rigidBody, const Time& timeStep); // Update the state of a rigid body public : PhysicsEngine(PhysicsWorld* world, const Time& timeStep) throw (std::invalid_argument); // Constructor PhysicsEngine(const PhysicsEngine& engine); // Copy-constructor - virtual ~PhysicsEngine(); // Destructor + ~PhysicsEngine(); // Destructor - virtual void start(); // Start the physics simulation - virtual void stop(); // Stop the physics simulation - virtual void update()=0; // Update the physics simulation + void start(); // Start the physics simulation + void stop(); // Stop the physics simulation + void update(); // Update the physics simulation + void updateDynamic(); // TODO : Delete this method + void updateCollision(); // TODO : Delete this collision void initializeDisplayTime(const Time& displayTime); // Initialize the display time void updateDisplayTime(const Time& newDisplayTime); // Update the display time };