JoltPhysics3D: Rework RigidBody wrapper

- Add a clear way to setup dynamic/kinematic or static bodies
- Body registration to the world is batched (all bodies created before a physics step are added together, which is what Jolt is optimized for)
- Added support for empty shapes (= rigid bodies without collision) using a very small shape and tagging the body as sensor
This commit is contained in:
SirLynix
2023-04-05 08:50:39 +02:00
committed by Jérôme Leclercq
parent 67b1710adb
commit d610baf920
14 changed files with 472 additions and 157 deletions

View File

@@ -21,6 +21,12 @@ namespace Nz
Max = TranslatedRotatedDecoration
};
enum class JoltMotionQuality
{
Discrete,
LinearCast
};
}
#endif // NAZARA_JOLTPHYSICS3D_ENUMS_HPP

View File

@@ -20,7 +20,9 @@
namespace JPH
{
class BodyID;
class PhysicsSystem;
class Shape;
}
namespace Nz
@@ -31,6 +33,7 @@ namespace Nz
class NAZARA_JOLTPHYSICS3D_API JoltPhysWorld3D
{
friend JoltCharacter;
friend JoltRigidBody3D;
public:
struct RaycastHit;
@@ -47,10 +50,13 @@ namespace Nz
Time GetStepSize() const;
inline bool IsBodyActive(UInt32 bodyIndex) const;
inline bool IsBodyRegistered(UInt32 bodyIndex) const;
bool RaycastQuery(const Vector3f& from, const Vector3f& to, const FunctionRef<std::optional<float>(const RaycastHit& hitInfo)>& callback);
bool RaycastQueryFirst(const Vector3f& from, const Vector3f& to, const FunctionRef<void(const RaycastHit& hitInfo)>& callback);
void RefreshBodies();
void SetGravity(const Vector3f& gravity);
void SetMaxStepCount(std::size_t maxStepCount);
void SetStepSize(Time stepSize);
@@ -77,13 +83,19 @@ namespace Nz
struct JoltWorld;
const JPH::Shape* GetNullShape() const;
void OnPreStep(float deltatime);
void RegisterBody(const JPH::BodyID& bodyID, bool activate, bool removeFromDeactivationList);
inline void RegisterCharacter(JoltCharacter* character);
void UnregisterBody(const JPH::BodyID& bodyID, bool destroy, bool removeFromRegisterList);
inline void UnregisterCharacter(JoltCharacter* character);
std::size_t m_maxStepCount;
std::unique_ptr<std::atomic_uint64_t[]> m_activeBodies;
std::unique_ptr<std::uint64_t[]> m_registeredBodies;
std::unique_ptr<JoltWorld> m_world;
std::vector<JoltCharacter*> m_characters;
Vector3f m_gravity;

View File

@@ -14,6 +14,14 @@ namespace Nz
return m_activeBodies[blockIndex] & (UInt64(1u) << localIndex);
}
inline bool JoltPhysWorld3D::IsBodyRegistered(UInt32 bodyIndex) const
{
UInt32 blockIndex = bodyIndex / 64;
UInt32 localIndex = bodyIndex % 64;
return m_registeredBodies[blockIndex] & (UInt64(1u) << localIndex);
}
inline void JoltPhysWorld3D::RegisterCharacter(JoltCharacter* character)
{
auto it = std::lower_bound(m_characters.begin(), m_characters.end(), character);

View File

@@ -19,6 +19,7 @@
namespace JPH
{
class Body;
class BodyCreationSettings;
}
namespace Nz
@@ -28,8 +29,11 @@ namespace Nz
class NAZARA_JOLTPHYSICS3D_API JoltRigidBody3D
{
public:
JoltRigidBody3D(JoltPhysWorld3D* world, const Matrix4f& mat = Matrix4f::Identity());
JoltRigidBody3D(JoltPhysWorld3D* world, std::shared_ptr<JoltCollider3D> geom, const Matrix4f& mat = Matrix4f::Identity());
struct DynamicSettings;
struct StaticSettings;
JoltRigidBody3D(JoltPhysWorld3D& world, const DynamicSettings& settings);
JoltRigidBody3D(JoltPhysWorld3D& world, const StaticSettings& settings);
JoltRigidBody3D(const JoltRigidBody3D& object) = delete;
JoltRigidBody3D(JoltRigidBody3D&& object) noexcept;
~JoltRigidBody3D();
@@ -38,7 +42,9 @@ namespace Nz
void AddForce(const Vector3f& force, const Vector3f& point, CoordSys coordSys = CoordSys::Global);
void AddTorque(const Vector3f& torque, CoordSys coordSys = CoordSys::Global);
inline void DisableSimulation();
inline void DisableSleeping();
void EnableSimulation(bool enable);
void EnableSleeping(bool enable);
void FallAsleep();
@@ -53,16 +59,16 @@ namespace Nz
float GetLinearDamping() const;
Vector3f GetLinearVelocity() const;
float GetMass() const;
Vector3f GetMassCenter(CoordSys coordSys = CoordSys::Local) const;
Matrix4f GetMatrix() const;
Vector3f GetPosition() const;
std::pair<Vector3f, Quaternionf> GetPositionAndRotation() const;
Quaternionf GetRotation() const;
inline JoltPhysWorld3D* GetWorld() const;
inline JoltPhysWorld3D& GetWorld() const;
bool IsSimulationEnabled() const;
inline bool IsSimulationEnabled() const;
bool IsSleeping() const;
bool IsSleepingEnabled() const;
bool IsStatic() const;
void SetAngularDamping(float angularDamping);
void SetAngularVelocity(const Vector3f& angularVelocity);
@@ -70,7 +76,6 @@ namespace Nz
void SetLinearDamping(float damping);
void SetLinearVelocity(const Vector3f& velocity);
void SetMass(float mass, bool recomputeInertia = true);
void SetMassCenter(const Vector3f& center);
void SetPosition(const Vector3f& position);
void SetRotation(const Quaternionf& rotation);
@@ -86,14 +91,53 @@ namespace Nz
JoltRigidBody3D& operator=(const JoltRigidBody3D& object) = delete;
JoltRigidBody3D& operator=(JoltRigidBody3D&& object) noexcept;
struct CommonSettings
{
std::shared_ptr<JoltCollider3D> geom;
Quaternionf rotation = Quaternionf::Identity();
Vector3f position = Vector3f::Zero();
bool initiallySleeping = false;
bool isSimulationEnabled = true;
bool isTrigger = false;
};
struct DynamicSettings : CommonSettings
{
// Default values from Jolt
JoltMotionQuality motionQuality = JoltMotionQuality::Discrete;
Vector3f angularVelocity = Vector3f::Zero();
Vector3f linearVelocity = Vector3f::Zero();
bool allowSleeping = true;
float angularDamping = 0.05f;
float friction = 0.2f;
float gravityFactor = 1.f;
float linearDamping = 0.05f;
float mass = 1.f;
float maxAngularVelocity = 0.25f * Pi<float> * 60.f;
float maxLinearVelocity = 500.f;
float restitution = 0.f;
};
struct StaticSettings : CommonSettings
{
};
protected:
void Destroy();
void Destroy(bool worldDestruction = false);
private:
void BuildSettings(const CommonSettings& settings, JPH::BodyCreationSettings& creationSettings);
void BuildSettings(const DynamicSettings& settings, JPH::BodyCreationSettings& creationSettings);
void BuildSettings(const StaticSettings& settings, JPH::BodyCreationSettings& creationSettings);
bool ShouldActivate() const;
std::shared_ptr<JoltCollider3D> m_geom;
JPH::Body* m_body;
JoltPhysWorld3D* m_world;
UInt32 m_bodyIndex;
bool m_isSimulationEnabled;
bool m_isTrigger;
};
}

View File

@@ -6,6 +6,11 @@
namespace Nz
{
inline void JoltRigidBody3D::DisableSimulation()
{
return EnableSimulation(false);
}
inline void JoltRigidBody3D::DisableSleeping()
{
return EnableSleeping(false);
@@ -31,9 +36,14 @@ namespace Nz
return m_geom;
}
inline JoltPhysWorld3D* JoltRigidBody3D::GetWorld() const
inline JoltPhysWorld3D& JoltRigidBody3D::GetWorld() const
{
return m_world;
return *m_world;
}
inline bool JoltRigidBody3D::IsSimulationEnabled() const
{
return m_isSimulationEnabled;
}
}

View File

@@ -9,7 +9,7 @@ namespace Nz
template<typename... Args>
JoltRigidBody3DComponent JoltPhysics3DSystem::CreateRigidBody(Args&&... args)
{
return JoltRigidBody3DComponent(&m_physWorld, std::forward<Args>(args)...);
return JoltRigidBody3DComponent(m_physWorld, std::forward<Args>(args)...);
}
inline JoltPhysWorld3D& JoltPhysics3DSystem::GetPhysWorld()