camera movement yay

This commit is contained in:
Mars 2024-11-15 12:40:13 -05:00
parent 45e8a99bd1
commit 924fb0be7a
2 changed files with 144 additions and 63 deletions

View file

@ -14,7 +14,7 @@ common_cpp_args = [
'-Wno-c++98-compat-pedantic', '-Wno-c++98-compat-pedantic',
'-Wno-pre-c++20-compat-pedantic', '-Wno-pre-c++20-compat-pedantic',
'-Wno-padded', '-Wno-padded',
'-mavx2' '-mavx2',
] ]
add_project_arguments(cpp.get_supported_arguments(common_cpp_args), language: 'cpp') add_project_arguments(cpp.get_supported_arguments(common_cpp_args), language: 'cpp')

View file

@ -1,5 +1,4 @@
// Include necessary headers // Include necessary headers
#include <GLFW/glfw3.h>
#include <chrono> // For time-related functions #include <chrono> // For time-related functions
#include <fmt/format.h> // For string formatting #include <fmt/format.h> // For string formatting
#include <shaderc/shaderc.hpp> // For shader compilation #include <shaderc/shaderc.hpp> // For shader compilation
@ -39,8 +38,8 @@ VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
#include "vkfw.hpp" // Include GLFW C++ bindings #include "vkfw.hpp" // Include GLFW C++ bindings
// Constants for window dimensions // Constants for window dimensions
constexpr i32 WIDTH = 800; constexpr i32 WIDTH = 1920;
constexpr i32 HEIGHT = 600; constexpr i32 HEIGHT = 1080;
// CAMERA_SPEED of camera movement // CAMERA_SPEED of camera movement
constexpr f64 CAMERA_SPEED = 1.0; constexpr f64 CAMERA_SPEED = 1.0;
@ -130,9 +129,9 @@ class VulkanApp {
} }
// Shut down ImGui // Shut down ImGui
ImGui_ImplVulkan_Shutdown(); // ImGui_ImplVulkan_Shutdown();
ImGui_ImplGlfw_Shutdown(); // ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext(); // ImGui::DestroyContext();
} }
private: private:
@ -206,6 +205,12 @@ class VulkanApp {
glm::mat4 mView; ///< View matrix 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. * @brief Struct to store queue family indices.
* *
@ -280,6 +285,10 @@ class VulkanApp {
fn moveRight(f64 deltaTime) -> void { position += right * CAMERA_SPEED * deltaTime; } 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 { fn rotate(double xoffset, double yoffset) -> void {
const double sensitivity = 0.1; const double sensitivity = 0.1;
yaw += xoffset * sensitivity; yaw += xoffset * sensitivity;
@ -320,37 +329,16 @@ class VulkanApp {
camera.moveBackward(deltaTime); camera.moveBackward(deltaTime);
if (window.getKey(vkfw::Key::eD) == vkfw::eTrue) if (window.getKey(vkfw::Key::eD) == vkfw::eTrue)
camera.moveRight(deltaTime); 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( fmt::println(
"New position: {} {} {}", camera.getPosition()[0], camera.getPosition()[1], camera.getPosition()[2] "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<Camera*>(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. * @brief Initializes the application window using GLFW.
* *
@ -372,19 +360,67 @@ class VulkanApp {
mWindow = vkfw::createWindowUnique(WIDTH, HEIGHT, "Vulkan", hints); mWindow = vkfw::createWindowUnique(WIDTH, HEIGHT, "Vulkan", hints);
// Set the user pointer to this instance, allowing us to access it in callbacks // 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 // Configure cursor for FPS-style camera control
// glfwSetInputMode(mWindow.get(), GLFW_CURSOR, GLFW_CURSOR_DISABLED); mWindow->set<vkfw::InputMode::eCursor>(vkfw::CursorMode::eDisabled);
// Set up mouse callback // 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::InputMode::eCursor>(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::InputMode::eCursor>(vkfw::CursorMode::eDisabled);
}
};
// Set up the window resize callback // Set up the window resize callback
mWindow->callbacks()->on_window_resize = 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 // Set the framebuffer resized flag when the window is resized
std::bit_cast<VulkanApp*>(window.getUserPointer())->mFramebufferResized = true; mFramebufferResized = true;
}; };
} }
@ -431,7 +467,7 @@ class VulkanApp {
createDescriptorSets(); // Allocate and update descriptor sets createDescriptorSets(); // Allocate and update descriptor sets
createCommandBuffers(); // Create command buffers for rendering commands createCommandBuffers(); // Create command buffers for rendering commands
createSyncObjects(); // Create synchronization objects (semaphores and fences) 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. * sets up the style, initializes ImGui for GLFW and Vulkan, and creates a descriptor pool for ImGui.
*/ */
fn initImGui() -> void { fn initImGui() -> void {
// Temporarily disabled ImGui initialization
/*
// Create ImGui context // Create ImGui context
IMGUI_CHECKVERSION(); IMGUI_CHECKVERSION();
ImGui::CreateContext(); ImGui::CreateContext();
@ -494,6 +532,7 @@ class VulkanApp {
}; };
ImGui_ImplVulkan_Init(&initInfo); ImGui_ImplVulkan_Init(&initInfo);
*/
} }
/** /**
@ -503,34 +542,32 @@ class VulkanApp {
* polls for events and draws frames until the window is closed. * polls for events and draws frames until the window is closed.
*/ */
fn mainLoop() -> void { fn mainLoop() -> void {
// Set initial time variables
f64 lastFrame = 0.0; f64 lastFrame = 0.0;
f64 deltaTime = 0.0; f64 deltaTime = 0.0;
f64 lastFpsUpdate = 0.0;
i32 frameCounter = 0;
// While the window is open,
while (!mWindow->shouldClose()) { while (!mWindow->shouldClose()) {
// Calculate time between frames
f64 currentFrame = vkfw::getTime(); f64 currentFrame = vkfw::getTime();
deltaTime = currentFrame - lastFrame; deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame; lastFrame = currentFrame;
// Process input for camera movement
processInput(mWindow.get(), mCamera, deltaTime); processInput(mWindow.get(), mCamera, deltaTime);
// Create view matrix from camera
mView = mCamera.getViewMatrix(); mView = mCamera.getViewMatrix();
// Update the FPS counter if (currentFrame - lastFpsUpdate > 1.0) {
// updateFPS(mWindow.get(), "Vulkan"); mWindow->setTitle(
fmt::format("Vulkan - {:.0f}FPS", static_cast<f32>(frameCounter / (currentFrame - lastFpsUpdate)))
);
lastFpsUpdate = currentFrame;
frameCounter = 0;
}
++frameCounter;
// Poll for events
vkfw::pollEvents(); vkfw::pollEvents();
// Draw a frame
drawFrame(); drawFrame();
} }
// Wait for the device to finish
mDevice->waitIdle(); mDevice->waitIdle();
} }
@ -2118,18 +2155,62 @@ class VulkanApp {
nullptr nullptr
); );
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<f32>(mSwapChainExtent.width) / static_cast<f32>(mSwapChainExtent.height),
0.1F,
100.0F
)
};
// 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<glm::mat4> 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 // Draw the indexed vertices
commandBuffer.drawIndexed(static_cast<u32>(mIndices.size()), 1, 0, 0, 0); commandBuffer.drawIndexed(static_cast<u32>(mIndices.size()), 1, 0, 0, 0);
}
ImGui_ImplVulkan_NewFrame(); // ImGui_ImplVulkan_NewFrame();
ImGui_ImplGlfw_NewFrame(); // ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame(); // ImGui::NewFrame();
// Your ImGui code here // Your ImGui code here
ImGui::ShowDemoWindow(); // ImGui::ShowDemoWindow();
ImGui::Render(); // ImGui::Render();
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), commandBuffer); // ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), commandBuffer);
// End the render pass // End the render pass
commandBuffer.endRenderPass(); commandBuffer.endRenderPass();
@ -2193,7 +2274,7 @@ class VulkanApp {
.view = mView, .view = mView,
// Projection matrix - glm::perspective(fov, aspect, near, far) // Projection matrix - glm::perspective(fov, aspect, near, far)
.proj = glm::perspective( .proj = glm::perspective(
glm::radians(45.0F), glm::radians(90.0F),
static_cast<f32>(mSwapChainExtent.width) / static_cast<f32>(mSwapChainExtent.height), static_cast<f32>(mSwapChainExtent.width) / static_cast<f32>(mSwapChainExtent.height),
0.1F, 0.1F,
100.0F 100.0F