clean project

This commit is contained in:
Helar Jaadla
2022-03-07 17:52:41 +02:00
parent a174b45bd2
commit cbeb10ec35
5100 changed files with 837159 additions and 0 deletions

View File

@@ -0,0 +1,91 @@
/************************************************************************************
Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
Your use of this SDK or tool is subject to the Oculus SDK License Agreement, available at
https://developer.oculus.com/licenses/oculussdk/
Unless required by applicable law or agreed to in writing, the Utilities SDK 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.
************************************************************************************/
using Oculus.Interaction.Input;
using UnityEngine;
using UnityEngine.Assertions;
namespace Oculus.Interaction.Throw
{
/// <summary>
/// Provides pose information for a controller.
/// </summary>
public class ControllerPoseInputDevice : MonoBehaviour, IPoseInputDevice
{
[SerializeField, Interface(typeof(IController))]
private MonoBehaviour _controller;
public IController Controller { get; private set; }
[SerializeField]
private Transform _trackingSpaceTransform;
public bool IsInputValid =>
Controller.IsConnected &&
Controller.IsPoseValid;
public bool IsHighConfidence => IsInputValid;
public bool GetRootPose(out Pose pose)
{
pose = new Pose();
if (!IsInputValid)
{
return false;
}
if (!Controller.TryGetPose(out pose))
{
return false;
}
return true;
}
protected virtual void Awake()
{
Controller = _controller as IController;
}
protected virtual void Start()
{
Assert.IsNotNull(_controller);
Assert.IsNotNull(_trackingSpaceTransform);
}
public (Vector3, Vector3) GetExternalVelocities()
{
return (Vector3.zero, Vector3.zero);
}
#region Inject
public void InjectAllControllerPoseInputDevice(
IController controller,
Transform trackingSpaceTransform)
{
InjectController(controller);
InjectTrackingSpaceTransform(trackingSpaceTransform);
}
public void InjectController(IController controller)
{
_controller = controller as MonoBehaviour;
Controller = controller;
}
public void InjectTrackingSpaceTransform(Transform trackingSpaceTransform)
{
_trackingSpaceTransform = trackingSpaceTransform;
}
#endregion
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 05e1160b52479574a9092dd2fef44bfe
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,284 @@
/************************************************************************************
Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
Your use of this SDK or tool is subject to the Oculus SDK License Agreement, available at
https://developer.oculus.com/licenses/oculussdk/
Unless required by applicable law or agreed to in writing, the Utilities SDK 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.
************************************************************************************/
using Oculus.Interaction.Input;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Assertions;
namespace Oculus.Interaction.Throw
{
/// <summary>
/// Provides pose information for a hand.
/// </summary>
public class HandPoseInputDevice : MonoBehaviour, IPoseInputDevice
{
[SerializeField, Interface(typeof(IHand))]
private MonoBehaviour _hand;
public IHand Hand { get; private set; }
[SerializeField]
private float _bufferLengthSeconds = 0.1f;
[SerializeField]
private float _sampleFrequency = 90.0f;
public float BufferLengthSeconds
{
get
{
return _bufferLengthSeconds;
}
set
{
_bufferLengthSeconds = value;
}
}
public float SampleFrequency
{
get
{
return _sampleFrequency;
}
set
{
_sampleFrequency = value;
}
}
public bool IsInputValid => Hand.IsTrackedDataValid;
public bool IsHighConfidence => Hand.IsHighConfidence;
private int _bufferSize = -1;
private class HandJointPoseMetaData
{
public HandJointPoseMetaData(HandFinger finger,
HandJointId joint, int bufferLength)
{
Finger = finger;
JointId = joint;
Velocities = new List<Vector3>();
_previousPosition = null;
_lastWritePos = -1;
_bufferLength = bufferLength;
}
public void BufferNewValue(Pose newPose, float delta)
{
Vector3 newPosition = newPose.position;
Vector3 newVelocity = _previousPosition.HasValue ?
((newPosition - _previousPosition.Value) / delta) : Vector3.zero;
int nextWritePos = (_lastWritePos < 0) ? 0 :
(_lastWritePos + 1) % _bufferLength;
if (Velocities.Count <= nextWritePos)
{
Velocities.Add(newVelocity);
}
else
{
Velocities[nextWritePos] = newVelocity;
}
_previousPosition = newPosition;
_lastWritePos = nextWritePos;
}
public Vector3 GetAverageVelocityVector()
{
Vector3 average = Vector3.zero;
foreach (var speed in Velocities)
{
average += speed;
}
average /= Velocities.Count;
return average;
}
public void ResetSpeedsBuffer()
{
Velocities.Clear();
_lastWritePos = -1;
_previousPosition = null;
}
public readonly HandFinger Finger;
public readonly HandJointId JointId;
public readonly List<Vector3> Velocities;
private Vector3? _previousPosition;
private int _lastWritePos;
private int _bufferLength;
}
private HandJointPoseMetaData[] _jointPoseInfoArray = null;
public bool GetRootPose(out Pose pose)
{
pose = new Pose();
if (!IsInputValid)
{
return false;
}
if (!Hand.GetJointPose(HandJointId.HandWristRoot,
out pose))
{
return false;
}
Pose palmOffset = new Pose();
if (!Hand.GetPalmPoseLocal(out palmOffset))
{
return false;
}
palmOffset.Postmultiply(pose);
pose = palmOffset;
return true;
}
protected virtual void Awake()
{
Hand = _hand as IHand;
}
protected virtual void Start()
{
Assert.IsNotNull(_hand);
_bufferSize = Mathf.CeilToInt(_bufferLengthSeconds
* _sampleFrequency);
}
protected virtual void LateUpdate()
{
BufferFingerVelocities();
}
private void BufferFingerVelocities()
{
if (!IsInputValid)
{
return;
}
AllocateFingerBonesArrayIfNecessary();
BufferFingerBoneVelocities();
}
private void AllocateFingerBonesArrayIfNecessary()
{
if (_jointPoseInfoArray != null)
{
return;
}
_jointPoseInfoArray = new[]
{
new HandJointPoseMetaData(HandFinger.Thumb,
HandJointId.HandThumb3,
_bufferSize),
new HandJointPoseMetaData(HandFinger.Index,
HandJointId.HandIndex3,
_bufferSize),
new HandJointPoseMetaData(HandFinger.Middle,
HandJointId.HandMiddle3,
_bufferSize),
new HandJointPoseMetaData(HandFinger.Ring,
HandJointId.HandRing3,
_bufferSize),
new HandJointPoseMetaData(HandFinger.Pinky,
HandJointId.HandPinky3,
_bufferSize)
};
}
private bool GetFingerIsHighConfidence(HandFinger handFinger)
{
return Hand.IsTrackedDataValid &&
Hand.GetFingerIsHighConfidence(handFinger);
}
private bool GetJointPose(HandJointId handJointId, out Pose pose)
{
pose = new Pose();
if (!Hand.IsTrackedDataValid)
{
return false;
}
if (!Hand.GetJointPose(handJointId, out pose))
{
return false;
}
return true;
}
private void BufferFingerBoneVelocities()
{
float deltaValue = Time.deltaTime;
foreach (var jointPoseInfo in _jointPoseInfoArray)
{
if (!GetFingerIsHighConfidence(jointPoseInfo.Finger))
{
continue;
}
Pose jointPose;
if (!GetJointPose(jointPoseInfo.JointId, out jointPose))
{
continue;
}
jointPoseInfo.BufferNewValue(jointPose, deltaValue);
}
}
public (Vector3, Vector3) GetExternalVelocities()
{
if (_jointPoseInfoArray == null)
{
return (Vector3.zero, Vector3.zero);
}
Vector3 averageVelocityAllFingers = Vector3.zero;
foreach (var fingerMetaInfo in _jointPoseInfoArray)
{
averageVelocityAllFingers += fingerMetaInfo.GetAverageVelocityVector();
}
averageVelocityAllFingers /= _jointPoseInfoArray.Length;
foreach (var item in _jointPoseInfoArray)
{
item.ResetSpeedsBuffer();
}
return (averageVelocityAllFingers, Vector3.zero);
}
#region Inject
public void InjectAllHandPoseInputDevice(
IHand hand)
{
InjectHand(hand);
}
public void InjectHand(IHand hand)
{
_hand = hand as MonoBehaviour;
Hand = hand;
}
#endregion
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3fb913c9e194da6449a32f1bf3cc991b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,31 @@
/************************************************************************************
Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
Your use of this SDK or tool is subject to the Oculus SDK License Agreement, available at
https://developer.oculus.com/licenses/oculussdk/
Unless required by applicable law or agreed to in writing, the Utilities SDK 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.
************************************************************************************/
using UnityEngine;
namespace Oculus.Interaction.Throw
{
/// <summary>
/// Interface to input device that be used to drive mechanics like
/// throwing (via velocity calculation).
/// </summary>
public interface IPoseInputDevice
{
bool IsInputValid { get; }
bool IsHighConfidence { get; }
bool GetRootPose(out Pose pose);
(Vector3, Vector3) GetExternalVelocities();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 977ecdca40477174eb47996d9c8d700d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,91 @@
/************************************************************************************
Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
Your use of this SDK or tool is subject to the Oculus SDK License Agreement, available at
https://developer.oculus.com/licenses/oculussdk/
Unless required by applicable law or agreed to in writing, the Utilities SDK 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.
************************************************************************************/
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Oculus.Interaction.Throw
{
/// <summary>
/// Transform information used to derive velocities.
/// </summary>
public struct TransformSample
{
public TransformSample(Vector3 position, Quaternion rotation, float time,
int frameIndex)
{
Position = position;
Rotation = rotation;
SampleTime = time;
FrameIndex = frameIndex;
}
public static TransformSample Interpolate(TransformSample start,
TransformSample fin, float time)
{
float alpha = Mathf.Clamp01(Mathf.InverseLerp(start.SampleTime,
fin.SampleTime, time));
return new TransformSample(Vector3.Lerp(start.Position, fin.Position, alpha),
Quaternion.Slerp(start.Rotation, fin.Rotation, alpha),
time, (int)Mathf.Lerp((float)start.FrameIndex, (float)fin.FrameIndex, alpha));
}
public readonly Vector3 Position;
public readonly Quaternion Rotation;
public readonly float SampleTime;
public readonly int FrameIndex;
}
/// <summary>
/// Information related to release velocities such as linear and
/// angular.
/// </summary>
public struct ReleaseVelocityInformation
{
public Vector3 LinearVelocity;
public Vector3 AngularVelocity;
public Vector3 Origin;
public bool IsSelectedVelocity;
public ReleaseVelocityInformation(Vector3 linearVelocity,
Vector3 angularVelocity,
Vector3 origin,
bool isSelectedVelocity = false)
{
LinearVelocity = linearVelocity;
AngularVelocity = angularVelocity;
Origin = origin;
IsSelectedVelocity = isSelectedVelocity;
}
}
/// <summary>
/// Interface to velocity calculator used to make throwing
/// possible.
/// </summary>
public interface IVelocityCalculator
{
float UpdateFrequency { get; }
event Action<List<ReleaseVelocityInformation>> WhenThrowVelocitiesChanged;
event Action<ReleaseVelocityInformation> WhenNewSampleAvailable;
ReleaseVelocityInformation CalculateThrowVelocity(Transform objectThrown);
IReadOnlyList<ReleaseVelocityInformation> LastThrowVelocities();
void SetUpdateFrequency(float frequency);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0f8fbc86c372ee34581f48a516c6e816
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,666 @@
/************************************************************************************
Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
Your use of this SDK or tool is subject to the Oculus SDK License Agreement, available at
https://developer.oculus.com/licenses/oculussdk/
Unless required by applicable law or agreed to in writing, the Utilities SDK 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.
************************************************************************************/
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Assertions;
namespace Oculus.Interaction.Throw
{
/// <summary>
/// Velocity calculator that depends only on an IPoseInputDevice,
/// which means its input agnostic.
/// </summary>
public class StandardVelocityCalculator : MonoBehaviour, IVelocityCalculator
{
[Serializable]
public class BufferingParams
{
public float BufferLengthSeconds = 0.4f;
public float SampleFrequency = 90.0f;
public void Validate()
{
Assert.IsTrue(BufferLengthSeconds > 0.0f);
Assert.IsTrue(SampleFrequency > 0.0f);
}
}
private struct SamplePoseData
{
public readonly Pose TransformPose;
public readonly Vector3 LinearVelocity;
public readonly Vector3 AngularVelocity;
public readonly float Time;
public SamplePoseData(Pose transformPose,
Vector3 linearVelocity, Vector3 angularVelocity, float time)
{
TransformPose = transformPose;
LinearVelocity = linearVelocity;
AngularVelocity = angularVelocity;
Time = time;
}
}
[SerializeField, Interface(typeof(IPoseInputDevice))]
private MonoBehaviour _throwInputDevice;
public IPoseInputDevice ThrowInputDevice { get; private set; }
[SerializeField]
[Tooltip("The reference position is the center of mass of the hand or controller." +
" Use this in case the computed center of mass is not entirely correct.")]
private Vector3 _referenceOffset = Vector3.zero;
[SerializeField, Tooltip("Related to buffering velocities, used for final release " +
"velocity calculation.")]
private BufferingParams _bufferingParams;
[SerializeField, Tooltip("Influence of latest velocities upon release.")]
[Range(0.0f, 1.0f)]
private float _instantVelocityInfluence = 1.0f;
[SerializeField]
[Range(0.0f, 1.0f), Tooltip("Influence of derived velocities trend upon release.")]
private float _trendVelocityInfluence = 1.0f;
[SerializeField]
[Range(0.0f, 1.0f), Tooltip("Influence of tangential velcities upon release, which" +
" can be affected by rotational motion.")]
private float _tangentialVelocityInfluence = 1.0f;
[SerializeField]
[Range(0.0f, 1.0f), Tooltip("Influence of external velocities upon release. For hands, " +
"this can include fingers.")]
private float _fingerSpeedInfluence = 0.0f;
[SerializeField, Tooltip("Time of anticipated release. Hand tracking " +
"might experience greater latency compared to controllers.")]
private float _stepBackTime = 0.08f;
[SerializeField, Tooltip("Trend velocity uses a window of velocities, " +
"assuming not too many of those velocities are zero. If they exceed a max percentage " +
"then a last resort method is used.")]
private float _maxPercentZeroSamplesTrendVeloc = 0.5f;
[SerializeField, Tooltip("Lower this number in case linear release velocity feels " +
"too fast. It scales each linear velocity sample buffered.")]
private float _linearVelocityScaleModifier = 0.8f;
public float UpdateFrequency => _updateFrequency;
private float _updateFrequency = -1.0f;
private float _updateLatency = -1.0f;
private float _lastUpdateTime = -1.0f;
public Vector3 ReferenceOffset
{
get
{
return _referenceOffset;
}
set
{
_referenceOffset = value;
}
}
public float InstantVelocityInfluence {
get
{
return _instantVelocityInfluence;
}
set
{
_instantVelocityInfluence = value;
}
}
public float TrendVelocityInfluence
{
get
{
return _trendVelocityInfluence;
}
set
{
_trendVelocityInfluence = value;
}
}
public float TangentialVelocityInfluence
{
get
{
return _tangentialVelocityInfluence;
}
set
{
_tangentialVelocityInfluence = value;
}
}
public float FingerSpeedInfluence
{
get
{
return _fingerSpeedInfluence;
}
set
{
_fingerSpeedInfluence = value;
}
}
public float StepBackTime
{
get
{
return _stepBackTime;
}
set
{
_stepBackTime = value;
}
}
public float MaxPercentZeroSamplesTrendVeloc
{
get
{
return _maxPercentZeroSamplesTrendVeloc;
}
set
{
_maxPercentZeroSamplesTrendVeloc = value;
}
}
public float LinearVelocityScaleModifier
{
get
{
return _linearVelocityScaleModifier;
}
set
{
_linearVelocityScaleModifier = value;
}
}
public Vector3 AddedInstantLinearVelocity { get; private set; }
public Vector3 AddedTrendLinearVelocity { get; private set; }
public Vector3 AddedTangentialLinearVelocity { get; private set; }
List<ReleaseVelocityInformation> _currentThrowVelocities = new List<ReleaseVelocityInformation>();
public event Action<List<ReleaseVelocityInformation>> WhenThrowVelocitiesChanged = delegate { };
public event Action<ReleaseVelocityInformation> WhenNewSampleAvailable = delegate { };
private Vector3 _linearVelocity;
private Vector3 _angularVelocity;
private Vector3? _previousReferencePosition;
private Quaternion? _previousReferenceRotation;
private float _accumulatedDelta;
private List<SamplePoseData> _bufferedPoses = new List<SamplePoseData>();
private int _lastWritePos = -1;
private int _bufferSize = -1;
private List<SamplePoseData> _windowWithMovement = new List<SamplePoseData>();
private List<SamplePoseData> _tempWindow = new List<SamplePoseData>();
private const float _TREND_DOT_THRESHOLD = 0.6f;
protected virtual void Awake()
{
ThrowInputDevice = _throwInputDevice as IPoseInputDevice;
}
protected virtual void Start()
{
Assert.IsNotNull(_bufferingParams);
_bufferingParams.Validate();
_bufferSize = Mathf.CeilToInt(_bufferingParams.BufferLengthSeconds
* _bufferingParams.SampleFrequency);
_bufferedPoses.Capacity = _bufferSize;
Assert.IsNotNull(ThrowInputDevice);
}
public ReleaseVelocityInformation CalculateThrowVelocity(Transform objectThrown)
{
Vector3 linearVelocity = Vector3.zero,
angularVelocity = Vector3.zero;
IncludeInstantVelocities(ref linearVelocity, ref angularVelocity);
IncludeTrendVelocities(ref linearVelocity, ref angularVelocity);
IncludeTangentialInfluence(ref linearVelocity, objectThrown.position);
IncludeExternalVelocities(ref linearVelocity);
_currentThrowVelocities.Clear();
// queue items in order from lastWritePos to earliest sample
int numPoses = _bufferedPoses.Count;
for (int readPos = _lastWritePos, itemsRead = 0;
itemsRead < numPoses; readPos--, itemsRead++)
{
if (readPos < 0)
{
readPos = numPoses - 1;
}
var item = _bufferedPoses[readPos];
ReleaseVelocityInformation newSample = new ReleaseVelocityInformation(
item.LinearVelocity,
item.AngularVelocity,
item.TransformPose.position,
false);
_currentThrowVelocities.Add(newSample);
}
ReleaseVelocityInformation newVelocity = new ReleaseVelocityInformation(linearVelocity,
angularVelocity,
_previousReferencePosition.HasValue ? _previousReferencePosition.Value : Vector3.zero,
true);
_currentThrowVelocities.Add(newVelocity);
WhenThrowVelocitiesChanged(_currentThrowVelocities);
_bufferedPoses.Clear();
_lastWritePos = -1;
return newVelocity;
}
private void IncludeInstantVelocities(ref Vector3 linearVelocity,
ref Vector3 angularVelocity)
{
Vector3 instantLinearVelocity = Vector3.zero,
instantAngularVelocity = Vector3.zero;
IncludeEstimatedReleaseVelocities(ref instantLinearVelocity,
ref instantAngularVelocity);
AddedInstantLinearVelocity = instantLinearVelocity * _instantVelocityInfluence;
linearVelocity += AddedInstantLinearVelocity;
angularVelocity += instantAngularVelocity * _instantVelocityInfluence;
}
private void IncludeEstimatedReleaseVelocities(ref Vector3 linearVelocity,
ref Vector3 angularVelocity)
{
linearVelocity = _linearVelocity;
angularVelocity = _angularVelocity;
if (_stepBackTime < Mathf.Epsilon)
{
return;
}
int beforeIndex, afterIndex;
float lookupTime = Time.time - _stepBackTime;
(beforeIndex, afterIndex) = FindPoseIndicesBasedOnTime(lookupTime);
if (beforeIndex < 0 || afterIndex < 0)
{
return;
}
var previousPoseData = _bufferedPoses[beforeIndex];
var nextPoseData = _bufferedPoses[afterIndex];
float previousTime = previousPoseData.Time;
float nextTime = nextPoseData.Time;
float t = (lookupTime - previousTime) / (nextTime - previousTime);
Vector3 lerpedVelocity = Vector3.Lerp(previousPoseData.LinearVelocity,
nextPoseData.LinearVelocity, t);
Quaternion previousAngularVelocityQuat =
VelocityCalculatorUtilMethods.AngularVelocityToQuat(previousPoseData.AngularVelocity);
Quaternion nextAngularVelocityQuat =
VelocityCalculatorUtilMethods.AngularVelocityToQuat(nextPoseData.AngularVelocity);
Quaternion lerpedAngularVelocQuat = Quaternion.Slerp(previousAngularVelocityQuat,
nextAngularVelocityQuat, t);
Vector3 lerpedAngularVelocity = VelocityCalculatorUtilMethods.QuatToAngularVeloc(
lerpedAngularVelocQuat);
linearVelocity = lerpedVelocity;
angularVelocity = lerpedAngularVelocity;
}
private void IncludeTrendVelocities(ref Vector3 linearVelocity,
ref Vector3 angularVelocity)
{
Vector3 trendLinearVelocity, trendAngularVelocity;
(trendLinearVelocity, trendAngularVelocity) = ComputeTrendVelocities();
AddedTrendLinearVelocity = trendLinearVelocity * + _trendVelocityInfluence;
linearVelocity += AddedTrendLinearVelocity;
angularVelocity += trendLinearVelocity * _trendVelocityInfluence;
}
private void IncludeTangentialInfluence(ref Vector3 linearVelocity, Vector3 interactablePosition)
{
var addedTangentialLinearVelocity = CalculateTangentialVector(interactablePosition);
AddedTangentialLinearVelocity =
addedTangentialLinearVelocity * _tangentialVelocityInfluence;
linearVelocity += AddedTangentialLinearVelocity;
}
private void IncludeExternalVelocities(ref Vector3 linearVelocity)
{
Vector3 extraLinearVelocity, extraAngularVelocity;
(extraLinearVelocity, extraAngularVelocity) = ThrowInputDevice.GetExternalVelocities();
float addedFingerSpeed = extraLinearVelocity.magnitude * _fingerSpeedInfluence;
linearVelocity += linearVelocity.normalized * addedFingerSpeed;
}
private (int, int) FindPoseIndicesBasedOnTime(float time)
{
int beforeIndex = -1, afterIndex = -1;
int numPoses = _bufferedPoses.Count;
for (int i = 0; i < numPoses-1; i++)
{
var currPose = _bufferedPoses[i];
var nextPose = _bufferedPoses[i + 1];
if (currPose.Time < time && nextPose.Time > time)
{
beforeIndex = i;
afterIndex = i + 1;
}
}
return (beforeIndex, afterIndex);
}
private (Vector3, Vector3) ComputeTrendVelocities()
{
Vector3 trendLinearVelocity = Vector3.zero;
Vector3 trendAngularVelocity = Vector3.zero;
if (_bufferedPoses.Count == 0)
{
return (trendLinearVelocity, trendAngularVelocity);
}
if (BufferedVelocitiesValid())
{
FindLargestWindowWithMovement();
if (_windowWithMovement.Count == 0)
{
return (trendAngularVelocity, trendAngularVelocity);
}
foreach (var item in _windowWithMovement)
{
trendLinearVelocity += item.LinearVelocity;
trendAngularVelocity += item.AngularVelocity;
}
trendLinearVelocity /= _bufferedPoses.Count;
trendAngularVelocity /= _bufferedPoses.Count;
}
else
{
(trendLinearVelocity, trendAngularVelocity) =
FindMostRecentBufferedSampleWithMovement();
}
return (trendLinearVelocity, trendAngularVelocity);
}
/// <summary>
/// Do we have enough buffered velocities to derive some sort of trend?
/// If not, return false. This can happen when a user performs a very fast over or
/// underhand throw where most velocities are zero.
/// </summary>
/// <returns></returns>
private bool BufferedVelocitiesValid()
{
int numZeroVectors = 0;
foreach(var item in _bufferedPoses)
{
var velocityVector = item.LinearVelocity;
if (velocityVector.sqrMagnitude < Mathf.Epsilon)
{
numZeroVectors++;
}
}
int numTotalVectors = _bufferedPoses.Count;
float percentZero = (float)numZeroVectors / numTotalVectors;
bool bufferedVelocitiesValid = percentZero > _maxPercentZeroSamplesTrendVeloc ?
false : true;
return bufferedVelocitiesValid;
}
private void FindLargestWindowWithMovement()
{
int numPoses = _bufferedPoses.Count;
bool newWindowFound = false;
_windowWithMovement.Clear();
_tempWindow.Clear();
Vector3 initialVector = Vector3.zero;
// start backwards from last sample
for (int readPos = _lastWritePos, itemsRead = 0;
itemsRead < numPoses; readPos--, itemsRead++)
{
if (readPos < 0)
{
readPos = numPoses - 1;
}
var item = _bufferedPoses[readPos];
bool currentItemHasMovement = item.LinearVelocity.sqrMagnitude > 0.0f;
if (currentItemHasMovement)
{
if (!newWindowFound)
{
newWindowFound = true;
_tempWindow.Clear();
initialVector = item.LinearVelocity;
}
// include vectors that are roughly the same direction as initial velocity
if (Vector3.Dot(initialVector.normalized, item.LinearVelocity.normalized)
> _TREND_DOT_THRESHOLD)
{
_tempWindow.Add(item);
}
}
// end of window when we hit something with no speed
else if (!currentItemHasMovement && newWindowFound)
{
newWindowFound = false;
if (_tempWindow.Count > _windowWithMovement.Count)
{
TransferToDestBuffer(_tempWindow, _windowWithMovement);
}
}
}
// in case window continues till end of buffer
if (newWindowFound)
{
if (_tempWindow.Count > _windowWithMovement.Count)
{
TransferToDestBuffer(_tempWindow, _windowWithMovement);
}
}
}
private (Vector3, Vector3) FindMostRecentBufferedSampleWithMovement()
{
int numPoses = _bufferedPoses.Count;
Vector3 linearVelocity = Vector3.zero;
Vector3 angularVelocity = Vector3.zero;
for (int readPos = _lastWritePos, itemsRead = 0;
itemsRead < numPoses; readPos--, itemsRead++)
{
if (readPos < 0)
{
readPos = numPoses - 1;
}
var item = _bufferedPoses[readPos];
var itemLinearVelocity = item.LinearVelocity;
var itemAngularVelocity = item.AngularVelocity;
if (itemLinearVelocity.sqrMagnitude > Mathf.Epsilon &&
itemAngularVelocity.sqrMagnitude > Mathf.Epsilon)
{
linearVelocity = itemLinearVelocity;
angularVelocity = itemAngularVelocity;
break;
}
}
return (linearVelocity, angularVelocity);
}
private void TransferToDestBuffer(List<SamplePoseData> source, List<SamplePoseData> dest)
{
dest.Clear();
foreach (var sourceItem in source)
{
dest.Add(sourceItem);
}
}
private Vector3 CalculateTangentialVector(Vector3 objectPosition)
{
if (_previousReferencePosition == null)
{
return Vector3.zero;
}
float angularVelocityMag = _angularVelocity.magnitude;
if (angularVelocityMag < Mathf.Epsilon)
{
return Vector3.zero;
}
Vector3 centerOfMassToObject = objectPosition - _previousReferencePosition.Value;
float radius = centerOfMassToObject.magnitude;
Vector3 centerOfMassToObjectNorm = centerOfMassToObject.normalized;
Vector3 axisOfRotation = _angularVelocity.normalized;
Vector3 tangentialDirection = Vector3.Cross(axisOfRotation, centerOfMassToObjectNorm);
// https://byjus.com/tangential-velocity-formula/
return tangentialDirection * radius * angularVelocityMag;
}
public IReadOnlyList<ReleaseVelocityInformation> LastThrowVelocities()
{
return _currentThrowVelocities;
}
public void SetUpdateFrequency(float frequency)
{
_updateFrequency = frequency;
_updateLatency = 1.0f / _updateFrequency;
}
protected virtual void LateUpdate()
{
if (_updateLatency > 0.0f && _lastUpdateTime > 0.0f &&
(Time.time - _lastUpdateTime) < _updateLatency)
{
return;
}
Pose referencePose;
if (!ThrowInputDevice.IsInputValid || !ThrowInputDevice.IsHighConfidence ||
!ThrowInputDevice.GetRootPose(out referencePose))
{
return;
}
_lastUpdateTime = Time.time;
referencePose = new Pose(
_referenceOffset + referencePose.position,
referencePose.rotation);
UpdateVelocitiesAndBuffer(Time.deltaTime, referencePose);
}
private void UpdateVelocitiesAndBuffer(float delta, Pose referencePose)
{
_accumulatedDelta += delta;
UpdateLatestVelocitiesAndPoseValues(referencePose, _accumulatedDelta);
_accumulatedDelta = 0.0f;
int nextWritePos = (_lastWritePos < 0) ? 0 :
(_lastWritePos + 1) % _bufferSize;
var newPose = new SamplePoseData(referencePose, _linearVelocity,
_angularVelocity, Time.time);
if (_bufferedPoses.Count <= nextWritePos)
{
_bufferedPoses.Add(newPose);
}
else
{
_bufferedPoses[nextWritePos] = newPose;
}
_lastWritePos = nextWritePos;
}
private void UpdateLatestVelocitiesAndPoseValues(Pose referencePose, float delta)
{
(_linearVelocity, _angularVelocity) = GetLatestLinearAndAngularVelocities(
referencePose, delta);
_linearVelocity *= _linearVelocityScaleModifier;
WhenNewSampleAvailable(new ReleaseVelocityInformation(_linearVelocity, _angularVelocity,
referencePose.position));
_previousReferencePosition = referencePose.position;
_previousReferenceRotation = referencePose.rotation;
}
private (Vector3, Vector3) GetLatestLinearAndAngularVelocities(Pose referencePose,
float delta)
{
if (!_previousReferencePosition.HasValue || delta < Mathf.Epsilon)
{
return (Vector3.zero, Vector3.zero);
}
Vector3 newLinearVelocity = (referencePose.position -
_previousReferencePosition.Value) / delta;
var newAngularVelocity = VelocityCalculatorUtilMethods.ToAngularVelocity(
_previousReferenceRotation.Value,
referencePose.rotation, delta);
return (newLinearVelocity, newAngularVelocity);
}
#region Inject
public void InjectAllStandardVelocityCalculator(
IPoseInputDevice poseInputDevice,
BufferingParams bufferingParams)
{
InjectPoseInputDevice(poseInputDevice);
InjectBufferingParams(bufferingParams);
}
public void InjectPoseInputDevice(IPoseInputDevice poseInputDevice)
{
_throwInputDevice = poseInputDevice as MonoBehaviour;
ThrowInputDevice = poseInputDevice;
}
public void InjectBufferingParams(BufferingParams bufferingParams)
{
_bufferingParams = bufferingParams;
}
#endregion
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cc8862bea98fed5448c81a6a656d69cf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: