| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336 |
- //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
- //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
- #pragma once
- #include "BsCorePrerequisites.h"
- #include "BsPhysicsCommon.h"
- namespace bs
- {
- /** @addtogroup Physics
- * @{
- */
- /** Type of force or torque that can be applied to a rigidbody. */
- enum class ForceMode
- {
- Force, /**< Value applied is a force. */
- Impulse, /**< Value applied is an impulse (a direct change in its linear or angular momentum). */
- Velocity, /**< Value applied is velocity. */
- Acceleration /**< Value applied is accelearation. */
- };
- /** Type of force that can be applied to a rigidbody at an arbitrary point. */
- enum class PointForceMode
- {
- Force, /**< Value applied is a force. */
- Impulse, /**< Value applied is an impulse (a direct change in its linear or angular momentum). */
- };
- /**
- * Rigidbody is a dynamic physics object that can be moved using forces (or directly). It will interact with other
- * static and dynamic physics objects in the scene accordingly (it will push other non-kinematic rigidbodies,
- * and collide with static objects).
- *
- * The shape and mass of a rigidbody is governed by its colliders. You must attach at least one collider for the
- * rigidbody to be valid.
- */
- class BS_CORE_EXPORT Rigidbody
- {
- public:
- /** Flags that control options of a Rigidbody object. */
- enum class Flag
- {
- /** No options. */
- None = 0x00,
- /** Automatically calculate center of mass transform and inertia tensors from child shapes (colliders). */
- AutoTensors = 0x01,
- /** Calculate mass distribution from child shapes (colliders). Only relevant when auto-tensors is on. */
- AutoMass = 0x02,
- /**
- * Enables continous collision detection. This can prevent fast moving bodies from tunneling through each other.
- * This must also be enabled globally in Physics otherwise the flag will be ignored.
- */
- CCD = 0x04
- };
- /**
- * Constructs a new rigidbody.
- *
- * @param[in] linkedSO Scene object that owns this rigidbody. All physics updates applied to this object
- * will be transfered to this scene object (the movement/rotation resulting from
- * those updates).
- */
- Rigidbody(const HSceneObject& linkedSO);
- virtual ~Rigidbody();
- /**
- * Moves the rigidbody to a specific position. This method will ensure physically correct movement, meaning the body
- * will collide with other objects along the way.
- */
- virtual void move(const Vector3& position) = 0;
- /**
- * Rotates the rigidbody. This method will ensure physically correct rotation, meaning the body will collide with
- * other objects along the way.
- */
- virtual void rotate(const Quaternion& rotation) = 0;
- /** Returns the current position of the rigidbody. */
- virtual Vector3 getPosition() const = 0;
- /** Returns the current rotation of the rigidbody. */
- virtual Quaternion getRotation() const = 0;
- /**
- * Moves and rotates the rigidbody to a specific position. Unlike move() and rotate() this will not transform the
- * body in a physically correct manner, but will instead "teleport" it immediately to the specified position and
- * rotation.
- */
- virtual void setTransform(const Vector3& pos, const Quaternion& rot) = 0;
- /**
- * Sets the mass of the object and all of its collider shapes. Only relevant if Flag::AutoMass or Flag::AutoTensors
- * is turned off. Value of zero means the object is immovable (but can be rotated).
- */
- virtual void setMass(float mass) = 0;
- /**
- * Returns the mass of the object. This may be mass manually set by setMass(), or the mass of all child colliders,
- * depending if the mass is calculated automatically or not.
- */
- virtual float getMass() const = 0;
- /**
- * Sets if the body is kinematic. Kinematic body will not move in response to external forces (for example gravity,
- * or another object pushing it), essentially behaving like collider. Unlike a collider though, you can still move
- * the object and have other dynamic objects respond correctly (meaning it will push other objects).
- */
- virtual void setIsKinematic(bool kinematic) = 0;
- /** Checks if the body is kinematic. */
- virtual bool getIsKinematic() const = 0;
- /**
- * Checks if the body is sleeping. Objects that aren't moved/rotated for a while are put to sleep to reduce load
- * on the physics system.
- */
- virtual bool isSleeping() const = 0;
- /** Forces the object to sleep. Useful if you know the object will not move in any significant way for a while. */
- virtual void sleep() = 0;
- /**
- * Wakes an object up. Useful if you modified properties of this object, and potentially surrounding objects which
- * might result in the object being moved by physics (although the physics system will automatically wake the
- * object up for majority of such cases).
- */
- virtual void wakeUp() = 0;
- /** Sets a threshold of force and torque under which the object will be considered to be put to sleep. */
- virtual void setSleepThreshold(float threshold) = 0;
- /** Gets a threshold of force and torque under which the object will be considered to be put to sleep. */
- virtual float getSleepThreshold() const = 0;
- /** Sets whether or not the rigidbody will have the global gravity force applied to it. */
- virtual void setUseGravity(bool gravity) = 0;
- /** Gets whether or not the rigidbody will have the global gravity force applied to it. */
- virtual bool getUseGravity() const = 0;
- /** Sets the linear velocity of the body. */
- virtual void setVelocity(const Vector3& velocity) = 0;
- /** Returns the current linear velocity of the body. */
- virtual Vector3 getVelocity() const = 0;
- /** Sets the angular velocity of the body. */
- virtual void setAngularVelocity(const Vector3& velocity) = 0;
- /** Returns the current angular velocity of the body. */
- virtual Vector3 getAngularVelocity() const = 0;
- /** Sets the linear drag of the body. Higher drag values means the object resists linear movement more. */
- virtual void setDrag(float drag) = 0;
- /** Gets the linear drag of the body. Higher drag values means the object resists linear movement more. */
- virtual float getDrag() const = 0;
- /** Sets the angular drag of the body. Higher drag values means the object resists angular movement more. */
- virtual void setAngularDrag(float drag) = 0;
- /** Gets the angular drag of the body. Higher drag values means the object resists angular movement more. */
- virtual float getAngularDrag() const = 0;
- /**
- * Sets the inertia tensor in local mass space. Inertia tensor determines how difficult is to rotate the object.
- * Values of zero in the inertia tensor mean the object will be unable to rotate around a specific axis. Only
- * relevant if Flag::AutoTensors is turned off.
- */
- virtual void setInertiaTensor(const Vector3& tensor) = 0;
- /** Gets the inertia tensor in local mass space. */
- virtual Vector3 getInertiaTensor() const = 0;
- /** Returns the maximum angular velocity of the rigidbody. Velocity will be clamped to this value. */
- virtual void setMaxAngularVelocity(float maxVelocity) = 0;
- /** Gets the maximum angular velocity of the rigidbody. */
- virtual float getMaxAngularVelocity() const = 0;
- /**
- * Sets the rigidbody's center of mass transform. Only relevant if Flag::AutoTensors is turned off.
- *
- * @param[in] position Position of the center of mass.
- * @param[in] rotation Rotation that determines orientation of the inertia tensor (rotation of the center of
- * mass frame).
- */
- virtual void setCenterOfMass(const Vector3& position, const Quaternion& rotation) = 0;
- /** Returns the position of the center of mass. */
- virtual Vector3 getCenterOfMassPosition() const = 0;
- /** Returns the rotation of the inertia tensor. */
- virtual Quaternion getCenterOfMassRotation() const = 0;
- /**
- * Sets the number of iterations to use when solving for position. Higher values can improve precision and
- * numerical stability of the simulation.
- */
- virtual void setPositionSolverCount(UINT32 count) = 0;
- /** Gets the number of iterations to use when solving for position. */
- virtual UINT32 getPositionSolverCount() const = 0;
- /**
- * Sets the number of iterations to use when solving for velocity. Higher values can improve precision and
- * numerical stability of the simulation.
- */
- virtual void setVelocitySolverCount(UINT32 count) = 0;
- /** Gets the number of iterations to use when solving for velocity. */
- virtual UINT32 getVelocitySolverCount() const = 0;
- /** Sets flags that control the behaviour of the rigidbody. */
- virtual void setFlags(Flag flags) { mFlags = flags; }
- /** Gets flags that control the behaviour of the rigidbody. */
- virtual Flag getFlags() const { return mFlags; }
- /**
- * Applies a force to the center of the mass of the rigidbody. This will produce linear momentum.
- *
- * @param[in] force Force to apply.
- * @param[in] mode Determines what is the type of @p force.
- */
- virtual void addForce(const Vector3& force, ForceMode mode = ForceMode::Force) = 0;
- /**
- * Applies a torque to the rigidbody. This will produce angular momentum.
- *
- * @param[in] torque Torque to apply.
- * @param[in] mode Determines what is the type of @p torque.
- */
- virtual void addTorque(const Vector3& torque, ForceMode mode = ForceMode::Force) = 0;
- /**
- * Applies a force to a specific point on the rigidbody. This will in most cases produce both linear and angular
- * momentum.
- *
- * @param[in] force Force to apply.
- * @param[in] position World position to apply the force at.
- * @param[in] mode Determines what is the type of @p force.
- */
- virtual void addForceAtPoint(const Vector3& force, const Vector3& position,
- PointForceMode mode = PointForceMode::Force) = 0;
- /**
- * Returns the total (linear + angular) velocity at a specific point.
- *
- * @param[in] point Point in world space.
- * @return Total velocity of the point.
- */
- virtual Vector3 getVelocityAtPoint(const Vector3& point) const = 0;
- /** Registers a new collider as a child of this rigidbody. */
- virtual void addCollider(FCollider* collider) = 0;
- /** Removes a collider from the child list of this rigidbody. */
- virtual void removeCollider(FCollider* collider) = 0;
- /** Removes all colliders from the child list of this rigidbody. */
- virtual void removeColliders() = 0;
- /**
- * Recalculates rigidbody's mass, inertia tensors and center of mass depending on the currently set child colliders.
- * This should be called whenever relevant child collider properties change (like mass or shape).
- *
- * If automatic tensor calculation is turned off then this will do nothing. If automatic mass calculation is turned
- * off then this will use the mass set directly on the body using setMass().
- */
- virtual void updateMassDistribution() { }
- /**
- * Creates a new rigidbody.
- *
- * @param[in] linkedSO Scene object that owns this rigidbody. All physics updates applied to this object
- * will be transfered to this scene object (the movement/rotation resulting from
- * those updates).
- */
- static SPtr<Rigidbody> create(const HSceneObject& linkedSO);
- /** Triggered when one of the colliders owned by the rigidbody starts colliding with another object. */
- Event<void(const CollisionData&)> onCollisionBegin;
- /** Triggered when a previously colliding collider stays in collision. Triggered once per frame. */
- Event<void(const CollisionData&)> onCollisionStay;
- /** Triggered when one of the colliders owned by the rigidbody stops colliding with another object. */
- Event<void(const CollisionData&)> onCollisionEnd;
- /** @name Internal
- * @{
- */
- /**
- * Sets the priority of the physics update. Bodies with a higher priority will be updated before the bodies with
- * lower priority. This allows you to control the order of updated in case rigidbodies are in some way dependant.
- */
- void _setPriority(UINT32 priority);
- /** Sets a unique ID of the rigidbody, so it can be recognized by the physics system. */
- void _setPhysicsId(UINT32 id) { mPhysicsId = id; }
- /**
- * Applies new transform values retrieved from the most recent physics update (values resulting from physics
- * simulation).
- */
- void _setTransform(const Vector3& position, const Quaternion& rotation);
- /**
- * 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:
- friend class FCollider;
- Flag mFlags = Flag::None;
- PhysicsObjectOwner mOwner;
- UINT32 mPhysicsId = 0;
- HSceneObject mLinkedSO;
- };
- /** @} */
- }
|