RtB/src/RenderCamera.cpp

122 lines
3.3 KiB
C++

/* ================================================================
RenderCamera
----------------
This header file defines the RenderCamera class.
================================================================ */
#include "RenderCamera.hpp"
#include "Log.hpp"
#include <math.h> // fminf, M_PI
#define PI 3.1415926535897932384626433832795
#define PI_OVER_180 0.017453292519943295769236907684886
#define PI_OVER_360 0.0087266462599716478846184538424431
#ifndef fminf // Just for the winderps
#define fminf(a,b) (a) < (b) ? (a) : (b)
#endif
/* ======== Constructors and Destructors ======== */
RenderCamera::RenderCamera() {
fov_angle = M_PI / 4.0f;
size = 40.0f; // Default orthogonal size of 40 meters, vertically
near = 0.1f;
far = 512.0f;
pitch = yaw = 0;
render_mode = 0;
flags = 0;
width = height = 1;
render_view = NULL;
}
RenderCamera::~RenderCamera() {
}
/* ======== Update functions ======== */
void RenderCamera::updateProjection(int width_, int height_) {
width = width_;
height = height_;
GLfloat wf = (GLfloat)width;
GLfloat hf = (GLfloat)height;
GLfloat aspect = wf/hf;
if (render_mode == 0) {
float y = 1.0f / tan((fov_angle)/2.0f);
float x = (1/(aspect))*y;
p_matrix[0] = Vec4(x, 0.0f, 0.0f, 0.0f);
p_matrix[1] = Vec4(0.0f, y, 0.0f, 0.0f);
p_matrix[2] = Vec4(0.0f, 0.0f, far/(far-near), 1.0f);
p_matrix[3] = Vec4(0.0f, 0.0f, -((far*near)/(far-near)), 0.0f);
} else {
float x = size * aspect;
float y = size;
p_matrix[0] = Vec4(2.0f / x, 0.0f, 0.0f, 0.0f);
p_matrix[1] = Vec4(0.0f, 2.0f / y, 0.0f, 0.0f);
p_matrix[2] = Vec4(0.0f, 0.0f, 1.0f/(far-near), 0.0f);
p_matrix[3] = Vec4(0.0f, 0.0f, -near/(far-near), 1.0f);
}
}
void RenderCamera::doRefresh() {
if (!(flags & DIRTY)) return;
float c_p = cos(pitch * M_PI / 180.0f);
float s_p = sin(pitch * M_PI / 180.0f);
float c_y = cos(yaw * M_PI / 180.0f);
float s_y = sin(yaw * M_PI / 180.0f);
Vec3 x(c_y, 0, -s_y);
Vec3 y(s_y*s_p, c_p, c_y * s_p);
Vec3 z(s_y * c_p, -s_p, c_p * c_y);
mv_matrix = Mat4(
Vec4(x.x, y.x, z.x, 0.0f),
Vec4(x.y, y.y, z.y, 0.0f),
Vec4(x.z, y.z, z.z, 0.0f),
Vec4(-x.dotProduct(position), -y.dotProduct(position), -z.dotProduct(position), 1.0f)
);
flags &= ~DIRTY;
}
/* ======== Setter functions ======== */
// sets to orthogonal or perspective rendering
void RenderCamera::setRenderMode(int mode) {
if (mode == 1) {
render_mode = mode;
} else {
render_mode = 0;
}
updateProjection(width, height);
}
int RenderCamera::setRenderView(RenderView *rv) {
if (rv == NULL) return 1;
render_view = rv;
return 0;
}
void RenderCamera::setPosition(float x, float y, float z) {
position.x = x;
position.y = y;
position.z = z;
flags |= DIRTY;
}
void RenderCamera::setPitch(float pitch_) {
pitch = pitch_;
flags |= DIRTY;
}
void RenderCamera::setYaw(float yaw_) {
yaw = yaw_;
flags |= DIRTY;
}
/* ======== Getter functions ======== */
RenderView* RenderCamera::getRenderView() {
return render_view;
}
Vec3 RenderCamera::getPosition() {
return position;
}
float RenderCamera::getYaw() {
return yaw;
}
float RenderCamera::getPitch() {
return pitch;
}
float RenderCamera::getSize() {
return size;
}
Mat4 RenderCamera::getModelview() {
return mv_matrix;
}
int RenderCamera::getRenderMode() {
return render_mode;
}