OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 // Adapted from: |
| 6 // https://github.com/googlevr/gvr-unity-sdk/blob/master/Samples/DaydreamLabsCon
trollerPlayground/Assets/GoogleVR/Scripts/Controller/GvrArmModel.cs |
| 7 |
| 8 #include "chrome/browser/android/vr_shell/elbow_model.h" |
| 9 |
| 10 #include <cmath> |
| 11 |
| 12 #include "device/vr/vr_math.h" |
| 13 |
| 14 namespace vr_shell { |
| 15 |
| 16 namespace { |
| 17 |
| 18 constexpr vr::Quatf kNoRotation = {0.0f, 0.0f, 0.0f, 1.0f}; |
| 19 constexpr gfx::Point3F kDefaultShoulderRight = {0.19f, -0.19f, 0.03f}; |
| 20 constexpr float kFadeDistanceFromFace = 0.34f; |
| 21 constexpr gfx::Point3F kDefaultRelativeElbow = {0.195f, -0.5f, 0.075f}; |
| 22 constexpr gfx::Point3F kDefaultRelativeWrist = {0.0f, 0.0f, -0.25f}; |
| 23 constexpr gfx::Vector3dF kForward = {0.0f, 0.0f, -1.0f}; |
| 24 constexpr gfx::Vector3dF kUp = {0.0f, 1.0f, 0.0f}; |
| 25 constexpr gfx::Vector3dF kDefaultArmExtensionOffset = {-0.13f, 0.14f, -0.08f}; |
| 26 constexpr float kMinExtensionAngle = 7.0f; |
| 27 constexpr float kMaxExtenstionAngle = 60.0f; |
| 28 constexpr float kExtensionWeight = 0.4f; |
| 29 constexpr float kDeltaAlpha = 3.0f; |
| 30 constexpr float kDefaultElbowRotationRatio = 0.4f; |
| 31 |
| 32 } // namespace |
| 33 |
| 34 ElbowModel::ElbowModel(gvr::ControllerHandedness handedness) |
| 35 : handedness_(handedness), |
| 36 alpha_value_(1.0f), |
| 37 torso_direction_{0.0f, 0.0f, 0.0f} {} |
| 38 |
| 39 ElbowModel::~ElbowModel() = default; |
| 40 |
| 41 void ElbowModel::UpdateHandedness() { |
| 42 handed_multiplier_ = { |
| 43 handedness_ == GVR_CONTROLLER_RIGHT_HANDED ? 1.0f : -1.0f, 1.0f, 1.0f}; |
| 44 shoulder_rotation_ = kNoRotation; |
| 45 shoulder_position_ = |
| 46 vr::ScalePoint(kDefaultShoulderRight, handed_multiplier_); |
| 47 } |
| 48 |
| 49 void ElbowModel::Update(const UpdateData& update) { |
| 50 UpdateHandedness(); |
| 51 UpdateTorsoDirection(update); |
| 52 ApplyArmModel(update); |
| 53 UpdateTransparency(update); |
| 54 } |
| 55 |
| 56 void ElbowModel::UpdateTorsoDirection(const UpdateData& update) { |
| 57 auto head_direction = update.head_direction; |
| 58 head_direction.set_y(0); |
| 59 vr::NormalizeVector(&head_direction); |
| 60 |
| 61 // Determine the gaze direction horizontally. |
| 62 float angular_velocity = update.gyro.Length(); |
| 63 float gaze_filter_strength = |
| 64 vr::Clampf((angular_velocity - 0.2f) / 45.0f, 0.0f, 0.1f); |
| 65 torso_direction_ = |
| 66 vr::QuatSlerp(torso_direction_, head_direction, gaze_filter_strength); |
| 67 |
| 68 // Rotate the fixed joints. |
| 69 auto gaze_rotation = vr::GetVectorRotation(kForward, torso_direction_); |
| 70 shoulder_rotation_ = gaze_rotation; |
| 71 vr::Mat4f gaze_rotation_mat; |
| 72 vr::QuatToMatrix(gaze_rotation, &gaze_rotation_mat); |
| 73 shoulder_position_ = vr::ToPoint(vr::MatrixVectorRotate( |
| 74 gaze_rotation_mat, vr::ToVector(shoulder_position_))); |
| 75 } |
| 76 |
| 77 void ElbowModel::ApplyArmModel(const UpdateData& update) { |
| 78 // Controller's orientation relative to the user. |
| 79 auto controller_orientation = update.orientation; |
| 80 controller_orientation = vr::QuatProduct(vr::InvertQuat(shoulder_rotation_), |
| 81 controller_orientation); |
| 82 |
| 83 // Relative positions of the joints. |
| 84 elbow_position_ = vr::ScalePoint(kDefaultRelativeElbow, handed_multiplier_); |
| 85 wrist_position_ = vr::ScalePoint(kDefaultRelativeWrist, handed_multiplier_); |
| 86 auto arm_extension_offset = |
| 87 vr::ScaleVector(kDefaultArmExtensionOffset, handed_multiplier_); |
| 88 |
| 89 // Extract just the x rotation angle. |
| 90 vr::Mat4f controller_orientation_mat; |
| 91 QuatToMatrix(controller_orientation, &controller_orientation_mat); |
| 92 auto controller_forward = |
| 93 vr::MatrixVectorRotate(controller_orientation_mat, kForward); |
| 94 float x_angle = |
| 95 90.0f - gfx::AngleBetweenVectorsInDegrees(controller_forward, kUp); |
| 96 |
| 97 // Remove the z rotation from the controller |
| 98 auto x_y_rotation = vr::GetVectorRotation(kForward, controller_forward); |
| 99 |
| 100 // Offset the elbow by the extension. |
| 101 float normalized_angle = (x_angle - kMinExtensionAngle) / |
| 102 (kMaxExtenstionAngle - kMinExtensionAngle); |
| 103 float extension_ratio = vr::Clampf(normalized_angle, 0.0f, 1.0f); |
| 104 elbow_position_ = elbow_position_ + |
| 105 gfx::ScaleVector3d(arm_extension_offset, extension_ratio); |
| 106 |
| 107 // Calculate the lerp interpolation factor. |
| 108 float total_angle = vr::QuatAngleDegrees(x_y_rotation, kNoRotation); |
| 109 float lerp_suppresion = 1.0f - pow(total_angle / 180.0f, 6); |
| 110 float lerp_value = lerp_suppresion * (kDefaultElbowRotationRatio + |
| 111 (1.0f - kDefaultElbowRotationRatio) * |
| 112 extension_ratio * kExtensionWeight); |
| 113 |
| 114 // Apply the absolute rotations to the joints. |
| 115 auto lerp_rotation = vr::QuatLerp(kNoRotation, x_y_rotation, lerp_value); |
| 116 elbow_rotation_ = vr::QuatProduct( |
| 117 vr::QuatProduct(shoulder_rotation_, vr::InvertQuat(lerp_rotation)), |
| 118 controller_orientation); |
| 119 wrist_rotation_ = vr::QuatProduct(shoulder_rotation_, controller_orientation); |
| 120 |
| 121 // Determine the relative positions. |
| 122 vr::Mat4f shoulder_rotation_mat; |
| 123 QuatToMatrix(shoulder_rotation_, &shoulder_rotation_mat); |
| 124 elbow_position_ = vr::ToPoint(vr::MatrixVectorRotate( |
| 125 shoulder_rotation_mat, vr::ToVector(elbow_position_))); |
| 126 vr::Mat4f elbow_rotation_mat; |
| 127 QuatToMatrix(elbow_rotation_, &elbow_rotation_mat); |
| 128 wrist_position_ = |
| 129 elbow_position_ + |
| 130 vr::MatrixVectorRotate(elbow_rotation_mat, vr::ToVector(wrist_position_)); |
| 131 } |
| 132 |
| 133 void ElbowModel::UpdateTransparency(const UpdateData& update) { |
| 134 float distance_to_face = vr::ToVector(wrist_position_).Length(); |
| 135 float alpha_change = kDeltaAlpha * update.delta_time_seconds; |
| 136 alpha_value_ = vr::Clampf(distance_to_face < kFadeDistanceFromFace |
| 137 ? alpha_value_ - alpha_change |
| 138 : alpha_value_ + alpha_change, |
| 139 0.0f, 1.0f); |
| 140 } |
| 141 |
| 142 } // namespace vr_shell |
OLD | NEW |