blob: 7663501f866f4c174f8073d47cfe27244d6b804a [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 "chrome/browser/vr/elements/repositioner.h"
#include "chrome/browser/vr/pose_util.h"
#include "chrome/browser/vr/ui_scene_constants.h"
#include "ui/gfx/geometry/angle_conversions.h"
#include "ui/gfx/geometry/quaternion.h"
namespace vr {
Repositioner::Repositioner(float content_depth)
: content_depth_(content_depth) {
set_hit_testable(false);
}
Repositioner::~Repositioner() = default;
gfx::Transform Repositioner::LocalTransform() const {
return transform_;
}
gfx::Transform Repositioner::GetTargetLocalTransform() const {
return transform_;
}
void Repositioner::UpdateTransform(const gfx::Transform& head_pose) {
DCHECK(kOrigin.SquaredDistanceTo(laser_origin_) <
content_depth_ * content_depth_);
gfx::Vector3dF laser_origin_vector = laser_origin_ - kOrigin;
float laser_origin_vector_length = laser_origin_vector.Length();
gfx::Vector3dF normalized_laser_direction;
bool success = laser_direction_.GetNormalized(&normalized_laser_direction);
DCHECK(success);
float d1 = -gfx::DotProduct(laser_origin_vector, normalized_laser_direction);
float d2 = std::sqrt(
content_depth_ * content_depth_ -
(laser_origin_vector_length * laser_origin_vector_length - d1 * d1));
float new_ray_distance = d1 + d2;
gfx::Vector3dF new_ray =
gfx::ScaleVector3d(normalized_laser_direction, new_ray_distance);
gfx::Vector3dF new_reticle_vector = laser_origin_vector;
new_reticle_vector.Add(new_ray);
gfx::Vector3dF head_up_vector = vr::GetUpVector(head_pose);
if (gfx::AngleBetweenVectorsInDegrees(head_up_vector, new_reticle_vector) ==
0.f)
return;
transform_.MakeIdentity();
gfx::Quaternion rotate_to_new_position({0, 0, -1}, new_reticle_vector);
transform_.ConcatTransform(gfx::Transform(rotate_to_new_position));
gfx::Vector3dF new_right_vector = {1, 0, 0};
transform_.TransformVector(&new_right_vector);
gfx::Vector3dF expected_right_vector =
gfx::CrossProduct(new_reticle_vector, head_up_vector);
gfx::Quaternion rotate_to_expected_right(new_right_vector,
expected_right_vector);
transform_.ConcatTransform(gfx::Transform(rotate_to_expected_right));
}
bool Repositioner::OnBeginFrame(const base::TimeTicks& time,
const gfx::Transform& head_pose) {
if (enabled_) {
UpdateTransform(head_pose);
return true;
}
return false;
}
void Repositioner::DumpGeometry(std::ostringstream* os) const {
gfx::Transform t = world_space_transform();
gfx::Vector3dF forward = {0, 0, -1};
t.TransformVector(&forward);
// Decompose the rotation to world x axis followed by world y axis
float x_rotation = std::asin(forward.y() / forward.Length());
gfx::Vector3dF projected_forward = {forward.x(), 0, forward.z()};
float y_rotation = std::acos(gfx::DotProduct(projected_forward, {0, 0, -1}) /
projected_forward.Length());
if (projected_forward.x() > 0.f)
y_rotation *= -1;
*os << "rx(" << gfx::RadToDeg(x_rotation) << ") "
<< "ry(" << gfx::RadToDeg(y_rotation) << ") ";
}
} // namespace vr