-
Notifications
You must be signed in to change notification settings - Fork 63
/
Copy pathFromXRHandDataSource.cs
283 lines (231 loc) · 9.87 KB
/
FromXRHandDataSource.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
// Copyright (c) Meta Platforms, Inc. and affiliates.
#if HAS_META_INTERACTION && HAS_META_AVATARS
using Meta.Utilities;
using Meta.Utilities.Input;
using Oculus.Interaction;
using Oculus.Interaction.Input;
using UnityEngine;
using UnityEngine.Assertions;
namespace Meta.Utilities.Input
{
[DefaultExecutionOrder(-80)]
public class FromXRHandDataSource : DataSource<HandDataAsset>
{
[SerializeField]
private Transform[] m_bones;
[SerializeField]
private Vector3 m_rootOffset;
[SerializeField]
private Vector3 m_rootAngleOffset;
[Header("OVR Data Source")]
[SerializeField, Interface(typeof(IOVRCameraRigRef))]
private MonoBehaviour m_cameraRigRef;
private IOVRCameraRigRef CameraRigRef { get; set; }
[SerializeField]
private bool m_processLateUpdates;
[Header("Shared Configuration")]
[SerializeField]
private Handedness m_handedness;
[SerializeField, Interface(typeof(ITrackingToWorldTransformer))]
private MonoBehaviour m_trackingToWorldTransformer;
private ITrackingToWorldTransformer TrackingToWorldTransformer { get; set; }
public bool ProcessLateUpdates
{
get => m_processLateUpdates;
set => m_processLateUpdates = value;
}
private readonly HandDataAsset m_handDataAsset = new();
[AutoSetFromParent]
[SerializeField] private XRInputManager m_xrInputManager;
private Transform m_ovrControllerAnchor;
private HandDataSourceConfig m_config;
private Pose m_poseOffset;
public static Quaternion WristFixupRotation { get; } = new(0.0f, 1.0f, 0.0f, 0.0f);
protected override HandDataAsset DataAsset => m_handDataAsset;
#if HAS_NAUGHTY_ATTRIBUTES
[NaughtyAttributes.ShowNativeProperty]
#endif
private Vector3 CurrentRootPosition => DataAsset?.Root.position ?? Vector3.zero;
private HandSkeleton m_skeleton;
protected void Awake()
{
m_skeleton = HandSkeletonOVR.CreateSkeletonData(m_handedness);
TrackingToWorldTransformer = m_trackingToWorldTransformer as ITrackingToWorldTransformer;
CameraRigRef = m_cameraRigRef as IOVRCameraRigRef;
UpdateConfig();
}
protected override void Start()
{
this.BeginStart(ref _started, base.Start);
Assert.IsNotNull(CameraRigRef);
Assert.IsNotNull(TrackingToWorldTransformer);
if (m_handedness == Handedness.Left)
{
Assert.IsNotNull(CameraRigRef.LeftHand);
m_ovrControllerAnchor = CameraRigRef.LeftController;
}
else
{
Assert.IsNotNull(CameraRigRef.RightHand);
m_ovrControllerAnchor = CameraRigRef.RightController;
}
var offset = new Pose(m_rootOffset, Quaternion.Euler(m_rootAngleOffset));
if (m_handedness == Handedness.Left)
{
offset.position.x = -offset.position.x;
offset.rotation = Quaternion.Euler(180f, 0f, 0f) * offset.rotation;
}
m_poseOffset = offset;
UpdateSkeleton();
UpdateConfig();
this.EndStart(ref _started);
}
protected override void OnEnable()
{
base.OnEnable();
if (_started)
{
CameraRigRef.WhenInputDataDirtied += HandleInputDataDirtied;
}
}
protected override void OnDisable()
{
if (_started)
{
CameraRigRef.WhenInputDataDirtied -= HandleInputDataDirtied;
}
base.OnDisable();
}
private void HandleInputDataDirtied(bool isLateUpdate)
{
if (isLateUpdate && !m_processLateUpdates)
{
return;
}
MarkInputDataRequiresUpdate();
}
private void UpdateSkeleton()
{
if (_started)
{
for (var i = 0; i < m_skeleton.joints.Length; i++)
{
m_skeleton.joints[i].pose.position = m_bones[i].localPosition;
m_skeleton.joints[i].pose.rotation = m_bones[i].localRotation;
}
}
}
private HandDataSourceConfig Config
{
get
{
if (m_config != null)
{
return m_config;
}
m_config = new HandDataSourceConfig()
{
Handedness = m_handedness
};
return m_config;
}
}
private void UpdateConfig()
{
Config.Handedness = m_handedness;
Config.TrackingToWorldTransformer = TrackingToWorldTransformer;
Config.HandSkeleton = m_skeleton;
}
protected override void UpdateData()
{
m_handDataAsset.Config = Config;
m_handDataAsset.IsDataValid = true;
m_handDataAsset.IsConnected = true;
if (!m_handDataAsset.IsConnected)
{
// revert state fields to their defaults
m_handDataAsset.IsTracked = default;
m_handDataAsset.RootPoseOrigin = default;
m_handDataAsset.PointerPoseOrigin = default;
m_handDataAsset.IsHighConfidence = default;
for (var fingerIdx = 0; fingerIdx < Constants.NUM_FINGERS; fingerIdx++)
{
m_handDataAsset.IsFingerPinching[fingerIdx] = default;
m_handDataAsset.IsFingerHighConfidence[fingerIdx] = default;
}
return;
}
m_handDataAsset.IsTracked = true;
m_handDataAsset.IsHighConfidence = true;
m_handDataAsset.HandScale = 1f;
m_handDataAsset.IsDominantHand = m_handedness == Handedness.Right;
var actions = m_xrInputManager.GetActions(m_handedness == Handedness.Left);
var anchor = m_xrInputManager.GetAnchor(m_handedness == Handedness.Left);
var indexStrength = actions.AxisIndexTrigger.action.ReadValue<float>();
var gripStrength = actions.AxisHandTrigger.action.ReadValue<float>();
m_handDataAsset.IsFingerHighConfidence[(int)HandFinger.Thumb] = true;
m_handDataAsset.IsFingerPinching[(int)HandFinger.Thumb] = indexStrength >= 0.95f || gripStrength >= 0.95f;
m_handDataAsset.FingerPinchStrength[(int)HandFinger.Thumb] = Mathf.Max(indexStrength, gripStrength);
m_handDataAsset.IsFingerHighConfidence[(int)HandFinger.Index] = true;
m_handDataAsset.IsFingerPinching[(int)HandFinger.Index] = indexStrength >= 0.95f;
m_handDataAsset.FingerPinchStrength[(int)HandFinger.Index] = indexStrength;
m_handDataAsset.IsFingerHighConfidence[(int)HandFinger.Middle] = true;
m_handDataAsset.IsFingerPinching[(int)HandFinger.Middle] = gripStrength >= 0.95f;
m_handDataAsset.FingerPinchStrength[(int)HandFinger.Middle] = gripStrength;
m_handDataAsset.IsFingerHighConfidence[(int)HandFinger.Ring] = true;
m_handDataAsset.IsFingerPinching[(int)HandFinger.Ring] = gripStrength >= 0.95f;
m_handDataAsset.FingerPinchStrength[(int)HandFinger.Ring] = gripStrength;
m_handDataAsset.IsFingerHighConfidence[(int)HandFinger.Pinky] = true;
m_handDataAsset.IsFingerPinching[(int)HandFinger.Pinky] = gripStrength >= 0.95f;
m_handDataAsset.FingerPinchStrength[(int)HandFinger.Pinky] = gripStrength;
m_handDataAsset.PointerPoseOrigin = PoseOrigin.RawTrackedPose;
m_handDataAsset.PointerPose = new Pose(anchor.localPosition, anchor.localRotation);
for (var i = 0; i < m_bones.Length; i++)
{
m_handDataAsset.Joints[i] = m_bones[i].localRotation;
}
m_handDataAsset.Joints[0] = WristFixupRotation;
// Convert controller pose from world to tracking space.
var pose = new Pose(m_ovrControllerAnchor.position, m_ovrControllerAnchor.rotation);
pose = Config.TrackingToWorldTransformer.ToTrackingPose(pose);
PoseUtils.Multiply(pose, m_poseOffset, ref m_handDataAsset.Root);
m_handDataAsset.RootPoseOrigin = PoseOrigin.RawTrackedPose;
}
#region Inject
public void InjectAllFromOVRControllerHandDataSource(UpdateModeFlags updateMode, IDataSource updateAfter,
Handedness handedness, ITrackingToWorldTransformer trackingToWorldTransformer,
IDataSource<HmdDataAsset> hmdData, Transform[] bones,
Vector3 rootOffset, Vector3 rootAngleOffset)
{
InjectAllDataSource(updateMode, updateAfter);
InjectHandedness(handedness);
InjectTrackingToWorldTransformer(trackingToWorldTransformer);
InjectBones(bones);
InjectRootOffset(rootOffset);
InjectRootAngleOffset(rootAngleOffset);
}
public void InjectHandedness(Handedness handedness)
{
m_handedness = handedness;
}
public void InjectTrackingToWorldTransformer(ITrackingToWorldTransformer trackingToWorldTransformer)
{
m_trackingToWorldTransformer = trackingToWorldTransformer as MonoBehaviour;
TrackingToWorldTransformer = trackingToWorldTransformer;
}
public void InjectBones(Transform[] bones)
{
m_bones = bones;
}
public void InjectRootOffset(Vector3 rootOffset)
{
m_rootOffset = rootOffset;
}
public void InjectRootAngleOffset(Vector3 rootAngleOffset)
{
m_rootAngleOffset = rootAngleOffset;
}
#endregion
}
}
#endif