From 1db9f2f60c8262c4a7a35c7ef68b4885fe8310d6 Mon Sep 17 00:00:00 2001 From: Kalle Bladin Date: Thu, 19 May 2016 23:21:48 -0400 Subject: [PATCH] Clean up camera class. --- include/openspace/util/camera.h | 268 +++++----- .../rendering/renderablemodelprojection.cpp | 1 - .../rendering/renderableplanetprojection.cpp | 1 - src/interaction/interactionhandler.cpp | 12 +- src/interaction/mousecontroller.cpp | 2 +- src/rendering/renderengine.cpp | 2 +- src/scene/scene.cpp | 4 +- src/scene/scenegraphnode.cpp | 2 +- src/util/camera.cpp | 457 +++++++++--------- 9 files changed, 356 insertions(+), 393 deletions(-) diff --git a/include/openspace/util/camera.h b/include/openspace/util/camera.h index ceddce1b50..123d3f07e2 100644 --- a/include/openspace/util/camera.h +++ b/include/openspace/util/camera.h @@ -40,169 +40,139 @@ namespace openspace { -class Camera { -public: - Camera(); - Camera(const Camera& o) - : sgctInternal(o.sgctInternal) - , _viewDirectionInCameraSpace(o._viewDirectionInCameraSpace) - , _focusPosition(o._focusPosition) - , _viewDirection(o._viewDirection) - , _lookUp(o._lookUp) - , _viewRotationMatrix(o._viewRotationMatrix) - , _scaling(o._scaling) - , _position(o._position) - , _maxFov(o._maxFov) - , _sinMaxFov(o._sinMaxFov) - { } + template + struct CachedDatum + { + CachedDatum() { isDirty = true; } + T datum; + bool isDirty; + }; - ~Camera(); - - - - // MUTATORS (SETTERS) - - void setPosition(psc pos); - void setFocusPosition(psc pos); - void setRotation(glm::quat rotation); - void setLookUpVector(glm::vec3 lookUp); - void setScaling(glm::vec2 scaling); - void setMaxFov(float fov); - - - - // RELATIVE MUTATORS - - void rotate(const glm::quat& rotation); - - - - - // ACCESSORS (GETTERS) - - const psc& position() const; - const psc& unsynchedPosition() const; - const psc& focusPosition() const; - const glm::vec3& viewDirection() const; - const glm::vec3& lookUpVector() const; - const glm::vec2& scaling() const; - float maxFov() const; - float sinMaxFov() const; - const glm::mat4& viewRotationMatrix() const; - - //@TODO this should simply be called viewMatrix! - //Rename after removing deprecated methods - const glm::mat4& combinedViewMatrix() const; - - - - - - // DEPRECATED ACCESSORS (GETTERS) - // @TODO use Camera::SgctInternal interface instead - - [[deprecated("Replaced by Camera::SgctInternal::viewMatrix()")]] - const glm::mat4& viewMatrix() const; - - [[deprecated("Replaced by Camera::SgctInternal::projectionMatrix()")]] - const glm::mat4& projectionMatrix() const; - - [[deprecated("Replaced by Camera::SgctInternal::viewProjectionMatrix()")]] - const glm::mat4& viewProjectionMatrix() const; - - - - - // SYNCHRONIZATION - - void postSynchronizationPreDraw(); - void preSynchronization(); - void serialize(SyncBuffer* syncBuffer); - void deserialize(SyncBuffer* syncBuffer); - - - - // Handles SGCT's internal matrices. Also caches a calculated viewProjection matrix. - class SgctInternal { - friend class Camera; + class Camera { + // For testing double vs float precision + typedef glm::dquat Quat; + typedef glm::dmat4 Mat4; + typedef glm::dvec3 Vec3; + // Static constants + static const Vec3 _VIEW_DIRECTION_CAMERA_SPACE; + static const Vec3 _LOOKUP_VECTOR_CAMERA_SPACE; public: + Camera(); + Camera(const Camera& o); + ~Camera(); + // Mutators + void setPosition(psc pos); + void setFocusPosition(psc pos); + void setRotation(Quat rotation); + void setScaling(glm::vec2 scaling); + void setMaxFov(float fov); + + // Relative mutators + void rotate(Quat rotation); + + // Accessors + const psc& position() const; + const psc& unsynchedPosition() const; + const psc& focusPosition() const; + const glm::vec3 viewDirectionWorldSpace() const; + const glm::vec3 lookUpVectorCameraSpace() const; + const glm::vec2& scaling() const; + const glm::mat4 viewRotationMatrix() const; + const glm::quat rotationQuaternion() const; + float maxFov() const; + float sinMaxFov() const; + //@TODO this should simply be called viewMatrix! + //Rename after removing deprecated methods + glm::mat4 combinedViewMatrix() const; - void setViewMatrix(glm::mat4 viewMatrix); - void setProjectionMatrix(glm::mat4 projectionMatrix); - + // DEPRECATED ACCESSORS (GETTERS) + // @TODO use Camera::SgctInternal interface instead + [[deprecated("Replaced by Camera::SgctInternal::viewMatrix()")]] const glm::mat4& viewMatrix() const; + + [[deprecated("Replaced by Camera::SgctInternal::projectionMatrix()")]] const glm::mat4& projectionMatrix() const; + + [[deprecated("Replaced by Camera::SgctInternal::viewProjectionMatrix()")]] const glm::mat4& viewProjectionMatrix() const; + // Synchronization + void postSynchronizationPreDraw(); + void preSynchronization(); + void serialize(SyncBuffer* syncBuffer); + void deserialize(SyncBuffer* syncBuffer); + + /** + Handles SGCT's internal matrices. Also caches a calculated viewProjection + matrix. This is the data that is different for different cameras within + SGCT. + */ + class SgctInternal { + friend class Camera; + public: + void setViewMatrix(glm::mat4 viewMatrix); + void setProjectionMatrix(glm::mat4 projectionMatrix); + + const glm::mat4& viewMatrix() const; + const glm::mat4& projectionMatrix() const; + const glm::mat4& viewProjectionMatrix() const; + private: + SgctInternal(); + SgctInternal(const SgctInternal& o) + : _viewMatrix(o._viewMatrix) + , _projectionMatrix(o._projectionMatrix) + , _cachedViewProjectionMatrix(o._cachedViewProjectionMatrix) + {} + + // State + glm::mat4 _viewMatrix; + glm::mat4 _projectionMatrix; + + // Cache + mutable CachedDatum _cachedViewProjectionMatrix; + mutable std::mutex _mutex; + } sgctInternal; private: - SgctInternal(); - SgctInternal(const SgctInternal& o) - : _viewMatrix(o._viewMatrix) - , _projectionMatrix(o._projectionMatrix) - , _dirtyViewProjectionMatrix(o._dirtyViewProjectionMatrix) - , _viewProjectionMatrix(o._viewProjectionMatrix) - {} - + /** + Class encapsulating data that needs to be synched between SGCT nodes. + Are all three variables (i.e. local, shared, synced) really neccessary? /EB + */ + template + struct SyncData { + SyncData() {} + SyncData(const SyncData& d) + : local(d.local), shared(d.shared), synced(d.synced) {} - glm::mat4 _viewMatrix; - glm::mat4 _projectionMatrix; + void serialize(SyncBuffer* syncBuffer) { syncBuffer->encode(shared); } + void deserialize(SyncBuffer* syncBuffer) { syncBuffer->decode(shared); } + void postSynchronizationPreDraw() { synced = shared; } + void preSynchronization() { shared = local; } + + T local; + T shared; + T synced; + }; + + // State of the camera + SyncData _rotation; + SyncData _scaling; + SyncData _position; + + psc _focusPosition; + + float _maxFov; + + // Cached data + mutable CachedDatum _cachedViewDirection; + mutable CachedDatum _cachedViewRotationMatrix; + mutable CachedDatum _cachedCombinedViewMatrix; + mutable CachedDatum _cachedSinMaxFov; - mutable bool _dirtyViewProjectionMatrix; - mutable glm::mat4 _viewProjectionMatrix; mutable std::mutex _mutex; - - } sgctInternal; - - -private: - - // Defines what direction in local camera space the camera is looking in. - const glm::vec3 _viewDirectionInCameraSpace; - - - psc _focusPosition; - glm::vec3 _viewDirection; - glm::vec3 _lookUp; - - - // Class encapsulating the synced data. Are all three variables - // (i.e. local, shared, synced) really neccessary? /EB - template - struct SyncData { - - SyncData() {} - - // copy constructor - SyncData(const SyncData& d) - : local(d.local), shared(d.shared), synced(d.synced) {} - - void serialize(SyncBuffer* syncBuffer) { syncBuffer->encode(shared); } - void deserialize(SyncBuffer* syncBuffer) { syncBuffer->decode(shared); } - void postSynchronizationPreDraw() { synced = shared; } - void preSynchronization() { shared = local; } - - T local; - T shared; - T synced; }; - - - SyncData _viewRotationMatrix; - SyncData _scaling; - SyncData _position; - - - float _maxFov; - float _sinMaxFov; - - - mutable std::mutex _mutex; - -}; - } // namespace openspace -#endif // __CAMERA_H__ +#endif // __CAMERA_H__ \ No newline at end of file diff --git a/modules/newhorizons/rendering/renderablemodelprojection.cpp b/modules/newhorizons/rendering/renderablemodelprojection.cpp index 529a1438dd..394b64adba 100644 --- a/modules/newhorizons/rendering/renderablemodelprojection.cpp +++ b/modules/newhorizons/rendering/renderablemodelprojection.cpp @@ -347,7 +347,6 @@ void RenderableModelProjection::render(const RenderData& data) { _frameCount++; _camScaling = data.camera.scaling(); - _up = data.camera.lookUpVector(); if (_capture && _performProjection) project(); diff --git a/modules/newhorizons/rendering/renderableplanetprojection.cpp b/modules/newhorizons/rendering/renderableplanetprojection.cpp index 07b252deb4..d742cd9cfb 100644 --- a/modules/newhorizons/rendering/renderableplanetprojection.cpp +++ b/modules/newhorizons/rendering/renderableplanetprojection.cpp @@ -575,7 +575,6 @@ void RenderablePlanetProjection::render(const RenderData& data) { clearAllProjections(); _camScaling = data.camera.scaling(); - _up = data.camera.lookUpVector(); if (_capture && _performProjection) project(); diff --git a/src/interaction/interactionhandler.cpp b/src/interaction/interactionhandler.cpp index 3feb36eebb..7663dae836 100644 --- a/src/interaction/interactionhandler.cpp +++ b/src/interaction/interactionhandler.cpp @@ -183,7 +183,7 @@ void InteractionHandler::setFocusNode(SceneGraphNode* node) { psc focusPos = node->worldPosition(); psc camToFocus = focusPos - _camera->position(); glm::vec3 viewDir = glm::normalize(camToFocus.vec3()); - glm::vec3 cameraView = glm::normalize(_camera->viewDirection()); + glm::vec3 cameraView = glm::normalize(_camera->viewDirectionWorldSpace()); //set new focus position _camera->setFocusPosition(node->worldPosition()); float dot = glm::dot(viewDir, cameraView); @@ -242,13 +242,13 @@ void InteractionHandler::orbit(const float &dx, const float &dy, const float &dz lockControls(); - glm::vec3 cameraUp = glm::normalize((glm::inverse(_camera->viewRotationMatrix()) * glm::vec4(_camera->lookUpVector(), 0))).xyz(); - glm::vec3 cameraRight = glm::cross(_camera->viewDirection(), cameraUp); + glm::vec3 cameraUp = glm::normalize((glm::inverse(_camera->viewRotationMatrix()) * glm::vec4(_camera->lookUpVectorCameraSpace(), 0))).xyz(); + glm::vec3 cameraRight = glm::cross(glm::vec3(_camera->viewDirectionWorldSpace()), cameraUp); glm::mat4 transform; transform = glm::rotate(glm::radians(dx * 100.f), cameraUp) * transform; transform = glm::rotate(glm::radians(dy * 100.f), cameraRight) * transform; - transform = glm::rotate(glm::radians(dz * 100.f), _camera->viewDirection()) * transform; + transform = glm::rotate(glm::radians(dz * 100.f), glm::vec3(_camera->viewDirectionWorldSpace())) * transform; //get "old" focus position @@ -328,7 +328,7 @@ void InteractionHandler::orbitDelta(const glm::quat& rotation) //relative_origin_coordinate = relative_origin_coordinate.vec4() * glm::inverse(rotation); relative_origin_coordinate = glm::inverse(rotation) * relative_origin_coordinate.vec4(); relative = relative_origin_coordinate + origin; - glm::mat4 la = glm::lookAt(_camera->position().vec3(), origin.vec3(), glm::rotate(rotation, _camera->lookUpVector())); + glm::mat4 la = glm::lookAt(_camera->position().vec3(), origin.vec3(), glm::rotate(rotation, glm::vec3(_camera->lookUpVectorCameraSpace()))); unlockControls(); @@ -337,7 +337,7 @@ void InteractionHandler::orbitDelta(const glm::quat& rotation) //camera_->setRotation(glm::mat4_cast(rotation)); - _camera->setRotation(la); + _camera->setRotation(glm::quat_cast(la)); //camera_->setLookUpVector(); diff --git a/src/interaction/mousecontroller.cpp b/src/interaction/mousecontroller.cpp index 73db191e71..67dacbd26e 100644 --- a/src/interaction/mousecontroller.cpp +++ b/src/interaction/mousecontroller.cpp @@ -57,7 +57,7 @@ glm::vec3 MouseController::mapToTrackball(glm::vec2 mousePos) { glm::vec3 MouseController::mapToCamera(glm::vec3 trackballPos) { //Get x,y,z axis vectors of current camera view - glm::vec3 currentViewYaxis = glm::normalize(_handler->camera()->lookUpVector()); + glm::vec3 currentViewYaxis = glm::normalize(_handler->camera()->lookUpVectorCameraSpace()); psc viewDir = _handler->camera()->position() - _handler->focusNode()->worldPosition(); glm::vec3 currentViewZaxis = glm::normalize(viewDir.vec3()); glm::vec3 currentViewXaxis = glm::normalize(glm::cross(currentViewYaxis, currentViewZaxis)); diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index ccdeffa6d8..aab59c553e 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -285,7 +285,7 @@ bool RenderEngine::initializeGL() { //_mainCamera->setCameraDirection(glm::normalize(-viewdir)); //_mainCamera->setCameraDirection(glm::vec3(0.f, 0.f, -1.f)); //_mainCamera->setLookUpVector(glm::normalize(upVector)); - _mainCamera->setLookUpVector(glm::vec3(0.f, 1.f, 0.f)); + //_mainCamera->setLookUpVector(glm::vec3(0.f, 1.f, 0.f)); // set the initial fov to be 0.0 which means everything will be culled //float maxFov = 0.0f; diff --git a/src/scene/scene.cpp b/src/scene/scene.cpp index 20a8b7de6e..419e8505f7 100644 --- a/src/scene/scene.cpp +++ b/src/scene/scene.cpp @@ -299,9 +299,9 @@ bool Scene::loadSceneInternal(const std::string& sceneDescriptionFilePath) { } // Check crash for when fn == nullptr - glm::mat4 la = glm::lookAt(cameraPosition.vec3(), fn->worldPosition().vec3(), c->lookUpVector()); + glm::mat4 la = glm::lookAt(cameraPosition.vec3(), fn->worldPosition().vec3(), glm::vec3(c->lookUpVectorCameraSpace())); - c->setRotation(la); + c->setRotation(glm::quat_cast(la)); c->setPosition(cameraPosition); c->setScaling(cameraScaling); diff --git a/src/scene/scenegraphnode.cpp b/src/scene/scenegraphnode.cpp index 21d2343a24..0663a469c7 100644 --- a/src/scene/scenegraphnode.cpp +++ b/src/scene/scenegraphnode.cpp @@ -380,7 +380,7 @@ bool SceneGraphNode::sphereInsideFrustum(const psc& s_pos, const PowerScaledScal const Camera* camera) { // direction the camera is looking at in power scale - psc psc_camdir = psc(camera->viewDirection()); + psc psc_camdir = psc(camera->viewDirectionWorldSpace()); // the position of the camera, moved backwards in the view direction to encapsulate // the sphere radius diff --git a/src/util/camera.cpp b/src/util/camera.cpp index b68e8b4839..19d92bac55 100644 --- a/src/util/camera.cpp +++ b/src/util/camera.cpp @@ -30,235 +30,230 @@ #include namespace openspace { - -Camera::Camera() - : _maxFov(0.f) - , _sinMaxFov(0.f) - , _viewDirection(0,0,-1) - , _viewDirectionInCameraSpace(0.f, 0.f, -1.f) - , _focusPosition() -{ - _scaling.local = glm::vec2(1.f, 0.f); - _viewRotationMatrix.local = glm::mat4(1.0f); - _position.local = psc(); -} -Camera::~Camera() { } - - - -////////////////////////////////////////////////////////////////////////////////////////// -// CAMERA MUTATORS (SETTERS) // -////////////////////////////////////////////////////////////////////////////////////////// - -void Camera::setPosition(psc pos){ - std::lock_guard _lock(_mutex); - _position.local = std::move(pos); -} - -void Camera::setFocusPosition(psc pos) { - std::lock_guard _lock(_mutex); - _focusPosition = pos; -} - -void Camera::setRotation(glm::quat rotation) { - std::lock_guard _lock(_mutex); - _viewRotationMatrix.local = glm::mat4_cast(glm::normalize(rotation)); -} - -void Camera::setLookUpVector(glm::vec3 lookUp) { - std::lock_guard _lock(_mutex); - _lookUp = std::move(lookUp); -} - -void Camera::setScaling(glm::vec2 scaling) { - std::lock_guard _lock(_mutex); - _scaling.local = std::move(scaling); -} - -void Camera::setMaxFov(float fov) { - std::lock_guard _lock(_mutex); - _maxFov = fov; - _sinMaxFov = sin(_maxFov); -} - - -////////////////////////////////////////////////////////////////////////////////////////// -// CAMERA ACCESSORS (GETTERS) // -////////////////////////////////////////////////////////////////////////////////////////// - - -const psc& Camera::position() const { - return _position.synced; - -} - -const psc& Camera::unsynchedPosition() const { - return _position.local; -} - -const psc& Camera::focusPosition() const { - return _focusPosition; -} - -const glm::vec3& Camera::viewDirection() const { - return _viewDirection; -} - -const glm::vec3& Camera::lookUpVector() const { - return _lookUp; -} - -const glm::vec2& Camera::scaling() const { - return _scaling.synced; -} - -float Camera::maxFov() const { - return _maxFov; -} - -float Camera::sinMaxFov() const { - return _sinMaxFov; -} - -const glm::mat4& Camera::viewRotationMatrix() const { - return _viewRotationMatrix.synced; -} - -const glm::mat4& Camera::combinedViewMatrix() const { - glm::vec3 cameraPosition = position().vec3(); - glm::mat4 viewTransform = glm::inverse(glm::translate(glm::mat4(1.0), cameraPosition)); - viewTransform = glm::mat4(viewRotationMatrix()) * viewTransform; - return viewTransform; -} - - - - - -////////////////////////////////////////////////////////////////////////////////////////// -// DEPRECATED CAMERA ACCESSORS (GETTERS) // -////////////////////////////////////////////////////////////////////////////////////////// - -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(); -} - - - -////////////////////////////////////////////////////////////////////////////////////////// -// CAMERA RELATICVE MUTATORS // -////////////////////////////////////////////////////////////////////////////////////////// - - -void Camera::rotate(const glm::quat& rotation) { - std::lock_guard _lock(_mutex); - glm::mat4 tmp = glm::mat4_cast(rotation); - _viewRotationMatrix.local = _viewRotationMatrix.local * tmp; -} - - - - -////////////////////////////////////////////////////////////////////////////////////////// -// CAMERA SYNCHRONIZATION // -////////////////////////////////////////////////////////////////////////////////////////// - -void Camera::serialize(SyncBuffer* syncBuffer){ - _mutex.lock(); - - _viewRotationMatrix.serialize(syncBuffer); - _position.serialize(syncBuffer); - _scaling.serialize(syncBuffer); - - _mutex.unlock(); -} - -void Camera::deserialize(SyncBuffer* syncBuffer){ - _mutex.lock(); - - _viewRotationMatrix.deserialize(syncBuffer); - _position.deserialize(syncBuffer); - _scaling.deserialize(syncBuffer); - - _mutex.unlock(); -} - -void Camera::postSynchronizationPreDraw(){ - _mutex.lock(); - - _viewRotationMatrix.postSynchronizationPreDraw(); - _position.postSynchronizationPreDraw(); - _scaling.postSynchronizationPreDraw(); - - glm::vec4 localViewDir = glm::vec4(_viewDirectionInCameraSpace, 0.f); - _viewDirection = (glm::inverse(_viewRotationMatrix.local) * localViewDir).xyz(); - _viewDirection = glm::normalize(_viewDirection); - - _mutex.unlock(); -} - -void Camera::preSynchronization(){ - _mutex.lock(); - - _viewRotationMatrix.preSynchronization(); - _position.preSynchronization(); - _scaling.preSynchronization(); - - _mutex.unlock(); -} - - - - - -////////////////////////////////////////////////////////////////////////////////////////// -// SGCT NODE DEPENTENT // -////////////////////////////////////////////////////////////////////////////////////////// -Camera::SgctInternal::SgctInternal() - : _viewMatrix() - , _projectionMatrix() - , _dirtyViewProjectionMatrix(true) -{ - -} - -void Camera::SgctInternal::setViewMatrix(glm::mat4 viewMatrix) { - std::lock_guard _lock(_mutex); - _viewMatrix = std::move(viewMatrix); - _dirtyViewProjectionMatrix = true; -} - - -void Camera::SgctInternal::setProjectionMatrix(glm::mat4 projectionMatrix) { - std::lock_guard _lock(_mutex); - _projectionMatrix = std::move(projectionMatrix); - _dirtyViewProjectionMatrix = true; -} - -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 (_dirtyViewProjectionMatrix) { - std::lock_guard _lock(_mutex); - _viewProjectionMatrix = _projectionMatrix * _viewMatrix; - _dirtyViewProjectionMatrix = false; - } - return _viewProjectionMatrix; -} - -} // namespace openspace + const Camera::Vec3 Camera::_VIEW_DIRECTION_CAMERA_SPACE = Camera::Vec3(0, 0, -1); + const Camera::Vec3 Camera::_LOOKUP_VECTOR_CAMERA_SPACE = Camera::Vec3(0, 1, 0); + + Camera::Camera() + : _maxFov(0.f) + , _focusPosition() + { + _scaling.local = glm::vec2(1.f, 0.f); + _position.local = psc(); + Vec3 eulerAngles(0.0f, 0.0f, 0.0f); + _rotation.local = Quat(eulerAngles); + } + + Camera::Camera(const Camera& o) + : sgctInternal(o.sgctInternal) + , _focusPosition(o._focusPosition) + , _cachedViewDirection(o._cachedViewDirection) + , _rotation(o._rotation) + , _scaling(o._scaling) + , _position(o._position) + , _maxFov(o._maxFov) + { } + + Camera::~Camera() { } + + ////////////////////////////////////////////////////////////////////////////////////// + // CAMERA MUTATORS (SETTERS) // + ////////////////////////////////////////////////////////////////////////////////////// + + void Camera::setPosition(psc pos) { + std::lock_guard _lock(_mutex); + _position.local = std::move(pos); + } + + void Camera::setFocusPosition(psc pos) { + std::lock_guard _lock(_mutex); + _focusPosition = pos; + } + + void Camera::setRotation(Quat rotation) { + std::lock_guard _lock(_mutex); + _rotation.local = rotation; + _cachedViewRotationMatrix.isDirty = true; + _cachedCombinedViewMatrix.isDirty = true; + } + + void Camera::setScaling(glm::vec2 scaling) { + std::lock_guard _lock(_mutex); + _scaling.local = std::move(scaling); + } + + void Camera::setMaxFov(float fov) { + std::lock_guard _lock(_mutex); + _maxFov = fov; + _cachedSinMaxFov.isDirty = true; + } + + ////////////////////////////////////////////////////////////////////////////////////// + // CAMERA RELATICVE MUTATORS // + ////////////////////////////////////////////////////////////////////////////////////// + + void Camera::rotate(Quat rotation) { + std::lock_guard _lock(_mutex); + _rotation.local = _rotation.local * rotation; + } + + ////////////////////////////////////////////////////////////////////////////////////// + // CAMERA ACCESSORS (GETTERS) // + ////////////////////////////////////////////////////////////////////////////////////// + + const psc& Camera::position() const { + return _position.synced; + } + + const psc& Camera::unsynchedPosition() const { + return _position.local; + } + + const psc& Camera::focusPosition() const { + return _focusPosition; + } + + const glm::vec3 Camera::viewDirectionWorldSpace() const { + if (_cachedViewDirection.isDirty) { + _cachedViewDirection.datum = + glm::inverse(_rotation.local) * Vec3(_VIEW_DIRECTION_CAMERA_SPACE); + _cachedViewDirection.datum = glm::normalize(_cachedViewDirection.datum); + } + return _cachedViewDirection.datum; + } + + const glm::vec3 Camera::lookUpVectorCameraSpace() const { + return _LOOKUP_VECTOR_CAMERA_SPACE; + } + + const glm::vec2& Camera::scaling() const { + return _scaling.synced; + } + + float Camera::maxFov() const { + return _maxFov; + } + + float Camera::sinMaxFov() const { + if (_cachedSinMaxFov.isDirty) { + _cachedSinMaxFov.datum = sin(_maxFov); + } + return _cachedSinMaxFov.datum; + } + + const glm::mat4 Camera::viewRotationMatrix() const { + if (_cachedViewRotationMatrix.isDirty) { + _cachedViewRotationMatrix.datum = glm::mat4_cast(_rotation.local); + } + return _cachedViewRotationMatrix.datum; + } + + const glm::quat Camera::rotationQuaternion() const { + return _rotation.synced; + } + + glm::mat4 Camera::combinedViewMatrix() const { + if (_cachedCombinedViewMatrix.isDirty) { + glm::vec3 cameraPosition = position().vec3(); + glm::mat4 cameraTranslation = + glm::inverse(glm::translate(glm::mat4(1.0), cameraPosition)); + _cachedCombinedViewMatrix.datum = + glm::mat4(viewRotationMatrix()) * cameraTranslation; + } + return _cachedCombinedViewMatrix.datum; + } + + ////////////////////////////////////////////////////////////////////////////////////// + // DEPRECATED CAMERA ACCESSORS (GETTERS) // + ////////////////////////////////////////////////////////////////////////////////////// + + 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(); + } + + ////////////////////////////////////////////////////////////////////////////////////// + // CAMERA SYNCHRONIZATION // + ////////////////////////////////////////////////////////////////////////////////////// + + void Camera::serialize(SyncBuffer* syncBuffer) { + std::lock_guard _lock(_mutex); + + _rotation.serialize(syncBuffer); + _position.serialize(syncBuffer); + _scaling.serialize(syncBuffer); + } + + void Camera::deserialize(SyncBuffer* syncBuffer) { + std::lock_guard _lock(_mutex); + + _rotation.deserialize(syncBuffer); + _position.deserialize(syncBuffer); + _scaling.deserialize(syncBuffer); + } + + void Camera::postSynchronizationPreDraw() { + std::lock_guard _lock(_mutex); + + _rotation.postSynchronizationPreDraw(); + _position.postSynchronizationPreDraw(); + _scaling.postSynchronizationPreDraw(); + + _cachedViewDirection.isDirty = true; + } + + void Camera::preSynchronization() { + std::lock_guard _lock(_mutex); + + _rotation.preSynchronization(); + _position.preSynchronization(); + _scaling.preSynchronization(); + } + + ////////////////////////////////////////////////////////////////////////////////////// + // SGCT NODE DEPENTENT // + ////////////////////////////////////////////////////////////////////////////////////// + Camera::SgctInternal::SgctInternal() + : _viewMatrix() + , _projectionMatrix() + { } + + void Camera::SgctInternal::setViewMatrix(glm::mat4 viewMatrix) { + std::lock_guard _lock(_mutex); + + _viewMatrix = std::move(viewMatrix); + _cachedViewProjectionMatrix.isDirty = true; + } + + void Camera::SgctInternal::setProjectionMatrix(glm::mat4 projectionMatrix) { + std::lock_guard _lock(_mutex); + + _projectionMatrix = std::move(projectionMatrix); + _cachedViewProjectionMatrix.isDirty = true; + } + + 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 _lock(_mutex); + _cachedViewProjectionMatrix.datum = _projectionMatrix * _viewMatrix; + _cachedViewProjectionMatrix.isDirty = false; + } + return _cachedViewProjectionMatrix.datum; + } + +} // namespace openspace \ No newline at end of file