From b2831e2b5dd99b109f067cbc9e57b287ee87fc0e Mon Sep 17 00:00:00 2001 From: bailwillharr Date: Thu, 5 Jan 2023 13:21:33 +0000 Subject: [PATCH] Re-add model loading and clean up code --- CMakeLists.txt | 22 +-- include/gfx_device.hpp | 2 +- include/resource_manager.hpp | 16 ++- include/resources/mesh.hpp | 9 +- include/scene.hpp | 51 ++++++- include/systems/render.hpp | 18 ++- include/systems/transform.hpp | 54 +------- include/util/model_loader.hpp | 13 ++ include/window.hpp | 2 +- src/application.cpp | 8 ++ src/gfx_device_vulkan.cpp | 149 ++++++++++++--------- src/scene_manager.cpp | 2 +- src/systems/render.cpp | 40 ++++-- src/systems/transform.cpp | 56 ++++++++ src/util/model_loader.cpp | 235 +++++++++++++++++++++++++++++++++ src/window.cpp | 12 +- test/CMakeLists.txt | 7 +- test/src/camera_controller.cpp | 116 +++++++++------- test/src/camera_controller.hpp | 19 +-- test/src/game.cpp | 127 ++++++++++++------ test/src/main.cpp | 2 +- 21 files changed, 701 insertions(+), 259 deletions(-) create mode 100644 include/util/model_loader.hpp create mode 100644 src/systems/transform.cpp create mode 100644 src/util/model_loader.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index cb2a1f4..781056f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,7 @@ set(SRC_FILES "src/ecs_system.cpp" "src/application.cpp" + "src/systems/transform.cpp" "src/systems/render.cpp" "src/resources/material.cpp" @@ -21,6 +22,7 @@ set(SRC_FILES "src/gfx_device_vulkan.cpp" "src/util/files.cpp" + "src/util/model_loader.cpp" "src/scene_manager.cpp" "src/input_manager.cpp" @@ -46,6 +48,7 @@ set(INCLUDE_FILES "include/engine_api.h" "include/util/files.hpp" + "include/util/model_loader.hpp" "include/util.hpp" "include/logger.hpp" @@ -81,8 +84,9 @@ set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD_REQUIRED ON) if (MSVC) target_compile_options(${PROJECT_NAME} PRIVATE /W3) target_compile_options(${PROJECT_NAME} PRIVATE /MP) - target_compile_definitions(${PROJECT_NAME} PRIVATE _CRT_SECURE_NO_WARNINGS) +else() + target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -Werror -pedantic) endif() target_include_directories(${PROJECT_NAME} PUBLIC include) @@ -125,7 +129,7 @@ if(ENGINE_BUILD_OPENGL) set(BUILD_SHARED_LIBS OFF) add_subdirectory(dependencies/glad) target_link_libraries(${PROJECT_NAME} PUBLIC glad) - target_include_directories(${PROJECT_NAME} PUBLIC dependencies/glad/include) + target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC dependencies/glad/include) endif() if(ENGINE_BUILD_VULKAN) @@ -137,7 +141,7 @@ if(ENGINE_BUILD_VULKAN) add_subdirectory(dependencies/volk) target_link_libraries(${PROJECT_NAME} PRIVATE volk_headers) # Vulkan Memory Allocator - target_include_directories(${PROJECT_NAME} PRIVATE dependencies/VulkanMemoryAllocator/include) + target_include_directories(${PROJECT_NAME} SYSTEM PRIVATE dependencies/VulkanMemoryAllocator/include) # shaderc if (MSVC) include(FindVulkan) @@ -151,7 +155,7 @@ endif() # SDL2: find_package(SDL2) if (SDL2_FOUND) - target_include_directories(${PROJECT_NAME} PUBLIC ${SDL2_INCLUDE_DIRS}) + target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC ${SDL2_INCLUDE_DIRS}) else() set(SDL2_DISABLE_INSTALL ON CACHE INTERNAL "" FORCE) set(SDL_SHARED ON CACHE INTERNAL "" FORCE) @@ -159,7 +163,7 @@ else() set(SDL_TEST OFF CACHE INTERNAL "" FORCE) set(BUILD_SHARED_LIBS ON) add_subdirectory(dependencies/SDL) - target_include_directories(${PROJECT_NAME} PUBLIC dependencies/SDL/include) + target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC dependencies/SDL/include) endif() target_link_libraries(${PROJECT_NAME} PUBLIC SDL2::SDL2) target_link_libraries(${PROJECT_NAME} PUBLIC SDL2::SDL2main) @@ -167,14 +171,14 @@ target_link_libraries(${PROJECT_NAME} PUBLIC SDL2::SDL2main) # GLM: set(BUILD_SHARED_LIBS OFF) add_subdirectory(dependencies/glm) -target_include_directories(${PROJECT_NAME} PUBLIC dependencies/glm) +target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC dependencies/glm) # spdlog set(SPDLOG_BUILD_SHARED OFF CACHE INTERNAL "" FORCE) set(BUILD_SHARED_LIBS OFF) add_subdirectory(dependencies/spdlog) target_link_libraries(${PROJECT_NAME} PUBLIC spdlog) -target_include_directories(${PROJECT_NAME} PUBLIC dependencies/spdlog/include) +target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC dependencies/spdlog/include) # freetype #set(FT_DISABLE_ZLIB TRUE CACHE INTERNAL "" FORCE) @@ -188,7 +192,7 @@ target_include_directories(${PROJECT_NAME} PUBLIC dependencies/spdlog/include) #target_include_directories(${PROJECT_NAME} PRIVATE dependencies/freetype/include) # stb -target_include_directories(${PROJECT_NAME} PRIVATE dependencies/stb) +target_include_directories(${PROJECT_NAME} SYSTEM PRIVATE dependencies/stb) # assimp set(BUILD_SHARED_LIBS OFF CACHE INTERNAL "" FORCE) @@ -197,5 +201,5 @@ set(ASSIMP_BUILD_ZLIB ON CACHE INTERNAL "" FORCE) set(ASSIMP_NO_EXPORT ON CACHE INTERNAL "" FORCE) set(ASSIMP_INSTALL OFF CACHE INTERNAL "" FORCE) add_subdirectory(dependencies/assimp) -target_include_directories(${PROJECT_NAME} PRIVATE dependencies/assimp/include) +target_include_directories(${PROJECT_NAME} SYSTEM PRIVATE dependencies/assimp/include) target_link_libraries(${PROJECT_NAME} PRIVATE assimp) diff --git a/include/gfx_device.hpp b/include/gfx_device.hpp index b202817..262ea7b 100644 --- a/include/gfx_device.hpp +++ b/include/gfx_device.hpp @@ -30,7 +30,7 @@ namespace engine { gfx::Pipeline* createPipeline(const char* vertShaderPath, const char* fragShaderPath, const gfx::VertexFormat& vertexFormat, uint64_t uniformBufferSize, bool alphaBlending, bool backfaceCulling); void destroyPipeline(const gfx::Pipeline* pipeline); - void updateUniformBuffer(const gfx::Pipeline* pipeline, void* data, size_t size, uint32_t offset); + void updateUniformBuffer(const gfx::Pipeline* pipeline, const void* data, size_t size, uint32_t offset); gfx::Buffer* createBuffer(gfx::BufferType type, uint64_t size, const void* data); void destroyBuffer(const gfx::Buffer* buffer); diff --git a/include/resource_manager.hpp b/include/resource_manager.hpp index 769c650..66e8710 100644 --- a/include/resource_manager.hpp +++ b/include/resource_manager.hpp @@ -7,15 +7,15 @@ namespace engine { + class IResourceManager { + public: + virtual ~IResourceManager() = default; + }; + template - class ResourceManager { + class ResourceManager : public IResourceManager { public: - ResourceManager() {} - ~ResourceManager() {} - ResourceManager(const ResourceManager&) = delete; - ResourceManager& operator=(const ResourceManager&) = delete; - std::shared_ptr add(const std::string& name, std::unique_ptr&& resource) { if (m_resources.contains(name) == false) { @@ -34,8 +34,12 @@ namespace engine { std::weak_ptr ptr = m_resources.at(name); if (ptr.expired() == false) { return ptr.lock(); + } else { + m_resources.erase(name); } } + // resource doesn't exist: + throw std::runtime_error("Resource doesn't exist: " + name); return {}; } diff --git a/include/resources/mesh.hpp b/include/resources/mesh.hpp index 9a4258d..1f7a06c 100644 --- a/include/resources/mesh.hpp +++ b/include/resources/mesh.hpp @@ -29,11 +29,18 @@ public: m_vb = m_gfx->createBuffer(gfx::BufferType::VERTEX, vertices.size() * sizeof(Vertex), vertices.data()); std::vector indices(m_count); - for (int i = 0; i < m_count; i++) { + for (uint32_t i = 0; i < m_count; i++) { indices[i] = i; } m_ib = m_gfx->createBuffer(gfx::BufferType::INDEX, indices.size() * sizeof(uint32_t), indices.data()); } + Mesh(GFXDevice* gfx, const std::vector& vertices, const std::vector& indices) + : m_gfx(gfx) + { + m_count = vertices.size(); + m_vb = m_gfx->createBuffer(gfx::BufferType::VERTEX, vertices.size() * sizeof(Vertex), vertices.data()); + m_ib = m_gfx->createBuffer(gfx::BufferType::INDEX, indices.size() * sizeof(uint32_t), indices.data()); + } ~Mesh() { m_gfx->destroyBuffer(m_ib); diff --git a/include/scene.hpp b/include/scene.hpp index fad7175..59d1227 100644 --- a/include/scene.hpp +++ b/include/scene.hpp @@ -2,6 +2,7 @@ #include "log.hpp" +#include "resource_manager.hpp" #include "ecs_system.hpp" #include @@ -23,6 +24,34 @@ namespace engine { void update(float ts); + Application* app() { return m_app; } + + /* resource stuff */ + + template + void registerResourceManager() + { + size_t hash = typeid(T).hash_code(); + assert(m_resourceManagers.contains(hash) == false && "Registering resource manager type more than once."); + m_resourceManagers.emplace(hash, std::make_unique>()); + } + + template + std::shared_ptr addResource(const std::string& name, std::unique_ptr&& resource) + { + auto resourceManager = getResourceManager(); + return resourceManager->add(name, std::move(resource)); + } + + template + std::shared_ptr getResource(const std::string& name) + { + auto resourceManager = getResourceManager(); + return resourceManager->get(name); + } + + /* ecs stuff */ + uint32_t createEntity(const std::string& tag, uint32_t parent = 0); uint32_t getEntity(const std::string& tag, uint32_t parent = 0); @@ -97,12 +126,30 @@ namespace engine { return castedPtr; } - Application* app() { return m_app; } - private: Application* const m_app; uint32_t m_nextEntityID = 1000; + /* resource stuff */ + + std::map> m_resourceManagers{}; + + template + ResourceManager* getResourceManager() + { + size_t hash = typeid(T).hash_code(); + auto it = m_resourceManagers.find(hash); + if (it == m_resourceManagers.end()) { + throw std::runtime_error("Cannot find resource manager."); + } + auto ptr = it->second.get(); + auto castedPtr = dynamic_cast*>(ptr); + assert(castedPtr != nullptr); + return castedPtr; + } + + /* ecs stuff */ + size_t m_nextSignaturePosition = 0; // maps component hashes to signature positions std::map m_componentSignaturePositions{}; diff --git a/include/systems/render.hpp b/include/systems/render.hpp index e72a074..1ea9dae 100644 --- a/include/systems/render.hpp +++ b/include/systems/render.hpp @@ -12,13 +12,23 @@ namespace engine { class RenderSystem : public System { public: - RenderSystem(Scene* scene) - : System(scene, { typeid(TransformComponent).hash_code(), typeid(RenderableComponent).hash_code() }) - { - } + RenderSystem(Scene* scene); void onUpdate(float ts) override; + void setCameraEntity(uint32_t entity) { m_camera.camEntity = entity; } + + private: + struct { + // only uses transform component, which is required for all entities anyway + uint32_t camEntity = 0; + float horizontalFovDegrees = 70.0f; + float clipNear = 0.1f; + float clipFar = 1000.0f; + } m_camera; + + float m_viewportAspectRatio = 1.0f; + }; } diff --git a/include/systems/transform.hpp b/include/systems/transform.hpp index 5b02950..0fd83c4 100644 --- a/include/systems/transform.hpp +++ b/include/systems/transform.hpp @@ -1,65 +1,17 @@ #pragma once #include "ecs_system.hpp" -#include "components/transform.hpp" -#include "scene.hpp" -#include "log.hpp" - -#include -#include -#include - -#include -#include namespace engine { class TransformSystem : public System { public: - TransformSystem(Scene* scene) - : System(scene, { typeid(TransformComponent).hash_code() }) - { - } + TransformSystem(Scene* scene); - void onUpdate(float ts) override - { - for (uint32_t entity : m_entities) { + void onUpdate(float ts) override; - auto t = m_scene->getComponent(entity); - -// TRACE("tag is {}", t->tag); - - glm::mat4 transform; - - // rotation - transform = glm::mat4_cast(t->rotation); - // position - reinterpret_cast(transform[3]) = t->position; - // scale (effectively applied first) - transform = glm::scale(transform, t->scale); - - if (t->parent != 0) { - transform = m_scene->getComponent(t->parent)->worldMatrix * transform; - } - - t->worldMatrix = transform; - } - - } - - uint32_t getChildEntity(uint32_t parent, const std::string& tag) - { - for (uint32_t entity : m_entities) { - auto t = m_scene->getComponent(entity); - if (t->parent == parent) { - if (t->tag == tag) { - return entity; - } - } - } - return 0; - } + uint32_t getChildEntity(uint32_t parent, const std::string& tag); }; diff --git a/include/util/model_loader.hpp b/include/util/model_loader.hpp new file mode 100644 index 0000000..2656616 --- /dev/null +++ b/include/util/model_loader.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "scene.hpp" + +#include "resources/shader.hpp" + +#include + +namespace engine::util { + + uint32_t loadMeshFromFile(Scene* parent, const std::string& path); + +} diff --git a/include/window.hpp b/include/window.hpp index 0215f64..8505e3e 100644 --- a/include/window.hpp +++ b/include/window.hpp @@ -114,7 +114,7 @@ namespace engine { // returns the number of frames elapsed since window creation uint64_t getFrameCount() const; - uint64_t getStartTime() const;; + uint64_t getStartTime() const; float dt() const; // returns delta time in seconds uint64_t getFPS() const; uint64_t getAvgFPS() const; diff --git a/src/application.cpp b/src/application.cpp index e170e01..07f646c 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -73,6 +73,8 @@ namespace engine { auto beginFrame = std::chrono::steady_clock::now(); auto endFrame = beginFrame + FRAMETIME_LIMIT; + auto lastTick = m_window->getNanos(); + // single-threaded game loop while (m_window->isRunning()) { @@ -91,6 +93,12 @@ namespace engine { m_window->getInputAndEvents(); /* fps limiter */ + uint64_t now = m_window->getNanos(); + if (now - lastTick >= 1000000000LL * 10LL) { + lastTick = now; + m_window->setTitle(std::to_string(m_window->getAvgFPS())); + m_window->resetAvgFPS(); + } if (m_enableFrameLimiter) { std::this_thread::sleep_until(endFrame); } diff --git a/src/gfx_device_vulkan.cpp b/src/gfx_device_vulkan.cpp index 1c9a65d..3f1c4ef 100644 --- a/src/gfx_device_vulkan.cpp +++ b/src/gfx_device_vulkan.cpp @@ -155,8 +155,9 @@ namespace engine { return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; case gfx::BufferType::INDEX: return VK_BUFFER_USAGE_INDEX_BUFFER_BIT; + default: + throw std::runtime_error("This buffer type does not have usage bits"); } - throw std::runtime_error("Unknown buffer type"); } static VkFilter getTextureFilter(gfx::TextureFilter filter) @@ -222,7 +223,7 @@ namespace engine { static std::vector getRequiredVulkanExtensions(SDL_Window* window) { - SDL_bool res; + [[maybe_unused]] SDL_bool res; unsigned int sdlExtensionCount = 0; res = SDL_Vulkan_GetInstanceExtensions(window, &sdlExtensionCount, nullptr); @@ -239,7 +240,7 @@ namespace engine { constexpr const char* VALIDATION_LAYER_NAME = "VK_LAYER_KHRONOS_validation"; LayerInfo info; - VkResult res; + [[maybe_unused]] VkResult res; uint32_t layerCount; res = vkEnumerateInstanceLayerProperties(&layerCount, nullptr); @@ -269,6 +270,7 @@ namespace engine { const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData) { + (void)pUserData; std::string msgType{}; @@ -357,7 +359,7 @@ namespace engine { { uint32_t bitmask = static_cast(flags); - for (int i = 0; i < queues.size(); i++) { + for (size_t i = 0; i < queues.size(); i++) { if (bitmask & static_cast(QueueFlags::GRAPHICS)) { if (queues[i].supportsGraphics == false) continue; @@ -382,7 +384,7 @@ namespace engine { { Swapchain::MSTarget target{}; - VkResult res; + [[maybe_unused]] VkResult res; VkImageCreateInfo imageInfo{}; imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; @@ -408,7 +410,8 @@ namespace engine { res = vmaCreateImage(allocator, &imageInfo, &allocInfo, &target.colorImage, &target.colorImageAllocation, nullptr); assert(res == VK_SUCCESS); - VkImageViewCreateInfo imageViewInfo{ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; + VkImageViewCreateInfo imageViewInfo{}; + imageViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; imageViewInfo.image = target.colorImage; imageViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; imageViewInfo.format = colorFormat; @@ -433,7 +436,7 @@ namespace engine { { DepthBuffer db{}; - VkResult res; + [[maybe_unused]] VkResult res; VkImageCreateInfo imageInfo{}; imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; @@ -459,7 +462,8 @@ namespace engine { res = vmaCreateImage(allocator, &imageInfo, &allocInfo, &db.image, &db.allocation, nullptr); assert(res == VK_SUCCESS); - VkImageViewCreateInfo imageViewInfo{ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; + VkImageViewCreateInfo imageViewInfo{}; + imageViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; imageViewInfo.image = db.image; imageViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; imageViewInfo.format = VK_FORMAT_D32_SFLOAT; @@ -498,9 +502,9 @@ namespace engine { } // This is called not just on initialisation, but also when the window is resized. - static void createSwapchain(VkDevice device, VkPhysicalDevice physicalDevice, VmaAllocator allocator, std::vector queues, SDL_Window* window, VkSurfaceKHR surface, Swapchain* swapchain, bool vsync) + static void createSwapchain(VkDevice device, VkPhysicalDevice physicalDevice, VmaAllocator allocator, std::vector queues, SDL_Window* window, VkSurfaceKHR surface, bool vsync, Swapchain* swapchain) { - VkResult res; + [[maybe_unused]] VkResult res; // get surface capabilities VkSurfaceCapabilitiesKHR caps; @@ -576,7 +580,7 @@ namespace engine { } } } - + uint32_t imageCount = caps.minImageCount + 1; if (caps.maxImageCount > 0 && imageCount > caps.maxImageCount) { imageCount = caps.maxImageCount; @@ -723,7 +727,7 @@ namespace engine { swapchain->imageViews.resize(swapchain->images.size()); swapchain->framebuffers.resize(swapchain->images.size()); - for (int i = 0; i < swapchain->images.size(); i++) { + for (size_t i = 0; i < swapchain->images.size(); i++) { VkImageViewCreateInfo createInfo{}; createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; @@ -783,7 +787,7 @@ namespace engine { static void copyBuffer(VkDevice device, VkCommandPool commandPool, VkQueue queue, VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) { - VkResult res; + [[maybe_unused]] VkResult res; VkCommandBufferAllocateInfo allocInfo{}; allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; @@ -828,11 +832,12 @@ namespace engine { } - VkCommandBuffer beginOneTimeCommands(VkDevice device, VkCommandPool commandPool, VkQueue queue) + VkCommandBuffer beginOneTimeCommands(VkDevice device, VkCommandPool commandPool) { - VkResult res; + [[maybe_unused]] VkResult res; - VkCommandBufferAllocateInfo allocInfo{ VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO }; + VkCommandBufferAllocateInfo allocInfo{}; + allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; allocInfo.commandPool = commandPool; allocInfo.commandBufferCount = 1; @@ -841,7 +846,8 @@ namespace engine { res = vkAllocateCommandBuffers(device, &allocInfo, &commandBuffer); assert(res == VK_SUCCESS); - VkCommandBufferBeginInfo beginInfo{ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; + VkCommandBufferBeginInfo beginInfo{}; + beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; res = vkBeginCommandBuffer(commandBuffer, &beginInfo); @@ -852,11 +858,12 @@ namespace engine { static void endOneTimeCommands(VkDevice device, VkCommandPool commandPool, VkCommandBuffer commandBuffer, VkQueue queue) { - VkResult res; + [[maybe_unused]] VkResult res; res = vkEndCommandBuffer(commandBuffer); assert(res == VK_SUCCESS); - VkSubmitInfo submitInfo{ VK_STRUCTURE_TYPE_SUBMIT_INFO }; + VkSubmitInfo submitInfo{}; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = &commandBuffer; @@ -871,7 +878,8 @@ namespace engine { static void cmdTransitionImageLayout(VkCommandBuffer commandBuffer, VkImageLayout oldLayout, VkImageLayout newLayout, uint32_t mipLevels, VkImage image) { - VkImageMemoryBarrier barrier{ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER }; + VkImageMemoryBarrier barrier{}; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; barrier.oldLayout = oldLayout; barrier.newLayout = newLayout; barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; @@ -911,7 +919,8 @@ namespace engine { static void cmdGenerateMipmaps(VkCommandBuffer commandBuffer, VkImage image, int32_t width, int32_t height, uint32_t mipLevels) { - VkImageMemoryBarrier barrier{ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER }; + VkImageMemoryBarrier barrier{}; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; barrier.image = image; barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; @@ -1052,9 +1061,9 @@ namespace engine { // get the both the engine and application versions int appVersionMajor = 0, appVersionMinor = 0, appVersionPatch = 0; - assert(versionFromCharArray(appVersion, &appVersionMajor, &appVersionMinor, &appVersionPatch)); + versionFromCharArray(appVersion, &appVersionMajor, &appVersionMinor, &appVersionPatch); int engineVersionMajor = 0, engineVersionMinor = 0, engineVersionPatch = 0; - assert(versionFromCharArray(ENGINE_VERSION, &engineVersionMajor, &engineVersionMinor, &engineVersionPatch)); + versionFromCharArray(ENGINE_VERSION, &engineVersionMajor, &engineVersionMinor, &engineVersionPatch); VkApplicationInfo applicationInfo{ .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, @@ -1134,7 +1143,8 @@ namespace engine { { VkDebugUtilsMessengerCreateInfoEXT createInfo = getDebugMessengerCreateInfo(); - VkResult res = vkCreateDebugUtilsMessengerEXT(pimpl->instance, &createInfo, nullptr, &pimpl->debugMessenger); + [[maybe_unused]] VkResult res; + res = vkCreateDebugUtilsMessengerEXT(pimpl->instance, &createInfo, nullptr, &pimpl->debugMessenger); assert(res == VK_SUCCESS); } @@ -1311,8 +1321,8 @@ namespace engine { .flags = 0, .queueCreateInfoCount = (uint32_t)queueCreateInfos.size(), .pQueueCreateInfos = queueCreateInfos.data(), - // IGNORED: .enabledLayerCount - // IGNORED: .ppEnabledLayerNames + .enabledLayerCount = 0, + .ppEnabledLayerNames = nullptr, .enabledExtensionCount = (uint32_t)requiredDeviceExtensions.size(), .ppEnabledExtensionNames = requiredDeviceExtensions.data(), .pEnabledFeatures = &deviceFeatures, @@ -1335,8 +1345,9 @@ namespace engine { VkCommandPoolCreateInfo gfxCmdPoolInfo{ .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, + .pNext = nullptr, .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, - .queueFamilyIndex = pimpl->gfxQueue.familyIndex, + .queueFamilyIndex = pimpl->gfxQueue.familyIndex }; res = vkCreateCommandPool(pimpl->device, &gfxCmdPoolInfo, nullptr, &pimpl->commandPool); @@ -1344,12 +1355,13 @@ namespace engine { VkCommandBufferAllocateInfo gfxCmdBufInfo{ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, + .pNext = nullptr, .commandPool = pimpl->commandPool, .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, .commandBufferCount = 1 }; - for (int i = 0; i < FRAMES_IN_FLIGHT; i++) { + for (uint32_t i = 0; i < FRAMES_IN_FLIGHT; i++) { res = vkAllocateCommandBuffers(pimpl->device, &gfxCmdBufInfo, &pimpl->commandBuffers[i]); assert(res == VK_SUCCESS); } @@ -1402,14 +1414,15 @@ namespace engine { .pTypeExternalMemoryHandleTypes = nullptr }; - VkResult res = vmaCreateAllocator(&createInfo, &pimpl->allocator); + [[maybe_unused]] VkResult res; + res = vmaCreateAllocator(&createInfo, &pimpl->allocator); assert(res == VK_SUCCESS); } // Now make the swapchain - createSwapchain(pimpl->device, pimpl->physicalDevice, pimpl->allocator, pimpl->queues, window, pimpl->surface, &pimpl->swapchain, pimpl->vsync); + createSwapchain(pimpl->device, pimpl->physicalDevice, pimpl->allocator, pimpl->queues, window, pimpl->surface, pimpl->vsync, &pimpl->swapchain); @@ -1417,7 +1430,7 @@ namespace engine { fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; fenceInfo.pNext = nullptr; - for (int i = 0; i < FRAMES_IN_FLIGHT; i++) { + for (uint32_t i = 0; i < FRAMES_IN_FLIGHT; i++) { res = vkCreateFence(pimpl->device, &fenceInfo, nullptr, &pimpl->inFlightFences[i]); assert(res == VK_SUCCESS); } @@ -1429,7 +1442,8 @@ namespace engine { pimpl->uboLayoutBinding.stageFlags = VK_SHADER_STAGE_ALL_GRAPHICS; pimpl->uboLayoutBinding.pImmutableSamplers = nullptr; - VkDescriptorSetLayoutCreateInfo descriptorSetLayoutInfo{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO }; + VkDescriptorSetLayoutCreateInfo descriptorSetLayoutInfo{}; + descriptorSetLayoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; descriptorSetLayoutInfo.bindingCount = 1; descriptorSetLayoutInfo.pBindings = &pimpl->uboLayoutBinding; res = vkCreateDescriptorSetLayout(pimpl->device, &descriptorSetLayoutInfo, nullptr, &pimpl->descriptorSetLayout); @@ -1442,7 +1456,8 @@ namespace engine { pimpl->samplerLayoutBinding.pImmutableSamplers = nullptr; pimpl->samplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - VkDescriptorSetLayoutCreateInfo samplerSetLayoutInfo{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO }; + VkDescriptorSetLayoutCreateInfo samplerSetLayoutInfo{}; + samplerSetLayoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; samplerSetLayoutInfo.bindingCount = 1; samplerSetLayoutInfo.pBindings = &pimpl->samplerLayoutBinding; res = vkCreateDescriptorSetLayout(pimpl->device, &samplerSetLayoutInfo, nullptr, &pimpl->samplerSetLayout); @@ -1456,7 +1471,7 @@ namespace engine { vkDestroyDescriptorSetLayout(pimpl->device, pimpl->samplerSetLayout, nullptr); vkDestroyDescriptorSetLayout(pimpl->device, pimpl->descriptorSetLayout, nullptr); - for (int i = 0; i < FRAMES_IN_FLIGHT; i++) { + for (uint32_t i = 0; i < FRAMES_IN_FLIGHT; i++) { vkDestroyFence(pimpl->device, pimpl->inFlightFences[i], nullptr); vkDestroySemaphore(pimpl->device, pimpl->swapchain.releaseSemaphores[i], nullptr); vkDestroySemaphore(pimpl->device, pimpl->swapchain.acquireSemaphores[i], nullptr); @@ -1509,6 +1524,7 @@ namespace engine { .vertexBuffer = vertexBuffer, .indexBuffer = indexBuffer, // will be ignored if nullptr .count = count, + .pushConstantData{} }; memcpy(call.pushConstantData, pushConstantData, pushConstantSize); @@ -1535,7 +1551,7 @@ namespace engine { if (res == VK_ERROR_OUT_OF_DATE_KHR) { // recreate swapchain waitIdle(); - createSwapchain(pimpl->device, pimpl->physicalDevice, pimpl->allocator, pimpl->queues, pimpl->window, pimpl->surface, &pimpl->swapchain, &pimpl->vsync); + createSwapchain(pimpl->device, pimpl->physicalDevice, pimpl->allocator, pimpl->queues, pimpl->window, pimpl->surface, pimpl->vsync, &pimpl->swapchain); return; } else { @@ -1547,13 +1563,15 @@ namespace engine { // now record command buffer { - VkCommandBufferBeginInfo beginInfo{ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; + VkCommandBufferBeginInfo beginInfo{}; + beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; beginInfo.flags = 0; beginInfo.pInheritanceInfo = nullptr; res = vkBeginCommandBuffer(pimpl->commandBuffers[frameIndex], &beginInfo); assert(res == VK_SUCCESS); - VkRenderPassBeginInfo renderPassInfo{ VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO }; + VkRenderPassBeginInfo renderPassInfo{}; + renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; renderPassInfo.renderPass = pimpl->swapchain.renderpass; renderPassInfo.framebuffer = pimpl->swapchain.framebuffers[imageIndex]; renderPassInfo.renderArea.offset = { 0, 0 }; @@ -1636,7 +1654,8 @@ namespace engine { assert(res == VK_SUCCESS); } - VkSubmitInfo submitInfo{ VK_STRUCTURE_TYPE_SUBMIT_INFO }; + VkSubmitInfo submitInfo{}; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; submitInfo.waitSemaphoreCount = 1; @@ -1650,7 +1669,8 @@ namespace engine { res = vkQueueSubmit(pimpl->gfxQueue.handle, 1, &submitInfo, pimpl->inFlightFences[frameIndex]); assert(res == VK_SUCCESS); - VkPresentInfoKHR presentInfo{ VK_STRUCTURE_TYPE_PRESENT_INFO_KHR }; + VkPresentInfoKHR presentInfo{}; + presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; presentInfo.waitSemaphoreCount = 1; presentInfo.pWaitSemaphores = &pimpl->swapchain.releaseSemaphores[frameIndex]; @@ -1664,7 +1684,7 @@ namespace engine { if (res == VK_SUBOPTIMAL_KHR || res == VK_ERROR_OUT_OF_DATE_KHR) { // recreate swapchain waitIdle(); - createSwapchain(pimpl->device, pimpl->physicalDevice, pimpl->allocator, pimpl->queues, pimpl->window, pimpl->surface, &pimpl->swapchain, &pimpl->vsync); + createSwapchain(pimpl->device, pimpl->physicalDevice, pimpl->allocator, pimpl->queues, pimpl->window, pimpl->surface, pimpl->vsync, &pimpl->swapchain); } else { assert(res == VK_SUCCESS); @@ -1676,7 +1696,7 @@ namespace engine { gfx::Pipeline* GFXDevice::createPipeline(const char* vertShaderPath, const char* fragShaderPath, const gfx::VertexFormat& vertexFormat, uint64_t uniformBufferSize, bool alphaBlending, bool backfaceCulling) { - VkResult res; + [[maybe_unused]] VkResult res; gfx::Pipeline* pipeline = new gfx::Pipeline; @@ -1689,12 +1709,13 @@ namespace engine { // create uniform buffers pipeline->uniformBuffers.resize(FRAMES_IN_FLIGHT); - for (int i = 0; i < FRAMES_IN_FLIGHT; i++) { + for (uint32_t i = 0; i < FRAMES_IN_FLIGHT; i++) { auto buf = new gfx::Buffer{}; buf->size = uniformBufferSize; buf->type = gfx::BufferType::UNIFORM; - VkBufferCreateInfo bufferInfo{ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; + VkBufferCreateInfo bufferInfo{}; + bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; bufferInfo.size = buf->size; bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; @@ -1734,7 +1755,7 @@ namespace engine { res = vkAllocateDescriptorSets(pimpl->device, &dSetAllocInfo, pipeline->descriptorSets.data()); assert(res == VK_SUCCESS); - for (int i = 0; i < FRAMES_IN_FLIGHT; i++) { + for (uint32_t i = 0; i < FRAMES_IN_FLIGHT; i++) { VkDescriptorBufferInfo bufferInfo{}; bufferInfo.buffer = pipeline->uniformBuffers[i]->buffer; bufferInfo.offset = 0; @@ -1771,13 +1792,15 @@ namespace engine { attribDescs.push_back(vulkanAttribDesc); } - VkPipelineShaderStageCreateInfo vertShaderStageInfo{ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO }; + VkPipelineShaderStageCreateInfo vertShaderStageInfo{}; + vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT; vertShaderStageInfo.module = vertShaderModule; vertShaderStageInfo.pName = "main"; vertShaderStageInfo.pSpecializationInfo = nullptr; - VkPipelineShaderStageCreateInfo fragShaderStageInfo{ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO }; + VkPipelineShaderStageCreateInfo fragShaderStageInfo{}; + fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT; fragShaderStageInfo.module = fragShaderModule; fragShaderStageInfo.pName = "main"; @@ -1949,21 +1972,21 @@ namespace engine { vkDestroyDescriptorPool(pimpl->device, pipeline->descriptorPool, nullptr); - for (int i = 0; i < FRAMES_IN_FLIGHT; i++) { + for (uint32_t i = 0; i < FRAMES_IN_FLIGHT; i++) { destroyBuffer(pipeline->uniformBuffers[i]); } delete pipeline; } - void GFXDevice::updateUniformBuffer(const gfx::Pipeline* pipeline, void* data, size_t size, uint32_t offset) + void GFXDevice::updateUniformBuffer(const gfx::Pipeline* pipeline, const void* data, size_t size, uint32_t offset) { assert(size <= pipeline->uniformBuffers[0]->size); - VkResult res; + [[maybe_unused]] VkResult res; for (gfx::Buffer* buffer : pipeline->uniformBuffers) { - void* uniformDest; + void* uniformDest = nullptr; res = vmaMapMemory(pimpl->allocator, buffer->allocation, &uniformDest); assert(res == VK_SUCCESS); memcpy((uint8_t*)uniformDest + offset, data, size); @@ -1974,7 +1997,7 @@ namespace engine { gfx::Buffer* GFXDevice::createBuffer(gfx::BufferType type, uint64_t size, const void* data) { - VkResult res; + [[maybe_unused]] VkResult res; auto out = new gfx::Buffer{}; out->size = size; @@ -1986,7 +2009,8 @@ namespace engine { // first create the staging buffer { - VkBufferCreateInfo stagingBufferInfo{ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; + VkBufferCreateInfo stagingBufferInfo{}; + stagingBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; stagingBufferInfo.size = out->size; stagingBufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; stagingBufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; @@ -2009,7 +2033,8 @@ namespace engine { // create the actual buffer on the GPU { - VkBufferCreateInfo gpuBufferInfo{ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; + VkBufferCreateInfo gpuBufferInfo{}; + gpuBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; gpuBufferInfo.size = out->size; gpuBufferInfo.usage = vkinternal::getBufferUsageFlag(type) | VK_BUFFER_USAGE_TRANSFER_DST_BIT; gpuBufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; @@ -2042,7 +2067,7 @@ namespace engine { { auto out = new gfx::Texture; - VkResult res; + [[maybe_unused]] VkResult res; size_t imageSize = w * h * 4; @@ -2052,7 +2077,8 @@ namespace engine { VkBuffer stagingBuffer; VmaAllocation stagingAllocation; { - VkBufferCreateInfo stagingBufferInfo{ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; + VkBufferCreateInfo stagingBufferInfo{}; + stagingBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; stagingBufferInfo.size = imageSize; stagingBufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; stagingBufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; @@ -2074,7 +2100,8 @@ namespace engine { } // create the image - VkImageCreateInfo imageInfo{ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; + VkImageCreateInfo imageInfo{}; + imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; imageInfo.imageType = VK_IMAGE_TYPE_2D; imageInfo.extent.width = w; imageInfo.extent.height = h; @@ -2097,7 +2124,7 @@ namespace engine { // transition the image layout { - VkCommandBuffer commandBuffer = beginOneTimeCommands(pimpl->device, pimpl->commandPool, pimpl->gfxQueue.handle); + VkCommandBuffer commandBuffer = beginOneTimeCommands(pimpl->device, pimpl->commandPool); // begin cmd buffer @@ -2130,7 +2157,8 @@ namespace engine { vmaDestroyBuffer(pimpl->allocator, stagingBuffer, stagingAllocation); // create image view - VkImageViewCreateInfo imageViewInfo{ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; + VkImageViewCreateInfo imageViewInfo{}; + imageViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; imageViewInfo.image = out->image; imageViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; imageViewInfo.format = VK_FORMAT_R8G8B8A8_SRGB; @@ -2151,7 +2179,8 @@ namespace engine { VkFilter magFilterInternal = vkinternal::getTextureFilter(magFilter); VkFilter minFilterInternal = vkinternal::getTextureFilter(minFilter); - VkSamplerCreateInfo samplerInfo{ VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO }; + VkSamplerCreateInfo samplerInfo{}; + samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; samplerInfo.magFilter = magFilterInternal; samplerInfo.minFilter = minFilterInternal; samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; @@ -2201,7 +2230,7 @@ namespace engine { res = vkAllocateDescriptorSets(pimpl->device, &dSetAllocInfo, out->descriptorSets.data()); assert(res == VK_SUCCESS); - for (int i = 0; i < FRAMES_IN_FLIGHT; i++) { + for (uint32_t i = 0; i < FRAMES_IN_FLIGHT; i++) { VkDescriptorImageInfo imageInfo{}; imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; imageInfo.imageView = out->imageView; diff --git a/src/scene_manager.cpp b/src/scene_manager.cpp index 3670aef..788039d 100644 --- a/src/scene_manager.cpp +++ b/src/scene_manager.cpp @@ -25,7 +25,7 @@ namespace engine { void SceneManager::updateActiveScene(float ts) { if (m_activeSceneIndex >= 0) { - assert(m_activeSceneIndex < m_scenes.size()); + assert((size_t)m_activeSceneIndex < m_scenes.size()); m_scenes[m_activeSceneIndex]->update(ts); } } diff --git a/src/systems/render.cpp b/src/systems/render.cpp index 7df3b48..eb36e03 100644 --- a/src/systems/render.cpp +++ b/src/systems/render.cpp @@ -1,6 +1,7 @@ #include "systems/render.hpp" #include "application.hpp" +#include "window.hpp" #include "gfx_device.hpp" #include "resources/material.hpp" @@ -13,27 +14,43 @@ namespace engine { + RenderSystem::RenderSystem(Scene* scene) + : System(scene, { typeid(TransformComponent).hash_code(), typeid(RenderableComponent).hash_code() }) + { + + } + void RenderSystem::onUpdate(float ts) { + (void)ts; + GFXDevice* const gfx = m_scene->app()->gfx(); - constexpr float FOV_H = 75.0f; - constexpr float CLIP_NEAR = 0.1f; - constexpr float CLIP_FAR = 100.0f; + /* camera stuff */ - uint32_t w, h; - gfx->getViewportSize(&w, &h); - float aspect = w / h; - float verticalFOV = FOV_H / aspect; - glm::mat4 projMatrix = glm::perspectiveZO(verticalFOV, aspect, CLIP_NEAR, CLIP_FAR); + const auto cameraTransform = m_scene->getComponent(m_camera.camEntity); + + // do not render if camera is not set + if (cameraTransform == nullptr) return; + + glm::mat4 viewMatrix = glm::inverse(cameraTransform->worldMatrix); + + if (m_scene->app()->window()->getWindowResized()) { + uint32_t w, h; + gfx->getViewportSize(&w, &h); + m_viewportAspectRatio = (float)w / (float)h; + } + const float horizontalFovRadians = glm::radians(m_camera.horizontalFovDegrees); + const float verticalFov = glm::atan( glm::tan(horizontalFovRadians / 2.0f) / m_viewportAspectRatio ) * 2.0f; + const glm::mat4 projMatrix = glm::perspectiveZO(verticalFov, m_viewportAspectRatio, m_camera.clipNear, m_camera.clipFar); + + /* render all renderable entities */ for (uint32_t entity : m_entities) { auto t = m_scene->getComponent(entity); auto r = m_scene->getComponent(entity); -// TRACE("rendering {}", t->tag); - gfx->updateUniformBuffer(r->material->getShader()->getPipeline(), &projMatrix, sizeof(projMatrix), 0); struct { @@ -42,7 +59,7 @@ namespace engine { } pushConsts{}; pushConsts.model = t->worldMatrix; - pushConsts.view = glm::mat4{ 1.0f }; + pushConsts.view = viewMatrix; gfx->draw( r->material->getShader()->getPipeline(), @@ -53,6 +70,7 @@ namespace engine { sizeof(pushConsts), r->material->m_texture->getHandle() ); + } } diff --git a/src/systems/transform.cpp b/src/systems/transform.cpp new file mode 100644 index 0000000..a8b727e --- /dev/null +++ b/src/systems/transform.cpp @@ -0,0 +1,56 @@ +#include "systems/transform.hpp" + +#include "scene.hpp" +#include "components/transform.hpp" + +#include + +namespace engine { + + TransformSystem::TransformSystem(Scene* scene) + : System(scene, { typeid(TransformComponent).hash_code() }) + { + } + + void TransformSystem::onUpdate(float ts) + { + (void)ts; + + for (uint32_t entity : m_entities) { + + auto t = m_scene->getComponent(entity); + + glm::mat4 transform; + + // rotation + transform = glm::mat4_cast(t->rotation); + // position + reinterpret_cast(transform[3]) = t->position; + // scale (effectively applied first) + transform = glm::scale(transform, t->scale); + + if (t->parent != 0) { + transform = m_scene->getComponent(t->parent)->worldMatrix * transform; + } + + t->worldMatrix = transform; + } + } + + uint32_t TransformSystem::getChildEntity(uint32_t parent, const std::string& tag) + { + for (uint32_t entity : m_entities) { + auto t = m_scene->getComponent(entity); + if (t->parent == parent) { + if (t->tag == tag) { + return entity; + } + } + } + return 0; + } + + + +} + diff --git a/src/util/model_loader.cpp b/src/util/model_loader.cpp new file mode 100644 index 0000000..804f3f7 --- /dev/null +++ b/src/util/model_loader.cpp @@ -0,0 +1,235 @@ +#include "util/model_loader.hpp" + +#include "log.hpp" + +#include "application.hpp" + +#include "components/transform.hpp" +#include "components/renderable.hpp" + +#include "resources/texture.hpp" +#include "resources/material.hpp" +#include "resources/shader.hpp" +#include "resources/mesh.hpp" + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +namespace engine::util { + + static void buildGraph( + const std::map>& textures, + const std::vector>& meshes, + const std::vector& meshTextureIndices, + aiNode* parentNode, Scene* scene, uint32_t parentObj) + { + + // convert to glm column major + glm::mat4 transform; + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + transform[i][j] = parentNode->mTransformation[j][i]; + } + } + + // get position + glm::vec3 position{ transform[3][0], transform[3][1], transform[3][2] }; + + // remove position from matrix + transform[3][0] = 0.0f; + transform[3][1] = 0.0f; + transform[3][2] = 0.0f; + + // get scale + glm::vec3 scale{}; + scale.x = sqrt(transform[0][0] * transform[0][0] + transform[0][1] * transform[0][1] + transform[0][2] * transform[0][2]); + scale.y = sqrt(transform[1][0] * transform[1][0] + transform[1][1] * transform[1][1] + transform[1][2] * transform[1][2]); + scale.z = sqrt(transform[2][0] * transform[2][0] + transform[2][1] * transform[2][1] + transform[2][2] * transform[2][2]); + + // remove scaling from matrix + for (int row = 0; row < 3; row++) { + transform[0][row] /= scale.x; + transform[1][row] /= scale.y; + transform[2][row] /= scale.z; + } + + // get rotation + glm::quat rotation = glm::quat_cast(transform); + + // update position, scale, rotation + auto parentTransform = scene->getComponent(parentObj); + parentTransform->position = position; + parentTransform->scale = scale; + parentTransform->rotation = rotation; + + for (uint32_t i = 0; i < parentNode->mNumMeshes; i++) { + // create child node for each mesh + auto child = scene->createEntity("_mesh" + std::to_string(i), parentObj); + auto childRenderer = scene->addComponent(child); + childRenderer->mesh = meshes[parentNode->mMeshes[i]]; + childRenderer->material = std::make_shared(scene->getResource("theShader")); + if (textures.contains(meshTextureIndices[parentNode->mMeshes[i]])) { + childRenderer->material->m_texture = textures.at(meshTextureIndices[parentNode->mMeshes[i]]); + } else { + childRenderer->material->m_texture = scene->getResource("whiteTexture"); + } + } + + for (uint32_t i = 0; i < parentNode->mNumChildren; i++) { + buildGraph( + textures, + meshes, + meshTextureIndices, + parentNode->mChildren[i], + scene, + scene->createEntity("child" + std::to_string(i), parentObj) + ); + } + } + + uint32_t loadMeshFromFile(Scene* parent, const std::string& path) + { + Assimp::Importer importer; + + class myStream : public Assimp::LogStream { + public: + void write(const char* message) override { + (void)message; + DEBUG("ASSIMP: {}", message); + } + }; + + const unsigned int severity = Assimp::Logger::Debugging | Assimp::Logger::Info | Assimp::Logger::Err | Assimp::Logger::Warn; + Assimp::DefaultLogger::get()->attachStream(new myStream, severity); + + // remove everything but texcoords, normals, meshes, materials + importer.SetPropertyInteger(AI_CONFIG_PP_RVC_FLAGS, + aiComponent_ANIMATIONS | + aiComponent_BONEWEIGHTS | + aiComponent_CAMERAS | + aiComponent_COLORS | + aiComponent_LIGHTS | + aiComponent_TANGENTS_AND_BITANGENTS | + aiComponent_TEXTURES | + 0 + ); + importer.SetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE, + aiPrimitiveType_POINT | + aiPrimitiveType_LINE | + aiPrimitiveType_POLYGON + ); + + const aiScene* scene = importer.ReadFile(path, + aiProcess_JoinIdenticalVertices | + aiProcess_Triangulate | + aiProcess_SortByPType | + aiProcess_RemoveComponent | + aiProcess_SplitLargeMeshes | // leave at default maximum + aiProcess_ValidateDataStructure | // make sure to log the output + aiProcess_ImproveCacheLocality | + aiProcess_RemoveRedundantMaterials | + aiProcess_FindInvalidData | + aiProcess_GenSmoothNormals | + aiProcess_GenUVCoords | + aiProcess_TransformUVCoords | + aiProcess_FlipUVs | // Maybe? + 0 + ); + + const char* errString = importer.GetErrorString(); + if (errString[0] != '\0' || scene == nullptr) { + throw std::runtime_error(errString); + } + + if (scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE) { + throw std::runtime_error(errString); + } + + assert(scene->HasAnimations() == false); + assert(scene->HasCameras() == false); + assert(scene->HasLights() == false); + assert(scene->hasSkeletons() == false); + + INFO("material count: {}, mesh count: {}", scene->mNumMaterials, scene->mNumMeshes); + + std::map> textures{}; + + for (uint32_t i = 0; i < scene->mNumMaterials; i++) { + const aiMaterial* m = scene->mMaterials[i]; + INFO("Material {}:", i); + INFO(" Name: {}", m->GetName().C_Str()); + for (uint32_t j = 0; j < m->mNumProperties; j++) { + const aiMaterialProperty* p = m->mProperties[j]; + INFO(" prop {}, key: {}", j, p->mKey.C_Str()); + } + + if (aiGetMaterialTextureCount(m, aiTextureType_DIFFUSE) >= 1) { + aiString texPath{}; + aiGetMaterialTexture(m, aiTextureType_DIFFUSE, 0, &texPath); + INFO(" Diffuse tex: {}", texPath.C_Str()); + std::filesystem::path absPath = path; + absPath = absPath.parent_path(); + absPath /= texPath.C_Str(); + try { + textures[i] = std::make_shared(parent->app()->gfx(), absPath); + } catch (const std::runtime_error& e) { + textures[i] = parent->getResource("textures/white.png"); + } + } + } + + std::vector> meshes{}; + std::vector meshMaterialIndices{}; + for (uint32_t i = 0; i < scene->mNumMeshes; i++) { + const aiMesh* m = scene->mMeshes[i]; + meshMaterialIndices.push_back(m->mMaterialIndex); + std::vector vertices(m->mNumVertices); + std::vector indices(m->mNumFaces * 3); + INFO("Mesh {}: vertex count {}", i, vertices.size()); + INFO("Mesh {}: index count {}", i, indices.size()); + + for (uint32_t j = 0; j < vertices.size(); j++) { + Vertex v{}; + v.pos.x = m->mVertices[j].x; + v.pos.y = m->mVertices[j].y; + v.pos.z = m->mVertices[j].z; + v.norm.x = m->mNormals[j].x; + v.norm.y = m->mNormals[j].y; + v.norm.z = m->mNormals[j].z; + vertices[j] = v; + } + if (m->mNumUVComponents[0] >= 2) { + for (uint32_t j = 0; j < vertices.size(); j++) { + vertices[j].uv.x = m->mTextureCoords[0][j].x; + vertices[j].uv.y = m->mTextureCoords[0][j].y; + + } + } + + for (uint32_t j = 0; j < indices.size() / 3; j++) { + indices[j * 3 + 0] = m->mFaces[j].mIndices[0]; + indices[j * 3 + 1] = m->mFaces[j].mIndices[1]; + indices[j * 3 + 2] = m->mFaces[j].mIndices[2]; + } + meshes.push_back(std::make_shared(parent->app()->gfx(), vertices, indices)); + } + + uint32_t obj = parent->createEntity(scene->GetShortFilename(path.c_str())); + + buildGraph(textures, meshes, meshMaterialIndices, scene->mRootNode, parent, obj); + + Assimp::DefaultLogger::kill(); + return obj; + } + +} diff --git a/src/window.cpp b/src/window.cpp index 3202e1f..0e275ca 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -53,17 +53,15 @@ namespace engine { throw std::runtime_error("Unable to create window: " + std::string(SDL_GetError())); } - // get window size - int winWidth, winHeight; - SDL_GetWindowSize(m_handle, &winWidth, &winHeight); - m_winSize.x = winWidth; - m_winSize.y = winHeight; - const int WINDOWED_MIN_WIDTH = 640; const int WINDOWED_MIN_HEIGHT = 480; SDL_SetWindowMinimumSize(m_handle, WINDOWED_MIN_WIDTH, WINDOWED_MIN_HEIGHT); - // onResize(m_winSize.x, m_winSize.y); + // get window size + int winWidth, winHeight; + SDL_GetWindowSize(m_handle, &winWidth, &winHeight); + + onResize(winWidth, winHeight); } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ac33403..602a0e5 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -11,6 +11,8 @@ set(GAME_SOURCES src/main.cpp src/game.cpp src/game.hpp + src/camera_controller.cpp + src/camera_controller.hpp ) @@ -29,6 +31,9 @@ set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD_REQUIRED ON) if (MSVC) target_compile_options(${PROJECT_NAME} PRIVATE /W3) target_compile_options(${PROJECT_NAME} PRIVATE /MP) + target_compile_definitions(${PROJECT_NAME} PRIVATE _CRT_SECURE_NO_WARNINGS) +else() + target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -Werror -pedantic) endif() target_include_directories(${PROJECT_NAME} PRIVATE src) @@ -49,4 +54,4 @@ get_target_property(ENGINE_SOURCE_DIR engine SOURCE_DIR) add_custom_command( TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E create_symlink - ${ENGINE_SOURCE_DIR}/res/engine $/res/engine) \ No newline at end of file + ${ENGINE_SOURCE_DIR}/res/engine $/res/engine) diff --git a/test/src/camera_controller.cpp b/test/src/camera_controller.cpp index bc4ab06..f3e2d39 100644 --- a/test/src/camera_controller.cpp +++ b/test/src/camera_controller.cpp @@ -1,9 +1,11 @@ #include "camera_controller.hpp" -#include "object.hpp" - +#include "application.hpp" #include "window.hpp" -#include "input.hpp" +#include "input_manager.hpp" +#include "scene.hpp" + +#include "components/transform.hpp" #include #include @@ -12,91 +14,99 @@ #include -CameraController::CameraController(engine::Object* parent) : - CustomComponent(parent) +CameraControllerSystem::CameraControllerSystem(engine::Scene* scene) + : System(scene, { typeid(engine::TransformComponent).hash_code(), typeid(CameraControllerComponent).hash_code() }) { - standingHeight = parent->transform.position.y; - m_yaw = glm::half_pi(); } -void CameraController::onUpdate(glm::mat4 t) +void CameraControllerSystem::onUpdate(float ts) { + engine::TransformComponent* t = nullptr; + CameraControllerComponent* c = nullptr; + for (uint32_t entity : m_entities) { + t = m_scene->getComponent(entity); + c = m_scene->getComponent(entity); + break; + } + if (t == nullptr) return; + if (c == nullptr) return; + // calculate new position // use one unit per meter - const float dt = win.dt(); + const float dt = ts; // jumping constexpr float G = 9.8f; - constexpr float JUMPHEIGHT = 16.0f * 25.4f / 1000.0f; // 16 inches +// constexpr float JUMPHEIGHT = 16.0f * 25.4f / 1000.0f; // 16 inches constexpr float JUMPVEL = (float)2.82231110971133017648; //std::sqrt(2 * G * JUMPHEIGHT); //constexpr float JUMPDURATION = 0.5f; //constexpr float JUMPVEL = G * JUMPDURATION / 2.0f; - if (inp.getButton("jump") && isJumping == false) { - isJumping = true; - dy = JUMPVEL; + if (m_scene->app()->inputManager()->getButton("jump") && c->isJumping == false) { + c->isJumping = true; + c->dy = JUMPVEL; //standingHeight = tcomp->position.y; } - if (isJumping) { - dy -= G * dt; - parent.transform.position.y += dy * dt; - if (parent.transform.position.y < standingHeight) { - isJumping = false; - dy = 0.0f; - parent.transform.position.y = standingHeight; + if (c->isJumping) { + c->dy -= G * dt; + t->position.y += c->dy * dt; + if (t->position.y < c->standingHeight) { + c->isJumping = false; + c->dy = 0.0f; + t->position.y = c->standingHeight; } } - if (win.getButton(engine::inputs::MouseButton::M_LEFT)) { + if (m_scene->app()->window()->getButton(engine::inputs::MouseButton::M_LEFT)) { //standingHeight = tcomp->position.y; - dy += dt * thrust; - isJumping = true; + c->dy += dt * c->thrust; + c->isJumping = true; } // in metres per second //constexpr float SPEED = 1.5f; - float SPEED = walk_speed; - if (win.getKey(engine::inputs::Key::LSHIFT)) SPEED *= 10.0f; + float SPEED = c->walk_speed; + if (m_scene->app()->inputManager()->getButton("sprint")) SPEED *= 10.0f; - const float dx = inp.getAxis("movex") * SPEED; - const float dz = (-inp.getAxis("movey")) * SPEED; + const float dx = m_scene->app()->inputManager()->getAxis("movex") * SPEED; + const float dz = (-m_scene->app()->inputManager()->getAxis("movey")) * SPEED; // calculate new pitch and yaw constexpr float MAX_PITCH = glm::half_pi(); constexpr float MIN_PITCH = -MAX_PITCH; - float dPitch = inp.getAxis("looky") * -1.0f * m_cameraSensitivity; - m_pitch += dPitch; - if (m_pitch <= MIN_PITCH || m_pitch >= MAX_PITCH) { - m_pitch -= dPitch; + float dPitch = m_scene->app()->inputManager()->getAxis("looky") * -1.0f * c->m_cameraSensitivity; + c->m_pitch += dPitch; + if (c->m_pitch <= MIN_PITCH || c->m_pitch >= MAX_PITCH) { + c->m_pitch -= dPitch; } - m_yaw += inp.getAxis("lookx") * -1.0f * m_cameraSensitivity; + c->m_yaw += m_scene->app()->inputManager()->getAxis("lookx") * -1.0f * c->m_cameraSensitivity; // update position relative to camera direction in xz plane - const glm::vec3 d2xRotated = glm::rotateY(glm::vec3{ dx, 0.0f, 0.0f }, m_yaw); - const glm::vec3 d2zRotated = glm::rotateY(glm::vec3{ 0.0f, 0.0f, dz }, m_yaw); - parent.transform.position += (d2xRotated + d2zRotated) * dt; - parent.transform.position.y += dy * dt; + const glm::vec3 d2xRotated = glm::rotateY(glm::vec3{ dx, 0.0f, 0.0f }, c->m_yaw); + const glm::vec3 d2zRotated = glm::rotateY(glm::vec3{ 0.0f, 0.0f, dz }, c->m_yaw); + t->position += (d2xRotated + d2zRotated) * dt; + t->position.y += c->dy * dt; constexpr float MAX_DISTANCE_FROM_ORIGIN = 1000.0f; - if (glm::length(parent.transform.position) > MAX_DISTANCE_FROM_ORIGIN) { - parent.transform.position = { 0.0f, standingHeight, 0.0f }; - dy = 0.0f; - isJumping = false; + if (glm::length(t->position) > MAX_DISTANCE_FROM_ORIGIN) { + t->position = { 0.0f, c->standingHeight, 0.0f }; + c->dy = 0.0f; + c->isJumping = false; } /* ROTATION STUFF */ // pitch quaternion - const float halfPitch = m_pitch / 2.0f; + const float halfPitch = c->m_pitch / 2.0f; glm::quat pitchQuat{}; pitchQuat.x = glm::sin(halfPitch); pitchQuat.y = 0.0f; @@ -104,7 +114,7 @@ void CameraController::onUpdate(glm::mat4 t) pitchQuat.w = glm::cos(halfPitch); // yaw quaternion - const float halfYaw = m_yaw / 2.0f; + const float halfYaw = c->m_yaw / 2.0f; glm::quat yawQuat{}; yawQuat.x = 0.0f; yawQuat.y = glm::sin(halfYaw); @@ -112,18 +122,24 @@ void CameraController::onUpdate(glm::mat4 t) yawQuat.w = glm::cos(halfYaw); // update rotation - parent.transform.rotation = yawQuat * pitchQuat; + t->rotation = yawQuat * pitchQuat; - if (win.getKeyPress(engine::inputs::Key::P)) { + + + /* user interface inputs */ + + if (m_scene->app()->window()->getKeyPress(engine::inputs::Key::K_P)) { std::string pos_string{ - "x: " + std::to_string(parent.transform.position.x) + - " y: " + std::to_string(parent.transform.position.y) + - " z: " + std::to_string(parent.transform.position.z) + "x: " + std::to_string(t->position.x) + + " y: " + std::to_string(t->position.y) + + " z: " + std::to_string(t->position.z) }; -#ifdef NDEBUG - win.infoBox("POSITION", pos_string); -#endif + m_scene->app()->window()->infoBox("POSITION", pos_string); INFO("position: " + pos_string); } + if (m_scene->app()->inputManager()->getButtonPress("fullscreen")) { + m_scene->app()->window()->toggleFullscreen(); + } + } diff --git a/test/src/camera_controller.hpp b/test/src/camera_controller.hpp index 066fa9d..23c591c 100644 --- a/test/src/camera_controller.hpp +++ b/test/src/camera_controller.hpp @@ -1,16 +1,10 @@ #pragma once -#include "components/custom.hpp" - -class CameraController : public engine::components::CustomComponent { - -public: - CameraController(engine::Object* parent); - void onUpdate(glm::mat4 t) override; +#include "ecs_system.hpp" +struct CameraControllerComponent { float m_cameraSensitivity = 0.007f; -private: float m_yaw = 0.0f; float m_pitch = 0.0f; @@ -20,5 +14,12 @@ private: float dy = 0.0f; float standingHeight = 0.0f; const float thrust = 25.0f; - +}; + +class CameraControllerSystem : public engine::System { + +public: + CameraControllerSystem(engine::Scene* scene); + + void onUpdate(float ts) override; }; diff --git a/test/src/game.cpp b/test/src/game.cpp index 12c25b8..663b178 100644 --- a/test/src/game.cpp +++ b/test/src/game.cpp @@ -1,7 +1,10 @@ #include "config.h" +#include "camera_controller.hpp" + #include "application.hpp" #include "window.hpp" +#include "input_manager.hpp" #include "scene_manager.hpp" #include "scene.hpp" @@ -9,69 +12,105 @@ #include "components/renderable.hpp" #include "systems/transform.hpp" +#include "systems/render.hpp" #include "resources/mesh.hpp" #include "resources/material.hpp" #include "resources/shader.hpp" #include "resources/texture.hpp" +#include "util/model_loader.hpp" + +struct RotateComponent { + float rotation = 0.0f; +}; + +class RotateSystem : public engine::System { +public: + RotateSystem(engine::Scene* scene) + : System(scene, { typeid(engine::TransformComponent).hash_code(), typeid(RotateComponent).hash_code() }) + { + } + + void onUpdate(float ts) override + { + for (uint32_t entity : m_entities) { + auto t = m_scene->getComponent(entity); + auto r = m_scene->getComponent(entity); + r->rotation += ts; + r->rotation = glm::mod(r->rotation, glm::two_pi()); + t->rotation = glm::angleAxis(r->rotation, glm::vec3{0.0f, 0.0f, 1.0f}); + } + } +}; + + + void playGame() { engine::Application app(PROJECT_NAME, PROJECT_VERSION); + app.setFrameLimiter(false); + // configure window app.window()->setRelativeMouseMode(true); + + + // input config + + // user interface mappings + app.inputManager()->addInputButton("fullscreen", engine::inputs::Key::K_F11); + // game buttons + app.inputManager()->addInputButton("fire", engine::inputs::MouseButton::M_LEFT); + app.inputManager()->addInputButton("aim", engine::inputs::MouseButton::M_RIGHT); + app.inputManager()->addInputButton("jump", engine::inputs::Key::K_SPACE); + app.inputManager()->addInputButton("sprint", engine::inputs::Key::K_LSHIFT); + // game movement + app.inputManager()->addInputButtonAsAxis("movex", engine::inputs::Key::K_D, engine::inputs::Key::K_A); + app.inputManager()->addInputButtonAsAxis("movey", engine::inputs::Key::K_W, engine::inputs::Key::K_S); + // looking around + app.inputManager()->addInputAxis("lookx", engine::inputs::MouseAxis::X); + app.inputManager()->addInputAxis("looky", engine::inputs::MouseAxis::Y); + + + auto myScene = app.sceneManager()->createEmptyScene(); - std::shared_ptr myMaterial; - { - engine::resources::Shader::VertexParams vertParams{}; - vertParams.hasNormal = true; - vertParams.hasUV0 = true; - auto myShader = std::make_unique( - app.gfx(), - app.getResourcePath("engine/shaders/texture.vert").c_str(), - app.getResourcePath("engine/shaders/texture.frag").c_str(), - vertParams, - false, - true - ); - myMaterial = std::make_shared(std::move(myShader)); - myMaterial->m_texture = std::make_shared( - app.gfx(), - app.getResourcePath("engine/textures/white.png") - ); - } + myScene->registerComponent(); + myScene->registerComponent(); - auto myMesh = std::make_shared( + myScene->registerSystem(); + myScene->registerSystem(); + + myScene->registerResourceManager(); + myScene->registerResourceManager(); + + auto camera = myScene->createEntity("camera"); + myScene->addComponent(camera); + myScene->getSystem()->setCameraEntity(camera); + + engine::resources::Shader::VertexParams vertParams{}; + vertParams.hasNormal = true; + vertParams.hasUV0 = true; + auto theShader = std::make_unique( app.gfx(), - std::vector{ - { { 0.5f, 0.5f, 0.0f }, { 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f } }, - { { -0.5f, -0.5f, 0.0f }, { 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f } }, - { { 0.5f, -0.5f, 0.0f }, { 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f } }, - } + app.getResourcePath("engine/shaders/texture.vert").c_str(), + app.getResourcePath("engine/shaders/texture.frag").c_str(), + vertParams, + false, + true + ); + auto whiteTexture = std::make_unique( + app.gfx(), + app.getResourcePath("engine/textures/white.png") ); + auto keepTexture = myScene->addResource("whiteTexture", std::move(whiteTexture)); + auto keepShader = myScene->addResource("theShader", std::move(theShader)); - constexpr int N = 100; - - for (int i = 0; i < N; i++) { - for (int j = 0; j < N; j++) { - - auto entity = myScene->createEntity(std::to_string(i * 10 + j)); - - auto t = myScene->getComponent(entity); - float x = ((float)(i) * 10.0f / (float)(N) ) - 5.0f; - float y = ((float)(j) * 10.0f / (float)(N) ) - 5.0f; - t->position = {x, y, -35.0f}; - t->scale /= (float)(N) / 4.0f; - - auto r = myScene->addComponent(entity); - r->material = myMaterial; - r->mesh = myMesh; - - } - } + engine::util::loadMeshFromFile(myScene, app.getResourcePath("models/lego/lego.dae")); app.gameLoop(); + + INFO("texture addr: {}, shader addr: {}", (void*)keepTexture->getHandle(), (void*)keepShader->getPipeline()); } diff --git a/test/src/main.cpp b/test/src/main.cpp index 04e94fb..151e851 100644 --- a/test/src/main.cpp +++ b/test/src/main.cpp @@ -7,7 +7,7 @@ #include -int main(int argc, char *argv[]) +int main(int, char *[]) { engine::setupLog(PROJECT_NAME);