Commit 5e5b9bf5 authored by Robert Menzel's avatar Robert Menzel

Oculus SDK 0.4 compatible SimpleRiftController

parent 351a2917
cmake @ a0eb0dda
Subproject commit c4eead9bcb430fed3e99ee0df0f2b06559df5db4
Subproject commit a0eb0dda91ce5d621d47de52bcecdd494b00e353
......@@ -42,8 +42,15 @@
//
/////////////////////////////////////////////////////////////////////////////////////
#if ACGL_RIFT_SDK_VERSION < 40
// used for SDK 0.2.5
#include <OVR.h>
#include <OVRVersion.h>
#else
#include <OVR_Version.h>
#include <OVR_CAPI.h>
#include <OVR_CAPI_GL.h>
#endif
/////////////////////////////////////////////////////////////////////////////////////
// reactivate compiler warnings:
......
......@@ -33,7 +33,10 @@
*
*/
#ifdef ACGL_USE_OCULUS_RIFT
#if ACGL_RIFT_SDK_VERSION >= 40
#include <OVR_Version.h>
#if ((OVR_MAJOR_VERSION > 0) || (OVR_MINOR_VERSION >= 4))
#include <ACGL/ACGL.hh>
......@@ -56,7 +59,7 @@ namespace OVR{
void shutdownSDK();
// create a standard Rift, can be replaced with own, more specialized code:
ovrHmd createHMD(bool _headTrackingIsRequired = false, bool _headTranslationTrackingIsAllowed = true);
ovrHmd createHMD(uint32_t _riftNumber = 0);
void destroyHMD(ovrHmd _hmd);
// SDK gives different sizes per eye, return the max to make things easier:
......@@ -65,8 +68,8 @@ namespace OVR{
// returns a ovrEyeRenderDesc[2] used by the SDK in _eyeRenderDesc. The returned struct stores the size of the
// textures, so update this if the textures change in size!
// _eyeRenderDesc has to be an array with at least two elements!
void generateEyeTextureDescription(ACGL::OpenGL::SharedTexture2D _leftTexture,
ACGL::OpenGL::SharedTexture2D _rightTexture,
void generateEyeTextureDescription(ACGL::OpenGL::ConstSharedTexture2D _leftTexture,
ACGL::OpenGL::ConstSharedTexture2D _rightTexture,
ovrGLTexture _eyeRenderDesc[2]);
// the Rift SDK needs to know our window, this function hides the window system/OS specifics:
......@@ -92,3 +95,4 @@ namespace OVR{
#endif // RIFT_VERSION
#endif // ACGL_USE_OCULUS_RIFT
#endif
......@@ -13,7 +13,7 @@
#include <ACGL/ACGL.hh>
#ifdef ACGL_USE_OCULUS_RIFT
#if ACGL_RIFT_SDK_VERSION < 32
#if ACGL_RIFT_SDK_VERSION < 40
#include <ACGL/Math/Math.hh>
#include <glm/gtc/quaternion.hpp>
......@@ -221,5 +221,72 @@ ACGL_SMARTPOINTER_TYPEDEFS(SimpleRiftController)
}
}
#else
#include <ACGL/Math/Math.hh>
#include <glm/gtc/quaternion.hpp>
#include <ACGL/Scene/OculusRiftCamera.hh>
#include <ACGL/Scene/GenericCamera.hh>
//#include <ACGL/Scene/HMDCamera.hh>
#include <ACGL/OpenGL/Objects/Texture.hh>
#include <ACGL/HardwareSupport/OVRWrapper.hh>
#include <ACGL/HardwareSupport/RiftSdk.hh>
namespace ACGL{
namespace HardwareSupport{
class SimpleRiftController
{
public:
SimpleRiftController(uint32_t _riftnumber = 0);
~SimpleRiftController();
// only used for compatibility with the old SimpleRiftController:
ACGL::Scene::SharedGenericCamera getCamera() {
if (mHMD) { return mCamera; }
else { return mNormalCamera; }
}
ACGL::Scene::SharedOculusRiftCamera getOVRCamera() { return mCamera; }
// set the textures to render into to this size or smaller:
glm::uvec2 getOptimalRenderSizePerEye() { return OVR::getOptimalRenderSizePerEye(mHMD); }
// update the camera to catch the position for the eye 0 or 1, don't assume that 0 is left!
// call updateCameraEye(0) and updateCameraEye(1) once per frame!
ACGL::Scene::GenericCamera::Eye updateCameraEye(int _eyeNumber);
//! 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();
// if _outputViewportSize is 0, use mOutputViewportSize (set previously by setOutputViewportSize() );
void configureRendering(ACGL::OpenGL::ConstSharedTexture2D _leftTexture, ACGL::OpenGL::ConstSharedTexture2D _rightTexture );
void renderDistorted();
void setGLFWWindow(GLFWwindow *_window) { mGLFWWindow = _window; }
bool getSuccessfulConnected() { return (mHMD != NULL); }
private:
ACGL::Scene::SharedOculusRiftCamera mCamera;
ACGL::Scene::SharedGenericCamera mNormalCamera;
ovrHmd mHMD;
bool mRenderingConfigured;
ovrGLTexture mGLTexture[2];
GLFWwindow *mGLFWWindow;
int mNextExpectedEyeNumber;
};
ACGL_SMARTPOINTER_TYPEDEFS(SimpleRiftController)
}
}
#endif // RIFT_VERSION
#endif // ACGL_USE_OCULUS_RIFT
\ No newline at end of file
......@@ -16,7 +16,7 @@
* users body to the requested eye.
*
*/
#if ACGL_RIFT_SDK_VERSION >= 32
#if ACGL_RIFT_SDK_VERSION == 32
#include <ACGL/ACGL.hh>
#include <ACGL/Scene/GenericCamera.hh>
......@@ -65,5 +65,71 @@ private:
ACGL_SMARTPOINTER_TYPEDEFS(OculusRiftCamera)
}
}
#else
// SDK 0.4 or later:
#include <ACGL/ACGL.hh>
#include <ACGL/Scene/MoveableObject.hh>
#include <ACGL/Scene/CameraBase.hh>
#include <ACGL/Scene/GenericCamera.hh>
#include <OVR_CAPI.h>
namespace ACGL{
namespace Scene {
class OculusRiftCamera : public GenericCamera { //public CameraBase, public MoveableObject {
public:
OculusRiftCamera();
void connectWithRift(ovrHmd _hmd) { mHmd = _hmd; }
virtual glm::vec3 getPosition() const override;
virtual glm::mat4 getViewMatrix() const override;
virtual glm::mat4 getProjectionMatrix() const override;
virtual glm::uvec2 getViewportSize() const override;
/**
* Set the near clipping plane of the camera.
* The plane is defined only by a distance from the camera.
* @param _plane New near clipping plane of the camera.
*/
//void setNearClippingPlane(float _plane);
/// Gets the near clip distance
//float getNearClippingPlane() const { return mNearClippingPlane; }
/**
* Set the far clipping plane of the camera.
* The plane is defined only by a distance from the camera.
* @param _plane New far clipping plane of the camera.
*/
//void setFarClippingPlane(float _plane);
/// Gets the far clip distance
//float getFarClippingPlane() const { return mFarClippingPlane; }
void setViewportSize(const glm::uvec2 _size) { mViewportSize = _size; }
// returns which eye was configured:
GenericCamera::Eye setPoseForEyeFromRift(int _eyeNumber);
ovrPosef* getPoseOfEyes() { return mPoseOfEyes; }
ovrEyeRenderDesc mEyeRenderDesc[2]; // needed for the projection matrix per eye as well as the view matrix
private:
ovrHmd mHmd;
glm::uvec2 mViewportSize;
ovrPosef mPoseOfEyes[2];
//float mNearClippingPlane;
//float mFarClippingPlane;
glm::vec3 mEyePosition;
glm::mat4 mViewMatrix;
glm::mat4 mProjectionMatrix;
};
ACGL_SMARTPOINTER_TYPEDEFS(OculusRiftCamera)
}
}
#endif // ACGL_RIFT_SDK_VERSION
......@@ -54,21 +54,14 @@ void shutdownSDK()
// _headTrackingIsRequired = if false, the call will create a dummy device that won't generate any data in case no real Rift is connected
// (for developing without an actual device).
// _headTranslationTrackingIsAllowed = if true the Tracking of DK2 will get supported, if false even a DK2 will behave like a DK1
ovrHmd createHMD(bool _headTrackingIsRequired, bool _headTranslationTrackingIsAllowed)
ovrHmd createHMD(uint32_t _riftNumber)
{
//cout << "createRift()" << endl;
if (!ACGL_RiftSDKInitialized) {
error() << "Rift SDK not initialized correctly - did you call/check initRiftSDK()?" << endl;
}
ovrHmd mHmd = ovrHmd_Create(0);
if (!mHmd && _headTrackingIsRequired) {
error() << "could not connect to an Oculus Rift HMD" << endl;
return NULL;
}
else if (!mHmd && !_headTrackingIsRequired) {
ovrHmd mHmd = ovrHmd_Create(_riftNumber);
if (!mHmd) {
#if ACGL_RIFT_USE_DUMMY
warning() << "could not connect to a real Oculus Rift HMD - generating sensorless dummy" << endl;
mHmd = ovrHmd_CreateDebug(ovrHmd_DK1);
......@@ -76,9 +69,6 @@ ovrHmd createHMD(bool _headTrackingIsRequired, bool _headTranslationTrackingIsAl
debug() << "could not connect to a real Oculus Rift HMD" << endl;
mHmd = NULL;
#endif
//ovrHmd_SetEnabledCaps(mHmd, ovrHmdCap_NoMirrorToWindow);
return mHmd;
}
......@@ -89,12 +79,9 @@ ovrHmd createHMD(bool _headTrackingIsRequired, bool _headTranslationTrackingIsAl
// start the tracking:
// what the application supports:
unsigned int supportedCaps = ovrTrackingCap_Orientation | ovrTrackingCap_MagYawCorrection | ovrTrackingCap_Position; // | ovrHmdCap_LowPersistence | ovrHmdCap_DynamicPrediction;
if (_headTranslationTrackingIsAllowed) supportedCaps |= ovrTrackingCap_Position;
// what the device must deliver as a bare minimum:
unsigned int requiredCaps = 0;
if (_headTrackingIsRequired) requiredCaps |= ovrTrackingCap_Orientation;
ovrBool ok = ovrHmd_ConfigureTracking(mHmd, supportedCaps, requiredCaps);
if (!ok) {
......@@ -126,7 +113,7 @@ glm::uvec2 getOptimalRenderSizePerEye(ovrHmd _hmd)
return glm::uvec2(glm::max(optimalLeft.w, optimalRight.w), glm::max(optimalLeft.h, optimalRight.h));
}
void generateEyeTextureDescription(ACGL::OpenGL::SharedTexture2D _leftTexture, ACGL::OpenGL::SharedTexture2D _rightTexture, ovrGLTexture _eyeRenderDesc[2])
void generateEyeTextureDescription(ACGL::OpenGL::ConstSharedTexture2D _leftTexture, ACGL::OpenGL::ConstSharedTexture2D _rightTexture, ovrGLTexture _eyeRenderDesc[2])
{
// same for both eyes:
for (int eyeIndex = 0; eyeIndex < 2; ++eyeIndex) {
......
......@@ -2,7 +2,7 @@
#include <ACGL/OpenGL/Creator/ShaderProgramCreator.hh>
#ifdef ACGL_USE_OCULUS_RIFT
#if ACGL_RIFT_SDK_VERSION < 32
#if ACGL_RIFT_SDK_VERSION < 40
using namespace OVR;
using namespace ACGL;
......@@ -736,5 +736,87 @@ void SimpleRiftController::renderDistortedP( ACGL::OpenGL::ConstSharedShaderProg
glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 ); // create 2 triangles with no attributes
}
#else
#include <ACGL/HardwareSupport/RiftSdk.hh>
using namespace ACGL;
using namespace ACGL::Utils;
using namespace ACGL::Scene;
using namespace ACGL::HardwareSupport;
using namespace ACGL::OpenGL;
using namespace std;
SimpleRiftController::SimpleRiftController(uint32_t _riftnumber) : mRenderingConfigured(false), mGLFWWindow(NULL), mNextExpectedEyeNumber(0) {
OVR::initSDK();
mHMD = OVR::createHMD(_riftnumber);
OVR::deactivateHealthWarning(mHMD);
mCamera = SharedOculusRiftCamera(new OculusRiftCamera());
mCamera->connectWithRift(mHMD);
// set a good default viewport:
glm::uvec2 viewport = getPhysicalScreenResolution();
viewport.x /= 2;
mCamera->setViewportSize(viewport);
}
SimpleRiftController::~SimpleRiftController() {
OVR::destroyHMD(mHMD);
OVR::shutdownSDK();
}
void SimpleRiftController::configureRendering(ACGL::OpenGL::ConstSharedTexture2D _leftTexture, ACGL::OpenGL::ConstSharedTexture2D _rightTexture) {
if (!mHMD) return;
assert(mGLFWWindow && "call setGLFWWindow first!");
int width, height;
glfwGetWindowSize(mGLFWWindow, &width, &height);
// mEyeRenderDesc will be set by this:
ACGL::HardwareSupport::OVR::configureRendering(mHMD, mCamera->mEyeRenderDesc, glm::uvec2(width,height), mGLFWWindow);
// mEyeTexture will be set:
ACGL::HardwareSupport::OVR::generateEyeTextureDescription(_leftTexture, _rightTexture, mGLTexture);
mRenderingConfigured = true;
}
void SimpleRiftController::renderDistorted() {
if (!mHMD) return;
assert(mRenderingConfigured && "SimpleRiftController::renderDistorted(): configure rendering first, call configureRendering() !");
assert(mNextExpectedEyeNumber == 2 && "call updateCameraEye for both eyes first!");
mNextExpectedEyeNumber = 0; // for the next frame
ovrHmd_EndFrame(mHMD, mCamera->getPoseOfEyes(), (ovrTexture*)mGLTexture);
}
glm::uvec2 SimpleRiftController::getPhysicalScreenResolution() {
return glm::uvec2(1920, 1080); // TODO!
}
GenericCamera::Eye SimpleRiftController::updateCameraEye(int _eyeNumber)
{
if (!mHMD) return GenericCamera::EYE_LEFT;
// make sure to switch between eye 0 and 1 exactly once per frame
assert(_eyeNumber == 0 || _eyeNumber == 1);
assert(_eyeNumber == mNextExpectedEyeNumber);
mNextExpectedEyeNumber++; // will wrap around in renderDistorted!
if (_eyeNumber == 0) {
// has to be called at the beginning of the frame, one reason why the eye order is important!
OVR::beginFrame(mHMD);
OVR::deactivateHealthWarning(mHMD);
}
return mCamera->setPoseForEyeFromRift(_eyeNumber);
}
#endif
#endif
#endif
\ No newline at end of file
......@@ -4,14 +4,12 @@
* Distributed under the terms of the MIT License (see LICENSE.TXT). *
**********************************************************************/
#if ACGL_RIFT_SDK_VERSION >= 32
#include <ACGL/Scene/OculusRiftCamera.hh>
#include <ACGL/Utils/Log.hh>
#include <ACGL/HardwareSupport/RiftSdk.hh>
#if ACGL_RIFT_SDK_VERSION == 32
#include <glm/ext.hpp>
#include <glm/gtc/matrix_transform.hpp>
......@@ -144,4 +142,84 @@ glm::uvec2 OculusRiftCamera::getViewportSize() const
}
}
#endif // ACGL_RIFT_SDK_VERSION >= 32
#else
// 0.4 version:
namespace ACGL{
namespace Scene{
using namespace std;
using namespace ACGL::Utils;
using namespace ACGL::HardwareSupport;
//OculusRiftCamera::OculusRiftCamera() : MoveableObject(), CameraBase()
OculusRiftCamera::OculusRiftCamera() : GenericCamera()
{
mHmd = NULL;
//mNearClippingPlane = 0.1; // 10 cm
//mFarClippingPlane = 5000.0; // 5000 meter
}
glm::vec3 OculusRiftCamera::getPosition() const
{
return mEyePosition;
}
glm::mat4 OculusRiftCamera::getViewMatrix() const
{
return mViewMatrix;
}
glm::mat4 OculusRiftCamera::getProjectionMatrix() const
{
return mProjectionMatrix;
}
glm::uvec2 OculusRiftCamera::getViewportSize() const
{
return mViewportSize;
}
GenericCamera::Eye OculusRiftCamera::setPoseForEyeFromRift(int _eyeNumber)
{
assert(_eyeNumber == 0 || _eyeNumber == 1);
ovrEyeType eyeType = mHmd->EyeRenderOrder[_eyeNumber];
ovrPosef eyePose = ovrHmd_GetEyePose(mHmd, eyeType);
mPoseOfEyes[eyeType] = eyePose;
GenericCamera::Eye eye;
if (eyeType == ovrEye_Left) eye = GenericCamera::EYE_LEFT;
if (eyeType == ovrEye_Right) eye = GenericCamera::EYE_RIGHT;
// pose:
glm::quat rotation{ eyePose.Orientation.w, eyePose.Orientation.x, eyePose.Orientation.y, eyePose.Orientation.z };
glm::vec3 translation{ eyePose.Position.x, eyePose.Position.y, eyePose.Position.z };
//std::cout << glm::to_string(translation) << std::endl;
// projection:
ovrMatrix4f ovrp = ovrMatrix4f_Projection(mEyeRenderDesc[_eyeNumber].Fov, getNearClippingPlane(), getFarClippingPlane(), true);
glm::mat4 projection{
ovrp.M[0][0], ovrp.M[1][0], ovrp.M[2][0], ovrp.M[3][0],
ovrp.M[0][1], ovrp.M[1][1], ovrp.M[2][1], ovrp.M[3][1],
ovrp.M[0][2], ovrp.M[1][2], ovrp.M[2][2], ovrp.M[3][2],
ovrp.M[0][3], ovrp.M[1][3], ovrp.M[2][3], ovrp.M[3][3]
};
mProjectionMatrix = projection;
glm::vec3 eyeOffset{ mEyeRenderDesc[_eyeNumber].ViewAdjust.x, mEyeRenderDesc[_eyeNumber].ViewAdjust.y, mEyeRenderDesc[_eyeNumber].ViewAdjust.z };
glm::vec4 basePosition = glm::vec4(MoveableObject::getPosition(), 1.0);
mEyePosition = glm::vec3{ glm::inverse(getViewMatrix()) * basePosition };
mViewMatrix = glm::translate(eyeOffset) * glm::inverse( glm::translate(translation) * glm::mat4_cast(rotation) ) * MoveableObject::getModelMatrix();
//mCamera.setHeadEyeOffset(eyeOffset);
//mCamera.setHeadOffsetMatrix(glm::translate(translation) * glm::mat4_cast(rotation));
return eye;
}
}
}
#endif // ACGL_RIFT_SDK_VERSION
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment