268 lines
6.5 KiB
C++
268 lines
6.5 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) {
|
|
_calcView();
|
|
}
|
|
|
|
void OrthographicCamera::_calcView() {
|
|
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; }
|
|
|
|
void OrthographicCamera::setLeftPlane(float left) {
|
|
_leftPlane = left;
|
|
_calcView();
|
|
}
|
|
|
|
void OrthographicCamera::setRightPlane(float right) {
|
|
_rightPlane = right;
|
|
_calcView();
|
|
}
|
|
|
|
void OrthographicCamera::setBottomPlane(float bottom) {
|
|
_bottomPlane = bottom;
|
|
_calcView();
|
|
}
|
|
|
|
void OrthographicCamera::setTopPlane(float top) {
|
|
_topPlane = top;
|
|
_calcView();
|
|
}
|
|
|
|
void OrthographicCamera::setNearPlane(float near) {
|
|
_nearPlane = near;
|
|
_calcView();
|
|
}
|
|
|
|
void OrthographicCamera::setFarPlane(float far) {
|
|
_farPlane = far;
|
|
_calcView();
|
|
}
|
|
|
|
void OrthographicCamera::setOrthographicProjection(float left, float right, float bottom, float top, float near, float far) {
|
|
_leftPlane = left;
|
|
_rightPlane = right;
|
|
_bottomPlane = bottom;
|
|
_topPlane = top;
|
|
_nearPlane = near;
|
|
_farPlane = far;
|
|
_calcView();
|
|
}
|
|
|
|
// 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) {
|
|
_calcView();
|
|
}
|
|
|
|
void PerspectiveCamera::_calcView() {
|
|
setProjection(glm::perspective(glm::radians(_fov), _ratio, _nearPlane, _farPlane));
|
|
}
|
|
|
|
float PerspectiveCamera::getFOV() const { return _fov; }
|
|
|
|
float PerspectiveCamera::getAspectRatio() const { return _ratio; }
|
|
|
|
float PerspectiveCamera::getNearPlane() const { return _nearPlane; }
|
|
|
|
float PerspectiveCamera::getFarPlane() const { return _farPlane; }
|
|
|
|
void PerspectiveCamera::setFOV(float fov) {
|
|
_fov = fov;
|
|
_calcView();
|
|
}
|
|
|
|
void PerspectiveCamera::setAspectRatio(float aspectRatio) {
|
|
_ratio = aspectRatio;
|
|
_calcView();
|
|
}
|
|
|
|
void PerspectiveCamera::setNearPlane(float near) {
|
|
_nearPlane = near;
|
|
_calcView();
|
|
}
|
|
|
|
void PerspectiveCamera::setFarPlane(float far) {
|
|
_farPlane = far;
|
|
_calcView();
|
|
}
|
|
|
|
void PerspectiveCamera::setPerspectiveProjection(float fov, float aspectRatio, float near, float far) {
|
|
_fov = fov;
|
|
_ratio = aspectRatio;
|
|
_nearPlane = near;
|
|
_farPlane = far;
|
|
_calcView();
|
|
}
|
|
|
|
} |