Files
XCEngine/tests/Physics/test_physics_world.cpp

164 lines
5.9 KiB
C++

#include <gtest/gtest.h>
#include <XCEngine/Components/BoxColliderComponent.h>
#include <XCEngine/Components/CapsuleColliderComponent.h>
#include <XCEngine/Components/GameObject.h>
#include <XCEngine/Components/RigidbodyComponent.h>
#include <XCEngine/Components/SphereColliderComponent.h>
#include <XCEngine/Physics/PhysicsWorld.h>
#include <XCEngine/Scene/Scene.h>
namespace {
TEST(PhysicsWorld_Test, DefaultWorldStartsUninitialized) {
XCEngine::Physics::PhysicsWorld world;
EXPECT_FALSE(world.IsInitialized());
EXPECT_EQ(world.GetNativeActorCount(), 0u);
EXPECT_EQ(world.GetNativeShapeCount(), 0u);
}
TEST(PhysicsWorld_Test, InitializeStoresCreateInfoWithoutMarkingWorldReadyYet) {
XCEngine::Components::Scene scene("PhysicsScene");
XCEngine::Physics::PhysicsWorld world;
XCEngine::Physics::PhysicsWorldCreateInfo createInfo;
createInfo.scene = &scene;
createInfo.gravity = XCEngine::Math::Vector3(0.0f, -3.5f, 0.0f);
const bool expectedInitialized = XCEngine::Physics::PhysicsWorld::IsPhysXAvailable();
EXPECT_EQ(world.Initialize(createInfo), expectedInitialized);
EXPECT_EQ(world.IsInitialized(), expectedInitialized);
EXPECT_EQ(world.GetCreateInfo().scene, &scene);
EXPECT_EQ(world.GetCreateInfo().gravity, XCEngine::Math::Vector3(0.0f, -3.5f, 0.0f));
}
TEST(PhysicsWorld_Test, StepWithoutInitializationIsNoOp) {
XCEngine::Physics::PhysicsWorld world;
world.Step(0.016f);
EXPECT_FALSE(world.IsInitialized());
}
TEST(PhysicsWorld_Test, InitializeBuildsNativeActorsFromSceneComponents) {
using namespace XCEngine::Components;
Scene scene("PhysicsScene");
GameObject* ground = scene.CreateGameObject("Ground");
ground->AddComponent<BoxColliderComponent>();
GameObject* player = scene.CreateGameObject("Player");
player->AddComponent<RigidbodyComponent>();
player->AddComponent<SphereColliderComponent>();
GameObject* childTrigger = scene.CreateGameObject("ChildTrigger", player);
childTrigger->AddComponent<CapsuleColliderComponent>();
XCEngine::Physics::PhysicsWorld world;
XCEngine::Physics::PhysicsWorldCreateInfo createInfo = {};
createInfo.scene = &scene;
const bool expectedInitialized = XCEngine::Physics::PhysicsWorld::IsPhysXAvailable();
ASSERT_EQ(world.Initialize(createInfo), expectedInitialized);
EXPECT_EQ(world.GetTrackedRigidbodyCount(), 1u);
EXPECT_EQ(world.GetTrackedColliderCount(), 3u);
if (!expectedInitialized) {
EXPECT_EQ(world.GetNativeActorCount(), 0u);
EXPECT_EQ(world.GetNativeShapeCount(), 0u);
return;
}
EXPECT_EQ(world.GetNativeActorCount(), 2u);
EXPECT_EQ(world.GetNativeShapeCount(), 3u);
}
TEST(PhysicsWorld_Test, ComponentChangesRebuildNativeActorOwnership) {
using namespace XCEngine::Components;
Scene scene("PhysicsScene");
GameObject* player = scene.CreateGameObject("Player");
player->AddComponent<RigidbodyComponent>();
SphereColliderComponent* playerSphere = player->AddComponent<SphereColliderComponent>();
BoxColliderComponent* playerBox = player->AddComponent<BoxColliderComponent>();
GameObject* child = scene.CreateGameObject("Child", player);
child->AddComponent<CapsuleColliderComponent>();
XCEngine::Physics::PhysicsWorld world;
XCEngine::Physics::PhysicsWorldCreateInfo createInfo = {};
createInfo.scene = &scene;
const bool expectedInitialized = XCEngine::Physics::PhysicsWorld::IsPhysXAvailable();
ASSERT_EQ(world.Initialize(createInfo), expectedInitialized);
EXPECT_EQ(world.GetTrackedRigidbodyCount(), 1u);
EXPECT_EQ(world.GetTrackedColliderCount(), 3u);
if (!expectedInitialized) {
return;
}
EXPECT_EQ(world.GetNativeActorCount(), 1u);
EXPECT_EQ(world.GetNativeShapeCount(), 3u);
ASSERT_TRUE(player->RemoveComponent(playerBox));
EXPECT_EQ(world.GetTrackedRigidbodyCount(), 1u);
EXPECT_EQ(world.GetTrackedColliderCount(), 2u);
EXPECT_EQ(world.GetNativeActorCount(), 1u);
EXPECT_EQ(world.GetNativeShapeCount(), 2u);
child->AddComponent<RigidbodyComponent>();
EXPECT_EQ(world.GetTrackedRigidbodyCount(), 2u);
EXPECT_EQ(world.GetTrackedColliderCount(), 2u);
EXPECT_EQ(world.GetNativeActorCount(), 2u);
EXPECT_EQ(world.GetNativeShapeCount(), 2u);
scene.DestroyGameObject(player);
EXPECT_EQ(world.GetTrackedRigidbodyCount(), 0u);
EXPECT_EQ(world.GetTrackedColliderCount(), 0u);
EXPECT_EQ(world.GetNativeActorCount(), 0u);
EXPECT_EQ(world.GetNativeShapeCount(), 0u);
(void)playerSphere;
}
TEST(PhysicsWorld_Test, DynamicSimulationWritesBackTransform) {
using namespace XCEngine::Components;
if (!XCEngine::Physics::PhysicsWorld::IsPhysXAvailable()) {
GTEST_SKIP() << "PhysX backend is not available in this build.";
}
Scene scene("PhysicsScene");
GameObject* ground = scene.CreateGameObject("Ground");
ground->GetTransform()->SetPosition(XCEngine::Math::Vector3(0.0f, -0.5f, 0.0f));
BoxColliderComponent* groundCollider = ground->AddComponent<BoxColliderComponent>();
groundCollider->SetSize(XCEngine::Math::Vector3(20.0f, 1.0f, 20.0f));
GameObject* ball = scene.CreateGameObject("Ball");
ball->GetTransform()->SetPosition(XCEngine::Math::Vector3(0.0f, 4.0f, 0.0f));
RigidbodyComponent* rigidbody = ball->AddComponent<RigidbodyComponent>();
rigidbody->SetBodyType(XCEngine::Physics::PhysicsBodyType::Dynamic);
rigidbody->SetMass(1.0f);
rigidbody->SetUseGravity(true);
SphereColliderComponent* sphere = ball->AddComponent<SphereColliderComponent>();
sphere->SetRadius(0.5f);
XCEngine::Physics::PhysicsWorld world;
XCEngine::Physics::PhysicsWorldCreateInfo createInfo = {};
createInfo.scene = &scene;
ASSERT_TRUE(world.Initialize(createInfo));
const float initialY = ball->GetTransform()->GetPosition().y;
for (int index = 0; index < 30; ++index) {
world.Step(1.0f / 60.0f);
}
EXPECT_LT(ball->GetTransform()->GetPosition().y, initialY - 0.1f);
}
} // namespace