Rename ChipmunkPhysics2D and JoltPhysics3D to Physics[2D|3D]

This commit is contained in:
Lynix
2024-02-09 20:59:53 +01:00
committed by Jérôme Leclercq
parent 139bed2b0a
commit e336c8a514
116 changed files with 3044 additions and 3042 deletions

View File

@@ -0,0 +1,212 @@
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Physics2D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_PHYSICS2D_COLLIDER2D_HPP
#define NAZARA_PHYSICS2D_COLLIDER2D_HPP
#include <NazaraUtils/Prerequisites.hpp>
#include <Nazara/Core/ObjectLibrary.hpp>
#include <Nazara/Math/Rect.hpp>
#include <Nazara/Math/Vector2.hpp>
#include <Nazara/Physics2D/Config.hpp>
#include <Nazara/Physics2D/Enums.hpp>
#include <NazaraUtils/FunctionRef.hpp>
#include <NazaraUtils/Signal.hpp>
#include <NazaraUtils/SparsePtr.hpp>
#include <vector>
struct cpBody;
struct cpShape;
namespace Nz
{
class RigidBody2D;
class NAZARA_PHYSICS2D_API Collider2D
{
friend RigidBody2D;
friend class CompoundCollider2D; //< See CompoundCollider2D::CreateShapes
public:
inline Collider2D();
Collider2D(const Collider2D&) = delete;
Collider2D(Collider2D&&) = delete;
virtual ~Collider2D();
virtual Vector2f ComputeCenterOfMass() const = 0;
virtual float ComputeMomentOfInertia(float mass) const = 0;
virtual void ForEachPolygon(const FunctionRef<void(const Vector2f* vertices, std::size_t vertexCount)>& callback) const;
inline UInt32 GetCategoryMask() const;
inline UInt32 GetCollisionGroup() const;
inline unsigned int GetCollisionId() const;
inline UInt32 GetCollisionMask() const;
inline float GetElasticity() const;
inline float GetFriction() const;
inline Vector2f GetSurfaceVelocity() const;
virtual ColliderType2D GetType() const = 0;
inline bool IsTrigger() const;
inline void SetCategoryMask(UInt32 categoryMask);
inline void SetCollisionGroup(UInt32 groupId);
inline void SetCollisionId(unsigned int typeId);
inline void SetCollisionMask(UInt32 mask);
inline void SetElasticity(float elasticity);
inline void SetFriction(float friction);
inline void SetSurfaceVelocity(const Vector2f& surfaceVelocity);
inline void SetTrigger(bool trigger);
Collider2D& operator=(const Collider2D&) = delete;
Collider2D& operator=(Collider2D&&) = delete;
// Signals:
NazaraSignal(OnColliderRelease, const Collider2D* /*collider*/);
protected:
virtual std::size_t CreateShapes(cpBody* body, std::vector<cpShape*>* shapes) const = 0;
UInt32 m_categoryMask;
UInt32 m_collisionGroup;
UInt32 m_collisionMask;
Vector2f m_surfaceVelocity;
bool m_trigger;
float m_elasticity;
float m_friction;
unsigned int m_collisionId;
private:
virtual std::size_t GenerateShapes(cpBody* body, std::vector<cpShape*>* shapes) const;
};
class NAZARA_PHYSICS2D_API BoxCollider2D : public Collider2D
{
public:
BoxCollider2D(const Vector2f& size, float radius = 0.f);
BoxCollider2D(const Rectf& rect, float radius = 0.f);
Nz::Vector2f ComputeCenterOfMass() const override;
float ComputeMomentOfInertia(float mass) const override;
inline float GetRadius() const;
inline const Rectf& GetRect() const;
inline Vector2f GetSize() const;
ColliderType2D GetType() const override;
private:
std::size_t CreateShapes(cpBody* body, std::vector<cpShape*>* shapes) const override;
Rectf m_rect;
float m_radius;
};
class NAZARA_PHYSICS2D_API CircleCollider2D : public Collider2D
{
public:
CircleCollider2D(float radius, const Vector2f& offset = Vector2f::Zero());
Nz::Vector2f ComputeCenterOfMass() const override;
float ComputeMomentOfInertia(float mass) const override;
inline const Vector2f& GetOffset() const;
inline float GetRadius() const;
ColliderType2D GetType() const override;
private:
std::size_t CreateShapes(cpBody* body, std::vector<cpShape*>* shapes) const override;
Vector2f m_offset;
float m_radius;
};
class NAZARA_PHYSICS2D_API CompoundCollider2D : public Collider2D
{
public:
CompoundCollider2D(std::vector<std::shared_ptr<Collider2D>> geoms);
Nz::Vector2f ComputeCenterOfMass() const override;
float ComputeMomentOfInertia(float mass) const override;
inline bool DoesOverrideCollisionProperties() const;
inline const std::vector<std::shared_ptr<Collider2D>>& GetGeoms() const;
ColliderType2D GetType() const override;
inline void OverridesCollisionProperties(bool shouldOverride);
private:
std::size_t CreateShapes(cpBody* body, std::vector<cpShape*>* shapes) const override;
std::size_t GenerateShapes(cpBody* body, std::vector<cpShape*>* shapes) const override;
std::vector<std::shared_ptr<Collider2D>> m_geoms;
bool m_doesOverrideCollisionProperties;
};
class NAZARA_PHYSICS2D_API ConvexCollider2D : public Collider2D
{
public:
ConvexCollider2D(SparsePtr<const Vector2f> vertices, std::size_t vertexCount, float radius = 0.f);
Nz::Vector2f ComputeCenterOfMass() const override;
float ComputeMomentOfInertia(float mass) const override;
ColliderType2D GetType() const override;
inline const std::vector<Vector2d>& GetVertices() const;
private:
std::size_t CreateShapes(cpBody* body, std::vector<cpShape*>* shapes) const override;
std::vector<Vector2d> m_vertices;
float m_radius;
};
class NAZARA_PHYSICS2D_API NullCollider2D : public Collider2D
{
public:
NullCollider2D() = default;
Nz::Vector2f ComputeCenterOfMass() const override;
float ComputeMomentOfInertia(float mass) const override;
ColliderType2D GetType() const override;
private:
std::size_t CreateShapes(cpBody* body, std::vector<cpShape*>* shapes) const override;
};
class NAZARA_PHYSICS2D_API SegmentCollider2D : public Collider2D
{
public:
inline SegmentCollider2D(const Vector2f& first, const Vector2f& second, float thickness = 1.f);
inline SegmentCollider2D(const Vector2f& first, const Vector2f& firstNeighbor, const Vector2f& second, const Vector2f& secondNeighbor, float thickness = 1.f);
Nz::Vector2f ComputeCenterOfMass() const override;
float ComputeMomentOfInertia(float mass) const override;
inline const Vector2f& GetFirstPoint() const;
inline const Vector2f& GetFirstPointNeighbor() const;
inline float GetLength() const;
inline const Vector2f& GetSecondPoint() const;
inline const Vector2f& GetSecondPointNeighbor() const;
inline float GetThickness() const;
ColliderType2D GetType() const override;
private:
std::size_t CreateShapes(cpBody* body, std::vector<cpShape*>* shapes) const override;
Vector2f m_first;
Vector2f m_firstNeighbor;
Vector2f m_second;
Vector2f m_secondNeighbor;
float m_thickness;
};
}
#include <Nazara/Physics2D/Collider2D.inl>
#endif // NAZARA_PHYSICS2D_COLLIDER2D_HPP

View File

@@ -0,0 +1,196 @@
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Physics2D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <memory>
#include <Nazara/Physics2D/Debug.hpp>
namespace Nz
{
inline Collider2D::Collider2D() :
m_categoryMask(0xFFFFFFFF),
m_collisionGroup(0),
m_collisionMask(0xFFFFFFFF),
m_surfaceVelocity(Vector2f::Zero()),
m_trigger(false),
m_elasticity(0.f),
m_friction(0.f),
m_collisionId(0)
{
}
inline UInt32 Collider2D::GetCategoryMask() const
{
return m_categoryMask;
}
inline UInt32 Collider2D::GetCollisionGroup() const
{
return m_collisionGroup;
}
inline unsigned int Collider2D::GetCollisionId() const
{
return m_collisionId;
}
inline UInt32 Collider2D::GetCollisionMask() const
{
return m_collisionMask;
}
inline float Collider2D::GetElasticity() const
{
return m_elasticity;
}
inline float Collider2D::GetFriction() const
{
return m_friction;
}
inline Vector2f Collider2D::GetSurfaceVelocity() const
{
return m_surfaceVelocity;
}
inline bool Collider2D::IsTrigger() const
{
return m_trigger;
}
inline void Collider2D::SetCategoryMask(UInt32 categoryMask)
{
m_categoryMask = categoryMask;
}
inline void Collider2D::SetCollisionGroup(UInt32 groupId)
{
m_collisionGroup = groupId;
}
inline void Collider2D::SetCollisionId(unsigned int typeId)
{
m_collisionId = typeId;
}
inline void Collider2D::SetCollisionMask(UInt32 mask)
{
m_collisionMask = mask;
}
inline void Collider2D::SetElasticity(float elasticity)
{
m_elasticity = elasticity;
}
inline void Collider2D::SetFriction(float friction)
{
m_friction = friction;
}
inline void Collider2D::SetSurfaceVelocity(const Vector2f& surfaceVelocity)
{
m_surfaceVelocity = surfaceVelocity;
}
inline void Collider2D::SetTrigger(bool trigger)
{
m_trigger = trigger;
}
inline float BoxCollider2D::GetRadius() const
{
return m_radius;
}
inline const Rectf& BoxCollider2D::GetRect() const
{
return m_rect;
}
inline Vector2f BoxCollider2D::GetSize() const
{
return m_rect.GetLengths();
}
inline const Vector2f& CircleCollider2D::GetOffset() const
{
return m_offset;
}
inline float CircleCollider2D::GetRadius() const
{
return m_radius;
}
inline bool Nz::CompoundCollider2D::DoesOverrideCollisionProperties() const
{
return m_doesOverrideCollisionProperties;
}
inline const std::vector<std::shared_ptr<Collider2D>>& CompoundCollider2D::GetGeoms() const
{
return m_geoms;
}
inline void Nz::CompoundCollider2D::OverridesCollisionProperties(bool shouldOverride)
{
m_doesOverrideCollisionProperties = shouldOverride;
}
inline const std::vector<Vector2d>& ConvexCollider2D::GetVertices() const
{
return m_vertices;
}
SegmentCollider2D::SegmentCollider2D(const Vector2f& first, const Vector2f& second, float thickness) :
SegmentCollider2D(first, first, second, second, thickness)
{
}
inline SegmentCollider2D::SegmentCollider2D(const Vector2f& first, const Vector2f& firstNeighbor, const Vector2f& second, const Vector2f& secondNeighbor, float thickness) :
m_first(first),
m_firstNeighbor(firstNeighbor),
m_second(second),
m_secondNeighbor(secondNeighbor),
m_thickness(thickness)
{
}
inline const Vector2f& SegmentCollider2D::GetFirstPoint() const
{
return m_first;
}
inline const Vector2f& SegmentCollider2D::GetFirstPointNeighbor() const
{
return m_firstNeighbor;
}
inline float SegmentCollider2D::GetLength() const
{
return m_first.Distance(m_second);
}
inline const Vector2f& SegmentCollider2D::GetSecondPoint() const
{
return m_second;
}
inline const Vector2f& SegmentCollider2D::GetSecondPointNeighbor() const
{
return m_secondNeighbor;
}
inline float SegmentCollider2D::GetThickness() const
{
return m_thickness;
}
}
#include <Nazara/Physics2D/DebugOff.hpp>

View File

@@ -0,0 +1,34 @@
// this file was automatically generated and should not be edited
/*
Nazara Engine - Physics2D module
Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
#ifndef NAZARA_PHYSICS2D_COMPONENTS_HPP
#define NAZARA_PHYSICS2D_COMPONENTS_HPP
#include <Nazara/Physics2D/Components/RigidBody2DComponent.hpp>
#endif // NAZARA_PHYSICS2D_COMPONENTS_HPP

View File

@@ -0,0 +1,40 @@
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Physics2D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_PHYSICS2D_COMPONENTS_RIGIDBODY2DCOMPONENT_HPP
#define NAZARA_PHYSICS2D_COMPONENTS_RIGIDBODY2DCOMPONENT_HPP
#include <NazaraUtils/Prerequisites.hpp>
#include <Nazara/Physics2D/RigidBody2D.hpp>
#include <variant>
namespace Nz
{
class NAZARA_PHYSICS2D_API RigidBody2DComponent : public RigidBody2D
{
friend class Physics2DSystem;
public:
inline RigidBody2DComponent(const RigidBody2D::DynamicSettings& settings);
inline RigidBody2DComponent(const RigidBody2D::StaticSettings& settings);
RigidBody2DComponent(const RigidBody2DComponent&) = delete;
RigidBody2DComponent(RigidBody2DComponent&&) noexcept = default;
~RigidBody2DComponent() = default;
RigidBody2DComponent& operator=(const RigidBody2DComponent&) = delete;
RigidBody2DComponent& operator=(RigidBody2DComponent&&) noexcept = default;
private:
inline void Construct(PhysWorld2D& world);
using Setting = std::variant<RigidBody2D::DynamicSettings, RigidBody2D::StaticSettings>;
std::unique_ptr<Setting> m_settings;
};
}
#include <Nazara/Physics2D/Components/RigidBody2DComponent.inl>
#endif // NAZARA_PHYSICS2D_COMPONENTS_RIGIDBODY2DCOMPONENT_HPP

View File

@@ -0,0 +1,30 @@
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Physics2D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Physics2D/Debug.hpp>
namespace Nz
{
inline RigidBody2DComponent::RigidBody2DComponent(const RigidBody2D::DynamicSettings& settings)
{
m_settings = std::make_unique<Setting>(settings);
}
inline RigidBody2DComponent::RigidBody2DComponent(const RigidBody2D::StaticSettings& settings)
{
m_settings = std::make_unique<Setting>(settings);
}
inline void RigidBody2DComponent::Construct(PhysWorld2D& world)
{
assert(m_settings);
std::visit([&](auto&& arg)
{
Create(world, arg);
}, *m_settings);
m_settings.reset();
}
}
#include <Nazara/Physics2D/DebugOff.hpp>

View File

@@ -0,0 +1,48 @@
/*
Nazara Engine - Physics2D module
Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
#ifndef NAZARA_PHYSICS2D_CONFIG_HPP
#define NAZARA_PHYSICS2D_CONFIG_HPP
/// Chaque modification d'un paramètre du module nécessite une recompilation de celui-ci
// Active les tests de sécurité basés sur le code (Conseillé pour le développement)
#define NAZARA_PHYSICS2D_SAFE 1
/// Vérification des valeurs et types de certaines constantes
#include <Nazara/Physics2D/ConfigCheck.hpp>
#if defined(NAZARA_STATIC)
#define NAZARA_PHYSICS2D_API
#else
#ifdef NAZARA_PHYSICS2D_BUILD
#define NAZARA_PHYSICS2D_API NAZARA_EXPORT
#else
#define NAZARA_PHYSICS2D_API NAZARA_IMPORT
#endif
#endif
#endif // NAZARA_PHYSICS2D_CONFIG_HPP

View File

@@ -0,0 +1,19 @@
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Physics2D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_PHYSICS2D_CONFIGCHECK_HPP
#define NAZARA_PHYSICS2D_CONFIGCHECK_HPP
/// This file is used to check the constant values defined in Config.hpp
#include <type_traits>
#define NazaraCheckTypeAndVal(name, type, op, val, err) static_assert(std::is_ ##type <decltype(name)>::value && name op val, #type err)
// config checks
#undef NazaraCheckTypeAndVal
#endif // NAZARA_PHYSICS2D_CONFIGCHECK_HPP

View File

@@ -0,0 +1,5 @@
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Physics2D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
// no header guards

View File

@@ -0,0 +1,5 @@
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Physics2D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
// no header guards

View File

@@ -0,0 +1,25 @@
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Physics2D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_PHYSICS2D_ENUMS_HPP
#define NAZARA_PHYSICS2D_ENUMS_HPP
namespace Nz
{
enum class ColliderType2D
{
Box,
Compound,
Convex,
Circle,
Null,
Segment,
Max = Segment
};
}
#endif // NAZARA_PHYSICS2D_ENUMS_HPP

View File

@@ -0,0 +1,61 @@
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Physics2D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_PHYSICS2D_PHYSARBITER2D_HPP
#define NAZARA_PHYSICS2D_PHYSARBITER2D_HPP
#include <NazaraUtils/Prerequisites.hpp>
#include <Nazara/Math/Vector2.hpp>
#include <Nazara/Physics2D/Config.hpp>
#include <NazaraUtils/MovablePtr.hpp>
struct cpArbiter;
namespace Nz
{
class RigidBody2D;
class NAZARA_PHYSICS2D_API PhysArbiter2D
{
public:
inline PhysArbiter2D(cpArbiter* arbiter);
PhysArbiter2D(const PhysArbiter2D&) = delete;
PhysArbiter2D(PhysArbiter2D&&) = default;
~PhysArbiter2D() = default;
float ComputeTotalKinematicEnergy() const;
Nz::Vector2f ComputeTotalImpulse() const;
std::pair<RigidBody2D*, RigidBody2D*> GetBodies() const;
std::size_t GetContactCount() const;
float GetContactDepth(std::size_t i) const;
Vector2f GetContactPointA(std::size_t i) const;
Vector2f GetContactPointB(std::size_t i) const;
float GetElasticity() const;
float GetFriction() const;
Vector2f GetNormal() const;
Vector2f GetSurfaceVelocity() const;
bool IsFirstContact() const;
bool IsRemoval() const;
void SetElasticity(float elasticity);
void SetFriction(float friction);
void SetSurfaceVelocity(const Vector2f& surfaceVelocity);
PhysArbiter2D& operator=(const PhysArbiter2D&) = delete;
PhysArbiter2D& operator=(PhysArbiter2D&&) = default;
private:
MovablePtr<cpArbiter> m_arbiter;
};
}
#include <Nazara/Physics2D/PhysArbiter2D.inl>
#endif // NAZARA_PHYSICS2D_PHYSARBITER2D_HPP

View File

@@ -0,0 +1,16 @@
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Physics2D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <memory>
#include <Nazara/Physics2D/Debug.hpp>
namespace Nz
{
inline PhysArbiter2D::PhysArbiter2D(cpArbiter* arbiter) :
m_arbiter(arbiter)
{
}
}
#include <Nazara/Physics2D/DebugOff.hpp>

View File

@@ -0,0 +1,238 @@
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Physics2D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_PHYSICS2D_PHYSCONSTRAINT2D_HPP
#define NAZARA_PHYSICS2D_PHYSCONSTRAINT2D_HPP
#include <NazaraUtils/Prerequisites.hpp>
#include <Nazara/Core/HandledObject.hpp>
#include <Nazara/Core/ObjectHandle.hpp>
#include <Nazara/Math/Angle.hpp>
#include <Nazara/Physics2D/Config.hpp>
#include <Nazara/Physics2D/PhysWorld2D.hpp>
#include <Nazara/Physics2D/RigidBody2D.hpp>
#include <NazaraUtils/MovablePtr.hpp>
struct cpConstraint;
namespace Nz
{
class PhysConstraint2D;
using PhysConstraint2DHandle = ObjectHandle<PhysConstraint2D>;
class NAZARA_PHYSICS2D_API PhysConstraint2D : public HandledObject<PhysConstraint2D>
{
public:
PhysConstraint2D(const PhysConstraint2D&) = delete;
PhysConstraint2D(PhysConstraint2D&& constraint) noexcept;
virtual ~PhysConstraint2D();
void EnableBodyCollision(bool enable);
RigidBody2D& GetBodyA();
const RigidBody2D& GetBodyA() const;
RigidBody2D& GetBodyB();
const RigidBody2D& GetBodyB() const;
float GetErrorBias() const;
float GetLastImpulse() const;
float GetMaxBias() const;
float GetMaxForce() const;
PhysWorld2D& GetWorld();
const PhysWorld2D& GetWorld() const;
bool IsBodyCollisionEnabled() const;
bool IsSingleBody() const;
void SetErrorBias(float bias);
void SetMaxBias(float bias);
void SetMaxForce(float force);
PhysConstraint2D& operator=(const PhysConstraint2D&) = delete;
PhysConstraint2D& operator=(PhysConstraint2D&& constraint) noexcept;
protected:
PhysConstraint2D(PhysWorld2D* world, cpConstraint* constraint);
MovablePtr<cpConstraint> m_constraint;
private:
void Destroy();
};
class PhysDampedSpringConstraint2D;
using PhysDampedSpringConstraint2DHandle = ObjectHandle<PhysDampedSpringConstraint2D>;
class NAZARA_PHYSICS2D_API PhysDampedSpringConstraint2D : public PhysConstraint2D
{
public:
PhysDampedSpringConstraint2D(RigidBody2D& first, RigidBody2D& second, const Vector2f& firstAnchor, const Vector2f& secondAnchor, float restLength, float stiffness, float damping);
~PhysDampedSpringConstraint2D() = default;
float GetDamping() const;
Vector2f GetFirstAnchor() const;
float GetRestLength() const;
Vector2f GetSecondAnchor() const;
float GetStiffness() const;
void SetDamping(float newDamping);
void SetFirstAnchor(const Vector2f& firstAnchor);
void SetRestLength(float newLength);
void SetSecondAnchor(const Vector2f& firstAnchor);
void SetStiffness(float newStiffness);
};
class PhysDampedRotarySpringConstraint2D;
using PhysDampedRotarySpringConstraint2DHandle = ObjectHandle<PhysDampedRotarySpringConstraint2D>;
class NAZARA_PHYSICS2D_API PhysDampedRotarySpringConstraint2D : public PhysConstraint2D
{
public:
PhysDampedRotarySpringConstraint2D(RigidBody2D& first, RigidBody2D& second, const RadianAnglef& restAngle, float stiffness, float damping);
~PhysDampedRotarySpringConstraint2D() = default;
float GetDamping() const;
RadianAnglef GetRestAngle() const;
float GetStiffness() const;
void SetDamping(float newDamping);
void SetRestAngle(const RadianAnglef& newAngle);
void SetStiffness(float newStiffness);
};
class PhysGearConstraint2D;
using PhysGearConstraint2DHandle = ObjectHandle<PhysGearConstraint2D>;
class NAZARA_PHYSICS2D_API PhysGearConstraint2D : public PhysConstraint2D
{
public:
PhysGearConstraint2D(RigidBody2D& first, RigidBody2D& second, float phase, float ratio);
~PhysGearConstraint2D() = default;
float GetPhase() const;
float GetRatio() const;
void SetPhase(float phase);
void SetRatio(float ratio);
};
class PhysMotorConstraint2D;
using PhysMotorConstraint2DHandle = ObjectHandle<PhysMotorConstraint2D>;
class NAZARA_PHYSICS2D_API PhysMotorConstraint2D : public PhysConstraint2D
{
public:
PhysMotorConstraint2D(RigidBody2D& first, RigidBody2D& second, float rate);
~PhysMotorConstraint2D() = default;
float GetRate() const;
void SetRate(float rate);
};
class PhysPinConstraint2D;
using PhysPinConstraint2DHandle = ObjectHandle<PhysPinConstraint2D>;
class NAZARA_PHYSICS2D_API PhysPinConstraint2D : public PhysConstraint2D
{
public:
PhysPinConstraint2D(RigidBody2D& body, const Vector2f& anchor);
PhysPinConstraint2D(RigidBody2D& first, RigidBody2D& second, const Vector2f& firstAnchor, const Vector2f& secondAnchor);
~PhysPinConstraint2D() = default;
float GetDistance() const;
Vector2f GetFirstAnchor() const;
Vector2f GetSecondAnchor() const;
void SetDistance(float newDistance);
void SetFirstAnchor(const Vector2f& firstAnchor);
void SetSecondAnchor(const Vector2f& firstAnchor);
};
class PhysPivotConstraint2D;
using PhysPivotConstraint2DHandle = ObjectHandle<PhysPivotConstraint2D>;
class NAZARA_PHYSICS2D_API PhysPivotConstraint2D : public PhysConstraint2D
{
public:
PhysPivotConstraint2D(RigidBody2D& body, const Vector2f& anchor);
PhysPivotConstraint2D(RigidBody2D& first, RigidBody2D& second, const Vector2f& anchor);
PhysPivotConstraint2D(RigidBody2D& first, RigidBody2D& second, const Vector2f& firstAnchor, const Vector2f& secondAnchor);
~PhysPivotConstraint2D() = default;
Vector2f GetFirstAnchor() const;
Vector2f GetSecondAnchor() const;
void SetFirstAnchor(const Vector2f& firstAnchor);
void SetSecondAnchor(const Vector2f& firstAnchor);
};
class PhysRatchetConstraint2D;
using PhysRatchetConstraint2DHandle = ObjectHandle<PhysRatchetConstraint2D>;
class NAZARA_PHYSICS2D_API PhysRatchetConstraint2D : public PhysConstraint2D
{
public:
PhysRatchetConstraint2D(RigidBody2D& first, RigidBody2D& second, float phase, float ratchet);
~PhysRatchetConstraint2D() = default;
RadianAnglef GetAngle() const;
float GetPhase() const;
float GetRatchet() const;
void SetAngle(const RadianAnglef& angle);
void SetPhase(float phase);
void SetRatchet(float ratchet);
};
class PhysRotaryLimitConstraint2D;
using PhysRotaryLimitConstraint2DHandle = ObjectHandle<PhysRotaryLimitConstraint2D>;
class NAZARA_PHYSICS2D_API PhysRotaryLimitConstraint2D : public PhysConstraint2D
{
public:
PhysRotaryLimitConstraint2D(RigidBody2D& first, RigidBody2D& second, const RadianAnglef& minAngle, const RadianAnglef& maxAngle);
~PhysRotaryLimitConstraint2D() = default;
RadianAnglef GetMaxAngle() const;
RadianAnglef GetMinAngle() const;
void SetMaxAngle(const RadianAnglef& maxAngle);
void SetMinAngle(const RadianAnglef& minAngle);
};
class PhysSlideConstraint2D;
using PhysSlideConstraint2DHandle = ObjectHandle<PhysSlideConstraint2D>;
class NAZARA_PHYSICS2D_API PhysSlideConstraint2D : public PhysConstraint2D
{
public:
PhysSlideConstraint2D(RigidBody2D& first, RigidBody2D& second, const Vector2f& firstAnchor, const Vector2f& secondAnchor, float min, float max);
~PhysSlideConstraint2D() = default;
Vector2f GetFirstAnchor() const;
float GetMaxDistance() const;
float GetMinDistance() const;
Vector2f GetSecondAnchor() const;
void SetFirstAnchor(const Vector2f& firstAnchor);
void SetMaxDistance(float newMaxDistance);
void SetMinDistance(float newMinDistance);
void SetSecondAnchor(const Vector2f& firstAnchor);
};
}
#include <Nazara/Physics2D/PhysConstraint2D.inl>
#endif // NAZARA_PHYSICS2D_PHYSCONSTRAINT2D_HPP

View File

@@ -0,0 +1,12 @@
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Physics2D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <memory>
#include <Nazara/Physics2D/Debug.hpp>
namespace Nz
{
}
#include <Nazara/Physics2D/DebugOff.hpp>

View File

@@ -0,0 +1,163 @@
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Physics2D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_PHYSICS2D_PHYSWORLD2D_HPP
#define NAZARA_PHYSICS2D_PHYSWORLD2D_HPP
#include <NazaraUtils/Prerequisites.hpp>
#include <Nazara/Core/Color.hpp>
#include <Nazara/Core/Time.hpp>
#include <Nazara/Math/Angle.hpp>
#include <Nazara/Math/Vector2.hpp>
#include <Nazara/Physics2D/Config.hpp>
#include <Nazara/Physics2D/RigidBody2D.hpp>
#include <NazaraUtils/Bitset.hpp>
#include <NazaraUtils/FunctionRef.hpp>
#include <NazaraUtils/Signal.hpp>
#include <functional>
#include <memory>
#include <unordered_map>
#include <vector>
struct cpCollisionHandler;
struct cpSpace;
namespace Nz
{
class PhysArbiter2D;
class NAZARA_PHYSICS2D_API PhysWorld2D
{
friend RigidBody2D;
using ContactEndCallback = std::function<void(PhysWorld2D& world, PhysArbiter2D& arbiter, RigidBody2D& bodyA, RigidBody2D& bodyB, void* userdata)>;
using ContactPreSolveCallback = std::function<bool(PhysWorld2D& world, PhysArbiter2D& arbiter, RigidBody2D& bodyA, RigidBody2D& bodyB, void* userdata)>;
using ContactPostSolveCallback = std::function<void(PhysWorld2D& world, PhysArbiter2D& arbiter, RigidBody2D& bodyA, RigidBody2D& bodyB, void* userdata)>;
using ContactStartCallback = std::function<bool(PhysWorld2D& world, PhysArbiter2D& arbiter, RigidBody2D& bodyA, RigidBody2D& bodyB, void* userdata)>;
using DebugDrawCircleCallback = std::function<void(const Vector2f& origin, const RadianAnglef& rotation, float radius, const Color& outlineColor, const Color& fillColor, void* userdata)>;
using DebugDrawDotCallback = std::function<void(const Vector2f& origin, float radius, const Color& color, void* userdata)>;
using DebugDrawPolygonCallback = std::function<void(const Vector2f* vertices, std::size_t vertexCount, float radius, const Color& outlineColor, const Color& fillColor, void* userdata)>;
using DebugDrawSegmentCallback = std::function<void(const Vector2f& first, const Vector2f& second, const Color& color, void* userdata)>;
using DebugDrawTickSegmentCallback = std::function<void(const Vector2f& first, const Vector2f& second, float thickness, const Color& outlineColor, const Color& fillColor, void* userdata)>;
using DebugDrawGetColorCallback = std::function<Color(RigidBody2D& body, std::size_t shapeIndex, void* userdata)>;
public:
struct ContactCallbacks;
struct DebugDrawOptions;
struct NearestQueryResult;
struct RaycastHit;
PhysWorld2D();
PhysWorld2D(const PhysWorld2D&) = delete;
PhysWorld2D(PhysWorld2D&&) = delete;
~PhysWorld2D();
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, RigidBody2D** 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<void(const RaycastHit&)>& callback);
bool RaycastQuery(const Vector2f& from, const Vector2f& to, float radius, UInt32 collisionGroup, UInt32 categoryMask, UInt32 collisionMask, std::vector<RaycastHit>* 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<void(RigidBody2D*)>& callback);
void RegionQuery(const Rectf& boundingBox, UInt32 collisionGroup, UInt32 categoryMask, UInt32 collisionMask, std::vector<RigidBody2D*>* 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);
PhysWorld2D& operator=(const PhysWorld2D&) = delete;
PhysWorld2D& operator=(PhysWorld2D&&) = 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
{
RigidBody2D* nearestBody;
Vector2f closestPoint;
Vector2f fraction;
float distance;
};
struct RaycastHit
{
RigidBody2D* nearestBody;
Vector2f hitPos;
Vector2f hitNormal;
float fraction;
};
NazaraSignal(OnPhysWorld2DPreStep, const PhysWorld2D* /*physWorld*/, float /*invStepCount*/);
NazaraSignal(OnPhysWorld2DPostStep, const PhysWorld2D* /*physWorld*/, float /*invStepCount*/);
private:
using PostStep = std::function<void(RigidBody2D* body)>;
static constexpr std::size_t FreeBodyIdGrowRate = 256;
void DeferBodyAction(RigidBody2D& rigidBody, PostStep&& func);
void InitCallbacks(cpCollisionHandler* handler, ContactCallbacks callbacks);
inline UInt32 RegisterBody(RigidBody2D& rigidBody);
inline void UnregisterBody(UInt32 bodyIndex);
inline void UpdateBodyPointer(RigidBody2D& rigidBody);
std::size_t m_maxStepCount;
std::unordered_map<cpCollisionHandler*, std::unique_ptr<ContactCallbacks>> m_callbacks;
std::unordered_map<UInt32, std::vector<PostStep>> m_rigidBodyPostSteps;
std::vector<RigidBody2D*> m_bodies;
cpSpace* m_handle;
Bitset<UInt64> m_freeBodyIndices;
Time m_stepSize;
Time m_timestepAccumulator;
};
}
#include <Nazara/Physics2D/PhysWorld2D.inl>
#endif // NAZARA_PHYSICS2D_PHYSWORLD2D_HPP

View File

@@ -0,0 +1,47 @@
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Physics2D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <cassert>
#include <Nazara/Physics2D/Debug.hpp>
namespace Nz
{
inline UInt32 PhysWorld2D::RegisterBody(RigidBody2D& rigidBody)
{
std::size_t bodyIndex = m_freeBodyIndices.FindFirst();
if (bodyIndex == m_freeBodyIndices.npos)
{
bodyIndex = m_freeBodyIndices.GetSize();
m_freeBodyIndices.Resize(bodyIndex + FreeBodyIdGrowRate, true);
m_bodies.resize(m_freeBodyIndices.GetSize());
}
assert(m_freeBodyIndices.Test(bodyIndex));
m_freeBodyIndices.Set(bodyIndex, false);
assert(!m_bodies[bodyIndex]);
m_bodies[bodyIndex] = &rigidBody;
return SafeCast<UInt32>(bodyIndex);
}
inline void PhysWorld2D::UnregisterBody(UInt32 bodyIndex)
{
assert(!m_freeBodyIndices.Test(bodyIndex));
m_freeBodyIndices.Set(bodyIndex, true);
assert(m_bodies[bodyIndex]);
m_bodies[bodyIndex] = nullptr;
m_rigidBodyPostSteps.erase(bodyIndex);
}
inline void PhysWorld2D::UpdateBodyPointer(RigidBody2D& rigidBody)
{
UInt32 bodyIndex = rigidBody.GetBodyIndex();
assert(m_bodies[bodyIndex]);
m_bodies[bodyIndex] = &rigidBody;
}
}
#include <Nazara/Physics2D/DebugOff.hpp>

View File

@@ -0,0 +1,33 @@
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Physics2D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_PHYSICS2D_HPP
#define NAZARA_PHYSICS2D_HPP
#include <NazaraUtils/Prerequisites.hpp>
#include <Nazara/Core/Core.hpp>
#include <Nazara/Physics2D/Config.hpp>
namespace Nz
{
class NAZARA_PHYSICS2D_API Physics2D : public ModuleBase<Physics2D>
{
friend ModuleBase;
public:
using Dependencies = TypeList<Core>;
struct Config {};
Physics2D(Config /*config*/);
~Physics2D() = default;
private:
static Physics2D* s_instance;
};
}
#endif // NAZARA_PHYSICS2D_HPP

View File

@@ -0,0 +1,180 @@
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Physics2D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_PHYSICS2D_RIGIDBODY2D_HPP
#define NAZARA_PHYSICS2D_RIGIDBODY2D_HPP
#include <NazaraUtils/Prerequisites.hpp>
#include <Nazara/Core/Enums.hpp>
#include <Nazara/Math/Angle.hpp>
#include <Nazara/Math/Rect.hpp>
#include <Nazara/Physics2D/Collider2D.hpp>
#include <Nazara/Physics2D/Config.hpp>
#include <NazaraUtils/Signal.hpp>
#include <functional>
#include <limits>
struct cpBody;
namespace Nz
{
class PhysArbiter2D;
class PhysWorld2D;
class NAZARA_PHYSICS2D_API RigidBody2D
{
public:
struct DynamicSettings;
struct StaticSettings;
using VelocityFunc = std::function<void(RigidBody2D& body2D, const Vector2f& gravity, float damping, float deltaTime)>;
inline RigidBody2D(PhysWorld2D& world, const DynamicSettings& settings);
inline RigidBody2D(PhysWorld2D& world, const StaticSettings& settings);
RigidBody2D(const RigidBody2D& object);
RigidBody2D(RigidBody2D&& object) noexcept;
inline ~RigidBody2D();
inline void AddForce(const Vector2f& force, CoordSys coordSys = CoordSys::Global);
void AddForce(const Vector2f& force, const Vector2f& point, CoordSys coordSys = CoordSys::Global);
inline void AddImpulse(const Vector2f& impulse, CoordSys coordSys = CoordSys::Global);
void AddImpulse(const Vector2f& impulse, const Vector2f& point, CoordSys coordSys = CoordSys::Global);
void AddTorque(const RadianAnglef& torque);
bool ClosestPointQuery(const Vector2f& position, Vector2f* closestPoint = nullptr, float* closestDistance = nullptr) const;
void EnableSimulation(bool simulation);
void ForEachArbiter(const FunctionRef<void(PhysArbiter2D& /*arbiter*/)>& callback);
void ForceSleep();
Rectf GetAABB() const;
RadianAnglef GetAngularVelocity() const;
inline UInt32 GetBodyIndex() const;
float GetElasticity(std::size_t shapeIndex = 0) const;
float GetFriction(std::size_t shapeIndex = 0) const;
inline const std::shared_ptr<Collider2D>& GetGeom() const;
inline cpBody* GetHandle() const;
inline float GetMass() const;
Vector2f GetMassCenter(CoordSys coordSys = CoordSys::Local) const;
float GetMomentOfInertia() const;
Vector2f GetPosition() const;
inline const Vector2f& GetPositionOffset() const;
RadianAnglef GetRotation() const;
inline std::size_t GetShapeCount() const;
inline std::size_t GetShapeIndex(cpShape* shape) const;
Vector2f GetSurfaceVelocity(std::size_t shapeIndex = 0) const;
Vector2f GetVelocity() const;
inline const VelocityFunc& GetVelocityFunction() const;
inline PhysWorld2D* GetWorld() const;
inline bool IsKinematic() const;
inline bool IsSimulationEnabled() const;
bool IsSleeping() const;
inline bool IsStatic() const;
void ResetVelocityFunction();
void SetAngularVelocity(const RadianAnglef& angularVelocity);
void SetElasticity(float elasticity);
void SetElasticity(std::size_t shapeIndex, float elasticity);
void SetFriction(float friction);
void SetFriction(std::size_t shapeIndex, float friction);
void SetGeom(std::shared_ptr<Collider2D> geom, bool recomputeMoment = true, bool recomputeMassCenter = true);
void SetMass(float mass, bool recomputeMoment = true);
void SetMassCenter(const Vector2f& center, CoordSys coordSys = CoordSys::Local);
void SetMomentOfInertia(float moment);
void SetPosition(const Vector2f& position);
void SetPositionOffset(const Vector2f& offset);
void SetRotation(const RadianAnglef& rotation);
void SetSurfaceVelocity(const Vector2f& surfaceVelocity);
void SetSurfaceVelocity(std::size_t shapeIndex, const Vector2f& surfaceVelocity);
void SetStatic(bool setStaticBody = true);
void SetVelocity(const Vector2f& velocity);
void SetVelocityFunction(VelocityFunc velocityFunc);
void TeleportTo(const Vector2f& position, const RadianAnglef& rotation);
RadianAnglef ToLocal(const RadianAnglef& worldRotation);
Vector2f ToLocal(const Vector2f& worldPosition);
RadianAnglef ToWorld(const RadianAnglef& localRotation);
Vector2f ToWorld(const Vector2f& localPosition);
void UpdateVelocity(const Vector2f& gravity, float damping, float deltaTime);
void Wakeup();
RigidBody2D& operator=(const RigidBody2D& object);
RigidBody2D& operator=(RigidBody2D&& object) noexcept;
static constexpr UInt32 InvalidBodyIndex = std::numeric_limits<UInt32>::max();
static constexpr std::size_t InvalidShapeIndex = std::numeric_limits<std::size_t>::max();
struct CommonSettings
{
std::shared_ptr<Collider2D> geom;
RadianAnglef rotation = RadianAnglef::Zero();
Vector2f position = Vector2f::Zero();
bool initiallySleeping = false;
bool isSimulationEnabled = true;
};
struct DynamicSettings : CommonSettings
{
DynamicSettings() = default;
DynamicSettings(std::shared_ptr<Collider2D> collider, float mass_) :
mass(mass_)
{
geom = std::move(collider);
}
RadianAnglef angularVelocity = RadianAnglef::Zero();
Vector2f linearVelocity = Vector2f::Zero();
float gravityFactor = 1.f;
float mass = 1.f;
};
struct StaticSettings : CommonSettings
{
StaticSettings() = default;
StaticSettings(std::shared_ptr<Collider2D> collider)
{
geom = std::move(collider);
}
};
protected:
RigidBody2D() = default;
void Create(PhysWorld2D& world, const DynamicSettings& settings);
void Create(PhysWorld2D& world, const StaticSettings& settings);
void Destroy();
private:
void DestroyBody();
void RegisterToSpace();
void UnregisterFromSpace();
static void CopyBodyData(cpBody* from, cpBody* to);
static void CopyShapeData(cpShape* from, cpShape* to);
std::vector<cpShape*> m_shapes;
std::shared_ptr<Collider2D> m_geom;
MovablePtr<cpBody> m_handle;
MovablePtr<PhysWorld2D> m_world;
UInt32 m_bodyIndex;
Vector2f m_positionOffset;
VelocityFunc m_velocityFunc;
bool m_isRegistered;
bool m_isSimulationEnabled;
bool m_isStatic;
float m_gravityFactor;
float m_mass;
};
}
#include <Nazara/Physics2D/RigidBody2D.inl>
#endif // NAZARA_PHYSICS2D_RIGIDBODY2D_HPP

View File

@@ -0,0 +1,99 @@
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Physics2D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Physics2D/Debug.hpp>
namespace Nz
{
inline RigidBody2D::RigidBody2D(PhysWorld2D& world, const DynamicSettings& settings)
{
Create(world, settings);
}
inline RigidBody2D::RigidBody2D(PhysWorld2D& world, const StaticSettings& settings)
{
Create(world, settings);
}
inline RigidBody2D::~RigidBody2D()
{
Destroy();
}
inline void RigidBody2D::AddForce(const Vector2f& force, CoordSys coordSys)
{
return AddForce(force, GetMassCenter(coordSys), coordSys);
}
inline void RigidBody2D::AddImpulse(const Vector2f& impulse, CoordSys coordSys)
{
return AddImpulse(impulse, GetMassCenter(coordSys), coordSys);
}
inline UInt32 RigidBody2D::GetBodyIndex() const
{
return m_bodyIndex;
}
inline const std::shared_ptr<Collider2D>& RigidBody2D::GetGeom() const
{
return m_geom;
}
inline cpBody* RigidBody2D::GetHandle() const
{
return m_handle;
}
inline float RigidBody2D::GetMass() const
{
return m_mass;
}
inline const Vector2f& RigidBody2D::GetPositionOffset() const
{
return m_positionOffset;
}
inline std::size_t RigidBody2D::GetShapeIndex(cpShape* shape) const
{
auto it = std::find(m_shapes.begin(), m_shapes.end(), shape);
if (it == m_shapes.end())
return InvalidShapeIndex;
return std::distance(m_shapes.begin(), it);
}
inline std::size_t RigidBody2D::GetShapeCount() const
{
return m_shapes.size();
}
inline const RigidBody2D::VelocityFunc& RigidBody2D::GetVelocityFunction() const
{
return m_velocityFunc;
}
inline PhysWorld2D* RigidBody2D::GetWorld() const
{
return m_world;
}
inline bool RigidBody2D::IsKinematic() const
{
return m_mass <= 0.f;
}
inline bool RigidBody2D::IsSimulationEnabled() const
{
return m_isSimulationEnabled;
}
inline bool RigidBody2D::IsStatic() const
{
return m_isStatic;
}
}
#include <Nazara/Physics2D/DebugOff.hpp>

View File

@@ -0,0 +1,34 @@
// this file was automatically generated and should not be edited
/*
Nazara Engine - Physics2D module
Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
#ifndef NAZARA_PHYSICS2D_SYSTEMS_HPP
#define NAZARA_PHYSICS2D_SYSTEMS_HPP
#include <Nazara/Physics2D/Systems/Physics2DSystem.hpp>
#endif // NAZARA_PHYSICS2D_SYSTEMS_HPP

View File

@@ -0,0 +1,96 @@
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Physics2D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_PHYSICS2D_SYSTEMS_PHYSICS2DSYSTEM_HPP
#define NAZARA_PHYSICS2D_SYSTEMS_PHYSICS2DSYSTEM_HPP
#include <NazaraUtils/Prerequisites.hpp>
#include <Nazara/Core/Time.hpp>
#include <Nazara/Physics2D/PhysWorld2D.hpp>
#include <Nazara/Physics2D/Components/RigidBody2DComponent.hpp>
#include <NazaraUtils/TypeList.hpp>
#include <entt/entt.hpp>
namespace Nz
{
class NAZARA_PHYSICS2D_API Physics2DSystem
{
using ContactEndCallback = std::function<void(PhysWorld2D& world, PhysArbiter2D& arbiter, entt::handle entityA, entt::handle entityB, void* userdata)>;
using ContactPostSolveCallback = std::function<void(PhysWorld2D& world, PhysArbiter2D& arbiter, entt::handle entityA, entt::handle entityB, void* userdata)>;
using ContactPreSolveCallback = std::function<bool(PhysWorld2D& world, PhysArbiter2D& arbiter, entt::handle entityA, entt::handle entityB, void* userdata)>;
using ContactStartCallback = std::function<bool(PhysWorld2D& world, PhysArbiter2D& arbiter, entt::handle entityA, entt::handle entityB, void* userdata)>;
public:
static constexpr Int64 ExecutionOrder = 0;
using Components = TypeList<RigidBody2DComponent, class NodeComponent>;
struct ContactCallbacks;
struct NearestQueryResult;
struct RaycastHit;
Physics2DSystem(entt::registry& registry);
Physics2DSystem(const Physics2DSystem&) = delete;
Physics2DSystem(Physics2DSystem&&) = delete;
~Physics2DSystem();
inline PhysWorld2D& GetPhysWorld();
inline const PhysWorld2D& GetPhysWorld() const;
inline entt::handle GetRigidBodyEntity(UInt32 bodyIndex) const;
inline bool NearestBodyQuery(const Vector2f& from, float maxDistance, UInt32 collisionGroup, UInt32 categoryMask, UInt32 collisionMask, entt::handle* nearestEntity = nullptr);
inline bool NearestBodyQuery(const Vector2f& from, float maxDistance, UInt32 collisionGroup, UInt32 categoryMask, UInt32 collisionMask, NearestQueryResult* result);
inline void RaycastQuery(const Vector2f& from, const Vector2f& to, float radius, UInt32 collisionGroup, UInt32 categoryMask, UInt32 collisionMask, const FunctionRef<void(const RaycastHit&)>& callback);
inline bool RaycastQuery(const Vector2f& from, const Vector2f& to, float radius, UInt32 collisionGroup, UInt32 categoryMask, UInt32 collisionMask, std::vector<RaycastHit>* hitInfos);
inline bool RaycastQueryFirst(const Vector2f& from, const Vector2f& to, float radius, UInt32 collisionGroup, UInt32 categoryMask, UInt32 collisionMask, RaycastHit* hitInfo = nullptr);
inline void RegionQuery(const Rectf& boundingBox, UInt32 collisionGroup, UInt32 categoryMask, UInt32 collisionMask, const FunctionRef<void(entt::handle)>& callback);
inline void RegionQuery(const Rectf& boundingBox, UInt32 collisionGroup, UInt32 categoryMask, UInt32 collisionMask, std::vector<entt::handle>* bodies);
inline void RegisterCallbacks(unsigned int collisionId, ContactCallbacks callbacks);
inline void RegisterCallbacks(unsigned int collisionIdA, unsigned int collisionIdB, ContactCallbacks callbacks);
void Update(Time elapsedTime);
Physics2DSystem& operator=(const Physics2DSystem&) = delete;
Physics2DSystem& operator=(Physics2DSystem&&) = delete;
struct ContactCallbacks
{
ContactEndCallback endCallback = nullptr;
ContactPostSolveCallback postSolveCallback = nullptr;
ContactPreSolveCallback preSolveCallback = nullptr;
ContactStartCallback startCallback = nullptr;
void* userdata = nullptr;
};
struct NearestQueryResult : PhysWorld2D::NearestQueryResult
{
entt::handle nearestEntity;
};
struct RaycastHit : PhysWorld2D::RaycastHit
{
entt::handle nearestEntity;
};
private:
void OnBodyConstruct(entt::registry& registry, entt::entity entity);
void OnBodyDestruct(entt::registry& registry, entt::entity entity);
PhysWorld2D::ContactCallbacks SetupContactCallbacks(ContactCallbacks callbacks);
std::vector<entt::entity> m_bodyIndicesToEntity;
entt::registry& m_registry;
entt::observer m_physicsConstructObserver;
entt::scoped_connection m_bodyConstructConnection;
entt::scoped_connection m_bodyDestructConnection;
PhysWorld2D m_physWorld;
};
}
#include <Nazara/Physics2D/Systems/Physics2DSystem.inl>
#endif // NAZARA_PHYSICS2D_SYSTEMS_PHYSICS2DSYSTEM_HPP

View File

@@ -0,0 +1,130 @@
// Copyright (C) 2024 Jérôme "SirLynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Physics2D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Physics2D/Debug.hpp>
namespace Nz
{
inline PhysWorld2D& Physics2DSystem::GetPhysWorld()
{
return m_physWorld;
}
inline const PhysWorld2D& Physics2DSystem::GetPhysWorld() const
{
return m_physWorld;
}
inline entt::handle Physics2DSystem::GetRigidBodyEntity(UInt32 bodyIndex) const
{
return entt::handle(m_registry, m_bodyIndicesToEntity[bodyIndex]);
}
inline bool Physics2DSystem::NearestBodyQuery(const Vector2f& from, float maxDistance, UInt32 collisionGroup, UInt32 categoryMask, UInt32 collisionMask, entt::handle* nearestEntity)
{
RigidBody2D* nearestBody;
if (!m_physWorld.NearestBodyQuery(from, maxDistance, collisionGroup, categoryMask, collisionMask, &nearestBody))
return false;
if (nearestEntity)
{
if (nearestBody)
*nearestEntity = GetRigidBodyEntity(nearestBody->GetBodyIndex());
else
*nearestEntity = {};
}
return true;
}
inline bool Physics2DSystem::NearestBodyQuery(const Vector2f& from, float maxDistance, UInt32 collisionGroup, UInt32 categoryMask, UInt32 collisionMask, NearestQueryResult* result)
{
if (!m_physWorld.NearestBodyQuery(from, maxDistance, collisionGroup, categoryMask, collisionMask, result))
return false;
if (result)
{
if (result->nearestBody)
result->nearestEntity = GetRigidBodyEntity(result->nearestBody->GetBodyIndex());
else
result->nearestEntity = {};
}
return true;
}
inline void Physics2DSystem::RaycastQuery(const Vector2f& from, const Vector2f& to, float radius, UInt32 collisionGroup, UInt32 categoryMask, UInt32 collisionMask, const FunctionRef<void(const RaycastHit&)>& callback)
{
return m_physWorld.RaycastQuery(from, to, radius, collisionGroup, categoryMask, collisionMask, [&](const PhysWorld2D::RaycastHit& hitInfo)
{
RaycastHit extendedHitInfo;
static_cast<PhysWorld2D::RaycastHit&>(extendedHitInfo) = hitInfo;
if (extendedHitInfo.nearestBody)
extendedHitInfo.nearestEntity = GetRigidBodyEntity(extendedHitInfo.nearestBody->GetBodyIndex());
callback(extendedHitInfo);
});
}
inline bool Physics2DSystem::RaycastQuery(const Vector2f& from, const Vector2f& to, float radius, UInt32 collisionGroup, UInt32 categoryMask, UInt32 collisionMask, std::vector<RaycastHit>* hitInfos)
{
NazaraAssert(hitInfos, "invalid output pointer");
std::size_t originalSize = hitInfos->size();
RaycastQuery(from, to, radius, collisionGroup, categoryMask, collisionMask, [&](const RaycastHit& hitInfo)
{
hitInfos->emplace_back(hitInfo);
});
return hitInfos->size() != originalSize;
}
inline bool Physics2DSystem::RaycastQueryFirst(const Vector2f& from, const Vector2f& to, float radius, UInt32 collisionGroup, UInt32 categoryMask, UInt32 collisionMask, RaycastHit* hitInfo)
{
if (!m_physWorld.RaycastQueryFirst(from, to, radius, collisionGroup, categoryMask, collisionMask, hitInfo))
return false;
if (hitInfo)
{
if (hitInfo->nearestBody)
hitInfo->nearestEntity = GetRigidBodyEntity(hitInfo->nearestBody->GetBodyIndex());
else
hitInfo->nearestEntity = {};
}
return true;
}
inline void Physics2DSystem::RegionQuery(const Rectf& boundingBox, UInt32 collisionGroup, UInt32 categoryMask, UInt32 collisionMask, const FunctionRef<void(entt::handle)>& callback)
{
return m_physWorld.RegionQuery(boundingBox, collisionGroup, categoryMask, collisionMask, [&](RigidBody2D* body)
{
callback(GetRigidBodyEntity(body->GetBodyIndex()));
});
}
inline void Physics2DSystem::RegionQuery(const Rectf& boundingBox, UInt32 collisionGroup, UInt32 categoryMask, UInt32 collisionMask, std::vector<entt::handle>* bodies)
{
NazaraAssert(bodies, "invalid output pointer");
return m_physWorld.RegionQuery(boundingBox, collisionGroup, categoryMask, collisionMask, [&](RigidBody2D* body)
{
bodies->emplace_back(GetRigidBodyEntity(body->GetBodyIndex()));
});
}
inline void Physics2DSystem::RegisterCallbacks(unsigned int collisionId, ContactCallbacks callbacks)
{
return m_physWorld.RegisterCallbacks(collisionId, SetupContactCallbacks(std::move(callbacks)));
}
inline void Physics2DSystem::RegisterCallbacks(unsigned int collisionIdA, unsigned int collisionIdB, ContactCallbacks callbacks)
{
return m_physWorld.RegisterCallbacks(collisionIdA, collisionIdB, SetupContactCallbacks(std::move(callbacks)));
}
}
#include <Nazara/Physics2D/DebugOff.hpp>