Tanoda
SlidingWindowThrow.cs
Go to the documentation of this file.
1/******************************************************************************
2 * Copyright (C) Ultraleap, Inc. 2011-2020. *
3 * *
4 * Use subject to the terms of the Apache License 2.0 available at *
5 * http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
6 * between Ultraleap and you, your company or other organization. *
7 ******************************************************************************/
8
10using System.Collections.Generic;
11using UnityEngine;
12
13namespace Leap.Unity.Interaction {
14
22
26 private float _windowLength = 0.05F;
27
31 private float _windowDelay = 0.02F;
32
37 private AnimationCurve _velocityMultiplierCurve = new AnimationCurve(
38 new Keyframe(0.0F, 1.0F, 0, 0),
39 new Keyframe(3.0F, 1.5F, 0, 0));
40
41 private struct VelocitySample {
42 public float time;
43 public Vector3 position;
44 public Quaternion rotation;
45
46 public VelocitySample(Vector3 position, Quaternion rotation, float time) {
47 this.position = position;
48 this.rotation = rotation;
49 this.time = Time.fixedTime;
50 }
51
52 public static VelocitySample Interpolate(VelocitySample a, VelocitySample b, float time) {
53 float alpha = Mathf.Clamp01(Mathf.InverseLerp(a.time, b.time, time));
54
55 return new VelocitySample(Vector3.Lerp(a.position, b.position, alpha),
56 Quaternion.Slerp(a.rotation, b.rotation, alpha),
57 time);
58 }
59 }
60
61 private Queue<VelocitySample> _velocityQueue = new Queue<VelocitySample>(64);
62
66 public void OnHold(InteractionBehaviour intObj,
68 _velocityQueue.Enqueue(new VelocitySample(intObj.rigidbody.position,
69 intObj.rigidbody.rotation,
70 Time.fixedTime));
71
72 while (true) {
73 VelocitySample oldestVelocity = _velocityQueue.Peek();
74
75 // Dequeue conservatively if the oldest velocity is more than 4 frames later
76 // than the start of the window.
77 if (oldestVelocity.time + (Time.fixedDeltaTime * 4) < Time.fixedTime
78 - _windowLength
79 - _windowDelay) {
80 _velocityQueue.Dequeue();
81 }
82 else {
83 break;
84 }
85 }
86 }
87
91 public void OnThrow(InteractionBehaviour intObj, InteractionController throwingController) {
92 if (_velocityQueue.Count < 2) {
93 intObj.rigidbody.velocity = Vector3.zero;
94 intObj.rigidbody.angularVelocity = Vector3.zero;
95 return;
96 }
97
98 float windowEnd = Time.fixedTime - _windowDelay;
99 float windowStart = windowEnd - _windowLength;
100
101 // 0 occurs before 1,
102 // start occurs before end.
103 VelocitySample start0, start1;
104 VelocitySample end0, end1;
105 VelocitySample s0, s1;
106
107 s0 = s1 = start0 = start1 = end0 = end1 = _velocityQueue.Dequeue();
108
109 while (_velocityQueue.Count != 0) {
110 s0 = s1;
111 s1 = _velocityQueue.Dequeue();
112
113 if (s0.time < windowStart && s1.time >= windowStart) {
114 start0 = s0;
115 start1 = s1;
116 }
117
118 if (s0.time < windowEnd && s1.time >= windowEnd) {
119 end0 = s0;
120 end1 = s1;
121
122 // We have assigned both start and end and can break out of the loop.
123 _velocityQueue.Clear();
124 break;
125 }
126 }
127
128 VelocitySample start = VelocitySample.Interpolate(start0, start1, windowStart);
129 VelocitySample end = VelocitySample.Interpolate(end0, end1, windowEnd);
130
131 Vector3 interpolatedVelocity = PhysicsUtility.ToLinearVelocity(start.position,
132 end.position,
133 _windowLength);
134
135 intObj.rigidbody.velocity = interpolatedVelocity;
136 intObj.rigidbody.angularVelocity = PhysicsUtility.ToAngularVelocity(start.rotation,
137 end.rotation,
138 _windowLength);
139
140 intObj.rigidbody.velocity *= _velocityMultiplierCurve.Evaluate(intObj.rigidbody.velocity.magnitude);
141 }
142
143 }
144
145}
InteractionBehaviours are components that enable GameObjects to interact with interaction controllers...
Rigidbody rigidbody
The Rigidbody associated with this interaction object.
The sliding window throw handler implements a simple heuristic that provides a reasonably accurate me...
void OnThrow(InteractionBehaviour intObj, InteractionController throwingController)
Transfers the averaged velocity to the released object.
void OnHold(InteractionBehaviour intObj, ReadonlyList< InteractionController > controllers)
Samples the current velocity and adds it to a rolling average.
Interaction objects feed their throw handlers callbacks when they are held (for data collection) and ...
A simple wrapper around List to provide readonly access. Useful when you want to return a list to som...
Definition: ReadonlyList.cs:20