/******************************************************************************** * ReactPhysics3D physics library, http://www.reactphysics3d.com * * Copyright (c) 2010-2018 Daniel Chappuis * ********************************************************************************* * * * This software is provided 'as-is', without any express or implied warranty. * * In no event will the authors be held liable for any damages arising from the * * use of this software. * * * * Permission is granted to anyone to use this software for any purpose, * * including commercial applications, and to alter it and redistribute it * * freely, subject to the following restrictions: * * * * 1. The origin of this software must not be misrepresented; you must not claim * * that you wrote the original software. If you use this software in a * * product, an acknowledgment in the product documentation would be * * appreciated but is not required. * * * * 2. Altered source versions must be plainly marked as such, and must not be * * misrepresented as being the original software. * * * * 3. This notice may not be removed or altered from any source distribution. * * * ********************************************************************************/ #ifndef REACTPHYSICS3D_DYNAMICS_WORLD_H #define REACTPHYSICS3D_DYNAMICS_WORLD_H // Libraries #include "CollisionWorld.h" #include "systems/ConstraintSolverSystem.h" #include "configuration.h" #include "utils/Logger.h" #include "systems/ContactSolverSystem.h" #include "systems/DynamicsSystem.h" #include "engine/Islands.h" /// Namespace ReactPhysics3D namespace reactphysics3d { // Declarations class CollisionDetectionSystem; class Island; class RigidBody; // Class DynamicsWorld /** * This class represents a dynamics world. This class inherits from * the CollisionWorld class. In a dynamics world, bodies can collide * and their movements are simulated using the laws of physics. */ class DynamicsWorld : public CollisionWorld { protected : // -------------------- Attributes -------------------- // /// All the islands of bodies of the current frame Islands mIslands; /// Contact solver system ContactSolverSystem mContactSolverSystem; /// Constraint solver system ConstraintSolverSystem mConstraintSolverSystem; /// Dynamics system DynamicsSystem mDynamicsSystem; /// Number of iterations for the velocity solver of the Sequential Impulses technique uint mNbVelocitySolverIterations; /// Number of iterations for the position solver of the Sequential Impulses technique uint mNbPositionSolverIterations; /// True if the spleeping technique for inactive bodies is enabled bool mIsSleepingEnabled; /// All the rigid bodies of the physics world List mRigidBodies; /// All the joints of the world List mJoints; /// Gravity vector of the world Vector3 mGravity; /// True if the gravity force is on bool mIsGravityEnabled; /// Sleep linear velocity threshold decimal mSleepLinearVelocity; /// Sleep angular velocity threshold decimal mSleepAngularVelocity; /// Time (in seconds) before a body is put to sleep if its velocity /// becomes smaller than the sleep velocity. decimal mTimeBeforeSleep; /// Current joint id uint mCurrentJointId; // -------------------- Methods -------------------- // /// Solve the contacts and constraints void solveContactsAndConstraints(decimal timeStep); /// Solve the position error correction of the constraints void solvePositionCorrection(); /// Compute the islands of awake bodies. void computeIslands(); /// Compute the islands using potential contacts and joints and create the actual contacts. void createIslands(); /// Put bodies to sleep if needed. void updateSleepingBodies(decimal timeStep); /// Add the joint to the list of joints of the two bodies involved in the joint void addJointToBody(Joint* joint); public : // -------------------- Methods -------------------- // /// Constructor DynamicsWorld(const Vector3& mGravity, const WorldSettings& worldSettings = WorldSettings(), Logger* logger = nullptr, Profiler* profiler = nullptr); /// Destructor virtual ~DynamicsWorld() override; /// Deleted copy-constructor DynamicsWorld(const DynamicsWorld& world) = delete; /// Deleted assignment operator DynamicsWorld& operator=(const DynamicsWorld& world) = delete; /// Update the physics simulation void update(decimal timeStep); /// Get the number of iterations for the velocity constraint solver uint getNbIterationsVelocitySolver() const; /// Set the number of iterations for the velocity constraint solver void setNbIterationsVelocitySolver(uint nbIterations); /// Get the number of iterations for the position constraint solver uint getNbIterationsPositionSolver() const; /// Set the number of iterations for the position constraint solver void setNbIterationsPositionSolver(uint nbIterations); /// Set the position correction technique used for contacts void setContactsPositionCorrectionTechnique(ContactsPositionCorrectionTechnique technique); /// Set the position correction technique used for joints void setJointsPositionCorrectionTechnique(JointsPositionCorrectionTechnique technique); /// Create a rigid body into the physics world. RigidBody* createRigidBody(const Transform& transform); /// Destroy a rigid body and all the joints which it belongs void destroyRigidBody(RigidBody* rigidBody); /// Create a joint between two bodies in the world and return a pointer to the new joint Joint* createJoint(const JointInfo& jointInfo); /// Destroy a joint void destroyJoint(Joint* joint); /// Return the gravity vector of the world Vector3 getGravity() const; /// Set the gravity vector of the world void setGravity(Vector3& gravity); /// Return if the gravity is on bool isGravityEnabled() const; /// Enable/Disable the gravity void setIsGratityEnabled(bool isGravityEnabled); /// Return the number of rigid bodies in the world uint getNbRigidBodies() const; /// Return the number of joints in the world uint getNbJoints() const; /// Return true if the sleeping technique is enabled bool isSleepingEnabled() const; /// Enable/Disable the sleeping technique void enableSleeping(bool isSleepingEnabled); /// Return the current sleep linear velocity decimal getSleepLinearVelocity() const; /// Set the sleep linear velocity. void setSleepLinearVelocity(decimal sleepLinearVelocity); /// Return the current sleep angular velocity decimal getSleepAngularVelocity() const; /// Set the sleep angular velocity. void setSleepAngularVelocity(decimal sleepAngularVelocity); /// Return the time a body is required to stay still before sleeping decimal getTimeBeforeSleep() const; /// Set the time a body is required to stay still before sleeping void setTimeBeforeSleep(decimal timeBeforeSleep); /// Set an event listener object to receive events callbacks. void setEventListener(EventListener* eventListener); // -------------------- Friendship -------------------- // friend class RigidBody; friend class Joint; friend class BallAndSocketJoint; friend class FixedJoint; friend class HingeJoint; friend class SliderJoint; }; // Get the number of iterations for the velocity constraint solver /** * @return The number of iterations of the velocity constraint solver */ inline uint DynamicsWorld::getNbIterationsVelocitySolver() const { return mNbVelocitySolverIterations; } // Set the number of iterations for the velocity constraint solver /** * @param nbIterations Number of iterations for the velocity solver */ inline void DynamicsWorld::setNbIterationsVelocitySolver(uint nbIterations) { mNbVelocitySolverIterations = nbIterations; RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::World, "Dynamics World: Set nb iterations velocity solver to " + std::to_string(nbIterations)); } // Get the number of iterations for the position constraint solver /** * @return The number of iterations of the position constraint solver */ inline uint DynamicsWorld::getNbIterationsPositionSolver() const { return mNbPositionSolverIterations; } // Set the number of iterations for the position constraint solver /** * @param nbIterations Number of iterations for the position solver */ inline void DynamicsWorld::setNbIterationsPositionSolver(uint nbIterations) { mNbPositionSolverIterations = nbIterations; RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::World, "Dynamics World: Set nb iterations position solver to " + std::to_string(nbIterations)); } // Set the position correction technique used for contacts /** * @param technique Technique used for the position correction (Baumgarte or Split Impulses) */ inline void DynamicsWorld::setContactsPositionCorrectionTechnique( ContactsPositionCorrectionTechnique technique) { if (technique == ContactsPositionCorrectionTechnique::BAUMGARTE_CONTACTS) { mContactSolverSystem.setIsSplitImpulseActive(false); } else { mContactSolverSystem.setIsSplitImpulseActive(true); } } // Set the position correction technique used for joints /** * @param technique Technique used for the joins position correction (Baumgarte or Non Linear Gauss Seidel) */ inline void DynamicsWorld::setJointsPositionCorrectionTechnique( JointsPositionCorrectionTechnique technique) { if (technique == JointsPositionCorrectionTechnique::BAUMGARTE_JOINTS) { mConstraintSolverSystem.setIsNonLinearGaussSeidelPositionCorrectionActive(false); } else { mConstraintSolverSystem.setIsNonLinearGaussSeidelPositionCorrectionActive(true); } } // Return the gravity vector of the world /** * @return The current gravity vector (in meter per seconds squared) */ inline Vector3 DynamicsWorld::getGravity() const { return mGravity; } // Set the gravity vector of the world /** * @param gravity The gravity vector (in meter per seconds squared) */ inline void DynamicsWorld::setGravity(Vector3& gravity) { mGravity = gravity; RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::World, "Dynamics World: Set gravity vector to " + gravity.to_string()); } // Return if the gravity is enaled /** * @return True if the gravity is enabled in the world */ inline bool DynamicsWorld::isGravityEnabled() const { return mIsGravityEnabled; } // Enable/Disable the gravity /** * @param isGravityEnabled True if you want to enable the gravity in the world * and false otherwise */ inline void DynamicsWorld::setIsGratityEnabled(bool isGravityEnabled) { mIsGravityEnabled = isGravityEnabled; RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::World, "Dynamics World: isGravityEnabled= " + (isGravityEnabled ? std::string("true") : std::string("false"))); } // Return the number of rigid bodies in the world /** * @return Number of rigid bodies in the world */ inline uint DynamicsWorld::getNbRigidBodies() const { return mRigidBodies.size(); } /// Return the number of joints in the world /** * @return Number of joints in the world */ inline uint DynamicsWorld::getNbJoints() const { return mJoints.size(); } // Return true if the sleeping technique is enabled /** * @return True if the sleeping technique is enabled and false otherwise */ inline bool DynamicsWorld::isSleepingEnabled() const { return mIsSleepingEnabled; } // Return the current sleep linear velocity /** * @return The sleep linear velocity (in meters per second) */ inline decimal DynamicsWorld::getSleepLinearVelocity() const { return mSleepLinearVelocity; } // Set the sleep linear velocity. /// When the velocity of a body becomes smaller than the sleep linear/angular /// velocity for a given amount of time, the body starts sleeping and does not need /// to be simulated anymore. /** * @param sleepLinearVelocity The sleep linear velocity (in meters per second) */ inline void DynamicsWorld::setSleepLinearVelocity(decimal sleepLinearVelocity) { assert(sleepLinearVelocity >= decimal(0.0)); mSleepLinearVelocity = sleepLinearVelocity; RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::World, "Dynamics World: sleepLinearVelocity= " + std::to_string(sleepLinearVelocity)); } // Return the current sleep angular velocity /** * @return The sleep angular velocity (in radian per second) */ inline decimal DynamicsWorld::getSleepAngularVelocity() const { return mSleepAngularVelocity; } // Set the sleep angular velocity. /// When the velocity of a body becomes smaller than the sleep linear/angular /// velocity for a given amount of time, the body starts sleeping and does not need /// to be simulated anymore. /** * @param sleepAngularVelocity The sleep angular velocity (in radian per second) */ inline void DynamicsWorld::setSleepAngularVelocity(decimal sleepAngularVelocity) { assert(sleepAngularVelocity >= decimal(0.0)); mSleepAngularVelocity = sleepAngularVelocity; RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::World, "Dynamics World: sleepAngularVelocity= " + std::to_string(sleepAngularVelocity)); } // Return the time a body is required to stay still before sleeping /** * @return Time a body is required to stay still before sleeping (in seconds) */ inline decimal DynamicsWorld::getTimeBeforeSleep() const { return mTimeBeforeSleep; } // Set the time a body is required to stay still before sleeping /** * @param timeBeforeSleep Time a body is required to stay still before sleeping (in seconds) */ inline void DynamicsWorld::setTimeBeforeSleep(decimal timeBeforeSleep) { assert(timeBeforeSleep >= decimal(0.0)); mTimeBeforeSleep = timeBeforeSleep; RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::World, "Dynamics World: timeBeforeSleep= " + std::to_string(timeBeforeSleep)); } // Set an event listener object to receive events callbacks. /// If you use "nullptr" as an argument, the events callbacks will be disabled. /** * @param eventListener Pointer to the event listener object that will receive * event callbacks during the simulation */ inline void DynamicsWorld::setEventListener(EventListener* eventListener) { mEventListener = eventListener; } } #endif