feat(physics): add physx raycast queries
This commit is contained in:
@@ -160,4 +160,124 @@ TEST(PhysicsWorld_Test, DynamicSimulationWritesBackTransform) {
|
||||
EXPECT_LT(ball->GetTransform()->GetPosition().y, initialY - 0.1f);
|
||||
}
|
||||
|
||||
TEST(PhysicsWorld_Test, RaycastHitsClosestCollider) {
|
||||
using namespace XCEngine::Components;
|
||||
|
||||
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* target = scene.CreateGameObject("Target");
|
||||
target->GetTransform()->SetPosition(XCEngine::Math::Vector3(0.0f, 2.0f, 0.0f));
|
||||
SphereColliderComponent* sphereCollider = target->AddComponent<SphereColliderComponent>();
|
||||
sphereCollider->SetRadius(0.5f);
|
||||
|
||||
XCEngine::Physics::PhysicsWorld world;
|
||||
XCEngine::Physics::PhysicsWorldCreateInfo createInfo = {};
|
||||
createInfo.scene = &scene;
|
||||
|
||||
const bool expectedInitialized = XCEngine::Physics::PhysicsWorld::IsPhysXAvailable();
|
||||
ASSERT_EQ(world.Initialize(createInfo), expectedInitialized);
|
||||
|
||||
XCEngine::Physics::RaycastHit hit;
|
||||
const bool result = world.Raycast(
|
||||
XCEngine::Math::Vector3(0.0f, 5.0f, 0.0f),
|
||||
XCEngine::Math::Vector3::Down(),
|
||||
10.0f,
|
||||
hit);
|
||||
|
||||
if (!expectedInitialized) {
|
||||
EXPECT_FALSE(result);
|
||||
EXPECT_EQ(hit.gameObject, nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT_TRUE(result);
|
||||
EXPECT_EQ(hit.gameObject, target);
|
||||
EXPECT_NEAR(hit.distance, 2.5f, 0.02f);
|
||||
EXPECT_NEAR(hit.point.x, 0.0f, 0.001f);
|
||||
EXPECT_NEAR(hit.point.y, 2.5f, 0.02f);
|
||||
EXPECT_NEAR(hit.point.z, 0.0f, 0.001f);
|
||||
EXPECT_NEAR(hit.normal.x, 0.0f, 0.001f);
|
||||
EXPECT_NEAR(hit.normal.y, 1.0f, 0.02f);
|
||||
EXPECT_NEAR(hit.normal.z, 0.0f, 0.001f);
|
||||
EXPECT_FALSE(hit.isTrigger);
|
||||
}
|
||||
|
||||
TEST(PhysicsWorld_Test, RaycastMissClearsHitOutput) {
|
||||
using namespace XCEngine::Components;
|
||||
|
||||
Scene scene("PhysicsScene");
|
||||
GameObject* target = scene.CreateGameObject("Target");
|
||||
target->AddComponent<BoxColliderComponent>();
|
||||
|
||||
XCEngine::Physics::PhysicsWorld world;
|
||||
XCEngine::Physics::PhysicsWorldCreateInfo createInfo = {};
|
||||
createInfo.scene = &scene;
|
||||
|
||||
const bool expectedInitialized = XCEngine::Physics::PhysicsWorld::IsPhysXAvailable();
|
||||
ASSERT_EQ(world.Initialize(createInfo), expectedInitialized);
|
||||
|
||||
XCEngine::Physics::RaycastHit hit;
|
||||
hit.gameObject = target;
|
||||
hit.point = XCEngine::Math::Vector3::One();
|
||||
hit.normal = XCEngine::Math::Vector3::Up();
|
||||
hit.distance = 123.0f;
|
||||
hit.isTrigger = true;
|
||||
|
||||
const bool result = world.Raycast(
|
||||
XCEngine::Math::Vector3(0.0f, 5.0f, 0.0f),
|
||||
XCEngine::Math::Vector3::Up(),
|
||||
10.0f,
|
||||
hit);
|
||||
|
||||
EXPECT_FALSE(result);
|
||||
EXPECT_EQ(hit.gameObject, nullptr);
|
||||
EXPECT_EQ(hit.point, XCEngine::Math::Vector3::Zero());
|
||||
EXPECT_EQ(hit.normal, XCEngine::Math::Vector3::Zero());
|
||||
EXPECT_FLOAT_EQ(hit.distance, 0.0f);
|
||||
EXPECT_FALSE(hit.isTrigger);
|
||||
}
|
||||
|
||||
TEST(PhysicsWorld_Test, RaycastCanHitTriggerCollider) {
|
||||
using namespace XCEngine::Components;
|
||||
|
||||
Scene scene("PhysicsScene");
|
||||
GameObject* trigger = scene.CreateGameObject("Trigger");
|
||||
SphereColliderComponent* sphereCollider = trigger->AddComponent<SphereColliderComponent>();
|
||||
sphereCollider->SetRadius(1.0f);
|
||||
sphereCollider->SetTrigger(true);
|
||||
|
||||
XCEngine::Physics::PhysicsWorld world;
|
||||
XCEngine::Physics::PhysicsWorldCreateInfo createInfo = {};
|
||||
createInfo.scene = &scene;
|
||||
|
||||
const bool expectedInitialized = XCEngine::Physics::PhysicsWorld::IsPhysXAvailable();
|
||||
ASSERT_EQ(world.Initialize(createInfo), expectedInitialized);
|
||||
|
||||
XCEngine::Physics::RaycastHit hit;
|
||||
const bool result = world.Raycast(
|
||||
XCEngine::Math::Vector3(0.0f, 0.0f, -5.0f),
|
||||
XCEngine::Math::Vector3::Forward(),
|
||||
10.0f,
|
||||
hit);
|
||||
|
||||
if (!expectedInitialized) {
|
||||
EXPECT_FALSE(result);
|
||||
EXPECT_EQ(hit.gameObject, nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT_TRUE(result);
|
||||
EXPECT_EQ(hit.gameObject, trigger);
|
||||
EXPECT_NEAR(hit.distance, 4.0f, 0.02f);
|
||||
EXPECT_TRUE(hit.isTrigger);
|
||||
EXPECT_NEAR(hit.normal.x, 0.0f, 0.001f);
|
||||
EXPECT_NEAR(hit.normal.y, 0.0f, 0.001f);
|
||||
EXPECT_NEAR(hit.normal.z, -1.0f, 0.02f);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Reference in New Issue
Block a user