123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258 |
- // 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 original:
- // https://github.com/googlevr/daydream-elements/blob/master/Assets/DaydreamElements/Elements/ArmModels/Scripts/ArmModels/TransitionArmModel.cs
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Runtime.CompilerServices;
- using UnityEngine;
- using UnityEngine.Events;
- #if ENABLE_VR || ENABLE_AR
- using UnityEngine.Experimental.XR.Interaction;
- using UnityEngine.SpatialTracking;
- [assembly: InternalsVisibleTo("UnityEditor.XR.LegacyInputHelpers")]
- namespace UnityEngine.XR.LegacyInputHelpers
- {
- [Serializable]
- public class ArmModelTransition
- {
- [SerializeField]
- String m_KeyName;
- /// <summary>
- /// the string name that will be used to trigger a transition
- /// </summary>
- public string transitionKeyName
- {
- get { return m_KeyName; }
- set { m_KeyName = value; }
- }
- [SerializeField]
- ArmModel m_ArmModel;
- /// <summary>
- /// the arm model that will be transitioned to on receiving this event.
- /// </summary>
- public ArmModel armModel
- {
- get { return m_ArmModel; }
- set { m_ArmModel = value; }
- }
- }
- public class TransitionArmModel : ArmModel
- {
- [SerializeField]
- ArmModel m_CurrentArmModelComponent = null;
- /// <summary>
- /// This field contains the current active arm model that will be used as the input to the tracked pose driver which is
- /// using the transitional arm model.
- /// </summary>
- public ArmModel currentArmModelComponent
- {
- get { return m_CurrentArmModelComponent; }
- set { m_CurrentArmModelComponent = value; }
- }
- [SerializeField]
- public List<ArmModelTransition> m_ArmModelTransitions = new List<ArmModelTransition>();
- /// Max number of active transitions that can be going on at one time.
- /// Transitions are only completed when the controller rotates, so if TransitionToArmModel
- /// is called several times without the controller moving, the number of active transitions can
- /// add up.
- private const int MAX_ACTIVE_TRANSITIONS = 10;
- /// When transitioning to a new arm model, drop any old transitions that have barely begun.
- private const float DROP_TRANSITION_THRESHOLD = 0.035f;
- /// Threshold for clamping transitions that have been completed.
- private const float LERP_CLAMP_THRESHOLD = 0.95f;
- /// Minimum amount of angular velocity on the controller before transitioning occurs.
- private const float MIN_ANGULAR_VELOCITY = 0.2f;
- /// Unit less weight for how much the angular velocity impacts the transition.
- private const float ANGULAR_VELOCITY_DIVISOR = 45.0f;
- internal struct ArmModelBlendData
- {
- public ArmModel armModel;
- public float currentBlendAmount;
- }
- internal List<ArmModelBlendData> armModelBlendData = new List<ArmModelBlendData>(MAX_ACTIVE_TRANSITIONS);
- ArmModelBlendData currentBlendingArmModel;
-
- public bool Queue(string key)
- {
- // attempt to find the arm model to blend to using the supplied key.
- foreach(var am in m_ArmModelTransitions)
- {
- if(am.transitionKeyName == key)
- {
- Queue(am.armModel);
- return true;
- }
- }
- return false;
- }
- public void Queue(ArmModel newArmModel)
- {
- if(newArmModel == null)
- {
- return;
- }
- if(m_CurrentArmModelComponent == null)
- {
- m_CurrentArmModelComponent = newArmModel;
- }
- RemoveJustStartingTransitions();
- if (armModelBlendData.Count == MAX_ACTIVE_TRANSITIONS)
- {
- RemoveOldestTransition();
- }
- var ambd = new ArmModelBlendData();
- ambd.armModel = newArmModel;
- ambd.currentBlendAmount = 0.0f;
- armModelBlendData.Add(ambd);
- }
-
- void RemoveJustStartingTransitions()
- {
- for( int i = 0; i < armModelBlendData.Count; ++i)
- {
- ArmModelBlendData ambd = armModelBlendData[i];
- if (ambd.currentBlendAmount < DROP_TRANSITION_THRESHOLD)
- {
- armModelBlendData.RemoveAt(i);
- }
- }
- }
- void RemoveOldestTransition()
- {
- armModelBlendData.RemoveAt(0);
- }
- public override PoseDataFlags GetPoseFromProvider(out Pose output)
- {
- if (UpdateBlends())
- {
- output = finalPose;
- return PoseDataFlags.Position | PoseDataFlags.Rotation;
- }
- output = Pose.identity;
- return PoseDataFlags.NoData;
- }
- bool UpdateBlends()
- {
- if (currentArmModelComponent == null)
- {
- return false;
- }
- if (m_CurrentArmModelComponent.OnControllerInputUpdated())
- {
- m_NeckPosition = m_CurrentArmModelComponent.neckPosition;
- m_ElbowPosition = m_CurrentArmModelComponent.elbowPosition;
- m_WristPosition = m_CurrentArmModelComponent.wristPosition;
- m_ControllerPosition = m_CurrentArmModelComponent.controllerPosition;
- m_ElbowRotation = m_CurrentArmModelComponent.elbowRotation;
- m_WristRotation = m_CurrentArmModelComponent.wristRotation;
- m_ControllerRotation = m_CurrentArmModelComponent.controllerRotation;
- #if UNITY_EDITOR
- m_TorsoDirection = m_CurrentArmModelComponent.torsoDirection;
- m_TorsoRotation = m_CurrentArmModelComponent.torsoRotation;
- #endif
- Vector3 angVel;
- if (TryGetAngularVelocity(poseSource, out angVel) && armModelBlendData.Count > 0)
- {
- float angularVelocity = angVel.magnitude;
- float lerpValue = Mathf.Clamp(((angularVelocity) - MIN_ANGULAR_VELOCITY) / ANGULAR_VELOCITY_DIVISOR, 0.0f, 0.1f);
-
- for (int i = 0; i < armModelBlendData.Count; ++i)
- {
- ArmModelBlendData ambd = armModelBlendData[i];
- ambd.currentBlendAmount = Mathf.Lerp(ambd.currentBlendAmount, 1.0f, lerpValue);
- if (ambd.currentBlendAmount > LERP_CLAMP_THRESHOLD)
- {
- ambd.currentBlendAmount = 1.0f;
- }
- else
- {
- ambd.armModel.OnControllerInputUpdated();
- m_NeckPosition = Vector3.Slerp(neckPosition, ambd.armModel.neckPosition, ambd.currentBlendAmount);
- m_ElbowPosition = Vector3.Slerp(elbowPosition, ambd.armModel.elbowPosition, ambd.currentBlendAmount);
- m_WristPosition = Vector3.Slerp(wristPosition, ambd.armModel.wristPosition, ambd.currentBlendAmount);
- m_ControllerPosition = Vector3.Slerp(controllerPosition, ambd.armModel.controllerPosition, ambd.currentBlendAmount);
- m_ElbowRotation = Quaternion.Slerp(elbowRotation, ambd.armModel.elbowRotation, ambd.currentBlendAmount);
- m_WristRotation = Quaternion.Slerp(wristRotation, ambd.armModel.wristRotation, ambd.currentBlendAmount);
- m_ControllerRotation = Quaternion.Slerp(controllerRotation, ambd.armModel.controllerRotation, ambd.currentBlendAmount);
- }
- // write back.
- armModelBlendData[i] = ambd;
- if (ambd.currentBlendAmount >= 1.0f)
- {
- m_CurrentArmModelComponent = ambd.armModel;
- armModelBlendData.RemoveRange(0, i + 1);
- }
- }
- }
- else if (armModelBlendData.Count > 0)
- {
- Debug.LogErrorFormat(this.gameObject, "Unable to get angular acceleration for node");
- return false;
- }
- finalPose = new Pose(controllerPosition, controllerRotation);
- return true;
- }
- else
- {
- return false;
- }
- }
- #if UNITY_EDITOR
- internal List<ArmModelBlendData> GetActiveBlends()
- {
- return armModelBlendData;
- }
- #endif
- }
- }
- #endif
|