1 // 2 // Copyright (c) 2008-2017 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 23 #pragma once 24 25 #include "../IO/VectorBuffer.h" 26 #include "../Scene/Component.h" 27 28 #include <Bullet/LinearMath/btMotionState.h> 29 30 class btCompoundShape; 31 class btRigidBody; 32 33 namespace Urho3D 34 { 35 36 class CollisionShape; 37 class Constraint; 38 class PhysicsWorld; 39 class SmoothedTransform; 40 41 /// Rigid body collision event signaling mode. 42 enum CollisionEventMode 43 { 44 COLLISION_NEVER = 0, 45 COLLISION_ACTIVE, 46 COLLISION_ALWAYS 47 }; 48 49 /// Physics rigid body component. 50 class URHO3D_API RigidBody : public Component, public btMotionState 51 { 52 URHO3D_OBJECT(RigidBody, Component); 53 54 public: 55 /// Construct. 56 RigidBody(Context* context); 57 /// Destruct. Free the rigid body and geometries. 58 virtual ~RigidBody(); 59 /// Register object factory. 60 static void RegisterObject(Context* context); 61 62 /// Handle attribute write access. 63 virtual void OnSetAttribute(const AttributeInfo& attr, const Variant& src); 64 /// Apply attribute changes that can not be applied immediately. Called after scene load or a network update. 65 virtual void ApplyAttributes(); 66 /// Handle enabled/disabled state change. 67 virtual void OnSetEnabled(); 68 /// Return initial world transform to Bullet. 69 virtual void getWorldTransform(btTransform& worldTrans) const; 70 /// Update world transform from Bullet. 71 virtual void setWorldTransform(const btTransform& worldTrans); 72 /// Visualize the component as debug geometry. 73 virtual void DrawDebugGeometry(DebugRenderer* debug, bool depthTest); 74 75 /// Set mass. Zero mass makes the body static. 76 void SetMass(float mass); 77 /// Set rigid body position in world space. 78 void SetPosition(const Vector3& position); 79 /// Set rigid body rotation in world space. 80 void SetRotation(const Quaternion& rotation); 81 /// Set rigid body position and rotation in world space as an atomic operation. 82 void SetTransform(const Vector3& position, const Quaternion& rotation); 83 /// Set linear velocity. 84 void SetLinearVelocity(const Vector3& velocity); 85 /// Set linear degrees of freedom. Use 1 to enable an axis or 0 to disable. Default is all axes enabled (1, 1, 1). 86 void SetLinearFactor(const Vector3& factor); 87 /// Set linear velocity deactivation threshold. 88 void SetLinearRestThreshold(float threshold); 89 /// Set linear velocity damping factor. 90 void SetLinearDamping(float damping); 91 /// Set angular velocity. 92 void SetAngularVelocity(const Vector3& angularVelocity); 93 /// Set angular degrees of freedom. Use 1 to enable an axis or 0 to disable. Default is all axes enabled (1, 1, 1). 94 void SetAngularFactor(const Vector3& factor); 95 /// Set angular velocity deactivation threshold. 96 void SetAngularRestThreshold(float threshold); 97 /// Set angular velocity damping factor. 98 void SetAngularDamping(float factor); 99 /// Set friction coefficient. 100 void SetFriction(float friction); 101 /// Set anisotropic friction. 102 void SetAnisotropicFriction(const Vector3& friction); 103 /// Set rolling friction coefficient. 104 void SetRollingFriction(float friction); 105 /// Set restitution coefficient. 106 void SetRestitution(float restitution); 107 /// Set contact processing threshold. 108 void SetContactProcessingThreshold(float threshold); 109 /// Set continuous collision detection swept sphere radius. 110 void SetCcdRadius(float radius); 111 /// Set continuous collision detection motion-per-simulation-step threshold. 0 disables, which is the default. 112 void SetCcdMotionThreshold(float threshold); 113 /// Set whether gravity is applied to rigid body. 114 void SetUseGravity(bool enable); 115 /// Set gravity override. If zero, uses physics world's gravity. 116 void SetGravityOverride(const Vector3& gravity); 117 /// Set rigid body kinematic mode. In kinematic mode forces are not applied to the rigid body. 118 void SetKinematic(bool enable); 119 /// Set rigid body trigger mode. In trigger mode collisions are reported but do not apply forces. 120 void SetTrigger(bool enable); 121 /// Set collision layer. 122 void SetCollisionLayer(unsigned layer); 123 /// Set collision mask. 124 void SetCollisionMask(unsigned mask); 125 /// Set collision group and mask. 126 void SetCollisionLayerAndMask(unsigned layer, unsigned mask); 127 /// Set collision event signaling mode. Default is to signal when rigid bodies are active. 128 void SetCollisionEventMode(CollisionEventMode mode); 129 /// Apply force to center of mass. 130 void ApplyForce(const Vector3& force); 131 /// Apply force at local position. 132 void ApplyForce(const Vector3& force, const Vector3& position); 133 /// Apply torque. 134 void ApplyTorque(const Vector3& torque); 135 /// Apply impulse to center of mass. 136 void ApplyImpulse(const Vector3& impulse); 137 /// Apply impulse at local position. 138 void ApplyImpulse(const Vector3& impulse, const Vector3& position); 139 /// Apply torque impulse. 140 void ApplyTorqueImpulse(const Vector3& torque); 141 /// Reset accumulated forces. 142 void ResetForces(); 143 /// Activate rigid body if it was resting. 144 void Activate(); 145 /// Readd rigid body to the physics world to clean up internal state like stale contacts. 146 void ReAddBodyToWorld(); 147 /// Disable mass update. Call this to optimize performance when adding or editing multiple collision shapes in the same node. 148 void DisableMassUpdate(); 149 /// Re-enable mass update and recalculate the mass/inertia by calling UpdateMass(). Call when collision shape changes are finished. 150 void EnableMassUpdate(); 151 152 /// Return physics world. GetPhysicsWorld()153 PhysicsWorld* GetPhysicsWorld() const { return physicsWorld_; } 154 155 /// Return Bullet rigid body. GetBody()156 btRigidBody* GetBody() const { return body_.Get(); } 157 158 /// Return Bullet compound collision shape. GetCompoundShape()159 btCompoundShape* GetCompoundShape() const { return compoundShape_.Get(); } 160 161 /// Return mass. GetMass()162 float GetMass() const { return mass_; } 163 164 /// Return rigid body position in world space. 165 Vector3 GetPosition() const; 166 /// Return rigid body rotation in world space. 167 Quaternion GetRotation() const; 168 /// Return linear velocity. 169 Vector3 GetLinearVelocity() const; 170 /// Return linear degrees of freedom. 171 Vector3 GetLinearFactor() const; 172 /// Return linear velocity at local point. 173 Vector3 GetVelocityAtPoint(const Vector3& position) const; 174 /// Return linear velocity deactivation threshold. 175 float GetLinearRestThreshold() const; 176 /// Return linear velocity damping factor. 177 float GetLinearDamping() const; 178 /// Return angular velocity. 179 Vector3 GetAngularVelocity() const; 180 /// Return angular degrees of freedom. 181 Vector3 GetAngularFactor() const; 182 /// Return angular velocity deactivation threshold. 183 float GetAngularRestThreshold() const; 184 /// Return angular velocity damping factor. 185 float GetAngularDamping() const; 186 /// Return friction coefficient. 187 float GetFriction() const; 188 /// Return anisotropic friction. 189 Vector3 GetAnisotropicFriction() const; 190 /// Return rolling friction coefficient. 191 float GetRollingFriction() const; 192 /// Return restitution coefficient. 193 float GetRestitution() const; 194 /// Return contact processing threshold. 195 float GetContactProcessingThreshold() const; 196 /// Return continuous collision detection swept sphere radius. 197 float GetCcdRadius() const; 198 /// Return continuous collision detection motion-per-simulation-step threshold. 199 float GetCcdMotionThreshold() const; 200 201 /// Return whether rigid body uses gravity. GetUseGravity()202 bool GetUseGravity() const { return useGravity_; } 203 204 /// Return gravity override. If zero (default), uses the physics world's gravity. GetGravityOverride()205 const Vector3& GetGravityOverride() const { return gravityOverride_; } 206 207 /// Return center of mass offset. GetCenterOfMass()208 const Vector3& GetCenterOfMass() const { return centerOfMass_; } 209 210 /// Return kinematic mode flag. IsKinematic()211 bool IsKinematic() const { return kinematic_; } 212 213 /// Return whether this RigidBody is acting as a trigger. IsTrigger()214 bool IsTrigger() const { return trigger_; } 215 216 /// Return whether rigid body is active (not sleeping.) 217 bool IsActive() const; 218 219 /// Return collision layer. GetCollisionLayer()220 unsigned GetCollisionLayer() const { return collisionLayer_; } 221 222 /// Return collision mask. GetCollisionMask()223 unsigned GetCollisionMask() const { return collisionMask_; } 224 225 /// Return collision event signaling mode. GetCollisionEventMode()226 CollisionEventMode GetCollisionEventMode() const { return collisionEventMode_; } 227 228 /// 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. 229 void GetCollidingBodies(PODVector<RigidBody*>& result) const; 230 231 /// Apply new world transform after a simulation step. Called internally. 232 void ApplyWorldTransform(const Vector3& newWorldPosition, const Quaternion& newWorldRotation); 233 /// 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. 234 void UpdateMass(); 235 /// Update gravity parameters to the Bullet rigid body. 236 void UpdateGravity(); 237 /// Set network angular velocity attribute. 238 void SetNetAngularVelocityAttr(const PODVector<unsigned char>& value); 239 /// Return network angular velocity attribute. 240 const PODVector<unsigned char>& GetNetAngularVelocityAttr() const; 241 /// Add a constraint that refers to this rigid body. 242 void AddConstraint(Constraint* constraint); 243 /// Remove a constraint that refers to this rigid body. 244 void RemoveConstraint(Constraint* constraint); 245 /// Remove the rigid body. 246 void ReleaseBody(); 247 248 protected: 249 /// Handle node being assigned. 250 virtual void OnNodeSet(Node* node); 251 /// Handle scene being assigned. 252 virtual void OnSceneSet(Scene* scene); 253 /// Handle node transform being dirtied. 254 virtual void OnMarkedDirty(Node* node); 255 256 private: 257 /// Create the rigid body, or re-add to the physics world with changed flags. Calls UpdateMass(). 258 void AddBodyToWorld(); 259 /// Remove the rigid body from the physics world. 260 void RemoveBodyFromWorld(); 261 /// Handle SmoothedTransform target position update. 262 void HandleTargetPosition(StringHash eventType, VariantMap& eventData); 263 /// Handle SmoothedTransform target rotation update. 264 void HandleTargetRotation(StringHash eventType, VariantMap& eventData); 265 266 /// Bullet rigid body. 267 UniquePtr<btRigidBody> body_; 268 /// Bullet compound collision shape. 269 UniquePtr<btCompoundShape> compoundShape_; 270 /// Compound collision shape with center of mass offset applied. 271 UniquePtr<btCompoundShape> shiftedCompoundShape_; 272 /// Physics world. 273 WeakPtr<PhysicsWorld> physicsWorld_; 274 /// Smoothed transform, if has one. 275 WeakPtr<SmoothedTransform> smoothedTransform_; 276 /// Constraints that refer to this rigid body. 277 PODVector<Constraint*> constraints_; 278 /// Gravity override vector. 279 Vector3 gravityOverride_; 280 /// Center of mass offset. 281 Vector3 centerOfMass_; 282 /// Mass. 283 float mass_; 284 /// Attribute buffer for network replication. 285 mutable VectorBuffer attrBuffer_; 286 /// Collision layer. 287 unsigned collisionLayer_; 288 /// Collision mask. 289 unsigned collisionMask_; 290 /// Collision event signaling mode. 291 CollisionEventMode collisionEventMode_; 292 /// Last interpolated position from the simulation. 293 mutable Vector3 lastPosition_; 294 /// Last interpolated rotation from the simulation. 295 mutable Quaternion lastRotation_; 296 /// Kinematic flag. 297 bool kinematic_; 298 /// Trigger flag. 299 bool trigger_; 300 /// Use gravity flag. 301 bool useGravity_; 302 /// Readd body to world flag. 303 bool readdBody_; 304 /// Body exists in world flag. 305 bool inWorld_; 306 /// Mass update enable flag. 307 bool enableMassUpdate_; 308 /// Internal flag whether has simulated at least once. 309 mutable bool hasSimulated_; 310 }; 311 312 } 313