blob: e5a389abe64fbdfeb6c3f189089d3c3dceabe0f9 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/modules/xr/xr_bounded_reference_space.h"
#include "device/vr/public/mojom/vr_service.mojom-blink.h"
#include "third_party/blink/renderer/modules/xr/xr_reference_space_event.h"
#include "third_party/blink/renderer/modules/xr/xr_rigid_transform.h"
#include "third_party/blink/renderer/modules/xr/xr_session.h"
#include "third_party/blink/renderer/modules/xr/xr_utils.h"
namespace blink {
XRBoundedReferenceSpace::XRBoundedReferenceSpace(XRSession* session)
: XRReferenceSpace(session, Type::kTypeBoundedFloor) {}
XRBoundedReferenceSpace::XRBoundedReferenceSpace(
XRSession* session,
XRRigidTransform* origin_offset)
: XRReferenceSpace(session, origin_offset, Type::kTypeBoundedFloor) {}
XRBoundedReferenceSpace::~XRBoundedReferenceSpace() = default;
// No default pose for bounded reference spaces.
std::unique_ptr<TransformationMatrix>
XRBoundedReferenceSpace::DefaultViewerPose() {
return nullptr;
}
void XRBoundedReferenceSpace::EnsureUpdated() {
// Check first to see if the stage parameters have updated since the last
// call. We only need to update the transform and bounds if it has.
if (stage_parameters_id_ == session()->StageParametersId())
return;
stage_parameters_id_ = session()->StageParametersId();
const device::mojom::blink::VRDisplayInfoPtr& display_info =
session()->GetVRDisplayInfo();
if (display_info && display_info->stage_parameters) {
// Use the transform given by xrDisplayInfo's stage_parameters if available.
bounded_space_from_mojo_ = std::make_unique<TransformationMatrix>(
display_info->stage_parameters->standing_transform.matrix());
// In order to ensure that the bounds continue to line up with the user's
// physical environment we need to transform by the inverse of the
// originOffset. TODO(https://crbug.com/1008466): move originOffset to
// separate class? If yes, that class would need to apply a transform
// in the boundsGeometry accessor.
TransformationMatrix bounds_transform = InverseOriginOffsetMatrix();
if (display_info->stage_parameters->bounds) {
bounds_geometry_.clear();
for (const auto& bound : *(display_info->stage_parameters->bounds)) {
FloatPoint3D p =
bounds_transform.MapPoint(FloatPoint3D(bound.x, 0.0, bound.z));
bounds_geometry_.push_back(
DOMPointReadOnly::Create(p.X(), p.Y(), p.Z(), 1.0));
}
} else {
double hx = display_info->stage_parameters->size_x * 0.5;
double hz = display_info->stage_parameters->size_z * 0.5;
FloatPoint3D a = bounds_transform.MapPoint(FloatPoint3D(hx, 0.0, -hz));
FloatPoint3D b = bounds_transform.MapPoint(FloatPoint3D(hx, 0.0, hz));
FloatPoint3D c = bounds_transform.MapPoint(FloatPoint3D(-hx, 0.0, hz));
FloatPoint3D d = bounds_transform.MapPoint(FloatPoint3D(-hx, 0.0, -hz));
bounds_geometry_.clear();
bounds_geometry_.push_back(
DOMPointReadOnly::Create(a.X(), a.Y(), a.Z(), 1.0));
bounds_geometry_.push_back(
DOMPointReadOnly::Create(b.X(), b.Y(), b.Z(), 1.0));
bounds_geometry_.push_back(
DOMPointReadOnly::Create(c.X(), c.Y(), c.Z(), 1.0));
bounds_geometry_.push_back(
DOMPointReadOnly::Create(d.X(), d.Y(), d.Z(), 1.0));
}
} else {
// If stage parameters aren't available set the transform to null, which
// will subsequently cause this reference space to return null poses.
bounded_space_from_mojo_.reset();
bounds_geometry_.clear();
}
DispatchEvent(*XRReferenceSpaceEvent::Create(event_type_names::kReset, this));
}
// Gets the pose of the mojo origin in this reference space, corresponding to a
// transform from mojo coordinates to reference space coordinates. Ideally in
// the future this reference space can be used without additional transforms,
// with the various XR backends returning poses already in the right space.
std::unique_ptr<TransformationMatrix> XRBoundedReferenceSpace::SpaceFromMojo(
const TransformationMatrix& mojo_from_viewer) {
EnsureUpdated();
// If the reference space has a transform apply it to the base pose and return
// that, otherwise return null.
if (bounded_space_from_mojo_) {
std::unique_ptr<TransformationMatrix> space_from_mojo(
std::make_unique<TransformationMatrix>(*bounded_space_from_mojo_));
return space_from_mojo;
}
return nullptr;
}
HeapVector<Member<DOMPointReadOnly>> XRBoundedReferenceSpace::boundsGeometry() {
EnsureUpdated();
return bounds_geometry_;
}
base::Optional<XRNativeOriginInformation>
XRBoundedReferenceSpace::NativeOrigin() const {
return XRNativeOriginInformation::Create(this);
}
void XRBoundedReferenceSpace::Trace(blink::Visitor* visitor) {
visitor->Trace(bounds_geometry_);
XRReferenceSpace::Trace(visitor);
}
void XRBoundedReferenceSpace::OnReset() {
// Anything that would cause an external source to try to tell us that we've
// been reset should have also updated the stage_parameters, and thus caused
// us to reset via that mechanism instead.
}
XRBoundedReferenceSpace* XRBoundedReferenceSpace::cloneWithOriginOffset(
XRRigidTransform* origin_offset) {
return MakeGarbageCollected<XRBoundedReferenceSpace>(this->session(),
origin_offset);
}
} // namespace blink