Commit cb06ba9e authored by Klaus Weidner's avatar Klaus Weidner Committed by Commit Bot

Refactor WebXR reference space and pose internals

Avoid using generic names such as "base pose" or "transform", and try to
always specifically say which two spaces are connected by transforms.

Use the B_from_A naming convention where possible, so that transforms
can be chained naturally.

Bug: 1008102
Change-Id: I74988f89340375197017f9f518f69d4fd03e7d76
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1825585Reviewed-by: default avatarAlexander Cooper <alcooper@chromium.org>
Reviewed-by: default avatarPiotr Bialecki <bialpio@chromium.org>
Commit-Queue: Klaus Weidner <klausw@chromium.org>
Cr-Commit-Position: refs/heads/master@{#700403}
parent 9b3b4da6
...@@ -23,7 +23,8 @@ XRBoundedReferenceSpace::XRBoundedReferenceSpace( ...@@ -23,7 +23,8 @@ XRBoundedReferenceSpace::XRBoundedReferenceSpace(
XRBoundedReferenceSpace::~XRBoundedReferenceSpace() = default; XRBoundedReferenceSpace::~XRBoundedReferenceSpace() = default;
// No default pose for bounded reference spaces. // No default pose for bounded reference spaces.
std::unique_ptr<TransformationMatrix> XRBoundedReferenceSpace::DefaultPose() { std::unique_ptr<TransformationMatrix>
XRBoundedReferenceSpace::DefaultViewerPose() {
return nullptr; return nullptr;
} }
...@@ -40,12 +41,14 @@ void XRBoundedReferenceSpace::EnsureUpdated() { ...@@ -40,12 +41,14 @@ void XRBoundedReferenceSpace::EnsureUpdated() {
if (display_info && display_info->stage_parameters) { if (display_info && display_info->stage_parameters) {
// Use the transform given by xrDisplayInfo's stage_parameters if available. // Use the transform given by xrDisplayInfo's stage_parameters if available.
floor_level_transform_ = std::make_unique<TransformationMatrix>( bounded_space_from_mojo_ = std::make_unique<TransformationMatrix>(
display_info->stage_parameters->standing_transform.matrix()); display_info->stage_parameters->standing_transform.matrix());
// In order to ensure that the bounds continue to line up with the user's // 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 // physical environment we need to transform by the inverse of the
// originOffset. // 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(); TransformationMatrix bounds_transform = InverseOriginOffsetMatrix();
if (display_info->stage_parameters->bounds) { if (display_info->stage_parameters->bounds) {
...@@ -78,31 +81,28 @@ void XRBoundedReferenceSpace::EnsureUpdated() { ...@@ -78,31 +81,28 @@ void XRBoundedReferenceSpace::EnsureUpdated() {
} else { } else {
// If stage parameters aren't available set the transform to null, which // If stage parameters aren't available set the transform to null, which
// will subsequently cause this reference space to return null poses. // will subsequently cause this reference space to return null poses.
floor_level_transform_.reset(); bounded_space_from_mojo_.reset();
bounds_geometry_.clear(); bounds_geometry_.clear();
} }
DispatchEvent(*XRReferenceSpaceEvent::Create(event_type_names::kReset, this)); DispatchEvent(*XRReferenceSpaceEvent::Create(event_type_names::kReset, this));
} }
// Transforms a given pose from a "base" reference space used by the XR // Gets the pose of the mojo origin in this reference space, corresponding to a
// service to the bounded (floor level) reference space. Ideally in the future // transform from mojo coordinates to reference space coordinates. Ideally in
// this reference space can be used without additional transforms, with // the future this reference space can be used without additional transforms,
// the various XR backends returning poses already in the right space. // with the various XR backends returning poses already in the right space.
std::unique_ptr<TransformationMatrix> std::unique_ptr<TransformationMatrix> XRBoundedReferenceSpace::SpaceFromMojo(
XRBoundedReferenceSpace::TransformBasePose( const TransformationMatrix& mojo_from_viewer) {
const TransformationMatrix& base_pose) {
EnsureUpdated(); EnsureUpdated();
// If the reference space has a transform apply it to the base pose and return // If the reference space has a transform apply it to the base pose and return
// that, otherwise return null. // that, otherwise return null.
if (floor_level_transform_) { if (bounded_space_from_mojo_) {
std::unique_ptr<TransformationMatrix> pose( std::unique_ptr<TransformationMatrix> space_from_mojo(
std::make_unique<TransformationMatrix>(*floor_level_transform_)); std::make_unique<TransformationMatrix>(*bounded_space_from_mojo_));
pose->Multiply(base_pose); return space_from_mojo;
return pose;
} }
return nullptr; return nullptr;
} }
......
...@@ -19,9 +19,9 @@ class XRBoundedReferenceSpace final : public XRReferenceSpace { ...@@ -19,9 +19,9 @@ class XRBoundedReferenceSpace final : public XRReferenceSpace {
XRBoundedReferenceSpace(XRSession*, XRRigidTransform*); XRBoundedReferenceSpace(XRSession*, XRRigidTransform*);
~XRBoundedReferenceSpace() override; ~XRBoundedReferenceSpace() override;
std::unique_ptr<TransformationMatrix> DefaultPose() override; std::unique_ptr<TransformationMatrix> DefaultViewerPose() override;
std::unique_ptr<TransformationMatrix> TransformBasePose( std::unique_ptr<TransformationMatrix> SpaceFromMojo(
const TransformationMatrix& base_pose) override; const TransformationMatrix& mojo_from_viewer) override;
HeapVector<Member<DOMPointReadOnly>> boundsGeometry(); HeapVector<Member<DOMPointReadOnly>> boundsGeometry();
...@@ -36,7 +36,7 @@ class XRBoundedReferenceSpace final : public XRReferenceSpace { ...@@ -36,7 +36,7 @@ class XRBoundedReferenceSpace final : public XRReferenceSpace {
void EnsureUpdated(); void EnsureUpdated();
HeapVector<Member<DOMPointReadOnly>> bounds_geometry_; HeapVector<Member<DOMPointReadOnly>> bounds_geometry_;
std::unique_ptr<TransformationMatrix> floor_level_transform_; std::unique_ptr<TransformationMatrix> bounded_space_from_mojo_;
unsigned int stage_parameters_id_ = 0; unsigned int stage_parameters_id_ = 0;
}; };
......
...@@ -111,11 +111,12 @@ void XRCanvasInputProvider::UpdateInputSource(PointerEvent* event) { ...@@ -111,11 +111,12 @@ void XRCanvasInputProvider::UpdateInputSource(PointerEvent* event) {
// projection matrix to get a 3D point in space, which is then returned in // projection matrix to get a 3D point in space, which is then returned in
// matrix form so we can use it as an XRInputSource's pointerMatrix. // matrix form so we can use it as an XRInputSource's pointerMatrix.
XRViewData& view = session_->views()[0]; XRViewData& view = session_->views()[0];
TransformationMatrix pointer_transform_matrix = view.UnprojectPointer( TransformationMatrix viewer_from_pointer = view.UnprojectPointer(
element_x, element_y, canvas_->OffsetWidth(), canvas_->OffsetHeight()); element_x, element_y, canvas_->OffsetWidth(), canvas_->OffsetHeight());
// Update the input source's pointer matrix. // Update the pointer pose in input space. For screen tapping, input
input_source_->SetPointerTransformMatrix(&pointer_transform_matrix); // space is equivalent to viewer space.
input_source_->SetInputFromPointer(&viewer_from_pointer);
} }
void XRCanvasInputProvider::ClearInputSource() { void XRCanvasInputProvider::ClearInputSource() {
......
...@@ -59,7 +59,8 @@ XRViewerPose* XRFrame::getViewerPose(XRReferenceSpace* reference_space, ...@@ -59,7 +59,8 @@ XRViewerPose* XRFrame::getViewerPose(XRReferenceSpace* reference_space,
session_->LogGetPose(); session_->LogGetPose();
std::unique_ptr<TransformationMatrix> pose = std::unique_ptr<TransformationMatrix> pose =
reference_space->GetViewerPoseMatrix(base_pose_matrix_.get()); reference_space->SpaceFromViewerWithDefaultAndOffset(
mojo_from_viewer_.get());
if (!pose) { if (!pose) {
return nullptr; return nullptr;
} }
...@@ -102,11 +103,11 @@ XRPose* XRFrame::getPose(XRSpace* space_A, ...@@ -102,11 +103,11 @@ XRPose* XRFrame::getPose(XRSpace* space_A,
return nullptr; return nullptr;
} }
return space_A->getPose(space_B, base_pose_matrix_.get()); return space_A->getPose(space_B, mojo_from_viewer_.get());
} }
void XRFrame::SetBasePoseMatrix(const TransformationMatrix& base_pose_matrix) { void XRFrame::SetMojoFromViewer(const TransformationMatrix& mojo_from_viewer) {
base_pose_matrix_ = std::make_unique<TransformationMatrix>(base_pose_matrix); mojo_from_viewer_ = std::make_unique<TransformationMatrix>(mojo_from_viewer);
} }
void XRFrame::Deactivate() { void XRFrame::Deactivate() {
......
...@@ -41,7 +41,7 @@ class XRFrame final : public ScriptWrappable { ...@@ -41,7 +41,7 @@ class XRFrame final : public ScriptWrappable {
XRWorldInformation* worldInformation() const { return world_information_; } XRWorldInformation* worldInformation() const { return world_information_; }
XRAnchorSet* trackedAnchors() const; XRAnchorSet* trackedAnchors() const;
void SetBasePoseMatrix(const TransformationMatrix&); void SetMojoFromViewer(const TransformationMatrix&);
void Trace(blink::Visitor*) override; void Trace(blink::Visitor*) override;
...@@ -64,8 +64,9 @@ class XRFrame final : public ScriptWrappable { ...@@ -64,8 +64,9 @@ class XRFrame final : public ScriptWrappable {
const Member<XRSession> session_; const Member<XRSession> session_;
// Maps from mojo space to headset space. // Viewer pose in mojo space, the matrix maps from viewer (headset) space to
std::unique_ptr<TransformationMatrix> base_pose_matrix_; // mojo space.
std::unique_ptr<TransformationMatrix> mojo_from_viewer_;
// Frames are only active during callbacks. getPose and getViewerPose should // Frames are only active during callbacks. getPose and getViewerPose should
// only be called from JS on active frames. // only be called from JS on active frames.
......
...@@ -15,7 +15,7 @@ XRGripSpace::XRGripSpace(XRSession* session, XRInputSource* source) ...@@ -15,7 +15,7 @@ XRGripSpace::XRGripSpace(XRSession* session, XRInputSource* source)
: XRSpace(session), input_source_(source) {} : XRSpace(session), input_source_(source) {}
XRPose* XRGripSpace::getPose(XRSpace* other_space, XRPose* XRGripSpace::getPose(XRSpace* other_space,
const TransformationMatrix* base_pose_matrix) { const TransformationMatrix* mojo_from_viewer) {
// Grip is only available when using tracked pointer for input. // Grip is only available when using tracked pointer for input.
if (input_source_->TargetRayMode() != if (input_source_->TargetRayMode() !=
device::mojom::XRTargetRayMode::POINTING) { device::mojom::XRTargetRayMode::POINTING) {
...@@ -23,23 +23,27 @@ XRPose* XRGripSpace::getPose(XRSpace* other_space, ...@@ -23,23 +23,27 @@ XRPose* XRGripSpace::getPose(XRSpace* other_space,
} }
// Make sure the required pose matrices are available. // Make sure the required pose matrices are available.
if (!base_pose_matrix || !input_source_->BasePose()) { if (!mojo_from_viewer || !input_source_->MojoFromInput()) {
return nullptr; return nullptr;
} }
std::unique_ptr<TransformationMatrix> grip_pose = // Calculate grip pose in other_space, aka other_from_grip
other_space->TransformBaseInputPose(*(input_source_->BasePose()), std::unique_ptr<TransformationMatrix> other_from_grip =
*base_pose_matrix); other_space->SpaceFromInputForViewer(*(input_source_->MojoFromInput()),
*mojo_from_viewer);
if (!grip_pose) { if (!other_from_grip) {
return nullptr; return nullptr;
} }
// Account for any changes made to the reference space's origin offset so // Account for any changes made to the reference space's origin offset so
// that things like teleportation works. // that things like teleportation works.
TransformationMatrix adjusted_pose = //
other_space->InverseOriginOffsetMatrix().Multiply(*grip_pose); // This is offset_from_grip = offset_from_other * other_from_grip,
return MakeGarbageCollected<XRPose>(adjusted_pose, // where offset_from_other = inverse(other_from_offset).
// TODO(https://crbug.com/1008466): move originOffset to separate class?
TransformationMatrix offset_from_grip =
other_space->InverseOriginOffsetMatrix().Multiply(*other_from_grip);
return MakeGarbageCollected<XRPose>(offset_from_grip,
input_source_->emulatedPosition()); input_source_->emulatedPosition());
} }
......
...@@ -81,7 +81,7 @@ XRInputSource* XRInputSource::CreateOrUpdateFrom( ...@@ -81,7 +81,7 @@ XRInputSource* XRInputSource::CreateOrUpdateFrom(
updated_source->state_.handedness = desc->handedness; updated_source->state_.handedness = desc->handedness;
updated_source->state_.emulated_position = desc->emulated_position; updated_source->state_.emulated_position = desc->emulated_position;
updated_source->pointer_transform_matrix_ = updated_source->input_from_pointer_ =
TryGetTransformationMatrix(desc->pointer_offset); TryGetTransformationMatrix(desc->pointer_offset);
updated_source->state_.profiles.clear(); updated_source->state_.profiles.clear();
...@@ -90,7 +90,7 @@ XRInputSource* XRInputSource::CreateOrUpdateFrom( ...@@ -90,7 +90,7 @@ XRInputSource* XRInputSource::CreateOrUpdateFrom(
} }
} }
updated_source->base_pose_matrix_ = TryGetTransformationMatrix(state->grip); updated_source->mojo_from_input_ = TryGetTransformationMatrix(state->grip);
return updated_source; return updated_source;
} }
...@@ -114,10 +114,10 @@ XRInputSource::XRInputSource(const XRInputSource& other) ...@@ -114,10 +114,10 @@ XRInputSource::XRInputSource(const XRInputSource& other)
MakeGarbageCollected<XRTargetRaySpace>(other.session_, this)), MakeGarbageCollected<XRTargetRaySpace>(other.session_, this)),
grip_space_(MakeGarbageCollected<XRGripSpace>(other.session_, this)), grip_space_(MakeGarbageCollected<XRGripSpace>(other.session_, this)),
gamepad_(other.gamepad_), gamepad_(other.gamepad_),
base_pose_matrix_( mojo_from_input_(
TryGetTransformationMatrix(other.base_pose_matrix_.get())), TryGetTransformationMatrix(other.mojo_from_input_.get())),
pointer_transform_matrix_( input_from_pointer_(
TryGetTransformationMatrix(other.pointer_transform_matrix_.get())) {} TryGetTransformationMatrix(other.input_from_pointer_.get())) {}
const String XRInputSource::handedness() const { const String XRInputSource::handedness() const {
switch (state_.handedness) { switch (state_.handedness) {
...@@ -186,10 +186,9 @@ bool XRInputSource::InvalidatesSameObject( ...@@ -186,10 +186,9 @@ bool XRInputSource::InvalidatesSameObject(
return false; return false;
} }
void XRInputSource::SetPointerTransformMatrix( void XRInputSource::SetInputFromPointer(
const TransformationMatrix* pointer_transform_matrix) { const TransformationMatrix* input_from_pointer) {
pointer_transform_matrix_ = input_from_pointer_ = TryGetTransformationMatrix(input_from_pointer);
TryGetTransformationMatrix(pointer_transform_matrix);
} }
void XRInputSource::SetGamepadConnected(bool state) { void XRInputSource::SetGamepadConnected(bool state) {
......
...@@ -59,7 +59,7 @@ class XRInputSource : public ScriptWrappable, public Gamepad::Client { ...@@ -59,7 +59,7 @@ class XRInputSource : public ScriptWrappable, public Gamepad::Client {
uint32_t source_id() const { return state_.source_id; } uint32_t source_id() const { return state_.source_id; }
void SetPointerTransformMatrix(const TransformationMatrix*); void SetInputFromPointer(const TransformationMatrix*);
void SetGamepadConnected(bool state); void SetGamepadConnected(bool state);
// Gamepad::Client // Gamepad::Client
...@@ -74,11 +74,11 @@ class XRInputSource : public ScriptWrappable, public Gamepad::Client { ...@@ -74,11 +74,11 @@ class XRInputSource : public ScriptWrappable, public Gamepad::Client {
device::mojom::XRTargetRayMode TargetRayMode() const { device::mojom::XRTargetRayMode TargetRayMode() const {
return state_.target_ray_mode; return state_.target_ray_mode;
} }
const TransformationMatrix* BasePose() const { const TransformationMatrix* MojoFromInput() const {
return base_pose_matrix_.get(); return mojo_from_input_.get();
} }
const TransformationMatrix* PointerTransform() const { const TransformationMatrix* InputFromPointer() const {
return pointer_transform_matrix_.get(); return input_from_pointer_.get();
} }
void OnSelectStart(); void OnSelectStart();
...@@ -132,11 +132,14 @@ class XRInputSource : public ScriptWrappable, public Gamepad::Client { ...@@ -132,11 +132,14 @@ class XRInputSource : public ScriptWrappable, public Gamepad::Client {
Member<XRGripSpace> grip_space_; Member<XRGripSpace> grip_space_;
Member<Gamepad> gamepad_; Member<Gamepad> gamepad_;
std::unique_ptr<TransformationMatrix> base_pose_matrix_; // Input device pose in mojo space. This is the grip pose for
// tracked controllers, and the viewer pose for screen input.
std::unique_ptr<TransformationMatrix> mojo_from_input_;
// This is the transform to apply to the base_pose_matrix_ to get the pointer // Pointer pose in input device space, this is the transform to apply to
// matrix. In most cases it should be static. // mojo_from_input_ to get the pointer matrix. In most cases it should be
std::unique_ptr<TransformationMatrix> pointer_transform_matrix_; // static.
std::unique_ptr<TransformationMatrix> input_from_pointer_;
}; };
} // namespace blink } // namespace blink
......
...@@ -21,14 +21,14 @@ class XRObjectSpace : public XRSpace { ...@@ -21,14 +21,14 @@ class XRObjectSpace : public XRSpace {
explicit XRObjectSpace(XRSession* session, const T* object) explicit XRObjectSpace(XRSession* session, const T* object)
: XRSpace(session), object_(object) {} : XRSpace(session), object_(object) {}
std::unique_ptr<TransformationMatrix> GetTransformToMojoSpace() override { std::unique_ptr<TransformationMatrix> MojoFromSpace() override {
auto mojo_to_object = object_->poseMatrix(); auto object_from_mojo = object_->poseMatrix();
if (!mojo_to_object.IsInvertible()) { if (!object_from_mojo.IsInvertible()) {
return nullptr; return nullptr;
} }
return std::make_unique<TransformationMatrix>(mojo_to_object.Inverse()); return std::make_unique<TransformationMatrix>(object_from_mojo.Inverse());
} }
void Trace(blink::Visitor* visitor) override { void Trace(blink::Visitor* visitor) override {
......
...@@ -48,54 +48,51 @@ XRReferenceSpace::~XRReferenceSpace() = default; ...@@ -48,54 +48,51 @@ XRReferenceSpace::~XRReferenceSpace() = default;
XRPose* XRReferenceSpace::getPose( XRPose* XRReferenceSpace::getPose(
XRSpace* other_space, XRSpace* other_space,
const TransformationMatrix* base_pose_matrix) { const TransformationMatrix* mojo_from_viewer) {
if (type_ == Type::kTypeViewer) { if (type_ == Type::kTypeViewer) {
std::unique_ptr<TransformationMatrix> viewer_pose_matrix = std::unique_ptr<TransformationMatrix> offsetspace_from_viewer =
other_space->GetViewerPoseMatrix(base_pose_matrix); other_space->SpaceFromViewerWithDefaultAndOffset(mojo_from_viewer);
if (!viewer_pose_matrix) { if (!offsetspace_from_viewer) {
return nullptr; return nullptr;
} }
return MakeGarbageCollected<XRPose>(*viewer_pose_matrix, return MakeGarbageCollected<XRPose>(*offsetspace_from_viewer,
session()->EmulatedPosition()); session()->EmulatedPosition());
} else { } else {
return XRSpace::getPose(other_space, base_pose_matrix); return XRSpace::getPose(other_space, mojo_from_viewer);
} }
} }
void XRReferenceSpace::UpdateFloorLevelTransform() { void XRReferenceSpace::SetFloorFromMojo() {
const device::mojom::blink::VRDisplayInfoPtr& display_info = const device::mojom::blink::VRDisplayInfoPtr& display_info =
session()->GetVRDisplayInfo(); session()->GetVRDisplayInfo();
if (display_info && display_info->stage_parameters) { if (display_info && display_info->stage_parameters) {
// Use the transform given by xrDisplayInfo's stage_parameters if available. // Use the transform given by xrDisplayInfo's stage_parameters if available.
floor_level_transform_ = std::make_unique<TransformationMatrix>( floor_from_mojo_ = std::make_unique<TransformationMatrix>(
display_info->stage_parameters->standing_transform.matrix()); display_info->stage_parameters->standing_transform.matrix());
} else { } else {
// Otherwise, create a transform based on the default emulated height. // Otherwise, create a transform based on the default emulated height.
floor_level_transform_ = std::make_unique<TransformationMatrix>(); floor_from_mojo_ = std::make_unique<TransformationMatrix>();
floor_level_transform_->Translate3d(0, kDefaultEmulationHeightMeters, 0); floor_from_mojo_->Translate3d(0, kDefaultEmulationHeightMeters, 0);
} }
display_info_id_ = session()->DisplayInfoPtrId(); display_info_id_ = session()->DisplayInfoPtrId();
} }
// Returns a default pose if no base pose is available. Only applicable to // Returns a default viewer pose if no actual viewer pose is available. Only
// viewer reference spaces. // applicable to viewer reference spaces.
std::unique_ptr<TransformationMatrix> XRReferenceSpace::DefaultPose() { std::unique_ptr<TransformationMatrix> XRReferenceSpace::DefaultViewerPose() {
// A viewer reference space always returns an identity matrix. // A viewer reference space always returns an identity matrix.
return type_ == Type::kTypeViewer ? std::make_unique<TransformationMatrix>() return type_ == Type::kTypeViewer ? std::make_unique<TransformationMatrix>()
: nullptr; : nullptr;
} }
// Transforms a given pose from a "base" reference space used by the XR std::unique_ptr<TransformationMatrix> XRReferenceSpace::SpaceFromMojo(
// service to the space represenced by this reference space. const TransformationMatrix& mojo_from_viewer) {
std::unique_ptr<TransformationMatrix> XRReferenceSpace::TransformBasePose(
const TransformationMatrix& base_pose) {
switch (type_) { switch (type_) {
case Type::kTypeLocal: case Type::kTypeLocal:
// Currently all base poses are 'local' poses, so return directly. // Currently 'local' space is equivalent to mojo space.
return std::make_unique<TransformationMatrix>(base_pose); return std::make_unique<TransformationMatrix>();
break;
case Type::kTypeLocalFloor: case Type::kTypeLocalFloor:
// Currently all base poses are 'local' space, so use of 'local-floor' // Currently all base poses are 'local' space, so use of 'local-floor'
// reference spaces requires adjustment. Ideally the service will // reference spaces requires adjustment. Ideally the service will
...@@ -105,57 +102,77 @@ std::unique_ptr<TransformationMatrix> XRReferenceSpace::TransformBasePose( ...@@ -105,57 +102,77 @@ std::unique_ptr<TransformationMatrix> XRReferenceSpace::TransformBasePose(
// Check first to see if the xrDisplayInfo has updated since the last // Check first to see if the xrDisplayInfo has updated since the last
// call. If so, update the floor-level transform. // call. If so, update the floor-level transform.
if (display_info_id_ != session()->DisplayInfoPtrId()) if (display_info_id_ != session()->DisplayInfoPtrId())
UpdateFloorLevelTransform(); SetFloorFromMojo();
return std::make_unique<TransformationMatrix>(*floor_from_mojo_);
// Apply the floor-level transform to the base pose.
if (floor_level_transform_) {
auto pose =
std::make_unique<TransformationMatrix>(*floor_level_transform_);
pose->Multiply(base_pose);
return pose;
}
break;
case Type::kTypeViewer: case Type::kTypeViewer:
// Always return the default pose because we will only get here for an // Return viewer_from_mojo which is the inverse of mojo_from_viewer.
// "viewer" reference space. return std::make_unique<TransformationMatrix>(mojo_from_viewer.Inverse());
return DefaultPose();
case Type::kTypeUnbounded: case Type::kTypeUnbounded:
// For now we assume that poses returned by systems that support unbounded // For now we assume that poses returned by systems that support unbounded
// reference spaces are already in the correct space. // reference spaces are already in the correct space. Return an identity.
return std::make_unique<TransformationMatrix>(base_pose); return std::make_unique<TransformationMatrix>();
case Type::kTypeBoundedFloor: case Type::kTypeBoundedFloor:
NOTREACHED() << "kTypeBoundedFloor should be handled by subclass";
break; break;
} }
return nullptr; return nullptr;
} }
// Serves the same purpose as TransformBasePose, but for input poses. Needs to // Returns the refspace-from-viewerspace transform, corresponding to the pose of
// know the head pose so that cases like the viewer frame of reference can // the viewer in this space. This takes the mojo_from_viewer transform (viewer
// properly adjust the input's relative position. // pose in mojo space) as input, and left-multiplies space_from_mojo onto that.
std::unique_ptr<TransformationMatrix> XRReferenceSpace::TransformBaseInputPose( std::unique_ptr<TransformationMatrix> XRReferenceSpace::SpaceFromViewer(
const TransformationMatrix& base_input_pose, const TransformationMatrix& mojo_from_viewer) {
const TransformationMatrix& base_pose) { if (type_ == Type::kTypeViewer) {
return TransformBasePose(base_input_pose); // Special case for viewer space, always return an identity matrix
// explicitly. In theory the default behavior of multiplying SpaceFromMojo *
// MojoFromViewer would be equivalent, but that would likely return an
// almost-identity due to rounding errors.
return std::make_unique<TransformationMatrix>();
}
// Return space_from_viewer = space_from_mojo * mojo_from_viewer
auto space_from_viewer = SpaceFromMojo(mojo_from_viewer);
if (!space_from_viewer)
return nullptr;
space_from_viewer->Multiply(mojo_from_viewer);
return space_from_viewer;
}
std::unique_ptr<TransformationMatrix> XRReferenceSpace::SpaceFromInputForViewer(
const TransformationMatrix& mojo_from_input,
const TransformationMatrix& mojo_from_viewer) {
// Return space_from_input = space_from_mojo * mojo_from_input
auto space_from_input = SpaceFromMojo(mojo_from_viewer);
if (!space_from_input)
return nullptr;
space_from_input->Multiply(mojo_from_input);
return space_from_input;
} }
std::unique_ptr<TransformationMatrix> std::unique_ptr<TransformationMatrix> XRReferenceSpace::MojoFromSpace() {
XRReferenceSpace::GetTransformToMojoSpace() {
// XRReferenceSpace doesn't do anything special with the base pose, but // XRReferenceSpace doesn't do anything special with the base pose, but
// derived reference spaces (bounded, unbounded, stationary, etc.) have their // derived reference spaces (bounded, unbounded, stationary, etc.) have their
// own custom behavior. // own custom behavior.
// Calculate the offset space's pose (including originOffset) in mojo
// space.
TransformationMatrix identity; TransformationMatrix identity;
std::unique_ptr<TransformationMatrix> transform_matrix = std::unique_ptr<TransformationMatrix> mojo_from_offsetspace =
TransformBasePose(identity); SpaceFromViewer(identity);
if (!transform_matrix) { if (!mojo_from_offsetspace) {
// Transform wasn't possible. // Transform wasn't possible.
return nullptr; return nullptr;
} }
// Must account for position and orientation defined by origin offset. // Must account for position and orientation defined by origin offset.
transform_matrix->Multiply(origin_offset_->TransformMatrix()); // Result is mojo_from_offset = mojo_from_ref * ref_from_offset,
return transform_matrix; // where ref_from_offset is originOffset's transform matrix.
// TODO(https://crbug.com/1008466): move originOffset to separate class?
mojo_from_offsetspace->Multiply(origin_offset_->TransformMatrix());
return mojo_from_offsetspace;
} }
TransformationMatrix XRReferenceSpace::OriginOffsetMatrix() { TransformationMatrix XRReferenceSpace::OriginOffsetMatrix() {
......
...@@ -36,14 +36,16 @@ class XRReferenceSpace : public XRSpace { ...@@ -36,14 +36,16 @@ class XRReferenceSpace : public XRSpace {
XRPose* getPose(XRSpace* other_space, XRPose* getPose(XRSpace* other_space,
const TransformationMatrix* base_pose_matrix) override; const TransformationMatrix* base_pose_matrix) override;
std::unique_ptr<TransformationMatrix> DefaultPose() override; std::unique_ptr<TransformationMatrix> DefaultViewerPose() override;
std::unique_ptr<TransformationMatrix> TransformBasePose( std::unique_ptr<TransformationMatrix> SpaceFromMojo(
const TransformationMatrix& base_pose) override; const TransformationMatrix& mojo_from_viewer) override;
std::unique_ptr<TransformationMatrix> TransformBaseInputPose( std::unique_ptr<TransformationMatrix> SpaceFromViewer(
const TransformationMatrix& base_input_pose, const TransformationMatrix& mojo_from_viewer) override;
const TransformationMatrix& base_pose) override; std::unique_ptr<TransformationMatrix> SpaceFromInputForViewer(
const TransformationMatrix& mojo_from_input,
const TransformationMatrix& mojo_from_viewer) override;
std::unique_ptr<TransformationMatrix> GetTransformToMojoSpace() override; std::unique_ptr<TransformationMatrix> MojoFromSpace() override;
TransformationMatrix OriginOffsetMatrix() override; TransformationMatrix OriginOffsetMatrix() override;
TransformationMatrix InverseOriginOffsetMatrix() override; TransformationMatrix InverseOriginOffsetMatrix() override;
...@@ -60,11 +62,11 @@ class XRReferenceSpace : public XRSpace { ...@@ -60,11 +62,11 @@ class XRReferenceSpace : public XRSpace {
virtual XRReferenceSpace* cloneWithOriginOffset( virtual XRReferenceSpace* cloneWithOriginOffset(
XRRigidTransform* origin_offset); XRRigidTransform* origin_offset);
void UpdateFloorLevelTransform(); void SetFloorFromMojo();
unsigned int display_info_id_ = 0; unsigned int display_info_id_ = 0;
std::unique_ptr<TransformationMatrix> floor_level_transform_; std::unique_ptr<TransformationMatrix> floor_from_mojo_;
Member<XRRigidTransform> origin_offset_; Member<XRRigidTransform> origin_offset_;
Type type_; Type type_;
}; };
......
...@@ -419,38 +419,38 @@ ScriptPromise XRSession::CreateAnchor(ScriptState* script_state, ...@@ -419,38 +419,38 @@ ScriptPromise XRSession::CreateAnchor(ScriptState* script_state,
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise promise = resolver->Promise(); ScriptPromise promise = resolver->Promise();
// Transformation from mojo space to passed in |space|. // Transformation from passed in |space| to mojo space.
std::unique_ptr<TransformationMatrix> space_from_mojo = std::unique_ptr<TransformationMatrix> mojo_from_space =
space->GetTransformToMojoSpace(); space->MojoFromSpace();
DVLOG(3) << __func__ DVLOG(3) << __func__
<< ": space_from_mojo = " << space_from_mojo->ToString(true); << ": mojo_from_space = " << mojo_from_space->ToString(true);
// Matrix will be null if transformation from mojo space to object space is // Matrix will be null if transformation from object space to mojo space is
// not invertible, log & bail out in that case. // not invertible, log & bail out in that case.
if (!space_from_mojo || !space_from_mojo->IsInvertible()) { if (!mojo_from_space || !mojo_from_space->IsInvertible()) {
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
kNonInvertibleMatrix); kNonInvertibleMatrix);
return ScriptPromise(); return ScriptPromise();
} }
auto mojo_from_space = space_from_mojo->Inverse(); auto space_from_mojo = mojo_from_space->Inverse();
DVLOG(3) << __func__ DVLOG(3) << __func__
<< ": mojo_from_space = " << mojo_from_space.ToString(true); << ": space_from_mojo = " << space_from_mojo.ToString(true);
// Transformation from passed in pose to |space|. // Transformation from passed in pose to |space|.
auto space_from_initial_pose = initial_pose->TransformMatrix(); auto mojo_from_initial_pose = initial_pose->TransformMatrix();
auto mojo_from_initial_pose = mojo_from_space * space_from_initial_pose; auto space_from_initial_pose = space_from_mojo * mojo_from_initial_pose;
DVLOG(3) << __func__ << ": space_from_initial_pose = "
<< space_from_initial_pose.ToString(true);
DVLOG(3) << __func__ << ": mojo_from_initial_pose = " DVLOG(3) << __func__ << ": mojo_from_initial_pose = "
<< mojo_from_initial_pose.ToString(true); << mojo_from_initial_pose.ToString(true);
DVLOG(3) << __func__ << ": space_from_initial_pose = "
<< space_from_initial_pose.ToString(true);
TransformationMatrix::DecomposedType decomposed; TransformationMatrix::DecomposedType decomposed;
if (!mojo_from_initial_pose.Decompose(decomposed)) { if (!space_from_initial_pose.Decompose(decomposed)) {
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
kUnableToDecomposeMatrix); kUnableToDecomposeMatrix);
return ScriptPromise(); return ScriptPromise();
...@@ -923,7 +923,7 @@ void XRSession::ApplyPendingRenderState() { ...@@ -923,7 +923,7 @@ void XRSession::ApplyPendingRenderState() {
void XRSession::UpdatePresentationFrameState( void XRSession::UpdatePresentationFrameState(
double timestamp, double timestamp,
std::unique_ptr<TransformationMatrix> base_pose_matrix, std::unique_ptr<TransformationMatrix> mojo_from_viewer,
const device::mojom::blink::XRFrameDataPtr& frame_data) { const device::mojom::blink::XRFrameDataPtr& frame_data) {
TRACE_EVENT0("gpu", __FUNCTION__); TRACE_EVENT0("gpu", __FUNCTION__);
DVLOG(2) << __FUNCTION__ << " : frame_data valid? " DVLOG(2) << __FUNCTION__ << " : frame_data valid? "
...@@ -932,9 +932,9 @@ void XRSession::UpdatePresentationFrameState( ...@@ -932,9 +932,9 @@ void XRSession::UpdatePresentationFrameState(
if (ended_) if (ended_)
return; return;
base_pose_matrix_ = std::move(base_pose_matrix); mojo_from_viewer_ = std::move(mojo_from_viewer);
DVLOG(2) << __FUNCTION__ << " : base_pose_matrix_ valid? " DVLOG(2) << __FUNCTION__ << " : mojo_from_viewer_ valid? "
<< (base_pose_matrix_ ? true : false); << (mojo_from_viewer_ ? true : false);
// Update objects that might change on per-frame basis. // Update objects that might change on per-frame basis.
if (frame_data) { if (frame_data) {
...@@ -1036,12 +1036,12 @@ XRFrame* XRSession::CreatePresentationFrame() { ...@@ -1036,12 +1036,12 @@ XRFrame* XRSession::CreatePresentationFrame() {
XRFrame* presentation_frame = XRFrame* presentation_frame =
MakeGarbageCollected<XRFrame>(this, world_information_); MakeGarbageCollected<XRFrame>(this, world_information_);
// TODO(1004201): Determine if world_information_ should be treated similarly // TODO(https://crbug.com/1004201): Determine if world_information_ should be
// to the base pose matrix. // treated similarly to mojo_from_viewer_.
if (base_pose_matrix_ && visibility_state_ != XRVisibilityState::HIDDEN) { if (mojo_from_viewer_ && visibility_state_ != XRVisibilityState::HIDDEN) {
DVLOG(2) << __func__ << " : base_pose_matrix_ is set and not hidden," DVLOG(2) << __func__ << " : mojo_from_viewer_ is set and not hidden,"
<< " updating presentation frame"; << " updating presentation frame";
presentation_frame->SetBasePoseMatrix(*base_pose_matrix_); presentation_frame->SetMojoFromViewer(*mojo_from_viewer_);
} }
return presentation_frame; return presentation_frame;
} }
......
...@@ -224,7 +224,7 @@ class XRSession final ...@@ -224,7 +224,7 @@ class XRSession final
bool HasPendingActivity() const override; bool HasPendingActivity() const override;
// Creates presentation frame based on current state of the session. // Creates presentation frame based on current state of the session.
// State currently used in XRFrame creation is base_pose_matrix_ and // State currently used in XRFrame creation is mojo_from_viewer_ and
// world_information_. The created XRFrame also stores a reference to this // world_information_. The created XRFrame also stores a reference to this
// XRSession. // XRSession.
XRFrame* CreatePresentationFrame(); XRFrame* CreatePresentationFrame();
...@@ -233,7 +233,7 @@ class XRSession final ...@@ -233,7 +233,7 @@ class XRSession final
// presentation frames. // presentation frames.
void UpdatePresentationFrameState( void UpdatePresentationFrameState(
double timestamp, double timestamp,
std::unique_ptr<TransformationMatrix> base_pose_matrix, std::unique_ptr<TransformationMatrix> mojo_from_viewer,
const device::mojom::blink::XRFrameDataPtr& frame_data); const device::mojom::blink::XRFrameDataPtr& frame_data);
private: private:
...@@ -315,7 +315,8 @@ class XRSession final ...@@ -315,7 +315,8 @@ class XRSession final
input_binding_; input_binding_;
Member<XRFrameRequestCallbackCollection> callback_collection_; Member<XRFrameRequestCallbackCollection> callback_collection_;
std::unique_ptr<TransformationMatrix> base_pose_matrix_; // Viewer pose in mojo space.
std::unique_ptr<TransformationMatrix> mojo_from_viewer_;
bool ended_ = false; bool ended_ = false;
bool pending_frame_ = false; bool pending_frame_ = false;
......
...@@ -16,24 +16,29 @@ XRSpace::XRSpace(XRSession* session) : session_(session) {} ...@@ -16,24 +16,29 @@ XRSpace::XRSpace(XRSession* session) : session_(session) {}
XRSpace::~XRSpace() = default; XRSpace::~XRSpace() = default;
std::unique_ptr<TransformationMatrix> XRSpace::GetTransformToMojoSpace() { std::unique_ptr<TransformationMatrix> XRSpace::MojoFromSpace() {
// The base XRSpace does not have any relevant information, so can't determine // The base XRSpace does not have any relevant information, so can't determine
// a transform here. // a transform here.
return nullptr; return nullptr;
} }
std::unique_ptr<TransformationMatrix> XRSpace::DefaultPose() { std::unique_ptr<TransformationMatrix> XRSpace::DefaultViewerPose() {
return nullptr; return nullptr;
} }
std::unique_ptr<TransformationMatrix> XRSpace::TransformBasePose( std::unique_ptr<TransformationMatrix> XRSpace::SpaceFromMojo(
const TransformationMatrix& base_pose) { const TransformationMatrix& mojo_from_viewer) {
return nullptr; return nullptr;
} }
std::unique_ptr<TransformationMatrix> XRSpace::TransformBaseInputPose( std::unique_ptr<TransformationMatrix> XRSpace::SpaceFromViewer(
const TransformationMatrix& base_input_pose, const TransformationMatrix& mojo_from_viewer) {
const TransformationMatrix& base_pose) { return nullptr;
}
std::unique_ptr<TransformationMatrix> XRSpace::SpaceFromInputForViewer(
const TransformationMatrix& mojo_from_input,
const TransformationMatrix& mojo_from_viewer) {
return nullptr; return nullptr;
} }
...@@ -49,18 +54,17 @@ TransformationMatrix XRSpace::InverseOriginOffsetMatrix() { ...@@ -49,18 +54,17 @@ TransformationMatrix XRSpace::InverseOriginOffsetMatrix() {
XRPose* XRSpace::getPose(XRSpace* other_space, XRPose* XRSpace::getPose(XRSpace* other_space,
const TransformationMatrix* base_pose_matrix) { const TransformationMatrix* base_pose_matrix) {
std::unique_ptr<TransformationMatrix> mojo_from_this = std::unique_ptr<TransformationMatrix> mojo_from_space = MojoFromSpace();
GetTransformToMojoSpace(); if (!mojo_from_space) {
if (!mojo_from_this) {
return nullptr; return nullptr;
} }
// Rigid transforms should always be invertible. // Rigid transforms should always be invertible.
DCHECK(mojo_from_this->IsInvertible()); DCHECK(mojo_from_space->IsInvertible());
TransformationMatrix this_from_mojo = mojo_from_this->Inverse(); TransformationMatrix space_from_mojo = mojo_from_space->Inverse();
std::unique_ptr<TransformationMatrix> mojo_from_other = std::unique_ptr<TransformationMatrix> mojo_from_other =
other_space->GetTransformToMojoSpace(); other_space->MojoFromSpace();
if (!mojo_from_other) { if (!mojo_from_other) {
return nullptr; return nullptr;
} }
...@@ -68,33 +72,38 @@ XRPose* XRSpace::getPose(XRSpace* other_space, ...@@ -68,33 +72,38 @@ XRPose* XRSpace::getPose(XRSpace* other_space,
// TODO(crbug.com/969133): Update how EmulatedPosition is determined here once // TODO(crbug.com/969133): Update how EmulatedPosition is determined here once
// spec issue https://github.com/immersive-web/webxr/issues/534 has been // spec issue https://github.com/immersive-web/webxr/issues/534 has been
// resolved. // resolved.
TransformationMatrix this_from_other = TransformationMatrix space_from_other =
this_from_mojo.Multiply(*mojo_from_other); space_from_mojo.Multiply(*mojo_from_other);
return MakeGarbageCollected<XRPose>(this_from_other, return MakeGarbageCollected<XRPose>(space_from_other,
session()->EmulatedPosition()); session()->EmulatedPosition());
} }
std::unique_ptr<TransformationMatrix> XRSpace::GetViewerPoseMatrix( std::unique_ptr<TransformationMatrix>
const TransformationMatrix* base_pose_matrix) { XRSpace::SpaceFromViewerWithDefaultAndOffset(
std::unique_ptr<TransformationMatrix> pose; const TransformationMatrix* mojo_from_viewer) {
std::unique_ptr<TransformationMatrix> space_from_viewer;
// If we don't have a valid base pose, request the reference space's default // If we don't have a valid base pose, request the reference space's default
// pose. Most common when tracking is lost. // viewer pose. Most common when tracking is lost.
if (base_pose_matrix) { if (mojo_from_viewer) {
pose = TransformBasePose(*base_pose_matrix); space_from_viewer = SpaceFromViewer(*mojo_from_viewer);
} else { } else {
pose = DefaultPose(); space_from_viewer = DefaultViewerPose();
} }
// Can only update an XRViewerPose's views with an invertible matrix. // Can only update an XRViewerPose's views with an invertible matrix.
if (!pose || !pose->IsInvertible()) { if (!space_from_viewer || !space_from_viewer->IsInvertible()) {
return nullptr; return nullptr;
} }
// Account for any changes made to the reference space's origin offset so that // Account for any changes made to the reference space's origin offset so that
// things like teleportation works. // things like teleportation works.
//
// This is offset_from_viewer = offset_from_space * space_from_viewer,
// where offset_from_viewer = inverse(viewer_from_offset).
// TODO(https://crbug.com/1008466): move originOffset to separate class?
return std::make_unique<TransformationMatrix>( return std::make_unique<TransformationMatrix>(
InverseOriginOffsetMatrix().Multiply(*pose)); InverseOriginOffsetMatrix().Multiply(*space_from_viewer));
} }
ExecutionContext* XRSpace::GetExecutionContext() const { ExecutionContext* XRSpace::GetExecutionContext() const {
......
...@@ -28,24 +28,45 @@ class XRSpace : public EventTargetWithInlineData { ...@@ -28,24 +28,45 @@ class XRSpace : public EventTargetWithInlineData {
explicit XRSpace(XRSession*); explicit XRSpace(XRSession*);
~XRSpace() override; ~XRSpace() override;
// Get a transform that maps from this space to mojo space (aka device space). // Gets a default viewer pose appropriate for this space. This is an identity
// Unless noted otherwise, all data returned over vr_service.mojom interfaces // for viewer space, null for everything else.
// is relative to mojo space. virtual std::unique_ptr<TransformationMatrix> DefaultViewerPose();
// Returns nullptr if computing a transform is not possible.
virtual std::unique_ptr<TransformationMatrix> GetTransformToMojoSpace(); // Gets the pose of this space's origin in mojo space. This is a transform
// that maps from this space to mojo space (aka device space). Unless noted
virtual std::unique_ptr<TransformationMatrix> DefaultPose(); // otherwise, all data returned over vr_service.mojom interfaces is expressed
virtual std::unique_ptr<TransformationMatrix> TransformBasePose( // in mojo space coordinates. Returns nullptr if computing a transform is not
const TransformationMatrix& base_pose); // possible.
virtual std::unique_ptr<TransformationMatrix> TransformBaseInputPose( virtual std::unique_ptr<TransformationMatrix> MojoFromSpace();
const TransformationMatrix& base_input_pose,
const TransformationMatrix& base_pose); // Gets the pose of the mojo origin in this reference space, corresponding
// to a transform from mojo coordinates to reference space coordinates.
virtual std::unique_ptr<TransformationMatrix> SpaceFromMojo(
const TransformationMatrix& mojo_from_viewer);
// Gets the viewer pose in this space, corresponding to a transform from
// viewer coordinates to this space's coordinates. (The position elements of
// the transformation matrix are the viewer's location in this space's
// coordinates.)
virtual std::unique_ptr<TransformationMatrix> SpaceFromViewer(
const TransformationMatrix& mojo_from_viewer);
// Gets an input pose in this space. This requires the viewer pose as
// an additional input since a "viewer" space needs to transform the
// input pose to headset-relative coordinates.
virtual std::unique_ptr<TransformationMatrix> SpaceFromInputForViewer(
const TransformationMatrix& mojo_from_input,
const TransformationMatrix& mojo_from_viewer);
virtual XRPose* getPose(XRSpace* other_space, virtual XRPose* getPose(XRSpace* other_space,
const TransformationMatrix* base_pose_matrix); const TransformationMatrix* mojo_from_viewer);
std::unique_ptr<TransformationMatrix> GetViewerPoseMatrix( // Gets the viewer pose in this space, including using an appropriate
const TransformationMatrix* base_pose_matrix); // default pose (i.e. if tracking is lost), and applying originOffset
// as applicable. TODO(https://crbug.com/1008466): consider moving
// the originOffset handling to a separate class?
std::unique_ptr<TransformationMatrix> SpaceFromViewerWithDefaultAndOffset(
const TransformationMatrix* mojo_from_viewer);
XRSession* session() const { return session_; } XRSession* session() const { return session_; }
......
...@@ -14,90 +14,96 @@ namespace blink { ...@@ -14,90 +14,96 @@ namespace blink {
XRTargetRaySpace::XRTargetRaySpace(XRSession* session, XRInputSource* source) XRTargetRaySpace::XRTargetRaySpace(XRSession* session, XRInputSource* source)
: XRSpace(session), input_source_(source) {} : XRSpace(session), input_source_(source) {}
std::unique_ptr<TransformationMatrix> XRTargetRaySpace::GetPointerPoseForScreen( std::unique_ptr<TransformationMatrix> XRTargetRaySpace::OtherSpaceFromScreenTap(
XRSpace* other_space, XRSpace* other_space,
const TransformationMatrix& base_pose_matrix) { const TransformationMatrix& mojo_from_viewer) {
// If the pointer origin is the screen we need the head's base pose and // If the pointer origin is the screen, the input space is viewer space, and
// the pointer transform matrix to continue. The pointer transform will // we need the head's viewer pose and the pointer pose in continue. The
// represent the point the canvas was clicked as an offset from the view. // pointer transform will represent the point the canvas was clicked as an
if (!input_source_->PointerTransform()) { // offset from the view.
if (!input_source_->InputFromPointer()) {
return nullptr; return nullptr;
} }
// Multiply the head pose and pointer transform to get the final pointer. // other_from_pointer = other_from_input * input_from_pointer,
std::unique_ptr<TransformationMatrix> pointer_pose = // where input space is equivalent to viewer space for screen taps.
other_space->TransformBasePose(base_pose_matrix); std::unique_ptr<TransformationMatrix> other_from_pointer =
if (!pointer_pose) { other_space->SpaceFromViewer(mojo_from_viewer);
if (!other_from_pointer) {
return nullptr; return nullptr;
} }
other_from_pointer->Multiply(*(input_source_->InputFromPointer()));
pointer_pose->Multiply(*(input_source_->PointerTransform())); return other_from_pointer;
return pointer_pose;
} }
std::unique_ptr<TransformationMatrix> XRTargetRaySpace::GetTrackedPointerPose( std::unique_ptr<TransformationMatrix>
XRTargetRaySpace::OtherSpaceFromTrackedPointer(
XRSpace* other_space, XRSpace* other_space,
const TransformationMatrix& base_pose_matrix) { const TransformationMatrix& mojo_from_viewer) {
if (!input_source_->BasePose()) { if (!input_source_->MojoFromInput()) {
return nullptr; return nullptr;
} }
std::unique_ptr<TransformationMatrix> grip_pose = // Calculate other_from_pointer = other_from_input * input_from_pointer
other_space->TransformBaseInputPose(*(input_source_->BasePose()), std::unique_ptr<TransformationMatrix> other_from_pointer =
base_pose_matrix); other_space->SpaceFromInputForViewer(*(input_source_->MojoFromInput()),
mojo_from_viewer);
if (!grip_pose) { if (!other_from_pointer) {
return nullptr; return nullptr;
} }
if (input_source_->InputFromPointer()) {
if (input_source_->PointerTransform()) { other_from_pointer->Multiply(*(input_source_->InputFromPointer()));
grip_pose->Multiply(*(input_source_->PointerTransform()));
} }
return other_from_pointer;
return grip_pose;
} }
XRPose* XRTargetRaySpace::getPose( XRPose* XRTargetRaySpace::getPose(
XRSpace* other_space, XRSpace* other_space,
const TransformationMatrix* base_pose_matrix) { const TransformationMatrix* mojo_from_viewer) {
// If we don't have a valid base pose (most common when tracking is lost), // If we don't have a valid base pose (most common when tracking is lost),
// we can't get a target ray pose regardless of the mode. // we can't get a target ray pose regardless of the mode.
if (!base_pose_matrix) { if (!mojo_from_viewer) {
DVLOG(2) << __func__ << " : base_pose_matrix is null, returning nullptr"; DVLOG(2) << __func__ << " : mojo_from_viewer is null, returning nullptr";
return nullptr; return nullptr;
} }
std::unique_ptr<TransformationMatrix> pointer_pose = nullptr; std::unique_ptr<TransformationMatrix> other_from_ray = nullptr;
switch (input_source_->TargetRayMode()) { switch (input_source_->TargetRayMode()) {
case device::mojom::XRTargetRayMode::TAPPING: { case device::mojom::XRTargetRayMode::TAPPING: {
pointer_pose = GetPointerPoseForScreen(other_space, *base_pose_matrix); other_from_ray = OtherSpaceFromScreenTap(other_space, *mojo_from_viewer);
break; break;
} }
case device::mojom::XRTargetRayMode::GAZING: { case device::mojom::XRTargetRayMode::GAZING: {
// If the pointer origin is the users head, this is a gaze cursor and the // If the pointer origin is the users head, this is a gaze cursor and the
// returned pointer is based on the device pose. Just return the head pose // returned pointer is based on the device pose. Just return the head pose
// as the pointer pose. // as the pointer pose.
pointer_pose = other_space->TransformBasePose(*base_pose_matrix); other_from_ray = other_space->SpaceFromViewer(*mojo_from_viewer);
break; break;
} }
case device::mojom::XRTargetRayMode::POINTING: { case device::mojom::XRTargetRayMode::POINTING: {
pointer_pose = GetTrackedPointerPose(other_space, *base_pose_matrix); other_from_ray =
OtherSpaceFromTrackedPointer(other_space, *mojo_from_viewer);
break; break;
} }
} }
if (!pointer_pose) { if (!other_from_ray) {
DVLOG(2) << __func__ << " : " DVLOG(2) << __func__ << " : "
<< "pointer_pose is null, input_source_->TargetRayMode() = " << "other_from_ray is null, input_source_->TargetRayMode() = "
<< input_source_->TargetRayMode(); << input_source_->TargetRayMode();
return nullptr; return nullptr;
} }
// Account for any changes made to the reference space's origin offset so that // Account for any changes made to the reference space's origin offset so that
// things like teleportation works. // things like teleportation works.
TransformationMatrix adjusted_pose = //
other_space->InverseOriginOffsetMatrix().Multiply(*pointer_pose); // otheroffset_from_ray = otheroffset_from_other * other_from_ray
return MakeGarbageCollected<XRPose>(adjusted_pose, // where otheroffset_from_other = inverse(other_from_otheroffset)
// TODO(https://crbug.com/1008466): move originOffset to separate class?
TransformationMatrix otheroffset_from_ray =
other_space->InverseOriginOffsetMatrix().Multiply(*other_from_ray);
return MakeGarbageCollected<XRPose>(otheroffset_from_ray,
input_source_->emulatedPosition()); input_source_->emulatedPosition());
} }
......
...@@ -20,12 +20,12 @@ class XRTargetRaySpace : public XRSpace { ...@@ -20,12 +20,12 @@ class XRTargetRaySpace : public XRSpace {
void Trace(blink::Visitor*) override; void Trace(blink::Visitor*) override;
private: private:
std::unique_ptr<TransformationMatrix> GetPointerPoseForScreen( std::unique_ptr<TransformationMatrix> OtherSpaceFromScreenTap(
XRSpace* other_space, XRSpace* other_space,
const TransformationMatrix& base_pose_matrix); const TransformationMatrix& mojo_from_viewer);
std::unique_ptr<TransformationMatrix> GetTrackedPointerPose( std::unique_ptr<TransformationMatrix> OtherSpaceFromTrackedPointer(
XRSpace* other_space, XRSpace* other_space,
const TransformationMatrix& base_pose_matrix); const TransformationMatrix& mojo_from_viewer);
Member<XRInputSource> input_source_; Member<XRInputSource> input_source_;
}; };
......
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