185 lines
6.5 KiB
C++
185 lines
6.5 KiB
C++
#include <chrono>
|
|
#include <thread>
|
|
#include <destrum/App.h>
|
|
|
|
#include <destrum/FS/AssetFS.h>
|
|
|
|
#include "glm/gtx/transform.hpp"
|
|
#include "spdlog/spdlog.h"
|
|
|
|
App::App(): renderer{meshCache} {
|
|
}
|
|
|
|
void App::init(const AppParams& params) {
|
|
m_params = params;
|
|
|
|
AssetFS::GetInstance().Init(params.exeDir);
|
|
// AssetFS::GetInstance().Mount("engine", params.exeDir / "assets" / "engine");
|
|
// AssetFS::GetInstance().Mount("game", params.exeDir / "assets" / "game");
|
|
|
|
window = SDL_CreateWindow(
|
|
params.windowTitle.c_str(),
|
|
// pos
|
|
SDL_WINDOWPOS_UNDEFINED,
|
|
SDL_WINDOWPOS_UNDEFINED,
|
|
// size
|
|
params.windowSize.x,
|
|
params.windowSize.y,
|
|
SDL_WINDOW_VULKAN);
|
|
|
|
SDL_SetWindowResizable(window, SDL_TRUE);
|
|
if (!window) {
|
|
spdlog::error("Failed to create window. SDL Error: {}", SDL_GetError());
|
|
std::exit(1);
|
|
}
|
|
|
|
gfxDevice.init(window, params.appName, false);
|
|
renderer.init(gfxDevice, params.renderSize);
|
|
|
|
//Read whole file
|
|
auto file = AssetFS::GetInstance().ReadBytes("engine://assetfstest.txt");
|
|
std::string fileStr(file.begin(), file.end());
|
|
spdlog::info("Read from assetfstest.txt: {}", fileStr);
|
|
testMesh.name = "Test Mesh";
|
|
testMesh.vertices = vertices;
|
|
testMesh.indices = indices;
|
|
|
|
testMeshID = meshCache.addMesh(gfxDevice, testMesh);
|
|
spdlog::info("TestMesh uploaded with id: {}", testMeshID);
|
|
|
|
float aspectRatio = static_cast<float>(params.renderSize.x) / static_cast<float>(params.renderSize.y);
|
|
camera.setAspectRatio(aspectRatio);
|
|
|
|
//Look 90 deg to the right
|
|
camera.SetRotation(glm::radians(glm::vec2(90.f, 0.f)));
|
|
|
|
inputManager.Init();
|
|
|
|
}
|
|
|
|
void App::run() {
|
|
const float FPS = 30.f;
|
|
const float dt = 1.f / FPS;
|
|
|
|
auto prevTime = std::chrono::high_resolution_clock::now();
|
|
float accumulator = dt; // so that we get at least 1 update before render
|
|
|
|
isRunning = true;
|
|
while (isRunning) {
|
|
const auto newTime = std::chrono::high_resolution_clock::now();
|
|
frameTime = std::chrono::duration<float>(newTime - prevTime).count();
|
|
|
|
if (frameTime > 0.07f && frameTime < 5.f) {
|
|
// if >=5.f - debugging?
|
|
spdlog::warn("Frame drop detected, time: {:.4f}s", frameTime);
|
|
}
|
|
|
|
accumulator += frameTime;
|
|
prevTime = newTime;
|
|
|
|
float newFPS = 1.f / frameTime;
|
|
if (newFPS == std::numeric_limits<float>::infinity()) {
|
|
// can happen when frameTime == 0
|
|
newFPS = 0;
|
|
}
|
|
avgFPS = std::lerp(avgFPS, newFPS, 0.1f);
|
|
|
|
if (accumulator > 10 * dt) {
|
|
// game stopped for debug
|
|
accumulator = dt;
|
|
}
|
|
|
|
while (accumulator >= dt) {
|
|
inputManager.BeginFrame();
|
|
SDL_Event event;
|
|
while (SDL_PollEvent(&event)) {
|
|
if (event.type == SDL_QUIT) {
|
|
isRunning = false;
|
|
return;
|
|
}
|
|
if (event.type == SDL_WINDOWEVENT) {
|
|
switch (event.window.event) {
|
|
case SDL_WINDOWEVENT_SIZE_CHANGED:
|
|
/* fallthrough */
|
|
case SDL_WINDOWEVENT_RESIZED:
|
|
m_params.windowSize = {event.window.data1, event.window.data2};
|
|
break;
|
|
}
|
|
}
|
|
inputManager.ProcessEvent(event);
|
|
|
|
if (inputManager.IsKeyDown(SDL_SCANCODE_W)) {
|
|
camera.m_position += camera.GetForward() * dt * 5.f;
|
|
}
|
|
if (inputManager.IsKeyDown(SDL_SCANCODE_S)) {
|
|
camera.m_position -= camera.GetForward() * dt * 5.f;
|
|
}
|
|
if (inputManager.IsKeyDown(SDL_SCANCODE_A)) {
|
|
camera.m_position -= camera.GetRight() * dt * 5.f;
|
|
}
|
|
if (inputManager.IsKeyDown(SDL_SCANCODE_D)) {
|
|
camera.m_position += camera.GetRight() * dt * 5.f;
|
|
}
|
|
|
|
// rotation
|
|
if (inputManager.IsKeyDown(SDL_SCANCODE_LEFT)) {
|
|
camera.SetRotation(camera.GetYaw() - glm::radians(90.f) * dt, camera.GetPitch());
|
|
}
|
|
if (inputManager.IsKeyDown(SDL_SCANCODE_RIGHT)) {
|
|
camera.SetRotation(camera.GetYaw() + glm::radians(90.f) * dt, camera.GetPitch());
|
|
}
|
|
if (inputManager.IsKeyDown(SDL_SCANCODE_UP)) {
|
|
camera.SetRotation(camera.GetYaw(), camera.GetPitch() + glm::radians(90.f) * dt);
|
|
}
|
|
if (inputManager.IsKeyDown(SDL_SCANCODE_DOWN)) {
|
|
camera.SetRotation(camera.GetYaw(), camera.GetPitch() - glm::radians(90.f) * dt);
|
|
}
|
|
|
|
camera.Update(dt);
|
|
|
|
}
|
|
|
|
if (gfxDevice.needsSwapchainRecreate()) {
|
|
spdlog::info("Recreating swapchain to size: {}x{}", m_params.windowSize.x, m_params.windowSize.y);
|
|
gfxDevice.recreateSwapchain(m_params.windowSize.x, m_params.windowSize.y);
|
|
renderer.resize(gfxDevice, { m_params.windowSize.x, m_params.windowSize.y });
|
|
float aspectRatio = float(m_params.windowSize.x) / float(m_params.windowSize.y);
|
|
camera.setAspectRatio(aspectRatio);
|
|
}
|
|
|
|
accumulator -= dt;
|
|
}
|
|
|
|
if (!gfxDevice.needsSwapchainRecreate()) {
|
|
glm::mat4 objMatrix = glm::mat4(1.f);
|
|
objMatrix = glm::translate(objMatrix, glm::vec3(0.f, -3.0f, 0.f));
|
|
renderer.beginDrawing(gfxDevice);
|
|
renderer.drawMesh(testMeshID, glm::mat4(1.f), 0);
|
|
renderer.drawMesh(testMeshID, objMatrix, 0);
|
|
renderer.endDrawing();
|
|
|
|
|
|
auto cmd = gfxDevice.beginFrame();
|
|
const auto& drawImage = renderer.getDrawImage(gfxDevice);
|
|
renderer.draw(cmd, gfxDevice, camera, GameRenderer::SceneData{
|
|
camera, glm::vec3(0.1f), 0.5f, glm::vec3(0.5f), 0.01f
|
|
});
|
|
gfxDevice.endFrame(cmd, drawImage, {
|
|
.clearColor = {{0.f, 0.f, 0.5f, 1.f}},
|
|
.drawImageBlitRect = glm::ivec4{}}
|
|
);
|
|
}
|
|
if (frameLimit) {
|
|
// Delay to not overload the CPU
|
|
const auto now = std::chrono::high_resolution_clock::now();
|
|
const auto frameTime = std::chrono::duration<float>(now - prevTime).count();
|
|
if (dt > frameTime) {
|
|
SDL_Delay(static_cast<std::uint32_t>(dt - frameTime));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void App::cleanup() {
|
|
}
|