Bug 1344393 - Add StageParameters for Oculus draft
authorKearwood Gilbert <kgilbert@mozilla.com>
Fri, 17 Mar 2017 13:33:56 -0700
changeset 501631 0d9e96d80a2e
parent 501569 05bfa2831c0b
child 549948 73a2096fc7cb
push id50057
push userbmo:kgilbert@mozilla.com
push dateMon, 20 Mar 2017 17:48:59 +0000
bugs1344393
milestone55.0a1
Bug 1344393 - Add StageParameters for Oculus MozReview-Commit-ID: 9OkleewwS2b
gfx/vr/gfxVROculus.cpp
gfx/vr/gfxVROculus.h
gfx/vr/ovr_capi_dynamic.h
--- a/gfx/vr/gfxVROculus.cpp
+++ b/gfx/vr/gfxVROculus.cpp
@@ -93,16 +93,17 @@ static pfn_ovr_SetBool ovr_SetBool = nul
 static pfn_ovr_GetInt ovr_GetInt = nullptr;
 static pfn_ovr_SetInt ovr_SetInt = nullptr;
 static pfn_ovr_GetFloat ovr_GetFloat = nullptr;
 static pfn_ovr_SetFloat ovr_SetFloat = nullptr;
 static pfn_ovr_GetFloatArray ovr_GetFloatArray = nullptr;
 static pfn_ovr_SetFloatArray ovr_SetFloatArray = nullptr;
 static pfn_ovr_GetString ovr_GetString = nullptr;
 static pfn_ovr_SetString ovr_SetString = nullptr;
+static pfn_ovr_GetBoundaryDimensions ovr_GetBoundaryDimensions = nullptr;
 
 #ifdef XP_WIN
 static pfn_ovr_CreateTextureSwapChainDX ovr_CreateTextureSwapChainDX = nullptr;
 static pfn_ovr_GetTextureSwapChainBufferDX ovr_GetTextureSwapChainBufferDX = nullptr;
 static pfn_ovr_CreateMirrorTextureDX ovr_CreateMirrorTextureDX = nullptr;
 static pfn_ovr_GetMirrorTextureBufferDX ovr_GetMirrorTextureBufferDX = nullptr;
 #endif
 
@@ -281,16 +282,17 @@ InitializeOculusCAPI()
   REQUIRE_FUNCTION(ovr_GetInt);
   REQUIRE_FUNCTION(ovr_SetInt);
   REQUIRE_FUNCTION(ovr_GetFloat);
   REQUIRE_FUNCTION(ovr_SetFloat);
   REQUIRE_FUNCTION(ovr_GetFloatArray);
   REQUIRE_FUNCTION(ovr_SetFloatArray);
   REQUIRE_FUNCTION(ovr_GetString);
   REQUIRE_FUNCTION(ovr_SetString);
+  REQUIRE_FUNCTION(ovr_GetBoundaryDimensions);
 
 #ifdef XP_WIN
 
   REQUIRE_FUNCTION(ovr_CreateTextureSwapChainDX);
   REQUIRE_FUNCTION(ovr_GetTextureSwapChainBufferDX);
   REQUIRE_FUNCTION(ovr_CreateMirrorTextureDX);
   REQUIRE_FUNCTION(ovr_GetMirrorTextureBufferDX);
 
@@ -351,16 +353,17 @@ VRDisplayOculus::VRDisplayOculus(ovrSess
   , mQuadVS(nullptr)
   , mQuadPS(nullptr)
   , mLinearSamplerState(nullptr)
   , mVSConstantBuffer(nullptr)
   , mPSConstantBuffer(nullptr)
   , mVertexBuffer(nullptr)
   , mInputLayout(nullptr)
   , mIsPresenting(false)
+  , mEyeHeight(OVR_DEFAULT_EYE_HEIGHT)
 {
   MOZ_COUNT_CTOR_INHERITED(VRDisplayOculus, VRDisplayHost);
 
   mDisplayInfo.mDisplayName.AssignLiteral("Oculus VR HMD");
   mDisplayInfo.mIsConnected = true;
   mDisplayInfo.mIsMounted = false;
 
   mDesc = ovr_GetHmdDesc(aSession);
@@ -368,16 +371,17 @@ VRDisplayOculus::VRDisplayOculus(ovrSess
   mDisplayInfo.mCapabilityFlags = VRDisplayCapabilityFlags::Cap_None;
   if (mDesc.AvailableTrackingCaps & ovrTrackingCap_Orientation) {
     mDisplayInfo.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_Orientation;
     mDisplayInfo.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_AngularAcceleration;
   }
   if (mDesc.AvailableTrackingCaps & ovrTrackingCap_Position) {
     mDisplayInfo.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_Position;
     mDisplayInfo.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_LinearAcceleration;
+    mDisplayInfo.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_StageParameters;
   }
   mDisplayInfo.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_External;
   mDisplayInfo.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_MountDetection;
   mDisplayInfo.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_Present;
 
   mFOVPort[VRDisplayInfo::Eye_Left] = mDesc.DefaultEyeFov[ovrEye_Left];
   mFOVPort[VRDisplayInfo::Eye_Right] = mDesc.DefaultEyeFov[ovrEye_Right];
 
@@ -396,16 +400,18 @@ VRDisplayOculus::VRDisplayOculus(ovrSess
     mDisplayInfo.mEyeTranslation[eye] = Point3D(renderDesc.HmdToEyeOffset.x, renderDesc.HmdToEyeOffset.y, renderDesc.HmdToEyeOffset.z);
 
     texSize[eye] = ovr_GetFovTextureSize(mSession, (ovrEyeType)eye, mFOVPort[eye], pixelsPerDisplayPixel);
   }
 
   // take the max of both for eye resolution
   mDisplayInfo.mEyeResolution.width = std::max(texSize[VRDisplayInfo::Eye_Left].w, texSize[VRDisplayInfo::Eye_Right].w);
   mDisplayInfo.mEyeResolution.height = std::max(texSize[VRDisplayInfo::Eye_Left].h, texSize[VRDisplayInfo::Eye_Right].h);
+
+  UpdateStageParameters();
 }
 
 VRDisplayOculus::~VRDisplayOculus() {
   StopPresentation();
   Destroy();
   MOZ_COUNT_DTOR_INHERITED(VRDisplayOculus, VRDisplayHost);
 }
 
@@ -414,19 +420,58 @@ VRDisplayOculus::Destroy()
 {
   if (mSession) {
     ovr_Destroy(mSession);
     mSession = nullptr;
   }
 }
 
 void
+VRDisplayOculus::UpdateStageParameters()
+{
+  ovrVector3f playArea;
+  ovrResult res = ovr_GetBoundaryDimensions(mSession, ovrBoundary_PlayArea, &playArea);
+  if (res == ovrSuccess) {
+    mDisplayInfo.mStageSize.width = playArea.x;
+    mDisplayInfo.mStageSize.height = playArea.z;
+  } else {
+    // If we fail, fall back to reasonable defaults.
+    // 1m x 1m space
+    mDisplayInfo.mStageSize.width = 1.0f;
+    mDisplayInfo.mStageSize.height = 1.0f;
+  }
+
+  mEyeHeight = ovr_GetFloat(mSession, OVR_KEY_EYE_HEIGHT, OVR_DEFAULT_EYE_HEIGHT);
+
+  mDisplayInfo.mSittingToStandingTransform._11 = 1.0f;
+  mDisplayInfo.mSittingToStandingTransform._12 = 0.0f;
+  mDisplayInfo.mSittingToStandingTransform._13 = 0.0f;
+  mDisplayInfo.mSittingToStandingTransform._14 = 0.0f;
+
+  mDisplayInfo.mSittingToStandingTransform._21 = 0.0f;
+  mDisplayInfo.mSittingToStandingTransform._22 = 1.0f;
+  mDisplayInfo.mSittingToStandingTransform._23 = 0.0f;
+  mDisplayInfo.mSittingToStandingTransform._24 = 0.0f;
+
+  mDisplayInfo.mSittingToStandingTransform._31 = 0.0f;
+  mDisplayInfo.mSittingToStandingTransform._32 = 0.0f;
+  mDisplayInfo.mSittingToStandingTransform._33 = 1.0f;
+  mDisplayInfo.mSittingToStandingTransform._34 = 0.0f;
+
+  mDisplayInfo.mSittingToStandingTransform._41 = 0.0f;
+  mDisplayInfo.mSittingToStandingTransform._42 = mEyeHeight;
+  mDisplayInfo.mSittingToStandingTransform._43 = 0.0f;
+  mDisplayInfo.mSittingToStandingTransform._44 = 1.0f;
+}
+
+void
 VRDisplayOculus::ZeroSensor()
 {
   ovr_RecenterTrackingOrigin(mSession);
+  UpdateStageParameters();
 }
 
 VRHMDSensorState
 VRDisplayOculus::GetSensorState()
 {
   mInputFrameID++;
 
   VRHMDSensorState result;
@@ -435,16 +480,17 @@ VRDisplayOculus::GetSensorState()
     // XXX We might need to call ovr_GetPredictedDisplayTime even if we don't use the result.
     // If we don't call it, the Oculus driver will spew out many warnings...
     double predictedFrameTime = ovr_GetPredictedDisplayTime(mSession, mInputFrameID);
     frameDelta = predictedFrameTime - ovr_GetTimeInSeconds();
   }
   result = GetSensorState(frameDelta);
   result.inputFrameID = mInputFrameID;
   mLastSensorState[result.inputFrameID % kMaxLatencyFrames] = result;
+  result.position[1] -= mEyeHeight;
   return result;
 }
 
 VRHMDSensorState
 VRDisplayOculus::GetSensorState(double timeOffset)
 {
   VRHMDSensorState result;
   result.Clear();
@@ -983,16 +1029,21 @@ VRSystemManagerOculus::GetHMDs(nsTArray<
     mHMDInfo = nullptr;
   } else if (mHMDInfo == nullptr) {
     // HMD Detected
     ovrSession session;
     ovrGraphicsLuid luid;
     ovrResult orv = ovr_Create(&session, &luid);
     if (orv == ovrSuccess) {
       mSession = session;
+      orv = ovr_SetTrackingOriginType(session, ovrTrackingOrigin_FloorLevel);
+      if (orv != ovrSuccess) {
+        NS_WARNING("ovr_SetTrackingOriginType failed.\n");
+      }
+
       mHMDInfo = new VRDisplayOculus(session);
     }
   }
 
   if (mHMDInfo) {
     aHMDResult.AppendElement(mHMDInfo);
   }
 }
@@ -1094,16 +1145,19 @@ VRSystemManagerOculus::HandleInput()
       poseState.linearVelocity[0] = pose.LinearVelocity.x;
       poseState.linearVelocity[1] = pose.LinearVelocity.y;
       poseState.linearVelocity[2] = pose.LinearVelocity.z;
 
       poseState.flags |= GamepadCapabilityFlags::Cap_LinearAcceleration;
       poseState.linearAcceleration[0] = pose.LinearAcceleration.x;
       poseState.linearAcceleration[1] = pose.LinearAcceleration.y;
       poseState.linearAcceleration[2] = pose.LinearAcceleration.z;
+
+      float eyeHeight = ovr_GetFloat(mSession, OVR_KEY_EYE_HEIGHT, OVR_DEFAULT_EYE_HEIGHT);
+      poseState.position[1] -= eyeHeight;
     }
     HandlePoseTracking(i, poseState, controller);
   }
 }
 
 void
 VRSystemManagerOculus::HandleButtonPress(uint32_t aControllerIdx,
                                          uint32_t aButton,
--- a/gfx/vr/gfxVROculus.h
+++ b/gfx/vr/gfxVROculus.h
@@ -43,16 +43,17 @@ public:
 protected:
   virtual void StartPresentation() override;
   virtual void StopPresentation() override;
   virtual void SubmitFrame(mozilla::layers::TextureSourceD3D11* aSource,
                            const IntSize& aSize,
                            const VRHMDSensorState& aSensorState,
                            const gfx::Rect& aLeftEyeRect,
                            const gfx::Rect& aRightEyeRect) override;
+  void UpdateStageParameters();
 
 public:
   explicit VRDisplayOculus(ovrSession aSession);
 
 protected:
   virtual ~VRDisplayOculus();
   void Destroy();
 
@@ -77,17 +78,18 @@ protected:
   layers::VertexShaderConstants mVSConstants;
   layers::PixelShaderConstants mPSConstants;
   RefPtr<ID3D11Buffer> mVSConstantBuffer;
   RefPtr<ID3D11Buffer> mPSConstantBuffer;
   RefPtr<ID3D11Buffer> mVertexBuffer;
   RefPtr<ID3D11InputLayout> mInputLayout;
 
   bool mIsPresenting;
-  
+  float mEyeHeight;
+
   bool UpdateConstantBuffers();
 
   struct Vertex
   {
     float position[2];
   };
 };
 
--- a/gfx/vr/ovr_capi_dynamic.h
+++ b/gfx/vr/ovr_capi_dynamic.h
@@ -562,32 +562,40 @@ typedef enum {
   ovrDebugHudStereo_Off = 0,
   ovrDebugHudStereo_Quad = 1,
   ovrDebugHudStereo_QuadWithCrosshair = 2,
   ovrDebugHudStereo_CrosshairAtInfinity = 3,
   ovrDebugHudStereo_Count,
   ovrDebugHudStereo_EnumSize = 0x7fffffff
 } ovrDebugHudStereoMode;
 
+typedef enum {
+  // Outer boundary - closely represents user setup walls
+  ovrBoundary_Outer = 0x0001,
+  // Play area - safe rectangular area inside outer boundary which can optionally be used to restrict user interactions and motion.
+  ovrBoundary_PlayArea = 0x0100,
+} ovrBoundaryType;
+
 typedef ovrBool(OVR_PFN* pfn_ovr_GetBool)(ovrSession session, const char* propertyName, ovrBool defaultVal);
-typedef ovrBool(OVR_PFN* pfn_ovr_SetBool)(ovrSession session, const char* propertyName, ovrBool value); 
+typedef ovrBool(OVR_PFN* pfn_ovr_SetBool)(ovrSession session, const char* propertyName, ovrBool value);
 typedef int (OVR_PFN* pfn_ovr_GetInt)(ovrSession session, const char* propertyName, int defaultVal);
 typedef ovrBool (OVR_PFN* pfn_ovr_SetInt)(ovrSession session, const char* propertyName, int value);
 typedef float (OVR_PFN* pfn_ovr_GetFloat)(ovrSession session, const char* propertyName, float defaultVal);
 typedef ovrBool (OVR_PFN* pfn_ovr_SetFloat)(ovrSession session, const char* propertyName, float value);
 typedef unsigned int (OVR_PFN* pfn_ovr_GetFloatArray)(ovrSession session, const char* propertyName,
   float values[], unsigned int valuesCapacity);
 typedef ovrBool (OVR_PFN* pfn_ovr_SetFloatArray)(ovrSession session, const char* propertyName,
   const float values[], unsigned int valuesSize);
 typedef const char* (OVR_PFN* pfn_ovr_GetString)(ovrSession session, const char* propertyName,
   const char* defaultVal);
 typedef ovrBool (OVR_PFN* pfn_ovr_SetString)(ovrSession session, const char* propertyName,
   const char* value);
-
-
+typedef ovrResult (OVR_PFN* pfn_ovr_GetBoundaryDimensions)(ovrSession session,
+                                                           ovrBoundaryType boundaryType,
+                                                           ovrVector3f* outDimensions);
 
 typedef enum {
   ovrError_MemoryAllocationFailure = -1000,
   ovrError_SocketCreationFailure = -1001,
   ovrError_InvalidSession = -1002,
   ovrError_Timeout = -1003,
   ovrError_NotInitialized = -1004,
   ovrError_InvalidParameter = -1005,
@@ -709,14 +717,17 @@ typedef ovrResult (OVR_PFN* pfn_ovr_GetT
 typedef ovrResult (OVR_PFN* pfn_ovr_CreateMirrorTextureGL)(ovrSession session,
 	const ovrMirrorTextureDesc* desc,
 	ovrMirrorTexture* out_MirrorTexture);
 
 typedef ovrResult (OVR_PFN* pfn_ovr_GetMirrorTextureBufferGL)(ovrSession session,
 	ovrMirrorTexture mirrorTexture,
 	unsigned int* out_TexId);
 
-#ifdef __cplusplus 
+#define OVR_KEY_EYE_HEIGHT "EyeHeight" // float meters
+#define OVR_DEFAULT_EYE_HEIGHT 1.675f
+
+#ifdef __cplusplus
 }
 #endif
 
 #endif /* mozilla_ovr_capi_dynamic_h_ */
 #endif /* OVR_CAPI_h */