Skip to content

Commit a52fab5

Browse files
author
lawwong
committed
Now update tracked hand bone pose correctly
1 parent e1b2a21 commit a52fab5

3 files changed

Lines changed: 140 additions & 72 deletions

File tree

Assets/HTC.UnityPlugin/VRModule/Modules/OculusVRModule.cs

Lines changed: 138 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,6 @@ public override void UpdateRenderModel()
160160

161161
if (m_index == s_rightControllerIndex && VIUOvrAvatar.SUPPORTED)
162162
{
163-
Debug.Log("lawwong right ctrl " + m_index);
164163
LoadAvatar();
165164
if (m_rightModel == null)
166165
{
@@ -182,7 +181,6 @@ public override void UpdateRenderModel()
182181

183182
if (m_index == s_leftControllerIndex && VIUOvrAvatar.SUPPORTED)
184183
{
185-
Debug.Log("lawwong left ctrl " + m_index);
186184
LoadAvatar();
187185
if (m_leftModel == null)
188186
{
@@ -256,8 +254,28 @@ private bool IsHand()
256254
private string m_systemHeadsetName;
257255
private OVRPlugin.TrackingOrigin m_prevTrackingSpace;
258256

259-
private bool m_isLeftHandTracked;
260-
private bool m_isRightHandTracked;
257+
#if VIU_OCULUSVR_20_0_OR_NEWER
258+
private struct SkeletonData
259+
{
260+
public bool isLeft;
261+
public bool ready;
262+
public OVRPlugin.Skeleton data;
263+
public SkeletonData GetReady()
264+
{
265+
if (!ready)
266+
{
267+
ready = OVRPlugin.GetSkeleton(isLeft ? OVRPlugin.SkeletonType.HandLeft : OVRPlugin.SkeletonType.HandRight, out data);
268+
}
269+
270+
return this;
271+
}
272+
}
273+
274+
private SkeletonData m_leftSkeletonData = new SkeletonData() { isLeft = true };
275+
private SkeletonData m_rightSkeletonData = new SkeletonData() { isLeft = false };
276+
private static readonly Quaternion m_leftRotOffset = Quaternion.LookRotation(Vector3.right, Vector3.down);
277+
private static readonly Quaternion m_rightRotOffset = Quaternion.LookRotation(Vector3.right, Vector3.up);
278+
#endif
261279

262280
static OculusVRModule()
263281
{
@@ -347,7 +365,7 @@ public override void OnActivated()
347365
m_systemHeadsetType = OVRPlugin.GetSystemHeadsetType();
348366
m_systemHeadsetName = m_systemHeadsetType.ToString();
349367
m_prevTrackingSpace = OVRPlugin.GetTrackingOriginType();
350-
UpdateTrackingSpaceType();
368+
//UpdateTrackingSpaceType();
351369

352370
EnsureDeviceStateLength((uint)s_index2node.Length);
353371

@@ -361,30 +379,38 @@ public override void OnDeactivated()
361379

362380
public override void UpdateTrackingSpaceType()
363381
{
382+
OVRPlugin.TrackingOrigin demandTrackingOrigin;
364383
switch (VRModule.trackingSpaceType)
365384
{
366385
case VRModuleTrackingSpaceType.RoomScale:
367386
#if !VIU_OCULUSVR_19_0_OR_NEWER
368387
if (OVRPlugin.GetSystemHeadsetType().Equals(OVRPlugin.SystemHeadset.Oculus_Go))
369388
{
370-
OVRPlugin.SetTrackingOriginType(OVRPlugin.TrackingOrigin.EyeLevel);
389+
demandTrackingOrigin = OVRPlugin.TrackingOrigin.EyeLevel;
371390
}
372391
else
373392
#endif
374393
{
375-
OVRPlugin.SetTrackingOriginType(OVRPlugin.TrackingOrigin.FloorLevel);
376-
Debug.Log("lawwong SetTrackingOriginType FloorLevel");
394+
demandTrackingOrigin = OVRPlugin.TrackingOrigin.FloorLevel;
377395
}
378396
break;
379397
case VRModuleTrackingSpaceType.Stationary:
380-
OVRPlugin.SetTrackingOriginType(OVRPlugin.TrackingOrigin.EyeLevel);
381-
Debug.Log("lawwong SetTrackingOriginType EyeLevel");
398+
demandTrackingOrigin = OVRPlugin.TrackingOrigin.EyeLevel;
382399
break;
400+
default:
401+
return;
402+
}
403+
404+
if (OVRPlugin.GetTrackingOriginType() != demandTrackingOrigin)
405+
{
406+
OVRPlugin.SetTrackingOriginType(demandTrackingOrigin);
383407
}
384408
}
385409

386410
public override void Update()
387411
{
412+
UpdateTrackingSpaceType();
413+
388414
// set physics update rate to vr render rate
389415
if (VRModule.lockPhysicsUpdateRateToRenderFrequency && Time.timeScale > 0.0f)
390416
{
@@ -401,7 +427,7 @@ public override uint GetLeftControllerDeviceIndex()
401427
{
402428
IVRModuleDeviceState prevState;
403429
IVRModuleDeviceStateRW currState;
404-
if (TryGetValidDeviceState(s_leftHandIndex, out prevState, out currState)) { return s_leftHandIndex; }
430+
if (TryGetValidDeviceState(s_leftHandIndex, out prevState, out currState) && currState.isConnected) { return s_leftHandIndex; }
405431
if (TryGetValidDeviceState(s_leftControllerIndex, out prevState, out currState) && currState.isConnected) { return s_leftControllerIndex; }
406432
return INVALID_DEVICE_INDEX;
407433
}
@@ -410,7 +436,7 @@ public override uint GetRightControllerDeviceIndex()
410436
{
411437
IVRModuleDeviceState prevState;
412438
IVRModuleDeviceStateRW currState;
413-
if (TryGetValidDeviceState(s_rightHandIndex, out prevState, out currState)) { return s_rightHandIndex; }
439+
if (TryGetValidDeviceState(s_rightHandIndex, out prevState, out currState) && currState.isConnected) { return s_rightHandIndex; }
414440
if (TryGetValidDeviceState(s_rightControllerIndex, out prevState, out currState) && currState.isConnected) { return s_rightControllerIndex; }
415441
return INVALID_DEVICE_INDEX;
416442
}
@@ -421,10 +447,22 @@ private static RigidPose ToPose(OVRPlugin.Posef value)
421447
return new RigidPose(ovrPose.position, ovrPose.orientation);
422448
}
423449

424-
private static RigidPose ToRigidPose(OVRPlugin.Posef value)
450+
private static Quaternion leftHandRotOffset = Quaternion.Inverse(Quaternion.LookRotation(Vector3.right, Vector3.down));
451+
private static Quaternion rightHandRotOffset = Quaternion.Inverse(Quaternion.LookRotation(Vector3.right, Vector3.down));
452+
private static RigidPose FromHandPose(OVRPlugin.Posef value, bool isLeft)
425453
{
426-
var ovrPose = value.ToOVRPose();
427-
return new RigidPose(ovrPose.position, ovrPose.orientation);
454+
return FromHandPose(value);
455+
//var ovrPose = value.ToOVRPose();
456+
////return new RigidPose(ovrPose.position, ovrPose.orientation * (isLeft ? leftHandRotOffset : rightHandRotOffset));
457+
//return new RigidPose(ovrPose.position, ovrPose.orientation);
458+
}
459+
private static RigidPose FromHandPose(OVRPlugin.Posef value)
460+
{
461+
return new RigidPose()
462+
{
463+
pos = value.Position.FromFlippedZVector3f(),
464+
rot = value.Orientation.FromFlippedZQuatf(),
465+
};
428466
}
429467

430468
public override void BeforeRenderUpdate()
@@ -457,7 +495,11 @@ public override void BeforeRenderUpdate()
457495

458496
if ((handState.Status & (OVRPlugin.HandStatus.HandTracked | OVRPlugin.HandStatus.InputStateValid)) == 0)
459497
{
460-
currState.Reset();
498+
if (prevState.isConnected)
499+
{
500+
Debug.Log("[VIU][OculusVRModule] device disconnected. name:" + prevState.modelNumber + " model:" + prevState.deviceModel);
501+
currState.Reset();
502+
}
461503
continue;
462504
}
463505
}
@@ -468,8 +510,8 @@ public override void BeforeRenderUpdate()
468510
if (prevState.isConnected)
469511
{
470512
Debug.Log("[VIU][OculusVRModule] device disconnected. name:" + prevState.modelNumber + " model:" + prevState.deviceModel);
513+
currState.Reset();
471514
}
472-
currState.Reset();
473515
continue;
474516
}
475517

@@ -666,68 +708,94 @@ public override void BeforeRenderUpdate()
666708
case VRModuleDeviceModel.OculusTrackedHandLeft:
667709
case VRModuleDeviceModel.OculusTrackedHandRight:
668710
#if VIU_OCULUSVR_20_0_OR_NEWER
669-
if ((handState.Status & OVRPlugin.HandStatus.InputStateValid) != 0)
670-
{
671-
currState.SetButtonPress(VRModuleRawButton.GestureIndexPinch, (handState.Pinches & OVRPlugin.HandFingerPinch.Index) == OVRPlugin.HandFingerPinch.Index);
672-
currState.SetButtonPress(VRModuleRawButton.GestureMiddlePinch, (handState.Pinches & OVRPlugin.HandFingerPinch.Middle) == OVRPlugin.HandFingerPinch.Middle);
673-
currState.SetButtonPress(VRModuleRawButton.GestureRingPinch, (handState.Pinches & OVRPlugin.HandFingerPinch.Ring) == OVRPlugin.HandFingerPinch.Ring);
674-
currState.SetButtonPress(VRModuleRawButton.GesturePinkyPinch, (handState.Pinches & OVRPlugin.HandFingerPinch.Pinky) == OVRPlugin.HandFingerPinch.Pinky);
675-
676-
currState.SetButtonTouch(VRModuleRawButton.GestureIndexPinch, (handState.Pinches & OVRPlugin.HandFingerPinch.Index) == OVRPlugin.HandFingerPinch.Index);
677-
currState.SetButtonTouch(VRModuleRawButton.GestureMiddlePinch, (handState.Pinches & OVRPlugin.HandFingerPinch.Middle) == OVRPlugin.HandFingerPinch.Middle);
678-
currState.SetButtonTouch(VRModuleRawButton.GestureRingPinch, (handState.Pinches & OVRPlugin.HandFingerPinch.Ring) == OVRPlugin.HandFingerPinch.Ring);
679-
currState.SetButtonTouch(VRModuleRawButton.GesturePinkyPinch, (handState.Pinches & OVRPlugin.HandFingerPinch.Pinky) == OVRPlugin.HandFingerPinch.Pinky);
680-
681-
currState.SetAxisValue(VRModuleRawAxis.IndexPinch, handState.PinchStrength[(int)HandFinger.Index]);
682-
currState.SetAxisValue(VRModuleRawAxis.MiddlePinch, handState.PinchStrength[(int)HandFinger.Middle]);
683-
currState.SetAxisValue(VRModuleRawAxis.RingPinch, handState.PinchStrength[(int)HandFinger.Ring]);
684-
currState.SetAxisValue(VRModuleRawAxis.PinkyPinch, handState.PinchStrength[(int)HandFinger.Pinky]);
685-
686-
// Map index pinch to trigger
687-
currState.SetButtonPress(VRModuleRawButton.Trigger, currState.GetButtonPress(VRModuleRawButton.GestureIndexPinch));
688-
currState.SetButtonTouch(VRModuleRawButton.Trigger, currState.GetButtonTouch(VRModuleRawButton.GestureIndexPinch));
689-
currState.SetAxisValue(VRModuleRawAxis.Trigger, currState.GetAxisValue(VRModuleRawAxis.IndexPinch));
690-
691-
currState.pose = ToRigidPose(handState.PointerPose);
692-
currState.isPoseValid = currState.pose != RigidPose.identity;
693-
}
694-
else
695711
{
696-
currState.pose = ToRigidPose(handState.RootPose);
697-
currState.isPoseValid = currState.pose != RigidPose.identity;
698-
}
699-
700-
if ((handState.Status & OVRPlugin.HandStatus.HandTracked) != 0)
701-
{
702-
var skeletonType = node == OVRPlugin.Node.HandLeft ? OVRPlugin.SkeletonType.HandLeft : OVRPlugin.SkeletonType.HandRight;
703-
OVRPlugin.Skeleton ovrSkeleton;
704-
if (!OVRPlugin.GetSkeleton(skeletonType, out ovrSkeleton))
712+
var isLeft = node == OVRPlugin.Node.HandLeft;
713+
if ((handState.Status & OVRPlugin.HandStatus.InputStateValid) != 0)
705714
{
706-
Debug.LogWarning("[OculusVRModule] OVRPlugin.GetSkeleton fail. skeletonType=" + skeletonType);
715+
currState.SetButtonPress(VRModuleRawButton.GestureIndexPinch, (handState.Pinches & OVRPlugin.HandFingerPinch.Index) == OVRPlugin.HandFingerPinch.Index);
716+
currState.SetButtonPress(VRModuleRawButton.GestureMiddlePinch, (handState.Pinches & OVRPlugin.HandFingerPinch.Middle) == OVRPlugin.HandFingerPinch.Middle);
717+
currState.SetButtonPress(VRModuleRawButton.GestureRingPinch, (handState.Pinches & OVRPlugin.HandFingerPinch.Ring) == OVRPlugin.HandFingerPinch.Ring);
718+
currState.SetButtonPress(VRModuleRawButton.GesturePinkyPinch, (handState.Pinches & OVRPlugin.HandFingerPinch.Pinky) == OVRPlugin.HandFingerPinch.Pinky);
719+
720+
currState.SetButtonTouch(VRModuleRawButton.GestureIndexPinch, (handState.Pinches & OVRPlugin.HandFingerPinch.Index) == OVRPlugin.HandFingerPinch.Index);
721+
currState.SetButtonTouch(VRModuleRawButton.GestureMiddlePinch, (handState.Pinches & OVRPlugin.HandFingerPinch.Middle) == OVRPlugin.HandFingerPinch.Middle);
722+
currState.SetButtonTouch(VRModuleRawButton.GestureRingPinch, (handState.Pinches & OVRPlugin.HandFingerPinch.Ring) == OVRPlugin.HandFingerPinch.Ring);
723+
currState.SetButtonTouch(VRModuleRawButton.GesturePinkyPinch, (handState.Pinches & OVRPlugin.HandFingerPinch.Pinky) == OVRPlugin.HandFingerPinch.Pinky);
724+
725+
currState.SetAxisValue(VRModuleRawAxis.IndexPinch, handState.PinchStrength[(int)HandFinger.Index]);
726+
currState.SetAxisValue(VRModuleRawAxis.MiddlePinch, handState.PinchStrength[(int)HandFinger.Middle]);
727+
currState.SetAxisValue(VRModuleRawAxis.RingPinch, handState.PinchStrength[(int)HandFinger.Ring]);
728+
currState.SetAxisValue(VRModuleRawAxis.PinkyPinch, handState.PinchStrength[(int)HandFinger.Pinky]);
729+
730+
// Map index pinch to trigger
731+
currState.SetButtonPress(VRModuleRawButton.Trigger, currState.GetButtonPress(VRModuleRawButton.GestureIndexPinch));
732+
currState.SetButtonTouch(VRModuleRawButton.Trigger, currState.GetButtonTouch(VRModuleRawButton.GestureIndexPinch));
733+
currState.SetAxisValue(VRModuleRawAxis.Trigger, currState.GetAxisValue(VRModuleRawAxis.IndexPinch));
707734
}
708-
else
735+
736+
if ((handState.Status & OVRPlugin.HandStatus.HandTracked) != 0)
709737
{
710-
for (var boneId = OVRSkeleton.BoneId.Hand_Start; boneId < OVRSkeleton.BoneId.Hand_End; ++boneId)
711-
{
712-
var bone = ovrSkeleton.Bones[(int)boneId];
738+
var rotOffset = isLeft ? m_leftRotOffset : m_rightRotOffset;
739+
var rotOffsetInv = Quaternion.Inverse(rotOffset);
713740

714-
RigidPose parentPose;
715-
if (bone.ParentBoneIndex == (short)OVRPlugin.BoneId.Invalid)
716-
{
717-
parentPose = ToRigidPose(handState.RootPose);
718-
}
719-
else
741+
currState.isPoseValid = true;
742+
currState.pose = new RigidPose()
743+
{
744+
pos = handState.RootPose.Position.FromFlippedZVector3f(),
745+
rot = handState.RootPose.Orientation.FromFlippedZQuatf() * rotOffsetInv,
746+
};
747+
748+
// TODO: PointerPose?
749+
//currState.handJoints[HandJointName.Palm] = new JointPose()
750+
//{
751+
// isValid = true,
752+
// pose = new RigidPose()
753+
// {
754+
// pos = handState.PointerPose.Position.FromFlippedZVector3f(),
755+
// rot = handState.PointerPose.Orientation.FromFlippedZQuatf() * rotOffsetInv,
756+
// },
757+
//};
758+
759+
var skeletonData = isLeft ? m_leftSkeletonData.GetReady() : m_rightSkeletonData.GetReady();
760+
if (skeletonData.ready)
761+
{
762+
for (var boneId = OVRSkeleton.BoneId.Hand_Start; boneId < OVRSkeleton.BoneId.Hand_End; ++boneId)
720763
{
721-
parentPose = currState.handJoints[s_ovrBoneIdToHandJointName[bone.ParentBoneIndex]].pose;
764+
var bone = skeletonData.data.Bones[(int)boneId];
765+
766+
RigidPose parentPose;
767+
if (bone.ParentBoneIndex == (short)OVRPlugin.BoneId.Invalid)
768+
{
769+
parentPose = currState.pose;
770+
}
771+
else
772+
{
773+
parentPose = currState.handJoints[s_ovrBoneIdToHandJointName[bone.ParentBoneIndex]].pose;
774+
}
775+
776+
currState.handJoints[s_ovrBoneIdToHandJointName[(int)boneId]] = new JointPose()
777+
{
778+
isValid = true,
779+
pose = parentPose *
780+
new RigidPose()
781+
{
782+
pos = Vector3.zero,
783+
rot = rotOffset,
784+
} *
785+
new RigidPose()
786+
{
787+
pos = bone.Pose.Position.FromFlippedZVector3f() * handState.HandScale,
788+
rot = handState.BoneRotations[(int)boneId].FromFlippedZQuatf() * rotOffsetInv,
789+
},
790+
};
722791
}
723-
724-
currState.handJoints[s_ovrBoneIdToHandJointName[(int)boneId]] = new JointPose()
725-
{
726-
isValid = true,
727-
pose = parentPose * ToRigidPose(bone.Pose),
728-
};
729792
}
730793
}
794+
else
795+
{
796+
currState.isPoseValid = false;
797+
currState.pose = RigidPose.identity;
798+
}
731799
}
732800
#endif
733801
break;

Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/OculusVRExtension/VIUOvrAvatarComponent.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ private void Update()
9696
}
9797
catch (Exception e)
9898
{
99-
Debug.Log("lawwong CompUpdate " + (isLeft ? "L" : "R") + " " + e.Message + " -- " + e.StackTrace);
99+
Debug.LogException(e);
100100
}
101101
}
102102

Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/ViveRole/RoleMaps/HandRole.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ private void MappingLeftRightHands()
158158
}
159159
else
160160
{
161-
leftIndex = VRModule.GetRightControllerDeviceIndex();
161+
leftIndex = VRModule.GetLeftControllerDeviceIndex();
162162
if (leftIndex >= deviceCount || RoleMap.IsDeviceConnectedAndBound(leftIndex))
163163
{
164164
leftIndex = VRModule.INVALID_DEVICE_INDEX;

0 commit comments

Comments
 (0)