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