PhysicsWorld2D.h 9.8 KB

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