camera control

feature/softbody-runtime-control
Benjamin Kraft 4 months ago
parent dda4ec2fe5
commit 95527a5a55
  1. 6
      include/application.hpp
  2. 28
      include/camera.hpp
  3. 44
      include/input.hpp
  4. 2
      include/simulation.hpp
  5. 2
      shaders/shader.comp
  6. 60
      src/camera.cpp
  7. 73
      src/input.cpp
  8. 2
      src/soft_body.cpp
  9. 20
      src/vulkan/application.cpp
  10. 2
      src/vulkan/command_pool.cpp

@ -13,6 +13,8 @@
#include <array>
#include <memory>
#include <vulkan/vulkan_core.h>
#include <map>
#include <glm/vec2.hpp>
class Instance;
class Swapchain;
@ -23,13 +25,13 @@ class Image;
class ComputePipeline;
class Fence;
class Semaphore;
class Camera;
class Application {
public:
explicit Application();
void mainLoop();
~Application();
protected:
Swapchain* swapchain = nullptr;
Pipeline* graphicsPipeline = nullptr;
@ -52,4 +54,6 @@ protected:
virtual void recordComputeCommands(VkCommandBuffer cmdBuffer) {}
void update();
void createSyncObjects();
Camera* camera = nullptr;
};

@ -0,0 +1,28 @@
#pragma once
#include <glm/mat4x4.hpp>
#include <glm/gtc/quaternion.hpp>
#include <vulkan/vulkan_core.h>
#include "input.hpp"
class Camera : private MouseListener {
private:
glm::vec3 position {0, 0, 0};
float phi = 0;
float theta = 0;
float fov = 45;
float near = 0.1;
float far = 100;
VkExtent2D& extent;
public:
explicit Camera(VkExtent2D& extent);
void update(float dt);
glm::mat4 view() const;
glm::mat4 projection() const;
glm::vec3 localToWorld(const glm::vec3& direction) const;
protected:
void mouseMoved(float deltaX, float deltaY) override;
};

@ -0,0 +1,44 @@
#pragma once
#include <GLFW/glfw3.h>
#include <map>
#include <set>
class Listener;
class MouseListener;
class Input {
friend Listener;
friend MouseListener;
public:
explicit Input(GLFWwindow* window);
static Input* instance;
static std::map<int, bool> KeyIsDown;
static std::map<int, bool> MouseButtonIsDown;
private:
GLFWwindow* window;
std::set<Listener*> listeners;
void keyPressed(int key);
void keyReleased(int key);
void mouseButtonPressed(int button);
void mouseButtonReleased(int button);
void mouseMoved(double newX, double newY);
double oldX {}, oldY {};
};
class Listener {
public:
Listener();
virtual ~Listener();
};
class KeyListener : Listener {
};
class MouseListener : public Listener {
public:
virtual void mouseMoved(float deltaX, float deltaY) {};
};

@ -1,6 +1,6 @@
#pragma once
#include "vulkan/application.hpp"
#include "application.hpp"
class SoftBody;
class Buffer;

@ -12,5 +12,5 @@ layout (std140, set = 0, binding = 0) buffer VertexBuffer {
};
void main() {
// vertices[0].position.z += 0.001;
}

@ -0,0 +1,60 @@
#include "camera.hpp"
#include "application.hpp"
#include "vulkan/instance.hpp"
#include "input.hpp"
#include <glm/gtc/matrix_transform.hpp>
const std::map<int, glm::vec3> moveDirections {
{GLFW_KEY_A, {-1, 0, 0}},
{GLFW_KEY_D, {1, 0, 0}},
{GLFW_KEY_S, {0, 0, 1}},
{GLFW_KEY_W, {0, 0, -1}},
{GLFW_KEY_E, {0, 1, 0}},
{GLFW_KEY_Q, {0, -1, 0}},
};
void Camera::update(float dt) {
glm::vec3 add {};
for (const auto &[key, dir] : moveDirections)
if (Input::KeyIsDown[key])
add += dir;
position += localToWorld(add) * dt;
}
glm::mat4 Camera::view() const {
glm::vec3 forward = localToWorld({0, 0, -1});
return glm::lookAt(position, position + forward, glm::vec3(0, 1, 0));
}
glm::mat4 Camera::projection() const {
float aspect = static_cast<float>(extent.width) / static_cast<float>(extent.height);
return glm::perspective(glm::radians(fov), aspect, near, far);
}
glm::vec3 Camera::localToWorld(const glm::vec3& direction) const {
float x = glm::sin(phi) * glm::cos(theta);
float y = glm::sin(theta);
float z = -glm::cos(phi) * glm::cos(theta);
glm::vec3 forward {x, y, z};
glm::qua rotation = glm::quatLookAt(forward, glm::vec3(0, 1, 0));
return rotation * direction;
}
Camera::Camera(VkExtent2D &extent) : extent(extent) {
}
void Camera::mouseMoved(float deltaX, float deltaY) {
if (!Input::MouseButtonIsDown[GLFW_MOUSE_BUTTON_RIGHT])
return;
const float div = 300;
phi += deltaX / div;
theta += -deltaY / div;
float margin = 0.1;
theta = glm::clamp(theta, -glm::half_pi<float>() + margin, glm::half_pi<float>() - margin);
}

@ -0,0 +1,73 @@
#include "input.hpp"
std::map<int, bool> Input::KeyIsDown;
std::map<int, bool> Input::MouseButtonIsDown;
Input* Input::instance;
Input::Input(GLFWwindow *window) : window(window) {
instance = this;
glfwSetWindowUserPointer(window, this);
glfwSetKeyCallback(window, [](GLFWwindow* window, int key, int scancode, int action, int mods){
auto inputManager = reinterpret_cast<Input*>(glfwGetWindowUserPointer(window));
if (action == GLFW_PRESS)
inputManager->keyPressed(key);
if (action == GLFW_RELEASE)
inputManager->keyReleased(key);
});
glfwSetCursorPosCallback(window, [](GLFWwindow* window, double xpos, double ypos){
auto inputManager = reinterpret_cast<Input*>(glfwGetWindowUserPointer(window));
inputManager->mouseMoved(xpos, ypos);
});
glfwGetCursorPos(window, &oldX, &oldY);
glfwSetMouseButtonCallback(window, [](GLFWwindow* window, int button, int action, int mods){
auto inputManager = reinterpret_cast<Input*>(glfwGetWindowUserPointer(window));
if (action == GLFW_PRESS)
inputManager->mouseButtonPressed(button);
if (action == GLFW_RELEASE)
inputManager->mouseButtonReleased(button);
});
}
void Input::keyPressed(int key) {
Input::KeyIsDown[key] = true;
}
void Input::keyReleased(int key) {
Input::KeyIsDown[key] = false;
}
void Input::mouseButtonPressed(int button) {
Input::MouseButtonIsDown[button] = true;
if (button == GLFW_MOUSE_BUTTON_RIGHT)
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
}
void Input::mouseButtonReleased(int button) {
Input::MouseButtonIsDown[button] = false;
if (button == GLFW_MOUSE_BUTTON_RIGHT)
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
}
void Input::mouseMoved(double newX, double newY) {
float deltaX = static_cast<float>(newX - oldX);
float deltaY = static_cast<float>(newY - oldY);
for (auto listener : listeners){
if (auto mouseListener = dynamic_cast<MouseListener*>(listener)){
mouseListener->mouseMoved(deltaX, deltaY);
}
}
oldX = newX;
oldY = newY;
}
Listener::Listener() {
Input::instance->listeners.insert(this);
}
Listener::~Listener() {
Input::instance->listeners.erase(this);
}

@ -65,7 +65,7 @@ SoftBody::SoftBody(Mesh* mesh, float compliance) : compliance(compliance) {
uint32_t a = out.trifacelist[i * 3 + 0];
uint32_t b = out.trifacelist[i * 3 + 1];
uint32_t c = out.trifacelist[i * 3 + 2];
if (out.trifacemarkerlist[i] != 0)
if (out.trifacemarkerlist[i] != 1)
faces.emplace_back(Face(a, b, c));
}
faces.shrink_to_fit();

@ -1,4 +1,4 @@
#include "vulkan/application.hpp"
#include "application.hpp"
#include "vulkan/swapchain.hpp"
#include "vulkan/pipeline.hpp"
#include "vulkan/instance.hpp"
@ -6,12 +6,13 @@
#include "vulkan/command_pool.hpp"
#include "vulkan/image.hpp"
#include "vulkan/synchronization.hpp"
#include <glm/gtc/matrix_transform.hpp>
#include "camera.hpp"
#include "input.hpp"
Application::Application() {
new Instance;
new Input(Instance::instance->window);
createSyncObjects();
swapchain = new Swapchain();
graphicsPipeline = new Pipeline(swapchain->renderPass);
@ -25,6 +26,7 @@ Application::Application() {
graphicsPipeline->updateDescriptor(0, uniformBuffer, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
computePipeline = new ComputePipeline();
camera = new Camera(swapchain->extent);
char* stats;
vmaBuildStatsString(Instance::instance->allocator, &stats, VK_TRUE);
@ -38,11 +40,9 @@ void Application::updateUniformBuffer() {
elapsed += 0.007;
UniformBufferObject ubo {};
ubo.model = glm::rotate(glm::mat4(1), elapsed * glm::radians(90.f), glm::vec3(0, 0, 1));
ubo.view = glm::lookAt(glm::vec3(5), glm::vec3(0), glm::vec3(0, 0, 1));
ubo.projection = glm::perspective(glm::radians(45.f),
static_cast<float>(swapchain->extent.width) / static_cast<float>(swapchain->extent.height),
0.1f, 10.f);
ubo.model = glm::mat4(1);
ubo.view = camera->view();
ubo.projection = camera->projection();
ubo.projection[1][1] *= -1;
memcpy(uniformBuffer->allocationInfo.pMappedData, &ubo, sizeof(UniformBufferObject));
@ -125,6 +125,7 @@ void Application::drawFrame() {
vkResetCommandBuffer(Instance::instance->commandPool->graphicsBuffer, 0);
recordGraphicsCommandBuffer(imageIndex);
camera->update(0.017);
updateUniformBuffer();
VkSubmitInfo submitInfo {};
@ -198,6 +199,7 @@ Application::~Application() {
delete uniformBuffer;
delete graphicsPipeline;
delete computePipeline;
delete camera;
delete Instance::instance;
}

@ -1,5 +1,5 @@
#include "vulkan/command_pool.hpp"
#include "vulkan/application.hpp"
#include "application.hpp"
#include "vulkan/instance.hpp"
CommandPool::CommandPool() {

Loading…
Cancel
Save