1 | //************************************ bs::framework - Copyright 2018 Marko Pintera **************************************// |
2 | //*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********// |
3 | #pragma once |
4 | |
5 | #include "BsCorePrerequisites.h" |
6 | #include "Physics/BsPhysicsCommon.h" |
7 | |
8 | namespace bs |
9 | { |
10 | /** @addtogroup Physics |
11 | * @{ |
12 | */ |
13 | |
14 | /** Type of force or torque that can be applied to a rigidbody. */ |
15 | enum class BS_SCRIPT_EXPORT(m:Physics) ForceMode |
16 | { |
17 | Force, /**< Value applied is a force. */ |
18 | Impulse, /**< Value applied is an impulse (a direct change in its linear or angular momentum). */ |
19 | Velocity, /**< Value applied is velocity. */ |
20 | Acceleration /**< Value applied is accelearation. */ |
21 | }; |
22 | |
23 | /** Type of force that can be applied to a rigidbody at an arbitrary point. */ |
24 | enum class BS_SCRIPT_EXPORT(m:Physics) PointForceMode |
25 | { |
26 | Force, /**< Value applied is a force. */ |
27 | Impulse, /**< Value applied is an impulse (a direct change in its linear or angular momentum). */ |
28 | }; |
29 | |
30 | /** Flags that control options of a Rigidbody object. */ |
31 | enum class BS_SCRIPT_EXPORT(m:Physics) RigidbodyFlag |
32 | { |
33 | /** No options. */ |
34 | None = 0x00, |
35 | /** Automatically calculate center of mass transform and inertia tensors from child shapes (colliders). */ |
36 | AutoTensors = 0x01, |
37 | /** Calculate mass distribution from child shapes (colliders). Only relevant when auto-tensors is on. */ |
38 | AutoMass = 0x02, |
39 | /** |
40 | * Enables continous collision detection. This can prevent fast moving bodies from tunneling through each other. |
41 | * This must also be enabled globally in Physics otherwise the flag will be ignored. |
42 | */ |
43 | CCD = 0x04 |
44 | }; |
45 | |
46 | /** |
47 | * Rigidbody is a dynamic physics object that can be moved using forces (or directly). It will interact with other |
48 | * static and dynamic physics objects in the scene accordingly (it will push other non-kinematic rigidbodies, |
49 | * and collide with static objects). |
50 | * |
51 | * The shape and mass of a rigidbody is governed by its colliders. You must attach at least one collider for the |
52 | * rigidbody to be valid. |
53 | */ |
54 | class BS_CORE_EXPORT Rigidbody |
55 | { |
56 | public: |
57 | /** |
58 | * Constructs a new rigidbody. |
59 | * |
60 | * @param[in] linkedSO Scene object that owns this rigidbody. All physics updates applied to this object |
61 | * will be transfered to this scene object (the movement/rotation resulting from |
62 | * those updates). |
63 | */ |
64 | Rigidbody(const HSceneObject& linkedSO); |
65 | virtual ~Rigidbody() = default; |
66 | |
67 | /** |
68 | * Moves the rigidbody to a specific position. This method will ensure physically correct movement, meaning the body |
69 | * will collide with other objects along the way. |
70 | */ |
71 | virtual void move(const Vector3& position) = 0; |
72 | |
73 | /** |
74 | * Rotates the rigidbody. This method will ensure physically correct rotation, meaning the body will collide with |
75 | * other objects along the way. |
76 | */ |
77 | virtual void rotate(const Quaternion& rotation) = 0; |
78 | |
79 | /** Returns the current position of the rigidbody. */ |
80 | virtual Vector3 getPosition() const = 0; |
81 | |
82 | /** Returns the current rotation of the rigidbody. */ |
83 | virtual Quaternion getRotation() const = 0; |
84 | |
85 | /** |
86 | * Moves and rotates the rigidbody to a specific position. Unlike move() and rotate() this will not transform the |
87 | * body in a physically correct manner, but will instead "teleport" it immediately to the specified position and |
88 | * rotation. |
89 | */ |
90 | virtual void setTransform(const Vector3& pos, const Quaternion& rot) = 0; |
91 | |
92 | /** |
93 | * Determines the mass of the object and all of its collider shapes. Only relevant if RigidbodyFlag::AutoMass or |
94 | * RigidbodyFlag::AutoTensors is turned off. Value of zero means the object is immovable (but can be rotated). |
95 | */ |
96 | virtual void setMass(float mass) = 0; |
97 | |
98 | /** @copydoc setMass() */ |
99 | virtual float getMass() const = 0; |
100 | |
101 | /** |
102 | * Determines if the body is kinematic. Kinematic body will not move in response to external forces (for example |
103 | * gravity, or another object pushing it), essentially behaving like collider. Unlike a collider though, you can |
104 | * still move the object and have other dynamic objects respond correctly (meaning it will push other objects). |
105 | */ |
106 | virtual void setIsKinematic(bool kinematic) = 0; |
107 | |
108 | /** @copydoc setIsKinematic() */ |
109 | virtual bool getIsKinematic() const = 0; |
110 | |
111 | /** |
112 | * Checks if the body is sleeping. Objects that aren't moved/rotated for a while are put to sleep to reduce load |
113 | * on the physics system. |
114 | */ |
115 | virtual bool isSleeping() const = 0; |
116 | |
117 | /** Forces the object to sleep. Useful if you know the object will not move in any significant way for a while. */ |
118 | virtual void sleep() = 0; |
119 | |
120 | /** |
121 | * Wakes an object up. Useful if you modified properties of this object, and potentially surrounding objects which |
122 | * might result in the object being moved by physics (although the physics system will automatically wake the |
123 | * object up for majority of such cases). |
124 | */ |
125 | virtual void wakeUp() = 0; |
126 | |
127 | /** Determines a threshold of force and torque under which the object will be considered to be put to sleep. */ |
128 | virtual void setSleepThreshold(float threshold) = 0; |
129 | |
130 | /** @copydoc setSleepThreshold() */ |
131 | virtual float getSleepThreshold() const = 0; |
132 | |
133 | /** Determines whether or not the rigidbody will have the global gravity force applied to it. */ |
134 | virtual void setUseGravity(bool gravity) = 0; |
135 | |
136 | /** @copydoc setUseGravity() */ |
137 | virtual bool getUseGravity() const = 0; |
138 | |
139 | /** Determines the linear velocity of the body. */ |
140 | virtual void setVelocity(const Vector3& velocity) = 0; |
141 | |
142 | /** @copydoc setVelocity() */ |
143 | virtual Vector3 getVelocity() const = 0; |
144 | |
145 | /** Determines the angular velocity of the body. */ |
146 | virtual void setAngularVelocity(const Vector3& velocity) = 0; |
147 | |
148 | /** @copydoc setAngularVelocity() */ |
149 | virtual Vector3 getAngularVelocity() const = 0; |
150 | |
151 | /** Determines the linear drag of the body. Higher drag values means the object resists linear movement more. */ |
152 | virtual void setDrag(float drag) = 0; |
153 | |
154 | /** @copydoc setDrag() */ |
155 | virtual float getDrag() const = 0; |
156 | |
157 | /** Determines the angular drag of the body. Higher drag values means the object resists angular movement more. */ |
158 | virtual void setAngularDrag(float drag) = 0; |
159 | |
160 | /** @copydoc setAngularDrag() */ |
161 | virtual float getAngularDrag() const = 0; |
162 | |
163 | /** |
164 | * Determines the inertia tensor in local mass space. Inertia tensor determines how difficult is to rotate the |
165 | * object. Values of zero in the inertia tensor mean the object will be unable to rotate around a specific axis. |
166 | * Only relevant if RigidbodyFlag::AutoTensors is turned off. |
167 | */ |
168 | virtual void setInertiaTensor(const Vector3& tensor) = 0; |
169 | |
170 | /** @copydoc setInertiaTensor() */ |
171 | virtual Vector3 getInertiaTensor() const = 0; |
172 | |
173 | /** Determines the maximum angular velocity of the rigidbody. Velocity will be clamped to this value. */ |
174 | virtual void setMaxAngularVelocity(float maxVelocity) = 0; |
175 | |
176 | /** @copydoc setMaxAngularVelocity() */ |
177 | virtual float getMaxAngularVelocity() const = 0; |
178 | |
179 | /** |
180 | * Sets the rigidbody's center of mass transform. Only relevant if RigibodyFlag::AutoTensors is turned off. |
181 | * |
182 | * @param[in] position Position of the center of mass. |
183 | * @param[in] rotation Rotation that determines orientation of the inertia tensor (rotation of the center of |
184 | * mass frame). |
185 | */ |
186 | virtual void setCenterOfMass(const Vector3& position, const Quaternion& rotation) = 0; |
187 | |
188 | /** Returns the position of the center of mass. */ |
189 | virtual Vector3 getCenterOfMassPosition() const = 0; |
190 | |
191 | /** Returns the rotation of the inertia tensor. */ |
192 | virtual Quaternion getCenterOfMassRotation() const = 0; |
193 | |
194 | /** |
195 | * Determines the number of iterations to use when solving for position. Higher values can improve precision and |
196 | * numerical stability of the simulation. |
197 | */ |
198 | virtual void setPositionSolverCount(UINT32 count) = 0; |
199 | |
200 | /** @copydoc setPositionSolverCount() */ |
201 | virtual UINT32 getPositionSolverCount() const = 0; |
202 | |
203 | /** |
204 | * Determines the number of iterations to use when solving for velocity. Higher values can improve precision and |
205 | * numerical stability of the simulation. |
206 | */ |
207 | virtual void setVelocitySolverCount(UINT32 count) = 0; |
208 | |
209 | /** @copydoc setVelocitySolverCount() */ |
210 | virtual UINT32 getVelocitySolverCount() const = 0; |
211 | |
212 | /** Flags that control the behaviour of the rigidbody. */ |
213 | virtual void setFlags(RigidbodyFlag flags) { mFlags = flags; } |
214 | |
215 | /** @copydoc setFlags() */ |
216 | virtual RigidbodyFlag getFlags() const { return mFlags; } |
217 | |
218 | /** |
219 | * Applies a force to the center of the mass of the rigidbody. This will produce linear momentum. |
220 | * |
221 | * @param[in] force Force to apply. |
222 | * @param[in] mode Determines what is the type of @p force. |
223 | */ |
224 | virtual void addForce(const Vector3& force, ForceMode mode = ForceMode::Force) = 0; |
225 | |
226 | /** |
227 | * Applies a torque to the rigidbody. This will produce angular momentum. |
228 | * |
229 | * @param[in] torque Torque to apply. |
230 | * @param[in] mode Determines what is the type of @p torque. |
231 | */ |
232 | virtual void addTorque(const Vector3& torque, ForceMode mode = ForceMode::Force) = 0; |
233 | |
234 | /** |
235 | * Applies a force to a specific point on the rigidbody. This will in most cases produce both linear and angular |
236 | * momentum. |
237 | * |
238 | * @param[in] force Force to apply. |
239 | * @param[in] position World position to apply the force at. |
240 | * @param[in] mode Determines what is the type of @p force. |
241 | */ |
242 | virtual void addForceAtPoint(const Vector3& force, const Vector3& position, |
243 | PointForceMode mode = PointForceMode::Force) = 0; |
244 | |
245 | /** |
246 | * Returns the total (linear + angular) velocity at a specific point. |
247 | * |
248 | * @param[in] point Point in world space. |
249 | * @return Total velocity of the point. |
250 | */ |
251 | virtual Vector3 getVelocityAtPoint(const Vector3& point) const = 0; |
252 | |
253 | /** Registers a new collider as a child of this rigidbody. */ |
254 | virtual void addCollider(Collider* collider) = 0; |
255 | |
256 | /** Removes a collider from the child list of this rigidbody. */ |
257 | virtual void removeCollider(Collider* collider) = 0; |
258 | |
259 | /** Removes all colliders from the child list of this rigidbody. */ |
260 | virtual void removeColliders() = 0; |
261 | |
262 | /** |
263 | * Recalculates rigidbody's mass, inertia tensors and center of mass depending on the currently set child colliders. |
264 | * This should be called whenever relevant child collider properties change (like mass or shape). |
265 | * |
266 | * If automatic tensor calculation is turned off then this will do nothing. If automatic mass calculation is turned |
267 | * off then this will use the mass set directly on the body using setMass(). |
268 | */ |
269 | virtual void updateMassDistribution() { } |
270 | |
271 | /** |
272 | * Creates a new rigidbody. |
273 | * |
274 | * @param[in] linkedSO Scene object that owns this rigidbody. All physics updates applied to this object |
275 | * will be transfered to this scene object (the movement/rotation resulting from |
276 | * those updates). |
277 | */ |
278 | static SPtr<Rigidbody> create(const HSceneObject& linkedSO); |
279 | |
280 | /** Triggered when one of the colliders owned by the rigidbody starts colliding with another object. */ |
281 | Event<void(const CollisionDataRaw&)> onCollisionBegin; |
282 | |
283 | /** Triggered when a previously colliding collider stays in collision. Triggered once per frame. */ |
284 | Event<void(const CollisionDataRaw&)> onCollisionStay; |
285 | |
286 | /** Triggered when one of the colliders owned by the rigidbody stops colliding with another object. */ |
287 | Event<void(const CollisionDataRaw&)> onCollisionEnd; |
288 | |
289 | /** @name Internal |
290 | * @{ |
291 | */ |
292 | |
293 | /** |
294 | * Sets the priority of the physics update. Bodies with a higher priority will be updated before the bodies with |
295 | * lower priority. This allows you to control the order of updated in case rigidbodies are in some way dependant. |
296 | */ |
297 | void _setPriority(UINT32 priority); |
298 | |
299 | /** Sets a unique ID of the rigidbody, so it can be recognized by the physics system. */ |
300 | void _setPhysicsId(UINT32 id) { mPhysicsId = id; } |
301 | |
302 | /** |
303 | * Applies new transform values retrieved from the most recent physics update (values resulting from physics |
304 | * simulation). |
305 | */ |
306 | void _setTransform(const Vector3& position, const Quaternion& rotation); |
307 | |
308 | /** |
309 | * Sets the object that owns this physics object, if any. Used for high level systems so they can easily map their |
310 | * high level physics objects from the low level ones returned by various queries and events. |
311 | */ |
312 | void _setOwner(PhysicsOwnerType type, void* owner) { mOwner.type = type; mOwner.ownerData = owner; } |
313 | |
314 | /** |
315 | * Gets the object that owns this physics object, if any. Used for high level systems so they can easily map their |
316 | * high level physics objects from the low level ones returned by various queries and events. |
317 | */ |
318 | void* _getOwner(PhysicsOwnerType type) const { return mOwner.type == type ? mOwner.ownerData : nullptr; } |
319 | |
320 | /** @} */ |
321 | |
322 | protected: |
323 | RigidbodyFlag mFlags = RigidbodyFlag::None; |
324 | PhysicsObjectOwner mOwner; |
325 | UINT32 mPhysicsId = 0; |
326 | HSceneObject mLinkedSO; |
327 | }; |
328 | |
329 | /** @} */ |
330 | } |