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 |