Commit 8081952c authored by Bill Orr's avatar Bill Orr Committed by Commit Bot

Fix Windows mixed reality tracking loss handling

When tracking is regained, we should go back to the original origin.
This means we should use an anchor rather than a
SpatialStationaryFrameOfReference.

Bug: 965528
Change-Id: I8183b141cf4f9931a50866da4f2f97b54d43289e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1633990Reviewed-by: default avatarAlexander Cooper <alcooper@chromium.org>
Commit-Queue: Bill Orr <billorr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#664400}
parent 732a05e3
......@@ -249,7 +249,8 @@ void MixedRealityRenderLoop::StopRuntime() {
if (window_)
ShowWindow(window_->hwnd(), SW_HIDE);
holographic_space_ = nullptr;
origin_ = nullptr;
anchor_origin_ = nullptr;
stationary_origin_ = nullptr;
last_origin_from_attached_ = base::nullopt;
attached_ = nullptr;
ClearStageStatics();
......@@ -298,7 +299,11 @@ void MixedRealityRenderLoop::InitializeOrigin() {
if (!stationary_frame)
return;
origin_ = stationary_frame->CoordinateSystem();
stationary_origin_ = stationary_frame->CoordinateSystem();
// Instead of using the stationary_frame, use an anchor.
anchor_origin_ =
WMRSpatialAnchorFactory::TryCreateRelativeTo(stationary_origin_.get());
}
void MixedRealityRenderLoop::ClearStageOrigin() {
......@@ -387,7 +392,8 @@ void MixedRealityRenderLoop::OnSessionStart() {
LogViewerType(VrViewerType::WINDOWS_MIXED_REALITY_UNKNOWN);
// Each session should start with new origins.
origin_ = nullptr;
stationary_origin_ = nullptr;
anchor_origin_ = nullptr;
attached_ = nullptr;
last_origin_from_attached_ = base::nullopt;
......@@ -427,12 +433,13 @@ mojom::XRGamepadDataPtr MixedRealityRenderLoop::GetNextGamepadData() {
return nullptr;
}
if (!origin_) {
if (!anchor_origin_) {
WMRLogging::TraceError(WMRErrorLocation::kGamepadMissingOrigin);
return nullptr;
}
return input_helper_->GetWebVRGamepadData(origin_.get(), timestamp_.get());
return input_helper_->GetWebVRGamepadData(anchor_origin_.get(),
timestamp_.get());
}
struct EyeToWorldDecomposed {
......@@ -586,7 +593,7 @@ void MixedRealityRenderLoop::UpdateWMRDataForNextFrame() {
return;
// Make sure we have an origin.
if (!origin_) {
if (!anchor_origin_) {
InitializeOrigin();
}
......@@ -681,10 +688,11 @@ bool MixedRealityRenderLoop::UpdateStageParameters() {
// SpatialStageFrameOfReference.CurrentChanged to also re-calculate this.
bool changed = false;
if (stage_transform_needs_updating_) {
if (!(stage_origin_ && origin_) && current_display_info_->stageParameters) {
if (!(stage_origin_ && anchor_origin_) &&
current_display_info_->stageParameters) {
changed = true;
current_display_info_->stageParameters = nullptr;
} else if (stage_origin_ && origin_) {
} else if (stage_origin_ && anchor_origin_) {
changed = true;
current_display_info_->stageParameters = nullptr;
......@@ -692,7 +700,8 @@ bool MixedRealityRenderLoop::UpdateStageParameters() {
mojom::VRStageParameters::New();
Matrix4x4 origin_to_stage;
if (!origin_->TryGetTransformTo(stage_origin_.get(), &origin_to_stage)) {
if (!anchor_origin_->TryGetTransformTo(stage_origin_.get(),
&origin_to_stage)) {
// We failed to get a transform between the two, so force a
// recalculation of the stage origin and leave the stageParameters null.
ClearStageOrigin();
......@@ -728,7 +737,7 @@ mojom::XRFrameDataPtr MixedRealityRenderLoop::GetNextFrameData() {
mojom::XRFrameDataPtr ret =
CreateDefaultFrameData(timestamp_.get(), next_frame_id_);
if ((!attached_ && !origin_) || !pose_) {
if ((!attached_ && !anchor_origin_) || !pose_) {
TRACE_EVENT_INSTANT0("xr", "No origin or no pose",
TRACE_EVENT_SCOPE_THREAD);
// If we don't have an origin or pose for this frame, we can still give out
......@@ -743,13 +752,15 @@ mojom::XRFrameDataPtr MixedRealityRenderLoop::GetNextFrameData() {
ABI::Windows::Graphics::Holographic::HolographicStereoTransform view;
bool got_view = false;
if (origin_ && pose_->TryGetViewTransform(origin_.get(), &view)) {
if (anchor_origin_ &&
pose_->TryGetViewTransform(anchor_origin_.get(), &view)) {
got_view = true;
// TODO(http://crbug.com/931393): Send down emulated_position_, and report
// reset events when this changes.
emulated_position_ = false;
ABI::Windows::Foundation::Numerics::Matrix4x4 transform;
if (attached_coordinates->TryGetTransformTo(origin_.get(), &transform)) {
if (attached_coordinates->TryGetTransformTo(anchor_origin_.get(),
&transform)) {
last_origin_from_attached_ = gfx::Transform(
transform.M11, transform.M21, transform.M31, transform.M41,
transform.M12, transform.M22, transform.M32, transform.M42,
......@@ -823,7 +834,7 @@ mojom::XRFrameDataPtr MixedRealityRenderLoop::GetNextFrameData() {
}
ret->pose->input_state =
input_helper_->GetInputState(origin_.get(), timestamp_.get());
input_helper_->GetInputState(anchor_origin_.get(), timestamp_.get());
if (emulated_position_ && last_origin_from_attached_) {
gfx::DecomposedTransform attached_from_view_decomp;
......
......@@ -90,8 +90,9 @@ class MixedRealityRenderLoop : public XRCompositorCommon {
std::unique_ptr<WMRHolographicSpace> holographic_space_;
std::unique_ptr<WMRStageOrigin> spatial_stage_;
std::unique_ptr<WMRCoordinateSystem> origin_;
std::unique_ptr<WMRCoordinateSystem> stationary_origin_;
std::unique_ptr<WMRCoordinateSystem> stage_origin_;
std::unique_ptr<WMRCoordinateSystem> anchor_origin_;
bool stage_transform_needs_updating_ = false;
std::unique_ptr<WMRAttachedOrigin> attached_;
bool emulated_position_ = false;
......
......@@ -25,6 +25,8 @@ using SpatialMovementRange =
using ABI::Windows::Foundation::IEventHandler;
using ABI::Windows::Foundation::IReference;
using ABI::Windows::Graphics::Holographic::IHolographicSpace;
using ABI::Windows::Perception::Spatial::ISpatialAnchor;
using ABI::Windows::Perception::Spatial::ISpatialAnchorStatics;
using ABI::Windows::Perception::Spatial::ISpatialCoordinateSystem;
using ABI::Windows::Perception::Spatial::ISpatialLocator;
using ABI::Windows::Perception::Spatial::
......@@ -122,6 +124,34 @@ std::unique_ptr<WMRStageStatics> WMRStageStaticsFactory::Create() {
return std::make_unique<WMRStageStaticsImpl>(stage_statics);
}
std::unique_ptr<WMRCoordinateSystem>
WMRSpatialAnchorFactory::TryCreateRelativeTo(WMRCoordinateSystem* origin) {
if (MixedRealityDeviceStatics::ShouldUseMocks()) {
MockWMRStationaryOrigin origin;
return origin.CoordinateSystem();
}
ComPtr<ISpatialAnchorStatics> anchor_statics;
base::win::ScopedHString spatial_anchor_string =
base::win::ScopedHString::Create(
RuntimeClass_Windows_Perception_Spatial_SpatialAnchor);
HRESULT hr = base::win::RoGetActivationFactory(spatial_anchor_string.get(),
IID_PPV_ARGS(&anchor_statics));
if (FAILED(hr))
return nullptr;
ComPtr<ISpatialAnchor> anchor;
hr = anchor_statics->TryCreateRelativeTo(origin->GetRawPtr(), &anchor);
if (FAILED(hr) || !anchor)
return nullptr;
// Make a WMRCoordinateSystemImpl wrapping the coordinate system.
ComPtr<ISpatialCoordinateSystem> coordinate_system;
hr = anchor->get_CoordinateSystem(&coordinate_system);
DCHECK(SUCCEEDED(hr));
return std::make_unique<WMRCoordinateSystemImpl>(coordinate_system);
}
std::unique_ptr<WMRInputManager> WMRInputManagerFactory::GetForWindow(
HWND hwnd) {
if (MixedRealityDeviceStatics::ShouldUseMocks()) {
......
......@@ -25,6 +25,12 @@ class WMRStageStaticsFactory {
static std::unique_ptr<WMRStageStatics> Create();
};
class WMRSpatialAnchorFactory {
public:
static std::unique_ptr<WMRCoordinateSystem> TryCreateRelativeTo(
WMRCoordinateSystem* origin);
};
class WMRInputManagerFactory {
public:
static std::unique_ptr<WMRInputManager> GetForWindow(HWND hwnd);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment