#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) { _proj = glm::ortho(_leftPlane, _rightPlane, _bottomPlane, _topPlane, _nearPlane, _farPlane); } // PerspectiveCamera class /* PerspectiveCamera::PerspectiveCamera( 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) { _proj = glm::ortho(_leftPlane, _rightPlane, _bottomPlane, _topPlane, _nearPlane, _farPlane); } */ }