From 74f3ac8021034a23fe3eb899a18a7dd9421bd4dd Mon Sep 17 00:00:00 2001 From: Lynix Date: Thu, 10 Nov 2016 18:31:27 +0100 Subject: [PATCH] SDK: Add components and system for 2D physics --- SDK/include/NDK/Components.hpp | 2 + .../NDK/Components/CollisionComponent2D.hpp | 58 ++++ .../NDK/Components/CollisionComponent2D.inl | 70 +++++ .../NDK/Components/CollisionComponent3D.hpp | 7 +- .../NDK/Components/PhysicsComponent2D.hpp | 65 ++++ .../NDK/Components/PhysicsComponent2D.inl | 284 ++++++++++++++++++ .../NDK/Components/PhysicsComponent3D.hpp | 2 +- .../NDK/Components/PhysicsComponent3D.inl | 2 +- SDK/include/NDK/Systems.hpp | 1 + SDK/include/NDK/Systems/PhysicsSystem2D.hpp | 42 +++ SDK/include/NDK/Systems/PhysicsSystem2D.inl | 32 ++ .../NDK/Components/CollisionComponent2D.cpp | 108 +++++++ .../NDK/Components/CollisionComponent3D.cpp | 2 +- SDK/src/NDK/Components/PhysicsComponent2D.cpp | 92 ++++++ SDK/src/NDK/Sdk.cpp | 13 +- SDK/src/NDK/Systems/PhysicsSystem2D.cpp | 140 +++++++++ SDK/src/NDK/Systems/PhysicsSystem3D.cpp | 4 +- SDK/src/NDK/World.cpp | 2 + include/Nazara/Physics2D/RigidBody2D.hpp | 2 +- 19 files changed, 917 insertions(+), 11 deletions(-) create mode 100644 SDK/include/NDK/Components/CollisionComponent2D.hpp create mode 100644 SDK/include/NDK/Components/CollisionComponent2D.inl create mode 100644 SDK/include/NDK/Components/PhysicsComponent2D.hpp create mode 100644 SDK/include/NDK/Components/PhysicsComponent2D.inl create mode 100644 SDK/include/NDK/Systems/PhysicsSystem2D.hpp create mode 100644 SDK/include/NDK/Systems/PhysicsSystem2D.inl create mode 100644 SDK/src/NDK/Components/CollisionComponent2D.cpp create mode 100644 SDK/src/NDK/Components/PhysicsComponent2D.cpp create mode 100644 SDK/src/NDK/Systems/PhysicsSystem2D.cpp diff --git a/SDK/include/NDK/Components.hpp b/SDK/include/NDK/Components.hpp index 3338e5f52..3a2916009 100644 --- a/SDK/include/NDK/Components.hpp +++ b/SDK/include/NDK/Components.hpp @@ -6,6 +6,7 @@ #define NDK_COMPONENTS_GLOBAL_HPP #include +#include #include #include #include @@ -13,6 +14,7 @@ #include #include #include +#include #include #include diff --git a/SDK/include/NDK/Components/CollisionComponent2D.hpp b/SDK/include/NDK/Components/CollisionComponent2D.hpp new file mode 100644 index 000000000..b282a850e --- /dev/null +++ b/SDK/include/NDK/Components/CollisionComponent2D.hpp @@ -0,0 +1,58 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#pragma once + +#ifndef NDK_COMPONENTS_COLLISIONCOMPONENT2D_HPP +#define NDK_COMPONENTS_COLLISIONCOMPONENT2D_HPP + +#include +#include +#include + +namespace Nz +{ + class RigidBody2D; +} + +namespace Ndk +{ + class Entity; + + class NDK_API CollisionComponent2D : public Component + { + friend class PhysicsSystem2D; + + public: + CollisionComponent2D(Nz::Collider2DRef geom = Nz::Collider2DRef()); + CollisionComponent2D(const CollisionComponent2D& collision); + ~CollisionComponent2D() = default; + + const Nz::Collider2DRef& GetGeom() const; + + void SetGeom(Nz::Collider2DRef geom); + + CollisionComponent2D& operator=(Nz::Collider2DRef geom); + CollisionComponent2D& operator=(CollisionComponent2D&& collision) = default; + + static ComponentIndex componentIndex; + + private: + void InitializeStaticBody(); + Nz::RigidBody2D* GetStaticBody(); + + void OnAttached() override; + void OnComponentAttached(BaseComponent& component) override; + void OnComponentDetached(BaseComponent& component) override; + void OnDetached() override; + + std::unique_ptr m_staticBody; + Nz::Collider2DRef m_geom; + bool m_bodyUpdated; + }; +} + +#include + +#endif // NDK_COMPONENTS_COLLISIONCOMPONENT2D_HPP diff --git a/SDK/include/NDK/Components/CollisionComponent2D.inl b/SDK/include/NDK/Components/CollisionComponent2D.inl new file mode 100644 index 000000000..62bf422cb --- /dev/null +++ b/SDK/include/NDK/Components/CollisionComponent2D.inl @@ -0,0 +1,70 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#include +#include +#include +#include +#include + +namespace Ndk +{ + /*! + * \brief Constructs a CollisionComponent2D object with a geometry + * + * \param geom Reference to a geometry symbolizing the entity + */ + + inline CollisionComponent2D::CollisionComponent2D(Nz::Collider2DRef geom) : + m_geom(std::move(geom)), + m_bodyUpdated(false) + { + } + + /*! + * \brief Constructs a CollisionComponent2D object by copy semantic + * + * \param collision CollisionComponent2D to copy + */ + + inline CollisionComponent2D::CollisionComponent2D(const CollisionComponent2D& collision) : + m_geom(collision.m_geom), + m_bodyUpdated(false) + { + } + + /*! + * \brief Gets the geometry representing the entity + * \return A constant reference to the physics geometry + */ + + inline const Nz::Collider2DRef& CollisionComponent2D::GetGeom() const + { + return m_geom; + } + + /*! + * \brief Assigns the geometry to this component + * \return A reference to this + * + * \param geom Reference to a geometry symbolizing the entity + */ + + inline CollisionComponent2D& CollisionComponent2D::operator=(Nz::Collider2DRef geom) + { + SetGeom(geom); + + return *this; + } + + /*! + * \brief Gets the static body used by the entity + * \return A pointer to the entity + */ + + inline Nz::RigidBody2D* CollisionComponent2D::GetStaticBody() + { + return m_staticBody.get(); + } +} diff --git a/SDK/include/NDK/Components/CollisionComponent3D.hpp b/SDK/include/NDK/Components/CollisionComponent3D.hpp index f6a07ede6..9a9671660 100644 --- a/SDK/include/NDK/Components/CollisionComponent3D.hpp +++ b/SDK/include/NDK/Components/CollisionComponent3D.hpp @@ -4,8 +4,8 @@ #pragma once -#ifndef NDK_COMPONENTS_COLLISIONCOMPONENT_HPP -#define NDK_COMPONENTS_COLLISIONCOMPONENT_HPP +#ifndef NDK_COMPONENTS_COLLISIONCOMPONENT3D_HPP +#define NDK_COMPONENTS_COLLISIONCOMPONENT3D_HPP #include #include @@ -23,7 +23,6 @@ namespace Ndk class NDK_API CollisionComponent3D : public Component { friend class PhysicsSystem3D; - friend class StaticCollisionSystem; public: CollisionComponent3D(Nz::Collider3DRef geom = Nz::Collider3DRef()); @@ -56,4 +55,4 @@ namespace Ndk #include -#endif // NDK_COMPONENTS_COLLISIONCOMPONENT_HPP +#endif // NDK_COMPONENTS_COLLISIONCOMPONENT3D_HPP diff --git a/SDK/include/NDK/Components/PhysicsComponent2D.hpp b/SDK/include/NDK/Components/PhysicsComponent2D.hpp new file mode 100644 index 000000000..90dd7a5e6 --- /dev/null +++ b/SDK/include/NDK/Components/PhysicsComponent2D.hpp @@ -0,0 +1,65 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#pragma once + +#ifndef NDK_COMPONENTS_PHYSICSCOMPONENT2D_HPP +#define NDK_COMPONENTS_PHYSICSCOMPONENT2D_HPP + +#include +#include +#include + +namespace Ndk +{ + class Entity; + + class NDK_API PhysicsComponent2D : public Component + { + friend class CollisionComponent2D; + friend class PhysicsSystem2D; + + public: + PhysicsComponent2D() = default; + PhysicsComponent2D(const PhysicsComponent2D& physics); + ~PhysicsComponent2D() = default; + + void AddForce(const Nz::Vector2f& force, Nz::CoordSys coordSys = Nz::CoordSys_Global); + void AddForce(const Nz::Vector2f& force, const Nz::Vector2f& point, Nz::CoordSys coordSys = Nz::CoordSys_Global); + void AddTorque(float torque); + + Nz::Rectf GetAABB() const; + float GetAngularVelocity() const; + Nz::Vector2f GetCenterOfGravity(Nz::CoordSys coordSys = Nz::CoordSys_Local) const; + float GetMass() const; + Nz::Vector2f GetPosition() const; + float GetRotation() const; + Nz::Vector2f GetVelocity() const; + + bool IsSleeping() const; + + void SetAngularVelocity(float angularVelocity); + void SetMass(float mass); + void SetMassCenter(const Nz::Vector2f& center); + void SetPosition(const Nz::Vector2f& position); + void SetRotation(float rotation); + void SetVelocity(const Nz::Vector2f& velocity); + + static ComponentIndex componentIndex; + + private: + Nz::RigidBody2D& GetRigidBody(); + + void OnAttached() override; + void OnComponentAttached(BaseComponent& component) override; + void OnComponentDetached(BaseComponent& component) override; + void OnDetached() override; + + std::unique_ptr m_object; + }; +} + +#include + +#endif // NDK_COMPONENTS_PHYSICSCOMPONENT2D_HPP diff --git a/SDK/include/NDK/Components/PhysicsComponent2D.inl b/SDK/include/NDK/Components/PhysicsComponent2D.inl new file mode 100644 index 000000000..312e23e3a --- /dev/null +++ b/SDK/include/NDK/Components/PhysicsComponent2D.inl @@ -0,0 +1,284 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#include +#include "PhysicsComponent2D.hpp" + +namespace Ndk +{ + /*! + * \brief Constructs a PhysicsComponent2D object by copy semantic + * + * \param physics PhysicsComponent2D to copy + */ + + inline PhysicsComponent2D::PhysicsComponent2D(const PhysicsComponent2D& physics) + { + // No copy of physical object (because we only create it when attached to an entity) + NazaraUnused(physics); + } + + /*! + * \brief Applies a physics force to the entity + * + * \param force Force to apply on the entity + * \param coordSys System coordinates to consider + * + * \remark Produces a NazaraAssert if the physics object is invalid + */ + + inline void PhysicsComponent2D::AddForce(const Nz::Vector2f& force, Nz::CoordSys coordSys) + { + NazaraAssert(m_object, "Invalid physics object"); + + m_object->AddForce(force, coordSys); + } + + /*! + * \brief Applies a physics force to the entity + * + * \param force Force to apply on the entity + * \param point Point where to apply the force + * \param coordSys System coordinates to consider + * + * \remark Produces a NazaraAssert if the physics object is invalid + */ + + inline void PhysicsComponent2D::AddForce(const Nz::Vector2f& force, const Nz::Vector2f& point, Nz::CoordSys coordSys) + { + NazaraAssert(m_object, "Invalid physics object"); + + m_object->AddForce(force, point, coordSys); + } + + /*! + * \brief Applies a torque to the entity + * + * \param torque Torque to apply on the entity + * + * \remark Produces a NazaraAssert if the physics object is invalid + */ + + inline void PhysicsComponent2D::AddTorque(float torque) + { + NazaraAssert(m_object, "Invalid physics object"); + + m_object->AddTorque(torque); + } + + /*! + * \brief Gets the AABB of the physics object + * \return AABB of the object + * + * \remark Produces a NazaraAssert if the physics object is invalid + */ + inline Nz::Rectf PhysicsComponent2D::GetAABB() const + { + NazaraAssert(m_object, "Invalid physics object"); + + return m_object->GetAABB(); + } + + /*! + * \brief Gets the angular velocity of the physics object + * \return Angular velocity of the object + * + * \remark Produces a NazaraAssert if the physics object is invalid + */ + + inline float PhysicsComponent2D::GetAngularVelocity() const + { + NazaraAssert(m_object, "Invalid physics object"); + + return m_object->GetAngularVelocity(); + } + + /*! + * \brief Gets the gravity center of the physics object + * \return Gravity center of the object + * + * \param coordSys System coordinates to consider + * + * \remark Produces a NazaraAssert if the physics object is invalid + */ + + inline Nz::Vector2f PhysicsComponent2D::GetCenterOfGravity(Nz::CoordSys coordSys) const + { + NazaraAssert(m_object, "Invalid physics object"); + + return m_object->GetCenterOfGravity(coordSys); + } + + /*! + * \brief Gets the mass of the physics object + * \return Mass of the object + * + * \remark Produces a NazaraAssert if the physics object is invalid + */ + + inline float PhysicsComponent2D::GetMass() const + { + NazaraAssert(m_object, "Invalid physics object"); + + return m_object->GetMass(); + } + + /*! + * \brief Gets the position of the physics object + * \return Position of the object + * + * \remark Produces a NazaraAssert if the physics object is invalid + */ + + inline Nz::Vector2f PhysicsComponent2D::GetPosition() const + { + NazaraAssert(m_object, "Invalid physics object"); + + return m_object->GetPosition(); + } + + /*! + * \brief Gets the rotation of the physics object + * \return Rotation of the object + * + * \remark Produces a NazaraAssert if the physics object is invalid + */ + + inline float PhysicsComponent2D::GetRotation() const + { + NazaraAssert(m_object, "Invalid physics object"); + + return m_object->GetRotation(); + } + + /*! + * \brief Gets the velocity of the physics object + * \return Velocity of the object + * + * \remark Produces a NazaraAssert if the physics object is invalid + */ + + inline Nz::Vector2f PhysicsComponent2D::GetVelocity() const + { + NazaraAssert(m_object, "Invalid physics object"); + + return m_object->GetVelocity(); + } + + /*! + * \brief Checks whether the entity is currently sleeping + * \return true If it is the case + * + * \remark Produces a NazaraAssert if the physics object is invalid + */ + + inline bool PhysicsComponent2D::IsSleeping() const + { + NazaraAssert(m_object, "Invalid physics object"); + + return m_object->IsSleeping(); + } + + /*! + * \brief Sets the angular velocity of the physics object + * + * \param angularVelocity Angular velocity of the object + * + * \remark Produces a NazaraAssert if the physics object is invalid + */ + + inline void PhysicsComponent2D::SetAngularVelocity(float angularVelocity) + { + NazaraAssert(m_object, "Invalid physics object"); + + m_object->SetAngularVelocity(angularVelocity); + } + + /*! + * \brief Sets the mass of the physics object + * + * \param mass Mass of the object + * + * \remark Produces a NazaraAssert if the physics object is invalid + * \remark Produces a NazaraAssert if the mass is negative + */ + + inline void PhysicsComponent2D::SetMass(float mass) + { + NazaraAssert(m_object, "Invalid physics object"); + NazaraAssert(mass > 0.f, "Mass should be positive"); + + m_object->SetMass(mass); + } + + /*! + * \brief Sets the gravity center of the physics object + * + * \param center Gravity center of the object + * + * \remark Produces a NazaraAssert if the physics object is invalid + */ + + inline void PhysicsComponent2D::SetMassCenter(const Nz::Vector2f& center) + { + NazaraAssert(m_object, "Invalid physics object"); + + m_object->SetMassCenter(center); + } + + /*! + * \brief Sets the position of the physics object + * + * \param position Position of the object + * + * \remark Produces a NazaraAssert if the physics object is invalid + */ + + inline void PhysicsComponent2D::SetPosition(const Nz::Vector2f& position) + { + NazaraAssert(m_object, "Invalid physics object"); + + m_object->SetPosition(position); + } + + /*! + * \brief Sets the rotation of the physics object + * + * \param rotation Rotation of the object + * + * \remark Produces a NazaraAssert if the physics object is invalid + */ + + inline void PhysicsComponent2D::SetRotation(float rotation) + { + NazaraAssert(m_object, "Invalid physics object"); + + m_object->SetRotation(rotation); + } + + /*! + * \brief Sets the velocity of the physics object + * + * \param velocity Velocity of the object + * + * \remark Produces a NazaraAssert if the physics object is invalid + */ + + inline void PhysicsComponent2D::SetVelocity(const Nz::Vector2f& velocity) + { + NazaraAssert(m_object, "Invalid physics object"); + + m_object->SetVelocity(velocity); + } + + /*! + * \brief Gets the underlying physics object + * \return A reference to the physics object + */ + + inline Nz::RigidBody2D& PhysicsComponent2D::GetRigidBody() + { + return *m_object.get(); + } +} diff --git a/SDK/include/NDK/Components/PhysicsComponent3D.hpp b/SDK/include/NDK/Components/PhysicsComponent3D.hpp index fc1367d84..9fb1bb45e 100644 --- a/SDK/include/NDK/Components/PhysicsComponent3D.hpp +++ b/SDK/include/NDK/Components/PhysicsComponent3D.hpp @@ -56,7 +56,7 @@ namespace Ndk static ComponentIndex componentIndex; private: - Nz::RigidBody3D& GetPhysObject(); + Nz::RigidBody3D& GetRigidBody(); void OnAttached() override; void OnComponentAttached(BaseComponent& component) override; diff --git a/SDK/include/NDK/Components/PhysicsComponent3D.inl b/SDK/include/NDK/Components/PhysicsComponent3D.inl index 84bc36db7..cad098af8 100644 --- a/SDK/include/NDK/Components/PhysicsComponent3D.inl +++ b/SDK/include/NDK/Components/PhysicsComponent3D.inl @@ -350,7 +350,7 @@ namespace Ndk * \return A reference to the physics object */ - inline Nz::RigidBody3D& PhysicsComponent3D::GetPhysObject() + inline Nz::RigidBody3D& PhysicsComponent3D::GetRigidBody() { return *m_object.get(); } diff --git a/SDK/include/NDK/Systems.hpp b/SDK/include/NDK/Systems.hpp index 45a79bc6c..a0ee23e77 100644 --- a/SDK/include/NDK/Systems.hpp +++ b/SDK/include/NDK/Systems.hpp @@ -7,6 +7,7 @@ #include #include +#include #include #include #include diff --git a/SDK/include/NDK/Systems/PhysicsSystem2D.hpp b/SDK/include/NDK/Systems/PhysicsSystem2D.hpp new file mode 100644 index 000000000..31426450a --- /dev/null +++ b/SDK/include/NDK/Systems/PhysicsSystem2D.hpp @@ -0,0 +1,42 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#pragma once + +#ifndef NDK_SYSTEMS_PHYSICSSYSTEM2D_HPP +#define NDK_SYSTEMS_PHYSICSSYSTEM2D_HPP + +#include +#include +#include +#include + +namespace Ndk +{ + class NDK_API PhysicsSystem2D : public System + { + public: + PhysicsSystem2D(); + PhysicsSystem2D(const PhysicsSystem2D& system); + ~PhysicsSystem2D() = default; + + Nz::PhysWorld2D& GetWorld(); + const Nz::PhysWorld2D& GetWorld() const; + + static SystemIndex systemIndex; + + private: + void CreatePhysWorld() const; + void OnEntityValidation(Entity* entity, bool justAdded) override; + void OnUpdate(float elapsedTime) override; + + EntityList m_dynamicObjects; + EntityList m_staticObjects; + mutable std::unique_ptr m_world; ///TODO: std::optional (Should I make a Nz::Optional class?) + }; +} + +#include + +#endif // NDK_SYSTEMS_PHYSICSSYSTEM2D_HPP diff --git a/SDK/include/NDK/Systems/PhysicsSystem2D.inl b/SDK/include/NDK/Systems/PhysicsSystem2D.inl new file mode 100644 index 000000000..21a34a6d4 --- /dev/null +++ b/SDK/include/NDK/Systems/PhysicsSystem2D.inl @@ -0,0 +1,32 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +namespace Ndk +{ + /*! + * \brief Gets the physical world + * \return A reference to the physical world + */ + + inline Nz::PhysWorld2D& PhysicsSystem2D::GetWorld() + { + if (!m_world) + CreatePhysWorld(); + + return *m_world; + } + + /*! + * \brief Gets the physical world + * \return A constant reference to the physical world + */ + + inline const Nz::PhysWorld2D& PhysicsSystem2D::GetWorld() const + { + if (!m_world) + CreatePhysWorld(); + + return *m_world; + } +} diff --git a/SDK/src/NDK/Components/CollisionComponent2D.cpp b/SDK/src/NDK/Components/CollisionComponent2D.cpp new file mode 100644 index 000000000..be6106a45 --- /dev/null +++ b/SDK/src/NDK/Components/CollisionComponent2D.cpp @@ -0,0 +1,108 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#include +#include +#include +#include +#include +#include + +namespace Ndk +{ + /*! + * \ingroup NDK + * \class Ndk::CollisionComponent2D + * \brief NDK class that represents a two-dimensional collision geometry + */ + + /*! + * \brief Sets geometry for the entity + * + * \param geom Geometry used for collisions + * + * \remark Produces a NazaraAssert if the entity has no physics component and has no static body + */ + + void CollisionComponent2D::SetGeom(Nz::Collider2DRef geom) + { + m_geom = std::move(geom); + + if (m_entity->HasComponent()) + { + // We update the geometry of the PhysiscsObject linked to the PhysicsComponent2D + PhysicsComponent2D& physComponent = m_entity->GetComponent(); + physComponent.GetRigidBody().SetGeom(m_geom); + } + else + { + NazaraAssert(m_staticBody, "An entity without physics component should have a static body"); + m_staticBody->SetGeom(m_geom); + } + } + + /*! + * \brief Initializes the static body + * + * \remark Produces a NazaraAssert if entity is invalid + * \remark Produces a NazaraAssert if entity is not linked to a world, or the world has no physics system + */ + + void CollisionComponent2D::InitializeStaticBody() + { + NazaraAssert(m_entity, "Invalid entity"); + World* entityWorld = m_entity->GetWorld(); + + NazaraAssert(entityWorld, "Entity must have world"); + NazaraAssert(entityWorld->HasSystem(), "World must have a physics system"); + Nz::PhysWorld2D& physWorld = entityWorld->GetSystem().GetWorld(); + + m_staticBody.reset(new Nz::RigidBody2D(&physWorld, m_geom)); + } + + /*! + * \brief Operation to perform when component is attached to an entity + */ + + void CollisionComponent2D::OnAttached() + { + if (!m_entity->HasComponent()) + InitializeStaticBody(); + } + + /*! + * \brief Operation to perform when component is attached to this component + * + * \param component Component being attached + */ + + void CollisionComponent2D::OnComponentAttached(BaseComponent& component) + { + if (IsComponent(component)) + m_staticBody.reset(); + } + + /*! + * \brief Operation to perform when component is detached from this component + * + * \param component Component being detached + */ + + void CollisionComponent2D::OnComponentDetached(BaseComponent& component) + { + if (IsComponent(component)) + InitializeStaticBody(); + } + + /*! + * \brief Operation to perform when component is detached from an entity + */ + + void CollisionComponent2D::OnDetached() + { + m_staticBody.reset(); + } + + ComponentIndex CollisionComponent2D::componentIndex; +} diff --git a/SDK/src/NDK/Components/CollisionComponent3D.cpp b/SDK/src/NDK/Components/CollisionComponent3D.cpp index 423b06cb4..d54c460be 100644 --- a/SDK/src/NDK/Components/CollisionComponent3D.cpp +++ b/SDK/src/NDK/Components/CollisionComponent3D.cpp @@ -33,7 +33,7 @@ namespace Ndk { // We update the geometry of the PhysiscsObject linked to the PhysicsComponent3D PhysicsComponent3D& physComponent = m_entity->GetComponent(); - physComponent.GetPhysObject().SetGeom(m_geom); + physComponent.GetRigidBody().SetGeom(m_geom); } else { diff --git a/SDK/src/NDK/Components/PhysicsComponent2D.cpp b/SDK/src/NDK/Components/PhysicsComponent2D.cpp new file mode 100644 index 000000000..db66178b9 --- /dev/null +++ b/SDK/src/NDK/Components/PhysicsComponent2D.cpp @@ -0,0 +1,92 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#include +#include +#include +#include +#include +#include +#include + +namespace Ndk +{ + /*! + * \ingroup NDK + * \class Ndk::PhysicsComponent2D + * \brief NDK class that represents a physics point, without any collision + */ + + /*! + * \brief Operation to perform when component is attached to an entity + * + * \remark Produces a NazaraAssert if the world does not have a physics system + */ + + void PhysicsComponent2D::OnAttached() + { + World* entityWorld = m_entity->GetWorld(); + NazaraAssert(entityWorld->HasSystem(), "World must have a 2D physics system"); + + Nz::PhysWorld2D& world = entityWorld->GetSystem().GetWorld(); + + Nz::Collider2DRef geom; + if (m_entity->HasComponent()) + geom = m_entity->GetComponent().GetGeom(); + + Nz::Matrix4f matrix; + if (m_entity->HasComponent()) + matrix = m_entity->GetComponent().GetTransformMatrix(); + else + matrix.MakeIdentity(); + + m_object.reset(new Nz::RigidBody2D(&world, 1.f, geom)); + m_object->SetPosition(Nz::Vector2f(matrix.GetTranslation())); + } + + /*! + * \brief Operation to perform when component is attached to this component + * + * \param component Component being attached + * + * \remark Produces a NazaraAssert if physical object is invalid + */ + + void PhysicsComponent2D::OnComponentAttached(BaseComponent& component) + { + if (IsComponent(component)) + { + NazaraAssert(m_object, "Invalid object"); + m_object->SetGeom(static_cast(component).GetGeom()); + } + } + + /*! + * \brief Operation to perform when component is detached from this component + * + * \param component Component being detached + * + * \remark Produces a NazaraAssert if physical object is invalid + */ + + void PhysicsComponent2D::OnComponentDetached(BaseComponent& component) + { + if (IsComponent(component)) + { + NazaraAssert(m_object, "Invalid object"); + m_object->SetGeom(Nz::NullCollider2D::New()); + } + } + + /*! + * \brief Operation to perform when component is detached from an entity + */ + + void PhysicsComponent2D::OnDetached() + { + m_object.reset(); + } + + ComponentIndex PhysicsComponent2D::componentIndex; +} diff --git a/SDK/src/NDK/Sdk.cpp b/SDK/src/NDK/Sdk.cpp index 36283ada3..81080af06 100644 --- a/SDK/src/NDK/Sdk.cpp +++ b/SDK/src/NDK/Sdk.cpp @@ -9,14 +9,18 @@ #include #include #include +#include #include #include #include #include +#include #include #include +#include #include #include +#include #include #include @@ -68,6 +72,7 @@ namespace Ndk Nz::Lua::Initialize(); Nz::Noise::Initialize(); + Nz::Physics2D::Initialize(); Nz::Physics3D::Initialize(); Nz::Utility::Initialize(); @@ -83,9 +88,11 @@ namespace Ndk BaseComponent::Initialize(); // Shared components - InitializeComponent("NdkColli"); + InitializeComponent("NdkColl2"); + InitializeComponent("NdkColl3"); InitializeComponent("NdkNode"); - InitializeComponent("NdkPhys"); + InitializeComponent("NdkPhys2"); + InitializeComponent("NdkPhys3"); InitializeComponent("NdkVeloc"); #ifndef NDK_SERVER @@ -103,6 +110,7 @@ namespace Ndk BaseSystem::Initialize(); // Shared systems + InitializeSystem(); InitializeSystem(); InitializeSystem(); @@ -161,6 +169,7 @@ namespace Ndk // Shared modules Nz::Lua::Uninitialize(); Nz::Noise::Uninitialize(); + Nz::Physics2D::Uninitialize(); Nz::Physics3D::Uninitialize(); Nz::Utility::Uninitialize(); diff --git a/SDK/src/NDK/Systems/PhysicsSystem2D.cpp b/SDK/src/NDK/Systems/PhysicsSystem2D.cpp new file mode 100644 index 000000000..adedfc170 --- /dev/null +++ b/SDK/src/NDK/Systems/PhysicsSystem2D.cpp @@ -0,0 +1,140 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#include +#include +#include +#include +#include +#include + +namespace Ndk +{ + /*! + * \ingroup NDK + * \class Ndk::PhysicsSystem2D + * \brief NDK class that represents a two-dimensional physics system + * + * \remark This system is enabled if the entity has the trait: NodeComponent and any of these two: CollisionComponent3D or PhysicsComponent3D + * \remark Static objects do not have a velocity specified by the physical engine + */ + + /*! + * \brief Constructs an PhysicsSystem object by default + */ + + PhysicsSystem2D::PhysicsSystem2D() + { + Requires(); + RequiresAny(); + Excludes(); + } + + /*! + * \brief Constructs a PhysicsSystem object by copy semantic + * + * \param system PhysicsSystem to copy + */ + + PhysicsSystem2D::PhysicsSystem2D(const PhysicsSystem2D& system) : + System(system), + m_world() + { + } + + void PhysicsSystem2D::CreatePhysWorld() const + { + NazaraAssert(!m_world, "Physics world should not be created twice"); + + m_world = std::make_unique(); + } + + /*! + * \brief Operation to perform when entity is validated for the system + * + * \param entity Pointer to the entity + * \param justAdded Is the entity newly added + */ + + void PhysicsSystem2D::OnEntityValidation(Entity* entity, bool justAdded) + { + // It's possible our entity got revalidated because of the addition/removal of a PhysicsComponent3D + if (!justAdded) + { + // We take the opposite array from which the entity should belong to + auto& entities = (entity->HasComponent()) ? m_staticObjects : m_dynamicObjects; + entities.Remove(entity); + } + + auto& entities = (entity->HasComponent()) ? m_dynamicObjects : m_staticObjects; + entities.Insert(entity); + + if (!m_world) + CreatePhysWorld(); + } + + /*! + * \brief Operation to perform when system is updated + * + * \param elapsedTime Delta time used for the update + */ + + void PhysicsSystem2D::OnUpdate(float elapsedTime) + { + if (!m_world) + return; + + m_world->Step(elapsedTime); + + for (const Ndk::EntityHandle& entity : m_dynamicObjects) + { + NodeComponent& node = entity->GetComponent(); + PhysicsComponent2D& phys = entity->GetComponent(); + + Nz::RigidBody2D& body = phys.GetRigidBody(); + node.SetRotation(Nz::EulerAnglesf(0.f, 0.f, body.GetRotation()), Nz::CoordSys_Global); + node.SetPosition(Nz::Vector3f(body.GetPosition(), node.GetPosition(Nz::CoordSys_Global).z), Nz::CoordSys_Global); + } + + float invElapsedTime = 1.f / elapsedTime; + for (const Ndk::EntityHandle& entity : m_staticObjects) + { + CollisionComponent2D& collision = entity->GetComponent(); + NodeComponent& node = entity->GetComponent(); + + Nz::RigidBody2D* body = collision.GetStaticBody(); + + Nz::Vector2f oldPosition = body->GetPosition(); + Nz::Vector2f newPosition = Nz::Vector2f(node.GetPosition(Nz::CoordSys_Global)); + + // To move static objects and ensure their collisions, we have to specify them a velocity + // (/!\: the physical motor does not apply the speed on static objects) + if (newPosition != oldPosition) + { + body->SetPosition(newPosition); + body->SetVelocity((newPosition - oldPosition) * invElapsedTime); + } + else + body->SetVelocity(Nz::Vector2f::Zero()); + +/* + if (newRotation != oldRotation) + { + Nz::Quaternionf transition = newRotation * oldRotation.GetConjugate(); + Nz::EulerAnglesf angles = transition.ToEulerAngles(); + Nz::Vector3f angularVelocity(Nz::ToRadians(angles.pitch * invElapsedTime), + Nz::ToRadians(angles.yaw * invElapsedTime), + Nz::ToRadians(angles.roll * invElapsedTime)); + + physObj->SetRotation(oldRotation); + physObj->SetAngularVelocity(angularVelocity); + } + else + physObj->SetAngularVelocity(Nz::Vector3f::Zero()); +*/ + } + } + + SystemIndex PhysicsSystem2D::systemIndex; +} diff --git a/SDK/src/NDK/Systems/PhysicsSystem3D.cpp b/SDK/src/NDK/Systems/PhysicsSystem3D.cpp index fd5e05d66..c26c932e0 100644 --- a/SDK/src/NDK/Systems/PhysicsSystem3D.cpp +++ b/SDK/src/NDK/Systems/PhysicsSystem3D.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include namespace Ndk @@ -27,6 +28,7 @@ namespace Ndk { Requires(); RequiresAny(); + Excludes(); } /*! @@ -90,7 +92,7 @@ namespace Ndk NodeComponent& node = entity->GetComponent(); PhysicsComponent3D& phys = entity->GetComponent(); - Nz::RigidBody3D& physObj = phys.GetPhysObject(); + Nz::RigidBody3D& physObj = phys.GetRigidBody(); node.SetRotation(physObj.GetRotation(), Nz::CoordSys_Global); node.SetPosition(physObj.GetPosition(), Nz::CoordSys_Global); } diff --git a/SDK/src/NDK/World.cpp b/SDK/src/NDK/World.cpp index f0cfbb44b..78b250aaf 100644 --- a/SDK/src/NDK/World.cpp +++ b/SDK/src/NDK/World.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -40,6 +41,7 @@ namespace Ndk void World::AddDefaultSystems() { + AddSystem(); AddSystem(); AddSystem(); diff --git a/include/Nazara/Physics2D/RigidBody2D.hpp b/include/Nazara/Physics2D/RigidBody2D.hpp index b45526641..79b7d64bc 100644 --- a/include/Nazara/Physics2D/RigidBody2D.hpp +++ b/include/Nazara/Physics2D/RigidBody2D.hpp @@ -60,7 +60,7 @@ namespace Nz RigidBody2D& operator=(RigidBody2D&& object); private: - void Create(float mass = 0.f, float moment = 0.f); + void Create(float mass = 1.f, float moment = 1.f); void Destroy(); std::vector m_shapes;