diff --git a/src/Engine/entities/camera.cpp b/src/Engine/entities/camera.cpp index 7cdff68..74bdc73 100644 --- a/src/Engine/entities/camera.cpp +++ b/src/Engine/entities/camera.cpp @@ -4,8 +4,34 @@ Camera* Camera::current_camera{}; -// Helper function prototype -bool operator == (CameraOrientation& a, CameraOrientation& b); +/// HELPER STUFF + +glm::vec3 AxisData::front() const +{ + return std::move(glm::normalize(glm::cross(up, right))); +} + +glm::vec3 CameraOrientation::target() const +{ + return std::move(position + focal_dist * axes.front()); +} + +// These are linked statically to prevent external use. May be exposed later. + +static bool operator == (AxisData& a, AxisData& b) +{ + return (a.right == b.right) && + (a.up == b.up); +} + +static bool operator == (CameraOrientation& a, CameraOrientation& b) +{ + return (a.position == b.position) && + (a.axes == b.axes) && + (a.focal_dist == b.focal_dist); +} + +/// Camera class methods Camera::Camera(CameraOrientation& o) : orientation(std::move(o)) {} @@ -19,55 +45,52 @@ void Camera::stop() { flush(); } -void Camera::setDirection(float yaw, float pitch) +void Camera::ypr(float yaw, float pitch, float roll) { - orientation.direction.x = cos(glm::radians(pitch)) * cos(glm::radians(yaw)); - orientation.direction.y = sin(glm::radians(pitch)); - orientation.direction.z = cos(glm::radians(pitch)) * sin(glm::radians(yaw)); - orientation.direction *= -1; + // Roll + auto front = orientation.axes.front(); + auto roll_mat = glm::rotate(glm::mat4(1.0f), glm::radians(roll), front); + orientation.axes.right = roll_mat * orientation.axes.right; + orientation.axes.up = roll_mat * orientation.axes.up; + // Yaw + orientation.axes.right = glm::rotate(glm::mat4(1.0f), glm::radians(yaw), orientation.axes.up) * orientation.axes.right; + // Pitch + orientation.axes.up = glm::rotate(glm::mat4(1.0f), glm::radians(pitch), orientation.axes.right) * orientation.axes.up; } -void Camera::setDirection(glm::vec3& target) +void Camera::lookAt(glm::vec3& target) { - orientation.direction = glm::normalize(target - orientation.position); + // Get previous roll value in radians + auto prev_direction = orientation.axes.front(); + auto fk_right = glm::normalize(glm::cross(prev_direction, Directions::UP)); + float roll = acos(glm::dot(fk_right, orientation.axes.right)); + + // Get the direction right + auto direction = glm::normalize(target - orientation.position); + orientation.axes.right = glm::normalize(glm::cross(direction, Directions::UP)); + orientation.axes.up = glm::normalize(glm::cross(orientation.axes.right, direction)); + + // Roll + auto front = orientation.axes.front(); + auto roll_mat = glm::rotate(glm::mat4(1.0f), roll, front); + orientation.axes.right = roll_mat * orientation.axes.right; + orientation.axes.up = roll_mat * orientation.axes.up; } -void Camera::setPosition(glm::vec3& pos) +void Camera::recompute() { - orientation.position = pos; -} - -void Camera::setRoll(float roll) -{ - orientation.roll = roll; -} - -void Camera::recompute_if_dirty() -{ - if (orientation == previous_orientation) - { - return; - } - recalculateAxes(); - viewMatrix = glm::lookAt(orientation.position, orientation.target(), axes.up); - previous_orientation = orientation; + viewMatrix = glm::lookAt(orientation.position, orientation.target(), orientation.axes.up); } void Camera::flush() { if (current_camera) { - current_camera->recompute_if_dirty(); + current_camera->recompute(); } setViewMatrix(current_camera); } -void Camera::recalculateAxes() -{ - axes.right = glm::normalize(glm::cross(Directions::UP, -orientation.direction)); - axes.up = glm::normalize(glm::cross(-orientation.direction, axes.right)); -} - void Camera::setViewMatrix(Camera* c) { glm::mat4 mat(1.0f); @@ -78,17 +101,36 @@ void Camera::setViewMatrix(Camera* c) Program::current_program->setMat4(Program::current_program->metadata.view_mat_name, mat); } -// HELPER STUFF +/// Camera movement methods -glm::vec3 CameraOrientation::target() -{ - return std::move(position + focal_dist * direction); +void Camera::rmoveFD(float amt) { + orientation.position += amt * orientation.axes.front(); } -bool operator == (CameraOrientation& a, CameraOrientation& b) -{ - return (a.position == b.position) && - (a.direction == b.direction) && - (a.roll == b.roll) && - (a.focal_dist == b.focal_dist); +void Camera::rmoveBK(float amt) { + orientation.position += amt * orientation.axes.front(); +} + +void Camera::rmoveRT(float amt) { + orientation.position += amt * orientation.axes.right; +} + +void Camera::rmoveLT(float amt) { + orientation.position += amt * orientation.axes.right; +} + +void Camera::rmoveUP(float amt) { + orientation.position += amt * orientation.axes.up; +} + +void Camera::rmoveDN(float amt) { + orientation.position += amt * orientation.axes.up; +} + +void Camera::rturnLT(float amt) { + ypr(amt, 0, 0); +} + +void Camera::rturnRT(float amt) { + ypr(amt, 0, 0); } \ No newline at end of file diff --git a/src/Engine/entities/camera.h b/src/Engine/entities/camera.h index c69b741..9a96922 100644 --- a/src/Engine/entities/camera.h +++ b/src/Engine/entities/camera.h @@ -3,22 +3,22 @@ #include "../window.h" #include -// Roll is not implemented. +struct AxisData +{ + glm::vec3 up; + glm::vec3 right; + + glm::vec3 front() const; +}; + struct CameraOrientation { glm::vec3 position; - glm::vec3 direction; - float roll; + AxisData axes; float focal_dist; - glm::vec3 target(); -}; - -struct AxisData -{ - glm::vec3 up; - glm::vec3 right; + glm::vec3 target() const; }; class Camera { @@ -28,27 +28,46 @@ class Camera { void stop(); CameraOrientation orientation; - void setDirection(float yaw, float pitch); - void setDirection(glm::vec3& target); - void setPosition(glm::vec3& pos); - void setRoll(float roll); + + // Yaw, pitch by a certain amount in degrees. Incremental. + // +ve yaw: towards left of axes.front() + // OR anticlockwise along axes.up (right hand thumb rule) + // +ve pitch: upwards ( axes.up --> see Camera::axes) + // OR anticlockwise along axes.right (right hand thumb rule) + // +ve roll: Anticlockwise along orientation.direction (right hand thumb rule) + void ypr(float yaw, float pitch, float roll); + // Set a target to look at. + void lookAt(glm::vec3& target); // Mostly to be used by flush() but can be used manually. - void recompute_if_dirty(); + void recompute(); static void flush(); static Camera* current_camera; -private: - AxisData axes; - void recalculateAxes(); + // Move methods + void rmoveFD(float amt = FDBK); + void rmoveBK(float amt = -FDBK); + void rmoveRT(float amt = LTRT); + void rmoveLT(float amt = -LTRT); + void rmoveUP(float amt = UPDN); + void rmoveDN(float amt = -UPDN); + void rturnRT(float amt = YAWM); + void rturnLT(float amt = -YAWM); +private: glm::mat4 viewMatrix; static void setViewMatrix(Camera* c); - // Contains the previous orientation - CameraOrientation previous_orientation; + /// Default movement weights + + constexpr static float UPDN = 0.05f; + constexpr static float LTRT = 0.075f; + constexpr static float FDBK = 0.075f; + + // This should always be -ve for directions to make sense. + constexpr static float YAWM = -1.0f; }; namespace Directions { diff --git a/src/Engine/input_handler.h b/src/Engine/input_handler.h index adcdc37..fcc6650 100644 --- a/src/Engine/input_handler.h +++ b/src/Engine/input_handler.h @@ -7,16 +7,24 @@ class InputHandler { public: - InputHandler(Window* window); - void attach(Window* window); + void attach(Window* wndow); + virtual void listen() = 0; + +protected: + Window* attached_window; +}; + +class KeyboardInputHandler : InputHandler { + +public: + KeyboardInputHandler(Window* window); void connect(int key, std::function func); void connect(std::vector keys, std::function func); void disconnect(int key); void disconnect(std::vector keys); - void listen(); + void listen() override; private: - Window* attached_window; std::vector>> binds; std::vector, std::function>> binds_m; }; \ No newline at end of file diff --git a/src/Engine/input_handler.cpp b/src/Engine/kbd_input_handler.cpp similarity index 64% rename from src/Engine/input_handler.cpp rename to src/Engine/kbd_input_handler.cpp index f4a36c2..b35247d 100644 --- a/src/Engine/input_handler.cpp +++ b/src/Engine/kbd_input_handler.cpp @@ -1,29 +1,31 @@ #include #include "input_handler.h" -InputHandler::InputHandler(Window* window) +void InputHandler::attach(Window* window) { - attach(window); + attached_window = window; } -void InputHandler::attach(Window* window) +/// Specific stuff + +KeyboardInputHandler::KeyboardInputHandler(Window* window) { - attached_window = window; + this->attach(window); } -void InputHandler::connect(int key, std::function func) +void KeyboardInputHandler::connect(int key, std::function func) { auto pair = std::make_pair(key, func); binds.push_back(pair); } -void InputHandler::connect(std::vector keys, std::function func) +void KeyboardInputHandler::connect(std::vector keys, std::function func) { auto pair = std::make_pair(keys, func); binds_m.push_back(pair); } -void InputHandler::disconnect(int key) +void KeyboardInputHandler::disconnect(int key) { for (int i = 0; i < binds.size(); i++) { @@ -34,7 +36,7 @@ void InputHandler::disconnect(int key) } } -void InputHandler::disconnect(std::vector keys) +void KeyboardInputHandler::disconnect(std::vector keys) { for (int i = 0; i < binds_m.size(); i++) { @@ -45,7 +47,7 @@ void InputHandler::disconnect(std::vector keys) } } -void InputHandler::listen() +void KeyboardInputHandler::listen() { auto* ptr = attached_window->getWindowPointer(); for (auto b : binds) diff --git a/src/Engine/main.cpp b/src/Engine/main.cpp index 4f05688..0d7eac9 100644 --- a/src/Engine/main.cpp +++ b/src/Engine/main.cpp @@ -22,7 +22,7 @@ int main() auto *window = new Window(600, 600, "OpenGL Engine " + version, {45.0f, 0.1f, 100.0f}); Initializer::GLAD_Init(); - auto *handler = new InputHandler(window); + auto *handler = new KeyboardInputHandler(window); handler->connect(GLFW_KEY_ESCAPE, [&window]() { window->close(); }); @@ -54,26 +54,36 @@ int main() prog->setInt("texture0", *container); prog->setInt("texture1", *smile); - CameraOrientation o{glm::vec3(0, 0, 3), Directions::INTO_SCREEN, 0.0f, 1.0f}; + CameraOrientation o{glm::vec3(0, 0, 2), {Directions::UP, Directions::RIGHT}, 1.0f}; auto *cam = new Camera(o); cam->start(); - auto mix_ratio = PingPongMap(0, 1, 0.5); + handler->connect(GLFW_KEY_W, [&cam]() { cam->rmoveFD(); }); + handler->connect(GLFW_KEY_S, [&cam]() { cam->rmoveBK(); }); + handler->connect(GLFW_KEY_Q, [&cam]() { cam->rmoveLT(); }); + handler->connect(GLFW_KEY_E, [&cam]() { cam->rmoveRT(); }); + + handler->connect(GLFW_KEY_A, [&cam]() { cam->rturnLT(); }); + handler->connect(GLFW_KEY_D, [&cam]() { cam->rturnRT(); }); + + auto camera_y = SinMap(0.3, 8, 0.4); glClearColor(0.1f, 0.1f, 0.1f, 1.0f); + prog->setFloat("ratio", 0.7f); + + //cam->ypr(0, 0, 10.0f); + while (!window->should_close()) { Window::clear(); handler->listen(); - - prog->setFloat("ratio", mix_ratio); - instance->orientation.position.z = mix_ratio; - instance->orientation.rotation.x -= 0.7f; - instance->orientation.rotation.y += 0.57f; instance->render(); + //cam->orientation.position.y = camera_y; + //cam->lookAt(instance->orientation.position); + //cam->ypr(0,0, 10); Camera::flush(); window->buffer_swap(); } diff --git a/src/GLCore/base/gl_math_defs.h b/src/GLCore/base/gl_math_defs.h index e8758b7..45996a1 100644 --- a/src/GLCore/base/gl_math_defs.h +++ b/src/GLCore/base/gl_math_defs.h @@ -4,3 +4,7 @@ #include #include +inline glm::vec3 operator * (glm::mat4 m, glm::vec3 v) +{ + return std::move(glm::vec3(m * glm::vec4(v, 1.0f))); +}