Torque3D/Engine/source/platform/input/oculusVR/oculusVRHMDDevice.cpp
DavidWyand-GG 85730dfb59 Oculus Rift Improvements
- Now requires OVR SDK 0.2.5
- New chromatic aberration correction shader.  Can be disabled by
setting $pref::OculusVR::UseChromaticAberrationCorrection to false prior
to enabling Rift display (such as for screen shots).
- FXAA on by default when using full screen on the Rift.
- Can now manually override IPD from script.  Otherwise value set in
profile is used.
- Raw sensor data now available through input events (set
$OculusVR::GenerateSensorRawEvents to true) and console methods.  The
raw data is acceleration, angular velocity, and magnetometer reading.
- Can determine if magnetometer calibration data is available using a
console method in order to notify the user.
2013-10-19 00:46:39 -04:00

233 lines
7.4 KiB
C++

//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#include "platform/input/oculusVR/oculusVRHMDDevice.h"
OculusVRHMDDevice::OculusVRHMDDevice()
{
mIsValid = false;
mIsSimulation = false;
mDevice = NULL;
}
OculusVRHMDDevice::~OculusVRHMDDevice()
{
cleanUp();
}
void OculusVRHMDDevice::cleanUp()
{
if(mDevice)
{
mDevice->Release();
mDevice = NULL;
}
mIsValid = false;
}
void OculusVRHMDDevice::set(OVR::HMDDevice* hmd, OVR::HMDInfo& info, bool calculateDistortionScale)
{
mIsValid = false;
mIsSimulation = false;
mDevice = hmd;
// DeviceInfo
mProductName = info.ProductName;
mManufacturer = info.Manufacturer;
mVersion = info.Version;
mDisplayDeviceName = info.DisplayDeviceName;
mDisplayId = info.DisplayId;
mDesktopPosition.x = info.DesktopX;
mDesktopPosition.y = info.DesktopY;
mResolution.x = info.HResolution;
mResolution.y = info.VResolution;
mScreenSize.x = info.HScreenSize;
mScreenSize.y = info.VScreenSize;
mVerticalEyeCenter = info.VScreenCenter;
mEyeToScreen = info.EyeToScreenDistance;
mLensSeparation = info.LensSeparationDistance;
mProfileInterpupillaryDistance = info.InterpupillaryDistance;
mInterpupillaryDistance = mProfileInterpupillaryDistance;
mKDistortion.x = info.DistortionK[0];
mKDistortion.y = info.DistortionK[1];
mKDistortion.z = info.DistortionK[2];
mKDistortion.w = info.DistortionK[3];
mChromaticAbCorrection.x = info.ChromaAbCorrection[0];
mChromaticAbCorrection.y = info.ChromaAbCorrection[1];
mChromaticAbCorrection.z = info.ChromaAbCorrection[2];
mChromaticAbCorrection.w = info.ChromaAbCorrection[3];
// Calculated values
calculateValues(calculateDistortionScale);
mIsValid = true;
}
void OculusVRHMDDevice::createSimulation(SimulationTypes simulationType, bool calculateDistortionScale)
{
if(simulationType == ST_RIFT_PREVIEW)
{
createSimulatedPreviewRift(calculateDistortionScale);
}
}
void OculusVRHMDDevice::createSimulatedPreviewRift(bool calculateDistortionScale)
{
mIsValid = true;
mIsSimulation = true;
mProductName = "Oculus Rift DK1-SLA1";
mManufacturer = "Oculus VR";
mVersion = 0;
mDisplayDeviceName = "";
mResolution.x = 1280;
mResolution.y = 800;
mScreenSize.x = 0.14975999f;
mScreenSize.y = 0.093599997f;
mVerticalEyeCenter = 0.046799999f;
mEyeToScreen = 0.041000001f;
mLensSeparation = 0.064000003f;
mProfileInterpupillaryDistance = 0.064000003f;
mInterpupillaryDistance = mProfileInterpupillaryDistance;
mKDistortion.x = 1.0000000f;
mKDistortion.y = 0.22000000f;
mKDistortion.z = 0.23999999f;
mKDistortion.w = 0.00000000f;
mChromaticAbCorrection.x = 0.995999f;
mChromaticAbCorrection.y = -0.004f;
mChromaticAbCorrection.z = 1.014f;
mChromaticAbCorrection.z = 0.0f;
calculateValues(calculateDistortionScale);
}
void OculusVRHMDDevice::setIPD(F32 ipd, bool calculateDistortionScale)
{
mInterpupillaryDistance = ipd;
// Recalculate as some values rely on the IPD
calculateValues(calculateDistortionScale);
}
// Computes scale that should be applied to the input render texture
// before distortion to fit the result in the same screen size.
// The 'fitRadius' parameter specifies the distance away from distortion center at
// which the input and output coordinates will match, assuming [-1,1] range.
F32 OculusVRHMDDevice::calcScale(F32 fitRadius)
{
F32 s = fitRadius;
// This should match distortion equation used in shader.
F32 ssq = s * s;
F32 scale = s * (mKDistortion.x + mKDistortion.y * ssq + mKDistortion.z * ssq * ssq + mKDistortion.w * ssq * ssq * ssq);
return scale;
}
void OculusVRHMDDevice::calculateValues(bool calculateDistortionScale)
{
F32 halfScreenX = mScreenSize.x * 0.5f;
if(halfScreenX > 0)
{
F32 halfLensSeparation = mLensSeparation * 0.5;
F32 offset = halfLensSeparation / halfScreenX;
mEyeUVOffset.x = offset - 0.5;
mEyeUVOffset.y = 1.0f - offset - 0.5;
}
else
{
mEyeUVOffset.x = 0.5f;
mEyeUVOffset.y = 0.5f;
}
F32 lensOffset = mLensSeparation * 0.5f;
F32 lensShift = mScreenSize.x * 0.25f - lensOffset;
F32 lensViewportShift = 4.0f * lensShift / mScreenSize.x;
mXCenterOffset= lensViewportShift;
// Determine how the input texture should be scaled relative to the back buffer
// so that we fit the distorted view to the backbuffer after calculating the
// distortion. In reference to section 5.6.3 Distortion Scale and FOV in the
// SDK docs.
if(!calculateDistortionScale)
{
// Do not calculate a distortion scale for the input texture. This means that the input
// texture and the backbuffer will be the same resolution.
mDistortionFit.x = 0.0f;
mDistortionFit.y = 0.0f;
}
else if (mScreenSize.x > 0.140f) // 7"
{
mDistortionFit.x = -1.0f;
mDistortionFit.y = 0.0f;
}
else // 5"
{
mDistortionFit.x = 0.0f;
mDistortionFit.y = 1.0f;
}
// Compute distortion scale from DistortionFitX & DistortionFitY.
// Fit value of 0.0 means "no fit".
if (mIsZero(mDistortionFit.x) && mIsZero(mDistortionFit.y))
{
mDistortionScale = 1.0f;
}
else
{
// Convert fit value to distortion-centered coordinates before fit radius
// calculation.
// NOTE: For now just assume a full view the same size as the HMD supports. It is
// possible that this full view is smaller or larger.
F32 stereoAspect = 0.5f * mResolution.x / mResolution.y;
F32 dx = mDistortionFit.x - mXCenterOffset;
F32 dy = mDistortionFit.y / stereoAspect;
F32 fitRadius = sqrt(dx * dx + dy * dy);
mDistortionScale = calcScale(fitRadius)/fitRadius;
}
// Calculate the vertical FOV for a single eye
mAspectRatio = F32(mResolution.x * 0.5f) / F32(mResolution.y);
F32 halfScreenDistance = mScreenSize.y * 0.5f * mDistortionScale;
mYFOV = 2.0f * mAtan(halfScreenDistance / mEyeToScreen);
F32 viewCenter = mScreenSize.x * 0.25f;
F32 eyeProjectionShift = viewCenter - (mInterpupillaryDistance * 0.5f);
mProjectionCenterOffset.set(4.0f * eyeProjectionShift / mScreenSize.x, 0.0f);
mEyeWorldOffset.set(mInterpupillaryDistance * 0.5f, 0.0f, 0.0f);
}