clean project
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
/************************************************************************************
|
||||
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;
|
||||
using UnityEngine.Assertions;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace Oculus.Interaction.HandPosing.Visuals
|
||||
{
|
||||
/// <summary>
|
||||
/// A static (non-user controlled) representation of a hand. This script is used
|
||||
/// to be able to manually visualize hand grab poses.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(HandPuppet))]
|
||||
public class HandGhost : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// The puppet is used to actually move the representation of the hand.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
private HandPuppet _puppet;
|
||||
|
||||
/// <summary>
|
||||
/// The GripPoint of the hand. Needs to be
|
||||
/// at the same position/rotation as the gripPoint used
|
||||
/// by the visual HandPuppet controlled by the user.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
private Transform _gripPoint;
|
||||
|
||||
/// <summary>
|
||||
/// The HandGrab point can be set so the ghost automatically
|
||||
/// adopts the desired pose of said point.
|
||||
/// </summary>
|
||||
[SerializeField, Optional]
|
||||
private HandGrabPoint _handGrabPoint;
|
||||
|
||||
#region editor events
|
||||
protected virtual void Reset()
|
||||
{
|
||||
_puppet = this.GetComponent<HandPuppet>();
|
||||
_handGrabPoint = this.GetComponentInParent<HandGrabPoint>();
|
||||
}
|
||||
|
||||
protected virtual void OnValidate()
|
||||
{
|
||||
if (_puppet == null
|
||||
|| _gripPoint == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_handGrabPoint == null)
|
||||
{
|
||||
HandGrabPoint point = this.GetComponentInParent<HandGrabPoint>();
|
||||
if (point != null)
|
||||
{
|
||||
SetPose(point);
|
||||
}
|
||||
}
|
||||
else if (_handGrabPoint != null)
|
||||
{
|
||||
SetPose(_handGrabPoint);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
protected virtual void Start()
|
||||
{
|
||||
Assert.IsNotNull(_puppet);
|
||||
Assert.IsNotNull(_gripPoint);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Relay to the Puppet to set the ghost hand to the desired static pose
|
||||
/// </summary>
|
||||
/// <param name="handGrabPoint">The point to read the HandPose from</param>
|
||||
public void SetPose(HandGrabPoint handGrabPoint)
|
||||
{
|
||||
HandPose userPose = handGrabPoint.HandPose;
|
||||
if (userPose == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Transform relativeTo = handGrabPoint.RelativeTo;
|
||||
_puppet.SetJointRotations(userPose.JointRotations);
|
||||
SetGripPose(handGrabPoint.RelativeGrip, relativeTo);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Moves the underlying puppet so the grip point aligns with the given parameters
|
||||
/// </summary>
|
||||
/// <param name="gripPose">The relative grip pose to align the hand to</param>
|
||||
/// <param name="relativeTo">The object to use as anchor</param>
|
||||
public void SetGripPose(Pose gripPose, Transform relativeTo)
|
||||
{
|
||||
Pose inverseGrip = _gripPoint.RelativeOffset(this.transform);
|
||||
gripPose.Premultiply(inverseGrip);
|
||||
gripPose.Postmultiply(relativeTo.GetPose());
|
||||
_puppet.SetRootPose(gripPose);
|
||||
}
|
||||
|
||||
#region Inject
|
||||
public void InjectHandPuppet(HandPuppet puppet)
|
||||
{
|
||||
_puppet = puppet;
|
||||
}
|
||||
public void InjectGripPoint(Transform gripPoint)
|
||||
{
|
||||
_gripPoint = gripPoint;
|
||||
}
|
||||
public void InjectOptionalHandGrabPoint(HandGrabPoint handGrabPoint)
|
||||
{
|
||||
_handGrabPoint = handGrabPoint;
|
||||
}
|
||||
|
||||
public void InjectAllHandGhost(HandPuppet puppet, Transform gripPoint)
|
||||
{
|
||||
InjectHandPuppet(puppet);
|
||||
InjectGripPoint(gripPoint);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2d179fd81cd2e344ab2e610cd5f7260e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,47 @@
|
||||
/************************************************************************************
|
||||
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.HandPosing.Visuals
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds references to the prefabs for Ghost-Hands, so they can be instantiated
|
||||
/// in runtime to represent static poses.
|
||||
/// </summary>
|
||||
[CreateAssetMenu(menuName = "Oculus/Interaction/SDK/Pose Authoring/Hand Ghost Provider")]
|
||||
public class HandGhostProvider : ScriptableObject
|
||||
{
|
||||
/// <summary>
|
||||
/// The prefab for the left hand ghost.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
private HandGhost _leftHand;
|
||||
/// <summary>
|
||||
/// The prefab for the right hand ghost.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
private HandGhost _rightHand;
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to obtain the prototypes
|
||||
/// The result is to be instanced, not used directly.
|
||||
/// </summary>
|
||||
/// <param name="handedness">The desired handedness of the ghost prefab</param>
|
||||
/// <returns>A Ghost prefab</returns>
|
||||
public HandGhost GetHand(Handedness handedness)
|
||||
{
|
||||
return handedness == Handedness.Left ? _leftHand : _rightHand;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 84de3b22a7efbab46967c1a17f5b8cda
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,294 @@
|
||||
/************************************************************************************
|
||||
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 System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Assertions;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace Oculus.Interaction.HandPosing.Visuals
|
||||
{
|
||||
/// <summary>
|
||||
/// This component is used to drive the HandGrabModifier.
|
||||
/// It sets the desired fingers and wrist positions of the hand structure
|
||||
/// in the modifier, informing it of any changes coming from the HandGrabInteractor.
|
||||
/// </summary>
|
||||
public class HandGrabInteractorVisual : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// The HandGrabInteractor, to override the tracked hand
|
||||
/// when snapping to something.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
[Interface(typeof(ISnapper))]
|
||||
private List<MonoBehaviour> _snappers;
|
||||
private List<ISnapper> Snappers;
|
||||
|
||||
private ITrackingToWorldTransformer Transformer;
|
||||
|
||||
/// <summary>
|
||||
/// The modifier is part of the InputDataStack and this
|
||||
/// class will set its values each frame.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
private SyntheticHandModifier _modifier;
|
||||
|
||||
private bool _areFingersFree = true;
|
||||
private bool _isWristFree = true;
|
||||
|
||||
private ISnapper _currentSnapper;
|
||||
|
||||
protected bool _started = false;
|
||||
|
||||
#region manual initialization
|
||||
public static HandGrabInteractorVisual Create(
|
||||
GameObject gameObject,
|
||||
List<ISnapper> snappers,
|
||||
ITrackingToWorldTransformer transformer,
|
||||
SyntheticHandModifier modifier)
|
||||
{
|
||||
HandGrabInteractorVisual component = gameObject.AddComponent<HandGrabInteractorVisual>();
|
||||
component.Snappers = snappers;
|
||||
component.Transformer = transformer;
|
||||
component._modifier = modifier;
|
||||
return component;
|
||||
}
|
||||
#endregion
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
Snappers = _snappers.ConvertAll(mono => mono as ISnapper);
|
||||
}
|
||||
|
||||
protected virtual void Start()
|
||||
{
|
||||
this.BeginStart(ref _started);
|
||||
foreach (ISnapper snapper in Snappers)
|
||||
{
|
||||
Assert.IsNotNull(snapper);
|
||||
}
|
||||
|
||||
Assert.IsNotNull(_modifier);
|
||||
Transformer = _modifier.Config.TrackingToWorldTransformer;
|
||||
Assert.IsNotNull(Transformer);
|
||||
|
||||
this.EndStart(ref _started);
|
||||
}
|
||||
|
||||
protected virtual void OnEnable()
|
||||
{
|
||||
if (_started)
|
||||
{
|
||||
RegisterCallbacks(true);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnDisable()
|
||||
{
|
||||
if (_started)
|
||||
{
|
||||
RegisterCallbacks(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
UpdateHand(_currentSnapper);
|
||||
_modifier.MarkInputDataRequiresUpdate();
|
||||
}
|
||||
|
||||
private void RegisterCallbacks(bool register)
|
||||
{
|
||||
if (register)
|
||||
{
|
||||
foreach (ISnapper snapper in _snappers)
|
||||
{
|
||||
snapper.WhenSnapStarted += HandleSnapStarted;
|
||||
snapper.WhenSnapEnded += HandleSnapEnded;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (ISnapper snapper in _snappers)
|
||||
{
|
||||
snapper.WhenSnapStarted -= HandleSnapStarted;
|
||||
snapper.WhenSnapEnded -= HandleSnapEnded;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
private void HandleSnapStarted(ISnapper snapper)
|
||||
{
|
||||
_currentSnapper = snapper;
|
||||
}
|
||||
|
||||
private void HandleSnapEnded(ISnapper snapper)
|
||||
{
|
||||
if (_currentSnapper == snapper)
|
||||
{
|
||||
_currentSnapper = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void UpdateHand(ISnapper constrainingSnapper)
|
||||
{
|
||||
if (constrainingSnapper != null)
|
||||
{
|
||||
ConstrainingForce(constrainingSnapper, out float fingersConstraint, out float wristConstraint);
|
||||
UpdateHandPose(constrainingSnapper, fingersConstraint, wristConstraint);
|
||||
}
|
||||
else
|
||||
{
|
||||
FreeFingers();
|
||||
FreeWrist();
|
||||
}
|
||||
}
|
||||
|
||||
private void ConstrainingForce(ISnapper snapper, out float fingersConstraint, out float wristConstraint)
|
||||
{
|
||||
ISnapData snap = snapper.SnapData;
|
||||
fingersConstraint = wristConstraint = 0;
|
||||
if (snap == null || snap.HandPose == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool isSnapping = snapper.IsSnapping;
|
||||
|
||||
if (snap.SnapType == SnapType.HandToObject
|
||||
|| snap.SnapType == SnapType.HandToObjectAndReturn)
|
||||
{
|
||||
fingersConstraint = snapper.SnapStrength;
|
||||
wristConstraint = snapper.SnapStrength;
|
||||
}
|
||||
else if (isSnapping
|
||||
&& snap.SnapType == SnapType.ObjectToHand)
|
||||
{
|
||||
fingersConstraint = 1f;
|
||||
wristConstraint = 1f;
|
||||
}
|
||||
|
||||
if (fingersConstraint >= 1f && !isSnapping)
|
||||
{
|
||||
fingersConstraint = 0;
|
||||
}
|
||||
|
||||
if (wristConstraint >= 1f && !isSnapping)
|
||||
{
|
||||
wristConstraint = 0f;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateHandPose(ISnapper snapper, float fingersConstraint, float wristConstraint)
|
||||
{
|
||||
ISnapData snap = snapper.SnapData;
|
||||
|
||||
if (fingersConstraint > 0f)
|
||||
{
|
||||
UpdateFingers(snap.HandPose, snapper.SnappingFingers(), fingersConstraint);
|
||||
_areFingersFree = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
FreeFingers();
|
||||
}
|
||||
|
||||
if (wristConstraint > 0f)
|
||||
{
|
||||
Pose wristPose = GetWristPose(snap.WorldSnapPose, snapper.WristToGripOffset);
|
||||
wristPose = Transformer.ToTrackingPose(wristPose);
|
||||
_modifier.LockWristPose(wristPose, wristConstraint);
|
||||
_isWristFree = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
FreeWrist();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the desired rotation values for each joint based on the provided SnapAddress.
|
||||
/// Apart from the rotations it also writes in the modifier if it should allow rotations
|
||||
/// past that.
|
||||
/// When no snap is provided, it frees all fingers allowing unconstrained tracked motion.
|
||||
/// </summary>
|
||||
private void UpdateFingers(HandPose handPose, HandFingerFlags grabbingFingers, float strength)
|
||||
{
|
||||
Quaternion[] desiredRotations = handPose.JointRotations;
|
||||
_modifier.OverrideAllJoints(desiredRotations, strength);
|
||||
|
||||
for (int fingerIndex = 0; fingerIndex < Constants.NUM_FINGERS; fingerIndex++)
|
||||
{
|
||||
int fingerFlag = 1 << fingerIndex;
|
||||
JointFreedom fingerFreedom = handPose.FingersFreedom[fingerIndex];
|
||||
if (fingerFreedom == JointFreedom.Constrained
|
||||
&& ((int)grabbingFingers & fingerFlag) != 0)
|
||||
{
|
||||
fingerFreedom = JointFreedom.Locked;
|
||||
}
|
||||
_modifier.SetFingerFreedom((HandFinger)fingerIndex, fingerFreedom);
|
||||
}
|
||||
}
|
||||
|
||||
private Pose GetWristPose(Pose gripPoint, Pose wristToGripOffset)
|
||||
{
|
||||
Pose gripToWrist = wristToGripOffset;
|
||||
gripToWrist.Invert();
|
||||
gripPoint.Premultiply(gripToWrist);
|
||||
return gripPoint;
|
||||
}
|
||||
|
||||
private bool FreeFingers()
|
||||
{
|
||||
if (!_areFingersFree)
|
||||
{
|
||||
_modifier.FreeAllJoints();
|
||||
_areFingersFree = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool FreeWrist()
|
||||
{
|
||||
if (!_isWristFree)
|
||||
{
|
||||
_modifier.FreeWrist();
|
||||
_isWristFree = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#region Inject
|
||||
|
||||
public void InjectSnappers(List<ISnapper> snappers)
|
||||
{
|
||||
_snappers = snappers.ConvertAll(mono => mono as MonoBehaviour);
|
||||
Snappers = snappers;
|
||||
}
|
||||
public void InjectModifier(SyntheticHandModifier modifier)
|
||||
{
|
||||
_modifier = modifier;
|
||||
}
|
||||
|
||||
public void InjectAllHandGrabInteractorVisual(List<ISnapper> snappers, SyntheticHandModifier modifier)
|
||||
{
|
||||
InjectSnappers(snappers);
|
||||
InjectModifier(modifier);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2ff26c21ac005534e8af75f8427be9d1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,106 @@
|
||||
/************************************************************************************
|
||||
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 System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Oculus.Interaction.HandPosing.Visuals
|
||||
{
|
||||
/// <summary>
|
||||
/// Stores the translation between hand tracked data and the represented joint.
|
||||
/// </summary>
|
||||
[System.Serializable]
|
||||
public class HandJointMap
|
||||
{
|
||||
/// <summary>
|
||||
/// The unique identifier for the joint.
|
||||
/// </summary>
|
||||
public HandJointId id;
|
||||
/// <summary>
|
||||
/// The transform that this joint drives.
|
||||
/// </summary>
|
||||
public Transform transform;
|
||||
/// <summary>
|
||||
/// The rotation offset between the hand-tracked joint, and the represented joint.
|
||||
/// </summary>
|
||||
public Vector3 rotationOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Get the rotationOffset as a Quaternion.
|
||||
/// </summary>
|
||||
public Quaternion RotationOffset
|
||||
{
|
||||
get
|
||||
{
|
||||
return Quaternion.Euler(rotationOffset);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the raw rotation of the joint, taken from the tracking data
|
||||
/// </summary>
|
||||
public Quaternion TrackedRotation
|
||||
{
|
||||
get
|
||||
{
|
||||
return Quaternion.Inverse(RotationOffset) * transform.localRotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A collection of joint maps to quick access the joints that are actually available in the hand rig.
|
||||
/// Stores an internal array of indices so it can transform from positions in the HandPose.HAND_JOINTIDS collection
|
||||
/// to the JointMap List without having to search for the (maybe unavailable) index every time.
|
||||
/// </summary>
|
||||
[System.Serializable]
|
||||
public class JointCollection
|
||||
{
|
||||
/// <summary>
|
||||
/// List of indices of the joints in the actual rig for quick access
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private int[] _jointIndices = new int[FingersMetadata.HAND_JOINT_IDS.Length];
|
||||
|
||||
/// <summary>
|
||||
/// List of joints in the actual rig
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private List<HandJointMap> _jointMaps;
|
||||
|
||||
public JointCollection(List<HandJointMap> joints)
|
||||
{
|
||||
_jointMaps = joints;
|
||||
for (int i = 0; i < FingersMetadata.HAND_JOINT_IDS.Length; i++)
|
||||
{
|
||||
HandJointId boneId = FingersMetadata.HAND_JOINT_IDS[i];
|
||||
_jointIndices[i] = joints.FindIndex(bone => bone.id == boneId);
|
||||
}
|
||||
}
|
||||
|
||||
public HandJointMap this[int jointIndex]
|
||||
{
|
||||
get
|
||||
{
|
||||
int joint = _jointIndices[jointIndex];
|
||||
if (joint >= 0)
|
||||
{
|
||||
return _jointMaps[joint];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 890181c147a8cc94597b7ab04b4db257
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,122 @@
|
||||
/************************************************************************************
|
||||
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 System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace Oculus.Interaction.HandPosing.Visuals
|
||||
{
|
||||
/// <summary>
|
||||
/// This class is a visual representation of a rigged hand (typically a skin-mesh renderer)
|
||||
/// that can move its position/rotation and the rotations of the joints that compose it.
|
||||
/// It also can offset the rotations of the individual joints, adapting the provided
|
||||
/// data to any rig.
|
||||
/// </summary>
|
||||
public class HandPuppet : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// Joints of the hand and their relative rotations compared to hand-tracking.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
private List<HandJointMap> _jointMaps = new List<HandJointMap>(FingersMetadata.HAND_JOINT_IDS.Length);
|
||||
|
||||
/// <summary>
|
||||
/// General getter for the joints of the hand.
|
||||
/// </summary>
|
||||
public List<HandJointMap> JointMaps
|
||||
{
|
||||
get
|
||||
{
|
||||
return _jointMaps;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Current scale of the represented hand.
|
||||
/// </summary>
|
||||
public float Scale
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.transform.localScale.x;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.transform.localScale = Vector3.one * value;
|
||||
}
|
||||
}
|
||||
|
||||
private JointCollection _jointsCache;
|
||||
private JointCollection JointsCache
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_jointsCache == null)
|
||||
{
|
||||
_jointsCache = new JointCollection(_jointMaps);
|
||||
}
|
||||
return _jointsCache;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rotates all the joints in this puppet to the desired pose.
|
||||
/// </summary>
|
||||
/// <param name="jointRotations">
|
||||
/// Array of rotations to use for the fingers. It must follow the FingersMetaData.HAND_JOINT_IDS order.
|
||||
/// </param>
|
||||
public void SetJointRotations(in Quaternion[] jointRotations)
|
||||
{
|
||||
for (int i = 0; i < FingersMetadata.HAND_JOINT_IDS.Length; ++i)
|
||||
{
|
||||
HandJointMap jointMap = JointsCache[i];
|
||||
if (jointMap != null)
|
||||
{
|
||||
Transform jointTransform = jointMap.transform;
|
||||
Quaternion targetRot = jointMap.RotationOffset * jointRotations[i];
|
||||
jointTransform.localRotation = targetRot;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rotates and Translate the hand Wrist so it aligns with the given pose.
|
||||
/// It can apply an offset for when using controllers.
|
||||
/// </summary>
|
||||
/// <param name="rootPose">The Wrist Pose to set this puppet to.</param>
|
||||
/// </param>
|
||||
public void SetRootPose(in Pose rootPose)
|
||||
{
|
||||
this.transform.SetPose(rootPose, Space.World);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copies the rotations of all the joints available in the puppet
|
||||
/// as they are visually presented.
|
||||
/// Note that any missing joints are skipped.
|
||||
/// </summary>
|
||||
/// <param name="result">Structure to copy the joints to</param>
|
||||
public void CopyCachedJoints(ref HandPose result)
|
||||
{
|
||||
for (int i = 0; i < FingersMetadata.HAND_JOINT_IDS.Length; ++i)
|
||||
{
|
||||
HandJointMap jointMap = JointsCache[i];
|
||||
if (jointMap != null)
|
||||
{
|
||||
result.JointRotations[i] = jointMap.TrackedRotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c3bf6df4a5ac85847831e1fb5fa00ff8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user