diff --git a/SDK/include/NDK/Components/CollisionComponent.hpp b/SDK/include/NDK/Components/CollisionComponent.hpp new file mode 100644 index 000000000..c421f127a --- /dev/null +++ b/SDK/include/NDK/Components/CollisionComponent.hpp @@ -0,0 +1,56 @@ +// 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_COLLISIONCOMPONENT_HPP +#define NDK_COMPONENTS_COLLISIONCOMPONENT_HPP + +#include +#include +#include + +class NzPhysObject; + +namespace Ndk +{ + class Entity; + + class NDK_API CollisionComponent : public Component + { + friend class PhysicsSystem; + friend class StaticCollisionSystem; + + public: + CollisionComponent(NzPhysGeomRef geom = NzPhysGeomRef()); + CollisionComponent(const CollisionComponent& collision); + ~CollisionComponent() = default; + + const NzPhysGeomRef& GetGeom() const; + + void SetGeom(NzPhysGeomRef geom); + + CollisionComponent& operator=(NzPhysGeomRef geom); + CollisionComponent& operator=(CollisionComponent&& collision) = default; + + static ComponentIndex componentIndex; + + private: + void InitializeStaticBody(); + NzPhysObject* GetStaticBody(); + + void OnAttached() override; + void OnComponentAttached(BaseComponent& component) override; + void OnComponentDetached(BaseComponent& component) override; + void OnDetached() override; + + std::unique_ptr m_staticBody; + NzPhysGeomRef m_geom; + bool m_bodyUpdated; + }; +} + +#include + +#endif // NDK_COMPONENTS_COLLISIONCOMPONENT_HPP diff --git a/SDK/include/NDK/Components/CollisionComponent.inl b/SDK/include/NDK/Components/CollisionComponent.inl new file mode 100644 index 000000000..2f748c1d6 --- /dev/null +++ b/SDK/include/NDK/Components/CollisionComponent.inl @@ -0,0 +1,40 @@ +// 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 + +namespace Ndk +{ + inline CollisionComponent::CollisionComponent(NzPhysGeomRef geom) : + m_geom(std::move(geom)), + m_bodyUpdated(false) + { + } + + inline CollisionComponent::CollisionComponent(const CollisionComponent& collision) : + m_geom(collision.m_geom), + m_bodyUpdated(false) + { + } + + inline const NzPhysGeomRef& CollisionComponent::GetGeom() const + { + return m_geom; + } + + inline CollisionComponent& CollisionComponent::operator=(NzPhysGeomRef geom) + { + SetGeom(geom); + + return *this; + } + + inline NzPhysObject* CollisionComponent::GetStaticBody() + { + return m_staticBody.get(); + } +} diff --git a/SDK/include/NDK/Components/PhysicsComponent.hpp b/SDK/include/NDK/Components/PhysicsComponent.hpp new file mode 100644 index 000000000..4385735f9 --- /dev/null +++ b/SDK/include/NDK/Components/PhysicsComponent.hpp @@ -0,0 +1,72 @@ +// 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_PHYSICSCOMPONENT_HPP +#define NDK_COMPONENTS_PHYSICSCOMPONENT_HPP + +#include +#include +#include + +namespace Ndk +{ + class Entity; + + class NDK_API PhysicsComponent : public Component + { + friend class CollisionComponent; + friend class PhysicsSystem; + + public: + PhysicsComponent() = default; + PhysicsComponent(const PhysicsComponent& physics); + ~PhysicsComponent() = default; + + void AddForce(const NzVector3f& force, nzCoordSys coordSys = nzCoordSys_Global); + void AddForce(const NzVector3f& force, const NzVector3f& point, nzCoordSys coordSys = nzCoordSys_Global); + void AddTorque(const NzVector3f& torque, nzCoordSys coordSys = nzCoordSys_Global); + + void EnableAutoSleep(bool autoSleep); + + NzBoxf GetAABB() const; + NzVector3f GetAngularVelocity() const; + float GetGravityFactor() const; + float GetMass() const; + NzVector3f GetMassCenter(nzCoordSys coordSys = nzCoordSys_Local) const; + const NzMatrix4f& GetMatrix() const; + NzVector3f GetPosition() const; + NzQuaternionf GetRotation() const; + NzVector3f GetVelocity() const; + + bool IsAutoSleepEnabled() const; + bool IsMoveable() const; + bool IsSleeping() const; + + void SetAngularVelocity(const NzVector3f& angularVelocity); + void SetGravityFactor(float gravityFactor); + void SetMass(float mass); + void SetMassCenter(const NzVector3f& center); + void SetPosition(const NzVector3f& position); + void SetRotation(const NzQuaternionf& rotation); + void SetVelocity(const NzVector3f& velocity); + + static ComponentIndex componentIndex; + + private: + NzPhysObject& GetPhysObject(); + + 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_PHYSICSCOMPONENT_HPP diff --git a/SDK/include/NDK/Components/PhysicsComponent.inl b/SDK/include/NDK/Components/PhysicsComponent.inl new file mode 100644 index 000000000..fec47f8f5 --- /dev/null +++ b/SDK/include/NDK/Components/PhysicsComponent.inl @@ -0,0 +1,174 @@ +// 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 + +namespace Ndk +{ + inline PhysicsComponent::PhysicsComponent(const PhysicsComponent& physics) + { + // Pas de copie de l'objet physique (étant donné que nous n'allons le créer qu'une fois attaché à une entité) + NazaraUnused(physics); + } + + inline void PhysicsComponent::AddForce(const NzVector3f& force, nzCoordSys coordSys) + { + NazaraAssert(m_object, "Invalid physics object"); + + m_object->AddForce(force, coordSys); + } + + inline void PhysicsComponent::AddForce(const NzVector3f& force, const NzVector3f& point, nzCoordSys coordSys) + { + NazaraAssert(m_object, "Invalid physics object"); + + m_object->AddForce(force, point, coordSys); + } + + inline void PhysicsComponent::AddTorque(const NzVector3f& torque, nzCoordSys coordSys) + { + NazaraAssert(m_object, "Invalid physics object"); + + m_object->AddForce(torque, coordSys); + } + + inline void PhysicsComponent::EnableAutoSleep(bool autoSleep) + { + NazaraAssert(m_object, "Invalid physics object"); + + m_object->EnableAutoSleep(autoSleep); + } + + inline NzBoxf PhysicsComponent::GetAABB() const + { + NazaraAssert(m_object, "Invalid physics object"); + + return m_object->GetAABB(); + } + + inline NzVector3f PhysicsComponent::GetAngularVelocity() const + { + NazaraAssert(m_object, "Invalid physics object"); + + return m_object->GetAngularVelocity(); + } + + inline float PhysicsComponent::GetGravityFactor() const + { + NazaraAssert(m_object, "Invalid physics object"); + + return m_object->GetGravityFactor(); + } + + inline float PhysicsComponent::GetMass() const + { + NazaraAssert(m_object, "Invalid physics object"); + + return m_object->GetMass(); + } + + inline NzVector3f PhysicsComponent::GetMassCenter(nzCoordSys coordSys) const + { + NazaraAssert(m_object, "Invalid physics object"); + + return m_object->GetMassCenter(coordSys); + } + + inline const NzMatrix4f& PhysicsComponent::GetMatrix() const + { + NazaraAssert(m_object, "Invalid physics object"); + + return m_object->GetMatrix(); + } + + inline NzVector3f PhysicsComponent::GetPosition() const + { + NazaraAssert(m_object, "Invalid physics object"); + + return m_object->GetPosition(); + } + + inline NzQuaternionf PhysicsComponent::GetRotation() const + { + NazaraAssert(m_object, "Invalid physics object"); + + return m_object->GetRotation(); + } + + inline NzVector3f PhysicsComponent::GetVelocity() const + { + NazaraAssert(m_object, "Invalid physics object"); + + return m_object->GetVelocity(); + } + + inline bool PhysicsComponent::IsAutoSleepEnabled() const + { + NazaraAssert(m_object, "Invalid physics object"); + + return m_object->IsAutoSleepEnabled(); + } + + inline bool PhysicsComponent::IsSleeping() const + { + NazaraAssert(m_object, "Invalid physics object"); + + return m_object->IsSleeping(); + } + + inline void PhysicsComponent::SetAngularVelocity(const NzVector3f& angularVelocity) + { + NazaraAssert(m_object, "Invalid physics object"); + + m_object->SetAngularVelocity(angularVelocity); + } + + inline void PhysicsComponent::SetGravityFactor(float gravityFactor) + { + NazaraAssert(m_object, "Invalid physics object"); + + m_object->SetGravityFactor(gravityFactor); + } + + inline void PhysicsComponent::SetMass(float mass) + { + NazaraAssert(m_object, "Invalid physics object"); + NazaraAssert(mass > 0.f, "Mass should be positive"); + + m_object->SetMass(mass); + } + + inline void PhysicsComponent::SetMassCenter(const NzVector3f& center) + { + NazaraAssert(m_object, "Invalid physics object"); + + m_object->SetMassCenter(center); + } + + inline void PhysicsComponent::SetPosition(const NzVector3f& position) + { + NazaraAssert(m_object, "Invalid physics object"); + + m_object->SetPosition(position); + } + + inline void PhysicsComponent::SetRotation(const NzQuaternionf& rotation) + { + NazaraAssert(m_object, "Invalid physics object"); + + m_object->SetRotation(rotation); + } + + inline void PhysicsComponent::SetVelocity(const NzVector3f& velocity) + { + NazaraAssert(m_object, "Invalid physics object"); + + m_object->SetVelocity(velocity); + } + + inline NzPhysObject& PhysicsComponent::GetPhysObject() + { + return *m_object.get(); + } +} diff --git a/SDK/include/NDK/Systems/PhysicsSystem.hpp b/SDK/include/NDK/Systems/PhysicsSystem.hpp new file mode 100644 index 000000000..d7a3f0ba1 --- /dev/null +++ b/SDK/include/NDK/Systems/PhysicsSystem.hpp @@ -0,0 +1,36 @@ +// 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_PHYSICSSYSTEM_HPP +#define NDK_SYSTEMS_PHYSICSSYSTEM_HPP + +#include +#include + +namespace Ndk +{ + class NDK_API PhysicsSystem : public System + { + public: + PhysicsSystem(); + PhysicsSystem(const PhysicsSystem& system); + ~PhysicsSystem() = default; + + NzPhysWorld& GetWorld(); + const NzPhysWorld& GetWorld() const; + + void Update(float elapsedTime); + + static SystemIndex systemIndex; + + private: + NzPhysWorld m_world; + }; +} + +#include + +#endif // NDK_SYSTEMS_PHYSICSSYSTEM_HPP diff --git a/SDK/include/NDK/Systems/PhysicsSystem.inl b/SDK/include/NDK/Systems/PhysicsSystem.inl new file mode 100644 index 000000000..78d396282 --- /dev/null +++ b/SDK/include/NDK/Systems/PhysicsSystem.inl @@ -0,0 +1,16 @@ +// 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 +{ + inline NzPhysWorld& PhysicsSystem::GetWorld() + { + return m_world; + } + + inline const NzPhysWorld& PhysicsSystem::GetWorld() const + { + return m_world; + } +} diff --git a/SDK/include/NDK/Systems/StaticCollisionSystem.hpp b/SDK/include/NDK/Systems/StaticCollisionSystem.hpp new file mode 100644 index 000000000..edaa6b0e2 --- /dev/null +++ b/SDK/include/NDK/Systems/StaticCollisionSystem.hpp @@ -0,0 +1,29 @@ +// 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_STATICCOLLISIONSYSTEM_HPP +#define NDK_SYSTEMS_STATICCOLLISIONSYSTEM_HPP + +#include + +namespace Ndk +{ + class NDK_API StaticCollisionSystem : public System + { + public: + StaticCollisionSystem(); + StaticCollisionSystem(const StaticCollisionSystem& system) = default; + ~StaticCollisionSystem() = default; + + void Update(float elapsedTime); + + static SystemIndex systemIndex; + }; +} + +#include + +#endif // NDK_SYSTEMS_STATICCOLLISIONSYSTEM_HPP diff --git a/SDK/include/NDK/Systems/StaticCollisionSystem.inl b/SDK/include/NDK/Systems/StaticCollisionSystem.inl new file mode 100644 index 000000000..668f8b9e2 --- /dev/null +++ b/SDK/include/NDK/Systems/StaticCollisionSystem.inl @@ -0,0 +1,7 @@ +// 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 +{ +} diff --git a/SDK/src/NDK/Components/CollisionComponent.cpp b/SDK/src/NDK/Components/CollisionComponent.cpp new file mode 100644 index 000000000..827a698ac --- /dev/null +++ b/SDK/src/NDK/Components/CollisionComponent.cpp @@ -0,0 +1,67 @@ +// 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 +{ + void CollisionComponent::SetGeom(NzPhysGeomRef geom) + { + m_geom = std::move(geom); + + if (m_entity->HasComponent()) + { + // On met à jour la géométrie du PhysObject associé au PhysicsComponent + PhysicsComponent& physComponent = m_entity->GetComponent(); + physComponent.GetPhysObject().SetGeom(m_geom); + } + else + { + NazaraAssert(m_staticBody, "An entity without physics component should have a static body"); + m_staticBody->SetGeom(m_geom); + } + } + + void CollisionComponent::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"); + NzPhysWorld& physWorld = entityWorld->GetSystem().GetWorld(); + + m_staticBody.reset(new NzPhysObject(&physWorld, m_geom)); + m_staticBody->EnableAutoSleep(false); + } + + void CollisionComponent::OnAttached() + { + if (!m_entity->HasComponent()) + InitializeStaticBody(); + } + + void CollisionComponent::OnComponentAttached(BaseComponent& component) + { + if (component.GetIndex() == GetComponentIndex()) + m_staticBody.reset(); + } + + void CollisionComponent::OnComponentDetached(BaseComponent& component) + { + if (component.GetIndex() == GetComponentIndex()) + InitializeStaticBody(); + } + + void CollisionComponent::OnDetached() + { + m_staticBody.reset(); + } + + ComponentIndex CollisionComponent::componentIndex; +} diff --git a/SDK/src/NDK/Components/PhysicsComponent.cpp b/SDK/src/NDK/Components/PhysicsComponent.cpp new file mode 100644 index 000000000..d900b46d7 --- /dev/null +++ b/SDK/src/NDK/Components/PhysicsComponent.cpp @@ -0,0 +1,59 @@ +// 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 +{ + void PhysicsComponent::OnAttached() + { + World* entityWorld = m_entity->GetWorld(); + NazaraAssert(entityWorld->HasSystem(), "World must have a physics system"); + + NzPhysWorld& world = entityWorld->GetSystem().GetWorld(); + + NzPhysGeomRef geom; + if (m_entity->HasComponent()) + geom = m_entity->GetComponent().GetGeom(); + + NzMatrix4f matrix; + if (m_entity->HasComponent()) + matrix = m_entity->GetComponent().GetTransformMatrix(); + else + matrix.MakeIdentity(); + + m_object.reset(new NzPhysObject(&world, geom, matrix)); + m_object->SetMass(1.f); + } + + void PhysicsComponent::OnComponentAttached(BaseComponent& component) + { + if (component.GetIndex() == GetComponentIndex()) + { + NazaraAssert(m_object, "Invalid object"); + m_object->SetGeom(static_cast(component).GetGeom()); + } + } + + void PhysicsComponent::OnComponentDetached(BaseComponent& component) + { + if (component.GetIndex() == GetComponentIndex()) + { + NazaraAssert(m_object, "Invalid object"); + m_object->SetGeom(NzNullGeom::New()); + } + } + + void PhysicsComponent::OnDetached() + { + m_object.reset(); + } + + ComponentIndex PhysicsComponent::componentIndex; +} diff --git a/SDK/src/NDK/Sdk.cpp b/SDK/src/NDK/Sdk.cpp index 6d2bff6d4..6537dffe5 100644 --- a/SDK/src/NDK/Sdk.cpp +++ b/SDK/src/NDK/Sdk.cpp @@ -13,10 +13,14 @@ #include #include #include +#include #include #include +#include #include #include +#include +#include #include namespace Ndk @@ -49,12 +53,16 @@ namespace Ndk BaseSystem::Initialize(); // Composants + InitializeComponent("NdkColli"); InitializeComponent("NdkList"); InitializeComponent("NdkNode"); + InitializeComponent("NdkPhys"); InitializeComponent("NdkVeloc"); // Systèmes InitializeSystem(); + InitializeSystem(); + InitializeSystem(); InitializeSystem(); NazaraNotice("Initialized: SDK"); diff --git a/SDK/src/NDK/Systems/PhysicsSystem.cpp b/SDK/src/NDK/Systems/PhysicsSystem.cpp new file mode 100644 index 000000000..d171e1697 --- /dev/null +++ b/SDK/src/NDK/Systems/PhysicsSystem.cpp @@ -0,0 +1,40 @@ +// 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 +{ + PhysicsSystem::PhysicsSystem() + { + Requires(); + } + + PhysicsSystem::PhysicsSystem(const PhysicsSystem& system) : + System(system), + m_world() + { + } + + void PhysicsSystem::Update(float elapsedTime) + { + m_world.Step(elapsedTime); + + for (const Ndk::EntityHandle& entity : GetEntities()) + { + NodeComponent& node = entity->GetComponent(); + PhysicsComponent& phys = entity->GetComponent(); + + NzPhysObject& physObj = phys.GetPhysObject(); + node.SetRotation(physObj.GetRotation(), nzCoordSys_Global); + node.SetPosition(physObj.GetPosition(), nzCoordSys_Global); + } + } + + SystemIndex PhysicsSystem::systemIndex; +} diff --git a/SDK/src/NDK/Systems/StaticCollisionSystem.cpp b/SDK/src/NDK/Systems/StaticCollisionSystem.cpp new file mode 100644 index 000000000..4ac3deb24 --- /dev/null +++ b/SDK/src/NDK/Systems/StaticCollisionSystem.cpp @@ -0,0 +1,60 @@ +// 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 + +namespace Ndk +{ + StaticCollisionSystem::StaticCollisionSystem() + { + Requires(); + Excludes(); + } + + void StaticCollisionSystem::Update(float elapsedTime) + { + float invElapsedTime = 1.f / elapsedTime; + for (const Ndk::EntityHandle& entity : GetEntities()) + { + CollisionComponent& collision = entity->GetComponent(); + NodeComponent& node = entity->GetComponent(); + + NzPhysObject* physObj = collision.GetStaticBody(); + + NzQuaternionf oldRotation = physObj->GetRotation(); + NzVector3f oldPosition = physObj->GetPosition(); + NzQuaternionf newRotation = node.GetRotation(nzCoordSys_Global); + NzVector3f newPosition = node.GetPosition(nzCoordSys_Global); + + // Pour déplacer des objets statiques et assurer les collisions, il faut leur définir une vitesse + // (note importante: le moteur physique n'applique pas la vitesse sur les objets statiques) + if (newPosition != oldPosition) + { + physObj->SetPosition(newPosition); + physObj->SetVelocity((newPosition - oldPosition) * invElapsedTime); + } + else + physObj->SetVelocity(NzVector3f::Zero()); + + if (newRotation != oldRotation) + { + NzQuaternionf transition = newRotation * oldRotation.GetConjugate(); + NzEulerAnglesf angles = transition.ToEulerAngles(); + NzVector3f angularVelocity(NzToRadians(angles.pitch * invElapsedTime), + NzToRadians(angles.yaw * invElapsedTime), + NzToRadians(angles.roll * invElapsedTime)); + + physObj->SetRotation(oldRotation); + physObj->SetAngularVelocity(angularVelocity); + } + else + physObj->SetAngularVelocity(NzVector3f::Zero()); + } + } + + SystemIndex StaticCollisionSystem::systemIndex; +} diff --git a/SDK/src/NDK/Systems/VelocitySystem.cpp b/SDK/src/NDK/Systems/VelocitySystem.cpp index 415889e20..a3968a053 100644 --- a/SDK/src/NDK/Systems/VelocitySystem.cpp +++ b/SDK/src/NDK/Systems/VelocitySystem.cpp @@ -4,6 +4,7 @@ #include #include +#include #include namespace Ndk @@ -11,6 +12,7 @@ namespace Ndk VelocitySystem::VelocitySystem() { Requires(); + Excludes(); } void VelocitySystem::Update(float elapsedTime) diff --git a/SDK/src/NDK/World.cpp b/SDK/src/NDK/World.cpp index c1a91fa10..79d84ffcf 100644 --- a/SDK/src/NDK/World.cpp +++ b/SDK/src/NDK/World.cpp @@ -5,6 +5,8 @@ #include #include #include +#include +#include #include namespace Ndk @@ -18,6 +20,8 @@ namespace Ndk void World::AddDefaultSystems() { AddSystem(); + AddSystem(); + AddSystem(); AddSystem(); }