// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com) // This file is part of the "Nazara Engine - ChipmunkPhysics2D module" // For conditions of distribution and use, see copyright notice in Config.hpp #pragma once #ifndef NAZARA_CHIPMUNKPHYSICS2D_CHIPMUNKPHYSWORLD2D_HPP #define NAZARA_CHIPMUNKPHYSICS2D_CHIPMUNKPHYSWORLD2D_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct cpCollisionHandler; struct cpSpace; namespace Nz { class ChipmunkArbiter2D; class NAZARA_CHIPMUNKPHYSICS2D_API ChipmunkPhysWorld2D { friend ChipmunkRigidBody2D; using ContactEndCallback = std::function; using ContactPreSolveCallback = std::function; using ContactPostSolveCallback = std::function; using ContactStartCallback = std::function; using DebugDrawCircleCallback = std::function; using DebugDrawDotCallback = std::function; using DebugDrawPolygonCallback = std::function; using DebugDrawSegmentCallback = std::function; using DebugDrawTickSegmentCallback = std::function; using DebugDrawGetColorCallback = std::function; public: struct ContactCallbacks; struct DebugDrawOptions; struct NearestQueryResult; struct RaycastHit; ChipmunkPhysWorld2D(); ChipmunkPhysWorld2D(const ChipmunkPhysWorld2D&) = delete; ChipmunkPhysWorld2D(ChipmunkPhysWorld2D&&) = delete; ~ChipmunkPhysWorld2D(); void DebugDraw(const DebugDrawOptions& options, bool drawShapes = true, bool drawConstraints = true, bool drawCollisions = true) const; float GetDamping() const; Vector2f GetGravity() const; cpSpace* GetHandle() const; std::size_t GetIterationCount() const; std::size_t GetMaxStepCount() const; Time GetStepSize() const; bool NearestBodyQuery(const Vector2f& from, float maxDistance, UInt32 collisionGroup, UInt32 categoryMask, UInt32 collisionMask, ChipmunkRigidBody2D** nearestBody = nullptr); bool NearestBodyQuery(const Vector2f& from, float maxDistance, UInt32 collisionGroup, UInt32 categoryMask, UInt32 collisionMask, NearestQueryResult* result); void RaycastQuery(const Vector2f& from, const Vector2f& to, float radius, UInt32 collisionGroup, UInt32 categoryMask, UInt32 collisionMask, const FunctionRef& callback); bool RaycastQuery(const Vector2f& from, const Vector2f& to, float radius, UInt32 collisionGroup, UInt32 categoryMask, UInt32 collisionMask, std::vector* hitInfos); bool RaycastQueryFirst(const Vector2f& from, const Vector2f& to, float radius, UInt32 collisionGroup, UInt32 categoryMask, UInt32 collisionMask, RaycastHit* hitInfo = nullptr); void RegionQuery(const Rectf& boundingBox, UInt32 collisionGroup, UInt32 categoryMask, UInt32 collisionMask, const FunctionRef& callback); void RegionQuery(const Rectf& boundingBox, UInt32 collisionGroup, UInt32 categoryMask, UInt32 collisionMask, std::vector* bodies); void RegisterCallbacks(unsigned int collisionId, ContactCallbacks callbacks); void RegisterCallbacks(unsigned int collisionIdA, unsigned int collisionIdB, ContactCallbacks callbacks); void SetDamping(float dampingValue); void SetGravity(const Vector2f& gravity); void SetIterationCount(std::size_t iterationCount); void SetMaxStepCount(std::size_t maxStepCount); void SetSleepTime(Time sleepTime); void SetStepSize(Time stepSize); void Step(Time timestep); void UseSpatialHash(float cellSize, std::size_t entityCount); ChipmunkPhysWorld2D& operator=(const ChipmunkPhysWorld2D&) = delete; ChipmunkPhysWorld2D& operator=(ChipmunkPhysWorld2D&&) = delete; struct ContactCallbacks { ContactEndCallback endCallback = nullptr; ContactPostSolveCallback postSolveCallback = nullptr; ContactPreSolveCallback preSolveCallback = nullptr; ContactStartCallback startCallback = nullptr; void* userdata = nullptr; }; struct DebugDrawOptions { Color constraintColor = Color::Blue(); Color collisionPointColor = Color::Green(); Color shapeOutlineColor = Color::Red(); DebugDrawCircleCallback circleCallback; DebugDrawGetColorCallback colorCallback; DebugDrawDotCallback dotCallback; DebugDrawPolygonCallback polygonCallback; DebugDrawSegmentCallback segmentCallback; DebugDrawTickSegmentCallback thickSegmentCallback; void* userdata = nullptr; }; struct NearestQueryResult { ChipmunkRigidBody2D* nearestBody; Vector2f closestPoint; Vector2f fraction; float distance; }; struct RaycastHit { ChipmunkRigidBody2D* nearestBody; Vector2f hitPos; Vector2f hitNormal; float fraction; }; NazaraSignal(OnPhysWorld2DPreStep, const ChipmunkPhysWorld2D* /*physWorld*/, float /*invStepCount*/); NazaraSignal(OnPhysWorld2DPostStep, const ChipmunkPhysWorld2D* /*physWorld*/, float /*invStepCount*/); private: using PostStep = std::function; static constexpr std::size_t FreeBodyIdGrowRate = 256; void DeferBodyAction(ChipmunkRigidBody2D& rigidBody, PostStep&& func); void InitCallbacks(cpCollisionHandler* handler, ContactCallbacks callbacks); inline UInt32 RegisterBody(ChipmunkRigidBody2D& rigidBody); inline void UnregisterBody(UInt32 bodyIndex); inline void UpdateBodyPointer(ChipmunkRigidBody2D& rigidBody); std::size_t m_maxStepCount; std::unordered_map> m_callbacks; std::unordered_map> m_rigidBodyPostSteps; std::vector m_bodies; cpSpace* m_handle; Bitset m_freeBodyIndices; Time m_stepSize; Time m_timestepAccumulator; }; } #include #endif // NAZARA_CHIPMUNKPHYSICS2D_CHIPMUNKPHYSWORLD2D_HPP