| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347 |
- //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
- //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
- #pragma once
- #include <cfloat>
- #include "BsCorePrerequisites.h"
- #include "BsPhysicsCommon.h"
- #include "BsFJoint.h"
- namespace BansheeEngine
- {
- /** @addtogroup Physics
- * @{
- */
- struct JOINT_DESC;
- /**
- * Base class for all Joint types. Joints constrain how two rigidbodies move relative to one another (for example a door
- * hinge). One of the bodies in the joint must always be movable (non-kinematic).
- */
- class BS_CORE_EXPORT Joint
- {
- public:
- Joint() { }
- virtual ~Joint() { }
- /** @copydoc FJoint::getBody */
- inline Rigidbody* getBody(JointBody body) const;
- /** @copydoc FJoint::setBody */
- inline void setBody(JointBody body, Rigidbody* value);
- /** @copydoc FJoint::getPosition */
- inline Vector3 getPosition(JointBody body) const;
- /** @copydoc FJoint::getRotation */
- inline Quaternion getRotation(JointBody body) const;
- /** @copydoc FJoint::setTransform */
- inline void setTransform(JointBody body, const Vector3& position, const Quaternion& rotation);
- /** @copydoc FJoint::getBreakForce */
- inline float getBreakForce() const;
- /** @copydoc FJoint::setBreakForce */
- inline void setBreakForce(float force);
- /** @copydoc FJoint::getBreakTorque */
- inline float getBreakTorque() const;
- /** @copydoc FJoint::setBreakTorque */
- inline void setBreakTorque(float torque);
- /** @copydoc FJoint::getEnableCollision */
- inline bool getEnableCollision() const;
- /** @copydoc FJoint::setEnableCollision */
- inline void setEnableCollision(bool value);
- /** Triggered when the joint's break force or torque is exceeded. */
- Event<void()> onJointBreak;
- /** @name Internal
- * @{
- */
- /**
- * Sets the object that owns this physics object, if any. Used for high level systems so they can easily map their
- * high level physics objects from the low level ones returned by various queries and events.
- */
- void _setOwner(PhysicsOwnerType type, void* owner) { mOwner.type = type; mOwner.ownerData = owner; }
- /**
- * Gets the object that owns this physics object, if any. Used for high level systems so they can easily map their
- * high level physics objects from the low level ones returned by various queries and events.
- */
- void* _getOwner(PhysicsOwnerType type) const { return mOwner.type == type ? mOwner.ownerData : nullptr; }
- /** @} */
- protected:
- PhysicsObjectOwner mOwner;
- FJoint* mInternal = nullptr;
- };
- /** Structure used for initializing a new Joint. */
- struct JOINT_DESC
- {
- struct BodyInfo
- {
- Rigidbody* body = nullptr;
- Vector3 position = Vector3::ZERO;
- Quaternion rotation = Quaternion::IDENTITY;
- };
- BodyInfo bodies[2];
- float breakForce = FLT_MAX;
- float breakTorque = FLT_MAX;
- bool enableCollision = false;
- };
- /**
- * Controls spring parameters for a physics joint limits. If a limit is soft (body bounces back due to restition when
- * the limit is reached) the spring will pull the body back towards the limit using the specified parameters.
- */
- struct Spring
- {
- /** Constructs a spring with no force. */
- Spring() { }
- /**
- * Constructs a spring.
- *
- * @param stiffness Spring strength. Force proportional to the position error.
- * @param damping Damping strength. Force propertional to the velocity error.
- */
- Spring(float stiffness, float damping)
- :stiffness(stiffness), damping(damping)
- { }
- bool operator==(const Spring& other) const
- {
- return stiffness == other.stiffness && damping == other.damping;
- }
- /** Spring strength. Force proportional to the position error. */
- float stiffness = 0.0f;
- /** Damping strength. Force propertional to the velocity error. */
- float damping = 0.0f;
- };
- /** Contains common values used by all Joint limit types. */
- struct LimitCommon
- {
- LimitCommon(float contactDist = -1.0f)
- :contactDist(contactDist)
- { }
- LimitCommon(const Spring& spring, float restitution = 0.0f)
- : restitution(restitution), spring(spring)
- { }
- /**
- * Distance from the limit at which it becomes active. Allows the solver to activate earlier than the limit is
- * reached to avoid breaking the limit.
- */
- float contactDist = -1.0f;
- /**
- * Controls how do objects react when the limit is reached, values closer to zero specify non-ellastic collision,
- * while those closer to one specify more ellastic (i.e bouncy) collision. Must be in [0, 1] range.
- */
- float restitution = 0.0f;
- /** Spring that controls how are the bodies pulled back towards the limit when they breach it. */
- Spring spring;
- };
- /** Represents a joint limit between two distance values. Lower value must be less than the upper value. */
- struct LimitLinearRange : LimitCommon
- {
- /** Constructs an empty limit. */
- LimitLinearRange()
- { }
- /**
- * Constructs a hard limit. Once the limit is reached the movement of the attached bodies will come to a stop.
- *
- * @param lower Lower distance of the limit. Must be less than @p upper.
- * @param upper Upper distance of the limit. Must be more than @p lower.
- * @param contactDist Distance from the limit at which it becomes active. Allows the solver to activate earlier
- * than the limit is reached to avoid breaking the limit. Specify -1 for the default.
- */
- LimitLinearRange(float lower, float upper, float contactDist = -1.0f)
- :LimitCommon(contactDist), lower(lower), upper(upper)
- { }
- /**
- * Constructs a soft limit. Once the limit is reached the bodies will bounce back according to the resitution
- * parameter and will be pulled back towards the limit by the provided spring.
- *
- * @param lower Lower distance of the limit. Must be less than @p upper.
- * @param upper Upper distance of the limit. Must be more than @p lower.
- * @param spring Spring that controls how are the bodies pulled back towards the limit when they breach it.
- * @param restitution Controls how do objects react when the limit is reached, values closer to zero specify
- * non-ellastic collision, while those closer to one specify more ellastic (i.e bouncy)
- * collision. Must be in [0, 1] range.
- */
- LimitLinearRange(float lower, float upper, const Spring& spring, float restitution = 0.0f)
- :LimitCommon(spring, restitution), lower(lower), upper(upper)
- { }
- bool operator==(const LimitLinearRange& other) const
- {
- return lower == other.lower && upper == other.upper && contactDist == other.contactDist &&
- restitution == other.restitution && spring == other.spring;
- }
- /** Lower distance of the limit. Must be less than #upper. */
- float lower = 0.0f;
- /** Upper distance of the limit. Must be more than #lower. */
- float upper = 0.0f;
- };
- /** Represents a joint limit between zero a single distance value. */
- struct LimitLinear : LimitCommon
- {
- /** Constructs an empty limit. */
- LimitLinear()
- { }
- /**
- * Constructs a hard limit. Once the limit is reached the movement of the attached bodies will come to a stop.
- *
- * @param extent Distance at which the limit becomes active.
- * @param contactDist Distance from the limit at which it becomes active. Allows the solver to activate earlier
- * than the limit is reached to avoid breaking the limit. Specify -1 for the default.
- */
- LimitLinear(float extent, float contactDist = -1.0f)
- :LimitCommon(contactDist), extent(extent)
- { }
- /**
- * Constructs a soft limit. Once the limit is reached the bodies will bounce back according to the resitution
- * parameter and will be pulled back towards the limit by the provided spring.
- *
- * @param extent Distance at which the limit becomes active.
- * @param spring Spring that controls how are the bodies pulled back towards the limit when they breach it.
- * @param restitution Controls how do objects react when the limit is reached, values closer to zero specify
- * non-ellastic collision, while those closer to one specify more ellastic (i.e bouncy)
- * collision. Must be in [0, 1] range.
- */
- LimitLinear(float extent, const Spring& spring, float restitution = 0.0f)
- :LimitCommon(spring, restitution), extent(extent)
- { }
- bool operator==(const LimitLinear& other) const
- {
- return extent == other.extent && contactDist == other.contactDist && restitution == other.restitution &&
- spring == other.spring;
- }
- /** Distance at which the limit becomes active. */
- float extent = 0.0f;
- };
- /** Represents a joint limit between two angles. */
- struct LimitAngularRange : LimitCommon
- {
- /** Constructs an empty limit. */
- LimitAngularRange()
- { }
- /**
- * Constructs a hard limit. Once the limit is reached the movement of the attached bodies will come to a stop.
- *
- * @param lower Lower angle of the limit. Must be less than @p upper.
- * @param upper Upper angle of the limit. Must be more than @p lower.
- * @param contactDist Distance from the limit at which it becomes active. Allows the solver to activate earlier
- * than the limit is reached to avoid breaking the limit. Specify -1 for the default.
- */
- LimitAngularRange(Radian lower, Radian upper, float contactDist = -1.0f)
- :LimitCommon(contactDist), lower(lower), upper(upper)
- { }
- /**
- * Constructs a soft limit. Once the limit is reached the bodies will bounce back according to the resitution
- * parameter and will be pulled back towards the limit by the provided spring.
- *
- * @param lower Lower angle of the limit. Must be less than @p upper.
- * @param upper Upper angle of the limit. Must be more than @p lower.
- * @param spring Spring that controls how are the bodies pulled back towards the limit when they breach it.
- * @param restitution Controls how do objects react when the limit is reached, values closer to zero specify
- * non-ellastic collision, while those closer to one specify more ellastic (i.e bouncy)
- * collision. Must be in [0, 1] range.
- */
- LimitAngularRange(Radian lower, Radian upper, const Spring& spring, float restitution = 0.0f)
- :LimitCommon(spring, restitution), lower(lower), upper(upper)
- { }
- bool operator==(const LimitAngularRange& other) const
- {
- return lower == other.lower && upper == other.upper && contactDist == other.contactDist &&
- restitution == other.restitution && spring == other.spring;
- }
- /** Lower angle of the limit. Must be less than #upper. */
- Radian lower = Radian(0.0f);
- /** Upper angle of the limit. Must be less than #lower. */
- Radian upper = Radian(0.0f);
- };
- /** Represents a joint limit that contraints movement to within an elliptical cone. */
- struct LimitConeRange : LimitCommon
- {
- /** Constructs a limit with a 45 degree cone. */
- LimitConeRange()
- { }
- /**
- * Constructs a hard limit. Once the limit is reached the movement of the attached bodies will come to a stop.
- *
- * @param yLimitAngle Y angle of the cone. Movement is constrainted between 0 and this angle on the Y axis.
- * @param zLimitAngle Z angle of the cone. Movement is constrainted between 0 and this angle on the Z axis.
- * @param contactDist Distance from the limit at which it becomes active. Allows the solver to activate
- * earlier than the limit is reached to avoid breaking the limit. Specify -1 for the
- * default.
- */
- LimitConeRange(Radian yLimitAngle, Radian zLimitAngle, float contactDist = -1.0f)
- :LimitCommon(contactDist), yLimitAngle(yLimitAngle), zLimitAngle(zLimitAngle)
- { }
- /**
- * Constructs a soft limit. Once the limit is reached the bodies will bounce back according to the resitution
- * parameter and will be pulled back towards the limit by the provided spring.
- *
- * @param yLimitAngle Y angle of the cone. Movement is constrainted between 0 and this angle on the Y axis.
- * @param zLimitAngle Z angle of the cone. Movement is constrainted between 0 and this angle on the Z axis.
- * @param spring Spring that controls how are the bodies pulled back towards the limit when they breach it.
- * @param restitution Controls how do objects react when the limit is reached, values closer to zero specify
- * non-ellastic collision, while those closer to one specify more ellastic (i.e bouncy)
- * collision. Must be in [0, 1] range.
- */
- LimitConeRange(Radian yLimitAngle, Radian zLimitAngle, const Spring& spring, float restitution = 0.0f)
- :LimitCommon(spring, restitution), yLimitAngle(yLimitAngle), zLimitAngle(zLimitAngle)
- { }
- bool operator==(const LimitConeRange& other) const
- {
- return yLimitAngle == other.yLimitAngle && zLimitAngle == other.zLimitAngle &&
- contactDist == other.contactDist && restitution == other.restitution && spring == other.spring;
- }
- /** Y angle of the cone. Movement is constrainted between 0 and this angle on the Y axis. */
- Radian yLimitAngle = Radian(Math::PI * 0.5f);
- /** Z angle of the cone. Movement is constrainted between 0 and this angle on the Z axis. */
- Radian zLimitAngle = Radian(Math::PI * 0.5f);
- };
- /** @} */
- }
|