Experimentation using Vulkan.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

163 lines
4.3 KiB

// Copyright 2022 Simon Boyé
#include <VkExpe.h>
#include <core/utils.h>
#include <core/Logger.h>
#include <stdexcept>
#include <iostream>
#include <chrono>
void SdlWindowDeleter::operator()(SDL_Window* window) const {
SDL_DestroyWindow(window);
}
VkExpe::VkExpe(int argc, char** argv) {
}
VkExpe::~VkExpe() {
shutdown();
}
void VkExpe::initialize() {
SDL_Init(SDL_INIT_EVENTS | SDL_INIT_VIDEO);
auto const window = SDL_CreateWindow(
"vk_expe",
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
1920, 1080,
SDL_WINDOW_VULKAN
| SDL_WINDOW_ALLOW_HIGHDPI
| SDL_WINDOW_SHOWN
| SDL_WINDOW_RESIZABLE
);
m_window = WindowUP(
window
);
if(!m_window)
throw std::runtime_error("failed to create window");
m_vulkan.initialize(m_window.get());
}
void VkExpe::shutdown() {
m_vulkan.shutdown();
m_window.reset();
if (SDL_WasInit(0))
SDL_Quit();
}
void VkExpe::run() {
if(m_running)
throw std::runtime_error("calling run while already running");
initialize();
m_running = true;
auto running_guard = make_guard([this] {
m_running = false;
});
auto last_time = std::chrono::high_resolution_clock::now();
SDL_Event event;
while(m_running) {
while(SDL_PollEvent(&event)) {
switch(event.type) {
case SDL_QUIT:
m_running = false;
break;
case SDL_KEYDOWN: {
if(event.key.keysym.scancode == SDL_SCANCODE_ESCAPE)
m_running = false;
break;
}
case SDL_MOUSEMOTION: {
m_mouse_offset += Vector2(
event.motion.xrel,
event.motion.yrel
);
break;
}
case SDL_WINDOWEVENT: {
switch(event.window.event) {
case SDL_WINDOWEVENT_RESIZED: {
m_vulkan.invalidate_swapchain();
break;
}
case SDL_WINDOWEVENT_FOCUS_GAINED: {
SDL_SetRelativeMouseMode(SDL_TRUE);
break;
}
case SDL_WINDOWEVENT_FOCUS_LOST: {
SDL_SetRelativeMouseMode(SDL_FALSE);
break;
}
}
break;
}
}
}
const auto new_time = std::chrono::high_resolution_clock::now();
const auto elapsed = new_time - last_time;
last_time = new_time;
update(std::chrono::duration<double>(elapsed).count());
m_vulkan.set_camera(m_camera_position, m_camera_z, m_camera_y);
m_vulkan.draw_frame();
m_mouse_offset = Vector2::Zero();
}
}
void VkExpe::update(double elapsed) {
int key_count = 0;
const auto keys = SDL_GetKeyboardState(&key_count);
const auto test_key = [key_count, keys](int scan_code) {
return scan_code < key_count && keys[scan_code];
};
if (!m_mouse_offset.isZero()) {
const Real x_sensi = 0.001;
const Real y_sensi = -0.001;
const Vector3 camera_x = m_camera_y.cross(m_camera_z);
Vector3 axis =
x_sensi * m_mouse_offset[0] * m_camera_y +
y_sensi * m_mouse_offset[1] * camera_x;
Real rot_norm = axis.norm();
AngleAxis rot(rot_norm, axis / rot_norm);
m_camera_y = rot * m_camera_y;
m_camera_z = rot * m_camera_z;
}
Vector3 walk_direction = Vector3::Zero();
if(test_key(SDL_SCANCODE_W))
walk_direction += Vector3::UnitZ();
if(test_key(SDL_SCANCODE_S))
walk_direction -= Vector3::UnitZ();
if(test_key(SDL_SCANCODE_A))
walk_direction -= Vector3::UnitX();
if(test_key(SDL_SCANCODE_D))
walk_direction += Vector3::UnitX();
if(test_key(SDL_SCANCODE_SPACE))
walk_direction -= Vector3::UnitY();
if(test_key(SDL_SCANCODE_LCTRL))
walk_direction += Vector3::UnitY();
if(!walk_direction.isZero()) {
walk_direction.normalize();
const Real base_velocity = 1;
Matrix3 camera_basis;
camera_basis << m_camera_y.cross(m_camera_z), m_camera_y, m_camera_z;
m_camera_position += elapsed * base_velocity * (camera_basis * walk_direction);
}
}