KlassischeKeplerKriege/game/renderer_polygon_3d/camera.hpp
2016-10-04 16:25:23 +02:00

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;
};
}