Ajout de Jolt Physics + 1ere version des factory entitecomposants - camera, transform, rigidbody, collider, renderer
This commit is contained in:
@@ -0,0 +1,193 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/SoftBody/SoftBodyBendConstraintTest.h>
|
||||
#include <Jolt/Physics/SoftBody/SoftBodyCreationSettings.h>
|
||||
#include <Utils/SoftBodyCreator.h>
|
||||
#include <Layers.h>
|
||||
#include <Renderer/DebugRendererImp.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(SoftBodyBendConstraintTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(SoftBodyBendConstraintTest, Test)
|
||||
}
|
||||
|
||||
void SoftBodyBendConstraintTest::Initialize()
|
||||
{
|
||||
CreateFloor();
|
||||
|
||||
default_random_engine random;
|
||||
uniform_real_distribution<float> random_float(-0.1f, 0.1f);
|
||||
|
||||
auto inv_mass = [](uint, uint inZ) { return inZ < 2? 0.0f : 1.0f; };
|
||||
auto perturbation = [&random, &random_float](uint, uint inZ) { return Vec3(random_float(random), (inZ & 1)? 0.1f : -0.1f, random_float(random)); };
|
||||
|
||||
{
|
||||
random.seed(1234);
|
||||
|
||||
// Cloth without bend constraints
|
||||
Ref<SoftBodySharedSettings> cloth_settings = SoftBodyCreator::CreateCloth(cNumVerticesX, cNumVerticesZ, cVertexSpacing, inv_mass, perturbation, SoftBodySharedSettings::EBendType::None);
|
||||
SoftBodyCreationSettings cloth(cloth_settings, RVec3(-5.0f, 5.0f, 0), Quat::sIdentity(), Layers::MOVING);
|
||||
mBodyInterface->CreateAndAddSoftBody(cloth, EActivation::Activate);
|
||||
}
|
||||
|
||||
{
|
||||
random.seed(1234);
|
||||
|
||||
// Cloth with distance bend constraints
|
||||
Ref<SoftBodySharedSettings> cloth_settings = SoftBodyCreator::CreateCloth(cNumVerticesX, cNumVerticesZ, cVertexSpacing, inv_mass, perturbation, SoftBodySharedSettings::EBendType::Distance);
|
||||
SoftBodyCreationSettings cloth(cloth_settings, RVec3(0.0f, 5.0f, 0), Quat::sIdentity(), Layers::MOVING);
|
||||
mBodyInterface->CreateAndAddSoftBody(cloth, EActivation::Activate);
|
||||
}
|
||||
|
||||
{
|
||||
random.seed(1234);
|
||||
|
||||
// Cloth with dihedral bend constraints
|
||||
Ref<SoftBodySharedSettings> cloth_settings = SoftBodyCreator::CreateCloth(cNumVerticesX, cNumVerticesZ, cVertexSpacing, inv_mass, perturbation, SoftBodySharedSettings::EBendType::Dihedral);
|
||||
SoftBodyCreationSettings cloth(cloth_settings, RVec3(5.0f, 5.0f, 0), Quat::sIdentity(), Layers::MOVING);
|
||||
mBodyInterface->CreateAndAddSoftBody(cloth, EActivation::Activate);
|
||||
}
|
||||
|
||||
{
|
||||
random.seed(1234);
|
||||
|
||||
// Cloth with Cosserat rod constraints
|
||||
Ref<SoftBodySharedSettings> cloth_settings = SoftBodyCreator::CreateCloth(cNumVerticesX, cNumVerticesZ, cVertexSpacing, inv_mass, perturbation, SoftBodySharedSettings::EBendType::None);
|
||||
|
||||
// Get rid of created edges, we're replacing them with rods
|
||||
cloth_settings->mEdgeConstraints.clear();
|
||||
|
||||
// Copy of SoftBodyCreator::CreateCloth: Function to get the vertex index of a point on the cloth
|
||||
auto vertex_index = [](uint inX, uint inY)
|
||||
{
|
||||
return inX + inY * cNumVerticesX;
|
||||
};
|
||||
|
||||
// Create bend twist constraints
|
||||
constexpr float cCompliance = 1.0e-5f;
|
||||
auto get_rod = [&constraints = cloth_settings->mRodStretchShearConstraints, vertex_index, cCompliance](uint inX1, uint inZ1, uint inX2, uint inZ2)
|
||||
{
|
||||
uint32 v0 = vertex_index(inX1, inZ1);
|
||||
uint32 v1 = vertex_index(inX2, inZ2);
|
||||
JPH_ASSERT(v0 < v1);
|
||||
|
||||
for (uint i = 0; i < uint(constraints.size()); ++i)
|
||||
if (constraints[i].mVertex[0] == v0 && constraints[i].mVertex[1] == v1)
|
||||
return i;
|
||||
|
||||
constraints.emplace_back(v0, v1, cCompliance);
|
||||
return uint(constraints.size() - 1);
|
||||
};
|
||||
for (uint z = 1; z < cNumVerticesZ - 1; ++z)
|
||||
for (uint x = 0; x < cNumVerticesX - 1; ++x)
|
||||
{
|
||||
if (z > 1 && x < cNumVerticesX - 2)
|
||||
cloth_settings->mRodBendTwistConstraints.emplace_back(get_rod(x, z, x + 1, z), get_rod(x + 1, z, x + 2, z), cCompliance);
|
||||
if (z < cNumVerticesZ - 2)
|
||||
cloth_settings->mRodBendTwistConstraints.emplace_back(get_rod(x, z, x, z + 1), get_rod(x, z + 1, x, z + 2), cCompliance);
|
||||
if (x < cNumVerticesX - 2 && z < cNumVerticesZ - 2)
|
||||
{
|
||||
cloth_settings->mRodBendTwistConstraints.emplace_back(get_rod(x, z, x + 1, z + 1), get_rod(x + 1, z + 1, x + 2, z + 2), cCompliance);
|
||||
cloth_settings->mRodBendTwistConstraints.emplace_back(get_rod(x + 2, z, x + 1, z + 1), get_rod(x + 1, z + 1, x, z + 2), cCompliance);
|
||||
}
|
||||
}
|
||||
cloth_settings->CalculateRodProperties();
|
||||
|
||||
// Optimize the settings
|
||||
cloth_settings->Optimize();
|
||||
SoftBodyCreationSettings cloth(cloth_settings, RVec3(10.0f, 5.0f, 0), Quat::sIdentity(), Layers::MOVING);
|
||||
mBodyInterface->CreateAndAddSoftBody(cloth, EActivation::Activate);
|
||||
}
|
||||
|
||||
{
|
||||
// Create sphere
|
||||
SoftBodyCreationSettings sphere(SoftBodyCreator::CreateSphere(1.0f, 10, 20, SoftBodySharedSettings::EBendType::None), RVec3(-5.0f, 5.0f, 10.0f), Quat::sIdentity(), Layers::MOVING);
|
||||
mBodyInterface->CreateAndAddSoftBody(sphere, EActivation::Activate);
|
||||
}
|
||||
|
||||
{
|
||||
// Create sphere with distance bend constraints
|
||||
SoftBodyCreationSettings sphere(SoftBodyCreator::CreateSphere(1.0f, 10, 20, SoftBodySharedSettings::EBendType::Distance), RVec3(0.0f, 5.0f, 10.0f), Quat::sIdentity(), Layers::MOVING);
|
||||
mBodyInterface->CreateAndAddSoftBody(sphere, EActivation::Activate);
|
||||
}
|
||||
|
||||
{
|
||||
// Create sphere with dihedral bend constraints
|
||||
SoftBodyCreationSettings sphere(SoftBodyCreator::CreateSphere(1.0f, 10, 20, SoftBodySharedSettings::EBendType::Dihedral), RVec3(5.0f, 5.0f, 10.0f), Quat::sIdentity(), Layers::MOVING);
|
||||
mBodyInterface->CreateAndAddSoftBody(sphere, EActivation::Activate);
|
||||
}
|
||||
|
||||
{
|
||||
// Create sphere with Cosserat rod constraints
|
||||
uint cNumTheta = 10;
|
||||
uint cNumPhi = 20;
|
||||
Ref<SoftBodySharedSettings> sphere_settings = SoftBodyCreator::CreateSphere(1.0f, cNumTheta, cNumPhi, SoftBodySharedSettings::EBendType::None);
|
||||
|
||||
// Get rid of created edges, we're replacing them with rods
|
||||
sphere_settings->mEdgeConstraints.clear();
|
||||
|
||||
// Copy of SoftBodyCreator::CreateSphere: Function to get the vertex index of a point on the sphere
|
||||
auto vertex_index = [cNumTheta, cNumPhi](uint inTheta, uint inPhi) -> uint
|
||||
{
|
||||
if (inTheta == 0)
|
||||
return 0;
|
||||
else if (inTheta == cNumTheta - 1)
|
||||
return 1;
|
||||
else
|
||||
return 2 + (inTheta - 1) * cNumPhi + inPhi % cNumPhi;
|
||||
};
|
||||
|
||||
// Create bend twist constraints
|
||||
constexpr float cCompliance = 1.0e-4f;
|
||||
auto get_rod = [&constraints = sphere_settings->mRodStretchShearConstraints, vertex_index, cCompliance](uint inTheta1, uint inPhi1, uint inTheta2, uint inPhi2)
|
||||
{
|
||||
uint32 v0 = vertex_index(inTheta1, inPhi1);
|
||||
uint32 v1 = vertex_index(inTheta2, inPhi2);
|
||||
JPH_ASSERT(v0 != v1);
|
||||
|
||||
for (uint i = 0; i < uint(constraints.size()); ++i)
|
||||
if ((constraints[i].mVertex[0] == v0 && constraints[i].mVertex[1] == v1)
|
||||
|| (constraints[i].mVertex[0] == v1 && constraints[i].mVertex[1] == v0))
|
||||
return i;
|
||||
|
||||
constraints.emplace_back(v0, v1, cCompliance);
|
||||
return uint(constraints.size() - 1);
|
||||
};
|
||||
|
||||
// Rings along the side
|
||||
for (uint phi = 0; phi < cNumPhi; ++phi)
|
||||
for (uint theta = 0; theta < cNumTheta - 1; ++theta)
|
||||
{
|
||||
if (theta < cNumTheta - 2)
|
||||
sphere_settings->mRodBendTwistConstraints.emplace_back(get_rod(theta, phi, theta + 1, phi), get_rod(theta + 1, phi, theta + 2, phi), cCompliance);
|
||||
if (theta > 0 && phi < cNumPhi - 1)
|
||||
sphere_settings->mRodBendTwistConstraints.emplace_back(get_rod(theta, phi, theta, phi + 1), get_rod(theta, phi + 1, theta, (phi + 2) % cNumPhi), cCompliance);
|
||||
}
|
||||
|
||||
// Close the caps
|
||||
for (uint phi1 = 0, phi2 = cNumPhi / 2; phi1 < cNumPhi / 2; ++phi1, phi2 = (phi2 + 1) % cNumPhi)
|
||||
{
|
||||
sphere_settings->mRodBendTwistConstraints.emplace_back(get_rod(0, phi1, 1, phi1), get_rod(0, phi2, 1, phi2), cCompliance);
|
||||
sphere_settings->mRodBendTwistConstraints.emplace_back(get_rod(cNumTheta - 2, phi1, cNumTheta - 1, phi1), get_rod(cNumTheta - 2, phi2, cNumTheta - 1, phi2), cCompliance);
|
||||
}
|
||||
|
||||
sphere_settings->CalculateRodProperties();
|
||||
|
||||
// Optimize the settings
|
||||
sphere_settings->Optimize();
|
||||
SoftBodyCreationSettings sphere(sphere_settings, RVec3(10.0f, 5.0f, 10.0f), Quat::sIdentity(), Layers::MOVING);
|
||||
mBodyInterface->CreateAndAddSoftBody(sphere, EActivation::Activate);
|
||||
}
|
||||
}
|
||||
|
||||
void SoftBodyBendConstraintTest::PrePhysicsUpdate(const PreUpdateParams &inParams)
|
||||
{
|
||||
mDebugRenderer->DrawText3D(RVec3(-5.0f, 7.5f, 0), "No bend constraints", Color::sWhite);
|
||||
mDebugRenderer->DrawText3D(RVec3(0.0f, 7.5f, 0), "Distance bend constraints", Color::sWhite);
|
||||
mDebugRenderer->DrawText3D(RVec3(5.0f, 7.5f, 0), "Dihedral angle bend constraints", Color::sWhite);
|
||||
mDebugRenderer->DrawText3D(RVec3(10.0f, 7.5f, 0), "Cosserat rod constraints", Color::sWhite);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
|
||||
class SoftBodyBendConstraintTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, SoftBodyBendConstraintTest)
|
||||
|
||||
// Description of the test
|
||||
virtual const char * GetDescription() const override
|
||||
{
|
||||
return "Shows the effect of bend constraint type in a soft body.";
|
||||
}
|
||||
|
||||
// See: Test
|
||||
virtual void Initialize() override;
|
||||
virtual void PrePhysicsUpdate(const PreUpdateParams &inParams) override;
|
||||
|
||||
private:
|
||||
// Size and spacing of the cloth
|
||||
static constexpr int cNumVerticesX = 10;
|
||||
static constexpr int cNumVerticesZ = 10;
|
||||
static constexpr float cVertexSpacing = 0.5f;
|
||||
};
|
||||
@@ -0,0 +1,158 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/SoftBody/SoftBodyContactListenerTest.h>
|
||||
#include <Jolt/Physics/Body/BodyCreationSettings.h>
|
||||
#include <Jolt/Physics/SoftBody/SoftBodyCreationSettings.h>
|
||||
#include <Jolt/Physics/SoftBody/SoftBodyManifold.h>
|
||||
#include <Jolt/Physics/Collision/Shape/SphereShape.h>
|
||||
#include <Utils/SoftBodyCreator.h>
|
||||
#include <Renderer/DebugRendererImp.h>
|
||||
#include <Layers.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(SoftBodyContactListenerTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(SoftBodyContactListenerTest, Test)
|
||||
}
|
||||
|
||||
void SoftBodyContactListenerTest::Initialize()
|
||||
{
|
||||
// Install contact listener for soft bodies
|
||||
mPhysicsSystem->SetSoftBodyContactListener(this);
|
||||
|
||||
// Floor
|
||||
CreateFloor();
|
||||
|
||||
// Start the 1st cycle
|
||||
StartCycle();
|
||||
}
|
||||
|
||||
void SoftBodyContactListenerTest::UpdateLabel()
|
||||
{
|
||||
// Draw current state
|
||||
const char *cycle_names[] = { "Accept contact", "Sphere 10x mass", "Cloth 10x mass", "Sphere infinite mass", "Cloth infinite mass", "Sensor contact", "Reject contact", "Kinematic Sphere", "Kinematic Sphere, cloth infinite mass", "Kinematic sphere, sensor contact", "Kinematic Sphere, reject contact" };
|
||||
SetBodyLabel(mOtherBodyID, cycle_names[mCycle]);
|
||||
}
|
||||
|
||||
void SoftBodyContactListenerTest::PrePhysicsUpdate(const PreUpdateParams &inParams)
|
||||
{
|
||||
mTime += inParams.mDeltaTime;
|
||||
if (mTime > 2.5f)
|
||||
{
|
||||
// Next cycle
|
||||
mCycle = (mCycle + 1) % 10;
|
||||
mTime = 0.0f;
|
||||
|
||||
// Remove the old scene
|
||||
mBodyInterface->RemoveBody(mOtherBodyID);
|
||||
mBodyInterface->DestroyBody(mOtherBodyID);
|
||||
mBodyInterface->RemoveBody(mSoftBodyID);
|
||||
mBodyInterface->DestroyBody(mSoftBodyID);
|
||||
|
||||
// Start the new
|
||||
StartCycle();
|
||||
}
|
||||
|
||||
UpdateLabel();
|
||||
}
|
||||
|
||||
void SoftBodyContactListenerTest::StartCycle()
|
||||
{
|
||||
// Create the cloth
|
||||
Ref<SoftBodySharedSettings> cloth_settings = SoftBodyCreator::CreateClothWithFixatedCorners(15, 15, 0.75f);
|
||||
|
||||
// Create cloth that's fixated at the corners
|
||||
SoftBodyCreationSettings cloth(cloth_settings, RVec3(0, 5, 0), Quat::sRotation(Vec3::sAxisY(), 0.25f * JPH_PI), Layers::MOVING);
|
||||
cloth.mUpdatePosition = false; // Don't update the position of the cloth as it is fixed to the world
|
||||
cloth.mMakeRotationIdentity = false; // Test explicitly checks if soft bodies with a rotation collide with shapes properly
|
||||
mSoftBodyID = mBodyInterface->CreateAndAddSoftBody(cloth, EActivation::Activate);
|
||||
|
||||
// If we want a kinematic sphere
|
||||
bool kinematic = mCycle > 6;
|
||||
|
||||
// Create sphere
|
||||
BodyCreationSettings bcs(new SphereShape(1.0f), RVec3(0, 7, 0), Quat::sIdentity(), kinematic? EMotionType::Kinematic : EMotionType::Dynamic, Layers::MOVING);
|
||||
bcs.mOverrideMassProperties = EOverrideMassProperties::CalculateInertia;
|
||||
bcs.mMassPropertiesOverride.mMass = 100.0f;
|
||||
if (kinematic)
|
||||
bcs.mLinearVelocity = Vec3(0, -2.5f, 0);
|
||||
mOtherBodyID = mBodyInterface->CreateAndAddBody(bcs, EActivation::Activate);
|
||||
|
||||
UpdateLabel();
|
||||
}
|
||||
|
||||
SoftBodyValidateResult SoftBodyContactListenerTest::OnSoftBodyContactValidate(const Body &inSoftBody, const Body &inOtherBody, SoftBodyContactSettings &ioSettings)
|
||||
{
|
||||
switch (mCycle)
|
||||
{
|
||||
case 0:
|
||||
// Normal
|
||||
return SoftBodyValidateResult::AcceptContact;
|
||||
|
||||
case 1:
|
||||
// Makes the sphere 10x as heavy
|
||||
ioSettings.mInvMassScale2 = 0.1f;
|
||||
ioSettings.mInvInertiaScale2 = 0.1f;
|
||||
return SoftBodyValidateResult::AcceptContact;
|
||||
|
||||
case 2:
|
||||
// Makes the cloth 10x as heavy
|
||||
ioSettings.mInvMassScale1 = 0.1f;
|
||||
return SoftBodyValidateResult::AcceptContact;
|
||||
|
||||
case 3:
|
||||
// Makes the sphere have infinite mass
|
||||
ioSettings.mInvMassScale2 = 0.0f;
|
||||
ioSettings.mInvInertiaScale2 = 0.0f;
|
||||
return SoftBodyValidateResult::AcceptContact;
|
||||
|
||||
case 4:
|
||||
// Makes the cloth have infinite mass
|
||||
ioSettings.mInvMassScale1 = 0.0f;
|
||||
return SoftBodyValidateResult::AcceptContact;
|
||||
|
||||
case 5:
|
||||
// Sensor contact
|
||||
ioSettings.mIsSensor = true;
|
||||
return SoftBodyValidateResult::AcceptContact;
|
||||
|
||||
case 6:
|
||||
// No contacts
|
||||
return SoftBodyValidateResult::RejectContact;
|
||||
|
||||
case 7:
|
||||
// Kinematic sphere
|
||||
return SoftBodyValidateResult::AcceptContact;
|
||||
|
||||
case 8:
|
||||
// Kinematic sphere, cloth infinite mass
|
||||
ioSettings.mInvMassScale1 = 0.0f;
|
||||
return SoftBodyValidateResult::AcceptContact;
|
||||
|
||||
case 9:
|
||||
// Kinematic sphere, sensor contact
|
||||
ioSettings.mIsSensor = true;
|
||||
return SoftBodyValidateResult::AcceptContact;
|
||||
|
||||
default:
|
||||
// No contacts
|
||||
return SoftBodyValidateResult::RejectContact;
|
||||
}
|
||||
}
|
||||
|
||||
void SoftBodyContactListenerTest::OnSoftBodyContactAdded(const Body &inSoftBody, const SoftBodyManifold &inManifold)
|
||||
{
|
||||
// Draw contacts
|
||||
RMat44 com = inSoftBody.GetCenterOfMassTransform();
|
||||
for (const SoftBodyVertex &vertex : inManifold.GetVertices())
|
||||
if (inManifold.HasContact(vertex))
|
||||
{
|
||||
RVec3 position = com * inManifold.GetLocalContactPoint(vertex);
|
||||
Vec3 normal = inManifold.GetContactNormal(vertex);
|
||||
mDebugRenderer->DrawMarker(position, Color::sRed, 0.1f);
|
||||
mDebugRenderer->DrawArrow(position, position + normal, Color::sGreen, 0.1f);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
#include <Jolt/Physics/SoftBody/SoftBodyContactListener.h>
|
||||
|
||||
class SoftBodyContactListenerTest : public Test, public SoftBodyContactListener
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, SoftBodyContactListenerTest)
|
||||
|
||||
// Description of the test
|
||||
virtual const char * GetDescription() const override
|
||||
{
|
||||
return "Shows how to use contact listeners for soft bodies to affect the simulation.";
|
||||
}
|
||||
|
||||
// See: Test
|
||||
virtual void Initialize() override;
|
||||
virtual void PrePhysicsUpdate(const PreUpdateParams &inParams) override;
|
||||
virtual void GetInitialCamera(CameraState &ioState) const override { ioState.mPos = RVec3(15, 10, 15); }
|
||||
|
||||
// Test is not deterministic as it creates/removes bodies in a way that's not compatible with the determinism check
|
||||
virtual bool IsDeterministic() const override { return false; }
|
||||
|
||||
// See: SoftBodyContactListener
|
||||
virtual SoftBodyValidateResult OnSoftBodyContactValidate(const Body &inSoftBody, const Body &inOtherBody, SoftBodyContactSettings &ioSettings) override;
|
||||
virtual void OnSoftBodyContactAdded(const Body &inSoftBody, const SoftBodyManifold &inManifold) override;
|
||||
|
||||
private:
|
||||
void UpdateLabel();
|
||||
|
||||
void StartCycle();
|
||||
|
||||
float mTime = 0.0f;
|
||||
int mCycle = 0;
|
||||
BodyID mSoftBodyID;
|
||||
BodyID mOtherBodyID;
|
||||
};
|
||||
@@ -0,0 +1,186 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2025 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/SoftBody/SoftBodyCosseratRodConstraintTest.h>
|
||||
#include <Jolt/Physics/SoftBody/SoftBodyCreationSettings.h>
|
||||
#include <Jolt/Physics/SoftBody/SoftBodyMotionProperties.h>
|
||||
#include <Utils/SoftBodyCreator.h>
|
||||
#include <Layers.h>
|
||||
#include <Renderer/DebugRendererImp.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(SoftBodyCosseratRodConstraintTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(SoftBodyCosseratRodConstraintTest, Test)
|
||||
}
|
||||
|
||||
void SoftBodyCosseratRodConstraintTest::Initialize()
|
||||
{
|
||||
CreateFloor();
|
||||
|
||||
// Create a hanging helix
|
||||
{
|
||||
constexpr float cRadius = 0.5f;
|
||||
constexpr int cNumVertices = 128;
|
||||
constexpr float cHeight = 5.0f;
|
||||
constexpr float cNumCycles = 10;
|
||||
|
||||
Ref<SoftBodySharedSettings> helix_settings = new SoftBodySharedSettings;
|
||||
for (int i = 0; i < cNumVertices; ++i)
|
||||
{
|
||||
float fraction = float(i) / (cNumVertices - 1);
|
||||
|
||||
SoftBodySharedSettings::Vertex v;
|
||||
float alpha = cNumCycles * 2.0f * JPH_PI * fraction;
|
||||
v.mPosition = Float3(cRadius * Sin(alpha), 0.5f * (1.0f - fraction * cHeight), cRadius * Cos(alpha));
|
||||
v.mInvMass = i == 0? 0.0f : 1.0e-2f;
|
||||
helix_settings->mVertices.push_back(v);
|
||||
|
||||
if (i > 0)
|
||||
helix_settings->mRodStretchShearConstraints.push_back(SoftBodySharedSettings::RodStretchShear(i - 1, i));
|
||||
|
||||
if (i > 1)
|
||||
helix_settings->mRodBendTwistConstraints.push_back(SoftBodySharedSettings::RodBendTwist(i - 2, i - 1));
|
||||
}
|
||||
|
||||
helix_settings->CalculateRodProperties();
|
||||
helix_settings->Optimize();
|
||||
|
||||
SoftBodyCreationSettings helix(helix_settings, RVec3(0, 10, 0), Quat::sIdentity(), Layers::MOVING);
|
||||
mSoftBodies.push_back(mBodyInterface->CreateAndAddSoftBody(helix, EActivation::Activate));
|
||||
}
|
||||
|
||||
// Create a tree with a static root
|
||||
{
|
||||
// Root particle
|
||||
Ref<SoftBodySharedSettings> tree_settings = new SoftBodySharedSettings;
|
||||
SoftBodySharedSettings::Vertex v;
|
||||
v.mPosition = Float3(0, 0, 0);
|
||||
v.mInvMass = 0.0f;
|
||||
tree_settings->mVertices.push_back(v);
|
||||
|
||||
// Create branches
|
||||
struct Branch
|
||||
{
|
||||
uint32 mPreviousVertex;
|
||||
uint32 mPreviousRod;
|
||||
Vec3 mDirection;
|
||||
uint32 mDepth;
|
||||
};
|
||||
Array<Branch> branches;
|
||||
branches.push_back({ 0, uint32(-1), Vec3::sAxisY(), 0 });
|
||||
while (!branches.empty())
|
||||
{
|
||||
// Take the next branch
|
||||
Branch branch = branches.front();
|
||||
branches.erase(branches.begin());
|
||||
|
||||
// Create vertex
|
||||
SoftBodySharedSettings::Vertex &previous_vertex = tree_settings->mVertices[branch.mPreviousVertex];
|
||||
(Vec3(previous_vertex.mPosition) + branch.mDirection).StoreFloat3(&v.mPosition);
|
||||
v.mInvMass = branch.mDepth > 0? 2.0f * previous_vertex.mInvMass : 1.0e-3f;
|
||||
uint32 new_vertex = uint32(tree_settings->mVertices.size());
|
||||
tree_settings->mVertices.push_back(v);
|
||||
|
||||
// Create rod
|
||||
uint32 new_rod = uint32(tree_settings->mRodStretchShearConstraints.size());
|
||||
tree_settings->mRodStretchShearConstraints.push_back(SoftBodySharedSettings::RodStretchShear(branch.mPreviousVertex, new_vertex));
|
||||
if (branch.mPreviousRod != uint32(-1))
|
||||
tree_settings->mRodBendTwistConstraints.push_back(SoftBodySharedSettings::RodBendTwist(branch.mPreviousRod, new_rod));
|
||||
|
||||
// Create sub branches
|
||||
if (branch.mDepth < 10)
|
||||
for (uint32 i = 0; i < 2; ++i)
|
||||
{
|
||||
// Determine new child direction
|
||||
float angle = DegreesToRadians(-15.0f + i * 30.0f);
|
||||
Vec3 new_direction = Quat::sRotation(branch.mDepth & 1? Vec3::sAxisZ() : Vec3::sAxisX(), angle) * branch.mDirection;
|
||||
|
||||
// Create new branch
|
||||
branches.push_back({ new_vertex, new_rod, new_direction, branch.mDepth + 1 });
|
||||
}
|
||||
}
|
||||
|
||||
tree_settings->CalculateRodProperties();
|
||||
tree_settings->Optimize();
|
||||
|
||||
SoftBodyCreationSettings tree(tree_settings, RVec3(10, 0, 0), Quat::sIdentity(), Layers::MOVING);
|
||||
mSoftBodies.push_back(mBodyInterface->CreateAndAddSoftBody(tree, EActivation::Activate));
|
||||
}
|
||||
|
||||
// Create a weed like structure
|
||||
{
|
||||
// Root particle
|
||||
Ref<SoftBodySharedSettings> weed_settings = new SoftBodySharedSettings;
|
||||
|
||||
constexpr int cNumVertices = 64;
|
||||
constexpr int cNumStrands = 50;
|
||||
|
||||
default_random_engine random;
|
||||
uniform_real_distribution<float> radius_distribution(0, 1.0f);
|
||||
uniform_real_distribution<float> phase_distribution(0, 2.0f * JPH_PI);
|
||||
|
||||
for (int strand = 0; strand < cNumStrands; ++strand)
|
||||
{
|
||||
// Place at a random location
|
||||
float radius = radius_distribution(random);
|
||||
float theta = phase_distribution(random);
|
||||
Vec3 root_pos = Vec3(radius * Sin(theta), 0, radius * Cos(theta));
|
||||
|
||||
// Randomize the phase of the wave
|
||||
float phase1 = phase_distribution(random);
|
||||
float phase2 = phase_distribution(random);
|
||||
|
||||
uint32 first_vertex = uint32(weed_settings->mVertices.size());
|
||||
for (int i = 0; i < cNumVertices; ++i)
|
||||
{
|
||||
// Generate a wavy pattern
|
||||
float amplitude = 0.1f * Sin(phase1 + i * 2.0f * JPH_PI / 8);
|
||||
Vec3 pos = root_pos + Vec3(Sin(phase2) * amplitude, 0.1f * i, Cos(phase2) * amplitude);
|
||||
|
||||
SoftBodySharedSettings::Vertex v;
|
||||
pos.StoreFloat3(&v.mPosition);
|
||||
v.mInvMass = i == 0? 0.0f : 0.1f;
|
||||
weed_settings->mVertices.push_back(v);
|
||||
}
|
||||
|
||||
uint32 first_rod = uint32(weed_settings->mRodStretchShearConstraints.size());
|
||||
for (int i = 0; i < cNumVertices - 1; ++i)
|
||||
weed_settings->mRodStretchShearConstraints.push_back(SoftBodySharedSettings::RodStretchShear(first_vertex + i, first_vertex + i + 1));
|
||||
|
||||
for (int i = 0; i < cNumVertices - 2; ++i)
|
||||
weed_settings->mRodBendTwistConstraints.push_back(SoftBodySharedSettings::RodBendTwist(first_rod + i, first_rod + i + 1));
|
||||
}
|
||||
|
||||
weed_settings->CalculateRodProperties();
|
||||
weed_settings->Optimize();
|
||||
|
||||
SoftBodyCreationSettings weed(weed_settings, RVec3(20, 0, 0), Quat::sIdentity(), Layers::MOVING);
|
||||
weed.mGravityFactor = 0.8f;
|
||||
mSoftBodies.push_back(mBodyInterface->CreateAndAddSoftBody(weed, EActivation::Activate));
|
||||
}
|
||||
}
|
||||
|
||||
void SoftBodyCosseratRodConstraintTest::PrePhysicsUpdate(const PreUpdateParams &inParams)
|
||||
{
|
||||
// Draw the soft body rods
|
||||
for (BodyID id : mSoftBodies)
|
||||
{
|
||||
BodyLockRead lock(mPhysicsSystem->GetBodyLockInterface(), id);
|
||||
if (lock.Succeeded())
|
||||
{
|
||||
const Body &body = lock.GetBody();
|
||||
const SoftBodyMotionProperties *mp = static_cast<const SoftBodyMotionProperties *>(body.GetMotionProperties());
|
||||
RMat44 com = body.GetCenterOfMassTransform();
|
||||
|
||||
for (const SoftBodySharedSettings::RodStretchShear &r : mp->GetSettings()->mRodStretchShearConstraints)
|
||||
{
|
||||
RVec3 x0 = com * mp->GetVertex(r.mVertex[0]).mPosition;
|
||||
RVec3 x1 = com * mp->GetVertex(r.mVertex[1]).mPosition;
|
||||
mDebugRenderer->DrawLine(x0, x1, Color::sWhite);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2025 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
|
||||
class SoftBodyCosseratRodConstraintTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, SoftBodyCosseratRodConstraintTest)
|
||||
|
||||
// Description of the test
|
||||
virtual const char * GetDescription() const override
|
||||
{
|
||||
return "Shows the effect of Cosserat rod constraints in a soft body that control bend, twist and shear between particles.";
|
||||
}
|
||||
|
||||
// See: Test
|
||||
virtual void Initialize() override;
|
||||
virtual void PrePhysicsUpdate(const PreUpdateParams &inParams) override;
|
||||
|
||||
private:
|
||||
BodyIDVector mSoftBodies;
|
||||
};
|
||||
@@ -0,0 +1,49 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/SoftBody/SoftBodyCustomUpdateTest.h>
|
||||
#include <Jolt/Physics/SoftBody/SoftBodyCreationSettings.h>
|
||||
#include <Jolt/Physics/SoftBody/SoftBodyMotionProperties.h>
|
||||
#include <Utils/SoftBodyCreator.h>
|
||||
#include <Layers.h>
|
||||
#include <Renderer/DebugRendererImp.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(SoftBodyCustomUpdateTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(SoftBodyCustomUpdateTest, Test)
|
||||
}
|
||||
|
||||
void SoftBodyCustomUpdateTest::Initialize()
|
||||
{
|
||||
// Floor
|
||||
CreateFloor();
|
||||
|
||||
// Create a body but do not add it to the physics system (we're updating it ourselves)
|
||||
SoftBodyCreationSettings sphere(SoftBodyCreator::CreateSphere(), RVec3(0, 5, 0), Quat::sIdentity(), Layers::MOVING);
|
||||
sphere.mPressure = 2000.0f;
|
||||
mBody = mBodyInterface->CreateSoftBody(sphere);
|
||||
}
|
||||
|
||||
void SoftBodyCustomUpdateTest::PrePhysicsUpdate(const PreUpdateParams &inParams)
|
||||
{
|
||||
// Note that passing a variable delta time results in differences in behavior, usually you want to have a fixed time step.
|
||||
// For this demo we'll just clamp the delta time to 1/60th of a second and allow behavioral changes due to frame rate fluctuations.
|
||||
float dt = min(inParams.mDeltaTime, 1.0f / 60.0f);
|
||||
|
||||
// Call the update now
|
||||
SoftBodyMotionProperties *mp = static_cast<SoftBodyMotionProperties *>(mBody->GetMotionProperties());
|
||||
mp->CustomUpdate(dt, *mBody, *mPhysicsSystem);
|
||||
|
||||
#ifdef JPH_DEBUG_RENDERER
|
||||
// Draw it as well since it's not added to the world
|
||||
mBody->GetShape()->Draw(mDebugRenderer, mBody->GetCenterOfMassTransform(), Vec3::sOne(), Color::sWhite, false, false);
|
||||
#else
|
||||
// Draw the vertices
|
||||
RMat44 com = mBody->GetCenterOfMassTransform();
|
||||
for (const SoftBodyVertex &v : mp->GetVertices())
|
||||
mDebugRenderer->DrawMarker(com * v.mPosition, Color::sRed, 0.1f);
|
||||
#endif // JPH_DEBUG_RENDERER
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
|
||||
class SoftBodyCustomUpdateTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, SoftBodyCustomUpdateTest)
|
||||
|
||||
// Description of the test
|
||||
virtual const char *GetDescription() const override
|
||||
{
|
||||
return "Shows how you can update a soft body outside of the main physics simulation step.";
|
||||
}
|
||||
|
||||
// See: Test
|
||||
virtual void Initialize() override;
|
||||
virtual void PrePhysicsUpdate(const PreUpdateParams &inParams) override;
|
||||
|
||||
private:
|
||||
Body * mBody;
|
||||
};
|
||||
@@ -0,0 +1,59 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/SoftBody/SoftBodyForceTest.h>
|
||||
#include <Jolt/Physics/Body/BodyCreationSettings.h>
|
||||
#include <Jolt/Physics/SoftBody/SoftBodyCreationSettings.h>
|
||||
#include <Utils/SoftBodyCreator.h>
|
||||
#include <Renderer/DebugRendererImp.h>
|
||||
#include <External/Perlin.h>
|
||||
#include <Layers.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(SoftBodyForceTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(SoftBodyForceTest, Test)
|
||||
}
|
||||
|
||||
void SoftBodyForceTest::Initialize()
|
||||
{
|
||||
CreateFloor();
|
||||
|
||||
static constexpr uint cGridSize = 30;
|
||||
|
||||
// Create hanging cloth
|
||||
auto inv_mass = [](uint inX, uint inZ) {
|
||||
return (inX == 0 && inZ == 0)
|
||||
|| (inX == cGridSize - 1 && inZ == 0)? 0.0f : 1.0f;
|
||||
};
|
||||
SoftBodyCreationSettings cloth(SoftBodyCreator::CreateCloth(cGridSize, cGridSize, 0.75f, inv_mass), RVec3(0, 15.0f, 0), Quat::sRotation(Vec3::sAxisX(), 0.5f * JPH_PI), Layers::MOVING);
|
||||
mBodyID = mBodyInterface->CreateAndAddSoftBody(cloth, EActivation::Activate);
|
||||
}
|
||||
|
||||
void SoftBodyForceTest::PrePhysicsUpdate(const PreUpdateParams &inParams)
|
||||
{
|
||||
mTime += inParams.mDeltaTime;
|
||||
|
||||
// Apply a fluctuating force
|
||||
constexpr float cMaxForce = 10000.0f;
|
||||
constexpr float cMaxAngle = DegreesToRadians(90.0f);
|
||||
Vec3 force(0, 0, 0.5f * cMaxForce * (1.0f + PerlinNoise3(0, 0, mTime / 2.0f, 256, 256, 256)));
|
||||
force = Mat44::sRotationY(cMaxAngle * PerlinNoise3(mTime / 10.0f, 0, 0, 256, 256, 256)) * force;
|
||||
mBodyInterface->AddForce(mBodyID, force);
|
||||
|
||||
// Draw the force
|
||||
RVec3 offset(0, 10, 0);
|
||||
DebugRenderer::sInstance->DrawArrow(offset, offset + 10.0f * force.Normalized(), Color::sGreen, 0.1f);
|
||||
}
|
||||
|
||||
void SoftBodyForceTest::SaveState(StateRecorder &inStream) const
|
||||
{
|
||||
inStream.Write(mTime);
|
||||
}
|
||||
|
||||
void SoftBodyForceTest::RestoreState(StateRecorder &inStream)
|
||||
{
|
||||
inStream.Read(mTime);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
|
||||
class SoftBodyForceTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, SoftBodyForceTest)
|
||||
|
||||
// Description of the test
|
||||
virtual const char *GetDescription() const override
|
||||
{
|
||||
return "Shows how to apply a global force to a soft body.";
|
||||
}
|
||||
|
||||
// See: Test
|
||||
virtual void Initialize() override;
|
||||
virtual void PrePhysicsUpdate(const PreUpdateParams &inParams) override;
|
||||
virtual void SaveState(StateRecorder &inStream) const override;
|
||||
virtual void RestoreState(StateRecorder &inStream) override;
|
||||
|
||||
private:
|
||||
float mTime = 0.0f;
|
||||
BodyID mBodyID;
|
||||
};
|
||||
@@ -0,0 +1,50 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2023 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/SoftBody/SoftBodyFrictionTest.h>
|
||||
#include <Jolt/Physics/SoftBody/SoftBodyCreationSettings.h>
|
||||
#include <Utils/SoftBodyCreator.h>
|
||||
#include <Layers.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(SoftBodyFrictionTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(SoftBodyFrictionTest, Test)
|
||||
}
|
||||
|
||||
void SoftBodyFrictionTest::Initialize()
|
||||
{
|
||||
// Floor
|
||||
Body &floor = CreateFloor();
|
||||
floor.SetFriction(1.0f);
|
||||
|
||||
// Bodies with increasing friction
|
||||
Ref<SoftBodySharedSettings> sphere_settings = SoftBodyCreator::CreateSphere();
|
||||
for (SoftBodySharedSettings::Vertex &v : sphere_settings->mVertices)
|
||||
v.mVelocity = Float3(0, 0, 10);
|
||||
SoftBodyCreationSettings sphere(sphere_settings, RVec3::sZero(), Quat::sIdentity(), Layers::MOVING);
|
||||
sphere.mPressure = 2000.0f;
|
||||
|
||||
for (int i = 0; i <= 10; ++i)
|
||||
{
|
||||
sphere.mPosition = RVec3(-50.0f + i * 10.0f, 1.0f, 0);
|
||||
sphere.mFriction = 0.1f * i;
|
||||
BodyID id = mBodyInterface->CreateAndAddSoftBody(sphere, EActivation::Activate);
|
||||
SetBodyLabel(id, StringFormat("Friction: %.1f", double(sphere.mFriction)));
|
||||
}
|
||||
|
||||
Ref<SoftBodySharedSettings> cube_settings = SoftBodySharedSettings::sCreateCube(5, 0.5f);
|
||||
for (SoftBodySharedSettings::Vertex &v : cube_settings->mVertices)
|
||||
v.mVelocity = Float3(0, 0, 10);
|
||||
SoftBodyCreationSettings cube(cube_settings, RVec3::sZero(), Quat::sIdentity(), Layers::MOVING);
|
||||
|
||||
for (int i = 0; i <= 10; ++i)
|
||||
{
|
||||
cube.mPosition = RVec3(-50.0f + i * 10.0f, 1.0f, -5.0f);
|
||||
cube.mFriction = 0.1f * i;
|
||||
BodyID id = mBodyInterface->CreateAndAddSoftBody(cube, EActivation::Activate);
|
||||
SetBodyLabel(id, StringFormat("Friction: %.1f", double(cube.mFriction)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2023 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
|
||||
class SoftBodyFrictionTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, SoftBodyFrictionTest)
|
||||
|
||||
// Description of the test
|
||||
virtual const char *GetDescription() const override
|
||||
{
|
||||
return "Tests soft bodies with various values for friction. Note that this has very little effect.";
|
||||
}
|
||||
|
||||
// See: Test
|
||||
virtual void Initialize() override;
|
||||
};
|
||||
@@ -0,0 +1,43 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2023 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/SoftBody/SoftBodyGravityFactorTest.h>
|
||||
#include <Jolt/Physics/SoftBody/SoftBodyCreationSettings.h>
|
||||
#include <Utils/SoftBodyCreator.h>
|
||||
#include <Layers.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(SoftBodyGravityFactorTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(SoftBodyGravityFactorTest, Test)
|
||||
}
|
||||
|
||||
void SoftBodyGravityFactorTest::Initialize()
|
||||
{
|
||||
// Floor
|
||||
CreateFloor();
|
||||
|
||||
// Bodies with increasing gravity factor
|
||||
SoftBodyCreationSettings sphere(SoftBodyCreator::CreateSphere(), RVec3::sZero(), Quat::sIdentity(), Layers::MOVING);
|
||||
sphere.mPressure = 2000.0f;
|
||||
|
||||
for (int i = 0; i <= 10; ++i)
|
||||
{
|
||||
sphere.mPosition = RVec3(-50.0f + i * 10.0f, 10.0f, 0);
|
||||
sphere.mGravityFactor = 0.1f * i;
|
||||
BodyID id = mBodyInterface->CreateAndAddSoftBody(sphere, EActivation::Activate);
|
||||
SetBodyLabel(id, StringFormat("GravityFactor: %.1f", double(sphere.mGravityFactor)));
|
||||
}
|
||||
|
||||
SoftBodyCreationSettings cube(SoftBodySharedSettings::sCreateCube(5, 0.5f), RVec3::sZero(), Quat::sIdentity(), Layers::MOVING);
|
||||
|
||||
for (int i = 0; i <= 10; ++i)
|
||||
{
|
||||
cube.mPosition = RVec3(-50.0f + i * 10.0f, 10.0f, -5.0f);
|
||||
cube.mGravityFactor = 0.1f * i;
|
||||
BodyID id = mBodyInterface->CreateAndAddSoftBody(cube, EActivation::Activate);
|
||||
SetBodyLabel(id, StringFormat("GravityFactor: %.1f", double(cube.mGravityFactor)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2023 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
|
||||
class SoftBodyGravityFactorTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, SoftBodyGravityFactorTest)
|
||||
|
||||
// Description of the test
|
||||
virtual const char *GetDescription() const override
|
||||
{
|
||||
return "Shows soft bodies with various gravity factor values.";
|
||||
}
|
||||
|
||||
// See: Test
|
||||
virtual void Initialize() override;
|
||||
};
|
||||
@@ -0,0 +1,46 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2023 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/SoftBody/SoftBodyKinematicTest.h>
|
||||
#include <Jolt/Physics/SoftBody/SoftBodyCreationSettings.h>
|
||||
#include <Jolt/Physics/SoftBody/SoftBodyMotionProperties.h>
|
||||
#include <Utils/SoftBodyCreator.h>
|
||||
#include <Layers.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(SoftBodyKinematicTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(SoftBodyKinematicTest, Test)
|
||||
}
|
||||
|
||||
void SoftBodyKinematicTest::Initialize()
|
||||
{
|
||||
// Floor
|
||||
CreateFloor();
|
||||
|
||||
// A sphere
|
||||
Ref<SoftBodySharedSettings> sphere_settings = SoftBodyCreator::CreateSphere();
|
||||
sphere_settings->mVertices[0].mInvMass = 0.0f;
|
||||
sphere_settings->mVertices[0].mVelocity = Float3(0, 0, 5);
|
||||
SoftBodyCreationSettings sphere(sphere_settings, RVec3(0, 5, 0), Quat::sIdentity(), Layers::MOVING);
|
||||
sphere.mPressure = 2000.0f;
|
||||
mSphereID = mBodyInterface->CreateAndAddSoftBody(sphere, EActivation::Activate);
|
||||
}
|
||||
|
||||
void SoftBodyKinematicTest::PrePhysicsUpdate(const PreUpdateParams &inParams)
|
||||
{
|
||||
// Update the velocity of the first vertex
|
||||
BodyLockWrite body_lock(mPhysicsSystem->GetBodyLockInterface(), mSphereID);
|
||||
if (body_lock.Succeeded())
|
||||
{
|
||||
Body &body = body_lock.GetBody();
|
||||
SoftBodyMotionProperties *mp = static_cast<SoftBodyMotionProperties *>(body.GetMotionProperties());
|
||||
RVec3 com = body.GetCenterOfMassPosition();
|
||||
if (com.GetZ() >= 10.0f)
|
||||
mp->GetVertex(0).mVelocity = Vec3(0, 0, -5);
|
||||
else if (com.GetZ() <= -10.0f)
|
||||
mp->GetVertex(0).mVelocity = Vec3(0, 0, 5);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2023 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
|
||||
class SoftBodyKinematicTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, SoftBodyKinematicTest)
|
||||
|
||||
// Description of the test
|
||||
virtual const char *GetDescription() const override
|
||||
{
|
||||
return "Shows how to make a soft body vertex kinematic and control it.";
|
||||
}
|
||||
|
||||
// See: Test
|
||||
virtual void Initialize() override;
|
||||
virtual void PrePhysicsUpdate(const PreUpdateParams &inParams) override;
|
||||
|
||||
private:
|
||||
BodyID mSphereID;
|
||||
};
|
||||
@@ -0,0 +1,42 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/SoftBody/SoftBodyLRAConstraintTest.h>
|
||||
#include <Jolt/Physics/SoftBody/SoftBodyCreationSettings.h>
|
||||
#include <Utils/SoftBodyCreator.h>
|
||||
#include <Layers.h>
|
||||
#include <Renderer/DebugRendererImp.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(SoftBodyLRAConstraintTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(SoftBodyLRAConstraintTest, Test)
|
||||
}
|
||||
|
||||
void SoftBodyLRAConstraintTest::Initialize()
|
||||
{
|
||||
CreateFloor();
|
||||
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
auto inv_mass = [](uint, uint inZ) { return inZ == 0? 0.0f : 1.0f; };
|
||||
auto perturbation = [](uint, uint) { return Vec3::sZero(); };
|
||||
|
||||
SoftBodySharedSettings::VertexAttributes va;
|
||||
va.mShearCompliance = va.mCompliance = 1.0e-3f; // Soften the edges a bit so that the effect of the LRA constraints is more visible
|
||||
va.mLRAType = i == 0? SoftBodySharedSettings::ELRAType::None : SoftBodySharedSettings::ELRAType::EuclideanDistance;
|
||||
|
||||
Ref<SoftBodySharedSettings> cloth_settings = SoftBodyCreator::CreateCloth(cNumVerticesX, cNumVerticesZ, cVertexSpacing, inv_mass, perturbation, SoftBodySharedSettings::EBendType::None, va);
|
||||
|
||||
SoftBodyCreationSettings cloth(cloth_settings, RVec3(-10.0f + i * 20.0f, 25.0f, 0), Quat::sIdentity(), Layers::MOVING);
|
||||
mBodyInterface->CreateAndAddSoftBody(cloth, EActivation::Activate);
|
||||
}
|
||||
}
|
||||
|
||||
void SoftBodyLRAConstraintTest::PrePhysicsUpdate(const PreUpdateParams &inParams)
|
||||
{
|
||||
mDebugRenderer->DrawText3D(RVec3(-10, 26, -0.5f * cNumVerticesZ * cVertexSpacing), "Without LRA constraints", Color::sWhite);
|
||||
mDebugRenderer->DrawText3D(RVec3(10, 26, -0.5f * cNumVerticesZ * cVertexSpacing), "With LRA constraints", Color::sWhite);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
|
||||
class SoftBodyLRAConstraintTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, SoftBodyLRAConstraintTest)
|
||||
|
||||
// Description of the test
|
||||
virtual const char * GetDescription() const override
|
||||
{
|
||||
return "Shows the effect of Long Range Attachment (LRA) constraints in a soft body which can help reduce cloth stretching.";
|
||||
}
|
||||
|
||||
// See: Test
|
||||
virtual void Initialize() override;
|
||||
virtual void PrePhysicsUpdate(const PreUpdateParams &inParams) override;
|
||||
|
||||
private:
|
||||
// Size and spacing of the cloth
|
||||
static constexpr int cNumVerticesX = 10;
|
||||
static constexpr int cNumVerticesZ = 50;
|
||||
static constexpr float cVertexSpacing = 0.5f;
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2023 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/SoftBody/SoftBodyPressureTest.h>
|
||||
#include <Jolt/Physics/SoftBody/SoftBodyCreationSettings.h>
|
||||
#include <Utils/SoftBodyCreator.h>
|
||||
#include <Layers.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(SoftBodyPressureTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(SoftBodyPressureTest, Test)
|
||||
}
|
||||
|
||||
void SoftBodyPressureTest::Initialize()
|
||||
{
|
||||
// Floor
|
||||
CreateFloor();
|
||||
|
||||
// Bodies with increasing pressure
|
||||
SoftBodyCreationSettings sphere(SoftBodyCreator::CreateSphere(2.0f), RVec3::sZero(), Quat::sIdentity(), Layers::MOVING);
|
||||
|
||||
for (int i = 0; i <= 10; ++i)
|
||||
{
|
||||
sphere.mPosition = RVec3(-50.0f + i * 10.0f, 10.0f, 0);
|
||||
sphere.mPressure = 1000.0f * i;
|
||||
BodyID id = mBodyInterface->CreateAndAddSoftBody(sphere, EActivation::Activate);
|
||||
SetBodyLabel(id, StringFormat("Pressure: %g", double(sphere.mPressure)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2023 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
|
||||
class SoftBodyPressureTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, SoftBodyPressureTest)
|
||||
|
||||
// Description of the test
|
||||
virtual const char *GetDescription() const override
|
||||
{
|
||||
return "Tests soft bodies with various values for internal pressure.";
|
||||
}
|
||||
|
||||
// See: Test
|
||||
virtual void Initialize() override;
|
||||
};
|
||||
@@ -0,0 +1,44 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2023 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/SoftBody/SoftBodyRestitutionTest.h>
|
||||
#include <Jolt/Physics/SoftBody/SoftBodyCreationSettings.h>
|
||||
#include <Utils/SoftBodyCreator.h>
|
||||
#include <Layers.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(SoftBodyRestitutionTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(SoftBodyRestitutionTest, Test)
|
||||
}
|
||||
|
||||
void SoftBodyRestitutionTest::Initialize()
|
||||
{
|
||||
// Floor
|
||||
Body &floor = CreateFloor();
|
||||
floor.SetRestitution(0.0f);
|
||||
|
||||
// Bodies with increasing restitution
|
||||
SoftBodyCreationSettings sphere(SoftBodyCreator::CreateSphere(), RVec3::sZero(), Quat::sIdentity(), Layers::MOVING);
|
||||
sphere.mPressure = 2000.0f;
|
||||
|
||||
for (int i = 0; i <= 10; ++i)
|
||||
{
|
||||
sphere.mPosition = RVec3(-50.0f + i * 10.0f, 10.0f, 0);
|
||||
sphere.mRestitution = 0.1f * i;
|
||||
BodyID id = mBodyInterface->CreateAndAddSoftBody(sphere, EActivation::Activate);
|
||||
SetBodyLabel(id, StringFormat("Restitution: %.1f", double(sphere.mRestitution)));
|
||||
}
|
||||
|
||||
SoftBodyCreationSettings cube(SoftBodySharedSettings::sCreateCube(5, 0.5f), RVec3::sZero(), Quat::sIdentity(), Layers::MOVING);
|
||||
|
||||
for (int i = 0; i <= 10; ++i)
|
||||
{
|
||||
cube.mPosition = RVec3(-50.0f + i * 10.0f, 10.0f, -5.0f);
|
||||
cube.mRestitution = 0.1f * i;
|
||||
BodyID id = mBodyInterface->CreateAndAddSoftBody(cube, EActivation::Activate);
|
||||
SetBodyLabel(id, StringFormat("Restitution: %.1f", double(cube.mRestitution)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2023 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
|
||||
class SoftBodyRestitutionTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, SoftBodyRestitutionTest)
|
||||
|
||||
// Description of the test
|
||||
virtual const char *GetDescription() const override
|
||||
{
|
||||
return "Tests soft bodies with various values for restitution. Note that this has very little effect.";
|
||||
}
|
||||
|
||||
// See: Test
|
||||
virtual void Initialize() override;
|
||||
};
|
||||
@@ -0,0 +1,69 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/SoftBody/SoftBodySensorTest.h>
|
||||
#include <Jolt/Physics/Body/BodyCreationSettings.h>
|
||||
#include <Jolt/Physics/SoftBody/SoftBodyCreationSettings.h>
|
||||
#include <Jolt/Physics/Collision/Shape/SphereShape.h>
|
||||
#include <Jolt/Physics/Collision/Shape/TaperedCylinderShape.h>
|
||||
#include <Jolt/Physics/SoftBody/SoftBodyManifold.h>
|
||||
#include <Utils/SoftBodyCreator.h>
|
||||
#include <Renderer/DebugRendererImp.h>
|
||||
#include <Layers.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(SoftBodySensorTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(SoftBodySensorTest, Test)
|
||||
}
|
||||
|
||||
void SoftBodySensorTest::Initialize()
|
||||
{
|
||||
// Install contact listener for soft bodies
|
||||
mPhysicsSystem->SetSoftBodyContactListener(this);
|
||||
|
||||
// Floor
|
||||
CreateFloor();
|
||||
|
||||
// Create cloth that's fixated at the corners
|
||||
SoftBodyCreationSettings cloth(SoftBodyCreator::CreateClothWithFixatedCorners(), RVec3(0, 10.0f, 0), Quat::sIdentity(), Layers::MOVING);
|
||||
mBodyInterface->CreateAndAddSoftBody(cloth, EActivation::Activate);
|
||||
|
||||
// Some sensors to detect the cloth
|
||||
BodyCreationSettings cylinder_sensor(new TaperedCylinderShapeSettings(4.0f, 1.0f, 2.0f), RVec3(0, 6, 0), Quat::sRotation(Vec3::sAxisX(), 0.5f * JPH_PI), EMotionType::Static, Layers::SENSOR);
|
||||
cylinder_sensor.mIsSensor = true;
|
||||
mBodyInterface->CreateAndAddBody(cylinder_sensor, EActivation::DontActivate);
|
||||
|
||||
BodyCreationSettings sphere_sensor(new SphereShape(4.0f), RVec3(4, 5, 0), Quat::sIdentity(), EMotionType::Static, Layers::SENSOR);
|
||||
sphere_sensor.mIsSensor = true;
|
||||
mBodyInterface->CreateAndAddBody(sphere_sensor, EActivation::DontActivate);
|
||||
|
||||
// Sphere that falls on the cloth to check that we don't ignore this collision
|
||||
BodyCreationSettings bcs(new SphereShape(1.0f), RVec3(0, 15, 0), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING);
|
||||
bcs.mOverrideMassProperties = EOverrideMassProperties::CalculateInertia;
|
||||
bcs.mMassPropertiesOverride.mMass = 500.0f;
|
||||
mBodyInterface->CreateAndAddBody(bcs, EActivation::Activate);
|
||||
}
|
||||
|
||||
void SoftBodySensorTest::OnSoftBodyContactAdded(const Body &inSoftBody, const SoftBodyManifold &inManifold)
|
||||
{
|
||||
// Draw the vertices that are in contact
|
||||
RMat44 com = inSoftBody.GetCenterOfMassTransform();
|
||||
for (const SoftBodyVertex &v : inManifold.GetVertices())
|
||||
if (inManifold.HasContact(v))
|
||||
DebugRenderer::sInstance->DrawMarker(com * v.mPosition, Color::sGreen, 0.1f);
|
||||
|
||||
// Draw the sensors that are in contact with the soft body
|
||||
for (uint i = 0; i < inManifold.GetNumSensorContacts(); ++i)
|
||||
{
|
||||
BodyID sensor_id = inManifold.GetSensorContactBodyID(i);
|
||||
BodyLockRead lock(mPhysicsSystem->GetBodyLockInterfaceNoLock(), sensor_id); // Can't lock in a callback
|
||||
if (lock.SucceededAndIsInBroadPhase())
|
||||
{
|
||||
AABox bounds = lock.GetBody().GetWorldSpaceBounds();
|
||||
DebugRenderer::sInstance->DrawWireBox(bounds, Color::sGreen);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
#include <Jolt/Physics/SoftBody/SoftBodyContactListener.h>
|
||||
|
||||
class SoftBodySensorTest : public Test, public SoftBodyContactListener
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, SoftBodySensorTest)
|
||||
|
||||
// Description of the test
|
||||
virtual const char *GetDescription() const override
|
||||
{
|
||||
return "Shows interaction between a soft body and a sensor.";
|
||||
}
|
||||
|
||||
// See: Test
|
||||
virtual void Initialize() override;
|
||||
|
||||
// See: SoftBodyContactListener
|
||||
virtual void OnSoftBodyContactAdded(const Body &inSoftBody, const SoftBodyManifold &inManifold) override;
|
||||
};
|
||||
@@ -0,0 +1,87 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2023 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/SoftBody/SoftBodyShapesTest.h>
|
||||
#include <Jolt/Physics/Body/BodyCreationSettings.h>
|
||||
#include <Jolt/Physics/SoftBody/SoftBodyCreationSettings.h>
|
||||
#include <Jolt/Physics/Collision/Shape/SphereShape.h>
|
||||
#include <Jolt/Physics/Collision/Shape/BoxShape.h>
|
||||
#include <Jolt/Physics/Collision/Shape/CapsuleShape.h>
|
||||
#include <Jolt/Physics/Collision/Shape/TaperedCapsuleShape.h>
|
||||
#include <Jolt/Physics/Collision/Shape/CylinderShape.h>
|
||||
#include <Jolt/Physics/Collision/Shape/TaperedCylinderShape.h>
|
||||
#include <Jolt/Physics/Collision/Shape/ConvexHullShape.h>
|
||||
#include <Jolt/Physics/Collision/Shape/StaticCompoundShape.h>
|
||||
#include <Jolt/Physics/Collision/Shape/RotatedTranslatedShape.h>
|
||||
#include <Utils/SoftBodyCreator.h>
|
||||
#include <Renderer/DebugRendererImp.h>
|
||||
#include <Layers.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(SoftBodyShapesTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(SoftBodyShapesTest, Test)
|
||||
}
|
||||
|
||||
void SoftBodyShapesTest::Initialize()
|
||||
{
|
||||
const Quat cCubeOrientation = Quat::sRotation(Vec3::sReplicate(sqrt(1.0f / 3.0f)), DegreesToRadians(45.0f));
|
||||
|
||||
// Floor
|
||||
CreateMeshTerrain();
|
||||
|
||||
// Create cloth that's fixated at the corners
|
||||
SoftBodyCreationSettings cloth(SoftBodyCreator::CreateClothWithFixatedCorners(), RVec3(0, 10.0f, 0), Quat::sRotation(Vec3::sAxisY(), 0.25f * JPH_PI), Layers::MOVING);
|
||||
cloth.mUpdatePosition = false; // Don't update the position of the cloth as it is fixed to the world
|
||||
cloth.mMakeRotationIdentity = false; // Test explicitly checks if soft bodies with a rotation collide with shapes properly
|
||||
mBodyInterface->CreateAndAddSoftBody(cloth, EActivation::Activate);
|
||||
|
||||
// Create cube
|
||||
SoftBodyCreationSettings cube(SoftBodySharedSettings::sCreateCube(5, 0.5f), RVec3(20.0f, 10.0f, 0.0f), cCubeOrientation, Layers::MOVING);
|
||||
cube.mRestitution = 0.0f;
|
||||
mBodyInterface->CreateAndAddSoftBody(cube, EActivation::Activate);
|
||||
|
||||
// Create pressurized sphere
|
||||
SoftBodyCreationSettings sphere(SoftBodyCreator::CreateSphere(), RVec3(15.0f, 10.0f, 15.0f), Quat::sIdentity(), Layers::MOVING);
|
||||
sphere.mPressure = 2000.0f;
|
||||
mBodyInterface->CreateAndAddSoftBody(sphere, EActivation::Activate);
|
||||
|
||||
// Sphere below pressurized sphere
|
||||
RefConst<Shape> sphere_shape = new SphereShape(1.0f);
|
||||
BodyCreationSettings bcs(sphere_shape, RVec3(15.5f, 7.0f, 15.0f), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING);
|
||||
bcs.mOverrideMassProperties = EOverrideMassProperties::CalculateInertia;
|
||||
bcs.mMassPropertiesOverride.mMass = 100.0f;
|
||||
mBodyInterface->CreateAndAddBody(bcs, EActivation::Activate);
|
||||
|
||||
// Various shapes above cloth
|
||||
ConvexHullShapeSettings tetrahedron({ Vec3(-2, -2, -2), Vec3(0, -2, 2), Vec3(2, -2, -2), Vec3(0, 2, 0) });
|
||||
tetrahedron.SetEmbedded();
|
||||
|
||||
StaticCompoundShapeSettings compound_shape;
|
||||
compound_shape.SetEmbedded();
|
||||
Quat rotate_x = Quat::sRotation(Vec3::sAxisX(), 0.5f * JPH_PI);
|
||||
compound_shape.AddShape(Vec3::sZero(), rotate_x, new CapsuleShape(2, 0.5f));
|
||||
compound_shape.AddShape(Vec3(0, 0, -2), Quat::sIdentity(), new SphereShape(1));
|
||||
compound_shape.AddShape(Vec3(0, 0, 2), Quat::sIdentity(), new SphereShape(1));
|
||||
|
||||
RefConst<Shape> shapes[] = {
|
||||
sphere_shape,
|
||||
new BoxShape(Vec3(0.75f, 1.0f, 1.25f)),
|
||||
new RotatedTranslatedShape(Vec3::sZero(), rotate_x, new CapsuleShape(1, 0.5f)),
|
||||
new RotatedTranslatedShape(Vec3::sZero(), rotate_x, TaperedCapsuleShapeSettings(1.0f, 1.0f, 0.5f).Create().Get()),
|
||||
new RotatedTranslatedShape(Vec3::sZero(), rotate_x, new CylinderShape(1, 0.5f)),
|
||||
new RotatedTranslatedShape(Vec3::sZero(), rotate_x, TaperedCylinderShapeSettings(1, 0.5f, 1.0f).Create().Get()),
|
||||
tetrahedron.Create().Get(),
|
||||
compound_shape.Create().Get(),
|
||||
};
|
||||
int num_shapes = (int)std::size(shapes);
|
||||
|
||||
for (int i = 0; i < num_shapes; ++i)
|
||||
{
|
||||
bcs.SetShape(shapes[i % num_shapes]);
|
||||
bcs.mPosition = RVec3(-float(num_shapes) + 2.0f * i, 15.0f, 0);
|
||||
mBodyInterface->CreateAndAddBody(bcs, EActivation::Activate);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2023 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
|
||||
class SoftBodyShapesTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, SoftBodyShapesTest)
|
||||
|
||||
// Description of the test
|
||||
virtual const char *GetDescription() const override
|
||||
{
|
||||
return "Shows interaction between various collision shapes and soft bodies.";
|
||||
}
|
||||
|
||||
// See: Test
|
||||
virtual void Initialize() override;
|
||||
};
|
||||
@@ -0,0 +1,174 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/SoftBody/SoftBodySkinnedConstraintTest.h>
|
||||
#include <Jolt/Physics/SoftBody/SoftBodyCreationSettings.h>
|
||||
#include <Jolt/Physics/SoftBody/SoftBodyMotionProperties.h>
|
||||
#include <Utils/SoftBodyCreator.h>
|
||||
#include <Layers.h>
|
||||
#include <Renderer/DebugRendererImp.h>
|
||||
#include <Application/DebugUI.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(SoftBodySkinnedConstraintTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(SoftBodySkinnedConstraintTest, Test)
|
||||
}
|
||||
|
||||
Array<Mat44> SoftBodySkinnedConstraintTest::GetWorldSpacePose(float inTime) const
|
||||
{
|
||||
Array<Mat44> pose;
|
||||
pose.resize(cNumJoints);
|
||||
|
||||
// Create local space pose
|
||||
pose[0] = Mat44::sTranslation(Vec3(0.0f, cBodyPosY, -0.5f * (cNumVerticesZ - 1) * cVertexSpacing));
|
||||
for (int i = 1; i < cNumJoints; ++i)
|
||||
{
|
||||
float amplitude = 0.25f * min(inTime, 2.0f); // Fade effect in over time
|
||||
Mat44 rotation = Mat44::sRotationX(amplitude * Sin(0.25f * JPH_PI * i + 2.0f * inTime));
|
||||
Mat44 translation = Mat44::sTranslation(Vec3(0, 0, (cNumVerticesZ - 1) * cVertexSpacing / (cNumJoints - 1)));
|
||||
pose[i] = rotation * translation;
|
||||
}
|
||||
|
||||
// Convert to world space
|
||||
for (int i = 1; i < cNumJoints; ++i)
|
||||
pose[i] = pose[i - 1] * pose[i];
|
||||
|
||||
return pose;
|
||||
}
|
||||
|
||||
void SoftBodySkinnedConstraintTest::SkinVertices(bool inHardSkinAll)
|
||||
{
|
||||
RMat44 com = mBody->GetCenterOfMassTransform();
|
||||
|
||||
// Make pose relative to the center of mass of the body
|
||||
Array<Mat44> pose = GetWorldSpacePose(mTime);
|
||||
Mat44 offset = com.InversedRotationTranslation().ToMat44();
|
||||
for (Mat44 &m : pose)
|
||||
m = offset * m;
|
||||
|
||||
SoftBodyMotionProperties *mp = static_cast<SoftBodyMotionProperties *>(mBody->GetMotionProperties());
|
||||
mp->SetEnableSkinConstraints(sEnableSkinConstraints);
|
||||
mp->SetSkinnedMaxDistanceMultiplier(sMaxDistanceMultiplier);
|
||||
if (sUpdateSkinning || inHardSkinAll)
|
||||
mp->SkinVertices(com, pose.data(), cNumJoints, inHardSkinAll, *mTempAllocator);
|
||||
}
|
||||
|
||||
void SoftBodySkinnedConstraintTest::Initialize()
|
||||
{
|
||||
CreateFloor();
|
||||
|
||||
// Where we'll place the body
|
||||
RVec3 body_translation(0.0f, cBodyPosY, 0);
|
||||
|
||||
// Make first and last row kinematic
|
||||
auto inv_mass = [](uint, uint inZ) { return inZ == 0 || inZ == cNumVerticesZ - 1? 0.0f : 1.0f; };
|
||||
Ref<SoftBodySharedSettings> settings = SoftBodyCreator::CreateCloth(cNumVerticesX, cNumVerticesZ, cVertexSpacing, inv_mass);
|
||||
|
||||
// Make edges soft
|
||||
for (SoftBodySharedSettings::Edge &e : settings->mEdgeConstraints)
|
||||
e.mCompliance = 1.0e-3f;
|
||||
|
||||
// Create inverse bind matrices by moving the bind pose to the center of mass space for the body
|
||||
Array<Mat44> bind_pose = GetWorldSpacePose(0.0f);
|
||||
Mat44 offset = Mat44::sTranslation(Vec3(-body_translation));
|
||||
for (Mat44 &m : bind_pose)
|
||||
m = offset * m;
|
||||
for (int i = 0; i < cNumJoints; ++i)
|
||||
settings->mInvBindMatrices.push_back(SoftBodySharedSettings::InvBind(i, bind_pose[i].Inversed()));
|
||||
|
||||
// Create skinned vertices
|
||||
auto get_vertex = [](uint inX, uint inZ) { return inX + inZ * cNumVerticesX; };
|
||||
for (int z = 0; z < cNumVerticesZ; ++z)
|
||||
for (int x = 0; x < cNumVerticesX; ++x)
|
||||
{
|
||||
uint vertex_idx = get_vertex(x, z);
|
||||
SoftBodySharedSettings::Skinned skinned(vertex_idx, settings->mVertices[vertex_idx].mInvMass > 0.0f? 2.0f : 0.0f, 0.1f, 40.0f);
|
||||
|
||||
// Find closest joints
|
||||
int closest_joint = -1, prev_closest_joint = -1;
|
||||
float closest_joint_dist = FLT_MAX, prev_closest_joint_dist = FLT_MAX;
|
||||
for (int i = 0; i < cNumJoints; ++i)
|
||||
{
|
||||
float dist = abs(settings->mVertices[vertex_idx].mPosition.z - bind_pose[i].GetTranslation().GetZ());
|
||||
if (dist < closest_joint_dist)
|
||||
{
|
||||
prev_closest_joint = closest_joint;
|
||||
prev_closest_joint_dist = closest_joint_dist;
|
||||
closest_joint = i;
|
||||
closest_joint_dist = dist;
|
||||
}
|
||||
else if (dist < prev_closest_joint_dist)
|
||||
{
|
||||
prev_closest_joint = i;
|
||||
prev_closest_joint_dist = dist;
|
||||
}
|
||||
}
|
||||
if (closest_joint_dist == 0.0f)
|
||||
{
|
||||
// Hard skin to closest joint
|
||||
skinned.mWeights[0] = SoftBodySharedSettings::SkinWeight(closest_joint, 1.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Skin to two closest joints
|
||||
skinned.mWeights[0] = SoftBodySharedSettings::SkinWeight(closest_joint, 1.0f / closest_joint_dist);
|
||||
skinned.mWeights[1] = SoftBodySharedSettings::SkinWeight(prev_closest_joint, 1.0f / prev_closest_joint_dist);
|
||||
skinned.NormalizeWeights();
|
||||
}
|
||||
|
||||
settings->mSkinnedConstraints.push_back(skinned);
|
||||
}
|
||||
|
||||
// Calculate the information needed for skinned constraints
|
||||
settings->CalculateSkinnedConstraintNormals();
|
||||
|
||||
// Optimize the settings (note that this is the second time we call this, the first time was in SoftBodyCreator::CreateCloth,
|
||||
// this is a bit wasteful but we must do it because we added more constraints)
|
||||
settings->Optimize();
|
||||
|
||||
// Create the body
|
||||
SoftBodyCreationSettings cloth(settings, body_translation, Quat::sIdentity(), Layers::MOVING);
|
||||
mBody = mBodyInterface->CreateSoftBody(cloth);
|
||||
mBodyInterface->AddBody(mBody->GetID(), EActivation::Activate);
|
||||
|
||||
// Initially hard skin all vertices to the pose
|
||||
SkinVertices(true);
|
||||
}
|
||||
|
||||
void SoftBodySkinnedConstraintTest::PrePhysicsUpdate(const PreUpdateParams &inParams)
|
||||
{
|
||||
// Draw the pose pre step
|
||||
Array<Mat44> pose = GetWorldSpacePose(mTime);
|
||||
for (int i = 1; i < cNumJoints; ++i)
|
||||
{
|
||||
mDebugRenderer->DrawArrow(RVec3(pose[i - 1].GetTranslation()), RVec3(pose[i].GetTranslation()), Color::sGreen, 0.1f);
|
||||
mDebugRenderer->DrawCoordinateSystem(RMat44(pose[i]), 0.5f);
|
||||
}
|
||||
|
||||
// Update time
|
||||
mTime += sTimeScale * inParams.mDeltaTime;
|
||||
|
||||
// Calculate skinned vertices but do not hard skin them
|
||||
SkinVertices(false);
|
||||
}
|
||||
|
||||
void SoftBodySkinnedConstraintTest::SaveState(StateRecorder &inStream) const
|
||||
{
|
||||
inStream.Write(mTime);
|
||||
}
|
||||
|
||||
void SoftBodySkinnedConstraintTest::RestoreState(StateRecorder &inStream)
|
||||
{
|
||||
inStream.Read(mTime);
|
||||
}
|
||||
|
||||
void SoftBodySkinnedConstraintTest::CreateSettingsMenu(DebugUI *inUI, UIElement *inSubMenu)
|
||||
{
|
||||
inUI->CreateSlider(inSubMenu, "Time Scale", sTimeScale, 0.0f, 10.0f, 0.1f, [](float inValue) { sTimeScale = inValue; });
|
||||
inUI->CreateCheckBox(inSubMenu, "Update Skinning", sUpdateSkinning, [](UICheckBox::EState inState) { sUpdateSkinning = inState == UICheckBox::STATE_CHECKED; });
|
||||
inUI->CreateCheckBox(inSubMenu, "Enable Skin Constraints", sEnableSkinConstraints, [](UICheckBox::EState inState) { sEnableSkinConstraints = inState == UICheckBox::STATE_CHECKED; });
|
||||
inUI->CreateSlider(inSubMenu, "Max Distance Multiplier", sMaxDistanceMultiplier, 0.0f, 10.0f, 0.1f, [](float inValue) { sMaxDistanceMultiplier = inValue; });
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
#include <Jolt/Physics/Body/Body.h>
|
||||
|
||||
class SoftBodySkinnedConstraintTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, SoftBodySkinnedConstraintTest)
|
||||
|
||||
// Description of the test
|
||||
virtual const char * GetDescription() const override
|
||||
{
|
||||
return "Shows how to attach a soft body to a skinned mesh and control the animation.";
|
||||
}
|
||||
|
||||
// See: Test
|
||||
virtual void Initialize() override;
|
||||
virtual void PrePhysicsUpdate(const PreUpdateParams &inParams) override;
|
||||
virtual void GetInitialCamera(CameraState &ioState) const override { ioState.mPos = RVec3(15, 30, 15); }
|
||||
virtual void SaveState(StateRecorder &inStream) const override;
|
||||
virtual void RestoreState(StateRecorder &inStream) override;
|
||||
virtual bool HasSettingsMenu() const override { return true; }
|
||||
virtual void CreateSettingsMenu(DebugUI *inUI, UIElement *inSubMenu) override;
|
||||
|
||||
private:
|
||||
// Size and spacing of the cloth
|
||||
static constexpr int cNumVerticesX = 10;
|
||||
static constexpr int cNumVerticesZ = 50;
|
||||
static constexpr float cVertexSpacing = 0.5f;
|
||||
|
||||
// Number of joints that drive the cloth
|
||||
static constexpr int cNumJoints = 11;
|
||||
|
||||
// Position of the body
|
||||
static constexpr float cBodyPosY = 20.0f;
|
||||
|
||||
// Get a procedurally generated pose
|
||||
Array<Mat44> GetWorldSpacePose(float inTime) const;
|
||||
|
||||
// Skin the vertices of the soft body to the pose
|
||||
void SkinVertices(bool inHardSkinAll);
|
||||
|
||||
// The soft body
|
||||
Body * mBody;
|
||||
|
||||
// Current time
|
||||
float mTime = 0.0f;
|
||||
|
||||
// Settings
|
||||
static inline float sTimeScale = 1.0f;
|
||||
static inline bool sUpdateSkinning = true;
|
||||
static inline bool sEnableSkinConstraints = true;
|
||||
static inline float sMaxDistanceMultiplier = 1.0f;
|
||||
};
|
||||
@@ -0,0 +1,87 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2023 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/SoftBody/SoftBodyStressTest.h>
|
||||
#include <Jolt/Physics/Body/BodyCreationSettings.h>
|
||||
#include <Jolt/Physics/SoftBody/SoftBodyCreationSettings.h>
|
||||
#include <Jolt/Physics/Collision/Shape/BoxShape.h>
|
||||
#include <Utils/SoftBodyCreator.h>
|
||||
#include <Application/DebugUI.h>
|
||||
#include <Layers.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(SoftBodyStressTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(SoftBodyStressTest, Test)
|
||||
}
|
||||
|
||||
const char *SoftBodyStressTest::sScenes[] =
|
||||
{
|
||||
"SpheresVsBoxes",
|
||||
"LargeCloth"
|
||||
};
|
||||
|
||||
const char *SoftBodyStressTest::sSceneName = "SpheresVsBoxes";
|
||||
|
||||
void SoftBodyStressTest::Initialize()
|
||||
{
|
||||
if (strcmp(sSceneName, "SpheresVsBoxes") == 0)
|
||||
{
|
||||
// Floor
|
||||
CreateMeshTerrain();
|
||||
|
||||
// Pressurized sphere settings
|
||||
SoftBodyCreationSettings sphere(SoftBodyCreator::CreateSphere(), RVec3::sZero(), Quat::sIdentity(), Layers::MOVING);
|
||||
sphere.mPressure = 2000.0f;
|
||||
|
||||
// Box settings
|
||||
BodyCreationSettings box(new BoxShape(Vec3::sOne()), RVec3::sZero(), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING);
|
||||
box.mOverrideMassProperties = EOverrideMassProperties::CalculateInertia;
|
||||
box.mMassPropertiesOverride.mMass = 100.0f;
|
||||
|
||||
for (int x = 0; x <= 10; ++x)
|
||||
for (int z = 0; z <= 10; ++z)
|
||||
{
|
||||
sphere.mPosition = RVec3(-20.0_r + 4.0_r * x, 5.0_r, -20.0_r + 4.0_r * z);
|
||||
mBodyInterface->CreateAndAddSoftBody(sphere, EActivation::Activate);
|
||||
|
||||
box.mPosition = sphere.mPosition + RVec3(0, 4, 0);
|
||||
mBodyInterface->CreateAndAddBody(box, EActivation::Activate);
|
||||
}
|
||||
}
|
||||
else if (strcmp(sSceneName, "LargeCloth") == 0)
|
||||
{
|
||||
// Floor
|
||||
CreateFloor();
|
||||
|
||||
// Create cloth that's fixated at the corners
|
||||
SoftBodyCreationSettings cloth(SoftBodyCreator::CreateClothWithFixatedCorners(100, 100, 0.25f), RVec3(0, 15.0f, 0), Quat::sIdentity(), Layers::MOVING);
|
||||
cloth.mUpdatePosition = false; // Don't update the position of the cloth as it is fixed to the world
|
||||
mBodyInterface->CreateAndAddSoftBody(cloth, EActivation::Activate);
|
||||
|
||||
// Box settings
|
||||
BodyCreationSettings box(new BoxShape(Vec3::sReplicate(0.5f)), RVec3::sZero(), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING);
|
||||
box.mOverrideMassProperties = EOverrideMassProperties::CalculateInertia;
|
||||
box.mMassPropertiesOverride.mMass = 10.0f;
|
||||
|
||||
// Create a number of boxes that fall on the cloth
|
||||
for (int x = 0; x <= 10; ++x)
|
||||
for (int z = 0; z <= 10; ++z)
|
||||
{
|
||||
box.mPosition = cloth.mPosition + RVec3(-10.0_r + 2.0_r * x, 2.0_r, -10.0_r + 2.0_r * z);
|
||||
mBodyInterface->CreateAndAddBody(box, EActivation::Activate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SoftBodyStressTest::CreateSettingsMenu(DebugUI *inUI, UIElement *inSubMenu)
|
||||
{
|
||||
inUI->CreateTextButton(inSubMenu, "Select Scene", [this, inUI]() {
|
||||
UIElement *scene_name = inUI->CreateMenu();
|
||||
for (uint i = 0; i < size(sScenes); ++i)
|
||||
inUI->CreateTextButton(scene_name, sScenes[i], [this, i]() { sSceneName = sScenes[i]; RestartTest(); });
|
||||
inUI->ShowMenu(scene_name);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2023 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
|
||||
class SoftBodyStressTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, SoftBodyStressTest)
|
||||
|
||||
// Description of the test
|
||||
virtual const char * GetDescription() const override
|
||||
{
|
||||
return "Stresses the soft body system by creating a large number of soft bodies / a soft body with many vertices.";
|
||||
}
|
||||
|
||||
// See: Test
|
||||
virtual void Initialize() override;
|
||||
|
||||
// Optional settings menu
|
||||
virtual bool HasSettingsMenu() const override { return true; }
|
||||
virtual void CreateSettingsMenu(DebugUI *inUI, UIElement *inSubMenu) override;
|
||||
|
||||
private:
|
||||
// List of possible scene names
|
||||
static const char * sScenes[];
|
||||
|
||||
// Filename of animation to load for this test
|
||||
static const char * sSceneName;
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2023 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/SoftBody/SoftBodyUpdatePositionTest.h>
|
||||
#include <Jolt/Physics/SoftBody/SoftBodyCreationSettings.h>
|
||||
#include <Utils/SoftBodyCreator.h>
|
||||
#include <Layers.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(SoftBodyUpdatePositionTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(SoftBodyUpdatePositionTest, Test)
|
||||
}
|
||||
|
||||
void SoftBodyUpdatePositionTest::Initialize()
|
||||
{
|
||||
// Floor
|
||||
CreateFloor();
|
||||
|
||||
// Bodies with various settings for 'make rotation identity' and 'update position'
|
||||
SoftBodyCreationSettings sphere(SoftBodySharedSettings::sCreateCube(5, 0.5f), RVec3::sZero(), Quat::sRotation(Vec3::sReplicate(1.0f / sqrt(3.0f)), 0.25f * JPH_PI), Layers::MOVING);
|
||||
|
||||
for (int update_position = 0; update_position < 2; ++update_position)
|
||||
for (int make_rotation_identity = 0; make_rotation_identity < 2; ++make_rotation_identity)
|
||||
{
|
||||
sphere.mPosition = RVec3(update_position * 10.0f, 10.0f, make_rotation_identity * 10.0f);
|
||||
sphere.mUpdatePosition = update_position != 0;
|
||||
sphere.mMakeRotationIdentity = make_rotation_identity != 0;
|
||||
BodyID id = mBodyInterface->CreateAndAddSoftBody(sphere, EActivation::Activate);
|
||||
SetBodyLabel(id, StringFormat("UpdatePosition: %s\nMakeRotationIdentity: %s", update_position != 0? "On" : "Off", make_rotation_identity != 0? "On" : "Off"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2023 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
|
||||
class SoftBodyUpdatePositionTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, SoftBodyUpdatePositionTest)
|
||||
|
||||
// Description of the test
|
||||
virtual const char *GetDescription() const override
|
||||
{
|
||||
return "This test tests soft bodies with and without 'update position' and 'make rotation identity'.\n"
|
||||
"The labels of the bodies that don't update their position will stay in place.\n"
|
||||
"If you turn on 'Draw Bounding Boxes' then you will see that the cubes that with 'make rotation identity' have a smaller bounding box.";
|
||||
}
|
||||
|
||||
// See: Test
|
||||
virtual void Initialize() override;
|
||||
};
|
||||
@@ -0,0 +1,38 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/SoftBody/SoftBodyVertexRadiusTest.h>
|
||||
#include <Jolt/Physics/Body/BodyCreationSettings.h>
|
||||
#include <Jolt/Physics/Collision/Shape/SphereShape.h>
|
||||
#include <Jolt/Physics/SoftBody/SoftBodyCreationSettings.h>
|
||||
#include <Utils/SoftBodyCreator.h>
|
||||
#include <Layers.h>
|
||||
#include <Application/DebugUI.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(SoftBodyVertexRadiusTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(SoftBodyVertexRadiusTest, Test)
|
||||
}
|
||||
|
||||
void SoftBodyVertexRadiusTest::Initialize()
|
||||
{
|
||||
// Floor
|
||||
CreateFloor();
|
||||
|
||||
// Create sphere
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(new SphereShape(2.0f), RVec3(0, 0, 0), Quat::sIdentity(), EMotionType::Static, Layers::NON_MOVING), EActivation::DontActivate);
|
||||
|
||||
// Create cloth with specified vertex radius
|
||||
mSharedSettings = SoftBodyCreator::CreateCloth(30, 30, 0.5f);
|
||||
SoftBodyCreationSettings cloth(mSharedSettings, RVec3(0, 5, 0), Quat::sRotation(Vec3::sAxisY(), 0.25f * JPH_PI), Layers::MOVING);
|
||||
cloth.mVertexRadius = sVertexRadius;
|
||||
mBodyInterface->CreateAndAddSoftBody(cloth, EActivation::Activate);
|
||||
}
|
||||
|
||||
void SoftBodyVertexRadiusTest::CreateSettingsMenu(DebugUI *inUI, UIElement *inSubMenu)
|
||||
{
|
||||
inUI->CreateSlider(inSubMenu, "Vertex Radius", sVertexRadius, 0.0f, 0.5f, 0.01f, [](float inValue) { sVertexRadius = inValue; });
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
#include <Jolt/Physics/SoftBody/SoftBodySharedSettings.h>
|
||||
|
||||
class SoftBodyVertexRadiusTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, SoftBodyVertexRadiusTest)
|
||||
|
||||
// Description of the test
|
||||
virtual const char * GetDescription() const override
|
||||
{
|
||||
return "Shows how you can use the vertex radius of a soft body to prevent z-fighting while rendering it.";
|
||||
}
|
||||
|
||||
// See: Test
|
||||
virtual void Initialize() override;
|
||||
|
||||
// Optional settings menu
|
||||
virtual bool HasSettingsMenu() const override { return true; }
|
||||
virtual void CreateSettingsMenu(DebugUI *inUI, UIElement *inSubMenu) override;
|
||||
|
||||
private:
|
||||
Ref<SoftBodySharedSettings> mSharedSettings;
|
||||
|
||||
static inline float sVertexRadius = 0.01f;
|
||||
};
|
||||
@@ -0,0 +1,41 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/SoftBody/SoftBodyVsFastMovingTest.h>
|
||||
#include <Jolt/Physics/Body/BodyCreationSettings.h>
|
||||
#include <Jolt/Physics/SoftBody/SoftBodyCreationSettings.h>
|
||||
#include <Jolt/Physics/Collision/Shape/SphereShape.h>
|
||||
#include <Utils/SoftBodyCreator.h>
|
||||
#include <Layers.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(SoftBodyVsFastMovingTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(SoftBodyVsFastMovingTest, Test)
|
||||
}
|
||||
|
||||
void SoftBodyVsFastMovingTest::Initialize()
|
||||
{
|
||||
// Floor
|
||||
CreateFloor();
|
||||
|
||||
// Create sphere moving towards the cloth
|
||||
BodyCreationSettings bcs(new SphereShape(1.0f), RVec3(-2, 20, 0), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING);
|
||||
bcs.mMotionQuality = EMotionQuality::LinearCast;
|
||||
bcs.mOverrideMassProperties = EOverrideMassProperties::CalculateInertia;
|
||||
bcs.mMassPropertiesOverride.mMass = 25.0f;
|
||||
bcs.mLinearVelocity = Vec3(0, -250, 0);
|
||||
mBodyInterface->CreateAndAddBody(bcs, EActivation::Activate);
|
||||
|
||||
// Create cloth that's fixated at the corners
|
||||
SoftBodyCreationSettings cloth(SoftBodyCreator::CreateClothWithFixatedCorners(), RVec3(0, 15, 0), Quat::sRotation(Vec3::sAxisX(), 0.1f * JPH_PI) * Quat::sRotation(Vec3::sAxisY(), 0.25f * JPH_PI), Layers::MOVING);
|
||||
cloth.mUpdatePosition = false; // Don't update the position of the cloth as it is fixed to the world
|
||||
cloth.mMakeRotationIdentity = false; // Test explicitly checks if soft bodies with a rotation collide with shapes properly
|
||||
mBodyInterface->CreateAndAddSoftBody(cloth, EActivation::Activate);
|
||||
|
||||
// Create another body with a higher ID than the cloth
|
||||
bcs.mPosition = RVec3(2, 20, 0);
|
||||
mBodyInterface->CreateAndAddBody(bcs, EActivation::Activate);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
|
||||
class SoftBodyVsFastMovingTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, SoftBodyVsFastMovingTest)
|
||||
|
||||
// Description of the test
|
||||
virtual const char *GetDescription() const override
|
||||
{
|
||||
return "Shows interaction between a fast moving (CCD) object and a soft body.";
|
||||
}
|
||||
|
||||
// See: Test
|
||||
virtual void Initialize() override;
|
||||
};
|
||||
Reference in New Issue
Block a user