OculusRiftCamera.cc 4 KB
Newer Older
1 2 3 4 5 6
/***********************************************************************
 * Copyright 2011-2013 Computer Graphics Group RWTH Aachen University. *
 * All rights reserved.                                                *
 * Distributed under the terms of the MIT License (see LICENSE.TXT).   *
 **********************************************************************/

7
#if ACGL_RIFT_SDK_VERSION >= 32
Robert Menzel's avatar
Robert Menzel committed
8

9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
#include <ACGL/Scene/OculusRiftCamera.hh>

#include <ACGL/Utils/Log.hh>

#include <ACGL/HardwareSupport/RiftSdk.hh>

#include <glm/ext.hpp>
#include <glm/gtc/matrix_transform.hpp>

namespace ACGL{
namespace Scene{

using namespace std;
using namespace ACGL::Utils;
using namespace ACGL::HardwareSupport;

static glm::quat ovr2glm(const ovrQuatf& _quat)
{
	glm::quat q;
	q.x = _quat.x;
	q.y = _quat.y;
	q.z = _quat.z;
	q.w = _quat.w;
	return q;
}
static glm::vec3 ovr2glm(const ovrVector3f& _vec)
{
	// This cast is ok as ovrVector3f has the same internal structure
	return *(glm::vec3*)&_vec;
}
static glm::mat4 ovr2glm(const ovrMatrix4f& _matrix)
{
	// CAUTION: column-major vs. row-major difference
	return glm::transpose(*(glm::mat4*)&_matrix);
	/*glm::mat4 m;
	for (int i = 0; i < 4; ++i) {
		for (int j = 0; j < 4; ++j) {
			m[i][j] = _matrix.M[j][i];
		}
	}
	return m;*/
}
	
void OculusRiftCamera::connectWithRift(ovrHmd _hmd)
{
	mHmd = _hmd;
	ovrHmdDesc hmdDesc;
	ovrHmd_GetDesc(_hmd, &hmdDesc);
	mActiveEye = 0;

	// both eyes are equal,
	// two texture rendering, NOT side-by-side:
	glm::uvec2 renderTargetSizeForOneEye = getOptimalRenderSizePerEye(_hmd);
	ovrSizei ovrRenderTargetSizeForOneEye;
	ovrRenderTargetSizeForOneEye.w = renderTargetSizeForOneEye.x;
	ovrRenderTargetSizeForOneEye.h = renderTargetSizeForOneEye.y;

	ovrRecti perEyeViewport;
	perEyeViewport.Pos = { 0, 0 };
	perEyeViewport.Size = ovrRenderTargetSizeForOneEye;

	for (int i = 0; i < 2; ++i) {
		// for all eyes:
		mEyeDescription[i].Eye = hmdDesc.EyeRenderOrder[i];
		mEyeDescription[i].Fov = hmdDesc.DefaultEyeFov[i];
		mEyeDescription[i].TextureSize = ovrRenderTargetSizeForOneEye;
		mEyeDescription[i].RenderViewport = perEyeViewport;

		// the eye ordering (left-right or right-left) is defined by the SDK based on the
		// hardware!
		if (mEyeDescription[i].Eye == ovrEye_Left) {
				mEyeOrdering[i] = GenericCamera::Eye::EYE_LEFT;
		} else {
				mEyeOrdering[i] = GenericCamera::Eye::EYE_RIGHT;
		}
	}
}


GenericCamera::Eye OculusRiftCamera::startRenderingEye(int _eyeNumber)
{
	mPoseUsedForRendering[_eyeNumber] = ovrHmd_BeginEyeRender(mHmd, mEyeDescription[_eyeNumber].Eye);
	setEye(mEyeOrdering[_eyeNumber]);
	mActiveEye = _eyeNumber;

	/*debug() << "Render Eye " << mActiveEye << ": "
			<< mPoseUsedForRendering[_eyeNumber].Orientation.w << " "
			<< mPoseUsedForRendering[_eyeNumber].Orientation.x << " "
			<< mPoseUsedForRendering[_eyeNumber].Orientation.y << " "
			<< mPoseUsedForRendering[_eyeNumber].Orientation.z << endl;*/

	updateFromRift();

	return mEyeOrdering[_eyeNumber];
}

void OculusRiftCamera::stopRenderingEye(int _eyeNumber, ovrTexture* eyeTexture)
{
	ovrHmd_EndEyeRender(mHmd, mEyeDescription[_eyeNumber].Eye, mPoseUsedForRendering[_eyeNumber], eyeTexture);
}

void OculusRiftCamera::updateFromRift()
{
	// get orientation quaternion and set camera state
	// get translation and set it.

	// empty for now as matrices are constructed on-the-fly
}

glm::mat4 OculusRiftCamera::getProjectionMatrix() const
{
	ovrMatrix4f projectionMatrix = ovrMatrix4f_Projection(mEyeDescription[mActiveEye].Fov, getNearClippingPlane(), getFarClippingPlane(), true);
	return ovr2glm(projectionMatrix);
}

glm::vec3 OculusRiftCamera::getPosition() const
{
	return ovr2glm(mPoseUsedForRendering->Position);
}

glm::mat4 OculusRiftCamera::getViewMatrix() const
{
	return glm::mat4_cast(ovr2glm(mPoseUsedForRendering->Orientation)) * glm::translate(ovr2glm(mPoseUsedForRendering->Position));
}

glm::uvec2 OculusRiftCamera::getViewportSize() const
{
	return glm::uvec2(
		mEyeDescription[mActiveEye].TextureSize.w,
		mEyeDescription[mActiveEye].TextureSize.h);
}

}
}
Robert Menzel's avatar
Robert Menzel committed
143

144
#endif // ACGL_RIFT_SDK_VERSION >= 32