Browse Source

Gjk, FPS view.

master
Draklaw 4 years ago
parent
commit
f19e59f819
  1. 1
      CMakeLists.txt
  2. 141
      src/Simplex.cpp
  3. 75
      src/Simplex.h
  4. 78
      src/VkExpe.cpp
  5. 10
      src/VkExpe.h
  6. 30
      src/VulkanTutorial.cpp
  7. 8
      src/VulkanTutorial.h
  8. 13
      src/core.h

1
CMakeLists.txt

@ -34,6 +34,7 @@ add_executable(vk_expe
src/Vulkan/Swapchain.cpp src/Vulkan/Swapchain.cpp
src/main.cpp src/main.cpp
src/utils.cpp src/utils.cpp
src/Simplex.cpp
src/Logger.cpp src/Logger.cpp
src/Planet.cpp src/Planet.cpp
src/VkExpe.cpp src/VkExpe.cpp

141
src/Simplex.cpp

@ -0,0 +1,141 @@
#include <Simplex.h>
Vector3 polyhedron_support(Vector3AV polyhedron, const Vector3& direction) {
assert(polyhedron.size() > 0);
Index best = 0;
Real best_dot = polyhedron[0].dot(direction);
for (Index index = 1; index < polyhedron.size(); index += 1) {
Real dot = polyhedron[index].dot(direction);
if (dot > best_dot) {
best = index;
best_dot = dot;
}
}
return polyhedron[best];
}
Simplex::Simplex() = default;
Simplex::Simplex(const Vector3& point)
: m_points{ point, Vector3{}, Vector3{}, Vector3{} }
, m_point_count(1)
{}
Gjk::Gjk(Vector3AV polyhedron0, Vector3AV polyhedron1, const Vector3& direction)
: m_polyhedron0(polyhedron0)
, m_polyhedron1(polyhedron1)
, m_direction(direction)
{}
Gjk::~Gjk() = default;
const Vector3& Gjk::direction() const {
return m_direction;
}
bool Gjk::operator()() {
while (true) {
m_simplex.push(support(m_direction));
if (m_simplex.last().dot(m_direction) < Real(0))
return false;
if (nextSimplex())
return true;
}
}
bool Gjk::nextSimplex() {
switch(m_simplex.point_count()) {
case 1: return nextFromPoint();
case 2: return nextFromLine();
case 3: return nextFromTriangle();
case 4: return nextFromTetrahedron();
}
return false;
}
bool Gjk::nextFromPoint() {
m_direction = -m_simplex.last();
return false;
}
bool Gjk::nextFromLine() {
Vector3 v01 = m_simplex.point(1) - m_simplex.point(0);
Vector3 v1o = -m_simplex.point(1);
m_direction = v01.cross(v1o).cross(v01);
return false;
}
bool Gjk::nextFromTriangle() {
Vector3 v20 = m_simplex.point(0) - m_simplex.point(2);
Vector3 v21 = m_simplex.point(1) - m_simplex.point(2);
Vector3 v2o = -m_simplex.point(2);
Vector3 n = v20.cross(v21);
Vector3 n0 = n.cross(v21);
Vector3 n1 = v20.cross(n);
if(n0.dot(v2o) > Real(0)) {
m_simplex.pop(0);
m_direction = n0;
}
else if(n1.dot(v2o) > Real(0)) {
m_simplex.pop(1);
m_direction = n1;
}
else if(n.dot(v2o) > Real(0)) {
m_direction = n;
}
else {
m_simplex.swap(0, 1);
m_direction = -n;
}
return false;
}
bool Gjk::nextFromTetrahedron() {
Vector3 v30 = m_simplex.point(0) - m_simplex.point(3);
Vector3 v31 = m_simplex.point(1) - m_simplex.point(3);
Vector3 v32 = m_simplex.point(2) - m_simplex.point(3);
Vector3 v3o = -m_simplex.point(3);
Vector3 n[3] = {
v31.cross(v32),
v32.cross(v30),
v30.cross(v31),
};
Real d[3] = {
n[0].dot(v3o),
n[1].dot(v3o),
n[2].dot(v3o),
};
Index best = (d[0] > d[1])? ((d[0] > d[2])? 0: 2):
((d[1] > d[2])? 1: 2);
if(d[best] <= Real(0))
return true;
m_simplex.pop(best);
m_direction = n[best];
return false;
}
Vector3 Gjk::support(const Vector3& direction) const
{
return polyhedron_support(m_polyhedron0, direction)
- polyhedron_support(m_polyhedron1, -direction);
}

75
src/Simplex.h

@ -0,0 +1,75 @@
#pragma once
#include <core.h>
class Simplex {
public:
Simplex();
Simplex(const Vector3& point);
inline Index point_count() const {
return m_point_count;
}
inline const Vector3& point(Index index) const {
assert(index < m_point_count);
return m_points[index];
}
inline const Vector3& last() const {
assert(m_point_count > 0);
return point(m_point_count - 1);
}
inline void push(const Vector3& point) {
assert(m_point_count < MaxPointCount);
m_points[m_point_count] = point;
m_point_count += 1;
}
inline void pop(Index index) {
assert(index < m_point_count);
for(Index i = index; i + 1 < m_point_count; i += 1)
m_points[i] = m_points[i + 1];
m_point_count -= 1;
}
inline void swap(Index index0, Index index1) {
using std::swap;
swap(m_points[index0], m_points[index1]);
}
private:
static constexpr Index MaxPointCount = 4;
private:
Vector3 m_points[MaxPointCount];
Index m_point_count = 0;
};
class Gjk {
public:
Gjk(Vector3AV polyhedron0, Vector3AV polyhedron1, const Vector3& direction=Vector3::UnitX());
~Gjk();
const Vector3& direction() const;
bool operator()();
private:
bool nextSimplex();
bool nextFromPoint();
bool nextFromLine();
bool nextFromTriangle();
bool nextFromTetrahedron();
Vector3 support(const Vector3& direction) const;
private:
Vector3AV m_polyhedron0;
Vector3AV m_polyhedron1;
Simplex m_simplex;
Vector3 m_direction;
};

78
src/VkExpe.cpp

@ -5,6 +5,7 @@
#include <stdexcept> #include <stdexcept>
#include <iostream> #include <iostream>
#include <chrono>
void SdlWindowDeleter::operator()(SDL_Window* window) const { void SdlWindowDeleter::operator()(SDL_Window* window) const {
@ -25,7 +26,7 @@ void VkExpe::initialize() {
auto const window = SDL_CreateWindow( auto const window = SDL_CreateWindow(
"vk_expe", "vk_expe",
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
800, 600, 1920, 1080,
SDL_WINDOW_VULKAN SDL_WINDOW_VULKAN
| SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_ALLOW_HIGHDPI
| SDL_WINDOW_SHOWN | SDL_WINDOW_SHOWN
@ -60,6 +61,8 @@ void VkExpe::run() {
m_running = false; m_running = false;
}); });
auto last_time = std::chrono::high_resolution_clock::now();
SDL_Event event; SDL_Event event;
while(m_running) { while(m_running) {
while(SDL_PollEvent(&event)) { while(SDL_PollEvent(&event)) {
@ -72,17 +75,88 @@ void VkExpe::run() {
m_running = false; m_running = false;
break; break;
} }
case SDL_MOUSEMOTION: {
m_mouse_offset += Vector2(
event.motion.xrel,
event.motion.yrel
);
break;
}
case SDL_WINDOWEVENT: { case SDL_WINDOWEVENT: {
switch(event.window.event) { switch(event.window.event) {
case SDL_WINDOWEVENT_RESIZED: { case SDL_WINDOWEVENT_RESIZED: {
m_vulkan.invalidate_swapchain(); 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_vulkan.draw_frame();
// m_running = false;
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);
} }
} }

10
src/VkExpe.h

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <core.h>
#include <VulkanTutorial.h> #include <VulkanTutorial.h>
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
@ -26,8 +27,17 @@ public:
void run(); void run();
void update(double elapsed);
private: private:
VulkanTutorial m_vulkan; VulkanTutorial m_vulkan;
Vector3 m_camera_position = Vector3(0.0f, 0.0f, -3.0f);
Vector3 m_camera_z = Vector3(0.0f, 0.0f, 1.0f);
Vector3 m_camera_y = Vector3(0.0f, 1.0f, 0.0f);
WindowUP m_window; WindowUP m_window;
bool m_running = false; bool m_running = false;
Vector2 m_mouse_offset = Vector2::Zero();
}; };

30
src/VulkanTutorial.cpp

@ -196,6 +196,12 @@ void VulkanTutorial::shutdown() {
m_context.shutdown(); m_context.shutdown();
} }
void VulkanTutorial::set_camera(const Vector3& camera_position, const Vector3& camera_z, const Vector3& camera_y) {
m_camera_position = camera_position;
m_camera_z = camera_z;
m_camera_y = camera_y;
}
void VulkanTutorial::draw_frame() { void VulkanTutorial::draw_frame() {
m_swapchain.begin_frame(); m_swapchain.begin_frame();
auto const image_index = m_swapchain.current_image_index(); auto const image_index = m_swapchain.current_image_index();
@ -206,15 +212,14 @@ void VulkanTutorial::draw_frame() {
} }
m_last_frame_time = now; m_last_frame_time = now;
const float alpha = SecondsD(m_time).count() * (2.0 * M_PI) / 10.0; Matrix3 linear_view;
const float dist = 2.0f; linear_view <<
const Eigen::Matrix4f view = look_at_matrix( m_camera_y.cross(m_camera_z).transpose(),
// Eigen::Vector3f(0.0f, 0.0f, -dist), m_camera_y.transpose(),
Eigen::Vector3f(0.0f, -dist, -dist), m_camera_z.transpose();
// dist * Eigen::Vector3f(std::cos(alpha), std::sin(alpha), -1.0), Matrix4 view;
Eigen::Vector3f::Zero(), view << linear_view, linear_view * -m_camera_position,
-Eigen::Vector3f::UnitY() Vector4::UnitW().transpose();
);
const float fov = M_PI / 3.0f; const float fov = M_PI / 3.0f;
const float near = 0.1f; const float near = 0.1f;
@ -227,12 +232,7 @@ void VulkanTutorial::draw_frame() {
near, far near, far
); );
using Transform = Eigen::Transform<float, 3, Eigen::Affine>;
Transform model = Transform::Identity(); Transform model = Transform::Identity();
model.rotate(Eigen::AngleAxisf(
alpha,
Eigen::Vector3f::UnitY()
));
const Uniforms uniforms = { const Uniforms uniforms = {
.scene_from_model = model.matrix(), .scene_from_model = model.matrix(),
@ -241,7 +241,7 @@ void VulkanTutorial::draw_frame() {
0.5 * m_swapchain.extent().width, 0.5 * m_swapchain.extent().width,
0.5 * m_swapchain.extent().height, 0.5 * m_swapchain.extent().height,
}, },
.lod = std::cos(alpha) * 0.5f + 0.5f, // .lod = std::cos(alpha) * 0.5f + 0.5f,
}; };
void* uniform_buffer; void* uniform_buffer;

8
src/VulkanTutorial.h

@ -1,5 +1,7 @@
#pragma once #pragma once
#include <core.h>
#include <Vulkan/Context.h> #include <Vulkan/Context.h>
#include <Vulkan/Swapchain.h> #include <Vulkan/Swapchain.h>
@ -35,6 +37,8 @@ public:
void initialize(SDL_Window* window); void initialize(SDL_Window* window);
void shutdown(); void shutdown();
void set_camera(const Vector3& camera_position, const Vector3& camera_z, const Vector3& camera_y);
void draw_frame(); void draw_frame();
void invalidate_swapchain(); void invalidate_swapchain();
@ -78,6 +82,10 @@ private:
std::vector<VkCommandBuffer> m_command_buffers; std::vector<VkCommandBuffer> m_command_buffers;
std::vector<VkSemaphore> m_render_done; std::vector<VkSemaphore> m_render_done;
Vector3 m_camera_position = Vector3(0.0f, 0.0f, -3.0f);
Vector3 m_camera_z = Vector3(0.0f, 0.0f, 1.0f);
Vector3 m_camera_y = Vector3(0.0f, 1.0f, 0.0f);
TimePoint m_last_frame_time; TimePoint m_last_frame_time;
Duration m_time = Duration(0); Duration m_time = Duration(0);
}; };

13
src/core.h

@ -8,8 +8,21 @@
using Byte = unsigned char; using Byte = unsigned char;
using Index = uint32_t; using Index = uint32_t;
using Real = float; using Real = float;
using Vector2 = Eigen::Matrix<Real, 2, 1>;
using Vector3 = Eigen::Matrix<Real, 3, 1>; using Vector3 = Eigen::Matrix<Real, 3, 1>;
using Vector4 = Eigen::Matrix<Real, 4, 1>;
using Matrix2 = Eigen::Matrix<Real, 2, 2>;
using Matrix3 = Eigen::Matrix<Real, 3, 3>;
using Matrix4 = Eigen::Matrix<Real, 4, 4>;
using Transform = Eigen::Transform<Real, 3, Eigen::Affine>;
using AngleAxis = Eigen::AngleAxis<Real>;
using Quaternion = Eigen::Quaternion<Real>;
using Triangle = Eigen::Array<Index, 3, 1>; using Triangle = Eigen::Array<Index, 3, 1>;

Loading…
Cancel
Save