mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-20 04:34:48 +00:00
The chromatic aberration correction for the simulated Oculus Rift was wrong, producing a black screen.
233 lines
7.4 KiB
C++
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.w = 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);
|
|
}
|