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

@@ -31,7 +31,7 @@ int main()
#endif
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>();
{
@@ -86,7 +86,8 @@ int main()
boxEntity.emplace<Nz::NodeComponent>();
#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
std::shared_ptr<Nz::BulletBoxCollider3D> wallCollider = std::make_shared<Nz::BulletBoxCollider3D>(Nz::Vector3f(BoxDims, BoxDims, 1.f));
#endif
@@ -116,11 +117,13 @@ int main()
#endif
#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
auto& ballPhysics = boxEntity.emplace<Nz::BulletRigidBody3DComponent>(physSystem.CreateRigidBody(boxCollider));
auto& boxBody = boxEntity.emplace<Nz::BulletRigidBody3DComponent>(physSystem.CreateRigidBody(boxCollider));
#endif
ballPhysics.SetMass(0.f);
std::shared_ptr<Nz::Model> colliderModel;
{
@@ -132,14 +135,14 @@ int main()
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);
colliderModel = std::make_shared<Nz::Model>(colliderGraphicalMesh);
for (std::size_t i = 0; i < colliderModel->GetSubMeshCount(); ++i)
colliderModel->SetMaterial(i, colliderMat);
boxGfx.AttachRenderable(std::move(colliderModel));*/
boxGfx.AttachRenderable(std::move(colliderModel));
}
}
@@ -178,11 +181,14 @@ int main()
ballNode.SetScale(radius);
#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
auto& ballPhysics = ballEntity.emplace<Nz::BulletRigidBody3DComponent>(physSystem.CreateRigidBody(sphereCollider));
#endif
ballPhysics.SetMass(4.f / 3.f * Nz::Pi<float> * Nz::IntegralPow(radius, 3));
//ballPhysics.DisableSleeping();
}
@@ -222,12 +228,14 @@ int main()
#endif
#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
auto& ballPhysics = ballEntity.emplace<Nz::BulletRigidBody3DComponent>(physSystem.CreateRigidBody(boxCollider));
ballEntity.emplace<Nz::BulletRigidBody3DComponent>(physSystem.CreateRigidBody(boxCollider));
#endif
ballPhysics.SetMass(width * height * depth);
//ballPhysics.DisableSleeping();
}
// Lumière
@@ -273,7 +281,43 @@ int main()
NazaraSlot(Nz::WindowEventHandler, OnMouseMoved, cameraMove);
NazaraSlot(Nz::WindowEventHandler, OnMouseMoved, grabbedObjectMove);
#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
std::optional<Nz::BulletPivotConstraint3D> grabConstraint;
#endif
@@ -328,8 +372,12 @@ int main()
{
if (lastHitInfo.hitBody && lastHitInfo.hitEntity != boxEntity)
{
#if USE_JOLT
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)
{
@@ -337,7 +385,11 @@ int main()
Nz::Vector3f to = cameraComponent.Unproject({ float(event.x), float(event.y), 1.f });
Nz::Vector3f newPosition = from + (to - from).Normalize() * distance;
#if USE_JOLT
grabConstraint->SetPosition(newPosition);
#else
grabConstraint->SetSecondAnchor(newPosition);
#endif
});
}
else