Bug 1299932 - Part 3: Handle OpenVR controller position and orientation; r?kip
MozReview-Commit-ID: FyneJ5JfeNE
--- a/gfx/vr/VRDisplayHost.cpp
+++ b/gfx/vr/VRDisplayHost.cpp
@@ -181,8 +181,21 @@ VRControllerHost::SetButtonPressed(uint6
mButtonPressed = aBit;
}
uint64_t
VRControllerHost::GetButtonPressed()
{
return mButtonPressed;
}
+
+void
+VRControllerHost::SetPose(const dom::GamepadPoseState& aPose)
+{
+ mPose = aPose;
+}
+
+const dom::GamepadPoseState&
+VRControllerHost::GetPose()
+{
+ return mPose;
+}
+
--- a/gfx/vr/VRDisplayHost.h
+++ b/gfx/vr/VRDisplayHost.h
@@ -11,16 +11,17 @@
#include "nsString.h"
#include "nsCOMPtr.h"
#include "mozilla/RefPtr.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/Atomics.h"
#include "mozilla/EnumeratedArray.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/TypedEnumBits.h"
+#include "mozilla/dom/GamepadPoseState.h"
namespace mozilla {
namespace layers {
class PTextureParent;
#if defined(XP_WIN)
class TextureSourceD3D11;
#endif
} // namespace layers
@@ -87,24 +88,27 @@ class VRControllerHost {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRControllerHost)
const VRControllerInfo& GetControllerInfo() const;
void SetIndex(uint32_t aIndex);
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);
virtual ~VRControllerHost();
VRControllerInfo mControllerInfo;
// The controller index in VRControllerManager.
uint32_t mIndex;
// The current button pressed bit of button mask.
uint64_t mButtonPressed;
+ dom::GamepadPoseState mPose;
};
} // namespace gfx
} // namespace mozilla
#endif /* GFX_VR_DISPLAY_HOST_H */
--- a/gfx/vr/VRManager.cpp
+++ b/gfx/vr/VRManager.cpp
@@ -89,16 +89,20 @@ VRManager::VRManager()
}
// OSVR is cross platform compatible
mgr = VRDisplayManagerOSVR::Create();
if (mgr) {
mManagers.AppendElement(mgr);
}
#endif
+ // Enable gamepad extensions while VR is enabled.
+ if (gfxPrefs::VREnabled()) {
+ Preferences::SetBool("dom.gamepad.extensions.enabled", true);
+ }
}
VRManager::~VRManager()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!mInitialized);
MOZ_COUNT_DTOR(VRManager);
}
--- a/gfx/vr/gfxVR.cpp
+++ b/gfx/vr/gfxVR.cpp
@@ -108,8 +108,20 @@ VRControllerManager::NewAxisMove(uint32_
{
dom::GamepadAxisInformation a(aIndex, dom::GamepadServiceType::VR,
aAxis, aValue);
VRManager* vm = VRManager::Get();
MOZ_ASSERT(vm);
vm->NotifyGamepadChange<dom::GamepadAxisInformation>(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<dom::GamepadPoseInformation>(a);
+}
--- a/gfx/vr/gfxVR.h
+++ b/gfx/vr/gfxVR.h
@@ -15,16 +15,20 @@
#include "mozilla/EnumeratedArray.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/TypedEnumBits.h"
namespace mozilla {
namespace layers {
class PTextureParent;
}
+namespace dom {
+enum class GamepadMappingType : uint32_t;
+struct GamepadPoseState;
+}
namespace gfx {
class VRLayerParent;
class VRDisplayHost;
class VRControllerHost;
enum class VRDeviceType : uint16_t {
Oculus,
OpenVR,
@@ -247,16 +251,17 @@ public:
static uint32_t AllocateControllerID();
virtual bool Init() = 0;
virtual void Destroy() = 0;
virtual void HandleInput() = 0;
virtual void GetControllers(nsTArray<RefPtr<VRControllerHost>>& aControllerResult) = 0;
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);
protected:
VRControllerManager() : mInstalled(false), mControllerCount(0) {}
virtual ~VRControllerManager() {}
@@ -264,14 +269,17 @@ protected:
uint32_t mControllerCount;
static Atomic<uint32_t> sControllerBase;
private:
virtual void HandleButtonPress(uint32_t aControllerIdx,
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
} // namespace mozilla
#endif /* GFX_VR_H */
--- a/gfx/vr/gfxVROpenVR.cpp
+++ b/gfx/vr/gfxVROpenVR.cpp
@@ -485,17 +485,17 @@ VRDisplayManagerOpenVR::GetHMDs(nsTArray
}
VRControllerOpenVR::VRControllerOpenVR()
: VRControllerHost(VRDeviceType::OpenVR)
{
MOZ_COUNT_CTOR_INHERITED(VRControllerOpenVR, VRControllerHost);
mControllerInfo.mControllerName.AssignLiteral("OpenVR HMD");
#ifdef MOZ_GAMEPAD
- mControllerInfo.mMappingType = static_cast<uint32_t>(dom::GamepadMappingType::_empty);
+ mControllerInfo.mMappingType = static_cast<uint32_t>(GamepadMappingType::_empty);
#else
mControllerInfo.mMappingType = 0;
#endif
mControllerInfo.mNumButtons = gNumOpenVRButtonMask;
mControllerInfo.mNumAxes = gNumOpenVRAxis;
}
VRControllerOpenVR::~VRControllerOpenVR()
@@ -578,16 +578,19 @@ VRControllerManagerOpenVR::HandleInput()
uint32_t axis = 0;
if (!mOpenVRInstalled) {
return;
}
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];
MOZ_ASSERT(mVRSystem->GetTrackedDeviceClass(controller->GetTrackedIndex())
== vr::TrackedDeviceClass_Controller);
if (mVRSystem->GetControllerState(controller->GetTrackedIndex(), &state)) {
@@ -600,16 +603,54 @@ VRControllerManagerOpenVR::HandleInput()
axis = static_cast<uint32_t>(VRControllerAxisType::TrackpadYAxis);
HandleAxisMove(controller->GetIndex(), axis,
state.rAxis[gOpenVRAxes[axis]].y);
axis = static_cast<uint32_t>(VRControllerAxisType::Trigger);
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);
+ }
}
}
void
VRControllerManagerOpenVR::HandleButtonPress(uint32_t aControllerIdx,
uint64_t aButtonPressed)
{
uint64_t buttonMask = 0;
@@ -640,16 +681,27 @@ VRControllerManagerOpenVR::HandleAxisMov
float aValue)
{
if (aValue != 0.0f) {
NewAxisMove(aControllerIdx, aAxis, aValue);
}
}
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<RefPtr<VRControllerHost>>& aControllerResult)
{
if (!mOpenVRInstalled) {
return;
}
aControllerResult.Clear();
for (uint32_t i = 0; i < mOpenVRController.Length(); ++i) {
--- a/gfx/vr/gfxVROpenVR.h
+++ b/gfx/vr/gfxVROpenVR.h
@@ -119,16 +119,19 @@ public:
private:
VRControllerManagerOpenVR();
~VRControllerManagerOpenVR();
virtual void HandleButtonPress(uint32_t aControllerIdx,
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<RefPtr<impl::VRControllerOpenVR>> mOpenVRController;
vr::IVRSystem *mVRSystem;
};
} // namespace gfx
} // namespace mozilla