RigidBody.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. //
  2. // Copyright (c) 2008-2020 the Urho3D project.
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. /// \file
  23. #pragma once
  24. #include "../IO/VectorBuffer.h"
  25. #include "../Scene/Component.h"
  26. #include <Bullet/LinearMath/btMotionState.h>
  27. class btCompoundShape;
  28. class btRigidBody;
  29. namespace Urho3D
  30. {
  31. class CollisionShape;
  32. class Constraint;
  33. class PhysicsWorld;
  34. class SmoothedTransform;
  35. /// Rigid body collision event signaling mode.
  36. enum CollisionEventMode
  37. {
  38. COLLISION_NEVER = 0,
  39. COLLISION_ACTIVE,
  40. COLLISION_ALWAYS
  41. };
  42. /// Physics rigid body component.
  43. class URHO3D_API RigidBody : public Component, public btMotionState
  44. {
  45. URHO3D_OBJECT(RigidBody, Component);
  46. public:
  47. /// Construct.
  48. explicit RigidBody(Context* context);
  49. /// Destruct. Free the rigid body and geometries.
  50. ~RigidBody() override;
  51. /// Register object factory.
  52. static void RegisterObject(Context* context);
  53. /// Apply attribute changes that can not be applied immediately. Called after scene load or a network update.
  54. void ApplyAttributes() override;
  55. /// Handle enabled/disabled state change.
  56. void OnSetEnabled() override;
  57. /// Return initial world transform to Bullet.
  58. /// @nobind
  59. void getWorldTransform(btTransform& worldTrans) const override;
  60. /// Update world transform from Bullet.
  61. /// @nobind
  62. void setWorldTransform(const btTransform& worldTrans) override;
  63. /// Visualize the component as debug geometry.
  64. void DrawDebugGeometry(DebugRenderer* debug, bool depthTest) override;
  65. /// Set mass. Zero mass makes the body static.
  66. /// @property
  67. void SetMass(float mass);
  68. /// Set rigid body position in world space.
  69. /// @property
  70. void SetPosition(const Vector3& position);
  71. /// Set rigid body rotation in world space.
  72. /// @property
  73. void SetRotation(const Quaternion& rotation);
  74. /// Set rigid body position and rotation in world space as an atomic operation.
  75. void SetTransform(const Vector3& position, const Quaternion& rotation);
  76. /// Set linear velocity.
  77. /// @property
  78. void SetLinearVelocity(const Vector3& velocity);
  79. /// Set linear degrees of freedom. Use 1 to enable an axis or 0 to disable. Default is all axes enabled (1, 1, 1).
  80. /// @property
  81. void SetLinearFactor(const Vector3& factor);
  82. /// Set linear velocity deactivation threshold.
  83. /// @property
  84. void SetLinearRestThreshold(float threshold);
  85. /// Set linear velocity damping factor.
  86. /// @property
  87. void SetLinearDamping(float damping);
  88. /// Set angular velocity.
  89. /// @property
  90. void SetAngularVelocity(const Vector3& velocity);
  91. /// Set angular degrees of freedom. Use 1 to enable an axis or 0 to disable. Default is all axes enabled (1, 1, 1).
  92. /// @property
  93. void SetAngularFactor(const Vector3& factor);
  94. /// Set angular velocity deactivation threshold.
  95. /// @property
  96. void SetAngularRestThreshold(float threshold);
  97. /// Set angular velocity damping factor.
  98. /// @property
  99. void SetAngularDamping(float damping);
  100. /// Set friction coefficient.
  101. /// @property
  102. void SetFriction(float friction);
  103. /// Set anisotropic friction.
  104. /// @property
  105. void SetAnisotropicFriction(const Vector3& friction);
  106. /// Set rolling friction coefficient.
  107. /// @property
  108. void SetRollingFriction(float friction);
  109. /// Set restitution coefficient.
  110. /// @property
  111. void SetRestitution(float restitution);
  112. /// Set contact processing threshold.
  113. /// @property
  114. void SetContactProcessingThreshold(float threshold);
  115. /// Set continuous collision detection swept sphere radius.
  116. /// @property
  117. void SetCcdRadius(float radius);
  118. /// Set continuous collision detection motion-per-simulation-step threshold. 0 disables, which is the default.
  119. /// @property
  120. void SetCcdMotionThreshold(float threshold);
  121. /// Set whether gravity is applied to rigid body.
  122. /// @property
  123. void SetUseGravity(bool enable);
  124. /// Set gravity override. If zero, uses physics world's gravity.
  125. /// @property
  126. void SetGravityOverride(const Vector3& gravity);
  127. /// Set rigid body kinematic mode. In kinematic mode forces are not applied to the rigid body.
  128. /// @property
  129. void SetKinematic(bool enable);
  130. /// Set rigid body trigger mode. In trigger mode collisions are reported but do not apply forces.
  131. /// @property
  132. void SetTrigger(bool enable);
  133. /// Set collision layer.
  134. /// @property
  135. void SetCollisionLayer(unsigned layer);
  136. /// Set collision mask.
  137. /// @property
  138. void SetCollisionMask(unsigned mask);
  139. /// Set collision group and mask.
  140. void SetCollisionLayerAndMask(unsigned layer, unsigned mask);
  141. /// Set collision event signaling mode. Default is to signal when rigid bodies are active.
  142. /// @property
  143. void SetCollisionEventMode(CollisionEventMode mode);
  144. /// Apply force to center of mass.
  145. void ApplyForce(const Vector3& force);
  146. /// Apply force at local position.
  147. void ApplyForce(const Vector3& force, const Vector3& position);
  148. /// Apply torque.
  149. void ApplyTorque(const Vector3& torque);
  150. /// Apply impulse to center of mass.
  151. void ApplyImpulse(const Vector3& impulse);
  152. /// Apply impulse at local position.
  153. void ApplyImpulse(const Vector3& impulse, const Vector3& position);
  154. /// Apply torque impulse.
  155. void ApplyTorqueImpulse(const Vector3& torque);
  156. /// Reset accumulated forces.
  157. void ResetForces();
  158. /// Activate rigid body if it was resting.
  159. void Activate();
  160. /// Readd rigid body to the physics world to clean up internal state like stale contacts.
  161. void ReAddBodyToWorld();
  162. /// Disable mass update. Call this to optimize performance when adding or editing multiple collision shapes in the same node.
  163. void DisableMassUpdate();
  164. /// Re-enable mass update and recalculate the mass/inertia by calling UpdateMass(). Call when collision shape changes are finished.
  165. void EnableMassUpdate();
  166. /// Return physics world.
  167. PhysicsWorld* GetPhysicsWorld() const { return physicsWorld_; }
  168. /// Return Bullet rigid body.
  169. btRigidBody* GetBody() const { return body_.Get(); }
  170. /// Return Bullet compound collision shape.
  171. btCompoundShape* GetCompoundShape() const { return compoundShape_.Get(); }
  172. /// Return mass.
  173. /// @property
  174. float GetMass() const { return mass_; }
  175. /// Return rigid body position in world space.
  176. /// @property
  177. Vector3 GetPosition() const;
  178. /// Return rigid body rotation in world space.
  179. /// @property
  180. Quaternion GetRotation() const;
  181. /// Return linear velocity.
  182. /// @property
  183. Vector3 GetLinearVelocity() const;
  184. /// Return linear degrees of freedom.
  185. /// @property
  186. Vector3 GetLinearFactor() const;
  187. /// Return linear velocity at local point.
  188. Vector3 GetVelocityAtPoint(const Vector3& position) const;
  189. /// Return linear velocity deactivation threshold.
  190. /// @property
  191. float GetLinearRestThreshold() const;
  192. /// Return linear velocity damping factor.
  193. /// @property
  194. float GetLinearDamping() const;
  195. /// Return angular velocity.
  196. /// @property
  197. Vector3 GetAngularVelocity() const;
  198. /// Return angular degrees of freedom.
  199. /// @property
  200. Vector3 GetAngularFactor() const;
  201. /// Return angular velocity deactivation threshold.
  202. /// @property
  203. float GetAngularRestThreshold() const;
  204. /// Return angular velocity damping factor.
  205. /// @property
  206. float GetAngularDamping() const;
  207. /// Return friction coefficient.
  208. /// @property
  209. float GetFriction() const;
  210. /// Return anisotropic friction.
  211. /// @property
  212. Vector3 GetAnisotropicFriction() const;
  213. /// Return rolling friction coefficient.
  214. /// @property
  215. float GetRollingFriction() const;
  216. /// Return restitution coefficient.
  217. /// @property
  218. float GetRestitution() const;
  219. /// Return contact processing threshold.
  220. /// @property
  221. float GetContactProcessingThreshold() const;
  222. /// Return continuous collision detection swept sphere radius.
  223. /// @property
  224. float GetCcdRadius() const;
  225. /// Return continuous collision detection motion-per-simulation-step threshold.
  226. /// @property
  227. float GetCcdMotionThreshold() const;
  228. /// Return whether rigid body uses gravity.
  229. /// @property
  230. bool GetUseGravity() const { return useGravity_; }
  231. /// Return gravity override. If zero (default), uses the physics world's gravity.
  232. /// @property
  233. const Vector3& GetGravityOverride() const { return gravityOverride_; }
  234. /// Return center of mass offset.
  235. /// @property
  236. const Vector3& GetCenterOfMass() const { return centerOfMass_; }
  237. /// Return kinematic mode flag.
  238. /// @property
  239. bool IsKinematic() const { return kinematic_; }
  240. /// Return whether this RigidBody is acting as a trigger.
  241. /// @property
  242. bool IsTrigger() const { return trigger_; }
  243. /// Return whether rigid body is active (not sleeping).
  244. /// @property
  245. bool IsActive() const;
  246. /// Return collision layer.
  247. /// @property
  248. unsigned GetCollisionLayer() const { return collisionLayer_; }
  249. /// Return collision mask.
  250. /// @property
  251. unsigned GetCollisionMask() const { return collisionMask_; }
  252. /// Return collision event signaling mode.
  253. /// @property
  254. CollisionEventMode GetCollisionEventMode() const { return collisionEventMode_; }
  255. /// Return colliding rigid bodies from the last simulation step. Only returns collisions that were sent as events (depends on collision event mode) and excludes e.g. static-static collisions.
  256. void GetCollidingBodies(PODVector<RigidBody*>& result) const;
  257. /// Apply new world transform after a simulation step. Called internally.
  258. void ApplyWorldTransform(const Vector3& newWorldPosition, const Quaternion& newWorldRotation);
  259. /// Update mass and inertia to the Bullet rigid body. Readd body to world if necessary: if was in world and the Bullet collision shape to use changed.
  260. void UpdateMass();
  261. /// Update gravity parameters to the Bullet rigid body.
  262. void UpdateGravity();
  263. /// Set network angular velocity attribute.
  264. void SetNetAngularVelocityAttr(const PODVector<unsigned char>& value);
  265. /// Return network angular velocity attribute.
  266. const PODVector<unsigned char>& GetNetAngularVelocityAttr() const;
  267. /// Add a constraint that refers to this rigid body.
  268. void AddConstraint(Constraint* constraint);
  269. /// Remove a constraint that refers to this rigid body.
  270. void RemoveConstraint(Constraint* constraint);
  271. /// Remove the rigid body.
  272. void ReleaseBody();
  273. protected:
  274. /// Handle node being assigned.
  275. void OnNodeSet(Node* node) override;
  276. /// Handle scene being assigned.
  277. void OnSceneSet(Scene* scene) override;
  278. /// Handle node transform being dirtied.
  279. void OnMarkedDirty(Node* node) override;
  280. private:
  281. /// Create the rigid body, or re-add to the physics world with changed flags. Calls UpdateMass().
  282. void AddBodyToWorld();
  283. /// Remove the rigid body from the physics world.
  284. void RemoveBodyFromWorld();
  285. /// Handle SmoothedTransform target position update.
  286. void HandleTargetPosition(StringHash eventType, VariantMap& eventData);
  287. /// Handle SmoothedTransform target rotation update.
  288. void HandleTargetRotation(StringHash eventType, VariantMap& eventData);
  289. /// Mark body dirty.
  290. void MarkBodyDirty() { readdBody_ = true; }
  291. /// Bullet rigid body.
  292. UniquePtr<btRigidBody> body_;
  293. /// Bullet compound collision shape.
  294. UniquePtr<btCompoundShape> compoundShape_;
  295. /// Compound collision shape with center of mass offset applied.
  296. UniquePtr<btCompoundShape> shiftedCompoundShape_;
  297. /// Physics world.
  298. WeakPtr<PhysicsWorld> physicsWorld_;
  299. /// Smoothed transform, if has one.
  300. WeakPtr<SmoothedTransform> smoothedTransform_;
  301. /// Constraints that refer to this rigid body.
  302. PODVector<Constraint*> constraints_;
  303. /// Gravity override vector.
  304. Vector3 gravityOverride_;
  305. /// Center of mass offset.
  306. Vector3 centerOfMass_;
  307. /// Mass.
  308. float mass_;
  309. /// Attribute buffer for network replication.
  310. mutable VectorBuffer attrBuffer_;
  311. /// Collision layer.
  312. unsigned collisionLayer_;
  313. /// Collision mask.
  314. unsigned collisionMask_;
  315. /// Collision event signaling mode.
  316. CollisionEventMode collisionEventMode_;
  317. /// Last interpolated position from the simulation.
  318. mutable Vector3 lastPosition_;
  319. /// Last interpolated rotation from the simulation.
  320. mutable Quaternion lastRotation_;
  321. /// Kinematic flag.
  322. bool kinematic_;
  323. /// Trigger flag.
  324. bool trigger_;
  325. /// Use gravity flag.
  326. bool useGravity_;
  327. /// Readd body to world flag.
  328. bool readdBody_;
  329. /// Body exists in world flag.
  330. bool inWorld_;
  331. /// Mass update enable flag.
  332. bool enableMassUpdate_;
  333. /// Internal flag whether has simulated at least once.
  334. mutable bool hasSimulated_;
  335. };
  336. }