blob: 3f422cdff50cb6f9ff155178fef3a6f1bf3dbbcc [file] [log] [blame]
// Copyright 2017 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 "modules/xr/XRFrameOfReference.h"
#include "modules/xr/XRStageBounds.h"
namespace blink {
// Rough estimate of avg human eye height in meters.
const double kDefaultEmulationHeight = 1.6;
XRFrameOfReference::XRFrameOfReference(XRSession* session, Type type)
: XRCoordinateSystem(session), type_(type) {}
XRFrameOfReference::~XRFrameOfReference() = default;
void XRFrameOfReference::UpdatePoseTransform(
std::unique_ptr<TransformationMatrix> transform) {
pose_transform_ = std::move(transform);
}
void XRFrameOfReference::UpdateStageBounds(XRStageBounds* bounds) {
bounds_ = bounds;
// TODO(bajones): Fire a boundschange event
}
// Enables emulated height when using a stage frame of reference, which should
// only be used if the sytem does not have a native concept of how far above the
// floor the XRDevice is at any given moment. This applies a static vertical
// offset to the coordinate system so that the user feels approximately like
// they are standing on a floor plane located at Y = 0. An explicit offset in
// meters can be given if the page has specific needs.
void XRFrameOfReference::UseEmulatedHeight(double value) {
if (value == 0.0) {
value = kDefaultEmulationHeight;
}
emulatedHeight_ = value;
pose_transform_ = TransformationMatrix::Create();
pose_transform_->Translate3d(0, emulatedHeight_, 0);
}
// Transforms a given pose from a "base" coordinate system used by the XR
// service to the frame of reference's coordinate system. This model is a bit
// over-simplified and will need to be made more robust when we start dealing
// with world-scale 6DoF tracking.
std::unique_ptr<TransformationMatrix> XRFrameOfReference::TransformBasePose(
const TransformationMatrix& base_pose) {
switch (type_) {
case kTypeHeadModel: {
// TODO(bajones): Detect if base pose is already neck modeled and return
// it unchanged if so for better performance.
// Strip out translation component.
std::unique_ptr<TransformationMatrix> pose(
TransformationMatrix::Create(base_pose));
pose->SetM41(0.0);
pose->SetM42(0.0);
pose->SetM43(0.0);
// TODO(bajones): Apply our own neck model
return pose;
} break;
case kTypeEyeLevel:
// For now we assume that all base poses are delivered as eye-level poses.
// Thus in this case we just return the pose without transformation.
return TransformationMatrix::Create(base_pose);
break;
case kTypeStage:
// If the stage has a transform apply it to the base pose and return that,
// otherwise return null.
if (pose_transform_) {
std::unique_ptr<TransformationMatrix> pose(
TransformationMatrix::Create(*pose_transform_));
pose->Multiply(base_pose);
return pose;
}
break;
}
return nullptr;
}
void XRFrameOfReference::Trace(blink::Visitor* visitor) {
visitor->Trace(bounds_);
XRCoordinateSystem::Trace(visitor);
}
} // namespace blink