mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-03-15 10:09:48 -05:00
* Cleanup * CMake cleanups * Update current year * Update copyright header * Use script to return list of all modules * Update credits, license and ghoul
284 lines
9.4 KiB
C++
284 lines
9.4 KiB
C++
/*****************************************************************************************
|
|
* *
|
|
* OpenSpace *
|
|
* *
|
|
* Copyright (c) 2014-2019 *
|
|
* *
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
|
* software and associated documentation files (the "Software"), to deal in the Software *
|
|
* without restriction, including without limitation the rights to use, copy, modify, *
|
|
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
|
* permit persons to whom the Software is furnished to do so, subject to the following *
|
|
* conditions: *
|
|
* *
|
|
* The above copyright notice and this permission notice shall be included in all copies *
|
|
* or substantial portions of the Software. *
|
|
* *
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
|
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
|
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
|
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
|
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
|
****************************************************************************************/
|
|
|
|
#include <openspace/util/camera.h>
|
|
|
|
#include <sstream>
|
|
|
|
namespace openspace {
|
|
|
|
const glm::dvec3 Camera::ViewDirectionCameraSpace = glm::dvec3(0.0, 0.0, -1.0);
|
|
const glm::dvec3 Camera::UpDirectionCameraSpace = glm::dvec3(0.0, 1.0, 0.0);
|
|
|
|
Camera::Camera(const Camera& o)
|
|
: sgctInternal(o.sgctInternal)
|
|
, _position(o._position)
|
|
, _rotation(o._rotation)
|
|
, _scaling(o._scaling)
|
|
, _maxFov(o._maxFov)
|
|
, _cachedViewDirection(o._cachedViewDirection)
|
|
, _cachedLookupVector(o._cachedLookupVector)
|
|
{}
|
|
|
|
void Camera::setPositionVec3(glm::dvec3 pos) {
|
|
std::lock_guard<std::mutex> _lock(_mutex);
|
|
_position = std::move(pos);
|
|
|
|
_cachedCombinedViewMatrix.isDirty = true;
|
|
}
|
|
|
|
void Camera::setRotation(glm::dquat rotation) {
|
|
std::lock_guard<std::mutex> _lock(_mutex);
|
|
_rotation = std::move(rotation);
|
|
_cachedViewDirection.isDirty = true;
|
|
_cachedLookupVector.isDirty = true;
|
|
_cachedViewRotationMatrix.isDirty = true;
|
|
_cachedCombinedViewMatrix.isDirty = true;
|
|
}
|
|
|
|
void Camera::setScaling(float scaling) {
|
|
std::lock_guard<std::mutex> _lock(_mutex);
|
|
_scaling = scaling;
|
|
_cachedViewScaleMatrix.isDirty = true;
|
|
_cachedCombinedViewMatrix.isDirty = true;
|
|
}
|
|
|
|
void Camera::setMaxFov(float fov) {
|
|
std::lock_guard<std::mutex> _lock(_mutex);
|
|
_maxFov = fov;
|
|
_cachedSinMaxFov.isDirty = true;
|
|
}
|
|
|
|
void Camera::setParent(SceneGraphNode* parent) {
|
|
_parent = parent;
|
|
}
|
|
|
|
void Camera::rotate(glm::dquat rotation) {
|
|
std::lock_guard<std::mutex> _lock(_mutex);
|
|
_rotation = std::move(rotation) * static_cast<glm::dquat>(_rotation);
|
|
|
|
_cachedViewDirection.isDirty = true;
|
|
_cachedLookupVector.isDirty = true;
|
|
_cachedViewRotationMatrix.isDirty = true;
|
|
_cachedCombinedViewMatrix.isDirty = true;
|
|
}
|
|
|
|
const glm::dvec3& Camera::positionVec3() const {
|
|
return _position;
|
|
}
|
|
|
|
glm::dvec3 Camera::eyePositionVec3() const {
|
|
glm::dvec4 eyeInEyeSpace(0.0, 0.0, 0.0, 1.0);
|
|
|
|
glm::dmat4 invViewMatrix = glm::inverse(sgctInternal.viewMatrix());
|
|
glm::dmat4 invRotationMatrix = glm::mat4_cast(static_cast<glm::dquat>(_rotation));
|
|
glm::dmat4 invTranslationMatrix = glm::translate(
|
|
glm::dmat4(1.0),
|
|
static_cast<glm::dvec3>(_position)
|
|
);
|
|
|
|
glm::dmat4 invViewScale = glm::inverse(viewScaleMatrix());
|
|
|
|
glm::dvec4 eyeInWorldSpace = invTranslationMatrix * invRotationMatrix *
|
|
invViewScale * invViewMatrix * eyeInEyeSpace;
|
|
|
|
return glm::dvec3(eyeInWorldSpace.x, eyeInWorldSpace.y, eyeInWorldSpace.z);
|
|
}
|
|
|
|
const glm::dvec3& Camera::unsynchedPositionVec3() const {
|
|
return _position;
|
|
}
|
|
|
|
const glm::dvec3& Camera::viewDirectionWorldSpace() const {
|
|
if (_cachedViewDirection.isDirty) {
|
|
_cachedViewDirection.datum = glm::normalize(
|
|
static_cast<glm::dquat>(_rotation) * ViewDirectionCameraSpace
|
|
);
|
|
_cachedViewDirection.isDirty = false;
|
|
}
|
|
return _cachedViewDirection.datum;
|
|
}
|
|
|
|
const glm::dvec3& Camera::lookUpVectorCameraSpace() const {
|
|
return UpDirectionCameraSpace;
|
|
}
|
|
|
|
const glm::dvec3& Camera::lookUpVectorWorldSpace() const {
|
|
if (_cachedLookupVector.isDirty) {
|
|
_cachedLookupVector.datum = glm::normalize(
|
|
static_cast<glm::dquat>(_rotation) * UpDirectionCameraSpace
|
|
);
|
|
_cachedLookupVector.isDirty = false;
|
|
}
|
|
|
|
return _cachedLookupVector.datum;
|
|
}
|
|
|
|
float Camera::maxFov() const {
|
|
return _maxFov;
|
|
}
|
|
|
|
float Camera::sinMaxFov() const {
|
|
if (_cachedSinMaxFov.isDirty) {
|
|
_cachedSinMaxFov.datum = sin(_maxFov);
|
|
_cachedSinMaxFov.isDirty = true;
|
|
}
|
|
return _cachedSinMaxFov.datum;
|
|
}
|
|
|
|
SceneGraphNode* Camera::parent() const {
|
|
return _parent;
|
|
}
|
|
|
|
float Camera::scaling() const {
|
|
return _scaling;
|
|
}
|
|
|
|
const glm::dmat4& Camera::viewRotationMatrix() const {
|
|
if (_cachedViewRotationMatrix.isDirty) {
|
|
_cachedViewRotationMatrix.datum = glm::mat4_cast(
|
|
glm::inverse(static_cast<glm::dquat>(_rotation))
|
|
);
|
|
_cachedViewRotationMatrix.isDirty = false;
|
|
}
|
|
return _cachedViewRotationMatrix.datum;
|
|
}
|
|
|
|
const glm::dmat4& Camera::viewScaleMatrix() const {
|
|
if (_cachedViewScaleMatrix.isDirty) {
|
|
_cachedViewScaleMatrix.datum = glm::scale(glm::mat4(1.f), glm::vec3(_scaling));
|
|
_cachedViewScaleMatrix.isDirty = false;
|
|
}
|
|
return _cachedViewScaleMatrix.datum;
|
|
}
|
|
|
|
const glm::dquat& Camera::rotationQuaternion() const {
|
|
return _rotation;
|
|
}
|
|
|
|
const glm::dmat4& Camera::combinedViewMatrix() const {
|
|
if (_cachedCombinedViewMatrix.isDirty) {
|
|
const glm::dmat4 cameraTranslation = glm::inverse(
|
|
glm::translate(glm::dmat4(1.0), static_cast<glm::dvec3>(_position))
|
|
);
|
|
_cachedCombinedViewMatrix.datum =
|
|
glm::dmat4(sgctInternal.viewMatrix()) *
|
|
glm::dmat4(viewScaleMatrix()) *
|
|
glm::dmat4(viewRotationMatrix()) *
|
|
cameraTranslation;
|
|
_cachedCombinedViewMatrix.isDirty = false;
|
|
}
|
|
return _cachedCombinedViewMatrix.datum;
|
|
}
|
|
|
|
void Camera::invalidateCache() {
|
|
_cachedViewDirection.isDirty = true;
|
|
_cachedLookupVector.isDirty = true;
|
|
_cachedViewRotationMatrix.isDirty = true;
|
|
_cachedCombinedViewMatrix.isDirty = true;
|
|
_cachedViewScaleMatrix.isDirty = true;
|
|
_cachedSinMaxFov.isDirty = true;
|
|
}
|
|
|
|
void Camera::serialize(std::ostream& os) const {
|
|
const glm::dvec3 p = positionVec3();
|
|
const glm::dquat q = rotationQuaternion();
|
|
os << p.x << " " << p.y << " " << p.z << std::endl;
|
|
os << q.x << " " << q.y << " " << q.z << " " << q.w << std::endl;
|
|
}
|
|
|
|
void Camera::deserialize(std::istream& is) {
|
|
glm::dvec3 p;
|
|
glm::dquat q;
|
|
is >> p.x >> p.y >> p.z;
|
|
is >> q.x >> q.y >> q.z >> q.w;
|
|
setPositionVec3(p);
|
|
setRotation(q);
|
|
}
|
|
|
|
Camera::SgctInternal::SgctInternal(const SgctInternal& o)
|
|
: _viewMatrix(o._viewMatrix)
|
|
, _projectionMatrix(o._projectionMatrix)
|
|
, _cachedViewProjectionMatrix(o._cachedViewProjectionMatrix)
|
|
{}
|
|
|
|
void Camera::SgctInternal::setSceneMatrix(glm::mat4 sceneMatrix) {
|
|
std::lock_guard<std::mutex> _lock(_mutex);
|
|
|
|
_sceneMatrix = std::move(sceneMatrix);
|
|
}
|
|
|
|
void Camera::SgctInternal::setViewMatrix(glm::mat4 viewMatrix) {
|
|
std::lock_guard<std::mutex> _lock(_mutex);
|
|
|
|
_viewMatrix = std::move(viewMatrix);
|
|
_cachedViewProjectionMatrix.isDirty = true;
|
|
}
|
|
|
|
void Camera::SgctInternal::setProjectionMatrix(glm::mat4 projectionMatrix) {
|
|
std::lock_guard<std::mutex> _lock(_mutex);
|
|
|
|
_projectionMatrix = std::move(projectionMatrix);
|
|
_cachedViewProjectionMatrix.isDirty = true;
|
|
}
|
|
|
|
const glm::mat4& Camera::SgctInternal::sceneMatrix() const {
|
|
return _sceneMatrix;
|
|
}
|
|
|
|
const glm::mat4& Camera::SgctInternal::viewMatrix() const {
|
|
return _viewMatrix;
|
|
}
|
|
|
|
const glm::mat4& Camera::SgctInternal::projectionMatrix() const {
|
|
return _projectionMatrix;
|
|
}
|
|
|
|
const glm::mat4& Camera::SgctInternal::viewProjectionMatrix() const {
|
|
if (_cachedViewProjectionMatrix.isDirty) {
|
|
std::lock_guard<std::mutex> _lock(_mutex);
|
|
_cachedViewProjectionMatrix.datum = _projectionMatrix * _viewMatrix;
|
|
_cachedViewProjectionMatrix.isDirty = false;
|
|
}
|
|
return _cachedViewProjectionMatrix.datum;
|
|
}
|
|
|
|
const glm::mat4& Camera::viewMatrix() const {
|
|
return sgctInternal.viewMatrix();
|
|
}
|
|
|
|
const glm::mat4& Camera::projectionMatrix() const {
|
|
return sgctInternal.projectionMatrix();
|
|
}
|
|
|
|
const glm::mat4& Camera::viewProjectionMatrix() const {
|
|
return sgctInternal.viewProjectionMatrix();
|
|
}
|
|
|
|
std::vector<Syncable*> Camera::getSyncables() {
|
|
return { &_position, &_rotation, &_scaling };
|
|
}
|
|
|
|
} // namespace openspace
|