From 924fb0be7a52659d351ece8330840d8c2b40489e Mon Sep 17 00:00:00 2001 From: Mars Date: Fri, 15 Nov 2024 12:40:13 -0500 Subject: [PATCH] camera movement yay --- meson.build | 4 +- src/main.cpp | 203 +++++++++++++++++++++++++++++++++++---------------- 2 files changed, 144 insertions(+), 63 deletions(-) diff --git a/meson.build b/meson.build index 3fddbaa..806cc41 100644 --- a/meson.build +++ b/meson.build @@ -14,7 +14,7 @@ common_cpp_args = [ '-Wno-c++98-compat-pedantic', '-Wno-pre-c++20-compat-pedantic', '-Wno-padded', - '-mavx2' + '-mavx2', ] add_project_arguments(cpp.get_supported_arguments(common_cpp_args), language: 'cpp') @@ -40,4 +40,4 @@ executable( sources: files('src/main.cpp'), include_directories: include_directories('include', is_system: true), dependencies: deps, -) +) \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index f360294..de02b9c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,4 @@ // Include necessary headers -#include #include // For time-related functions #include // For string formatting #include // For shader compilation @@ -39,8 +38,8 @@ VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE #include "vkfw.hpp" // Include GLFW C++ bindings // Constants for window dimensions -constexpr i32 WIDTH = 800; -constexpr i32 HEIGHT = 600; +constexpr i32 WIDTH = 1920; +constexpr i32 HEIGHT = 1080; // CAMERA_SPEED of camera movement constexpr f64 CAMERA_SPEED = 1.0; @@ -130,9 +129,9 @@ class VulkanApp { } // Shut down ImGui - ImGui_ImplVulkan_Shutdown(); - ImGui_ImplGlfw_Shutdown(); - ImGui::DestroyContext(); + // ImGui_ImplVulkan_Shutdown(); + // ImGui_ImplGlfw_Shutdown(); + // ImGui::DestroyContext(); } private: @@ -206,6 +205,12 @@ class VulkanApp { glm::mat4 mView; ///< View matrix + // Mouse input tracking + bool mFirstMouse = true; ///< Flag for first mouse movement + f64 mLastX = WIDTH / 2.0; ///< Last mouse X position + f64 mLastY = HEIGHT / 2.0; ///< Last mouse Y position + bool mCursorCaptured = true; ///< Flag indicating if cursor is captured + /** * @brief Struct to store queue family indices. * @@ -280,6 +285,10 @@ class VulkanApp { fn moveRight(f64 deltaTime) -> void { position += right * CAMERA_SPEED * deltaTime; } + fn moveUp(f64 deltaTime) -> void { position += glm::dvec3(0.0, 0.0, 1.0) * CAMERA_SPEED * deltaTime; } + + fn moveDown(f64 deltaTime) -> void { position -= glm::dvec3(0.0, 0.0, 1.0) * CAMERA_SPEED * deltaTime; } + fn rotate(double xoffset, double yoffset) -> void { const double sensitivity = 0.1; yaw += xoffset * sensitivity; @@ -320,37 +329,16 @@ class VulkanApp { camera.moveBackward(deltaTime); if (window.getKey(vkfw::Key::eD) == vkfw::eTrue) camera.moveRight(deltaTime); + if (window.getKey(vkfw::Key::eSpace) == vkfw::eTrue) + camera.moveUp(deltaTime); + if (window.getKey(vkfw::Key::eLeftShift) == vkfw::eTrue) + camera.moveDown(deltaTime); fmt::println( "New position: {} {} {}", camera.getPosition()[0], camera.getPosition()[1], camera.getPosition()[2] ); } - // static fn mouseCallback(const vkfw::Window& window, double xpos, double ypos) -> void { - // auto& camera = *static_cast(window.getUserPointer()); - - // static struct { - // bool first_mouse = true; - // double last_x = WIDTH / 2.0; - // double last_y = HEIGHT / 2.0; - // } MouseState; - - // if (MouseState.first_mouse) { - // MouseState.last_x = xpos; - // MouseState.last_y = ypos; - // MouseState.first_mouse = false; - // return; - // } - - // double xoffset = xpos - MouseState.last_x; - // double yoffset = MouseState.last_y - ypos; // Reversed since y-coordinates range from bottom to top - - // MouseState.last_x = xpos; - // MouseState.last_y = ypos; - - // camera.rotate(xoffset, yoffset); - // } - /** * @brief Initializes the application window using GLFW. * @@ -372,19 +360,67 @@ class VulkanApp { mWindow = vkfw::createWindowUnique(WIDTH, HEIGHT, "Vulkan", hints); // Set the user pointer to this instance, allowing us to access it in callbacks - mWindow->setUserPointer(this); // Store camera pointer for callbacks + mWindow->setUserPointer(this); - // Configure cursor - // glfwSetInputMode(mWindow.get(), GLFW_CURSOR, GLFW_CURSOR_DISABLED); + // Configure cursor for FPS-style camera control + mWindow->set(vkfw::CursorMode::eDisabled); // Set up mouse callback - // mWindow->callbacks()->on_cursor_move = mouseCallback; + mWindow->callbacks()->on_cursor_move = + [this](const vkfw::Window& /*window*/, f64 xpos, f64 ypos) -> void { + if (!mCursorCaptured) + return; // Skip camera movement when cursor is not captured + + if (mFirstMouse) { + mLastX = xpos; + mLastY = ypos; + mFirstMouse = false; + return; + } + + f64 xoffset = xpos - mLastX; + f64 yoffset = mLastY - ypos; // Reversed since y-coordinates range from bottom to top + + mLastX = xpos; + mLastY = ypos; + + mCamera.rotate(-xoffset, yoffset); // Invert xoffset for correct horizontal movement + }; + + // Set up key callback for escape + mWindow->callbacks()->on_key = [this]( + const vkfw::Window& window, + const vkfw::Key& key, + const i32& /*scancode*/, + const vkfw::KeyAction& action, + const vkfw::ModifierKeyFlags& /*mods*/ + ) -> void { + if (key == vkfw::Key::eEscape && action == vkfw::KeyAction::ePress) { + mCursorCaptured = false; + window.set(vkfw::CursorMode::eNormal); + } + }; + + // Set up mouse button callback for re-capture + mWindow->callbacks()->on_mouse_button = [this]( + const vkfw::Window& window, + const vkfw::MouseButton& button, + const vkfw::MouseButtonAction& action, + const vkfw::ModifierKeyFlags& /*mods*/ + ) -> void { + if (button == vkfw::MouseButton::eLeft && action == vkfw::MouseButtonAction::ePress && + !mCursorCaptured) { + mCursorCaptured = true; + mFirstMouse = true; // Reset first mouse flag to avoid jumps + window.set(vkfw::CursorMode::eDisabled); + } + }; // Set up the window resize callback mWindow->callbacks()->on_window_resize = - [](const vkfw::Window& window, usize /*width*/, usize /*height*/) -> void { + [this](const vkfw::Window& /*window*/, usize /*width*/, usize /*height*/) -> void { // Set the framebuffer resized flag when the window is resized - std::bit_cast(window.getUserPointer())->mFramebufferResized = true; + mFramebufferResized = true; }; } @@ -431,7 +467,7 @@ class VulkanApp { createDescriptorSets(); // Allocate and update descriptor sets createCommandBuffers(); // Create command buffers for rendering commands createSyncObjects(); // Create synchronization objects (semaphores and fences) - initImGui(); // Initialize Dear ImGui for GUI rendering + // initImGui(); // Initialize Dear ImGui for GUI rendering } /** @@ -441,6 +477,8 @@ class VulkanApp { * sets up the style, initializes ImGui for GLFW and Vulkan, and creates a descriptor pool for ImGui. */ fn initImGui() -> void { + // Temporarily disabled ImGui initialization + /* // Create ImGui context IMGUI_CHECKVERSION(); ImGui::CreateContext(); @@ -494,6 +532,7 @@ class VulkanApp { }; ImGui_ImplVulkan_Init(&initInfo); + */ } /** @@ -503,34 +542,32 @@ class VulkanApp { * polls for events and draws frames until the window is closed. */ fn mainLoop() -> void { - // Set initial time variables - f64 lastFrame = 0.0; - f64 deltaTime = 0.0; + f64 lastFrame = 0.0; + f64 deltaTime = 0.0; + f64 lastFpsUpdate = 0.0; + i32 frameCounter = 0; - // While the window is open, while (!mWindow->shouldClose()) { - // Calculate time between frames f64 currentFrame = vkfw::getTime(); deltaTime = currentFrame - lastFrame; lastFrame = currentFrame; - // Process input for camera movement processInput(mWindow.get(), mCamera, deltaTime); - - // Create view matrix from camera mView = mCamera.getViewMatrix(); - // Update the FPS counter - // updateFPS(mWindow.get(), "Vulkan"); + if (currentFrame - lastFpsUpdate > 1.0) { + mWindow->setTitle( + fmt::format("Vulkan - {:.0f}FPS", static_cast(frameCounter / (currentFrame - lastFpsUpdate))) + ); + lastFpsUpdate = currentFrame; + frameCounter = 0; + } + ++frameCounter; - // Poll for events vkfw::pollEvents(); - - // Draw a frame drawFrame(); } - // Wait for the device to finish mDevice->waitIdle(); } @@ -2118,18 +2155,62 @@ class VulkanApp { nullptr ); - // Draw the indexed vertices - commandBuffer.drawIndexed(static_cast(mIndices.size()), 1, 0, 0, 0); + UniformBufferObject ubo { + // Model matrix - glm::rotate(matrix, angle, axis) + .model = glm::mat4(1.0F), + // View matrix - glm::lookAt(eye, center, up) + .view = mView, + // Projection matrix - glm::perspective(fov, aspect, near, far) + .proj = glm::perspective( + glm::radians(90.0F), + static_cast(mSwapChainExtent.width) / static_cast(mSwapChainExtent.height), + 0.1F, + 100.0F + ) + }; - ImGui_ImplVulkan_NewFrame(); - ImGui_ImplGlfw_NewFrame(); - ImGui::NewFrame(); + // Flip the Y axis, because glm was designed for OpenGL + ubo.proj[1][1] *= -1; + + // Copy the uniform buffer object to the mapped memory + memcpy(mUniformBuffersMapped[mCurrentFrame], &ubo, sizeof(ubo)); + + // Example: Add extra clones with different translations + std::vector modelMatrices = { + glm::translate(glm::mat4(1.0F), glm::vec3(2.0F, 0.0F, 0.0F)), + glm::translate(glm::mat4(1.0F), glm::vec3(-2.0F, 0.0F, 0.0F)), + glm::translate(glm::mat4(1.0F), glm::vec3(0.0F, 2.0F, 0.0F)) + }; + + for (const auto& modelMatrix : modelMatrices) { + // Update model matrix for each clone + ubo.model = modelMatrix; + memcpy(mUniformBuffersMapped[mCurrentFrame], &ubo, sizeof(ubo)); + + // Bind the descriptor sets + commandBuffer.bindDescriptorSets( + vk::PipelineBindPoint::eGraphics, + mPipelineLayout.get(), + 0, + 1, + &mDescriptorSets[mCurrentFrame], + 0, + nullptr + ); + + // Draw the indexed vertices + commandBuffer.drawIndexed(static_cast(mIndices.size()), 1, 0, 0, 0); + } + + // ImGui_ImplVulkan_NewFrame(); + // ImGui_ImplGlfw_NewFrame(); + // ImGui::NewFrame(); // Your ImGui code here - ImGui::ShowDemoWindow(); + // ImGui::ShowDemoWindow(); - ImGui::Render(); - ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), commandBuffer); + // ImGui::Render(); + // ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), commandBuffer); // End the render pass commandBuffer.endRenderPass(); @@ -2193,7 +2274,7 @@ class VulkanApp { .view = mView, // Projection matrix - glm::perspective(fov, aspect, near, far) .proj = glm::perspective( - glm::radians(45.0F), + glm::radians(90.0F), static_cast(mSwapChainExtent.width) / static_cast(mSwapChainExtent.height), 0.1F, 100.0F