diff --git a/include/ACGL/Scene/CameraBase.hh b/include/ACGL/Scene/CameraBase.hh index 0e43f7ac37691821823729a0233967b841ca6d3f..dc5af02b5cc9613e12eed59625b3e4ba1c350b90 100644 --- a/include/ACGL/Scene/CameraBase.hh +++ b/include/ACGL/Scene/CameraBase.hh @@ -1,5 +1,11 @@ +/*********************************************************************** + * Copyright 2011-2013 Computer Graphics Group RWTH Aachen University. * + * All rights reserved. * + * Distributed under the terms of the MIT License (see LICENSE.TXT). * + **********************************************************************/ #pragma once +#include <ACGL/ACGL.hh> #include <ACGL/Math/Math.hh> namespace ACGL{ @@ -9,7 +15,8 @@ namespace Scene{ * @brief Common interface for cameras * * This interface only contains getter on purpose. - * All logic that wants to modify a camera should know the actual structure of the camera and therefore use the specific subclass. + * All logic that wants to modify a camera should know the actual structure of the camera and therefore use the + * specific subclass. */ class CameraBase { diff --git a/include/ACGL/Scene/GenericCamera.hh b/include/ACGL/Scene/GenericCamera.hh index c486dac9f0d91de3bb01d61c8b167c50e3ed8a3f..c57afa7862cdf6f92fc8abce73e66e7535667188 100644 --- a/include/ACGL/Scene/GenericCamera.hh +++ b/include/ACGL/Scene/GenericCamera.hh @@ -42,7 +42,7 @@ * Other camera models rotate first and translate later (e.g. bundler)! The rotation * is the same, the translation differs. * - * TODO: support stereo! + * TODO: support more stereo modes! */ namespace ACGL{ @@ -183,7 +183,7 @@ class GenericCamera : public CameraBase float getFarClippingPlane() const { return mFarClippingPlane; } /// Gets size of the viewport - glm::uvec2 getViewportSize() const { return mViewportSize; } + virtual glm::uvec2 getViewportSize() const { return mViewportSize; } /// Gets width of the viewport unsigned int getViewportWidth() const { return mViewportSize.x; } /// Gets height of the viewport @@ -244,11 +244,11 @@ class GenericCamera : public CameraBase // /// Gets the currently active view matrix (depends on stereo mode and current eye) - glm::mat4 getViewMatrix() const; + virtual glm::mat4 getViewMatrix() const; /// Gets the currently active view matrix (depends on stereo mode and current eye) glm::mat4 getInverseViewMatrix() const; /// Gets the currently active projection matrix (depends on stereo mode and current eye) - glm::mat4 getProjectionMatrix() const; + virtual glm::mat4 getProjectionMatrix() const; /////////////////////////////////////////////////////////////////////////////////////////// @@ -307,7 +307,7 @@ class GenericCamera : public CameraBase * @param _position New position of the camera. */ void setPosition( const glm::vec3 &_position ) { mPosition = _position; } - glm::vec3 getPosition() const { return mPosition; } + virtual glm::vec3 getPosition() const { return mPosition; } /// Moves the camera by a given vector (in eyespace) void move( const glm::vec3 &_vector ); diff --git a/include/ACGL/Scene/HMDCamera.hh b/include/ACGL/Scene/HMDCamera.hh new file mode 100644 index 0000000000000000000000000000000000000000..26f81cf8266fe2895f64a338bbbabc340d4f7899 --- /dev/null +++ b/include/ACGL/Scene/HMDCamera.hh @@ -0,0 +1,78 @@ +/*********************************************************************** + * Copyright 2011-2013 Computer Graphics Group RWTH Aachen University. * + * All rights reserved. * + * Distributed under the terms of the MIT License (see LICENSE.TXT). * + **********************************************************************/ +#pragma once + +/** + * This camera class extends the GenericCamera to better support a + * HeadMountedDisplay. + * + * The usual GenericCamera API controls the position and orientation + * of the *neck* of the camera while the added API add a head rotation + * and an offset of the neck to the eyes. + * These additional values should be set by the HMD hardware. + * + * The projection matrix can also handle an offset applied from the *left* + * to the projection matrix from the GenericCamera. This is needed for + * some HMDs. + * + */ + +#include <ACGL/ACGL.hh> +#include <ACGL/Scene/GenericCamera.hh> + +namespace ACGL{ +namespace Scene{ + +class HMDCamera : public GenericCamera +{ +public: + + HMDCamera(); + virtual ~HMDCamera() {} + + //! View plus the neck transformation + virtual glm::mat4 getViewMatrix() const; + + //! projection of the current eye translated by the projection center offset + virtual glm::mat4 getProjectionMatrix() const; + + //! projection offset for the left eye, the right eye will mult the X component with -1 + void setProjectionCenterOffset( const glm::vec2 &_projectionCenterOffset ); + + /* + * o = eye + * x = neck == point of rotation + * + * |---| <- mNeckToEyeHorizontalDistance + * + * /----\ + * |o | --- + * | | | <- mNeckToEyeVerticalDistance + * \__ | | + * |x| --- + */ + void setNeckToEyeVerticalDistance( float _f ); + void setNeckToEyeHorizontalDistance( float _f ); + + void setHMDRotation( const glm::mat3 &_rotation ); + +private: + //! stored as a translation vector + glm::vec2 mProjectionCenterOffset; + + //! height of the eyes above the neck, just height difference in meters + float mNeckToEyeVerticalDistance; + + //! distance eyes to neck without the height in meters + float mNeckToEyeHorizontalDistance; + + //! rotation of the HMD + glm::mat4 mHMDRotation; +}; +ACGL_SMARTPOINTER_TYPEDEFS(HMDCamera) + +} +} diff --git a/src/ACGL/Scene/CameraBase.cc b/src/ACGL/Scene/CameraBase.cc index 660000fc7d3737492516bbf3ef1c09f992b2e160..a9044cd7692555daad1faf850844cb47197d26cc 100644 --- a/src/ACGL/Scene/CameraBase.cc +++ b/src/ACGL/Scene/CameraBase.cc @@ -1,3 +1,9 @@ +/*********************************************************************** + * Copyright 2011-2013 Computer Graphics Group RWTH Aachen University. * + * All rights reserved. * + * Distributed under the terms of the MIT License (see LICENSE.TXT). * + **********************************************************************/ + #include <ACGL/Scene/CameraBase.hh> namespace ACGL{ diff --git a/src/ACGL/Scene/FixedCamera.cc b/src/ACGL/Scene/FixedCamera.cc index 181828bff1fc56616c1c1b66bf616e37a4d9ea55..2dbf9ae3f8d74d399058722205894b1f96565f3c 100644 --- a/src/ACGL/Scene/FixedCamera.cc +++ b/src/ACGL/Scene/FixedCamera.cc @@ -1,3 +1,8 @@ +/*********************************************************************** + * Copyright 2011-2013 Computer Graphics Group RWTH Aachen University. * + * All rights reserved. * + * Distributed under the terms of the MIT License (see LICENSE.TXT). * + **********************************************************************/ #include <ACGL/Scene/FixedCamera.hh> diff --git a/src/ACGL/Scene/HMDCamera.cc b/src/ACGL/Scene/HMDCamera.cc new file mode 100644 index 0000000000000000000000000000000000000000..ac066509d68c1f7625cbccb9b267dfe4350604a8 --- /dev/null +++ b/src/ACGL/Scene/HMDCamera.cc @@ -0,0 +1,68 @@ +/*********************************************************************** + * Copyright 2011-2013 Computer Graphics Group RWTH Aachen University. * + * All rights reserved. * + * Distributed under the terms of the MIT License (see LICENSE.TXT). * + **********************************************************************/ + +#include <ACGL/Scene/HMDCamera.hh> + +namespace ACGL{ +namespace Scene{ + +HMDCamera::HMDCamera() +{ + setStereoMode( GenericCamera::PARALLEL_SHIFT ); + mNeckToEyeVerticalDistance = 0.0f; + mNeckToEyeHorizontalDistance = 0.0f; + + mHMDRotation = glm::mat4(1.0f); +} + +void HMDCamera::setProjectionCenterOffset( const glm::vec2 &_projectionCenterOffset ) +{ + mProjectionCenterOffset = _projectionCenterOffset; +} + +void HMDCamera::setNeckToEyeVerticalDistance( float _f ) +{ + mNeckToEyeVerticalDistance = _f; +} + +void HMDCamera::setNeckToEyeHorizontalDistance( float _f ) +{ + mNeckToEyeHorizontalDistance = _f; +} + +void HMDCamera::setHMDRotation( const glm::mat3 &_rotation ) +{ + mHMDRotation = glm::mat4( _rotation ); +} + + +glm::mat4 HMDCamera::getViewMatrix() const +{ + glm::mat4 viewMatrix = GenericCamera::getViewMatrix(); + + glm::vec3 up = -mNeckToEyeVerticalDistance * glm::normalize( getUpDirection() ); + glm::vec3 forward = -mNeckToEyeHorizontalDistance * glm::normalize( getForwardDirection() ); + + glm::mat4 neck = glm::translate( up ) * glm::translate( forward ); + + return neck * mHMDRotation * viewMatrix; +} + + +glm::mat4 HMDCamera::getProjectionMatrix() const +{ + glm::mat4 projectionOffset; + if (getEye() == GenericCamera::EYE_RIGHT) { + projectionOffset = glm::translate( -mProjectionCenterOffset.x, mProjectionCenterOffset.y, 0.0f ); + } else { + projectionOffset = glm::translate( mProjectionCenterOffset.x, mProjectionCenterOffset.y, 0.0f ); + } + return projectionOffset * GenericCamera::getProjectionMatrix(); // yes, from the left side! +} + + +} +}