Saxum/extern/acgl/include/ACGL/HardwareSupport/SimpleRiftController.hh

224 lines
9.1 KiB
C++
Raw Normal View History

2014-10-20 15:31:26 +00:00
#pragma once
/**
* IMPORTANT: DON'T EXPECT THIS CLASS TO HAVE A FINAL AND STABLE API!
*
* This class needs the LibOVR version 0.2.4 or higher to work.
* Headers of this lib need to be placed in the search path.
*
* In addition ACGL_USE_OCULUS_RIFT has to be defined.
*
*
*/
#include <ACGL/ACGL.hh>
#ifdef ACGL_USE_OCULUS_RIFT
#include <ACGL/Math/Math.hh>
#include <glm/gtc/quaternion.hpp>
#include <ACGL/Scene/HMDCamera.hh>
#include <ACGL/OpenGL/Objects/Texture.hh>
#include <ACGL/OpenGL/Managers.hh>
#include <ACGL/HardwareSupport/OVRWrapper.hh>
namespace ACGL{
namespace HardwareSupport{
/**
* This class provides access to the Oculus Rift. It can read out the orientation and control a HMDCamera
* based on this.
* Distorted rendering is provided in two ways:
* * renderDistorted( texture ) if the input is one side-by-side rendered image
* * renderDistorted( texture, texture ) if the input are two seperate textures for the both eyes
*
* Alternatively the application can implement the distortion on its own (e.g. to add other effects in the
* same pass). For this the needed parameters are provided.
*
* Use the camera provided by this class (getCamera) or provide your own (attachCamera).
* This class needs to use a HMDCamera which is derived from GenericCamera!
*/
class SimpleRiftController
{
public:
/**
* _riftnumber: which device to use in case multiple are attached - NOTE: the Rift SDK has problems supporting this yet!
* _performAutomaticMagneticCalibration: try to calibrate the magetometer to reduce drift
* the user has to look into at least four very different directions
* for this to work.
*/
SimpleRiftController( uint32_t _riftnumber = 0 );
~SimpleRiftController();
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Camera and sensor handling:
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
//! attach an external camera to manipulate (see updateCamera)
//! per default the SimpleRiftController already has a camera which can be used as well
//! only one camera can be attached at all times
void attachCamera( ACGL::Scene::SharedHMDCamera _camera );
ACGL::Scene::SharedHMDCamera getCamera() { return mCamera; }
//! Query the orientation of the Rift and set it as the cameras orientation.
//! This will do nothing if no Rift is attached (so the camera can get controlled
//! e.g. by a mouse)!
void updateCamera();
//! returns the current orientation as a rotation matrix from the device.
//! this can be used as an alternative to updateCamera if the attached camera should not be used.
glm::mat3 getCurrentRotation();
//! sets the amound of seconds to predict the headmovements into the future
//! default is 0.03f, should be no more than the rendering latency!
void setPrediction( float _seconds );
void setFoVMultiplier( float _factor ) { mFoVMultiplier = _factor; updateCameraFoV(); }
float getFoVMultiplier() { return mFoVMultiplier; }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Access to direct sensor data as an alternative to the use of the ACGL camera
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
//! get the rotation as a quaternion, the native format of the Rift (with sensor fusion):
glm::quat getFusedRotationQuaternion();
//! get the rotation as a quaternion, the native format of the Rift (without sensor fusion):
glm::quat getRotationQuaternion();
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// RAW parameters for distortion rendering:
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
//! Default is 1.0, larger values result in higher FoVs and larger areas of the Rift being used.
//! Note that - depending on the lenses used - the user will not be able to see the whole screen.
//! Often 1.75 is enough.
//! Increase the offscreen rendering viewport accordingly to counter the decreased image quality.
void setDistortionScaleFactor( float _f );
float getDistortionScaleFactor() { return mDistortionScaleFactor; }
//! x,y are the values for the left eye. z,w the values for the right eye
glm::vec4 getLensCenter();
//! x,y are the values for the left eye. z,w the values for the right eye
glm::vec4 getScreenCenter();
//! x,y are the values for both eyes, ignore z,w
glm::vec4 getScale();
//! x,y are the values for both eyes, ignore z,w
glm::vec4 getScaleIn();
//! the four distortion parameters are the same for both eyes
glm::vec4 getHmdWarpParam();
//! the four chromatic aberation parameters are the same for both eyes
glm::vec4 getChromAbParam();
//! the full physical screen resolution, offscreen rendering should get performed at a higher resolution!
//! 'full' means it's the size used for both eyes!
glm::uvec2 getPhysicalScreenResolution();
//! returns the stereo projection from the stored camera adjusted for the rift
//! returns nonsens in case no camera was set
glm::mat4 getProjectionMatrixFromCamera();
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Optional integrated distortion rendering:
//
// If it's activated and used, make sure the RiftDistort* shader files are located where the
// ShaderProgramFileManager can find them.
// They may set texture units 0..3 and render to Framebuffer 0 (which will get bound) using the viewport of the
// physical dimensions of the rift!
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
void renderDistorted( ACGL::OpenGL::ConstSharedTexture2D _sideBySideTexture );
void renderDistorted( ACGL::OpenGL::ConstSharedTexture2D _leftTexture, ACGL::OpenGL::ConstSharedTexture2D _rightTexture );
void renderDistortedP( ACGL::OpenGL::ConstSharedShaderProgram _program );
bool getSuccessfulConnected() { return mSuccessfulConnected; }
//! activate and deactivate the distortion, only works if the renderers above are used, does not change the raw
//! distortion parameters!
void setDistortion( bool _value ) { mUseDistortion = _value; }
bool getDistortion() { return mUseDistortion; }
//! activate and deactivate the chromatic aberation correction (true to correct the aberation), only works if the renderers
//! above are used, does not change the raw distortion parameters!
void setChromaticAberation( bool _value ) { mUseChromaticAberation = _value; }
bool getChromaticAberation() { return mUseChromaticAberation; }
//! Sets the size of the final rendering. This should be the size of the window to render into.
void setOutputViewportSize( glm::uvec2 _size ) { mOutputViewport = _size; }
//! Defines that the current HMD orientations should be defined as "no rotation"
//! Can be used to "reset" the orientation.
//! Note: if the user is just looking in the wrong direction, use setNeutralYaw(), if e.g. looking up should be
//! neutral (laying on the ground), this is the way to go.
void setNeutralPosition();
void resetNeutralRotation() {setNeutralPosition();}
//! Will define the current view direction as the neutral direction but only takes yaw into account.
//! Will also reset the neutral position.
//! Basically works as if the Rift was started in the current orientation
void setNeutralYaw();
private:
// for rendering:
ACGL::OpenGL::SharedShaderProgram mDistortShaderSideBySide;
ACGL::OpenGL::SharedShaderProgram mDistortShaderTwoTextures;
ACGL::OpenGL::SharedVertexArrayObject mVAO;
GLint uLensCenter;
GLint uScreenCenter;
GLint uScale;
GLint uScaleIn;
GLint uHmdWarpParam;
GLint uChromAbParam;
GLint uDistort;
GLint uCorrectChromaticAberation;
bool mBuildInShader;
bool mUseDistortion;
bool mUseChromaticAberation;
glm::uvec2 mOutputViewport; // if it's 0,0 -> use the Rifts screen dimensions!
private:
glm::vec4 getShaderValue( int v );
void updateCameraFoV();
bool mSuccessfulConnected;
ACGL::Scene::SharedHMDCamera mCamera;
float mDistortionScaleFactor;
// handles to the rift:
OVR::Ptr<OVR::DeviceManager> mORManager;
OVR::Ptr<OVR::HMDDevice> mORDevice;
OVR::Ptr<OVR::SensorDevice> mORSensor;
OVR::SensorFusion *mORSensorFusion;
OVR::HMDInfo *mORHMDInfo;
// all rotations are relative to the one the Rift started with:
OVR::Quatf mInverseNeutralRotation; // as quaternion
float mPredictionTime;
float mFoVMultiplier;
};
ACGL_SMARTPOINTER_TYPEDEFS(SimpleRiftController)
}
}
#endif // ACGL_USE_OCULUS_RIFT