feat: improve fps controller / add fog and ambient light to the scene
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
#include <destrum/Physics/JoltPhysicsWorld.h>
|
||||
#include <destrum/Components/Physics/SphereCollider.h>
|
||||
#include <destrum/Components/Physics/BoxCollider.h>
|
||||
#include <destrum/Components/Physics/CapsuleCollider.h>
|
||||
#include <destrum/Components/Physics/Collider.h>
|
||||
#include <destrum/Components/Animator.h>
|
||||
#include <destrum/Components/CameraComponent.h>
|
||||
@@ -110,6 +111,16 @@ namespace {
|
||||
child->GetTransform().SetParent(&parent->GetTransform(), false);
|
||||
scene.CommitPendingAdditions();
|
||||
|
||||
SceneEnvironment& environment = scene.GetEnvironment();
|
||||
environment.ambientColor = {0.2f, 0.3f, 0.4f};
|
||||
environment.ambientIntensity = 2.0f;
|
||||
environment.fogColor = {0.6f, 0.7f, 0.8f};
|
||||
environment.fogDensity = 0.05f;
|
||||
environment.skyboxRotationSpeed = 0.5f;
|
||||
environment.skyboxRotation = 1.0f;
|
||||
scene.Update(1.0f);
|
||||
check(close(environment.skyboxRotation, 1.5f), "scene updates must spin the skybox");
|
||||
|
||||
const auto path = std::filesystem::temp_directory_path() / "destrum_scene_test.json";
|
||||
check(SceneSerializer::Save(scene, path), "scene save must succeed");
|
||||
check(SceneSerializer::Load(scene, path), "scene load must succeed");
|
||||
@@ -121,6 +132,14 @@ namespace {
|
||||
"scene round-trip must preserve hierarchy");
|
||||
check(close(loadedChild->GetTransform().GetLocalPosition().x, 1.f),
|
||||
"scene round-trip must preserve local transforms");
|
||||
const SceneEnvironment& loadedEnvironment = scene.GetEnvironment();
|
||||
check(loadedEnvironment.ambientColor == glm::vec3{0.2f, 0.3f, 0.4f} &&
|
||||
close(loadedEnvironment.ambientIntensity, 2.0f) &&
|
||||
loadedEnvironment.fogColor == glm::vec3{0.6f, 0.7f, 0.8f} &&
|
||||
close(loadedEnvironment.fogDensity, 0.05f) &&
|
||||
close(loadedEnvironment.skyboxRotationSpeed, 0.5f) &&
|
||||
close(loadedEnvironment.skyboxRotation, 1.5f),
|
||||
"scene round-trip must preserve the environment settings");
|
||||
|
||||
SceneManager::GetInstance().Destroy();
|
||||
}
|
||||
@@ -410,6 +429,59 @@ namespace {
|
||||
SceneManager::GetInstance().Destroy();
|
||||
}
|
||||
|
||||
void testFrozenRotationCapsule()
|
||||
{
|
||||
Scene& scene = SceneManager::GetInstance().CreateScene("frozen-capsule");
|
||||
|
||||
GameObject* floor = scene.CreateGameObject("floor");
|
||||
floor->GetTransform().SetLocalPosition({0.0f, -1.0f, 0.0f});
|
||||
floor->AddComponent<BoxCollider>(glm::vec3{10.0f, 0.5f, 10.0f});
|
||||
floor->AddComponent<Rigidbody>()->SetType(RigidbodyType::Static);
|
||||
|
||||
GameObject* character = scene.CreateGameObject("character");
|
||||
character->AddComponent<CapsuleCollider>(0.4f, 1.8f);
|
||||
auto* body = character->AddComponent<Rigidbody>();
|
||||
body->SetFriction(1.0f);
|
||||
body->SetFreezeRotation(true);
|
||||
character->GetTransform().SetWorldPosition({0.0f, 1.0f, 0.0f});
|
||||
|
||||
GameObject* trigger = scene.CreateGameObject("trigger");
|
||||
trigger->GetTransform().SetWorldPosition({2.0f, 0.0f, 0.0f});
|
||||
trigger->AddComponent<BoxCollider>(glm::vec3{2.0f})->SetTrigger(true);
|
||||
trigger->AddComponent<Rigidbody>()->SetType(RigidbodyType::Static);
|
||||
|
||||
scene.CommitPendingAdditions();
|
||||
scene.GetPhysics().RefreshGameObject(*floor);
|
||||
scene.GetPhysics().RefreshGameObject(*character);
|
||||
scene.GetPhysics().RefreshGameObject(*trigger);
|
||||
|
||||
// Sliding with friction would tip a free capsule over
|
||||
body->SetLinearVelocity({4.0f, 0.0f, 0.0f});
|
||||
for (int step = 0; step < 180; ++step) {
|
||||
scene.FixedUpdate(1.0f / 60.0f);
|
||||
}
|
||||
|
||||
const glm::vec3 position = character->GetTransform().GetWorldPosition();
|
||||
const glm::quat rotation = character->GetTransform().GetWorldRotation();
|
||||
check(std::abs(rotation.w) > 0.999f, "a capsule with frozen rotation must stay upright");
|
||||
check(std::abs(position.y - (-0.5f + 0.9f)) < 0.05f, "a capsule must rest on top of the floor");
|
||||
|
||||
// Cast from inside the capsule (and the trigger it is standing in), like a ground check does
|
||||
PhysicsRaycastHit hit{};
|
||||
const bool hitGround = body->GetPhysicsWorld()->Raycast(
|
||||
position - glm::vec3{0.0f, 0.7f, 0.0f}, glm::vec3{0.0f, -1.0f, 0.0f}, 0.3f, hit, body->GetBody());
|
||||
check(hitGround && hit.object == floor && hit.normal.y > 0.9f,
|
||||
"a ground ray must skip the caster and triggers and hit the floor");
|
||||
|
||||
PhysicsRaycastHit selfHit{};
|
||||
check(body->GetPhysicsWorld()->Raycast(
|
||||
position - glm::vec3{0.0f, 0.7f, 0.0f}, glm::vec3{0.0f, -1.0f, 0.0f}, 0.3f, selfHit) &&
|
||||
selfHit.object == character,
|
||||
"a ray that doesn't ignore the caster must hit it");
|
||||
|
||||
SceneManager::GetInstance().Destroy();
|
||||
}
|
||||
|
||||
void testAnimatorAssetReferences()
|
||||
{
|
||||
GameObject object{"animated"};
|
||||
@@ -974,6 +1046,7 @@ int main()
|
||||
testAssetReferenceCacheKeys();
|
||||
testTriggerZone();
|
||||
testSceneCurrentCamera();
|
||||
testFrozenRotationCapsule();
|
||||
std::cout << "destrum tests passed\n";
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user