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:
parent
67b1710adb
commit
d610baf920
|
|
@ -31,7 +31,7 @@ int main()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
auto& windowing = app.AddComponent<Nz::AppWindowingComponent>();
|
auto& windowing = app.AddComponent<Nz::AppWindowingComponent>();
|
||||||
Nz::Window& mainWindow = windowing.CreateWindow(Nz::VideoMode(1920, 1080), "Physics playground");
|
Nz::Window& mainWindow = windowing.CreateWindow(Nz::VideoMode(1280, 720), "Physics playground");
|
||||||
|
|
||||||
auto& fs = app.AddComponent<Nz::AppFilesystemComponent>();
|
auto& fs = app.AddComponent<Nz::AppFilesystemComponent>();
|
||||||
{
|
{
|
||||||
|
|
@ -86,7 +86,8 @@ int main()
|
||||||
boxEntity.emplace<Nz::NodeComponent>();
|
boxEntity.emplace<Nz::NodeComponent>();
|
||||||
|
|
||||||
#if USE_JOLT
|
#if USE_JOLT
|
||||||
std::shared_ptr<Nz::JoltBoxCollider3D> wallCollider = std::make_shared<Nz::JoltBoxCollider3D>(Nz::Vector3f(BoxDims, BoxDims, 1.f));
|
float thickness = 1.f;
|
||||||
|
std::shared_ptr<Nz::JoltBoxCollider3D> wallCollider = std::make_shared<Nz::JoltBoxCollider3D>(Nz::Vector3f(BoxDims + thickness * 2.f, BoxDims + thickness * 2.f, thickness));
|
||||||
#else
|
#else
|
||||||
std::shared_ptr<Nz::BulletBoxCollider3D> wallCollider = std::make_shared<Nz::BulletBoxCollider3D>(Nz::Vector3f(BoxDims, BoxDims, 1.f));
|
std::shared_ptr<Nz::BulletBoxCollider3D> wallCollider = std::make_shared<Nz::BulletBoxCollider3D>(Nz::Vector3f(BoxDims, BoxDims, 1.f));
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -116,11 +117,13 @@ int main()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if USE_JOLT
|
#if USE_JOLT
|
||||||
auto& ballPhysics = boxEntity.emplace<Nz::JoltRigidBody3DComponent>(physSystem.CreateRigidBody(boxCollider));
|
Nz::JoltRigidBody3D::StaticSettings settings;
|
||||||
|
settings.geom = boxCollider;
|
||||||
|
|
||||||
|
auto& boxBody = boxEntity.emplace<Nz::JoltRigidBody3DComponent>(physSystem.CreateRigidBody(settings));
|
||||||
#else
|
#else
|
||||||
auto& ballPhysics = boxEntity.emplace<Nz::BulletRigidBody3DComponent>(physSystem.CreateRigidBody(boxCollider));
|
auto& boxBody = boxEntity.emplace<Nz::BulletRigidBody3DComponent>(physSystem.CreateRigidBody(boxCollider));
|
||||||
#endif
|
#endif
|
||||||
ballPhysics.SetMass(0.f);
|
|
||||||
|
|
||||||
std::shared_ptr<Nz::Model> colliderModel;
|
std::shared_ptr<Nz::Model> colliderModel;
|
||||||
{
|
{
|
||||||
|
|
@ -132,14 +135,14 @@ int main()
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
/*std::shared_ptr<Nz::Mesh> colliderMesh = Nz::Mesh::Build(boxCollider->GenerateDebugMesh());
|
std::shared_ptr<Nz::Mesh> colliderMesh = Nz::Mesh::Build(boxCollider->GenerateDebugMesh());
|
||||||
std::shared_ptr<Nz::GraphicalMesh> colliderGraphicalMesh = Nz::GraphicalMesh::BuildFromMesh(*colliderMesh);
|
std::shared_ptr<Nz::GraphicalMesh> colliderGraphicalMesh = Nz::GraphicalMesh::BuildFromMesh(*colliderMesh);
|
||||||
|
|
||||||
colliderModel = std::make_shared<Nz::Model>(colliderGraphicalMesh);
|
colliderModel = std::make_shared<Nz::Model>(colliderGraphicalMesh);
|
||||||
for (std::size_t i = 0; i < colliderModel->GetSubMeshCount(); ++i)
|
for (std::size_t i = 0; i < colliderModel->GetSubMeshCount(); ++i)
|
||||||
colliderModel->SetMaterial(i, colliderMat);
|
colliderModel->SetMaterial(i, colliderMat);
|
||||||
|
|
||||||
boxGfx.AttachRenderable(std::move(colliderModel));*/
|
boxGfx.AttachRenderable(std::move(colliderModel));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -178,11 +181,14 @@ int main()
|
||||||
ballNode.SetScale(radius);
|
ballNode.SetScale(radius);
|
||||||
|
|
||||||
#if USE_JOLT
|
#if USE_JOLT
|
||||||
auto& ballPhysics = ballEntity.emplace<Nz::JoltRigidBody3DComponent>(physSystem.CreateRigidBody(sphereCollider));
|
Nz::JoltRigidBody3D::DynamicSettings settings;
|
||||||
|
settings.geom = sphereCollider;
|
||||||
|
settings.mass = 4.f / 3.f * Nz::Pi<float> * Nz::IntegralPow(radius, 3);
|
||||||
|
|
||||||
|
auto& ballPhysics = ballEntity.emplace<Nz::JoltRigidBody3DComponent>(physSystem.CreateRigidBody(settings));
|
||||||
#else
|
#else
|
||||||
auto& ballPhysics = ballEntity.emplace<Nz::BulletRigidBody3DComponent>(physSystem.CreateRigidBody(sphereCollider));
|
auto& ballPhysics = ballEntity.emplace<Nz::BulletRigidBody3DComponent>(physSystem.CreateRigidBody(sphereCollider));
|
||||||
#endif
|
#endif
|
||||||
ballPhysics.SetMass(4.f / 3.f * Nz::Pi<float> * Nz::IntegralPow(radius, 3));
|
|
||||||
//ballPhysics.DisableSleeping();
|
//ballPhysics.DisableSleeping();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -222,12 +228,14 @@ int main()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if USE_JOLT
|
#if USE_JOLT
|
||||||
auto& ballPhysics = ballEntity.emplace<Nz::JoltRigidBody3DComponent>(physSystem.CreateRigidBody(boxCollider));
|
Nz::JoltRigidBody3D::DynamicSettings settings;
|
||||||
|
settings.geom = boxCollider;
|
||||||
|
settings.mass = width * height * depth;
|
||||||
|
|
||||||
|
ballEntity.emplace<Nz::JoltRigidBody3DComponent>(physSystem.CreateRigidBody(settings));
|
||||||
#else
|
#else
|
||||||
auto& ballPhysics = ballEntity.emplace<Nz::BulletRigidBody3DComponent>(physSystem.CreateRigidBody(boxCollider));
|
ballEntity.emplace<Nz::BulletRigidBody3DComponent>(physSystem.CreateRigidBody(boxCollider));
|
||||||
#endif
|
#endif
|
||||||
ballPhysics.SetMass(width * height * depth);
|
|
||||||
//ballPhysics.DisableSleeping();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lumière
|
// Lumière
|
||||||
|
|
@ -273,7 +281,43 @@ int main()
|
||||||
NazaraSlot(Nz::WindowEventHandler, OnMouseMoved, cameraMove);
|
NazaraSlot(Nz::WindowEventHandler, OnMouseMoved, cameraMove);
|
||||||
NazaraSlot(Nz::WindowEventHandler, OnMouseMoved, grabbedObjectMove);
|
NazaraSlot(Nz::WindowEventHandler, OnMouseMoved, grabbedObjectMove);
|
||||||
#if USE_JOLT
|
#if USE_JOLT
|
||||||
std::optional<Nz::JoltPivotConstraint3D> grabConstraint;
|
struct GrabConstraint
|
||||||
|
{
|
||||||
|
GrabConstraint(Nz::JoltRigidBody3D& body, const Nz::Vector3f& grabPos) :
|
||||||
|
grabBody(body.GetWorld(), BodySettings(grabPos)),
|
||||||
|
grabConstraint(body, grabBody, grabPos)
|
||||||
|
{
|
||||||
|
body.WakeUp();
|
||||||
|
body.EnableSleeping(false);
|
||||||
|
grabConstraint.SetDamping(1.f);
|
||||||
|
grabConstraint.SetFrequency(5.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
~GrabConstraint()
|
||||||
|
{
|
||||||
|
grabConstraint.GetBodyA().EnableSleeping(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetPosition(const Nz::Vector3f& pos)
|
||||||
|
{
|
||||||
|
grabBody.SetPosition(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Nz::JoltRigidBody3D::DynamicSettings BodySettings(const Nz::Vector3f& pos)
|
||||||
|
{
|
||||||
|
Nz::JoltRigidBody3D::DynamicSettings settings;
|
||||||
|
settings.mass = 0.f; //< kinematic
|
||||||
|
settings.isSimulationEnabled = false;
|
||||||
|
settings.position = pos;
|
||||||
|
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
Nz::JoltRigidBody3D grabBody;
|
||||||
|
Nz::JoltDistanceConstraint3D grabConstraint;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::optional<GrabConstraint> grabConstraint;
|
||||||
#else
|
#else
|
||||||
std::optional<Nz::BulletPivotConstraint3D> grabConstraint;
|
std::optional<Nz::BulletPivotConstraint3D> grabConstraint;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -328,8 +372,12 @@ int main()
|
||||||
{
|
{
|
||||||
if (lastHitInfo.hitBody && lastHitInfo.hitEntity != boxEntity)
|
if (lastHitInfo.hitBody && lastHitInfo.hitEntity != boxEntity)
|
||||||
{
|
{
|
||||||
|
#if USE_JOLT
|
||||||
grabConstraint.emplace(*lastHitInfo.hitBody, lastHitInfo.hitPosition);
|
grabConstraint.emplace(*lastHitInfo.hitBody, lastHitInfo.hitPosition);
|
||||||
//grabConstraint->SetImpulseClamp(30.f);
|
#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, [&, body = lastHitInfo.hitBody, distance = Nz::Vector3f::Distance(from, lastHitInfo.hitPosition)](const Nz::WindowEventHandler*, const Nz::WindowEvent::MouseMoveEvent& event)
|
||||||
{
|
{
|
||||||
|
|
@ -337,7 +385,11 @@ int main()
|
||||||
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 });
|
||||||
|
|
||||||
Nz::Vector3f newPosition = from + (to - from).Normalize() * distance;
|
Nz::Vector3f newPosition = from + (to - from).Normalize() * distance;
|
||||||
|
#if USE_JOLT
|
||||||
|
grabConstraint->SetPosition(newPosition);
|
||||||
|
#else
|
||||||
grabConstraint->SetSecondAnchor(newPosition);
|
grabConstraint->SetSecondAnchor(newPosition);
|
||||||
|
#endif
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -348,8 +348,10 @@ int main()
|
||||||
auto floorCollider = std::make_shared<Nz::JoltBoxCollider3D>(Nz::Vector3f(planeSize.x, 1.f, planeSize.y));
|
auto floorCollider = std::make_shared<Nz::JoltBoxCollider3D>(Nz::Vector3f(planeSize.x, 1.f, planeSize.y));
|
||||||
auto translatedFloorCollider = std::make_shared<Nz::JoltTranslatedRotatedCollider3D>(std::move(floorCollider), Nz::Vector3f::Down() * 0.5f);
|
auto translatedFloorCollider = std::make_shared<Nz::JoltTranslatedRotatedCollider3D>(std::move(floorCollider), Nz::Vector3f::Down() * 0.5f);
|
||||||
|
|
||||||
auto& planeBody = floorEntity.emplace<Nz::JoltRigidBody3DComponent>(physSytem.CreateRigidBody(translatedFloorCollider));
|
Nz::JoltRigidBody3D::StaticSettings floorSettings;
|
||||||
planeBody.SetMass(0.f);
|
floorSettings.geom = std::move(translatedFloorCollider);
|
||||||
|
|
||||||
|
auto& planeBody = floorEntity.emplace<Nz::JoltRigidBody3DComponent>(physSytem.CreateRigidBody(floorSettings));
|
||||||
|
|
||||||
std::shared_ptr<Nz::GraphicalMesh> boxMeshGfx = Nz::GraphicalMesh::Build(Nz::Primitive::Box(Nz::Vector3f(0.5f, 0.5f, 0.5f)), meshPrimitiveParams);
|
std::shared_ptr<Nz::GraphicalMesh> boxMeshGfx = Nz::GraphicalMesh::Build(Nz::Primitive::Box(Nz::Vector3f(0.5f, 0.5f, 0.5f)), meshPrimitiveParams);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,12 @@ namespace Nz
|
||||||
|
|
||||||
Max = TranslatedRotatedDecoration
|
Max = TranslatedRotatedDecoration
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class JoltMotionQuality
|
||||||
|
{
|
||||||
|
Discrete,
|
||||||
|
LinearCast
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // NAZARA_JOLTPHYSICS3D_ENUMS_HPP
|
#endif // NAZARA_JOLTPHYSICS3D_ENUMS_HPP
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,9 @@
|
||||||
|
|
||||||
namespace JPH
|
namespace JPH
|
||||||
{
|
{
|
||||||
|
class BodyID;
|
||||||
class PhysicsSystem;
|
class PhysicsSystem;
|
||||||
|
class Shape;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
|
|
@ -31,6 +33,7 @@ namespace Nz
|
||||||
class NAZARA_JOLTPHYSICS3D_API JoltPhysWorld3D
|
class NAZARA_JOLTPHYSICS3D_API JoltPhysWorld3D
|
||||||
{
|
{
|
||||||
friend JoltCharacter;
|
friend JoltCharacter;
|
||||||
|
friend JoltRigidBody3D;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct RaycastHit;
|
struct RaycastHit;
|
||||||
|
|
@ -47,10 +50,13 @@ namespace Nz
|
||||||
Time GetStepSize() const;
|
Time GetStepSize() const;
|
||||||
|
|
||||||
inline bool IsBodyActive(UInt32 bodyIndex) 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 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);
|
bool RaycastQueryFirst(const Vector3f& from, const Vector3f& to, const FunctionRef<void(const RaycastHit& hitInfo)>& callback);
|
||||||
|
|
||||||
|
void RefreshBodies();
|
||||||
|
|
||||||
void SetGravity(const Vector3f& gravity);
|
void SetGravity(const Vector3f& gravity);
|
||||||
void SetMaxStepCount(std::size_t maxStepCount);
|
void SetMaxStepCount(std::size_t maxStepCount);
|
||||||
void SetStepSize(Time stepSize);
|
void SetStepSize(Time stepSize);
|
||||||
|
|
@ -77,13 +83,19 @@ namespace Nz
|
||||||
|
|
||||||
struct JoltWorld;
|
struct JoltWorld;
|
||||||
|
|
||||||
|
const JPH::Shape* GetNullShape() const;
|
||||||
|
|
||||||
void OnPreStep(float deltatime);
|
void OnPreStep(float deltatime);
|
||||||
|
|
||||||
|
void RegisterBody(const JPH::BodyID& bodyID, bool activate, bool removeFromDeactivationList);
|
||||||
inline void RegisterCharacter(JoltCharacter* character);
|
inline void RegisterCharacter(JoltCharacter* character);
|
||||||
|
|
||||||
|
void UnregisterBody(const JPH::BodyID& bodyID, bool destroy, bool removeFromRegisterList);
|
||||||
inline void UnregisterCharacter(JoltCharacter* character);
|
inline void UnregisterCharacter(JoltCharacter* character);
|
||||||
|
|
||||||
std::size_t m_maxStepCount;
|
std::size_t m_maxStepCount;
|
||||||
std::unique_ptr<std::atomic_uint64_t[]> m_activeBodies;
|
std::unique_ptr<std::atomic_uint64_t[]> m_activeBodies;
|
||||||
|
std::unique_ptr<std::uint64_t[]> m_registeredBodies;
|
||||||
std::unique_ptr<JoltWorld> m_world;
|
std::unique_ptr<JoltWorld> m_world;
|
||||||
std::vector<JoltCharacter*> m_characters;
|
std::vector<JoltCharacter*> m_characters;
|
||||||
Vector3f m_gravity;
|
Vector3f m_gravity;
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,14 @@ namespace Nz
|
||||||
return m_activeBodies[blockIndex] & (UInt64(1u) << localIndex);
|
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)
|
inline void JoltPhysWorld3D::RegisterCharacter(JoltCharacter* character)
|
||||||
{
|
{
|
||||||
auto it = std::lower_bound(m_characters.begin(), m_characters.end(), character);
|
auto it = std::lower_bound(m_characters.begin(), m_characters.end(), character);
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
namespace JPH
|
namespace JPH
|
||||||
{
|
{
|
||||||
class Body;
|
class Body;
|
||||||
|
class BodyCreationSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
|
|
@ -28,8 +29,11 @@ namespace Nz
|
||||||
class NAZARA_JOLTPHYSICS3D_API JoltRigidBody3D
|
class NAZARA_JOLTPHYSICS3D_API JoltRigidBody3D
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
JoltRigidBody3D(JoltPhysWorld3D* world, const Matrix4f& mat = Matrix4f::Identity());
|
struct DynamicSettings;
|
||||||
JoltRigidBody3D(JoltPhysWorld3D* world, std::shared_ptr<JoltCollider3D> geom, const Matrix4f& mat = Matrix4f::Identity());
|
struct StaticSettings;
|
||||||
|
|
||||||
|
JoltRigidBody3D(JoltPhysWorld3D& world, const DynamicSettings& settings);
|
||||||
|
JoltRigidBody3D(JoltPhysWorld3D& world, const StaticSettings& settings);
|
||||||
JoltRigidBody3D(const JoltRigidBody3D& object) = delete;
|
JoltRigidBody3D(const JoltRigidBody3D& object) = delete;
|
||||||
JoltRigidBody3D(JoltRigidBody3D&& object) noexcept;
|
JoltRigidBody3D(JoltRigidBody3D&& object) noexcept;
|
||||||
~JoltRigidBody3D();
|
~JoltRigidBody3D();
|
||||||
|
|
@ -38,7 +42,9 @@ namespace Nz
|
||||||
void AddForce(const Vector3f& force, const Vector3f& point, CoordSys coordSys = CoordSys::Global);
|
void AddForce(const Vector3f& force, const Vector3f& point, CoordSys coordSys = CoordSys::Global);
|
||||||
void AddTorque(const Vector3f& torque, CoordSys coordSys = CoordSys::Global);
|
void AddTorque(const Vector3f& torque, CoordSys coordSys = CoordSys::Global);
|
||||||
|
|
||||||
|
inline void DisableSimulation();
|
||||||
inline void DisableSleeping();
|
inline void DisableSleeping();
|
||||||
|
void EnableSimulation(bool enable);
|
||||||
void EnableSleeping(bool enable);
|
void EnableSleeping(bool enable);
|
||||||
|
|
||||||
void FallAsleep();
|
void FallAsleep();
|
||||||
|
|
@ -53,16 +59,16 @@ namespace Nz
|
||||||
float GetLinearDamping() const;
|
float GetLinearDamping() const;
|
||||||
Vector3f GetLinearVelocity() const;
|
Vector3f GetLinearVelocity() const;
|
||||||
float GetMass() const;
|
float GetMass() const;
|
||||||
Vector3f GetMassCenter(CoordSys coordSys = CoordSys::Local) const;
|
|
||||||
Matrix4f GetMatrix() const;
|
Matrix4f GetMatrix() const;
|
||||||
Vector3f GetPosition() const;
|
Vector3f GetPosition() const;
|
||||||
std::pair<Vector3f, Quaternionf> GetPositionAndRotation() const;
|
std::pair<Vector3f, Quaternionf> GetPositionAndRotation() const;
|
||||||
Quaternionf GetRotation() const;
|
Quaternionf GetRotation() const;
|
||||||
inline JoltPhysWorld3D* GetWorld() const;
|
inline JoltPhysWorld3D& GetWorld() const;
|
||||||
|
|
||||||
bool IsSimulationEnabled() const;
|
inline bool IsSimulationEnabled() const;
|
||||||
bool IsSleeping() const;
|
bool IsSleeping() const;
|
||||||
bool IsSleepingEnabled() const;
|
bool IsSleepingEnabled() const;
|
||||||
|
bool IsStatic() const;
|
||||||
|
|
||||||
void SetAngularDamping(float angularDamping);
|
void SetAngularDamping(float angularDamping);
|
||||||
void SetAngularVelocity(const Vector3f& angularVelocity);
|
void SetAngularVelocity(const Vector3f& angularVelocity);
|
||||||
|
|
@ -70,7 +76,6 @@ namespace Nz
|
||||||
void SetLinearDamping(float damping);
|
void SetLinearDamping(float damping);
|
||||||
void SetLinearVelocity(const Vector3f& velocity);
|
void SetLinearVelocity(const Vector3f& velocity);
|
||||||
void SetMass(float mass, bool recomputeInertia = true);
|
void SetMass(float mass, bool recomputeInertia = true);
|
||||||
void SetMassCenter(const Vector3f& center);
|
|
||||||
void SetPosition(const Vector3f& position);
|
void SetPosition(const Vector3f& position);
|
||||||
void SetRotation(const Quaternionf& rotation);
|
void SetRotation(const Quaternionf& rotation);
|
||||||
|
|
||||||
|
|
@ -86,14 +91,53 @@ namespace Nz
|
||||||
JoltRigidBody3D& operator=(const JoltRigidBody3D& object) = delete;
|
JoltRigidBody3D& operator=(const JoltRigidBody3D& object) = delete;
|
||||||
JoltRigidBody3D& operator=(JoltRigidBody3D&& object) noexcept;
|
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:
|
protected:
|
||||||
void Destroy();
|
void Destroy(bool worldDestruction = false);
|
||||||
|
|
||||||
private:
|
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;
|
std::shared_ptr<JoltCollider3D> m_geom;
|
||||||
JPH::Body* m_body;
|
JPH::Body* m_body;
|
||||||
JoltPhysWorld3D* m_world;
|
JoltPhysWorld3D* m_world;
|
||||||
UInt32 m_bodyIndex;
|
UInt32 m_bodyIndex;
|
||||||
|
bool m_isSimulationEnabled;
|
||||||
|
bool m_isTrigger;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,11 @@
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
|
inline void JoltRigidBody3D::DisableSimulation()
|
||||||
|
{
|
||||||
|
return EnableSimulation(false);
|
||||||
|
}
|
||||||
|
|
||||||
inline void JoltRigidBody3D::DisableSleeping()
|
inline void JoltRigidBody3D::DisableSleeping()
|
||||||
{
|
{
|
||||||
return EnableSleeping(false);
|
return EnableSleeping(false);
|
||||||
|
|
@ -31,9 +36,14 @@ namespace Nz
|
||||||
return m_geom;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ namespace Nz
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
JoltRigidBody3DComponent JoltPhysics3DSystem::CreateRigidBody(Args&&... 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()
|
inline JoltPhysWorld3D& JoltPhysics3DSystem::GetPhysWorld()
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ namespace Nz
|
||||||
|
|
||||||
JPH::CharacterSettings settings;
|
JPH::CharacterSettings settings;
|
||||||
settings.mShape = shapeResult.Get();
|
settings.mShape = shapeResult.Get();
|
||||||
|
settings.mLayer = 1;
|
||||||
|
|
||||||
m_character = std::make_unique<JPH::Character>(&settings, ToJolt(position), ToJolt(rotation), 0, m_physicsWorld.GetPhysicsSystem());
|
m_character = std::make_unique<JPH::Character>(&settings, ToJolt(position), ToJolt(rotation), 0, m_physicsWorld.GetPhysicsSystem());
|
||||||
m_character->AddToPhysicsSystem();
|
m_character->AddToPhysicsSystem();
|
||||||
|
|
@ -108,7 +109,7 @@ namespace Nz
|
||||||
m_character->Activate(false);
|
m_character->Activate(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JoltCharacter::PreSimulate(float elapsedTime)
|
void JoltCharacter::PreSimulate(float /*elapsedTime*/)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,12 +52,12 @@ namespace Nz
|
||||||
|
|
||||||
JoltPhysWorld3D& JoltConstraint3D::GetWorld()
|
JoltPhysWorld3D& JoltConstraint3D::GetWorld()
|
||||||
{
|
{
|
||||||
return *GetBodyA().GetWorld();
|
return GetBodyA().GetWorld();
|
||||||
}
|
}
|
||||||
|
|
||||||
const JoltPhysWorld3D& JoltConstraint3D::GetWorld() const
|
const JoltPhysWorld3D& JoltConstraint3D::GetWorld() const
|
||||||
{
|
{
|
||||||
return *GetBodyA().GetWorld();
|
return GetBodyA().GetWorld();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JoltConstraint3D::IsSingleBody() const
|
bool JoltConstraint3D::IsSingleBody() const
|
||||||
|
|
|
||||||
|
|
@ -15,20 +15,19 @@
|
||||||
#include <Jolt/Physics/Collision/CollisionCollectorImpl.h>
|
#include <Jolt/Physics/Collision/CollisionCollectorImpl.h>
|
||||||
#include <Jolt/Physics/Collision/RayCast.h>
|
#include <Jolt/Physics/Collision/RayCast.h>
|
||||||
#include <Jolt/Physics/Collision/ObjectLayer.h>
|
#include <Jolt/Physics/Collision/ObjectLayer.h>
|
||||||
|
#include <Jolt/Physics/Collision/Shape/SphereShape.h>
|
||||||
#include <Jolt/Physics/Collision/BroadPhase/BroadPhaseLayer.h>
|
#include <Jolt/Physics/Collision/BroadPhase/BroadPhaseLayer.h>
|
||||||
#include <Jolt/Physics/PhysicsSettings.h>
|
#include <Jolt/Physics/PhysicsSettings.h>
|
||||||
#include <Jolt/Physics/PhysicsSystem.h>
|
#include <Jolt/Physics/PhysicsSystem.h>
|
||||||
#include <Jolt/Physics/PhysicsStepListener.h>
|
#include <Jolt/Physics/PhysicsStepListener.h>
|
||||||
#include <Jolt/Physics/Body/BodyActivationListener.h>
|
#include <Jolt/Physics/Body/BodyActivationListener.h>
|
||||||
|
#include <tsl/ordered_set.h>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <iostream>
|
|
||||||
#include <Nazara/JoltPhysics3D/Debug.hpp>
|
#include <Nazara/JoltPhysics3D/Debug.hpp>
|
||||||
|
|
||||||
namespace DitchMeAsap
|
namespace DitchMeAsap
|
||||||
{
|
{
|
||||||
using namespace JPH;
|
using namespace JPH;
|
||||||
using std::cout;
|
|
||||||
using std::endl;
|
|
||||||
|
|
||||||
// Layer that objects can be in, determines which other objects it can collide with
|
// Layer that objects can be in, determines which other objects it can collide with
|
||||||
// Typically you at least want to have 1 layer for moving bodies and 1 layer for static bodies, but you can have more
|
// Typically you at least want to have 1 layer for moving bodies and 1 layer for static bodies, but you can have more
|
||||||
|
|
@ -130,7 +129,7 @@ namespace DitchMeAsap
|
||||||
};
|
};
|
||||||
|
|
||||||
// An example contact listener
|
// An example contact listener
|
||||||
class MyContactListener : public ContactListener
|
/*class MyContactListener : public ContactListener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// See: ContactListener
|
// See: ContactListener
|
||||||
|
|
@ -156,7 +155,7 @@ namespace DitchMeAsap
|
||||||
{
|
{
|
||||||
cout << "A contact was removed" << endl;
|
cout << "A contact was removed" << endl;
|
||||||
}
|
}
|
||||||
};
|
};*/
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
|
|
@ -227,7 +226,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnBodyActivated(const JPH::BodyID& inBodyID, UInt64 inBodyUserData) override
|
void OnBodyActivated(const JPH::BodyID& inBodyID, UInt64 /*inBodyUserData*/) override
|
||||||
{
|
{
|
||||||
UInt32 bodyIndex = inBodyID.GetIndex();
|
UInt32 bodyIndex = inBodyID.GetIndex();
|
||||||
UInt32 blockIndex = bodyIndex / 64;
|
UInt32 blockIndex = bodyIndex / 64;
|
||||||
|
|
@ -236,7 +235,7 @@ namespace Nz
|
||||||
m_physWorld.m_activeBodies[blockIndex] |= UInt64(1u) << localIndex;
|
m_physWorld.m_activeBodies[blockIndex] |= UInt64(1u) << localIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnBodyDeactivated(const JPH::BodyID& inBodyID, UInt64 inBodyUserData) override
|
void OnBodyDeactivated(const JPH::BodyID& inBodyID, UInt64 /*inBodyUserData*/) override
|
||||||
{
|
{
|
||||||
UInt32 bodyIndex = inBodyID.GetIndex();
|
UInt32 bodyIndex = inBodyID.GetIndex();
|
||||||
UInt32 blockIndex = bodyIndex / 64;
|
UInt32 blockIndex = bodyIndex / 64;
|
||||||
|
|
@ -268,8 +267,15 @@ namespace Nz
|
||||||
|
|
||||||
struct JoltPhysWorld3D::JoltWorld
|
struct JoltPhysWorld3D::JoltWorld
|
||||||
{
|
{
|
||||||
|
using BodySet = tsl::ordered_set<JPH::BodyID, std::hash<JPH::BodyID>, std::equal_to<JPH::BodyID>, std::allocator<JPH::BodyID>, std::vector<JPH::BodyID>>;
|
||||||
|
|
||||||
JPH::TempAllocatorImpl tempAllocator;
|
JPH::TempAllocatorImpl tempAllocator;
|
||||||
JPH::PhysicsSystem physicsSystem;
|
JPH::PhysicsSystem physicsSystem;
|
||||||
|
BodySet pendingAdditionActivate;
|
||||||
|
BodySet pendingAdditionNoActivate;
|
||||||
|
BodySet pendingDeactivations;
|
||||||
|
std::vector<JPH::BodyID> tempBodyIDVec;
|
||||||
|
std::unique_ptr<JPH::SphereShape> nullShape;
|
||||||
|
|
||||||
JoltPhysWorld3D::BodyActivationListener bodyActivationListener;
|
JoltPhysWorld3D::BodyActivationListener bodyActivationListener;
|
||||||
JoltPhysWorld3D::StepListener stepListener;
|
JoltPhysWorld3D::StepListener stepListener;
|
||||||
|
|
@ -305,9 +311,14 @@ namespace Nz
|
||||||
m_world->physicsSystem.AddStepListener(&m_world->stepListener);
|
m_world->physicsSystem.AddStepListener(&m_world->stepListener);
|
||||||
|
|
||||||
std::size_t blockCount = (m_world->physicsSystem.GetMaxBodies() - 1) / 64 + 1;
|
std::size_t blockCount = (m_world->physicsSystem.GetMaxBodies() - 1) / 64 + 1;
|
||||||
|
|
||||||
m_activeBodies = std::make_unique<std::atomic_uint64_t[]>(blockCount);
|
m_activeBodies = std::make_unique<std::atomic_uint64_t[]>(blockCount);
|
||||||
for (std::size_t i = 0; i < blockCount; ++i)
|
for (std::size_t i = 0; i < blockCount; ++i)
|
||||||
m_activeBodies[i] = 0;
|
m_activeBodies[i] = 0;
|
||||||
|
|
||||||
|
m_registeredBodies = std::make_unique<std::uint64_t[]>(blockCount);
|
||||||
|
for (std::size_t i = 0; i < blockCount; ++i)
|
||||||
|
m_registeredBodies[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
JoltPhysWorld3D::~JoltPhysWorld3D() = default;
|
JoltPhysWorld3D::~JoltPhysWorld3D() = default;
|
||||||
|
|
@ -377,9 +388,57 @@ namespace Nz
|
||||||
hitInfo.hitBody = reinterpret_cast<JoltRigidBody3D*>(static_cast<std::uintptr_t>(body.GetUserData()));
|
hitInfo.hitBody = reinterpret_cast<JoltRigidBody3D*>(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);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JoltPhysWorld3D::RefreshBodies()
|
||||||
|
{
|
||||||
|
// Batch add bodies (keeps the broadphase efficient)
|
||||||
|
JPH::BodyInterface& bodyInterface = m_world->physicsSystem.GetBodyInterfaceNoLock();
|
||||||
|
auto AddBodies = [&](const JoltWorld::BodySet& bodies, JPH::EActivation activation)
|
||||||
|
{
|
||||||
|
for (const JPH::BodyID& bodyId : bodies)
|
||||||
|
{
|
||||||
|
UInt32 bodyIndex = bodyId.GetIndex();
|
||||||
|
UInt32 blockIndex = bodyIndex / 64;
|
||||||
|
UInt32 localIndex = bodyIndex % 64;
|
||||||
|
|
||||||
|
m_registeredBodies[blockIndex] |= UInt64(1u) << localIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bodies.size() == 1)
|
||||||
|
bodyInterface.AddBody(bodies.front(), activation);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_world->tempBodyIDVec.resize(bodies.size());
|
||||||
|
std::memcpy(&m_world->tempBodyIDVec[0], bodies.data(), bodies.size() * sizeof(JPH::BodyID));
|
||||||
|
|
||||||
|
JPH::BodyInterface::AddState addState = bodyInterface.AddBodiesPrepare(m_world->tempBodyIDVec.data(), SafeCast<int>(m_world->tempBodyIDVec.size()));
|
||||||
|
bodyInterface.AddBodiesFinalize(m_world->tempBodyIDVec.data(), SafeCast<int>(m_world->tempBodyIDVec.size()), addState, activation);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle pending register/unregister bodies
|
||||||
|
if (!m_world->pendingAdditionActivate.empty())
|
||||||
|
{
|
||||||
|
AddBodies(m_world->pendingAdditionActivate, JPH::EActivation::Activate);
|
||||||
|
m_world->pendingAdditionActivate.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_world->pendingAdditionNoActivate.empty())
|
||||||
|
{
|
||||||
|
AddBodies(m_world->pendingAdditionNoActivate, JPH::EActivation::DontActivate);
|
||||||
|
m_world->pendingAdditionNoActivate.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_world->pendingDeactivations.empty())
|
||||||
|
{
|
||||||
|
bodyInterface.DeactivateBodies(m_world->pendingDeactivations.data(), SafeCast<int>(m_world->pendingDeactivations.size()));
|
||||||
|
m_world->pendingDeactivations.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void JoltPhysWorld3D::SetGravity(const Vector3f& gravity)
|
void JoltPhysWorld3D::SetGravity(const Vector3f& gravity)
|
||||||
{
|
{
|
||||||
m_world->physicsSystem.SetGravity(ToJolt(gravity));
|
m_world->physicsSystem.SetGravity(ToJolt(gravity));
|
||||||
|
|
@ -397,18 +456,12 @@ namespace Nz
|
||||||
|
|
||||||
void JoltPhysWorld3D::Step(Time timestep)
|
void JoltPhysWorld3D::Step(Time timestep)
|
||||||
{
|
{
|
||||||
|
RefreshBodies();
|
||||||
|
|
||||||
JPH::JobSystem& jobSystem = JoltPhysics3D::Instance()->GetThreadPool();
|
JPH::JobSystem& jobSystem = JoltPhysics3D::Instance()->GetThreadPool();
|
||||||
|
|
||||||
m_timestepAccumulator += timestep;
|
|
||||||
|
|
||||||
float stepSize = m_stepSize.AsSeconds<float>();
|
float stepSize = m_stepSize.AsSeconds<float>();
|
||||||
|
|
||||||
static bool firstStep = true;
|
m_timestepAccumulator += timestep;
|
||||||
if (firstStep)
|
|
||||||
{
|
|
||||||
m_world->physicsSystem.OptimizeBroadPhase();
|
|
||||||
firstStep = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t stepCount = 0;
|
std::size_t stepCount = 0;
|
||||||
while (m_timestepAccumulator >= m_stepSize && stepCount < m_maxStepCount)
|
while (m_timestepAccumulator >= m_stepSize && stepCount < m_maxStepCount)
|
||||||
|
|
@ -423,6 +476,63 @@ namespace Nz
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JoltPhysWorld3D::RegisterBody(const JPH::BodyID& bodyID, bool activate, bool removeFromDeactivationList)
|
||||||
|
{
|
||||||
|
assert(removeFromDeactivationList || !m_world->pendingDeactivations.contains(bodyID));
|
||||||
|
|
||||||
|
auto& activationSet = (activate) ? m_world->pendingAdditionActivate : m_world->pendingAdditionNoActivate;
|
||||||
|
activationSet.insert(bodyID);
|
||||||
|
|
||||||
|
if (removeFromDeactivationList)
|
||||||
|
{
|
||||||
|
auto& otherActivationSet = (activate) ? m_world->pendingAdditionNoActivate : m_world->pendingAdditionActivate;
|
||||||
|
otherActivationSet.erase(bodyID);
|
||||||
|
|
||||||
|
m_world->pendingDeactivations.erase(bodyID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JoltPhysWorld3D::UnregisterBody(const JPH::BodyID& bodyID, bool destroy, bool removeFromActivationList)
|
||||||
|
{
|
||||||
|
if (destroy)
|
||||||
|
{
|
||||||
|
auto& bodyInterface = m_world->physicsSystem.GetBodyInterface();
|
||||||
|
|
||||||
|
UInt32 bodyIndex = bodyID.GetIndex();
|
||||||
|
if (IsBodyRegistered(bodyIndex))
|
||||||
|
{
|
||||||
|
UInt32 blockIndex = bodyIndex / 64;
|
||||||
|
UInt32 localIndex = bodyIndex % 64;
|
||||||
|
|
||||||
|
m_registeredBodies[blockIndex] &= ~(UInt64(1u) << localIndex);
|
||||||
|
|
||||||
|
bodyInterface.RemoveBody(bodyID);
|
||||||
|
}
|
||||||
|
|
||||||
|
bodyInterface.DestroyBody(bodyID);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_world->pendingDeactivations.insert(bodyID);
|
||||||
|
|
||||||
|
if (removeFromActivationList)
|
||||||
|
{
|
||||||
|
m_world->pendingAdditionActivate.erase(bodyID);
|
||||||
|
m_world->pendingAdditionNoActivate.erase(bodyID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const JPH::Shape* JoltPhysWorld3D::GetNullShape() const
|
||||||
|
{
|
||||||
|
if (!m_world->nullShape)
|
||||||
|
{
|
||||||
|
m_world->nullShape = std::make_unique<JPH::SphereShape>(std::numeric_limits<float>::epsilon());
|
||||||
|
m_world->nullShape->SetEmbedded();
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_world->nullShape.get();
|
||||||
|
}
|
||||||
|
|
||||||
void JoltPhysWorld3D::OnPreStep(float deltatime)
|
void JoltPhysWorld3D::OnPreStep(float deltatime)
|
||||||
{
|
{
|
||||||
for (JoltCharacter* character : m_characters)
|
for (JoltCharacter* character : m_characters)
|
||||||
|
|
|
||||||
|
|
@ -17,46 +17,57 @@
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
JoltRigidBody3D::JoltRigidBody3D(JoltPhysWorld3D* world, const Matrix4f& mat) :
|
JoltRigidBody3D::JoltRigidBody3D(JoltPhysWorld3D& world, const DynamicSettings& settings) :
|
||||||
JoltRigidBody3D(world, nullptr, mat)
|
m_geom(settings.geom),
|
||||||
|
m_world(&world),
|
||||||
|
m_isSimulationEnabled(false),
|
||||||
|
m_isTrigger(settings.isTrigger)
|
||||||
{
|
{
|
||||||
}
|
|
||||||
|
|
||||||
JoltRigidBody3D::JoltRigidBody3D(JoltPhysWorld3D* world, std::shared_ptr<JoltCollider3D> geom, const Matrix4f& mat) :
|
|
||||||
m_geom(std::move(geom)),
|
|
||||||
m_world(world)
|
|
||||||
{
|
|
||||||
NazaraAssert(m_world, "Invalid world");
|
|
||||||
|
|
||||||
if (!m_geom)
|
|
||||||
m_geom = std::make_shared<JoltSphereCollider3D>(std::numeric_limits<float>::epsilon());
|
|
||||||
|
|
||||||
JPH::BodyInterface& bodyInterface = m_world->GetPhysicsSystem()->GetBodyInterface();
|
JPH::BodyInterface& bodyInterface = m_world->GetPhysicsSystem()->GetBodyInterface();
|
||||||
|
|
||||||
JPH::Vec3 position = ToJolt(mat.GetTranslation());
|
JPH::BodyCreationSettings creationSettings;
|
||||||
JPH::Quat rotation = ToJolt(mat.GetRotation().Normalize());
|
BuildSettings(settings, creationSettings);
|
||||||
|
|
||||||
JPH::BodyCreationSettings settings(m_geom->GetShapeSettings(), position, rotation, JPH::EMotionType::Dynamic, 1);
|
|
||||||
|
|
||||||
m_body = bodyInterface.CreateBody(settings);
|
|
||||||
m_body->SetUserData(SafeCast<UInt64>(reinterpret_cast<std::uintptr_t>(this)));
|
|
||||||
|
|
||||||
|
m_body = bodyInterface.CreateBody(creationSettings);
|
||||||
JPH::BodyID bodyId = m_body->GetID();
|
JPH::BodyID bodyId = m_body->GetID();
|
||||||
|
|
||||||
bodyInterface.AddBody(bodyId, JPH::EActivation::Activate);
|
|
||||||
m_bodyIndex = bodyId.GetIndex();
|
m_bodyIndex = bodyId.GetIndex();
|
||||||
|
|
||||||
|
if (settings.isSimulationEnabled)
|
||||||
|
m_world->RegisterBody(bodyId, !settings.initiallySleeping, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
JoltRigidBody3D::JoltRigidBody3D(JoltRigidBody3D&& object) noexcept :
|
JoltRigidBody3D::JoltRigidBody3D(JoltPhysWorld3D& world, const StaticSettings& settings) :
|
||||||
m_geom(std::move(object.m_geom)),
|
m_geom(settings.geom),
|
||||||
m_body(object.m_body),
|
m_world(&world),
|
||||||
m_bodyIndex(object.m_bodyIndex),
|
m_isSimulationEnabled(false),
|
||||||
m_world(object.m_world)
|
m_isTrigger(settings.isTrigger)
|
||||||
{
|
{
|
||||||
m_body->SetUserData(SafeCast<UInt64>(reinterpret_cast<std::uintptr_t>(this)));
|
JPH::BodyInterface& bodyInterface = m_world->GetPhysicsSystem()->GetBodyInterface();
|
||||||
|
|
||||||
object.m_body = nullptr;
|
JPH::BodyCreationSettings creationSettings;
|
||||||
object.m_bodyIndex = std::numeric_limits<UInt32>::max();
|
BuildSettings(settings, creationSettings);
|
||||||
|
|
||||||
|
m_body = bodyInterface.CreateBody(creationSettings);
|
||||||
|
JPH::BodyID bodyId = m_body->GetID();
|
||||||
|
m_bodyIndex = bodyId.GetIndex();
|
||||||
|
|
||||||
|
if (settings.isSimulationEnabled)
|
||||||
|
m_world->RegisterBody(bodyId, false, false); //< static bodies cannot be activated
|
||||||
|
}
|
||||||
|
|
||||||
|
JoltRigidBody3D::JoltRigidBody3D(JoltRigidBody3D&& body) noexcept :
|
||||||
|
m_geom(std::move(body.m_geom)),
|
||||||
|
m_body(body.m_body),
|
||||||
|
m_world(body.m_world),
|
||||||
|
m_bodyIndex(body.m_bodyIndex),
|
||||||
|
m_isSimulationEnabled(body.m_isSimulationEnabled),
|
||||||
|
m_isTrigger(body.m_isTrigger)
|
||||||
|
{
|
||||||
|
body.m_body = nullptr;
|
||||||
|
body.m_bodyIndex = std::numeric_limits<UInt32>::max();
|
||||||
|
|
||||||
|
if (m_body)
|
||||||
|
m_body->SetUserData(SafeCast<UInt64>(reinterpret_cast<std::uintptr_t>(this)));
|
||||||
}
|
}
|
||||||
|
|
||||||
JoltRigidBody3D::~JoltRigidBody3D()
|
JoltRigidBody3D::~JoltRigidBody3D()
|
||||||
|
|
@ -69,10 +80,8 @@ namespace Nz
|
||||||
switch (coordSys)
|
switch (coordSys)
|
||||||
{
|
{
|
||||||
case CoordSys::Global:
|
case CoordSys::Global:
|
||||||
{
|
|
||||||
m_body->AddForce(ToJolt(force));
|
m_body->AddForce(ToJolt(force));
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
case CoordSys::Local:
|
case CoordSys::Local:
|
||||||
m_body->AddForce(m_body->GetRotation() * ToJolt(force));
|
m_body->AddForce(m_body->GetRotation() * ToJolt(force));
|
||||||
|
|
@ -80,21 +89,17 @@ namespace Nz
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
void JoltRigidBody3D::AddForce(const Vector3f& force, const Vector3f& point, CoordSys coordSys)
|
void JoltRigidBody3D::AddForce(const Vector3f& force, const Vector3f& point, CoordSys coordSys)
|
||||||
{
|
{
|
||||||
switch (coordSys)
|
switch (coordSys)
|
||||||
{
|
{
|
||||||
case CoordSys::Global:
|
case CoordSys::Global:
|
||||||
WakeUp();
|
m_body->AddForce(ToJolt(force), ToJolt(point));
|
||||||
m_body->applyForce(ToJolt(force), ToJolt(point));
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CoordSys::Local:
|
case CoordSys::Local:
|
||||||
{
|
m_body->AddForce(m_body->GetRotation() * ToJolt(force), ToJolt(ToWorld(point)));
|
||||||
Matrix4f transformMatrix = GetMatrix();
|
break;
|
||||||
return AddForce(transformMatrix.Transform(force, 0.f), point, CoordSys::Global);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -103,74 +108,83 @@ namespace Nz
|
||||||
switch (coordSys)
|
switch (coordSys)
|
||||||
{
|
{
|
||||||
case CoordSys::Global:
|
case CoordSys::Global:
|
||||||
WakeUp();
|
m_body->AddTorque(ToJolt(torque));
|
||||||
m_body->applyTorque(ToJolt(torque));
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CoordSys::Local:
|
case CoordSys::Local:
|
||||||
Matrix4f transformMatrix = GetMatrix();
|
m_body->AddTorque(m_body->GetRotation() * ToJolt(torque));
|
||||||
WakeUp();
|
|
||||||
m_body->applyTorque(ToJolt(transformMatrix.Transform(torque, 0.f)));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
void JoltRigidBody3D::EnableSimulation(bool enable)
|
||||||
|
{
|
||||||
|
if (m_isSimulationEnabled == enable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (enable)
|
||||||
|
m_world->RegisterBody(m_body->GetID(), true, true);
|
||||||
|
else
|
||||||
|
m_world->UnregisterBody(m_body->GetID(), false, true);
|
||||||
|
|
||||||
|
m_isSimulationEnabled = enable;
|
||||||
|
}
|
||||||
|
|
||||||
void JoltRigidBody3D::EnableSleeping(bool enable)
|
void JoltRigidBody3D::EnableSleeping(bool enable)
|
||||||
{
|
{
|
||||||
m_body->SetAllowSleeping(enable);
|
m_body->SetAllowSleeping(enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
void JoltRigidBody3D::FallAsleep()
|
void JoltRigidBody3D::FallAsleep()
|
||||||
{
|
{
|
||||||
if (m_body->getActivationState() != DISABLE_DEACTIVATION)
|
JPH::BodyInterface& bodyInterface = m_world->GetPhysicsSystem()->GetBodyInterface();
|
||||||
m_body->setActivationState(ISLAND_SLEEPING);
|
bodyInterface.DeactivateBody(m_body->GetID());
|
||||||
}
|
}
|
||||||
|
|
||||||
Boxf JoltRigidBody3D::GetAABB() const
|
Boxf JoltRigidBody3D::GetAABB() const
|
||||||
{
|
{
|
||||||
btVector3 min, max;
|
const JPH::AABox& aabb = m_body->GetWorldSpaceBounds();
|
||||||
m_body->getAabb(min, max);
|
return Boxf(FromJolt(aabb.mMin), FromJolt(aabb.GetSize()));
|
||||||
|
|
||||||
return Boxf(FromJolt(min), FromJolt(max));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float JoltRigidBody3D::GetAngularDamping() const
|
float JoltRigidBody3D::GetAngularDamping() const
|
||||||
{
|
{
|
||||||
return m_body->getAngularDamping();
|
if NAZARA_UNLIKELY(IsStatic())
|
||||||
|
return 0.f;
|
||||||
|
|
||||||
|
return m_body->GetMotionProperties()->GetAngularDamping();
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3f JoltRigidBody3D::GetAngularVelocity() const
|
Vector3f JoltRigidBody3D::GetAngularVelocity() const
|
||||||
{
|
{
|
||||||
return FromJolt(m_body->getAngularVelocity());
|
return FromJolt(m_body->GetAngularVelocity());
|
||||||
}
|
}
|
||||||
|
|
||||||
float JoltRigidBody3D::GetLinearDamping() const
|
float JoltRigidBody3D::GetLinearDamping() const
|
||||||
{
|
{
|
||||||
return m_body->getLinearDamping();
|
if NAZARA_UNLIKELY(IsStatic())
|
||||||
|
return 0.f;
|
||||||
|
|
||||||
|
return m_body->GetMotionProperties()->GetLinearDamping();
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3f JoltRigidBody3D::GetLinearVelocity() const
|
Vector3f JoltRigidBody3D::GetLinearVelocity() const
|
||||||
{
|
{
|
||||||
return FromJolt(m_body->getLinearVelocity());
|
return FromJolt(m_body->GetLinearVelocity());
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
float JoltRigidBody3D::GetMass() const
|
float JoltRigidBody3D::GetMass() const
|
||||||
{
|
{
|
||||||
|
if NAZARA_UNLIKELY(IsStatic())
|
||||||
|
return 0.f;
|
||||||
|
|
||||||
return 1.f / m_body->GetMotionProperties()->GetInverseMass();
|
return 1.f / m_body->GetMotionProperties()->GetInverseMass();
|
||||||
}
|
}
|
||||||
#if 0
|
|
||||||
Vector3f JoltRigidBody3D::GetMassCenter(CoordSys coordSys) const
|
|
||||||
{
|
|
||||||
return FromJolt(m_body->getCenterOfMassPosition());
|
|
||||||
}
|
|
||||||
|
|
||||||
Matrix4f JoltRigidBody3D::GetMatrix() const
|
Matrix4f JoltRigidBody3D::GetMatrix() const
|
||||||
{
|
{
|
||||||
return FromJolt(m_body->getWorldTransform());
|
return FromJolt(m_body->GetCenterOfMassTransform());
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
Vector3f JoltRigidBody3D::GetPosition() const
|
Vector3f JoltRigidBody3D::GetPosition() const
|
||||||
{
|
{
|
||||||
|
|
@ -190,13 +204,6 @@ namespace Nz
|
||||||
return FromJolt(m_body->GetRotation());
|
return FromJolt(m_body->GetRotation());
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
bool JoltRigidBody3D::IsSimulationEnabled() const
|
|
||||||
{
|
|
||||||
return m_body->isActive();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool JoltRigidBody3D::IsSleeping() const
|
bool JoltRigidBody3D::IsSleeping() const
|
||||||
{
|
{
|
||||||
return m_body->IsActive();
|
return m_body->IsActive();
|
||||||
|
|
@ -207,30 +214,42 @@ namespace Nz
|
||||||
return m_body->GetAllowSleeping();
|
return m_body->GetAllowSleeping();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
bool JoltRigidBody3D::IsStatic() const
|
||||||
|
{
|
||||||
|
return m_body->GetMotionType() == JPH::EMotionType::Static;
|
||||||
|
}
|
||||||
|
|
||||||
void JoltRigidBody3D::SetAngularDamping(float angularDamping)
|
void JoltRigidBody3D::SetAngularDamping(float angularDamping)
|
||||||
{
|
{
|
||||||
m_body->setDamping(m_body->getLinearDamping(), angularDamping);
|
if NAZARA_UNLIKELY(IsStatic())
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_body->GetMotionProperties()->SetAngularDamping(angularDamping);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JoltRigidBody3D::SetAngularVelocity(const Vector3f& angularVelocity)
|
void JoltRigidBody3D::SetAngularVelocity(const Vector3f& angularVelocity)
|
||||||
{
|
{
|
||||||
m_body->setAngularVelocity(ToJolt(angularVelocity));
|
m_body->SetAngularVelocity(ToJolt(angularVelocity));
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
void JoltRigidBody3D::SetGeom(std::shared_ptr<JoltCollider3D> geom, bool recomputeInertia)
|
void JoltRigidBody3D::SetGeom(std::shared_ptr<JoltCollider3D> geom, bool recomputeInertia)
|
||||||
{
|
{
|
||||||
if (m_geom != geom)
|
if (m_geom != geom)
|
||||||
{
|
{
|
||||||
float mass = GetMass();
|
float mass = GetMass();
|
||||||
|
|
||||||
if (geom)
|
const JPH::Shape* shape;
|
||||||
m_geom = std::move(geom);
|
m_geom = std::move(geom);
|
||||||
|
if (m_geom)
|
||||||
|
shape = m_geom->GetShapeSettings()->Create().Get();
|
||||||
else
|
else
|
||||||
m_geom = std::make_shared<JoltSphereCollider3D>(std::numeric_limits<float>::epsilon());
|
{
|
||||||
|
m_body->SetIsSensor(true);
|
||||||
|
shape = m_world->GetNullShape();
|
||||||
|
}
|
||||||
|
|
||||||
JPH::BodyInterface& bodyInterface = m_world->GetPhysicsSystem()->GetBodyInterface();
|
JPH::BodyInterface& bodyInterface = m_world->GetPhysicsSystem()->GetBodyInterface();
|
||||||
bodyInterface.SetShape(m_body->GetID(), m_geom->GetShapeSettings()->Create().Get(), false, JPH::EActivation::Activate);
|
bodyInterface.SetShape(m_body->GetID(), m_geom->GetShapeSettings()->Create().Get(), false, (ShouldActivate()) ? JPH::EActivation::Activate : JPH::EActivation::DontActivate);
|
||||||
if (recomputeInertia)
|
if (recomputeInertia)
|
||||||
{
|
{
|
||||||
JPH::MassProperties massProperties = m_body->GetShape()->GetMassProperties();
|
JPH::MassProperties massProperties = m_body->GetShape()->GetMassProperties();
|
||||||
|
|
@ -242,6 +261,9 @@ namespace Nz
|
||||||
|
|
||||||
void JoltRigidBody3D::SetLinearDamping(float damping)
|
void JoltRigidBody3D::SetLinearDamping(float damping)
|
||||||
{
|
{
|
||||||
|
if NAZARA_UNLIKELY(IsStatic())
|
||||||
|
return;
|
||||||
|
|
||||||
m_body->GetMotionProperties()->SetLinearDamping(damping);
|
m_body->GetMotionProperties()->SetLinearDamping(damping);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -270,34 +292,28 @@ namespace Nz
|
||||||
JPH::BodyInterface& bodyInterface = m_world->GetPhysicsSystem()->GetBodyInterfaceNoLock();
|
JPH::BodyInterface& bodyInterface = m_world->GetPhysicsSystem()->GetBodyInterfaceNoLock();
|
||||||
bodyInterface.DeactivateBody(m_body->GetID());
|
bodyInterface.DeactivateBody(m_body->GetID());
|
||||||
|
|
||||||
m_body->SetMotionType(JPH::EMotionType::Static);
|
m_body->SetMotionType(JPH::EMotionType::Kinematic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JoltRigidBody3D::SetMassCenter(const Vector3f& center)
|
|
||||||
{
|
|
||||||
//m_body->GetMotionProperties()->set
|
|
||||||
}
|
|
||||||
|
|
||||||
void JoltRigidBody3D::SetPosition(const Vector3f& position)
|
void JoltRigidBody3D::SetPosition(const Vector3f& position)
|
||||||
{
|
{
|
||||||
JPH::BodyInterface& bodyInterface = m_world->GetPhysicsSystem()->GetBodyInterfaceNoLock();
|
JPH::BodyInterface& bodyInterface = m_world->GetPhysicsSystem()->GetBodyInterfaceNoLock();
|
||||||
bodyInterface.SetPosition(m_body->GetID(), ToJolt(position), JPH::EActivation::Activate);
|
bodyInterface.SetPosition(m_body->GetID(), ToJolt(position), (ShouldActivate()) ? JPH::EActivation::Activate : JPH::EActivation::DontActivate);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JoltRigidBody3D::SetRotation(const Quaternionf& rotation)
|
void JoltRigidBody3D::SetRotation(const Quaternionf& rotation)
|
||||||
{
|
{
|
||||||
JPH::BodyInterface& body_interface = m_world->GetPhysicsSystem()->GetBodyInterfaceNoLock();
|
JPH::BodyInterface& bodyInterface = m_world->GetPhysicsSystem()->GetBodyInterfaceNoLock();
|
||||||
body_interface.SetRotation(m_body->GetID(), ToJolt(rotation), JPH::EActivation::Activate);
|
bodyInterface.SetRotation(m_body->GetID(), ToJolt(rotation), (ShouldActivate()) ? JPH::EActivation::Activate : JPH::EActivation::DontActivate);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JoltRigidBody3D::TeleportTo(const Vector3f& position, const Quaternionf& rotation)
|
void JoltRigidBody3D::TeleportTo(const Vector3f& position, const Quaternionf& rotation)
|
||||||
{
|
{
|
||||||
JPH::BodyInterface& bodyInterface = m_world->GetPhysicsSystem()->GetBodyInterfaceNoLock();
|
JPH::BodyInterface& bodyInterface = m_world->GetPhysicsSystem()->GetBodyInterfaceNoLock();
|
||||||
bodyInterface.SetPositionAndRotation(m_body->GetID(), ToJolt(position), ToJolt(rotation), JPH::EActivation::Activate);
|
bodyInterface.SetPositionAndRotation(m_body->GetID(), ToJolt(position), ToJolt(rotation), (ShouldActivate()) ? JPH::EActivation::Activate : JPH::EActivation::DontActivate);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
Quaternionf JoltRigidBody3D::ToLocal(const Quaternionf& worldRotation)
|
Quaternionf JoltRigidBody3D::ToLocal(const Quaternionf& worldRotation)
|
||||||
{
|
{
|
||||||
return GetRotation().Conjugate() * worldRotation;
|
return GetRotation().Conjugate() * worldRotation;
|
||||||
|
|
@ -305,8 +321,7 @@ namespace Nz
|
||||||
|
|
||||||
Vector3f JoltRigidBody3D::ToLocal(const Vector3f& worldPosition)
|
Vector3f JoltRigidBody3D::ToLocal(const Vector3f& worldPosition)
|
||||||
{
|
{
|
||||||
btTransform worldTransform = m_body->getWorldTransform();
|
return FromJolt(m_body->GetInverseCenterOfMassTransform() * ToJolt(worldPosition));
|
||||||
return GetMatrix().InverseTransform() * worldPosition;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Quaternionf JoltRigidBody3D::ToWorld(const Quaternionf& localRotation)
|
Quaternionf JoltRigidBody3D::ToWorld(const Quaternionf& localRotation)
|
||||||
|
|
@ -316,45 +331,100 @@ namespace Nz
|
||||||
|
|
||||||
Vector3f JoltRigidBody3D::ToWorld(const Vector3f& localPosition)
|
Vector3f JoltRigidBody3D::ToWorld(const Vector3f& localPosition)
|
||||||
{
|
{
|
||||||
return GetMatrix() * localPosition;
|
return FromJolt(m_body->GetCenterOfMassTransform() * ToJolt(localPosition));
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void JoltRigidBody3D::WakeUp()
|
void JoltRigidBody3D::WakeUp()
|
||||||
{
|
{
|
||||||
JPH::BodyInterface& body_interface = m_world->GetPhysicsSystem()->GetBodyInterface();
|
JPH::BodyInterface& bodyInterface = m_world->GetPhysicsSystem()->GetBodyInterface();
|
||||||
body_interface.ActivateBody(m_body->GetID());
|
bodyInterface.ActivateBody(m_body->GetID());
|
||||||
}
|
}
|
||||||
|
|
||||||
JoltRigidBody3D& JoltRigidBody3D::operator=(JoltRigidBody3D&& object) noexcept
|
JoltRigidBody3D& JoltRigidBody3D::operator=(JoltRigidBody3D&& body) noexcept
|
||||||
{
|
{
|
||||||
Destroy();
|
Destroy();
|
||||||
|
|
||||||
m_body = object.m_body;
|
m_body = body.m_body;
|
||||||
m_bodyIndex = object.m_bodyIndex;
|
m_bodyIndex = body.m_bodyIndex;
|
||||||
m_geom = std::move(object.m_geom);
|
m_geom = std::move(body.m_geom);
|
||||||
m_world = object.m_world;
|
m_world = body.m_world;
|
||||||
|
m_isSimulationEnabled = body.m_isSimulationEnabled;
|
||||||
|
m_isTrigger = body.m_isTrigger;
|
||||||
|
|
||||||
m_body->SetUserData(SafeCast<UInt64>(reinterpret_cast<std::uintptr_t>(this)));
|
body.m_body = nullptr;
|
||||||
|
body.m_bodyIndex = std::numeric_limits<UInt32>::max();
|
||||||
|
|
||||||
object.m_body = nullptr;
|
if (m_body)
|
||||||
object.m_bodyIndex = std::numeric_limits<UInt32>::max();
|
m_body->SetUserData(SafeCast<UInt64>(reinterpret_cast<std::uintptr_t>(this)));
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JoltRigidBody3D::Destroy()
|
void JoltRigidBody3D::Destroy(bool worldDestruction)
|
||||||
{
|
{
|
||||||
if (m_body)
|
if (m_body)
|
||||||
{
|
{
|
||||||
JPH::BodyID bodyId = m_body->GetID();
|
|
||||||
|
|
||||||
JPH::BodyInterface& bodyInterface = m_world->GetPhysicsSystem()->GetBodyInterface();
|
JPH::BodyInterface& bodyInterface = m_world->GetPhysicsSystem()->GetBodyInterface();
|
||||||
bodyInterface.RemoveBody(bodyId);
|
m_world->UnregisterBody(m_body->GetID(), true, !worldDestruction);
|
||||||
bodyInterface.DestroyBody(bodyId);
|
|
||||||
m_body = nullptr;
|
m_body = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_geom.reset();
|
m_geom.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JoltRigidBody3D::BuildSettings(const DynamicSettings& settings, JPH::BodyCreationSettings& creationSettings)
|
||||||
|
{
|
||||||
|
BuildSettings(static_cast<const CommonSettings&>(settings), creationSettings);
|
||||||
|
|
||||||
|
creationSettings.mAngularDamping = settings.angularDamping;
|
||||||
|
creationSettings.mAngularVelocity = ToJolt(settings.angularVelocity);
|
||||||
|
creationSettings.mLinearDamping = settings.linearDamping;
|
||||||
|
creationSettings.mLinearVelocity = ToJolt(settings.linearVelocity);
|
||||||
|
creationSettings.mFriction = settings.friction;
|
||||||
|
creationSettings.mGravityFactor = settings.gravityFactor;
|
||||||
|
creationSettings.mMaxAngularVelocity = settings.maxAngularVelocity;
|
||||||
|
creationSettings.mMaxLinearVelocity = settings.maxLinearVelocity;
|
||||||
|
creationSettings.mObjectLayer = 1;
|
||||||
|
creationSettings.mRestitution = settings.restitution;
|
||||||
|
creationSettings.mUserData = SafeCast<UInt64>(reinterpret_cast<std::uintptr_t>(this));
|
||||||
|
|
||||||
|
creationSettings.mMassPropertiesOverride = creationSettings.GetShape()->GetMassProperties();
|
||||||
|
creationSettings.mMassPropertiesOverride.ScaleToMass(settings.mass);
|
||||||
|
|
||||||
|
creationSettings.mMotionType = (settings.mass > 0.f) ? JPH::EMotionType::Dynamic : JPH::EMotionType::Kinematic;
|
||||||
|
|
||||||
|
switch (settings.motionQuality)
|
||||||
|
{
|
||||||
|
case JoltMotionQuality::Discrete: creationSettings.mMotionQuality = JPH::EMotionQuality::Discrete; break;
|
||||||
|
case JoltMotionQuality::LinearCast: creationSettings.mMotionQuality = JPH::EMotionQuality::LinearCast; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JoltRigidBody3D::BuildSettings(const StaticSettings& settings, JPH::BodyCreationSettings& creationSettings)
|
||||||
|
{
|
||||||
|
BuildSettings(static_cast<const CommonSettings&>(settings), creationSettings);
|
||||||
|
|
||||||
|
creationSettings.mMotionType = JPH::EMotionType::Static;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JoltRigidBody3D::BuildSettings(const CommonSettings& settings, JPH::BodyCreationSettings& creationSettings)
|
||||||
|
{
|
||||||
|
if (settings.geom)
|
||||||
|
{
|
||||||
|
creationSettings.SetShapeSettings(settings.geom->GetShapeSettings());
|
||||||
|
creationSettings.mIsSensor = settings.isTrigger;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
creationSettings.SetShape(m_world->GetNullShape());
|
||||||
|
creationSettings.mIsSensor = true; //< not the best solution but enough for now
|
||||||
|
creationSettings.mPosition = ToJolt(settings.position);
|
||||||
|
creationSettings.mRotation = ToJolt(settings.rotation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JoltRigidBody3D::ShouldActivate() const
|
||||||
|
{
|
||||||
|
return m_isSimulationEnabled && m_world->IsBodyRegistered(m_bodyIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ namespace Nz
|
||||||
// Ensure every RigidBody3D is destroyed before world is
|
// Ensure every RigidBody3D is destroyed before world is
|
||||||
auto rigidBodyView = m_registry.view<JoltRigidBody3DComponent>();
|
auto rigidBodyView = m_registry.view<JoltRigidBody3DComponent>();
|
||||||
for (auto [entity, rigidBodyComponent] : rigidBodyView.each())
|
for (auto [entity, rigidBodyComponent] : rigidBodyView.each())
|
||||||
rigidBodyComponent.Destroy();
|
rigidBodyComponent.Destroy(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JoltPhysics3DSystem::Dump()
|
void JoltPhysics3DSystem::Dump()
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ local modules = {
|
||||||
},
|
},
|
||||||
JoltPhysics3D = {
|
JoltPhysics3D = {
|
||||||
Deps = {"NazaraUtility"},
|
Deps = {"NazaraUtility"},
|
||||||
Packages = { "joltphysics", "entt" }
|
Packages = { "joltphysics", "entt", "ordered_map" }
|
||||||
},
|
},
|
||||||
Network = {
|
Network = {
|
||||||
Deps = {"NazaraCore"},
|
Deps = {"NazaraCore"},
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue