| @@ -0,0 +1,152 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // 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. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| #ifndef _OCULUSVRDEVICE_H_ | ||
| #define _OCULUSVRDEVICE_H_ | ||
|
|
||
| #include "platform/input/oculusVR/oculusVRConstants.h" | ||
| #include "platform/input/oculusVR/oculusVRHMDDevice.h" | ||
| #include "platform/input/oculusVR/oculusVRSensorDevice.h" | ||
| #include "platform/input/IInputDevice.h" | ||
| #include "platform/input/event.h" | ||
| #include "platform/output/IDisplayDevice.h" | ||
| #include "core/util/tSingleton.h" | ||
| #include "math/mQuat.h" | ||
| #include "math/mPoint4.h" | ||
| #include "OVR.h" | ||
|
|
||
| #define DEFAULT_RIFT_UNIT 0 | ||
|
|
||
| class OculusVRDevice : public IInputDevice, public IDisplayDevice | ||
| { | ||
| public: | ||
| static bool smEnableDevice; | ||
|
|
||
| // If no HMD is present simulate it being available | ||
| static bool smSimulateHMD; | ||
|
|
||
| // Type of rotation events to broadcast | ||
| static bool smGenerateAngleAxisRotationEvents; | ||
| static bool smGenerateEulerRotationEvents; | ||
|
|
||
| // Broadcast sensor rotation as axis | ||
| static bool smGenerateRotationAsAxisEvents; | ||
|
|
||
| // The maximum sensor angle when used as an axis event | ||
| // as measured from a vector pointing straight up (in degrees) | ||
| static F32 smMaximumAxisAngle; | ||
|
|
||
| // Indicates that a whole frame event should be generated and frames | ||
| // should be buffered. | ||
| static bool smGenerateWholeFrameEvents; | ||
|
|
||
| protected: | ||
| class DeviceListener : public OVR::MessageHandler | ||
| { | ||
| protected: | ||
| OculusVRDevice* mOwner; | ||
|
|
||
| public: | ||
| DeviceListener(OculusVRDevice* owner) { mOwner = owner; } | ||
| virtual ~DeviceListener() { mOwner = NULL; } | ||
|
|
||
| virtual void OnMessage(const OVR::Message&); | ||
| }; | ||
|
|
||
| // Our OVR SDK device listener class | ||
| DeviceListener* mListener; | ||
|
|
||
| // The OVR SDK device manager | ||
| OVR::DeviceManager* mDeviceManager; | ||
|
|
||
| // Discovered HMD devices | ||
| Vector<OculusVRHMDDevice*> mHMDDevices; | ||
|
|
||
| // Discovered sensor devices | ||
| Vector<OculusVRSensorDevice*> mSensorDevices; | ||
|
|
||
| /// Is the device active | ||
| bool mActive; | ||
|
|
||
| // Should the input texture into the HMD (the render target that the scene has been | ||
| // rendered to) be scaled according to the HMD's distortion calculation? | ||
| bool mScaleInputTexture; | ||
|
|
||
| protected: | ||
| void cleanUp(); | ||
|
|
||
| /// Build out the codes used for controller actions with the | ||
| /// Input Event Manager | ||
| void buildCodeTable(); | ||
|
|
||
| void addHMDDevice(OVR::HMDDevice* hmd); | ||
|
|
||
| void createSimulatedHMD(); | ||
|
|
||
| void addSensorDevice(OVR::SensorDevice* sensor); | ||
|
|
||
| void createSimulatedSensor(); | ||
|
|
||
| public: | ||
| OculusVRDevice(); | ||
| ~OculusVRDevice(); | ||
|
|
||
| static void staticInit(); | ||
|
|
||
| bool enable(); | ||
| void disable(); | ||
|
|
||
| bool getActive() { return mActive; } | ||
| void setActive(bool state) { mActive = state; } | ||
|
|
||
| bool process(); | ||
|
|
||
| // IDisplayDevice | ||
| virtual bool providesYFOV() const; | ||
| virtual F32 getYFOV() const; | ||
| virtual bool providesEyeOffset() const; | ||
| virtual const Point3F& getEyeOffset() const; | ||
| virtual bool providesProjectionOffset() const; | ||
| virtual const Point2F& getProjectionOffset() const; | ||
|
|
||
| // HMDs | ||
| U32 getHMDCount() const { return mHMDDevices.size(); } | ||
| const OculusVRHMDDevice* getHMDDevice(U32 index) const; | ||
|
|
||
| // Sensors | ||
| U32 getSensorCount() const { return mSensorDevices.size(); } | ||
| const OculusVRSensorDevice* getSensorDevice(U32 index) const; | ||
| EulerF getSensorEulerRotation(U32 index); | ||
| F32 getSensorPredictionTime(U32 index); | ||
| void setSensorPredictionTime(U32 index, F32 dt); | ||
| void setAllSensorPredictionTime(F32 dt); | ||
| void resetAllSensors(); | ||
|
|
||
| public: | ||
| // For ManagedSingleton. | ||
| static const char* getSingletonName() { return "OculusVRDevice"; } | ||
| }; | ||
|
|
||
| /// Returns the OculusVRDevice singleton. | ||
| #define OCULUSVRDEV ManagedSingleton<OculusVRDevice>::instance() | ||
|
|
||
| #endif // _OCULUSVRDEVICE_H_ |
| @@ -0,0 +1,208 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // 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; | ||
|
|
||
| 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; | ||
| mInterpupillaryDistance = info.InterpupillaryDistance; | ||
|
|
||
| mKDistortion.x = info.DistortionK[0]; | ||
| mKDistortion.y = info.DistortionK[1]; | ||
| mKDistortion.z = info.DistortionK[2]; | ||
| mKDistortion.w = info.DistortionK[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; | ||
| mInterpupillaryDistance = 0.064000003f; | ||
|
|
||
| mKDistortion.x = 1.0000000f; | ||
| mKDistortion.y = 0.22000000f; | ||
| mKDistortion.z = 0.23999999f; | ||
| mKDistortion.w = 0.00000000f; | ||
|
|
||
| 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); | ||
| } |
| @@ -0,0 +1,187 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // 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. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| #ifndef _OCULUSVRHMDDEVICE_H_ | ||
| #define _OCULUSVRHMDDEVICE_H_ | ||
|
|
||
| #include "core/util/str.h" | ||
| #include "math/mQuat.h" | ||
| #include "math/mPoint2.h" | ||
| #include "math/mPoint3.h" | ||
| #include "math/mPoint4.h" | ||
| #include "platform/input/oculusVR/oculusVRConstants.h" | ||
| #include "platform/types.h" | ||
| #include "OVR.h" | ||
|
|
||
| class OculusVRHMDDevice | ||
| { | ||
| public: | ||
| enum SimulationTypes { | ||
| ST_RIFT_PREVIEW, | ||
| }; | ||
|
|
||
| protected: | ||
| bool mIsValid; | ||
|
|
||
| bool mIsSimulation; | ||
|
|
||
| OVR::HMDDevice* mDevice; | ||
|
|
||
| // From OVR::DeviceInfo | ||
| String mProductName; | ||
| String mManufacturer; | ||
| U32 mVersion; | ||
|
|
||
| // Windows display device name used in EnumDisplaySettings/CreateDC | ||
| String mDisplayDeviceName; | ||
|
|
||
| // Whole screen resolution | ||
| Point2I mResolution; | ||
|
|
||
| // Physical screen size in meters | ||
| Point2F mScreenSize; | ||
|
|
||
| // Physical offset from the top of the screen to the center of the | ||
| // eye, in meters. Usually half of the vertical physical screen size | ||
| F32 mVerticalEyeCenter; | ||
|
|
||
| // Physical distance from the eye to the screen | ||
| F32 mEyeToScreen; | ||
|
|
||
| // Physical distance between lens centers, in meters | ||
| F32 mLensSeparation; | ||
|
|
||
| // Physical distance between the user's eye centers | ||
| F32 mInterpupillaryDistance; | ||
|
|
||
| // The eye IPD as a Point3F | ||
| Point3F mEyeWorldOffset; | ||
|
|
||
| // Radial distortion correction coefficients used by the barrel distortion shader | ||
| Point4F mKDistortion; | ||
|
|
||
| // 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 | ||
| // is the right eye. | ||
| Point2F mEyeUVOffset; | ||
|
|
||
| // Used to adjust where an eye's view is rendered to account for the lenses not | ||
| // being in the center of the physical screen half. | ||
| F32 mXCenterOffset; | ||
|
|
||
| // When calculating the distortion scale to use to increase the size of the input texture | ||
| // this determines how we should attempt to fit the distorted view into the backbuffer. | ||
| Point2F mDistortionFit; | ||
|
|
||
| // Is the factor by which the input texture size is increased to make post-distortion | ||
| // result distortion fit the viewport. If the input texture is the same size as the | ||
| // backbuffer, then this should be 1.0. | ||
| F32 mDistortionScale; | ||
|
|
||
| // Aspect ratio for a single eye | ||
| F32 mAspectRatio; | ||
|
|
||
| // Vertical field of view | ||
| F32 mYFOV; | ||
|
|
||
| // The amount to offset the projection matrix to account for the eye not being in the | ||
| // center of the screen. | ||
| Point2F mProjectionCenterOffset; | ||
|
|
||
| protected: | ||
| F32 calcScale(F32 fitRadius); | ||
|
|
||
| void calculateValues(bool calculateDistortionScale); | ||
|
|
||
| void createSimulatedPreviewRift(bool calculateDistortionScale); | ||
|
|
||
| public: | ||
| OculusVRHMDDevice(); | ||
| ~OculusVRHMDDevice(); | ||
|
|
||
| void cleanUp(); | ||
|
|
||
| // Set the HMD properties based on information from the OVR device | ||
| void set(OVR::HMDDevice* hmd, OVR::HMDInfo& info, bool calculateDistortionScale); | ||
|
|
||
| // Set the HMD properties based on a simulation of the given type | ||
| void createSimulation(SimulationTypes simulationType, bool calculateDistortionScale); | ||
|
|
||
| bool isValid() const {return mIsValid;} | ||
| bool isSimulated() const {return mIsSimulation;} | ||
|
|
||
| const char* getProductName() const { return mProductName.c_str(); } | ||
| const char* getManufacturer() const { return mManufacturer.c_str(); } | ||
| U32 getVersion() const { return mVersion; } | ||
|
|
||
| // Windows display device name used in EnumDisplaySettings/CreateDC | ||
| const char* getDisplayDeviceName() const { return mDisplayDeviceName.c_str(); } | ||
|
|
||
| // Whole screen resolution | ||
| const Point2I& getResolution() const { return mResolution; } | ||
|
|
||
| // Physical screen size in meters | ||
| const Point2F& getScreenSize() const { return mScreenSize; } | ||
|
|
||
| // Physical offset from the top of the screen to the center of the | ||
| // eye, in meters. Usually half of the vertical physical screen size | ||
| F32 getVerticalEyeCenter() const { return mVerticalEyeCenter; } | ||
|
|
||
| // Physical distance from the eye to the screen | ||
| F32 getEyeToScreen() const { return mEyeToScreen; } | ||
|
|
||
| // Physical distance between lens centers, in meters | ||
| F32 getLensSeparation() const { return mLensSeparation; } | ||
|
|
||
| // Physical distance between the user's eye centers | ||
| F32 getIPD() const { return mInterpupillaryDistance; } | ||
|
|
||
| // 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; } | ||
|
|
||
| // Calculated values of eye x offset from center in normalized (uv) coordinates. | ||
| const Point2F& getEyeUVOffset() const { return mEyeUVOffset; } | ||
|
|
||
| // Used to adjust where an eye's view is rendered to account for the lenses not | ||
| // being in the center of the physical screen half. | ||
| F32 getCenterOffset() const { return mXCenterOffset; } | ||
|
|
||
| // Is the factor by which the input texture size is increased to make post-distortion | ||
| // result distortion fit the viewport. | ||
| F32 getDistortionScale() const { return mDistortionScale; } | ||
|
|
||
| // Aspect ration for a single eye | ||
| F32 getAspectRation() const { return mAspectRatio; } | ||
|
|
||
| // Vertical field of view | ||
| F32 getYFOV() const { return mYFOV; } | ||
|
|
||
| // The amount to offset the projection matrix to account for the eye not being in the | ||
| // center of the screen. | ||
| const Point2F& getProjectionCenterOffset() const { return mProjectionCenterOffset; } | ||
| }; | ||
|
|
||
| #endif // _OCULUSVRHMDDEVICE_H_ |
| @@ -0,0 +1,96 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // 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/oculusVRSensorData.h" | ||
| #include "platform/input/oculusVR/oculusVRUtil.h" | ||
| #include "console/console.h" | ||
|
|
||
| OculusVRSensorData::OculusVRSensorData() | ||
| { | ||
| reset(); | ||
| } | ||
|
|
||
| void OculusVRSensorData::reset() | ||
| { | ||
| mDataSet = false; | ||
| } | ||
|
|
||
| void OculusVRSensorData::setData(const OVR::SensorFusion& data, const F32& maxAxisRadius) | ||
| { | ||
| // Sensor rotation | ||
| OVR::Quatf orientation; | ||
| if(data.GetPredictionDelta() > 0) | ||
| { | ||
| orientation = data.GetPredictedOrientation(); | ||
| } | ||
| else | ||
| { | ||
| orientation = data.GetOrientation(); | ||
| } | ||
| OVR::Matrix4f orientMat(orientation); | ||
| OculusVRUtil::convertRotation(orientMat.M, mRot); | ||
| mRotQuat.set(mRot); | ||
|
|
||
| // Sensor rotation in Euler format | ||
| OculusVRUtil::convertRotation(orientation, mRotEuler); | ||
|
|
||
| // Sensor rotation as axis | ||
| OculusVRUtil::calculateAxisRotation(mRot, maxAxisRadius, mRotAxis); | ||
|
|
||
| mDataSet = true; | ||
| } | ||
|
|
||
| void OculusVRSensorData::simulateData(const F32& maxAxisRadius) | ||
| { | ||
| // Sensor rotation | ||
| mRot.identity(); | ||
| mRotQuat.identity(); | ||
| mRotEuler.zero(); | ||
|
|
||
| // Sensor rotation as axis | ||
| OculusVRUtil::calculateAxisRotation(mRot, maxAxisRadius, mRotAxis); | ||
|
|
||
| mDataSet = true; | ||
| } | ||
|
|
||
| U32 OculusVRSensorData::compare(OculusVRSensorData* other) | ||
| { | ||
| S32 result = DIFF_NONE; | ||
|
|
||
| // Check rotation | ||
| if(mRotEuler.x != other->mRotEuler.x || mRotEuler.y != other->mRotEuler.y || mRotEuler.z != other->mRotEuler.z || !mDataSet) | ||
| { | ||
| result |= DIFF_ROT; | ||
| } | ||
|
|
||
| // Check rotation as axis | ||
| if(mRotAxis.x != other->mRotAxis.x || !mDataSet) | ||
| { | ||
| result |= DIFF_ROTAXISX; | ||
| } | ||
| if(mRotAxis.y != other->mRotAxis.y || !mDataSet) | ||
| { | ||
| result |= DIFF_ROTAXISY; | ||
| } | ||
|
|
||
| return result; | ||
| } |
| @@ -0,0 +1,68 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // 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. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| #ifndef _OCULUSVRSENSORDATA_H_ | ||
| #define _OCULUSVRSENSORDATA_H_ | ||
|
|
||
| #include "platform/types.h" | ||
| #include "math/mMatrix.h" | ||
| #include "math/mQuat.h" | ||
| #include "math/mPoint2.h" | ||
| #include "OVR.h" | ||
|
|
||
| struct OculusVRSensorData | ||
| { | ||
| enum DataDifferences { | ||
| DIFF_NONE = 0, | ||
| DIFF_ROT = (1<<0), | ||
| DIFF_ROTAXISX = (1<<1), | ||
| DIFF_ROTAXISY = (1<<2), | ||
|
|
||
| DIFF_ROTAXIS = (DIFF_ROTAXISX | DIFF_ROTAXISY), | ||
| }; | ||
|
|
||
| bool mDataSet; | ||
|
|
||
| // Rotation | ||
| MatrixF mRot; | ||
| QuatF mRotQuat; | ||
| EulerF mRotEuler; | ||
|
|
||
| // Controller rotation as axis x, y | ||
| Point2F mRotAxis; | ||
|
|
||
| OculusVRSensorData(); | ||
|
|
||
| /// Reset the data | ||
| void reset(); | ||
|
|
||
| /// Set data based on given sensor fusion | ||
| void setData(const OVR::SensorFusion& data, const F32& maxAxisRadius); | ||
|
|
||
| /// Simulate valid data | ||
| void simulateData(const F32& maxAxisRadius); | ||
|
|
||
| /// Compare this data and given and return differences | ||
| U32 compare(OculusVRSensorData* other); | ||
| }; | ||
|
|
||
| #endif // _OCULUSVRSENSORDATA_H_ |
| @@ -0,0 +1,265 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // 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/oculusVRSensorDevice.h" | ||
| #include "platform/input/oculusVR/oculusVRSensorData.h" | ||
| #include "platform/input/oculusVR/oculusVRUtil.h" | ||
| #include "platform/platformInput.h" | ||
|
|
||
| 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}; | ||
|
|
||
| OculusVRSensorDevice::OculusVRSensorDevice() | ||
| { | ||
| mIsValid = false; | ||
| mIsSimulation = false; | ||
| mDevice = NULL; | ||
|
|
||
| for(U32 i=0; i<2; ++i) | ||
| { | ||
| mDataBuffer[i] = new OculusVRSensorData(); | ||
| } | ||
| mPrevData = mDataBuffer[0]; | ||
| } | ||
|
|
||
| OculusVRSensorDevice::~OculusVRSensorDevice() | ||
| { | ||
| cleanUp(); | ||
|
|
||
| for(U32 i=0; i<2; ++i) | ||
| { | ||
| delete mDataBuffer[i]; | ||
| mDataBuffer[i] = NULL; | ||
| } | ||
| mPrevData = NULL; | ||
| } | ||
|
|
||
| void OculusVRSensorDevice::cleanUp() | ||
| { | ||
| mSensorFusion.AttachToSensor(NULL); | ||
|
|
||
| if(mDevice) | ||
| { | ||
| mDevice->Release(); | ||
| mDevice = NULL; | ||
| } | ||
|
|
||
| mIsValid = false; | ||
| } | ||
|
|
||
| void OculusVRSensorDevice::set(OVR::SensorDevice* sensor, OVR::SensorInfo& info, S32 actionCodeIndex) | ||
| { | ||
| mIsValid = false; | ||
|
|
||
| mDevice = sensor; | ||
| mSensorFusion.AttachToSensor(sensor); | ||
|
|
||
| // DeviceInfo | ||
| mProductName = info.ProductName; | ||
| mManufacturer = info.Manufacturer; | ||
| mVersion = info.Version; | ||
|
|
||
| // SensorInfo | ||
| mVendorId = info.VendorId; | ||
| mProductId = info.ProductId; | ||
| mSerialNumber = info.SerialNumber; | ||
|
|
||
| mActionCodeIndex = actionCodeIndex; | ||
|
|
||
| if(mActionCodeIndex >= OculusVRConstants::MaxSensors) | ||
| { | ||
| // Cannot declare more sensors than we are able to handle | ||
| mIsValid = false; | ||
| } | ||
| else | ||
| { | ||
| mIsValid = true; | ||
| } | ||
| } | ||
|
|
||
| void OculusVRSensorDevice::createSimulation(SimulationTypes simulationType, S32 actionCodeIndex) | ||
| { | ||
| if(simulationType == ST_RIFT_PREVIEW) | ||
| { | ||
| createSimulatedPreviewRift(actionCodeIndex); | ||
| } | ||
| } | ||
|
|
||
| void OculusVRSensorDevice::createSimulatedPreviewRift(S32 actionCodeIndex) | ||
| { | ||
| mIsValid = false; | ||
| mIsSimulation = true; | ||
|
|
||
| // DeviceInfo | ||
| mProductName = "Tracker DK"; | ||
| mManufacturer = "Oculus VR, Inc."; | ||
| mVersion = 0; | ||
|
|
||
| // SensorInfo | ||
| mVendorId = 10291; | ||
| mProductId = 1; | ||
| mSerialNumber = "000000000000"; | ||
|
|
||
| mActionCodeIndex = actionCodeIndex; | ||
|
|
||
| if(mActionCodeIndex >= OculusVRConstants::MaxSensors) | ||
| { | ||
| // Cannot declare more sensors than we are able to handle | ||
| mIsValid = false; | ||
| } | ||
| else | ||
| { | ||
| mIsValid = true; | ||
| } | ||
| } | ||
|
|
||
| void OculusVRSensorDevice::buildCodeTable() | ||
| { | ||
| // Obtain all of the device codes | ||
| for(U32 i=0; i<OculusVRConstants::MaxSensors; ++i) | ||
| { | ||
| OVR_SENSORROT[i] = INPUTMGR->getNextDeviceCode(); | ||
|
|
||
| OVR_SENSORROTANG[i] = INPUTMGR->getNextDeviceCode(); | ||
|
|
||
| OVR_SENSORROTAXISX[i] = INPUTMGR->getNextDeviceCode(); | ||
| OVR_SENSORROTAXISY[i] = INPUTMGR->getNextDeviceCode(); | ||
| } | ||
|
|
||
| // Build out the virtual map | ||
| char buffer[64]; | ||
| for(U32 i=0; i<OculusVRConstants::MaxSensors; ++i) | ||
| { | ||
| dSprintf(buffer, 64, "ovr_sensorrot%d", i); | ||
| INPUTMGR->addVirtualMap( buffer, SI_ROT, OVR_SENSORROT[i] ); | ||
|
|
||
| dSprintf(buffer, 64, "ovr_sensorrotang%d", i); | ||
| INPUTMGR->addVirtualMap( buffer, SI_ROT, 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] ); | ||
| } | ||
| } | ||
|
|
||
| bool OculusVRSensorDevice::process(U32 deviceType, bool generateRotAsAngAxis, bool generateRotAsEuler, bool generateRotationAsAxisEvents, F32 maxAxisRadius) | ||
| { | ||
| if(!mIsValid) | ||
| return false; | ||
|
|
||
| // Store the current data from the sensor and compare with previous data | ||
| U32 diff; | ||
| OculusVRSensorData* currentBuffer = (mPrevData == mDataBuffer[0]) ? mDataBuffer[1] : mDataBuffer[0]; | ||
| if(!mIsSimulation) | ||
| { | ||
| currentBuffer->setData(mSensorFusion, maxAxisRadius); | ||
| } | ||
| else | ||
| { | ||
| currentBuffer->simulateData(maxAxisRadius); | ||
| } | ||
| diff = mPrevData->compare(currentBuffer); | ||
|
|
||
| // Update the previous data pointer. We do this here in case someone calls our | ||
| // console functions during one of the input events below. | ||
| mPrevData = currentBuffer; | ||
|
|
||
| // Rotation event | ||
| if(diff & OculusVRSensorData::DIFF_ROT) | ||
| { | ||
| if(generateRotAsAngAxis) | ||
| { | ||
| INPUTMGR->buildInputEvent(deviceType, OculusVRConstants::DefaultOVRBase, SI_ROT, OVR_SENSORROT[mActionCodeIndex], SI_MOVE, currentBuffer->mRotQuat); | ||
| } | ||
|
|
||
| if(generateRotAsEuler) | ||
| { | ||
| // Convert angles to degrees | ||
| VectorF angles; | ||
| for(U32 i=0; i<3; ++i) | ||
| { | ||
| angles[i] = mRadToDeg(currentBuffer->mRotEuler[i]); | ||
| } | ||
| INPUTMGR->buildInputEvent(deviceType, OculusVRConstants::DefaultOVRBase, SI_POS, OVR_SENSORROTANG[mActionCodeIndex], SI_MOVE, angles); | ||
| } | ||
| } | ||
|
|
||
| // Rotation as axis event | ||
| if(generateRotationAsAxisEvents && diff & OculusVRSensorData::DIFF_ROTAXIS) | ||
| { | ||
| if(diff & OculusVRSensorData::DIFF_ROTAXISX) | ||
| INPUTMGR->buildInputEvent(deviceType, OculusVRConstants::DefaultOVRBase, SI_AXIS, OVR_SENSORROTAXISX[mActionCodeIndex], SI_MOVE, currentBuffer->mRotAxis.x); | ||
| if(diff & OculusVRSensorData::DIFF_ROTAXISY) | ||
| INPUTMGR->buildInputEvent(deviceType, OculusVRConstants::DefaultOVRBase, SI_AXIS, OVR_SENSORROTAXISY[mActionCodeIndex], SI_MOVE, currentBuffer->mRotAxis.y); | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| void OculusVRSensorDevice::reset() | ||
| { | ||
| if(!mIsValid) | ||
| return; | ||
|
|
||
| mSensorFusion.Reset(); | ||
| } | ||
|
|
||
| F32 OculusVRSensorDevice::getPredictionTime() const | ||
| { | ||
| if(!mIsValid) | ||
| return 0.0f; | ||
|
|
||
| return mSensorFusion.GetPredictionDelta(); | ||
| } | ||
|
|
||
| void OculusVRSensorDevice::setPredictionTime(F32 dt) | ||
| { | ||
| if(!mIsValid) | ||
| return; | ||
|
|
||
| mSensorFusion.SetPrediction(dt); | ||
| } | ||
|
|
||
| EulerF OculusVRSensorDevice::getEulerRotation() | ||
| { | ||
| if(!mIsValid) | ||
| return Point3F::Zero; | ||
|
|
||
| OVR::Quatf orientation; | ||
| if(mSensorFusion.GetPredictionDelta() > 0) | ||
| { | ||
| orientation = mSensorFusion.GetPredictedOrientation(); | ||
| } | ||
| else | ||
| { | ||
| orientation = mSensorFusion.GetOrientation(); | ||
| } | ||
|
|
||
| // Sensor rotation in Euler format | ||
| EulerF rot; | ||
| OculusVRUtil::convertRotation(orientation, rot); | ||
|
|
||
| return rot; | ||
| } |
| @@ -0,0 +1,122 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // 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. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| #ifndef _OCULUSVRSENSORDEVICE_H_ | ||
| #define _OCULUSVRSENSORDEVICE_H_ | ||
|
|
||
| #include "core/util/str.h" | ||
| #include "math/mQuat.h" | ||
| #include "math/mPoint2.h" | ||
| #include "math/mPoint3.h" | ||
| #include "math/mPoint4.h" | ||
| #include "platform/input/oculusVR/oculusVRConstants.h" | ||
| #include "platform/types.h" | ||
| #include "OVR.h" | ||
|
|
||
| struct OculusVRSensorData; | ||
|
|
||
| class OculusVRSensorDevice | ||
| { | ||
| public: | ||
| enum SimulationTypes { | ||
| ST_RIFT_PREVIEW, | ||
| }; | ||
|
|
||
| public: | ||
| // Action codes | ||
| static U32 OVR_SENSORROT[OculusVRConstants::MaxSensors]; // SI_ROT | ||
|
|
||
| static U32 OVR_SENSORROTANG[OculusVRConstants::MaxSensors]; // SI_POS but is EulerF | ||
|
|
||
| static U32 OVR_SENSORROTAXISX[OculusVRConstants::MaxSensors]; // SI_AXIS | ||
| static U32 OVR_SENSORROTAXISY[OculusVRConstants::MaxSensors]; | ||
|
|
||
| protected: | ||
| bool mIsValid; | ||
|
|
||
| bool mIsSimulation; | ||
|
|
||
| OVR::SensorDevice* mDevice; | ||
|
|
||
| OVR::SensorFusion mSensorFusion; | ||
|
|
||
| // From OVR::DeviceInfo | ||
| String mProductName; | ||
| String mManufacturer; | ||
| U32 mVersion; | ||
|
|
||
| // From OVR::SensorInfo | ||
| U16 mVendorId; | ||
| U16 mProductId; | ||
| String mSerialNumber; | ||
|
|
||
| // Assigned by the OculusVRDevice | ||
| S32 mActionCodeIndex; | ||
|
|
||
| // Buffers to store data for sensor | ||
| OculusVRSensorData* mDataBuffer[2]; | ||
|
|
||
| // Points to the buffer that holds the previously collected data | ||
| // for the sensor | ||
| OculusVRSensorData* mPrevData; | ||
|
|
||
| protected: | ||
| void createSimulatedPreviewRift(S32 actionCodeIndex); | ||
|
|
||
| public: | ||
| OculusVRSensorDevice(); | ||
| virtual ~OculusVRSensorDevice(); | ||
|
|
||
| static void buildCodeTable(); | ||
|
|
||
| void cleanUp(); | ||
|
|
||
| // Set the sensor properties based on information from the OVR device | ||
| void set(OVR::SensorDevice* sensor, OVR::SensorInfo& info, S32 actionCodeIndex); | ||
|
|
||
| // Set the sensor properties based on a simulation of the given type | ||
| void createSimulation(SimulationTypes simulationType, S32 actionCodeIndex); | ||
|
|
||
| bool isValid() const {return mIsValid;} | ||
| bool isSimulated() {return mIsSimulation;} | ||
|
|
||
| bool process(U32 deviceType, bool generateRotAsAngAxis, bool generateRotAsEuler, bool generateRotationAsAxisEvents, F32 maxAxisRadius); | ||
|
|
||
| void reset(); | ||
|
|
||
| // Get the prediction time for the sensor fusion. The time is in seconds. | ||
| F32 getPredictionTime() const; | ||
|
|
||
| // Set the prediction time for the sensor fusion. The time is in seconds. | ||
| void setPredictionTime(F32 dt); | ||
|
|
||
| const char* getProductName() { return mProductName.c_str(); } | ||
| const char* getManufacturer() { return mManufacturer.c_str(); } | ||
| U32 getVersion() { return mVersion; } | ||
| U16 getVendorId() { return mVendorId; } | ||
| U16 getProductId() { return mProductId; } | ||
| const char* getSerialNumber() { return mSerialNumber; } | ||
|
|
||
| EulerF getEulerRotation(); | ||
| }; | ||
|
|
||
| #endif // _OCULUSVRSENSORDEVICE_H_ |
| @@ -0,0 +1,76 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // 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/oculusVRUtil.h" | ||
|
|
||
| namespace OculusVRUtil | ||
| { | ||
|
|
||
| void convertRotation(const F32 inRotMat[4][4], MatrixF& outRotation) | ||
| { | ||
| // Set rotation. We need to convert from sensor coordinates to | ||
| // Torque coordinates. The sensor matrix is stored row-major. | ||
| // The conversion is: | ||
| // | ||
| // Sensor Torque | ||
| // a b c a b c a -c b | ||
| // d e f --> -g -h -i --> -g i -h | ||
| // g h i d e f d -f e | ||
| outRotation.setColumn(0, Point4F( inRotMat[0][0], -inRotMat[2][0], inRotMat[1][0], 0.0f)); | ||
| outRotation.setColumn(1, Point4F(-inRotMat[0][2], inRotMat[2][2], -inRotMat[1][2], 0.0f)); | ||
| outRotation.setColumn(2, Point4F( inRotMat[0][1], -inRotMat[2][1], inRotMat[1][1], 0.0f)); | ||
| outRotation.setPosition(Point3F::Zero); | ||
| } | ||
|
|
||
| void convertRotation(OVR::Quatf& inRotation, EulerF& outRotation) | ||
| { | ||
| F32 yaw, pitch, roll; | ||
| inRotation.GetEulerAngles<OVR::Axis_Y, OVR::Axis_X, OVR::Axis_Z>(&yaw, &pitch, &roll); | ||
| outRotation.x = -pitch; | ||
| outRotation.y = roll; | ||
| outRotation.z = -yaw; | ||
| } | ||
|
|
||
| void calculateAxisRotation(const MatrixF& inRotation, const F32& maxAxisRadius, Point2F& outRotation) | ||
| { | ||
| const VectorF& controllerUp = inRotation.getUpVector(); | ||
| Point2F axis(0,0); | ||
| axis.x = controllerUp.x; | ||
| axis.y = controllerUp.y; | ||
|
|
||
| // Limit the axis angle to that given to us | ||
| if(axis.len() > maxAxisRadius) | ||
| { | ||
| axis.normalize(maxAxisRadius); | ||
| } | ||
|
|
||
| // Renormalize to the range of 0..1 | ||
| if(maxAxisRadius != 0.0f) | ||
| { | ||
| axis /= maxAxisRadius; | ||
| } | ||
|
|
||
| outRotation.x = axis.x; | ||
| outRotation.y = axis.y; | ||
| } | ||
|
|
||
| } |
| @@ -0,0 +1,42 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // 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. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| #ifndef _OCULUSVRUTIL_H_ | ||
| #define _OCULUSVRUTIL_H_ | ||
|
|
||
| #include "math/mPoint2.h" | ||
| #include "math/mMatrix.h" | ||
| #include "OVR.h" | ||
|
|
||
| namespace OculusVRUtil | ||
| { | ||
| /// Convert an OVR sensor's rotation to a Torque 3D matrix | ||
| void convertRotation(const F32 inRotMat[4][4], MatrixF& outRotation); | ||
|
|
||
| /// Convert an OVR sensor's rotation to Torque 3D Euler angles (in radians) | ||
| void convertRotation(OVR::Quatf& inRotation, EulerF& outRotation); | ||
|
|
||
| /// Calcualte a sensor's rotation as if it were a thumb stick axis | ||
| void calculateAxisRotation(const MatrixF& inRotation, const F32& maxAxisRadius, Point2F& outRotation); | ||
| } | ||
|
|
||
| #endif // _OCULUSVRUTIL_H_ |
| @@ -0,0 +1,125 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // 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. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| // Only load these functions if an Oculus VR device is present | ||
| if(!isFunction(isOculusVRDeviceActive)) | ||
| return; | ||
|
|
||
| //----------------------------------------------------------------------------- | ||
|
|
||
| function oculusSensorMetricsCallback() | ||
| { | ||
| return " | OVR Sensor 0 |" @ | ||
| " rot: " @ getOVRSensorEulerRotation(0); | ||
| } | ||
|
|
||
| //----------------------------------------------------------------------------- | ||
|
|
||
| // Call this function from createCanvas() to have the Canvas attach itself | ||
| // to the Rift's display. The Canvas' window will still open on the primary | ||
| // display if that is different from the Rift, but it will move to the Rift | ||
| // when it goes full screen. If the Rift is not connected then nothing | ||
| // will happen. | ||
| function pointCanvasToOculusVRDisplay() | ||
| { | ||
| $pref::Video::displayOutputDevice = getOVRHMDDisplayDeviceName(0); | ||
| } | ||
|
|
||
| //----------------------------------------------------------------------------- | ||
|
|
||
| // Call this function from GameConnection::initialControlSet() just before | ||
| // your "Canvas.setContent(PlayGui);" call, or at any time you wish to switch | ||
| // to a side-by-side rendering and the appropriate barrel distortion. This | ||
| // will turn on side-by-side rendering and tell the GameConnection to use the | ||
| // Rift as its display device. | ||
| // Parameters: | ||
| // %gameConnection - The client GameConnection instance | ||
| // %trueStereoRendering - If true will enable stereo rendering with an eye | ||
| // offset for each viewport. This will render each frame twice. If false | ||
| // then a pseudo stereo rendering is done with only a single render per frame. | ||
| function enableOculusVRDisplay(%gameConnection, %trueStereoRendering) | ||
| { | ||
| setOVRHMDAsGameConnectionDisplayDevice(%gameConnection); | ||
| PlayGui.renderStyle = "stereo side by side"; | ||
|
|
||
| if(%trueStereoRendering) | ||
| { | ||
| OVRBarrelDistortionPostFX.isEnabled = true; | ||
| } | ||
| else | ||
| { | ||
| OVRBarrelDistortionMonoPostFX.isEnabled = true; | ||
| } | ||
|
|
||
| // Reset all sensors | ||
| ovrResetAllSensors(); | ||
| } | ||
|
|
||
| // Call this function when ever you wish to turn off the stereo rendering | ||
| // and barrel distortion for the Rift. | ||
| function disableOculusVRDisplay(%gameConnection) | ||
| { | ||
| %gameConnection.clearDisplayDevice(); | ||
| PlayGui.renderStyle = "standard"; | ||
| OVRBarrelDistortionPostFX.isEnabled = false; | ||
| OVRBarrelDistortionMonoPostFX.isEnabled = false; | ||
| } | ||
|
|
||
| // Helper function to set the standard Rift control scheme. You could place | ||
| // this function in GameConnection::initialControlSet() at the same time | ||
| // you call enableOculusVRDisplay(). | ||
| function setStandardOculusVRControlScheme(%gameConnection) | ||
| { | ||
| if(isOVRHMDSimulated(0)) | ||
| { | ||
| // We are simulating a HMD so allow the mouse and gamepad to control | ||
| // both yaw and pitch. | ||
| %gameConnection.setControlSchemeParameters(true, true, true); | ||
| } | ||
| else | ||
| { | ||
| // A HMD is connected so have the mouse and gamepad only add to yaw | ||
| %gameConnection.setControlSchemeParameters(true, true, false); | ||
| } | ||
| } | ||
|
|
||
| //----------------------------------------------------------------------------- | ||
|
|
||
| // Helper function to set the resolution for the Rift. | ||
| // Parameters: | ||
| // %fullscreen - If true then the display will be forced to full screen. If | ||
| // pointCanvasToOculusVRDisplay() was called before the Canvas was created, then | ||
| // the full screen display will appear on the Rift. | ||
| function setVideoModeForOculusVRDisplay(%fullscreen) | ||
| { | ||
| %res = getOVRHMDResolution(0); | ||
| Canvas.setVideoMode(%res.x, %res.y, %fullscreen, 32, 0); | ||
| } | ||
|
|
||
| //----------------------------------------------------------------------------- | ||
|
|
||
| // Reset all Oculus Rift sensors. This will make the Rift's current heading | ||
| // be considered the origin. | ||
| function resetOculusVRSensors() | ||
| { | ||
| ovrResetAllSensors(); | ||
| } |
| @@ -0,0 +1,123 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // 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. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| // Only load these shaders if an Oculus VR device is present | ||
| if(!isFunction(isOculusVRDeviceActive)) | ||
| return; | ||
|
|
||
| //----------------------------------------------------------------------------- | ||
| // Shader data | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| singleton ShaderData( OVRMonoToStereoShader ) | ||
| { | ||
| DXVertexShaderFile = "shaders/common/postFx/postFxV.hlsl"; | ||
| DXPixelShaderFile = "shaders/common/postFx/oculusvr/monoToStereoP.hlsl"; | ||
|
|
||
| pixVersion = 2.0; | ||
| }; | ||
|
|
||
| singleton ShaderData( OVRBarrelDistortionShader ) | ||
| { | ||
| DXVertexShaderFile = "shaders/common/postFx/postFxV.hlsl"; | ||
| DXPixelShaderFile = "shaders/common/postFx/oculusvr/barrelDistortionP.hlsl"; | ||
|
|
||
| pixVersion = 2.0; | ||
| }; | ||
|
|
||
| //----------------------------------------------------------------------------- | ||
| // GFX state blocks | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| singleton GFXStateBlockData( OVRBarrelDistortionStateBlock : PFX_DefaultStateBlock ) | ||
| { | ||
| samplersDefined = true; | ||
| samplerStates[0] = SamplerClampLinear; | ||
| }; | ||
|
|
||
| //----------------------------------------------------------------------------- | ||
| // Barrel Distortion 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. | ||
| //----------------------------------------------------------------------------- | ||
| singleton BarrelDistortionPostEffect( OVRBarrelDistortionPostFX ) | ||
| { | ||
| isEnabled = false; | ||
| allowReflectPass = false; | ||
|
|
||
| renderTime = "PFXAfterDiffuse"; | ||
| renderPriority = 100; | ||
|
|
||
| // The barrel distortion | ||
| shader = OVRBarrelDistortionShader; | ||
| stateBlock = OVRBarrelDistortionStateBlock; | ||
|
|
||
| texture[0] = "$backBuffer"; | ||
|
|
||
| scaleOutput = 1.25; | ||
| }; | ||
|
|
||
| //----------------------------------------------------------------------------- | ||
| // Barrel Distortion Mono PostFx | ||
| // | ||
| // To be used with the Oculus Rift. | ||
| // Takes a non-stereo image and turns it into a stereo pair with barrel | ||
| // distortion applied. Only a vertical slice around the center of the back | ||
| // buffer is used to generate the pseudo stereo pair. | ||
| //----------------------------------------------------------------------------- | ||
| singleton PostEffect( OVRBarrelDistortionMonoPostFX ) | ||
| { | ||
| isEnabled = false; | ||
| allowReflectPass = false; | ||
|
|
||
| renderTime = "PFXAfterDiffuse"; | ||
| renderPriority = 100; | ||
|
|
||
| // Converts the mono display to a stereo one | ||
| shader = OVRMonoToStereoShader; | ||
| stateBlock = OVRBarrelDistortionStateBlock; | ||
|
|
||
| texture[0] = "$backBuffer"; | ||
| target = "$outTex"; | ||
|
|
||
| // The actual barrel distortion | ||
| new BarrelDistortionPostEffect(OVRBarrelDistortionMonoStage2PostFX) | ||
| { | ||
| shader = OVRBarrelDistortionShader; | ||
| stateBlock = OVRBarrelDistortionStateBlock; | ||
| texture[0] = "$inTex"; | ||
| target = "$backBuffer"; | ||
|
|
||
| scaleOutput = 1.25; | ||
| }; | ||
|
|
||
| }; | ||
|
|
||
| function OVRBarrelDistortionMonoPostFX::setShaderConsts( %this ) | ||
| { | ||
| %HMDIndex = 0; | ||
|
|
||
| %xOffsets = getOVRHMDEyeXOffsets(%HMDIndex); | ||
| %this.setShaderConst( "$LensXOffsets", %xOffsets ); | ||
| } |
| @@ -0,0 +1,81 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // 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; | ||
|
|
||
| // 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 HmdWarp(float2 in01, float2 lensCenter) | ||
| { | ||
| float2 theta = (in01 - 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); | ||
| return lensCenter + Scale * theta1; | ||
| } | ||
|
|
||
| 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; | ||
| } | ||
|
|
||
| float2 tc = HmdWarp(texCoord, lensCenter); | ||
|
|
||
| float4 color; | ||
| if (any(clamp(tc, ScreenCenter-float2(0.25,0.5), ScreenCenter+float2(0.25, 0.5)) - tc)) | ||
| { | ||
| color = float4(0,0,0,0); | ||
| } | ||
| else | ||
| { | ||
| tc.x += xOffset; | ||
| color = tex2D(backBuffer, tc); | ||
| } | ||
|
|
||
| return color; | ||
| } |
| @@ -0,0 +1,60 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // 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 float2 LensXOffsets; | ||
|
|
||
| float4 main( PFXVertToPix IN ) : COLOR0 | ||
| { | ||
| float2 texCoord; | ||
| float xOffset; | ||
| float2 lensCenter; | ||
| lensCenter.y = 0.5; | ||
| if(IN.uv0.x < 0.5) | ||
| { | ||
| texCoord.x = IN.uv0.x; | ||
| texCoord.y = IN.uv0.y; | ||
| xOffset = 0.0; | ||
| lensCenter.x = LensXOffsets.x; | ||
| } | ||
| else | ||
| { | ||
| texCoord.x = IN.uv0.x - 0.5; | ||
| texCoord.y = IN.uv0.y; | ||
| xOffset = 0.5; | ||
| lensCenter.x = LensXOffsets.y; | ||
| } | ||
|
|
||
| texCoord.x *= 2.0; | ||
| texCoord.x += lensCenter.x; | ||
| texCoord.x *= 0.5; | ||
| texCoord.x += 0.25; | ||
|
|
||
| float4 color = tex2D(backBuffer, texCoord); | ||
|
|
||
| return color; | ||
| } |
| @@ -0,0 +1,125 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // 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. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| // Only load these functions if an Oculus VR device is present | ||
| if(!isFunction(isOculusVRDeviceActive)) | ||
| return; | ||
|
|
||
| //----------------------------------------------------------------------------- | ||
|
|
||
| function oculusSensorMetricsCallback() | ||
| { | ||
| return " | OVR Sensor 0 |" @ | ||
| " rot: " @ getOVRSensorEulerRotation(0); | ||
| } | ||
|
|
||
| //----------------------------------------------------------------------------- | ||
|
|
||
| // Call this function from createCanvas() to have the Canvas attach itself | ||
| // to the Rift's display. The Canvas' window will still open on the primary | ||
| // display if that is different from the Rift, but it will move to the Rift | ||
| // when it goes full screen. If the Rift is not connected then nothing | ||
| // will happen. | ||
| function pointCanvasToOculusVRDisplay() | ||
| { | ||
| $pref::Video::displayOutputDevice = getOVRHMDDisplayDeviceName(0); | ||
| } | ||
|
|
||
| //----------------------------------------------------------------------------- | ||
|
|
||
| // Call this function from GameConnection::initialControlSet() just before | ||
| // your "Canvas.setContent(PlayGui);" call, or at any time you wish to switch | ||
| // to a side-by-side rendering and the appropriate barrel distortion. This | ||
| // will turn on side-by-side rendering and tell the GameConnection to use the | ||
| // Rift as its display device. | ||
| // Parameters: | ||
| // %gameConnection - The client GameConnection instance | ||
| // %trueStereoRendering - If true will enable stereo rendering with an eye | ||
| // offset for each viewport. This will render each frame twice. If false | ||
| // then a pseudo stereo rendering is done with only a single render per frame. | ||
| function enableOculusVRDisplay(%gameConnection, %trueStereoRendering) | ||
| { | ||
| setOVRHMDAsGameConnectionDisplayDevice(%gameConnection); | ||
| PlayGui.renderStyle = "stereo side by side"; | ||
|
|
||
| if(%trueStereoRendering) | ||
| { | ||
| OVRBarrelDistortionPostFX.isEnabled = true; | ||
| } | ||
| else | ||
| { | ||
| OVRBarrelDistortionMonoPostFX.isEnabled = true; | ||
| } | ||
|
|
||
| // Reset all sensors | ||
| ovrResetAllSensors(); | ||
| } | ||
|
|
||
| // Call this function when ever you wish to turn off the stereo rendering | ||
| // and barrel distortion for the Rift. | ||
| function disableOculusVRDisplay(%gameConnection) | ||
| { | ||
| %gameConnection.clearDisplayDevice(); | ||
| PlayGui.renderStyle = "standard"; | ||
| OVRBarrelDistortionPostFX.isEnabled = false; | ||
| OVRBarrelDistortionMonoPostFX.isEnabled = false; | ||
| } | ||
|
|
||
| // Helper function to set the standard Rift control scheme. You could place | ||
| // this function in GameConnection::initialControlSet() at the same time | ||
| // you call enableOculusVRDisplay(). | ||
| function setStandardOculusVRControlScheme(%gameConnection) | ||
| { | ||
| if(isOVRHMDSimulated(0)) | ||
| { | ||
| // We are simulating a HMD so allow the mouse and gamepad to control | ||
| // both yaw and pitch. | ||
| %gameConnection.setControlSchemeParameters(true, true, true); | ||
| } | ||
| else | ||
| { | ||
| // A HMD is connected so have the mouse and gamepad only add to yaw | ||
| %gameConnection.setControlSchemeParameters(true, true, false); | ||
| } | ||
| } | ||
|
|
||
| //----------------------------------------------------------------------------- | ||
|
|
||
| // Helper function to set the resolution for the Rift. | ||
| // Parameters: | ||
| // %fullscreen - If true then the display will be forced to full screen. If | ||
| // pointCanvasToOculusVRDisplay() was called before the Canvas was created, then | ||
| // the full screen display will appear on the Rift. | ||
| function setVideoModeForOculusVRDisplay(%fullscreen) | ||
| { | ||
| %res = getOVRHMDResolution(0); | ||
| Canvas.setVideoMode(%res.x, %res.y, %fullscreen, 32, 0); | ||
| } | ||
|
|
||
| //----------------------------------------------------------------------------- | ||
|
|
||
| // Reset all Oculus Rift sensors. This will make the Rift's current heading | ||
| // be considered the origin. | ||
| function resetOculusVRSensors() | ||
| { | ||
| ovrResetAllSensors(); | ||
| } |
| @@ -0,0 +1,123 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // 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. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| // Only load these shaders if an Oculus VR device is present | ||
| if(!isFunction(isOculusVRDeviceActive)) | ||
| return; | ||
|
|
||
| //----------------------------------------------------------------------------- | ||
| // Shader data | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| singleton ShaderData( OVRMonoToStereoShader ) | ||
| { | ||
| DXVertexShaderFile = "shaders/common/postFx/postFxV.hlsl"; | ||
| DXPixelShaderFile = "shaders/common/postFx/oculusvr/monoToStereoP.hlsl"; | ||
|
|
||
| pixVersion = 2.0; | ||
| }; | ||
|
|
||
| singleton ShaderData( OVRBarrelDistortionShader ) | ||
| { | ||
| DXVertexShaderFile = "shaders/common/postFx/postFxV.hlsl"; | ||
| DXPixelShaderFile = "shaders/common/postFx/oculusvr/barrelDistortionP.hlsl"; | ||
|
|
||
| pixVersion = 2.0; | ||
| }; | ||
|
|
||
| //----------------------------------------------------------------------------- | ||
| // GFX state blocks | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| singleton GFXStateBlockData( OVRBarrelDistortionStateBlock : PFX_DefaultStateBlock ) | ||
| { | ||
| samplersDefined = true; | ||
| samplerStates[0] = SamplerClampLinear; | ||
| }; | ||
|
|
||
| //----------------------------------------------------------------------------- | ||
| // Barrel Distortion 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. | ||
| //----------------------------------------------------------------------------- | ||
| singleton BarrelDistortionPostEffect( OVRBarrelDistortionPostFX ) | ||
| { | ||
| isEnabled = false; | ||
| allowReflectPass = false; | ||
|
|
||
| renderTime = "PFXAfterDiffuse"; | ||
| renderPriority = 100; | ||
|
|
||
| // The barrel distortion | ||
| shader = OVRBarrelDistortionShader; | ||
| stateBlock = OVRBarrelDistortionStateBlock; | ||
|
|
||
| texture[0] = "$backBuffer"; | ||
|
|
||
| scaleOutput = 1.25; | ||
| }; | ||
|
|
||
| //----------------------------------------------------------------------------- | ||
| // Barrel Distortion Mono PostFx | ||
| // | ||
| // To be used with the Oculus Rift. | ||
| // Takes a non-stereo image and turns it into a stereo pair with barrel | ||
| // distortion applied. Only a vertical slice around the center of the back | ||
| // buffer is used to generate the pseudo stereo pair. | ||
| //----------------------------------------------------------------------------- | ||
| singleton PostEffect( OVRBarrelDistortionMonoPostFX ) | ||
| { | ||
| isEnabled = false; | ||
| allowReflectPass = false; | ||
|
|
||
| renderTime = "PFXAfterDiffuse"; | ||
| renderPriority = 100; | ||
|
|
||
| // Converts the mono display to a stereo one | ||
| shader = OVRMonoToStereoShader; | ||
| stateBlock = OVRBarrelDistortionStateBlock; | ||
|
|
||
| texture[0] = "$backBuffer"; | ||
| target = "$outTex"; | ||
|
|
||
| // The actual barrel distortion | ||
| new BarrelDistortionPostEffect(OVRBarrelDistortionMonoStage2PostFX) | ||
| { | ||
| shader = OVRBarrelDistortionShader; | ||
| stateBlock = OVRBarrelDistortionStateBlock; | ||
| texture[0] = "$inTex"; | ||
| target = "$backBuffer"; | ||
|
|
||
| scaleOutput = 1.25; | ||
| }; | ||
|
|
||
| }; | ||
|
|
||
| function OVRBarrelDistortionMonoPostFX::setShaderConsts( %this ) | ||
| { | ||
| %HMDIndex = 0; | ||
|
|
||
| %xOffsets = getOVRHMDEyeXOffsets(%HMDIndex); | ||
| %this.setShaderConst( "$LensXOffsets", %xOffsets ); | ||
| } |
| @@ -0,0 +1,81 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // 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; | ||
|
|
||
| // 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 HmdWarp(float2 in01, float2 lensCenter) | ||
| { | ||
| float2 theta = (in01 - 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); | ||
| return lensCenter + Scale * theta1; | ||
| } | ||
|
|
||
| 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; | ||
| } | ||
|
|
||
| float2 tc = HmdWarp(texCoord, lensCenter); | ||
|
|
||
| float4 color; | ||
| if (any(clamp(tc, ScreenCenter-float2(0.25,0.5), ScreenCenter+float2(0.25, 0.5)) - tc)) | ||
| { | ||
| color = float4(0,0,0,0); | ||
| } | ||
| else | ||
| { | ||
| tc.x += xOffset; | ||
| color = tex2D(backBuffer, tc); | ||
| } | ||
|
|
||
| return color; | ||
| } |
| @@ -0,0 +1,60 @@ | ||
| //----------------------------------------------------------------------------- | ||
| // 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 float2 LensXOffsets; | ||
|
|
||
| float4 main( PFXVertToPix IN ) : COLOR0 | ||
| { | ||
| float2 texCoord; | ||
| float xOffset; | ||
| float2 lensCenter; | ||
| lensCenter.y = 0.5; | ||
| if(IN.uv0.x < 0.5) | ||
| { | ||
| texCoord.x = IN.uv0.x; | ||
| texCoord.y = IN.uv0.y; | ||
| xOffset = 0.0; | ||
| lensCenter.x = LensXOffsets.x; | ||
| } | ||
| else | ||
| { | ||
| texCoord.x = IN.uv0.x - 0.5; | ||
| texCoord.y = IN.uv0.y; | ||
| xOffset = 0.5; | ||
| lensCenter.x = LensXOffsets.y; | ||
| } | ||
|
|
||
| texCoord.x *= 2.0; | ||
| texCoord.x += lensCenter.x; | ||
| texCoord.x *= 0.5; | ||
| texCoord.x += 0.25; | ||
|
|
||
| float4 color = tex2D(backBuffer, texCoord); | ||
|
|
||
| return color; | ||
| } |
| @@ -0,0 +1,80 @@ | ||
| <?php | ||
| //----------------------------------------------------------------------------- | ||
| // 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. | ||
| //----------------------------------------------------------------------------- | ||
|
|
||
| beginModule( 'oculusVR' ); | ||
|
|
||
| // Look for the optional global from the project.conf. | ||
| global $OCULUSVR_SDK_PATH; | ||
| if (!$OCULUSVR_SDK_PATH) | ||
| { | ||
| // First look for an environment var. | ||
| $OCULUSVR_SDK_PATH = getenv( "TORQUE_OCULUSVR_PATH" ); | ||
|
|
||
| if (strlen($OCULUSVR_SDK_PATH) == 0 || !file_exists($OCULUSVR_SDK_PATH)) | ||
| { | ||
| // Sometimes users get confused and use this var. | ||
| $OCULUSVR_SDK_PATH = getenv( "OCULUSVR_SDK_PATH" ); | ||
| } | ||
|
|
||
| // We need forward slashes for paths. | ||
| $OCULUSVR_SDK_PATH = str_replace( "\\", "/", $OCULUSVR_SDK_PATH); | ||
|
|
||
| // Remove trailing slashes. | ||
| $OCULUSVR_SDK_PATH = rtrim($OCULUSVR_SDK_PATH, " /"); | ||
| } | ||
|
|
||
| // If we still don't have the SDK path then let the user know. | ||
| if (!file_exists($OCULUSVR_SDK_PATH)) | ||
| { | ||
| trigger_error( | ||
| "\n*******************************************************************". | ||
| "\n". | ||
| "\n We were not able to find a valid path to the Oculus Rift SDK!". | ||
| "\n". | ||
| "\n You must install the latest Oculus VR SDK and set the path via a". | ||
| "\n \$OCULUSVR_SDK_PATH variable in your buildFiles/project.conf file". | ||
| "\n or by setting the TORQUE_OCULUSVR_PATH system environment variable". | ||
| "\n (may require a reboot).". | ||
| "\n". | ||
| "\n*******************************************************************". | ||
| "\n", E_USER_ERROR ); | ||
| } | ||
|
|
||
| // Only Windows is supported at this time | ||
| if ( Generator::$platform == "win32" ) | ||
| { | ||
| // Source | ||
| addEngineSrcDir( "platform/input/oculusVR" ); | ||
|
|
||
| // Includes | ||
| addIncludePath( $OCULUSVR_SDK_PATH . "/LibOVR/Include" ); | ||
| addIncludePath( $OCULUSVR_SDK_PATH . "/LibOVR/Src" ); | ||
|
|
||
| // Libs | ||
| addProjectLibDir( $OCULUSVR_SDK_PATH . "/LibOVR/Lib/Win32" ); | ||
| addProjectLibInput( "libovr.lib", "libovrd.lib" ); | ||
| } | ||
|
|
||
| endModule(); | ||
|
|
||
| ?> |