Skip to content

Commit

Permalink
[renderer] Added mouse input handling.
Browse files Browse the repository at this point in the history
Rotate octree when left mouse button is hold down and mouse is being moved.
Added extensive camera class from Sascha Willems' example repository.
  • Loading branch information
IAmNotHanni committed Apr 26, 2020
1 parent 7128b9a commit fef9cc2
Show file tree
Hide file tree
Showing 7 changed files with 225 additions and 393 deletions.
5 changes: 5 additions & 0 deletions include/inexor/vulkan-renderer/application.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ class Application : public VulkanRenderer, public tools::CommandLineArgumentPars

VkResult update_keyboard_input();

VkResult update_mouse_input();

// TODO: Refactor!
double cursor_x, cursor_y;

public:
VkResult init();

Expand Down
357 changes: 168 additions & 189 deletions include/inexor/vulkan-renderer/camera.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,207 +3,186 @@
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/quaternion.hpp>
#include <spdlog/spdlog.h>

#include <mutex>

namespace inexor::vulkan_renderer {

/// TODO: Add mutex!
/// TODO: Because this camera class will be used by scripting as well, runtime errors should be expected.
// TODO: Refactor method naming!
class Camera {
private:
glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f);

glm::vec3 direction = glm::vec3(0.0f, 0.0f, 0.0f);

float camera_speed = 1.0f;

// TODO: Change with respect to window resolution!
float aspect_ratio = 800 / 600;

float yaw = 0.0f;

float pitch = 0.0f;

float roll = 0.0f;

float near_plane = 0.1f;

float far_plane = 10.0f;

float zoom = 45.0f;

bool camera_is_moving = false;

bool moving_backwards = false;

glm::vec3 world_up = glm::vec3(0.0f, 0.0f, 1.0f);

glm::vec3 world_front = glm::vec3(1.0f, 0.0f, 0.0f);
float fov;
float znear, zfar;

glm::vec3 world_right = glm::vec3(0.0f, 1.0f, 0.0f);
void updateViewMatrix() {
glm::mat4 rotM = glm::mat4(1.0f);
glm::mat4 transM;

glm::mat4 view_matrix = glm::mat4();
rotM = glm::rotate(rotM, glm::radians(rotation.x), glm::vec3(1.0f, 0.0f, 0.0f));
rotM = glm::rotate(rotM, glm::radians(rotation.y), glm::vec3(0.0f, 1.0f, 0.0f));
rotM = glm::rotate(rotM, glm::radians(rotation.z), glm::vec3(0.0f, 0.0f, 1.0f));

glm::mat4 projection_matrix = glm::mat4();
transM = glm::translate(glm::mat4(1.0f), position * glm::vec3(1.0f, 1.0f, -1.0f));

/// Neccesary for taking into account the relative speed of the system's CPU.
/// The timestep will be calculated in the main loop and will be passed on when update() is called.
float timestep;
if (type == CameraType::firstperson) {
matrices.view = rotM * transM;
} else {
matrices.view = transM * rotM;
}

private:
/// @brief Updates the view matrix.
void update_view_matrix();

/// @brief Updates the projection matrix.
void update_projection_matrix();
updated = true;
};

public:
Camera() = default;

~Camera() = default;

/// @brief Updates all matrices.
void update_matrices();

/// @brief Start moving the camera every time update() is called.
/// @param moving_backwards [in] True if the camera is moving backwards, false otherwise.
void start_camera_movement(bool moving_backwards = false);

/// @brief Ends moving the camera every time update() is called.
void end_camera_movement();

/// @brief Updates camera movement.
/// @brief timestep [in] A float which scales with the amount of time which has passed since last rendering.
void update(float timestep);

/// @brief Sets the camera position.
/// @param position [in] The position of the camera.
void set_position(const glm::vec3 &position);

/// @brief Returns he current camera position.
glm::vec3 get_position() const;

/// @brief Sets the relative speed of the camera.
/// @param speed [in] The velocity of the camera movement.
void set_speed(float camera_speed);

/// @brief Returns the camera speed.
float get_speed() const;

/// @brief
/// @param direction [in] The direction in which we look.
void set_direction(const glm::vec3 &direction);

/// @brief Returns the direction in which the camera is looking.
glm::vec3 get_direction() const;

/// @brief Moves the camera forwards with respect to the relative camera speed.
void move_forwards();

/// @brief Moves the camera backwards with respect to the relative camera speed.
void move_backwards();

/// @brief Moves the camera along the x-axis.
/// @param y [in] The distance on the x-axis.
void move_camera_x(float x);

/// @brief Moves the camera along the y-axis.
/// @param y [in] The distance on the y-axis.
void move_camera_y(float y);

/// @brief Moves the camera along the z-axis.
/// @param y [in] The distance on the z-axis.
void move_camera_z(float z);

/// @brief Sets the yaw rotation angle.
/// @param yaw [in] The yaw angle.
void set_yaw(float yaw);

/// @brief Sets the pitch rotation angle.
/// @param pitch [in] The pitch angle.
void set_pitch(float pitch);

/// @brief Sets the roll rotation angle.
/// @param roll [in] The roll angle.
void set_roll(float roll);

/// @brief Returns the yaw rotation angle.
float get_yaw() const;

/// @brief Returns the pitch rotation angle.
float get_pitch() const;

/// @brief Returns the roll rotation angle.
float get_roll() const;

/// @brief Sets the near plane for calculating the projection matrix.
/// @param near_plane [in] The z-distance to the near plane.
void set_near_plane(float near_plane);

/// @brief Returns the near plane.
float get_near_plane() const;

/// @brief Sets the far plane for calculating the projection matrix.
/// @param far_plane [in] The z-distance to the far plane.
void set_far_plane(float far_plane);

/// @brief Returns the far plane.
float get_far_plane() const;

/// @brief Sets the aspect ratio.
/// @param aspect_ratio [in] The aspect ratio.
void set_aspect_ratio(float aspect_ratio);

/// @brief Returns the aspect ratio.
float get_aspect_ratio() const;

/// @brief Sets the rotation of the camera matrix.
/// @param yaw [in] The yaw angle.
/// @param pitch [in] The pitch angle.
/// @param roll [in] The roll angle.
void set_rotation(float yaw, float pitch, float roll);

/// @brief Rotates the Camera around a certain center.
/// @brief rotation_center [in] The center of rotation.
/// @brief angle_x [in] The angle around x-axis.
/// @brief angle_y [in] The angle around y-axis.
/// @todo
void rotate(const glm::vec3 &rotation_center, float angle_x, float angle_y);

/// @brief Returns the rotation vector of the camera relative to the up vector.
/// @todo
glm::vec3 get_rotation() const;

/// @brief Returns the up vector.
glm::vec3 get_up() const;

/// @brief Returns the front vector.
glm::vec3 get_front() const;

/// @brief Returns the right vector.
glm::vec3 get_right() const;

/// @brief Pan function (translate both camera eye and lookat point).
/// @param x The angle on the x-axis.
/// @param y The angle on the y-axis.
/// @todo
void pan(float x, float y);

/// @brief Sets the zoom of the camera.
/// @param zoom [in] The camera zoom.
void set_zoom(float zoom);

// TODO: min/max zoom!
/// @brief Returns the camera zoom.
float get_zoom() const;

/// @brief Returns the view matrix.
glm::mat4 get_view_matrix();

/// @brief Returns the projection matrix.
glm::mat4 get_projection_matrix();
enum CameraType { lookat, firstperson };
CameraType type = CameraType::lookat;

glm::vec3 rotation = glm::vec3();
glm::vec3 position = glm::vec3();

float rotationSpeed = 1.0f;
float movementSpeed = 1.0f;

bool updated = false;

struct {
glm::mat4 perspective;
glm::mat4 view;
} matrices;

struct {
bool left = false;
bool right = false;
bool up = false;
bool down = false;
} keys;

bool moving() {
return keys.left || keys.right || keys.up || keys.down;
}

float getNearClip() {
return znear;
}

float getFarClip() {
return zfar;
}

void setPerspective(float fov, float aspect, float znear, float zfar) {
this->fov = fov;
this->znear = znear;
this->zfar = zfar;
matrices.perspective = glm::perspective(glm::radians(fov), aspect, znear, zfar);
};

void updateAspectRatio(float aspect) {
matrices.perspective = glm::perspective(glm::radians(fov), aspect, znear, zfar);
}

void setPosition(glm::vec3 position) {
this->position = position;
updateViewMatrix();
}

void setRotation(glm::vec3 rotation) {
this->rotation = rotation;
updateViewMatrix();
};

void rotate(glm::vec3 delta) {
this->rotation += delta;
updateViewMatrix();
}

void setTranslation(glm::vec3 translation) {
this->position = translation;
updateViewMatrix();
};

void translate(glm::vec3 delta) {
this->position += delta;
updateViewMatrix();
}

void update(float deltaTime) {
updated = false;
if (type == CameraType::firstperson) {
if (moving()) {
glm::vec3 camFront;
camFront.x = -cos(glm::radians(rotation.x)) * sin(glm::radians(rotation.y));
camFront.y = sin(glm::radians(rotation.x));
camFront.z = cos(glm::radians(rotation.x)) * cos(glm::radians(rotation.y));
camFront = glm::normalize(camFront);

float moveSpeed = deltaTime * movementSpeed;

if (keys.up)
position += camFront * moveSpeed;
if (keys.down)
position -= camFront * moveSpeed;
if (keys.left)
position -= glm::normalize(glm::cross(camFront, glm::vec3(0.0f, 1.0f, 0.0f))) * moveSpeed;
if (keys.right)
position += glm::normalize(glm::cross(camFront, glm::vec3(0.0f, 1.0f, 0.0f))) * moveSpeed;

updateViewMatrix();
}
}
};

// Update camera passing separate axis data (gamepad)
// Returns true if view or position has been changed
bool updatePad(glm::vec2 axisLeft, glm::vec2 axisRight, float deltaTime) {
bool retVal = false;

if (type == CameraType::firstperson) {
// Use the common console thumbstick layout
// Left = view, right = move

const float deadZone = 0.0015f;
const float range = 1.0f - deadZone;

glm::vec3 camFront;
camFront.x = -cos(glm::radians(rotation.x)) * sin(glm::radians(rotation.y));
camFront.y = sin(glm::radians(rotation.x));
camFront.z = cos(glm::radians(rotation.x)) * cos(glm::radians(rotation.y));
camFront = glm::normalize(camFront);

float moveSpeed = deltaTime * movementSpeed * 2.0f;
float rotSpeed = deltaTime * rotationSpeed * 50.0f;

// Move
if (fabsf(axisLeft.y) > deadZone) {
float pos = (fabsf(axisLeft.y) - deadZone) / range;
position -= camFront * pos * ((axisLeft.y < 0.0f) ? -1.0f : 1.0f) * moveSpeed;
retVal = true;
}
if (fabsf(axisLeft.x) > deadZone) {
float pos = (fabsf(axisLeft.x) - deadZone) / range;
position += glm::normalize(glm::cross(camFront, glm::vec3(0.0f, 1.0f, 0.0f))) * pos * ((axisLeft.x < 0.0f) ? -1.0f : 1.0f) * moveSpeed;
retVal = true;
}

// Rotate
if (fabsf(axisRight.x) > deadZone) {
float pos = (fabsf(axisRight.x) - deadZone) / range;
rotation.y += pos * ((axisRight.x < 0.0f) ? -1.0f : 1.0f) * rotSpeed;
retVal = true;
}
if (fabsf(axisRight.y) > deadZone) {
float pos = (fabsf(axisRight.y) - deadZone) / range;
rotation.x -= pos * ((axisRight.y < 0.0f) ? -1.0f : 1.0f) * rotSpeed;
retVal = true;
}
} else {
// todo: move code from example base class for look-at
}

if (retVal) {
updateViewMatrix();
}

return retVal;
}
};

} // namespace inexor::vulkan_renderer
Loading

0 comments on commit fef9cc2

Please sign in to comment.