Skip to content

Instantly share code, notes, and snippets.

@Journeyman1337
Created October 10, 2021 19:01
Show Gist options
  • Save Journeyman1337/46f47de48370718ca0a300766ed17b14 to your computer and use it in GitHub Desktop.
Save Journeyman1337/46f47de48370718ca0a300766ed17b14 to your computer and use it in GitHub Desktop.
camera and transform
#include "Camera.hpp"
Camera::Camera() : view_changed(true), view_matrix(1.0f), projection_changed(true), projection_matrix(1.0f), view_projection_changed(true), view_projection_matrix(1.0f), projection(Projection::Orthographic), orthographic_size(0.0f), perspective_fov(90.0f), screen_dimensions(1.0f, 1.0f)
{
}
const glm::mat4& Camera::GetViewMatrix()
{
if (this->view_changed == true)
{
this->view_matrix = glm::lookAt(this->position, this->position + this->GetForwardDirection(), this->position + this->GetUpDirection());
this->view_changed = false;
this->view_projection_changed = true;
}
return this->view_matrix;
}
const glm::mat4& Camera::GetProjectionMatrix()
{
if (this->projection_changed == true)
{
if (this->projection == Projection::Perspective)
{
this->projection_matrix = glm::perspectiveFov(this->perspective_fov, this->screen_dimensions.x, this->screen_dimensions.y, 0.1f, 100.0f);
}
else if (this->projection == Projection::Orthographic)
{
float orthographic_width = this->orthographic_size * screen_dimensions.x;
float orthographic_height = this->orthographic_size * screen_dimensions.y;
this->projection_matrix = glm::ortho(orthographic_width / 2, orthographic_width / 2, -orthographic_height / 2, orthographic_height / 2);
}
this->projection_changed = false;
this->view_projection_changed = true;
}
return this->projection_matrix;
}
const glm::mat4& Camera::GetViewPorjectionMatrix()
{
if (this->view_changed == true || this->projection_changed == true || view_projection_changed == true)
{
this->view_projection_matrix == this->GetProjectionMatrix() * this->GetViewMatrix();
this->view_projection_changed = false;
}
return this->view_projection_matrix;
}
float Camera::GetPerspectiveFov() const
{
return this->perspective_fov;
}
float Camera::GetOrthographicSize() const
{
return this->orthographic_size;
}
Camera::Projection Camera::GetProjection() const
{
return this->projection;
}
const glm::vec2& Camera::GetScreenDimensions() const
{
return this->screen_dimensions;
}
void Camera::SetProjection(Projection projection)
{
this->projection_changed = true; //even if Camera* is casted to Transform*, this still gets set correctly...
this->projection = projection;
}
void Camera::SetPerspectiveFov(float fov)
{
this->perspective_fov = fov;
this->projection_changed = true;
}
void Camera::SetOrthographicSize(float size)
{
this->orthographic_size = size;
this->projection_changed = true;
}
void Camera::SetScreenDimensions(const glm::vec2& dimensions)
{
this->projection_changed = true;
this->screen_dimensions = dimensions;
}
void Camera::SetPosition(const glm::vec3& position)
{
this->view_changed = true;
Transform::SetPosition(position);
}
void Camera::SetRotation(const glm::quat& rotation)
{
this->view_changed = true;
Transform::SetRotation(rotation);
}
void Camera::SetScale(const glm::vec3& scale)
{
Transform::SetScale(scale);
}
void Camera::Translate(const glm::vec3& translation)
{
this->view_changed = true;
Transform::Translate(translation);
}
void Camera::Scale(const glm::vec3& scale)
{
Transform::Scale(scale);
}
void Camera::ScaleScalar(const float& scalar)
{
Transform::ScaleScalar(scalar);
}
void Camera::Rotate(const glm::quat& rotation)
{
this->view_changed = true;
Transform::Rotate(rotation);
}
void Camera::RotateEuler(const glm::vec3& angles)
{
this->view_changed = true;
Transform::RotateEuler(angles);
}
void Camera::LookAt(const glm::vec3& target_position)
{
this->view_changed = true;
Transform::LookAt(target_position);
}
#pragma once
#include "Transform.hpp"
#include <glm/glm.hpp>
class Camera : public Transform
{
public:
enum class Projection
{
Perspective,
Orthographic
};
protected:
bool view_changed;
glm::mat4 view_matrix;
bool projection_changed;
glm::mat4 projection_matrix;
bool view_projection_changed;
glm::mat4 view_projection_matrix;
Projection projection;
float perspective_fov;
glm::vec2 screen_dimensions;
float orthographic_size;
public:
Camera();
~Camera() = default;
Camera(const Camera& other) = delete;
using Transform::Transform;
const glm::mat4& GetViewMatrix();
const glm::mat4& GetProjectionMatrix();
const glm::mat4& GetViewPorjectionMatrix();
float GetPerspectiveFov() const;
float GetOrthographicSize() const;
Projection GetProjection() const;
const glm::vec2& GetScreenDimensions() const;
void SetProjection(Projection projection);
void SetPerspectiveFov(float fov);
void SetOrthographicSize(float size);
void SetScreenDimensions(const glm::vec2& dimensions);
void SetPosition(const glm::vec3& position) override;
void SetRotation(const glm::quat& rotation) override;
void SetScale(const glm::vec3& scale) override;
void Translate(const glm::vec3& translation) override;
void Scale(const glm::vec3& scale) override;
void ScaleScalar(const float& scalar) override;
void Rotate(const glm::quat& rotation) override;
void RotateEuler(const glm::vec3& angles) override;
void LookAt(const glm::vec3& target_position) override;
};
#include "Transform.hpp"
#include "Camera.hpp"
#include <glm/ext/quaternion_transform.hpp>
#include <glm/gtx/transform.hpp>
Transform::Transform() : position(0.0f, 0.0f, 0.0f), rotation(), scale(1.0f, 1.0f, 1.0f), model_changed(true), model_matrix(1.0f)
{
}
const glm::mat4& Transform::GetModelMatrix()
{
if (this->model_changed == true)
{
// when you multiply glm objects it goes in opposite order.
// first scale, then rotation, then translation.
this->model_matrix = glm::mat4(1.0f);
glm::scale(this->model_matrix, this->scale);
glm::mat4 rotation_matrix = glm::toMat4(this->rotation);
this->model_matrix *= rotation_matrix;
glm::translate(this->model_matrix, this->position);
}
return this->model_matrix;
}
const glm::vec3& Transform::GetPosition() const
{
return this->position;
}
const glm::quat& Transform::GetRotation() const
{
return this->rotation;
}
const glm::vec3& Transform::GetScale() const
{
return this->scale;
}
glm::vec3 Transform::GetEulerAngles() const
{
return glm::eulerAngles(this->rotation);
}
glm::vec3 Transform::GetForwardDirection() const
{
return this->rotation * glm::vec3(0.0f, 1.0f, 0.0f);
}
glm::vec3 Transform::GetBackwardDirection() const
{
return this->rotation * glm::vec3(0.0f, -1.0f, 0.0f);
}
glm::vec3 Transform::GetRightDirection() const
{
return this->rotation * glm::vec3(1.0f, 0.0f, 0.0f);
}
glm::vec3 Transform::GetLeftDirection() const
{
return this->rotation * glm::vec3(-1.0f, 0.0f, 0.0f);
}
glm::vec3 Transform::GetUpDirection() const
{
return this->rotation * glm::vec3(0.0f, 0.0f, 1.0f);
}
glm::vec3 Transform::GetDownDirection() const
{
return this->rotation * glm::vec3(0.0f, 0.0f, -1.0f);
}
void Transform::SetPosition(const glm::vec3& position)
{
this->model_changed = true;
this->position = position;
}
void Transform::SetRotation(const glm::quat& rotation)
{
this->model_changed = true;
this->rotation = rotation;
}
void Transform::SetScale(const glm::vec3& scale)
{
this->model_changed = true;
this->scale = scale;
}
void Transform::Translate(const glm::vec3& translation)
{
this->model_changed = true;
this->position += translation;
}
void Transform::Scale(const glm::vec3& scale)
{
this->model_changed = true;
this->scale *= scale;
}
void Transform::ScaleScalar(const float& scalar)
{
this->model_changed = true;
this->scale *= scalar;
}
void Transform::Rotate(const glm::quat& rotation)
{
this->model_changed = true;
this->rotation *= rotation;
}
void Transform::RotateEuler(const glm::vec3& angles)
{
this->model_changed = true;
glm::rotate(this->rotation, angles.x, this->GetRightDirection());
glm::rotate(this->rotation, angles.y, this->GetForwardDirection());
glm::rotate(this->rotation, angles.z, this->GetUpDirection());
}
void Transform::LookAt(const glm::vec3& target_position)
{
this->model_changed = true;
auto new_direction = glm::normalize(this->position - target_position);
glm::vec3 right = glm::normalize(glm::cross(glm::vec3(0.0f, 1.0f, 0.0f), new_direction));
glm::vec3 up = glm::cross(new_direction, right);
this->rotation = glm::conjugate(glm::toQuat(glm::lookAt(this->position, target_position, up)));
}
glm::mat4 GetMVP(Transform& transform, Camera& camera)
{
return camera.GetProjectionMatrix() * camera.GetViewMatrix() * transform.GetModelMatrix();
}
#pragma once
#include <glm/glm.hpp>
#include <glm/gtx/quaternion.hpp>
class Transform
{
protected:
glm::vec3 position;
glm::quat rotation;
glm::vec3 scale;
bool model_changed;
glm::mat4 model_matrix;
public:
Transform();
~Transform() = default;
Transform(const Transform& other) = delete;
const glm::mat4& GetModelMatrix();
const glm::vec3& GetPosition() const;
const glm::quat& GetRotation() const;
const glm::vec3& GetScale() const;
glm::vec3 GetEulerAngles() const;
glm::vec3 GetForwardDirection() const;
glm::vec3 GetBackwardDirection() const;
glm::vec3 GetRightDirection() const;
glm::vec3 GetLeftDirection() const;
glm::vec3 GetUpDirection() const;
glm::vec3 GetDownDirection() const;
virtual void SetPosition(const glm::vec3& position);
virtual void SetRotation(const glm::quat& rotation);
virtual void SetScale(const glm::vec3& scale);
virtual void Translate(const glm::vec3& translation);
virtual void Scale(const glm::vec3& scale);
virtual void ScaleScalar(const float& scalar);
virtual void Rotate(const glm::quat& rotation);
virtual void RotateEuler(const glm::vec3& angles);
virtual void LookAt(const glm::vec3& target_position);
};
class Camera;
glm::mat4 GetMVP(Transform& transform, Camera& camera);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment