moving camera

This commit is contained in:
2024-06-12 17:18:10 +02:00
parent 75cd769681
commit 5ec6ff42ab

View File

@@ -7,149 +7,165 @@
#include <Nazara/Physics3D.hpp> #include <Nazara/Physics3D.hpp>
#include <random> #include <random>
static void CreateLight(Nz::EnttWorld &world) static Nz::Vector3f Get2DDirectionVectorFromRotation(float yaw) {
{ return {
entt::handle lightEntity = world.CreateEntity(); -std::sin(yaw),
{ 0,
auto &lightNode = lightEntity.emplace<Nz::NodeComponent>(); -std::cos(yaw),
lightNode.SetPosition({0, 1, 0}); };
auto &entityLight = lightEntity.emplace<Nz::LightComponent>();
auto &spotLight = entityLight.AddLight<Nz::PointLight>(1);
spotLight.EnableShadowCasting(true);
spotLight.UpdateShadowMapSize(1024);
}
} }
static void CreateBoxes(Nz::EnttWorld& world) static void CreateLight(Nz::EnttWorld &world)
{ {
constexpr float BoxDims = 16.f; entt::handle lightEntity = world.CreateEntity();
{
auto &lightNode = lightEntity.emplace<Nz::NodeComponent>();
lightNode.SetPosition({0, 5, 0});
std::mt19937 rd(42); auto &entityLight = lightEntity.emplace<Nz::LightComponent>();
auto &spotLight = entityLight.AddLight<Nz::PointLight>(1);
spotLight.EnableShadowCasting(true);
spotLight.UpdateShadowMapSize(1024);
spotLight.UpdateRadius(10.0f);
spotLight.UpdateDiffuseFactor(0.5f);
}
}
static void CreateBoxes(Nz::EnttWorld &world)
{
constexpr float BoxDims = 1.f;
std::mt19937 rd(42);
std::uniform_real_distribution<float> colorDis(0.f, 360.f); std::uniform_real_distribution<float> colorDis(0.f, 360.f);
std::uniform_real_distribution<float> radiusDis(0.1f, 0.5f); std::uniform_real_distribution<float> radiusDis(0.1f, 0.5f);
std::uniform_real_distribution<float> lengthDis(0.2f, 1.5f); std::uniform_real_distribution<float> lengthDis(0.2f, 1.5f);
std::shared_ptr<Nz::GraphicalMesh> boxMesh = Nz::GraphicalMesh::Build(Nz::Primitive::Box(Nz::Vector3f(1.f))); std::shared_ptr<Nz::GraphicalMesh> boxMesh = Nz::GraphicalMesh::Build(Nz::Primitive::Box(Nz::Vector3f(1.f)));
constexpr std::size_t BoxCount = 100; constexpr std::size_t BoxCount = 100;
for (std::size_t i = 0; i < BoxCount; ++i) for (std::size_t i = 0; i < BoxCount; ++i)
{ {
float width = lengthDis(rd); float width = lengthDis(rd);
float height = lengthDis(rd); float height = lengthDis(rd);
float depth = lengthDis(rd); float depth = lengthDis(rd);
std::uniform_real_distribution<float> xRandom(-BoxDims * 0.5f + width, BoxDims * 0.5f - width); std::uniform_real_distribution<float> xRandom(-BoxDims * 0.5f + width, BoxDims * 0.5f - width);
std::uniform_real_distribution<float> yRandom(-BoxDims * 0.5f + height, BoxDims * 0.5f - height); std::uniform_real_distribution<float> yRandom(-BoxDims * 0.5f + height, BoxDims * 0.5f - height);
std::uniform_real_distribution<float> zRandom(-BoxDims * 0.5f + depth, BoxDims * 0.5f - depth); std::uniform_real_distribution<float> zRandom(-BoxDims * 0.5f + depth, BoxDims * 0.5f - depth);
entt::handle boxEntity = world.CreateEntity(); entt::handle boxEntity = world.CreateEntity();
std::shared_ptr<Nz::MaterialInstance> boxMaterial = Nz::MaterialInstance::Instantiate(Nz::MaterialType::Phong); std::shared_ptr<Nz::MaterialInstance> boxMaterial = Nz::MaterialInstance::Instantiate(Nz::MaterialType::Phong);
boxMaterial->SetValueProperty("BaseColor", Nz::Color::sRGBToLinear(Nz::Color::FromHSV(colorDis(rd), 1.f, 1.f))); boxMaterial->SetValueProperty("BaseColor", Nz::Color::sRGBToLinear(Nz::Color::FromHSV(colorDis(rd), 1.f, 1.f)));
std::shared_ptr<Nz::Model> sphereModel = std::make_shared<Nz::Model>(boxMesh); std::shared_ptr<Nz::Model> sphereModel = std::make_shared<Nz::Model>(boxMesh);
sphereModel->SetMaterial(0, std::move(boxMaterial)); sphereModel->SetMaterial(0, std::move(boxMaterial));
boxEntity.emplace<Nz::GraphicsComponent>(std::move(sphereModel)); boxEntity.emplace<Nz::GraphicsComponent>(std::move(sphereModel));
auto &ballNode = boxEntity.emplace<Nz::NodeComponent>(); auto &ballNode = boxEntity.emplace<Nz::NodeComponent>();
ballNode.SetPosition({xRandom(rd), yRandom(rd), zRandom(rd)}); ballNode.SetPosition({xRandom(rd), yRandom(rd) + 20.0f, zRandom(rd)});
ballNode.SetScale({width, height, depth}); ballNode.SetScale({width, height, depth});
std::shared_ptr<Nz::BoxCollider3D> boxCollider = std::make_shared<Nz::BoxCollider3D>(Nz::Vector3f(width, height, depth)); std::shared_ptr<Nz::BoxCollider3D> boxCollider = std::make_shared<Nz::BoxCollider3D>(Nz::Vector3f(width, height, depth));
Nz::RigidBody3D::DynamicSettings settings; Nz::RigidBody3D::DynamicSettings settings;
settings.geom = boxCollider; settings.geom = boxCollider;
settings.mass = width * height * depth; settings.mass = width * height * depth;
boxEntity.emplace<Nz::RigidBody3DComponent>(settings); boxEntity.emplace<Nz::RigidBody3DComponent>(settings);
} }
} }
static void CreateModel(Nz::EnttWorld &world) static void CreateModel(Nz::EnttWorld &world)
{ {
std::filesystem::path resourceDir = "assets/models"; std::filesystem::path resourceDir = "assets/models";
Nz::MeshParams meshParams; Nz::MeshParams meshParams;
meshParams.center = true; meshParams.center = true;
meshParams.vertexRotation = Nz::EulerAnglesf(0.f, 0.f, 0.f); meshParams.vertexRotation = Nz::EulerAnglesf(0.f, 0.f, 0.f);
meshParams.vertexScale = Nz::Vector3f(1.0f); meshParams.vertexScale = Nz::Vector3f(1.0f);
meshParams.vertexDeclaration = Nz::VertexDeclaration::Get(Nz::VertexLayout::XYZ_Normal_UV_Tangent); meshParams.vertexDeclaration = Nz::VertexDeclaration::Get(Nz::VertexLayout::XYZ_Normal_UV_Tangent);
std::shared_ptr<Nz::Mesh> deambuMesh = Nz::Mesh::LoadFromFile(resourceDir / "sol.obj", meshParams); std::shared_ptr<Nz::Mesh> deambuMesh = Nz::Mesh::LoadFromFile(resourceDir / "sol.obj", meshParams);
if (!deambuMesh) if (!deambuMesh)
{ {
NazaraError("failed to load model"); NazaraError("failed to load model");
return; return;
} }
std::shared_ptr<Nz::GraphicalMesh> gfxMesh = Nz::GraphicalMesh::BuildFromMesh(*deambuMesh); std::shared_ptr<Nz::GraphicalMesh> gfxMesh = Nz::GraphicalMesh::BuildFromMesh(*deambuMesh);
std::shared_ptr<Nz::Model> deambModel = std::make_shared<Nz::Model>(std::move(gfxMesh)); std::shared_ptr<Nz::Model> deambModel = std::make_shared<Nz::Model>(std::move(gfxMesh));
entt::handle deambEntity = world.CreateEntity(); entt::handle deambEntity = world.CreateEntity();
{ {
auto &entityGfx = deambEntity.emplace<Nz::GraphicsComponent>(); auto &entityGfx = deambEntity.emplace<Nz::GraphicsComponent>();
entityGfx.AttachRenderable(deambModel); entityGfx.AttachRenderable(deambModel);
auto &entityNode = deambEntity.emplace<Nz::NodeComponent>(); auto &entityNode = deambEntity.emplace<Nz::NodeComponent>();
entityNode.SetPosition(Nz::Vector3f(0.f, 0.f, 0.f)); entityNode.SetPosition(Nz::Vector3f(0.f, 0.f, 0.f));
} }
std::shared_ptr<Nz::RenderDevice> device = Nz::Graphics::Instance()->GetRenderDevice(); std::shared_ptr<Nz::RenderDevice> device = Nz::Graphics::Instance()->GetRenderDevice();
std::shared_ptr<Nz::MaterialInstance> material = Nz::MaterialInstance::Instantiate(Nz::MaterialType::Phong); std::shared_ptr<Nz::MaterialInstance> material = Nz::MaterialInstance::Instantiate(Nz::MaterialType::Phong);
for (std::string_view passName : {"DepthPass", "ForwardPass"}) for (std::string_view passName : {"DepthPass", "ForwardPass"})
{ {
material->UpdatePassStates(passName, [](Nz::RenderStates &states) material->UpdatePassStates(passName, [](Nz::RenderStates &states)
{ {
states.depthClamp = true; states.depthClamp = true;
return true; }); return true; });
} }
std::mt19937 rd(42); std::mt19937 rd(42);
std::uniform_real_distribution<float> colorDis(0.f, 360.f); std::uniform_real_distribution<float> colorDis(0.f, 360.f);
material->SetValueProperty("BaseColor", Nz::Color::sRGBToLinear(Nz::Color::FromHSV(colorDis(rd), 1.f, 1.f))); material->SetValueProperty("BaseColor", Nz::Color::sRGBToLinear(Nz::Color::FromHSV(colorDis(rd), 1.f, 1.f)));
for (std::size_t i = 0; i < deambModel->GetSubMeshCount(); ++i) for (std::size_t i = 0; i < deambModel->GetSubMeshCount(); ++i)
deambModel->SetMaterial(i, material); deambModel->SetMaterial(i, material);
Nz::VertexMapper vertexMapper(*deambuMesh->GetSubMesh(0));
Nz::VertexMapper vertexMapper(*deambuMesh->GetSubMesh(0));
Nz::SparsePtr<Nz::Vector3f> vertices = vertexMapper.GetComponentPtr<Nz::Vector3f>(Nz::VertexComponent::Position); Nz::SparsePtr<Nz::Vector3f> vertices = vertexMapper.GetComponentPtr<Nz::Vector3f>(Nz::VertexComponent::Position);
auto shipCollider = std::make_shared<Nz::ConvexHullCollider3D>(vertices, vertexMapper.GetVertexCount(), 0.1f); auto shipCollider = std::make_shared<Nz::ConvexHullCollider3D>(vertices, vertexMapper.GetVertexCount(), 0.1f);
Nz::RigidBody3D::StaticSettings settings; Nz::RigidBody3D::StaticSettings settings;
settings.geom = shipCollider; settings.geom = shipCollider;
deambEntity.emplace<Nz::RigidBody3DComponent>(settings); deambEntity.emplace<Nz::RigidBody3DComponent>(settings);
} }
static Nz::EulerAnglesf camAngles(0.f, 0.f, 0.f); static Nz::EulerAnglesf camAngles(0.f, 0.f, 0.f);
static void CreateCamera(Nz::EnttWorld &world, Nz::Window &window) static void CreateCamera(Nz::EnttWorld &world, Nz::Window &window, Nz::Application<Nz::Graphics, Nz::Physics3D> &app)
{ {
Nz::RenderSystem &renderSystem = world.AddSystem<Nz::RenderSystem>(); Nz::RenderSystem &renderSystem = world.AddSystem<Nz::RenderSystem>();
Nz::SwapchainParameters params; Nz::SwapchainParameters params;
params.presentMode.clear(); params.presentMode.clear();
params.presentMode.push_back(Nz::PresentMode::VerticalSync); params.presentMode.push_back(Nz::PresentMode::VerticalSync);
Nz::WindowSwapchain &windowSwapchain = renderSystem.CreateSwapchain(window, params); Nz::WindowSwapchain &windowSwapchain = renderSystem.CreateSwapchain(window, params);
// Création de la caméra // Création de la caméra
entt::handle cameraEntity = world.CreateEntity(); entt::handle cameraEntity = world.CreateEntity();
auto &cameraNode = cameraEntity.emplace<Nz::NodeComponent>(); auto &cameraNode = cameraEntity.emplace<Nz::NodeComponent>();
cameraNode.SetPosition({0, 5, 0}); cameraNode.SetPosition({0, 1, 0});
auto &cameraComponent = cameraEntity.emplace<Nz::CameraComponent>(std::make_shared<Nz::RenderWindow>(windowSwapchain), Nz::ProjectionType::Perspective); auto &cameraComponent = cameraEntity.emplace<Nz::CameraComponent>(std::make_shared<Nz::RenderWindow>(windowSwapchain), Nz::ProjectionType::Perspective);
cameraComponent.UpdateClearColor(Nz::Color(0.3f, 0.8f, 1.0f)); cameraComponent.UpdateClearColor(Nz::Color(0.3f, 0.8f, 1.0f));
cameraComponent.UpdateZNear(0.1f);
cameraComponent.UpdateZFar(100.0f);
window.GetEventHandler().OnMouseMoved.Connect([&](const Nz::WindowEventHandler * /*eventHandler*/, const Nz::WindowEvent::MouseMoveEvent &event) entt::handle playerEntity = world.CreateEntity();
{
auto &playerNode = playerEntity.emplace<Nz::NodeComponent>();
playerNode.SetPosition({0, 5, 0});
cameraNode.SetParent(playerEntity);
window.GetEventHandler().OnMouseMoved.Connect([&](const Nz::WindowEventHandler * /*eventHandler*/, const Nz::WindowEvent::MouseMoveEvent &event)
{
constexpr float sensitivity = 0.3f; constexpr float sensitivity = 0.3f;
camAngles.yaw -= event.deltaX * sensitivity; camAngles.yaw -= event.deltaX * sensitivity;
@@ -157,47 +173,88 @@ static void CreateCamera(Nz::EnttWorld &world, Nz::Window &window)
camAngles.pitch = Nz::Clamp(camAngles.pitch - event.deltaY * sensitivity, -89.f, 89.f); camAngles.pitch = Nz::Clamp(camAngles.pitch - event.deltaY * sensitivity, -89.f, 89.f);
cameraNode.SetRotation(camAngles); }); camAngles.roll = 0.0f;
cameraNode.SetRotation(camAngles);
});
std::shared_ptr<Nz::BoxCollider3D> boxCollider = std::make_shared<Nz::BoxCollider3D>(Nz::Vector3f(1, 2, 1));
static const int playerMass = 100000;
Nz::RigidBody3D::DynamicSettings settings;
settings.geom = boxCollider;
settings.mass = playerMass;
auto &playerBody = playerEntity.emplace<Nz::RigidBody3DComponent>(settings);
app.AddUpdaterFunc([&](){
static Nz::MillisecondClock updateClock;
if (std::optional<Nz::Time> deltaTime = updateClock.RestartIfOver(Nz::Time::TickDuration(60)))
{
camAngles.roll = 0;
cameraNode.SetRotation(camAngles);
Nz::Vector3f front = Get2DDirectionVectorFromRotation(camAngles.yaw.ToRadians());
Nz::Vector3f left = Get2DDirectionVectorFromRotation(camAngles.yaw.ToRadians() + 3.1415926535/2.0);
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Z))
playerBody.AddForce(front * 10.f * playerMass, Nz::CoordSys::Local);
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::S))
playerBody.AddForce(-front * 10.f * playerMass, Nz::CoordSys::Local);
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Q))
playerBody.AddForce(left * 10.f * playerMass, Nz::CoordSys::Local);
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::D))
playerBody.AddForce(-left * 10.f * playerMass, Nz::CoordSys::Local);
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Space))
playerBody.AddForce(Nz::Vector3f::Up() * 15.f * playerMass, Nz::CoordSys::Local);
}
});
} }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
Nz::Application<Nz::Graphics, Nz::Physics3D> app(argc, argv); Nz::Application<Nz::Graphics, Nz::Physics3D> app(argc, argv);
auto &windowing = app.AddComponent<Nz::WindowingAppComponent>(); auto &windowing = app.AddComponent<Nz::WindowingAppComponent>();
std::string windowTitle = "Blitz 2"; std::string windowTitle = "Blitz 2";
Nz::Window &window = windowing.CreateWindow(Nz::VideoMode(1920, 1080, 32), windowTitle); Nz::Window &window = windowing.CreateWindow(Nz::VideoMode(1920, 1080, 32), windowTitle);
auto &ecs = app.AddComponent<Nz::EntitySystemAppComponent>(); auto &ecs = app.AddComponent<Nz::EntitySystemAppComponent>();
auto &world = ecs.AddWorld<Nz::EnttWorld>(); auto &world = ecs.AddWorld<Nz::EnttWorld>();
auto& physSystem = world.AddSystem<Nz::Physics3DSystem>(); auto &physSystem = world.AddSystem<Nz::Physics3DSystem>();
physSystem.GetPhysWorld().SetMaxStepCount(1); physSystem.GetPhysWorld().SetMaxStepCount(1);
physSystem.GetPhysWorld().SetStepSize(Nz::Time::TickDuration(50)); physSystem.GetPhysWorld().SetStepSize(Nz::Time::TickDuration(50));
physSystem.GetPhysWorld().SetGravity(Nz::Vector3f::Down() * 9.81f); physSystem.GetPhysWorld().SetGravity(Nz::Vector3f::Down() * 9.81f);
CreateCamera(world, window); CreateCamera(world, window, app);
CreateBoxes(world); CreateBoxes(world);
CreateModel(world); CreateModel(world);
CreateLight(world); CreateLight(world);
Nz::Mouse::SetRelativeMouseMode(true); Nz::Mouse::SetRelativeMouseMode(true);
Nz::MillisecondClock fpsClock; Nz::MillisecondClock fpsClock;
unsigned int fps = 0; unsigned int fps = 0;
app.AddUpdaterFunc([&](){ app.AddUpdaterFunc([&]()
{
fps++; fps++;
if (fpsClock.RestartIfOver(Nz::Time::Second())) if (fpsClock.RestartIfOver(Nz::Time::Second()))
{ {
window.SetTitle(windowTitle + " - " + Nz::NumberToString(fps) + " FPS" + " - " + Nz::NumberToString(world.GetAliveEntityCount()) + " entities"); window.SetTitle(windowTitle + " - " + Nz::NumberToString(fps) + " FPS" + " - " + Nz::NumberToString(world.GetAliveEntityCount()) + " entities");
fps = 0; fps = 0;
} } });
});
return app.Run(); return app.Run();
} }