You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
469 lines
23 KiB
C++
469 lines
23 KiB
C++
/*
|
|
* Copyright (c) Contributors to the Open 3D Engine Project.
|
|
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
*
|
|
*/
|
|
|
|
#include <AzFramework/Physics/Common/PhysicsSceneQueries.h>
|
|
#include <AzFramework/Physics/PhysicsSystem.h>
|
|
#include <AzFramework/Physics/RigidBodyBus.h>
|
|
#include <AzFramework/Physics/Shape.h>
|
|
#include <AzFramework/Physics/Collision/CollisionLayers.h>
|
|
#include <AzFramework/Physics/Common/PhysicsTypes.h>
|
|
#include <PhysX/ColliderComponentBus.h>
|
|
|
|
#include <Tests/PhysXGenericTestFixture.h>
|
|
#include <Tests/PhysXTestCommon.h>
|
|
|
|
namespace PhysX
|
|
{
|
|
TEST_F(GenericPhysicsInterfaceTest, Gravity_DynamicBody_BodyFalls)
|
|
{
|
|
AzPhysics::SceneHandle sceneHandle = CreateTestScene();
|
|
auto* rigidBody = TestUtils::AddUnitBoxToScene(sceneHandle, AZ::Vector3(0.0f, 0.0f, 100.0f));
|
|
TestUtils::UpdateScene(sceneHandle, 1.0f / 60.f, 60);
|
|
|
|
// expect velocity to be -gt and distance fallen to be 1/2gt^2, but allow quite a lot of tolerance
|
|
// due to potential differences in back end integration schemes etc.
|
|
EXPECT_NEAR(rigidBody->GetLinearVelocity().GetZ(), -10.0f, 0.5f);
|
|
EXPECT_NEAR(rigidBody->GetTransform().GetTranslation().GetZ(), 95.0f, 0.5f);
|
|
EXPECT_NEAR(rigidBody->GetCenterOfMassWorld().GetZ(), 95.0f, 0.5f);
|
|
EXPECT_NEAR(rigidBody->GetPosition().GetZ(), 95.0f, 0.5f);
|
|
}
|
|
|
|
TEST_F(GenericPhysicsInterfaceTest, IncreaseMass_StaggeredTowerOfBoxes_TowerOverbalances)
|
|
{
|
|
AzPhysics::SceneHandle sceneHandle = CreateTestScene();
|
|
|
|
// make a tower of boxes which is staggered but should still balance if all the blocks are the same mass
|
|
TestUtils::AddStaticUnitBoxToScene(sceneHandle, AZ::Vector3(0.0f, 0.0f, 0.5f));
|
|
AzPhysics::RigidBody* boxB = TestUtils::AddUnitBoxToScene(sceneHandle, AZ::Vector3(0.3f, 0.0f, 1.5f));
|
|
AzPhysics::RigidBody* boxC = TestUtils::AddUnitBoxToScene(sceneHandle, AZ::Vector3(0.6f, 0.0f, 2.5f));
|
|
|
|
// check that the tower balances
|
|
TestUtils::UpdateScene(sceneHandle, 1.0f / 60.0f, 60);
|
|
EXPECT_NEAR(2.5f, boxC->GetPosition().GetZ(), 0.01f);
|
|
|
|
// increasing the mass of the top block in the tower should overbalance it
|
|
boxC->SetMass(5.0f);
|
|
EXPECT_NEAR(1.0f, boxB->GetMass(), 0.01f);
|
|
EXPECT_NEAR(1.0f, boxB->GetInverseMass(), 0.01f);
|
|
EXPECT_NEAR(5.0f, boxC->GetMass(), 0.01f);
|
|
EXPECT_NEAR(0.2f, boxC->GetInverseMass(), 0.01f);
|
|
boxB->ForceAwake();
|
|
boxC->ForceAwake();
|
|
TestUtils::UpdateScene(sceneHandle, 1.0f / 60.0f, 300);
|
|
EXPECT_GT(0.0f, static_cast<float>(boxC->GetPosition().GetZ()));
|
|
}
|
|
|
|
TEST_F(GenericPhysicsInterfaceTest, GetCenterOfMass_FallingBody_CenterOfMassCorrectDuringFall)
|
|
{
|
|
AzPhysics::SceneHandle sceneHandle = CreateTestScene();
|
|
|
|
TestUtils::AddStaticUnitBoxToScene(sceneHandle, AZ::Vector3(0.0f, 0.0f, 0.0f));
|
|
AzPhysics::RigidBody* boxDynamic = TestUtils::AddUnitBoxToScene(sceneHandle, AZ::Vector3(0.0f, 0.0f, 2.0f));
|
|
auto tolerance = 1e-3f;
|
|
|
|
EXPECT_TRUE(boxDynamic->GetCenterOfMassWorld().IsClose(AZ::Vector3(0.0f, 0.0f, 2.0f), tolerance));
|
|
EXPECT_TRUE(boxDynamic->GetCenterOfMassLocal().IsClose(AZ::Vector3(0.0f, 0.0f, 0.0f), tolerance));
|
|
TestUtils::UpdateScene(sceneHandle, 1.0f / 60.0f, 300);
|
|
EXPECT_NEAR(static_cast<float>(boxDynamic->GetCenterOfMassWorld().GetZ()), 1.0f, 1e-3f);
|
|
EXPECT_TRUE(boxDynamic->GetCenterOfMassLocal().IsClose(AZ::Vector3(0.0f, 0.0f, 0.0f), tolerance));
|
|
}
|
|
|
|
TEST_F(GenericPhysicsInterfaceTest, SetLinearVelocity_DynamicBox_AffectsTrajectory)
|
|
{
|
|
AzPhysics::SceneHandle sceneHandle = CreateTestScene();
|
|
AzPhysics::RigidBody* boxA = TestUtils::AddUnitBoxToScene(sceneHandle, AZ::Vector3(0.0f, -5.0f, 10.0f));
|
|
AzPhysics::RigidBody* boxB = TestUtils::AddUnitBoxToScene(sceneHandle, AZ::Vector3(0.0f, 5.0f, 10.0f));
|
|
|
|
boxA->SetLinearVelocity(AZ::Vector3(10.0f, 0.0f, 0.0f));
|
|
for (int i = 1; i < 10; i++)
|
|
{
|
|
float xPreviousA = boxA->GetPosition().GetX();
|
|
float xPreviousB = boxB->GetPosition().GetX();
|
|
TestUtils::UpdateScene(sceneHandle, 1.0f / 60.0f, 10);
|
|
EXPECT_GT(static_cast<float>(boxA->GetPosition().GetX()), xPreviousA);
|
|
EXPECT_NEAR(boxB->GetPosition().GetX(), xPreviousB, 1e-3f);
|
|
}
|
|
}
|
|
|
|
TEST_F(GenericPhysicsInterfaceTest, ApplyLinearImpulse_DynamicBox_AffectsTrajectory)
|
|
{
|
|
AzPhysics::SceneHandle sceneHandle = CreateTestScene();
|
|
AzPhysics::RigidBody* boxA = TestUtils::AddUnitBoxToScene(sceneHandle, AZ::Vector3(0.0f, 0.0f, 100.0f));
|
|
AzPhysics::RigidBody* boxB = TestUtils::AddUnitBoxToScene(sceneHandle, AZ::Vector3(0.0f, 10.0f, 100.0f));
|
|
|
|
boxA->ApplyLinearImpulse(AZ::Vector3(10.0f, 0.0f, 0.0f));
|
|
for (int i = 1; i < 10; i++)
|
|
{
|
|
float xPreviousA = boxA->GetPosition().GetX();
|
|
float xPreviousB = boxB->GetPosition().GetX();
|
|
TestUtils::UpdateScene(sceneHandle, 1.0f / 60.0f, 10);
|
|
EXPECT_GT(static_cast<float>(boxA->GetPosition().GetX()), xPreviousA);
|
|
EXPECT_NEAR(boxB->GetPosition().GetX(), xPreviousB, 1e-3f);
|
|
}
|
|
}
|
|
|
|
// allow a more generous tolerance on tests involving objects in contact, since the way physics engines normally
|
|
// handle multiple contacts between objects can lead to slight imbalances in contact forces
|
|
static constexpr float ContactTestTolerance = 0.01f;
|
|
|
|
TEST_F(GenericPhysicsInterfaceTest, GetAngularVelocity_DynamicCapsuleOnSlope_GainsAngularVelocity)
|
|
{
|
|
AzPhysics::SceneHandle sceneHandle = CreateTestScene();
|
|
|
|
AZ::Transform slopeTransform = AZ::Transform::CreateRotationY(0.1f);
|
|
TestUtils::AddStaticFloorToScene(sceneHandle, slopeTransform);
|
|
AzPhysics::SimulatedBodyHandle capsuleHandle = TestUtils::AddCapsuleToScene(sceneHandle,
|
|
slopeTransform.TransformPoint(AZ::Vector3::CreateAxisZ()));
|
|
auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get();
|
|
auto* capsule = azdynamic_cast<AzPhysics::RigidBody*>(sceneInterface->GetSimulatedBodyFromHandle(sceneHandle, capsuleHandle));
|
|
|
|
// the capsule should roll down the slope, picking up angular velocity parallel to the Y axis
|
|
float angularVelocityMagnitude = capsule->GetAngularVelocity().GetLength();
|
|
TestUtils::UpdateScene(sceneHandle, 1.0f / 60.0f, 60);
|
|
angularVelocityMagnitude = capsule->GetAngularVelocity().GetLength();
|
|
for (int i = 0; i < 60; i++)
|
|
{
|
|
TestUtils::UpdateScene(sceneHandle, 1.0f / 60.0f, 1);
|
|
auto angularVelocity = capsule->GetAngularVelocity();
|
|
EXPECT_TRUE(angularVelocity.IsPerpendicular(AZ::Vector3::CreateAxisX(), ContactTestTolerance));
|
|
EXPECT_TRUE(angularVelocity.IsPerpendicular(AZ::Vector3::CreateAxisZ(), ContactTestTolerance));
|
|
EXPECT_TRUE(capsule->GetAngularVelocity().GetLength() > angularVelocityMagnitude);
|
|
angularVelocityMagnitude = angularVelocity.GetLength();
|
|
}
|
|
}
|
|
|
|
TEST_F(GenericPhysicsInterfaceTest, SetAngularVelocity_DynamicCapsule_StartsRolling)
|
|
{
|
|
AzPhysics::SceneHandle sceneHandle = CreateTestScene();
|
|
|
|
TestUtils::AddStaticFloorToScene(sceneHandle);
|
|
AzPhysics::SimulatedBodyHandle capsuleHandle = TestUtils::AddCapsuleToScene(sceneHandle, AZ::Vector3::CreateAxisZ());
|
|
auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get();
|
|
auto* capsule = azdynamic_cast<AzPhysics::RigidBody*>(sceneInterface->GetSimulatedBodyFromHandle(sceneHandle, capsuleHandle));
|
|
|
|
// capsule should remain stationary
|
|
for (int i = 0; i < 60; i++)
|
|
{
|
|
TestUtils::UpdateScene(sceneHandle, 1.0f / 60.0f, 1);
|
|
EXPECT_TRUE(capsule->GetPosition().IsClose(AZ::Vector3::CreateAxisZ(), ContactTestTolerance));
|
|
EXPECT_TRUE(capsule->GetLinearVelocity().IsClose(AZ::Vector3::CreateZero(), ContactTestTolerance));
|
|
EXPECT_TRUE(capsule->GetAngularVelocity().IsClose(AZ::Vector3::CreateZero(), ContactTestTolerance));
|
|
}
|
|
|
|
// apply an angular velocity and it should start rolling
|
|
auto angularVelocity = AZ::Vector3::CreateAxisY(10.0f);
|
|
capsule->SetAngularVelocity(angularVelocity);
|
|
EXPECT_TRUE(capsule->GetAngularVelocity().IsClose(angularVelocity));
|
|
|
|
for (int i = 0; i < 60; i++)
|
|
{
|
|
float xPrevious = capsule->GetPosition().GetX();
|
|
TestUtils::UpdateScene(sceneHandle, 1.0f / 60.0f, 1);
|
|
EXPECT_TRUE(capsule->GetPosition().GetX() > xPrevious);
|
|
}
|
|
}
|
|
|
|
TEST_F(GenericPhysicsInterfaceTest, GetLinearVelocityAtWorldPoint_FallingRotatingCapsule_EdgeVelocitiesCorrect)
|
|
{
|
|
AzPhysics::SceneHandle sceneHandle = CreateTestScene();
|
|
|
|
// create dynamic capsule and start it falling and rotating
|
|
AzPhysics::SimulatedBodyHandle capsuleHandle = TestUtils::AddCapsuleToScene(sceneHandle, AZ::Vector3::CreateAxisZ());
|
|
auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get();
|
|
auto* capsule = azdynamic_cast<AzPhysics::RigidBody*>(sceneInterface->GetSimulatedBodyFromHandle(sceneHandle, capsuleHandle));
|
|
|
|
float angularVelocityMagnitude = 1.0f;
|
|
capsule->SetAngularVelocity(AZ::Vector3::CreateAxisY(angularVelocityMagnitude));
|
|
capsule->SetAngularDamping(0.0f);
|
|
TestUtils::UpdateScene(sceneHandle, 1.0f / 60.0f, 60);
|
|
|
|
// check the velocities at some points on the rim of the capsule are as expected
|
|
for (int i = 0; i < 60; i++)
|
|
{
|
|
TestUtils::UpdateScene(sceneHandle, 1.0f / 60.0f, 1);
|
|
auto position = capsule->GetPosition();
|
|
float fallingSpeed = capsule->GetLinearVelocity().GetZ();
|
|
float radius = 0.5f;
|
|
AZ::Vector3 z = AZ::Vector3::CreateAxisZ(radius);
|
|
AZ::Vector3 x = AZ::Vector3::CreateAxisX(radius);
|
|
|
|
auto v1 = capsule->GetLinearVelocityAtWorldPoint(position - z);
|
|
auto v2 = capsule->GetLinearVelocityAtWorldPoint(position - x);
|
|
auto v3 = capsule->GetLinearVelocityAtWorldPoint(position + x);
|
|
|
|
EXPECT_TRUE(v1.IsClose(AZ::Vector3(-radius * angularVelocityMagnitude, 0.0f, fallingSpeed)));
|
|
EXPECT_TRUE(v2.IsClose(AZ::Vector3(0.0f, 0.0f, fallingSpeed + radius * angularVelocityMagnitude)));
|
|
EXPECT_TRUE(v3.IsClose(AZ::Vector3(0.0f, 0.0f, fallingSpeed - radius * angularVelocityMagnitude)));
|
|
}
|
|
}
|
|
|
|
TEST_F(GenericPhysicsInterfaceTest, GetPosition_RollingCapsule_OrientationCorrect)
|
|
{
|
|
AzPhysics::SceneHandle sceneHandle = CreateTestScene();
|
|
|
|
TestUtils::AddStaticFloorToScene(sceneHandle);
|
|
|
|
// create dynamic capsule and start it rolling
|
|
AzPhysics::SimulatedBodyHandle capsuleHandle = TestUtils::AddCapsuleToScene(sceneHandle, AZ::Vector3::CreateAxisZ());
|
|
auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get();
|
|
auto* capsule = azdynamic_cast<AzPhysics::RigidBody*>(sceneInterface->GetSimulatedBodyFromHandle(sceneHandle, capsuleHandle));
|
|
|
|
capsule->SetLinearVelocity(AZ::Vector3::CreateAxisX(5.0f));
|
|
capsule->SetAngularVelocity(AZ::Vector3::CreateAxisY(10.0f));
|
|
TestUtils::UpdateScene(sceneHandle, 1.0f / 60.0f, 60);
|
|
|
|
// check the capsule orientation evolves as expected
|
|
for (int i = 0; i < 60; i++)
|
|
{
|
|
auto orientationPrevious = capsule->GetOrientation();
|
|
float xPrevious = capsule->GetPosition().GetX();
|
|
TestUtils::UpdateScene(sceneHandle, 1.0f / 60.0f, 1);
|
|
float angle = 2.0f * (capsule->GetPosition().GetX() - xPrevious);
|
|
EXPECT_TRUE(capsule->GetOrientation().IsClose(orientationPrevious * AZ::Quaternion::CreateRotationY(angle)));
|
|
}
|
|
}
|
|
|
|
TEST_F(GenericPhysicsInterfaceTest, OffCenterImpulse_DynamicCapsule_StartsRotating)
|
|
{
|
|
auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get();
|
|
AzPhysics::SceneHandle sceneHandle = CreateTestScene();
|
|
|
|
TestUtils::AddStaticFloorToScene(sceneHandle);
|
|
AZ::Vector3 posA(0.0f, -5.0f, 1.0f);
|
|
AZ::Vector3 posB(0.0f, 0.0f, 1.0f);
|
|
AZ::Vector3 posC(0.0f, 5.0f, 1.0f);
|
|
AzPhysics::SimulatedBodyHandle capsuleAHandle = TestUtils::AddCapsuleToScene(sceneHandle, posA);
|
|
auto* capsuleA = azdynamic_cast<AzPhysics::RigidBody*>(sceneInterface->GetSimulatedBodyFromHandle(sceneHandle, capsuleAHandle));
|
|
AzPhysics::SimulatedBodyHandle capsuleBHandle = TestUtils::AddCapsuleToScene(sceneHandle, posB);
|
|
auto* capsuleB = azdynamic_cast<AzPhysics::RigidBody*>(sceneInterface->GetSimulatedBodyFromHandle(sceneHandle, capsuleBHandle));
|
|
AzPhysics::SimulatedBodyHandle capsuleCHandle = TestUtils::AddCapsuleToScene(sceneHandle, posC);
|
|
auto* capsuleC = azdynamic_cast<AzPhysics::RigidBody*>(sceneInterface->GetSimulatedBodyFromHandle(sceneHandle, capsuleCHandle));
|
|
|
|
// all the capsules should be stationary initially
|
|
for (int i = 0; i < 10; i++)
|
|
{
|
|
TestUtils::UpdateScene(sceneHandle, 1.0f / 60.0f, 1);
|
|
EXPECT_TRUE(capsuleA->GetPosition().IsClose(posA));
|
|
EXPECT_TRUE(capsuleA->GetAngularVelocity().IsClose(AZ::Vector3::CreateZero(), ContactTestTolerance));
|
|
EXPECT_TRUE(capsuleB->GetPosition().IsClose(posB));
|
|
EXPECT_TRUE(capsuleB->GetAngularVelocity().IsClose(AZ::Vector3::CreateZero(), ContactTestTolerance));
|
|
EXPECT_TRUE(capsuleC->GetPosition().IsClose(posC));
|
|
EXPECT_TRUE(capsuleC->GetAngularVelocity().IsClose(AZ::Vector3::CreateZero(), ContactTestTolerance));
|
|
}
|
|
|
|
// apply off-center impulses to capsule A and C, and an impulse through the center of B
|
|
AZ::Vector3 impulse(0.0f, 0.0f, 10.0f);
|
|
capsuleA->ApplyLinearImpulseAtWorldPoint(impulse, posA + AZ::Vector3::CreateAxisX(0.5f));
|
|
capsuleB->ApplyLinearImpulseAtWorldPoint(impulse, posB);
|
|
capsuleC->ApplyLinearImpulseAtWorldPoint(impulse, posC + AZ::Vector3::CreateAxisX(-0.5f));
|
|
|
|
// A and C should be rotating in opposite directions, B should still have 0 angular velocity
|
|
for (int i = 0; i < 30; i++)
|
|
{
|
|
TestUtils::UpdateScene(sceneHandle, 1.0f / 60.0f, 1);
|
|
EXPECT_TRUE(capsuleA->GetAngularVelocity().GetY() < 0.0f);
|
|
EXPECT_TRUE(capsuleB->GetAngularVelocity().IsClose(AZ::Vector3::CreateZero(), ContactTestTolerance));
|
|
EXPECT_TRUE(capsuleC->GetAngularVelocity().GetY() > 0.0f);
|
|
}
|
|
}
|
|
|
|
TEST_F(GenericPhysicsInterfaceTest, ApplyAngularImpulse_DynamicSphere_StartsRotating)
|
|
{
|
|
AzPhysics::SceneHandle sceneHandle = CreateTestScene();
|
|
if (auto* physicsSystem = AZ::Interface<AzPhysics::SystemInterface>::Get())
|
|
{
|
|
physicsSystem->GetScene(sceneHandle);
|
|
}
|
|
TestUtils::AddStaticFloorToScene(sceneHandle);
|
|
|
|
auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get();
|
|
AzPhysics::RigidBody* spheres[3];
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
AzPhysics::SimulatedBodyHandle simBodyHandle = TestUtils::AddSphereToScene(sceneHandle, AZ::Vector3(0.0f, -5.0f + 5.0f * i, 1.0f));
|
|
spheres[i] = azdynamic_cast<AzPhysics::RigidBody*>(sceneInterface->GetSimulatedBodyFromHandle(sceneHandle, simBodyHandle));
|
|
}
|
|
|
|
// all the spheres should start stationary
|
|
TestUtils::UpdateScene(sceneHandle, 1.0f / 60.0f, 10);
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
EXPECT_TRUE(spheres[i]->GetAngularVelocity().IsClose(AZ::Vector3::CreateZero()));
|
|
}
|
|
|
|
// apply angular impulses and they should gain angular velocity parallel to the impulse direction
|
|
AZ::Vector3 impulses[3] = { AZ::Vector3(2.0f, 4.0f, 0.0f), AZ::Vector3(-3.0f, 1.0f, 0.0f),
|
|
AZ::Vector3(-2.0f, 3.0f, 0.0f) };
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
spheres[i]->ApplyAngularImpulse(impulses[i]);
|
|
}
|
|
|
|
TestUtils::UpdateScene(sceneHandle, 1.0f / 60.0f, 10);
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
auto angVel = spheres[i]->GetAngularVelocity();
|
|
EXPECT_TRUE(angVel.GetProjected(impulses[i]).IsClose(angVel, 0.1f));
|
|
}
|
|
}
|
|
|
|
TEST_F(GenericPhysicsInterfaceTest, StartAsleep_FallingBox_DoesNotFall)
|
|
{
|
|
AzPhysics::SceneHandle sceneHandle = CreateTestScene();
|
|
auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get();
|
|
|
|
// Box should start asleep
|
|
AzPhysics::RigidBodyConfiguration config;
|
|
config.m_startAsleep = true;
|
|
config.m_colliderAndShapeData = AzPhysics::ShapeColliderPair(
|
|
AZStd::make_shared<Physics::ColliderConfiguration>(),
|
|
AZStd::make_shared<Physics::SphereShapeConfiguration>()
|
|
);
|
|
|
|
AzPhysics::SimulatedBodyHandle rigidBodyHandle = sceneInterface->AddSimulatedBody(sceneHandle, &config);
|
|
TestUtils::UpdateScene(sceneHandle, 1.0f / 60.0f, 100);
|
|
|
|
// Check the box is still at 0 and hasn't dropped
|
|
AzPhysics::SimulatedBody* box = sceneInterface->GetSimulatedBodyFromHandle(sceneHandle, rigidBodyHandle);
|
|
EXPECT_NEAR(0.0f, box->GetPosition().GetZ(), 0.01f);
|
|
}
|
|
|
|
TEST_F(GenericPhysicsInterfaceTest, ForceAsleep_FallingBox_BecomesStationary)
|
|
{
|
|
AzPhysics::SceneHandle sceneHandle = CreateTestScene();
|
|
|
|
TestUtils::AddStaticFloorToScene(sceneHandle);
|
|
AzPhysics::RigidBody* box = TestUtils::AddUnitBoxToScene(sceneHandle, AZ::Vector3(0.0f, 0.0f, 10.0f));
|
|
TestUtils::UpdateScene(sceneHandle, 1.0f / 60.0f, 60);
|
|
|
|
EXPECT_TRUE(box->IsAwake());
|
|
|
|
auto pos = box->GetPosition();
|
|
box->ForceAsleep();
|
|
EXPECT_FALSE(box->IsAwake());
|
|
TestUtils::UpdateScene(sceneHandle, 1.0f / 60.0f, 30);
|
|
EXPECT_FALSE(box->IsAwake());
|
|
// the box should be asleep so it shouldn't have moved
|
|
EXPECT_TRUE(box->GetPosition().IsClose(pos));
|
|
}
|
|
|
|
TEST_F(GenericPhysicsInterfaceTest, ForceAwake_SleepingBox_SleepStateCorrect)
|
|
{
|
|
AzPhysics::SceneHandle sceneHandle = CreateTestScene();
|
|
|
|
TestUtils::AddStaticFloorToScene(sceneHandle);
|
|
AzPhysics::RigidBody* box = TestUtils::AddUnitBoxToScene(sceneHandle, AZ::Vector3(0.0f, 0.0f, 1.0f));
|
|
|
|
TestUtils::UpdateScene(sceneHandle, 1.0f / 60.0f, 60);
|
|
EXPECT_FALSE(box->IsAwake());
|
|
|
|
box->ForceAwake();
|
|
EXPECT_TRUE(box->IsAwake());
|
|
|
|
//bring these tests into a cpp and into PhysXTests.
|
|
|
|
TestUtils::UpdateScene(sceneHandle, 1.0f / 60.0f, 60);
|
|
// the box should have gone back to sleep
|
|
EXPECT_FALSE(box->IsAwake());
|
|
}
|
|
|
|
TEST_F(GenericPhysicsInterfaceTest, GetAabb_Box_ValidExtents)
|
|
{
|
|
AzPhysics::SceneHandle sceneHandle = CreateTestScene();
|
|
|
|
AZ::Vector3 posBox(0.0f, 0.0f, 0.0f);
|
|
AzPhysics::RigidBody* box = TestUtils::AddUnitBoxToScene(sceneHandle, posBox);
|
|
|
|
EXPECT_TRUE(box->GetAabb().GetMin().IsClose(posBox - 0.5f * AZ::Vector3::CreateOne()));
|
|
EXPECT_TRUE(box->GetAabb().GetMax().IsClose(posBox + 0.5f * AZ::Vector3::CreateOne()));
|
|
|
|
// rotate the box and check the bounding box is still correct
|
|
AZ::Quaternion quat = AZ::Quaternion::CreateRotationZ(0.25f * AZ::Constants::Pi);
|
|
box->SetTransform(AZ::Transform::CreateFromQuaternionAndTranslation(quat, posBox));
|
|
|
|
AZ::Vector3 boxExtent(sqrtf(0.5f), sqrtf(0.5f), 0.5f);
|
|
EXPECT_TRUE(box->GetAabb().GetMin().IsClose(posBox - boxExtent));
|
|
EXPECT_TRUE(box->GetAabb().GetMax().IsClose(posBox + boxExtent));
|
|
}
|
|
|
|
TEST_F(GenericPhysicsInterfaceTest, GetAabb_Sphere_ValidExtents)
|
|
{
|
|
AzPhysics::SceneHandle sceneHandle = CreateTestScene();
|
|
|
|
AZ::Vector3 posSphere(0.0f, 0.0f, 0.0f);
|
|
AzPhysics::SimulatedBodyHandle simBodyHandle = TestUtils::AddSphereToScene(sceneHandle, posSphere);
|
|
|
|
auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get();
|
|
auto* sphere = azdynamic_cast<AzPhysics::RigidBody*>(sceneInterface->GetSimulatedBodyFromHandle(sceneHandle, simBodyHandle));
|
|
|
|
EXPECT_TRUE(sphere->GetAabb().GetMin().IsClose(posSphere - 0.5f * AZ::Vector3::CreateOne()));
|
|
EXPECT_TRUE(sphere->GetAabb().GetMax().IsClose(posSphere + 0.5f * AZ::Vector3::CreateOne()));
|
|
|
|
// rotate the sphere and check the bounding box is still correct
|
|
AZ::Quaternion quat = AZ::Quaternion::CreateRotationZ(0.25f * AZ::Constants::Pi);
|
|
sphere->SetTransform(AZ::Transform::CreateFromQuaternionAndTranslation(quat, posSphere));
|
|
|
|
EXPECT_TRUE(sphere->GetAabb().GetMin().IsClose(posSphere - 0.5f * AZ::Vector3::CreateOne()));
|
|
EXPECT_TRUE(sphere->GetAabb().GetMax().IsClose(posSphere + 0.5f * AZ::Vector3::CreateOne()));
|
|
}
|
|
|
|
TEST_F(GenericPhysicsInterfaceTest, GetAabb_Capsule_ValidExtents)
|
|
{
|
|
AzPhysics::SceneHandle sceneHandle = CreateTestScene();
|
|
|
|
AZ::Vector3 posCapsule(0.0f, 0.0f, 0.0f);
|
|
AzPhysics::SimulatedBodyHandle capsuleHandle = TestUtils::AddCapsuleToScene(sceneHandle, posCapsule);
|
|
auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get();
|
|
auto* capsule = azdynamic_cast<AzPhysics::RigidBody*>(sceneInterface->GetSimulatedBodyFromHandle(sceneHandle, capsuleHandle));
|
|
|
|
EXPECT_TRUE(capsule->GetAabb().GetMin().IsClose(posCapsule - AZ::Vector3(0.5f, 1.0f, 0.5f)));
|
|
EXPECT_TRUE(capsule->GetAabb().GetMax().IsClose(posCapsule + AZ::Vector3(0.5f, 1.0f, 0.5f)));
|
|
|
|
// rotate the bodies and check the bounding boxes are still correct
|
|
AZ::Quaternion quat = AZ::Quaternion::CreateRotationZ(0.25f * AZ::Constants::Pi);
|
|
capsule->SetTransform(AZ::Transform::CreateFromQuaternionAndTranslation(quat, posCapsule));
|
|
|
|
AZ::Vector3 capsuleExtent(0.5f + sqrt(0.125f), 0.5f + sqrt(0.125f), 0.5f);
|
|
EXPECT_TRUE(capsule->GetAabb().GetMin().IsClose(posCapsule - capsuleExtent));
|
|
EXPECT_TRUE(capsule->GetAabb().GetMax().IsClose(posCapsule + capsuleExtent));
|
|
}
|
|
|
|
TEST_F(GenericPhysicsInterfaceTest, Materials_BoxesSharingDefaultMaterial_JumpingSameHeight)
|
|
{
|
|
AzPhysics::SceneHandle sceneHandle = CreateTestScene();
|
|
|
|
TestUtils::AddStaticFloorToScene(sceneHandle);
|
|
AzPhysics::RigidBody* boxB = TestUtils::AddUnitBoxToScene(sceneHandle, AZ::Vector3(1.0f, 0.0f, 10.0f));
|
|
AzPhysics::RigidBody* boxC = TestUtils::AddUnitBoxToScene(sceneHandle, AZ::Vector3(-1.0f, 0.0f, 10.0f));
|
|
|
|
auto material = boxC->GetShape(0)->GetMaterial();
|
|
material->SetRestitution(1.0f);
|
|
|
|
TestUtils::UpdateScene(sceneHandle, 1.0f / 60.0f, 150);
|
|
|
|
// boxB and boxC should have the same material (default)
|
|
// so they should both bounce high
|
|
EXPECT_NEAR(boxB->GetPosition().GetZ(), boxC->GetPosition().GetZ(), 0.5f);
|
|
}
|
|
|
|
TEST_F(GenericPhysicsInterfaceTest, Collider_ColliderTag_IsSetFromConfiguration)
|
|
{
|
|
const AZStd::string colliderTagName = "ColliderTestTag";
|
|
Physics::ColliderConfiguration colliderConfig;
|
|
colliderConfig.m_tag = colliderTagName;
|
|
Physics::SphereShapeConfiguration shapeConfig;
|
|
|
|
AZStd::shared_ptr<Physics::Shape> shape;
|
|
Physics::SystemRequestBus::BroadcastResult(shape, &Physics::SystemRequests::CreateShape, colliderConfig, shapeConfig);
|
|
|
|
EXPECT_EQ(shape->GetTag(), AZ::Crc32(colliderTagName));
|
|
}
|
|
|
|
} // namespace Physics
|