44using UnityEngine ;
55using System . Runtime . InteropServices ;
66using System ;
7+ using System . Collections ;
8+ using HTC . UnityPlugin . LiteCoroutineSystem ;
79#if VIU_VIVE_HAND_TRACKING
810using ViveHandTracking ;
911#endif
@@ -16,20 +18,20 @@ public class ViveHandTrackingSubmodule : VRModule.SubmoduleBase
1618 private struct HandResultData
1719 {
1820 public bool isConnected ;
19- public Vector3 [ ] joints ;
20- public GestureType gesture ;
21- public float confidence ;
22- public float pinchLevel ;
21+ public GestureResult rawData ;
2322 }
2423
24+ private static readonly string LOG_PREFIX = "[" + typeof ( ViveHandTrackingSubmodule ) . Name + "] " ;
2525 private const int RETRY_COUNT = 5 ;
2626 private const float RETRY_INTERVAL = 1f ;
2727 private static readonly int sizeofGestureResult = Marshal . SizeOf ( typeof ( GestureResult ) ) ;
2828
2929 private GestureOption option = new GestureOption ( ) ;
3030 private bool isStarted ;
3131 private int retryCount ;
32- private float nextRetryTime ;
32+ private WaitForTicks retryInterval = WaitForTicks . Seconds ( RETRY_INTERVAL ) ;
33+ private LiteCoroutine startDetectionCoroutine ;
34+ private LiteTask startDetectionTask = new LiteTask ( ) ;
3335
3436 private int lastResultFrame ;
3537 private HandResultData leftResult ;
@@ -42,61 +44,75 @@ private struct HandResultData
4244 protected override void OnActivated ( )
4345 {
4446 retryCount = RETRY_COUNT ;
45- nextRetryTime = 0f ;
4647 GestureInterface . UseExternalTransform ( true ) ;
4748 }
4849
4950 protected override void OnDeactivated ( )
5051 {
5152 GestureInterface . StopGestureDetection ( ) ;
53+ startDetectionTask . Cancel ( ) ;
5254 }
5355
5456 public override uint GetRightHandedIndex ( ) { return rightDeviceIndex ; }
5557
5658 public override uint GetLeftHandedIndex ( ) { return leftDeviceIndex ; }
5759
58- protected override void OnUpdateDeviceConnectionAndPoses ( )
60+ private IEnumerator StartDetectionCoroutine ( )
5961 {
60- // try start engine detection
61- if ( ! isStarted )
62+ while ( true )
6263 {
63- var now = Time . unscaledTime ;
64- if ( now >= nextRetryTime && retryCount >= 0 )
65- {
66- -- retryCount ;
67- nextRetryTime = now + RETRY_INTERVAL ;
64+ var error = GestureInterface . StartGestureDetection ( option ) ;
6865
69- var error = GestureInterface . StartGestureDetection ( option ) ;
66+ lock ( this )
67+ {
7068 switch ( error )
7169 {
7270 case GestureFailure . None :
7371 retryCount = RETRY_COUNT ;
7472 lastResultFrame = - 1 ;
7573 isStarted = true ;
76- Debug . Log ( "[ViveHandTrackingSubmodule] StartGestureDetection") ;
74+ Debug . Log ( LOG_PREFIX + " StartGestureDetection") ;
7775 break ;
7876 case GestureFailure . Camera :
7977 -- retryCount ;
80- nextRetryTime = now + RETRY_INTERVAL ;
8178 if ( retryCount >= 0 )
8279 {
83- Debug . LogWarning ( "[ViveHandTrackingSubmodule] StartGestureDetection fail. Front camera function not found. retrying...") ;
80+ Debug . LogWarning ( LOG_PREFIX + " StartGestureDetection fail. Front camera function not found. retrying(" + ( retryCount + 1 ) + ") ...") ;
8481 }
8582 else
8683 {
87- Debug . LogWarning ( "[ViveHandTrackingSubmodule] StartGestureDetection fail. Front camera function not found.") ;
84+ Debug . LogWarning ( LOG_PREFIX + " StartGestureDetection fail. Front camera function not found.") ;
8885 }
8986 break ;
9087 default :
9188 retryCount = 0 ;
92- Debug . LogWarning ( "[ViveHandTrackingSubmodule] StartGestureDetection fail. error:" + error ) ;
89+ Debug . LogWarning ( LOG_PREFIX + " StartGestureDetection fail. error:" + error ) ;
9390 break ;
9491
9592 }
93+
94+ if ( retryCount <= 0 || isStarted ) { yield break ; }
9695 }
96+
97+ yield return retryInterval ;
9798 }
99+ }
98100
99- if ( ! isStarted ) { return ; }
101+ protected override void OnUpdateDeviceConnectionAndPoses ( )
102+ {
103+ lock ( this )
104+ {
105+ if ( ! isStarted && retryCount > 0 && startDetectionTask . IsDone )
106+ {
107+ // try start engine detection
108+ LiteCoroutine . StartCoroutine ( ref startDetectionCoroutine , startDetectionTask . RestartTask ( StartDetectionCoroutine ( ) ) ) ;
109+ }
110+
111+ if ( ! isStarted ) { return ; }
112+ }
113+
114+ var hmdPose = VRModule . GetDeviceState ( VRModule . HMD_DEVICE_INDEX ) . pose ;
115+ GestureInterface . SetCameraTransform ( hmdPose . pos , hmdPose . rot ) ;
100116
101117 // fetch raw data from engine
102118 IntPtr resultPtr ;
@@ -109,7 +125,7 @@ protected override void OnUpdateDeviceConnectionAndPoses()
109125 isStarted = false ;
110126 return ;
111127 }
112- else if ( resultFrame < lastResultFrame )
128+ else if ( resultFrame <= lastResultFrame )
113129 {
114130 // skip frame
115131 return ;
@@ -128,21 +144,15 @@ protected override void OnUpdateDeviceConnectionAndPoses()
128144 leftResult = new HandResultData ( )
129145 {
130146 isConnected = true ,
131- joints = result . points ,
132- gesture = result . gesture ,
133- confidence = result . confidence ,
134- pinchLevel = result . pinchLevel ,
147+ rawData = result ,
135148 } ;
136149 }
137150 else
138151 {
139152 rightResult = new HandResultData ( )
140153 {
141154 isConnected = true ,
142- joints = result . points ,
143- gesture = result . gesture ,
144- confidence = result . confidence ,
145- pinchLevel = result . pinchLevel ,
155+ rawData = result ,
146156 } ;
147157 }
148158#if NET_4_6
@@ -184,7 +194,7 @@ private void UpdateDeviceConnectionAndPoses(ref HandResultData resultData, ref u
184194
185195 currState . isConnected = true ;
186196 currState . isPoseValid = true ;
187- UpdateDeviceJoints ( currState , resultData . joints , isLeft ) ;
197+ UpdateDeviceJoints ( currState , ref resultData , isLeft ) ;
188198 }
189199 else
190200 {
@@ -205,6 +215,22 @@ protected override void OnUpdateDeviceInput()
205215 UpdateDeviceInput ( ref rightResult , rightDeviceIndex ) ;
206216 }
207217
218+ #if VIU_VIVE_HAND_TRACKING_0_10_0_OR_NEWER
219+ [ StructLayout ( LayoutKind . Sequential ) ]
220+ private struct GestureResult
221+ {
222+ [ MarshalAs ( UnmanagedType . I1 ) ]
223+ public bool isLeft ;
224+ public Vector3 position ;
225+ [ MarshalAs ( UnmanagedType . ByValArray , SizeConst = 21 ) ]
226+ public Vector3 [ ] points ;
227+ [ MarshalAs ( UnmanagedType . ByValArray , SizeConst = 21 ) ]
228+ public Quaternion [ ] rotations ;
229+ public GestureType gesture ;
230+ public float confidence ;
231+ public PinchInfo pinch ;
232+ }
233+
208234 private void UpdateDeviceInput ( ref HandResultData resultData , uint index )
209235 {
210236 if ( ! resultData . isConnected ) { return ; }
@@ -214,12 +240,12 @@ private void UpdateDeviceInput(ref HandResultData resultData, uint index)
214240
215241 EnsureValidDeviceState ( index , out prevState , out currState ) ;
216242
217- var pinched = resultData . pinchLevel >= 0.95f ;
218- var gFist = resultData . gesture == GestureType . Fist && resultData . confidence > 0.1f ;
219- var gFive = resultData . gesture == GestureType . Five && resultData . confidence > 0.1f ;
220- var gOK = resultData . gesture == GestureType . OK && resultData . confidence > 0.1f ;
221- var gLike = resultData . gesture == GestureType . Like && resultData . confidence > 0.1f ;
222- var gPoint = resultData . gesture == GestureType . Point && resultData . confidence > 0.1f ;
243+ var pinched = resultData . rawData . pinch . pinchLevel >= 0.95f ;
244+ var gFist = resultData . rawData . gesture == GestureType . Fist && resultData . rawData . confidence > 0.1f ;
245+ var gFive = resultData . rawData . gesture == GestureType . Five && resultData . rawData . confidence > 0.1f ;
246+ var gOK = resultData . rawData . gesture == GestureType . OK && resultData . rawData . confidence > 0.1f ;
247+ var gLike = resultData . rawData . gesture == GestureType . Like && resultData . rawData . confidence > 0.1f ;
248+ var gPoint = resultData . rawData . gesture == GestureType . Point && resultData . rawData . confidence > 0.1f ;
223249 currState . SetButtonPress ( VRModuleRawButton . GestureIndexPinch , pinched ) ;
224250 currState . SetButtonTouch ( VRModuleRawButton . GestureIndexPinch , pinched ) ;
225251 currState . SetButtonPress ( VRModuleRawButton . GestureFist , gFist ) ;
@@ -234,13 +260,93 @@ private void UpdateDeviceInput(ref HandResultData resultData, uint index)
234260 currState . SetButtonTouch ( VRModuleRawButton . GestureIndexUp , gPoint ) ;
235261 currState . SetButtonPress ( VRModuleRawButton . Grip , gFist ) ;
236262 currState . SetButtonTouch ( VRModuleRawButton . Grip , gFist ) ;
237- currState . SetAxisValue ( VRModuleRawAxis . Trigger , resultData . pinchLevel ) ;
263+ currState . SetAxisValue ( VRModuleRawAxis . Trigger , resultData . rawData . pinch . pinchLevel ) ;
238264 }
239265
240- private static void UpdateDeviceJoints ( IVRModuleDeviceStateRW state , Vector3 [ ] rawJoints , bool isLeft )
266+ private static readonly Quaternion rotOffset = Quaternion . Inverse ( Quaternion . LookRotation ( Vector3 . down , Vector3 . forward ) ) ;
267+ private static void UpdateDeviceJoints ( IVRModuleDeviceStateRW state , ref HandResultData resultData , bool isLeft )
241268 {
242- var hmdPose = VRModule . GetDeviceState ( VRModule . HMD_DEVICE_INDEX ) . pose ;
243- GestureInterface . SetCameraTransform ( hmdPose . pos , hmdPose . rot ) ;
269+ var joints = resultData . rawData . points ;
270+ var rotations = resultData . rawData . rotations ;
271+
272+ state . pose = new RigidPose ( joints [ 0 ] , rotations [ 0 ] * rotOffset ) ;
273+
274+ state . handJoints [ HandJointName . Wrist ] = new JointPose ( new RigidPose ( joints [ 0 ] , rotations [ 0 ] * rotOffset ) ) ;
275+
276+ state . handJoints [ HandJointName . ThumbMetacarpal ] = new JointPose ( new RigidPose ( joints [ 1 ] , rotations [ 1 ] * rotOffset ) ) ;
277+ state . handJoints [ HandJointName . ThumbProximal ] = new JointPose ( new RigidPose ( joints [ 2 ] , rotations [ 2 ] * rotOffset ) ) ;
278+ state . handJoints [ HandJointName . ThumbDistal ] = new JointPose ( new RigidPose ( joints [ 3 ] , rotations [ 3 ] * rotOffset ) ) ;
279+ state . handJoints [ HandJointName . ThumbTip ] = new JointPose ( new RigidPose ( joints [ 4 ] , rotations [ 4 ] * rotOffset ) ) ;
280+
281+ state . handJoints [ HandJointName . IndexProximal ] = new JointPose ( new RigidPose ( joints [ 5 ] , rotations [ 5 ] * rotOffset ) ) ;
282+ state . handJoints [ HandJointName . IndexIntermediate ] = new JointPose ( new RigidPose ( joints [ 6 ] , rotations [ 6 ] * rotOffset ) ) ;
283+ state . handJoints [ HandJointName . IndexDistal ] = new JointPose ( new RigidPose ( joints [ 7 ] , rotations [ 7 ] * rotOffset ) ) ;
284+ state . handJoints [ HandJointName . IndexTip ] = new JointPose ( new RigidPose ( joints [ 8 ] , rotations [ 8 ] * rotOffset ) ) ;
285+
286+ state . handJoints [ HandJointName . MiddleProximal ] = new JointPose ( new RigidPose ( joints [ 9 ] , rotations [ 9 ] * rotOffset ) ) ;
287+ state . handJoints [ HandJointName . MiddleIntermediate ] = new JointPose ( new RigidPose ( joints [ 10 ] , rotations [ 10 ] * rotOffset ) ) ;
288+ state . handJoints [ HandJointName . MiddleDistal ] = new JointPose ( new RigidPose ( joints [ 11 ] , rotations [ 11 ] * rotOffset ) ) ;
289+ state . handJoints [ HandJointName . MiddleTip ] = new JointPose ( new RigidPose ( joints [ 12 ] , rotations [ 12 ] * rotOffset ) ) ;
290+
291+ state . handJoints [ HandJointName . RingProximal ] = new JointPose ( new RigidPose ( joints [ 13 ] , rotations [ 13 ] * rotOffset ) ) ;
292+ state . handJoints [ HandJointName . RingIntermediate ] = new JointPose ( new RigidPose ( joints [ 14 ] , rotations [ 14 ] * rotOffset ) ) ;
293+ state . handJoints [ HandJointName . RingDistal ] = new JointPose ( new RigidPose ( joints [ 15 ] , rotations [ 15 ] * rotOffset ) ) ;
294+ state . handJoints [ HandJointName . RingTip ] = new JointPose ( new RigidPose ( joints [ 16 ] , rotations [ 16 ] * rotOffset ) ) ;
295+
296+ state . handJoints [ HandJointName . PinkyProximal ] = new JointPose ( new RigidPose ( joints [ 17 ] , rotations [ 17 ] * rotOffset ) ) ;
297+ state . handJoints [ HandJointName . PinkyIntermediate ] = new JointPose ( new RigidPose ( joints [ 18 ] , rotations [ 18 ] * rotOffset ) ) ;
298+ state . handJoints [ HandJointName . PinkyDistal ] = new JointPose ( new RigidPose ( joints [ 19 ] , rotations [ 19 ] * rotOffset ) ) ;
299+ state . handJoints [ HandJointName . PinkyTip ] = new JointPose ( new RigidPose ( joints [ 20 ] , rotations [ 20 ] * rotOffset ) ) ;
300+ }
301+ #else
302+ [ StructLayout ( LayoutKind . Sequential ) ]
303+ private struct GestureResult
304+ {
305+ [ MarshalAs ( UnmanagedType . I1 ) ]
306+ public bool isLeft ;
307+ [ MarshalAs ( UnmanagedType . ByValArray , SizeConst = 21 ) ]
308+ public Vector3 [ ] points ;
309+ public GestureType gesture ;
310+ public float confidence ;
311+ public float pinchLevel ;
312+ }
313+
314+ private void UpdateDeviceInput ( ref HandResultData resultData , uint index )
315+ {
316+ if ( ! resultData . isConnected ) { return ; }
317+
318+ IVRModuleDeviceState prevState ;
319+ IVRModuleDeviceStateRW currState ;
320+
321+ EnsureValidDeviceState ( index , out prevState , out currState ) ;
322+
323+ var pinched = resultData . rawData . pinchLevel >= 0.95f ;
324+ var gFist = resultData . rawData . gesture == GestureType . Fist && resultData . rawData . confidence > 0.1f ;
325+ var gFive = resultData . rawData . gesture == GestureType . Five && resultData . rawData . confidence > 0.1f ;
326+ var gOK = resultData . rawData . gesture == GestureType . OK && resultData . rawData . confidence > 0.1f ;
327+ var gLike = resultData . rawData . gesture == GestureType . Like && resultData . rawData . confidence > 0.1f ;
328+ var gPoint = resultData . rawData . gesture == GestureType . Point && resultData . rawData . confidence > 0.1f ;
329+ currState . SetButtonPress ( VRModuleRawButton . GestureIndexPinch , pinched ) ;
330+ currState . SetButtonTouch ( VRModuleRawButton . GestureIndexPinch , pinched ) ;
331+ currState . SetButtonPress ( VRModuleRawButton . GestureFist , gFist ) ;
332+ currState . SetButtonTouch ( VRModuleRawButton . GestureFist , gFist ) ;
333+ currState . SetButtonPress ( VRModuleRawButton . GestureFive , gFive ) ;
334+ currState . SetButtonTouch ( VRModuleRawButton . GestureFive , gFive ) ;
335+ currState . SetButtonPress ( VRModuleRawButton . GestureOk , gOK ) ;
336+ currState . SetButtonTouch ( VRModuleRawButton . GestureOk , gOK ) ;
337+ currState . SetButtonPress ( VRModuleRawButton . GestureThumbUp , gLike ) ;
338+ currState . SetButtonTouch ( VRModuleRawButton . GestureThumbUp , gLike ) ;
339+ currState . SetButtonPress ( VRModuleRawButton . GestureIndexUp , gPoint ) ;
340+ currState . SetButtonTouch ( VRModuleRawButton . GestureIndexUp , gPoint ) ;
341+ currState . SetButtonPress ( VRModuleRawButton . Grip , gFist ) ;
342+ currState . SetButtonTouch ( VRModuleRawButton . Grip , gFist ) ;
343+ currState . SetAxisValue ( VRModuleRawAxis . Trigger , resultData . rawData . pinchLevel ) ;
344+ }
345+
346+ private static void UpdateDeviceJoints ( IVRModuleDeviceStateRW state , ref HandResultData resultData , bool isLeft )
347+ {
348+ var rawJoints = resultData . rawData . points ;
349+
244350 var roomSpaceWrist2index = rawJoints [ 5 ] - rawJoints [ 0 ] ;
245351 var roomSpaceWrist2middle = rawJoints [ 9 ] - rawJoints [ 0 ] ;
246352 var roomSpaceWrist2pinky = rawJoints [ 17 ] - rawJoints [ 0 ] ;
@@ -299,18 +405,7 @@ private static Quaternion CalculateJointRot(Vector3[] joints, int i, int iChild,
299405 var forward = joints [ iChild ] - joints [ i ] ;
300406 return Quaternion . LookRotation ( forward , Vector3 . Cross ( forward , right ) ) ;
301407 }
302-
303- [ StructLayout ( LayoutKind . Sequential ) ]
304- private struct GestureResult
305- {
306- [ MarshalAs ( UnmanagedType . I1 ) ]
307- public bool isLeft ;
308- [ MarshalAs ( UnmanagedType . ByValArray , SizeConst = 21 ) ]
309- public Vector3 [ ] points ;
310- public GestureType gesture ;
311- public float confidence ;
312- public float pinchLevel ;
313- }
408+ #endif
314409
315410 private static class GestureInterface
316411 {
@@ -332,5 +427,5 @@ private static class GestureInterface
332427 internal static extern void SetCameraTransform ( Vector3 position , Quaternion rotation ) ;
333428 }
334429#endif
335- }
336- }
430+ }
431+ }
0 commit comments