Skip to content

Commit

Permalink
opengl: added camera controller, to be tweaked
Browse files Browse the repository at this point in the history
  • Loading branch information
rxdu committed Nov 5, 2024
1 parent f3f75f0 commit 4b3eb84
Show file tree
Hide file tree
Showing 13 changed files with 202 additions and 31 deletions.
17 changes: 6 additions & 11 deletions src/app/panels/scene_panel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,26 +20,21 @@ ScenePanel::ScenePanel(const std::string& panel_name) : GlWidget(panel_name) {
this->SetNoTitleBar(true);
this->SetNoBackground(true);

camera_ =
std::make_unique<Camera>(glm::vec3(0.0f, 3.0f, 8.0f), -90.0f, -25.0f);

auto grid = std::make_unique<Grid>(10.0f, 1.0f, glm::vec3(0.7f, 0.7f, 0.7f));
this->AddOpenGLObject("grid", std::move(grid));
}

void ScenePanel::Draw() {
ImVec2 content_size = ImGui::GetContentRegionAvail();

// Orthographic projection for a top-down view
// get view matrices from camera
float aspect_ratio =
static_cast<float>(content_size.x) / static_cast<float>(content_size.y);
// std::cout << "aspect ratio: " << aspect_ratio << std::endl;
glm::mat4 projection =
glm::perspective(glm::radians(45.0f), aspect_ratio, 0.1f, 100.0f);

// Simple view matrix looking at an angle
glm::mat4 view = glm::lookAt(
glm::vec3(10.0f, 10.0f, 10.0f), // Camera positioned at an angle
glm::vec3(0.0f, 0.0f, 0.0f), // Looking at the origin
glm::vec3(0.0f, 1.0f, 0.0f) // Up vector pointing along the Y-axis
);
glm::mat4 projection = camera_->GetProjectionMatrix(aspect_ratio);
glm::mat4 view = camera_->GetViewMatrix();

UpdateView(projection, view);

Expand Down
4 changes: 4 additions & 0 deletions src/app/panels/scene_panel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,17 @@

#include "imview/widget/gl_widget.hpp"
#include "imview/component/opengl/grid.hpp"
#include "imview/component/opengl/camera.hpp"

namespace quickviz {
class ScenePanel : public GlWidget {
public:
ScenePanel(const std::string& panel_name);

void Draw() override;

private:
std::unique_ptr<Camera> camera_;
};
} // namespace quickviz

Expand Down
24 changes: 17 additions & 7 deletions src/imview/include/imview/component/opengl/camera.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,26 +40,36 @@ class Camera {
};

public:
enum class Movement { kForward, kBackward, kLeft, kRight };
enum class Movement { kForward, kBackward, kLeft, kRight, kUp, kDown };

public:
Camera(glm::vec3 position, float yaw, float pitch, float fov = default_fov);

void SetWorldUpVector(glm::vec3 up) { world_up_ = up; }

void Reset();
// public methods
glm::mat4 GetViewMatrix() const;
glm::mat4 GetProjectionMatrix(float aspect_ratio, float z_near = 0.1f,
float z_far = 100.0f) const;

void Reset();
void SetWorldUpVector(glm::vec3 up);
void LookAt(const glm::vec3& target);
glm::vec3 GetFront() const { return current_state_.front; }

void SetPosition(const glm::vec3& position);
glm::vec3 GetPosition() const { return current_state_.position; }
void SetYaw(float yaw);
float GetYaw() const { return current_state_.yaw; }
void SetPitch(float pitch);
float GetPitch() const { return current_state_.pitch; }
void SetFOV(float fov) { fov_ = fov; }
float GetFOV() const { return fov_; }
float GetMovementSpeed() const { return movement_speed_; }

void ProcessKeyboard(Movement direction, float dt);
void ProcessMouseMovement(float x_offset, float y_offset,
bool constrain_pitch = true);
void ProcessMouseScroll(float y_offset);

glm::vec3 GetPosition() const { return current_state_.position; }
glm::vec3 GetFront() const { return current_state_.front; }

private:
void UpdateCameraVectors();

Expand Down
23 changes: 22 additions & 1 deletion src/imview/include/imview/component/opengl/camera_controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,28 @@
#include "imview/component/opengl/camera.hpp"

namespace quickviz {
class CameraController {};
class CameraController {
public:
enum class Mode { kFirstPerson, kOrbit, kTopDown, kFreeLook };
using CameraMovement = Camera::Movement;

public:
CameraController(Camera& camera);

void SetMode(Mode mode);
void ProcessKeyboard(CameraMovement direction, float delta_time);
void ProcessMouseMovement(float x_offset, float y_offset);
void ProcessMouseScroll(float y_offset);

private:
void UpdateOrbitPosition();

Camera& camera_;
Mode mode_ = Mode::kOrbit;
glm::vec3 orbit_target_ = glm::vec3(0.0f, 0.0f, 0.0f);
float orbit_distance_ = 10.0f;
float top_down_height_ = 10.0f;
};
} // namespace quickviz

#endif // QUICKVIZ_CAMERA_CONTROLLER_HPP
2 changes: 2 additions & 0 deletions src/imview/include/imview/component/opengl/grid.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ class Grid : public OpenGLDrawable {

void SetLineColor(const glm::vec3& color, float alpha = 0.5f);

void InitGraphicsResources() override;
void DeinitGraphicsResources() override;
void OnDraw(const glm::mat4& projection, const glm::mat4& view) override;

private:
Expand Down
2 changes: 2 additions & 0 deletions src/imview/include/imview/component/opengl/triangle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ class Triangle : public OpenGLDrawable {

void SetColor(const glm::vec3& color, float alpha = 0.5f);

void InitGraphicsResources() override;
void DeinitGraphicsResources() override;
void OnDraw(const glm::mat4& projection, const glm::mat4& view) override;

private:
Expand Down
2 changes: 2 additions & 0 deletions src/imview/include/imview/interface/opengl_drawable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ class OpenGLDrawable {
virtual ~OpenGLDrawable() = default;

/****** public methods ******/
virtual void InitGraphicsResources() = 0;
virtual void DeinitGraphicsResources() = 0;
virtual void OnDraw(const glm::mat4& projection, const glm::mat4& view) = 0;
};
} // namespace quickviz
Expand Down
27 changes: 27 additions & 0 deletions src/imview/src/component/opengl/camera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ void Camera::Reset() {
UpdateCameraVectors();
}

void Camera::SetWorldUpVector(glm::vec3 up) {
world_up_ = up;
UpdateCameraVectors();
}

glm::mat4 Camera::GetViewMatrix() const {
return glm::lookAt(current_state_.position,
current_state_.position + current_state_.front,
Expand All @@ -44,6 +49,28 @@ glm::mat4 Camera::GetProjectionMatrix(float aspect_ratio, float z_near,
return glm::perspective(glm::radians(fov_), aspect_ratio, z_near, z_far);
}

void Camera::SetPosition(const glm::vec3& position) {
current_state_.position = position;
}

void Camera::SetYaw(float yaw) {
current_state_.yaw = yaw;
UpdateCameraVectors();
}

void Camera::SetPitch(float pitch) {
current_state_.pitch = pitch;
UpdateCameraVectors();
}

void Camera::LookAt(const glm::vec3& target) {
current_state_.front = glm::normalize(target - current_state_.position);
current_state_.right =
glm::normalize(glm::cross(current_state_.front, world_up_));
current_state_.up =
glm::normalize(glm::cross(current_state_.right, current_state_.front));
}

void Camera::UpdateCameraVectors() {
glm::vec3 front;
front.x = std::cos(glm::radians(current_state_.yaw)) *
Expand Down
74 changes: 73 additions & 1 deletion src/imview/src/component/opengl/camera_controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,76 @@

#include "imview/component/opengl/camera_controller.hpp"

namespace quickviz {} // namespace quickviz
namespace quickviz {
CameraController::CameraController(Camera& camera) : camera_(camera) {}

void CameraController::SetMode(CameraController::Mode mode) {
mode_ = mode;
if (mode == Mode::kTopDown) {
camera_.SetPosition(glm::vec3(0.0f, top_down_height_, 0.0f));
camera_.SetPitch(-90.0f);
camera_.SetYaw(0.0f);
}
}

void CameraController::ProcessKeyboard(
CameraController::CameraMovement direction, float delta_time) {
if (mode_ == Mode::kOrbit) return;
if (mode_ == Mode::kTopDown) {
float velocity = camera_.GetMovementSpeed() * delta_time;
glm::vec3 position = camera_.GetPosition();
// Move only along X and Z axes
if (direction == CameraMovement::kForward) position.z -= velocity;
if (direction == CameraMovement::kBackward) position.z += velocity;
if (direction == CameraMovement::kLeft) position.x -= velocity;
if (direction == CameraMovement::kRight) position.x += velocity;

camera_.SetPosition(position); // Update position without changing height
}
camera_.ProcessKeyboard(direction, delta_time);
}

void CameraController::ProcessMouseMovement(float x_offset, float y_offset) {
switch (mode_) {
case Mode::kFirstPerson:
case Mode::kFreeLook:
camera_.ProcessMouseMovement(x_offset, y_offset);
break;
case Mode::kOrbit:
camera_.ProcessMouseMovement(x_offset, y_offset);
UpdateOrbitPosition();
break;
case Mode::kTopDown:
// Ignore mouse movement for top-down view
break;
}
}

void CameraController::ProcessMouseScroll(float y_offset) {
if (mode_ == Mode::kOrbit) {
orbit_distance_ -= y_offset;
if (orbit_distance_ < 1.0f) orbit_distance_ = 1.0f;
UpdateOrbitPosition();
} else if (mode_ == Mode::kTopDown) {
glm::vec3 position = camera_.GetPosition();
position.y -= y_offset; // Adjust height (Y position) with scroll
if (position.y < 1.0f) position.y = 1.0f; // Set a minimum height
camera_.SetPosition(position);
} else {
camera_.ProcessMouseScroll(y_offset);
}
}

void CameraController::UpdateOrbitPosition() {
float cam_x = orbit_target_.x + orbit_distance_ *
cos(glm::radians(camera_.GetYaw())) *
cos(glm::radians(camera_.GetPitch()));
float cam_y =
orbit_target_.y + orbit_distance_ * sin(glm::radians(camera_.GetPitch()));
float cam_z = orbit_target_.z + orbit_distance_ *
sin(glm::radians(camera_.GetYaw())) *
cos(glm::radians(camera_.GetPitch()));
camera_.SetPosition(glm::vec3(cam_x, cam_y, cam_z));
camera_.LookAt(orbit_target_);
}
} // namespace quickviz
1 change: 0 additions & 1 deletion src/imview/src/component/opengl/frame_buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ void FrameBuffer::DestroyBuffers() {

void FrameBuffer::Bind(bool lock_aspect_ratio) const {
glBindFramebuffer(GL_FRAMEBUFFER, frame_buffer_);

if (lock_aspect_ratio) {
float expected_width = height_ * aspect_ratio_;
if (expected_width > width_) {
Expand Down
4 changes: 4 additions & 0 deletions src/imview/src/component/opengl/grid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ void Grid::SetLineColor(const glm::vec3& color, float alpha) {
alpha_ = alpha;
}

void Grid::InitGraphicsResources() {}

void Grid::DeinitGraphicsResources() {}

void Grid::OnDraw(const glm::mat4& projection, const glm::mat4& view) {
shader_.Use();
shader_.SetUniform("projection", projection);
Expand Down
4 changes: 4 additions & 0 deletions src/imview/src/component/opengl/triangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ void Triangle::SetColor(const glm::vec3& color, float alpha) {
alpha_ = alpha;
}

void Triangle::InitGraphicsResources() {}

void Triangle::DeinitGraphicsResources() {}

void Triangle::OnDraw(const glm::mat4& projection, const glm::mat4& view) {
shader_.Use();
shader_.SetUniform("projection", projection);
Expand Down
49 changes: 39 additions & 10 deletions src/imview/test/test_camera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "imview/window.hpp"
#include "imview/component/opengl/grid.hpp"
#include "imview/component/opengl/camera.hpp"
#include "imview/component/opengl/camera_controller.hpp"

using namespace quickviz;

Expand All @@ -27,23 +28,48 @@ float lastX = 1920 / 2.0f;
float lastY = 1080 / 2.0f;

Camera camera(glm::vec3(0.0f, 3.0f, 8.0f), -90.0f, -25.0f);
CameraController camera_controller(camera);

void ProcessInput(GLFWwindow* window) {
// if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) {
// std::cout << "W key pressed" << std::endl;
// camera.ProcessKeyboard(Camera::Movement::kForward, deltaTime);
// }
// if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) {
// std::cout << "S key pressed" << std::endl;
// camera.ProcessKeyboard(Camera::Movement::kBackward, deltaTime);
// }
// if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) {
// std::cout << "A key pressed" << std::endl;
// camera.ProcessKeyboard(Camera::Movement::kLeft, deltaTime);
// }
// if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) {
// std::cout << "D key pressed" << std::endl;
// camera.ProcessKeyboard(Camera::Movement::kRight, deltaTime);
// }
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) {
std::cout << "W key pressed" << std::endl;
camera.ProcessKeyboard(Camera::Movement::kForward, deltaTime);
camera_controller.ProcessKeyboard(
CameraController::CameraMovement::kForward, deltaTime);
}
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) {
std::cout << "S key pressed" << std::endl;
camera.ProcessKeyboard(Camera::Movement::kBackward, deltaTime);
camera_controller.ProcessKeyboard(
CameraController::CameraMovement::kBackward, deltaTime);
}
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) {
std::cout << "A key pressed" << std::endl;
camera.ProcessKeyboard(Camera::Movement::kLeft, deltaTime);
camera_controller.ProcessKeyboard(CameraController::CameraMovement::kLeft,
deltaTime);
}
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) {
std::cout << "D key pressed" << std::endl;
camera.ProcessKeyboard(Camera::Movement::kRight, deltaTime);
camera_controller.ProcessKeyboard(CameraController::CameraMovement::kRight,
deltaTime);
}
if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS) {
camera_controller.ProcessKeyboard(CameraController::CameraMovement::kUp,
deltaTime);
}
if (glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS) {
camera_controller.ProcessKeyboard(CameraController::CameraMovement::kDown,
deltaTime);
}
if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS) {
camera.Reset();
Expand All @@ -63,18 +89,21 @@ void MouseCallback(GLFWwindow* window, double xpos, double ypos) {
lastX = xpos;
lastY = ypos;

camera.ProcessMouseMovement(xoffset, yoffset);
// camera.ProcessMouseMovement(xoffset, yoffset);
camera_controller.ProcessMouseMovement(xoffset, yoffset);
}

void ScrollCallback(GLFWwindow* window, double xoffset, double yoffset) {
camera.ProcessMouseScroll(yoffset);
// camera.ProcessMouseScroll(yoffset);
camera_controller.ProcessMouseScroll(yoffset);
}

int main(int argc, char* argv[]) {
int width = 1920;
int height = 1080;
Window win("Test Window", width, height);

camera_controller.SetMode(CameraController::Mode::kTopDown);
glfwSetCursorPosCallback(win.GetWindowObject(), MouseCallback);
glfwSetScrollCallback(win.GetWindowObject(), ScrollCallback);
glfwSetInputMode(win.GetWindowObject(), GLFW_CURSOR, GLFW_CURSOR_DISABLED);
Expand Down

0 comments on commit 4b3eb84

Please sign in to comment.