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,163 @@
/************************************************************************************
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;
namespace Oculus.Interaction.GrabAPI
{
public class FingerGrabAPI : IFingerAPI
{
private Vector3 _poseVolumeCenterOffset = Vector3.zero;
private Vector3 _poseVolumeCenter = Vector3.zero;
private static readonly float START_THRESHOLD = 0.75f;
private static readonly float RELEASE_THRESHOLD = 0.25f;
private static readonly float FINGER_TIP_RADIUS = 0.01f;
private static readonly float POSE_VOLUME_RADIUS = 0.05f;
private static readonly Vector3 POSE_VOLUME_OFFSET_RIGHT = new Vector3(0.07f, -0.03f, 0.0f);
private static readonly Vector3 POSE_VOLUME_OFFSET_LEFT = new Vector3(-0.07f, 0.03f, 0.0f);
private class FingerGrabData
{
private readonly HandJointId _tipId;
private Vector3 _tipPosition;
public float GrabStrength;
public bool IsGrabbing;
public bool IsGrabbingChanged;
public FingerGrabData(HandFinger fingerId)
{
_tipId = HandJointUtils.GetHandFingerTip(fingerId);
}
public void UpdateTipValues(IHand hand)
{
if (hand.GetJointPoseFromWrist(_tipId, out Pose pose))
{
_tipPosition = pose.position;
}
}
public void UpdateGrabStrength(Vector3 poseVolumeCenter)
{
float outsidePoseVolumeRadius = POSE_VOLUME_RADIUS + FINGER_TIP_RADIUS;
float insidePoseVolumeRadius = POSE_VOLUME_RADIUS - FINGER_TIP_RADIUS;
float sqrOutsidePoseVolume = outsidePoseVolumeRadius * outsidePoseVolumeRadius;
float sqrInsidePoseVolume = insidePoseVolumeRadius * insidePoseVolumeRadius;
float sqrDist = (poseVolumeCenter - _tipPosition).sqrMagnitude;
if (sqrDist >= sqrOutsidePoseVolume)
{
GrabStrength = 0.0f;
}
else if (sqrDist <= sqrInsidePoseVolume)
{
GrabStrength = 1.0f;
}
else
{
float distance = Mathf.Sqrt(sqrDist);
GrabStrength = 1.0f - Mathf.Clamp01(
(distance - insidePoseVolumeRadius) / (2.0f * FINGER_TIP_RADIUS));
}
}
public void UpdateIsGrabbing()
{
IsGrabbingChanged = false;
if (GrabStrength > START_THRESHOLD)
{
if (!IsGrabbing)
{
IsGrabbing = true;
IsGrabbingChanged = true;
}
return;
}
if (GrabStrength < RELEASE_THRESHOLD)
{
if (IsGrabbing)
{
IsGrabbing = false;
IsGrabbingChanged = true;
}
}
}
}
private readonly FingerGrabData[] _fingersGrabData = {
new FingerGrabData(HandFinger.Thumb),
new FingerGrabData(HandFinger.Index),
new FingerGrabData(HandFinger.Middle),
new FingerGrabData(HandFinger.Ring),
new FingerGrabData(HandFinger.Pinky)
};
public bool GetFingerIsGrabbing(HandFinger finger)
{
return _fingersGrabData[(int)finger].IsGrabbing;
}
public bool GetFingerIsGrabbingChanged(HandFinger finger, bool targetGrabState)
{
return _fingersGrabData[(int)finger].IsGrabbingChanged &&
_fingersGrabData[(int)finger].IsGrabbing == targetGrabState;
}
public float GetFingerGrabStrength(HandFinger finger)
{
return _fingersGrabData[(int)finger].GrabStrength;
}
public Vector3 GetCenterOffset()
{
return _poseVolumeCenterOffset;
}
public void Update(IHand hand)
{
if (hand == null || !hand.IsTrackedDataValid)
{
return;
}
UpdateVolumeCenter(hand);
for (int i = 0; i < Constants.NUM_FINGERS; ++i)
{
_fingersGrabData[i].UpdateTipValues(hand);
_fingersGrabData[i].UpdateGrabStrength(_poseVolumeCenter);
_fingersGrabData[i].UpdateIsGrabbing();
}
}
private void UpdateVolumeCenter(IHand hand)
{
if (!hand.GetJointPoseFromWrist(HandJointId.HandWristRoot, out var wristPose))
{
return;
}
Matrix4x4 wristPoseMat = Matrix4x4.TRS(wristPose.position, wristPose.rotation, Vector3.one);
_poseVolumeCenterOffset = hand.Handedness == Handedness.Left
? POSE_VOLUME_OFFSET_LEFT
: POSE_VOLUME_OFFSET_RIGHT;
_poseVolumeCenter = wristPose.position +
wristPoseMat.MultiplyVector(_poseVolumeCenterOffset);
}
}
}

View File

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

View File

@@ -0,0 +1,271 @@
/************************************************************************************
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;
namespace Oculus.Interaction.GrabAPI
{
public class FingerPinchAPI : IFingerAPI
{
private bool _isPinchVisibilityGood;
private float DistanceStart => _isPinchVisibilityGood ? PINCH_HQ_DISTANCE_START : PINCH_DISTANCE_START;
private float DistanceStopMax => _isPinchVisibilityGood ? PINCH_HQ_DISTANCE_STOP_MAX : PINCH_DISTANCE_STOP_MAX;
private float DistanceStopOffset => _isPinchVisibilityGood ? PINCH_HQ_DISTANCE_STOP_OFFSET : PINCH_DISTANCE_STOP_OFFSET;
private const float PINCH_DISTANCE_START = 0.03f;
private const float PINCH_DISTANCE_STOP_MAX = 0.1f;
private const float PINCH_DISTANCE_STOP_OFFSET = 0.04f;
private const float PINCH_HQ_DISTANCE_START = 0.016f;
private const float PINCH_HQ_DISTANCE_STOP_MAX = 0.1f;
private const float PINCH_HQ_DISTANCE_STOP_OFFSET = 0.016f;
private const float PINCH_HQ_VIEW_ANGLE_THRESHOLD = 40f;
private HandJointId[] thumbJointList = new[]
{
HandJointId.HandThumb0,
HandJointId.HandThumb1,
HandJointId.HandThumb2,
HandJointId.HandThumb3,
HandJointId.HandThumbTip
};
private class FingerPinchData
{
private readonly HandJointId _tipId;
private float _minPinchDistance;
public Vector3 TipPosition { get; private set; }
public float PinchStrength;
public bool IsPinching;
public bool IsPinchingChanged;
public FingerPinchData(HandFinger fingerId)
{
_tipId = HandJointUtils.GetHandFingerTip(fingerId);
}
public void UpdateTipPosition(IHand hand)
{
if (hand.GetJointPoseFromWrist(_tipId, out Pose pose))
{
TipPosition = pose.position;
}
}
public void UpdateIsPinching(float distance, float start, float stopOffset, float stopMax)
{
IsPinchingChanged = false;
if (!IsPinching)
{
if (distance < start)
{
IsPinching = true;
IsPinchingChanged = true;
_minPinchDistance = distance;
}
}
else
{
_minPinchDistance = Mathf.Min(_minPinchDistance, distance);
if (distance > stopMax ||
distance > _minPinchDistance + stopOffset)
{
IsPinching = false;
IsPinchingChanged = true;
_minPinchDistance = float.MaxValue;
}
}
}
}
private readonly FingerPinchData[] _fingersPinchData =
{
new FingerPinchData(HandFinger.Thumb),
new FingerPinchData(HandFinger.Index),
new FingerPinchData(HandFinger.Middle),
new FingerPinchData(HandFinger.Ring),
new FingerPinchData(HandFinger.Pinky)
};
public bool GetFingerIsGrabbing(HandFinger finger)
{
if (finger == HandFinger.Thumb)
{
for (int i = 1; i < Constants.NUM_FINGERS; ++i)
{
if (_fingersPinchData[i].IsPinching)
{
return true;
}
}
return false;
}
return _fingersPinchData[(int)finger].IsPinching;
}
public Vector3 GetCenterOffset()
{
float maxStrength = float.NegativeInfinity;
Vector3 thumbTip = _fingersPinchData[0].TipPosition;
Vector3 center = thumbTip;
for (int i = 1; i < Constants.NUM_FINGERS; ++i)
{
float strength = _fingersPinchData[i].PinchStrength;
if (strength > maxStrength)
{
maxStrength = strength;
Vector3 fingerTip = _fingersPinchData[i].TipPosition;
center = (thumbTip + fingerTip) * 0.5f;
}
}
return center;
}
public bool GetFingerIsGrabbingChanged(HandFinger finger, bool targetPinchState)
{
if (finger == HandFinger.Thumb)
{
// Thumb pinching changed logic only happens on
// the first finger pinching changed when pinching,
// or any finger pinching changed when not pinching
bool pinching = GetFingerIsGrabbing(finger);
if (pinching != targetPinchState)
{
return false;
}
if (pinching)
{
for (int i = 1; i < Constants.NUM_FINGERS; ++i)
{
if (_fingersPinchData[i].IsPinching == pinching &&
!_fingersPinchData[i].IsPinchingChanged)
{
return false;
}
}
return true;
}
else
{
for (int i = 1; i < Constants.NUM_FINGERS; ++i)
{
if (_fingersPinchData[i].IsPinchingChanged)
{
return true;
}
}
return false;
}
}
return _fingersPinchData[(int)finger].IsPinchingChanged &&
_fingersPinchData[(int)finger].IsPinching == targetPinchState;
}
public float GetFingerGrabStrength(HandFinger finger)
{
if (finger == HandFinger.Thumb)
{
float max = 0.0f;
for (int i = 1; i < Constants.NUM_FINGERS; ++i)
{
max = Mathf.Max(max, _fingersPinchData[i].PinchStrength);
}
return max;
}
return _fingersPinchData[(int)finger].PinchStrength;
}
public void Update(IHand hand)
{
_isPinchVisibilityGood = PinchHasGoodVisibility(hand);
for (int i = 0; i < Constants.NUM_FINGERS; ++i)
{
_fingersPinchData[i].UpdateTipPosition(hand);
}
Vector3 thumbTipPosition = _fingersPinchData[0].TipPosition;
for (int i = 1; i < Constants.NUM_FINGERS; ++i)
{
float distance = GetClosestDistanceToThumb(hand, _fingersPinchData[i].TipPosition);
_fingersPinchData[i].UpdateIsPinching(distance,
DistanceStart, DistanceStopOffset, DistanceStopMax);
float pinchPercent = (distance - DistanceStart) /
(DistanceStopMax - DistanceStart);
_fingersPinchData[i].PinchStrength = 1f - Mathf.Clamp01(pinchPercent);
}
}
private float GetClosestDistanceToThumb(IHand hand, Vector3 position)
{
float minDistance = float.MaxValue;
for (int i = 0; i < thumbJointList.Length - 1; i++)
{
if (!hand.GetJointPoseFromWrist(thumbJointList[i], out Pose pose0))
{
return float.MaxValue;
}
if (!hand.GetJointPoseFromWrist(thumbJointList[i+1], out Pose pose1))
{
return float.MaxValue;
}
minDistance = Mathf.Min(minDistance,
ClosestDistanceToLineSegment(position, pose0.position, pose1.position));
}
return minDistance;
}
private float ClosestDistanceToLineSegment(Vector3 position, Vector3 p0, Vector3 p1)
{
Vector3 lineVec = p1 - p0;
Vector3 fromP0 = position - p0;
float normalizedProjection = Vector3.Dot(fromP0, lineVec) / Vector3.Dot(lineVec, lineVec);
float closestT = Mathf.Clamp01(normalizedProjection);
Vector3 closestPoint = p0 + closestT * lineVec;
return (closestPoint - position).magnitude;
}
private bool PinchHasGoodVisibility(IHand hand)
{
if (!hand.GetJointPose(HandJointId.HandWristRoot, out Pose wristPose)
|| !hand.GetCenterEyePose(out Pose centerEyePose))
{
return false;
}
Vector3 handVector = -1.0f * wristPose.forward;
Vector3 targetVector = -1.0f * centerEyePose.forward;
if (hand.Handedness == Handedness.Right)
{
handVector = -handVector;
}
float angle = Vector3.Angle(handVector, targetVector);
return angle <= PINCH_HQ_VIEW_ANGLE_THRESHOLD;
}
}
}

View File

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

View File

@@ -0,0 +1,108 @@
/************************************************************************************
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;
namespace Oculus.Interaction.GrabAPI
{
public class FingerRawPinchAPI : IFingerAPI
{
private class FingerPinchData
{
private readonly HandFinger _finger;
private readonly HandJointId _tipId;
public float PinchStrength;
public bool IsPinching;
public bool IsPinchingChanged;
public Vector3 TipPosition { get; private set; }
public FingerPinchData(HandFinger fingerId)
{
_finger = fingerId;
_tipId = HandJointUtils.GetHandFingerTip(fingerId);
}
public void UpdateTipPosition(IHand hand)
{
if (hand.GetJointPoseFromWrist(_tipId, out Pose pose))
{
TipPosition = pose.position;
}
}
public void UpdateIsPinching(IHand hand)
{
PinchStrength = hand.GetFingerPinchStrength(_finger);
bool isPinching = hand.GetFingerIsPinching(_finger);
IsPinchingChanged = isPinching != IsPinching;
IsPinching = isPinching;
}
}
private readonly FingerPinchData[] _fingersPinchData =
{
new FingerPinchData(HandFinger.Thumb),
new FingerPinchData(HandFinger.Index),
new FingerPinchData(HandFinger.Middle),
new FingerPinchData(HandFinger.Ring),
new FingerPinchData(HandFinger.Pinky)
};
public bool GetFingerIsGrabbing(HandFinger finger)
{
return _fingersPinchData[(int)finger].IsPinching;
}
public Vector3 GetCenterOffset()
{
float maxStrength = float.NegativeInfinity;
Vector3 thumbTip = _fingersPinchData[0].TipPosition;
Vector3 center = thumbTip;
for (int i = 1; i < Constants.NUM_FINGERS; ++i)
{
float strength = _fingersPinchData[i].PinchStrength;
if (strength > maxStrength)
{
maxStrength = strength;
Vector3 fingerTip = _fingersPinchData[i].TipPosition;
center = (thumbTip + fingerTip) * 0.5f;
}
}
return center;
}
public bool GetFingerIsGrabbingChanged(HandFinger finger, bool targetPinchState)
{
return _fingersPinchData[(int)finger].IsPinchingChanged &&
_fingersPinchData[(int)finger].IsPinching == targetPinchState;
}
public float GetFingerGrabStrength(HandFinger finger)
{
return _fingersPinchData[(int)finger].PinchStrength;
}
public void Update(IHand hand)
{
for (int i = 0; i < Constants.NUM_FINGERS; ++i)
{
_fingersPinchData[i].UpdateIsPinching(hand);
}
}
}
}

View File

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

View File

@@ -0,0 +1,27 @@
/************************************************************************************
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.GrabAPI
{
public class FingerRawPinchInjector : MonoBehaviour
{
[SerializeField]
private HandGrabAPI _handGrabAPI;
protected virtual void Start()
{
_handGrabAPI.InjectOptionalFingerPinchAPI(new FingerRawPinchAPI());
}
}
}

View File

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

View File

@@ -0,0 +1,26 @@
/************************************************************************************
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 UnityEngine;
namespace Oculus.Interaction.Grab
{
[Flags]
public enum GrabTypeFlags
{
None = 0,
Pinch = 1 << 0,
Palm = 1 << 1,
All = (1 << 2) - 1
}
}

View File

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

View File

@@ -0,0 +1,157 @@
/************************************************************************************
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;
namespace Oculus.Interaction.GrabAPI
{
public enum FingerRequirement
{
Ignored,
Optional,
Required
}
public enum FingerUnselectMode
{
AllReleased,
AnyReleased
}
[System.Serializable]
public struct GrabbingRule
{
[SerializeField]
private FingerRequirement _thumbRequirement;
[SerializeField]
private FingerRequirement _indexRequirement;
[SerializeField]
private FingerRequirement _middleRequirement;
[SerializeField]
private FingerRequirement _ringRequirement;
[SerializeField]
private FingerRequirement _pinkyRequirement;
[SerializeField]
private FingerUnselectMode _unselectMode;
public FingerUnselectMode UnselectMode => _unselectMode;
public bool SelectsWithOptionals
{
get
{
return _thumbRequirement != FingerRequirement.Required
&& _indexRequirement != FingerRequirement.Required
&& _middleRequirement != FingerRequirement.Required
&& _ringRequirement != FingerRequirement.Required
&& _pinkyRequirement != FingerRequirement.Required;
}
}
public FingerRequirement this[HandFinger fingerID]
{
get
{
switch (fingerID)
{
case HandFinger.Thumb: return _thumbRequirement;
case HandFinger.Index: return _indexRequirement;
case HandFinger.Middle: return _middleRequirement;
case HandFinger.Ring: return _ringRequirement;
case HandFinger.Pinky: return _pinkyRequirement;
}
return FingerRequirement.Ignored;
}
set
{
switch (fingerID)
{
case HandFinger.Thumb: _thumbRequirement = value; break;
case HandFinger.Index: _indexRequirement = value; break;
case HandFinger.Middle: _middleRequirement = value; break;
case HandFinger.Ring: _ringRequirement = value; break;
case HandFinger.Pinky: _pinkyRequirement = value; break;
}
}
}
public void StripIrrelevant(ref HandFingerFlags fingerFlags)
{
for (int i = 0; i < Constants.NUM_FINGERS; i++)
{
HandFinger finger = (HandFinger)i;
if (this[finger] == FingerRequirement.Ignored)
{
fingerFlags = (HandFingerFlags)((int)fingerFlags & ~(1 << i));
}
}
}
public GrabbingRule(HandFingerFlags mask, in GrabbingRule otherRule)
{
_thumbRequirement = (mask & HandFingerFlags.Thumb) != 0 ?
otherRule._thumbRequirement : FingerRequirement.Ignored;
_indexRequirement = (mask & HandFingerFlags.Index) != 0 ?
otherRule._indexRequirement : FingerRequirement.Ignored;
_middleRequirement = (mask & HandFingerFlags.Middle) != 0 ?
otherRule._middleRequirement : FingerRequirement.Ignored;
_ringRequirement = (mask & HandFingerFlags.Ring) != 0 ?
otherRule._ringRequirement : FingerRequirement.Ignored;
_pinkyRequirement = (mask & HandFingerFlags.Pinky) != 0 ?
otherRule._pinkyRequirement : FingerRequirement.Ignored;
_unselectMode = otherRule.UnselectMode;
}
#region Defaults
public static GrabbingRule DefaultPalmRule { get; } = new GrabbingRule()
{
_thumbRequirement = FingerRequirement.Optional,
_indexRequirement = FingerRequirement.Required,
_middleRequirement = FingerRequirement.Required,
_ringRequirement = FingerRequirement.Required,
_pinkyRequirement = FingerRequirement.Optional,
_unselectMode = FingerUnselectMode.AllReleased
};
public static GrabbingRule DefaultPinchRule { get; } = new GrabbingRule()
{
_thumbRequirement = FingerRequirement.Required,
_indexRequirement = FingerRequirement.Optional,
_middleRequirement = FingerRequirement.Optional,
_ringRequirement = FingerRequirement.Optional,
_pinkyRequirement = FingerRequirement.Optional,
_unselectMode = FingerUnselectMode.AllReleased
};
public static GrabbingRule FullGrab { get; } = new GrabbingRule()
{
_thumbRequirement = FingerRequirement.Required,
_indexRequirement = FingerRequirement.Required,
_middleRequirement = FingerRequirement.Required,
_ringRequirement = FingerRequirement.Required,
_pinkyRequirement = FingerRequirement.Required,
_unselectMode = FingerUnselectMode.AllReleased
};
#endregion
}
}

View File

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

View File

@@ -0,0 +1,228 @@
/************************************************************************************
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.GrabAPI;
using Oculus.Interaction.Input;
namespace Oculus.Interaction.Grab
{
public enum GrabType
{
PinchGrab = 1 << 0,
PalmGrab = 1 << 1
}
public interface IHandGrabInteractor
{
HandGrabAPI HandGrabApi { get; }
GrabTypeFlags SupportedGrabTypes { get; }
IHandGrabInteractable TargetInteractable { get; }
}
public interface IHandGrabInteractable
{
GrabTypeFlags SupportedGrabTypes { get; }
GrabbingRule PinchGrabRules { get; }
GrabbingRule PalmGrabRules { get; }
}
public class HandGrabInteractableData : IHandGrabInteractable
{
public GrabTypeFlags SupportedGrabTypes { get; set; } = GrabTypeFlags.All;
public GrabbingRule PinchGrabRules { get; set; } = GrabbingRule.DefaultPinchRule;
public GrabbingRule PalmGrabRules { get; set; } = GrabbingRule.DefaultPalmRule;
}
public static class HandGrab
{
public static void StoreGrabData(IHandGrabInteractor interactor,
IHandGrabInteractable interactable, ref HandGrabInteractableData cache)
{
HandGrabAPI api = interactor.HandGrabApi;
cache.SupportedGrabTypes = GrabTypeFlags.None;
if (SupportsPinch(interactor, interactable))
{
HandFingerFlags pinchFingers = api.HandPinchingFinger();
if (api.IsSustainingGrab(interactable.PinchGrabRules, pinchFingers))
{
cache.SupportedGrabTypes |= GrabTypeFlags.Pinch;
cache.PinchGrabRules = new GrabbingRule(pinchFingers, interactable.PinchGrabRules);
}
}
if (SupportsPalm(interactor, interactable))
{
HandFingerFlags palmFingers = api.HandPalmGrabbingFingers();
if(api.IsSustainingGrab(interactable.PalmGrabRules, palmFingers))
{
cache.SupportedGrabTypes |= GrabTypeFlags.Palm;
cache.PalmGrabRules = new GrabbingRule(palmFingers, interactable.PalmGrabRules);
}
}
}
public static float ComputeHoverStrength(IHandGrabInteractor interactor,
IHandGrabInteractable interactable, out GrabTypeFlags hoveringGrabTypes)
{
HandGrabAPI api = interactor.HandGrabApi;
hoveringGrabTypes = GrabTypeFlags.None;
float hoverStrength = 0f;
if (SupportsPinch(interactor, interactable))
{
float pinchStrength = api.GetHandPinchStrength(interactable.PinchGrabRules, false);
if (pinchStrength > hoverStrength)
{
hoverStrength = pinchStrength;
hoveringGrabTypes = GrabTypeFlags.Pinch;
}
}
if (SupportsPalm(interactor, interactable))
{
float palmStrength = api.GetHandPalmStrength(interactable.PalmGrabRules, false);
if (palmStrength > hoverStrength)
{
hoverStrength = palmStrength;
hoveringGrabTypes = GrabTypeFlags.Palm;
}
}
return hoverStrength;
}
public static bool ComputeShouldSelect(IHandGrabInteractor interactor,
IHandGrabInteractable interactable, out GrabTypeFlags selectingGrabTypes)
{
if (interactable == null)
{
selectingGrabTypes = GrabTypeFlags.None;
return false;
}
HandGrabAPI api = interactor.HandGrabApi;
selectingGrabTypes = GrabTypeFlags.None;
if (SupportsPinch(interactor, interactable) &&
api.IsHandSelectPinchFingersChanged(interactable.PinchGrabRules))
{
selectingGrabTypes |= GrabTypeFlags.Pinch;
}
if (SupportsPalm(interactor, interactable) &&
api.IsHandSelectPalmFingersChanged(interactable.PalmGrabRules))
{
selectingGrabTypes |= GrabTypeFlags.Palm;
}
return selectingGrabTypes != GrabTypeFlags.None;
}
public static bool ComputeShouldUnselect(IHandGrabInteractor interactor,
IHandGrabInteractable interactable)
{
HandGrabAPI api = interactor.HandGrabApi;
HandFingerFlags pinchFingers = api.HandPinchingFinger();
HandFingerFlags palmFingers = api.HandPalmGrabbingFingers();
if (interactable.SupportedGrabTypes == GrabTypeFlags.None)
{
if (!api.IsSustainingGrab(GrabbingRule.FullGrab, pinchFingers) &&
!api.IsSustainingGrab(GrabbingRule.FullGrab, palmFingers))
{
return true;
}
return false;
}
bool pinchHolding = false;
bool palmHolding = false;
bool pinchReleased = false;
bool palmReleased = false;
if (SupportsPinch(interactor, interactable.SupportedGrabTypes))
{
pinchHolding = api.IsSustainingGrab(interactable.PinchGrabRules, pinchFingers);
if (api.IsHandUnselectPinchFingersChanged(interactable.PinchGrabRules))
{
pinchReleased = true;
}
}
if (SupportsPalm(interactor, interactable.SupportedGrabTypes))
{
palmHolding = api.IsSustainingGrab(interactable.PalmGrabRules, palmFingers);
if (api.IsHandUnselectPalmFingersChanged(interactable.PalmGrabRules))
{
palmReleased = true;
}
}
return !pinchHolding && !palmHolding && (pinchReleased || palmReleased);
}
public static HandFingerFlags GrabbingFingers(IHandGrabInteractor interactor,
IHandGrabInteractable interactable)
{
HandGrabAPI api = interactor.HandGrabApi;
if (interactable == null)
{
return HandFingerFlags.None;
}
HandFingerFlags fingers = HandFingerFlags.None;
if (SupportsPinch(interactor, interactable))
{
HandFingerFlags pinchingFingers = api.HandPinchingFinger();
interactable.PinchGrabRules.StripIrrelevant(ref pinchingFingers);
fingers = fingers | pinchingFingers;
}
if (SupportsPalm(interactor, interactable))
{
HandFingerFlags grabbingFingers = api.HandPalmGrabbingFingers();
interactable.PalmGrabRules.StripIrrelevant(ref grabbingFingers);
fingers = fingers | grabbingFingers;
}
return fingers;
}
private static bool SupportsPinch(IHandGrabInteractor interactor,
IHandGrabInteractable interactable)
{
return SupportsPinch(interactor, interactable.SupportedGrabTypes);
}
private static bool SupportsPalm(IHandGrabInteractor interactor,
IHandGrabInteractable interactable)
{
return SupportsPalm(interactor, interactable.SupportedGrabTypes);
}
private static bool SupportsPinch(IHandGrabInteractor interactor,
GrabTypeFlags grabTypes)
{
return (interactor.SupportedGrabTypes & GrabTypeFlags.Pinch) != 0 &&
(grabTypes & GrabTypeFlags.Pinch) != 0;
}
private static bool SupportsPalm(IHandGrabInteractor interactor,
GrabTypeFlags grabTypes)
{
return (interactor.SupportedGrabTypes & GrabTypeFlags.Palm) != 0 &&
(grabTypes & GrabTypeFlags.Palm) != 0;
}
}
}

View File

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

View File

@@ -0,0 +1,337 @@
/************************************************************************************
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.GrabAPI
{
public class HandGrabAPI : MonoBehaviour
{
[SerializeField, Interface(typeof(IHand))]
private MonoBehaviour _hand;
public IHand Hand { get; private set; }
private IFingerAPI _fingerPinchAPI = new FingerPinchAPI();
private IFingerAPI _fingerPalmAPI = new FingerGrabAPI();
private bool _started;
protected virtual void Awake()
{
Hand = _hand as IHand;
}
protected virtual void Start()
{
this.BeginStart(ref _started);
Assert.IsNotNull(Hand);
Assert.IsNotNull(_fingerPinchAPI);
Assert.IsNotNull(_fingerPalmAPI);
this.EndStart(ref _started);
}
protected virtual void Update()
{
_fingerPinchAPI.Update(Hand);
_fingerPalmAPI.Update(Hand);
}
public HandFingerFlags HandPinchingFinger()
{
return HandGrabbingFingers(_fingerPinchAPI);
}
public HandFingerFlags HandPalmGrabbingFingers()
{
return HandGrabbingFingers(_fingerPalmAPI);
}
private HandFingerFlags HandGrabbingFingers(IFingerAPI fingerAPI)
{
HandFingerFlags grabbingFingers = HandFingerFlags.None;
for (int i = 0; i < Constants.NUM_FINGERS; i++)
{
HandFinger finger = (HandFinger)i;
bool isGrabbing = fingerAPI.GetFingerIsGrabbing(finger);
if (isGrabbing)
{
grabbingFingers |= (HandFingerFlags)(1 << i);
}
}
return grabbingFingers;
}
public bool IsHandPinchGrabbing(in GrabbingRule fingers)
{
HandFingerFlags pinchFingers = HandPinchingFinger();
return IsSustainingGrab(fingers, pinchFingers);
}
public bool IsHandPalmGrabbing(in GrabbingRule fingers)
{
HandFingerFlags palmFingers = HandPalmGrabbingFingers();
return IsSustainingGrab(fingers, palmFingers);
}
public bool IsSustainingGrab(in GrabbingRule fingers, HandFingerFlags grabbingFingers)
{
for (int i = 0; i < Constants.NUM_FINGERS; i++)
{
HandFinger finger = (HandFinger)i;
HandFingerFlags fingerFlag = (HandFingerFlags)(1 << i);
bool isFingerGrabbing = (grabbingFingers & fingerFlag) != 0;
if (fingers[finger] == FingerRequirement.Required)
{
if (fingers.UnselectMode == FingerUnselectMode.AnyReleased
&& !isFingerGrabbing)
{
return false;
}
if(fingers.UnselectMode == FingerUnselectMode.AllReleased
&& isFingerGrabbing)
{
return true;
}
}
else if (fingers[finger] == FingerRequirement.Optional)
{
if (fingers.UnselectMode == FingerUnselectMode.AnyReleased
&& !isFingerGrabbing)
{
return false;
}
if (fingers.UnselectMode == FingerUnselectMode.AllReleased
&& isFingerGrabbing)
{
return true;
}
}
}
return false;
}
/// <summary>
/// Determine whether the state of any of the finger pinches have changed this frame to
/// the target pinching state (on/off).
/// </summary>
/// <param name="fingers">Finger rules to check.</param>
public bool IsHandSelectPinchFingersChanged(in GrabbingRule fingers)
{
return IsHandSelectFingersChanged(fingers, _fingerPinchAPI);
}
/// <summary>
/// Determine whether the state of any of the finger grabs have changed this frame to
/// the target grabbing state (on/off).
/// </summary>
/// <param name="fingers">Finger rules to check.</param>
public bool IsHandSelectPalmFingersChanged(in GrabbingRule fingers)
{
return IsHandSelectFingersChanged(fingers, _fingerPalmAPI);
}
public bool IsHandUnselectPinchFingersChanged(in GrabbingRule fingers)
{
return IsHandUnselectFingersChanged(fingers, _fingerPinchAPI);
}
public bool IsHandUnselectPalmFingersChanged(in GrabbingRule fingers)
{
return IsHandUnselectFingersChanged(fingers, _fingerPalmAPI);
}
private bool IsHandSelectFingersChanged(in GrabbingRule fingers, IFingerAPI fingerAPI)
{
bool selectsWithOptionals = fingers.SelectsWithOptionals;
bool aFingerGrabbed = false;
for (int i = 0; i < Constants.NUM_FINGERS; i++)
{
HandFinger finger = (HandFinger)i;
if (fingers[finger] == FingerRequirement.Required)
{
if (!fingerAPI.GetFingerIsGrabbing(finger))
{
return false;
}
if (fingerAPI.GetFingerIsGrabbingChanged(finger, true))
{
aFingerGrabbed = true;
}
}
else if (selectsWithOptionals
&& fingers[finger] == FingerRequirement.Optional)
{
if (fingerAPI.GetFingerIsGrabbingChanged(finger, true))
{
return true;
}
}
}
return aFingerGrabbed;
}
private bool IsHandUnselectFingersChanged(in GrabbingRule fingers, IFingerAPI fingerAPI)
{
bool isAnyFingerGrabbing = false;
bool aFingerUngrabbed = false;
bool selectsWithOptionals = fingers.SelectsWithOptionals;
for (int i = 0; i < Constants.NUM_FINGERS; i++)
{
HandFinger finger = (HandFinger)i;
if (fingers[finger] == FingerRequirement.Ignored)
{
continue;
}
isAnyFingerGrabbing |= fingerAPI.GetFingerIsGrabbing(finger);
if (fingers[finger] == FingerRequirement.Required)
{
if (fingerAPI.GetFingerIsGrabbingChanged(finger, false))
{
aFingerUngrabbed = true;
if (fingers.UnselectMode == FingerUnselectMode.AnyReleased)
{
return true;
}
}
}
if (fingers[finger] == FingerRequirement.Optional)
{
if (fingerAPI.GetFingerIsGrabbingChanged(finger, false))
{
aFingerUngrabbed = true;
if (fingers.UnselectMode == FingerUnselectMode.AnyReleased
&& selectsWithOptionals)
{
return true;
}
}
}
}
return !isAnyFingerGrabbing && aFingerUngrabbed;
}
public Vector3 GetPinchCenter()
{
return WristOffsetToWorldPoint(_fingerPinchAPI.GetCenterOffset());
}
public Vector3 GetPalmCenter()
{
return WristOffsetToWorldPoint(_fingerPalmAPI.GetCenterOffset());
}
private Vector3 WristOffsetToWorldPoint(Vector3 offset)
{
if (!Hand.GetJointPose(HandJointId.HandWristRoot, out Pose wristPose))
{
return offset;
}
return wristPose.position + wristPose.rotation * offset;
}
public float GetHandPinchStrength(in GrabbingRule fingers,
bool includePinching = true)
{
return GetHandStrength(fingers, includePinching, _fingerPinchAPI);
}
public float GetHandPalmStrength(in GrabbingRule fingers,
bool includeGrabbing = true)
{
return GetHandStrength(fingers, includeGrabbing, _fingerPalmAPI);
}
public float GetFingerPinchStrength(HandFinger finger)
{
return _fingerPinchAPI.GetFingerGrabStrength(finger);
}
public float GetFingerPalmStrength(HandFinger finger)
{
return _fingerPalmAPI.GetFingerGrabStrength(finger);
}
private float GetHandStrength(in GrabbingRule fingers,
bool includeGrabbing, IFingerAPI fingerAPI)
{
float requiredMin = 1.0f;
float optionalMax = 0f;
for (int i = 0; i < Constants.NUM_FINGERS; i++)
{
HandFinger finger = (HandFinger)i;
if (!includeGrabbing && fingerAPI.GetFingerIsGrabbing((HandFinger)i))
{
continue;
}
if (fingers[finger] == FingerRequirement.Ignored)
{
continue;
}
if (fingers[finger] == FingerRequirement.Optional)
{
optionalMax = Mathf.Max(optionalMax, fingerAPI.GetFingerGrabStrength((HandFinger)i));
}
if (fingers[finger] == FingerRequirement.Required)
{
requiredMin = Mathf.Min(requiredMin, fingerAPI.GetFingerGrabStrength((HandFinger)i));
}
}
return Mathf.Min(requiredMin, optionalMax);
}
#region Inject
public void InjectAllHandGrabAPI(IHand hand)
{
InjectHand(hand);
}
public void InjectHand(IHand hand)
{
_hand = hand as MonoBehaviour;
Hand = hand;
}
public void InjectOptionalFingerPinchAPI(IFingerAPI fingerPinchAPI)
{
_fingerPinchAPI = fingerPinchAPI;
}
public void InjectOptionalFingerGrabAPI(IFingerAPI fingerGrabAPI)
{
_fingerPalmAPI = fingerGrabAPI;
}
#endregion
}
}

View File

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

View File

@@ -0,0 +1,26 @@
/************************************************************************************
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;
namespace Oculus.Interaction.GrabAPI
{
public interface IFingerAPI
{
bool GetFingerIsGrabbing(HandFinger finger);
bool GetFingerIsGrabbingChanged(HandFinger finger, bool targetPinchState);
float GetFingerGrabStrength(HandFinger finger);
Vector3 GetCenterOffset();
void Update(IHand hand);
}
}

View File

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