GraphicsTest/Camera.cpp

184 lines
4.7 KiB
C++

#include "Camera.h"
namespace NB {
// Camera class
Camera::Camera(const Vec3& pos, const Vec3& tar, const Vec3& up) {
_pos = pos;
_tar = tar;
_world_up = glm::normalize(up);
_dir = glm::normalize(_tar-_pos);
_right = normCross(_dir, _world_up);
_up = normCross(_right, _dir);
_proj = glm::ortho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f);
_calcLook();
}
void Camera::_calcLook() {
_look = glm::lookAt(_pos, _tar, (_lock_world_up)?_world_up:_up);
}
glm::vec3 Camera::normCross(const Vec3& a, const Vec3& b) {
return glm::normalize(glm::cross(a, b));
}
glm::vec3 Camera::transformVec(const Mat4& mat, const Vec3& vec) {
return Vec3(mat * glm::vec4(vec, 1.0f));
}
glm::vec3 Camera::getPos() const { return _pos; }
glm::vec3 Camera::getTarget() const { return _tar; }
glm::vec3 Camera::getDirection() const { return _dir; }
glm::vec3 Camera::getWorldUp() const { return _world_up; }
glm::vec3 Camera::getUp() const { return _up; }
glm::vec3 Camera::getRight() const { return _right; }
glm::mat4 Camera::getLookMatrix() const { return _look; }
glm::mat4 Camera::getProjectionMatrix() const { return _proj; }
glm::mat4 Camera::getFlattenedMatrices() const { return _proj * _look; }
bool Camera::isUpLocked() const { return _lock_world_up; }
void Camera::setProjection(const Mat4& proj) {
_proj = proj;
}
void Camera::setPos(const Vec3& pos) {
_pos = pos;
_calcLook();
}
void Camera::setTarget(const Vec3& tar) {
_tar = tar;
_dir = glm::normalize(_tar-_pos);
_right = normCross(_dir, _world_up);
_up = normCross(_right, _dir);
_calcLook();
}
void Camera::setDirection(const Vec3& dir) {
setTarget(glm::normalize(dir)+_pos);
}
void Camera::setWorldUp(const Vec3& up) {
_world_up = up;
_right = normCross(_dir, _up);
_up = normCross(_right, _dir);
_calcLook();
}
void Camera::lockToWorldUp(bool lock) {
if (!_lock_world_up && lock) {
resetUp();
}
_lock_world_up = lock;
}
void Camera::resetUp() {
_right = normCross(_dir, _world_up);
_up = normCross(_right, _dir);
_calcLook();
}
void Camera::addPos(const Vec3& add) {
_pos += add;
_dir = glm::normalize(_tar-_pos);
if (_lock_world_up) {
_right = normCross(_dir, _world_up);
} else {
_right = normCross(_dir, _up);
_up = normCross(_right, _dir);
}
_calcLook();
}
void Camera::panPos(const Vec3& add) {
_tar += add;
addPos(add);
}
void Camera::panPosRelative(const Vec3& add) {
panPos(add.x*_right + add.y*((_lock_world_up)?_world_up:_up) + add.z*_dir);
}
void Camera::addTarget(const Vec3& add) {
_tar += add;
_dir = glm::normalize(_tar-_pos);
_right = normCross(_dir, _world_up);
_up = normCross(_right, _dir);
_calcLook();
}
void Camera::roll(float ang) {
if (!_lock_world_up) {
Mat4 rot_mat = glm::rotate(Mat4(1.0f), ang, _dir);
_right = transformVec(rot_mat, _right);
_up = transformVec(rot_mat, _up);
_calcLook();
}
}
void Camera::pitch(float ang) {
Mat4 rot_mat = glm::rotate(Mat4(1.0f), ang, _right);
_dir = transformVec(rot_mat, _dir);
_up = transformVec(rot_mat, _up);
_tar = _pos + _dir;
_calcLook();
}
void Camera::yaw(float ang) {
Mat4 rot_mat = glm::rotate(Mat4(1.0f), ang, ((_lock_world_up)?_world_up:_up));
_dir = transformVec(rot_mat, _dir);
_right = transformVec(rot_mat, _right);
_up = normCross(_right, _dir);
_tar = _pos + _dir;
_calcLook();
}
// OrthographicCamera class
OrthographicCamera::OrthographicCamera(
const Vec3& pos,
const Vec3& tar,
const Vec3& up,
float left,
float right,
float bottom,
float top,
float near,
float far
) : Camera(pos, tar, up), _leftPlane(left), _rightPlane(right), _bottomPlane(bottom), _topPlane(top), _nearPlane(near), _farPlane(far) {
setProjection(glm::ortho(_leftPlane, _rightPlane, _bottomPlane, _topPlane, _nearPlane, _farPlane));
}
float OrthographicCamera::getLeftPlane() const { return _leftPlane; }
float OrthographicCamera::getRightPlane() const { return _rightPlane; }
float OrthographicCamera::getBottomPlane() const { return _bottomPlane; }
float OrthographicCamera::getTopPlane() const { return _topPlane; }
float OrthographicCamera::getNearPlane() const { return _nearPlane; }
float OrthographicCamera::getFarPlane() const { return _farPlane; }
// PerspectiveCamera class
PerspectiveCamera::PerspectiveCamera(
const Vec3& pos,
const Vec3& tar,
const Vec3& up ,
float fov,
float aspectRatio,
float near,
float far
) : Camera(pos, tar, up), _fov(fov), _ratio(aspectRatio), _nearPlane(near), _farPlane(far) {
setProjection(glm::perspective(glm::radians(_fov), _ratio, _nearPlane, _farPlane));
}
}