diff options
Diffstat (limited to 'LibOVR/Src/OVR_Stereo.cpp')
-rw-r--r-- | LibOVR/Src/OVR_Stereo.cpp | 243 |
1 files changed, 140 insertions, 103 deletions
diff --git a/LibOVR/Src/OVR_Stereo.cpp b/LibOVR/Src/OVR_Stereo.cpp index 936a02a..5f4cae3 100644 --- a/LibOVR/Src/OVR_Stereo.cpp +++ b/LibOVR/Src/OVR_Stereo.cpp @@ -81,12 +81,43 @@ bool FitCubicPolynomial ( float *pResult, const float *pFitX, const float *pFitY return true; } - +#define TPH_SPLINE_STATISTICS 0 +#if TPH_SPLINE_STATISTICS +static float max_scaledVal = 0; +static float average_total_out_of_range = 0; +static float average_out_of_range; +static int num_total = 0; +static int num_out_of_range = 0; +static int num_out_of_range_over_1 = 0; +static int num_out_of_range_over_2 = 0; +static int num_out_of_range_over_3 = 0; +static float percent_out_of_range; +#endif float EvalCatmullRom10Spline ( float const *K, float scaledVal ) { int const NumSegments = LensConfig::NumCoefficients; + #if TPH_SPLINE_STATISTICS + //Value should be in range of 0 to (NumSegments-1) (typically 10) if spline is valid. Right? + if (scaledVal > (NumSegments-1)) + { + num_out_of_range++; + average_total_out_of_range+=scaledVal; + average_out_of_range = average_total_out_of_range / ((float) num_out_of_range); + percent_out_of_range = 100.0f*(num_out_of_range)/num_total; + } + if (scaledVal > (NumSegments-1+1)) num_out_of_range_over_1++; + if (scaledVal > (NumSegments-1+2)) num_out_of_range_over_2++; + if (scaledVal > (NumSegments-1+3)) num_out_of_range_over_3++; + num_total++; + if (scaledVal > max_scaledVal) + { + max_scaledVal = scaledVal; + max_scaledVal = scaledVal; + } + #endif + float scaledValFloor = floorf ( scaledVal ); scaledValFloor = Alg::Max ( 0.0f, Alg::Min ( (float)(NumSegments-1), scaledValFloor ) ); float t = scaledVal - scaledValFloor; @@ -401,26 +432,26 @@ enum LensConfigStoredVersion struct LensConfigStored_CatmullRom10Version1 { // All these items must be fixed-length integers - no "float", no "int", etc. - UInt16 VersionNumber; // Must be LCSV_CatmullRom10Version1 + uint16_t VersionNumber; // Must be LCSV_CatmullRom10Version1 - UInt16 K[11]; - UInt16 MaxR; - UInt16 MetersPerTanAngleAtCenter; - UInt16 ChromaticAberration[4]; + uint16_t K[11]; + uint16_t MaxR; + uint16_t MetersPerTanAngleAtCenter; + uint16_t ChromaticAberration[4]; // InvK and MaxInvR are calculated on load. }; -UInt16 EncodeFixedPointUInt16 ( float val, UInt16 zeroVal, int fractionalBits ) +uint16_t EncodeFixedPointUInt16 ( float val, uint16_t zeroVal, int fractionalBits ) { OVR_ASSERT ( ( fractionalBits >= 0 ) && ( fractionalBits < 31 ) ); float valWhole = val * (float)( 1 << fractionalBits ); valWhole += (float)zeroVal + 0.5f; valWhole = floorf ( valWhole ); OVR_ASSERT ( ( valWhole >= 0.0f ) && ( valWhole < (float)( 1 << 16 ) ) ); - return (UInt16)valWhole; + return (uint16_t)valWhole; } -float DecodeFixedPointUInt16 ( UInt16 val, UInt16 zeroVal, int fractionalBits ) +float DecodeFixedPointUInt16 ( uint16_t val, uint16_t zeroVal, int fractionalBits ) { OVR_ASSERT ( ( fractionalBits >= 0 ) && ( fractionalBits < 31 ) ); float valFloat = (float)val; @@ -431,14 +462,14 @@ float DecodeFixedPointUInt16 ( UInt16 val, UInt16 zeroVal, int fractionalBits ) // Returns true on success. -bool LoadLensConfig ( LensConfig *presult, UByte const *pbuffer, int bufferSizeInBytes ) +bool LoadLensConfig ( LensConfig *presult, uint8_t const *pbuffer, int bufferSizeInBytes ) { if ( bufferSizeInBytes < 2 ) { // Can't even tell the version number! return false; } - UInt16 version = DecodeUInt16 ( pbuffer + 0 ); + uint16_t version = DecodeUInt16 ( pbuffer + 0 ); switch ( version ) { case LCSV_CatmullRom10Version1: @@ -504,7 +535,7 @@ int SaveLensConfigSizeInBytes ( LensConfig const &config ) } // Returns true on success. -bool SaveLensConfig ( UByte *pbuffer, int bufferSizeInBytes, LensConfig const &config ) +bool SaveLensConfig ( uint8_t *pbuffer, int bufferSizeInBytes, LensConfig const &config ) { if ( bufferSizeInBytes < (int)sizeof ( LensConfigStored_CatmullRom10Version1 ) ) { @@ -532,7 +563,7 @@ bool SaveLensConfig ( UByte *pbuffer, int bufferSizeInBytes, LensConfig const &c } - // Now store them out, sensitive to endinness. + // Now store them out, sensitive to endianness. EncodeUInt16 ( pbuffer + 0, lcs.VersionNumber ); for ( int i = 0; i < 11; i++ ) { @@ -555,7 +586,7 @@ void TestSaveLoadLensConfig ( LensConfig const &config ) OVR_ASSERT ( config.Eqn == Distortion_CatmullRom10 ); // As a test, make sure this can be encoded and decoded correctly. const int bufferSize = 256; - UByte buffer[bufferSize]; + uint8_t buffer[bufferSize]; OVR_ASSERT ( SaveLensConfigSizeInBytes ( config ) < bufferSize ); bool success; success = SaveLensConfig ( buffer, bufferSize, config ); @@ -590,7 +621,8 @@ HMDInfo CreateDebugHMDInfo(HmdTypeEnum hmdType) HMDInfo info; if ((hmdType != HmdType_DK1) && - (hmdType != HmdType_CrystalCoveProto)) + (hmdType != HmdType_CrystalCoveProto) && + (hmdType != HmdType_DK2)) { LogText("Debug HMDInfo - HmdType not supported. Defaulting to DK1.\n"); hmdType = HmdType_DK1; @@ -656,14 +688,14 @@ HMDInfo CreateDebugHMDInfo(HmdTypeEnum hmdType) return info; } - - // profile may be NULL, in which case it uses the hard-coded defaults. -HmdRenderInfo GenerateHmdRenderInfoFromHmdInfo ( HMDInfo const &hmdInfo, +HmdRenderInfo GenerateHmdRenderInfoFromHmdInfo ( HMDInfo const &hmdInfo, Profile const *profile /*=NULL*/, DistortionEqnType distortionType /*= Distortion_CatmullRom10*/, EyeCupType eyeCupOverride /*= EyeCup_LAST*/ ) { + OVR_ASSERT(profile); // profiles are required + HmdRenderInfo renderInfo; renderInfo.HmdType = hmdInfo.HmdType; @@ -718,15 +750,13 @@ HmdRenderInfo GenerateHmdRenderInfoFromHmdInfo ( HMDInfo const &hmdInfo, renderInfo.EyeRight = renderInfo.EyeLeft; - // Obtain data from profile. - if ( profile != NULL ) + char eyecup[16]; + if (profile->GetValue(OVR_KEY_EYE_CUP, eyecup, 16)) { - char eyecup[16]; - if (profile->GetValue(OVR_KEY_EYE_CUP, eyecup, 16)) - SetEyeCup(&renderInfo, eyecup); + SetEyeCup(&renderInfo, eyecup); } - + switch ( hmdInfo.HmdType ) { case HmdType_None: @@ -791,54 +821,60 @@ HmdRenderInfo GenerateHmdRenderInfoFromHmdInfo ( HMDInfo const &hmdInfo, default: OVR_ASSERT ( false ); break; } - if ( profile != NULL ) - { - // Set the customized user eye position - // TBD: Maybe we should separate custom camera positioning from custom distortion rendering ?? - if (profile->GetBoolValue(OVR_KEY_CUSTOM_EYE_RENDER, true)) - { - float eye2nose[2]; - if (profile->GetFloatValues(OVR_KEY_EYE_TO_NOSE_DISTANCE, eye2nose, 2) == 2) - { // Load per-eye half-IPD - renderInfo.EyeLeft.NoseToPupilInMeters = eye2nose[0]; - renderInfo.EyeRight.NoseToPupilInMeters = eye2nose[1]; - } - else - { // Use a centered IPD instead - float ipd = profile->GetFloatValue(OVR_KEY_IPD, OVR_DEFAULT_IPD); - renderInfo.EyeLeft.NoseToPupilInMeters = 0.5f * ipd; - renderInfo.EyeRight.NoseToPupilInMeters = 0.5f * ipd; - } + Profile* def = ProfileManager::GetInstance()->GetDefaultProfile(hmdInfo.HmdType); + + // Set the eye position + // Use the user profile value unless they have elected to use the defaults + if (!profile->GetBoolValue(OVR_KEY_CUSTOM_EYE_RENDER, true)) + profile = def; // use the default + + char user[32]; + profile->GetValue(OVR_KEY_USER, user, 32); // for debugging purposes + + // TBD: Maybe we should separate custom camera positioning from custom distortion rendering ?? + float eye2nose[2] = { OVR_DEFAULT_IPD / 2, OVR_DEFAULT_IPD / 2 }; + if (profile->GetFloatValues(OVR_KEY_EYE_TO_NOSE_DISTANCE, eye2nose, 2) == 2) + { + renderInfo.EyeLeft.NoseToPupilInMeters = eye2nose[0]; + renderInfo.EyeRight.NoseToPupilInMeters = eye2nose[1]; + } + else + { // Legacy profiles may not include half-ipd, so use the regular IPD value instead + float ipd = profile->GetFloatValue(OVR_KEY_IPD, OVR_DEFAULT_IPD); + renderInfo.EyeLeft.NoseToPupilInMeters = 0.5f * ipd; + renderInfo.EyeRight.NoseToPupilInMeters = 0.5f * ipd; + } - float eye2plate[2]; - if (profile->GetFloatValues(OVR_KEY_MAX_EYE_TO_PLATE_DISTANCE, eye2plate, 2) == 2) - { // Subtract the eye-cup height from the plate distance to get the eye-to-lens distance - // This measurement should be the the distance at maximum dial setting - // We still need to adjust with the dial offset - renderInfo.EyeLeft.ReliefInMeters = eye2plate[0] - renderInfo.LensSurfaceToMidplateInMeters; - renderInfo.EyeRight.ReliefInMeters = eye2plate[1] - renderInfo.LensSurfaceToMidplateInMeters; - - // Adjust the eye relief with the dial setting (from the assumed max eye relief) - int dial = profile->GetIntValue(OVR_KEY_EYE_RELIEF_DIAL, -1); - if (dial >= 0) - { - renderInfo.EyeLeft.ReliefInMeters -= ((10 - dial) * 0.001f); - renderInfo.EyeRight.ReliefInMeters -= ((10 - dial) * 0.001f); - } - } - else - { - // Set the eye relief with the user configured dial setting - int dial = profile->GetIntValue(OVR_KEY_EYE_RELIEF_DIAL, -1); - if (dial >= 0) - { // Assume a default of 7 to 17 mm eye relief based on the dial. This corresponds - // to the sampled and tuned distortion range on the DK1. - renderInfo.EyeLeft.ReliefInMeters = 0.007f + (dial * 0.001f); - renderInfo.EyeRight.ReliefInMeters = 0.007f + (dial * 0.001f); - } - } - } + float eye2plate[2]; + if ((profile->GetFloatValues(OVR_KEY_MAX_EYE_TO_PLATE_DISTANCE, eye2plate, 2) == 2) || + (def->GetFloatValues(OVR_KEY_MAX_EYE_TO_PLATE_DISTANCE, eye2plate, 2) == 2)) + { // Subtract the eye-cup height from the plate distance to get the eye-to-lens distance + // This measurement should be the the distance at maximum dial setting + // We still need to adjust with the dial offset + renderInfo.EyeLeft.ReliefInMeters = eye2plate[0] - renderInfo.LensSurfaceToMidplateInMeters; + renderInfo.EyeRight.ReliefInMeters = eye2plate[1] - renderInfo.LensSurfaceToMidplateInMeters; + + // Adjust the eye relief with the dial setting (from the assumed max eye relief) + int dial = profile->GetIntValue(OVR_KEY_EYE_RELIEF_DIAL, OVR_DEFAULT_EYE_RELIEF_DIAL); + renderInfo.EyeLeft.ReliefInMeters -= ((10 - dial) * 0.001f); + renderInfo.EyeRight.ReliefInMeters -= ((10 - dial) * 0.001f); } + else + { + // We shouldn't be here. The user or default profile should have the eye relief + OVR_ASSERT(false); + + // Set the eye relief with the user configured dial setting + //int dial = profile->GetIntValue(OVR_KEY_EYE_RELIEF_DIAL, OVR_DEFAULT_EYE_RELIEF_DIAL); + + // Assume a default of 7 to 17 mm eye relief based on the dial. This corresponds + // to the sampled and tuned distortion range on the DK1. + //renderInfo.EyeLeft.ReliefInMeters = 0.007f + (dial * 0.001f); + //renderInfo.EyeRight.ReliefInMeters = 0.007f + (dial * 0.001f); + } + + def->Release(); + // Now we know where the eyes are relative to the lenses, we can compute a distortion for each. // TODO: incorporate lateral offset in distortion generation. @@ -873,10 +909,11 @@ LensConfig GenerateLensConfigFromEyeRelief ( float eyeReliefInMeters, HmdRenderI LensConfig Config; }; - DistortionDescriptor distortions[10]; - for ( unsigned int i = 0; i < sizeof(distortions)/sizeof(distortions[0]); i++ ) + static const int MaxDistortions = 10; + DistortionDescriptor distortions[MaxDistortions]; + for (int i = 0; i < MaxDistortions; i++) { - distortions[i].Config.SetToIdentity(); + distortions[i].Config.SetToIdentity(); // Note: This line causes a false static analysis error -cat distortions[i].EyeRelief = 0.0f; distortions[i].MaxRadius = 1.0f; } @@ -889,7 +926,7 @@ LensConfig GenerateLensConfigFromEyeRelief ( float eyeReliefInMeters, HmdRenderI { numDistortions = 0; - + // Tuned at minimum dial setting - extended to r^2 == 1.8 distortions[numDistortions].Config.Eqn = Distortion_CatmullRom10; distortions[numDistortions].EyeRelief = 0.012760465f - 0.005f; @@ -905,9 +942,6 @@ LensConfig GenerateLensConfigFromEyeRelief ( float eyeReliefInMeters, HmdRenderI distortions[numDistortions].Config.K[8] = 5.1f; distortions[numDistortions].Config.K[9] = 7.4f; distortions[numDistortions].Config.K[10] = 11.0f; - distortions[numDistortions].SampleRadius[0] = 0.222717149f; - distortions[numDistortions].SampleRadius[1] = 0.512249443f; - distortions[numDistortions].SampleRadius[2] = 0.712694878f; distortions[numDistortions].MaxRadius = sqrt(1.8f); defaultDistortion = numDistortions; // this is the default numDistortions++; @@ -927,9 +961,6 @@ LensConfig GenerateLensConfigFromEyeRelief ( float eyeReliefInMeters, HmdRenderI distortions[numDistortions].Config.K[8] = 1.6986004f; distortions[numDistortions].Config.K[9] = 1.9940577f; distortions[numDistortions].Config.K[10] = 2.4783147f; - distortions[numDistortions].SampleRadius[0] = 0.222717149f; - distortions[numDistortions].SampleRadius[1] = 0.512249443f; - distortions[numDistortions].SampleRadius[2] = 0.712694878f; distortions[numDistortions].MaxRadius = 1.0f; numDistortions++; @@ -948,12 +979,11 @@ LensConfig GenerateLensConfigFromEyeRelief ( float eyeReliefInMeters, HmdRenderI distortions[numDistortions].Config.K[8] = 1.8f; distortions[numDistortions].Config.K[9] = 2.25f; distortions[numDistortions].Config.K[10] = 3.0f; - distortions[numDistortions].SampleRadius[0] = 0.222717149f; - distortions[numDistortions].SampleRadius[1] = 0.512249443f; - distortions[numDistortions].SampleRadius[2] = 0.712694878f; distortions[numDistortions].MaxRadius = 1.0f; numDistortions++; + + // Chromatic aberration doesn't seem to change with eye relief. for ( int i = 0; i < numDistortions; i++ ) { @@ -982,14 +1012,8 @@ LensConfig GenerateLensConfigFromEyeRelief ( float eyeReliefInMeters, HmdRenderI distortions[numDistortions].Config.K[8] = 1.620f; distortions[numDistortions].Config.K[9] = 1.840f; distortions[numDistortions].Config.K[10] = 2.200f; - distortions[numDistortions].SampleRadius[0] = 0.222717149f; - distortions[numDistortions].SampleRadius[1] = 0.512249443f; - distortions[numDistortions].SampleRadius[2] = 0.712694878f; distortions[numDistortions].MaxRadius = 1.0f; - distortions[numDistortions].SampleRadius[0] = 0.405405405f; - distortions[numDistortions].SampleRadius[1] = 0.675675676f; - distortions[numDistortions].SampleRadius[2] = 0.945945946f; defaultDistortion = numDistortions; // this is the default numDistortions++; @@ -1011,6 +1035,7 @@ LensConfig GenerateLensConfigFromEyeRelief ( float eyeReliefInMeters, HmdRenderI // Tuned Crystal Cove & DK2 Lens (CES & GDC) numDistortions = 0; + distortions[numDistortions].EyeRelief = 0.010f; distortions[numDistortions].Config.MetersPerTanAngleAtCenter = 0.036f; @@ -1028,10 +1053,26 @@ LensConfig GenerateLensConfigFromEyeRelief ( float eyeReliefInMeters, HmdRenderI distortions[numDistortions].Config.K[10] = 1.38f; //1.48f; distortions[numDistortions].MaxRadius = 1.0f; + /* + // Orange Lens on DK2 + distortions[numDistortions].EyeRelief = 0.010f; + distortions[numDistortions].Config.MetersPerTanAngleAtCenter = 0.031f; + + distortions[numDistortions].Config.Eqn = Distortion_CatmullRom10; + distortions[numDistortions].Config.K[0] = 1.00f; + distortions[numDistortions].Config.K[1] = 1.0169f; + distortions[numDistortions].Config.K[2] = 1.0378f; + distortions[numDistortions].Config.K[3] = 1.0648f; + distortions[numDistortions].Config.K[4] = 1.0990f; + distortions[numDistortions].Config.K[5] = 1.141f; + distortions[numDistortions].Config.K[6] = 1.192f; + distortions[numDistortions].Config.K[7] = 1.255f; + distortions[numDistortions].Config.K[8] = 1.335f; + distortions[numDistortions].Config.K[9] = 1.435f; + distortions[numDistortions].Config.K[10] = 1.56f; + distortions[numDistortions].MaxRadius = 1.0f; + */ - distortions[numDistortions].SampleRadius[0] = 0.405405405f; - distortions[numDistortions].SampleRadius[1] = 0.675675676f; - distortions[numDistortions].SampleRadius[2] = 0.945945946f; defaultDistortion = numDistortions; // this is the default numDistortions++; @@ -1078,8 +1119,7 @@ LensConfig GenerateLensConfigFromEyeRelief ( float eyeReliefInMeters, HmdRenderI } } - OVR_ASSERT ( numDistortions < (sizeof(distortions)/sizeof(distortions[0])) ); - + OVR_ASSERT(numDistortions < MaxDistortions); DistortionDescriptor *pUpper = NULL; DistortionDescriptor *pLower = NULL; @@ -1242,9 +1282,6 @@ LensConfig GenerateLensConfigFromEyeRelief ( float eyeReliefInMeters, HmdRenderI } - - - DistortionRenderDesc CalculateDistortionRenderDesc ( StereoEye eyeType, HmdRenderInfo const &hmd, const LensConfig *pLensOverride /*= NULL */ ) { @@ -1706,21 +1743,21 @@ void TransformScreenNDCToTanFovSpaceChroma ( Vector2f *resultR, Vector2f *result } // This mimics the second half of the distortion shader's function. -Vector2f TransformTanFovSpaceToRendertargetTexUV( StereoEyeParams const &eyeParams, +Vector2f TransformTanFovSpaceToRendertargetTexUV( ScaleAndOffset2D const &eyeToSourceUV, Vector2f const &tanEyeAngle ) { Vector2f textureUV; - textureUV.x = tanEyeAngle.x * eyeParams.EyeToSourceUV.Scale.x + eyeParams.EyeToSourceUV.Offset.x; - textureUV.y = tanEyeAngle.y * eyeParams.EyeToSourceUV.Scale.y + eyeParams.EyeToSourceUV.Offset.y; + textureUV.x = tanEyeAngle.x * eyeToSourceUV.Scale.x + eyeToSourceUV.Offset.x; + textureUV.y = tanEyeAngle.y * eyeToSourceUV.Scale.y + eyeToSourceUV.Offset.y; return textureUV; } -Vector2f TransformTanFovSpaceToRendertargetNDC( StereoEyeParams const &eyeParams, +Vector2f TransformTanFovSpaceToRendertargetNDC( ScaleAndOffset2D const &eyeToSourceNDC, Vector2f const &tanEyeAngle ) { Vector2f textureNDC; - textureNDC.x = tanEyeAngle.x * eyeParams.EyeToSourceNDC.Scale.x + eyeParams.EyeToSourceNDC.Offset.x; - textureNDC.y = tanEyeAngle.y * eyeParams.EyeToSourceNDC.Scale.y + eyeParams.EyeToSourceNDC.Offset.y; + textureNDC.x = tanEyeAngle.x * eyeToSourceNDC.Scale.x + eyeToSourceNDC.Offset.x; + textureNDC.y = tanEyeAngle.y * eyeToSourceNDC.Scale.y + eyeToSourceNDC.Offset.y; return textureNDC; } |