142 lines
4.1 KiB
C++
142 lines
4.1 KiB
C++
#pragma once
|
|
|
|
#include <glm/gtc/type_ptr.hpp>
|
|
#include <glm/gtx/euler_angles.hpp>
|
|
#include <glm/gtc/random.hpp>
|
|
#include <glm/vec3.hpp>
|
|
#include <glm/gtc/matrix_transform.hpp>
|
|
|
|
namespace endofthejedi {
|
|
// TODO:
|
|
// add shaking attributes to camera too
|
|
// and dirt effects
|
|
|
|
class Camera {
|
|
public:
|
|
Camera()
|
|
: m_aspectRatio(1.0), m_fov(util::deg2rad(90.0))
|
|
, m_zoom(1.0), m_position(0.0, 0.0, 0.0), m_angles(0.0, 0.0, 0.0)
|
|
, m_dirty(true)
|
|
{
|
|
}
|
|
|
|
// set camera zoom:
|
|
// 0 makes no sense,
|
|
// << 1 scales down
|
|
// 1 is neutral
|
|
// >> 1 makes things bigger
|
|
void setZoom(float zoom)
|
|
{
|
|
if (zoom != m_zoom) {
|
|
m_zoom = zoom;
|
|
m_dirty = true;
|
|
}
|
|
}
|
|
|
|
// set field of view.
|
|
// degree or radian? find it out.
|
|
void setFov(float fov)
|
|
{
|
|
if (fov != m_fov) {
|
|
m_fov = fov;
|
|
m_dirty = true;
|
|
}
|
|
}
|
|
|
|
// position of the camera in world space
|
|
void setPosition(const glm::vec3 &pos)
|
|
{
|
|
if (pos != m_position) {
|
|
m_position = pos;
|
|
m_dirty = true;
|
|
}
|
|
}
|
|
|
|
// some angles (in rad) for the camera.
|
|
void setAngles(const glm::vec3 &angles)
|
|
{
|
|
if (angles != m_angles) {
|
|
m_angles = angles;
|
|
m_dirty = true;
|
|
}
|
|
}
|
|
|
|
// all three arguments.
|
|
void setPositionAnglesZoom(const glm::vec3 &position, const glm::vec3 &angles, float zoom)
|
|
{
|
|
setZoom(zoom);
|
|
setPosition(position);
|
|
setAngles(angles);
|
|
}
|
|
|
|
float fov() const { return m_fov; }
|
|
float zoom() const { return m_zoom; }
|
|
const glm::vec3 &position() const { return m_position; }
|
|
const glm::vec3 &angles() const { return m_angles; }
|
|
float aspectRatio() const { return m_aspectRatio; }
|
|
|
|
void setAspectRatio(float r)
|
|
{
|
|
if (r != m_aspectRatio) {
|
|
m_aspectRatio = r;
|
|
m_dirty = true;
|
|
}
|
|
}
|
|
|
|
// recompute view matrix. return true if it was dirty and is now clean
|
|
// and recomputed.
|
|
bool refresh()
|
|
{
|
|
if (m_dirty) {
|
|
m_dirty = false;
|
|
recomputeMatrix();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
const glm::mat4 &viewMatrix() const { return m_viewMatrix; }
|
|
|
|
void recomputeMatrix()
|
|
{
|
|
glm::mat4 view;
|
|
|
|
// TODO: rest is smissing
|
|
|
|
//float a = 2.0*M_PI*m_lastTime/10.0;
|
|
//float s = glm::mod(m_lastTime, 5.0f)/1.0f;
|
|
view = glm::scale(view, glm::vec3(m_zoom, m_zoom, m_zoom));
|
|
view = glm::translate(view, m_position);
|
|
view = glm::rotate(view, m_angles.x, glm::vec3(1.0f, 0.0f, 0.0f));
|
|
view = glm::rotate(view, m_angles.y, glm::vec3(0.0f, 1.0f, 0.0f));
|
|
view = glm::rotate(view, m_angles.z, glm::vec3(0.0f, 0.0f, 1.0f));
|
|
|
|
// Generates a really hard-to-read matrix, but a normal, standard 4x4 matrix nonetheless
|
|
glm::mat4 projectionMatrix = glm::perspective(
|
|
// The horizontal Field of View, in degrees : the amount of
|
|
// "zoom". Think "camera lens". Usually between 90° (extra
|
|
// wide) and 30° (quite zoomed in)
|
|
m_fov,
|
|
|
|
m_aspectRatio, // aspect ratio
|
|
0.1f, // near clipping plane
|
|
100.0f // far clipping plane
|
|
);
|
|
|
|
|
|
|
|
//m_viewMatrix = view;
|
|
m_viewMatrix = projectionMatrix * view;
|
|
}
|
|
|
|
private:
|
|
float m_aspectRatio;
|
|
float m_fov;
|
|
float m_zoom;
|
|
glm::vec3 m_position;
|
|
glm::vec3 m_angles;
|
|
bool m_dirty;
|
|
|
|
glm::mat4 m_viewMatrix;
|
|
};
|
|
}
|