Ajout de Jolt Physics + 1ere version des factory entitecomposants - camera, transform, rigidbody, collider, renderer
This commit is contained in:
28
lib/All/JoltPhysics/Samples/Tests/Shapes/BoxShapeTest.cpp
Normal file
28
lib/All/JoltPhysics/Samples/Tests/Shapes/BoxShapeTest.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/Shapes/BoxShapeTest.h>
|
||||
#include <Jolt/Physics/Collision/Shape/BoxShape.h>
|
||||
#include <Jolt/Physics/Body/BodyCreationSettings.h>
|
||||
#include <Layers.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(BoxShapeTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(BoxShapeTest, Test)
|
||||
}
|
||||
|
||||
void BoxShapeTest::Initialize()
|
||||
{
|
||||
// Floor
|
||||
CreateFloor();
|
||||
|
||||
// Different sized boxes
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(new BoxShape(Vec3(20, 1, 1)), RVec3(0, 10, 0), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(new BoxShape(Vec3(2, 3, 4)), RVec3(0, 10, 10), Quat::sRotation(Vec3::sAxisZ(), 0.25f * JPH_PI), EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(new BoxShape(Vec3(0.5f, 0.75f, 1.0f)), RVec3(0, 10, 20), Quat::sRotation(Vec3::sAxisX(), 0.25f * JPH_PI) * Quat::sRotation(Vec3::sAxisZ(), 0.25f * JPH_PI), EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
}
|
||||
16
lib/All/JoltPhysics/Samples/Tests/Shapes/BoxShapeTest.h
Normal file
16
lib/All/JoltPhysics/Samples/Tests/Shapes/BoxShapeTest.h
Normal file
@@ -0,0 +1,16 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
|
||||
class BoxShapeTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, BoxShapeTest)
|
||||
|
||||
// See: Test
|
||||
virtual void Initialize() override;
|
||||
};
|
||||
@@ -0,0 +1,52 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/Shapes/CapsuleShapeTest.h>
|
||||
#include <Jolt/Physics/Collision/Shape/CapsuleShape.h>
|
||||
#include <Jolt/Physics/Body/BodyCreationSettings.h>
|
||||
#include <Layers.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(CapsuleShapeTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(CapsuleShapeTest, Test)
|
||||
}
|
||||
|
||||
void CapsuleShapeTest::Initialize()
|
||||
{
|
||||
// Floor
|
||||
CreateFloor();
|
||||
|
||||
RefConst<Shape> big_capsule = new CapsuleShape(2.5f, 2);
|
||||
|
||||
// Capsule on outer sphere
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(big_capsule, RVec3(0, 10, 0), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
|
||||
// Capsule on cylinder
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(big_capsule, RVec3(10, 10, 0), Quat::sRotation(Vec3::sAxisX(), 0.5f * JPH_PI), EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
|
||||
RefConst<Shape> long_capsule = new CapsuleShape(5, 1);
|
||||
|
||||
// Tower of capsules
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
for (int j = 0; j < 2; ++j)
|
||||
{
|
||||
RVec3 position;
|
||||
Quat rotation;
|
||||
if (i & 1)
|
||||
{
|
||||
position = RVec3(-4.0f + 8.0f * j, 2.0f + 3.0f * i, -20.0f);
|
||||
rotation = Quat::sRotation(Vec3::sAxisX(), 0.5f * JPH_PI);
|
||||
}
|
||||
else
|
||||
{
|
||||
position = RVec3(0, 2.0f + 3.0f * i, -20.0f - 4.0f + 8.0f * j);
|
||||
rotation = Quat::sRotation(Vec3::sAxisZ(), 0.5f * JPH_PI);
|
||||
}
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(long_capsule, position, rotation, EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
}
|
||||
}
|
||||
}
|
||||
16
lib/All/JoltPhysics/Samples/Tests/Shapes/CapsuleShapeTest.h
Normal file
16
lib/All/JoltPhysics/Samples/Tests/Shapes/CapsuleShapeTest.h
Normal file
@@ -0,0 +1,16 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
|
||||
class CapsuleShapeTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, CapsuleShapeTest)
|
||||
|
||||
// See: Test
|
||||
virtual void Initialize() override;
|
||||
};
|
||||
124
lib/All/JoltPhysics/Samples/Tests/Shapes/ConvexHullShapeTest.cpp
Normal file
124
lib/All/JoltPhysics/Samples/Tests/Shapes/ConvexHullShapeTest.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/Shapes/ConvexHullShapeTest.h>
|
||||
#include <Jolt/Physics/Collision/Shape/ConvexHullShape.h>
|
||||
#include <Jolt/Physics/Body/BodyCreationSettings.h>
|
||||
#include <Layers.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(ConvexHullShapeTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(ConvexHullShapeTest, Test)
|
||||
}
|
||||
|
||||
void ConvexHullShapeTest::Initialize()
|
||||
{
|
||||
// Floor
|
||||
CreateFloor();
|
||||
|
||||
// Create tetrahedron
|
||||
Array<Vec3> tetrahedron;
|
||||
tetrahedron.push_back(Vec3(-5, 0, -5));
|
||||
tetrahedron.push_back(Vec3(0, 0, 5));
|
||||
tetrahedron.push_back(Vec3(5, 0, -5));
|
||||
tetrahedron.push_back(Vec3(0, -5, 0));
|
||||
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(new ConvexHullShapeSettings(tetrahedron), RVec3(0, 10, 0), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
|
||||
// Create box
|
||||
Array<Vec3> box;
|
||||
box.push_back(Vec3(5, 5, 5));
|
||||
box.push_back(Vec3(-5, 5, 5));
|
||||
box.push_back(Vec3(5, -5, 5));
|
||||
box.push_back(Vec3(-5, -5, 5));
|
||||
box.push_back(Vec3(5, 5, -5));
|
||||
box.push_back(Vec3(-5, 5, -5));
|
||||
box.push_back(Vec3(5, -5, -5));
|
||||
box.push_back(Vec3(-5, -5, -5));
|
||||
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(new ConvexHullShapeSettings(box), RVec3(20, 10, 0), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
|
||||
// Add a sphere of many points
|
||||
Array<Vec3> sphere;
|
||||
for (float theta = 0.0f; theta <= JPH_PI; theta += JPH_PI / 20.0f)
|
||||
for (float phi = 0.0f; phi <= 2.0f * JPH_PI; phi += 2.0f * JPH_PI / 20.0f)
|
||||
sphere.push_back(5.0f * Vec3::sUnitSpherical(theta, phi));
|
||||
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(new ConvexHullShapeSettings(sphere), RVec3(40, 10, 0), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
|
||||
// Add a tapered cylinder of many points
|
||||
Array<Vec3> tapered_cylinder;
|
||||
for (float theta = 0.0f; theta <= 2.0f * JPH_PI; theta += JPH_PI / 128.0f)
|
||||
{
|
||||
tapered_cylinder.push_back(4.0f * Vec3(-0.1f, Sin(theta), Cos(theta)));
|
||||
tapered_cylinder.push_back(4.5f * Vec3(0.1f, Sin(theta), Cos(theta)));
|
||||
}
|
||||
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(new ConvexHullShapeSettings(tapered_cylinder), RVec3(60, 10, 0), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
|
||||
// Create convex hull with on one side nearly coplanar faces
|
||||
Array<Vec3> coplanar;
|
||||
coplanar.push_back(Vec3(1.04298747f, 4.68531752f, 0.858853102f));
|
||||
coplanar.push_back(Vec3(-1.00753999f, 4.63935566f, -0.959064901f));
|
||||
coplanar.push_back(Vec3(-1.01861656f, 4.72096348f, 0.846121550f));
|
||||
coplanar.push_back(Vec3(-2.37996006f, 1.26311386f, -1.10994697f));
|
||||
coplanar.push_back(Vec3(0.213164970f, 0.0198628306f, -1.70677519f));
|
||||
coplanar.push_back(Vec3(-2.27295995f, -0.899001241f, -0.472913086f));
|
||||
coplanar.push_back(Vec3(-1.85078228f, -1.25204790f, 2.42339849f));
|
||||
coplanar.push_back(Vec3(1.91183412f, -1.25204790f, 2.42339849f));
|
||||
coplanar.push_back(Vec3(-2.75279832f, 3.25019693f, 1.67055058f));
|
||||
coplanar.push_back(Vec3(-0.0697868019f, -2.78841114f, -0.422013819f));
|
||||
coplanar.push_back(Vec3(2.26410985f, -0.918261647f, -0.493922710f));
|
||||
coplanar.push_back(Vec3(0.765828013f, -2.82050991f, 1.91100550f));
|
||||
coplanar.push_back(Vec3(2.33326006f, 1.26643038f, -1.18808103f));
|
||||
coplanar.push_back(Vec3(-0.591650009f, 2.27845216f, -1.87628603f));
|
||||
coplanar.push_back(Vec3(-2.22145009f, 3.04359150f, 0.234738767f));
|
||||
coplanar.push_back(Vec3(-1.00753999f, 4.39097166f, -1.27783847f));
|
||||
coplanar.push_back(Vec3(0.995577991f, 4.39734173f, -1.27900386f));
|
||||
coplanar.push_back(Vec3(0.995577991f, 4.64572525f, -0.960230291f));
|
||||
coplanar.push_back(Vec3(2.74527335f, 3.06491613f, 1.77647924f));
|
||||
coplanar.push_back(Vec3(-1.53122997f, -2.18120861f, 2.31516361f));
|
||||
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(new ConvexHullShapeSettings(coplanar), RVec3(80, 10, 0), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
|
||||
// Bodies with random convex shapes
|
||||
default_random_engine random;
|
||||
uniform_real_distribution<float> hull_size(0.1f, 10.0f);
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
// Create random points
|
||||
Array<Vec3> points;
|
||||
for (int j = 0; j < 20; ++j)
|
||||
points.push_back(hull_size(random) * Vec3::sRandom(random));
|
||||
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(new ConvexHullShapeSettings(points), RVec3(-90.0f + i * 18.0f, 10, 20), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
}
|
||||
|
||||
// Bodies with random convex polygons (this is not something you should be doing, but this tests the 2D convex hull shape generation and allows you to test the probe against them)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
// Create random points
|
||||
Array<Vec3> points;
|
||||
for (int j = 0; j < 20; ++j)
|
||||
{
|
||||
Vec3 v = hull_size(random) * Vec3::sRandom(random);
|
||||
v.SetZ(0.0f);
|
||||
points.push_back(v);
|
||||
}
|
||||
|
||||
// Convex hull needs to be created with convex radius of 0 because the shape has no volume, so we cannot move the planes backwards to make space for the convex radius
|
||||
Ref<ShapeSettings> shape_settings = new ConvexHullShapeSettings(points, 0.0f);
|
||||
|
||||
BodyCreationSettings creation_settings(shape_settings, RVec3(-90.0f + i * 18.0f, 10, 40), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING);
|
||||
|
||||
// The polygon has no volume, so we need to provide a dummy mass and inertia for this shape
|
||||
creation_settings.mOverrideMassProperties = EOverrideMassProperties::MassAndInertiaProvided;
|
||||
creation_settings.mMassPropertiesOverride.mMass = 1.0f;
|
||||
creation_settings.mMassPropertiesOverride.mInertia = Mat44::sIdentity();
|
||||
|
||||
mBodyInterface->CreateAndAddBody(creation_settings, EActivation::Activate);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
|
||||
class ConvexHullShapeTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, ConvexHullShapeTest)
|
||||
|
||||
// See: Test
|
||||
virtual void Initialize() override;
|
||||
};
|
||||
@@ -0,0 +1,55 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/Shapes/CylinderShapeTest.h>
|
||||
#include <Jolt/Physics/Collision/Shape/CylinderShape.h>
|
||||
#include <Jolt/Physics/Body/BodyCreationSettings.h>
|
||||
#include <Layers.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(CylinderShapeTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(CylinderShapeTest, Test)
|
||||
}
|
||||
|
||||
void CylinderShapeTest::Initialize()
|
||||
{
|
||||
// Floor
|
||||
CreateFloor();
|
||||
|
||||
// Cylinder on flat part
|
||||
RefConst<Shape> big_cylinder = new CylinderShape(2.5f, 2);
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(big_cylinder, RVec3(0, 10, 0), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
|
||||
// Cylinder on round part
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(big_cylinder, RVec3(10, 10, 0), Quat::sRotation(Vec3::sAxisX(), 0.5f * JPH_PI), EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
|
||||
// Tower of cylinders
|
||||
RefConst<Shape> long_cylinder = new CylinderShape(5, 1);
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
for (int j = 0; j < 2; ++j)
|
||||
{
|
||||
RVec3 position;
|
||||
Quat rotation;
|
||||
if (i & 1)
|
||||
{
|
||||
position = RVec3(-4.0f + 8.0f * j, 2.0f + 3.0f * i, -20.0f);
|
||||
rotation = Quat::sRotation(Vec3::sAxisX(), 0.5f * JPH_PI);
|
||||
}
|
||||
else
|
||||
{
|
||||
position = RVec3(0, 2.0f + 3.0f * i, -20.0f - 4.0f + 8.0f * j);
|
||||
rotation = Quat::sRotation(Vec3::sAxisZ(), 0.5f * JPH_PI);
|
||||
}
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(long_cylinder, position, rotation, EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
}
|
||||
}
|
||||
|
||||
// Tower of thin cylinders
|
||||
RefConst<Shape> thin_cylinder = new CylinderShape(0.1f, 5.0f);
|
||||
for (int i = 0; i < 10; ++i)
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(thin_cylinder, RVec3(20.0f, 10.0f - 1.0f * i, 0), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
}
|
||||
16
lib/All/JoltPhysics/Samples/Tests/Shapes/CylinderShapeTest.h
Normal file
16
lib/All/JoltPhysics/Samples/Tests/Shapes/CylinderShapeTest.h
Normal file
@@ -0,0 +1,16 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
|
||||
class CylinderShapeTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, CylinderShapeTest)
|
||||
|
||||
// See: Test
|
||||
virtual void Initialize() override;
|
||||
};
|
||||
@@ -0,0 +1,125 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2023 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/Shapes/DeformedHeightFieldShapeTest.h>
|
||||
#include <External/Perlin.h>
|
||||
#include <Jolt/Physics/Body/BodyCreationSettings.h>
|
||||
#include <Jolt/Physics/Collision/Shape/SphereShape.h>
|
||||
#include <Jolt/Physics/Collision/ShapeCast.h>
|
||||
#include <Jolt/Physics/Collision/CollisionCollectorImpl.h>
|
||||
#include <Layers.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(DeformedHeightFieldShapeTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(DeformedHeightFieldShapeTest, Test)
|
||||
}
|
||||
|
||||
void DeformedHeightFieldShapeTest::Initialize()
|
||||
{
|
||||
constexpr float cCellSize = 1.0f;
|
||||
constexpr float cMaxHeight = 2.5f;
|
||||
constexpr float cSphereRadius = 2.0f;
|
||||
|
||||
// Create height samples
|
||||
mHeightSamples.resize(cSampleCount * cSampleCount);
|
||||
for (int y = 0; y < cSampleCount; ++y)
|
||||
for (int x = 0; x < cSampleCount; ++x)
|
||||
mHeightSamples[y * cSampleCount + x] = cMaxHeight * PerlinNoise3(float(x) * 8.0f / cSampleCount, 0, float(y) * 8.0f / cSampleCount, 256, 256, 256);
|
||||
|
||||
// Determine scale and offset of the terrain
|
||||
Vec3 offset(-0.5f * cCellSize * cSampleCount, 0, -0.5f * cCellSize * cSampleCount);
|
||||
Vec3 scale(cCellSize, 1.0f, cCellSize);
|
||||
|
||||
// Create height field
|
||||
HeightFieldShapeSettings settings(mHeightSamples.data(), offset, scale, cSampleCount);
|
||||
settings.mBlockSize = cBlockSize;
|
||||
settings.mBitsPerSample = 8;
|
||||
settings.mMinHeightValue = -15.0f;
|
||||
mHeightField = StaticCast<HeightFieldShape>(settings.Create().Get());
|
||||
mHeightFieldID = mBodyInterface->CreateAndAddBody(BodyCreationSettings(mHeightField, RVec3::sZero(), Quat::sIdentity(), EMotionType::Static, Layers::NON_MOVING), EActivation::DontActivate);
|
||||
|
||||
// Spheres on top of the terrain
|
||||
RefConst<Shape> sphere_shape = new SphereShape(cSphereRadius);
|
||||
for (float t = 0.2f; t < 12.4f; t += 0.1f)
|
||||
{
|
||||
// Get the center of the path
|
||||
Vec3 center = offset + GetPathCenter(t);
|
||||
|
||||
// Cast a ray onto the terrain
|
||||
RShapeCast shape_cast(sphere_shape, Vec3::sOne(), RMat44::sTranslation(RVec3(0, 10, 0) + center), Vec3(0, -20, 0));
|
||||
ClosestHitCollisionCollector<CastShapeCollector> collector;
|
||||
mPhysicsSystem->GetNarrowPhaseQuery().CastShape(shape_cast, { }, RVec3::sZero(), collector);
|
||||
if (collector.mHit.mBodyID2 == mHeightFieldID)
|
||||
{
|
||||
// Create sphere on terrain
|
||||
BodyCreationSettings bcs(sphere_shape, shape_cast.GetPointOnRay(collector.mHit.mFraction), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING);
|
||||
mBodyInterface->CreateAndAddBody(bcs, EActivation::DontActivate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vec3 DeformedHeightFieldShapeTest::GetPathCenter(float inTime) const
|
||||
{
|
||||
constexpr float cOffset = 5.0f;
|
||||
constexpr float cRadiusX = 60.0f;
|
||||
constexpr float cRadiusY = 25.0f;
|
||||
constexpr float cFallOff = 0.1f;
|
||||
constexpr float cAngularSpeed = 2.0f;
|
||||
constexpr float cDisplacementSpeed = 10.0f;
|
||||
|
||||
float fall_off = exp(-cFallOff * inTime);
|
||||
float angle = cAngularSpeed * inTime;
|
||||
return Vec3(cRadiusX * Cos(angle) * fall_off + 64.0f, 0, cOffset + cDisplacementSpeed * inTime + cRadiusY * Sin(angle) * fall_off);
|
||||
}
|
||||
|
||||
void DeformedHeightFieldShapeTest::PrePhysicsUpdate(const PreUpdateParams &inParams)
|
||||
{
|
||||
constexpr float cPitRadius = 6.0f;
|
||||
constexpr float cPitHeight = 1.0f;
|
||||
constexpr float cSpeedScale = 2.0f;
|
||||
|
||||
// Calculate center of pit
|
||||
Vec3 center = GetPathCenter(cSpeedScale * mTime);
|
||||
mTime += inParams.mDeltaTime;
|
||||
|
||||
// Calculate affected area
|
||||
int start_x = max((int)floor(center.GetX() - cPitRadius) & ~cBlockMask, 0);
|
||||
int start_y = max((int)floor(center.GetZ() - cPitRadius) & ~cBlockMask, 0);
|
||||
int count_x = min(((int)ceil(center.GetX() + cPitRadius) + cBlockMask) & ~cBlockMask, cSampleCount) - start_x;
|
||||
int count_y = min(((int)ceil(center.GetZ() + cPitRadius) + cBlockMask) & ~cBlockMask, cSampleCount) - start_y;
|
||||
|
||||
if (count_x > 0 && count_y > 0)
|
||||
{
|
||||
// Remember COM before we change the height field
|
||||
Vec3 old_com = mHeightField->GetCenterOfMass();
|
||||
|
||||
// A function to calculate the delta height at a certain distance from the center of the pit
|
||||
constexpr float cHalfPi = 0.5f * JPH_PI;
|
||||
auto pit_shape = [=](float inDistanceX, float inDistanceY) { return Cos(min(sqrt(Square(inDistanceX) + Square(inDistanceY)) * cHalfPi / cPitRadius, cHalfPi)); };
|
||||
|
||||
AABox affected_area;
|
||||
for (int y = 0; y < count_y; ++y)
|
||||
for (int x = 0; x < count_x; ++x)
|
||||
{
|
||||
// Update the height field
|
||||
float delta = pit_shape(float(start_x) + x - center.GetX(), float(start_y) + y - center.GetZ()) * cPitHeight;
|
||||
mHeightSamples[(start_y + y) * cSampleCount + start_x + x] -= delta;
|
||||
|
||||
// Keep track of affected area to wake up bodies
|
||||
affected_area.Encapsulate(mHeightField->GetPosition(start_x + x, start_y + y));
|
||||
}
|
||||
mHeightField->SetHeights(start_x, start_y, count_x, count_y, mHeightSamples.data() + start_y * cSampleCount + start_x, cSampleCount, *mTempAllocator);
|
||||
|
||||
// Notify the shape that it has changed its bounding box
|
||||
mBodyInterface->NotifyShapeChanged(mHeightFieldID, old_com, false, EActivation::DontActivate);
|
||||
|
||||
// Activate bodies in the affected area (a change in the height field doesn't wake up bodies)
|
||||
affected_area.ExpandBy(Vec3::sReplicate(0.1f));
|
||||
DefaultBroadPhaseLayerFilter broadphase_layer_filter = mPhysicsSystem->GetDefaultBroadPhaseLayerFilter(Layers::MOVING);
|
||||
DefaultObjectLayerFilter object_layer_filter = mPhysicsSystem->GetDefaultLayerFilter(Layers::MOVING);
|
||||
mBodyInterface->ActivateBodiesInAABox(affected_area, broadphase_layer_filter, object_layer_filter);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2023 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
#include <Jolt/Physics/Collision/Shape/HeightFieldShape.h>
|
||||
|
||||
class DeformedHeightFieldShapeTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, DeformedHeightFieldShapeTest)
|
||||
|
||||
// Description of the test
|
||||
virtual const char * GetDescription() const override
|
||||
{
|
||||
return "Shows how to deform a height field shape after it has been created.";
|
||||
}
|
||||
|
||||
// Initialize the test
|
||||
virtual void Initialize() override;
|
||||
|
||||
// Update the test, called before the physics update
|
||||
virtual void PrePhysicsUpdate(const PreUpdateParams &inParams) override;
|
||||
|
||||
// Test will never be deterministic since we're modifying the height field shape and not saving it
|
||||
virtual bool IsDeterministic() const override { return false; }
|
||||
|
||||
private:
|
||||
// Get the center of the path at time inTime, this follows a path that resembles the Jolt logo
|
||||
Vec3 GetPathCenter(float inTime) const;
|
||||
|
||||
// Size of the terrain
|
||||
static constexpr int cSampleCount = 128;
|
||||
|
||||
// Size of a block in the terrain
|
||||
static constexpr int cBlockSize = 4;
|
||||
|
||||
// Bits to mask out index within a block
|
||||
static constexpr int cBlockMask = cBlockSize - 1;
|
||||
|
||||
// The list of original height samples, we keep this to avoid precision loss of repeatedly decompressing and recompressing height samples
|
||||
Array<float> mHeightSamples;
|
||||
|
||||
// The height field shape
|
||||
Ref<HeightFieldShape> mHeightField;
|
||||
|
||||
// ID of the height field body
|
||||
BodyID mHeightFieldID;
|
||||
|
||||
// Current time
|
||||
float mTime = 0.0f;
|
||||
};
|
||||
24
lib/All/JoltPhysics/Samples/Tests/Shapes/EmptyShapeTest.cpp
Normal file
24
lib/All/JoltPhysics/Samples/Tests/Shapes/EmptyShapeTest.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/Shapes/EmptyShapeTest.h>
|
||||
#include <Jolt/Physics/Collision/Shape/EmptyShape.h>
|
||||
#include <Jolt/Physics/Body/BodyCreationSettings.h>
|
||||
#include <Layers.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(EmptyShapeTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(EmptyShapeTest, Test)
|
||||
}
|
||||
|
||||
void EmptyShapeTest::Initialize()
|
||||
{
|
||||
// Floor
|
||||
CreateFloor();
|
||||
|
||||
// Empty shape
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(new EmptyShape(), RVec3(0, 10, 0), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
}
|
||||
16
lib/All/JoltPhysics/Samples/Tests/Shapes/EmptyShapeTest.h
Normal file
16
lib/All/JoltPhysics/Samples/Tests/Shapes/EmptyShapeTest.h
Normal file
@@ -0,0 +1,16 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
|
||||
class EmptyShapeTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, EmptyShapeTest)
|
||||
|
||||
// See: Test
|
||||
virtual void Initialize() override;
|
||||
};
|
||||
@@ -0,0 +1,265 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/Shapes/HeightFieldShapeTest.h>
|
||||
#include <External/Perlin.h>
|
||||
#include <Jolt/Physics/Collision/Shape/BoxShape.h>
|
||||
#include <Jolt/Physics/Body/BodyCreationSettings.h>
|
||||
#include <Jolt/Physics/Collision/PhysicsMaterialSimple.h>
|
||||
#include <Jolt/Physics/Collision/CastResult.h>
|
||||
#include <Jolt/Physics/Collision/RayCast.h>
|
||||
#include <Application/DebugUI.h>
|
||||
#include <Utils/ReadData.h>
|
||||
#include <Utils/Log.h>
|
||||
#include <Utils/DebugRendererSP.h>
|
||||
#include <Layers.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(HeightFieldShapeTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(HeightFieldShapeTest, Test)
|
||||
}
|
||||
|
||||
static int sTerrainType = 0;
|
||||
|
||||
static const char *sTerrainTypes[] = {
|
||||
"Procedural Terrain 2^N",
|
||||
"Procedural Terrain 2^N + 1",
|
||||
"Heightfield 1",
|
||||
"Flat 2^N",
|
||||
"Flat 2^N + 1",
|
||||
"No Collision 2^N",
|
||||
"No Collision 2^N + 1"
|
||||
};
|
||||
|
||||
void HeightFieldShapeTest::Initialize()
|
||||
{
|
||||
if (sTerrainType == 0 || sTerrainType == 1)
|
||||
{
|
||||
const int n = sTerrainType == 0? 128 : 129;
|
||||
const float cell_size = 1.0f;
|
||||
const float max_height = 5.0f;
|
||||
|
||||
// Create height samples
|
||||
mTerrainSize = n;
|
||||
mTerrain.resize(n * n);
|
||||
for (int y = 0; y < n; ++y)
|
||||
for (int x = 0; x < n; ++x)
|
||||
mTerrain[y * n + x] = max_height * PerlinNoise3(float(x) * 8.0f / n, 0, float(y) * 8.0f / n, 256, 256, 256);
|
||||
|
||||
// Make some holes
|
||||
mTerrain[2 * n + 2] = HeightFieldShapeConstants::cNoCollisionValue;
|
||||
for (int y = 4; y < 33; ++y)
|
||||
for (int x = 4; x < 33; ++x)
|
||||
mTerrain[y * n + x] = HeightFieldShapeConstants::cNoCollisionValue;
|
||||
|
||||
// Make material indices
|
||||
uint8 max_material_index = 0;
|
||||
mMaterialIndices.resize(Square(n - 1));
|
||||
for (int y = 0; y < n - 1; ++y)
|
||||
for (int x = 0; x < n - 1; ++x)
|
||||
{
|
||||
uint8 material_index = uint8(round((Vec3(x * cell_size, 0, y * cell_size) - Vec3(n * cell_size / 2, 0, n * cell_size / 2)).Length() / 10.0f));
|
||||
max_material_index = max(max_material_index, material_index);
|
||||
mMaterialIndices[y * (n - 1) + x] = material_index;
|
||||
}
|
||||
|
||||
// Mark the corners to validate that materials and heights match
|
||||
mTerrain[0] = 0.0f;
|
||||
mTerrain[n - 1] = 10.0f;
|
||||
mTerrain[(n - 1) * n] = 20.0f;
|
||||
mTerrain[n * n - 1] = 30.0f;
|
||||
mMaterialIndices[0] = 0;
|
||||
mMaterialIndices[n - 2] = 1;
|
||||
mMaterialIndices[(n - 2) * (n - 1)] = 2;
|
||||
mMaterialIndices[Square(n - 1) - 1] = 3;
|
||||
|
||||
// Create materials
|
||||
for (uint8 i = 0; i <= max_material_index; ++i)
|
||||
mMaterials.push_back(new PhysicsMaterialSimple("Material " + ConvertToString(uint(i)), Color::sGetDistinctColor(i)));
|
||||
|
||||
// Determine scale and offset (deliberately apply extra offset and scale in Y direction)
|
||||
mTerrainOffset = Vec3(-0.5f * cell_size * n, -2.0f, -0.5f * cell_size * n);
|
||||
mTerrainScale = Vec3(cell_size, 1.5f, cell_size);
|
||||
}
|
||||
else if (sTerrainType == 2)
|
||||
{
|
||||
const int n = 1024;
|
||||
const float cell_size = 0.5f;
|
||||
|
||||
// Get height samples
|
||||
Array<uint8> data = ReadData("heightfield1.bin");
|
||||
if (data.size() != sizeof(float) * n * n)
|
||||
FatalError("Invalid file size");
|
||||
mTerrainSize = n;
|
||||
mTerrain.resize(n * n);
|
||||
memcpy(mTerrain.data(), data.data(), n * n * sizeof(float));
|
||||
|
||||
// Determine scale and offset
|
||||
mTerrainOffset = Vec3(-0.5f * cell_size * n, 0.0f, -0.5f * cell_size * n);
|
||||
mTerrainScale = Vec3(cell_size, 1.0f, cell_size);
|
||||
}
|
||||
else if (sTerrainType == 3 || sTerrainType == 4)
|
||||
{
|
||||
const int n = sTerrainType == 3? 128 : 129;
|
||||
const float cell_size = 1.0f;
|
||||
const float height = JPH_PI;
|
||||
|
||||
// Determine scale and offset
|
||||
mTerrainOffset = Vec3(-0.5f * cell_size * n, 0.0f, -0.5f * cell_size * n);
|
||||
mTerrainScale = Vec3(cell_size, 1.0f, cell_size);
|
||||
|
||||
// Mark the entire terrain as single height
|
||||
mTerrainSize = n;
|
||||
mTerrain.resize(n * n);
|
||||
for (float &v : mTerrain)
|
||||
v = height;
|
||||
}
|
||||
else if (sTerrainType == 5 || sTerrainType == 6)
|
||||
{
|
||||
const int n = sTerrainType == 4? 128 : 129;
|
||||
const float cell_size = 1.0f;
|
||||
|
||||
// Determine scale and offset
|
||||
mTerrainOffset = Vec3(-0.5f * cell_size * n, 0.0f, -0.5f * cell_size * n);
|
||||
mTerrainScale = Vec3(cell_size, 1.0f, cell_size);
|
||||
|
||||
// Mark the entire terrain as no collision
|
||||
mTerrainSize = n;
|
||||
mTerrain.resize(n * n);
|
||||
for (float &v : mTerrain)
|
||||
v = HeightFieldShapeConstants::cNoCollisionValue;
|
||||
}
|
||||
|
||||
// Create height field
|
||||
HeightFieldShapeSettings settings(mTerrain.data(), mTerrainOffset, mTerrainScale, mTerrainSize, mMaterialIndices.data(), mMaterials);
|
||||
settings.mBlockSize = 1 << sBlockSizeShift;
|
||||
settings.mBitsPerSample = sBitsPerSample;
|
||||
mHeightField = StaticCast<HeightFieldShape>(settings.Create().Get());
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(mHeightField, RVec3::sZero(), Quat::sIdentity(), EMotionType::Static, Layers::NON_MOVING), EActivation::DontActivate);
|
||||
|
||||
// Validate it
|
||||
float max_diff = -1.0f;
|
||||
uint max_diff_x = 0, max_diff_y = 0;
|
||||
float min_height = FLT_MAX, max_height = -FLT_MAX, avg_diff = 0.0f;
|
||||
for (uint y = 0; y < mTerrainSize; ++y)
|
||||
for (uint x = 0; x < mTerrainSize; ++x)
|
||||
{
|
||||
float h1 = mTerrain[y * mTerrainSize + x];
|
||||
if (h1 != HeightFieldShapeConstants::cNoCollisionValue)
|
||||
{
|
||||
h1 = mTerrainOffset.GetY() + mTerrainScale.GetY() * h1;
|
||||
if (mHeightField->IsNoCollision(x, y))
|
||||
FatalError("No collision where there should be");
|
||||
float h2 = mHeightField->GetPosition(x, y).GetY();
|
||||
float diff = abs(h2 - h1);
|
||||
if (diff > max_diff)
|
||||
{
|
||||
max_diff = diff;
|
||||
max_diff_x = x;
|
||||
max_diff_y = y;
|
||||
}
|
||||
min_height = min(min_height, h1);
|
||||
max_height = max(max_height, h1);
|
||||
avg_diff += diff;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!mHeightField->IsNoCollision(x, y))
|
||||
FatalError("Collision where there shouldn't be");
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate relative error
|
||||
float rel_error = min_height < max_height? 100.0f * max_diff / (max_height - min_height) : 0.0f;
|
||||
|
||||
// Max error we expect given sBitsPerSample (normally the error should be much lower because we quantize relative to the block rather than the full height)
|
||||
float max_error = 0.5f * 100.0f / ((1 << sBitsPerSample) - 1);
|
||||
|
||||
// Calculate average
|
||||
avg_diff /= mTerrainSize * mTerrainSize;
|
||||
|
||||
// Calculate amount of memory used
|
||||
Shape::Stats stats = mHeightField->GetStats();
|
||||
|
||||
// Trace stats
|
||||
Trace("Block size: %d, bits per sample: %d, min height: %g, max height: %g, avg diff: %g, max diff: %g at (%d, %d), relative error: %g%%, size: %u bytes", 1 << sBlockSizeShift, sBitsPerSample, (double)min_height, (double)max_height, (double)avg_diff, (double)max_diff, max_diff_x, max_diff_y, (double)rel_error, stats.mSizeBytes);
|
||||
if (rel_error > max_error)
|
||||
FatalError("Error too big!");
|
||||
|
||||
// Determine terrain height
|
||||
RayCastResult result;
|
||||
RVec3 start(0, 1000, 0);
|
||||
Vec3 direction(0, -2000, 0);
|
||||
RRayCast ray { start, direction };
|
||||
if (mPhysicsSystem->GetNarrowPhaseQuery().CastRay(ray, result, SpecifiedBroadPhaseLayerFilter(BroadPhaseLayers::NON_MOVING), SpecifiedObjectLayerFilter(Layers::NON_MOVING)))
|
||||
mHitPos = ray.GetPointOnRay(result.mFraction);
|
||||
|
||||
// Dynamic body
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(new BoxShape(Vec3(0.5f, 1.0f, 2.0f)), mHitPos + Vec3(0, 10, 0), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
}
|
||||
|
||||
void HeightFieldShapeTest::PrePhysicsUpdate(const PreUpdateParams &inParams)
|
||||
{
|
||||
// Test the 'GetHeight' function and draw a marker on the surface
|
||||
Vec3 test_pos = Vec3(inParams.mCameraState.mPos) + 10.0f * inParams.mCameraState.mForward, surface_pos;
|
||||
SubShapeID sub_shape_id;
|
||||
if (mHeightField->ProjectOntoSurface(test_pos, surface_pos, sub_shape_id))
|
||||
{
|
||||
Vec3 surface_normal = mHeightField->GetSurfaceNormal(sub_shape_id, surface_pos);
|
||||
DrawMarkerSP(mDebugRenderer, surface_pos, Color::sWhite, 1.0f);
|
||||
DrawArrowSP(mDebugRenderer, surface_pos, surface_pos + surface_normal, Color::sRed, 0.1f);
|
||||
}
|
||||
|
||||
// Draw the original uncompressed terrain
|
||||
if (sShowOriginalTerrain)
|
||||
for (uint y = 0; y < mTerrainSize; ++y)
|
||||
for (uint x = 0; x < mTerrainSize; ++x)
|
||||
{
|
||||
// Get original height
|
||||
float h = mTerrain[y * mTerrainSize + x];
|
||||
if (h == HeightFieldShapeConstants::cNoCollisionValue)
|
||||
continue;
|
||||
|
||||
// Get original position
|
||||
Vec3 original = mTerrainOffset + mTerrainScale * Vec3(float(x), h, float(y));
|
||||
|
||||
// Get compressed position
|
||||
Vec3 compressed = mHeightField->GetPosition(x, y);
|
||||
|
||||
// Draw marker that is red when error is too big and green when not
|
||||
const float cMaxError = 0.1f;
|
||||
float error = (original - compressed).Length();
|
||||
uint8 c = uint8(round(255.0f * min(error / cMaxError, 1.0f)));
|
||||
DrawMarkerSP(mDebugRenderer, original, Color(c, 255 - c, 0, 255), 0.1f);
|
||||
}
|
||||
}
|
||||
|
||||
void HeightFieldShapeTest::GetInitialCamera(CameraState &ioState) const
|
||||
{
|
||||
// Correct camera pos for hit position
|
||||
ioState.mPos += mHitPos;
|
||||
}
|
||||
|
||||
void HeightFieldShapeTest::CreateSettingsMenu(DebugUI *inUI, UIElement *inSubMenu)
|
||||
{
|
||||
inUI->CreateTextButton(inSubMenu, "Select Terrain", [this, inUI]() {
|
||||
UIElement *terrain_name = inUI->CreateMenu();
|
||||
for (uint i = 0; i < size(sTerrainTypes); ++i)
|
||||
inUI->CreateTextButton(terrain_name, sTerrainTypes[i], [this, i]() { sTerrainType = i; RestartTest(); });
|
||||
inUI->ShowMenu(terrain_name);
|
||||
});
|
||||
|
||||
inUI->CreateTextButton(inSubMenu, "Configuration Settings", [this, inUI]() {
|
||||
UIElement *terrain_settings = inUI->CreateMenu();
|
||||
inUI->CreateComboBox(terrain_settings, "Block Size", { "2", "4", "8" }, sBlockSizeShift - 1, [=](int inItem) { sBlockSizeShift = inItem + 1; });
|
||||
inUI->CreateSlider(terrain_settings, "Bits Per Sample", (float)sBitsPerSample, 1.0f, 8.0f, 1.0f, [=](float inValue) { sBitsPerSample = (int)inValue; });
|
||||
inUI->CreateTextButton(terrain_settings, "Accept", [this]() { RestartTest(); });
|
||||
inUI->ShowMenu(terrain_settings);
|
||||
});
|
||||
|
||||
inUI->CreateCheckBox(inSubMenu, "Show Original Terrain", sShowOriginalTerrain, [](UICheckBox::EState inState) { sShowOriginalTerrain = inState == UICheckBox::STATE_CHECKED; });
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
#include <Jolt/Physics/Collision/Shape/HeightFieldShape.h>
|
||||
|
||||
class HeightFieldShapeTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, HeightFieldShapeTest)
|
||||
|
||||
// Initialize the test
|
||||
virtual void Initialize() override;
|
||||
|
||||
// Update the test, called before the physics update
|
||||
virtual void PrePhysicsUpdate(const PreUpdateParams &inParams) override;
|
||||
|
||||
// Override to specify the initial camera state (local to GetCameraPivot)
|
||||
virtual void GetInitialCamera(CameraState &ioState) const override;
|
||||
|
||||
// Optional settings menu
|
||||
virtual bool HasSettingsMenu() const override { return true; }
|
||||
virtual void CreateSettingsMenu(DebugUI *inUI, UIElement *inSubMenu) override;
|
||||
|
||||
// Original (uncompressed) terrain
|
||||
Array<float> mTerrain;
|
||||
PhysicsMaterialList mMaterials;
|
||||
Array<uint8> mMaterialIndices;
|
||||
uint mTerrainSize;
|
||||
Vec3 mTerrainOffset;
|
||||
Vec3 mTerrainScale;
|
||||
|
||||
// Block size = 1 << sBlockSizeShift
|
||||
inline static int sBlockSizeShift = 2;
|
||||
|
||||
// Bits per sample
|
||||
inline static int sBitsPerSample = 8;
|
||||
|
||||
// Draw the terrain
|
||||
inline static bool sShowOriginalTerrain = false;
|
||||
|
||||
RefConst<HeightFieldShape> mHeightField;
|
||||
|
||||
RVec3 mHitPos = RVec3::sZero();
|
||||
};
|
||||
57
lib/All/JoltPhysics/Samples/Tests/Shapes/MeshShapeTest.cpp
Normal file
57
lib/All/JoltPhysics/Samples/Tests/Shapes/MeshShapeTest.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/Shapes/MeshShapeTest.h>
|
||||
#include <Jolt/Physics/Collision/Shape/BoxShape.h>
|
||||
#include <Jolt/Physics/Collision/Shape/MeshShape.h>
|
||||
#include <Jolt/Physics/Collision/PhysicsMaterialSimple.h>
|
||||
#include <Jolt/Geometry/Triangle.h>
|
||||
#include <Jolt/Physics/Body/BodyCreationSettings.h>
|
||||
#include <Layers.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(MeshShapeTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(MeshShapeTest, Test)
|
||||
}
|
||||
|
||||
void MeshShapeTest::Initialize()
|
||||
{
|
||||
// Create regular grid of triangles
|
||||
uint32 max_material_index = 0;
|
||||
TriangleList triangles;
|
||||
for (int x = -10; x < 10; ++x)
|
||||
for (int z = -10; z < 10; ++z)
|
||||
{
|
||||
float x1 = 10.0f * x;
|
||||
float z1 = 10.0f * z;
|
||||
float x2 = x1 + 10.0f;
|
||||
float z2 = z1 + 10.0f;
|
||||
|
||||
Float3 v1 = Float3(x1, 0, z1);
|
||||
Float3 v2 = Float3(x2, 0, z1);
|
||||
Float3 v3 = Float3(x1, 0, z2);
|
||||
Float3 v4 = Float3(x2, 0, z2);
|
||||
|
||||
uint32 material_index = uint32((Vec3(v1) + Vec3(v2) + Vec3(v3) + Vec3(v4)).Length() / 40.0f);
|
||||
max_material_index = max(max_material_index, material_index);
|
||||
triangles.push_back(Triangle(v1, v3, v4, material_index));
|
||||
triangles.push_back(Triangle(v1, v4, v2, material_index));
|
||||
}
|
||||
|
||||
// Create materials
|
||||
PhysicsMaterialList materials;
|
||||
for (uint i = 0; i <= max_material_index; ++i)
|
||||
materials.push_back(new PhysicsMaterialSimple("Material " + ConvertToString(i), Color::sGetDistinctColor(i)));
|
||||
|
||||
// Floor
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(new MeshShapeSettings(triangles, std::move(materials)), RVec3::sZero(), Quat::sRotation(Vec3::sAxisX(), 0.25f * JPH_PI), EMotionType::Static, Layers::NON_MOVING), EActivation::DontActivate);
|
||||
|
||||
// 1 body with zero friction to test active edge detection
|
||||
Ref<BoxShape> box_shape = new BoxShape(Vec3(2.0f, 2.0f, 2.0f), cDefaultConvexRadius, new PhysicsMaterialSimple("Box Material", Color::sYellow));
|
||||
Body &body = *mBodyInterface->CreateBody(BodyCreationSettings(box_shape, RVec3(0, 55.0f, -50.0f), Quat::sRotation(Vec3::sAxisX(), 0.25f * JPH_PI), EMotionType::Dynamic, Layers::MOVING));
|
||||
body.SetFriction(0.0f);
|
||||
mBodyInterface->AddBody(body.GetID(), EActivation::Activate);
|
||||
}
|
||||
16
lib/All/JoltPhysics/Samples/Tests/Shapes/MeshShapeTest.h
Normal file
16
lib/All/JoltPhysics/Samples/Tests/Shapes/MeshShapeTest.h
Normal file
@@ -0,0 +1,16 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
|
||||
class MeshShapeTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, MeshShapeTest)
|
||||
|
||||
// See: Test
|
||||
virtual void Initialize() override;
|
||||
};
|
||||
@@ -0,0 +1,95 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/Shapes/MeshShapeUserDataTest.h>
|
||||
#include <Jolt/Physics/Collision/Shape/BoxShape.h>
|
||||
#include <Jolt/Physics/Collision/Shape/MeshShape.h>
|
||||
#include <Jolt/Physics/Collision/Shape/StaticCompoundShape.h>
|
||||
#include <Jolt/Physics/Collision/RayCast.h>
|
||||
#include <Jolt/Physics/Collision/CastResult.h>
|
||||
#include <Jolt/Geometry/Triangle.h>
|
||||
#include <Jolt/Physics/Body/BodyCreationSettings.h>
|
||||
#include <Layers.h>
|
||||
#include <Renderer/DebugRendererImp.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(MeshShapeUserDataTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(MeshShapeUserDataTest, Test)
|
||||
}
|
||||
|
||||
void MeshShapeUserDataTest::Initialize()
|
||||
{
|
||||
std::default_random_engine random;
|
||||
|
||||
// Create regular grid of triangles
|
||||
uint32 user_data = 0;
|
||||
TriangleList triangles[2];
|
||||
for (int x = -10; x < 10; ++x)
|
||||
for (int z = -10; z < 10; ++z)
|
||||
{
|
||||
float x1 = 10.0f * x;
|
||||
float z1 = 10.0f * z;
|
||||
float x2 = x1 + 10.0f;
|
||||
float z2 = z1 + 10.0f;
|
||||
|
||||
Float3 v1 = Float3(x1, 0, z1);
|
||||
Float3 v2 = Float3(x2, 0, z1);
|
||||
Float3 v3 = Float3(x1, 0, z2);
|
||||
Float3 v4 = Float3(x2, 0, z2);
|
||||
|
||||
triangles[random() & 1].push_back(Triangle(v1, v3, v4, 0, user_data++));
|
||||
triangles[random() & 1].push_back(Triangle(v1, v4, v2, 0, user_data++));
|
||||
}
|
||||
|
||||
// Create a compound with 2 meshes
|
||||
StaticCompoundShapeSettings compound_settings;
|
||||
compound_settings.SetEmbedded();
|
||||
for (TriangleList &t : triangles)
|
||||
{
|
||||
// Shuffle the triangles
|
||||
std::shuffle(t.begin(), t.end(), random);
|
||||
|
||||
// Create mesh
|
||||
MeshShapeSettings mesh_settings(t);
|
||||
mesh_settings.mPerTriangleUserData = true;
|
||||
compound_settings.AddShape(Vec3::sZero(), Quat::sIdentity(), mesh_settings.Create().Get());
|
||||
}
|
||||
|
||||
// Create body
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(&compound_settings, RVec3::sZero(), Quat::sRotation(Vec3::sAxisX(), 0.25f * JPH_PI), EMotionType::Static, Layers::NON_MOVING), EActivation::DontActivate);
|
||||
|
||||
// 1 body with zero friction
|
||||
BodyCreationSettings bcs(new BoxShape(Vec3::sReplicate(2.0f)), RVec3(0, 55.0f, -50.0f), Quat::sRotation(Vec3::sAxisX(), 0.25f * JPH_PI), EMotionType::Dynamic, Layers::MOVING);
|
||||
bcs.mFriction = 0.0f;
|
||||
bcs.mEnhancedInternalEdgeRemoval = true; // Needed because the 2 meshes have a lot of active edges
|
||||
mBodyInterface->CreateAndAddBody(bcs, EActivation::Activate);
|
||||
}
|
||||
|
||||
void MeshShapeUserDataTest::PrePhysicsUpdate(const PreUpdateParams &inParams)
|
||||
{
|
||||
// Cast a ray
|
||||
RayCastResult hit;
|
||||
RRayCast ray(inParams.mCameraState.mPos, inParams.mCameraState.mForward * 100.0f);
|
||||
mPhysicsSystem->GetNarrowPhaseQuery().CastRay(ray, hit);
|
||||
|
||||
// Get body (if there was a hit)
|
||||
BodyLockRead lock(mPhysicsSystem->GetBodyLockInterface(), hit.mBodyID);
|
||||
if (lock.SucceededAndIsInBroadPhase())
|
||||
{
|
||||
// Get the leaf shape (mesh shape in this case)
|
||||
SubShapeID remainder;
|
||||
const Shape *shape = lock.GetBody().GetShape()->GetLeafShape(hit.mSubShapeID2, remainder);
|
||||
if (shape->GetType() == EShapeType::Mesh)
|
||||
{
|
||||
// Get user data from the triangle that was hit
|
||||
uint32 user_data = static_cast<const MeshShape *>(shape)->GetTriangleUserData(remainder);
|
||||
|
||||
// Draw it on screen
|
||||
RVec3 hit_pos = ray.GetPointOnRay(hit.mFraction);
|
||||
mDebugRenderer->DrawText3D(hit_pos, StringFormat("UserData: %d", user_data).c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
|
||||
class MeshShapeUserDataTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, MeshShapeUserDataTest)
|
||||
|
||||
// Description of the test
|
||||
virtual const char *GetDescription() const override
|
||||
{
|
||||
return "Shows how to store per triangle user data in a mesh shape and how to retrieve it.";
|
||||
}
|
||||
|
||||
// See: Test
|
||||
virtual void Initialize() override;
|
||||
virtual void PrePhysicsUpdate(const PreUpdateParams &inParams) override;
|
||||
};
|
||||
@@ -0,0 +1,172 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/Shapes/MutableCompoundShapeTest.h>
|
||||
#include <Jolt/Physics/Collision/Shape/StaticCompoundShape.h>
|
||||
#include <Jolt/Physics/Collision/Shape/MutableCompoundShape.h>
|
||||
#include <Jolt/Physics/Collision/Shape/BoxShape.h>
|
||||
#include <Jolt/Physics/Collision/Shape/TaperedCapsuleShape.h>
|
||||
#include <Jolt/Physics/Collision/Shape/CylinderShape.h>
|
||||
#include <Jolt/Physics/Body/BodyCreationSettings.h>
|
||||
#include <Jolt/Core/StreamWrapper.h>
|
||||
#include <Layers.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(MutableCompoundShapeTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(MutableCompoundShapeTest, Test)
|
||||
}
|
||||
|
||||
void MutableCompoundShapeTest::Initialize()
|
||||
{
|
||||
// Floor (extra thick because we can randomly add sub shapes that then may stick out underneath the floor and cause objects to be pushed through)
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(new BoxShape(Vec3(100.0f, 10.0f, 100.0f), 0.0f), RVec3(0.0f, -10.0f, 0.0f), Quat::sIdentity(), EMotionType::Static, Layers::NON_MOVING), EActivation::DontActivate);
|
||||
|
||||
// Compound with sub compound and rotation
|
||||
StaticCompoundShapeSettings sub_compound_settings;
|
||||
sub_compound_settings.AddShape(Vec3(0, 1.5f, 0), Quat::sRotation(Vec3::sAxisZ(), 0.5f * JPH_PI), new BoxShape(Vec3(1.5f, 0.25f, 0.2f)));
|
||||
sub_compound_settings.AddShape(Vec3(1.5f, 0, 0), Quat::sRotation(Vec3::sAxisZ(), 0.5f * JPH_PI), new CylinderShape(1.5f, 0.2f));
|
||||
sub_compound_settings.AddShape(Vec3(0, 0, 1.5f), Quat::sRotation(Vec3::sAxisX(), 0.5f * JPH_PI), new TaperedCapsuleShapeSettings(1.5f, 0.25f, 0.2f));
|
||||
mSubCompound = sub_compound_settings.Create().Get();
|
||||
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
// Create a mutable compound per body and fill it up with 2 shapes initially
|
||||
Ref<MutableCompoundShapeSettings> compound_shape = new MutableCompoundShapeSettings;
|
||||
compound_shape->AddShape(Vec3::sZero(), Quat::sRotation(Vec3::sAxisX(), -0.25f * JPH_PI) * Quat::sRotation(Vec3::sAxisZ(), 0.25f * JPH_PI), mSubCompound);
|
||||
compound_shape->AddShape(Vec3::sZero(), Quat::sRotation(Vec3::sAxisX(), 0.25f * JPH_PI) * Quat::sRotation(Vec3::sAxisZ(), -0.75f * JPH_PI), mSubCompound);
|
||||
|
||||
// Create a body
|
||||
BodyID body_id = mBodyInterface->CreateAndAddBody(BodyCreationSettings(compound_shape, RVec3(0, 10.0f + 5.0f * i, 0), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
mBodyIDs.push_back(body_id);
|
||||
}
|
||||
}
|
||||
|
||||
void MutableCompoundShapeTest::PrePhysicsUpdate(const PreUpdateParams &inParams)
|
||||
{
|
||||
BodyInterface &no_lock = mPhysicsSystem->GetBodyInterfaceNoLock();
|
||||
|
||||
uniform_real_distribution<float> roll_distribution(0, 1);
|
||||
|
||||
for (BodyID id : mBodyIDs)
|
||||
{
|
||||
BodyLockWrite lock(mPhysicsSystem->GetBodyLockInterface(), id);
|
||||
if (lock.Succeeded())
|
||||
{
|
||||
Body &body = lock.GetBody();
|
||||
|
||||
// Get the shape
|
||||
MutableCompoundShape *shape = static_cast<MutableCompoundShape *>(const_cast<Shape *>(body.GetShape()));
|
||||
|
||||
// Remember center of mass from before changes
|
||||
Vec3 old_com = shape->GetCenterOfMass();
|
||||
|
||||
// Consistently seeded random engine so that bodies move in a predictable way
|
||||
default_random_engine consistent_random;
|
||||
|
||||
// Simulate an engine data structure with strided positions/rotations
|
||||
struct PositionRotation
|
||||
{
|
||||
Vec3 mPosition;
|
||||
Quat mRotation;
|
||||
};
|
||||
Array<PositionRotation> pos_rot;
|
||||
|
||||
// Animate sub shapes
|
||||
uint count = shape->GetNumSubShapes();
|
||||
for (uint i = 0; i < count; ++i)
|
||||
{
|
||||
const CompoundShape::SubShape &sub_shape = shape->GetSubShape(i);
|
||||
pos_rot.push_back({ Vec3::sZero(), (Quat::sRotation(Vec3::sRandom(consistent_random), DegreesToRadians(10.0f) * inParams.mDeltaTime) * sub_shape.GetRotation()).Normalized() });
|
||||
}
|
||||
|
||||
// Set the new rotations/orientations on the sub shapes
|
||||
shape->ModifyShapes(0, count, &pos_rot.front().mPosition, &pos_rot.front().mRotation, sizeof(PositionRotation), sizeof(PositionRotation));
|
||||
|
||||
// Initialize frame dependent random number generator
|
||||
// Note: Explicitly using the Mersenne Twister random generator as on some platforms you get the seed back as the first random number
|
||||
mt19937 frame_random(mFrameNumber++);
|
||||
|
||||
// Roll the dice
|
||||
float roll = roll_distribution(frame_random);
|
||||
if (roll < 0.001f && count > 1)
|
||||
{
|
||||
// Remove a random shape
|
||||
uniform_int_distribution<uint> index_distribution(0, count - 1);
|
||||
shape->RemoveShape(index_distribution(frame_random));
|
||||
}
|
||||
else if (roll < 0.002f && count < 10)
|
||||
{
|
||||
// Add a shape in a random rotation
|
||||
shape->AddShape(Vec3::sZero(), Quat::sRandom(frame_random), mSubCompound);
|
||||
}
|
||||
|
||||
// Ensure that the center of mass is updated
|
||||
shape->AdjustCenterOfMass();
|
||||
|
||||
// Since we're already locking the body, we don't need to lock it again
|
||||
// We always update the mass properties of the shape because we're reorienting them every frame
|
||||
no_lock.NotifyShapeChanged(id, old_com, true, EActivation::Activate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MutableCompoundShapeTest::SaveState(StateRecorder &inStream) const
|
||||
{
|
||||
inStream.Write(mFrameNumber);
|
||||
|
||||
for (BodyID id : mBodyIDs)
|
||||
{
|
||||
BodyLockRead lock(mPhysicsSystem->GetBodyLockInterface(), id);
|
||||
if (lock.Succeeded())
|
||||
{
|
||||
const Body &body = lock.GetBody();
|
||||
|
||||
// Write the shape as a binary string
|
||||
stringstream data;
|
||||
StreamOutWrapper stream_out(data);
|
||||
body.GetShape()->SaveBinaryState(stream_out);
|
||||
inStream.Write(data.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MutableCompoundShapeTest::RestoreState(StateRecorder &inStream)
|
||||
{
|
||||
inStream.Read(mFrameNumber);
|
||||
|
||||
for (BodyID id : mBodyIDs)
|
||||
{
|
||||
BodyLockWrite lock(mPhysicsSystem->GetBodyLockInterface(), id);
|
||||
if (lock.Succeeded())
|
||||
{
|
||||
Body &body = lock.GetBody();
|
||||
|
||||
// Read the shape as a binary string
|
||||
string str;
|
||||
if (inStream.IsValidating())
|
||||
{
|
||||
stringstream data;
|
||||
StreamOutWrapper stream_out(data);
|
||||
body.GetShape()->SaveBinaryState(stream_out);
|
||||
str = data.str();
|
||||
}
|
||||
inStream.Read(str);
|
||||
|
||||
// Deserialize the shape
|
||||
stringstream data(str);
|
||||
StreamInWrapper stream_in(data);
|
||||
Shape::ShapeResult result = Shape::sRestoreFromBinaryState(stream_in);
|
||||
MutableCompoundShape *shape = StaticCast<MutableCompoundShape>(result.Get());
|
||||
|
||||
// Restore the pointers to the sub compound
|
||||
ShapeList sub_shapes(shape->GetNumSubShapes(), mSubCompound);
|
||||
shape->RestoreSubShapeState(sub_shapes.data(), (uint)sub_shapes.size());
|
||||
|
||||
// Update the shape (we're under lock protection, so use the no lock interface)
|
||||
mPhysicsSystem->GetBodyInterfaceNoLock().SetShape(id, shape, false, EActivation::DontActivate);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
|
||||
class MutableCompoundShapeTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, MutableCompoundShapeTest)
|
||||
|
||||
// See: Test
|
||||
virtual void Initialize() override;
|
||||
|
||||
// Update the test, called before the physics update
|
||||
virtual void PrePhysicsUpdate(const PreUpdateParams &inParams) override;
|
||||
|
||||
// Saving / restoring state for replay
|
||||
virtual void SaveState(StateRecorder &inStream) const override;
|
||||
virtual void RestoreState(StateRecorder &inStream) override;
|
||||
|
||||
private:
|
||||
BodyIDVector mBodyIDs;
|
||||
|
||||
RefConst<Shape> mSubCompound;
|
||||
|
||||
int mFrameNumber = 0;
|
||||
};
|
||||
@@ -0,0 +1,57 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/Shapes/OffsetCenterOfMassShapeTest.h>
|
||||
#include <Jolt/Physics/Collision/Shape/SphereShape.h>
|
||||
#include <Jolt/Physics/Collision/Shape/OffsetCenterOfMassShape.h>
|
||||
#include <Jolt/Physics/Body/BodyCreationSettings.h>
|
||||
#include <Layers.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(OffsetCenterOfMassShapeTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(OffsetCenterOfMassShapeTest, Test)
|
||||
}
|
||||
|
||||
void OffsetCenterOfMassShapeTest::Initialize()
|
||||
{
|
||||
// Floor
|
||||
Body &floor = CreateFloor();
|
||||
floor.SetFriction(1.0f);
|
||||
|
||||
Ref<ShapeSettings> sphere = new SphereShapeSettings(1.0f);
|
||||
Ref<OffsetCenterOfMassShapeSettings> left = new OffsetCenterOfMassShapeSettings(Vec3(-1, 0, 0), sphere);
|
||||
Ref<OffsetCenterOfMassShapeSettings> right = new OffsetCenterOfMassShapeSettings(Vec3(1, 0, 0), sphere);
|
||||
|
||||
// Sphere with center of mass moved to the left side
|
||||
Body &body_left = *mBodyInterface->CreateBody(BodyCreationSettings(left, RVec3(-5, 5, 0), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING));
|
||||
body_left.SetFriction(1.0f);
|
||||
mBodyInterface->AddBody(body_left.GetID(), EActivation::Activate);
|
||||
|
||||
// Sphere with center of mass centered
|
||||
Body &body_center = *mBodyInterface->CreateBody(BodyCreationSettings(sphere, RVec3(0, 5, 0), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING));
|
||||
body_center.SetFriction(1.0f);
|
||||
mBodyInterface->AddBody(body_center.GetID(), EActivation::Activate);
|
||||
|
||||
// Sphere with center of mass moved to the right side
|
||||
Body &body_right = *mBodyInterface->CreateBody(BodyCreationSettings(right, RVec3(5, 5, 0), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING));
|
||||
body_right.SetFriction(1.0f);
|
||||
mBodyInterface->AddBody(body_right.GetID(), EActivation::Activate);
|
||||
|
||||
// Create body and apply a large angular impulse so see that it spins around the COM
|
||||
BodyCreationSettings bcs(new OffsetCenterOfMassShapeSettings(Vec3(-3, 0, 0), new SphereShapeSettings(1.0f)), RVec3(-5, 5, 10), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING);
|
||||
bcs.mGravityFactor = 0.0f;
|
||||
bcs.mLinearDamping = 0.0f;
|
||||
bcs.mAngularDamping = 0.0f;
|
||||
Body *body_rotating1 = mBodyInterface->CreateBody(bcs);
|
||||
mBodyInterface->AddBody(body_rotating1->GetID(), EActivation::Activate);
|
||||
body_rotating1->AddAngularImpulse(Vec3(0, 1.0e6f, 0));
|
||||
|
||||
// Create the same body but this time apply a torque
|
||||
bcs.mPosition = RVec3(5, 5, 10);
|
||||
Body *body_rotating2 = mBodyInterface->CreateBody(bcs);
|
||||
mBodyInterface->AddBody(body_rotating2->GetID(), EActivation::Activate);
|
||||
body_rotating2->AddTorque(Vec3(0, 1.0e6f * 60.0f, 0)); // Assuming physics sim is at 60Hz here, otherwise the bodies won't rotate with the same speed
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
|
||||
// Tests the OffsetCenterOfMass shape
|
||||
class OffsetCenterOfMassShapeTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, OffsetCenterOfMassShapeTest)
|
||||
|
||||
// See: Test
|
||||
virtual void Initialize() override;
|
||||
};
|
||||
27
lib/All/JoltPhysics/Samples/Tests/Shapes/PlaneShapeTest.cpp
Normal file
27
lib/All/JoltPhysics/Samples/Tests/Shapes/PlaneShapeTest.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/Shapes/PlaneShapeTest.h>
|
||||
#include <Jolt/Physics/Collision/Shape/PlaneShape.h>
|
||||
#include <Jolt/Physics/Collision/Shape/SphereShape.h>
|
||||
#include <Jolt/Physics/Collision/Shape/BoxShape.h>
|
||||
#include <Jolt/Physics/Body/BodyCreationSettings.h>
|
||||
#include <Layers.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(PlaneShapeTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(PlaneShapeTest, Test)
|
||||
}
|
||||
|
||||
void PlaneShapeTest::Initialize()
|
||||
{
|
||||
// Create a plane as floor
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(new PlaneShape(Plane(Vec3(0.1f, 1.0f, 0.0f).Normalized(), 1.0f), nullptr, 100), RVec3(0, 0, 0), Quat::sIdentity(), EMotionType::Static, Layers::NON_MOVING), EActivation::DontActivate);
|
||||
|
||||
// Add some shapes
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(new SphereShape(0.5f), RVec3(0, 1, 0), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(new BoxShape(Vec3::sReplicate(0.5f)), RVec3(2, 1, 0), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
}
|
||||
16
lib/All/JoltPhysics/Samples/Tests/Shapes/PlaneShapeTest.h
Normal file
16
lib/All/JoltPhysics/Samples/Tests/Shapes/PlaneShapeTest.h
Normal file
@@ -0,0 +1,16 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
|
||||
class PlaneShapeTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, PlaneShapeTest)
|
||||
|
||||
// See: Test
|
||||
virtual void Initialize() override;
|
||||
};
|
||||
@@ -0,0 +1,35 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/Shapes/RotatedTranslatedShapeTest.h>
|
||||
#include <Jolt/Physics/Collision/Shape/ConvexHullShape.h>
|
||||
#include <Jolt/Physics/Collision/Shape/RotatedTranslatedShape.h>
|
||||
#include <Jolt/Physics/Body/BodyCreationSettings.h>
|
||||
#include <Layers.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(RotatedTranslatedShapeTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(RotatedTranslatedShapeTest, Test)
|
||||
}
|
||||
|
||||
void RotatedTranslatedShapeTest::Initialize()
|
||||
{
|
||||
// Floor
|
||||
CreateFloor();
|
||||
|
||||
// Create a cone centered on the origin with the point pointing upwards
|
||||
Array<Vec3> points;
|
||||
points.push_back(Vec3(0, 2.5f, 0));
|
||||
for (float a = 0; a < DegreesToRadians(360); a += DegreesToRadians(36))
|
||||
points.push_back(Vec3(Sin(a), -2.5f, Cos(a)));
|
||||
Ref<ConvexHullShapeSettings> convex_hull = new ConvexHullShapeSettings(points);
|
||||
|
||||
// Offset and rotate so that the cone is upside down on its point
|
||||
Ref<RotatedTranslatedShapeSettings> rot_trans = new RotatedTranslatedShapeSettings(Vec3(0, 2.5f, 0), Quat::sRotation(Vec3::sAxisX(), JPH_PI), convex_hull);
|
||||
|
||||
// Place at 0 so that the point touches the floor
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(rot_trans, RVec3::sZero(), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
|
||||
// Tests the RotatedTranslated shape
|
||||
class RotatedTranslatedShapeTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, RotatedTranslatedShapeTest)
|
||||
|
||||
// See: Test
|
||||
virtual void Initialize() override;
|
||||
};
|
||||
32
lib/All/JoltPhysics/Samples/Tests/Shapes/SphereShapeTest.cpp
Normal file
32
lib/All/JoltPhysics/Samples/Tests/Shapes/SphereShapeTest.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/Shapes/SphereShapeTest.h>
|
||||
#include <Jolt/Physics/Collision/Shape/SphereShape.h>
|
||||
#include <Jolt/Physics/Body/BodyCreationSettings.h>
|
||||
#include <Layers.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(SphereShapeTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(SphereShapeTest, Test)
|
||||
}
|
||||
|
||||
void SphereShapeTest::Initialize()
|
||||
{
|
||||
// Floor
|
||||
CreateFloor();
|
||||
|
||||
// Create different sized spheres
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(new SphereShape(1.0f), RVec3(0, 10, 0), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(new SphereShape(2.0f), RVec3(0, 10, 10), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(new SphereShape(0.5f), RVec3(0, 10, 20), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
|
||||
// Tower of spheres
|
||||
for (int i = 0; i < 10; ++i)
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(new SphereShape(0.5f), RVec3(10, 10 + 1.5f * i, 0), Quat::sRotation(Vec3::sAxisZ(), 0.25f * JPH_PI), EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
}
|
||||
16
lib/All/JoltPhysics/Samples/Tests/Shapes/SphereShapeTest.h
Normal file
16
lib/All/JoltPhysics/Samples/Tests/Shapes/SphereShapeTest.h
Normal file
@@ -0,0 +1,16 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
|
||||
class SphereShapeTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, SphereShapeTest)
|
||||
|
||||
// See: Test
|
||||
virtual void Initialize() override;
|
||||
};
|
||||
@@ -0,0 +1,62 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/Shapes/StaticCompoundShapeTest.h>
|
||||
#include <Jolt/Physics/Collision/Shape/StaticCompoundShape.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/Body/BodyCreationSettings.h>
|
||||
#include <Layers.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(StaticCompoundShapeTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(StaticCompoundShapeTest, Test)
|
||||
}
|
||||
|
||||
void StaticCompoundShapeTest::Initialize()
|
||||
{
|
||||
// Floor
|
||||
CreateFloor();
|
||||
|
||||
// Simple compound
|
||||
Ref<StaticCompoundShapeSettings> compound_shape1 = new StaticCompoundShapeSettings;
|
||||
compound_shape1->AddShape(Vec3::sZero(), Quat::sIdentity(), new CapsuleShape(5, 1));
|
||||
compound_shape1->AddShape(Vec3(0, -5, 0), Quat::sIdentity(), new SphereShape(2));
|
||||
compound_shape1->AddShape(Vec3(0, 5, 0), Quat::sIdentity(), new SphereShape(2));
|
||||
|
||||
// Compound with sub compound and rotation
|
||||
Ref<StaticCompoundShapeSettings> sub_compound = new StaticCompoundShapeSettings;
|
||||
sub_compound->AddShape(Vec3(0, 1.5f, 0), Quat::sRotation(Vec3::sAxisZ(), 0.5f * JPH_PI), new BoxShape(Vec3(1.5f, 0.25f, 0.2f)));
|
||||
sub_compound->AddShape(Vec3(1.5f, 0, 0), Quat::sRotation(Vec3::sAxisZ(), 0.5f * JPH_PI), new CylinderShape(1.5f, 0.2f));
|
||||
sub_compound->AddShape(Vec3(0, 0, 1.5f), Quat::sRotation(Vec3::sAxisX(), 0.5f * JPH_PI), new TaperedCapsuleShapeSettings(1.5f, 0.25f, 0.2f));
|
||||
|
||||
Ref<StaticCompoundShapeSettings> compound_shape2 = new StaticCompoundShapeSettings;
|
||||
compound_shape2->AddShape(Vec3(0, 0, 0), Quat::sRotation(Vec3::sAxisX(), -0.25f * JPH_PI) * Quat::sRotation(Vec3::sAxisZ(), 0.25f * JPH_PI), sub_compound);
|
||||
compound_shape2->AddShape(Vec3(0, -0.1f, 0), Quat::sRotation(Vec3::sAxisX(), 0.25f * JPH_PI) * Quat::sRotation(Vec3::sAxisZ(), -0.75f * JPH_PI), sub_compound);
|
||||
|
||||
// Compound with large amount of sub shapes
|
||||
Ref<StaticCompoundShapeSettings> compound_shape3 = new StaticCompoundShapeSettings;
|
||||
for (int y = -2; y <= 2; ++y)
|
||||
for (int x = -2; x <= 2; ++x)
|
||||
for (int z = -2; z <= 2; ++z)
|
||||
compound_shape3->AddShape(Vec3(0.5f * x, 0.5f * y, 0.5f * z), Quat::sRotation(Vec3::sAxisX(), -0.25f * JPH_PI) * Quat::sRotation(Vec3::sAxisZ(), 0.25f * JPH_PI), new BoxShape(Vec3::sReplicate(0.5f)));
|
||||
|
||||
Ref<StaticCompoundShapeSettings> shapes[] = { compound_shape1, compound_shape2, compound_shape3 };
|
||||
|
||||
for (int i = 0; i < 10; ++i)
|
||||
for (int j = 0; j < 3; ++j)
|
||||
{
|
||||
Quat rotation;
|
||||
if ((i & 1) == 0)
|
||||
rotation = Quat::sRotation(Vec3::sAxisX(), 0.5f * JPH_PI);
|
||||
else
|
||||
rotation = Quat::sRotation(Vec3::sAxisZ(), 0.5f * JPH_PI);
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(shapes[j], RVec3(0, 10.0f + 4.0f * i, j * 20.0f), rotation, EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
|
||||
class StaticCompoundShapeTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, StaticCompoundShapeTest)
|
||||
|
||||
// See: Test
|
||||
virtual void Initialize() override;
|
||||
};
|
||||
@@ -0,0 +1,56 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/Shapes/TaperedCapsuleShapeTest.h>
|
||||
#include <Jolt/Physics/Collision/Shape/TaperedCapsuleShape.h>
|
||||
#include <Jolt/Physics/Body/BodyCreationSettings.h>
|
||||
#include <Layers.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(TaperedCapsuleShapeTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(TaperedCapsuleShapeTest, Test)
|
||||
}
|
||||
|
||||
void TaperedCapsuleShapeTest::Initialize()
|
||||
{
|
||||
// Floor
|
||||
CreateFloor();
|
||||
|
||||
RefConst<ShapeSettings> big_taperedcapsule = new TaperedCapsuleShapeSettings(2.0f, 1.0f, 3.0f);
|
||||
RefConst<ShapeSettings> big_taperedcapsule2 = new TaperedCapsuleShapeSettings(2.0f, 3.0f, 1.0f);
|
||||
|
||||
// Tapered capsule on outer sphere
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(big_taperedcapsule, RVec3(0, 10, 0), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
|
||||
// Tapered capsule on other outer sphere
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(big_taperedcapsule2, RVec3(10, 10, 0), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
|
||||
// Tapered capsule on side
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(big_taperedcapsule, RVec3(20, 10, 0), Quat::sRotation(Vec3::sAxisX(), 0.5f * JPH_PI), EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
|
||||
RefConst<ShapeSettings> long_taperedcapsule = new TaperedCapsuleShapeSettings(5, 0.5f, 1.0f);
|
||||
|
||||
// Tower of tapered capsules
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
for (int j = 0; j < 2; ++j)
|
||||
{
|
||||
RVec3 position;
|
||||
Quat rotation;
|
||||
if (i & 1)
|
||||
{
|
||||
position = RVec3(-4.0f + 8.0f * j, 2.0f + 3.0f * i, -20.0f);
|
||||
rotation = Quat::sRotation(Vec3::sAxisX(), 0.5f * JPH_PI + (j & 1) * JPH_PI);
|
||||
}
|
||||
else
|
||||
{
|
||||
position = RVec3(0, 2.0f + 3.0f * i, -20.0f - 4.0f + 8.0f * j);
|
||||
rotation = Quat::sRotation(Vec3::sAxisZ(), 0.5f * JPH_PI + (j & 1) * JPH_PI);
|
||||
}
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(long_taperedcapsule, position, rotation, EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
|
||||
class TaperedCapsuleShapeTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, TaperedCapsuleShapeTest)
|
||||
|
||||
// See: Test
|
||||
virtual void Initialize() override;
|
||||
};
|
||||
@@ -0,0 +1,68 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/Shapes/TaperedCylinderShapeTest.h>
|
||||
#include <Jolt/Physics/Collision/Shape/TaperedCylinderShape.h>
|
||||
#include <Jolt/Physics/Body/BodyCreationSettings.h>
|
||||
#include <Layers.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(TaperedCylinderShapeTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(TaperedCylinderShapeTest, Test)
|
||||
}
|
||||
|
||||
void TaperedCylinderShapeTest::Initialize()
|
||||
{
|
||||
// Floor
|
||||
CreateFloor();
|
||||
|
||||
RefConst<ShapeSettings> big_taperedcylinder = new TaperedCylinderShapeSettings(2.0f, 1.0f, 3.0f);
|
||||
RefConst<ShapeSettings> big_taperedcylinder2 = new TaperedCylinderShapeSettings(2.0f, 3.0f, 1.0f);
|
||||
|
||||
// Tapered cylinder on large radius
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(big_taperedcylinder, RVec3(0, 10, 0), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
|
||||
// Tapered cylinder on small radius
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(big_taperedcylinder2, RVec3(10, 10, 0), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
|
||||
// Tapered cylinder on side
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(big_taperedcylinder, RVec3(20, 10, 0), Quat::sRotation(Vec3::sAxisX(), 0.5f * JPH_PI), EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
|
||||
RefConst<ShapeSettings> big_cone = new TaperedCylinderShapeSettings(2.0f, 0.0f, 3.0f, 0.0f);
|
||||
RefConst<ShapeSettings> big_cone2 = new TaperedCylinderShapeSettings(2.0f, 3.0f, 0.0f, 0.0f);
|
||||
|
||||
// Cone on large radius
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(big_cone, RVec3(0, 10, 10), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
|
||||
// Cone on small radius
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(big_cone2, RVec3(10, 10, 10), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
|
||||
// Cone on side
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(big_cone, RVec3(20, 10, 10), Quat::sRotation(Vec3::sAxisX(), 0.5f * JPH_PI), EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
|
||||
RefConst<ShapeSettings> long_taperedcylinder = new TaperedCylinderShapeSettings(5, 0.5f, 1.0f);
|
||||
|
||||
// Tower of tapered cylinders
|
||||
for (int i = 0; i < 10; ++i)
|
||||
{
|
||||
for (int j = 0; j < 2; ++j)
|
||||
{
|
||||
RVec3 position;
|
||||
Quat rotation;
|
||||
if (i & 1)
|
||||
{
|
||||
position = RVec3(-4.0f + 8.0f * j, 2.0f + 3.0f * i, -20.0f);
|
||||
rotation = Quat::sRotation(Vec3::sAxisX(), 0.5f * JPH_PI + (j & 1) * JPH_PI);
|
||||
}
|
||||
else
|
||||
{
|
||||
position = RVec3(0, 2.0f + 3.0f * i, -20.0f - 4.0f + 8.0f * j);
|
||||
rotation = Quat::sRotation(Vec3::sAxisZ(), 0.5f * JPH_PI + (j & 1) * JPH_PI);
|
||||
}
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(long_taperedcylinder, position, rotation, EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
|
||||
class TaperedCylinderShapeTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, TaperedCylinderShapeTest)
|
||||
|
||||
// See: Test
|
||||
virtual void Initialize() override;
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/Shapes/TriangleShapeTest.h>
|
||||
#include <Jolt/Physics/Collision/Shape/TriangleShape.h>
|
||||
#include <Jolt/Physics/Collision/Shape/BoxShape.h>
|
||||
#include <Jolt/Physics/Body/BodyCreationSettings.h>
|
||||
#include <Layers.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(TriangleShapeTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(TriangleShapeTest, Test)
|
||||
}
|
||||
|
||||
void TriangleShapeTest::Initialize()
|
||||
{
|
||||
// Single triangle
|
||||
RefConst<TriangleShape> triangle_shape = new TriangleShape(Vec3(-10, -1, 0), Vec3(0, 1, 10), Vec3(10, -2, -10), 0.01f);
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(triangle_shape, RVec3::sZero(), Quat::sIdentity(), EMotionType::Static, Layers::NON_MOVING), EActivation::DontActivate);
|
||||
|
||||
// Create a box above the triangle
|
||||
RefConst<Shape> box_shape = new BoxShape(Vec3(0.2f, 0.2f, 0.4f), 0.01f);
|
||||
mBodyInterface->CreateAndAddBody(BodyCreationSettings(box_shape, RVec3(0, 5, 0), Quat::sIdentity(), EMotionType::Dynamic, Layers::MOVING), EActivation::Activate);
|
||||
}
|
||||
16
lib/All/JoltPhysics/Samples/Tests/Shapes/TriangleShapeTest.h
Normal file
16
lib/All/JoltPhysics/Samples/Tests/Shapes/TriangleShapeTest.h
Normal file
@@ -0,0 +1,16 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
|
||||
class TriangleShapeTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, TriangleShapeTest)
|
||||
|
||||
// See: Test
|
||||
virtual void Initialize() override;
|
||||
};
|
||||
Reference in New Issue
Block a user