Browse Source

Merge pull request #497 from DavidWyand-GG/OculusRiftUpdate

Oculus Rift Improvements
David Wyand 12 years ago
parent
commit
6c0f8aa252

+ 20 - 9
Engine/source/platform/input/oculusVR/barrelDistortionPostEffect.cpp

@@ -42,6 +42,7 @@ IMPLEMENT_CONOBJECT(BarrelDistortionPostEffect);
 BarrelDistortionPostEffect::BarrelDistortionPostEffect() 
    :  PostEffect(),
       mHmdWarpParamSC(NULL),
+      mHmdChromaAbSC(NULL),
       mScaleSC(NULL),
       mScaleInSC(NULL),
       mLensCenterSC(NULL),
@@ -85,23 +86,22 @@ void BarrelDistortionPostEffect::onRemove()
 
 void BarrelDistortionPostEffect::_setupConstants( const SceneRenderState *state )
 {
+   // Test if setup is required before calling the parent method as the parent method
+   // will set up the shader constants buffer for us.
+   bool setupRequired = mShaderConsts.isNull();
+
    Parent::_setupConstants(state);
 
    // Define the shader constants
-   if(!mHmdWarpParamSC)
+   if(setupRequired)
+   {
       mHmdWarpParamSC = mShader->getShaderConstHandle( "$HmdWarpParam" );
-
-   if(!mScaleSC)
+      mHmdChromaAbSC = mShader->getShaderConstHandle( "$HmdChromaAbParam" );
       mScaleSC = mShader->getShaderConstHandle( "$Scale" );
-
-   if(!mScaleInSC)
       mScaleInSC = mShader->getShaderConstHandle( "$ScaleIn" );
-
-   if(!mLensCenterSC)
       mLensCenterSC = mShader->getShaderConstHandle( "$LensCenter" );
-
-   if(!mScreenCenterSC)
       mScreenCenterSC = mShader->getShaderConstHandle( "$ScreenCenter" );
+   }
 
    const Point2I &resolution = GFX->getActiveRenderTarget()->getSize();
    F32 widthScale = 0.5f;
@@ -119,6 +119,12 @@ void BarrelDistortionPostEffect::_setupConstants( const SceneRenderState *state
          mShaderConsts->set( mHmdWarpParamSC, distortion );
       }
 
+      if(mHmdChromaAbSC->isValid())
+      {
+         const Point4F& correction = hmd->getChromaticAbCorrection();
+         mShaderConsts->set( mHmdChromaAbSC, correction );
+      }
+
       if(mScaleSC->isValid())
       {
          F32 scaleFactor = hmd->getDistortionScale();
@@ -149,6 +155,11 @@ void BarrelDistortionPostEffect::_setupConstants( const SceneRenderState *state
          mShaderConsts->set( mHmdWarpParamSC, Point4F(0.0f, 0.0f, 0.0f, 0.0f) );
       }
 
+      if(mHmdChromaAbSC->isValid())
+      {
+         mShaderConsts->set( mHmdChromaAbSC, Point4F(1.0f, 0.0f, 1.0f, 0.0f) );
+      }
+
       if(mScaleSC->isValid())
       {
          mShaderConsts->set( mScaleSC, Point2F(1.0f, 1.0f) );

+ 1 - 0
Engine/source/platform/input/oculusVR/barrelDistortionPostEffect.h

@@ -31,6 +31,7 @@ class BarrelDistortionPostEffect : public PostEffect
 
 protected:
    GFXShaderConstHandle *mHmdWarpParamSC;
+   GFXShaderConstHandle *mHmdChromaAbSC;
    GFXShaderConstHandle *mScaleSC;
    GFXShaderConstHandle *mScaleInSC;
    GFXShaderConstHandle *mLensCenterSC;

+ 331 - 1
Engine/source/platform/input/oculusVR/oculusVRDevice.cpp

@@ -60,12 +60,16 @@ bool OculusVRDevice::smEnableDevice = true;
 
 bool OculusVRDevice::smSimulateHMD = true;
 
+bool OculusVRDevice::smUseChromaticAberrationCorrection = true;
+
 bool OculusVRDevice::smGenerateAngleAxisRotationEvents = true;
 bool OculusVRDevice::smGenerateEulerRotationEvents = false;
 
 bool OculusVRDevice::smGenerateRotationAsAxisEvents = false;
 F32 OculusVRDevice::smMaximumAxisAngle = 25.0f;
 
+bool OculusVRDevice::smGenerateSensorRawEvents = false;
+
 bool OculusVRDevice::smGenerateWholeFrameEvents = false;
 
 OculusVRDevice::OculusVRDevice()
@@ -99,6 +103,10 @@ void OculusVRDevice::staticInit()
       "@brief If true, the Oculus VR device will be enabled, if present.\n\n"
 	   "@ingroup Game");
 
+   Con::addVariable("pref::OculusVR::UseChromaticAberrationCorrection", TypeBool, &smUseChromaticAberrationCorrection, 
+      "@brief If true, Use the chromatic aberration correction version of the Oculus VR barrel distortion shader.\n\n"
+	   "@ingroup Game");
+
    Con::addVariable("OculusVR::GenerateAngleAxisRotationEvents", TypeBool, &smGenerateAngleAxisRotationEvents, 
       "@brief If true, broadcast sensor rotation events as angled axis.\n\n"
 	   "@ingroup Game");
@@ -114,6 +122,10 @@ void OculusVRDevice::staticInit()
       "Should range from 0 to 90 degrees.\n\n"
 	   "@ingroup Game");
 
+   Con::addVariable("OculusVR::GenerateSensorRawEvents", TypeBool, &smGenerateSensorRawEvents, 
+      "@brief If ture, broadcast sensor raw data: acceleration, angular velocity, magnetometer reading.\n\n"
+	   "@ingroup Game");
+
    Con::addVariable("OculusVR::GenerateWholeFrameEvents", TypeBool, &smGenerateWholeFrameEvents, 
       "@brief Indicates that a whole frame event should be generated and frames should be buffered.\n\n"
 	   "@ingroup Game");
@@ -313,7 +325,7 @@ bool OculusVRDevice::process()
    // Process each sensor
    for(U32 i=0; i<mSensorDevices.size(); ++i)
    {
-      mSensorDevices[i]->process(mDeviceType, smGenerateAngleAxisRotationEvents, smGenerateEulerRotationEvents, smGenerateRotationAsAxisEvents, maxAxisRadius);
+      mSensorDevices[i]->process(mDeviceType, smGenerateAngleAxisRotationEvents, smGenerateEulerRotationEvents, smGenerateRotationAsAxisEvents, maxAxisRadius, smGenerateSensorRawEvents);
    }
 
    return true;
@@ -391,6 +403,22 @@ const OculusVRHMDDevice* OculusVRDevice::getHMDDevice(U32 index) const
    return mHMDDevices[index];
 }
 
+F32 OculusVRDevice::getHMDCurrentIPD(U32 index)
+{
+   if(index >= mHMDDevices.size())
+      return -1.0f;
+
+   return mHMDDevices[index]->getIPD();
+}
+
+void OculusVRDevice::setHMDCurrentIPD(U32 index, F32 ipd)
+{
+   if(index >= mHMDDevices.size())
+      return;
+
+   return mHMDDevices[index]->setIPD(ipd, mScaleInputTexture);
+}
+
 //-----------------------------------------------------------------------------
 
 const OculusVRSensorDevice* OculusVRDevice::getSensorDevice(U32 index) const
@@ -409,6 +437,30 @@ EulerF OculusVRDevice::getSensorEulerRotation(U32 index)
    return mSensorDevices[index]->getEulerRotation();
 }
 
+VectorF OculusVRDevice::getSensorAcceleration(U32 index)
+{
+   if(index >= mSensorDevices.size())
+      return Point3F::Zero;
+
+   return mSensorDevices[index]->getAcceleration();
+}
+
+EulerF OculusVRDevice::getSensorAngularVelocity(U32 index)
+{
+   if(index >= mSensorDevices.size())
+      return Point3F::Zero;
+
+   return mSensorDevices[index]->getAngularVelocity();
+}
+
+VectorF OculusVRDevice::getSensorMagnetometer(U32 index)
+{
+   if(index >= mSensorDevices.size())
+      return Point3F::Zero;
+
+   return mSensorDevices[index]->getMagnetometer();
+}
+
 F32 OculusVRDevice::getSensorPredictionTime(U32 index)
 {
    const OculusVRSensorDevice* sensor = getSensorDevice(index);
@@ -438,6 +490,57 @@ void OculusVRDevice::setAllSensorPredictionTime(F32 dt)
    }
 }
 
+bool OculusVRDevice::getSensorGravityCorrection(U32 index)
+{
+   const OculusVRSensorDevice* sensor = getSensorDevice(index);
+   if(!sensor || !sensor->isValid())
+      return false;
+
+   return sensor->getGravityCorrection();
+}
+
+void OculusVRDevice::setSensorGravityCorrection(U32 index, bool state)
+{
+   if(index >= mSensorDevices.size())
+      return;
+
+   OculusVRSensorDevice* sensor = mSensorDevices[index];
+   if(!sensor->isValid())
+      return;
+
+   sensor->setGravityCorrection(state);
+}
+
+bool OculusVRDevice::getSensorYawCorrection(U32 index)
+{
+   const OculusVRSensorDevice* sensor = getSensorDevice(index);
+   if(!sensor || !sensor->isValid())
+      return false;
+
+   return sensor->getYawCorrection();
+}
+
+void OculusVRDevice::setSensorYawCorrection(U32 index, bool state)
+{
+   if(index >= mSensorDevices.size())
+      return;
+
+   OculusVRSensorDevice* sensor = mSensorDevices[index];
+   if(!sensor->isValid())
+      return;
+
+   sensor->setYawCorrection(state);
+}
+
+bool OculusVRDevice::getSensorMagnetometerCalibrated(U32 index)
+{
+   const OculusVRSensorDevice* sensor = getSensorDevice(index);
+   if(!sensor || !sensor->isValid())
+      return false;
+
+   return sensor->getMagnetometerCalibrationAvailable();
+}
+
 void OculusVRDevice::resetAllSensors()
 {
    // Reset each sensor
@@ -628,6 +731,46 @@ DefineEngineFunction(getOVRHMDDisplayDeviceName, const char*, (S32 index),,
    return hmd->getDisplayDeviceName();
 }
 
+DefineEngineFunction(getOVRHMDDisplayDeviceId, S32, (S32 index),,
+   "@brief MacOS display ID.\n\n"
+   "@param index The HMD index.\n"
+   "@return The ID of the HMD display device, if any.\n"
+   "@ingroup Game")
+{
+   if(!ManagedSingleton<OculusVRDevice>::instanceOrNull())
+   {
+      return -1;
+   }
+
+   const OculusVRHMDDevice* hmd = OCULUSVRDEV->getHMDDevice(index);
+   if(!hmd)
+   {
+      return -1;
+   }
+
+   return hmd->getDisplayDeviceId();
+}
+
+DefineEngineFunction(getOVRHMDDisplayDesktopPos, Point2I, (S32 index),,
+   "@brief Desktop coordinate position of the screen (can be negative; may not be present on all platforms).\n\n"
+   "@param index The HMD index.\n"
+   "@return Position of the screen.\n"
+   "@ingroup Game")
+{
+   if(!ManagedSingleton<OculusVRDevice>::instanceOrNull())
+   {
+      return Point2I::Zero;
+   }
+
+   const OculusVRHMDDevice* hmd = OCULUSVRDEV->getHMDDevice(index);
+   if(!hmd)
+   {
+      return Point2I::Zero;
+   }
+
+   return hmd->getDesktopPosition();
+}
+
 DefineEngineFunction(getOVRHMDResolution, Point2I, (S32 index),,
    "@brief Provides the OVR HMD screen resolution.\n\n"
    "@param index The HMD index.\n"
@@ -672,6 +815,78 @@ DefineEngineFunction(getOVRHMDDistortionCoefficients, String, (S32 index),,
    return buf;
 }
 
+DefineEngineFunction(getOVRHMDChromaticAbCorrection, String, (S32 index),,
+   "@brief Provides the OVR HMD chromatic aberration correction values.\n\n"
+   "@param index The HMD index.\n"
+   "@return A four component string with the chromatic aberration correction values.\n"
+   "@ingroup Game")
+{
+   if(!ManagedSingleton<OculusVRDevice>::instanceOrNull())
+   {
+      return "1 0 1 0";
+   }
+
+   const OculusVRHMDDevice* hmd = OCULUSVRDEV->getHMDDevice(index);
+   if(!hmd)
+   {
+      return "1 0 1 0";
+   }
+
+   const Point4F& c = hmd->getChromaticAbCorrection();
+   char buf[256];
+   dSprintf(buf, 256, "%g %g %g %g", c.x, c.y, c.z, c.w);
+
+   return buf;
+}
+
+DefineEngineFunction(getOVRHMDProfileIPD, F32, (S32 index),,
+   "@brief Physical distance between the user's eye centers as defined by the current profile.\n\n"
+   "@param index The HMD index.\n"
+   "@return The profile IPD.\n"
+   "@ingroup Game")
+{
+   if(!ManagedSingleton<OculusVRDevice>::instanceOrNull())
+   {
+      return -1.0f;
+   }
+
+   const OculusVRHMDDevice* hmd = OCULUSVRDEV->getHMDDevice(index);
+   if(!hmd)
+   {
+      return -1.0f;
+   }
+
+   return hmd->getProfileIPD();
+}
+
+DefineEngineFunction(getOVRHMDCurrentIPD, F32, (S32 index),,
+   "@brief Physical distance between the user's eye centers.\n\n"
+   "@param index The HMD index.\n"
+   "@return The current IPD.\n"
+   "@ingroup Game")
+{
+   if(!ManagedSingleton<OculusVRDevice>::instanceOrNull())
+   {
+      return -1.0f;
+   }
+
+   return OCULUSVRDEV->getHMDCurrentIPD(index);
+}
+
+DefineEngineFunction(setOVRHMDCurrentIPD, void, (S32 index, F32 ipd),,
+   "@brief Set the physical distance between the user's eye centers.\n\n"
+   "@param index The HMD index.\n"
+   "@param ipd The IPD to use.\n"
+   "@ingroup Game")
+{
+   if(!ManagedSingleton<OculusVRDevice>::instanceOrNull())
+   {
+      return;
+   }
+
+   OCULUSVRDEV->setHMDCurrentIPD(index, ipd);
+}
+
 DefineEngineFunction(getOVRHMDEyeXOffsets, Point2F, (S32 index),,
    "@brief Provides the OVR HMD eye x offsets in uv coordinates.\n\n"
    "@param index The HMD index.\n"
@@ -787,6 +1002,49 @@ DefineEngineFunction(getOVRSensorEulerRotation, Point3F, (S32 index),,
    return Point3F(mRadToDeg(rot.x), mRadToDeg(rot.y), mRadToDeg(rot.z));
 }
 
+DefineEngineFunction(getOVRSensorAcceleration, Point3F, (S32 index),,
+   "@brief Get the acceleration values for the given sensor index.\n\n"
+   "@param index The sensor index.\n"
+   "@return The acceleration values of the Oculus VR sensor, in m/s^2.\n"
+   "@ingroup Game")
+{
+   if(!ManagedSingleton<OculusVRDevice>::instanceOrNull())
+   {
+      return Point3F::Zero;
+   }
+
+   return OCULUSVRDEV->getSensorAcceleration(index);
+}
+
+DefineEngineFunction(getOVRSensorAngVelocity, Point3F, (S32 index),,
+   "@brief Get the angular velocity values for the given sensor index.\n\n"
+   "@param index The sensor index.\n"
+   "@return The angular velocity values of the Oculus VR sensor, in degrees/s.\n"
+   "@ingroup Game")
+{
+   if(!ManagedSingleton<OculusVRDevice>::instanceOrNull())
+   {
+      return Point3F::Zero;
+   }
+
+   EulerF rot = OCULUSVRDEV->getSensorAngularVelocity(index);
+   return Point3F(mRadToDeg(rot.x), mRadToDeg(rot.y), mRadToDeg(rot.z));
+}
+
+DefineEngineFunction(getOVRSensorMagnetometer, Point3F, (S32 index),,
+   "@brief Get the magnetometer reading (direction and field strength) for the given sensor index.\n\n"
+   "@param index The sensor index.\n"
+   "@return The magnetometer reading (direction and field strength) of the Oculus VR sensor, in Gauss.\n"
+   "@ingroup Game")
+{
+   if(!ManagedSingleton<OculusVRDevice>::instanceOrNull())
+   {
+      return Point3F::Zero;
+   }
+
+   return OCULUSVRDEV->getSensorMagnetometer(index);
+}
+
 DefineEngineFunction(getOVRSensorPredictionTime, F32, (S32 index),,
    "@brief Get the prediction time set for the given sensor index.\n\n"
    "@param index The sensor index.\n"
@@ -828,6 +1086,78 @@ DefineEngineFunction(setAllSensorPredictionTime, void, (F32 dt),,
    OCULUSVRDEV->setAllSensorPredictionTime(dt);
 }
 
+DefineEngineFunction(getOVRSensorGravityCorrection, bool, (S32 index),,
+   "@brief Get the gravity correction state for the given sensor index.\n\n"
+   "@param index The sensor index.\n"
+   "@return True if gravity correction (for pitch and roll) is active.\n"
+   "@ingroup Game")
+{
+   if(!ManagedSingleton<OculusVRDevice>::instanceOrNull())
+   {
+      return false;
+   }
+
+   return OCULUSVRDEV->getSensorGravityCorrection(index);
+}
+
+DefineEngineFunction(setOVRSensorGravityCorrection, void, (S32 index, bool state),,
+   "@brief Set the gravity correction state for the given sensor index.\n\n"
+   "@param index The sensor index.\n"
+   "@param state The gravity correction state to change to.\n"
+   "@ingroup Game")
+{
+   if(!ManagedSingleton<OculusVRDevice>::instanceOrNull())
+   {
+      return;
+   }
+
+   OCULUSVRDEV->setSensorGravityCorrection(index, state);
+}
+
+DefineEngineFunction(getOVRSensorYawCorrection, bool, (S32 index),,
+   "@brief Get the yaw correction state for the given sensor index.\n\n"
+   "@param index The sensor index.\n"
+   "@return True if yaw correction (using magnetometer calibration data) is active.\n"
+   "@ingroup Game")
+{
+   if(!ManagedSingleton<OculusVRDevice>::instanceOrNull())
+   {
+      return false;
+   }
+
+   return OCULUSVRDEV->getSensorYawCorrection(index);
+}
+
+DefineEngineFunction(setOVRSensorYawCorrection, void, (S32 index, bool state),,
+   "@brief Set the yaw correction state for the given sensor index.\n\n"
+   "@param index The sensor index.\n"
+   "@param state The yaw correction state to change to.\n"
+   "@note Yaw correction cannot be enabled if the user has disabled it through "
+   "the Oculus VR control panel.\n"
+   "@ingroup Game")
+{
+   if(!ManagedSingleton<OculusVRDevice>::instanceOrNull())
+   {
+      return;
+   }
+
+   OCULUSVRDEV->setSensorYawCorrection(index, state);
+}
+
+DefineEngineFunction(getOVRSensorMagnetometerCalibrated, bool, (S32 index),,
+   "@brief Get the magnetometer calibrated data state for the given sensor index.\n\n"
+   "@param index The sensor index.\n"
+   "@return True if magnetometer calibration data is available.\n"
+   "@ingroup Game")
+{
+   if(!ManagedSingleton<OculusVRDevice>::instanceOrNull())
+   {
+      return false;
+   }
+
+   return OCULUSVRDEV->getSensorMagnetometerCalibrated(index);
+}
+
 DefineEngineFunction(ovrResetAllSensors, void, (),,
    "@brief Resets all Oculus VR sensors.\n\n"
    "This resets all sensor orientations such that their 'normal' rotation "

+ 17 - 0
Engine/source/platform/input/oculusVR/oculusVRDevice.h

@@ -44,6 +44,10 @@ public:
    // If no HMD is present simulate it being available
    static bool smSimulateHMD;
 
+   // Use the chromatic aberration correction version of the barrel
+   // distortion shader.
+   static bool smUseChromaticAberrationCorrection;
+
    // Type of rotation events to broadcast
    static bool smGenerateAngleAxisRotationEvents;
    static bool smGenerateEulerRotationEvents;
@@ -55,6 +59,9 @@ public:
    // as measured from a vector pointing straight up (in degrees)
    static F32 smMaximumAxisAngle;
 
+   // Broadcast sensor raw data: acceleration, angular velocity, magnetometer reading
+   static bool smGenerateSensorRawEvents;
+
    // Indicates that a whole frame event should be generated and frames
    // should be buffered.
    static bool smGenerateWholeFrameEvents;
@@ -131,14 +138,24 @@ public:
    // HMDs
    U32 getHMDCount() const { return mHMDDevices.size(); }
    const OculusVRHMDDevice* getHMDDevice(U32 index) const;
+   F32 getHMDCurrentIPD(U32 index);
+   void setHMDCurrentIPD(U32 index, F32 ipd);
 
    // Sensors
    U32 getSensorCount() const { return mSensorDevices.size(); }
    const OculusVRSensorDevice* getSensorDevice(U32 index) const;
    EulerF getSensorEulerRotation(U32 index);
+   VectorF getSensorAcceleration(U32 index);
+   EulerF getSensorAngularVelocity(U32 index);
+   VectorF getSensorMagnetometer(U32 index);
    F32 getSensorPredictionTime(U32 index);
    void setSensorPredictionTime(U32 index, F32 dt);
    void setAllSensorPredictionTime(F32 dt);
+   bool getSensorGravityCorrection(U32 index);
+   void setSensorGravityCorrection(U32 index, bool state);
+   bool getSensorYawCorrection(U32 index);
+   void setSensorYawCorrection(U32 index, bool state);
+   bool getSensorMagnetometerCalibrated(U32 index);
    void resetAllSensors();
 
 public:

+ 26 - 2
Engine/source/platform/input/oculusVR/oculusVRHMDDevice.cpp

@@ -58,6 +58,10 @@ void OculusVRHMDDevice::set(OVR::HMDDevice* hmd, OVR::HMDInfo& info, bool calcul
    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;
@@ -68,13 +72,19 @@ void OculusVRHMDDevice::set(OVR::HMDDevice* hmd, OVR::HMDInfo& info, bool calcul
    mVerticalEyeCenter = info.VScreenCenter;
    mEyeToScreen = info.EyeToScreenDistance;
    mLensSeparation = info.LensSeparationDistance;
-   mInterpupillaryDistance = info.InterpupillaryDistance;
+   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);
 
@@ -109,13 +119,27 @@ void OculusVRHMDDevice::createSimulatedPreviewRift(bool calculateDistortionScale
    mVerticalEyeCenter = 0.046799999f;
    mEyeToScreen = 0.041000001f;
    mLensSeparation = 0.064000003f;
-   mInterpupillaryDistance = 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);
 }
 

+ 27 - 0
Engine/source/platform/input/oculusVR/oculusVRHMDDevice.h

@@ -54,6 +54,12 @@ protected:
    // Windows display device name used in EnumDisplaySettings/CreateDC
    String   mDisplayDeviceName;
 
+   // MacOS display ID
+   S32      mDisplayId;
+
+   // Desktop coordinate position of the screen (can be negative; may not be present on all platforms)
+   Point2I  mDesktopPosition;
+
    // Whole screen resolution
    Point2I  mResolution;
 
@@ -70,6 +76,9 @@ protected:
    // Physical distance between lens centers, in meters
    F32      mLensSeparation;
 
+   // Physical distance between the user's eye centers as defined in the current profile
+   F32      mProfileInterpupillaryDistance;
+
    // Physical distance between the user's eye centers
    F32      mInterpupillaryDistance;
 
@@ -79,6 +88,9 @@ protected:
    // Radial distortion correction coefficients used by the barrel distortion shader
    Point4F  mKDistortion;
 
+   // Chromatic aberration correction coefficients
+   Point4F mChromaticAbCorrection;
+
    // Calculated values of eye x offset from center in normalized (uv) coordinates
    // where each eye is 0..1.  Used for the mono to stereo postFX to simulate an
    // eye offset of the camera.  The x component is the left eye, the y component
@@ -137,6 +149,12 @@ public:
    // Windows display device name used in EnumDisplaySettings/CreateDC
    const char* getDisplayDeviceName() const { return mDisplayDeviceName.c_str(); }
 
+   // MacOS display ID
+   S32 getDisplayDeviceId() const { return mDisplayId; }
+
+   // Desktop coordinate position of the screen (can be negative; may not be present on all platforms)
+   const Point2I& getDesktopPosition() const { return mDesktopPosition; }
+
    // Whole screen resolution
    const Point2I& getResolution() const { return mResolution; }
 
@@ -153,15 +171,24 @@ public:
    // Physical distance between lens centers, in meters
    F32 getLensSeparation() const { return mLensSeparation; }
 
+   // Physical distance between the user's eye centers as defined by the current profile
+   F32 getProfileIPD() const { return mProfileInterpupillaryDistance; }
+
    // Physical distance between the user's eye centers
    F32 getIPD() const { return mInterpupillaryDistance; }
 
+   // Set a new physical distance between the user's eye centers
+   void setIPD(F32 ipd, bool calculateDistortionScale);
+
    // Provides the IPD of one eye as a Point3F
    const Point3F& getEyeWorldOffset() const { return mEyeWorldOffset; }
 
    // Radial distortion correction coefficients used by the barrel distortion shader
    const Point4F& getKDistortion() const { return mKDistortion; }
 
+   // Chromatic aberration correction coefficients used by the barrel distortion shader
+   const Point4F& getChromaticAbCorrection() const { return mChromaticAbCorrection; }
+
    // Calculated values of eye x offset from center in normalized (uv) coordinates.
    const Point2F& getEyeUVOffset() const { return mEyeUVOffset; }
 

+ 37 - 0
Engine/source/platform/input/oculusVR/oculusVRSensorData.cpp

@@ -56,6 +56,24 @@ void OculusVRSensorData::setData(OVR::SensorFusion& data, const F32& maxAxisRadi
    // Sensor rotation as axis
    OculusVRUtil::calculateAxisRotation(mRot, maxAxisRadius, mRotAxis);
 
+   // Sensor raw values
+   OVR::Vector3f accel = data.GetAcceleration();
+   OculusVRUtil::convertAcceleration(accel, mAcceleration);
+
+   OVR::Vector3f angVel = data.GetAngularVelocity();
+   OculusVRUtil::convertAngularVelocity(angVel, mAngVelocity);
+
+   OVR::Vector3f mag;
+   if(data.HasMagCalibration() && data.IsYawCorrectionEnabled())
+   {
+      mag = data.GetCalibratedMagnetometer();
+   }
+   else
+   {
+      mag = data.GetMagnetometer();
+   }
+   OculusVRUtil::convertMagnetometer(mag, mMagnetometer);
+
    mDataSet = true;
 }
 
@@ -69,6 +87,11 @@ void OculusVRSensorData::simulateData(const F32& maxAxisRadius)
    // Sensor rotation as axis
    OculusVRUtil::calculateAxisRotation(mRot, maxAxisRadius, mRotAxis);
 
+   // Sensor raw values
+   mAcceleration.zero();
+   mAngVelocity.zero();
+   mMagnetometer.zero();
+
    mDataSet = true;
 }
 
@@ -92,5 +115,19 @@ U32 OculusVRSensorData::compare(OculusVRSensorData* other)
       result |= DIFF_ROTAXISY;
    }
 
+   // Check raw values
+   if(mAcceleration.x != other->mAcceleration.x || mAcceleration.y != other->mAcceleration.y || mAcceleration.z != other->mAcceleration.z || !mDataSet)
+   {
+      result |= DIFF_ACCEL;
+   }
+   if(mAngVelocity.x != other->mAngVelocity.x || mAngVelocity.y != other->mAngVelocity.y || mAngVelocity.z != other->mAngVelocity.z || !mDataSet)
+   {
+      result |= DIFF_ANGVEL;
+   }
+   if(mMagnetometer.x != other->mMagnetometer.x || mMagnetometer.y != other->mMagnetometer.y || mMagnetometer.z != other->mMagnetometer.z || !mDataSet)
+   {
+      result |= DIFF_MAG;
+   }
+
    return result;
 }

+ 9 - 0
Engine/source/platform/input/oculusVR/oculusVRSensorData.h

@@ -36,8 +36,12 @@ struct OculusVRSensorData
       DIFF_ROT             = (1<<0),
       DIFF_ROTAXISX        = (1<<1),
       DIFF_ROTAXISY        = (1<<2),
+      DIFF_ACCEL           = (1<<3),
+      DIFF_ANGVEL          = (1<<4),
+      DIFF_MAG             = (1<<5),
 
       DIFF_ROTAXIS = (DIFF_ROTAXISX | DIFF_ROTAXISY),
+      DIFF_RAW = (DIFF_ACCEL | DIFF_ANGVEL | DIFF_MAG),
    };
 
    bool mDataSet;
@@ -50,6 +54,11 @@ struct OculusVRSensorData
    // Controller rotation as axis x, y
    Point2F mRotAxis;
 
+   // Raw values
+   VectorF mAcceleration;
+   EulerF  mAngVelocity;
+   VectorF mMagnetometer;
+
    OculusVRSensorData();
 
    /// Reset the data

+ 169 - 2
Engine/source/platform/input/oculusVR/oculusVRSensorDevice.cpp

@@ -29,6 +29,9 @@ U32 OculusVRSensorDevice::OVR_SENSORROT[OculusVRConstants::MaxSensors] = {0};
 U32 OculusVRSensorDevice::OVR_SENSORROTANG[OculusVRConstants::MaxSensors] = {0};
 U32 OculusVRSensorDevice::OVR_SENSORROTAXISX[OculusVRConstants::MaxSensors] = {0};
 U32 OculusVRSensorDevice::OVR_SENSORROTAXISY[OculusVRConstants::MaxSensors] = {0};
+U32 OculusVRSensorDevice::OVR_SENSORACCELERATION[OculusVRConstants::MaxSensors] = {0};
+U32 OculusVRSensorDevice::OVR_SENSORANGVEL[OculusVRConstants::MaxSensors] = {0};
+U32 OculusVRSensorDevice::OVR_SENSORMAGNETOMETER[OculusVRConstants::MaxSensors] = {0};
 
 OculusVRSensorDevice::OculusVRSensorDevice()
 {
@@ -74,6 +77,7 @@ void OculusVRSensorDevice::set(OVR::SensorDevice* sensor, OVR::SensorInfo& info,
 
    mDevice = sensor;
    mSensorFusion.AttachToSensor(sensor);
+   mYawCorrectionDisabled = !mSensorFusion.IsYawCorrectionEnabled();
 
    // DeviceInfo
    mProductName = info.ProductName;
@@ -110,6 +114,7 @@ void OculusVRSensorDevice::createSimulatedPreviewRift(S32 actionCodeIndex)
 {
    mIsValid = false;
    mIsSimulation = true;
+   mYawCorrectionDisabled = true;
 
    // DeviceInfo
    mProductName = "Tracker DK";
@@ -145,6 +150,10 @@ void OculusVRSensorDevice::buildCodeTable()
 
       OVR_SENSORROTAXISX[i] = INPUTMGR->getNextDeviceCode();
       OVR_SENSORROTAXISY[i] = INPUTMGR->getNextDeviceCode();
+
+      OVR_SENSORACCELERATION[i] = INPUTMGR->getNextDeviceCode();
+      OVR_SENSORANGVEL[i] = INPUTMGR->getNextDeviceCode();
+      OVR_SENSORMAGNETOMETER[i] = INPUTMGR->getNextDeviceCode();
    }
 
    // Build out the virtual map
@@ -155,16 +164,27 @@ void OculusVRSensorDevice::buildCodeTable()
       INPUTMGR->addVirtualMap( buffer, SI_ROT, OVR_SENSORROT[i] );
 
       dSprintf(buffer, 64, "ovr_sensorrotang%d", i);
-      INPUTMGR->addVirtualMap( buffer, SI_ROT, OVR_SENSORROTANG[i] );
+      INPUTMGR->addVirtualMap( buffer, SI_POS, OVR_SENSORROTANG[i] );
 
       dSprintf(buffer, 64, "ovr_sensorrotaxisx%d", i);
       INPUTMGR->addVirtualMap( buffer, SI_AXIS, OVR_SENSORROTAXISX[i] );
       dSprintf(buffer, 64, "ovr_sensorrotaxisy%d", i);
       INPUTMGR->addVirtualMap( buffer, SI_AXIS, OVR_SENSORROTAXISY[i] );
+
+      dSprintf(buffer, 64, "ovr_sensoracceleration%d", i);
+      INPUTMGR->addVirtualMap( buffer, SI_POS, OVR_SENSORACCELERATION[i] );
+
+      dSprintf(buffer, 64, "ovr_sensorangvel%d", i);
+      INPUTMGR->addVirtualMap( buffer, SI_POS, OVR_SENSORANGVEL[i] );
+
+      dSprintf(buffer, 64, "ovr_sensormagnetometer%d", i);
+      INPUTMGR->addVirtualMap( buffer, SI_POS, OVR_SENSORMAGNETOMETER[i] );
    }
 }
 
-bool OculusVRSensorDevice::process(U32 deviceType, bool generateRotAsAngAxis, bool generateRotAsEuler, bool generateRotationAsAxisEvents, F32 maxAxisRadius)
+//-----------------------------------------------------------------------------
+
+bool OculusVRSensorDevice::process(U32 deviceType, bool generateRotAsAngAxis, bool generateRotAsEuler, bool generateRotationAsAxisEvents, F32 maxAxisRadius, bool generateRawSensor)
 {
    if(!mIsValid)
       return false;
@@ -215,9 +235,32 @@ bool OculusVRSensorDevice::process(U32 deviceType, bool generateRotAsAngAxis, bo
          INPUTMGR->buildInputEvent(deviceType, OculusVRConstants::DefaultOVRBase, SI_AXIS, OVR_SENSORROTAXISY[mActionCodeIndex], SI_MOVE, currentBuffer->mRotAxis.y);
    }
 
+   // Raw sensor event
+   if(generateRawSensor && diff & OculusVRSensorData::DIFF_RAW)
+   {
+      if(diff & OculusVRSensorData::DIFF_ACCEL)
+         INPUTMGR->buildInputEvent(deviceType, OculusVRConstants::DefaultOVRBase, SI_POS, OVR_SENSORACCELERATION[mActionCodeIndex], SI_MOVE, currentBuffer->mAcceleration);
+
+      if(diff & OculusVRSensorData::DIFF_ANGVEL)
+      {
+         // Convert angles to degrees
+         VectorF angles;
+         for(U32 i=0; i<3; ++i)
+         {
+            angles[i] = mRadToDeg(currentBuffer->mAngVelocity[i]);
+         }
+         INPUTMGR->buildInputEvent(deviceType, OculusVRConstants::DefaultOVRBase, SI_POS, OVR_SENSORANGVEL[mActionCodeIndex], SI_MOVE, angles);
+      }
+
+      if(diff & OculusVRSensorData::DIFF_MAG)
+         INPUTMGR->buildInputEvent(deviceType, OculusVRConstants::DefaultOVRBase, SI_POS, OVR_SENSORMAGNETOMETER[mActionCodeIndex], SI_MOVE, currentBuffer->mMagnetometer);
+   }
+
    return true;
 }
 
+//-----------------------------------------------------------------------------
+
 void OculusVRSensorDevice::reset()
 {
    if(!mIsValid)
@@ -242,6 +285,51 @@ void OculusVRSensorDevice::setPredictionTime(F32 dt)
    mSensorFusion.SetPrediction(dt);
 }
 
+bool OculusVRSensorDevice::getGravityCorrection() const
+{
+   if(!mIsValid)
+      return false;
+
+   return mSensorFusion.IsGravityEnabled();
+}
+
+void OculusVRSensorDevice::setGravityCorrection(bool state)
+{
+   if(!mIsValid)
+      return;
+
+   mSensorFusion.SetGravityEnabled(state);
+}
+
+bool OculusVRSensorDevice::getYawCorrection() const
+{
+   if(!mIsValid)
+      return false;
+
+   return mSensorFusion.IsYawCorrectionEnabled();
+}
+
+void OculusVRSensorDevice::setYawCorrection(bool state)
+{
+   if(!mIsValid)
+      return;
+
+   if(mYawCorrectionDisabled || !mSensorFusion.HasMagCalibration())
+      return;
+
+   mSensorFusion.SetYawCorrectionEnabled(state);
+}
+
+bool OculusVRSensorDevice::getMagnetometerCalibrationAvailable() const
+{
+   if(!mIsValid)
+      return false;
+
+   return mSensorFusion.HasMagCalibration();
+}
+
+//-----------------------------------------------------------------------------
+
 EulerF OculusVRSensorDevice::getEulerRotation()
 {
    if(!mIsValid)
@@ -263,3 +351,82 @@ EulerF OculusVRSensorDevice::getEulerRotation()
 
    return rot;
 }
+
+EulerF OculusVRSensorDevice::getRawEulerRotation()
+{
+   if(!mIsValid)
+      return Point3F::Zero;
+
+   OVR::Quatf orientation;
+   orientation = mSensorFusion.GetOrientation();
+
+   // Sensor rotation in Euler format
+   EulerF rot;
+   OculusVRUtil::convertRotation(orientation, rot);
+
+   return rot;
+}
+
+VectorF OculusVRSensorDevice::getAcceleration()
+{
+   if(!mIsValid)
+      return VectorF::Zero;
+
+   OVR::Vector3f a = mSensorFusion.GetAcceleration();
+   
+   // Sensor acceleration in VectorF format
+   VectorF acceleration;
+   OculusVRUtil::convertAcceleration(a, acceleration);
+
+   return acceleration;
+}
+
+EulerF OculusVRSensorDevice::getAngularVelocity()
+{
+   if(!mIsValid)
+      return EulerF::Zero;
+
+   OVR::Vector3f v = mSensorFusion.GetAngularVelocity();
+   
+   // Sensor angular velocity in EulerF format
+   EulerF vel;
+   OculusVRUtil::convertAngularVelocity(v, vel);
+
+   return vel;
+}
+
+VectorF OculusVRSensorDevice::getMagnetometer()
+{
+   if(!mIsValid)
+      return VectorF::Zero;
+
+   OVR::Vector3f m;
+   if(mSensorFusion.HasMagCalibration() && mSensorFusion.IsYawCorrectionEnabled())
+   {
+      m = mSensorFusion.GetCalibratedMagnetometer();
+   }
+   else
+   {
+      m = mSensorFusion.GetMagnetometer();
+   }
+   
+   // Sensor magnetometer reading in VectorF format
+   VectorF mag;
+   OculusVRUtil::convertMagnetometer(m, mag);
+
+   return mag;
+}
+
+VectorF OculusVRSensorDevice::getRawMagnetometer()
+{
+   if(!mIsValid)
+      return VectorF::Zero;
+
+   OVR::Vector3f m = mSensorFusion.GetMagnetometer();
+   
+   // Sensor magnetometer reading in VectorF format
+   VectorF mag;
+   OculusVRUtil::convertMagnetometer(m, mag);
+
+   return mag;
+}

+ 45 - 1
Engine/source/platform/input/oculusVR/oculusVRSensorDevice.h

@@ -50,6 +50,10 @@ public:
    static U32 OVR_SENSORROTAXISX[OculusVRConstants::MaxSensors];  // SI_AXIS
    static U32 OVR_SENSORROTAXISY[OculusVRConstants::MaxSensors];
 
+   static U32 OVR_SENSORACCELERATION[OculusVRConstants::MaxSensors];    // SI_POS
+   static U32 OVR_SENSORANGVEL[OculusVRConstants::MaxSensors];          // SI_POS but is EulerF
+   static U32 OVR_SENSORMAGNETOMETER[OculusVRConstants::MaxSensors];    // SI_POS
+
 protected:
    bool mIsValid;
 
@@ -69,6 +73,9 @@ protected:
    U16      mProductId;
    String   mSerialNumber;
 
+   // Has yaw correction been disabled by the control panel
+   bool     mYawCorrectionDisabled;
+
    // Assigned by the OculusVRDevice
    S32 mActionCodeIndex;
 
@@ -99,7 +106,7 @@ public:
    bool isValid() const {return mIsValid;}
    bool isSimulated() {return mIsSimulation;}
 
-   bool process(U32 deviceType, bool generateRotAsAngAxis, bool generateRotAsEuler, bool generateRotationAsAxisEvents, F32 maxAxisRadius);
+   bool process(U32 deviceType, bool generateRotAsAngAxis, bool generateRotAsEuler, bool generateRotationAsAxisEvents, F32 maxAxisRadius, bool generateRawSensor);
 
    void reset();
 
@@ -109,6 +116,26 @@ public:
    // Set the prediction time for the sensor fusion.  The time is in seconds.
    void setPredictionTime(F32 dt);
 
+   // Is gravity correction enabled for pitch and roll
+   bool getGravityCorrection() const;
+
+   // Set the pitch and roll gravity correction
+   void setGravityCorrection(bool state);
+
+   // Has yaw correction been disabled using the control panel
+   bool getYawCorrectionUserDisabled() const { return mYawCorrectionDisabled; }
+
+   // Is yaw correction enabled
+   bool getYawCorrection() const;
+
+   // Set the yaw correction. Note: if magnetometer calibration data is not present,
+   // or user has disabled yaw correction in the control panel, this method will
+   // not enable it.
+   void setYawCorrection(bool state);
+
+   // Is magnetometer calibration data available for this sensor
+   bool getMagnetometerCalibrationAvailable() const;
+
    const char* getProductName() { return mProductName.c_str(); }
    const char* getManufacturer() { return mManufacturer.c_str(); }
    U32 getVersion() { return mVersion; }
@@ -116,7 +143,24 @@ public:
    U16 getProductId() { return mProductId; }
    const char* getSerialNumber() { return mSerialNumber; }
 
+   // Get the current rotation of the sensor.  Uses prediction if set.
    EulerF getEulerRotation();
+
+   // Get the current rotation of the sensor.
+   EulerF getRawEulerRotation();
+
+   // Get the current absolute acceleration reading, in m/s^2
+   VectorF getAcceleration();
+
+   // Get the current angular velocity reading, in rad/s
+   EulerF getAngularVelocity();
+
+   // Get the current magnetometer reading (direction and field strength), in Gauss.
+   // Uses magnetometer calibration if set.
+   VectorF getMagnetometer();
+
+   // Get the current raw magnetometer reading (direction and field strength), in Gauss
+   VectorF getRawMagnetometer();
 };
 
 #endif   // _OCULUSVRSENSORDEVICE_H_

+ 16 - 1
Engine/source/platform/input/oculusVR/oculusVRUtil.cpp

@@ -73,4 +73,19 @@ void calculateAxisRotation(const MatrixF& inRotation, const F32& maxAxisRadius,
    outRotation.y = axis.y;
 }
 
-}
+void convertAcceleration(OVR::Vector3f& inAcceleration, VectorF& outAcceleration)
+{
+   outAcceleration.set(inAcceleration.x, -inAcceleration.z, inAcceleration.y);
+}
+
+void convertAngularVelocity(OVR::Vector3f& inAngVel, EulerF& outAngVel)
+{
+   outAngVel.set(-inAngVel.x, inAngVel.z, -inAngVel.y);
+}
+
+void convertMagnetometer(OVR::Vector3f& inMagnetometer, VectorF& outMagnetometer)
+{
+   outMagnetometer.set(inMagnetometer.x, -inMagnetometer.z, inMagnetometer.y);
+}
+
+}

+ 9 - 0
Engine/source/platform/input/oculusVR/oculusVRUtil.h

@@ -37,6 +37,15 @@ namespace OculusVRUtil
 
    /// Calcualte a sensor's rotation as if it were a thumb stick axis
    void calculateAxisRotation(const MatrixF& inRotation, const F32& maxAxisRadius, Point2F& outRotation);
+
+   /// Convert an OVR sensor's acceleration to Torque 3D vector (in m/s^2)
+   void convertAcceleration(OVR::Vector3f& inAcceleration, VectorF& outAcceleration);
+
+   /// Convert OVR sensor's angular velocity to Torque 3D Euler angles (in radians/s)
+   void convertAngularVelocity(OVR::Vector3f& inAngVel, EulerF& outAngVel);
+
+   /// Convert an OVR sensor's magnetometer reading (direction and field strength) to Torque 3D vector (in Gauss)
+   void convertMagnetometer(OVR::Vector3f& inMagnetometer, VectorF& outMagnetometer);
 }
 
 #endif   // _OCULUSVRUTIL_H_

+ 10 - 2
Templates/Empty/game/core/scripts/client/oculusVR.cs

@@ -63,7 +63,14 @@ function enableOculusVRDisplay(%gameConnection, %trueStereoRendering)
    
    if(%trueStereoRendering)
    {
-      OVRBarrelDistortionPostFX.isEnabled = true;
+      if($pref::OculusVR::UseChromaticAberrationCorrection)
+      {
+         OVRBarrelDistortionChromaPostFX.isEnabled = true;
+      }
+      else
+      {
+         OVRBarrelDistortionPostFX.isEnabled = true;
+      }
    }
    else
    {
@@ -81,6 +88,7 @@ function disableOculusVRDisplay(%gameConnection)
    %gameConnection.clearDisplayDevice();
    PlayGui.renderStyle = "standard";
    OVRBarrelDistortionPostFX.isEnabled = false;
+   OVRBarrelDistortionChromaPostFX.isEnabled = false;
    OVRBarrelDistortionMonoPostFX.isEnabled = false;
 }
 
@@ -112,7 +120,7 @@ function setStandardOculusVRControlScheme(%gameConnection)
 function setVideoModeForOculusVRDisplay(%fullscreen)
 {
    %res = getOVRHMDResolution(0);
-   Canvas.setVideoMode(%res.x, %res.y, %fullscreen, 32, 0);
+   Canvas.setVideoMode(%res.x, %res.y, %fullscreen, 32, 4);
 }
 
 //-----------------------------------------------------------------------------

+ 34 - 0
Templates/Empty/game/core/scripts/client/postFx/ovrBarrelDistortion.cs

@@ -44,6 +44,14 @@ singleton ShaderData( OVRBarrelDistortionShader )
    pixVersion = 2.0;   
 };
 
+singleton ShaderData( OVRBarrelDistortionChromaShader )
+{
+   DXVertexShaderFile 	= "shaders/common/postFx/postFxV.hlsl";
+   DXPixelShaderFile 	= "shaders/common/postFx/oculusvr/barrelDistortionChromaP.hlsl";
+
+   pixVersion = 2.0;   
+};
+
 //-----------------------------------------------------------------------------
 // GFX state blocks
 //-----------------------------------------------------------------------------
@@ -78,6 +86,32 @@ singleton BarrelDistortionPostEffect( OVRBarrelDistortionPostFX )
    scaleOutput = 1.25;
 };
 
+//-----------------------------------------------------------------------------
+// Barrel Distortion with Chromatic Aberration Correction PostFx
+//
+// To be used with the Oculus Rift.
+// Expects a stereo pair to exist on the back buffer and then applies the
+// appropriate barrel distortion.
+// This version applies a chromatic aberration correction during the
+// barrel distortion.
+//-----------------------------------------------------------------------------
+singleton BarrelDistortionPostEffect( OVRBarrelDistortionChromaPostFX )
+{
+   isEnabled = false;
+   allowReflectPass = false;
+   
+   renderTime = "PFXAfterDiffuse";
+   renderPriority = 100;
+
+   // The barrel distortion   
+   shader = OVRBarrelDistortionChromaShader;
+   stateBlock = OVRBarrelDistortionStateBlock;
+   
+   texture[0] = "$backBuffer";
+   
+   scaleOutput = 1.25;
+};
+
 //-----------------------------------------------------------------------------
 // Barrel Distortion Mono PostFx
 //

+ 95 - 0
Templates/Empty/game/shaders/common/postFx/oculusvr/barrelDistortionChromaP.hlsl

@@ -0,0 +1,95 @@
+//-----------------------------------------------------------------------------
+// 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 "shadergen:/autogenConditioners.h"  
+#include "../postFx.hlsl"  
+#include "../../torque.hlsl"
+
+uniform sampler2D backBuffer : register(S0);
+
+uniform float3 LensCenter;    // x=Left X, y=Right X, z=Y
+uniform float2 ScreenCenter;
+uniform float2 Scale;
+uniform float2 ScaleIn;
+uniform float4 HmdWarpParam;
+uniform float4 HmdChromaAbParam; // Chromatic aberration correction
+
+float4 main( PFXVertToPix IN ) : COLOR0  
+{
+   float2 texCoord;
+   float xOffset;
+   float2 lensCenter;
+   lensCenter.y = LensCenter.z;
+   if(IN.uv0.x < 0.5)
+   {
+      texCoord.x = IN.uv0.x;
+      texCoord.y = IN.uv0.y;
+      xOffset = 0.0;
+      lensCenter.x = LensCenter.x;
+   }
+   else
+   {
+      texCoord.x = IN.uv0.x - 0.5;
+      texCoord.y = IN.uv0.y;
+      xOffset = 0.5;
+      lensCenter.x = LensCenter.y;
+   }
+   
+   // Scales input texture coordinates for distortion.
+   // ScaleIn maps texture coordinates to Scales to ([-1, 1]), although top/bottom will be
+   // larger due to aspect ratio.
+   float2 theta = (texCoord - lensCenter) * ScaleIn; // Scales to [-1, 1]
+   float rSq = theta.x * theta.x + theta.y * theta.y;
+   float2 theta1 = theta * (HmdWarpParam.x + HmdWarpParam.y * rSq + HmdWarpParam.z * rSq * rSq + HmdWarpParam.w * rSq * rSq * rSq);
+
+   // Detect whether blue texture coordinates are out of range
+   // since these will scaled out the furthest.
+   float2 thetaBlue = theta1 * (HmdChromaAbParam.z + HmdChromaAbParam.w * rSq);
+   float2 tcBlue = lensCenter + Scale * thetaBlue;
+   
+   float4 color;
+   if (any(clamp(tcBlue, ScreenCenter-float2(0.25,0.5), ScreenCenter+float2(0.25, 0.5)) - tcBlue))
+   {
+      color = float4(0,0,0,0);
+   }
+   else
+   {
+      // Now do blue texture lookup.
+      tcBlue.x += xOffset;
+      float blue = tex2D(backBuffer, tcBlue).b;
+
+      // Do green lookup (no scaling).
+      float2 tcGreen = lensCenter + Scale * theta1;
+      tcGreen.x += xOffset;
+      float green = tex2D(backBuffer, tcGreen).g;
+
+      // Do red scale and lookup.
+      float2 thetaRed = theta1 * (HmdChromaAbParam.x + HmdChromaAbParam.y * rSq);
+      float2 tcRed = lensCenter + Scale * thetaRed;
+      tcRed.x += xOffset;
+      float red = tex2D(backBuffer, tcRed).r;
+
+      color = float4(red, green, blue, 1);
+   }
+
+   return color;    
+}

+ 10 - 2
Templates/Full/game/core/scripts/client/oculusVR.cs

@@ -63,7 +63,14 @@ function enableOculusVRDisplay(%gameConnection, %trueStereoRendering)
    
    if(%trueStereoRendering)
    {
-      OVRBarrelDistortionPostFX.isEnabled = true;
+      if($pref::OculusVR::UseChromaticAberrationCorrection)
+      {
+         OVRBarrelDistortionChromaPostFX.isEnabled = true;
+      }
+      else
+      {
+         OVRBarrelDistortionPostFX.isEnabled = true;
+      }
    }
    else
    {
@@ -81,6 +88,7 @@ function disableOculusVRDisplay(%gameConnection)
    %gameConnection.clearDisplayDevice();
    PlayGui.renderStyle = "standard";
    OVRBarrelDistortionPostFX.isEnabled = false;
+   OVRBarrelDistortionChromaPostFX.isEnabled = false;
    OVRBarrelDistortionMonoPostFX.isEnabled = false;
 }
 
@@ -112,7 +120,7 @@ function setStandardOculusVRControlScheme(%gameConnection)
 function setVideoModeForOculusVRDisplay(%fullscreen)
 {
    %res = getOVRHMDResolution(0);
-   Canvas.setVideoMode(%res.x, %res.y, %fullscreen, 32, 0);
+   Canvas.setVideoMode(%res.x, %res.y, %fullscreen, 32, 4);
 }
 
 //-----------------------------------------------------------------------------

+ 34 - 0
Templates/Full/game/core/scripts/client/postFx/ovrBarrelDistortion.cs

@@ -44,6 +44,14 @@ singleton ShaderData( OVRBarrelDistortionShader )
    pixVersion = 2.0;   
 };
 
+singleton ShaderData( OVRBarrelDistortionChromaShader )
+{
+   DXVertexShaderFile 	= "shaders/common/postFx/postFxV.hlsl";
+   DXPixelShaderFile 	= "shaders/common/postFx/oculusvr/barrelDistortionChromaP.hlsl";
+
+   pixVersion = 2.0;   
+};
+
 //-----------------------------------------------------------------------------
 // GFX state blocks
 //-----------------------------------------------------------------------------
@@ -78,6 +86,32 @@ singleton BarrelDistortionPostEffect( OVRBarrelDistortionPostFX )
    scaleOutput = 1.25;
 };
 
+//-----------------------------------------------------------------------------
+// Barrel Distortion with Chromatic Aberration Correction PostFx
+//
+// To be used with the Oculus Rift.
+// Expects a stereo pair to exist on the back buffer and then applies the
+// appropriate barrel distortion.
+// This version applies a chromatic aberration correction during the
+// barrel distortion.
+//-----------------------------------------------------------------------------
+singleton BarrelDistortionPostEffect( OVRBarrelDistortionChromaPostFX )
+{
+   isEnabled = false;
+   allowReflectPass = false;
+   
+   renderTime = "PFXAfterDiffuse";
+   renderPriority = 100;
+
+   // The barrel distortion   
+   shader = OVRBarrelDistortionChromaShader;
+   stateBlock = OVRBarrelDistortionStateBlock;
+   
+   texture[0] = "$backBuffer";
+   
+   scaleOutput = 1.25;
+};
+
 //-----------------------------------------------------------------------------
 // Barrel Distortion Mono PostFx
 //

+ 95 - 0
Templates/Full/game/shaders/common/postFx/oculusvr/barrelDistortionChromaP.hlsl

@@ -0,0 +1,95 @@
+//-----------------------------------------------------------------------------
+// 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 "shadergen:/autogenConditioners.h"  
+#include "../postFx.hlsl"  
+#include "../../torque.hlsl"
+
+uniform sampler2D backBuffer : register(S0);
+
+uniform float3 LensCenter;    // x=Left X, y=Right X, z=Y
+uniform float2 ScreenCenter;
+uniform float2 Scale;
+uniform float2 ScaleIn;
+uniform float4 HmdWarpParam;
+uniform float4 HmdChromaAbParam; // Chromatic aberration correction
+
+float4 main( PFXVertToPix IN ) : COLOR0  
+{
+   float2 texCoord;
+   float xOffset;
+   float2 lensCenter;
+   lensCenter.y = LensCenter.z;
+   if(IN.uv0.x < 0.5)
+   {
+      texCoord.x = IN.uv0.x;
+      texCoord.y = IN.uv0.y;
+      xOffset = 0.0;
+      lensCenter.x = LensCenter.x;
+   }
+   else
+   {
+      texCoord.x = IN.uv0.x - 0.5;
+      texCoord.y = IN.uv0.y;
+      xOffset = 0.5;
+      lensCenter.x = LensCenter.y;
+   }
+   
+   // Scales input texture coordinates for distortion.
+   // ScaleIn maps texture coordinates to Scales to ([-1, 1]), although top/bottom will be
+   // larger due to aspect ratio.
+   float2 theta = (texCoord - lensCenter) * ScaleIn; // Scales to [-1, 1]
+   float rSq = theta.x * theta.x + theta.y * theta.y;
+   float2 theta1 = theta * (HmdWarpParam.x + HmdWarpParam.y * rSq + HmdWarpParam.z * rSq * rSq + HmdWarpParam.w * rSq * rSq * rSq);
+
+   // Detect whether blue texture coordinates are out of range
+   // since these will scaled out the furthest.
+   float2 thetaBlue = theta1 * (HmdChromaAbParam.z + HmdChromaAbParam.w * rSq);
+   float2 tcBlue = lensCenter + Scale * thetaBlue;
+   
+   float4 color;
+   if (any(clamp(tcBlue, ScreenCenter-float2(0.25,0.5), ScreenCenter+float2(0.25, 0.5)) - tcBlue))
+   {
+      color = float4(0,0,0,0);
+   }
+   else
+   {
+      // Now do blue texture lookup.
+      tcBlue.x += xOffset;
+      float blue = tex2D(backBuffer, tcBlue).b;
+
+      // Do green lookup (no scaling).
+      float2 tcGreen = lensCenter + Scale * theta1;
+      tcGreen.x += xOffset;
+      float green = tex2D(backBuffer, tcGreen).g;
+
+      // Do red scale and lookup.
+      float2 thetaRed = theta1 * (HmdChromaAbParam.x + HmdChromaAbParam.y * rSq);
+      float2 tcRed = lensCenter + Scale * thetaRed;
+      tcRed.x += xOffset;
+      float red = tex2D(backBuffer, tcRed).r;
+
+      color = float4(red, green, blue, 1);
+   }
+
+   return color;    
+}