nuclear@0: /************************************************************************************ nuclear@0: nuclear@0: Filename : OVR_Stereo.h nuclear@0: Content : Stereo rendering functions nuclear@0: Created : November 30, 2013 nuclear@0: Authors : Tom Fosyth nuclear@0: nuclear@0: Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. nuclear@0: nuclear@0: Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); nuclear@0: you may not use the Oculus VR Rift SDK except in compliance with the License, nuclear@0: which is provided at the time of installation or download, or which nuclear@0: otherwise accompanies this software in either electronic or hard copy form. nuclear@0: nuclear@0: You may obtain a copy of the License at nuclear@0: nuclear@0: http://www.oculusvr.com/licenses/LICENSE-3.2 nuclear@0: nuclear@0: Unless required by applicable law or agreed to in writing, the Oculus VR SDK nuclear@0: distributed under the License is distributed on an "AS IS" BASIS, nuclear@0: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. nuclear@0: See the License for the specific language governing permissions and nuclear@0: limitations under the License. nuclear@0: nuclear@0: *************************************************************************************/ nuclear@0: nuclear@0: #ifndef OVR_Stereo_h nuclear@0: #define OVR_Stereo_h nuclear@0: nuclear@0: #include "Sensors/OVR_DeviceConstants.h" nuclear@0: #include "Displays/OVR_Display.h" nuclear@0: #include "OVR_Profile.h" nuclear@0: nuclear@0: // CAPI Forward declaration. nuclear@0: typedef struct ovrFovPort_ ovrFovPort; nuclear@0: typedef struct ovrRecti_ ovrRecti; nuclear@0: nuclear@0: namespace OVR { nuclear@0: nuclear@0: class SensorDevice; // Opaque forward declaration nuclear@0: nuclear@0: nuclear@0: //----------------------------------------------------------------------------------- nuclear@0: // ***** Stereo Enumerations nuclear@0: nuclear@0: // StereoEye specifies which eye we are rendering for; it is used to nuclear@0: // retrieve StereoEyeParams. nuclear@0: enum StereoEye nuclear@0: { nuclear@0: StereoEye_Center, nuclear@0: StereoEye_Left, nuclear@0: StereoEye_Right nuclear@0: }; nuclear@0: nuclear@0: nuclear@0: //----------------------------------------------------------------------------------- nuclear@0: // ***** FovPort nuclear@0: nuclear@0: // FovPort describes Field Of View (FOV) of a viewport. nuclear@0: // This class has values for up, down, left and right, stored in nuclear@0: // tangent of the angle units to simplify calculations. nuclear@0: // nuclear@0: // As an example, for a standard 90 degree vertical FOV, we would nuclear@0: // have: { UpTan = tan(90 degrees / 2), DownTan = tan(90 degrees / 2) }. nuclear@0: // nuclear@0: // CreateFromRadians/Degrees helper functions can be used to nuclear@0: // access FOV in different units. nuclear@0: nuclear@0: struct FovPort nuclear@0: { nuclear@0: float UpTan; nuclear@0: float DownTan; nuclear@0: float LeftTan; nuclear@0: float RightTan; nuclear@0: nuclear@0: FovPort ( float sideTan = 0.0f ) : nuclear@0: UpTan(sideTan), DownTan(sideTan), LeftTan(sideTan), RightTan(sideTan) { } nuclear@0: FovPort ( float u, float d, float l, float r ) : nuclear@0: UpTan(u), DownTan(d), LeftTan(l), RightTan(r) { } nuclear@0: nuclear@0: // C-interop support: FovPort <-> ovrFovPort (implementation in OVR_CAPI.cpp). nuclear@0: FovPort(const ovrFovPort& src); nuclear@0: operator ovrFovPort () const; nuclear@0: nuclear@0: static FovPort CreateFromRadians(float horizontalFov, float verticalFov) nuclear@0: { nuclear@0: FovPort result; nuclear@0: result.UpTan = tanf ( verticalFov * 0.5f ); nuclear@0: result.DownTan = tanf ( verticalFov * 0.5f ); nuclear@0: result.LeftTan = tanf ( horizontalFov * 0.5f ); nuclear@0: result.RightTan = tanf ( horizontalFov * 0.5f ); nuclear@0: return result; nuclear@0: } nuclear@0: nuclear@0: static FovPort CreateFromDegrees(float horizontalFovDegrees, nuclear@0: float verticalFovDegrees) nuclear@0: { nuclear@0: return CreateFromRadians(DegreeToRad(horizontalFovDegrees), nuclear@0: DegreeToRad(verticalFovDegrees)); nuclear@0: } nuclear@0: nuclear@0: // Get Horizontal/Vertical components of Fov in radians. nuclear@0: float GetVerticalFovRadians() const { return atanf(UpTan) + atanf(DownTan); } nuclear@0: float GetHorizontalFovRadians() const { return atanf(LeftTan) + atanf(RightTan); } nuclear@0: // Get Horizontal/Vertical components of Fov in degrees. nuclear@0: float GetVerticalFovDegrees() const { return RadToDegree(GetVerticalFovRadians()); } nuclear@0: float GetHorizontalFovDegrees() const { return RadToDegree(GetHorizontalFovRadians()); } nuclear@0: nuclear@0: // Compute maximum tangent value among all four sides. nuclear@0: float GetMaxSideTan() const nuclear@0: { nuclear@0: return Alg::Max(Alg::Max(UpTan, DownTan), Alg::Max(LeftTan, RightTan)); nuclear@0: } nuclear@0: nuclear@0: // Converts Fov Tan angle units to [-1,1] render target NDC space nuclear@0: Vector2f TanAngleToRendertargetNDC(Vector2f const &tanEyeAngle); nuclear@0: nuclear@0: nuclear@0: // Compute per-channel minimum and maximum of Fov. nuclear@0: static FovPort Min(const FovPort& a, const FovPort& b) nuclear@0: { nuclear@0: FovPort fov( Alg::Min( a.UpTan , b.UpTan ), nuclear@0: Alg::Min( a.DownTan , b.DownTan ), nuclear@0: Alg::Min( a.LeftTan , b.LeftTan ), nuclear@0: Alg::Min( a.RightTan, b.RightTan ) ); nuclear@0: return fov; nuclear@0: } nuclear@0: nuclear@0: static FovPort Max(const FovPort& a, const FovPort& b) nuclear@0: { nuclear@0: FovPort fov( Alg::Max( a.UpTan , b.UpTan ), nuclear@0: Alg::Max( a.DownTan , b.DownTan ), nuclear@0: Alg::Max( a.LeftTan , b.LeftTan ), nuclear@0: Alg::Max( a.RightTan, b.RightTan ) ); nuclear@0: return fov; nuclear@0: } nuclear@0: }; nuclear@0: nuclear@0: nuclear@0: //----------------------------------------------------------------------------------- nuclear@0: // ***** ScaleAndOffset nuclear@0: nuclear@0: struct ScaleAndOffset2D nuclear@0: { nuclear@0: Vector2f Scale; nuclear@0: Vector2f Offset; nuclear@0: nuclear@0: ScaleAndOffset2D(float sx = 0.0f, float sy = 0.0f, float ox = 0.0f, float oy = 0.0f) nuclear@0: : Scale(sx, sy), Offset(ox, oy) nuclear@0: { } nuclear@0: }; nuclear@0: nuclear@0: nuclear@0: //----------------------------------------------------------------------------------- nuclear@0: // ***** Misc. utility functions. nuclear@0: nuclear@0: // Inputs are 4 points (pFitX[0],pFitY[0]) through (pFitX[3],pFitY[3]) nuclear@0: // Result is four coefficients in pResults[0] through pResults[3] such that nuclear@0: // y = pResult[0] + x * ( pResult[1] + x * ( pResult[2] + x * ( pResult[3] ) ) ); nuclear@0: // passes through all four input points. nuclear@0: // Return is true if it succeeded, false if it failed (because two control points nuclear@0: // have the same pFitX value). nuclear@0: bool FitCubicPolynomial ( float *pResult, const float *pFitX, const float *pFitY ); nuclear@0: nuclear@0: //----------------------------------------------------------------------------------- nuclear@0: // ***** LensConfig nuclear@0: nuclear@0: // LensConfig describes the configuration of a single lens in an HMD. nuclear@0: // - Eqn and K[] describe a distortion function. nuclear@0: // - MetersPerTanAngleAtCenter is the relationship between distance on a nuclear@0: // screen (at the center of the lens), and the angle variance of the light after it nuclear@0: // has passed through the lens. nuclear@0: // - ChromaticAberration is an array of parameters for controlling nuclear@0: // additional Red and Blue scaling in order to reduce chromatic aberration nuclear@0: // caused by the Rift lenses. nuclear@0: struct LensConfig nuclear@0: { nuclear@0: LensConfig() nuclear@0: : Eqn(Distortion_CatmullRom10) nuclear@0: //K() nuclear@0: , MaxR(0.0f) nuclear@0: , MetersPerTanAngleAtCenter(0.0f) nuclear@0: //ChromaticAberration() nuclear@0: //InvK() nuclear@0: , MaxInvR(0.0f) nuclear@0: { nuclear@0: memset(&K, 0, sizeof(K)); nuclear@0: memset(&ChromaticAberration, 0, sizeof(ChromaticAberration)); nuclear@0: memset(&InvK, 0, sizeof(InvK)); nuclear@0: } nuclear@0: nuclear@0: // The result is a scaling applied to the distance from the center of the lens. nuclear@0: float DistortionFnScaleRadiusSquared (float rsq) const; nuclear@0: // x,y,z components map to r,g,b scales. nuclear@0: Vector3f DistortionFnScaleRadiusSquaredChroma (float rsq) const; nuclear@0: nuclear@0: // DistortionFn applies distortion to the argument. nuclear@0: // Input: the distance in TanAngle/NIC space from the optical center to the input pixel. nuclear@0: // Output: the resulting distance after distortion. nuclear@0: float DistortionFn(float r) const nuclear@0: { nuclear@0: return r * DistortionFnScaleRadiusSquared ( r * r ); nuclear@0: } nuclear@0: nuclear@0: // DistortionFnInverse computes the inverse of the distortion function on an argument. nuclear@0: float DistortionFnInverse(float r) const; nuclear@0: nuclear@0: // Also computes the inverse, but using a polynomial approximation. Warning - it's just an approximation! nuclear@0: float DistortionFnInverseApprox(float r) const; nuclear@0: // Sets up InvK[]. nuclear@0: void SetUpInverseApprox(); nuclear@0: nuclear@0: // Sets a bunch of sensible defaults. nuclear@0: void SetToIdentity(); nuclear@0: nuclear@0: nuclear@0: nuclear@0: enum { NumCoefficients = 11 }; nuclear@0: nuclear@0: DistortionEqnType Eqn; nuclear@0: float K[NumCoefficients]; nuclear@0: float MaxR; // The highest R you're going to query for - the curve is unpredictable beyond it. nuclear@0: nuclear@0: float MetersPerTanAngleAtCenter; nuclear@0: nuclear@0: // Additional per-channel scaling is applied after distortion: nuclear@0: // Index [0] - Red channel constant coefficient. nuclear@0: // Index [1] - Red channel r^2 coefficient. nuclear@0: // Index [2] - Blue channel constant coefficient. nuclear@0: // Index [3] - Blue channel r^2 coefficient. nuclear@0: float ChromaticAberration[4]; nuclear@0: nuclear@0: float InvK[NumCoefficients]; nuclear@0: float MaxInvR; nuclear@0: }; nuclear@0: nuclear@0: nuclear@0: // For internal use - storing and loading lens config data nuclear@0: nuclear@0: // Returns true on success. nuclear@0: bool LoadLensConfig ( LensConfig *presult, uint8_t const *pbuffer, int bufferSizeInBytes ); nuclear@0: nuclear@0: // Returns number of bytes needed. nuclear@0: int SaveLensConfigSizeInBytes ( LensConfig const &config ); nuclear@0: // Returns true on success. nuclear@0: bool SaveLensConfig ( uint8_t *pbuffer, int bufferSizeInBytes, LensConfig const &config ); nuclear@0: nuclear@0: nuclear@0: //----------------------------------------------------------------------------------- nuclear@0: // ***** DistortionRenderDesc nuclear@0: nuclear@0: // This describes distortion for a single eye in an HMD with a display, not just the lens by itself. nuclear@0: struct DistortionRenderDesc nuclear@0: { nuclear@0: // The raw lens values. nuclear@0: LensConfig Lens; nuclear@0: nuclear@0: // These map from [-1,1] across the eye being rendered into TanEyeAngle space (but still distorted) nuclear@0: Vector2f LensCenter; nuclear@0: Vector2f TanEyeAngleScale; nuclear@0: // Computed from device characteristics, IPD and eye-relief. nuclear@0: // (not directly used for rendering, but very useful) nuclear@0: Vector2f PixelsPerTanAngleAtCenter; nuclear@0: }; nuclear@0: nuclear@0: nuclear@0: //------------------------------------------------------------------------------------- nuclear@0: // ***** HMDInfo nuclear@0: nuclear@0: // This structure describes various aspects of the HMD allowing us to configure rendering. nuclear@0: // nuclear@0: // Currently included data: nuclear@0: // - Physical screen dimensions, resolution, and eye distances. nuclear@0: // (some of these will be configurable with a tool in the future). nuclear@0: // These arguments allow us to properly setup projection across HMDs. nuclear@0: // - DisplayDeviceName for identifying HMD screen; system-specific interpretation. nuclear@0: // nuclear@0: // TBD: nuclear@0: // - Power on/ off? nuclear@0: // - Sensor rates and capabilities nuclear@0: // - Distortion radius/variables nuclear@0: // - Screen update frequency nuclear@0: // - Distortion needed flag nuclear@0: // - Update modes: nuclear@0: // Set update mode: Stereo (both sides together), mono (same in both eyes), nuclear@0: // Alternating, Alternating scan-lines. nuclear@0: nuclear@0: // Win32 Oculus VR Display Driver Shim Information nuclear@0: struct Win32ShimInfo nuclear@0: { nuclear@0: int DeviceNumber; nuclear@0: int NativeWidth; nuclear@0: int NativeHeight; nuclear@0: int Rotation; nuclear@0: int UseMirroring; nuclear@0: nuclear@0: Win32ShimInfo() : nuclear@0: DeviceNumber(-1), nuclear@0: NativeWidth(-1), nuclear@0: NativeHeight(-1), nuclear@0: Rotation(-1), nuclear@0: UseMirroring(1) nuclear@0: { nuclear@0: } nuclear@0: }; nuclear@0: nuclear@0: class HMDInfo nuclear@0: { nuclear@0: public: nuclear@0: // Name string describing the product: "Oculus Rift DK1", etc. nuclear@0: String ProductName; nuclear@0: String Manufacturer; nuclear@0: nuclear@0: unsigned Version; nuclear@0: nuclear@0: // Characteristics of the HMD screen and enclosure nuclear@0: HmdTypeEnum HmdType; nuclear@0: Size ResolutionInPixels; nuclear@0: Size ScreenSizeInMeters; nuclear@0: float ScreenGapSizeInMeters; nuclear@0: float CenterFromTopInMeters; nuclear@0: float LensSeparationInMeters; nuclear@0: Vector2f PelOffsetR; // Offsets from the green pel in pixels (i.e. usual values are 0.5 or 0.333) nuclear@0: Vector2f PelOffsetB; nuclear@0: nuclear@0: nuclear@0: // Timing & shutter data. All values in seconds. nuclear@0: struct ShutterInfo nuclear@0: { nuclear@0: HmdShutterTypeEnum Type; nuclear@0: float VsyncToNextVsync; // 1/framerate nuclear@0: float VsyncToFirstScanline; // for global shutter, vsync->shutter open. nuclear@0: float FirstScanlineToLastScanline; // for global shutter, will be zero. nuclear@0: float PixelSettleTime; // estimated. nuclear@0: float PixelPersistence; // Full persistence = 1/framerate. nuclear@0: } Shutter; nuclear@0: nuclear@0: // Desktop coordinate position of the screen (can be negative; may not be present on all platforms) nuclear@0: int DesktopX; nuclear@0: int DesktopY; nuclear@0: nuclear@0: // Windows: nuclear@0: // "\\\\.\\DISPLAY3", etc. Can be used in EnumDisplaySettings/CreateDC. nuclear@0: String DisplayDeviceName; nuclear@0: Win32ShimInfo ShimInfo; nuclear@0: nuclear@0: // MacOS: nuclear@0: int DisplayId; nuclear@0: nuclear@0: bool InCompatibilityMode; nuclear@0: nuclear@0: // Printed serial number for the HMD; should match external sticker nuclear@0: String PrintedSerial; nuclear@0: nuclear@0: // Tracker descriptor information: nuclear@0: int VendorId; nuclear@0: int ProductId; nuclear@0: int FirmwareMajor; nuclear@0: int FirmwareMinor; nuclear@0: nuclear@0: float CameraFrustumHFovInRadians; nuclear@0: float CameraFrustumVFovInRadians; nuclear@0: float CameraFrustumNearZInMeters; nuclear@0: float CameraFrustumFarZInMeters; nuclear@0: nuclear@0: // Constructor initializes all values to 0s. nuclear@0: // To create a "virtualized" HMDInfo, use CreateDebugHMDInfo instead. nuclear@0: HMDInfo() : nuclear@0: ProductName(), nuclear@0: Manufacturer(), nuclear@0: Version(0), nuclear@0: HmdType(HmdType_None), nuclear@0: ResolutionInPixels(0), nuclear@0: ScreenSizeInMeters(0.0f), nuclear@0: ScreenGapSizeInMeters(0.0f), nuclear@0: CenterFromTopInMeters(0), nuclear@0: LensSeparationInMeters(0), nuclear@0: PelOffsetR(0.0f,0.0f), nuclear@0: PelOffsetB(0.0f,0.0f), nuclear@0: //Shutter (initialized below) nuclear@0: DesktopX(0), nuclear@0: DesktopY(0), nuclear@0: DisplayDeviceName(), nuclear@0: ShimInfo(), nuclear@0: DisplayId(-1), nuclear@0: InCompatibilityMode(false), nuclear@0: PrintedSerial(), nuclear@0: VendorId(-1), nuclear@0: ProductId(-1), nuclear@0: FirmwareMajor(-1), nuclear@0: FirmwareMinor(-1), nuclear@0: CameraFrustumHFovInRadians(0.0f), nuclear@0: CameraFrustumVFovInRadians(0.0f), nuclear@0: CameraFrustumNearZInMeters(0.0f), nuclear@0: CameraFrustumFarZInMeters(0.0f) nuclear@0: { nuclear@0: Shutter.Type = HmdShutter_LAST; nuclear@0: Shutter.VsyncToNextVsync = 0.0f; nuclear@0: Shutter.VsyncToFirstScanline = 0.0f; nuclear@0: Shutter.FirstScanlineToLastScanline = 0.0f; nuclear@0: Shutter.PixelSettleTime = 0.0f; nuclear@0: Shutter.PixelPersistence = 0.0f; nuclear@0: } nuclear@0: nuclear@0: // Operator = copies local fields only (base class must be correct already) nuclear@0: void operator=(const HMDInfo& src) nuclear@0: { nuclear@0: ProductName = src.ProductName; nuclear@0: Manufacturer = src.Manufacturer; nuclear@0: Version = src.Version; nuclear@0: HmdType = src.HmdType; nuclear@0: ResolutionInPixels = src.ResolutionInPixels; nuclear@0: ScreenSizeInMeters = src.ScreenSizeInMeters; nuclear@0: ScreenGapSizeInMeters = src.ScreenGapSizeInMeters; nuclear@0: CenterFromTopInMeters = src.CenterFromTopInMeters; nuclear@0: LensSeparationInMeters = src.LensSeparationInMeters; nuclear@0: PelOffsetR = src.PelOffsetR; nuclear@0: PelOffsetB = src.PelOffsetB; nuclear@0: DesktopX = src.DesktopX; nuclear@0: DesktopY = src.DesktopY; nuclear@0: Shutter = src.Shutter; nuclear@0: DisplayDeviceName = src.DisplayDeviceName; nuclear@0: ShimInfo = src.ShimInfo; nuclear@0: DisplayId = src.DisplayId; nuclear@0: InCompatibilityMode = src.InCompatibilityMode; nuclear@0: VendorId = src.VendorId; nuclear@0: ProductId = src.ProductId; nuclear@0: FirmwareMajor = src.FirmwareMajor; nuclear@0: FirmwareMinor = src.FirmwareMinor; nuclear@0: PrintedSerial = src.PrintedSerial; nuclear@0: CameraFrustumHFovInRadians = src.CameraFrustumHFovInRadians; nuclear@0: CameraFrustumVFovInRadians = src.CameraFrustumVFovInRadians; nuclear@0: CameraFrustumNearZInMeters = src.CameraFrustumNearZInMeters; nuclear@0: CameraFrustumFarZInMeters = src.CameraFrustumFarZInMeters; nuclear@0: } nuclear@0: nuclear@0: void SetScreenParameters(int hres, int vres, nuclear@0: float hsize, float vsize, nuclear@0: float vCenterFromTopInMeters, float lensSeparationInMeters, nuclear@0: bool compatibilityMode) nuclear@0: { nuclear@0: ResolutionInPixels = Sizei(hres, vres); nuclear@0: ScreenSizeInMeters = Sizef(hsize, vsize); nuclear@0: CenterFromTopInMeters = vCenterFromTopInMeters; nuclear@0: LensSeparationInMeters = lensSeparationInMeters; nuclear@0: InCompatibilityMode = compatibilityMode; nuclear@0: } nuclear@0: nuclear@0: bool IsSameDisplay(const HMDInfo& o) const nuclear@0: { nuclear@0: return DisplayId == o.DisplayId && nuclear@0: DisplayDeviceName.CompareNoCase(o.DisplayDeviceName) == 0; nuclear@0: } nuclear@0: nuclear@0: static bool CreateFromSensorAndDisplay(SensorDevice* sensor, Display* display, HMDInfo* hmdi); nuclear@0: }; nuclear@0: nuclear@0: nuclear@0: //----------------------------------------------------------------------------------- nuclear@0: // ***** HmdRenderInfo nuclear@0: nuclear@0: // All the parts of the HMD info that are needed to set up the rendering system. nuclear@0: nuclear@0: struct HmdRenderInfo nuclear@0: { nuclear@0: // The start of this structure is intentionally very similar to HMDInfo in OVER_Device.h nuclear@0: // However to reduce interdependencies, one does not simply #include the other. nuclear@0: nuclear@0: HmdTypeEnum HmdType; nuclear@0: nuclear@0: // Size of the entire screen nuclear@0: Size ResolutionInPixels; nuclear@0: Size ScreenSizeInMeters; nuclear@0: float ScreenGapSizeInMeters; nuclear@0: Vector2f PelOffsetR; // Offsets from the green pel in pixels (i.e. usual values are 0.5 or 0.333) nuclear@0: Vector2f PelOffsetB; nuclear@0: nuclear@0: // Characteristics of the lenses. nuclear@0: float CenterFromTopInMeters; nuclear@0: float LensSeparationInMeters; nuclear@0: float LensDiameterInMeters; nuclear@0: float LensSurfaceToMidplateInMeters; nuclear@0: EyeCupType EyeCups; nuclear@0: nuclear@0: // Timing & shutter data. All values in seconds. nuclear@0: struct ShutterInfo nuclear@0: { nuclear@0: HmdShutterTypeEnum Type; nuclear@0: float VsyncToNextVsync; // 1/framerate nuclear@0: float VsyncToFirstScanline; // for global shutter, vsync->shutter open. nuclear@0: float FirstScanlineToLastScanline; // for global shutter, will be zero. nuclear@0: float PixelSettleTime; // estimated. nuclear@0: float PixelPersistence; // Full persistence = 1/framerate. nuclear@0: } Shutter; nuclear@0: nuclear@0: nuclear@0: // These are all set from the user's profile. nuclear@0: struct EyeConfig nuclear@0: { nuclear@0: // Distance from center of eyeball to front plane of lens. nuclear@0: float ReliefInMeters; nuclear@0: // Distance from nose (technically, center of Rift) to the middle of the eye. nuclear@0: float NoseToPupilInMeters; nuclear@0: nuclear@0: LensConfig Distortion; nuclear@0: } EyeLeft, EyeRight; nuclear@0: nuclear@0: nuclear@0: HmdRenderInfo() nuclear@0: { nuclear@0: HmdType = HmdType_None; nuclear@0: ResolutionInPixels.w = 0; nuclear@0: ResolutionInPixels.h = 0; nuclear@0: ScreenSizeInMeters.w = 0.0f; nuclear@0: ScreenSizeInMeters.h = 0.0f; nuclear@0: ScreenGapSizeInMeters = 0.0f; nuclear@0: CenterFromTopInMeters = 0.0f; nuclear@0: LensSeparationInMeters = 0.0f; nuclear@0: LensDiameterInMeters = 0.0f; nuclear@0: LensSurfaceToMidplateInMeters = 0.0f; nuclear@0: PelOffsetR = Vector2f ( 0.0f, 0.0f ); nuclear@0: PelOffsetB = Vector2f ( 0.0f, 0.0f ); nuclear@0: Shutter.Type = HmdShutter_LAST; nuclear@0: Shutter.VsyncToNextVsync = 0.0f; nuclear@0: Shutter.VsyncToFirstScanline = 0.0f; nuclear@0: Shutter.FirstScanlineToLastScanline = 0.0f; nuclear@0: Shutter.PixelSettleTime = 0.0f; nuclear@0: Shutter.PixelPersistence = 0.0f; nuclear@0: EyeCups = EyeCup_DK1A; nuclear@0: EyeLeft.ReliefInMeters = 0.0f; nuclear@0: EyeLeft.NoseToPupilInMeters = 0.0f; nuclear@0: EyeLeft.Distortion.SetToIdentity(); nuclear@0: EyeRight = EyeLeft; nuclear@0: } nuclear@0: nuclear@0: // The "center eye" is the position the HMD tracking returns, nuclear@0: // and games will also usually use it for audio, aiming reticles, some line-of-sight tests, etc. nuclear@0: EyeConfig GetEyeCenter() const nuclear@0: { nuclear@0: EyeConfig result; nuclear@0: result.ReliefInMeters = 0.5f * ( EyeLeft.ReliefInMeters + EyeRight.ReliefInMeters ); nuclear@0: result.NoseToPupilInMeters = 0.0f; nuclear@0: result.Distortion.SetToIdentity(); nuclear@0: return result; nuclear@0: } nuclear@0: nuclear@0: }; nuclear@0: nuclear@0: nuclear@0: //----------------------------------------------------------------------------------- nuclear@0: nuclear@0: // Stateless computation functions, in somewhat recommended execution order. nuclear@0: // For examples on how to use many of them, see the StereoConfig::UpdateComputedState function. nuclear@0: nuclear@0: const float OVR_DEFAULT_EXTRA_EYE_ROTATION = 30.0f * MATH_FLOAT_DEGREETORADFACTOR; nuclear@0: nuclear@0: // Creates a dummy debug HMDInfo matching a particular HMD model. nuclear@0: // Useful for development without an actual HMD attached. nuclear@0: HMDInfo CreateDebugHMDInfo(HmdTypeEnum hmdType); nuclear@0: nuclear@0: nuclear@0: // profile may be NULL, in which case it uses the hard-coded defaults. nuclear@0: // distortionType should be left at the default unless you require something specific for your distortion shaders. nuclear@0: // eyeCupOverride can be EyeCup_LAST, in which case it uses the one in the profile. nuclear@0: HmdRenderInfo GenerateHmdRenderInfoFromHmdInfo ( HMDInfo const &hmdInfo, nuclear@0: Profile const *profile = NULL, nuclear@0: DistortionEqnType distortionType = Distortion_CatmullRom10, nuclear@0: EyeCupType eyeCupOverride = EyeCup_LAST ); nuclear@0: nuclear@0: LensConfig GenerateLensConfigFromEyeRelief ( float eyeReliefInMeters, HmdRenderInfo const &hmd, nuclear@0: DistortionEqnType distortionType = Distortion_CatmullRom10 ); nuclear@0: nuclear@0: DistortionRenderDesc CalculateDistortionRenderDesc ( StereoEye eyeType, HmdRenderInfo const &hmd, nuclear@0: LensConfig const *pLensOverride = NULL ); nuclear@0: nuclear@0: FovPort CalculateFovFromEyePosition ( float eyeReliefInMeters, nuclear@0: float offsetToRightInMeters, nuclear@0: float offsetDownwardsInMeters, nuclear@0: float lensDiameterInMeters, nuclear@0: float extraEyeRotationInRadians = OVR_DEFAULT_EXTRA_EYE_ROTATION); nuclear@0: nuclear@0: FovPort CalculateFovFromHmdInfo ( StereoEye eyeType, nuclear@0: DistortionRenderDesc const &distortion, nuclear@0: HmdRenderInfo const &hmd, nuclear@0: float extraEyeRotationInRadians = OVR_DEFAULT_EXTRA_EYE_ROTATION ); nuclear@0: nuclear@0: FovPort GetPhysicalScreenFov ( StereoEye eyeType, DistortionRenderDesc const &distortion ); nuclear@0: nuclear@0: FovPort ClampToPhysicalScreenFov ( StereoEye eyeType, DistortionRenderDesc const &distortion, nuclear@0: FovPort inputFovPort ); nuclear@0: nuclear@0: Sizei CalculateIdealPixelSize ( StereoEye eyeType, DistortionRenderDesc const &distortion, nuclear@0: FovPort fov, float pixelsPerDisplayPixel ); nuclear@0: nuclear@0: Recti GetFramebufferViewport ( StereoEye eyeType, HmdRenderInfo const &hmd ); nuclear@0: nuclear@0: Matrix4f CreateProjection ( bool rightHanded, FovPort fov, nuclear@0: float zNear = 0.01f, float zFar = 10000.0f ); nuclear@0: nuclear@0: Matrix4f CreateOrthoSubProjection ( bool rightHanded, StereoEye eyeType, nuclear@0: float tanHalfFovX, float tanHalfFovY, nuclear@0: float unitsX, float unitsY, float distanceFromCamera, nuclear@0: float interpupillaryDistance, Matrix4f const &projection, nuclear@0: float zNear = 0.0f, float zFar = 0.0f ); nuclear@0: nuclear@0: ScaleAndOffset2D CreateNDCScaleAndOffsetFromFov ( FovPort fov ); nuclear@0: nuclear@0: ScaleAndOffset2D CreateUVScaleAndOffsetfromNDCScaleandOffset ( ScaleAndOffset2D scaleAndOffsetNDC, nuclear@0: Recti renderedViewport, nuclear@0: Sizei renderTargetSize ); nuclear@0: nuclear@0: nuclear@0: //----------------------------------------------------------------------------------- nuclear@0: // ***** StereoEyeParams nuclear@0: nuclear@0: // StereoEyeParams describes RenderDevice configuration needed to render nuclear@0: // the scene for one eye. nuclear@0: struct StereoEyeParams nuclear@0: { nuclear@0: StereoEye Eye; nuclear@0: Matrix4f HmdToEyeViewOffset; // Translation to be applied to view matrix. nuclear@0: nuclear@0: // Distortion and the VP on the physical display - the thing to run the distortion shader on. nuclear@0: DistortionRenderDesc Distortion; nuclear@0: Recti DistortionViewport; nuclear@0: nuclear@0: // Projection and VP of a particular view (you could have multiple of these). nuclear@0: Recti RenderedViewport; // Viewport that we render the standard scene to. nuclear@0: FovPort Fov; // The FOVs of this scene. nuclear@0: Matrix4f RenderedProjection; // Projection matrix used with this eye. nuclear@0: ScaleAndOffset2D EyeToSourceNDC; // Mapping from TanEyeAngle space to [-1,+1] on the rendered image. nuclear@0: ScaleAndOffset2D EyeToSourceUV; // Mapping from TanEyeAngle space to actual texture UV coords. nuclear@0: }; nuclear@0: nuclear@0: nuclear@0: //----------------------------------------------------------------------------------- nuclear@0: // A set of "forward-mapping" functions, mapping from framebuffer space to real-world and/or texture space. nuclear@0: Vector2f TransformScreenNDCToTanFovSpace ( DistortionRenderDesc const &distortion, nuclear@0: const Vector2f &framebufferNDC ); nuclear@0: void TransformScreenNDCToTanFovSpaceChroma ( Vector2f *resultR, Vector2f *resultG, Vector2f *resultB, nuclear@0: DistortionRenderDesc const &distortion, nuclear@0: const Vector2f &framebufferNDC ); nuclear@0: Vector2f TransformTanFovSpaceToRendertargetTexUV ( ScaleAndOffset2D const &eyeToSourceUV, nuclear@0: Vector2f const &tanEyeAngle ); nuclear@0: Vector2f TransformTanFovSpaceToRendertargetNDC ( ScaleAndOffset2D const &eyeToSourceNDC, nuclear@0: Vector2f const &tanEyeAngle ); nuclear@0: Vector2f TransformScreenPixelToScreenNDC( Recti const &distortionViewport, nuclear@0: Vector2f const &pixel ); nuclear@0: Vector2f TransformScreenPixelToTanFovSpace ( Recti const &distortionViewport, nuclear@0: DistortionRenderDesc const &distortion, nuclear@0: Vector2f const &pixel ); nuclear@0: Vector2f TransformScreenNDCToRendertargetTexUV( DistortionRenderDesc const &distortion, nuclear@0: StereoEyeParams const &eyeParams, nuclear@0: Vector2f const &pixel ); nuclear@0: Vector2f TransformScreenPixelToRendertargetTexUV( Recti const &distortionViewport, nuclear@0: DistortionRenderDesc const &distortion, nuclear@0: StereoEyeParams const &eyeParams, nuclear@0: Vector2f const &pixel ); nuclear@0: nuclear@0: // A set of "reverse-mapping" functions, mapping from real-world and/or texture space back to the framebuffer. nuclear@0: // Be aware that many of these are significantly slower than their forward-mapping counterparts. nuclear@0: Vector2f TransformTanFovSpaceToScreenNDC( DistortionRenderDesc const &distortion, nuclear@0: const Vector2f &tanEyeAngle, bool usePolyApprox = false ); nuclear@0: Vector2f TransformRendertargetNDCToTanFovSpace( const ScaleAndOffset2D &eyeToSourceNDC, nuclear@0: const Vector2f &textureNDC ); nuclear@0: nuclear@0: // Handy wrappers. nuclear@0: inline Vector2f TransformTanFovSpaceToRendertargetTexUV ( StereoEyeParams const &eyeParams, nuclear@0: Vector2f const &tanEyeAngle ) nuclear@0: { nuclear@0: return TransformTanFovSpaceToRendertargetTexUV ( eyeParams.EyeToSourceUV, tanEyeAngle ); nuclear@0: } nuclear@0: inline Vector2f TransformTanFovSpaceToRendertargetNDC ( StereoEyeParams const &eyeParams, nuclear@0: Vector2f const &tanEyeAngle ) nuclear@0: { nuclear@0: return TransformTanFovSpaceToRendertargetNDC ( eyeParams.EyeToSourceNDC, tanEyeAngle ); nuclear@0: } nuclear@0: nuclear@0: } //namespace OVR nuclear@0: nuclear@0: #endif // OVR_Stereo_h