// Copyright 2022 Simon Boyé #include #include #include #include #include #include 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(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); } }