diff --git a/gfx/vr/VRDisplayHost.cpp b/gfx/vr/VRDisplayHost.cpp index 418d08fe81f0..fd2fd6d6adbb 100644 --- a/gfx/vr/VRDisplayHost.cpp +++ b/gfx/vr/VRDisplayHost.cpp @@ -186,3 +186,16 @@ VRControllerHost::GetButtonPressed() { return mButtonPressed; } + +void +VRControllerHost::SetPose(const dom::GamepadPoseState& aPose) +{ + mPose = aPose; +} + +const dom::GamepadPoseState& +VRControllerHost::GetPose() +{ + return mPose; +} + diff --git a/gfx/vr/VRDisplayHost.h b/gfx/vr/VRDisplayHost.h index 973fc285a4d7..0e04e4fd2db5 100644 --- a/gfx/vr/VRDisplayHost.h +++ b/gfx/vr/VRDisplayHost.h @@ -16,6 +16,7 @@ #include "mozilla/EnumeratedArray.h" #include "mozilla/TimeStamp.h" #include "mozilla/TypedEnumBits.h" +#include "mozilla/dom/GamepadPoseState.h" namespace mozilla { namespace layers { @@ -92,6 +93,8 @@ public: uint32_t GetIndex(); void SetButtonPressed(uint64_t aBit); uint64_t GetButtonPressed(); + void SetPose(const dom::GamepadPoseState& aPose); + const dom::GamepadPoseState& GetPose(); protected: explicit VRControllerHost(VRDeviceType aType); @@ -102,6 +105,7 @@ protected: uint32_t mIndex; // The current button pressed bit of button mask. uint64_t mButtonPressed; + dom::GamepadPoseState mPose; }; } // namespace gfx diff --git a/gfx/vr/VRManager.cpp b/gfx/vr/VRManager.cpp index 108165f6ba84..db2e9b518109 100644 --- a/gfx/vr/VRManager.cpp +++ b/gfx/vr/VRManager.cpp @@ -94,6 +94,10 @@ VRManager::VRManager() mManagers.AppendElement(mgr); } #endif + // Enable gamepad extensions while VR is enabled. + if (gfxPrefs::VREnabled()) { + Preferences::SetBool("dom.gamepad.extensions.enabled", true); + } } VRManager::~VRManager() diff --git a/gfx/vr/gfxVR.cpp b/gfx/vr/gfxVR.cpp index e9c5bb7ccbf4..c0babb4f8013 100644 --- a/gfx/vr/gfxVR.cpp +++ b/gfx/vr/gfxVR.cpp @@ -113,3 +113,15 @@ VRControllerManager::NewAxisMove(uint32_t aIndex, uint32_t aAxis, MOZ_ASSERT(vm); vm->NotifyGamepadChange(a); } + +void +VRControllerManager::NewPoseState(uint32_t aIndex, + const dom::GamepadPoseState& aPose) +{ + dom::GamepadPoseInformation a(aIndex, dom::GamepadServiceType::VR, + aPose); + + VRManager* vm = VRManager::Get(); + MOZ_ASSERT(vm); + vm->NotifyGamepadChange(a); +} diff --git a/gfx/vr/gfxVR.h b/gfx/vr/gfxVR.h index 9d6c298c1874..b46875741385 100644 --- a/gfx/vr/gfxVR.h +++ b/gfx/vr/gfxVR.h @@ -20,6 +20,10 @@ namespace mozilla { namespace layers { class PTextureParent; } +namespace dom { +enum class GamepadMappingType : uint32_t; +struct GamepadPoseState; +} namespace gfx { class VRLayerParent; class VRDisplayHost; @@ -252,6 +256,7 @@ public: virtual void ScanForDevices() = 0; void NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed); void NewAxisMove(uint32_t aIndex, uint32_t aAxis, double aValue); + void NewPoseState(uint32_t aIndex, const dom::GamepadPoseState& aPose); void AddGamepad(const char* aID, uint32_t aMapping, uint32_t aNumButtons, uint32_t aNumAxes); void RemoveGamepad(uint32_t aIndex); @@ -269,6 +274,9 @@ private: uint64_t aButtonPressed) = 0; virtual void HandleAxisMove(uint32_t aControllerIdx, uint32_t aAxis, float aValue) = 0; + virtual void HandlePoseTracking(uint32_t aControllerIdx, + const dom::GamepadPoseState& aPose, + VRControllerHost* aController) = 0; }; } // namespace gfx diff --git a/gfx/vr/gfxVROpenVR.cpp b/gfx/vr/gfxVROpenVR.cpp index 3e87d431069e..01149c983114 100644 --- a/gfx/vr/gfxVROpenVR.cpp +++ b/gfx/vr/gfxVROpenVR.cpp @@ -490,7 +490,7 @@ VRControllerOpenVR::VRControllerOpenVR() MOZ_COUNT_CTOR_INHERITED(VRControllerOpenVR, VRControllerHost); mControllerInfo.mControllerName.AssignLiteral("OpenVR HMD"); #ifdef MOZ_GAMEPAD - mControllerInfo.mMappingType = static_cast(dom::GamepadMappingType::_empty); + mControllerInfo.mMappingType = static_cast(GamepadMappingType::_empty); #else mControllerInfo.mMappingType = 0; #endif @@ -583,6 +583,9 @@ VRControllerManagerOpenVR::HandleInput() MOZ_ASSERT(mVRSystem); + vr::TrackedDevicePose_t poses[vr::k_unMaxTrackedDeviceCount]; + mVRSystem->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseSeated, 0.0f, + poses, vr::k_unMaxTrackedDeviceCount); // Process OpenVR controller state for (uint32_t i = 0; i < mOpenVRController.Length(); ++i) { controller = mOpenVRController[i]; @@ -605,6 +608,44 @@ VRControllerManagerOpenVR::HandleInput() HandleAxisMove(controller->GetIndex(), axis, state.rAxis[gOpenVRAxes[axis]].x); } + + // Start to process pose + const ::vr::TrackedDevicePose_t& pose = poses[controller->GetTrackedIndex()]; + + if (pose.bDeviceIsConnected && pose.bPoseIsValid && + pose.eTrackingResult == vr::TrackingResult_Running_OK) { + gfx::Matrix4x4 m; + + // NOTE! mDeviceToAbsoluteTracking is a 3x4 matrix, not 4x4. But + // because of its arrangement, we can copy the 12 elements in and + // then transpose them to the right place. We do this so we can + // pull out a Quaternion. + memcpy(&m.components, &pose.mDeviceToAbsoluteTracking, sizeof(float) * 12); + m.Transpose(); + + gfx::Quaternion rot; + rot.SetFromRotationMatrix(m); + rot.Invert(); + + GamepadPoseState poseState; + poseState.flags |= GamepadCapabilityFlags::Cap_Orientation; + poseState.orientation[0] = rot.x; + poseState.orientation[1] = rot.y; + poseState.orientation[2] = rot.z; + poseState.orientation[3] = rot.w; + poseState.angularVelocity[0] = pose.vAngularVelocity.v[0]; + poseState.angularVelocity[1] = pose.vAngularVelocity.v[1]; + poseState.angularVelocity[2] = pose.vAngularVelocity.v[2]; + + poseState.flags |= GamepadCapabilityFlags::Cap_Position; + poseState.position[0] = m._41; + poseState.position[1] = m._42; + poseState.position[2] = m._43; + poseState.linearVelocity[0] = pose.vVelocity.v[0]; + poseState.linearVelocity[1] = pose.vVelocity.v[1]; + poseState.linearVelocity[2] = pose.vVelocity.v[2]; + HandlePoseTracking(controller->GetIndex(), poseState, controller); + } } } @@ -644,6 +685,17 @@ VRControllerManagerOpenVR::HandleAxisMove(uint32_t aControllerIdx, uint32_t aAxi } } +void +VRControllerManagerOpenVR::HandlePoseTracking(uint32_t aControllerIdx, + const GamepadPoseState& aPose, + VRControllerHost* aController) +{ + if (aPose != aController->GetPose()) { + aController->SetPose(aPose); + NewPoseState(aControllerIdx, aPose); + } +} + void VRControllerManagerOpenVR::GetControllers(nsTArray>& aControllerResult) { diff --git a/gfx/vr/gfxVROpenVR.h b/gfx/vr/gfxVROpenVR.h index 4357ccbc0af4..829f882531d3 100644 --- a/gfx/vr/gfxVROpenVR.h +++ b/gfx/vr/gfxVROpenVR.h @@ -124,6 +124,9 @@ private: uint64_t aButtonPressed) override; virtual void HandleAxisMove(uint32_t aControllerIdx, uint32_t aAxis, float aValue) override; + virtual void HandlePoseTracking(uint32_t aControllerIdx, + const dom::GamepadPoseState& aPose, + VRControllerHost* aController) override; bool mOpenVRInstalled; nsTArray> mOpenVRController;