camera refactor

This commit is contained in:
Benjamin Kyd
2023-04-29 22:42:19 +01:00
parent 9ec4536fdf
commit 1d0ec3330c
5 changed files with 194 additions and 189 deletions

View File

@@ -3,56 +3,51 @@
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <memory>
#include <mutex>
namespace inferno {
namespace inferno::graphics {
class Camera {
public:
Camera();
Camera(int w, int h);
struct _CameraImpl;
void update();
bool didUpdate();
void newFrame();
typedef struct Camera {
glm::mat4 ViewMatrix;
glm::mat4 ProjectionMatrix;
glm::mat4 LookMatrix;
float MouseSensitivity = 0.4f;
float CameraSpeed = 0.1f;
float Roll, Pitch, Yaw;
float FOV = 45.0f;
glm::vec3 Position = {};
glm::vec3 LookDirection = {};
glm::mat4 getViewMatrix();
glm::mat4 getProjectionMatrix();
glm::mat4 getCameraLook();
std::unique_ptr<_CameraImpl> _impl;
} Camera;
void setRasterViewport(glm::vec2 viewport);
std::unique_ptr<Camera> camera_create();
void camera_cleanup(std::unique_ptr<Camera>& camera);
// Keyboard
void moveCamera(uint8_t posDelta);
// Mouse Delta
void mouseMoved(glm::vec2 mouseDelta);
void camera_update(std::unique_ptr<Camera>& camera);
void camera_did_update(std::unique_ptr<Camera>& camera);
void camera_new_frame(std::unique_ptr<Camera>& camera);
void setPosition(glm::vec3 position);
void setEulerLook(float roll, float pitch, float yaw);
void setLook(glm::vec3 lookDirection);
glm::mat4 camera_get_view(std::unique_ptr<Camera>& camera);
glm::mat4 camera_get_projection(std::unique_ptr<Camera>& camera);
glm::mat4 camera_get_look(std::unique_ptr<Camera>& camera);
public:
void setRayViewport(glm::vec2 viewport);
glm::vec2 getRayViewport();
void raster_set_viewport(std::unique_ptr<Camera>& camera, glm::ivec2 viewport);
glm::ivec2 raster_get_viewport(std::unique_ptr<Camera>& camera);
public:
// necessary evil
float MouseSensitivity = 0.4f;
float CameraSpeed = 0.1f;
float Roll, Pitch, Yaw;
float FOV = 45.0f;
glm::vec3 Position = {};
glm::vec3 LookDirection = {};
void ray_set_viewport(std::unique_ptr<Camera>& camera, glm::ivec2 viewport);
glm::ivec2 ray_get_viewport(std::unique_ptr<Camera>& camera);
private:
glm::vec2 mViewport = { 100.0f, 100.0f };
glm::vec2 mRayViewport = { 200.0f, 200.0f };
glm::mat4 mViewMatrix = {};
glm::mat4 mProjMatrix = {};
glm::mat4 mCameraLook = {};
bool mDidUpdate;
void camera_move(std::unique_ptr<Camera>& camera, uint8_t movement_delta);
void camera_mouse_move(std::unique_ptr<Camera>& camera, glm::vec2 mouse_delta);
std::mutex _mCam;
};
void camera_set_position(std::unique_ptr<Camera>& camera, glm::vec3 position);
void camera_set_euler_look(std::unique_ptr<Camera>& camera, float roll,
float pitch, float yaw);
void camera_set_look(std::unique_ptr<Camera>& camera,
glm::vec3 look_direction);
}
} // namespace inferno::graphics

View File

@@ -25,20 +25,24 @@
namespace inferno {
InfernoApp* inferno_create()
std::unique_ptr<InfernoApp> inferno_create()
{
// MOTD
yolo::info("INFERNO HART v" INFERNO_VERSION);
InfernoApp* app = new InfernoApp();
std::unique_ptr<InfernoApp> app = std::make_unique<InfernoApp>();
app->Input = std::make_unique<InfernoInput>();
// Create window
graphics::window_create("Inferno v" INFERNO_VERSION, 1280, 720);
return app;
}
void inferno_cleanup(InfernoApp* app)
void inferno_cleanup(std::unique_ptr<InfernoApp>& app)
{
graphics::window_cleanup();
app.reset();
}
static void inferno_gui_help_marker(const char* desc)
@@ -53,7 +57,7 @@ static void inferno_gui_help_marker(const char* desc)
}
}
void inferno_preset_gui(InfernoApp* app)
void inferno_preset_gui(std::unique_ptr<InfernoApp>& app)
{
ImGuiID dockspace_id = ImGui::GetID("main");
@@ -70,7 +74,7 @@ void inferno_preset_gui(InfernoApp* app)
yolo::info("LAYOUT SET TO DEFAULT");
}
void inferno_move_input(InfernoApp* app)
void inferno_move_input(std::unique_ptr<InfernoApp>& app)
{
static GLFWcursor* cursor = glfwCreateStandardCursor(GLFW_HAND_CURSOR);
glfwSetCursor(graphics::window_get_glfw_window(), cursor);
@@ -109,13 +113,13 @@ void inferno_move_input(InfernoApp* app)
app->Input->MovementDelta |= 0b00000100;
}
void inferno_stop_move_input(InfernoApp* app)
void inferno_stop_move_input(std::unique_ptr<InfernoApp>& app)
{
app->Input->MovementDelta = 0x0;
app->Input->MouseDelta = { 0.0f, 0.0f };
}
int inferno_run(InfernoApp* app)
int inferno_run(std::unique_ptr<InfernoApp>& app)
{
while (true) {
@@ -152,25 +156,25 @@ int inferno_run(InfernoApp* app)
ImGui::EndMenuBar();
}
if (showPreview && ImGui::Begin("Preview", nullptr, ImGuiWindowFlags_NoScrollbar))
{
if (ImGui::IsWindowHovered())
{
if (showPreview && ImGui::Begin("Preview", nullptr, ImGuiWindowFlags_NoScrollbar)) {
if (ImGui::IsWindowHovered()) {
inferno_move_input(app);
} else
{
} else {
inferno_stop_move_input(app);
}
if (glm::length(app->Input->MouseDelta) > 0.0f) camera.mouseMoved(mouseDelta);
if (movementDelta != 0b00000000) camera.moveCamera(movementDelta);
if (glm::length(app->Input->MouseDelta) > 0.0f)
camera.mouseMoved(app->Input->MouseDelta);
if (app->Input->MovementDelta != 0b00000000)
camera.moveCamera(app->Input->MovementDelta);
camera.setRasterViewport({ImGui::GetWindowSize().x, ImGui::GetWindowSize().y});
mRasterRenderer->setTargetSize({ImGui::GetWindowSize().x, ImGui::GetWindowSize().y});
camera.setRasterViewport({ ImGui::GetWindowSize().x, ImGui::GetWindowSize().y });
mRasterRenderer->setTargetSize({ ImGui::GetWindowSize().x, ImGui::GetWindowSize().y });
mRasterRenderer->prepare();
mRasterRenderer->draw();
ImGui::Image((ImTextureID)mRasterRenderer->getRenderedTexture(),
ImGui::Image((ImTextureID)mRasterRenderer->getRenderedTexture(),inderno
{ mRasterRenderer->getTargetSize().x, mRasterRenderer->getTargetSize().y },
ImVec2(0,1), ImVec2(1,0));
ImVec2(0, 1), ImVec2(1, 0));
glBindFramebuffer(GL_FRAMEBUFFER, 0);
ImGui::End();
}

View File

@@ -6,23 +6,20 @@
namespace inferno {
class Window;
class HHM;
typedef struct InfernoInput {
glm::vec2 MouseDelta;
uint8_t MovementDelta;
} InfernoInput;
typedef struct InfernoApp {
InfernoInput* Input;
std::unique_ptr<InfernoInput> Input;
} InfernoApp;
InfernoApp* inferno_create();
void inferno_cleanup(InfernoApp* app);
void inferno_preset_gui(InfernoApp* app);
void inferno_move_input(InfernoApp* app);
void inferno_stop_move_input(InfernoApp* app);
int inferno_run(InfernoApp* app);
std::unique_ptr<InfernoApp> inferno_create();
void inferno_cleanup(std::unique_ptr<InfernoApp>& app);
void inferno_preset_gui(std::unique_ptr<InfernoApp>& app);
void inferno_move_input(std::unique_ptr<InfernoApp>& app);
void inferno_stop_move_input(std::unique_ptr<InfernoApp>& app);
int inferno_run(std::unique_ptr<InfernoApp>& app);
}

View File

@@ -5,6 +5,6 @@
int main(int argc, char** argv)
{
auto* inferno = inferno::inferno_create();
std::unique_ptr<inferno::InfernoApp> inferno = inferno::inferno_create();
return inferno::inferno_run(inferno);
}

View File

@@ -1,205 +1,214 @@
#include <scene/camera.hpp>
using namespace inferno;
namespace inferno::graphics {
Camera::Camera()
typedef struct _CameraImpl {
glm::ivec2 Viewport = { 100, 100 };
glm::ivec2 RayViewport = { 200, 200 };
bool DidUpdate;
std::mutex CamMutex;
} _CameraImpl;
std::unique_ptr<Camera> camera_create()
{
mProjMatrix = glm::perspective( glm::radians(FOV), 1.0f, 0.1f, 1000.0f );
std::unique_ptr<Camera> camera = std::make_unique<Camera>();
camera->_impl = std::make_unique<_CameraImpl>();
Roll = 0.0f;
Pitch = 0.0f;
Yaw = 0.0f;
camera->ProjectionMatrix = glm::perspective(
glm::radians(camera->FOV),
1.0f,
0.1f,
1000.0f);
camera->ViewMatrix = {};
Position = {};
LookDirection = {};
camera->Roll = 0.0f;
camera->Pitch = 0.0f;
camera->Yaw = 0.0f;
mViewMatrix = {};
camera->Position = {};
camera->LookDirection = {};
update();
camera_update(camera);
return camera;
}
Camera::Camera(int w, int h)
void camera_cleanup(std::unique_ptr<Camera>& camera)
{
mProjMatrix = glm::perspective(glm::radians(FOV), (float)w / (float)h, 0.1f, 1000.0f);
Roll = 0.0f;
Pitch = 0.0f;
Yaw = 0.0f;
Position = {};
LookDirection = {};
mViewMatrix = {};
update();
camera->_impl.reset();
camera.reset();
}
void Camera::update()
void camera_update(std::unique_ptr<Camera>& camera)
{
glm::mat4 matRoll = glm::mat4(1.0f);
glm::mat4 matPitch = glm::mat4(1.0f);
glm::mat4 matYaw = glm::mat4(1.0f);
glm::mat4 matRoll = glm::mat4(1.0f);
glm::mat4 matPitch = glm::mat4(1.0f);
glm::mat4 matYaw = glm::mat4(1.0f);
matRoll = glm::rotate(matRoll, Roll, glm::vec3(0.0f, 0.0f, 1.0f));
matPitch = glm::rotate(matPitch, Pitch, glm::vec3(1.0f, 0.0f, 0.0f));
matYaw = glm::rotate(matYaw, Yaw, glm::vec3( 0.0f, 1.0f, 0.0f));
matRoll = glm::rotate(matRoll, Roll, glm::vec3(0.0f, 0.0f, 1.0f));
matPitch = glm::rotate(matPitch, Pitch, glm::vec3(1.0f, 0.0f, 0.0f));
matYaw = glm::rotate(matYaw, Yaw, glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 rotate = matRoll * matPitch * matYaw;
mCameraLook = rotate;
glm::mat4 rotate = matRoll * matPitch * matYaw;
mCameraLook = rotate;
glm::mat4 translate = glm::mat4(1.0f);
translate = glm::translate(translate, -Position);
glm::mat4 translate = glm::mat4(1.0f);
translate = glm::translate(translate, -Position);
std::lock_guard<std::mutex> lock(this->_mCam);
std::lock_guard<std::mutex> lock(this->_mCam);
mViewMatrix = rotate * translate;
mProjMatrix = glm::perspective(glm::radians(FOV), mViewport.x / mViewport.y, 0.1f, 1000.0f);
mViewMatrix = rotate * translate;
mProjMatrix = glm::perspective(glm::radians(FOV), mViewport.x / mViewport.y, 0.1f, 1000.0f);
// Work out Look Vector
glm::mat4 inverseView = glm::inverse(mViewMatrix);
// Work out Look Vector
glm::mat4 inverseView = glm::inverse(mViewMatrix);
LookDirection.x = inverseView[2][0];
LookDirection.y = inverseView[2][1];
LookDirection.z = inverseView[2][2];
LookDirection.x = inverseView[2][0];
LookDirection.y = inverseView[2][1];
LookDirection.z = inverseView[2][2];
mDidUpdate = true;
mDidUpdate = true;
}
bool Camera::didUpdate()
{
std::lock_guard<std::mutex> lock(this->_mCam);
return mDidUpdate;
std::lock_guard<std::mutex> lock(this->_mCam);
return mDidUpdate;
}
void Camera::newFrame()
{
std::lock_guard<std::mutex> lock(this->_mCam);
mDidUpdate = false;
std::lock_guard<std::mutex> lock(this->_mCam);
mDidUpdate = false;
}
glm::mat4 Camera::getViewMatrix()
{
std::lock_guard<std::mutex> lock(this->_mCam);
return mViewMatrix;
std::lock_guard<std::mutex> lock(this->_mCam);
return mViewMatrix;
}
glm::mat4 Camera::getProjectionMatrix()
{
std::lock_guard<std::mutex> lock(this->_mCam);
return mProjMatrix;
std::lock_guard<std::mutex> lock(this->_mCam);
return mProjMatrix;
}
glm::mat4 Camera::getCameraLook()
{
std::lock_guard<std::mutex> lock(this->_mCam);
return mCameraLook;
std::lock_guard<std::mutex> lock(this->_mCam);
return mCameraLook;
}
void Camera::setRasterViewport(glm::vec2 viewport)
{
std::lock_guard<std::mutex> lock(this->_mCam);
mViewport = viewport;
mProjMatrix = glm::perspective(glm::radians(FOV), (float)viewport.x / (float)viewport.y, 0.1f, 1000.0f);
std::lock_guard<std::mutex> lock(this->_mCam);
mViewport = viewport;
mProjMatrix = glm::perspective(glm::radians(FOV), (float)viewport.x / (float)viewport.y, 0.1f, 1000.0f);
}
void Camera::moveCamera(uint8_t posDelta)
{
if (posDelta == 0) return;
if (posDelta == 0)
return;
// Rotate by camera direction
glm::vec3 delta(0.0f);
glm::mat2 rotate {
cos(Yaw), -sin(Yaw),
sin(Yaw), cos(Yaw)
};
// Rotate by camera direction
glm::vec3 delta(0.0f);
glm::vec2 f(0.0, 1.0);
f = f * rotate;
glm::mat2 rotate {
cos(Yaw), -sin(Yaw),
sin(Yaw), cos(Yaw)
};
if (posDelta & 0x80) {
delta.z -= f.y;
delta.x -= f.x;
}
if (posDelta & 0x20) {
delta.z += f.y;
delta.x += f.x;
}
if (posDelta & 0x40) {
delta.z += f.x;
delta.x += -f.y;
}
if (posDelta & 0x10) {
delta.z -= f.x;
delta.x -= -f.y;
}
if (posDelta & 0x8) {
delta.y += 1;
}
if (posDelta & 0x4) {
delta.y -= 1;
}
glm::vec2 f(0.0, 1.0);
f = f * rotate;
// get current view matrix
glm::mat4 mat = getViewMatrix();
glm::vec3 forward(mat[0][2], mat[1][2], mat[2][2]);
glm::vec3 strafe(mat[0][0], mat[1][0], mat[2][0]);
if (posDelta & 0x80) {
delta.z -= f.y;
delta.x -= f.x;
}
if (posDelta & 0x20) {
delta.z += f.y;
delta.x += f.x;
}
if (posDelta & 0x40) {
delta.z += f.x;
delta.x += -f.y;
}
if (posDelta & 0x10) {
delta.z -= f.x;
delta.x -= -f.y;
}
if (posDelta & 0x8) {
delta.y += 1;
}
if (posDelta & 0x4) {
delta.y -= 1;
}
// forward vector must be negative to look forward.
// read :http://in2gpu.com/2015/05/17/view-matrix/
Position += delta * CameraSpeed;
// get current view matrix
glm::mat4 mat = getViewMatrix();
glm::vec3 forward(mat[0][2], mat[1][2], mat[2][2]);
glm::vec3 strafe(mat[0][0], mat[1][0], mat[2][0]);
// update the view matrix
update();
// forward vector must be negative to look forward.
// read :http://in2gpu.com/2015/05/17/view-matrix/
Position += delta * CameraSpeed;
// update the view matrix
update();
}
void Camera::mouseMoved(glm::vec2 mouseDelta)
{
if (glm::length(mouseDelta) == 0) return;
// note that yaw and pitch must be converted to radians.
// this is done in update() by glm::rotate
Yaw += MouseSensitivity * (mouseDelta.x / 100);
Pitch += MouseSensitivity * (mouseDelta.y / 100);
Pitch = glm::clamp<float>(Pitch, -M_PI / 2, M_PI / 2);
if (glm::length(mouseDelta) == 0)
return;
// note that yaw and pitch must be converted to radians.
// this is done in update() by glm::rotate
Yaw += MouseSensitivity * (mouseDelta.x / 100);
Pitch += MouseSensitivity * (mouseDelta.y / 100);
Pitch = glm::clamp<float>(Pitch, -M_PI / 2, M_PI / 2);
update();
update();
}
void Camera::setPosition(glm::vec3 position)
{
Position = position;
Position = position;
update();
update();
}
void Camera::setEulerLook(float roll, float pitch, float yaw)
{
Roll = roll; Pitch = pitch; Yaw = yaw;
LookDirection.x = cos(Yaw) * cos(Pitch);
LookDirection.y = sin(Yaw) * cos(Pitch);
LookDirection.z = sin(Pitch);
Roll = roll;
Pitch = pitch;
Yaw = yaw;
LookDirection.x = cos(Yaw) * cos(Pitch);
LookDirection.y = sin(Yaw) * cos(Pitch);
LookDirection.z = sin(Pitch);
update();
update();
}
void Camera::setLook(glm::vec3 lookDirection)
{
LookDirection = lookDirection;
Pitch = asin(-lookDirection.y);
Yaw = atan2(lookDirection.x, lookDirection.z);
LookDirection = lookDirection;
Pitch = asin(-lookDirection.y);
Yaw = atan2(lookDirection.x, lookDirection.z);
update();
update();
}
void Camera::setRayViewport(glm::vec2 viewport)
{
std::lock_guard<std::mutex> lock(this->_mCam);
mRayViewport = viewport;
std::lock_guard<std::mutex> lock(this->_mCam);
mRayViewport = viewport;
}
glm::vec2 Camera::getRayViewport()
{
std::lock_guard<std::mutex> lock(this->_mCam);
return mRayViewport;
std::lock_guard<std::mutex> lock(this->_mCam);
return mRayViewport;
}
}