Chromium Code Reviews| Index: chrome/browser/android/vr_shell/elbow_model.cc |
| diff --git a/chrome/browser/android/vr_shell/elbow_model.cc b/chrome/browser/android/vr_shell/elbow_model.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..9ab7819b17be0269126c1d95bb2460512140823e |
| --- /dev/null |
| +++ b/chrome/browser/android/vr_shell/elbow_model.cc |
| @@ -0,0 +1,130 @@ |
| +// Copyright 2016 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. |
| + |
| +// Adapted from: |
| +// https://github.com/googlevr/gvr-unity-sdk/blob/master/Samples/DaydreamLabsControllerPlayground/Assets/GoogleVR/Scripts/Controller/GvrArmModel.cs |
| + |
| +#include "chrome/browser/android/vr_shell/elbow_model.h" |
| + |
| +#include <cmath> |
| + |
| +#include "chrome/browser/android/vr_shell/vr_math.h" |
| + |
| +namespace vr_shell { |
| + |
| +namespace { |
| + |
| +constexpr gvr::Quatf kNoRotation = {0.f, 0.f, 0.f, 1.f}; |
| +constexpr gvr::Vec3f kDefaultShoulderRight = {0.19f, -0.19f, 0.03f}; |
| +constexpr float kFadeDistanceFromFace = 0.34f; |
| +constexpr gvr::Vec3f kDefaultRelativeElbow = {0.195f, -0.5f, 0.075f}; |
| +constexpr gvr::Vec3f kDefaultRelativeWrist = {0.f, 0.f, -0.25f}; |
| +constexpr gvr::Vec3f kForward = {0.f, 0.f, -1.f}; |
| +constexpr gvr::Vec3f kUp = {0.f, 1.f, 0.f}; |
| +constexpr float kMinExtensionAngle = 7.f; |
| +constexpr float kMaxExtenstionAngle = 60.f; |
| +constexpr float kExtensionWeight = 0.4f; |
| +constexpr float kDeltaAlpha = 3.f; |
| + |
| +} // namespace |
| + |
| +ElbowModel::ElbowModel(gvr_controller_handedness handedness) |
| + : handedness_(handedness), alpha_value_(1.f), torso_direction_{0, 0, 0} {} |
| + |
| +ElbowModel::~ElbowModel() = default; |
| + |
| +void ElbowModel::UpdateHandedness() { |
| + handed_multiplier_ = {handedness_ == GVR_CONTROLLER_RIGHT_HANDED ? 1.f : -1.f, |
| + 1.f, 1.f}; |
| + shoulder_rotation_ = kNoRotation; |
| + shoulder_position_ = |
| + PointwiseVectorMul(kDefaultShoulderRight, handed_multiplier_); |
| +} |
| + |
| +void ElbowModel::Update(const UpdateData& update) { |
| + UpdateHandedness(); |
| + UpdateTorsoDirection(update); |
| + ApplyArmModel(update); |
| + UpdateTransparency(update); |
| +} |
| + |
| +void ElbowModel::UpdateTorsoDirection(const UpdateData& update) { |
| + auto head_direction = update.head_direction; |
| + head_direction.y = 0; |
| + NormalizeVector(head_direction); |
| + |
| + // Determine the gaze direction horizontally. |
| + float angular_velocity = VectorLength(update.gyro); |
| + float gaze_filter_strength = |
| + Clampf((angular_velocity - .2f) / 45.f, 0.f, 0.1f); |
|
cjgrant
2017/04/03 19:24:59
0.2f here (and everywhere please). Ie, not .2f or
acondor_
2017/04/19 18:44:27
Done.
|
| + torso_direction_ = |
| + QuatSlerp(torso_direction_, head_direction, gaze_filter_strength); |
| + |
| + // Rotate the fixed joints. |
| + auto gaze_rotation = FromToRotation(kForward, torso_direction_); |
| + shoulder_rotation_ = gaze_rotation; |
| + shoulder_position_ = |
| + MatrixVectorRotate(QuatToMatrix(gaze_rotation), shoulder_position_); |
| +} |
| + |
| +void ElbowModel::ApplyArmModel(const UpdateData& update) { |
| + // Controller's orientation relative to the player. |
|
cjgrant
2017/04/03 19:24:59
s/player/user/ everywhere?
acondor_
2017/04/19 18:44:27
Done.
|
| + auto controller_orientation = update.orientation; |
| + controller_orientation = |
| + QuatMultiply(QuatInverted(shoulder_rotation_), controller_orientation); |
| + |
| + // Relative positions of the joints. |
| + elbow_position_ = |
| + PointwiseVectorMul(kDefaultRelativeElbow, handed_multiplier_); |
| + wrist_position_ = |
| + PointwiseVectorMul(kDefaultRelativeWrist, handed_multiplier_); |
| + auto arm_extension_offset = |
| + PointwiseVectorMul({-0.13f, 0.14f, -0.08f}, handed_multiplier_); |
|
cjgrant
2017/04/03 19:24:59
The vector here should be a constant as well.
acondor_
2017/04/19 18:44:27
Done.
|
| + |
| + // Extract just the x rotation angle. |
| + auto controller_forward = |
| + MatrixVectorRotate(QuatToMatrix(controller_orientation), kForward); |
| + float x_angle = 90.f - VectorAngleDegrees(controller_forward, kUp); |
| + |
| + // Remove the z rotation from the controller |
| + auto x_y_rotation = FromToRotation(kForward, controller_forward); |
| + |
| + // Offset the elbow by the extension. |
| + float normalized_angle = (x_angle - kMinExtensionAngle) / |
| + (kMaxExtenstionAngle - kMinExtensionAngle); |
| + float extension_ratio = Clampf(normalized_angle, 0.f, 1.f); |
| + elbow_position_ = VectorAdd( |
| + elbow_position_, VectorScalarMul(arm_extension_offset, extension_ratio)); |
| + |
| + // Calculate the lerp interpolation factor. |
| + float total_angle = QuatAngleDegrees(x_y_rotation, kNoRotation); |
| + float lerp_suppresion = 1.f - pow(total_angle / 180.f, 6); |
| + float lerp_value = |
| + lerp_suppresion * (0.4f + 0.6f * extension_ratio * kExtensionWeight); |
|
asimjour1
2017/04/19 18:58:12
please move the magic numbers from here and define
acondor_
2017/04/21 21:04:31
Done.
|
| + |
| + // Apply the absolute rotations to the joints. |
| + auto lerp_rotation = QuatLerp(kNoRotation, x_y_rotation, lerp_value); |
| + elbow_rotation_ = QuatMultiply( |
| + QuatMultiply(shoulder_rotation_, QuatInverted(lerp_rotation)), |
| + controller_orientation); |
| + wrist_rotation_ = QuatMultiply(shoulder_rotation_, controller_orientation); |
| + |
| + // Determine the relative positions. |
| + elbow_position_ = |
| + MatrixVectorRotate(QuatToMatrix(shoulder_rotation_), elbow_position_); |
| + wrist_position_ = VectorAdd( |
| + elbow_position_, |
| + MatrixVectorRotate(QuatToMatrix(elbow_rotation_), wrist_position_)); |
| +} |
| + |
| +void ElbowModel::UpdateTransparency(const UpdateData& update) { |
|
asimjour1
2017/04/19 18:58:12
IIUC alpha_value/opacity can be obtained from the
acondor_
2017/04/21 21:04:31
Actually, this is an animation (so it depends on t
|
| + float distance_to_face = VectorLength(wrist_position_); |
| + float alpha_change = kDeltaAlpha * update.delta_time_seconds; |
| + alpha_value_ = Clampf(distance_to_face < kFadeDistanceFromFace |
| + ? alpha_value_ - alpha_change |
| + : alpha_value_ + alpha_change, |
| + 0.f, 1.f); |
| +} |
| + |
| +} // namespace vr_shell |