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 "../Scene/Component.h"
26 #include "../IO/VectorBuffer.h"
27 
28 #include <Box2D/Box2D.h>
29 
30 namespace Urho3D
31 {
32 
33 class Camera;
34 class CollisionShape2D;
35 class RigidBody2D;
36 
37 /// 2D Physics raycast hit.
38 struct URHO3D_API PhysicsRaycastResult2D
39 {
40     /// Construct with defaults.
PhysicsRaycastResult2DPhysicsRaycastResult2D41     PhysicsRaycastResult2D() :
42         body_(0)
43     {
44     }
45 
46     /// Test for inequality, added to prevent GCC from complaining.
47     bool operator !=(const PhysicsRaycastResult2D& rhs) const
48     {
49         return position_ != rhs.position_ || normal_ != rhs.normal_ || distance_ != rhs.distance_ || body_ != rhs.body_;
50     }
51 
52     /// Hit worldspace position.
53     Vector2 position_;
54     /// Hit worldspace normal.
55     Vector2 normal_;
56     /// Hit distance from ray origin.
57     float distance_;
58     /// Rigid body that was hit.
59     RigidBody2D* body_;
60 };
61 
62 /// Delayed world transform assignment for parented 2D rigidbodies.
63 struct DelayedWorldTransform2D
64 {
65     /// Rigid body.
66     RigidBody2D* rigidBody_;
67     /// Parent rigid body.
68     RigidBody2D* parentRigidBody_;
69     /// New world position.
70     Vector3 worldPosition_;
71     /// New world rotation.
72     Quaternion worldRotation_;
73 };
74 
75 /// 2D physics simulation world component. Should be added only to the root scene node.
76 class URHO3D_API PhysicsWorld2D : public Component, public b2ContactListener, public b2Draw
77 {
78     URHO3D_OBJECT(PhysicsWorld2D, Component);
79 
80 public:
81     /// Construct.
82     PhysicsWorld2D(Context* context);
83     /// Destruct.
84     virtual ~PhysicsWorld2D();
85     /// Register object factory.
86     static void RegisterObject(Context* context);
87 
88     /// Visualize the component as debug geometry.
89     virtual void DrawDebugGeometry(DebugRenderer* debug, bool depthTest);
90 
91     // Implement b2ContactListener
92     /// Called when two fixtures begin to touch.
93     virtual void BeginContact(b2Contact* contact);
94     /// Called when two fixtures cease to touch.
95     virtual void EndContact(b2Contact* contact);
96     /// Called when contact is updated.
97     virtual void PreSolve(b2Contact* contact, const b2Manifold* oldManifold);
98 
99     // Implement b2Draw
100     /// Draw a closed polygon provided in CCW order.
101     virtual void DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color);
102     /// Draw a solid closed polygon provided in CCW order.
103     virtual void DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color);
104     /// Draw a circle.
105     virtual void DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color);
106     /// Draw a solid circle.
107     virtual void DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color);
108     /// Draw a line segment.
109     virtual void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color);
110     /// Draw a transform. Choose your own length scale.
111     virtual void DrawTransform(const b2Transform& xf);
112     /// Draw a point.
113     virtual void DrawPoint(const b2Vec2& p, float32 size, const b2Color& color);
114 
115     /// Step the simulation forward.
116     void Update(float timeStep);
117     /// Add debug geometry to the debug renderer.
118     void DrawDebugGeometry();
119     /// Enable or disable automatic physics simulation during scene update. Enabled by default.
120     void SetUpdateEnabled(bool enable);
121     /// Set draw shape.
122     void SetDrawShape(bool drawShape);
123     /// Set draw joint.
124     void SetDrawJoint(bool drawJoint);
125     /// Set draw aabb.
126     void SetDrawAabb(bool drawAabb);
127     /// Set draw pair.
128     void SetDrawPair(bool drawPair);
129     /// Set draw center of mass.
130     void SetDrawCenterOfMass(bool drawCenterOfMass);
131     /// Set allow sleeping.
132     void SetAllowSleeping(bool enable);
133     /// Set warm starting.
134     void SetWarmStarting(bool enable);
135     /// Set continuous physics.
136     void SetContinuousPhysics(bool enable);
137     /// Set sub stepping.
138     void SetSubStepping(bool enable);
139     /// Set gravity.
140     void SetGravity(const Vector2& gravity);
141     /// Set auto clear forces.
142     void SetAutoClearForces(bool enable);
143     /// Set velocity iterations.
144     void SetVelocityIterations(int velocityIterations);
145     /// Set position iterations.
146     void SetPositionIterations(int positionIterations);
147     /// Add rigid body.
148     void AddRigidBody(RigidBody2D* rigidBody);
149     /// Remove rigid body.
150     void RemoveRigidBody(RigidBody2D* rigidBody);
151     /// Add a delayed world transform assignment. Called by RigidBody2D.
152     void AddDelayedWorldTransform(const DelayedWorldTransform2D& transform);
153 
154     /// Perform a physics world raycast and return all hits.
155     void Raycast(PODVector<PhysicsRaycastResult2D>& results, const Vector2& startPoint, const Vector2& endPoint,
156         unsigned collisionMask = M_MAX_UNSIGNED);
157     /// Perform a physics world raycast and return the closest hit.
158     void RaycastSingle(PhysicsRaycastResult2D& result, const Vector2& startPoint, const Vector2& endPoint,
159         unsigned collisionMask = M_MAX_UNSIGNED);
160     /// Return rigid body at point.
161     RigidBody2D* GetRigidBody(const Vector2& point, unsigned collisionMask = M_MAX_UNSIGNED);
162     /// Return rigid body at screen point.
163     RigidBody2D* GetRigidBody(int screenX, int screenY, unsigned collisionMask = M_MAX_UNSIGNED);
164     /// Return rigid bodies by a box query.
165     void GetRigidBodies(PODVector<RigidBody2D*>& result, const Rect& aabb, unsigned collisionMask = M_MAX_UNSIGNED);
166 
167     /// Return whether physics world will automatically simulate during scene update.
IsUpdateEnabled()168     bool IsUpdateEnabled() const { return updateEnabled_; }
169 
170     /// Return draw shape.
GetDrawShape()171     bool GetDrawShape() const { return (m_drawFlags & e_shapeBit) != 0; }
172 
173     /// Return draw joint.
GetDrawJoint()174     bool GetDrawJoint() const { return (m_drawFlags & e_jointBit) != 0; }
175 
176     /// Return draw aabb.
GetDrawAabb()177     bool GetDrawAabb() const { return (m_drawFlags & e_aabbBit) != 0; }
178 
179     /// Return draw pair.
GetDrawPair()180     bool GetDrawPair() const { return (m_drawFlags & e_pairBit) != 0; }
181 
182     /// Return draw center of mass.
GetDrawCenterOfMass()183     bool GetDrawCenterOfMass() const { return (m_drawFlags & e_centerOfMassBit) != 0; }
184 
185     /// Return allow sleeping.
186     bool GetAllowSleeping() const;
187     /// Return warm starting.
188     bool GetWarmStarting() const;
189     /// Return continuous physics.
190     bool GetContinuousPhysics() const;
191     /// Return sub stepping.
192     bool GetSubStepping() const;
193     /// Return auto clear forces.
194     bool GetAutoClearForces() const;
195 
196     /// Return gravity.
GetGravity()197     const Vector2& GetGravity() const { return gravity_; }
198 
199     /// Return velocity iterations.
GetVelocityIterations()200     int GetVelocityIterations() const { return velocityIterations_; }
201 
202     /// Return position iterations.
GetPositionIterations()203     int GetPositionIterations() const { return positionIterations_; }
204 
205     /// Return the Box2D physics world.
GetWorld()206     b2World* GetWorld() { return world_.Get(); }
207 
208     /// Set node dirtying to be disregarded.
SetApplyingTransforms(bool enable)209     void SetApplyingTransforms(bool enable) { applyingTransforms_ = enable; }
210 
211     /// Return whether node dirtying should be disregarded.
IsApplyingTransforms()212     bool IsApplyingTransforms() const { return applyingTransforms_; }
213 
214 protected:
215     /// Handle scene being assigned.
216     virtual void OnSceneSet(Scene* scene);
217 
218     /// Handle the scene subsystem update event, step simulation here.
219     void HandleSceneSubsystemUpdate(StringHash eventType, VariantMap& eventData);
220     /// Send begin contact events.
221     void SendBeginContactEvents();
222     /// Send end contact events.
223     void SendEndContactEvents();
224 
225     /// Box2D physics world.
226     UniquePtr<b2World> world_;
227     /// Gravity.
228     Vector2 gravity_;
229     /// Velocity iterations.
230     int velocityIterations_;
231     /// Position iterations.
232     int positionIterations_;
233 
234     /// Extra weak pointer to scene to allow for cleanup in case the world is destroyed before other components.
235     WeakPtr<Scene> scene_;
236     /// Debug renderer.
237     DebugRenderer* debugRenderer_;
238     /// Debug draw depth test mode.
239     bool debugDepthTest_;
240 
241     /// Automatic simulation update enabled flag.
242     bool updateEnabled_;
243     /// Whether is currently stepping the world. Used internally.
244     bool physicsStepping_;
245     /// Applying transforms.
246     bool applyingTransforms_;
247     /// Rigid bodies.
248     Vector<WeakPtr<RigidBody2D> > rigidBodies_;
249     /// Delayed (parented) world transform assignments.
250     HashMap<RigidBody2D*, DelayedWorldTransform2D> delayedWorldTransforms_;
251 
252     /// Contact info.
253     struct ContactInfo
254     {
255         /// Construct.
256         ContactInfo();
257         /// Construct.
258         ContactInfo(b2Contact* contract);
259         /// Write contact info to buffer.
260         const PODVector<unsigned char>& Serialize(VectorBuffer& buffer) const;
261 
262         /// Rigid body A.
263         SharedPtr<RigidBody2D> bodyA_;
264         /// Rigid body B.
265         SharedPtr<RigidBody2D> bodyB_;
266         /// Node A.
267         SharedPtr<Node> nodeA_;
268         /// Node B.
269         SharedPtr<Node> nodeB_;
270         /// Shape A.
271         SharedPtr<CollisionShape2D> shapeA_;
272         /// Shape B.
273         SharedPtr<CollisionShape2D> shapeB_;
274         /// Number of contact points.
275         int numPoints_;
276         /// Contact normal in world space.
277         Vector2 worldNormal_;
278         /// Contact positions in world space.
279         Vector2 worldPositions_[b2_maxManifoldPoints];
280         /// Contact overlap values.
281         float separations_[b2_maxManifoldPoints];
282     };
283     /// Begin contact infos.
284     Vector<ContactInfo> beginContactInfos_;
285     /// End contact infos.
286     Vector<ContactInfo> endContactInfos_;
287     /// Temporary buffer with contact data.
288     VectorBuffer contacts_;
289 };
290 
291 }
292