Compare commits
10 Commits
3fb1096d07
...
3514ac6340
| Author | SHA1 | Date |
|---|---|---|
|
|
3514ac6340 | |
|
|
1615bc4229 | |
|
|
f2672f6376 | |
|
|
f5fefc7b86 | |
|
|
3fd696385d | |
|
|
26dbdef50d | |
|
|
6cbfb01243 | |
|
|
f2ab31cc4b | |
|
|
62d5e611f1 | |
|
|
5253a80a24 |
|
|
@ -456,13 +456,13 @@ int main(int argc, char* argv[])
|
||||||
if (lastHitInfo.hitBody && lastHitInfo.hitEntity != boxColliderEntity)
|
if (lastHitInfo.hitBody && lastHitInfo.hitEntity != boxColliderEntity)
|
||||||
{
|
{
|
||||||
#if USE_JOLT
|
#if USE_JOLT
|
||||||
grabConstraint.emplace(*lastHitInfo.hitBody, lastHitInfo.hitPosition);
|
grabConstraint.emplace(static_cast<Nz::JoltRigidBody3D&>(*lastHitInfo.hitBody), lastHitInfo.hitPosition);
|
||||||
#else
|
#else
|
||||||
grabConstraint.emplace(*lastHitInfo.hitBody, lastHitInfo.hitPosition);
|
grabConstraint.emplace(*lastHitInfo.hitBody, lastHitInfo.hitPosition);
|
||||||
grabConstraint->SetImpulseClamp(30.f);
|
grabConstraint->SetImpulseClamp(30.f);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
grabbedObjectMove.Connect(eventHandler.OnMouseMoved, [&, body = lastHitInfo.hitBody, distance = Nz::Vector3f::Distance(from, lastHitInfo.hitPosition)](const Nz::WindowEventHandler*, const Nz::WindowEvent::MouseMoveEvent& event)
|
grabbedObjectMove.Connect(eventHandler.OnMouseMoved, [&, distance = Nz::Vector3f::Distance(from, lastHitInfo.hitPosition)](const Nz::WindowEventHandler*, const Nz::WindowEvent::MouseMoveEvent& event)
|
||||||
{
|
{
|
||||||
Nz::Vector3f from = cameraComponent.Unproject({ float(event.x), float(event.y), 0.f });
|
Nz::Vector3f from = cameraComponent.Unproject({ float(event.x), float(event.y), 0.f });
|
||||||
Nz::Vector3f to = cameraComponent.Unproject({ float(event.x), float(event.y), 1.f });
|
Nz::Vector3f to = cameraComponent.Unproject({ float(event.x), float(event.y), 1.f });
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ namespace Nz
|
||||||
|
|
||||||
static ErrorModeFlags ApplyFlags(ErrorModeFlags orFlags, ErrorModeFlags andFlags);
|
static ErrorModeFlags ApplyFlags(ErrorModeFlags orFlags, ErrorModeFlags andFlags);
|
||||||
|
|
||||||
static constexpr std::string_view GetCurrentFileRelativeToEngine(std::string_view file);
|
static constexpr std::string_view TranslateFilepath(std::string_view file);
|
||||||
static ErrorModeFlags GetFlags();
|
static ErrorModeFlags GetFlags();
|
||||||
static std::string GetLastError(std::string_view* file = nullptr, unsigned int* line = nullptr, std::string_view* function = nullptr);
|
static std::string GetLastError(std::string_view* file = nullptr, unsigned int* line = nullptr, std::string_view* function = nullptr);
|
||||||
static unsigned int GetLastSystemErrorCode();
|
static unsigned int GetLastSystemErrorCode();
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,13 @@
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
constexpr std::string_view Error::GetCurrentFileRelativeToEngine(std::string_view file)
|
constexpr std::string_view Error::TranslateFilepath(std::string_view file)
|
||||||
{
|
{
|
||||||
if (std::size_t offset = file.find("NazaraEngine/"); offset != file.npos)
|
if (std::size_t offset = file.rfind('/'); offset != file.npos)
|
||||||
return file.substr(offset);
|
return file.substr(offset + 1);
|
||||||
|
|
||||||
if (std::size_t offset = file.find("NazaraEngine\\"); offset != file.npos)
|
if (std::size_t offset = file.rfind('\\'); offset != file.npos)
|
||||||
return file.substr(offset);
|
return file.substr(offset + 1);
|
||||||
|
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
@ -22,6 +22,6 @@ namespace Nz
|
||||||
|
|
||||||
inline void Error::Trigger(ErrorType type, unsigned int line, std::string_view file, std::string_view function, std::string error)
|
inline void Error::Trigger(ErrorType type, unsigned int line, std::string_view file, std::string_view function, std::string error)
|
||||||
{
|
{
|
||||||
return TriggerInternal(type, std::move(error), line, GetCurrentFileRelativeToEngine(file), function);
|
return TriggerInternal(type, std::move(error), line, TranslateFilepath(file), function);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
|
||||||
|
// This file is part of the "Nazara Engine - JoltPhysics3D module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef NAZARA_JOLTPHYSICS3D_JOLTABSTRACTBODY_HPP
|
||||||
|
#define NAZARA_JOLTPHYSICS3D_JOLTABSTRACTBODY_HPP
|
||||||
|
|
||||||
|
#include <NazaraUtils/Prerequisites.hpp>
|
||||||
|
#include <Nazara/JoltPhysics3D/Config.hpp>
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
class NAZARA_JOLTPHYSICS3D_API JoltAbstractBody
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
JoltAbstractBody() = default;
|
||||||
|
JoltAbstractBody(const JoltAbstractBody&) = delete;
|
||||||
|
JoltAbstractBody(JoltAbstractBody&&) = delete;
|
||||||
|
virtual ~JoltAbstractBody();
|
||||||
|
|
||||||
|
virtual UInt32 GetBodyIndex() const = 0;
|
||||||
|
|
||||||
|
JoltAbstractBody& operator=(const JoltAbstractBody&) = delete;
|
||||||
|
JoltAbstractBody& operator=(JoltAbstractBody&&) = delete;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <Nazara/JoltPhysics3D/JoltAbstractBody.inl>
|
||||||
|
|
||||||
|
#endif // NAZARA_JOLTPHYSICS3D_JOLTABSTRACTBODY_HPP
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
|
||||||
|
// This file is part of the "Nazara Engine - JoltPhysics3D module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#include <Nazara/JoltPhysics3D/JoltAbstractBody.hpp>
|
||||||
|
#include <Nazara/JoltPhysics3D/Debug.hpp>
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <Nazara/JoltPhysics3D/DebugOff.hpp>
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include <NazaraUtils/Prerequisites.hpp>
|
#include <NazaraUtils/Prerequisites.hpp>
|
||||||
#include <Nazara/JoltPhysics3D/Config.hpp>
|
#include <Nazara/JoltPhysics3D/Config.hpp>
|
||||||
|
#include <Nazara/JoltPhysics3D/JoltAbstractBody.hpp>
|
||||||
#include <Nazara/JoltPhysics3D/JoltPhysicsStepListener.hpp>
|
#include <Nazara/JoltPhysics3D/JoltPhysicsStepListener.hpp>
|
||||||
#include <Nazara/Math/Quaternion.hpp>
|
#include <Nazara/Math/Quaternion.hpp>
|
||||||
#include <Nazara/Math/Vector3.hpp>
|
#include <Nazara/Math/Vector3.hpp>
|
||||||
|
|
@ -27,7 +28,7 @@ namespace Nz
|
||||||
class JoltCollider3D;
|
class JoltCollider3D;
|
||||||
class JoltPhysWorld3D;
|
class JoltPhysWorld3D;
|
||||||
|
|
||||||
class NAZARA_JOLTPHYSICS3D_API JoltCharacter : public JoltPhysicsStepListener
|
class NAZARA_JOLTPHYSICS3D_API JoltCharacter : public JoltAbstractBody, public JoltPhysicsStepListener
|
||||||
{
|
{
|
||||||
friend JoltPhysWorld3D;
|
friend JoltPhysWorld3D;
|
||||||
|
|
||||||
|
|
@ -42,11 +43,14 @@ namespace Nz
|
||||||
inline void DisableSleeping();
|
inline void DisableSleeping();
|
||||||
void EnableSleeping(bool enable);
|
void EnableSleeping(bool enable);
|
||||||
|
|
||||||
inline UInt32 GetBodyIndex() const;
|
UInt32 GetBodyIndex() const override;
|
||||||
|
inline const std::shared_ptr<JoltCollider3D>& GetCollider() const;
|
||||||
Vector3f GetLinearVelocity() const;
|
Vector3f GetLinearVelocity() const;
|
||||||
Quaternionf GetRotation() const;
|
inline JoltPhysWorld3D& GetPhysWorld();
|
||||||
|
inline const JoltPhysWorld3D& GetPhysWorld() const;
|
||||||
Vector3f GetPosition() const;
|
Vector3f GetPosition() const;
|
||||||
std::pair<Vector3f, Quaternionf> GetPositionAndRotation() const;
|
std::pair<Vector3f, Quaternionf> GetPositionAndRotation() const;
|
||||||
|
Quaternionf GetRotation() const;
|
||||||
Vector3f GetUp() const;
|
Vector3f GetUp() const;
|
||||||
|
|
||||||
bool IsOnGround() const;
|
bool IsOnGround() const;
|
||||||
|
|
@ -78,7 +82,7 @@ namespace Nz
|
||||||
void Destroy();
|
void Destroy();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void PostSimulate() override;
|
void PostSimulate(float elapsedTime) override;
|
||||||
void PreSimulate(float elapsedTime) override;
|
void PreSimulate(float elapsedTime) override;
|
||||||
|
|
||||||
std::shared_ptr<JoltCharacterImpl> m_impl;
|
std::shared_ptr<JoltCharacterImpl> m_impl;
|
||||||
|
|
@ -96,7 +100,7 @@ namespace Nz
|
||||||
JoltCharacterImpl(JoltCharacterImpl&&) = delete;
|
JoltCharacterImpl(JoltCharacterImpl&&) = delete;
|
||||||
virtual ~JoltCharacterImpl();
|
virtual ~JoltCharacterImpl();
|
||||||
|
|
||||||
virtual void PostSimulate(JoltCharacter& character);
|
virtual void PostSimulate(JoltCharacter& character, float elapsedTime);
|
||||||
virtual void PreSimulate(JoltCharacter& character, float elapsedTime);
|
virtual void PreSimulate(JoltCharacter& character, float elapsedTime);
|
||||||
|
|
||||||
JoltCharacterImpl& operator=(const JoltCharacterImpl&) = delete;
|
JoltCharacterImpl& operator=(const JoltCharacterImpl&) = delete;
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,19 @@ namespace Nz
|
||||||
return EnableSleeping(false);
|
return EnableSleeping(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline UInt32 JoltCharacter::GetBodyIndex() const
|
inline const std::shared_ptr<JoltCollider3D>& JoltCharacter::GetCollider() const
|
||||||
{
|
{
|
||||||
return m_bodyIndex;
|
return m_collider;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline JoltPhysWorld3D& JoltCharacter::GetPhysWorld()
|
||||||
|
{
|
||||||
|
return *m_world;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const JoltPhysWorld3D& JoltCharacter::GetPhysWorld() const
|
||||||
|
{
|
||||||
|
return *m_world;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void JoltCharacter::SetImpl(std::shared_ptr<JoltCharacterImpl> characterImpl)
|
inline void JoltCharacter::SetImpl(std::shared_ptr<JoltCharacterImpl> characterImpl)
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,10 @@ namespace JPH
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
|
class JoltAbstractBody;
|
||||||
class JoltCharacter;
|
class JoltCharacter;
|
||||||
class JoltCharacterImpl;
|
class JoltCharacterImpl;
|
||||||
|
class JoltCollider3D;
|
||||||
class JoltPhysicsStepListener;
|
class JoltPhysicsStepListener;
|
||||||
class JoltRigidBody3D;
|
class JoltRigidBody3D;
|
||||||
|
|
||||||
|
|
@ -38,13 +40,19 @@ namespace Nz
|
||||||
friend JoltRigidBody3D;
|
friend JoltRigidBody3D;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
struct PointCollisionInfo;
|
||||||
struct RaycastHit;
|
struct RaycastHit;
|
||||||
|
struct ShapeCollisionInfo;
|
||||||
|
|
||||||
JoltPhysWorld3D();
|
JoltPhysWorld3D();
|
||||||
JoltPhysWorld3D(const JoltPhysWorld3D&) = delete;
|
JoltPhysWorld3D(const JoltPhysWorld3D&) = delete;
|
||||||
JoltPhysWorld3D(JoltPhysWorld3D&& ph) = delete;
|
JoltPhysWorld3D(JoltPhysWorld3D&& ph) = delete;
|
||||||
~JoltPhysWorld3D();
|
~JoltPhysWorld3D();
|
||||||
|
|
||||||
|
bool CollisionQuery(const Vector3f& point, const FunctionRef<std::optional<float>(const PointCollisionInfo& collisionInfo)>& callback);
|
||||||
|
bool CollisionQuery(const JoltCollider3D& collider, const Matrix4f& colliderTransform, const FunctionRef<std::optional<float>(const ShapeCollisionInfo& hitInfo)>& callback);
|
||||||
|
bool CollisionQuery(const JoltCollider3D& collider, const Matrix4f& colliderTransform, const Vector3f& colliderScale, const FunctionRef<std::optional<float>(const ShapeCollisionInfo& hitInfo)>& callback);
|
||||||
|
|
||||||
UInt32 GetActiveBodyCount() const;
|
UInt32 GetActiveBodyCount() const;
|
||||||
Vector3f GetGravity() const;
|
Vector3f GetGravity() const;
|
||||||
std::size_t GetMaxStepCount() const;
|
std::size_t GetMaxStepCount() const;
|
||||||
|
|
@ -72,14 +80,28 @@ namespace Nz
|
||||||
JoltPhysWorld3D& operator=(const JoltPhysWorld3D&) = delete;
|
JoltPhysWorld3D& operator=(const JoltPhysWorld3D&) = delete;
|
||||||
JoltPhysWorld3D& operator=(JoltPhysWorld3D&&) = delete;
|
JoltPhysWorld3D& operator=(JoltPhysWorld3D&&) = delete;
|
||||||
|
|
||||||
|
struct PointCollisionInfo
|
||||||
|
{
|
||||||
|
JoltAbstractBody* hitBody = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
struct RaycastHit
|
struct RaycastHit
|
||||||
{
|
{
|
||||||
float fraction;
|
float fraction;
|
||||||
JoltRigidBody3D* hitBody = nullptr;
|
JoltAbstractBody* hitBody = nullptr;
|
||||||
Vector3f hitNormal;
|
Vector3f hitNormal;
|
||||||
Vector3f hitPosition;
|
Vector3f hitPosition;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ShapeCollisionInfo
|
||||||
|
{
|
||||||
|
JoltAbstractBody* hitBody = nullptr;
|
||||||
|
Vector3f collisionPosition1;
|
||||||
|
Vector3f collisionPosition2;
|
||||||
|
Vector3f penetrationAxis;
|
||||||
|
float penetrationDepth;
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class BodyActivationListener;
|
class BodyActivationListener;
|
||||||
friend BodyActivationListener;
|
friend BodyActivationListener;
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ namespace Nz
|
||||||
JoltPhysicsStepListener(JoltPhysicsStepListener&&) = delete;
|
JoltPhysicsStepListener(JoltPhysicsStepListener&&) = delete;
|
||||||
virtual ~JoltPhysicsStepListener();
|
virtual ~JoltPhysicsStepListener();
|
||||||
|
|
||||||
virtual void PostSimulate();
|
virtual void PostSimulate(float elapsedTime);
|
||||||
virtual void PreSimulate(float elapsedTime);
|
virtual void PreSimulate(float elapsedTime);
|
||||||
|
|
||||||
JoltPhysicsStepListener& operator=(const JoltPhysicsStepListener&) = delete;
|
JoltPhysicsStepListener& operator=(const JoltPhysicsStepListener&) = delete;
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include <NazaraUtils/Prerequisites.hpp>
|
#include <NazaraUtils/Prerequisites.hpp>
|
||||||
#include <Nazara/Core/Enums.hpp>
|
#include <Nazara/Core/Enums.hpp>
|
||||||
#include <Nazara/JoltPhysics3D/Config.hpp>
|
#include <Nazara/JoltPhysics3D/Config.hpp>
|
||||||
|
#include <Nazara/JoltPhysics3D/JoltAbstractBody.hpp>
|
||||||
#include <Nazara/JoltPhysics3D/JoltCollider3D.hpp>
|
#include <Nazara/JoltPhysics3D/JoltCollider3D.hpp>
|
||||||
#include <Nazara/Math/Matrix4.hpp>
|
#include <Nazara/Math/Matrix4.hpp>
|
||||||
#include <Nazara/Math/Quaternion.hpp>
|
#include <Nazara/Math/Quaternion.hpp>
|
||||||
|
|
@ -26,7 +27,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
class JoltPhysWorld3D;
|
class JoltPhysWorld3D;
|
||||||
|
|
||||||
class NAZARA_JOLTPHYSICS3D_API JoltRigidBody3D
|
class NAZARA_JOLTPHYSICS3D_API JoltRigidBody3D : public JoltAbstractBody
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
struct DynamicSettings;
|
struct DynamicSettings;
|
||||||
|
|
@ -54,7 +55,7 @@ namespace Nz
|
||||||
Vector3f GetAngularVelocity() const;
|
Vector3f GetAngularVelocity() const;
|
||||||
inline JPH::Body* GetBody();
|
inline JPH::Body* GetBody();
|
||||||
inline const JPH::Body* GetBody() const;
|
inline const JPH::Body* GetBody() const;
|
||||||
inline UInt32 GetBodyIndex() const;
|
UInt32 GetBodyIndex() const override;
|
||||||
inline const std::shared_ptr<JoltCollider3D>& GetGeom() const;
|
inline const std::shared_ptr<JoltCollider3D>& GetGeom() const;
|
||||||
float GetLinearDamping() const;
|
float GetLinearDamping() const;
|
||||||
Vector3f GetLinearVelocity() const;
|
Vector3f GetLinearVelocity() const;
|
||||||
|
|
|
||||||
|
|
@ -36,11 +36,6 @@ namespace Nz
|
||||||
return m_body;
|
return m_body;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline UInt32 JoltRigidBody3D::GetBodyIndex() const
|
|
||||||
{
|
|
||||||
return m_bodyIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const std::shared_ptr<JoltCollider3D>& JoltRigidBody3D::GetGeom() const
|
inline const std::shared_ptr<JoltCollider3D>& JoltRigidBody3D::GetGeom() const
|
||||||
{
|
{
|
||||||
return m_geom;
|
return m_geom;
|
||||||
|
|
|
||||||
|
|
@ -25,13 +25,19 @@ namespace Nz
|
||||||
static constexpr Int64 ExecutionOrder = 0;
|
static constexpr Int64 ExecutionOrder = 0;
|
||||||
using Components = TypeList<JoltCharacterComponent, JoltRigidBody3DComponent, class NodeComponent>;
|
using Components = TypeList<JoltCharacterComponent, JoltRigidBody3DComponent, class NodeComponent>;
|
||||||
|
|
||||||
|
struct PointCollisionInfo;
|
||||||
struct RaycastHit;
|
struct RaycastHit;
|
||||||
|
struct ShapeCollisionInfo;
|
||||||
|
|
||||||
JoltPhysics3DSystem(entt::registry& registry);
|
JoltPhysics3DSystem(entt::registry& registry);
|
||||||
JoltPhysics3DSystem(const JoltPhysics3DSystem&) = delete;
|
JoltPhysics3DSystem(const JoltPhysics3DSystem&) = delete;
|
||||||
JoltPhysics3DSystem(JoltPhysics3DSystem&&) = delete;
|
JoltPhysics3DSystem(JoltPhysics3DSystem&&) = delete;
|
||||||
~JoltPhysics3DSystem();
|
~JoltPhysics3DSystem();
|
||||||
|
|
||||||
|
bool CollisionQuery(const Vector3f& point, const FunctionRef<std::optional<float>(const PointCollisionInfo& collisionInfo)>& callback);
|
||||||
|
bool CollisionQuery(const JoltCollider3D& collider, const Matrix4f& colliderTransform, const FunctionRef<std::optional<float>(const ShapeCollisionInfo& hitInfo)>& callback);
|
||||||
|
bool CollisionQuery(const JoltCollider3D& collider, const Matrix4f& colliderTransform, const Vector3f& colliderScale, const FunctionRef<std::optional<float>(const ShapeCollisionInfo& hitInfo)>& callback);
|
||||||
|
|
||||||
inline JoltPhysWorld3D& GetPhysWorld();
|
inline JoltPhysWorld3D& GetPhysWorld();
|
||||||
inline const JoltPhysWorld3D& GetPhysWorld() const;
|
inline const JoltPhysWorld3D& GetPhysWorld() const;
|
||||||
inline entt::handle GetRigidBodyEntity(UInt32 bodyIndex) const;
|
inline entt::handle GetRigidBodyEntity(UInt32 bodyIndex) const;
|
||||||
|
|
@ -44,15 +50,26 @@ namespace Nz
|
||||||
JoltPhysics3DSystem& operator=(const JoltPhysics3DSystem&) = delete;
|
JoltPhysics3DSystem& operator=(const JoltPhysics3DSystem&) = delete;
|
||||||
JoltPhysics3DSystem& operator=(JoltPhysics3DSystem&&) = delete;
|
JoltPhysics3DSystem& operator=(JoltPhysics3DSystem&&) = delete;
|
||||||
|
|
||||||
|
struct PointCollisionInfo : JoltPhysWorld3D::PointCollisionInfo
|
||||||
|
{
|
||||||
|
entt::handle hitEntity;
|
||||||
|
};
|
||||||
|
|
||||||
struct RaycastHit : JoltPhysWorld3D::RaycastHit
|
struct RaycastHit : JoltPhysWorld3D::RaycastHit
|
||||||
{
|
{
|
||||||
entt::handle hitEntity;
|
entt::handle hitEntity;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ShapeCollisionInfo : JoltPhysWorld3D::ShapeCollisionInfo
|
||||||
|
{
|
||||||
|
entt::handle hitEntity;
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void OnBodyConstruct(entt::registry& registry, entt::entity entity);
|
void OnBodyConstruct(entt::registry& registry, entt::entity entity);
|
||||||
void OnCharacterConstruct(entt::registry& registry, entt::entity entity);
|
|
||||||
void OnBodyDestruct(entt::registry& registry, entt::entity entity);
|
void OnBodyDestruct(entt::registry& registry, entt::entity entity);
|
||||||
|
void OnCharacterConstruct(entt::registry& registry, entt::entity entity);
|
||||||
|
void OnCharacterDestruct(entt::registry& registry, entt::entity entity);
|
||||||
|
|
||||||
std::size_t m_stepCount;
|
std::size_t m_stepCount;
|
||||||
std::vector<entt::entity> m_bodyIndicesToEntity;
|
std::vector<entt::entity> m_bodyIndicesToEntity;
|
||||||
|
|
@ -60,8 +77,9 @@ namespace Nz
|
||||||
entt::observer m_characterConstructObserver;
|
entt::observer m_characterConstructObserver;
|
||||||
entt::observer m_rigidBodyConstructObserver;
|
entt::observer m_rigidBodyConstructObserver;
|
||||||
entt::scoped_connection m_bodyConstructConnection;
|
entt::scoped_connection m_bodyConstructConnection;
|
||||||
entt::scoped_connection m_characterConstructConnection;
|
|
||||||
entt::scoped_connection m_bodyDestructConnection;
|
entt::scoped_connection m_bodyDestructConnection;
|
||||||
|
entt::scoped_connection m_characterConstructConnection;
|
||||||
|
entt::scoped_connection m_characterDestructConnection;
|
||||||
JoltPhysWorld3D m_physWorld;
|
JoltPhysWorld3D m_physWorld;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,15 +8,14 @@
|
||||||
#define NAZARA_MATH_QUATERNION_HPP
|
#define NAZARA_MATH_QUATERNION_HPP
|
||||||
|
|
||||||
#include <Nazara/Math/Angle.hpp>
|
#include <Nazara/Math/Angle.hpp>
|
||||||
|
#include <Nazara/Math/EulerAngles.hpp>
|
||||||
|
#include <Nazara/Math/Vector3.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
struct SerializationContext;
|
struct SerializationContext;
|
||||||
|
|
||||||
template<typename T> class EulerAngles;
|
|
||||||
template<typename T> class Vector3;
|
|
||||||
|
|
||||||
template<typename T> class Quaternion
|
template<typename T> class Quaternion
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -31,6 +30,7 @@ namespace Nz
|
||||||
constexpr Quaternion(Quaternion&&) = default;
|
constexpr Quaternion(Quaternion&&) = default;
|
||||||
~Quaternion() = default;
|
~Quaternion() = default;
|
||||||
|
|
||||||
|
RadianAngle<T> AngleBetween(const Quaternion& vec) const;
|
||||||
constexpr bool ApproxEqual(const Quaternion& quat, T maxDifference = std::numeric_limits<T>::epsilon()) const;
|
constexpr bool ApproxEqual(const Quaternion& quat, T maxDifference = std::numeric_limits<T>::epsilon()) const;
|
||||||
|
|
||||||
Quaternion& ComputeW();
|
Quaternion& ComputeW();
|
||||||
|
|
@ -75,12 +75,14 @@ namespace Nz
|
||||||
constexpr bool operator>(const Quaternion& quat) const;
|
constexpr bool operator>(const Quaternion& quat) const;
|
||||||
constexpr bool operator>=(const Quaternion& quat) const;
|
constexpr bool operator>=(const Quaternion& quat) const;
|
||||||
|
|
||||||
|
static RadianAngle<T> AngleBetween(const Quaternion& lhs, const Quaternion& rhs);
|
||||||
static constexpr bool ApproxEqual(const Quaternion& lhs, const Quaternion& rhs, T maxDifference = std::numeric_limits<T>::epsilon());
|
static constexpr bool ApproxEqual(const Quaternion& lhs, const Quaternion& rhs, T maxDifference = std::numeric_limits<T>::epsilon());
|
||||||
static constexpr Quaternion Identity();
|
static constexpr Quaternion Identity();
|
||||||
static constexpr Quaternion Lerp(const Quaternion& from, const Quaternion& to, T interpolation);
|
static constexpr Quaternion Lerp(const Quaternion& from, const Quaternion& to, T interpolation);
|
||||||
static Quaternion LookAt(const Vector3<T>& forward, const Vector3<T>& up);
|
static Quaternion LookAt(const Vector3<T>& forward, const Vector3<T>& up);
|
||||||
static Quaternion Normalize(const Quaternion& quat, T* length = nullptr);
|
static Quaternion Normalize(const Quaternion& quat, T* length = nullptr);
|
||||||
static Quaternion RotationBetween(const Vector3<T>& from, const Vector3<T>& to);
|
static Quaternion RotationBetween(const Vector3<T>& from, const Vector3<T>& to);
|
||||||
|
static Quaternion RotateTowards(const Quaternion& from, const Quaternion& to, RadianAngle<T> maxRotation);
|
||||||
static Quaternion Mirror(Quaternion quat, const Vector3<T>& axis);
|
static Quaternion Mirror(Quaternion quat, const Vector3<T>& axis);
|
||||||
static Quaternion Slerp(const Quaternion& from, const Quaternion& to, T interpolation);
|
static Quaternion Slerp(const Quaternion& from, const Quaternion& to, T interpolation);
|
||||||
static constexpr Quaternion Zero();
|
static constexpr Quaternion Zero();
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,6 @@
|
||||||
|
|
||||||
#include <Nazara/Core/Algorithm.hpp>
|
#include <Nazara/Core/Algorithm.hpp>
|
||||||
#include <Nazara/Math/Config.hpp>
|
#include <Nazara/Math/Config.hpp>
|
||||||
#include <Nazara/Math/EulerAngles.hpp>
|
|
||||||
#include <Nazara/Math/Vector3.hpp>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
@ -116,6 +114,13 @@ namespace Nz
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
RadianAngle<T> Quaternion<T>::AngleBetween(const Quaternion& quat) const
|
||||||
|
{
|
||||||
|
T alpha = Vector3<T>::DotProduct(Vector3<T>(x, y, z), Vector3<T>(quat.x, quat.y, quat.z));
|
||||||
|
return std::acos(Nz::Clamp(alpha, T(-1.0), T(1.0)));
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr bool Quaternion<T>::ApproxEqual(const Quaternion& quat, T maxDifference) const
|
constexpr bool Quaternion<T>::ApproxEqual(const Quaternion& quat, T maxDifference) const
|
||||||
{
|
{
|
||||||
|
|
@ -571,6 +576,12 @@ namespace Nz
|
||||||
return z >= quat.z;
|
return z >= quat.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
RadianAngle<T> Quaternion<T>::AngleBetween(const Quaternion& lhs, const Quaternion& rhs)
|
||||||
|
{
|
||||||
|
return lhs.AngleBetween(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr bool Quaternion<T>::ApproxEqual(const Quaternion& lhs, const Quaternion& rhs, T maxDifference)
|
constexpr bool Quaternion<T>::ApproxEqual(const Quaternion& lhs, const Quaternion& rhs, T maxDifference)
|
||||||
{
|
{
|
||||||
|
|
@ -687,6 +698,16 @@ namespace Nz
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
Quaternion<T> Quaternion<T>::RotateTowards(const Quaternion& from, const Quaternion& to, RadianAngle<T> maxRotation)
|
||||||
|
{
|
||||||
|
RadianAngle<T> rotationBetween = AngleBetween(from, to);
|
||||||
|
if (rotationBetween < maxRotation)
|
||||||
|
return to;
|
||||||
|
|
||||||
|
return Slerp(from, to, std::min(maxRotation.value / rotationBetween.value), 1.f);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Quaternion<T> Quaternion<T>::Mirror(Quaternion quat, const Vector3<T>& axis)
|
Quaternion<T> Quaternion<T>::Mirror(Quaternion quat, const Vector3<T>& axis)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,7 @@ namespace Nz
|
||||||
static constexpr Vector3 Lerp(const Vector3& from, const Vector3& to, T interpolation);
|
static constexpr Vector3 Lerp(const Vector3& from, const Vector3& to, T interpolation);
|
||||||
static constexpr Vector3 Max(const Vector3& lhs, const Vector3& rhs);
|
static constexpr Vector3 Max(const Vector3& lhs, const Vector3& rhs);
|
||||||
static constexpr Vector3 Min(const Vector3& lhs, const Vector3& rhs);
|
static constexpr Vector3 Min(const Vector3& lhs, const Vector3& rhs);
|
||||||
|
static Vector3 RotateTowards(const Vector3& from, const Vector3& to, RadianAngle<T> maxAngle);
|
||||||
static Vector3 Normalize(const Vector3& vec);
|
static Vector3 Normalize(const Vector3& vec);
|
||||||
static constexpr Vector3 Right();
|
static constexpr Vector3 Right();
|
||||||
static constexpr T SquaredDistance(const Vector3& vec1, const Vector3& vec2);
|
static constexpr T SquaredDistance(const Vector3& vec1, const Vector3& vec2);
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@ namespace Nz
|
||||||
*
|
*
|
||||||
* \param vec The other vector to measure the angle with
|
* \param vec The other vector to measure the angle with
|
||||||
*
|
*
|
||||||
* \remark The vectors do not need to be normalised
|
* \remark The vectors need to be normalised
|
||||||
* \remark Produce a NazaraError if one of the vec components is null with NAZARA_MATH_SAFE defined
|
* \remark Produce a NazaraError if one of the vec components is null with NAZARA_MATH_SAFE defined
|
||||||
* \throw std::domain_error if NAZARA_MATH_SAFE is defined and one of the vec components is null
|
* \throw std::domain_error if NAZARA_MATH_SAFE is defined and one of the vec components is null
|
||||||
*
|
*
|
||||||
|
|
@ -132,20 +132,7 @@ namespace Nz
|
||||||
template<typename T>
|
template<typename T>
|
||||||
RadianAngle<T> Vector3<T>::AngleBetween(const Vector3& vec) const
|
RadianAngle<T> Vector3<T>::AngleBetween(const Vector3& vec) const
|
||||||
{
|
{
|
||||||
// sqrt(a) * sqrt(b) = sqrt(a*b)
|
T alpha = DotProduct(vec);
|
||||||
T divisor = std::sqrt(GetSquaredLength() * vec.GetSquaredLength());
|
|
||||||
|
|
||||||
#if NAZARA_MATH_SAFE
|
|
||||||
if (NumberEquals(divisor, T(0.0)))
|
|
||||||
{
|
|
||||||
std::string error("Division by zero");
|
|
||||||
|
|
||||||
NazaraError(error);
|
|
||||||
throw std::domain_error(std::move(error));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
T alpha = DotProduct(vec) / divisor;
|
|
||||||
return std::acos(Nz::Clamp(alpha, T(-1.0), T(1.0)));
|
return std::acos(Nz::Clamp(alpha, T(-1.0), T(1.0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -835,6 +822,20 @@ namespace Nz
|
||||||
return min;
|
return min;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
Vector3<T> Vector3<T>::RotateTowards(const Vector3& from, const Vector3& to, RadianAngle<T> maxAngle)
|
||||||
|
{
|
||||||
|
// https://gamedev.stackexchange.com/a/203036
|
||||||
|
RadianAngle<T> angleBetween = from.AngleBetween(to);
|
||||||
|
if (angleBetween < maxAngle)
|
||||||
|
return to;
|
||||||
|
|
||||||
|
Vector3 axis = CrossProduct(from, to);
|
||||||
|
|
||||||
|
Quaternion<T> rotationIncrement = Quaternion(maxAngle, axis);
|
||||||
|
return rotationIncrement * from;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Gives the normalized vector
|
* \brief Gives the normalized vector
|
||||||
* \return A normalized vector from the vec
|
* \return A normalized vector from the vec
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,10 @@ namespace Nz
|
||||||
Canvas& operator=(const Canvas&) = delete;
|
Canvas& operator=(const Canvas&) = delete;
|
||||||
Canvas& operator=(Canvas&&) = delete;
|
Canvas& operator=(Canvas&&) = delete;
|
||||||
|
|
||||||
|
NazaraSignal(OnUnhandledMouseButtonPressed, const WindowEventHandler* /*eventHandler*/, const WindowEvent::MouseButtonEvent& /*event*/);
|
||||||
|
NazaraSignal(OnUnhandledMouseButtonReleased, const WindowEventHandler* /*eventHandler*/, const WindowEvent::MouseButtonEvent& /*event*/);
|
||||||
|
NazaraSignal(OnUnhandledMouseMoved, const WindowEventHandler* /*eventHandler*/, const WindowEvent::MouseMoveEvent& /*event*/);
|
||||||
|
NazaraSignal(OnUnhandledMouseWheelMoved, const WindowEventHandler* /*eventHandler*/, const WindowEvent::MouseWheelEvent& /*event*/);
|
||||||
NazaraSignal(OnUnhandledKeyPressed, const WindowEventHandler* /*eventHandler*/, const WindowEvent::KeyEvent& /*event*/);
|
NazaraSignal(OnUnhandledKeyPressed, const WindowEventHandler* /*eventHandler*/, const WindowEvent::KeyEvent& /*event*/);
|
||||||
NazaraSignal(OnUnhandledKeyReleased, const WindowEventHandler* /*eventHandler*/, const WindowEvent::KeyEvent& /*event*/);
|
NazaraSignal(OnUnhandledKeyReleased, const WindowEventHandler* /*eventHandler*/, const WindowEvent::KeyEvent& /*event*/);
|
||||||
|
|
||||||
|
|
@ -55,7 +59,7 @@ namespace Nz
|
||||||
void UnregisterWidget(std::size_t index);
|
void UnregisterWidget(std::size_t index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<typename F> void DispatchEvent(std::size_t widgetIndex, F&& functor);
|
template<typename F> bool DispatchEvent(std::size_t widgetIndex, F&& functor);
|
||||||
|
|
||||||
void OnEventMouseButtonPressed(const WindowEventHandler* eventHandler, const WindowEvent::MouseButtonEvent& event);
|
void OnEventMouseButtonPressed(const WindowEventHandler* eventHandler, const WindowEvent::MouseButtonEvent& event);
|
||||||
void OnEventMouseButtonRelease(const WindowEventHandler* eventHandler, const WindowEvent::MouseButtonEvent& event);
|
void OnEventMouseButtonRelease(const WindowEventHandler* eventHandler, const WindowEvent::MouseButtonEvent& event);
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,10 @@ namespace Nz
|
||||||
|
|
||||||
// Regular OpenAL contexts are process-wide, but ALC_EXT_thread_local_context allows thread-local contexts
|
// Regular OpenAL contexts are process-wide, but ALC_EXT_thread_local_context allows thread-local contexts
|
||||||
const OpenALDevice* s_currentGlobalALDevice;
|
const OpenALDevice* s_currentGlobalALDevice;
|
||||||
|
|
||||||
|
#ifdef ALC_EXT_thread_local_context
|
||||||
thread_local const OpenALDevice* s_currentThreadALDevice;
|
thread_local const OpenALDevice* s_currentThreadALDevice;
|
||||||
|
#endif
|
||||||
|
|
||||||
template<typename FuncType, std::size_t FuncIndex, typename>
|
template<typename FuncType, std::size_t FuncIndex, typename>
|
||||||
struct ALWrapper;
|
struct ALWrapper;
|
||||||
|
|
@ -175,8 +178,10 @@ namespace Nz
|
||||||
alcDestroyContext(m_context);
|
alcDestroyContext(m_context);
|
||||||
alcCloseDevice(m_device);
|
alcCloseDevice(m_device);
|
||||||
|
|
||||||
|
#ifdef ALC_EXT_thread_local_context
|
||||||
if (s_currentThreadALDevice)
|
if (s_currentThreadALDevice)
|
||||||
s_currentThreadALDevice = nullptr;
|
s_currentThreadALDevice = nullptr;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (s_currentGlobalALDevice == this)
|
if (s_currentGlobalALDevice == this)
|
||||||
s_currentGlobalALDevice = nullptr;
|
s_currentGlobalALDevice = nullptr;
|
||||||
|
|
@ -331,6 +336,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
NAZARA_USE_ANONYMOUS_NAMESPACE
|
NAZARA_USE_ANONYMOUS_NAMESPACE
|
||||||
|
|
||||||
|
#ifdef ALC_EXT_thread_local_context
|
||||||
if (alcSetThreadContext)
|
if (alcSetThreadContext)
|
||||||
{
|
{
|
||||||
if (s_currentThreadALDevice != this)
|
if (s_currentThreadALDevice != this)
|
||||||
|
|
@ -340,17 +346,21 @@ namespace Nz
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
if (s_currentGlobalALDevice != this)
|
if (s_currentGlobalALDevice != this)
|
||||||
{
|
{
|
||||||
|
alcMakeContextCurrent(m_context);
|
||||||
|
s_currentGlobalALDevice = this;
|
||||||
|
|
||||||
|
#ifdef ALC_EXT_thread_local_context
|
||||||
/*
|
/*
|
||||||
From EXT_thread_local_context:
|
From EXT_thread_local_context:
|
||||||
alcMakeContextCurrent changes the current process-wide context and set the current thread-local context to NULL.
|
alcMakeContextCurrent changes the current process-wide context and set the current thread-local context to NULL.
|
||||||
This has the side effect of changing the current thread-local context, so that the new current process-wide context will be used.
|
This has the side effect of changing the current thread-local context, so that the new current process-wide context will be used.
|
||||||
*/
|
*/
|
||||||
alcMakeContextCurrent(m_context);
|
|
||||||
s_currentGlobalALDevice = this;
|
|
||||||
s_currentThreadALDevice = nullptr;
|
s_currentThreadALDevice = nullptr;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -514,9 +524,13 @@ namespace Nz
|
||||||
|
|
||||||
const OpenALDevice* OpenALDevice::GetCurrentDevice()
|
const OpenALDevice* OpenALDevice::GetCurrentDevice()
|
||||||
{
|
{
|
||||||
|
NAZARA_USE_ANONYMOUS_NAMESPACE
|
||||||
|
|
||||||
|
#ifdef ALC_EXT_thread_local_context
|
||||||
const OpenALDevice* device = s_currentThreadALDevice;
|
const OpenALDevice* device = s_currentThreadALDevice;
|
||||||
if (device)
|
if (device)
|
||||||
return device;
|
return device;
|
||||||
|
#endif
|
||||||
|
|
||||||
return s_currentGlobalALDevice;
|
return s_currentGlobalALDevice;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
|
||||||
|
// This file is part of the "Nazara Engine - JoltPhysics3D module"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
#include <Nazara/JoltPhysics3D/JoltAbstractBody.hpp>
|
||||||
|
#include <Nazara/JoltPhysics3D/Debug.hpp>
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
JoltAbstractBody::~JoltAbstractBody() = default;
|
||||||
|
}
|
||||||
|
|
@ -29,7 +29,13 @@ namespace Nz
|
||||||
m_bodyIndex(character.m_bodyIndex)
|
m_bodyIndex(character.m_bodyIndex)
|
||||||
{
|
{
|
||||||
character.m_bodyIndex = std::numeric_limits<UInt32>::max();
|
character.m_bodyIndex = std::numeric_limits<UInt32>::max();
|
||||||
|
|
||||||
|
if (m_character)
|
||||||
|
{
|
||||||
|
JPH::BodyInterface& bodyInterface = m_world->GetPhysicsSystem()->GetBodyInterfaceNoLock();
|
||||||
|
bodyInterface.SetUserData(m_character->GetBodyID(), SafeCast<UInt64>(reinterpret_cast<std::uintptr_t>(this)));
|
||||||
|
}
|
||||||
|
|
||||||
if (m_world)
|
if (m_world)
|
||||||
{
|
{
|
||||||
m_world->UnregisterStepListener(&character);
|
m_world->UnregisterStepListener(&character);
|
||||||
|
|
@ -52,6 +58,11 @@ namespace Nz
|
||||||
bodyLock.GetBody().SetAllowSleeping(enable);
|
bodyLock.GetBody().SetAllowSleeping(enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UInt32 JoltCharacter::GetBodyIndex() const
|
||||||
|
{
|
||||||
|
return m_bodyIndex;
|
||||||
|
}
|
||||||
|
|
||||||
Vector3f JoltCharacter::GetLinearVelocity() const
|
Vector3f JoltCharacter::GetLinearVelocity() const
|
||||||
{
|
{
|
||||||
return FromJolt(m_character->GetLinearVelocity(false));
|
return FromJolt(m_character->GetLinearVelocity(false));
|
||||||
|
|
@ -135,6 +146,12 @@ namespace Nz
|
||||||
|
|
||||||
character.m_bodyIndex = std::numeric_limits<UInt32>::max();
|
character.m_bodyIndex = std::numeric_limits<UInt32>::max();
|
||||||
|
|
||||||
|
if (m_character)
|
||||||
|
{
|
||||||
|
JPH::BodyInterface& bodyInterface = m_world->GetPhysicsSystem()->GetBodyInterfaceNoLock();
|
||||||
|
bodyInterface.SetUserData(m_character->GetBodyID(), SafeCast<UInt64>(reinterpret_cast<std::uintptr_t>(this)));
|
||||||
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -157,6 +174,9 @@ namespace Nz
|
||||||
|
|
||||||
m_bodyIndex = m_character->GetBodyID().GetIndex();
|
m_bodyIndex = m_character->GetBodyID().GetIndex();
|
||||||
|
|
||||||
|
JPH::BodyInterface& bodyInterface = m_world->GetPhysicsSystem()->GetBodyInterfaceNoLock();
|
||||||
|
bodyInterface.SetUserData(m_character->GetBodyID(), SafeCast<UInt64>(reinterpret_cast<std::uintptr_t>(this)));
|
||||||
|
|
||||||
m_world->RegisterStepListener(this);
|
m_world->RegisterStepListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -177,10 +197,10 @@ namespace Nz
|
||||||
m_collider.reset();
|
m_collider.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void JoltCharacter::PostSimulate()
|
void JoltCharacter::PostSimulate(float elapsedTime)
|
||||||
{
|
{
|
||||||
m_character->PostSimulation(0.05f);
|
m_character->PostSimulation(0.05f);
|
||||||
m_impl->PostSimulate(*this);
|
m_impl->PostSimulate(*this, elapsedTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JoltCharacter::PreSimulate(float elapsedTime)
|
void JoltCharacter::PreSimulate(float elapsedTime)
|
||||||
|
|
@ -191,7 +211,7 @@ namespace Nz
|
||||||
|
|
||||||
JoltCharacterImpl::~JoltCharacterImpl() = default;
|
JoltCharacterImpl::~JoltCharacterImpl() = default;
|
||||||
|
|
||||||
void JoltCharacterImpl::PostSimulate(JoltCharacter& /*character*/)
|
void JoltCharacterImpl::PostSimulate(JoltCharacter& /*character*/, float /*elapsedTime*/)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include <Nazara/JoltPhysics3D/JoltPhysWorld3D.hpp>
|
#include <Nazara/JoltPhysics3D/JoltPhysWorld3D.hpp>
|
||||||
#include <Nazara/JoltPhysics3D/JoltCharacter.hpp>
|
#include <Nazara/JoltPhysics3D/JoltCharacter.hpp>
|
||||||
|
#include <Nazara/JoltPhysics3D/JoltCollider3D.hpp>
|
||||||
#include <Nazara/JoltPhysics3D/JoltHelper.hpp>
|
#include <Nazara/JoltPhysics3D/JoltHelper.hpp>
|
||||||
#include <Nazara/JoltPhysics3D/JoltPhysics3D.hpp>
|
#include <Nazara/JoltPhysics3D/JoltPhysics3D.hpp>
|
||||||
#include <Nazara/JoltPhysics3D/JoltPhysicsStepListener.hpp>
|
#include <Nazara/JoltPhysics3D/JoltPhysicsStepListener.hpp>
|
||||||
|
|
@ -16,6 +17,8 @@
|
||||||
#include <Jolt/Physics/PhysicsSystem.h>
|
#include <Jolt/Physics/PhysicsSystem.h>
|
||||||
#include <Jolt/Physics/Body/BodyActivationListener.h>
|
#include <Jolt/Physics/Body/BodyActivationListener.h>
|
||||||
#include <Jolt/Physics/Collision/CastResult.h>
|
#include <Jolt/Physics/Collision/CastResult.h>
|
||||||
|
#include <Jolt/Physics/Collision/CollidePointResult.h>
|
||||||
|
#include <Jolt/Physics/Collision/CollideShape.h>
|
||||||
#include <Jolt/Physics/Collision/CollisionCollectorImpl.h>
|
#include <Jolt/Physics/Collision/CollisionCollectorImpl.h>
|
||||||
#include <Jolt/Physics/Collision/ObjectLayer.h>
|
#include <Jolt/Physics/Collision/ObjectLayer.h>
|
||||||
#include <Jolt/Physics/Collision/RayCast.h>
|
#include <Jolt/Physics/Collision/RayCast.h>
|
||||||
|
|
@ -162,10 +165,106 @@ namespace Nz
|
||||||
{
|
{
|
||||||
namespace NAZARA_ANONYMOUS_NAMESPACE
|
namespace NAZARA_ANONYMOUS_NAMESPACE
|
||||||
{
|
{
|
||||||
class CallbackHitResult : public JPH::CastRayCollector
|
class PointCallbackHitResult : public JPH::CollidePointCollector
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CallbackHitResult(const JPH::BodyLockInterface& bodyLockInterface, const Vector3f& from, const Vector3f& to, const FunctionRef<std::optional<float>(const JoltPhysWorld3D::RaycastHit& hitInfo)>& callback) :
|
PointCallbackHitResult(const JPH::BodyLockInterface& bodyLockInterface, const FunctionRef<std::optional<float>(const JoltPhysWorld3D::PointCollisionInfo& hitInfo)>& callback) :
|
||||||
|
m_bodyLockInterface(bodyLockInterface),
|
||||||
|
m_callback(callback),
|
||||||
|
m_didHit(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddHit(const JPH::CollidePointResult& result) override
|
||||||
|
{
|
||||||
|
JoltPhysWorld3D::PointCollisionInfo hitInfo;
|
||||||
|
|
||||||
|
JPH::BodyLockWrite lock(m_bodyLockInterface, result.mBodyID);
|
||||||
|
if (!lock.Succeeded())
|
||||||
|
return; //< body was destroyed
|
||||||
|
|
||||||
|
JPH::Body& body = lock.GetBody();
|
||||||
|
|
||||||
|
hitInfo.hitBody = reinterpret_cast<JoltAbstractBody*>(static_cast<std::uintptr_t>(body.GetUserData()));
|
||||||
|
|
||||||
|
if (auto fractionOpt = m_callback(hitInfo))
|
||||||
|
{
|
||||||
|
float fraction = fractionOpt.value();
|
||||||
|
if (fraction > 0.f)
|
||||||
|
{
|
||||||
|
m_didHit = true;
|
||||||
|
UpdateEarlyOutFraction(fraction);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ForceEarlyOut();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DidHit() const
|
||||||
|
{
|
||||||
|
return m_didHit;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const JPH::BodyLockInterface& m_bodyLockInterface;
|
||||||
|
const FunctionRef<std::optional<float>(const JoltPhysWorld3D::PointCollisionInfo& hitInfo)>& m_callback;
|
||||||
|
bool m_didHit;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ShapeCallbackHitResult : public JPH::CollideShapeCollector
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ShapeCallbackHitResult(const JPH::BodyLockInterface& bodyLockInterface, const FunctionRef<std::optional<float>(const JoltPhysWorld3D::ShapeCollisionInfo& hitInfo)>& callback) :
|
||||||
|
m_bodyLockInterface(bodyLockInterface),
|
||||||
|
m_callback(callback),
|
||||||
|
m_didHit(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddHit(const JPH::CollideShapeResult& result) override
|
||||||
|
{
|
||||||
|
JoltPhysWorld3D::ShapeCollisionInfo hitInfo;
|
||||||
|
hitInfo.collisionPosition1 = FromJolt(result.mContactPointOn1);
|
||||||
|
hitInfo.collisionPosition2 = FromJolt(result.mContactPointOn2);
|
||||||
|
hitInfo.penetrationAxis = FromJolt(result.mPenetrationAxis);
|
||||||
|
hitInfo.penetrationDepth = result.mPenetrationDepth;
|
||||||
|
|
||||||
|
JPH::BodyLockWrite lock(m_bodyLockInterface, result.mBodyID2);
|
||||||
|
if (!lock.Succeeded())
|
||||||
|
return; //< body was destroyed
|
||||||
|
|
||||||
|
JPH::Body& body = lock.GetBody();
|
||||||
|
|
||||||
|
hitInfo.hitBody = reinterpret_cast<JoltAbstractBody*>(static_cast<std::uintptr_t>(body.GetUserData()));
|
||||||
|
|
||||||
|
if (auto fractionOpt = m_callback(hitInfo))
|
||||||
|
{
|
||||||
|
float fraction = fractionOpt.value();
|
||||||
|
if (fraction > 0.f)
|
||||||
|
{
|
||||||
|
m_didHit = true;
|
||||||
|
UpdateEarlyOutFraction(fraction);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ForceEarlyOut();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DidHit() const
|
||||||
|
{
|
||||||
|
return m_didHit;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const JPH::BodyLockInterface& m_bodyLockInterface;
|
||||||
|
const FunctionRef<std::optional<float>(const JoltPhysWorld3D::ShapeCollisionInfo& hitInfo)>& m_callback;
|
||||||
|
bool m_didHit;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RaycastCallbackHitResult : public JPH::CastRayCollector
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RaycastCallbackHitResult(const JPH::BodyLockInterface& bodyLockInterface, const Vector3f& from, const Vector3f& to, const FunctionRef<std::optional<float>(const JoltPhysWorld3D::RaycastHit& hitInfo)>& callback) :
|
||||||
m_bodyLockInterface(bodyLockInterface),
|
m_bodyLockInterface(bodyLockInterface),
|
||||||
m_callback(callback),
|
m_callback(callback),
|
||||||
m_from(from),
|
m_from(from),
|
||||||
|
|
@ -186,7 +285,7 @@ namespace Nz
|
||||||
|
|
||||||
JPH::Body& body = lock.GetBody();
|
JPH::Body& body = lock.GetBody();
|
||||||
|
|
||||||
hitInfo.hitBody = reinterpret_cast<JoltRigidBody3D*>(static_cast<std::uintptr_t>(body.GetUserData()));
|
hitInfo.hitBody = reinterpret_cast<JoltAbstractBody*>(static_cast<std::uintptr_t>(body.GetUserData()));
|
||||||
hitInfo.hitNormal = FromJolt(body.GetWorldSpaceSurfaceNormal(result.mSubShapeID2, ToJolt(hitInfo.hitPosition)));
|
hitInfo.hitNormal = FromJolt(body.GetWorldSpaceSurfaceNormal(result.mSubShapeID2, ToJolt(hitInfo.hitPosition)));
|
||||||
|
|
||||||
if (auto fractionOpt = m_callback(hitInfo))
|
if (auto fractionOpt = m_callback(hitInfo))
|
||||||
|
|
@ -323,6 +422,35 @@ namespace Nz
|
||||||
|
|
||||||
JoltPhysWorld3D::~JoltPhysWorld3D() = default;
|
JoltPhysWorld3D::~JoltPhysWorld3D() = default;
|
||||||
|
|
||||||
|
bool JoltPhysWorld3D::CollisionQuery(const Vector3f& point, const FunctionRef<std::optional<float>(const PointCollisionInfo& collisionInfo)>& callback)
|
||||||
|
{
|
||||||
|
NAZARA_USE_ANONYMOUS_NAMESPACE
|
||||||
|
|
||||||
|
PointCallbackHitResult collector(m_world->physicsSystem.GetBodyLockInterface(), callback);
|
||||||
|
m_world->physicsSystem.GetNarrowPhaseQuery().CollidePoint(ToJolt(point), collector);
|
||||||
|
|
||||||
|
return collector.DidHit();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JoltPhysWorld3D::CollisionQuery(const JoltCollider3D& collider, const Matrix4f& colliderTransform, const FunctionRef<std::optional<float>(const ShapeCollisionInfo& hitInfo)>& callback)
|
||||||
|
{
|
||||||
|
return CollisionQuery(collider, colliderTransform, Vector3f::Unit(), callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JoltPhysWorld3D::CollisionQuery(const JoltCollider3D& collider, const Matrix4f& colliderTransform, const Vector3f& colliderScale, const FunctionRef<std::optional<float>(const ShapeCollisionInfo& hitInfo)>& callback)
|
||||||
|
{
|
||||||
|
NAZARA_USE_ANONYMOUS_NAMESPACE
|
||||||
|
|
||||||
|
JPH::Shape* shape = collider.GetShapeSettings()->Create().Get();
|
||||||
|
|
||||||
|
JPH::CollideShapeSettings collideShapeSettings;
|
||||||
|
|
||||||
|
ShapeCallbackHitResult collector(m_world->physicsSystem.GetBodyLockInterface(), callback);
|
||||||
|
m_world->physicsSystem.GetNarrowPhaseQuery().CollideShape(shape, ToJolt(colliderScale), ToJolt(colliderTransform), collideShapeSettings, JPH::Vec3::sZero(), collector);
|
||||||
|
|
||||||
|
return collector.DidHit();
|
||||||
|
}
|
||||||
|
|
||||||
UInt32 JoltPhysWorld3D::GetActiveBodyCount() const
|
UInt32 JoltPhysWorld3D::GetActiveBodyCount() const
|
||||||
{
|
{
|
||||||
return m_world->physicsSystem.GetNumActiveBodies(JPH::EBodyType::RigidBody);
|
return m_world->physicsSystem.GetNumActiveBodies(JPH::EBodyType::RigidBody);
|
||||||
|
|
@ -358,7 +486,7 @@ namespace Nz
|
||||||
|
|
||||||
JPH::RayCastSettings rayCastSettings;
|
JPH::RayCastSettings rayCastSettings;
|
||||||
|
|
||||||
CallbackHitResult collector(m_world->physicsSystem.GetBodyLockInterface(), from, to, callback);
|
RaycastCallbackHitResult collector(m_world->physicsSystem.GetBodyLockInterface(), from, to, callback);
|
||||||
m_world->physicsSystem.GetNarrowPhaseQuery().CastRay(rayCast, rayCastSettings, collector);
|
m_world->physicsSystem.GetNarrowPhaseQuery().CastRay(rayCast, rayCastSettings, collector);
|
||||||
|
|
||||||
return collector.DidHit();
|
return collector.DidHit();
|
||||||
|
|
@ -387,7 +515,7 @@ namespace Nz
|
||||||
RaycastHit hitInfo;
|
RaycastHit hitInfo;
|
||||||
hitInfo.fraction = collector.mHit.GetEarlyOutFraction();
|
hitInfo.fraction = collector.mHit.GetEarlyOutFraction();
|
||||||
hitInfo.hitPosition = Lerp(from, to, hitInfo.fraction);
|
hitInfo.hitPosition = Lerp(from, to, hitInfo.fraction);
|
||||||
hitInfo.hitBody = reinterpret_cast<JoltRigidBody3D*>(static_cast<std::uintptr_t>(body.GetUserData()));
|
hitInfo.hitBody = reinterpret_cast<JoltAbstractBody*>(static_cast<std::uintptr_t>(body.GetUserData()));
|
||||||
hitInfo.hitNormal = FromJolt(body.GetWorldSpaceSurfaceNormal(collector.mHit.mSubShapeID2, rayCast.GetPointOnRay(collector.mHit.GetEarlyOutFraction())));
|
hitInfo.hitNormal = FromJolt(body.GetWorldSpaceSurfaceNormal(collector.mHit.mSubShapeID2, rayCast.GetPointOnRay(collector.mHit.GetEarlyOutFraction())));
|
||||||
|
|
||||||
callback(hitInfo);
|
callback(hitInfo);
|
||||||
|
|
@ -473,7 +601,7 @@ namespace Nz
|
||||||
m_world->physicsSystem.Update(stepSize, 1, &m_world->tempAllocator, &jobSystem);
|
m_world->physicsSystem.Update(stepSize, 1, &m_world->tempAllocator, &jobSystem);
|
||||||
|
|
||||||
for (JoltPhysicsStepListener* stepListener : m_stepListeners)
|
for (JoltPhysicsStepListener* stepListener : m_stepListeners)
|
||||||
stepListener->PostSimulate();
|
stepListener->PostSimulate(stepSize);
|
||||||
|
|
||||||
m_timestepAccumulator -= m_stepSize;
|
m_timestepAccumulator -= m_stepSize;
|
||||||
stepCount++;
|
stepCount++;
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
JoltPhysicsStepListener::~JoltPhysicsStepListener() = default;
|
JoltPhysicsStepListener::~JoltPhysicsStepListener() = default;
|
||||||
|
|
||||||
void JoltPhysicsStepListener::PostSimulate()
|
void JoltPhysicsStepListener::PostSimulate(float /*elapsedTime*/)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -120,6 +120,11 @@ namespace Nz
|
||||||
return FromJolt(m_body->GetAngularVelocity());
|
return FromJolt(m_body->GetAngularVelocity());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UInt32 JoltRigidBody3D::GetBodyIndex() const
|
||||||
|
{
|
||||||
|
return m_bodyIndex;
|
||||||
|
}
|
||||||
|
|
||||||
float JoltRigidBody3D::GetLinearDamping() const
|
float JoltRigidBody3D::GetLinearDamping() const
|
||||||
{
|
{
|
||||||
if NAZARA_UNLIKELY(IsStatic())
|
if NAZARA_UNLIKELY(IsStatic())
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
// 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/JoltPhysics3D/Systems/JoltPhysics3DSystem.hpp>
|
#include <Nazara/JoltPhysics3D/Systems/JoltPhysics3DSystem.hpp>
|
||||||
|
#include <Nazara/JoltPhysics3D/JoltAbstractBody.hpp>
|
||||||
#include <Nazara/Core/Components/DisabledComponent.hpp>
|
#include <Nazara/Core/Components/DisabledComponent.hpp>
|
||||||
#include <Nazara/Utility/Components/NodeComponent.hpp>
|
#include <Nazara/Utility/Components/NodeComponent.hpp>
|
||||||
#include <Nazara/JoltPhysics3D/Debug.hpp>
|
#include <Nazara/JoltPhysics3D/Debug.hpp>
|
||||||
|
|
@ -15,8 +16,9 @@ namespace Nz
|
||||||
m_rigidBodyConstructObserver(m_registry, entt::collector.group<JoltRigidBody3DComponent, NodeComponent>(entt::exclude<DisabledComponent, JoltCharacterComponent>))
|
m_rigidBodyConstructObserver(m_registry, entt::collector.group<JoltRigidBody3DComponent, NodeComponent>(entt::exclude<DisabledComponent, JoltCharacterComponent>))
|
||||||
{
|
{
|
||||||
m_bodyConstructConnection = registry.on_construct<JoltRigidBody3DComponent>().connect<&JoltPhysics3DSystem::OnBodyConstruct>(this);
|
m_bodyConstructConnection = registry.on_construct<JoltRigidBody3DComponent>().connect<&JoltPhysics3DSystem::OnBodyConstruct>(this);
|
||||||
m_characterConstructConnection = registry.on_construct<JoltCharacterComponent>().connect<&JoltPhysics3DSystem::OnCharacterConstruct>(this);
|
|
||||||
m_bodyDestructConnection = registry.on_destroy<JoltRigidBody3DComponent>().connect<&JoltPhysics3DSystem::OnBodyDestruct>(this);
|
m_bodyDestructConnection = registry.on_destroy<JoltRigidBody3DComponent>().connect<&JoltPhysics3DSystem::OnBodyDestruct>(this);
|
||||||
|
m_characterConstructConnection = registry.on_construct<JoltCharacterComponent>().connect<&JoltPhysics3DSystem::OnCharacterConstruct>(this);
|
||||||
|
m_characterDestructConnection = registry.on_destroy<JoltCharacterComponent>().connect<&JoltPhysics3DSystem::OnCharacterDestruct>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
JoltPhysics3DSystem::~JoltPhysics3DSystem()
|
JoltPhysics3DSystem::~JoltPhysics3DSystem()
|
||||||
|
|
@ -34,6 +36,47 @@ namespace Nz
|
||||||
rigidBodyComponent.Destroy(true);
|
rigidBodyComponent.Destroy(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool JoltPhysics3DSystem::CollisionQuery(const Vector3f& point, const FunctionRef<std::optional<float>(const PointCollisionInfo& collisionInfo)>& callback)
|
||||||
|
{
|
||||||
|
return m_physWorld.CollisionQuery(point, [&](const JoltPhysWorld3D::PointCollisionInfo& hitInfo)
|
||||||
|
{
|
||||||
|
PointCollisionInfo extendedHitInfo;
|
||||||
|
static_cast<JoltPhysWorld3D::PointCollisionInfo&>(extendedHitInfo) = hitInfo;
|
||||||
|
|
||||||
|
if (extendedHitInfo.hitBody)
|
||||||
|
{
|
||||||
|
std::size_t bodyIndex = extendedHitInfo.hitBody->GetBodyIndex();
|
||||||
|
if (bodyIndex < m_bodyIndicesToEntity.size())
|
||||||
|
extendedHitInfo.hitEntity = entt::handle(m_registry, m_bodyIndicesToEntity[bodyIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return callback(extendedHitInfo);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JoltPhysics3DSystem::CollisionQuery(const JoltCollider3D& collider, const Matrix4f& shapeTransform, const FunctionRef<std::optional<float>(const ShapeCollisionInfo& hitInfo)>& callback)
|
||||||
|
{
|
||||||
|
return CollisionQuery(collider, shapeTransform, Vector3f::Unit(), callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JoltPhysics3DSystem::CollisionQuery(const JoltCollider3D& collider, const Matrix4f& colliderTransform, const Vector3f& colliderScale, const FunctionRef<std::optional<float>(const ShapeCollisionInfo& hitInfo)>& callback)
|
||||||
|
{
|
||||||
|
return m_physWorld.CollisionQuery(collider, colliderTransform, colliderScale, [&](const JoltPhysWorld3D::ShapeCollisionInfo& hitInfo)
|
||||||
|
{
|
||||||
|
ShapeCollisionInfo extendedHitInfo;
|
||||||
|
static_cast<JoltPhysWorld3D::ShapeCollisionInfo&>(extendedHitInfo) = hitInfo;
|
||||||
|
|
||||||
|
if (extendedHitInfo.hitBody)
|
||||||
|
{
|
||||||
|
std::size_t bodyIndex = extendedHitInfo.hitBody->GetBodyIndex();
|
||||||
|
if (bodyIndex < m_bodyIndicesToEntity.size())
|
||||||
|
extendedHitInfo.hitEntity = entt::handle(m_registry, m_bodyIndicesToEntity[bodyIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return callback(extendedHitInfo);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
bool JoltPhysics3DSystem::RaycastQuery(const Vector3f& from, const Vector3f& to, const FunctionRef<std::optional<float>(const RaycastHit& hitInfo)>& callback)
|
bool JoltPhysics3DSystem::RaycastQuery(const Vector3f& from, const Vector3f& to, const FunctionRef<std::optional<float>(const RaycastHit& hitInfo)>& callback)
|
||||||
{
|
{
|
||||||
return m_physWorld.RaycastQuery(from, to, [&](const JoltPhysWorld3D::RaycastHit& hitInfo)
|
return m_physWorld.RaycastQuery(from, to, [&](const JoltPhysWorld3D::RaycastHit& hitInfo)
|
||||||
|
|
@ -139,12 +182,6 @@ namespace Nz
|
||||||
m_bodyIndicesToEntity[uniqueIndex] = entity;
|
m_bodyIndicesToEntity[uniqueIndex] = entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JoltPhysics3DSystem::OnCharacterConstruct(entt::registry& registry, entt::entity entity)
|
|
||||||
{
|
|
||||||
JoltCharacterComponent& character = registry.get<JoltCharacterComponent>(entity);
|
|
||||||
character.Construct(m_physWorld);
|
|
||||||
}
|
|
||||||
|
|
||||||
void JoltPhysics3DSystem::OnBodyDestruct(entt::registry& registry, entt::entity entity)
|
void JoltPhysics3DSystem::OnBodyDestruct(entt::registry& registry, entt::entity entity)
|
||||||
{
|
{
|
||||||
// Unregister owning entity
|
// Unregister owning entity
|
||||||
|
|
@ -154,4 +191,26 @@ namespace Nz
|
||||||
|
|
||||||
m_bodyIndicesToEntity[uniqueIndex] = entt::null;
|
m_bodyIndicesToEntity[uniqueIndex] = entt::null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JoltPhysics3DSystem::OnCharacterConstruct(entt::registry& registry, entt::entity entity)
|
||||||
|
{
|
||||||
|
JoltCharacterComponent& character = registry.get<JoltCharacterComponent>(entity);
|
||||||
|
character.Construct(m_physWorld);
|
||||||
|
|
||||||
|
UInt32 uniqueIndex = character.GetBodyIndex();
|
||||||
|
if (uniqueIndex >= m_bodyIndicesToEntity.size())
|
||||||
|
m_bodyIndicesToEntity.resize(uniqueIndex + 1);
|
||||||
|
|
||||||
|
m_bodyIndicesToEntity[uniqueIndex] = entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JoltPhysics3DSystem::OnCharacterDestruct(entt::registry& registry, entt::entity entity)
|
||||||
|
{
|
||||||
|
// Unregister owning entity
|
||||||
|
JoltCharacterComponent& character = registry.get<JoltCharacterComponent>(entity);
|
||||||
|
UInt32 uniqueIndex = character.GetBodyIndex();
|
||||||
|
assert(uniqueIndex <= m_bodyIndicesToEntity.size());
|
||||||
|
|
||||||
|
m_bodyIndicesToEntity[uniqueIndex] = entt::null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -91,28 +91,29 @@ namespace Nz
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename F>
|
template<typename F>
|
||||||
void Canvas::DispatchEvent(std::size_t widgetIndex, F&& functor)
|
bool Canvas::DispatchEvent(std::size_t widgetIndex, F&& functor)
|
||||||
{
|
{
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
WidgetEntry& targetWidget = m_widgetEntries[widgetIndex];
|
WidgetEntry& targetWidget = m_widgetEntries[widgetIndex];
|
||||||
if (functor(targetWidget))
|
if (functor(targetWidget))
|
||||||
return;
|
return true;
|
||||||
|
|
||||||
if (!targetWidget.widget->m_parentWidget)
|
if (!targetWidget.widget->m_parentWidget)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
widgetIndex = targetWidget.widget->m_parentWidget->m_canvasIndex;
|
widgetIndex = targetWidget.widget->m_parentWidget->m_canvasIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::OnEventMouseButtonPressed(const WindowEventHandler* /*eventHandler*/, const WindowEvent::MouseButtonEvent& event)
|
void Canvas::OnEventMouseButtonPressed(const WindowEventHandler* eventHandler, const WindowEvent::MouseButtonEvent& event)
|
||||||
{
|
{
|
||||||
UpdateHoveredWidget(event.x, event.y);
|
UpdateHoveredWidget(event.x, event.y);
|
||||||
|
|
||||||
|
bool handled = false;
|
||||||
if (std::size_t targetWidgetIndex = GetMouseEventTarget(); targetWidgetIndex != InvalidCanvasIndex)
|
if (std::size_t targetWidgetIndex = GetMouseEventTarget(); targetWidgetIndex != InvalidCanvasIndex)
|
||||||
{
|
{
|
||||||
DispatchEvent(targetWidgetIndex, [&](WidgetEntry& widgetEntry)
|
handled = DispatchEvent(targetWidgetIndex, [&](WidgetEntry& widgetEntry)
|
||||||
{
|
{
|
||||||
int x = static_cast<int>(std::round(event.x - widgetEntry.box.x));
|
int x = static_cast<int>(std::round(event.x - widgetEntry.box.x));
|
||||||
int y = static_cast<int>(std::round(m_size.y - event.y - widgetEntry.box.y));
|
int y = static_cast<int>(std::round(m_size.y - event.y - widgetEntry.box.y));
|
||||||
|
|
@ -128,13 +129,17 @@ namespace Nz
|
||||||
|
|
||||||
SetMouseOwner(m_hoveredWidget);
|
SetMouseOwner(m_hoveredWidget);
|
||||||
m_mouseOwnerButtons[event.button] = true;
|
m_mouseOwnerButtons[event.button] = true;
|
||||||
|
|
||||||
|
if (!handled)
|
||||||
|
OnUnhandledMouseButtonPressed(eventHandler, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::OnEventMouseButtonRelease(const WindowEventHandler* /*eventHandler*/, const WindowEvent::MouseButtonEvent& event)
|
void Canvas::OnEventMouseButtonRelease(const WindowEventHandler* eventHandler, const WindowEvent::MouseButtonEvent& event)
|
||||||
{
|
{
|
||||||
|
bool handled = false;
|
||||||
if (std::size_t targetWidgetIndex = GetMouseEventTarget(); targetWidgetIndex != InvalidCanvasIndex)
|
if (std::size_t targetWidgetIndex = GetMouseEventTarget(); targetWidgetIndex != InvalidCanvasIndex)
|
||||||
{
|
{
|
||||||
DispatchEvent(targetWidgetIndex, [&](WidgetEntry& widgetEntry)
|
handled = DispatchEvent(targetWidgetIndex, [&](WidgetEntry& widgetEntry)
|
||||||
{
|
{
|
||||||
int x = static_cast<int>(std::round(event.x - widgetEntry.box.x));
|
int x = static_cast<int>(std::round(event.x - widgetEntry.box.x));
|
||||||
int y = static_cast<int>(std::round(m_size.y - event.y - widgetEntry.box.y));
|
int y = static_cast<int>(std::round(m_size.y - event.y - widgetEntry.box.y));
|
||||||
|
|
@ -148,6 +153,9 @@ namespace Nz
|
||||||
SetMouseOwner(InvalidCanvasIndex);
|
SetMouseOwner(InvalidCanvasIndex);
|
||||||
|
|
||||||
UpdateHoveredWidget(event.x, event.y);
|
UpdateHoveredWidget(event.x, event.y);
|
||||||
|
|
||||||
|
if (!handled)
|
||||||
|
OnUnhandledMouseButtonReleased(eventHandler, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::OnEventMouseEntered(const WindowEventHandler* /*eventHandler*/)
|
void Canvas::OnEventMouseEntered(const WindowEventHandler* /*eventHandler*/)
|
||||||
|
|
@ -185,7 +193,7 @@ namespace Nz
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::OnEventMouseMoved(const WindowEventHandler* /*eventHandler*/, const WindowEvent::MouseMoveEvent& event)
|
void Canvas::OnEventMouseMoved(const WindowEventHandler* eventHandler, const WindowEvent::MouseMoveEvent& event)
|
||||||
{
|
{
|
||||||
// Don't update hovered widget while the user doesn't release its mouse
|
// Don't update hovered widget while the user doesn't release its mouse
|
||||||
UpdateHoveredWidget(event.x, event.y);
|
UpdateHoveredWidget(event.x, event.y);
|
||||||
|
|
@ -197,15 +205,19 @@ namespace Nz
|
||||||
int x = static_cast<int>(std::round(event.x - targetWidget.box.x));
|
int x = static_cast<int>(std::round(event.x - targetWidget.box.x));
|
||||||
int y = static_cast<int>(std::round(m_size.y - event.y - targetWidget.box.y));
|
int y = static_cast<int>(std::round(m_size.y - event.y - targetWidget.box.y));
|
||||||
|
|
||||||
targetWidget.widget->OnMouseMoved(x, y, event.deltaX, -event.deltaY);
|
if (targetWidget.widget->OnMouseMoved(x, y, event.deltaX, -event.deltaY))
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OnUnhandledMouseMoved(eventHandler, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::OnEventMouseWheelMoved(const WindowEventHandler* /*eventHandler*/, const WindowEvent::MouseWheelEvent& event)
|
void Canvas::OnEventMouseWheelMoved(const WindowEventHandler* eventHandler, const WindowEvent::MouseWheelEvent& event)
|
||||||
{
|
{
|
||||||
|
bool handled = false;
|
||||||
if (std::size_t targetWidgetIndex = GetMouseEventTarget(); targetWidgetIndex != InvalidCanvasIndex)
|
if (std::size_t targetWidgetIndex = GetMouseEventTarget(); targetWidgetIndex != InvalidCanvasIndex)
|
||||||
{
|
{
|
||||||
DispatchEvent(targetWidgetIndex, [&](WidgetEntry& widgetEntry)
|
handled = DispatchEvent(targetWidgetIndex, [&](WidgetEntry& widgetEntry)
|
||||||
{
|
{
|
||||||
int x = static_cast<int>(std::round(event.x - widgetEntry.box.x));
|
int x = static_cast<int>(std::round(event.x - widgetEntry.box.x));
|
||||||
int y = static_cast<int>(std::round(m_size.y - event.y - widgetEntry.box.y));
|
int y = static_cast<int>(std::round(m_size.y - event.y - widgetEntry.box.y));
|
||||||
|
|
@ -213,6 +225,9 @@ namespace Nz
|
||||||
return widgetEntry.widget->OnMouseWheelMoved(x, y, event.delta);
|
return widgetEntry.widget->OnMouseWheelMoved(x, y, event.delta);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!handled)
|
||||||
|
OnUnhandledMouseWheelMoved(eventHandler, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::OnEventKeyPressed(const WindowEventHandler* eventHandler, const WindowEvent::KeyEvent& event)
|
void Canvas::OnEventKeyPressed(const WindowEventHandler* eventHandler, const WindowEvent::KeyEvent& event)
|
||||||
|
|
@ -276,7 +291,10 @@ namespace Nz
|
||||||
void Canvas::OnEventKeyReleased(const WindowEventHandler* eventHandler, const WindowEvent::KeyEvent& event)
|
void Canvas::OnEventKeyReleased(const WindowEventHandler* eventHandler, const WindowEvent::KeyEvent& event)
|
||||||
{
|
{
|
||||||
if (m_keyboardOwner != InvalidCanvasIndex)
|
if (m_keyboardOwner != InvalidCanvasIndex)
|
||||||
m_widgetEntries[m_keyboardOwner].widget->OnKeyReleased(event);
|
{
|
||||||
|
if (m_widgetEntries[m_keyboardOwner].widget->OnKeyReleased(event))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
OnUnhandledKeyReleased(eventHandler, event);
|
OnUnhandledKeyReleased(eventHandler, event);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue