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 USE_JOLT
|
||||
grabConstraint.emplace(*lastHitInfo.hitBody, lastHitInfo.hitPosition);
|
||||
grabConstraint.emplace(static_cast<Nz::JoltRigidBody3D&>(*lastHitInfo.hitBody), lastHitInfo.hitPosition);
|
||||
#else
|
||||
grabConstraint.emplace(*lastHitInfo.hitBody, lastHitInfo.hitPosition);
|
||||
grabConstraint->SetImpulseClamp(30.f);
|
||||
#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 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 constexpr std::string_view GetCurrentFileRelativeToEngine(std::string_view file);
|
||||
static constexpr std::string_view TranslateFilepath(std::string_view file);
|
||||
static ErrorModeFlags GetFlags();
|
||||
static std::string GetLastError(std::string_view* file = nullptr, unsigned int* line = nullptr, std::string_view* function = nullptr);
|
||||
static unsigned int GetLastSystemErrorCode();
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@
|
|||
|
||||
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)
|
||||
return file.substr(offset);
|
||||
if (std::size_t offset = file.rfind('/'); offset != file.npos)
|
||||
return file.substr(offset + 1);
|
||||
|
||||
if (std::size_t offset = file.find("NazaraEngine\\"); offset != file.npos)
|
||||
return file.substr(offset);
|
||||
if (std::size_t offset = file.rfind('\\'); offset != file.npos)
|
||||
return file.substr(offset + 1);
|
||||
|
||||
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)
|
||||
{
|
||||
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 <Nazara/JoltPhysics3D/Config.hpp>
|
||||
#include <Nazara/JoltPhysics3D/JoltAbstractBody.hpp>
|
||||
#include <Nazara/JoltPhysics3D/JoltPhysicsStepListener.hpp>
|
||||
#include <Nazara/Math/Quaternion.hpp>
|
||||
#include <Nazara/Math/Vector3.hpp>
|
||||
|
|
@ -27,7 +28,7 @@ namespace Nz
|
|||
class JoltCollider3D;
|
||||
class JoltPhysWorld3D;
|
||||
|
||||
class NAZARA_JOLTPHYSICS3D_API JoltCharacter : public JoltPhysicsStepListener
|
||||
class NAZARA_JOLTPHYSICS3D_API JoltCharacter : public JoltAbstractBody, public JoltPhysicsStepListener
|
||||
{
|
||||
friend JoltPhysWorld3D;
|
||||
|
||||
|
|
@ -42,11 +43,14 @@ namespace Nz
|
|||
inline void DisableSleeping();
|
||||
void EnableSleeping(bool enable);
|
||||
|
||||
inline UInt32 GetBodyIndex() const;
|
||||
UInt32 GetBodyIndex() const override;
|
||||
inline const std::shared_ptr<JoltCollider3D>& GetCollider() const;
|
||||
Vector3f GetLinearVelocity() const;
|
||||
Quaternionf GetRotation() const;
|
||||
inline JoltPhysWorld3D& GetPhysWorld();
|
||||
inline const JoltPhysWorld3D& GetPhysWorld() const;
|
||||
Vector3f GetPosition() const;
|
||||
std::pair<Vector3f, Quaternionf> GetPositionAndRotation() const;
|
||||
Quaternionf GetRotation() const;
|
||||
Vector3f GetUp() const;
|
||||
|
||||
bool IsOnGround() const;
|
||||
|
|
@ -78,7 +82,7 @@ namespace Nz
|
|||
void Destroy();
|
||||
|
||||
private:
|
||||
void PostSimulate() override;
|
||||
void PostSimulate(float elapsedTime) override;
|
||||
void PreSimulate(float elapsedTime) override;
|
||||
|
||||
std::shared_ptr<JoltCharacterImpl> m_impl;
|
||||
|
|
@ -96,7 +100,7 @@ namespace Nz
|
|||
JoltCharacterImpl(JoltCharacterImpl&&) = delete;
|
||||
virtual ~JoltCharacterImpl();
|
||||
|
||||
virtual void PostSimulate(JoltCharacter& character);
|
||||
virtual void PostSimulate(JoltCharacter& character, float elapsedTime);
|
||||
virtual void PreSimulate(JoltCharacter& character, float elapsedTime);
|
||||
|
||||
JoltCharacterImpl& operator=(const JoltCharacterImpl&) = delete;
|
||||
|
|
|
|||
|
|
@ -11,9 +11,19 @@ namespace Nz
|
|||
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)
|
||||
|
|
|
|||
|
|
@ -27,8 +27,10 @@ namespace JPH
|
|||
|
||||
namespace Nz
|
||||
{
|
||||
class JoltAbstractBody;
|
||||
class JoltCharacter;
|
||||
class JoltCharacterImpl;
|
||||
class JoltCollider3D;
|
||||
class JoltPhysicsStepListener;
|
||||
class JoltRigidBody3D;
|
||||
|
||||
|
|
@ -38,13 +40,19 @@ namespace Nz
|
|||
friend JoltRigidBody3D;
|
||||
|
||||
public:
|
||||
struct PointCollisionInfo;
|
||||
struct RaycastHit;
|
||||
struct ShapeCollisionInfo;
|
||||
|
||||
JoltPhysWorld3D();
|
||||
JoltPhysWorld3D(const JoltPhysWorld3D&) = delete;
|
||||
JoltPhysWorld3D(JoltPhysWorld3D&& ph) = delete;
|
||||
~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;
|
||||
Vector3f GetGravity() const;
|
||||
std::size_t GetMaxStepCount() const;
|
||||
|
|
@ -72,14 +80,28 @@ namespace Nz
|
|||
JoltPhysWorld3D& operator=(const JoltPhysWorld3D&) = delete;
|
||||
JoltPhysWorld3D& operator=(JoltPhysWorld3D&&) = delete;
|
||||
|
||||
struct PointCollisionInfo
|
||||
{
|
||||
JoltAbstractBody* hitBody = nullptr;
|
||||
};
|
||||
|
||||
struct RaycastHit
|
||||
{
|
||||
float fraction;
|
||||
JoltRigidBody3D* hitBody = nullptr;
|
||||
JoltAbstractBody* hitBody = nullptr;
|
||||
Vector3f hitNormal;
|
||||
Vector3f hitPosition;
|
||||
};
|
||||
|
||||
struct ShapeCollisionInfo
|
||||
{
|
||||
JoltAbstractBody* hitBody = nullptr;
|
||||
Vector3f collisionPosition1;
|
||||
Vector3f collisionPosition2;
|
||||
Vector3f penetrationAxis;
|
||||
float penetrationDepth;
|
||||
};
|
||||
|
||||
private:
|
||||
class BodyActivationListener;
|
||||
friend BodyActivationListener;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ namespace Nz
|
|||
JoltPhysicsStepListener(JoltPhysicsStepListener&&) = delete;
|
||||
virtual ~JoltPhysicsStepListener();
|
||||
|
||||
virtual void PostSimulate();
|
||||
virtual void PostSimulate(float elapsedTime);
|
||||
virtual void PreSimulate(float elapsedTime);
|
||||
|
||||
JoltPhysicsStepListener& operator=(const JoltPhysicsStepListener&) = delete;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include <NazaraUtils/Prerequisites.hpp>
|
||||
#include <Nazara/Core/Enums.hpp>
|
||||
#include <Nazara/JoltPhysics3D/Config.hpp>
|
||||
#include <Nazara/JoltPhysics3D/JoltAbstractBody.hpp>
|
||||
#include <Nazara/JoltPhysics3D/JoltCollider3D.hpp>
|
||||
#include <Nazara/Math/Matrix4.hpp>
|
||||
#include <Nazara/Math/Quaternion.hpp>
|
||||
|
|
@ -26,7 +27,7 @@ namespace Nz
|
|||
{
|
||||
class JoltPhysWorld3D;
|
||||
|
||||
class NAZARA_JOLTPHYSICS3D_API JoltRigidBody3D
|
||||
class NAZARA_JOLTPHYSICS3D_API JoltRigidBody3D : public JoltAbstractBody
|
||||
{
|
||||
public:
|
||||
struct DynamicSettings;
|
||||
|
|
@ -54,7 +55,7 @@ namespace Nz
|
|||
Vector3f GetAngularVelocity() const;
|
||||
inline JPH::Body* GetBody();
|
||||
inline const JPH::Body* GetBody() const;
|
||||
inline UInt32 GetBodyIndex() const;
|
||||
UInt32 GetBodyIndex() const override;
|
||||
inline const std::shared_ptr<JoltCollider3D>& GetGeom() const;
|
||||
float GetLinearDamping() const;
|
||||
Vector3f GetLinearVelocity() const;
|
||||
|
|
|
|||
|
|
@ -36,11 +36,6 @@ namespace Nz
|
|||
return m_body;
|
||||
}
|
||||
|
||||
inline UInt32 JoltRigidBody3D::GetBodyIndex() const
|
||||
{
|
||||
return m_bodyIndex;
|
||||
}
|
||||
|
||||
inline const std::shared_ptr<JoltCollider3D>& JoltRigidBody3D::GetGeom() const
|
||||
{
|
||||
return m_geom;
|
||||
|
|
|
|||
|
|
@ -25,13 +25,19 @@ namespace Nz
|
|||
static constexpr Int64 ExecutionOrder = 0;
|
||||
using Components = TypeList<JoltCharacterComponent, JoltRigidBody3DComponent, class NodeComponent>;
|
||||
|
||||
struct PointCollisionInfo;
|
||||
struct RaycastHit;
|
||||
struct ShapeCollisionInfo;
|
||||
|
||||
JoltPhysics3DSystem(entt::registry& registry);
|
||||
JoltPhysics3DSystem(const JoltPhysics3DSystem&) = delete;
|
||||
JoltPhysics3DSystem(JoltPhysics3DSystem&&) = delete;
|
||||
~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 const JoltPhysWorld3D& GetPhysWorld() const;
|
||||
inline entt::handle GetRigidBodyEntity(UInt32 bodyIndex) const;
|
||||
|
|
@ -44,15 +50,26 @@ namespace Nz
|
|||
JoltPhysics3DSystem& operator=(const JoltPhysics3DSystem&) = delete;
|
||||
JoltPhysics3DSystem& operator=(JoltPhysics3DSystem&&) = delete;
|
||||
|
||||
struct PointCollisionInfo : JoltPhysWorld3D::PointCollisionInfo
|
||||
{
|
||||
entt::handle hitEntity;
|
||||
};
|
||||
|
||||
struct RaycastHit : JoltPhysWorld3D::RaycastHit
|
||||
{
|
||||
entt::handle hitEntity;
|
||||
};
|
||||
|
||||
struct ShapeCollisionInfo : JoltPhysWorld3D::ShapeCollisionInfo
|
||||
{
|
||||
entt::handle hitEntity;
|
||||
};
|
||||
|
||||
private:
|
||||
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 OnCharacterConstruct(entt::registry& registry, entt::entity entity);
|
||||
void OnCharacterDestruct(entt::registry& registry, entt::entity entity);
|
||||
|
||||
std::size_t m_stepCount;
|
||||
std::vector<entt::entity> m_bodyIndicesToEntity;
|
||||
|
|
@ -60,8 +77,9 @@ namespace Nz
|
|||
entt::observer m_characterConstructObserver;
|
||||
entt::observer m_rigidBodyConstructObserver;
|
||||
entt::scoped_connection m_bodyConstructConnection;
|
||||
entt::scoped_connection m_characterConstructConnection;
|
||||
entt::scoped_connection m_bodyDestructConnection;
|
||||
entt::scoped_connection m_characterConstructConnection;
|
||||
entt::scoped_connection m_characterDestructConnection;
|
||||
JoltPhysWorld3D m_physWorld;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,15 +8,14 @@
|
|||
#define NAZARA_MATH_QUATERNION_HPP
|
||||
|
||||
#include <Nazara/Math/Angle.hpp>
|
||||
#include <Nazara/Math/EulerAngles.hpp>
|
||||
#include <Nazara/Math/Vector3.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
struct SerializationContext;
|
||||
|
||||
template<typename T> class EulerAngles;
|
||||
template<typename T> class Vector3;
|
||||
|
||||
template<typename T> class Quaternion
|
||||
{
|
||||
public:
|
||||
|
|
@ -31,6 +30,7 @@ namespace Nz
|
|||
constexpr Quaternion(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;
|
||||
|
||||
Quaternion& ComputeW();
|
||||
|
|
@ -75,12 +75,14 @@ namespace Nz
|
|||
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 Quaternion Identity();
|
||||
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 Normalize(const Quaternion& quat, T* length = nullptr);
|
||||
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 Slerp(const Quaternion& from, const Quaternion& to, T interpolation);
|
||||
static constexpr Quaternion Zero();
|
||||
|
|
|
|||
|
|
@ -4,8 +4,6 @@
|
|||
|
||||
#include <Nazara/Core/Algorithm.hpp>
|
||||
#include <Nazara/Math/Config.hpp>
|
||||
#include <Nazara/Math/EulerAngles.hpp>
|
||||
#include <Nazara/Math/Vector3.hpp>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
#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>
|
||||
constexpr bool Quaternion<T>::ApproxEqual(const Quaternion& quat, T maxDifference) const
|
||||
{
|
||||
|
|
@ -571,6 +576,12 @@ namespace Nz
|
|||
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>
|
||||
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>
|
||||
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 Max(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 constexpr Vector3 Right();
|
||||
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
|
||||
*
|
||||
* \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
|
||||
* \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>
|
||||
RadianAngle<T> Vector3<T>::AngleBetween(const Vector3& vec) const
|
||||
{
|
||||
// sqrt(a) * sqrt(b) = sqrt(a*b)
|
||||
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;
|
||||
T alpha = DotProduct(vec);
|
||||
return std::acos(Nz::Clamp(alpha, T(-1.0), T(1.0)));
|
||||
}
|
||||
|
||||
|
|
@ -835,6 +822,20 @@ namespace Nz
|
|||
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
|
||||
* \return A normalized vector from the vec
|
||||
|
|
|
|||
|
|
@ -32,6 +32,10 @@ namespace Nz
|
|||
Canvas& operator=(const 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(OnUnhandledKeyReleased, const WindowEventHandler* /*eventHandler*/, const WindowEvent::KeyEvent& /*event*/);
|
||||
|
||||
|
|
@ -55,7 +59,7 @@ namespace Nz
|
|||
void UnregisterWidget(std::size_t index);
|
||||
|
||||
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 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
|
||||
const OpenALDevice* s_currentGlobalALDevice;
|
||||
|
||||
#ifdef ALC_EXT_thread_local_context
|
||||
thread_local const OpenALDevice* s_currentThreadALDevice;
|
||||
#endif
|
||||
|
||||
template<typename FuncType, std::size_t FuncIndex, typename>
|
||||
struct ALWrapper;
|
||||
|
|
@ -175,8 +178,10 @@ namespace Nz
|
|||
alcDestroyContext(m_context);
|
||||
alcCloseDevice(m_device);
|
||||
|
||||
#ifdef ALC_EXT_thread_local_context
|
||||
if (s_currentThreadALDevice)
|
||||
s_currentThreadALDevice = nullptr;
|
||||
#endif
|
||||
|
||||
if (s_currentGlobalALDevice == this)
|
||||
s_currentGlobalALDevice = nullptr;
|
||||
|
|
@ -331,6 +336,7 @@ namespace Nz
|
|||
{
|
||||
NAZARA_USE_ANONYMOUS_NAMESPACE
|
||||
|
||||
#ifdef ALC_EXT_thread_local_context
|
||||
if (alcSetThreadContext)
|
||||
{
|
||||
if (s_currentThreadALDevice != this)
|
||||
|
|
@ -340,17 +346,21 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (s_currentGlobalALDevice != this)
|
||||
{
|
||||
alcMakeContextCurrent(m_context);
|
||||
s_currentGlobalALDevice = this;
|
||||
|
||||
#ifdef ALC_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.
|
||||
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;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -514,9 +524,13 @@ namespace Nz
|
|||
|
||||
const OpenALDevice* OpenALDevice::GetCurrentDevice()
|
||||
{
|
||||
NAZARA_USE_ANONYMOUS_NAMESPACE
|
||||
|
||||
#ifdef ALC_EXT_thread_local_context
|
||||
const OpenALDevice* device = s_currentThreadALDevice;
|
||||
if (device)
|
||||
return device;
|
||||
#endif
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
m_world->UnregisterStepListener(&character);
|
||||
|
|
@ -52,6 +58,11 @@ namespace Nz
|
|||
bodyLock.GetBody().SetAllowSleeping(enable);
|
||||
}
|
||||
|
||||
UInt32 JoltCharacter::GetBodyIndex() const
|
||||
{
|
||||
return m_bodyIndex;
|
||||
}
|
||||
|
||||
Vector3f JoltCharacter::GetLinearVelocity() const
|
||||
{
|
||||
return FromJolt(m_character->GetLinearVelocity(false));
|
||||
|
|
@ -135,6 +146,12 @@ namespace Nz
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -157,6 +174,9 @@ namespace Nz
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
@ -177,10 +197,10 @@ namespace Nz
|
|||
m_collider.reset();
|
||||
}
|
||||
|
||||
void JoltCharacter::PostSimulate()
|
||||
void JoltCharacter::PostSimulate(float elapsedTime)
|
||||
{
|
||||
m_character->PostSimulation(0.05f);
|
||||
m_impl->PostSimulate(*this);
|
||||
m_impl->PostSimulate(*this, elapsedTime);
|
||||
}
|
||||
|
||||
void JoltCharacter::PreSimulate(float elapsedTime)
|
||||
|
|
@ -191,7 +211,7 @@ namespace Nz
|
|||
|
||||
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/JoltCharacter.hpp>
|
||||
#include <Nazara/JoltPhysics3D/JoltCollider3D.hpp>
|
||||
#include <Nazara/JoltPhysics3D/JoltHelper.hpp>
|
||||
#include <Nazara/JoltPhysics3D/JoltPhysics3D.hpp>
|
||||
#include <Nazara/JoltPhysics3D/JoltPhysicsStepListener.hpp>
|
||||
|
|
@ -16,6 +17,8 @@
|
|||
#include <Jolt/Physics/PhysicsSystem.h>
|
||||
#include <Jolt/Physics/Body/BodyActivationListener.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/ObjectLayer.h>
|
||||
#include <Jolt/Physics/Collision/RayCast.h>
|
||||
|
|
@ -162,10 +165,106 @@ namespace Nz
|
|||
{
|
||||
namespace NAZARA_ANONYMOUS_NAMESPACE
|
||||
{
|
||||
class CallbackHitResult : public JPH::CastRayCollector
|
||||
class PointCallbackHitResult : public JPH::CollidePointCollector
|
||||
{
|
||||
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_callback(callback),
|
||||
m_from(from),
|
||||
|
|
@ -186,7 +285,7 @@ namespace Nz
|
|||
|
||||
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)));
|
||||
|
||||
if (auto fractionOpt = m_callback(hitInfo))
|
||||
|
|
@ -323,6 +422,35 @@ namespace Nz
|
|||
|
||||
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
|
||||
{
|
||||
return m_world->physicsSystem.GetNumActiveBodies(JPH::EBodyType::RigidBody);
|
||||
|
|
@ -358,7 +486,7 @@ namespace Nz
|
|||
|
||||
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);
|
||||
|
||||
return collector.DidHit();
|
||||
|
|
@ -387,7 +515,7 @@ namespace Nz
|
|||
RaycastHit hitInfo;
|
||||
hitInfo.fraction = collector.mHit.GetEarlyOutFraction();
|
||||
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())));
|
||||
|
||||
callback(hitInfo);
|
||||
|
|
@ -473,7 +601,7 @@ namespace Nz
|
|||
m_world->physicsSystem.Update(stepSize, 1, &m_world->tempAllocator, &jobSystem);
|
||||
|
||||
for (JoltPhysicsStepListener* stepListener : m_stepListeners)
|
||||
stepListener->PostSimulate();
|
||||
stepListener->PostSimulate(stepSize);
|
||||
|
||||
m_timestepAccumulator -= m_stepSize;
|
||||
stepCount++;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ namespace Nz
|
|||
{
|
||||
JoltPhysicsStepListener::~JoltPhysicsStepListener() = default;
|
||||
|
||||
void JoltPhysicsStepListener::PostSimulate()
|
||||
void JoltPhysicsStepListener::PostSimulate(float /*elapsedTime*/)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -120,6 +120,11 @@ namespace Nz
|
|||
return FromJolt(m_body->GetAngularVelocity());
|
||||
}
|
||||
|
||||
UInt32 JoltRigidBody3D::GetBodyIndex() const
|
||||
{
|
||||
return m_bodyIndex;
|
||||
}
|
||||
|
||||
float JoltRigidBody3D::GetLinearDamping() const
|
||||
{
|
||||
if NAZARA_UNLIKELY(IsStatic())
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/JoltPhysics3D/Systems/JoltPhysics3DSystem.hpp>
|
||||
#include <Nazara/JoltPhysics3D/JoltAbstractBody.hpp>
|
||||
#include <Nazara/Core/Components/DisabledComponent.hpp>
|
||||
#include <Nazara/Utility/Components/NodeComponent.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_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_characterConstructConnection = registry.on_construct<JoltCharacterComponent>().connect<&JoltPhysics3DSystem::OnCharacterConstruct>(this);
|
||||
m_characterDestructConnection = registry.on_destroy<JoltCharacterComponent>().connect<&JoltPhysics3DSystem::OnCharacterDestruct>(this);
|
||||
}
|
||||
|
||||
JoltPhysics3DSystem::~JoltPhysics3DSystem()
|
||||
|
|
@ -34,6 +36,47 @@ namespace Nz
|
|||
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)
|
||||
{
|
||||
return m_physWorld.RaycastQuery(from, to, [&](const JoltPhysWorld3D::RaycastHit& hitInfo)
|
||||
|
|
@ -139,12 +182,6 @@ namespace Nz
|
|||
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)
|
||||
{
|
||||
// Unregister owning entity
|
||||
|
|
@ -154,4 +191,26 @@ namespace Nz
|
|||
|
||||
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>
|
||||
void Canvas::DispatchEvent(std::size_t widgetIndex, F&& functor)
|
||||
bool Canvas::DispatchEvent(std::size_t widgetIndex, F&& functor)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
WidgetEntry& targetWidget = m_widgetEntries[widgetIndex];
|
||||
if (functor(targetWidget))
|
||||
return;
|
||||
return true;
|
||||
|
||||
if (!targetWidget.widget->m_parentWidget)
|
||||
return;
|
||||
return false;
|
||||
|
||||
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);
|
||||
|
||||
bool handled = false;
|
||||
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 y = static_cast<int>(std::round(m_size.y - event.y - widgetEntry.box.y));
|
||||
|
|
@ -128,13 +129,17 @@ namespace Nz
|
|||
|
||||
SetMouseOwner(m_hoveredWidget);
|
||||
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)
|
||||
{
|
||||
DispatchEvent(targetWidgetIndex, [&](WidgetEntry& widgetEntry)
|
||||
handled = DispatchEvent(targetWidgetIndex, [&](WidgetEntry& widgetEntry)
|
||||
{
|
||||
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));
|
||||
|
|
@ -148,6 +153,9 @@ namespace Nz
|
|||
SetMouseOwner(InvalidCanvasIndex);
|
||||
|
||||
UpdateHoveredWidget(event.x, event.y);
|
||||
|
||||
if (!handled)
|
||||
OnUnhandledMouseButtonReleased(eventHandler, event);
|
||||
}
|
||||
|
||||
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
|
||||
UpdateHoveredWidget(event.x, event.y);
|
||||
|
|
@ -197,15 +205,19 @@ namespace Nz
|
|||
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));
|
||||
|
||||
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)
|
||||
{
|
||||
DispatchEvent(targetWidgetIndex, [&](WidgetEntry& widgetEntry)
|
||||
handled = DispatchEvent(targetWidgetIndex, [&](WidgetEntry& widgetEntry)
|
||||
{
|
||||
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));
|
||||
|
|
@ -213,6 +225,9 @@ namespace Nz
|
|||
return widgetEntry.widget->OnMouseWheelMoved(x, y, event.delta);
|
||||
});
|
||||
}
|
||||
|
||||
if (!handled)
|
||||
OnUnhandledMouseWheelMoved(eventHandler, 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)
|
||||
{
|
||||
if (m_keyboardOwner != InvalidCanvasIndex)
|
||||
m_widgetEntries[m_keyboardOwner].widget->OnKeyReleased(event);
|
||||
{
|
||||
if (m_widgetEntries[m_keyboardOwner].widget->OnKeyReleased(event))
|
||||
return;
|
||||
}
|
||||
|
||||
OnUnhandledKeyReleased(eventHandler, event);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue