mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 07:42:04 +00:00
Bug 1631635 - Implement IsPositionEmulated for XRInputSource. r=kip,imanol
Differential Revision: https://phabricator.services.mozilla.com/D71678
This commit is contained in:
parent
92bbbc45cb
commit
2b669b7fa8
@ -36,7 +36,8 @@ bool GamepadPose::HasOrientation() const {
|
||||
}
|
||||
|
||||
bool GamepadPose::HasPosition() const {
|
||||
return bool(mPoseState.flags & GamepadCapabilityFlags::Cap_Position);
|
||||
return bool(mPoseState.flags & GamepadCapabilityFlags::Cap_Position) ||
|
||||
bool(mPoseState.flags & GamepadCapabilityFlags::Cap_PositionEmulated);
|
||||
}
|
||||
|
||||
void GamepadPose::GetPosition(JSContext* aJSContext,
|
||||
@ -44,7 +45,8 @@ void GamepadPose::GetPosition(JSContext* aJSContext,
|
||||
ErrorResult& aRv) {
|
||||
const bool valid =
|
||||
mPoseState.isPositionValid &&
|
||||
bool(mPoseState.flags & GamepadCapabilityFlags::Cap_Position);
|
||||
(bool(mPoseState.flags & GamepadCapabilityFlags::Cap_Position) ||
|
||||
bool(mPoseState.flags & GamepadCapabilityFlags::Cap_PositionEmulated));
|
||||
SetFloat32Array(aJSContext, this, aRetval, mPosition,
|
||||
valid ? mPoseState.position : nullptr, 3, aRv);
|
||||
}
|
||||
@ -54,7 +56,8 @@ void GamepadPose::GetLinearVelocity(JSContext* aJSContext,
|
||||
ErrorResult& aRv) {
|
||||
const bool valid =
|
||||
mPoseState.isPositionValid &&
|
||||
bool(mPoseState.flags & GamepadCapabilityFlags::Cap_Position);
|
||||
(bool(mPoseState.flags & GamepadCapabilityFlags::Cap_Position) ||
|
||||
bool(mPoseState.flags & GamepadCapabilityFlags::Cap_PositionEmulated));
|
||||
SetFloat32Array(aJSContext, this, aRetval, mLinearVelocity,
|
||||
valid ? mPoseState.linearVelocity : nullptr, 3, aRv);
|
||||
}
|
||||
|
@ -32,13 +32,19 @@ enum class GamepadCapabilityFlags : uint16_t {
|
||||
*/
|
||||
Cap_LinearAcceleration = 1 << 4,
|
||||
/**
|
||||
* Cap_TargetRaySpacePosition is set if the Gamepad has a target ray space position.
|
||||
* Cap_GripSpacePosition is set if the Gamepad has a grip space position.
|
||||
*/
|
||||
Cap_TargetRaySpacePosition = 1 << 5,
|
||||
Cap_GripSpacePosition = 1 << 5,
|
||||
/**
|
||||
* Cap_PositionEmulated is set if the VRDisplay is capable of setting a
|
||||
* emulated position (e.g. neck model) even if still doesn't support 6DOF
|
||||
* tracking.
|
||||
*/
|
||||
Cap_PositionEmulated = 1 << 6,
|
||||
/**
|
||||
* Cap_All used for validity checking during IPC serialization
|
||||
*/
|
||||
Cap_All = (1 << 6) - 1
|
||||
Cap_All = (1 << 7) - 1
|
||||
};
|
||||
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(GamepadCapabilityFlags)
|
||||
|
@ -49,7 +49,8 @@ VRFieldOfView::VRFieldOfView(nsISupports* aParent,
|
||||
mLeftDegrees(aSrc.leftDegrees) {}
|
||||
|
||||
bool VRDisplayCapabilities::HasPosition() const {
|
||||
return bool(mFlags & gfx::VRDisplayCapabilityFlags::Cap_Position);
|
||||
return bool(mFlags & gfx::VRDisplayCapabilityFlags::Cap_Position) ||
|
||||
bool(mFlags & gfx::VRDisplayCapabilityFlags::Cap_PositionEmulated);
|
||||
}
|
||||
|
||||
bool VRDisplayCapabilities::HasOrientation() const {
|
||||
@ -266,7 +267,9 @@ void VRPose::GetLinearVelocity(JSContext* aCx,
|
||||
JS::MutableHandle<JSObject*> aRetval,
|
||||
ErrorResult& aRv) {
|
||||
const bool valid =
|
||||
bool(mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Position);
|
||||
bool(mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Position) ||
|
||||
bool(mVRState.flags &
|
||||
gfx::VRDisplayCapabilityFlags::Cap_PositionEmulated);
|
||||
SetFloat32Array(aCx, this, aRetval, mLinearVelocity,
|
||||
valid ? mVRState.pose.linearVelocity : nullptr, 3, aRv);
|
||||
}
|
||||
|
@ -160,6 +160,7 @@ XRPose* XRFrame::GetPose(const XRSpace& aSpace, const XRSpace& aBaseSpace,
|
||||
// TODO (Bug 1616393) - Check if poses must be limited:
|
||||
// https://immersive-web.github.io/webxr/#poses-must-be-limited
|
||||
|
||||
const bool emulatedPosition = aSpace.IsPositionEmulated();
|
||||
gfx::Matrix4x4Double base;
|
||||
base.SetRotationFromQuaternion(aBaseSpace.GetEffectiveOriginOrientation());
|
||||
base.PreTranslate(-aBaseSpace.GetEffectiveOriginPosition());
|
||||
@ -167,7 +168,7 @@ XRPose* XRFrame::GetPose(const XRSpace& aSpace, const XRSpace& aBaseSpace,
|
||||
gfx::Matrix4x4Double matrix = aSpace.GetEffectiveOriginTransform() * base;
|
||||
|
||||
RefPtr<XRRigidTransform> transform = new XRRigidTransform(mParent, matrix);
|
||||
RefPtr<XRPose> pose = new XRPose(mParent, transform, false);
|
||||
RefPtr<XRPose> pose = new XRPose(mParent, transform, emulatedPosition);
|
||||
|
||||
return pose;
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "mozilla/dom/XRInputSourceEvent.h"
|
||||
#include "XRNativeOriginViewer.h"
|
||||
#include "XRNativeOriginTracker.h"
|
||||
#include "XRInputSpace.h"
|
||||
|
||||
#include "mozilla/dom/Gamepad.h"
|
||||
#include "mozilla/dom/GamepadManager.h"
|
||||
@ -170,13 +171,11 @@ void XRInputSource::Setup(XRSession* aSession, uint32_t aIndex) {
|
||||
}
|
||||
|
||||
RefPtr<XRNativeOrigin> nativeOriginTargetRay = nullptr;
|
||||
RefPtr<XRNativeOrigin> nativeOriginGrip = nullptr;
|
||||
mTargetRayMode = XRTargetRayMode::Tracked_pointer;
|
||||
switch (controllerState.targetRayMode) {
|
||||
case gfx::TargetRayMode::Gaze:
|
||||
mTargetRayMode = XRTargetRayMode::Gaze;
|
||||
nativeOriginTargetRay = new XRNativeOriginViewer(displayClient);
|
||||
nativeOriginGrip = new XRNativeOriginViewer(displayClient);
|
||||
break;
|
||||
case gfx::TargetRayMode::TrackedPointer:
|
||||
mTargetRayMode = XRTargetRayMode::Tracked_pointer;
|
||||
@ -184,7 +183,6 @@ void XRInputSource::Setup(XRSession* aSession, uint32_t aIndex) {
|
||||
// data internally.
|
||||
nativeOriginTargetRay =
|
||||
new XRNativeOriginTracker(&controllerState.targetRayPose);
|
||||
nativeOriginGrip = new XRNativeOriginTracker(&controllerState.pose);
|
||||
break;
|
||||
case gfx::TargetRayMode::Screen:
|
||||
mTargetRayMode = XRTargetRayMode::Screen;
|
||||
@ -193,10 +191,10 @@ void XRInputSource::Setup(XRSession* aSession, uint32_t aIndex) {
|
||||
MOZ_ASSERT(false && "Undefined TargetRayMode type.");
|
||||
break;
|
||||
}
|
||||
mTargetRaySpace =
|
||||
new XRSpace(aSession->GetParentObject(), aSession, nativeOriginTargetRay);
|
||||
mGripSpace =
|
||||
new XRSpace(aSession->GetParentObject(), aSession, nativeOriginGrip);
|
||||
|
||||
mTargetRaySpace = new XRInputSpace(aSession->GetParentObject(), aSession,
|
||||
nativeOriginTargetRay, aIndex);
|
||||
|
||||
const uint32_t gamepadId =
|
||||
displayInfo.mDisplayID * kVRControllerMaxCount + aIndex;
|
||||
const uint32_t hashKey = GamepadManager::GetGamepadIndexWithServiceType(
|
||||
@ -207,6 +205,10 @@ void XRInputSource::Setup(XRSession* aSession, uint32_t aIndex) {
|
||||
displayInfo.mDisplayID, controllerState.numButtons,
|
||||
controllerState.numAxes, controllerState.numHaptics, 0, 0);
|
||||
mIndex = aIndex;
|
||||
|
||||
if (!mGripSpace) {
|
||||
CreateGripSpace(aSession, controllerState);
|
||||
}
|
||||
}
|
||||
|
||||
void XRInputSource::SetGamepadIsConnected(bool aConnected) {
|
||||
@ -226,6 +228,13 @@ void XRInputSource::Update(XRSession* aSession) {
|
||||
displayInfo.mControllerState[mIndex];
|
||||
MOZ_ASSERT(controllerState.controllerName[0] != '\0');
|
||||
|
||||
// OculusVR and OpenVR controllers need to wait until
|
||||
// update functions to assign GamepadCapabilityFlags::Cap_GripSpacePosition
|
||||
// flag.
|
||||
if (!mGripSpace) {
|
||||
CreateGripSpace(aSession, controllerState);
|
||||
}
|
||||
|
||||
// Update button values.
|
||||
nsTArray<RefPtr<GamepadButton>> buttons;
|
||||
mGamepad->GetButtons(buttons);
|
||||
@ -348,5 +357,20 @@ void XRInputSource::DispatchEvent(const nsAString& aEvent,
|
||||
frame->EndInputSourceEvent();
|
||||
}
|
||||
|
||||
void XRInputSource::CreateGripSpace(
|
||||
XRSession* aSession, const gfx::VRControllerState& controllerState) {
|
||||
MOZ_ASSERT(!mGripSpace);
|
||||
MOZ_ASSERT(aSession && mIndex >= 0 && mGamepad);
|
||||
if (mTargetRayMode == XRTargetRayMode::Tracked_pointer &&
|
||||
controllerState.flags & GamepadCapabilityFlags::Cap_GripSpacePosition) {
|
||||
RefPtr<XRNativeOrigin> nativeOriginGrip = nullptr;
|
||||
nativeOriginGrip = new XRNativeOriginTracker(&controllerState.pose);
|
||||
mGripSpace = new XRInputSpace(aSession->GetParentObject(), aSession,
|
||||
nativeOriginGrip, mIndex);
|
||||
} else {
|
||||
mGripSpace = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -61,6 +61,8 @@ class XRInputSource final : public nsWrapperCache {
|
||||
ActionState_Released = 3
|
||||
};
|
||||
|
||||
void CreateGripSpace(XRSession* aSession,
|
||||
const gfx::VRControllerState& controllerState);
|
||||
void DispatchEvent(const nsAString& aEvent, XRSession* aSession);
|
||||
|
||||
nsTArray<nsString> mProfiles;
|
||||
|
34
dom/vr/XRInputSpace.cpp
Normal file
34
dom/vr/XRInputSpace.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "XRInputSpace.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
XRInputSpace::XRInputSpace(nsIGlobalObject* aParent, XRSession* aSession,
|
||||
XRNativeOrigin* aNativeOrigin,
|
||||
int32_t aControllerIndex)
|
||||
: XRSpace(aParent, aSession, aNativeOrigin), mIndex(aControllerIndex) {}
|
||||
|
||||
bool XRInputSpace::IsPositionEmulated() const {
|
||||
gfx::VRDisplayClient* display = mSession->GetDisplayClient();
|
||||
if (!display) {
|
||||
// When there are no sensors, the position is considered emulated.
|
||||
return true;
|
||||
}
|
||||
const gfx::VRDisplayInfo& displayInfo = display->GetDisplayInfo();
|
||||
const gfx::VRControllerState& controllerState =
|
||||
displayInfo.mControllerState[mIndex];
|
||||
MOZ_ASSERT(controllerState.controllerName[0] != '\0');
|
||||
|
||||
return (
|
||||
(controllerState.flags & GamepadCapabilityFlags::Cap_PositionEmulated) !=
|
||||
GamepadCapabilityFlags::Cap_None);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
33
dom/vr/XRInputSpace.h
Normal file
33
dom/vr/XRInputSpace.h
Normal file
@ -0,0 +1,33 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_XRInputSpace_h_
|
||||
#define mozilla_dom_XRInputSpace_h_
|
||||
|
||||
#include "XRInputSpace.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class XRInputSpace : public XRSpace {
|
||||
public:
|
||||
explicit XRInputSpace(nsIGlobalObject* aParent, XRSession* aSession,
|
||||
XRNativeOrigin* aNativeOrigin,
|
||||
int32_t aControllerIndex);
|
||||
|
||||
virtual bool IsPositionEmulated() const override;
|
||||
|
||||
protected:
|
||||
virtual ~XRInputSpace() = default;
|
||||
|
||||
private:
|
||||
int32_t mIndex;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_XRInputSpace_h_
|
@ -19,7 +19,8 @@ gfx::PointDouble3D XRNativeOriginLocal::GetPosition() {
|
||||
if (!mInitialPositionValid) {
|
||||
const gfx::VRHMDSensorState& sensorState = mDisplay->GetSensorState();
|
||||
gfx::PointDouble3D origin;
|
||||
if (sensorState.flags & VRDisplayCapabilityFlags::Cap_Position) {
|
||||
if (sensorState.flags & VRDisplayCapabilityFlags::Cap_Position ||
|
||||
sensorState.flags & VRDisplayCapabilityFlags::Cap_PositionEmulated) {
|
||||
mInitialPosition.x = sensorState.pose.position[0];
|
||||
mInitialPosition.y = sensorState.pose.position[1];
|
||||
mInitialPosition.z = sensorState.pose.position[2];
|
||||
|
@ -38,7 +38,7 @@ class XRSpace : public DOMEventTargetHelper {
|
||||
gfx::QuaternionDouble GetEffectiveOriginOrientation() const;
|
||||
gfx::PointDouble3D GetEffectiveOriginPosition() const;
|
||||
gfx::Matrix4x4Double GetEffectiveOriginTransform() const;
|
||||
bool IsPositionEmulated() const;
|
||||
virtual bool IsPositionEmulated() const;
|
||||
|
||||
protected:
|
||||
virtual ~XRSpace() = default;
|
||||
|
@ -39,6 +39,7 @@ UNIFIED_SOURCES = [
|
||||
'XRFrame.cpp',
|
||||
'XRInputSource.cpp',
|
||||
'XRInputSourceArray.cpp',
|
||||
'XRInputSpace.cpp',
|
||||
'XRNativeOriginFixed.cpp',
|
||||
'XRNativeOriginLocal.cpp',
|
||||
'XRNativeOriginLocalFloor.cpp',
|
||||
|
@ -119,13 +119,19 @@ enum class ControllerCapabilityFlags : uint16_t {
|
||||
*/
|
||||
Cap_LinearAcceleration = 1 << 4,
|
||||
/**
|
||||
* Cap_TargetRaySpacePosition is set if the Gamepad has a target ray space position.
|
||||
* Cap_TargetRaySpacePosition is set if the Gamepad has a grip space position.
|
||||
*/
|
||||
Cap_TargetRaySpacePosition = 1 << 5,
|
||||
Cap_GripSpacePosition = 1 << 5,
|
||||
/**
|
||||
* Cap_PositionEmulated is set if the XRInputSoruce is capable of setting a
|
||||
* emulated position (e.g. neck model) even if still doesn't support 6DOF
|
||||
* tracking.
|
||||
*/
|
||||
Cap_PositionEmulated = 1 << 6,
|
||||
/**
|
||||
* Cap_All used for validity checking during IPC serialization
|
||||
*/
|
||||
Cap_All = (1 << 6) - 1
|
||||
Cap_All = (1 << 7) - 1
|
||||
};
|
||||
|
||||
#endif // ifndef MOZILLA_INTERNAL_API
|
||||
|
@ -1266,7 +1266,7 @@ void OculusSession::UpdateControllerPose(VRSystemState& aState,
|
||||
controllerState.flags |=
|
||||
dom::GamepadCapabilityFlags::Cap_LinearAcceleration;
|
||||
controllerState.flags |=
|
||||
dom::GamepadCapabilityFlags::Cap_TargetRaySpacePosition;
|
||||
dom::GamepadCapabilityFlags::Cap_GripSpacePosition;
|
||||
}
|
||||
|
||||
if (bNewController || trackingState.HandStatusFlags[handIdx] &
|
||||
@ -1409,7 +1409,8 @@ void OculusSession::UpdateControllerInputs(VRSystemState& aState,
|
||||
|
||||
MOZ_ASSERT(axisIdx == kNumOculusAxes);
|
||||
}
|
||||
SetControllerSelectionAndSqueezeFrameId(controllerState, aState.displayState.lastSubmittedFrameId);
|
||||
SetControllerSelectionAndSqueezeFrameId(
|
||||
controllerState, aState.displayState.lastSubmittedFrameId);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1047,7 +1047,8 @@ void OpenVRSession::UpdateControllerButtons(VRSystemState& aState) {
|
||||
VRControllerState& controllerState = aState.controllerState[stateIndex];
|
||||
controllerState.hand = GetControllerHandFromControllerRole(role);
|
||||
mControllerMapper->UpdateButtons(controllerState, mControllerHand[role]);
|
||||
SetControllerSelectionAndSqueezeFrameId(controllerState, aState.displayState.lastSubmittedFrameId);
|
||||
SetControllerSelectionAndSqueezeFrameId(
|
||||
controllerState, aState.displayState.lastSubmittedFrameId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1072,9 +1073,10 @@ void OpenVRSession::UpdateControllerPoses(VRSystemState& aState) {
|
||||
} else {
|
||||
const ::vr::TrackedDevicePose_t& pose = poseData.pose;
|
||||
if (pose.bDeviceIsConnected) {
|
||||
controllerState.flags = (dom::GamepadCapabilityFlags::Cap_Orientation |
|
||||
dom::GamepadCapabilityFlags::Cap_Position |
|
||||
dom::GamepadCapabilityFlags::Cap_TargetRaySpacePosition);
|
||||
controllerState.flags =
|
||||
(dom::GamepadCapabilityFlags::Cap_Orientation |
|
||||
dom::GamepadCapabilityFlags::Cap_Position |
|
||||
dom::GamepadCapabilityFlags::Cap_GripSpacePosition);
|
||||
} else {
|
||||
controllerState.flags = dom::GamepadCapabilityFlags::Cap_None;
|
||||
}
|
||||
@ -1119,7 +1121,7 @@ void OpenVRSession::UpdateControllerPoses(VRSystemState& aState) {
|
||||
|
||||
// Calculate its target ray space by shifting degrees in x-axis
|
||||
// for ergonomic.
|
||||
const float kPointerAngleDegrees = -0.698; // 40 degrees.
|
||||
const float kPointerAngleDegrees = -0.698; // 40 degrees.
|
||||
gfx::Matrix4x4 rayMtx(m);
|
||||
rayMtx.RotateX(kPointerAngleDegrees);
|
||||
gfx::Quaternion rayRot;
|
||||
|
Loading…
Reference in New Issue
Block a user