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