RiftSdk.cc 6.43 KB
Newer Older
1 2 3 4 5 6 7 8
#include <ACGL/HardwareSupport/RiftSdk.hh>
#include <ACGL/OpenGL/Creator/ShaderProgramCreator.hh>

#include <iostream>

#include <ACGL/Utils/Log.hh>

#ifdef ACGL_USE_OCULUS_RIFT
9 10 11 12 13 14 15 16 17
#if ACGL_RIFT_SDK_VERSION >= 40

#ifdef ACGL_COMPILE_WITH_GLFW
	#define GLFW_EXPOSE_NATIVE_WIN32
	#define GLFW_EXPOSE_NATIVE_WGL
	#include <GLFW/glfw3.h>
	#include <GLFW/glfw3native.h>
#endif
#include <OVR_CAPI_GL.h>
18 19 20 21 22 23 24 25 26 27 28 29 30

namespace ACGL{
namespace HardwareSupport{

	using namespace std;
	using namespace ACGL::Utils;

	// C API helpers:

	static bool ACGL_RiftSDKInitialized = false;

	bool initRiftSDK()
	{
31 32
		cout << "initRiftSDK()" << endl;

33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
		if (ACGL_RiftSDKInitialized) return true; // don't init twice

		ovrBool ok = ovr_Initialize();
		if (!ok) {
			error() << "could not initialize Oculus Rift library" << endl;
		}
		else {
			ACGL_RiftSDKInitialized = true;
		}
		return ACGL_RiftSDKInitialized;
	}

	void shutdownRiftSDK()
	{
		ovr_Shutdown();
	}

	// For more sophisticated use cases build your own Rift for your needs based on the Rift SDK instead of using this default Rift.
	//
	// _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 createRift(bool _headTrackingIsRequired, bool _headTranslationTrackingIsAllowed)
	{
57 58
		cout << "createRift()" << endl;

59 60 61 62 63 64 65 66 67 68
		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) {
69 70 71 72 73 74 75 76 77

#if ACGL_RIFT_USE_DUMMY
            warning() << "could not connect to a real Oculus Rift HMD - generating sensorless dummy" << endl;
            mHmd = ovrHmd_CreateDebug(ovrHmd_DK1);
#else
            debug() << "could not connect to a real Oculus Rift HMD" << endl;
            mHmd = NULL;
#endif

78 79
			//ovrHmd_SetEnabledCaps(mHmd, ovrHmdCap_NoMirrorToWindow);

80
            return mHmd;
81
		}
82 83
		
		
84
		// debug output:
85
		debug() << "Connected to: " << mHmd->ProductName << endl;
86 87 88

		// start the tracking:
		// what the application supports:
89 90
		unsigned int supportedCaps = ovrTrackingCap_Orientation | ovrTrackingCap_MagYawCorrection | ovrTrackingCap_Position; // | ovrHmdCap_LowPersistence | ovrHmdCap_DynamicPrediction;
		if (_headTranslationTrackingIsAllowed) supportedCaps |= ovrTrackingCap_Position;
91 92 93

		// what the device must deliver as a bare minimum:
		unsigned int requiredCaps = 0;
94 95 96 97
		if (_headTrackingIsRequired) requiredCaps |= ovrTrackingCap_Orientation;


		ovrBool ok = ovrHmd_ConfigureTracking(mHmd, supportedCaps, requiredCaps);
98 99 100
		if (!ok) {
			error() << "could not get connected to a Rift tracker - only rendering is supported" << endl;
		}
101
		
102 103 104 105 106 107 108 109 110 111 112 113
		return mHmd;
	}

	void destroyRift(ovrHmd _hmd)
	{
		ovrHmd_Destroy(_hmd);
	}


	glm::uvec2 getOptimalRenderSizePerEye(ovrHmd _hmd)
	{
		if (_hmd == NULL) return glm::uvec2(640, 800);
114 115
		ovrSizei optimalLeft  = ovrHmd_GetFovTextureSize(_hmd, ovrEye_Left,  _hmd->DefaultEyeFov[0], 1.0f);
		ovrSizei optimalRight = ovrHmd_GetFovTextureSize(_hmd, ovrEye_Right, _hmd->DefaultEyeFov[1], 1.0f);
116 117 118 119

		debug() << "optimalLeft  " << optimalLeft.w << " " << optimalLeft.h << endl;
		debug() << "optimalRight " << optimalRight.w << " " << optimalRight.h << endl;

120 121
		debug() << "hmd: " << _hmd->ProductName << endl;
		debug() << "hmd WindowsPos: " << _hmd->WindowsPos.x << " " << _hmd->WindowsPos.y << endl;
122 123

		return glm::uvec2(glm::max(optimalLeft.w, optimalRight.w), glm::max(optimalLeft.h, optimalRight.h));
124 125

		//return glm::uvec2(960, 1200);
126
	}
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205

#ifdef ACGL_COMPILE_WITH_GLFW
	bool configureRendering( ovrHmd _hmd, ovrEyeRenderDesc _eyeRenderDesc[2], glm::uvec2 _renderTagetSize, GLFWwindow *_window )
	{
		glBindVertexArray(0);

		// Update ovr Rendering configuration
		ovrGLConfig cfg;
		cfg.OGL.Header.API = ovrRenderAPI_OpenGL;
		cfg.OGL.Header.RTSize.w = _renderTagetSize.x;
		cfg.OGL.Header.RTSize.h = _renderTagetSize.y;
		cfg.OGL.Header.Multisample = 0;

#ifdef OVR_OS_WIN32
		debug() << "configure Windows specifics" << std::endl;

		cfg.OGL.Window = glfwGetWin32Window( _window );
		cfg.OGL.DC = GetDC(cfg.OGL.Window);
#endif
#ifdef OVR_OS_MAC
		debug() << "configure Mac specifics: TODO" << std::endl;
#endif
#ifdef OVR_OS_LINUX
		debug() << "configure Linux specifics: TODO" << std::endl;
#endif

		debug() << "call ovrHmd_ConfigureRendering():" << std::endl;
		printOVRDistortionCaps(_hmd->DistortionCaps);
		unsigned int distortionCaps = _hmd->DistortionCaps ^ ovrDistortionCap_FlipInput; // don't flip the input
		//distortionCaps ^= ovrDistortionCap_NoRestore;
		distortionCaps ^= ovrDistortionCap_SRGB;

		printOVRDistortionCaps(distortionCaps);
		ovrBool ok = ovrHmd_ConfigureRendering(_hmd, (ovrRenderAPIConfig*)&cfg, distortionCaps, _hmd->DefaultEyeFov, _eyeRenderDesc);
		if (ok) {
			bool riftIsUsingExtendedDesktop = (bool)(_hmd->HmdCaps & ovrHmdCap_ExtendDesktop);
			if (riftIsUsingExtendedDesktop) {
				debug() << "rendering on extended desktop" << endl;
			} else {
				debug() << "rendering in direct rendering mode" << endl;
				ovrHmd_AttachToWindow(_hmd, cfg.OGL.Window, nullptr, nullptr);
			}

			debug() << "OVR Rendering configured" << std::endl;
		}
		else {
			error() << "OVR Rendering failed to get configured" << std::endl;
		}

		return (bool)ok;
	}
#endif

	bool deactivateHealthWarning(ovrHmd _hmd)
	{
		ovrHSWDisplayState displayState;
		ovrHmd_GetHSWDisplayState(_hmd, &displayState);

		if (displayState.Displayed) {
			ovrHmd_DismissHSWDisplay(_hmd);
			return true;
		}

		return false;
	}

	// prints the distortion caps for debugging:
	void printOVRDistortionCaps(unsigned int _caps) {
		debug() << endl << "Distortion caps: " << _caps << " = ";
		if (_caps & ovrDistortionCap_Chromatic) debug() << "Chromatic ";
		if (_caps & ovrDistortionCap_TimeWarp) debug() << "TimeWarp ";
		if (_caps & ovrDistortionCap_Vignette) debug() << "Vignette ";
		if (_caps & ovrDistortionCap_NoRestore) debug() << "GLStateChangedBySDK ";
		if (_caps & ovrDistortionCap_FlipInput) debug() << "FlipInput ";
		if (_caps & ovrDistortionCap_SRGB) debug() << "sRGB_Input ";
		if (_caps & ovrDistortionCap_Overdrive) debug() << "reduceDK2Artefacts ";
		debug() << endl << endl;
	}

206 207 208 209
}
}

#endif
210
#endif