Ajout de Jolt Physics + 1ere version des factory entitecomposants - camera, transform, rigidbody, collider, renderer
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/ConvexCollision/CapsuleVsBoxTest.h>
|
||||
#include <Jolt/Physics/Collision/Shape/RotatedTranslatedShape.h>
|
||||
#include <Jolt/Physics/Collision/Shape/CapsuleShape.h>
|
||||
#include <Jolt/Physics/Collision/Shape/BoxShape.h>
|
||||
#include <Jolt/Physics/Collision/CollideShape.h>
|
||||
#include <Jolt/Physics/Collision/CollisionDispatch.h>
|
||||
#include <Jolt/Physics/Collision/CollisionCollectorImpl.h>
|
||||
#include <Utils/DebugRendererSP.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(CapsuleVsBoxTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(CapsuleVsBoxTest, Test)
|
||||
}
|
||||
|
||||
void CapsuleVsBoxTest::PrePhysicsUpdate(const PreUpdateParams &inParams)
|
||||
{
|
||||
// Create box
|
||||
Vec3 box_min(-1.0f, -2.0f, 0.5f);
|
||||
Vec3 box_max(2.0f, -0.5f, 3.0f);
|
||||
Ref<RotatedTranslatedShapeSettings> box_settings = new RotatedTranslatedShapeSettings(0.5f * (box_min + box_max), Quat::sIdentity(), new BoxShapeSettings(0.5f * (box_max - box_min)));
|
||||
Ref<Shape> box_shape = box_settings->Create().Get();
|
||||
Mat44 box_transform(Vec4(0.516170502f, -0.803887904f, -0.295520246f, 0.0f), Vec4(0.815010250f, 0.354940295f, 0.458012700f, 0.0f), Vec4(-0.263298869f, -0.477264702f, 0.838386655f, 0.0f), Vec4(-10.2214508f, -18.6808319f, 40.7468987f, 1.0f));
|
||||
|
||||
// Create capsule
|
||||
float capsule_half_height = 75.0f;
|
||||
float capsule_radius = 1.5f;
|
||||
Quat capsule_compound_rotation(0.499999970f, -0.499999970f, -0.499999970f, 0.499999970f);
|
||||
Ref<RotatedTranslatedShapeSettings> capsule_settings = new RotatedTranslatedShapeSettings(Vec3(0, 0, 75), capsule_compound_rotation, new CapsuleShapeSettings(capsule_half_height, capsule_radius));
|
||||
Ref<Shape> capsule_shape = capsule_settings->Create().Get();
|
||||
Mat44 capsule_transform = Mat44::sTranslation(Vec3(-9.68538570f, -18.0328083f, 41.3212280f));
|
||||
|
||||
// Collision settings
|
||||
CollideShapeSettings settings;
|
||||
settings.mActiveEdgeMode = EActiveEdgeMode::CollideWithAll;
|
||||
settings.mBackFaceMode = EBackFaceMode::CollideWithBackFaces;
|
||||
settings.mCollectFacesMode = ECollectFacesMode::NoFaces;
|
||||
|
||||
// Collide the two shapes
|
||||
AllHitCollisionCollector<CollideShapeCollector> collector;
|
||||
CollisionDispatch::sCollideShapeVsShape(capsule_shape, box_shape, Vec3::sOne(), Vec3::sOne(), capsule_transform, box_transform, SubShapeIDCreator(), SubShapeIDCreator(), settings, collector);
|
||||
|
||||
#ifdef JPH_DEBUG_RENDERER
|
||||
// Draw the shapes
|
||||
box_shape->Draw(mDebugRenderer, RMat44(box_transform), Vec3::sOne(), Color::sWhite, false, false);
|
||||
capsule_shape->Draw(mDebugRenderer, RMat44(capsule_transform), Vec3::sOne(), Color::sWhite, false, false);
|
||||
#endif // JPH_DEBUG_RENDERER
|
||||
|
||||
// Draw contact points
|
||||
const CollideShapeResult &hit = collector.mHits[0];
|
||||
DrawMarkerSP(mDebugRenderer, hit.mContactPointOn1, Color::sRed, 1.0f);
|
||||
DrawMarkerSP(mDebugRenderer, hit.mContactPointOn2, Color::sGreen, 1.0f);
|
||||
|
||||
// Draw penetration axis with length of the penetration
|
||||
Vec3 pen_axis = hit.mPenetrationAxis;
|
||||
float pen_axis_len = pen_axis.Length();
|
||||
if (pen_axis_len > 0.0f)
|
||||
{
|
||||
pen_axis *= hit.mPenetrationDepth / pen_axis_len;
|
||||
DrawArrowSP(mDebugRenderer, hit.mContactPointOn2, hit.mContactPointOn2 + pen_axis, Color::sYellow, 0.01f);
|
||||
|
||||
#ifdef JPH_DEBUG_RENDERER
|
||||
Mat44 resolved_box = box_transform.PostTranslated(pen_axis);
|
||||
box_shape->Draw(mDebugRenderer, RMat44(resolved_box), Vec3::sOne(), Color::sGreen, false, false);
|
||||
#endif // JPH_DEBUG_RENDERER
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
// Does a very long capsule vs rotated embedded box test, this was a repro for a bug and can be used to test bug regression
|
||||
class CapsuleVsBoxTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, CapsuleVsBoxTest)
|
||||
|
||||
// Update the test, called before the physics update
|
||||
virtual void PrePhysicsUpdate(const PreUpdateParams &inParams) override;
|
||||
};
|
||||
@@ -0,0 +1,254 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/ConvexCollision/ClosestPointTest.h>
|
||||
#include <Jolt/Geometry/ClosestPoint.h>
|
||||
#include <Renderer/DebugRendererImp.h>
|
||||
#include <Utils/DebugRendererSP.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(ClosestPointTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(ClosestPointTest, Test)
|
||||
}
|
||||
|
||||
void ClosestPointTest::PrePhysicsUpdate(const PreUpdateParams &inParams)
|
||||
{
|
||||
Vec3 pos(inParams.mCameraState.mPos);
|
||||
|
||||
{
|
||||
// Normal tetrahedron
|
||||
Vec3 a(2, 0, 0);
|
||||
Vec3 b(1, 0, 1);
|
||||
Vec3 c(2, 0, 1);
|
||||
Vec3 d(1, 1, 0);
|
||||
|
||||
TestTetra(pos, a, b, c, d);
|
||||
}
|
||||
|
||||
{
|
||||
// Inside out tetrahedron
|
||||
Vec3 a(2, -2, 0);
|
||||
Vec3 b(1, -2, 1);
|
||||
Vec3 c(2, -2, 1);
|
||||
Vec3 d(1, -3, 0);
|
||||
|
||||
TestTetra(pos, a, b, c, d);
|
||||
}
|
||||
|
||||
{
|
||||
// Degenerate tetrahedron
|
||||
Vec3 a(2, 3, 0);
|
||||
Vec3 b = a;
|
||||
Vec3 c(2, 3, 1);
|
||||
Vec3 d(1, 4, 0);
|
||||
|
||||
TestTetra(pos, a, b, c, d);
|
||||
}
|
||||
|
||||
{
|
||||
// Degenerate tetrahedron
|
||||
Vec3 a(2, 6, 0);
|
||||
Vec3 b(1, 6, 1);
|
||||
Vec3 c = a;
|
||||
Vec3 d(1, 7, 0);
|
||||
|
||||
TestTetra(pos, a, b, c, d);
|
||||
}
|
||||
|
||||
{
|
||||
// Degenerate tetrahedron
|
||||
Vec3 a(2, 9, 0);
|
||||
Vec3 b(1, 9, 1);
|
||||
Vec3 c(2, 9, 1);
|
||||
Vec3 d = a;
|
||||
|
||||
TestTetra(pos, a, b, c, d);
|
||||
}
|
||||
|
||||
{
|
||||
// Degenerate tetrahedron
|
||||
Vec3 a(2, 12, 0);
|
||||
Vec3 b(1, 12, 1);
|
||||
Vec3 c = b;
|
||||
Vec3 d(1, 13, 0);
|
||||
|
||||
TestTetra(pos, a, b, c, d);
|
||||
}
|
||||
|
||||
{
|
||||
// Degenerate tetrahedron
|
||||
Vec3 a(2, 15, 0);
|
||||
Vec3 b(1, 15, 1);
|
||||
Vec3 c(2, 15, 1);
|
||||
Vec3 d = b;
|
||||
|
||||
TestTetra(pos, a, b, c, d);
|
||||
}
|
||||
|
||||
{
|
||||
// Degenerate tetrahedron
|
||||
Vec3 a(2, 18, 0);
|
||||
Vec3 b(1, 18, 1);
|
||||
Vec3 c(2, 18, 1);
|
||||
Vec3 d = c;
|
||||
|
||||
TestTetra(pos, a, b, c, d);
|
||||
}
|
||||
|
||||
{
|
||||
// Normal tri
|
||||
Vec3 a(5, 0, 0);
|
||||
Vec3 b(4, 0, 1);
|
||||
Vec3 c(5, 0, 1);
|
||||
|
||||
TestTri(pos, a, b, c);
|
||||
}
|
||||
|
||||
{
|
||||
// Degenerate tri
|
||||
Vec3 a(5, 3, 0);
|
||||
Vec3 b = a;
|
||||
Vec3 c(5, 3, 1);
|
||||
|
||||
TestTri(pos, a, b, c);
|
||||
}
|
||||
|
||||
{
|
||||
// Degenerate tri
|
||||
Vec3 a(5, 6, 0);
|
||||
Vec3 b(4, 6, 1);
|
||||
Vec3 c = a;
|
||||
|
||||
TestTri(pos, a, b, c);
|
||||
}
|
||||
|
||||
{
|
||||
// Degenerate tri
|
||||
Vec3 a(5, 9, 0);
|
||||
Vec3 b(4, 9, 1);
|
||||
Vec3 c = b;
|
||||
|
||||
TestTri(pos, a, b, c);
|
||||
}
|
||||
|
||||
{
|
||||
// Normal line
|
||||
Vec3 a(10, 0, 0);
|
||||
Vec3 b(9, 0, 1);
|
||||
TestLine(pos, a, b);
|
||||
}
|
||||
|
||||
{
|
||||
// Degenerate line
|
||||
Vec3 a(10, 3, 0);
|
||||
Vec3 b = a;
|
||||
TestLine(pos, a, b);
|
||||
}
|
||||
}
|
||||
|
||||
void ClosestPointTest::TestLine(Vec3Arg inPosition, Vec3Arg inA, Vec3Arg inB)
|
||||
{
|
||||
Vec3 a = inA - inPosition;
|
||||
Vec3 b = inB - inPosition;
|
||||
|
||||
uint32 set;
|
||||
Vec3 closest = ClosestPoint::GetClosestPointOnLine(a, b, set) + inPosition;
|
||||
|
||||
DrawLineSP(mDebugRenderer, inA, inB, Color::sWhite);
|
||||
|
||||
DrawMarkerSP(mDebugRenderer, closest, Color::sRed, 0.1f);
|
||||
|
||||
if (set & 0b0001)
|
||||
DrawMarkerSP(mDebugRenderer, inA, Color::sYellow, 0.5f);
|
||||
if (set & 0b0010)
|
||||
DrawMarkerSP(mDebugRenderer, inB, Color::sYellow, 0.5f);
|
||||
|
||||
Vec3 a2 = inA - closest;
|
||||
Vec3 b2 = inB - closest;
|
||||
|
||||
float u, v;
|
||||
ClosestPoint::GetBaryCentricCoordinates(a2, b2, u, v);
|
||||
DrawWireSphereSP(mDebugRenderer, u * inA + v * inB, 0.05f, Color::sGreen);
|
||||
|
||||
DrawText3DSP(mDebugRenderer, inA, "a");
|
||||
DrawText3DSP(mDebugRenderer, inB, "b");
|
||||
}
|
||||
|
||||
void ClosestPointTest::TestTri(Vec3Arg inPosition, Vec3Arg inA, Vec3Arg inB, Vec3Arg inC)
|
||||
{
|
||||
Vec3 a = inA - inPosition;
|
||||
Vec3 b = inB - inPosition;
|
||||
Vec3 c = inC - inPosition;
|
||||
|
||||
uint32 set;
|
||||
Vec3 closest = ClosestPoint::GetClosestPointOnTriangle(a, b, c, set) + inPosition;
|
||||
|
||||
DrawLineSP(mDebugRenderer, inA, inB, Color::sWhite);
|
||||
DrawLineSP(mDebugRenderer, inA, inC, Color::sWhite);
|
||||
DrawLineSP(mDebugRenderer, inB, inC, Color::sWhite);
|
||||
|
||||
DrawTriangleSP(mDebugRenderer, inA, inB, inC, Color::sGrey);
|
||||
|
||||
DrawMarkerSP(mDebugRenderer, closest, Color::sRed, 0.1f);
|
||||
|
||||
if (set & 0b0001)
|
||||
DrawMarkerSP(mDebugRenderer, inA, Color::sYellow, 0.5f);
|
||||
if (set & 0b0010)
|
||||
DrawMarkerSP(mDebugRenderer, inB, Color::sYellow, 0.5f);
|
||||
if (set & 0b0100)
|
||||
DrawMarkerSP(mDebugRenderer, inC, Color::sYellow, 0.5f);
|
||||
|
||||
Vec3 a2 = inA - closest;
|
||||
Vec3 b2 = inB - closest;
|
||||
Vec3 c2 = inC - closest;
|
||||
|
||||
float u, v, w;
|
||||
ClosestPoint::GetBaryCentricCoordinates(a2, b2, c2, u, v, w);
|
||||
DrawWireSphereSP(mDebugRenderer, u * inA + v * inB + w * inC, 0.05f, Color::sGreen);
|
||||
|
||||
DrawText3DSP(mDebugRenderer, inA, "a");
|
||||
DrawText3DSP(mDebugRenderer, inB, "b");
|
||||
DrawText3DSP(mDebugRenderer, inC, "c");
|
||||
}
|
||||
|
||||
void ClosestPointTest::TestTetra(Vec3Arg inPosition, Vec3Arg inA, Vec3Arg inB, Vec3Arg inC, Vec3Arg inD)
|
||||
{
|
||||
Vec3 a = inA - inPosition;
|
||||
Vec3 b = inB - inPosition;
|
||||
Vec3 c = inC - inPosition;
|
||||
Vec3 d = inD - inPosition;
|
||||
|
||||
uint32 set;
|
||||
Vec3 closest = ClosestPoint::GetClosestPointOnTetrahedron(a, b, c, d, set) + inPosition;
|
||||
|
||||
DrawLineSP(mDebugRenderer, inA, inB, Color::sWhite);
|
||||
DrawLineSP(mDebugRenderer, inA, inC, Color::sWhite);
|
||||
DrawLineSP(mDebugRenderer, inA, inD, Color::sWhite);
|
||||
DrawLineSP(mDebugRenderer, inB, inC, Color::sWhite);
|
||||
DrawLineSP(mDebugRenderer, inB, inD, Color::sWhite);
|
||||
DrawLineSP(mDebugRenderer, inC, inD, Color::sWhite);
|
||||
|
||||
DrawTriangleSP(mDebugRenderer, inA, inC, inB, Color::sGrey);
|
||||
DrawTriangleSP(mDebugRenderer, inA, inD, inC, Color::sGrey);
|
||||
DrawTriangleSP(mDebugRenderer, inA, inB, inD, Color::sGrey);
|
||||
DrawTriangleSP(mDebugRenderer, inB, inC, inD, Color::sGrey);
|
||||
|
||||
DrawMarkerSP(mDebugRenderer, closest, Color::sRed, 0.1f);
|
||||
|
||||
if (set & 0b0001)
|
||||
DrawMarkerSP(mDebugRenderer, inA, Color::sYellow, 0.5f);
|
||||
if (set & 0b0010)
|
||||
DrawMarkerSP(mDebugRenderer, inB, Color::sYellow, 0.5f);
|
||||
if (set & 0b0100)
|
||||
DrawMarkerSP(mDebugRenderer, inC, Color::sYellow, 0.5f);
|
||||
if (set & 0b1000)
|
||||
DrawMarkerSP(mDebugRenderer, inD, Color::sYellow, 0.5f);
|
||||
|
||||
DrawText3DSP(mDebugRenderer, inA, "a");
|
||||
DrawText3DSP(mDebugRenderer, inB, "b");
|
||||
DrawText3DSP(mDebugRenderer, inC, "c");
|
||||
DrawText3DSP(mDebugRenderer, inD, "d");
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
|
||||
// Test that interactively shows the algorithms from the ClosestPoints namespace
|
||||
class ClosestPointTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, ClosestPointTest)
|
||||
|
||||
// Update the test, called before the physics update
|
||||
virtual void PrePhysicsUpdate(const PreUpdateParams &inParams) override;
|
||||
|
||||
private:
|
||||
void TestLine(Vec3Arg inPosition, Vec3Arg inA, Vec3Arg inB);
|
||||
void TestTri(Vec3Arg inPosition, Vec3Arg inA, Vec3Arg inB, Vec3Arg inC);
|
||||
void TestTetra(Vec3Arg inPosition, Vec3Arg inA, Vec3Arg inB, Vec3Arg inC, Vec3Arg inD);
|
||||
};
|
||||
@@ -0,0 +1,176 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/ConvexCollision/ConvexHullShrinkTest.h>
|
||||
#include <Utils/Log.h>
|
||||
#include <Utils/DebugRendererSP.h>
|
||||
#include <Jolt/Geometry/ConvexSupport.h>
|
||||
#include <Jolt/Physics/Collision/Shape/ConvexHullShape.h>
|
||||
#include <Renderer/DebugRendererImp.h>
|
||||
#include <Utils/AssetStream.h>
|
||||
|
||||
JPH_SUPPRESS_WARNINGS_STD_BEGIN
|
||||
#include <fstream>
|
||||
JPH_SUPPRESS_WARNINGS_STD_END
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(ConvexHullShrinkTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(ConvexHullShrinkTest, Test)
|
||||
}
|
||||
|
||||
void ConvexHullShrinkTest::Initialize()
|
||||
{
|
||||
// First add a list of shapes that were problematic before
|
||||
mPoints = {
|
||||
{
|
||||
Vec3(1, 1, 1),
|
||||
Vec3(1, 1, -1),
|
||||
Vec3(1, -1, 1),
|
||||
Vec3(1, -1, -1),
|
||||
},
|
||||
{
|
||||
Vec3(1, 1, 1),
|
||||
Vec3(1, 1, -1),
|
||||
Vec3(1, -1, 1),
|
||||
Vec3(1, -1, -1),
|
||||
Vec3(-1, 1, 1),
|
||||
Vec3(-1, 1, -1),
|
||||
Vec3(-1, -1, 1),
|
||||
Vec3(-1, -1, -1),
|
||||
},
|
||||
{
|
||||
Vec3(0.24055352f, 0.42262089f, 0.20811508f),
|
||||
Vec3(0.23034751f, 0.42984104f, -0.21389426f),
|
||||
Vec3(0.21995061f, 0.43724900f, 0.20929135f),
|
||||
Vec3(0.18619442f, 0.44122630f, 0.10257969f),
|
||||
Vec3(-0.22997921f, 0.43706810f, 0.21128670f),
|
||||
Vec3(0.18488347f, -0.44135576f, 0.10415942f),
|
||||
Vec3(-0.20950880f, -0.43603044f, 0.20873074f),
|
||||
Vec3(-0.21230474f, -0.43691945f, -0.20506332f),
|
||||
Vec3(0.23440370f, -0.43392032f, 0.20985059f),
|
||||
Vec3(0.22406587f, -0.43578571f, -0.21132792f),
|
||||
Vec3(0.24845430f, -0.41821426f, -0.21033705f),
|
||||
Vec3(0.24780219f, -0.42262548f, 0.21058462f),
|
||||
Vec3(-0.24866026f, 0.41188520f, 0.20908103f),
|
||||
Vec3(-0.25144735f, 0.41933101f, -0.20718251f),
|
||||
Vec3(-0.24799588f, -0.20490804f, 0.21178717f),
|
||||
Vec3(0.01075744f, -0.41775572f, -0.22181017f),
|
||||
Vec3(-0.18624404f, -0.18736419f, -0.21975047f),
|
||||
Vec3(0.22080457f, 0.01773871f, -0.22080121f),
|
||||
Vec3(-0.17988407f, 0.40095943f, -0.21670545f),
|
||||
Vec3(-0.23094913f, 0.42154532f, 0.21846796f),
|
||||
Vec3(0.23783659f, 0.41114848f, -0.20812420f),
|
||||
Vec3(0.25242796f, 0.00087111f, 0.04875314f),
|
||||
Vec3(0.20976084f, 0.43694448f, -0.20819492f),
|
||||
Vec3(0.21914389f, -0.42215359f, -0.21839635f),
|
||||
Vec3(0.22120973f, 0.42172050f, 0.21581716f),
|
||||
Vec3(0.07287904f, 0.40937370f, 0.21898652f),
|
||||
Vec3(-0.23638439f, 0.42299985f, -0.21391643f),
|
||||
Vec3(0.25210538f, -0.20603905f, 0.20603551f),
|
||||
Vec3(-0.22867783f, -0.43080616f, -0.21309699f),
|
||||
Vec3(-0.22365719f, 0.43650645f, -0.20515810f),
|
||||
Vec3(-0.23701435f, 0.43320888f, -0.20985882f),
|
||||
Vec3(-0.24509817f, 0.42541492f, 0.21352110f),
|
||||
Vec3(0.22803798f, -0.41877448f, 0.21590335f),
|
||||
Vec3(-0.21627685f, -0.41884291f, 0.21908275f),
|
||||
Vec3(-0.24125161f, -0.13299965f, -0.21386964f),
|
||||
Vec3(-0.22310710f, -0.43280768f, 0.21368177f),
|
||||
Vec3(-0.23707944f, -0.41916745f, 0.21170078f),
|
||||
Vec3(-0.23729360f, -0.42400050f, -0.20905880f),
|
||||
Vec3(-0.23056241f, 0.44033193f, -0.00191451f),
|
||||
Vec3(-0.24118152f, -0.41101628f, -0.20855166f),
|
||||
Vec3(0.21646300f, 0.42087674f, -0.21763385f),
|
||||
Vec3(0.25090047f, -0.41023433f, 0.10248772f),
|
||||
Vec3(0.03950108f, -0.43627834f, -0.21231101f),
|
||||
Vec3(-0.22727611f, -0.24993966f, 0.21899925f),
|
||||
Vec3(0.24388977f, -0.07015021f, -0.21204789f)
|
||||
}
|
||||
};
|
||||
|
||||
// Open the external file with hulls
|
||||
// A stream containing predefined convex hulls
|
||||
AssetStream points_asset_stream("convex_hulls.bin", std::ios::in | std::ios::binary);
|
||||
std::istream &points_stream = points_asset_stream.Get();
|
||||
for (;;)
|
||||
{
|
||||
// Read the length of the next point cloud
|
||||
uint32 len = 0;
|
||||
points_stream.read((char *)&len, sizeof(len));
|
||||
if (points_stream.eof())
|
||||
break;
|
||||
|
||||
// Read the points
|
||||
if (len > 0)
|
||||
{
|
||||
Points p;
|
||||
for (uint32 i = 0; i < len; ++i)
|
||||
{
|
||||
Float3 v;
|
||||
points_stream.read((char *)&v, sizeof(v));
|
||||
p.push_back(Vec3(v));
|
||||
}
|
||||
mPoints.push_back(std::move(p));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConvexHullShrinkTest::PrePhysicsUpdate(const PreUpdateParams &inParams)
|
||||
{
|
||||
// Take one of the predefined shapes
|
||||
const Points &points = mIteration < mPoints.size()? mPoints[mIteration] : mPoints.back();
|
||||
mIteration++;
|
||||
|
||||
// Create shape
|
||||
ConvexHullShapeSettings settings(points, cDefaultConvexRadius);
|
||||
Shape::ShapeResult result = settings.Create();
|
||||
if (!result.IsValid())
|
||||
{
|
||||
Trace("%d: %s", mIteration - 1, result.GetError().c_str());
|
||||
return;
|
||||
}
|
||||
RefConst<ConvexHullShape> shape = StaticCast<ConvexHullShape>(result.Get());
|
||||
|
||||
// Shape creation may have reduced the convex radius, fetch the result
|
||||
const float convex_radius = shape->GetConvexRadius();
|
||||
if (convex_radius > 0.0f)
|
||||
{
|
||||
// Get the support function of the shape excluding convex radius and add the convex radius
|
||||
ConvexShape::SupportBuffer buffer;
|
||||
const ConvexShape::Support *support = shape->GetSupportFunction(ConvexShape::ESupportMode::ExcludeConvexRadius, buffer, Vec3::sOne());
|
||||
AddConvexRadius add_cvx(*support, convex_radius);
|
||||
|
||||
// Calculate the error w.r.t. the original hull
|
||||
float max_error = -FLT_MAX;
|
||||
int max_error_plane = 0;
|
||||
Vec3 max_error_support_point = Vec3::sZero();
|
||||
const Array<Plane> &planes = shape->GetPlanes();
|
||||
for (int i = 0; i < (int)planes.size(); ++i)
|
||||
{
|
||||
const Plane &plane = planes[i];
|
||||
Vec3 support_point = add_cvx.GetSupport(plane.GetNormal());
|
||||
float distance = plane.SignedDistance(support_point);
|
||||
if (distance > max_error)
|
||||
{
|
||||
max_error = distance;
|
||||
max_error_support_point = support_point;
|
||||
max_error_plane = i;
|
||||
}
|
||||
}
|
||||
if (max_error > settings.mMaxErrorConvexRadius)
|
||||
{
|
||||
Trace("%d, %f, %f", mIteration - 1, (double)convex_radius, (double)max_error);
|
||||
DrawMarkerSP(mDebugRenderer, max_error_support_point, Color::sPurple, 0.1f);
|
||||
DrawArrowSP(mDebugRenderer, max_error_support_point, max_error_support_point - max_error * planes[max_error_plane].GetNormal(), Color::sPurple, 0.01f);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef JPH_DEBUG_RENDERER
|
||||
// Draw the hulls
|
||||
shape->Draw(DebugRenderer::sInstance, RMat44::sIdentity(), Vec3::sOne(), Color::sRed, false, false);
|
||||
shape->DrawGetSupportFunction(DebugRenderer::sInstance, RMat44::sIdentity(), Vec3::sOne(), Color::sLightGrey, false);
|
||||
shape->DrawShrunkShape(DebugRenderer::sInstance, RMat44::sIdentity(), Vec3::sOne());
|
||||
#endif // JPH_DEBUG_RENDERER
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
|
||||
// Create a convex hull, shrink it with the convex radius and expand it again to check the error
|
||||
class ConvexHullShrinkTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, ConvexHullShrinkTest)
|
||||
|
||||
// Initialize the test
|
||||
virtual void Initialize() override;
|
||||
|
||||
// Update the test, called before the physics update
|
||||
virtual void PrePhysicsUpdate(const PreUpdateParams &inParams) override;
|
||||
|
||||
// Number used to scale the terrain and camera movement to the scene
|
||||
virtual float GetWorldScale() const override { return 0.2f; }
|
||||
|
||||
private:
|
||||
// A list of predefined points to feed the convex hull algorithm
|
||||
using Points = Array<Vec3>;
|
||||
Array<Points> mPoints;
|
||||
|
||||
// Which index in the list we're currently using
|
||||
size_t mIteration = 0;
|
||||
};
|
||||
@@ -0,0 +1,628 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/ConvexCollision/ConvexHullTest.h>
|
||||
#include <Jolt/Geometry/ConvexHullBuilder.h>
|
||||
#include <Utils/Log.h>
|
||||
#include <Utils/AssetStream.h>
|
||||
#include <Utils/DebugRendererSP.h>
|
||||
|
||||
JPH_SUPPRESS_WARNINGS_STD_BEGIN
|
||||
#include <fstream>
|
||||
JPH_SUPPRESS_WARNINGS_STD_END
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(ConvexHullTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(ConvexHullTest, Test)
|
||||
}
|
||||
|
||||
void ConvexHullTest::Initialize()
|
||||
{
|
||||
// First add a list of shapes that were problematic before
|
||||
mPoints = {
|
||||
{
|
||||
Vec3(-1, 0, -1),
|
||||
Vec3(1, 0, -1),
|
||||
Vec3(-1, 0, 1),
|
||||
Vec3(1, 0, 1)
|
||||
},
|
||||
{
|
||||
Vec3(-1, 0, -1),
|
||||
Vec3(1, 0, -1),
|
||||
Vec3(-1, 0, 1),
|
||||
Vec3(-0.5f, 0, -0.5f)
|
||||
},
|
||||
{
|
||||
Vec3(-1, 0, -1),
|
||||
Vec3(1, 0, -1),
|
||||
Vec3(-1, 0, 1),
|
||||
Vec3(1, 0, 1),
|
||||
Vec3(0, 1, 0)
|
||||
},
|
||||
{
|
||||
Vec3(1.25793016f, 0.157113776f, 1.22066617f),
|
||||
Vec3(1.92657053f, 0.157114446f, 0.240761176f),
|
||||
Vec3(1.40259242f, 0.157115221f, -0.834863901f),
|
||||
Vec3(1.94086421f, 0.157113507f, -0.790734947f),
|
||||
Vec3(2.20533752f, 0.157113209f, -0.281754375f),
|
||||
Vec3(0.0426187329f, 0.157113969f, -1.40533638f),
|
||||
Vec3(1.11055744f, 0.157113969f, -1.33626819f),
|
||||
Vec3(0.180490851f, 0.157114655f, 1.16420007f),
|
||||
Vec3(-1.34696794f, 0.157110974f, -0.978962243f),
|
||||
Vec3(-0.981223822f, 0.157110706f, -1.44589376f),
|
||||
Vec3(-1.8200444f, 0.157106474f, 1.05036092f),
|
||||
Vec3(-0.376947045f, 0.15711388f, 1.13544536f),
|
||||
Vec3(-1.37966835f, 0.157109678f, 1.08289516f),
|
||||
Vec3(-1.04599845f, 0.157108605f, 1.54891157f),
|
||||
Vec3(-0.597127378f, 0.157110557f, 1.57243586f),
|
||||
Vec3(-2.09407234f, 0.157106325f, 0.560136259f),
|
||||
Vec3(-1.91857386f, 0.157108605f, 0.0392456949f),
|
||||
Vec3(-2.08503342f, 0.157106936f, -0.506603181f),
|
||||
Vec3(-1.80278254f, 0.157107696f, -0.986931145f),
|
||||
Vec3(0.434835076f, 0.157112151f, 1.62568307f),
|
||||
Vec3(0.917346299f, 0.157111734f, 1.65097046f),
|
||||
Vec3(1.77710009f, 0.157112047f, 1.2388792f),
|
||||
Vec3(2.11432409f, 0.157112464f, 0.780689001f),
|
||||
},
|
||||
{
|
||||
Vec3(1.32055235f, -0.0982032791f, 0.020047307f),
|
||||
Vec3(-0.0175848603f, -0.104957283f, 0.020047307f),
|
||||
Vec3(-0.0175848603f, 0.098285675f, 0.020047307f),
|
||||
Vec3(1.32055235f, 0.098285675f, 0.020047307f),
|
||||
Vec3(1.00427914f, -0.0982032791f, 0.868395209f),
|
||||
Vec3(1.32055235f, -0.0982032791f, 2.63605499f),
|
||||
Vec3(1.00427914f, -0.0982032791f, 1.95698023f),
|
||||
Vec3(1.00427914f, -0.104957283f, 0.511006474f),
|
||||
Vec3(0.00150847435f, -0.104957283f, 0.511006474f),
|
||||
Vec3(0.271511227f, -0.179470509f, 0.868395209f),
|
||||
Vec3(0.00150847435f, -0.179470509f, 0.868395209f),
|
||||
Vec3(0.00150847435f, -0.179470509f, 0.511006474f),
|
||||
Vec3(0.271511227f, -0.179470509f, 0.511006474f),
|
||||
Vec3(1.00427914f, -0.145700991f, 1.95698023f),
|
||||
Vec3(1.00427914f, -0.145700991f, 2.40789247f),
|
||||
Vec3(0.271511227f, -0.179470509f, 2.40789247f),
|
||||
Vec3(0.271511227f, -0.179470509f, 1.95698023f),
|
||||
Vec3(0.00150847435f, -0.104957283f, 2.40789247f),
|
||||
Vec3(1.00427914f, -0.104957283f, 2.40789247f),
|
||||
Vec3(-0.0175848603f, -0.104957283f, 2.63605499f),
|
||||
Vec3(1.32055235f, 0.098285675f, 2.63605499f),
|
||||
Vec3(-0.0175848603f, 0.098285675f, 2.63605499f),
|
||||
Vec3(-0.0175848603f, -0.0929760709f, 1.31891572f),
|
||||
Vec3(-0.0175848603f, 0.0915316716f, 1.31891572f),
|
||||
Vec3(1.00427914f, -0.145700991f, 0.868395209f),
|
||||
Vec3(1.00427914f, -0.145700991f, 0.511006474f),
|
||||
Vec3(0.00150847435f, -0.104957283f, 0.868395209f),
|
||||
Vec3(0.00150847435f, -0.104957283f, 1.95698023f),
|
||||
Vec3(0.00150847435f, -0.179470509f, 1.95698023f),
|
||||
Vec3(0.00150847435f, -0.179470509f, 2.40789247f),
|
||||
Vec3(-0.0175848603f, -0.100129686f, 0.959797204f),
|
||||
Vec3(0.0878298879f, 0.139223307f, 1.04704332f),
|
||||
Vec3(0.122709334f, -0.147821367f, 1.15395057f),
|
||||
Vec3(0.122709334f, 0.139223307f, 1.15395057f),
|
||||
Vec3(0.19671753f, -0.118080139f, 1.15425301f),
|
||||
Vec3(0.0986568928f, -0.147821367f, 1.22612f),
|
||||
Vec3(0.175069571f, -0.118080139f, 1.2711879f),
|
||||
Vec3(-0.0175848603f, -0.147821367f, 0.959797204f),
|
||||
Vec3(0.0767889619f, -0.118080139f, 0.947003484f),
|
||||
Vec3(0.0878298879f, -0.147821367f, 1.04704332f),
|
||||
Vec3(0.18563965f, -0.118080139f, 1.03236175f),
|
||||
Vec3(-0.0175848603f, 0.098285675f, 0.959797204f),
|
||||
Vec3(0.0986568928f, 0.139223307f, 1.22612f),
|
||||
Vec3(0.0897113085f, -0.104957283f, 1.32667887f),
|
||||
Vec3(-0.0175848603f, -0.147821367f, 1.31891572f),
|
||||
Vec3(0.0897113085f, -0.118080139f, 1.32667887f),
|
||||
Vec3(0.175069571f, -0.104957283f, 1.2711879f),
|
||||
Vec3(0.18563965f, -0.104957283f, 1.03236175f),
|
||||
Vec3(0.19671753f, -0.104957283f, 1.15425301f),
|
||||
Vec3(0.0767889619f, -0.104957283f, 0.947003484f),
|
||||
Vec3(1.00427914f, 0.098285675f, 0.868395209f),
|
||||
Vec3(1.00427914f, 0.098285675f, 1.95698023f),
|
||||
Vec3(1.00427914f, 0.098285675f, 0.511006474f),
|
||||
Vec3(0.00150847435f, 0.098285675f, 0.511006474f),
|
||||
Vec3(0.00150847435f, 0.17087248f, 0.511006474f),
|
||||
Vec3(0.00150847435f, 0.17087248f, 0.868395209f),
|
||||
Vec3(0.271511227f, 0.17087248f, 0.868395209f),
|
||||
Vec3(0.271511227f, 0.17087248f, 0.511006474f),
|
||||
Vec3(0.271511227f, 0.17087248f, 2.40789247f),
|
||||
Vec3(1.00427914f, 0.137102962f, 2.40789247f),
|
||||
Vec3(1.00427914f, 0.137102962f, 1.95698023f),
|
||||
Vec3(0.271511227f, 0.17087248f, 1.95698023f),
|
||||
Vec3(0.00150847435f, 0.098285675f, 2.40789247f),
|
||||
Vec3(1.00427914f, 0.098285675f, 2.40789247f),
|
||||
Vec3(1.00427914f, 0.137102962f, 0.868395209f),
|
||||
Vec3(1.00427914f, 0.137102962f, 0.511006474f),
|
||||
Vec3(0.00150847435f, 0.098285675f, 0.868395209f),
|
||||
Vec3(0.00150847435f, 0.098285675f, 1.95698023f),
|
||||
Vec3(0.00150847435f, 0.17087248f, 1.95698023f),
|
||||
Vec3(0.00150847435f, 0.17087248f, 2.40789247f),
|
||||
Vec3(0.19671753f, 0.109482117f, 1.15425301f),
|
||||
Vec3(0.175069571f, 0.109482117f, 1.2711879f),
|
||||
Vec3(-0.0175848603f, 0.139223307f, 0.959797204f),
|
||||
Vec3(0.0767889619f, 0.109482117f, 0.947003484f),
|
||||
Vec3(0.18563965f, 0.109482117f, 1.03236175f),
|
||||
Vec3(0.0897113085f, 0.098285675f, 1.32667887f),
|
||||
Vec3(-0.0175848603f, 0.139223307f, 1.31891572f),
|
||||
Vec3(0.0897113085f, 0.109482117f, 1.32667887f),
|
||||
Vec3(0.175069571f, 0.098285675f, 1.2711879f),
|
||||
Vec3(0.19671753f, 0.098285675f, 1.15425301f),
|
||||
Vec3(0.18563965f, 0.098285675f, 1.03236175f),
|
||||
Vec3(0.0767889619f, 0.098285675f, 0.947003484f)
|
||||
},
|
||||
{
|
||||
Vec3(0.0212580804f, 1.29376173f, 0.0102035152f),
|
||||
Vec3(0.0225791596f, 1.05854928f, 0.0887729526f),
|
||||
Vec3(0.0596007220f, 0.984267414f, 0.0408750288f),
|
||||
Vec3(0.0722020790f, 0.980246127f, -0.0416274220f),
|
||||
Vec3(-0.00376634207f, -0.718282819f, 0.00411359267f),
|
||||
Vec3(-0.00188124576f, -0.718283117f, 0.00229378697f),
|
||||
Vec3(-0.00162511703f, -0.718282461f, 0.00753012672f),
|
||||
Vec3(-0.00118427153f, 1.36079276f, 0.00107491738f),
|
||||
Vec3(-6.78644137e-05f, -0.718282998f, 0.00426622201f),
|
||||
Vec3(0.00102991192f, 1.29927433f, 0.0230795704f),
|
||||
Vec3(0.00699944887f, 1.05855191f, 0.0887731761f),
|
||||
Vec3(-0.00603519706f, 1.04913890f, -0.102404378f),
|
||||
Vec3(-0.0212373994f, 1.31092644f, 0.00530112581f),
|
||||
Vec3(-0.0542707182f, 1.07623804f, 0.0403260253f),
|
||||
Vec3(-0.0946691483f, 1.07357991f, -0.0185115524f),
|
||||
Vec3(-0.0946691483f, 1.07357991f, -0.0185115524f)
|
||||
},
|
||||
{
|
||||
Vec3(0.0283679180f, 0.0443800166f, -0.00569444988f),
|
||||
Vec3(0.0327114500f, -0.0221119970f, 0.0232404359f),
|
||||
Vec3(0.0374971032f, 0.0148781445f, -0.0245264377f),
|
||||
Vec3(0.0439460576f, 0.0126368264f, 0.0197663195f),
|
||||
Vec3(-0.0327170566f, 0.0423904508f, 0.0181609988f),
|
||||
Vec3(-0.0306955911f, 0.0311534479f, -0.0281516202f),
|
||||
Vec3(-0.0262422040f, 0.0248970203f, 0.0450032614f),
|
||||
Vec3(-0.0262093470f, 0.00906597450f, 0.0481815264f),
|
||||
Vec3(-0.0256845430f, -0.00607067533f, -0.0401362479f),
|
||||
Vec3(-0.0179684199f, 0.0266145933f, -0.0394567028f),
|
||||
Vec3(-0.00567848794f, -0.0313231349f, -0.0263656937f),
|
||||
Vec3(-0.00444967486f, -0.0383231938f, 0.0206601117f),
|
||||
Vec3(-0.00329093798f, 0.0464436933f, 0.0343827978f),
|
||||
Vec3(-0.00225042878f, 0.0550651476f, -0.00304153794f),
|
||||
Vec3(0.00310287252f, 0.00219658483f, 0.0542362332f),
|
||||
Vec3(0.00435558241f, 0.00644031307f, -0.0455060303f),
|
||||
Vec3(0.00495047215f, -0.0144955292f, 0.0482611060f),
|
||||
Vec3(0.00510909408f, 0.0300753452f, -0.0415933356f),
|
||||
Vec3(0.00619197031f, 0.0269140154f, 0.0500008501f),
|
||||
Vec3(0.0190936550f, -0.0106478147f, 0.0453430638f),
|
||||
Vec3(0.0202461667f, 0.00821140409f, 0.0500608832f),
|
||||
Vec3(0.0199985132f, 0.0353404805f, 0.0413853638f),
|
||||
Vec3(0.0267947838f, -0.0155944452f, -0.0300960485f),
|
||||
Vec3(0.0274163429f, 0.0318853259f, -0.0288569275f),
|
||||
Vec3(-0.0404368788f, -0.0213200711f, -0.00530833099f),
|
||||
Vec3(-0.0383560173f, -0.0111571737f, 0.0346816145f),
|
||||
Vec3(-0.0453024730f, 0.00178011740f, -0.0218658112f),
|
||||
Vec3(-0.0482929349f, 0.0101582557f, 0.0191618335f)
|
||||
},
|
||||
{
|
||||
Vec3(0.19555497f, 0.06892325f, 0.21078214f),
|
||||
Vec3(0.20527978f, -0.01703966f, -0.09207391f),
|
||||
Vec3(0.21142941f, 0.01785821f, -0.09836373f),
|
||||
Vec3(0.21466828f, 0.05084385f, -0.03549951f),
|
||||
Vec3(-0.20511348f, -0.07018351f, -0.31925454f),
|
||||
Vec3(-0.19310803f, -0.13756239f, -0.33457401f),
|
||||
Vec3(-0.20095457f, -0.09572067f, -0.11383702f),
|
||||
Vec3(-0.18695570f, -0.14865115f, -0.19356145f),
|
||||
Vec3(-0.18073241f, -0.08639215f, -0.35319963f),
|
||||
Vec3(-0.18014188f, -0.15241129f, -0.34185338f),
|
||||
Vec3(-0.18174356f, -0.15312561f, -0.19147469f),
|
||||
Vec3(-0.19579467f, 0.01310298f, -0.00632396f),
|
||||
Vec3(-0.16814114f, -0.05610058f, -0.34890732f),
|
||||
Vec3(-0.16448530f, -0.16787034f, -0.29141789f),
|
||||
Vec3(-0.17525161f, 0.01533679f, 0.08730947f),
|
||||
Vec3(-0.17286175f, 0.08774700f, -0.01591185f),
|
||||
Vec3(-0.17077128f, 0.01983560f, 0.10070839f),
|
||||
Vec3(-0.14615997f, -0.16541340f, -0.37489247f),
|
||||
Vec3(-0.14595763f, -0.16490393f, -0.37515628f),
|
||||
Vec3(-0.16272801f, 0.07975677f, 0.08464866f),
|
||||
Vec3(-0.13369306f, -0.06286648f, -0.37556374f),
|
||||
Vec3(-0.14785704f, 0.14323678f, -0.01563696f),
|
||||
Vec3(-0.12817731f, -0.04268694f, -0.36287897f),
|
||||
Vec3(-0.14112462f, 0.13547241f, 0.05140329f),
|
||||
Vec3(-0.12341158f, -0.17782864f, -0.36954373f),
|
||||
Vec3(-0.12310848f, -0.18070405f, -0.20412853f),
|
||||
Vec3(-0.09967888f, -0.18289816f, -0.38768309f),
|
||||
Vec3(-0.09960851f, 0.14144828f, 0.12903015f),
|
||||
Vec3(-0.08962545f, -0.17236463f, -0.39919903f),
|
||||
Vec3(-0.09338194f, -0.00865331f, 0.23358464f),
|
||||
Vec3(-0.09496998f, 0.17418922f, 0.03730623f),
|
||||
Vec3(-0.09499961f, 0.16077143f, -0.03914160f),
|
||||
Vec3(-0.08221246f, -0.07778487f, -0.39787262f),
|
||||
Vec3(-0.07918695f, -0.14616625f, -0.40242865f),
|
||||
Vec3(-0.08256439f, 0.01469633f, 0.24209134f),
|
||||
Vec3(-0.07199146f, 0.16959090f, 0.11185526f),
|
||||
Vec3(-0.05876892f, -0.18819671f, -0.40239989f),
|
||||
Vec3(-0.05744339f, -0.18692162f, -0.40386000f),
|
||||
Vec3(-0.04441069f, -0.04126521f, -0.37501192f),
|
||||
Vec3(-0.04648328f, 0.18093951f, 0.03905040f),
|
||||
Vec3(-0.03611449f, -0.14904837f, -0.40508240f),
|
||||
Vec3(-0.03163360f, 0.17144355f, 0.13303288f),
|
||||
Vec3(-0.02255749f, -0.01798030f, 0.33883106f),
|
||||
Vec3(-0.01062212f, -0.11764656f, -0.39784804f),
|
||||
Vec3(0.00002799f, -0.18946082f, -0.39155373f),
|
||||
Vec3(0.00190875f, -0.16691279f, -0.40337407f),
|
||||
Vec3(0.02337403f, -0.03170533f, 0.38295418f),
|
||||
Vec3(0.02689898f, -0.03111388f, 0.38642361f),
|
||||
Vec3(0.03513940f, -0.09795553f, -0.38733068f),
|
||||
Vec3(0.04139633f, -0.18845227f, -0.32015734f),
|
||||
Vec3(0.04843888f, 0.12765829f, -0.09677977f),
|
||||
Vec3(0.04454701f, -0.14539991f, -0.38590988f),
|
||||
Vec3(0.04690936f, -0.17584648f, -0.38177087f),
|
||||
Vec3(0.05052238f, -0.18907529f, -0.35411724f),
|
||||
Vec3(0.07129140f, -0.02806735f, 0.41684112f),
|
||||
Vec3(0.07599759f, 0.02516599f, 0.43382310f),
|
||||
Vec3(0.08328492f, -0.18135514f, -0.32588836f),
|
||||
Vec3(0.08443428f, 0.07232403f, 0.37877142f),
|
||||
Vec3(0.09074404f, -0.15272216f, -0.36002999f),
|
||||
Vec3(0.09381036f, -0.04931259f, -0.32999005f),
|
||||
Vec3(0.09348832f, -0.17767928f, -0.33666068f),
|
||||
Vec3(0.09247280f, -0.01328942f, 0.44227284f),
|
||||
Vec3(0.09364306f, 0.03557658f, 0.44191616f),
|
||||
Vec3(0.09611026f, -0.01203391f, 0.44345939f),
|
||||
Vec3(0.09662163f, 0.03456752f, 0.44326156f),
|
||||
Vec3(0.10482377f, 0.12817247f, 0.27224415f),
|
||||
Vec3(0.11271536f, 0.12685699f, 0.26856660f),
|
||||
Vec3(0.10957191f, 0.03837919f, 0.43455946f),
|
||||
Vec3(0.11146642f, -0.01284471f, 0.42120608f),
|
||||
Vec3(0.11088928f, 0.00377234f, 0.44789928f),
|
||||
Vec3(0.11571233f, -0.12474029f, -0.34762913f),
|
||||
Vec3(0.12183426f, -0.16410264f, -0.30295142f),
|
||||
Vec3(0.12211698f, 0.01099167f, 0.44373258f),
|
||||
Vec3(0.12308656f, 0.01315179f, 0.44303578f),
|
||||
Vec3(0.13090495f, -0.15086941f, -0.31031519f),
|
||||
Vec3(0.14427974f, 0.09778974f, 0.30786031f),
|
||||
Vec3(0.14200252f, 0.01419945f, 0.41783332f),
|
||||
Vec3(0.14424091f, 0.06972501f, 0.37377491f),
|
||||
Vec3(0.14422383f, 0.02227210f, 0.41717034f),
|
||||
Vec3(0.15133176f, -0.03861540f, -0.27380293f),
|
||||
Vec3(0.14738929f, 0.06972805f, 0.37101438f),
|
||||
Vec3(0.15116664f, -0.13012324f, -0.26891800f),
|
||||
Vec3(0.15432675f, -0.05065062f, -0.27696538f),
|
||||
Vec3(0.17231981f, 0.09891064f, -0.04109610f),
|
||||
Vec3(0.15486444f, 0.03080789f, 0.39333733f),
|
||||
Vec3(0.16293872f, 0.09977609f, 0.23133035f),
|
||||
Vec3(0.17278114f, 0.05925680f, -0.13166353f),
|
||||
Vec3(0.17344120f, 0.06815492f, 0.29800513f),
|
||||
Vec3(0.18346339f, 0.03002923f, -0.16944433f),
|
||||
Vec3(0.18475264f, -0.03337195f, -0.21144425f),
|
||||
Vec3(0.18153211f, 0.05077920f, 0.29410797f),
|
||||
Vec3(0.18872119f, 0.08419117f, 0.18681980f),
|
||||
Vec3(0.19402013f, 0.03129275f, -0.14645814f),
|
||||
Vec3(0.20299899f, 0.06450803f, -0.05323168f),
|
||||
Vec3(-0.20916573f, -0.14482390f, -0.28754678f),
|
||||
Vec3(-0.21912349f, -0.12297497f, -0.25853595f),
|
||||
Vec3(-0.21891747f, -0.11492035f, -0.30946639f),
|
||||
Vec3(-0.22503024f, -0.09871494f, -0.27031892f),
|
||||
Vec3(-0.22503024f, -0.09871494f, -0.27031892f),
|
||||
Vec3(-0.22503024f, -0.09871494f, -0.27031892f)
|
||||
},
|
||||
{
|
||||
Vec3(0.28483882f, 0.09470236f, 0.11433057f),
|
||||
Vec3(0.30260321f, 0.07340867f, 0.00849266f),
|
||||
Vec3(0.30380272f, 0.05582517f, -0.22405298f),
|
||||
Vec3(0.30670973f, 0.02778204f, -0.22415190f),
|
||||
Vec3(-0.29766368f, -0.06492511f, -0.19135096f),
|
||||
Vec3(-0.28324991f, 0.02856347f, 0.16558051f),
|
||||
Vec3(-0.27339774f, 0.11253071f, -0.13812468f),
|
||||
Vec3(-0.26324614f, -0.03483995f, 0.34903234f),
|
||||
Vec3(-0.27118766f, -0.15035510f, -0.06431498f),
|
||||
Vec3(-0.26041472f, 0.10464326f, -0.20795805f),
|
||||
Vec3(-0.22156618f, -0.00712212f, 0.40348106f),
|
||||
Vec3(-0.20013636f, 0.13795423f, -0.23888915f),
|
||||
Vec3(-0.19368620f, 0.04208890f, 0.42129427f),
|
||||
Vec3(-0.18170905f, -0.10169907f, 0.38139578f),
|
||||
Vec3(-0.18724660f, 0.18995818f, 0.08522552f),
|
||||
Vec3(-0.17479378f, -0.05597380f, 0.41057986f),
|
||||
Vec3(-0.15012621f, 0.08595391f, 0.43914794f),
|
||||
Vec3(-0.11722116f, -0.10298516f, -0.30289822f),
|
||||
Vec3(-0.11217459f, 0.00596011f, 0.44133874f),
|
||||
Vec3(-0.11709289f, 0.23012112f, 0.12055066f),
|
||||
Vec3(-0.10705470f, 0.15775623f, -0.33419770f),
|
||||
Vec3(-0.08655276f, 0.09824081f, 0.43651989f),
|
||||
Vec3(-0.08401379f, 0.08668444f, -0.41111666f),
|
||||
Vec3(-0.08026488f, -0.24695427f, -0.01228247f),
|
||||
Vec3(-0.06294082f, 0.12666735f, -0.39178270f),
|
||||
Vec3(-0.05308891f, -0.07724215f, -0.37346649f),
|
||||
Vec3(-0.04869145f, -0.23846265f, -0.11154356f),
|
||||
Vec3(-0.04377052f, 0.06346821f, 0.44263243f),
|
||||
Vec3(-0.03821557f, 0.05776290f, -0.43330976f),
|
||||
Vec3(-0.01401243f, -0.07849873f, 0.37016886f),
|
||||
Vec3(-0.01267736f, -0.24327334f, -0.09846258f),
|
||||
Vec3(-0.00871999f, -0.24532425f, -0.01158716f),
|
||||
Vec3(0.00610917f, 0.20575316f, -0.32363408f),
|
||||
Vec3(0.01893912f, -0.02637211f, -0.44099009f),
|
||||
Vec3(0.03742292f, 0.25572568f, 0.11976100f),
|
||||
Vec3(0.04572892f, -0.02452080f, 0.37599292f),
|
||||
Vec3(0.04809525f, 0.11413645f, 0.38247618f),
|
||||
Vec3(0.04934106f, -0.01875172f, -0.43612641f),
|
||||
Vec3(0.07854398f, 0.13351599f, 0.34539741f),
|
||||
Vec3(0.11064179f, 0.03347895f, 0.33272063f),
|
||||
Vec3(0.11110801f, 0.04016598f, -0.42360800f),
|
||||
Vec3(0.12390327f, -0.20230874f, -0.01599736f),
|
||||
Vec3(0.13082972f, -0.19843940f, -0.08606190f),
|
||||
Vec3(0.12559986f, -0.02563187f, -0.38013845f),
|
||||
Vec3(0.12924608f, 0.16206453f, -0.34893369f),
|
||||
Vec3(0.15646456f, 0.21451330f, 0.16623015f),
|
||||
Vec3(0.17851203f, -0.14074428f, 0.08427754f),
|
||||
Vec3(0.19401437f, -0.15288332f, -0.03272480f),
|
||||
Vec3(0.20102191f, 0.08705597f, -0.37915167f),
|
||||
Vec3(0.20596674f, 0.06604006f, -0.38868805f),
|
||||
Vec3(0.26085311f, 0.08702713f, -0.32507085f),
|
||||
Vec3(0.27331018f, 0.15497627f, 0.11259682f),
|
||||
Vec3(0.27269470f, 0.03719006f, -0.31962081f),
|
||||
Vec3(0.27288356f, 0.06217747f, -0.33064606f),
|
||||
Vec3(-0.29314118f, -0.18079891f, 0.24351751f),
|
||||
Vec3(-0.30831277f, -0.06952596f, 0.07340523f),
|
||||
Vec3(-0.30126276f, -0.18365636f, 0.22815129f),
|
||||
Vec3(-0.30392047f, -0.17969127f, 0.22713920f),
|
||||
Vec3(-0.30392047f, -0.17969127f, 0.22713920f),
|
||||
Vec3(-0.30392047f, -0.17969127f, 0.22713920f)
|
||||
},
|
||||
{
|
||||
// A really small hull
|
||||
Vec3(-0.00707678869f, 0.00559568405f, -0.0239779726f),
|
||||
Vec3(0.0136205591f, 0.00541752577f, -0.0225500446f),
|
||||
Vec3(0.0135576781f, 0.00559568405f, -0.0224227905f),
|
||||
Vec3(-0.0108219199f, 0.00559568405f, -0.0223935191f),
|
||||
Vec3(0.0137226451f, 0.00559568405f, -0.0220940933f),
|
||||
Vec3(0.00301175844f, -0.0232942104f, -0.0214947499f),
|
||||
Vec3(0.017349612f, 0.00559568405f, 0.0241708681f),
|
||||
Vec3(0.00390899926f, -0.0368074179f, 0.0541367307f),
|
||||
Vec3(-0.0164459459f, 0.00559568405f, 0.0607497096f),
|
||||
Vec3(-0.0169881769f, 0.00559568405f, 0.0608173609f),
|
||||
Vec3(-0.0168782212f, 0.0052883029f, 0.0613293499f),
|
||||
Vec3(-0.00663783913f, 0.00559568405f, -0.024154868f),
|
||||
Vec3(-0.00507298298f, 0.00559568405f, -0.0242112875f),
|
||||
Vec3(-0.00565947127f, 0.00477081537f, -0.0243848339f),
|
||||
Vec3(0.0118075963f, 0.00124305487f, -0.0258472487f),
|
||||
Vec3(0.00860248506f, -0.00697988272f, -0.0276725553f),
|
||||
},
|
||||
{
|
||||
// Nearly co-planar hull (but not enough to go through the 2d hull builder)
|
||||
Vec3(0.129325435f, -0.213319957f, 0.00901593268f),
|
||||
Vec3(0.129251331f, -0.213436425f, 0.00932094082f),
|
||||
Vec3(0.160741553f, -0.171540618f, 0.0494558439f),
|
||||
Vec3(0.160671368f, -0.17165187f, 0.049765937f),
|
||||
Vec3(0.14228563f, 0.432965666f, 0.282429159f),
|
||||
Vec3(0.142746598f, 0.433226734f, 0.283286631f),
|
||||
Vec3(0.296031296f, 0.226935148f, 0.312804461f),
|
||||
Vec3(0.296214104f, 0.227568939f, 0.313606918f),
|
||||
Vec3(-0.00354258716f, -0.180767179f, -0.0762089267f),
|
||||
Vec3(-0.00372517109f, -0.1805875f, -0.0766792595f),
|
||||
Vec3(-0.0157070309f, -0.176182508f, -0.0833940506f),
|
||||
Vec3(-0.0161666721f, -0.175898403f, -0.0840280354f),
|
||||
Vec3(-0.342764735f, 0.0259497911f, -0.244388372f),
|
||||
Vec3(-0.342298329f, 0.0256615728f, -0.24456653f),
|
||||
Vec3(-0.366584063f, 0.0554589033f, -0.250078142f),
|
||||
Vec3(-0.366478682f, 0.0556178838f, -0.250342518f),
|
||||
},
|
||||
{
|
||||
// A hull with a very acute angle that won't properly build when using distance to plane only
|
||||
Vec3(-0.0451235026f, -0.103826642f, -0.0346511155f),
|
||||
Vec3(-0.0194563419f, -0.123563275f, -0.032212317f),
|
||||
Vec3(0.0323024541f, -0.0468643308f, -0.0307639092f),
|
||||
Vec3(0.0412166864f, -0.0884782523f, -0.0288816988f),
|
||||
Vec3(-0.0564572513f, 0.0207469314f, 0.0169318169f),
|
||||
Vec3(0.00537410378f, 0.105688639f, 0.0355164111f),
|
||||
Vec3(0.0209896415f, 0.117749952f, 0.0365252197f),
|
||||
Vec3(0.0211542398f, 0.118546993f, 0.0375355929f),
|
||||
}
|
||||
};
|
||||
|
||||
// Add a cube formed out of a regular grid of vertices, this shows how the algorithm deals
|
||||
// with many coplanar points
|
||||
{
|
||||
Points p;
|
||||
for (int x = 0; x < 10; ++x)
|
||||
for (int y = 0; y < 10; ++y)
|
||||
for (int z = 0; z < 10; ++z)
|
||||
p.push_back(Vec3::sReplicate(-0.5f) * 0.1f * Vec3(float(x), float(y), float(z)));
|
||||
mPoints.push_back(std::move(p));
|
||||
}
|
||||
|
||||
// Add disc of many points
|
||||
{
|
||||
Points p;
|
||||
Mat44 rot = Mat44::sRotationZ(0.25f * JPH_PI);
|
||||
for (float r = 0.0f; r < 2.0f; r += 0.1f)
|
||||
for (float phi = 0.0f; phi <= 2.0f * JPH_PI; phi += 2.0f * JPH_PI / 20.0f)
|
||||
p.push_back(rot * Vec3(r * Cos(phi), r * Sin(phi), 0));
|
||||
mPoints.push_back(std::move(p));
|
||||
}
|
||||
|
||||
// Add wedge shaped disc that is just above the hull tolerance on its widest side and zero on the other side
|
||||
{
|
||||
Points p;
|
||||
for (float phi = 0.0f; phi <= 2.0f * JPH_PI; phi += 2.0f * JPH_PI / 40.0f)
|
||||
{
|
||||
Vec3 pos(2.0f * Cos(phi), 0, 2.0f * Sin(phi));
|
||||
p.push_back(pos);
|
||||
p.push_back(pos + Vec3(0, 2.0e-3f * (2.0f + pos.GetX()) / 4.0f, 0));
|
||||
}
|
||||
mPoints.push_back(std::move(p));
|
||||
}
|
||||
|
||||
// Add a sphere of many points
|
||||
{
|
||||
Points p;
|
||||
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)
|
||||
p.push_back(Vec3::sUnitSpherical(theta, phi));
|
||||
mPoints.push_back(std::move(p));
|
||||
}
|
||||
|
||||
// Open the external file with hulls
|
||||
// A stream containing predefined convex hulls
|
||||
AssetStream points_asset_stream("convex_hulls.bin", std::ios::in | std::ios::binary);
|
||||
std::istream &points_stream = points_asset_stream.Get();
|
||||
for (;;)
|
||||
{
|
||||
// Read the length of the next point cloud
|
||||
uint32 len = 0;
|
||||
points_stream.read((char *)&len, sizeof(len));
|
||||
if (points_stream.eof())
|
||||
break;
|
||||
|
||||
// Read the points
|
||||
if (len > 0)
|
||||
{
|
||||
Points p;
|
||||
for (uint32 i = 0; i < len; ++i)
|
||||
{
|
||||
Float3 v;
|
||||
points_stream.read((char *)&v, sizeof(v));
|
||||
p.push_back(Vec3(v));
|
||||
}
|
||||
mPoints.push_back(std::move(p));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConvexHullTest::PrePhysicsUpdate(const PreUpdateParams &inParams)
|
||||
{
|
||||
const float display_scale = 10.0f;
|
||||
|
||||
float tolerance = 1.0e-3f;
|
||||
|
||||
Points points;
|
||||
if (mIteration < mPoints.size())
|
||||
{
|
||||
// Take one of the predefined shapes
|
||||
points = mPoints[mIteration];
|
||||
}
|
||||
else
|
||||
{
|
||||
uniform_real_distribution<float> zero_one(0.0f, 1.0f);
|
||||
uniform_real_distribution<float> zero_two(0.0f, 2.0f);
|
||||
|
||||
// Define vertex scale
|
||||
uniform_real_distribution<float> scale_start(0.1f, 0.5f);
|
||||
uniform_real_distribution<float> scale_range(0.1f, 2.0f);
|
||||
float start = scale_start(mRandom);
|
||||
uniform_real_distribution<float> vertex_scale(start, start + scale_range(mRandom));
|
||||
|
||||
// Define shape scale to make shape less sphere like
|
||||
uniform_real_distribution<float> shape_scale(0.1f, 1.0f);
|
||||
Vec3 scale(shape_scale(mRandom), shape_scale(mRandom), shape_scale(mRandom));
|
||||
|
||||
// Add some random points
|
||||
for (int i = 0; i < 100; ++i)
|
||||
{
|
||||
// Add random point
|
||||
Vec3 p1 = vertex_scale(mRandom) * Vec3::sRandom(mRandom) * scale;
|
||||
points.push_back(p1);
|
||||
|
||||
// Point close to p1
|
||||
Vec3 p2 = p1 + tolerance * zero_two(mRandom) * Vec3::sRandom(mRandom);
|
||||
points.push_back(p2);
|
||||
|
||||
// Point on a line to another point
|
||||
float fraction = zero_one(mRandom);
|
||||
Vec3 p3 = fraction * p1 + (1.0f - fraction) * points[mRandom() % points.size()];
|
||||
points.push_back(p3);
|
||||
|
||||
// Point close to p3
|
||||
Vec3 p4 = p3 + tolerance * zero_two(mRandom) * Vec3::sRandom(mRandom);
|
||||
points.push_back(p4);
|
||||
}
|
||||
}
|
||||
mIteration++;
|
||||
|
||||
using Face = ConvexHullBuilder::Face;
|
||||
using Edge = ConvexHullBuilder::Edge;
|
||||
ConvexHullBuilder builder(points);
|
||||
|
||||
// Build the hull
|
||||
const char *error = nullptr;
|
||||
ConvexHullBuilder::EResult result = builder.Initialize(INT_MAX, tolerance, error);
|
||||
if (result != ConvexHullBuilder::EResult::Success && result != ConvexHullBuilder::EResult::MaxVerticesReached)
|
||||
{
|
||||
Trace("Iteration %d: Failed to initialize from positions: %s", mIteration - 1, error);
|
||||
JPH_ASSERT(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine center of mass
|
||||
Vec3 com;
|
||||
float vol;
|
||||
builder.GetCenterOfMassAndVolume(com, vol);
|
||||
|
||||
// Test if all points are inside the hull with the given tolerance
|
||||
float max_error, coplanar_distance;
|
||||
int max_error_point;
|
||||
Face *max_error_face;
|
||||
builder.DetermineMaxError(max_error_face, max_error, max_error_point, coplanar_distance);
|
||||
|
||||
// Check if error is bigger than 4 * the tolerance
|
||||
if (max_error > 4.0f * max(tolerance, coplanar_distance))
|
||||
{
|
||||
Trace("Iteration %d: max_error=%g", mIteration - 1, (double)max_error);
|
||||
|
||||
// Draw point that had the max error
|
||||
Vec3 point = display_scale * (points[max_error_point] - com);
|
||||
DrawMarkerSP(mDebugRenderer, point, Color::sRed, 1.0f);
|
||||
DrawText3DSP(mDebugRenderer, point, StringFormat("%d: %g", max_error_point, (double)max_error), Color::sRed);
|
||||
|
||||
// Length of normal (2x area) for max error face
|
||||
Vec3 centroid = display_scale * (max_error_face->mCentroid - com);
|
||||
Vec3 centroid_plus_normal = centroid + max_error_face->mNormal.Normalized();
|
||||
DrawArrowSP(mDebugRenderer, centroid, centroid_plus_normal, Color::sGreen, 0.1f);
|
||||
DrawText3DSP(mDebugRenderer, centroid_plus_normal, ConvertToString(max_error_face->mNormal.Length()), Color::sGreen);
|
||||
|
||||
// Draw face that had the max error
|
||||
const Edge *e = max_error_face->mFirstEdge;
|
||||
Vec3 prev = display_scale * (points[e->mStartIdx] - com);
|
||||
do
|
||||
{
|
||||
const Edge *next = e->mNextEdge;
|
||||
Vec3 cur = display_scale * (points[next->mStartIdx] - com);
|
||||
DrawArrowSP(mDebugRenderer, prev, cur, Color::sYellow, 0.01f);
|
||||
DrawText3DSP(mDebugRenderer, prev, ConvertToString(e->mStartIdx), Color::sYellow);
|
||||
e = next;
|
||||
prev = cur;
|
||||
} while (e != max_error_face->mFirstEdge);
|
||||
|
||||
JPH_ASSERT(false);
|
||||
}
|
||||
|
||||
// Draw input points around center of mass
|
||||
for (Vec3 v : points)
|
||||
DrawMarkerSP(mDebugRenderer, display_scale * (v - com), Color::sWhite, 0.01f);
|
||||
|
||||
// Draw the hull around center of mass
|
||||
int color_idx = 0;
|
||||
for (Face *f : builder.GetFaces())
|
||||
{
|
||||
Color color = Color::sGetDistinctColor(color_idx++);
|
||||
|
||||
// First point
|
||||
const Edge *e = f->mFirstEdge;
|
||||
Vec3 p1 = display_scale * (points[e->mStartIdx] - com);
|
||||
|
||||
// Second point
|
||||
e = e->mNextEdge;
|
||||
Vec3 p2 = display_scale * (points[e->mStartIdx] - com);
|
||||
|
||||
// First line
|
||||
DrawLineSP(mDebugRenderer, p1, p2, Color::sGrey);
|
||||
|
||||
do
|
||||
{
|
||||
// Third point
|
||||
e = e->mNextEdge;
|
||||
Vec3 p3 = display_scale * (points[e->mStartIdx] - com);
|
||||
|
||||
DrawTriangleSP(mDebugRenderer, p1, p2, p3, color);
|
||||
|
||||
DrawLineSP(mDebugRenderer, p2, p3, Color::sGrey);
|
||||
|
||||
p2 = p3;
|
||||
}
|
||||
while (e != f->mFirstEdge);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
|
||||
// Simple test to create a convex hull
|
||||
class ConvexHullTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, ConvexHullTest)
|
||||
|
||||
// Initialize the test
|
||||
virtual void Initialize() override;
|
||||
|
||||
// Update the test, called before the physics update
|
||||
virtual void PrePhysicsUpdate(const PreUpdateParams &inParams) override;
|
||||
|
||||
private:
|
||||
// A list of predefined points to feed the convex hull algorithm
|
||||
using Points = Array<Vec3>;
|
||||
Array<Points> mPoints;
|
||||
|
||||
// Which index in the list we're currently using
|
||||
size_t mIteration = 0;
|
||||
|
||||
// If we run out of points, we start creating random points
|
||||
default_random_engine mRandom { 12345 };
|
||||
};
|
||||
@@ -0,0 +1,90 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/ConvexCollision/EPATest.h>
|
||||
#include <Jolt/Geometry/Sphere.h>
|
||||
#include <Jolt/Geometry/AABox.h>
|
||||
#include <Jolt/Geometry/ConvexSupport.h>
|
||||
#include <Jolt/Geometry/EPAPenetrationDepth.h>
|
||||
#include <Utils/DebugRendererSP.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(EPATest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(EPATest, Test)
|
||||
}
|
||||
|
||||
void EPATest::PrePhysicsUpdate(const PreUpdateParams &inParams)
|
||||
{
|
||||
AABox box(Vec3(1, 1, -2), Vec3(2, 2, 2));
|
||||
Sphere sphere(Vec3(4, 4, 0), sqrt(8.0f) + 0.01f);
|
||||
Mat44 matrix = Mat44::sRotationTranslation(Quat::sRotation(Vec3(1, 1, 1).Normalized(), 0.25f * JPH_PI), Vec3(1, 2, 3));
|
||||
bool intersecting = CollideBoxSphere(matrix, box, sphere);
|
||||
JPH_ASSERT(intersecting);
|
||||
(void)intersecting; // For when asserts are off
|
||||
}
|
||||
|
||||
bool EPATest::CollideBoxSphere(Mat44Arg inMatrix, const AABox &inBox, const Sphere &inSphere) const
|
||||
{
|
||||
// Draw the box and shere
|
||||
DrawBoxSP(mDebugRenderer, inMatrix, inBox, Color::sGrey);
|
||||
DrawSphereSP(mDebugRenderer, inMatrix * inSphere.GetCenter(), inSphere.GetRadius(), Color::sGrey);
|
||||
|
||||
// Transform the box and sphere according to inMatrix
|
||||
TransformedConvexObject transformed_box(inMatrix, inBox);
|
||||
TransformedConvexObject transformed_sphere(inMatrix, inSphere);
|
||||
|
||||
// Run the EPA algorithm
|
||||
EPAPenetrationDepth epa;
|
||||
Vec3 v1 = Vec3::sAxisX(), pa1, pb1;
|
||||
bool intersect1 = epa.GetPenetrationDepth(transformed_box, transformed_box, 0.0f, transformed_sphere, transformed_sphere, 0.0f, 1.0e-2f, FLT_EPSILON, v1, pa1, pb1);
|
||||
|
||||
// Draw iterative solution
|
||||
if (intersect1)
|
||||
{
|
||||
DrawMarkerSP(mDebugRenderer, pa1, Color::sRed, 1.0f);
|
||||
DrawMarkerSP(mDebugRenderer, pb1, Color::sGreen, 1.0f);
|
||||
DrawArrowSP(mDebugRenderer, pb1 + Vec3(0, 1, 0), pb1 + Vec3(0, 1, 0) + v1, Color::sYellow, 0.1f);
|
||||
}
|
||||
|
||||
// Calculate analytical solution
|
||||
Vec3 pa2 = inBox.GetClosestPoint(inSphere.GetCenter());
|
||||
Vec3 v2 = inSphere.GetCenter() - pa2;
|
||||
bool intersect2 = v2.LengthSq() <= Square(inSphere.GetRadius());
|
||||
|
||||
JPH_ASSERT(intersect1 == intersect2);
|
||||
if (intersect1 && intersect2)
|
||||
{
|
||||
Vec3 pb2 = inSphere.GetCenter() - inSphere.GetRadius() * v2.NormalizedOr(Vec3::sZero());
|
||||
|
||||
// Transform analytical solution
|
||||
v2 = inMatrix.Multiply3x3(v2);
|
||||
pa2 = inMatrix * pa2;
|
||||
pb2 = inMatrix * pb2;
|
||||
|
||||
// Draw analytical solution
|
||||
DrawMarkerSP(mDebugRenderer, pa2, Color::sOrange, 1.0f);
|
||||
DrawMarkerSP(mDebugRenderer, pb2, Color::sYellow, 1.0f);
|
||||
|
||||
// Check angle between v1 and v2
|
||||
float dot = v1.Dot(v2);
|
||||
float len = v1.Length() * v2.Length();
|
||||
float angle = RadiansToDegrees(ACos(dot / len));
|
||||
JPH_ASSERT(angle < 0.1f);
|
||||
Trace("Angle = %.9g", (double)angle);
|
||||
|
||||
// Check delta between contact on A
|
||||
Vec3 dpa = pa2 - pa1;
|
||||
JPH_ASSERT(dpa.IsNearZero(Square(8.0e-4f)));
|
||||
Trace("Delta A = %.9g", (double)dpa.Length());
|
||||
|
||||
// Check delta between contact on B
|
||||
Vec3 dpb = pb2 - pb1;
|
||||
JPH_ASSERT(dpb.IsNearZero(Square(8.0e-4f)));
|
||||
Trace("Delta B = %.9g", (double)dpb.Length());
|
||||
}
|
||||
|
||||
return intersect1;
|
||||
}
|
||||
20
lib/All/JoltPhysics/Samples/Tests/ConvexCollision/EPATest.h
Normal file
20
lib/All/JoltPhysics/Samples/Tests/ConvexCollision/EPATest.h
Normal file
@@ -0,0 +1,20 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
|
||||
// Does a single box vs sphere test without convex radius for visually debugging the EPA algorithm
|
||||
class EPATest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, EPATest)
|
||||
|
||||
// Update the test, called before the physics update
|
||||
virtual void PrePhysicsUpdate(const PreUpdateParams &inParams) override;
|
||||
|
||||
private:
|
||||
bool CollideBoxSphere(Mat44Arg inMatrix, const AABox &inBox, const Sphere &inSphere) const;
|
||||
};
|
||||
@@ -0,0 +1,221 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/ConvexCollision/InteractivePairsTest.h>
|
||||
#include <Input/Keyboard.h>
|
||||
#include <Jolt/Geometry/Sphere.h>
|
||||
#include <Jolt/Geometry/AABox.h>
|
||||
#include <Jolt/Geometry/ConvexSupport.h>
|
||||
#include <Jolt/Geometry/EPAPenetrationDepth.h>
|
||||
#include <Utils/DebugRendererSP.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(InteractivePairsTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(InteractivePairsTest, Test)
|
||||
}
|
||||
|
||||
void InteractivePairsTest::ProcessInput(const ProcessInputParams &inParams)
|
||||
{
|
||||
// Keyboard controls
|
||||
if (inParams.mKeyboard->IsKeyPressed(EKey::Z))
|
||||
{
|
||||
mKeyboardMode = true;
|
||||
mDistance -= inParams.mDeltaTime;
|
||||
}
|
||||
else if (inParams.mKeyboard->IsKeyPressed(EKey::C))
|
||||
{
|
||||
mKeyboardMode = true;
|
||||
mDistance += inParams.mDeltaTime;
|
||||
}
|
||||
else if (inParams.mKeyboard->IsKeyPressed(EKey::X))
|
||||
{
|
||||
mKeyboardMode = false;
|
||||
}
|
||||
|
||||
// Auto update
|
||||
if (!mKeyboardMode)
|
||||
mDistance -= inParams.mDeltaTime;
|
||||
|
||||
// Clamp distance
|
||||
if (mDistance < -4.0f)
|
||||
mDistance = 4.0f;
|
||||
if (mDistance > 4.0f)
|
||||
mDistance = -4.0f;
|
||||
}
|
||||
|
||||
void InteractivePairsTest::PrePhysicsUpdate(const PreUpdateParams &inParams)
|
||||
{
|
||||
float z = 0.0f;
|
||||
|
||||
const float r1 = 0.25f * JPH_PI;
|
||||
const float r2 = ATan(1.0f / sqrt(2.0f)); // When rotating cube by 45 degrees the one axis becomes sqrt(2) long while the other stays at length 1
|
||||
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
const float cvx_radius = i == 0? 0.0f : 0.1f; // First round without convex radius, second with
|
||||
const float edge_len = 1.0f - cvx_radius;
|
||||
AABox b(Vec3(-edge_len, -edge_len, -edge_len), Vec3(edge_len, edge_len, edge_len));
|
||||
|
||||
// Face vs face
|
||||
TestBoxVsBox(Vec3(0, 0, z), Vec3(0, 0, 0), cvx_radius, b, Vec3(mDistance, 0, z), Vec3(0, 0, 0), cvx_radius, b);
|
||||
z += 4;
|
||||
TestBoxVsBox(Vec3(0, 0, z), Vec3(0, 0, 0), cvx_radius, b, Vec3(mDistance, 0, z), Vec3(r1, 0, 0), cvx_radius, b);
|
||||
z += 4;
|
||||
|
||||
// Face vs edge
|
||||
TestBoxVsBox(Vec3(0, 0, z), Vec3(0, 0, 0), cvx_radius, b, Vec3(mDistance, 0, z), Vec3(0, r1, 0), cvx_radius, b);
|
||||
z += 4;
|
||||
TestBoxVsBox(Vec3(0, 0, z), Vec3(0, 0, 0), cvx_radius, b, Vec3(mDistance, 0, z), Vec3(0, 0, r1), cvx_radius, b);
|
||||
z += 4;
|
||||
|
||||
// Face vs vertex
|
||||
TestBoxVsBox(Vec3(0, 0, z), Vec3(0, 0, 0), cvx_radius, b, Vec3(mDistance, 0, z), Vec3(0, r2, r1), cvx_radius, b);
|
||||
z += 4;
|
||||
|
||||
// Edge vs edge
|
||||
TestBoxVsBox(Vec3(0, 0, z), Vec3(0, r1, 0), cvx_radius, b, Vec3(mDistance, 0, z), Vec3(0, r1, 0), cvx_radius, b);
|
||||
z += 4;
|
||||
TestBoxVsBox(Vec3(0, 0, z), Vec3(0, 0, r1), cvx_radius, b, Vec3(mDistance, 0, z), Vec3(0, r1, 0), cvx_radius, b);
|
||||
z += 4;
|
||||
|
||||
// Edge vs vertex
|
||||
TestBoxVsBox(Vec3(0, 0, z), Vec3(0, r2, r1), cvx_radius, b, Vec3(mDistance, 0, z), Vec3(0, r2, r1), cvx_radius, b);
|
||||
z += 4;
|
||||
|
||||
// Sphere vs face
|
||||
TestSphereVsBox(Vec3(0, 0, z), 1.0f, Vec3(mDistance, 0, z), Vec3(0, 0, 0), cvx_radius, b);
|
||||
z += 4;
|
||||
TestSphereVsBox(Vec3(0, 0, z), 1.0f, Vec3(mDistance, 0, z), Vec3(r1, 0, 0), cvx_radius, b);
|
||||
z += 4;
|
||||
|
||||
// Sphere vs edge
|
||||
TestSphereVsBox(Vec3(0, 0, z), 1.0f, Vec3(mDistance, 0, z), Vec3(0, r1, 0), cvx_radius, b);
|
||||
z += 4;
|
||||
TestSphereVsBox(Vec3(0, 0, z), 1.0f, Vec3(mDistance, 0, z), Vec3(0, 0, r1), cvx_radius, b);
|
||||
z += 4;
|
||||
|
||||
// Sphere vs vertex
|
||||
TestSphereVsBox(Vec3(0, 0, z), 1.0f, Vec3(mDistance, 0, z), Vec3(0, r2, r1), cvx_radius, b);
|
||||
z += 4;
|
||||
|
||||
// Sphere vs sphere
|
||||
TestSphereVsSphere(Vec3(0, 0, z), 1.0f, Vec3(mDistance, 0, z), 1.0f, i == 1);
|
||||
z += 4;
|
||||
}
|
||||
}
|
||||
|
||||
void InteractivePairsTest::TestBoxVsBox(Vec3Arg inTranslationA, Vec3Arg inRotationA, float inConvexRadiusA, const AABox &inA, Vec3Arg inTranslationB, Vec3Arg inRotationB, float inConvexRadiusB, const AABox &inB)
|
||||
{
|
||||
Mat44 mat_a = Mat44::sTranslation(inTranslationA) * Mat44::sRotationX(inRotationA.GetX()) * Mat44::sRotationY(inRotationA.GetY()) * Mat44::sRotationZ(inRotationA.GetZ());
|
||||
TransformedConvexObject a(mat_a, inA);
|
||||
|
||||
Mat44 mat_b = Mat44::sTranslation(inTranslationB) * Mat44::sRotationX(inRotationB.GetX()) * Mat44::sRotationY(inRotationB.GetY()) * Mat44::sRotationZ(inRotationB.GetZ());
|
||||
TransformedConvexObject b(mat_b, inB);
|
||||
|
||||
EPAPenetrationDepth pen_depth;
|
||||
Vec3 v = Vec3::sAxisX(), pa, pb;
|
||||
|
||||
DrawBoxSP(mDebugRenderer, mat_a, inA, Color::sWhite);
|
||||
|
||||
AABox widened_a = inA;
|
||||
widened_a.ExpandBy(Vec3::sReplicate(inConvexRadiusA));
|
||||
|
||||
AABox widened_b = inB;
|
||||
widened_b.ExpandBy(Vec3::sReplicate(inConvexRadiusB));
|
||||
|
||||
DrawBoxSP(mDebugRenderer, mat_a, inA, Color::sWhite);
|
||||
if (inConvexRadiusA > 0.0f)
|
||||
DrawWireBoxSP(mDebugRenderer, mat_a, widened_a, Color::sWhite);
|
||||
|
||||
AddConvexRadius a_inc(a, inConvexRadiusA);
|
||||
AddConvexRadius b_inc(b, inConvexRadiusB);
|
||||
|
||||
if (pen_depth.GetPenetrationDepth(a, a_inc, inConvexRadiusA, b, b_inc, inConvexRadiusB, 1.0e-4f, FLT_EPSILON, v, pa, pb))
|
||||
{
|
||||
DrawBoxSP(mDebugRenderer, mat_b, inB, Color::sRed);
|
||||
if (inConvexRadiusB > 0.0f)
|
||||
DrawWireBoxSP(mDebugRenderer, mat_b, widened_b, Color::sRed);
|
||||
DrawMarkerSP(mDebugRenderer, pa, Color::sYellow, 2.0f);
|
||||
DrawMarkerSP(mDebugRenderer, pb, Color::sCyan, 2.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawBoxSP(mDebugRenderer, mat_b, inB, Color::sGreen);
|
||||
if (inConvexRadiusB > 0.0f)
|
||||
DrawWireBoxSP(mDebugRenderer, mat_b, widened_b, Color::sGreen);
|
||||
}
|
||||
DrawArrowSP(mDebugRenderer, inTranslationB + Vec3(0, 2, 0), inTranslationB + v + Vec3(0, 2, 0), Color::sOrange, 0.05f);
|
||||
}
|
||||
|
||||
void InteractivePairsTest::TestSphereVsBox(Vec3Arg inTranslationA, float inRadiusA, Vec3Arg inTranslationB, Vec3Arg inRotationB, float inConvexRadiusB, const AABox &inB)
|
||||
{
|
||||
Sphere s(inTranslationA, inRadiusA);
|
||||
Mat44 mat_b = Mat44::sTranslation(inTranslationB) * Mat44::sRotationX(inRotationB.GetX()) * Mat44::sRotationY(inRotationB.GetY()) * Mat44::sRotationZ(inRotationB.GetZ());
|
||||
TransformedConvexObject b(mat_b, inB);
|
||||
|
||||
AABox widened_b = inB;
|
||||
widened_b.ExpandBy(Vec3::sReplicate(inConvexRadiusB));
|
||||
|
||||
EPAPenetrationDepth pen_depth;
|
||||
Vec3 v = Vec3::sAxisX(), pa, pb;
|
||||
|
||||
DrawSphereSP(mDebugRenderer, inTranslationA, inRadiusA, Color::sWhite);
|
||||
|
||||
AddConvexRadius b_inc(b, inConvexRadiusB);
|
||||
|
||||
if (pen_depth.GetPenetrationDepth(s, s, 0.0f, b, b_inc, inConvexRadiusB, 1.0e-4f, FLT_EPSILON, v, pa, pb))
|
||||
{
|
||||
DrawBoxSP(mDebugRenderer, mat_b, inB, Color::sRed);
|
||||
if (inConvexRadiusB > 0.0f)
|
||||
DrawWireBoxSP(mDebugRenderer, mat_b, widened_b, Color::sRed);
|
||||
DrawMarkerSP(mDebugRenderer, pa, Color::sYellow, 2.0f);
|
||||
DrawMarkerSP(mDebugRenderer, pb, Color::sCyan, 2.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawBoxSP(mDebugRenderer, mat_b, inB, Color::sGreen);
|
||||
if (inConvexRadiusB > 0.0f)
|
||||
DrawWireBoxSP(mDebugRenderer, mat_b, widened_b, Color::sGreen);
|
||||
}
|
||||
DrawArrowSP(mDebugRenderer, inTranslationB + Vec3(0, 2, 0), inTranslationB + v + Vec3(0, 2, 0), Color::sOrange, 0.05f);
|
||||
}
|
||||
|
||||
void InteractivePairsTest::TestSphereVsSphere(Vec3Arg inTranslationA, float inRadiusA, Vec3Arg inTranslationB, float inRadiusB, bool inTreatSphereAsPointWithConvexRadius)
|
||||
{
|
||||
Sphere s1(inTranslationA, inRadiusA);
|
||||
Sphere s2(inTranslationB, inRadiusB);
|
||||
|
||||
if (inTreatSphereAsPointWithConvexRadius)
|
||||
DrawWireSphereSP(mDebugRenderer, s1.GetCenter(), s1.GetRadius(), Color::sWhite);
|
||||
else
|
||||
DrawSphereSP(mDebugRenderer, s1.GetCenter(), s1.GetRadius(), Color::sWhite);
|
||||
|
||||
bool intersects;
|
||||
EPAPenetrationDepth pen_depth;
|
||||
Vec3 v = Vec3::sAxisX(), pa, pb;
|
||||
if (inTreatSphereAsPointWithConvexRadius)
|
||||
intersects = pen_depth.GetPenetrationDepth(PointConvexSupport { inTranslationA }, s1, inRadiusA, PointConvexSupport { inTranslationB }, s2, inRadiusB, 1.0e-4f, FLT_EPSILON, v, pa, pb);
|
||||
else
|
||||
intersects = pen_depth.GetPenetrationDepth(s1, s1, 0.0f, s2, s2, 0.0f, 1.0e-4f, FLT_EPSILON, v, pa, pb);
|
||||
|
||||
if (intersects)
|
||||
{
|
||||
if (inTreatSphereAsPointWithConvexRadius)
|
||||
DrawWireSphereSP(mDebugRenderer, s2.GetCenter(), s2.GetRadius(), Color::sRed);
|
||||
else
|
||||
DrawSphereSP(mDebugRenderer, s2.GetCenter(), s2.GetRadius(), Color::sRed);
|
||||
DrawMarkerSP(mDebugRenderer, pa, Color::sYellow, 2.0f);
|
||||
DrawMarkerSP(mDebugRenderer, pb, Color::sCyan, 2.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (inTreatSphereAsPointWithConvexRadius)
|
||||
DrawWireSphereSP(mDebugRenderer, s2.GetCenter(), s2.GetRadius(), Color::sGreen);
|
||||
else
|
||||
DrawSphereSP(mDebugRenderer, s2.GetCenter(), s2.GetRadius(), Color::sGreen);
|
||||
}
|
||||
DrawArrowSP(mDebugRenderer, inTranslationB + Vec3(0, 2, 0), inTranslationB + v + Vec3(0, 2, 0), Color::sOrange, 0.05f);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
|
||||
// Renders pairs of objects and their collisions. Use Z, X, C keys to control distance.
|
||||
class InteractivePairsTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, InteractivePairsTest)
|
||||
|
||||
// Process input
|
||||
virtual void ProcessInput(const ProcessInputParams &inParams) override;
|
||||
|
||||
// Update the test, called before the physics update
|
||||
virtual void PrePhysicsUpdate(const PreUpdateParams &inParams) override;
|
||||
|
||||
private:
|
||||
void TestBoxVsBox(Vec3Arg inTranslationA, Vec3Arg inRotationA, float inConvexRadiusA, const AABox &inA, Vec3Arg inTranslationB, Vec3Arg inRotationB, float inConvexRadiusB, const AABox &inB);
|
||||
void TestSphereVsBox(Vec3Arg inTranslationA, float inRadiusA, Vec3Arg inTranslationB, Vec3Arg inRotationB, float inConvexRadiusB, const AABox &inB);
|
||||
void TestSphereVsSphere(Vec3Arg inTranslationA, float inRadiusA, Vec3Arg inTranslationB, float inRadiusB, bool inTreatSphereAsPointWithConvexRadius);
|
||||
|
||||
bool mKeyboardMode = false;
|
||||
float mDistance = 3.0f;
|
||||
};
|
||||
@@ -0,0 +1,208 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Tests/ConvexCollision/RandomRayTest.h>
|
||||
#include <Jolt/Geometry/Sphere.h>
|
||||
#include <Jolt/Geometry/AABox.h>
|
||||
#include <Jolt/Geometry/GJKClosestPoint.h>
|
||||
#include <Jolt/Geometry/RayTriangle.h>
|
||||
#include <Jolt/Geometry/RaySphere.h>
|
||||
#include <Jolt/Geometry/RayAABox.h>
|
||||
#include <Jolt/Geometry/RayCapsule.h>
|
||||
#include <Jolt/Geometry/RayCylinder.h>
|
||||
#include <Jolt/Geometry/ConvexSupport.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/CylinderShape.h>
|
||||
#include <Renderer/DebugRendererImp.h>
|
||||
|
||||
JPH_IMPLEMENT_RTTI_VIRTUAL(RandomRayTest)
|
||||
{
|
||||
JPH_ADD_BASE_CLASS(RandomRayTest, Test)
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Tests the CastRay function
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename A, typename Context>
|
||||
void RandomRayTest::TestRay(const char *inTestName, RVec3Arg inRenderOffset, const A &inA, const Context &inContext, float (*inCompareFunc)(const Context &inContext, Vec3Arg inRayOrigin, Vec3Arg inRayDirection))
|
||||
{
|
||||
default_random_engine random(12345);
|
||||
uniform_real_distribution<float> random_scale(-2.0f, 2.0f);
|
||||
|
||||
#ifdef JPH_DEBUG
|
||||
const int count = 1000;
|
||||
#else
|
||||
const int count = 10000;
|
||||
#endif
|
||||
|
||||
int mismatches = 0;
|
||||
int nonzero_hits = 0;
|
||||
int zero_hits = 0;
|
||||
float total_error = 0;
|
||||
int total_error_count = 0;
|
||||
float min_error = FLT_MAX;
|
||||
float max_error = 0;
|
||||
|
||||
GJKClosestPoint gjk;
|
||||
|
||||
Trace("Starting: %s", inTestName);
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
Vec3 from(random_scale(random), random_scale(random), random_scale(random));
|
||||
Vec3 to(random_scale(random), random_scale(random), random_scale(random));
|
||||
Vec3 direction = to - from;
|
||||
|
||||
// Use GJK to cast a ray
|
||||
float fraction1 = 1.0f + FLT_EPSILON;
|
||||
if (!gjk.CastRay(from, direction, 1.0e-4f, inA, fraction1))
|
||||
fraction1 = FLT_MAX;
|
||||
|
||||
// Use the comparison function
|
||||
float fraction2 = inCompareFunc(inContext, from, direction);
|
||||
|
||||
// The comparison functions work with infinite rays, so a fraction > 1 means a miss
|
||||
if (fraction2 > 1.0f)
|
||||
fraction2 = FLT_MAX;
|
||||
|
||||
float error = abs(fraction1 - fraction2);
|
||||
if (error > 0.005f)
|
||||
{
|
||||
Trace("Mismatch iteration: %d (%f vs %f, diff: %f)", i, (double)fraction1, (double)fraction2, (double)abs(fraction2 - fraction1));
|
||||
++mismatches;
|
||||
|
||||
Color c;
|
||||
if (fraction2 == FLT_MAX)
|
||||
{
|
||||
c = Color::sRed;
|
||||
mDebugRenderer->DrawMarker(inRenderOffset + from + fraction1 * direction, Color::sRed, 0.1f);
|
||||
}
|
||||
else if (fraction1 == FLT_MAX)
|
||||
{
|
||||
c = Color::sBlue;
|
||||
mDebugRenderer->DrawMarker(inRenderOffset + from + fraction2 * direction, Color::sBlue, 0.1f);
|
||||
}
|
||||
else
|
||||
{
|
||||
total_error += abs(fraction2 - fraction1);
|
||||
total_error_count++;
|
||||
c = Color::sGreen;
|
||||
mDebugRenderer->DrawMarker(inRenderOffset + from + fraction1 * direction, Color::sCyan, 0.1f);
|
||||
mDebugRenderer->DrawMarker(inRenderOffset + from + fraction2 * direction, Color::sGreen, 0.1f);
|
||||
}
|
||||
mDebugRenderer->DrawArrow(inRenderOffset + from, inRenderOffset + to, c, 0.1f);
|
||||
}
|
||||
else if (fraction1 != FLT_MAX)
|
||||
{
|
||||
mDebugRenderer->DrawMarker(inRenderOffset + from + fraction1 * direction, Color::sYellow, 0.02f);
|
||||
}
|
||||
|
||||
if (fraction1 != FLT_MAX && fraction2 != FLT_MAX)
|
||||
{
|
||||
total_error += error;
|
||||
total_error_count++;
|
||||
min_error = min(min_error, error);
|
||||
max_error = max(max_error, error);
|
||||
}
|
||||
|
||||
if (fraction2 == 0.0f)
|
||||
++zero_hits;
|
||||
else if (fraction2 > 0 && fraction2 <= 1.0f)
|
||||
++nonzero_hits;
|
||||
}
|
||||
|
||||
Trace("Report for: %s", inTestName);
|
||||
Trace("Mismatches: %d (%.1f%%)", mismatches, 100.0 * mismatches / count);
|
||||
Trace("Hits (fraction = 0): %d (%.1f%%)", zero_hits, 100.0 * zero_hits / count);
|
||||
Trace("Hits (fraction > 0 and fraction <= 1): %d (%.1f%%)", nonzero_hits, 100.0 * nonzero_hits / count);
|
||||
Trace("Fraction error: Avg %f, Min %f, Max %f", total_error_count > 0? double(total_error / total_error_count) : 0.0, (double)min_error, (double)max_error);
|
||||
}
|
||||
|
||||
void RandomRayTest::PrePhysicsUpdate(const PreUpdateParams &inParams)
|
||||
{
|
||||
{
|
||||
RVec3 render_offset(0, 0, 0);
|
||||
Sphere sphere(Vec3(0.1f, 0.2f, 0.3f), 1.1f);
|
||||
mDebugRenderer->DrawSphere(render_offset + sphere.GetCenter(), sphere.GetRadius(), Color::sYellow);
|
||||
TestRay<Sphere, Sphere>("Sphere", render_offset, sphere, sphere, [](const Sphere &inSphere, Vec3Arg inRayOrigin, Vec3Arg inRayDirection) {
|
||||
return RaySphere(inRayOrigin, inRayDirection, inSphere.GetCenter(), inSphere.GetRadius());
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
RVec3 render_offset(5, 0, 0);
|
||||
SphereShape sphere_shape(1.1f);
|
||||
#ifdef JPH_DEBUG_RENDERER
|
||||
sphere_shape.Draw(mDebugRenderer, RMat44::sTranslation(render_offset), Vec3::sOne(), Color::sYellow, false, false);
|
||||
#endif // JPH_DEBUG_RENDERER
|
||||
ConvexShape::SupportBuffer buffer;
|
||||
const ConvexShape::Support *support = sphere_shape.GetSupportFunction(ConvexShape::ESupportMode::IncludeConvexRadius, buffer, Vec3::sOne());
|
||||
TestRay<ConvexShape::Support, SphereShape>("Sphere Shape", render_offset, *support, sphere_shape, [](const SphereShape &inSphere, Vec3Arg inRayOrigin, Vec3Arg inRayDirection) {
|
||||
return RaySphere(inRayOrigin, inRayDirection, Vec3::sZero(), inSphere.GetRadius());
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
RVec3 render_offset(10, 0, 0);
|
||||
AABox box(Vec3(-0.9f, -1.0f, -1.1f), Vec3(0.8f, 0.9f, 1.0f));
|
||||
mDebugRenderer->DrawBox(box.Transformed(Mat44::sTranslation(Vec3(render_offset))), Color::sYellow);
|
||||
TestRay<AABox, AABox>("Box", render_offset, box, box, [](const AABox &inBox, Vec3Arg inRayOrigin, Vec3Arg inRayDirection) {
|
||||
float fraction = RayAABox(inRayOrigin, RayInvDirection(inRayDirection), inBox.mMin, inBox.mMax);
|
||||
return max(fraction, 0.0f);
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
RVec3 render_offset(15, 0, 0);
|
||||
BoxShape box_shape(Vec3(0.9f, 1.0f, 1.1f), 0.0f);
|
||||
#ifdef JPH_DEBUG_RENDERER
|
||||
box_shape.Draw(mDebugRenderer, RMat44::sTranslation(render_offset), Vec3::sOne(), Color::sYellow, false, false);
|
||||
#endif // JPH_DEBUG_RENDERER
|
||||
ConvexShape::SupportBuffer buffer;
|
||||
const ConvexShape::Support *support = box_shape.GetSupportFunction(ConvexShape::ESupportMode::IncludeConvexRadius, buffer, Vec3::sOne());
|
||||
TestRay<ConvexShape::Support, BoxShape>("Box Shape", render_offset, *support, box_shape, [](const BoxShape &inBox, Vec3Arg inRayOrigin, Vec3Arg inRayDirection) {
|
||||
float fraction = RayAABox(inRayOrigin, RayInvDirection(inRayDirection), -inBox.GetHalfExtent(), inBox.GetHalfExtent());
|
||||
return max(fraction, 0.0f);
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
RVec3 render_offset(20, 0, 0);
|
||||
CapsuleShape capsule_shape(1.1f, 0.6f);
|
||||
#ifdef JPH_DEBUG_RENDERER
|
||||
capsule_shape.Draw(mDebugRenderer, RMat44::sTranslation(render_offset), Vec3::sOne(), Color::sYellow, false, false);
|
||||
#endif // JPH_DEBUG_RENDERER
|
||||
ConvexShape::SupportBuffer buffer;
|
||||
const ConvexShape::Support *support = capsule_shape.GetSupportFunction(ConvexShape::ESupportMode::IncludeConvexRadius, buffer, Vec3::sOne());
|
||||
TestRay<ConvexShape::Support, CapsuleShape>("Capsule Shape", render_offset, *support, capsule_shape, [](const CapsuleShape &inCapsule, Vec3Arg inRayOrigin, Vec3Arg inRayDirection) {
|
||||
return RayCapsule(inRayOrigin, inRayDirection, inCapsule.GetHalfHeightOfCylinder(), inCapsule.GetRadius());
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
RVec3 render_offset(25, 0, 0);
|
||||
CylinderShape cylinder_shape(1.5f, 0.6f, 0.0f);
|
||||
#ifdef JPH_DEBUG_RENDERER
|
||||
cylinder_shape.Draw(mDebugRenderer, RMat44::sTranslation(render_offset), Vec3::sOne(), Color::sYellow, false, false);
|
||||
#endif // JPH_DEBUG_RENDERER
|
||||
ConvexShape::SupportBuffer buffer;
|
||||
const ConvexShape::Support *support = cylinder_shape.GetSupportFunction(ConvexShape::ESupportMode::IncludeConvexRadius, buffer, Vec3::sOne());
|
||||
TestRay<ConvexShape::Support, CylinderShape>("Cylinder Shape", render_offset, *support, cylinder_shape, [](const CylinderShape &inCylinder, Vec3Arg inRayOrigin, Vec3Arg inRayDirection) {
|
||||
return RayCylinder(inRayOrigin, inRayDirection, inCylinder.GetHalfHeight(), inCylinder.GetRadius());
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
RVec3 render_offset(30, 0, 0);
|
||||
TriangleConvexSupport triangle(Vec3(0.1f, 0.9f, 0.3f), Vec3(-0.9f, -0.5f, 0.2f), Vec3(0.7f, -0.3f, -0.1f));
|
||||
mDebugRenderer->DrawTriangle(render_offset + triangle.mV1, render_offset + triangle.mV2, render_offset + triangle.mV3, Color::sYellow);
|
||||
TestRay<TriangleConvexSupport, TriangleConvexSupport>("Triangle", render_offset, triangle, triangle, [](const TriangleConvexSupport &inTriangle, Vec3Arg inRayOrigin, Vec3Arg inRayDirection) {
|
||||
return RayTriangle(inRayOrigin, inRayDirection, inTriangle.mV1, inTriangle.mV2, inTriangle.mV3);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Tests/Test.h>
|
||||
|
||||
// Tests a lot of random rays against convex shapes
|
||||
class RandomRayTest : public Test
|
||||
{
|
||||
public:
|
||||
JPH_DECLARE_RTTI_VIRTUAL(JPH_NO_EXPORT, RandomRayTest)
|
||||
|
||||
// Update the test, called before the physics update
|
||||
virtual void PrePhysicsUpdate(const PreUpdateParams &inParams) override;
|
||||
|
||||
private:
|
||||
template <typename A, typename Context>
|
||||
void TestRay(const char *inTestName, RVec3Arg inRenderOffset, const A &inA, const Context &inContext, float (*inCompareFunc)(const Context &inContext, Vec3Arg inRayOrigin, Vec3Arg inRayDirection));
|
||||
};
|
||||
Reference in New Issue
Block a user