// Copyright 2017 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Modified by Unity from originals located
// https://github.com/googlevr/daydream-elements/blob/master/Assets/DaydreamElements/Elements/ArmModels/Scripts/ArmModels/SwingArmModel.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
#if ENABLE_VR || ENABLE_AR
using UnityEngine.Experimental.XR.Interaction;
namespace UnityEngine.XR.LegacyInputHelpers
{
public class SwingArmModel : ArmModel
{
[Tooltip("Portion of controller rotation applied to the shoulder joint.")]
[SerializeField]
[Range(0.0f, 1.0f)]
float m_ShoulderRotationRatio = 0.5f;
///
/// Portion of controller rotation applied to the shoulder joint.
///
public float shoulderRotationRatio
{
get { return m_ShoulderRotationRatio; }
set { m_ShoulderRotationRatio = value; }
}
[Tooltip("Portion of controller rotation applied to the elbow joint.")]
[Range(0.0f, 1.0f)]
[SerializeField]
float m_ElbowRotationRatio = 0.3f;
///
/// Portion of controller rotation applied to the elbow joint.
///
public float elbowRotationRatio
{
get { return m_ElbowRotationRatio; }
set { m_ElbowRotationRatio = value; }
}
[Tooltip("Portion of controller rotation applied to the wrist joint.")]
[Range(0.0f, 1.0f)]
[SerializeField]
float m_WristRotationRatio = 0.2f;
///
/// Portion of controller rotation applied to the wrist joint.
///
public float wristRotationRatio
{
get { return m_WristRotationRatio; }
set { m_WristRotationRatio = value; }
}
[SerializeField]
Vector2 m_JointShiftAngle = new Vector2(160.0f, 180.0f);
///
/// Min angle of the controller before starting to lerp towards the shifted joint ratios.
///
public float minJointShiftAngle
{
get { return m_JointShiftAngle.x; }
set { m_JointShiftAngle.x = value; }
}
///
/// Max angle of the controller before starting to lerp towards the shifted joint ratios.
///
public float maxJointShiftAngle
{
get { return m_JointShiftAngle.y; }
set { m_JointShiftAngle.y = value; }
}
[Tooltip("Exponent applied to the joint shift ratio to control the curve of the shift.")]
[Range(1.0f, 20.0f)]
[SerializeField]
float m_JointShiftExponent = 6.0f;
///
/// Exponent applied to the joint shift ratio to control the curve of the shift.
///
public float jointShiftExponent
{
get { return m_JointShiftExponent; }
set { m_JointShiftExponent = value; }
}
[Tooltip("Portion of controller rotation applied to the shoulder joint when the controller is backwards.")]
[Range(0.0f, 1.0f)]
[SerializeField]
float m_ShiftedShoulderRotationRatio = 0.1f;
///
/// Portion of controller rotation applied to the shoulder joint when the controller is backwards.
///
public float shiftedShoulderRotationRatio
{
get { return m_ShiftedShoulderRotationRatio; }
set { m_ShiftedShoulderRotationRatio = value; }
}
[Tooltip("Portion of controller rotation applied to the elbow joint when the controller is backwards.")]
[Range(0.0f, 1.0f)]
[SerializeField]
float m_ShiftedElbowRotationRatio = 0.4f;
///
/// Portion of controller rotation applied to the elbow joint when the controller is backwards.
///
public float shiftedElbowRotationRatio
{
get { return m_ShiftedElbowRotationRatio; }
set { m_ShiftedElbowRotationRatio = value; }
}
[Tooltip("Portion of controller rotation applied to the wrist joint when the controller is backwards.")]
[Range(0.0f, 1.0f)]
[SerializeField]
float m_ShiftedWristRotationRatio = 0.5f;
///
/// Portion of controller rotation applied to the wrist joint when the controller is backwards.
///
public float shiftedWristRotationRatio
{
get { return m_ShiftedWristRotationRatio; }
set { m_ShiftedWristRotationRatio = value; }
}
protected override void CalculateFinalJointRotations(Quaternion controllerOrientation, Quaternion xyRotation, Quaternion lerpRotation)
{
// As the controller angle increases the ratio of the rotation applied to each joint shifts.
float totalAngle = Quaternion.Angle(xyRotation, Quaternion.identity);
float jointShiftAngleRange = maxJointShiftAngle - minJointShiftAngle;
float angleRatio = Mathf.Clamp01((totalAngle - minJointShiftAngle) / jointShiftAngleRange);
float jointShiftRatio = Mathf.Pow(angleRatio, m_JointShiftExponent);
// Calculate what portion of the rotation is applied to each joint.
float finalShoulderRatio = Mathf.Lerp(m_ShoulderRotationRatio, m_ShiftedShoulderRotationRatio, jointShiftRatio);
float finalElbowRatio = Mathf.Lerp(m_ElbowRotationRatio, m_ShiftedElbowRotationRatio, jointShiftRatio);
float finalWristRatio = Mathf.Lerp(m_WristRotationRatio, m_ShiftedWristRotationRatio, jointShiftRatio);
// Calculate relative rotations for each joint.
Quaternion swingShoulderRot = Quaternion.Lerp(Quaternion.identity, xyRotation, finalShoulderRatio);
Quaternion swingElbowRot = Quaternion.Lerp(Quaternion.identity, xyRotation, finalElbowRatio);
Quaternion swingWristRot = Quaternion.Lerp(Quaternion.identity, xyRotation, finalWristRatio);
// Calculate final rotations.
Quaternion shoulderRotation = m_TorsoRotation * swingShoulderRot;
m_ElbowRotation = shoulderRotation * swingElbowRot;
m_WristRotation = elbowRotation * swingWristRot;
m_ControllerRotation = m_TorsoRotation * controllerOrientation;
m_TorsoRotation = shoulderRotation;
}
}
}
#endif