Merge branch 'NDK' of https://github.com/DigitalPulseSoftware/NazaraEngine into NDK
Former-commit-id: 6e7a2cff46d6e077a3ee4434dd9f1a4a7fd00bb5
This commit is contained in:
commit
385b7fc3fd
|
|
@ -16,6 +16,8 @@ namespace Ndk
|
||||||
template<typename SystemType> constexpr SystemIndex GetSystemIndex();
|
template<typename SystemType> constexpr SystemIndex GetSystemIndex();
|
||||||
template<typename ComponentType, unsigned int N> ComponentIndex InitializeComponent(const char (&name)[N]);
|
template<typename ComponentType, unsigned int N> ComponentIndex InitializeComponent(const char (&name)[N]);
|
||||||
template<typename SystemType> SystemIndex InitializeSystem();
|
template<typename SystemType> SystemIndex InitializeSystem();
|
||||||
|
template<typename ComponentType, typename C> bool IsComponent(C& component);
|
||||||
|
template<typename SystemType, typename S> bool IsSystem(S& system);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <Ndk/Algorithm.inl>
|
#include <Ndk/Algorithm.inl>
|
||||||
|
|
|
||||||
|
|
@ -44,4 +44,16 @@ namespace Ndk
|
||||||
SystemType::systemIndex = SystemType::RegisterSystem();
|
SystemType::systemIndex = SystemType::RegisterSystem();
|
||||||
return SystemType::systemIndex;
|
return SystemType::systemIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename ComponentType, typename C>
|
||||||
|
bool IsComponent(C& component)
|
||||||
|
{
|
||||||
|
return component.GetIndex() == GetComponentIndex<ComponentType>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename SystemType, typename S>
|
||||||
|
bool IsSystem(S& system)
|
||||||
|
{
|
||||||
|
return system.GetIndex() == GetSystemIndex<SystemType>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,11 @@
|
||||||
|
|
||||||
namespace Ndk
|
namespace Ndk
|
||||||
{
|
{
|
||||||
|
class Entity;
|
||||||
|
|
||||||
class NDK_API BaseComponent
|
class NDK_API BaseComponent
|
||||||
{
|
{
|
||||||
|
friend Entity;
|
||||||
friend class Sdk;
|
friend class Sdk;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -35,10 +38,17 @@ namespace Ndk
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ComponentIndex m_componentIndex;
|
ComponentIndex m_componentIndex;
|
||||||
|
Entity* m_entity;
|
||||||
|
|
||||||
static ComponentIndex RegisterComponent(ComponentId id, Factory factoryFunc);
|
static ComponentIndex RegisterComponent(ComponentId id, Factory factoryFunc);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
virtual void OnAttached();
|
||||||
|
virtual void OnComponentAttached(BaseComponent& component);
|
||||||
|
virtual void OnComponentDetached(BaseComponent& component);
|
||||||
|
virtual void OnDetached();
|
||||||
|
void SetEntity(Entity* entity);
|
||||||
|
|
||||||
static bool Initialize();
|
static bool Initialize();
|
||||||
static void Uninitialize();
|
static void Uninitialize();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,8 @@
|
||||||
namespace Ndk
|
namespace Ndk
|
||||||
{
|
{
|
||||||
inline BaseComponent::BaseComponent(ComponentIndex index) :
|
inline BaseComponent::BaseComponent(ComponentIndex index) :
|
||||||
m_componentIndex(index)
|
m_componentIndex(index),
|
||||||
|
m_entity(nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -35,6 +36,19 @@ namespace Ndk
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void BaseComponent::SetEntity(Entity* entity)
|
||||||
|
{
|
||||||
|
if (m_entity != entity)
|
||||||
|
{
|
||||||
|
if (m_entity)
|
||||||
|
OnDetached();
|
||||||
|
|
||||||
|
m_entity = entity;
|
||||||
|
if (m_entity)
|
||||||
|
OnAttached();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline bool BaseComponent::Initialize()
|
inline bool BaseComponent::Initialize()
|
||||||
{
|
{
|
||||||
// Rien à faire
|
// Rien à faire
|
||||||
|
|
|
||||||
|
|
@ -51,16 +51,23 @@ namespace Ndk
|
||||||
template<typename ComponentType1, typename ComponentType2, typename... Rest> void Requires();
|
template<typename ComponentType1, typename ComponentType2, typename... Rest> void Requires();
|
||||||
void RequiresComponent(ComponentIndex index);
|
void RequiresComponent(ComponentIndex index);
|
||||||
|
|
||||||
|
template<typename ComponentType> void RequiresAny();
|
||||||
|
template<typename ComponentType1, typename ComponentType2, typename... Rest> void RequiresAny();
|
||||||
|
void RequiresAnyComponent(ComponentIndex index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void AddEntity(Entity* entity);
|
void AddEntity(Entity* entity);
|
||||||
|
|
||||||
virtual void OnEntityAdded(Entity* entity);
|
virtual void OnEntityAdded(Entity* entity);
|
||||||
virtual void OnEntityRemoved(Entity* entity);
|
virtual void OnEntityRemoved(Entity* entity);
|
||||||
|
virtual void OnEntityValidation(Entity* entity, bool justAdded);
|
||||||
|
|
||||||
void RemoveEntity(Entity* entity);
|
void RemoveEntity(Entity* entity);
|
||||||
|
|
||||||
void SetWorld(World& world);
|
void SetWorld(World& world);
|
||||||
|
|
||||||
|
void ValidateEntity(Entity* entity, bool justAdded);
|
||||||
|
|
||||||
static bool Initialize();
|
static bool Initialize();
|
||||||
static void Uninitialize();
|
static void Uninitialize();
|
||||||
|
|
||||||
|
|
@ -68,6 +75,7 @@ namespace Ndk
|
||||||
NzBitset<nzUInt64> m_entityBits;
|
NzBitset<nzUInt64> m_entityBits;
|
||||||
NzBitset<> m_excludedComponents;
|
NzBitset<> m_excludedComponents;
|
||||||
mutable NzBitset<> m_filterResult;
|
mutable NzBitset<> m_filterResult;
|
||||||
|
NzBitset<> m_requiredAnyComponents;
|
||||||
NzBitset<> m_requiredComponents;
|
NzBitset<> m_requiredComponents;
|
||||||
SystemIndex m_systemIndex;
|
SystemIndex m_systemIndex;
|
||||||
World* m_world;
|
World* m_world;
|
||||||
|
|
|
||||||
|
|
@ -87,11 +87,31 @@ namespace Ndk
|
||||||
m_requiredComponents.UnboundedSet(index);
|
m_requiredComponents.UnboundedSet(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename ComponentType>
|
||||||
|
void BaseSystem::RequiresAny()
|
||||||
|
{
|
||||||
|
static_assert(std::is_base_of<BaseComponent, ComponentType>(), "ComponentType is not a component");
|
||||||
|
|
||||||
|
RequiresAnyComponent(GetComponentIndex<ComponentType>());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ComponentType1, typename ComponentType2, typename... Rest>
|
||||||
|
void BaseSystem::RequiresAny()
|
||||||
|
{
|
||||||
|
RequiresAny<ComponentType1>();
|
||||||
|
RequiresAny<ComponentType2, Rest...>();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void BaseSystem::RequiresAnyComponent(ComponentIndex index)
|
||||||
|
{
|
||||||
|
m_requiredAnyComponents.UnboundedSet(index);
|
||||||
|
}
|
||||||
|
|
||||||
inline void BaseSystem::AddEntity(Entity* entity)
|
inline void BaseSystem::AddEntity(Entity* entity)
|
||||||
{
|
{
|
||||||
NazaraAssert(entity, "Invalid entity");
|
NazaraAssert(entity, "Invalid entity");
|
||||||
|
|
||||||
m_entities.push_back(entity->CreateHandle());
|
m_entities.emplace_back(entity);
|
||||||
m_entityBits.UnboundedSet(entity->GetId(), true);
|
m_entityBits.UnboundedSet(entity->GetId(), true);
|
||||||
|
|
||||||
entity->RegisterSystem(m_systemIndex);
|
entity->RegisterSystem(m_systemIndex);
|
||||||
|
|
@ -116,6 +136,14 @@ namespace Ndk
|
||||||
OnEntityRemoved(entity); // Et on appelle le callback
|
OnEntityRemoved(entity); // Et on appelle le callback
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void BaseSystem::ValidateEntity(Entity* entity, bool justAdded)
|
||||||
|
{
|
||||||
|
NazaraAssert(entity, "Invalid entity");
|
||||||
|
NazaraAssert(HasEntity(entity), "Entity should be part of system");
|
||||||
|
|
||||||
|
OnEntityValidation(entity, justAdded);
|
||||||
|
}
|
||||||
|
|
||||||
inline void BaseSystem::SetWorld(World& world)
|
inline void BaseSystem::SetWorld(World& world)
|
||||||
{
|
{
|
||||||
m_world = &world;
|
m_world = &world;
|
||||||
|
|
@ -132,5 +160,4 @@ namespace Ndk
|
||||||
{
|
{
|
||||||
// Rien à faire
|
// Rien à faire
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ namespace Ndk
|
||||||
BaseComponent* Component<ComponentType>::Clone() const
|
BaseComponent* Component<ComponentType>::Clone() const
|
||||||
{
|
{
|
||||||
///FIXME: Pas encore supporté par GCC (4.9.2)
|
///FIXME: Pas encore supporté par GCC (4.9.2)
|
||||||
//static_assert(std::is_trivially_copy_constructible<ComponentType>::value, "ComponentType should be copy-constructible");
|
//static_assert(std::is_trivially_copy_constructible<ComponentType>::value, "ComponentType must be copy-constructible");
|
||||||
|
|
||||||
return new ComponentType(static_cast<const ComponentType&>(*this));
|
return new ComponentType(static_cast<const ComponentType&>(*this));
|
||||||
}
|
}
|
||||||
|
|
@ -29,7 +29,7 @@ namespace Ndk
|
||||||
ComponentIndex Component<ComponentType>::RegisterComponent(ComponentId id)
|
ComponentIndex Component<ComponentType>::RegisterComponent(ComponentId id)
|
||||||
{
|
{
|
||||||
// Il faut que notre composant possède un constructeur par défaut (pour la factory)
|
// Il faut que notre composant possède un constructeur par défaut (pour la factory)
|
||||||
static_assert(std::is_default_constructible<ComponentType>::value, "ComponentType should be default-constructible");
|
static_assert(std::is_default_constructible<ComponentType>::value, "ComponentType must be default-constructible");
|
||||||
|
|
||||||
// On utilise les lambda pour créer une fonction factory
|
// On utilise les lambda pour créer une fonction factory
|
||||||
auto factory = []() -> BaseComponent*
|
auto factory = []() -> BaseComponent*
|
||||||
|
|
@ -37,8 +37,6 @@ namespace Ndk
|
||||||
return new ComponentType;
|
return new ComponentType;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Je ne sais pas si c'est un bug de GCC ou si c'est quelque chose que j'ai mal compris
|
|
||||||
// mais le fait est que ça ne compile pas si je ne précise pas Basecomponent::
|
|
||||||
return BaseComponent::RegisterComponent(id, factory);
|
return BaseComponent::RegisterComponent(id, factory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 <Nazara/Physics/Geom.hpp>
|
||||||
|
#include <NDK/Component.hpp>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class NzPhysObject;
|
||||||
|
|
||||||
|
namespace Ndk
|
||||||
|
{
|
||||||
|
class Entity;
|
||||||
|
|
||||||
|
class NDK_API CollisionComponent : public Component<CollisionComponent>
|
||||||
|
{
|
||||||
|
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<NzPhysObject> m_staticBody;
|
||||||
|
NzPhysGeomRef m_geom;
|
||||||
|
bool m_bodyUpdated;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <NDK/Components/CollisionComponent.inl>
|
||||||
|
|
||||||
|
#endif // NDK_COMPONENTS_COLLISIONCOMPONENT_HPP
|
||||||
|
|
@ -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 <NDK/Entity.hpp>
|
||||||
|
#include <NDK/World.hpp>
|
||||||
|
#include <NDK/Components/PhysicsComponent.hpp>
|
||||||
|
#include <NDK/Systems/PhysicsSystem.hpp>
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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 <Nazara/Physics/PhysObject.hpp>
|
||||||
|
#include <NDK/Component.hpp>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace Ndk
|
||||||
|
{
|
||||||
|
class Entity;
|
||||||
|
|
||||||
|
class NDK_API PhysicsComponent : public Component<PhysicsComponent>
|
||||||
|
{
|
||||||
|
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<NzPhysObject> m_object;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <NDK/Components/PhysicsComponent.inl>
|
||||||
|
|
||||||
|
#endif // NDK_COMPONENTS_PHYSICSCOMPONENT_HPP
|
||||||
|
|
@ -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 <Nazara/Core/Error.hpp>
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -80,6 +80,11 @@ namespace Ndk
|
||||||
return HasComponent(index);
|
return HasComponent(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool Entity::IsValid() const
|
||||||
|
{
|
||||||
|
return m_valid;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename ComponentType>
|
template<typename ComponentType>
|
||||||
void Entity::RemoveComponent()
|
void Entity::RemoveComponent()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
// 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_ENTITYLIST_HPP
|
||||||
|
#define NDK_ENTITYLIST_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Core/Bitset.hpp>
|
||||||
|
#include <NDK/Prerequesites.hpp>
|
||||||
|
#include <NDK/EntityHandle.hpp>
|
||||||
|
|
||||||
|
namespace Ndk
|
||||||
|
{
|
||||||
|
class NDK_API EntityList
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using Container = std::vector<EntityHandle>;
|
||||||
|
|
||||||
|
EntityList() = default;
|
||||||
|
~EntityList() = default;
|
||||||
|
|
||||||
|
void Clear();
|
||||||
|
|
||||||
|
bool Has(const Entity* entity);
|
||||||
|
bool Has(EntityId entity);
|
||||||
|
|
||||||
|
void Insert(Entity* entity);
|
||||||
|
|
||||||
|
void Remove(Entity* entity);
|
||||||
|
|
||||||
|
// Interface STD
|
||||||
|
Container::iterator begin();
|
||||||
|
Container::const_iterator begin() const;
|
||||||
|
|
||||||
|
Container::const_iterator cbegin() const;
|
||||||
|
Container::const_iterator cend() const;
|
||||||
|
Container::const_reverse_iterator crbegin() const;
|
||||||
|
Container::const_reverse_iterator crend() const;
|
||||||
|
|
||||||
|
bool empty() const;
|
||||||
|
|
||||||
|
Container::iterator end();
|
||||||
|
Container::const_iterator end() const;
|
||||||
|
|
||||||
|
Container::reverse_iterator rbegin();
|
||||||
|
Container::const_reverse_iterator rbegin() const;
|
||||||
|
|
||||||
|
Container::reverse_iterator rend();
|
||||||
|
Container::const_reverse_iterator rend() const;
|
||||||
|
|
||||||
|
Container::size_type size() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<EntityHandle> m_entities;
|
||||||
|
NzBitset<nzUInt64> m_entityBits;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <NDK/EntityList.inl>
|
||||||
|
|
||||||
|
#endif // NDK_ENTITYLIST_HPP
|
||||||
|
|
@ -0,0 +1,117 @@
|
||||||
|
// 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 <Nazara/Core/Error.hpp>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace Ndk
|
||||||
|
{
|
||||||
|
inline void EntityList::Clear()
|
||||||
|
{
|
||||||
|
m_entities.clear();
|
||||||
|
m_entityBits.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool EntityList::Has(const Entity* entity)
|
||||||
|
{
|
||||||
|
return entity && entity->IsValid() && Has(entity->GetId());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool EntityList::Has(EntityId entity)
|
||||||
|
{
|
||||||
|
return m_entityBits.UnboundedTest(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void EntityList::Insert(Entity* entity)
|
||||||
|
{
|
||||||
|
if (!Has(entity))
|
||||||
|
{
|
||||||
|
m_entities.emplace_back(entity);
|
||||||
|
m_entityBits.UnboundedSet(entity->GetId(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void EntityList::Remove(Entity* entity)
|
||||||
|
{
|
||||||
|
if (Has(entity))
|
||||||
|
{
|
||||||
|
auto it = std::find(m_entities.begin(), m_entities.end(), *entity);
|
||||||
|
NazaraAssert(it != m_entities.end(), "Entity should be part of the vector");
|
||||||
|
|
||||||
|
std::swap(*it, m_entities.back());
|
||||||
|
m_entities.pop_back(); // On le sort du vector
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interface STD
|
||||||
|
inline EntityList::Container::iterator EntityList::begin()
|
||||||
|
{
|
||||||
|
return m_entities.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline EntityList::Container::const_iterator EntityList::begin() const
|
||||||
|
{
|
||||||
|
return m_entities.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline EntityList::Container::const_iterator EntityList::cbegin() const
|
||||||
|
{
|
||||||
|
return m_entities.cbegin();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline EntityList::Container::const_iterator EntityList::cend() const
|
||||||
|
{
|
||||||
|
return m_entities.cend();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline EntityList::Container::const_reverse_iterator EntityList::crbegin() const
|
||||||
|
{
|
||||||
|
return m_entities.crbegin();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline EntityList::Container::const_reverse_iterator EntityList::crend() const
|
||||||
|
{
|
||||||
|
return m_entities.crend();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool EntityList::empty() const
|
||||||
|
{
|
||||||
|
return m_entities.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline EntityList::Container::iterator EntityList::end()
|
||||||
|
{
|
||||||
|
return m_entities.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline EntityList::Container::const_iterator EntityList::end() const
|
||||||
|
{
|
||||||
|
return m_entities.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline EntityList::Container::reverse_iterator EntityList::rbegin()
|
||||||
|
{
|
||||||
|
return m_entities.rbegin();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline EntityList::Container::const_reverse_iterator EntityList::rbegin() const
|
||||||
|
{
|
||||||
|
return m_entities.rbegin();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline EntityList::Container::reverse_iterator EntityList::rend()
|
||||||
|
{
|
||||||
|
return m_entities.rend();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline EntityList::Container::const_reverse_iterator EntityList::rend() const
|
||||||
|
{
|
||||||
|
return m_entities.rend();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline EntityList::Container::size_type EntityList::size() const
|
||||||
|
{
|
||||||
|
return m_entities.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
// 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 <Nazara/Physics/PhysWorld.hpp>
|
||||||
|
#include <NDK/EntityList.hpp>
|
||||||
|
#include <NDK/System.hpp>
|
||||||
|
|
||||||
|
namespace Ndk
|
||||||
|
{
|
||||||
|
class NDK_API PhysicsSystem : public System<PhysicsSystem>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PhysicsSystem();
|
||||||
|
PhysicsSystem(const PhysicsSystem& system);
|
||||||
|
~PhysicsSystem() = default;
|
||||||
|
|
||||||
|
NzPhysWorld& GetWorld();
|
||||||
|
const NzPhysWorld& GetWorld() const;
|
||||||
|
|
||||||
|
void Update(float elapsedTime);
|
||||||
|
|
||||||
|
static SystemIndex systemIndex;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void OnEntityValidation(Entity* entity, bool justAdded) override;
|
||||||
|
|
||||||
|
EntityList m_dynamicObjects;
|
||||||
|
EntityList m_staticObjects;
|
||||||
|
NzPhysWorld m_world;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <NDK/Systems/PhysicsSystem.inl>
|
||||||
|
|
||||||
|
#endif // NDK_SYSTEMS_PHYSICSSYSTEM_HPP
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,6 +8,24 @@ namespace Ndk
|
||||||
{
|
{
|
||||||
BaseComponent::~BaseComponent() = default;
|
BaseComponent::~BaseComponent() = default;
|
||||||
|
|
||||||
|
void BaseComponent::OnAttached()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseComponent::OnComponentAttached(BaseComponent& component)
|
||||||
|
{
|
||||||
|
NazaraUnused(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseComponent::OnComponentDetached(BaseComponent& component)
|
||||||
|
{
|
||||||
|
NazaraUnused(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseComponent::OnDetached()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<BaseComponent::ComponentEntry> BaseComponent::s_entries;
|
std::vector<BaseComponent::ComponentEntry> BaseComponent::s_entries;
|
||||||
std::unordered_map<ComponentId, ComponentIndex> BaseComponent::s_idToIndex;
|
std::unordered_map<ComponentId, ComponentIndex> BaseComponent::s_idToIndex;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,13 @@ namespace Ndk
|
||||||
if (m_filterResult.TestAny())
|
if (m_filterResult.TestAny())
|
||||||
return false; // Au moins un component exclu est présent
|
return false; // Au moins un component exclu est présent
|
||||||
|
|
||||||
|
// Si nous avons une liste de composants nécessaires
|
||||||
|
if (m_requiredAnyComponents.TestAny())
|
||||||
|
{
|
||||||
|
if (!m_requiredAnyComponents.Intersects(components))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -40,5 +47,11 @@ namespace Ndk
|
||||||
NazaraUnused(entity);
|
NazaraUnused(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BaseSystem::OnEntityValidation(Entity* entity, bool justAdded)
|
||||||
|
{
|
||||||
|
NazaraUnused(entity);
|
||||||
|
NazaraUnused(justAdded);
|
||||||
|
}
|
||||||
|
|
||||||
SystemIndex BaseSystem::s_nextIndex;
|
SystemIndex BaseSystem::s_nextIndex;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
// 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 <NDK/Components/CollisionComponent.hpp>
|
||||||
|
#include <Nazara/Physics/PhysObject.hpp>
|
||||||
|
#include <NDK/Algorithm.hpp>
|
||||||
|
#include <NDK/World.hpp>
|
||||||
|
#include <NDK/Components/PhysicsComponent.hpp>
|
||||||
|
#include <NDK/Systems/PhysicsSystem.hpp>
|
||||||
|
|
||||||
|
namespace Ndk
|
||||||
|
{
|
||||||
|
void CollisionComponent::SetGeom(NzPhysGeomRef geom)
|
||||||
|
{
|
||||||
|
m_geom = std::move(geom);
|
||||||
|
|
||||||
|
if (m_entity->HasComponent<PhysicsComponent>())
|
||||||
|
{
|
||||||
|
// On met à jour la géométrie du PhysObject associé au PhysicsComponent
|
||||||
|
PhysicsComponent& physComponent = m_entity->GetComponent<PhysicsComponent>();
|
||||||
|
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<PhysicsSystem>(), "World must have a physics system");
|
||||||
|
NzPhysWorld& physWorld = entityWorld->GetSystem<PhysicsSystem>().GetWorld();
|
||||||
|
|
||||||
|
m_staticBody.reset(new NzPhysObject(&physWorld, m_geom));
|
||||||
|
m_staticBody->EnableAutoSleep(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CollisionComponent::OnAttached()
|
||||||
|
{
|
||||||
|
if (!m_entity->HasComponent<PhysicsComponent>())
|
||||||
|
InitializeStaticBody();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CollisionComponent::OnComponentAttached(BaseComponent& component)
|
||||||
|
{
|
||||||
|
if (IsComponent<PhysicsComponent>(component))
|
||||||
|
m_staticBody.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CollisionComponent::OnComponentDetached(BaseComponent& component)
|
||||||
|
{
|
||||||
|
if (IsComponent<PhysicsComponent>(component))
|
||||||
|
InitializeStaticBody();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CollisionComponent::OnDetached()
|
||||||
|
{
|
||||||
|
m_staticBody.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
ComponentIndex CollisionComponent::componentIndex;
|
||||||
|
}
|
||||||
|
|
@ -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 <NDK/Components/PhysicsComponent.hpp>
|
||||||
|
#include <Nazara/Physics/PhysObject.hpp>
|
||||||
|
#include <NDK/Algorithm.hpp>
|
||||||
|
#include <NDK/World.hpp>
|
||||||
|
#include <NDK/Components/CollisionComponent.hpp>
|
||||||
|
#include <NDK/Components/NodeComponent.hpp>
|
||||||
|
#include <NDK/Systems/PhysicsSystem.hpp>
|
||||||
|
|
||||||
|
namespace Ndk
|
||||||
|
{
|
||||||
|
void PhysicsComponent::OnAttached()
|
||||||
|
{
|
||||||
|
World* entityWorld = m_entity->GetWorld();
|
||||||
|
NazaraAssert(entityWorld->HasSystem<PhysicsSystem>(), "World must have a physics system");
|
||||||
|
|
||||||
|
NzPhysWorld& world = entityWorld->GetSystem<PhysicsSystem>().GetWorld();
|
||||||
|
|
||||||
|
NzPhysGeomRef geom;
|
||||||
|
if (m_entity->HasComponent<CollisionComponent>())
|
||||||
|
geom = m_entity->GetComponent<CollisionComponent>().GetGeom();
|
||||||
|
|
||||||
|
NzMatrix4f matrix;
|
||||||
|
if (m_entity->HasComponent<NodeComponent>())
|
||||||
|
matrix = m_entity->GetComponent<NodeComponent>().GetTransformMatrix();
|
||||||
|
else
|
||||||
|
matrix.MakeIdentity();
|
||||||
|
|
||||||
|
m_object.reset(new NzPhysObject(&world, geom, matrix));
|
||||||
|
m_object->SetMass(1.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhysicsComponent::OnComponentAttached(BaseComponent& component)
|
||||||
|
{
|
||||||
|
if (IsComponent<CollisionComponent>(component))
|
||||||
|
{
|
||||||
|
NazaraAssert(m_object, "Invalid object");
|
||||||
|
m_object->SetGeom(static_cast<CollisionComponent&>(component).GetGeom());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhysicsComponent::OnComponentDetached(BaseComponent& component)
|
||||||
|
{
|
||||||
|
if (IsComponent<CollisionComponent>(component))
|
||||||
|
{
|
||||||
|
NazaraAssert(m_object, "Invalid object");
|
||||||
|
m_object->SetGeom(NzNullGeom::New());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhysicsComponent::OnDetached()
|
||||||
|
{
|
||||||
|
m_object.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
ComponentIndex PhysicsComponent::componentIndex;
|
||||||
|
}
|
||||||
|
|
@ -9,8 +9,11 @@
|
||||||
namespace Ndk
|
namespace Ndk
|
||||||
{
|
{
|
||||||
Entity::Entity(Entity&& entity) :
|
Entity::Entity(Entity&& entity) :
|
||||||
|
m_components(std::move(entity.m_components)),
|
||||||
m_handles(std::move(entity.m_handles)),
|
m_handles(std::move(entity.m_handles)),
|
||||||
m_id(entity.m_id),
|
m_id(entity.m_id),
|
||||||
|
m_componentBits(std::move(entity.m_componentBits)),
|
||||||
|
m_systemBits(std::move(entity.m_systemBits)),
|
||||||
m_world(entity.m_world),
|
m_world(entity.m_world),
|
||||||
m_valid(entity.m_valid)
|
m_valid(entity.m_valid)
|
||||||
{
|
{
|
||||||
|
|
@ -23,24 +26,34 @@ namespace Ndk
|
||||||
Destroy();
|
Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseComponent& Entity::AddComponent(std::unique_ptr<BaseComponent>&& component)
|
BaseComponent& Entity::AddComponent(std::unique_ptr<BaseComponent>&& componentPtr)
|
||||||
{
|
{
|
||||||
NazaraAssert(component, "Component must be valid");
|
NazaraAssert(componentPtr, "Component must be valid");
|
||||||
|
|
||||||
ComponentIndex index = component->GetIndex();
|
ComponentIndex index = componentPtr->GetIndex();
|
||||||
|
|
||||||
// Nous nous assurons que le vecteur de component est suffisamment grand pour contenir le nouveau component
|
// Nous nous assurons que le vecteur de component est suffisamment grand pour contenir le nouveau component
|
||||||
if (index >= m_components.size())
|
if (index >= m_components.size())
|
||||||
m_components.resize(index + 1);
|
m_components.resize(index + 1);
|
||||||
|
|
||||||
// Affectation et retour du component
|
// Affectation et retour du component
|
||||||
m_components[index] = std::move(component);
|
m_components[index] = std::move(componentPtr);
|
||||||
m_componentBits.UnboundedSet(index);
|
m_componentBits.UnboundedSet(index);
|
||||||
|
|
||||||
// On informe le monde que nous avons besoin d'une mise à jour
|
// On informe le monde que nous avons besoin d'une mise à jour
|
||||||
m_world->Invalidate(m_id);
|
m_world->Invalidate(m_id);
|
||||||
|
|
||||||
return *m_components[index].get();
|
// On récupère le component et on informe les composants existants du nouvel arrivant
|
||||||
|
BaseComponent& component = *m_components[index].get();
|
||||||
|
component.SetEntity(this);
|
||||||
|
|
||||||
|
for (unsigned int i = m_componentBits.FindFirst(); i != m_componentBits.npos; i = m_componentBits.FindNext(i))
|
||||||
|
{
|
||||||
|
if (i != index)
|
||||||
|
m_components[index]->OnComponentAttached(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
return component;
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityHandle Entity::CreateHandle()
|
EntityHandle Entity::CreateHandle()
|
||||||
|
|
@ -53,15 +66,14 @@ namespace Ndk
|
||||||
m_world->KillEntity(this);
|
m_world->KillEntity(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Entity::IsValid() const
|
|
||||||
{
|
|
||||||
return m_valid;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Entity::RemoveAllComponents()
|
void Entity::RemoveAllComponents()
|
||||||
{
|
{
|
||||||
|
for (unsigned int i = m_componentBits.FindFirst(); i != m_componentBits.npos; i = m_componentBits.FindNext(i))
|
||||||
|
RemoveComponent(i);
|
||||||
|
|
||||||
|
NazaraAssert(m_componentBits.TestNone(), "All components should be gone");
|
||||||
|
|
||||||
m_components.clear();
|
m_components.clear();
|
||||||
m_componentBits.Clear();
|
|
||||||
|
|
||||||
// On informe le monde que nous avons besoin d'une mise à jour
|
// On informe le monde que nous avons besoin d'une mise à jour
|
||||||
m_world->Invalidate(m_id);
|
m_world->Invalidate(m_id);
|
||||||
|
|
@ -72,6 +84,16 @@ namespace Ndk
|
||||||
///DOC: N'a aucun effet si le component n'est pas présent
|
///DOC: N'a aucun effet si le component n'est pas présent
|
||||||
if (HasComponent(index))
|
if (HasComponent(index))
|
||||||
{
|
{
|
||||||
|
// On récupère le component et on informe les composants du détachement
|
||||||
|
BaseComponent& component = *m_components[index].get();
|
||||||
|
for (unsigned int i = m_componentBits.FindFirst(); i != m_componentBits.npos; i = m_componentBits.FindNext(i))
|
||||||
|
{
|
||||||
|
if (i != index)
|
||||||
|
m_components[index]->OnComponentDetached(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
component.SetEntity(nullptr);
|
||||||
|
|
||||||
m_components[index].reset();
|
m_components[index].reset();
|
||||||
m_componentBits.Reset(index);
|
m_componentBits.Reset(index);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,13 @@
|
||||||
#include <Nazara/Utility/Utility.hpp>
|
#include <Nazara/Utility/Utility.hpp>
|
||||||
#include <NDK/Algorithm.hpp>
|
#include <NDK/Algorithm.hpp>
|
||||||
#include <NDK/BaseSystem.hpp>
|
#include <NDK/BaseSystem.hpp>
|
||||||
|
#include <NDK/Components/CollisionComponent.hpp>
|
||||||
#include <NDK/Components/ListenerComponent.hpp>
|
#include <NDK/Components/ListenerComponent.hpp>
|
||||||
#include <NDK/Components/NodeComponent.hpp>
|
#include <NDK/Components/NodeComponent.hpp>
|
||||||
|
#include <NDK/Components/PhysicsComponent.hpp>
|
||||||
#include <NDK/Components/VelocityComponent.hpp>
|
#include <NDK/Components/VelocityComponent.hpp>
|
||||||
#include <NDK/Systems/ListenerSystem.hpp>
|
#include <NDK/Systems/ListenerSystem.hpp>
|
||||||
|
#include <NDK/Systems/PhysicsSystem.hpp>
|
||||||
#include <NDK/Systems/VelocitySystem.hpp>
|
#include <NDK/Systems/VelocitySystem.hpp>
|
||||||
|
|
||||||
namespace Ndk
|
namespace Ndk
|
||||||
|
|
@ -49,12 +52,15 @@ namespace Ndk
|
||||||
BaseSystem::Initialize();
|
BaseSystem::Initialize();
|
||||||
|
|
||||||
// Composants
|
// Composants
|
||||||
|
InitializeComponent<CollisionComponent>("NdkColli");
|
||||||
InitializeComponent<ListenerComponent>("NdkList");
|
InitializeComponent<ListenerComponent>("NdkList");
|
||||||
InitializeComponent<NodeComponent>("NdkNode");
|
InitializeComponent<NodeComponent>("NdkNode");
|
||||||
|
InitializeComponent<PhysicsComponent>("NdkPhys");
|
||||||
InitializeComponent<VelocityComponent>("NdkVeloc");
|
InitializeComponent<VelocityComponent>("NdkVeloc");
|
||||||
|
|
||||||
// Systèmes
|
// Systèmes
|
||||||
InitializeSystem<ListenerSystem>();
|
InitializeSystem<ListenerSystem>();
|
||||||
|
InitializeSystem<PhysicsSystem>();
|
||||||
InitializeSystem<VelocitySystem>();
|
InitializeSystem<VelocitySystem>();
|
||||||
|
|
||||||
NazaraNotice("Initialized: SDK");
|
NazaraNotice("Initialized: SDK");
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
#include <Nazara/Audio/Audio.hpp>
|
#include <Nazara/Audio/Audio.hpp>
|
||||||
#include <NDK/Components/ListenerComponent.hpp>
|
#include <NDK/Components/ListenerComponent.hpp>
|
||||||
#include <NDK/Components/NodeComponent.hpp>
|
#include <NDK/Components/NodeComponent.hpp>
|
||||||
|
#include <NDK/Components/VelocityComponent.hpp>
|
||||||
|
|
||||||
namespace Ndk
|
namespace Ndk
|
||||||
{
|
{
|
||||||
|
|
@ -16,6 +17,8 @@ namespace Ndk
|
||||||
|
|
||||||
void ListenerSystem::Update(float elapsedTime)
|
void ListenerSystem::Update(float elapsedTime)
|
||||||
{
|
{
|
||||||
|
NazaraUnused(elapsedTime);
|
||||||
|
|
||||||
unsigned int activeListenerCount = 0;
|
unsigned int activeListenerCount = 0;
|
||||||
|
|
||||||
for (const Ndk::EntityHandle& entity : GetEntities())
|
for (const Ndk::EntityHandle& entity : GetEntities())
|
||||||
|
|
@ -25,10 +28,19 @@ namespace Ndk
|
||||||
if (!listener.IsActive())
|
if (!listener.IsActive())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// On récupère la position et la rotation pour les affecter au listener
|
||||||
const NodeComponent& node = entity->GetComponent<NodeComponent>();
|
const NodeComponent& node = entity->GetComponent<NodeComponent>();
|
||||||
NzAudio::SetListenerPosition(node.GetPosition(nzCoordSys_Global));
|
NzAudio::SetListenerPosition(node.GetPosition(nzCoordSys_Global));
|
||||||
NzAudio::SetListenerRotation(node.GetRotation(nzCoordSys_Global));
|
NzAudio::SetListenerRotation(node.GetRotation(nzCoordSys_Global));
|
||||||
|
|
||||||
|
// On vérifie la présence d'une donnée de vitesse, et on l'affecte
|
||||||
|
// (La vitesse du listener Audio ne le fait pas se déplacer, mais affecte par exemple l'effet Doppler)
|
||||||
|
if (entity->HasComponent<VelocityComponent>())
|
||||||
|
{
|
||||||
|
const VelocityComponent& velocity = entity->GetComponent<VelocityComponent>();
|
||||||
|
NzAudio::SetListenerVelocity(velocity.linearVelocity);
|
||||||
|
}
|
||||||
|
|
||||||
activeListenerCount++;
|
activeListenerCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,93 @@
|
||||||
|
// 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 <NDK/Systems/PhysicsSystem.hpp>
|
||||||
|
#include <Nazara/Physics/PhysObject.hpp>
|
||||||
|
#include <NDK/Components/CollisionComponent.hpp>
|
||||||
|
#include <NDK/Components/NodeComponent.hpp>
|
||||||
|
#include <NDK/Components/PhysicsComponent.hpp>
|
||||||
|
|
||||||
|
namespace Ndk
|
||||||
|
{
|
||||||
|
PhysicsSystem::PhysicsSystem()
|
||||||
|
{
|
||||||
|
Requires<NodeComponent>();
|
||||||
|
RequiresAny<CollisionComponent, PhysicsComponent>();
|
||||||
|
}
|
||||||
|
|
||||||
|
PhysicsSystem::PhysicsSystem(const PhysicsSystem& system) :
|
||||||
|
System(system),
|
||||||
|
m_world()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhysicsSystem::Update(float elapsedTime)
|
||||||
|
{
|
||||||
|
m_world.Step(elapsedTime);
|
||||||
|
|
||||||
|
for (const Ndk::EntityHandle& entity : m_dynamicObjects)
|
||||||
|
{
|
||||||
|
NodeComponent& node = entity->GetComponent<NodeComponent>();
|
||||||
|
PhysicsComponent& phys = entity->GetComponent<PhysicsComponent>();
|
||||||
|
|
||||||
|
NzPhysObject& physObj = phys.GetPhysObject();
|
||||||
|
node.SetRotation(physObj.GetRotation(), nzCoordSys_Global);
|
||||||
|
node.SetPosition(physObj.GetPosition(), nzCoordSys_Global);
|
||||||
|
}
|
||||||
|
|
||||||
|
float invElapsedTime = 1.f / elapsedTime;
|
||||||
|
for (const Ndk::EntityHandle& entity : m_staticObjects)
|
||||||
|
{
|
||||||
|
CollisionComponent& collision = entity->GetComponent<CollisionComponent>();
|
||||||
|
NodeComponent& node = entity->GetComponent<NodeComponent>();
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhysicsSystem::OnEntityValidation(Entity* entity, bool justAdded)
|
||||||
|
{
|
||||||
|
// Si l'entité ne vient pas d'être ajoutée au système, il est possible qu'elle fasse partie du mauvais tableau
|
||||||
|
if (!justAdded)
|
||||||
|
{
|
||||||
|
// On prend le tableau inverse de celui dont l'entité devrait faire partie
|
||||||
|
auto& entities = (entity->HasComponent<PhysicsComponent>()) ? m_staticObjects : m_dynamicObjects;
|
||||||
|
entities.Remove(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& entities = (entity->HasComponent<PhysicsComponent>()) ? m_dynamicObjects : m_staticObjects;
|
||||||
|
entities.Insert(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
SystemIndex PhysicsSystem::systemIndex;
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include <NDK/Systems/VelocitySystem.hpp>
|
#include <NDK/Systems/VelocitySystem.hpp>
|
||||||
#include <NDK/Components/NodeComponent.hpp>
|
#include <NDK/Components/NodeComponent.hpp>
|
||||||
|
#include <NDK/Components/PhysicsComponent.hpp>
|
||||||
#include <NDK/Components/VelocityComponent.hpp>
|
#include <NDK/Components/VelocityComponent.hpp>
|
||||||
|
|
||||||
namespace Ndk
|
namespace Ndk
|
||||||
|
|
@ -11,6 +12,7 @@ namespace Ndk
|
||||||
VelocitySystem::VelocitySystem()
|
VelocitySystem::VelocitySystem()
|
||||||
{
|
{
|
||||||
Requires<NodeComponent, VelocityComponent>();
|
Requires<NodeComponent, VelocityComponent>();
|
||||||
|
Excludes<PhysicsComponent>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VelocitySystem::Update(float elapsedTime)
|
void VelocitySystem::Update(float elapsedTime)
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#include <NDK/World.hpp>
|
#include <NDK/World.hpp>
|
||||||
#include <Nazara/Core/Error.hpp>
|
#include <Nazara/Core/Error.hpp>
|
||||||
#include <NDK/Systems/ListenerSystem.hpp>
|
#include <NDK/Systems/ListenerSystem.hpp>
|
||||||
|
#include <NDK/Systems/PhysicsSystem.hpp>
|
||||||
#include <NDK/Systems/VelocitySystem.hpp>
|
#include <NDK/Systems/VelocitySystem.hpp>
|
||||||
|
|
||||||
namespace Ndk
|
namespace Ndk
|
||||||
|
|
@ -18,6 +19,7 @@ namespace Ndk
|
||||||
void World::AddDefaultSystems()
|
void World::AddDefaultSystems()
|
||||||
{
|
{
|
||||||
AddSystem<ListenerSystem>();
|
AddSystem<ListenerSystem>();
|
||||||
|
AddSystem<PhysicsSystem>();
|
||||||
AddSystem<VelocitySystem>();
|
AddSystem<VelocitySystem>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -121,25 +123,30 @@ namespace Ndk
|
||||||
{
|
{
|
||||||
NazaraAssert(i < m_entities.size(), "Entity index out of range");
|
NazaraAssert(i < m_entities.size(), "Entity index out of range");
|
||||||
|
|
||||||
Entity& entity = m_entities[i].entity;
|
Entity* entity = &m_entities[i].entity;
|
||||||
|
|
||||||
// Aucun intérêt de traiter une entité n'existant plus
|
// Aucun intérêt de traiter une entité n'existant plus
|
||||||
if (entity.IsValid())
|
if (entity->IsValid())
|
||||||
{
|
{
|
||||||
for (auto& system : m_systems)
|
for (auto& system : m_systems)
|
||||||
{
|
{
|
||||||
// L'entité est-elle enregistrée comme faisant partie du système ?
|
// L'entité est-elle enregistrée comme faisant partie du système ?
|
||||||
bool partOfSystem = system->HasEntity(&entity);
|
bool partOfSystem = system->HasEntity(entity);
|
||||||
|
|
||||||
// Doit-elle en faire partie ?
|
// Doit-elle en faire partie ?
|
||||||
if (system->Filters(&entity) != partOfSystem)
|
if (system->Filters(entity))
|
||||||
{
|
{
|
||||||
// L'entité n'est pas dans l'état dans lequel elle devrait être vis-à-vis de ce système
|
// L'entité doit faire partie du système, revalidons-là (événement système) ou ajoutons-la au système
|
||||||
// si elle en fait partie, nous devons l'en enlever, et inversément
|
if (!partOfSystem)
|
||||||
if (partOfSystem)
|
system->AddEntity(entity);
|
||||||
system->RemoveEntity(&entity);
|
|
||||||
|
system->ValidateEntity(entity, !partOfSystem);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
system->AddEntity(&entity);
|
{
|
||||||
|
// Elle ne doit pas en faire partie, si elle en faisait partie nous devons la retirer
|
||||||
|
if (partOfSystem)
|
||||||
|
system->RemoveEntity(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -63,9 +63,9 @@ class NzBitset
|
||||||
void Swap(NzBitset& bitset);
|
void Swap(NzBitset& bitset);
|
||||||
|
|
||||||
bool Test(unsigned int bit) const;
|
bool Test(unsigned int bit) const;
|
||||||
bool TestAll();
|
bool TestAll() const;
|
||||||
bool TestAny();
|
bool TestAny() const;
|
||||||
bool TestNone();
|
bool TestNone() const;
|
||||||
|
|
||||||
template<typename T> T To() const;
|
template<typename T> T To() const;
|
||||||
NzString ToString() const;
|
NzString ToString() const;
|
||||||
|
|
|
||||||
|
|
@ -309,7 +309,7 @@ bool NzBitset<Block, Allocator>::Test(unsigned int bit) const
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Block, class Allocator>
|
template<typename Block, class Allocator>
|
||||||
bool NzBitset<Block, Allocator>::TestAll()
|
bool NzBitset<Block, Allocator>::TestAll() const
|
||||||
{
|
{
|
||||||
// Cas particulier du dernier bloc
|
// Cas particulier du dernier bloc
|
||||||
Block lastBlockMask = GetLastBlockMask();
|
Block lastBlockMask = GetLastBlockMask();
|
||||||
|
|
@ -325,7 +325,7 @@ bool NzBitset<Block, Allocator>::TestAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Block, class Allocator>
|
template<typename Block, class Allocator>
|
||||||
bool NzBitset<Block, Allocator>::TestAny()
|
bool NzBitset<Block, Allocator>::TestAny() const
|
||||||
{
|
{
|
||||||
if (m_blocks.empty())
|
if (m_blocks.empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -340,7 +340,7 @@ bool NzBitset<Block, Allocator>::TestAny()
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Block, class Allocator>
|
template<typename Block, class Allocator>
|
||||||
bool NzBitset<Block, Allocator>::TestNone()
|
bool NzBitset<Block, Allocator>::TestNone() const
|
||||||
{
|
{
|
||||||
return !TestAny();
|
return !TestAny();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (C) 2015 Jérôme Leclercq
|
// Copyright (C) 2015 Jérôme Leclercq
|
||||||
// This file is part of the "Nazara Engine - Physics module"
|
// This file is part of the "Nazara Engine - Physics module"
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
|
@ -8,12 +8,17 @@
|
||||||
#define NAZARA_GEOM_HPP
|
#define NAZARA_GEOM_HPP
|
||||||
|
|
||||||
#include <Nazara/Prerequesites.hpp>
|
#include <Nazara/Prerequesites.hpp>
|
||||||
#include <Nazara/Core/PrimitiveList.hpp>
|
|
||||||
#include <Nazara/Core/NonCopyable.hpp>
|
#include <Nazara/Core/NonCopyable.hpp>
|
||||||
|
#include <Nazara/Core/PrimitiveList.hpp>
|
||||||
|
#include <Nazara/Core/ObjectLibrary.hpp>
|
||||||
|
#include <Nazara/Core/ObjectListenerWrapper.hpp>
|
||||||
|
#include <Nazara/Core/ObjectRef.hpp>
|
||||||
|
#include <Nazara/Core/RefCounted.hpp>
|
||||||
#include <Nazara/Math/Box.hpp>
|
#include <Nazara/Math/Box.hpp>
|
||||||
#include <Nazara/Math/Quaternion.hpp>
|
#include <Nazara/Math/Quaternion.hpp>
|
||||||
#include <Nazara/Math/Vector3.hpp>
|
#include <Nazara/Math/Vector3.hpp>
|
||||||
#include <Nazara/Physics/Enums.hpp>
|
#include <Nazara/Physics/Enums.hpp>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
///TODO: CollisionModifier
|
///TODO: CollisionModifier
|
||||||
///TODO: HeightfieldGeom
|
///TODO: HeightfieldGeom
|
||||||
|
|
@ -21,126 +26,246 @@
|
||||||
///TODO: SceneGeom
|
///TODO: SceneGeom
|
||||||
///TODO: TreeGeom
|
///TODO: TreeGeom
|
||||||
|
|
||||||
|
class NzPhysGeom;
|
||||||
class NzPhysWorld;
|
class NzPhysWorld;
|
||||||
struct NewtonCollision;
|
struct NewtonCollision;
|
||||||
|
|
||||||
class NAZARA_API NzBaseGeom : NzNonCopyable
|
using NzPhysGeomConstListener = NzObjectListenerWrapper<const NzPhysGeom>;
|
||||||
|
using NzPhysGeomConstRef = NzObjectRef<const NzPhysGeom>;
|
||||||
|
using NzPhysGeomLibrary = NzObjectLibrary<NzPhysGeom>;
|
||||||
|
using NzPhysGeomListener = NzObjectListenerWrapper<NzPhysGeom>;
|
||||||
|
using NzPhysGeomRef = NzObjectRef<NzPhysGeom>;
|
||||||
|
|
||||||
|
class NAZARA_API NzPhysGeom : public NzRefCounted, NzNonCopyable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NzBaseGeom(NzPhysWorld* physWorld);
|
NzPhysGeom() = default;
|
||||||
virtual ~NzBaseGeom();
|
virtual ~NzPhysGeom();
|
||||||
|
|
||||||
virtual NzBoxf ComputeAABB(const NzVector3f& translation, const NzQuaternionf& rotation, const NzVector3f& scale) const;
|
NzBoxf ComputeAABB(const NzVector3f& translation, const NzQuaternionf& rotation, const NzVector3f& scale) const;
|
||||||
virtual NzBoxf ComputeAABB(const NzMatrix4f& offsetMatrix = NzMatrix4f::Identity()) const;
|
virtual NzBoxf ComputeAABB(const NzMatrix4f& offsetMatrix = NzMatrix4f::Identity(), const NzVector3f& scale = NzVector3f::Unit()) const;
|
||||||
virtual void ComputeInertialMatrix(NzVector3f* inertia, NzVector3f* center) const;
|
virtual void ComputeInertialMatrix(NzVector3f* inertia, NzVector3f* center) const;
|
||||||
virtual float ComputeVolume() const;
|
virtual float ComputeVolume() const;
|
||||||
|
|
||||||
NewtonCollision* GetHandle() const;
|
NewtonCollision* GetHandle(NzPhysWorld* world) const;
|
||||||
virtual nzGeomType GetType() const = 0;
|
virtual nzGeomType GetType() const = 0;
|
||||||
|
|
||||||
NzPhysWorld* GetWorld() const;
|
static NzPhysGeomRef Build(const NzPrimitiveList& list);
|
||||||
|
|
||||||
static NzBaseGeom* Build(NzPhysWorld* physWorld, const NzPrimitiveList& list);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
NewtonCollision* m_collision;
|
virtual NewtonCollision* CreateHandle(NzPhysWorld* world) const = 0;
|
||||||
NzPhysWorld* m_world;
|
|
||||||
|
mutable std::unordered_map<NzPhysWorld*, NewtonCollision*> m_handles;
|
||||||
|
|
||||||
|
static NzPhysGeomLibrary::LibraryMap s_library;
|
||||||
};
|
};
|
||||||
|
|
||||||
class NAZARA_API NzBoxGeom : public NzBaseGeom
|
class NzBoxGeom;
|
||||||
|
|
||||||
|
using NzBoxGeomConstListener = NzObjectListenerWrapper<const NzBoxGeom>;
|
||||||
|
using NzBoxGeomConstRef = NzObjectRef<const NzBoxGeom>;
|
||||||
|
using NzBoxGeomListener = NzObjectListenerWrapper<NzBoxGeom>;
|
||||||
|
using NzBoxGeomRef = NzObjectRef<NzBoxGeom>;
|
||||||
|
|
||||||
|
class NAZARA_API NzBoxGeom : public NzPhysGeom
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NzBoxGeom(NzPhysWorld* physWorld, const NzVector3f& lengths, const NzMatrix4f& transformMatrix = NzMatrix4f::Identity());
|
NzBoxGeom(const NzVector3f& lengths, const NzMatrix4f& transformMatrix = NzMatrix4f::Identity());
|
||||||
NzBoxGeom(NzPhysWorld* physWorld, const NzVector3f& lengths, const NzVector3f& translation, const NzQuaternionf& rotation = NzQuaternionf::Identity());
|
NzBoxGeom(const NzVector3f& lengths, const NzVector3f& translation, const NzQuaternionf& rotation = NzQuaternionf::Identity());
|
||||||
|
|
||||||
|
NzBoxf ComputeAABB(const NzMatrix4f& offsetMatrix = NzMatrix4f::Identity(), const NzVector3f& scale = NzVector3f::Unit()) const override;
|
||||||
|
float ComputeVolume() const override;
|
||||||
|
|
||||||
NzVector3f GetLengths() const;
|
NzVector3f GetLengths() const;
|
||||||
nzGeomType GetType() const override;
|
nzGeomType GetType() const override;
|
||||||
|
|
||||||
|
template<typename... Args> static NzBoxGeomRef New(Args&&... args);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
NewtonCollision* CreateHandle(NzPhysWorld* world) const override;
|
||||||
|
|
||||||
|
NzMatrix4f m_matrix;
|
||||||
NzVector3f m_lengths;
|
NzVector3f m_lengths;
|
||||||
};
|
};
|
||||||
|
|
||||||
class NAZARA_API NzCapsuleGeom : public NzBaseGeom
|
class NzCapsuleGeom;
|
||||||
|
|
||||||
|
using NzCapsuleGeomConstListener = NzObjectListenerWrapper<const NzCapsuleGeom>;
|
||||||
|
using NzCapsuleGeomConstRef = NzObjectRef<const NzCapsuleGeom>;
|
||||||
|
using NzCapsuleGeomListener = NzObjectListenerWrapper<NzCapsuleGeom>;
|
||||||
|
using NzCapsuleGeomRef = NzObjectRef<NzCapsuleGeom>;
|
||||||
|
|
||||||
|
class NAZARA_API NzCapsuleGeom : public NzPhysGeom
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NzCapsuleGeom(NzPhysWorld* physWorld, float length, float radius, const NzMatrix4f& transformMatrix = NzMatrix4f::Identity());
|
NzCapsuleGeom(float length, float radius, const NzMatrix4f& transformMatrix = NzMatrix4f::Identity());
|
||||||
NzCapsuleGeom(NzPhysWorld* physWorld, float length, float radius, const NzVector3f& translation, const NzQuaternionf& rotation = NzQuaternionf::Identity());
|
NzCapsuleGeom(float length, float radius, const NzVector3f& translation, const NzQuaternionf& rotation = NzQuaternionf::Identity());
|
||||||
|
|
||||||
float GetLength() const;
|
float GetLength() const;
|
||||||
float GetRadius() const;
|
float GetRadius() const;
|
||||||
nzGeomType GetType() const override;
|
nzGeomType GetType() const override;
|
||||||
|
|
||||||
|
template<typename... Args> static NzCapsuleGeomRef New(Args&&... args);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
NewtonCollision* CreateHandle(NzPhysWorld* world) const override;
|
||||||
|
|
||||||
|
NzMatrix4f m_matrix;
|
||||||
float m_length;
|
float m_length;
|
||||||
float m_radius;
|
float m_radius;
|
||||||
};
|
};
|
||||||
|
|
||||||
class NAZARA_API NzCompoundGeom : public NzBaseGeom
|
class NzCompoundGeom;
|
||||||
|
|
||||||
|
using NzCompoundGeomConstListener = NzObjectListenerWrapper<const NzCompoundGeom>;
|
||||||
|
using NzCompoundGeomConstRef = NzObjectRef<const NzCompoundGeom>;
|
||||||
|
using NzCompoundGeomListener = NzObjectListenerWrapper<NzCompoundGeom>;
|
||||||
|
using NzCompoundGeomRef = NzObjectRef<NzCompoundGeom>;
|
||||||
|
|
||||||
|
class NAZARA_API NzCompoundGeom : public NzPhysGeom
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NzCompoundGeom(NzPhysWorld* physWorld, NzBaseGeom** geoms, unsigned int geomCount);
|
NzCompoundGeom(NzPhysGeom** geoms, unsigned int geomCount);
|
||||||
|
|
||||||
|
const std::vector<NzPhysGeomRef>& GetGeoms() const;
|
||||||
nzGeomType GetType() const override;
|
nzGeomType GetType() const override;
|
||||||
|
|
||||||
|
template<typename... Args> static NzCompoundGeomRef New(Args&&... args);
|
||||||
|
|
||||||
|
private:
|
||||||
|
NewtonCollision* CreateHandle(NzPhysWorld* world) const override;
|
||||||
|
|
||||||
|
std::vector<NzPhysGeomRef> m_geoms;
|
||||||
};
|
};
|
||||||
|
|
||||||
class NAZARA_API NzConeGeom : public NzBaseGeom
|
class NzConeGeom;
|
||||||
|
|
||||||
|
using NzConeGeomConstListener = NzObjectListenerWrapper<const NzConeGeom>;
|
||||||
|
using NzConeGeomConstRef = NzObjectRef<const NzConeGeom>;
|
||||||
|
using NzConeGeomListener = NzObjectListenerWrapper<NzConeGeom>;
|
||||||
|
using NzConeGeomRef = NzObjectRef<NzConeGeom>;
|
||||||
|
|
||||||
|
class NAZARA_API NzConeGeom : public NzPhysGeom
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NzConeGeom(NzPhysWorld* physWorld, float length, float radius, const NzMatrix4f& transformMatrix = NzMatrix4f::Identity());
|
NzConeGeom(float length, float radius, const NzMatrix4f& transformMatrix = NzMatrix4f::Identity());
|
||||||
NzConeGeom(NzPhysWorld* physWorld, float length, float radius, const NzVector3f& translation, const NzQuaternionf& rotation = NzQuaternionf::Identity());
|
NzConeGeom(float length, float radius, const NzVector3f& translation, const NzQuaternionf& rotation = NzQuaternionf::Identity());
|
||||||
|
|
||||||
float GetLength() const;
|
float GetLength() const;
|
||||||
float GetRadius() const;
|
float GetRadius() const;
|
||||||
nzGeomType GetType() const override;
|
nzGeomType GetType() const override;
|
||||||
|
|
||||||
|
template<typename... Args> static NzConeGeomRef New(Args&&... args);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
NewtonCollision* CreateHandle(NzPhysWorld* world) const override;
|
||||||
|
|
||||||
|
NzMatrix4f m_matrix;
|
||||||
float m_length;
|
float m_length;
|
||||||
float m_radius;
|
float m_radius;
|
||||||
};
|
};
|
||||||
|
|
||||||
class NAZARA_API NzConvexHullGeom : public NzBaseGeom
|
class NzConvexHullGeom;
|
||||||
|
|
||||||
|
using NzConvexHullGeomConstListener = NzObjectListenerWrapper<const NzConvexHullGeom>;
|
||||||
|
using NzConvexHullGeomConstRef = NzObjectRef<const NzConvexHullGeom>;
|
||||||
|
using NzConvexHullGeomListener = NzObjectListenerWrapper<NzConvexHullGeom>;
|
||||||
|
using NzConvexHullGeomRef = NzObjectRef<NzConvexHullGeom>;
|
||||||
|
|
||||||
|
class NAZARA_API NzConvexHullGeom : public NzPhysGeom
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NzConvexHullGeom(NzPhysWorld* physWorld, const void* vertices, unsigned int vertexCount, unsigned int stride = sizeof(NzVector3f), float tolerance = 0.002f, const NzMatrix4f& transformMatrix = NzMatrix4f::Identity());
|
NzConvexHullGeom(const void* vertices, unsigned int vertexCount, unsigned int stride = sizeof(NzVector3f), float tolerance = 0.002f, const NzMatrix4f& transformMatrix = NzMatrix4f::Identity());
|
||||||
NzConvexHullGeom(NzPhysWorld* physWorld, const void* vertices, unsigned int vertexCount, unsigned int stride, float tolerance, const NzVector3f& translation, const NzQuaternionf& rotation = NzQuaternionf::Identity());
|
NzConvexHullGeom(const void* vertices, unsigned int vertexCount, unsigned int stride, float tolerance, const NzVector3f& translation, const NzQuaternionf& rotation = NzQuaternionf::Identity());
|
||||||
|
|
||||||
nzGeomType GetType() const override;
|
nzGeomType GetType() const override;
|
||||||
|
|
||||||
|
template<typename... Args> static NzConvexHullGeomRef New(Args&&... args);
|
||||||
|
|
||||||
|
private:
|
||||||
|
NewtonCollision* CreateHandle(NzPhysWorld* world) const override;
|
||||||
|
|
||||||
|
std::vector<NzVector3f> m_vertices;
|
||||||
|
NzMatrix4f m_matrix;
|
||||||
|
float m_tolerance;
|
||||||
|
unsigned int m_vertexStride;
|
||||||
};
|
};
|
||||||
|
|
||||||
class NAZARA_API NzCylinderGeom : public NzBaseGeom
|
class NzCylinderGeom;
|
||||||
|
|
||||||
|
using NzCylinderGeomConstListener = NzObjectListenerWrapper<const NzCylinderGeom>;
|
||||||
|
using NzCylinderGeomConstRef = NzObjectRef<const NzCylinderGeom>;
|
||||||
|
using NzCylinderGeomListener = NzObjectListenerWrapper<NzCylinderGeom>;
|
||||||
|
using NzCylinderGeomRef = NzObjectRef<NzCylinderGeom>;
|
||||||
|
|
||||||
|
class NAZARA_API NzCylinderGeom : public NzPhysGeom
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NzCylinderGeom(NzPhysWorld* physWorld, float length, float radius, const NzMatrix4f& transformMatrix = NzMatrix4f::Identity());
|
NzCylinderGeom(float length, float radius, const NzMatrix4f& transformMatrix = NzMatrix4f::Identity());
|
||||||
NzCylinderGeom(NzPhysWorld* physWorld, float length, float radius, const NzVector3f& translation, const NzQuaternionf& rotation = NzQuaternionf::Identity());
|
NzCylinderGeom(float length, float radius, const NzVector3f& translation, const NzQuaternionf& rotation = NzQuaternionf::Identity());
|
||||||
|
|
||||||
float GetLength() const;
|
float GetLength() const;
|
||||||
float GetRadius() const;
|
float GetRadius() const;
|
||||||
nzGeomType GetType() const override;
|
nzGeomType GetType() const override;
|
||||||
|
|
||||||
|
template<typename... Args> static NzCylinderGeomRef New(Args&&... args);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
NewtonCollision* CreateHandle(NzPhysWorld* world) const override;
|
||||||
|
|
||||||
|
NzMatrix4f m_matrix;
|
||||||
float m_length;
|
float m_length;
|
||||||
float m_radius;
|
float m_radius;
|
||||||
};
|
};
|
||||||
|
|
||||||
class NAZARA_API NzNullGeom : public NzBaseGeom
|
class NzNullGeom;
|
||||||
|
|
||||||
|
using NzNullGeomConstListener = NzObjectListenerWrapper<const NzNullGeom>;
|
||||||
|
using NzNullGeomConstRef = NzObjectRef<const NzNullGeom>;
|
||||||
|
using NzNullGeomListener = NzObjectListenerWrapper<NzNullGeom>;
|
||||||
|
using NzNullGeomRef = NzObjectRef<NzNullGeom>;
|
||||||
|
|
||||||
|
class NAZARA_API NzNullGeom : public NzPhysGeom
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NzNullGeom(NzPhysWorld* physWorld);
|
NzNullGeom();
|
||||||
|
|
||||||
nzGeomType GetType() const override;
|
nzGeomType GetType() const override;
|
||||||
};
|
|
||||||
|
|
||||||
class NAZARA_API NzSphereGeom : public NzBaseGeom
|
template<typename... Args> static NzNullGeomRef New(Args&&... args);
|
||||||
{
|
|
||||||
public:
|
|
||||||
NzSphereGeom(NzPhysWorld* physWorld, float radius, const NzMatrix4f& transformMatrix = NzMatrix4f::Identity());
|
|
||||||
NzSphereGeom(NzPhysWorld* physWorld, float radius, const NzVector3f& translation, const NzQuaternionf& rotation = NzQuaternionf::Identity());
|
|
||||||
|
|
||||||
NzVector3f GetRadius() const;
|
|
||||||
nzGeomType GetType() const override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NzVector3f m_radius;
|
NewtonCollision* CreateHandle(NzPhysWorld* world) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class NzSphereGeom;
|
||||||
|
|
||||||
|
using NzSphereGeomConstListener = NzObjectListenerWrapper<const NzSphereGeom>;
|
||||||
|
using NzSphereGeomConstRef = NzObjectRef<const NzSphereGeom>;
|
||||||
|
using NzSphereGeomListener = NzObjectListenerWrapper<NzSphereGeom>;
|
||||||
|
using NzSphereGeomRef = NzObjectRef<NzSphereGeom>;
|
||||||
|
|
||||||
|
class NAZARA_API NzSphereGeom : public NzPhysGeom
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NzSphereGeom(float radius, const NzMatrix4f& transformMatrix = NzMatrix4f::Identity());
|
||||||
|
NzSphereGeom(float radius, const NzVector3f& translation, const NzQuaternionf& rotation = NzQuaternionf::Identity());
|
||||||
|
|
||||||
|
NzBoxf ComputeAABB(const NzMatrix4f& offsetMatrix = NzMatrix4f::Identity(), const NzVector3f& scale = NzVector3f::Unit()) const override;
|
||||||
|
float ComputeVolume() const override;
|
||||||
|
|
||||||
|
float GetRadius() const;
|
||||||
|
nzGeomType GetType() const override;
|
||||||
|
|
||||||
|
template<typename... Args> static NzSphereGeomRef New(Args&&... args);
|
||||||
|
|
||||||
|
private:
|
||||||
|
NewtonCollision* CreateHandle(NzPhysWorld* world) const override;
|
||||||
|
|
||||||
|
NzVector3f m_position;
|
||||||
|
float m_radius;
|
||||||
|
};
|
||||||
|
|
||||||
|
#include <Nazara/Physics/Geom.inl>
|
||||||
|
|
||||||
#endif // NAZARA_PHYSWORLD_HPP
|
#endif // NAZARA_PHYSWORLD_HPP
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
// Copyright (C) 2015 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Engine - Physics module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <Nazara/Physics/Debug.hpp>
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
NzBoxGeomRef NzBoxGeom::New(Args&&... args)
|
||||||
|
{
|
||||||
|
std::unique_ptr<NzBoxGeom> object(new NzBoxGeom(std::forward<Args>(args)...));
|
||||||
|
object->SetPersistent(false);
|
||||||
|
|
||||||
|
return object.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
NzCapsuleGeomRef NzCapsuleGeom::New(Args&&... args)
|
||||||
|
{
|
||||||
|
std::unique_ptr<NzCapsuleGeom> object(new NzCapsuleGeom(std::forward<Args>(args)...));
|
||||||
|
object->SetPersistent(false);
|
||||||
|
|
||||||
|
return object.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
NzCompoundGeomRef NzCompoundGeom::New(Args&&... args)
|
||||||
|
{
|
||||||
|
std::unique_ptr<NzCompoundGeom> object(new NzCompoundGeom(std::forward<Args>(args)...));
|
||||||
|
object->SetPersistent(false);
|
||||||
|
|
||||||
|
return object.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
NzConeGeomRef NzConeGeom::New(Args&&... args)
|
||||||
|
{
|
||||||
|
std::unique_ptr<NzConeGeom> object(new NzConeGeom(std::forward<Args>(args)...));
|
||||||
|
object->SetPersistent(false);
|
||||||
|
|
||||||
|
return object.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
NzConvexHullGeomRef NzConvexHullGeom::New(Args&&... args)
|
||||||
|
{
|
||||||
|
std::unique_ptr<NzConvexHullGeom> object(new NzConvexHullGeom(std::forward<Args>(args)...));
|
||||||
|
object->SetPersistent(false);
|
||||||
|
|
||||||
|
return object.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
NzCylinderGeomRef NzCylinderGeom::New(Args&&... args)
|
||||||
|
{
|
||||||
|
std::unique_ptr<NzCylinderGeom> object(new NzCylinderGeom(std::forward<Args>(args)...));
|
||||||
|
object->SetPersistent(false);
|
||||||
|
|
||||||
|
return object.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
NzNullGeomRef NzNullGeom::New(Args&&... args)
|
||||||
|
{
|
||||||
|
std::unique_ptr<NzNullGeom> object(new NzNullGeom(std::forward<Args>(args)...));
|
||||||
|
object->SetPersistent(false);
|
||||||
|
|
||||||
|
return object.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
NzSphereGeomRef NzSphereGeom::New(Args&&... args)
|
||||||
|
{
|
||||||
|
std::unique_ptr<NzSphereGeom> object(new NzSphereGeom(std::forward<Args>(args)...));
|
||||||
|
object->SetPersistent(false);
|
||||||
|
|
||||||
|
return object.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <Nazara/Physics/DebugOff.hpp>
|
||||||
|
|
@ -13,16 +13,18 @@
|
||||||
#include <Nazara/Math/Matrix4.hpp>
|
#include <Nazara/Math/Matrix4.hpp>
|
||||||
#include <Nazara/Math/Quaternion.hpp>
|
#include <Nazara/Math/Quaternion.hpp>
|
||||||
#include <Nazara/Math/Vector3.hpp>
|
#include <Nazara/Math/Vector3.hpp>
|
||||||
|
#include <Nazara/Physics/Geom.hpp>
|
||||||
|
|
||||||
class NzBaseGeom;
|
|
||||||
class NzPhysWorld;
|
class NzPhysWorld;
|
||||||
struct NewtonBody;
|
struct NewtonBody;
|
||||||
|
|
||||||
class NAZARA_API NzPhysObject : NzNonCopyable
|
class NAZARA_API NzPhysObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NzPhysObject(NzPhysWorld* world, const NzMatrix4f& mat = NzMatrix4f::Identity());
|
NzPhysObject(NzPhysWorld* world, const NzMatrix4f& mat = NzMatrix4f::Identity());
|
||||||
NzPhysObject(NzPhysWorld* world, const NzBaseGeom* geom, const NzMatrix4f& mat = NzMatrix4f::Identity());
|
NzPhysObject(NzPhysWorld* world, NzPhysGeomRef geom, const NzMatrix4f& mat = NzMatrix4f::Identity());
|
||||||
|
NzPhysObject(const NzPhysObject& object);
|
||||||
|
NzPhysObject(NzPhysObject&& object);
|
||||||
~NzPhysObject();
|
~NzPhysObject();
|
||||||
|
|
||||||
void AddForce(const NzVector3f& force, nzCoordSys coordSys = nzCoordSys_Global);
|
void AddForce(const NzVector3f& force, nzCoordSys coordSys = nzCoordSys_Global);
|
||||||
|
|
@ -31,7 +33,9 @@ class NAZARA_API NzPhysObject : NzNonCopyable
|
||||||
|
|
||||||
void EnableAutoSleep(bool autoSleep);
|
void EnableAutoSleep(bool autoSleep);
|
||||||
|
|
||||||
|
NzBoxf GetAABB() const;
|
||||||
NzVector3f GetAngularVelocity() const;
|
NzVector3f GetAngularVelocity() const;
|
||||||
|
const NzPhysGeomRef& GetGeom() const;
|
||||||
float GetGravityFactor() const;
|
float GetGravityFactor() const;
|
||||||
NewtonBody* GetHandle() const;
|
NewtonBody* GetHandle() const;
|
||||||
float GetMass() const;
|
float GetMass() const;
|
||||||
|
|
@ -45,11 +49,17 @@ class NAZARA_API NzPhysObject : NzNonCopyable
|
||||||
bool IsMoveable() const;
|
bool IsMoveable() const;
|
||||||
bool IsSleeping() const;
|
bool IsSleeping() const;
|
||||||
|
|
||||||
|
void SetAngularVelocity(const NzVector3f& angularVelocity);
|
||||||
|
void SetGeom(NzPhysGeomRef geom);
|
||||||
void SetGravityFactor(float gravityFactor);
|
void SetGravityFactor(float gravityFactor);
|
||||||
void SetMass(float mass);
|
void SetMass(float mass);
|
||||||
void SetMassCenter(const NzVector3f& center);
|
void SetMassCenter(const NzVector3f& center);
|
||||||
void SetPosition(const NzVector3f& position);
|
void SetPosition(const NzVector3f& position);
|
||||||
void SetRotation(const NzQuaternionf& rotation);
|
void SetRotation(const NzQuaternionf& rotation);
|
||||||
|
void SetVelocity(const NzVector3f& velocity);
|
||||||
|
|
||||||
|
NzPhysObject& operator=(const NzPhysObject& object);
|
||||||
|
NzPhysObject& operator=(NzPhysObject&& object);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void UpdateBody();
|
void UpdateBody();
|
||||||
|
|
@ -57,12 +67,11 @@ class NAZARA_API NzPhysObject : NzNonCopyable
|
||||||
static void TransformCallback(const NewtonBody* body, const float* matrix, int threadIndex);
|
static void TransformCallback(const NewtonBody* body, const float* matrix, int threadIndex);
|
||||||
|
|
||||||
NzMatrix4f m_matrix;
|
NzMatrix4f m_matrix;
|
||||||
|
NzPhysGeomRef m_geom;
|
||||||
NzVector3f m_forceAccumulator;
|
NzVector3f m_forceAccumulator;
|
||||||
NzVector3f m_torqueAccumulator;
|
NzVector3f m_torqueAccumulator;
|
||||||
NewtonBody* m_body;
|
NewtonBody* m_body;
|
||||||
const NzBaseGeom* m_geom;
|
|
||||||
NzPhysWorld* m_world;
|
NzPhysWorld* m_world;
|
||||||
bool m_ownsGeom;
|
|
||||||
float m_gravityFactor;
|
float m_gravityFactor;
|
||||||
float m_mass;
|
float m_mass;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include <Nazara/Prerequesites.hpp>
|
#include <Nazara/Prerequesites.hpp>
|
||||||
#include <Nazara/Utility/BufferMapper.hpp>
|
#include <Nazara/Utility/BufferMapper.hpp>
|
||||||
|
#include <Nazara/Utility/IndexBuffer.hpp>
|
||||||
|
|
||||||
class NzIndexBuffer;
|
class NzIndexBuffer;
|
||||||
class NzIndexIterator;
|
class NzIndexIterator;
|
||||||
|
|
|
||||||
|
|
@ -10,62 +10,79 @@
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
NzBaseGeom* CreateGeomFromPrimitive(NzPhysWorld* physWorld, const NzPrimitive& primitive)
|
NzPhysGeomRef CreateGeomFromPrimitive(const NzPrimitive& primitive)
|
||||||
{
|
{
|
||||||
switch (primitive.type)
|
switch (primitive.type)
|
||||||
{
|
{
|
||||||
case nzPrimitiveType_Box:
|
case nzPrimitiveType_Box:
|
||||||
return new NzBoxGeom(physWorld, primitive.box.lengths, primitive.matrix);
|
return NzBoxGeom::New(primitive.box.lengths, primitive.matrix);
|
||||||
|
|
||||||
case nzPrimitiveType_Cone:
|
case nzPrimitiveType_Cone:
|
||||||
return new NzConeGeom(physWorld, primitive.cone.length, primitive.cone.radius, primitive.matrix);
|
return NzConeGeom::New(primitive.cone.length, primitive.cone.radius, primitive.matrix);
|
||||||
|
|
||||||
case nzPrimitiveType_Plane:
|
case nzPrimitiveType_Plane:
|
||||||
return new NzBoxGeom(physWorld, NzVector3f(primitive.plane.size.x, 0.01f, primitive.plane.size.y), primitive.matrix);
|
return NzBoxGeom::New(NzVector3f(primitive.plane.size.x, 0.01f, primitive.plane.size.y), primitive.matrix);
|
||||||
///TODO: PlaneGeom?
|
///TODO: PlaneGeom?
|
||||||
|
|
||||||
case nzPrimitiveType_Sphere:
|
case nzPrimitiveType_Sphere:
|
||||||
return new NzSphereGeom(physWorld, primitive.sphere.size, primitive.matrix.GetTranslation());
|
return NzSphereGeom::New(primitive.sphere.size, primitive.matrix.GetTranslation());
|
||||||
}
|
}
|
||||||
|
|
||||||
NazaraError("Primitive type not handled (0x" + NzString::Number(primitive.type, 16) + ')');
|
NazaraError("Primitive type not handled (0x" + NzString::Number(primitive.type, 16) + ')');
|
||||||
return nullptr;
|
return NzPhysGeomRef();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NzBaseGeom::NzBaseGeom(NzPhysWorld* physWorld) :
|
NzPhysGeom::~NzPhysGeom()
|
||||||
m_world(physWorld)
|
|
||||||
{
|
{
|
||||||
|
for (auto& pair : m_handles)
|
||||||
|
NewtonDestroyCollision(pair.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
NzBaseGeom::~NzBaseGeom()
|
NzBoxf NzPhysGeom::ComputeAABB(const NzVector3f& translation, const NzQuaternionf& rotation, const NzVector3f& scale) const
|
||||||
{
|
{
|
||||||
NewtonDestroyCollision(m_collision);
|
return ComputeAABB(NzMatrix4f::Transform(translation, rotation), scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
NzBoxf NzBaseGeom::ComputeAABB(const NzVector3f& translation, const NzQuaternionf& rotation, const NzVector3f& scale) const
|
NzBoxf NzPhysGeom::ComputeAABB(const NzMatrix4f& offsetMatrix, const NzVector3f& scale) const
|
||||||
{
|
{
|
||||||
NzVector3f min, max;
|
NzVector3f min, max;
|
||||||
NewtonCollisionCalculateAABB(m_collision, NzMatrix4f::Transform(translation, rotation), min, max);
|
|
||||||
|
|
||||||
// Et on applique le scale à la fin
|
// Si nous n'avons aucune instance, nous en créons une temporaire
|
||||||
|
if (m_handles.empty())
|
||||||
|
{
|
||||||
|
NzPhysWorld world;
|
||||||
|
|
||||||
|
NewtonCollision* collision = CreateHandle(&world);
|
||||||
|
{
|
||||||
|
NewtonCollisionCalculateAABB(collision, offsetMatrix, min, max);
|
||||||
|
}
|
||||||
|
NewtonDestroyCollision(collision);
|
||||||
|
}
|
||||||
|
else // Sinon on utilise une instance au hasard (elles sont toutes identiques de toute façon)
|
||||||
|
NewtonCollisionCalculateAABB(m_handles.begin()->second, offsetMatrix, min, max);
|
||||||
|
|
||||||
return NzBoxf(scale * min, scale * max);
|
return NzBoxf(scale * min, scale * max);
|
||||||
}
|
}
|
||||||
|
|
||||||
NzBoxf NzBaseGeom::ComputeAABB(const NzMatrix4f& offsetMatrix) const
|
void NzPhysGeom::ComputeInertialMatrix(NzVector3f* inertia, NzVector3f* center) const
|
||||||
{
|
|
||||||
NzVector3f min, max;
|
|
||||||
NewtonCollisionCalculateAABB(m_collision, offsetMatrix, min, max);
|
|
||||||
|
|
||||||
return NzBoxf(min, max);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NzBaseGeom::ComputeInertialMatrix(NzVector3f* inertia, NzVector3f* center) const
|
|
||||||
{
|
{
|
||||||
float inertiaMatrix[3];
|
float inertiaMatrix[3];
|
||||||
float origin[3];
|
float origin[3];
|
||||||
|
|
||||||
NewtonConvexCollisionCalculateInertialMatrix(m_collision, inertiaMatrix, origin);
|
// Si nous n'avons aucune instance, nous en créons une temporaire
|
||||||
|
if (m_handles.empty())
|
||||||
|
{
|
||||||
|
NzPhysWorld world;
|
||||||
|
|
||||||
|
NewtonCollision* collision = CreateHandle(&world);
|
||||||
|
{
|
||||||
|
NewtonConvexCollisionCalculateInertialMatrix(collision, inertiaMatrix, origin);
|
||||||
|
}
|
||||||
|
NewtonDestroyCollision(collision);
|
||||||
|
}
|
||||||
|
else // Sinon on utilise une instance au hasard (elles sont toutes identiques de toute façon)
|
||||||
|
NewtonConvexCollisionCalculateInertialMatrix(m_handles.begin()->second, inertiaMatrix, origin);
|
||||||
|
|
||||||
if (inertia)
|
if (inertia)
|
||||||
inertia->Set(inertiaMatrix);
|
inertia->Set(inertiaMatrix);
|
||||||
|
|
@ -74,22 +91,37 @@ void NzBaseGeom::ComputeInertialMatrix(NzVector3f* inertia, NzVector3f* center)
|
||||||
center->Set(origin);
|
center->Set(origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
float NzBaseGeom::ComputeVolume() const
|
float NzPhysGeom::ComputeVolume() const
|
||||||
{
|
{
|
||||||
return NewtonConvexCollisionCalculateVolume(m_collision);
|
float volume;
|
||||||
|
|
||||||
|
// Si nous n'avons aucune instance, nous en créons une temporaire
|
||||||
|
if (m_handles.empty())
|
||||||
|
{
|
||||||
|
NzPhysWorld world;
|
||||||
|
|
||||||
|
NewtonCollision* collision = CreateHandle(&world);
|
||||||
|
{
|
||||||
|
volume = NewtonConvexCollisionCalculateVolume(collision);
|
||||||
|
}
|
||||||
|
NewtonDestroyCollision(collision);
|
||||||
|
}
|
||||||
|
else // Sinon on utilise une instance au hasard (elles sont toutes identiques de toute façon)
|
||||||
|
volume = NewtonConvexCollisionCalculateVolume(m_handles.begin()->second);
|
||||||
|
|
||||||
|
return volume;
|
||||||
}
|
}
|
||||||
|
|
||||||
NewtonCollision* NzBaseGeom::GetHandle() const
|
NewtonCollision* NzPhysGeom::GetHandle(NzPhysWorld* world) const
|
||||||
{
|
{
|
||||||
return m_collision;
|
auto it = m_handles.find(world);
|
||||||
|
if (it == m_handles.end())
|
||||||
|
it = m_handles.insert(std::make_pair(world, CreateHandle(world))).first;
|
||||||
|
|
||||||
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
NzPhysWorld* NzBaseGeom::GetWorld() const
|
NzPhysGeomRef NzPhysGeom::Build(const NzPrimitiveList& list)
|
||||||
{
|
|
||||||
return m_world;
|
|
||||||
}
|
|
||||||
|
|
||||||
NzBaseGeom* NzBaseGeom::Build(NzPhysWorld* physWorld, const NzPrimitiveList& list)
|
|
||||||
{
|
{
|
||||||
unsigned int primitiveCount = list.GetSize();
|
unsigned int primitiveCount = list.GetSize();
|
||||||
|
|
||||||
|
|
@ -103,31 +135,48 @@ NzBaseGeom* NzBaseGeom::Build(NzPhysWorld* physWorld, const NzPrimitiveList& lis
|
||||||
|
|
||||||
if (primitiveCount > 1)
|
if (primitiveCount > 1)
|
||||||
{
|
{
|
||||||
std::vector<NzBaseGeom*> geoms(primitiveCount);
|
std::vector<NzPhysGeom*> geoms(primitiveCount);
|
||||||
|
|
||||||
for (unsigned int i = 0; i < primitiveCount; ++i)
|
for (unsigned int i = 0; i < primitiveCount; ++i)
|
||||||
geoms[i] = CreateGeomFromPrimitive(physWorld, list.GetPrimitive(i));
|
geoms[i] = CreateGeomFromPrimitive(list.GetPrimitive(i));
|
||||||
|
|
||||||
return new NzCompoundGeom(physWorld, &geoms[0], primitiveCount);
|
return NzCompoundGeom::New(&geoms[0], primitiveCount);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return CreateGeomFromPrimitive(physWorld, list.GetPrimitive(0));
|
return CreateGeomFromPrimitive(list.GetPrimitive(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NzPhysGeomLibrary::LibraryMap NzPhysGeom::s_library;
|
||||||
|
|
||||||
/********************************** BoxGeom **********************************/
|
/********************************** BoxGeom **********************************/
|
||||||
|
|
||||||
NzBoxGeom::NzBoxGeom(NzPhysWorld* physWorld, const NzVector3f& lengths, const NzMatrix4f& transformMatrix) :
|
NzBoxGeom::NzBoxGeom(const NzVector3f& lengths, const NzMatrix4f& transformMatrix) :
|
||||||
NzBaseGeom(physWorld),
|
m_matrix(transformMatrix),
|
||||||
m_lengths(lengths)
|
m_lengths(lengths)
|
||||||
{
|
{
|
||||||
m_collision = NewtonCreateBox(physWorld->GetHandle(), lengths.x, lengths.y, lengths.z, 0, transformMatrix);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NzBoxGeom::NzBoxGeom(NzPhysWorld* physWorld, const NzVector3f& lengths, const NzVector3f& translation, const NzQuaternionf& rotation) :
|
NzBoxGeom::NzBoxGeom(const NzVector3f& lengths, const NzVector3f& translation, const NzQuaternionf& rotation) :
|
||||||
NzBoxGeom(physWorld, lengths, NzMatrix4f::Transform(translation, rotation))
|
NzBoxGeom(lengths, NzMatrix4f::Transform(translation, rotation))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NzBoxf NzBoxGeom::ComputeAABB(const NzMatrix4f& offsetMatrix, const NzVector3f& scale) const
|
||||||
|
{
|
||||||
|
NzVector3f halfLengths(m_lengths * 0.5f);
|
||||||
|
|
||||||
|
NzBoxf aabb(-halfLengths.x, -halfLengths.y, -halfLengths.z, m_lengths.x, m_lengths.y, m_lengths.z);
|
||||||
|
aabb.Transform(offsetMatrix, true);
|
||||||
|
aabb *= scale;
|
||||||
|
|
||||||
|
return aabb;
|
||||||
|
}
|
||||||
|
|
||||||
|
float NzBoxGeom::ComputeVolume() const
|
||||||
|
{
|
||||||
|
return m_lengths.x * m_lengths.y * m_lengths.z;
|
||||||
|
}
|
||||||
|
|
||||||
NzVector3f NzBoxGeom::GetLengths() const
|
NzVector3f NzBoxGeom::GetLengths() const
|
||||||
{
|
{
|
||||||
return m_lengths;
|
return m_lengths;
|
||||||
|
|
@ -138,18 +187,22 @@ nzGeomType NzBoxGeom::GetType() const
|
||||||
return nzGeomType_Box;
|
return nzGeomType_Box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NewtonCollision* NzBoxGeom::CreateHandle(NzPhysWorld* world) const
|
||||||
|
{
|
||||||
|
return NewtonCreateBox(world->GetHandle(), m_lengths.x, m_lengths.y, m_lengths.z, 0, m_matrix);
|
||||||
|
}
|
||||||
|
|
||||||
/******************************** CapsuleGeom ********************************/
|
/******************************** CapsuleGeom ********************************/
|
||||||
|
|
||||||
NzCapsuleGeom::NzCapsuleGeom(NzPhysWorld* physWorld, float length, float radius, const NzMatrix4f& transformMatrix) :
|
NzCapsuleGeom::NzCapsuleGeom(float length, float radius, const NzMatrix4f& transformMatrix) :
|
||||||
NzBaseGeom(physWorld),
|
m_matrix(transformMatrix),
|
||||||
m_length(length),
|
m_length(length),
|
||||||
m_radius(radius)
|
m_radius(radius)
|
||||||
{
|
{
|
||||||
m_collision = NewtonCreateCapsule(physWorld->GetHandle(), radius, length, 0, transformMatrix);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NzCapsuleGeom::NzCapsuleGeom(NzPhysWorld* physWorld, float length, float radius, const NzVector3f& translation, const NzQuaternionf& rotation) :
|
NzCapsuleGeom::NzCapsuleGeom(float length, float radius, const NzVector3f& translation, const NzQuaternionf& rotation) :
|
||||||
NzCapsuleGeom(physWorld, length, radius, NzMatrix4f::Transform(translation, rotation))
|
NzCapsuleGeom(length, radius, NzMatrix4f::Transform(translation, rotation))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -168,23 +221,23 @@ nzGeomType NzCapsuleGeom::GetType() const
|
||||||
return nzGeomType_Capsule;
|
return nzGeomType_Capsule;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************* CompoundGeom ********************************/
|
NewtonCollision* NzCapsuleGeom::CreateHandle(NzPhysWorld* world) const
|
||||||
|
|
||||||
NzCompoundGeom::NzCompoundGeom(NzPhysWorld* physWorld, NzBaseGeom** geoms, unsigned int geomCount) :
|
|
||||||
NzBaseGeom(physWorld)
|
|
||||||
{
|
{
|
||||||
m_collision = NewtonCreateCompoundCollision(physWorld->GetHandle(), 0);
|
return NewtonCreateCapsule(world->GetHandle(), m_radius, m_length, 0, m_matrix);
|
||||||
NewtonCompoundCollisionBeginAddRemove(m_collision);
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < geomCount; ++i)
|
|
||||||
{
|
|
||||||
if (geoms[i]->GetType() == nzGeomType_Compound)
|
|
||||||
NazaraError("Cannot add compound geoms to other compound geoms");
|
|
||||||
else
|
|
||||||
NewtonCompoundCollisionAddSubCollision(m_collision, geoms[i]->GetHandle());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NewtonCompoundCollisionEndAddRemove(m_collision);
|
/******************************* CompoundGeom ********************************/
|
||||||
|
|
||||||
|
NzCompoundGeom::NzCompoundGeom(NzPhysGeom** geoms, unsigned int geomCount)
|
||||||
|
{
|
||||||
|
m_geoms.reserve(geomCount);
|
||||||
|
for (unsigned int i = 0; i < geomCount; ++i)
|
||||||
|
m_geoms.emplace_back(geoms[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<NzPhysGeomRef>& NzCompoundGeom::GetGeoms() const
|
||||||
|
{
|
||||||
|
return m_geoms;
|
||||||
}
|
}
|
||||||
|
|
||||||
nzGeomType NzCompoundGeom::GetType() const
|
nzGeomType NzCompoundGeom::GetType() const
|
||||||
|
|
@ -192,18 +245,38 @@ nzGeomType NzCompoundGeom::GetType() const
|
||||||
return nzGeomType_Compound;
|
return nzGeomType_Compound;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NewtonCollision* NzCompoundGeom::CreateHandle(NzPhysWorld* world) const
|
||||||
|
{
|
||||||
|
NewtonCollision* compoundCollision = NewtonCreateCompoundCollision(world->GetHandle(), 0);
|
||||||
|
|
||||||
|
NewtonCompoundCollisionBeginAddRemove(compoundCollision);
|
||||||
|
for (const NzPhysGeomRef& geom : m_geoms)
|
||||||
|
{
|
||||||
|
if (geom->GetType() == nzGeomType_Compound)
|
||||||
|
{
|
||||||
|
NzCompoundGeom* compoundGeom = static_cast<NzCompoundGeom*>(geom.Get());
|
||||||
|
for (const NzPhysGeomRef& piece : compoundGeom->GetGeoms())
|
||||||
|
NewtonCompoundCollisionAddSubCollision(compoundCollision, piece->GetHandle(world));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
NewtonCompoundCollisionAddSubCollision(compoundCollision, geom->GetHandle(world));
|
||||||
|
}
|
||||||
|
NewtonCompoundCollisionEndAddRemove(compoundCollision);
|
||||||
|
|
||||||
|
return compoundCollision;
|
||||||
|
}
|
||||||
|
|
||||||
/********************************* ConeGeom **********************************/
|
/********************************* ConeGeom **********************************/
|
||||||
|
|
||||||
NzConeGeom::NzConeGeom(NzPhysWorld* physWorld, float length, float radius, const NzMatrix4f& transformMatrix) :
|
NzConeGeom::NzConeGeom(float length, float radius, const NzMatrix4f& transformMatrix) :
|
||||||
NzBaseGeom(physWorld),
|
m_matrix(transformMatrix),
|
||||||
m_length(length),
|
m_length(length),
|
||||||
m_radius(radius)
|
m_radius(radius)
|
||||||
{
|
{
|
||||||
m_collision = NewtonCreateCone(physWorld->GetHandle(), radius, length, 0, transformMatrix);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NzConeGeom::NzConeGeom(NzPhysWorld* physWorld, float length, float radius, const NzVector3f& translation, const NzQuaternionf& rotation) :
|
NzConeGeom::NzConeGeom(float length, float radius, const NzVector3f& translation, const NzQuaternionf& rotation) :
|
||||||
NzConeGeom(physWorld, length, radius, NzMatrix4f::Transform(translation, rotation))
|
NzConeGeom(length, radius, NzMatrix4f::Transform(translation, rotation))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -222,16 +295,32 @@ nzGeomType NzConeGeom::GetType() const
|
||||||
return nzGeomType_Cone;
|
return nzGeomType_Cone;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************** ConvexHullGeom *******************************/
|
NewtonCollision* NzConeGeom::CreateHandle(NzPhysWorld* world) const
|
||||||
|
|
||||||
NzConvexHullGeom::NzConvexHullGeom(NzPhysWorld* physWorld, const void* vertices, unsigned int vertexCount, unsigned int stride, float tolerance, const NzMatrix4f& transformMatrix) :
|
|
||||||
NzBaseGeom(physWorld)
|
|
||||||
{
|
{
|
||||||
m_collision = NewtonCreateConvexHull(physWorld->GetHandle(), vertexCount, reinterpret_cast<const float*>(vertices), stride, tolerance, 0, transformMatrix);
|
return NewtonCreateCone(world->GetHandle(), m_radius, m_length, 0, m_matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
NzConvexHullGeom::NzConvexHullGeom(NzPhysWorld* physWorld, const void* vertices, unsigned int vertexCount, unsigned int stride, float tolerance, const NzVector3f& translation, const NzQuaternionf& rotation) :
|
/****************************** ConvexHullGeom *******************************/
|
||||||
NzConvexHullGeom(physWorld, vertices, vertexCount, stride, tolerance, NzMatrix4f::Transform(translation, rotation))
|
|
||||||
|
NzConvexHullGeom::NzConvexHullGeom(const void* vertices, unsigned int vertexCount, unsigned int stride, float tolerance, const NzMatrix4f& transformMatrix) :
|
||||||
|
m_matrix(transformMatrix),
|
||||||
|
m_tolerance(tolerance),
|
||||||
|
m_vertexStride(stride)
|
||||||
|
{
|
||||||
|
const nzUInt8* ptr = static_cast<const nzUInt8*>(vertices);
|
||||||
|
|
||||||
|
m_vertices.resize(vertexCount);
|
||||||
|
if (stride != sizeof(NzVector3f))
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < vertexCount; ++i)
|
||||||
|
m_vertices[i] = *reinterpret_cast<const NzVector3f*>(ptr + stride*i);
|
||||||
|
}
|
||||||
|
else // Fast path
|
||||||
|
std::memcpy(m_vertices.data(), vertices, vertexCount*sizeof(NzVector3f));
|
||||||
|
}
|
||||||
|
|
||||||
|
NzConvexHullGeom::NzConvexHullGeom(const void* vertices, unsigned int vertexCount, unsigned int stride, float tolerance, const NzVector3f& translation, const NzQuaternionf& rotation) :
|
||||||
|
NzConvexHullGeom(vertices, vertexCount, stride, tolerance, NzMatrix4f::Transform(translation, rotation))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -240,18 +329,22 @@ nzGeomType NzConvexHullGeom::GetType() const
|
||||||
return nzGeomType_Compound;
|
return nzGeomType_Compound;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NewtonCollision* NzConvexHullGeom::CreateHandle(NzPhysWorld* world) const
|
||||||
|
{
|
||||||
|
return NewtonCreateConvexHull(world->GetHandle(), m_vertices.size(), reinterpret_cast<const float*>(m_vertices.data()), sizeof(NzVector3f), m_tolerance, 0, m_matrix);
|
||||||
|
}
|
||||||
|
|
||||||
/******************************* CylinderGeom ********************************/
|
/******************************* CylinderGeom ********************************/
|
||||||
|
|
||||||
NzCylinderGeom::NzCylinderGeom(NzPhysWorld* physWorld, float length, float radius, const NzMatrix4f& transformMatrix) :
|
NzCylinderGeom::NzCylinderGeom(float length, float radius, const NzMatrix4f& transformMatrix) :
|
||||||
NzBaseGeom(physWorld),
|
m_matrix(transformMatrix),
|
||||||
m_length(length),
|
m_length(length),
|
||||||
m_radius(radius)
|
m_radius(radius)
|
||||||
{
|
{
|
||||||
m_collision = NewtonCreateCylinder(physWorld->GetHandle(), radius, length, 0, transformMatrix);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NzCylinderGeom::NzCylinderGeom(NzPhysWorld* physWorld, float length, float radius, const NzVector3f& translation, const NzQuaternionf& rotation) :
|
NzCylinderGeom::NzCylinderGeom(float length, float radius, const NzVector3f& translation, const NzQuaternionf& rotation) :
|
||||||
NzCylinderGeom(physWorld, length, radius, NzMatrix4f::Transform(translation, rotation))
|
NzCylinderGeom(length, radius, NzMatrix4f::Transform(translation, rotation))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -270,12 +363,15 @@ nzGeomType NzCylinderGeom::GetType() const
|
||||||
return nzGeomType_Cylinder;
|
return nzGeomType_Cylinder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NewtonCollision* NzCylinderGeom::CreateHandle(NzPhysWorld* world) const
|
||||||
|
{
|
||||||
|
return NewtonCreateCylinder(world->GetHandle(), m_radius, m_length, 0, m_matrix);
|
||||||
|
}
|
||||||
|
|
||||||
/********************************* NullGeom **********************************/
|
/********************************* NullGeom **********************************/
|
||||||
|
|
||||||
NzNullGeom::NzNullGeom(NzPhysWorld* physWorld) :
|
NzNullGeom::NzNullGeom()
|
||||||
NzBaseGeom(physWorld)
|
|
||||||
{
|
{
|
||||||
m_collision = NewtonCreateNull(physWorld->GetHandle());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nzGeomType NzNullGeom::GetType() const
|
nzGeomType NzNullGeom::GetType() const
|
||||||
|
|
@ -283,21 +379,39 @@ nzGeomType NzNullGeom::GetType() const
|
||||||
return nzGeomType_Null;
|
return nzGeomType_Null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NewtonCollision* NzNullGeom::CreateHandle(NzPhysWorld* world) const
|
||||||
|
{
|
||||||
|
return NewtonCreateNull(world->GetHandle());
|
||||||
|
}
|
||||||
|
|
||||||
/******************************** SphereGeom *********************************/
|
/******************************** SphereGeom *********************************/
|
||||||
|
|
||||||
NzSphereGeom::NzSphereGeom(NzPhysWorld* physWorld, float radius, const NzMatrix4f& transformMatrix) :
|
NzSphereGeom::NzSphereGeom(float radius, const NzMatrix4f& transformMatrix) :
|
||||||
NzBaseGeom(physWorld),
|
NzSphereGeom(radius, transformMatrix.GetTranslation())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NzSphereGeom::NzSphereGeom(float radius, const NzVector3f& translation, const NzQuaternionf& rotation) :
|
||||||
|
m_position(translation),
|
||||||
m_radius(radius)
|
m_radius(radius)
|
||||||
{
|
{
|
||||||
m_collision = NewtonCreateSphere(physWorld->GetHandle(), radius, 0, transformMatrix);
|
NazaraUnused(rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
NzSphereGeom::NzSphereGeom(NzPhysWorld* physWorld, float radius, const NzVector3f& translation, const NzQuaternionf& rotation) :
|
NzBoxf NzSphereGeom::ComputeAABB(const NzMatrix4f& offsetMatrix, const NzVector3f& scale) const
|
||||||
NzSphereGeom(physWorld, radius, NzMatrix4f::Transform(translation, rotation))
|
|
||||||
{
|
{
|
||||||
|
NzVector3f size(m_radius * scale);
|
||||||
|
NzVector3f position(offsetMatrix.GetTranslation());
|
||||||
|
|
||||||
|
return NzBoxf(position - size, position + size);
|
||||||
}
|
}
|
||||||
|
|
||||||
NzVector3f NzSphereGeom::GetRadius() const
|
float NzSphereGeom::ComputeVolume() const
|
||||||
|
{
|
||||||
|
return M_PI * m_radius * m_radius * m_radius / 3.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
float NzSphereGeom::GetRadius() const
|
||||||
{
|
{
|
||||||
return m_radius;
|
return m_radius;
|
||||||
}
|
}
|
||||||
|
|
@ -306,3 +420,8 @@ nzGeomType NzSphereGeom::GetType() const
|
||||||
{
|
{
|
||||||
return nzGeomType_Sphere;
|
return nzGeomType_Sphere;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NewtonCollision* NzSphereGeom::CreateHandle(NzPhysWorld* world) const
|
||||||
|
{
|
||||||
|
return NewtonCreateSphere(world->GetHandle(), m_radius, 0, NzMatrix4f::Translate(m_position));
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,56 +3,70 @@
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
#include <Nazara/Physics/PhysObject.hpp>
|
#include <Nazara/Physics/PhysObject.hpp>
|
||||||
|
#include <Nazara/Math/Algorithm.hpp>
|
||||||
#include <Nazara/Physics/Config.hpp>
|
#include <Nazara/Physics/Config.hpp>
|
||||||
#include <Nazara/Physics/Geom.hpp>
|
|
||||||
#include <Nazara/Physics/PhysWorld.hpp>
|
#include <Nazara/Physics/PhysWorld.hpp>
|
||||||
#include <Newton/Newton.h>
|
#include <Newton/Newton.h>
|
||||||
|
#include <algorithm>
|
||||||
#include <Nazara/Physics/Debug.hpp>
|
#include <Nazara/Physics/Debug.hpp>
|
||||||
|
|
||||||
NzPhysObject::NzPhysObject(NzPhysWorld* world, const NzMatrix4f& mat) :
|
NzPhysObject::NzPhysObject(NzPhysWorld* world, const NzMatrix4f& mat) :
|
||||||
|
NzPhysObject(world, NzNullGeom::New(), mat)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NzPhysObject::NzPhysObject(NzPhysWorld* world, NzPhysGeomRef geom, const NzMatrix4f& mat) :
|
||||||
m_matrix(mat),
|
m_matrix(mat),
|
||||||
|
m_geom(std::move(geom)),
|
||||||
m_forceAccumulator(NzVector3f::Zero()),
|
m_forceAccumulator(NzVector3f::Zero()),
|
||||||
m_torqueAccumulator(NzVector3f::Zero()),
|
m_torqueAccumulator(NzVector3f::Zero()),
|
||||||
m_world(world),
|
m_world(world),
|
||||||
m_ownsGeom(true),
|
|
||||||
m_gravityFactor(1.f),
|
m_gravityFactor(1.f),
|
||||||
m_mass(0.f)
|
m_mass(0.f)
|
||||||
{
|
{
|
||||||
#if NAZARA_PHYSICS_SAFE
|
NazaraAssert(m_world, "Invalid world");
|
||||||
if (!world)
|
|
||||||
NazaraError("Invalid physics world"); ///TODO: Unexcepted
|
|
||||||
#endif
|
|
||||||
|
|
||||||
m_geom = new NzNullGeom(world);
|
if (!m_geom)
|
||||||
m_body = NewtonCreateDynamicBody(world->GetHandle(), m_geom->GetHandle(), mat);
|
m_geom = NzNullGeom::New();
|
||||||
|
|
||||||
|
m_body = NewtonCreateDynamicBody(m_world->GetHandle(), m_geom->GetHandle(m_world), m_matrix);
|
||||||
NewtonBodySetUserData(m_body, this);
|
NewtonBodySetUserData(m_body, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
NzPhysObject::NzPhysObject(NzPhysWorld* world, const NzBaseGeom* geom, const NzMatrix4f& mat) :
|
NzPhysObject::NzPhysObject(const NzPhysObject& object) :
|
||||||
m_matrix(mat),
|
m_matrix(object.m_matrix),
|
||||||
|
m_geom(object.m_geom),
|
||||||
m_forceAccumulator(NzVector3f::Zero()),
|
m_forceAccumulator(NzVector3f::Zero()),
|
||||||
m_torqueAccumulator(NzVector3f::Zero()),
|
m_torqueAccumulator(NzVector3f::Zero()),
|
||||||
m_geom(geom),
|
m_world(object.m_world),
|
||||||
m_world(world),
|
m_gravityFactor(object.m_gravityFactor),
|
||||||
m_ownsGeom(false),
|
|
||||||
m_gravityFactor(1.f),
|
|
||||||
m_mass(0.f)
|
m_mass(0.f)
|
||||||
{
|
{
|
||||||
#if NAZARA_PHYSICS_SAFE
|
NazaraAssert(m_world, "Invalid world");
|
||||||
if (!world)
|
NazaraAssert(m_geom, "Invalid geometry");
|
||||||
NazaraError("Invalid physics world"); ///TODO: Unexcepted
|
|
||||||
#endif
|
|
||||||
|
|
||||||
m_body = NewtonCreateDynamicBody(world->GetHandle(), geom->GetHandle(), mat);
|
m_body = NewtonCreateDynamicBody(m_world->GetHandle(), m_geom->GetHandle(m_world), m_matrix);
|
||||||
NewtonBodySetUserData(m_body, this);
|
NewtonBodySetUserData(m_body, this);
|
||||||
|
SetMass(object.m_mass);
|
||||||
|
}
|
||||||
|
|
||||||
|
NzPhysObject::NzPhysObject(NzPhysObject&& object) :
|
||||||
|
m_matrix(std::move(object.m_matrix)),
|
||||||
|
m_forceAccumulator(std::move(object.m_forceAccumulator)),
|
||||||
|
m_torqueAccumulator(std::move(object.m_torqueAccumulator)),
|
||||||
|
m_body(object.m_body),
|
||||||
|
m_geom(std::move(object.m_geom)),
|
||||||
|
m_world(object.m_world),
|
||||||
|
m_gravityFactor(object.m_gravityFactor),
|
||||||
|
m_mass(object.m_mass)
|
||||||
|
{
|
||||||
|
object.m_body = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
NzPhysObject::~NzPhysObject()
|
NzPhysObject::~NzPhysObject()
|
||||||
{
|
{
|
||||||
|
if (m_body)
|
||||||
NewtonDestroyBody(m_world->GetHandle(), m_body);
|
NewtonDestroyBody(m_world->GetHandle(), m_body);
|
||||||
|
|
||||||
if (m_ownsGeom)
|
|
||||||
delete m_geom;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzPhysObject::AddForce(const NzVector3f& force, nzCoordSys coordSys)
|
void NzPhysObject::AddForce(const NzVector3f& force, nzCoordSys coordSys)
|
||||||
|
|
@ -82,8 +96,7 @@ void NzPhysObject::AddForce(const NzVector3f& force, const NzVector3f& point, nz
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nzCoordSys_Local:
|
case nzCoordSys_Local:
|
||||||
AddForce(m_matrix.Transform(force, 0.f), m_matrix.Transform(point));
|
return AddForce(m_matrix.Transform(force, 0.f), m_matrix.Transform(point), nzCoordSys_Global);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// On réveille le corps pour que le callback soit appelé et que les forces soient appliquées
|
// On réveille le corps pour que le callback soit appelé et que les forces soient appliquées
|
||||||
|
|
@ -112,6 +125,14 @@ void NzPhysObject::EnableAutoSleep(bool autoSleep)
|
||||||
NewtonBodySetAutoSleep(m_body, autoSleep);
|
NewtonBodySetAutoSleep(m_body, autoSleep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NzBoxf NzPhysObject::GetAABB() const
|
||||||
|
{
|
||||||
|
NzVector3f min, max;
|
||||||
|
NewtonBodyGetAABB(m_body, min, max);
|
||||||
|
|
||||||
|
return NzBoxf(min, max);
|
||||||
|
}
|
||||||
|
|
||||||
NzVector3f NzPhysObject::GetAngularVelocity() const
|
NzVector3f NzPhysObject::GetAngularVelocity() const
|
||||||
{
|
{
|
||||||
NzVector3f angularVelocity;
|
NzVector3f angularVelocity;
|
||||||
|
|
@ -120,6 +141,11 @@ NzVector3f NzPhysObject::GetAngularVelocity() const
|
||||||
return angularVelocity;
|
return angularVelocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const NzPhysGeomRef& NzPhysObject::GetGeom() const
|
||||||
|
{
|
||||||
|
return m_geom;
|
||||||
|
}
|
||||||
|
|
||||||
float NzPhysObject::GetGravityFactor() const
|
float NzPhysObject::GetGravityFactor() const
|
||||||
{
|
{
|
||||||
return m_gravityFactor;
|
return m_gravityFactor;
|
||||||
|
|
@ -191,6 +217,24 @@ bool NzPhysObject::IsSleeping() const
|
||||||
return NewtonBodyGetSleepState(m_body) != 0;
|
return NewtonBodyGetSleepState(m_body) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NzPhysObject::SetAngularVelocity(const NzVector3f& angularVelocity)
|
||||||
|
{
|
||||||
|
NewtonBodySetOmega(m_body, angularVelocity);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzPhysObject::SetGeom(NzPhysGeomRef geom)
|
||||||
|
{
|
||||||
|
if (m_geom.Get() != geom)
|
||||||
|
{
|
||||||
|
if (geom)
|
||||||
|
m_geom = geom;
|
||||||
|
else
|
||||||
|
m_geom = NzNullGeom::New();
|
||||||
|
|
||||||
|
NewtonBodySetCollision(m_body, m_geom->GetHandle(m_world));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void NzPhysObject::SetGravityFactor(float gravityFactor)
|
void NzPhysObject::SetGravityFactor(float gravityFactor)
|
||||||
{
|
{
|
||||||
m_gravityFactor = gravityFactor;
|
m_gravityFactor = gravityFactor;
|
||||||
|
|
@ -237,13 +281,56 @@ void NzPhysObject::SetRotation(const NzQuaternionf& rotation)
|
||||||
UpdateBody();
|
UpdateBody();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NzPhysObject::SetVelocity(const NzVector3f& velocity)
|
||||||
|
{
|
||||||
|
NewtonBodySetVelocity(m_body, velocity);
|
||||||
|
}
|
||||||
|
|
||||||
|
NzPhysObject& NzPhysObject::operator=(const NzPhysObject& object)
|
||||||
|
{
|
||||||
|
NzPhysObject physObj(object);
|
||||||
|
return operator=(std::move(physObj));
|
||||||
|
}
|
||||||
|
|
||||||
void NzPhysObject::UpdateBody()
|
void NzPhysObject::UpdateBody()
|
||||||
{
|
{
|
||||||
NewtonBodySetMatrix(m_body, m_matrix);
|
NewtonBodySetMatrix(m_body, m_matrix);
|
||||||
|
|
||||||
|
if (NzNumberEquals(m_mass, 0.f))
|
||||||
|
{
|
||||||
|
// http://newtondynamics.com/wiki/index.php5?title=Can_i_dynamicly_move_a_TriMesh%3F
|
||||||
|
NzVector3f min, max;
|
||||||
|
NewtonBodyGetAABB(m_body, min, max);
|
||||||
|
|
||||||
|
NewtonWorldForEachBodyInAABBDo(m_world->GetHandle(), min, max, [](const NewtonBody* const body, void* const userData)
|
||||||
|
{
|
||||||
|
NazaraUnused(userData);
|
||||||
|
NewtonBodySetSleepState(body, 0);
|
||||||
|
}, nullptr);
|
||||||
|
}
|
||||||
/*for (std::set<PhysObjectListener*>::iterator it = m_listeners.begin(); it != m_listeners.end(); ++it)
|
/*for (std::set<PhysObjectListener*>::iterator it = m_listeners.begin(); it != m_listeners.end(); ++it)
|
||||||
(*it)->PhysObjectOnUpdate(this);*/
|
(*it)->PhysObjectOnUpdate(this);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NzPhysObject& NzPhysObject::operator=(NzPhysObject&& object)
|
||||||
|
{
|
||||||
|
if (m_body)
|
||||||
|
NewtonDestroyBody(m_world->GetHandle(), m_body);
|
||||||
|
|
||||||
|
m_body = object.m_body;
|
||||||
|
m_forceAccumulator = std::move(object.m_forceAccumulator);
|
||||||
|
m_geom = std::move(object.m_geom);
|
||||||
|
m_gravityFactor = object.m_gravityFactor;
|
||||||
|
m_mass = object.m_mass;
|
||||||
|
m_matrix = std::move(object.m_matrix);
|
||||||
|
m_torqueAccumulator = std::move(object.m_torqueAccumulator);
|
||||||
|
m_world = object.m_world;
|
||||||
|
|
||||||
|
object.m_body = nullptr;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
void NzPhysObject::ForceAndTorqueCallback(const NewtonBody* body, float timeStep, int threadIndex)
|
void NzPhysObject::ForceAndTorqueCallback(const NewtonBody* body, float timeStep, int threadIndex)
|
||||||
{
|
{
|
||||||
NazaraUnused(timeStep);
|
NazaraUnused(timeStep);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue