Initialer Upload neues Unity-Projekt
This commit is contained in:
@ -0,0 +1,243 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Licensed under the Oculus SDK License Agreement (the "License");
|
||||
* you may not use the Oculus SDK except in compliance with the License,
|
||||
* which is provided at the time of installation or download, or which
|
||||
* otherwise accompanies this software in either electronic or hard copy form.
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://developer.oculus.com/licenses/oculussdk/
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, the Oculus 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.Grab;
|
||||
using Oculus.Interaction.HandGrab;
|
||||
using Oculus.Interaction.Input;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Oculus.Interaction
|
||||
{
|
||||
public class GrabStrengthIndicator : MonoBehaviour
|
||||
{
|
||||
[SerializeField, Interface(typeof(IHandGrabInteractor), typeof(IInteractor))]
|
||||
private UnityEngine.Object _handGrabInteractor;
|
||||
private IHandGrabInteractor HandGrab { get; set; }
|
||||
private IInteractor Interactor { get; set; }
|
||||
|
||||
[SerializeField]
|
||||
private MaterialPropertyBlockEditor _handMaterialPropertyBlockEditor;
|
||||
|
||||
[SerializeField]
|
||||
private float _glowLerpSpeed = 2f;
|
||||
[SerializeField]
|
||||
private float _glowColorLerpSpeed = 2f;
|
||||
|
||||
[SerializeField]
|
||||
private Color _fingerGlowColorWithInteractable;
|
||||
[SerializeField]
|
||||
private Color _fingerGlowColorWithNoInteractable;
|
||||
[SerializeField]
|
||||
private Color _fingerGlowColorHover;
|
||||
|
||||
#region public properties
|
||||
public float GlowLerpSpeed
|
||||
{
|
||||
get
|
||||
{
|
||||
return _glowLerpSpeed;
|
||||
}
|
||||
set
|
||||
{
|
||||
_glowLerpSpeed = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public float GlowColorLerpSpeed
|
||||
{
|
||||
get
|
||||
{
|
||||
return _glowColorLerpSpeed;
|
||||
}
|
||||
set
|
||||
{
|
||||
_glowColorLerpSpeed = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Color FingerGlowColorWithInteractable
|
||||
{
|
||||
get
|
||||
{
|
||||
return _fingerGlowColorWithInteractable;
|
||||
}
|
||||
set
|
||||
{
|
||||
_fingerGlowColorWithInteractable = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Color FingerGlowColorWithNoInteractable
|
||||
{
|
||||
get
|
||||
{
|
||||
return _fingerGlowColorWithNoInteractable;
|
||||
}
|
||||
set
|
||||
{
|
||||
_fingerGlowColorWithNoInteractable = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Color FingerGlowColorHover
|
||||
{
|
||||
get
|
||||
{
|
||||
return _fingerGlowColorHover;
|
||||
}
|
||||
set
|
||||
{
|
||||
_fingerGlowColorHover = value;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
private readonly int[] _handShaderGlowPropertyIds = new int[]
|
||||
{
|
||||
Shader.PropertyToID("_ThumbGlowValue"),
|
||||
Shader.PropertyToID("_IndexGlowValue"),
|
||||
Shader.PropertyToID("_MiddleGlowValue"),
|
||||
Shader.PropertyToID("_RingGlowValue"),
|
||||
Shader.PropertyToID("_PinkyGlowValue"),
|
||||
};
|
||||
|
||||
private readonly int _fingerGlowColorPropertyId = Shader.PropertyToID("_FingerGlowColor");
|
||||
|
||||
private Color _currentGlowColor;
|
||||
|
||||
protected bool _started = false;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
HandGrab = _handGrabInteractor as IHandGrabInteractor;
|
||||
Interactor = _handGrabInteractor as IInteractor;
|
||||
}
|
||||
|
||||
protected virtual void Start()
|
||||
{
|
||||
this.BeginStart(ref _started);
|
||||
|
||||
this.AssertField(_handMaterialPropertyBlockEditor, nameof(_handMaterialPropertyBlockEditor));
|
||||
this.AssertField(HandGrab, nameof(HandGrab));
|
||||
this.AssertField(Interactor, nameof(Interactor));
|
||||
|
||||
this.EndStart(ref _started);
|
||||
}
|
||||
|
||||
protected virtual void OnEnable()
|
||||
{
|
||||
if (_started)
|
||||
{
|
||||
Interactor.WhenPostprocessed += UpdateVisual;
|
||||
_currentGlowColor = _fingerGlowColorWithNoInteractable;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnDisable()
|
||||
{
|
||||
if (_started)
|
||||
{
|
||||
Interactor.WhenPostprocessed -= UpdateVisual;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateVisual()
|
||||
{
|
||||
bool isSelecting = Interactor.State == InteractorState.Select;
|
||||
bool isSelectingInteractable = Interactor.HasSelectedInteractable;
|
||||
bool hasHoverTarget = Interactor.HasCandidate;
|
||||
|
||||
Color desiredGlowColor = _fingerGlowColorHover;
|
||||
if (isSelecting)
|
||||
{
|
||||
desiredGlowColor = isSelectingInteractable
|
||||
? _fingerGlowColorWithInteractable
|
||||
: _fingerGlowColorWithNoInteractable;
|
||||
}
|
||||
|
||||
_currentGlowColor = Color.Lerp(_currentGlowColor, desiredGlowColor,
|
||||
Time.deltaTime * _glowColorLerpSpeed);
|
||||
_handMaterialPropertyBlockEditor.MaterialPropertyBlock.SetColor(_fingerGlowColorPropertyId, _currentGlowColor);
|
||||
|
||||
for (int i = 0; i < Constants.NUM_FINGERS; ++i)
|
||||
{
|
||||
if ((isSelecting && !isSelectingInteractable) ||
|
||||
(!isSelecting && !hasHoverTarget))
|
||||
{
|
||||
UpdateGlowValue(i, 0f);
|
||||
continue;
|
||||
}
|
||||
|
||||
float glowValue = 0f;
|
||||
HandFinger finger = (HandFinger)i;
|
||||
if ((HandGrab.SupportedGrabTypes & GrabTypeFlags.Pinch) != 0
|
||||
&& HandGrab.TargetInteractable != null
|
||||
&& (HandGrab.TargetInteractable.SupportedGrabTypes & GrabTypeFlags.Pinch) != 0
|
||||
&& HandGrab.TargetInteractable.PinchGrabRules[finger] != GrabAPI.FingerRequirement.Ignored)
|
||||
{
|
||||
glowValue = Mathf.Max(glowValue, HandGrab.HandGrabApi.GetFingerPinchStrength(finger));
|
||||
}
|
||||
|
||||
if ((HandGrab.SupportedGrabTypes & GrabTypeFlags.Palm) != 0
|
||||
&& HandGrab.TargetInteractable != null
|
||||
&& (HandGrab.TargetInteractable.SupportedGrabTypes & GrabTypeFlags.Palm) != 0
|
||||
&& HandGrab.TargetInteractable.PalmGrabRules[finger] != GrabAPI.FingerRequirement.Ignored)
|
||||
{
|
||||
glowValue = Mathf.Max(glowValue, HandGrab.HandGrabApi.GetFingerPalmStrength(finger));
|
||||
}
|
||||
|
||||
UpdateGlowValue(i, glowValue);
|
||||
}
|
||||
|
||||
_handMaterialPropertyBlockEditor.UpdateMaterialPropertyBlock();
|
||||
}
|
||||
|
||||
private void UpdateGlowValue(int fingerIndex, float glowValue)
|
||||
{
|
||||
float currentGlowValue = _handMaterialPropertyBlockEditor.MaterialPropertyBlock.GetFloat(_handShaderGlowPropertyIds[fingerIndex]);
|
||||
float newGlowValue = Mathf.MoveTowards(currentGlowValue, glowValue, _glowLerpSpeed * Time.deltaTime);
|
||||
_handMaterialPropertyBlockEditor.MaterialPropertyBlock.SetFloat(_handShaderGlowPropertyIds[fingerIndex], newGlowValue);
|
||||
}
|
||||
|
||||
#region Inject
|
||||
|
||||
public void InjectAllGrabStrengthIndicator(IHandGrabInteractor handGrabInteractor,
|
||||
MaterialPropertyBlockEditor handMaterialPropertyBlockEditor)
|
||||
{
|
||||
InjectHandGrab(handGrabInteractor);
|
||||
InjectHandMaterialPropertyBlockEditor(handMaterialPropertyBlockEditor);
|
||||
}
|
||||
|
||||
public void InjectHandGrab(IHandGrabInteractor handGrab)
|
||||
{
|
||||
_handGrabInteractor = handGrab as UnityEngine.Object;
|
||||
HandGrab = handGrab;
|
||||
Interactor = handGrab as IInteractor;
|
||||
}
|
||||
|
||||
public void InjectHandMaterialPropertyBlockEditor(MaterialPropertyBlockEditor handMaterialPropertyBlockEditor)
|
||||
{
|
||||
_handMaterialPropertyBlockEditor = handMaterialPropertyBlockEditor;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 887c8dbd7b891004dbddaf2d9f439564
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Licensed under the Oculus SDK License Agreement (the "License");
|
||||
* you may not use the Oculus SDK except in compliance with the License,
|
||||
* which is provided at the time of installation or download, or which
|
||||
* otherwise accompanies this software in either electronic or hard copy form.
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://developer.oculus.com/licenses/oculussdk/
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, the Oculus 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.HandGrab.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 HandGrab point can be set so the ghost automatically
|
||||
/// adopts the desired pose of said point.
|
||||
/// </summary>
|
||||
[SerializeField, Optional]
|
||||
[UnityEngine.Serialization.FormerlySerializedAs("_handGrabPoint")]
|
||||
private HandGrabPose _handGrabPose;
|
||||
|
||||
#region editor events
|
||||
protected virtual void Reset()
|
||||
{
|
||||
_puppet = this.GetComponent<HandPuppet>();
|
||||
_handGrabPose = this.GetComponentInParent<HandGrabPose>();
|
||||
}
|
||||
|
||||
protected virtual void OnValidate()
|
||||
{
|
||||
if (_puppet == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_handGrabPose == null)
|
||||
{
|
||||
HandGrabPose point = this.GetComponentInParent<HandGrabPose>();
|
||||
if (point != null)
|
||||
{
|
||||
SetPose(point);
|
||||
}
|
||||
}
|
||||
else if (_handGrabPose != null)
|
||||
{
|
||||
SetPose(_handGrabPose);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
protected virtual void Start()
|
||||
{
|
||||
this.AssertField(_puppet, nameof(_puppet));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Relay to the Puppet to set the ghost hand to the desired static pose
|
||||
/// </summary>
|
||||
/// <param name="handGrabPose">The point to read the HandPose from</param>
|
||||
public void SetPose(HandGrabPose handGrabPose)
|
||||
{
|
||||
HandPose userPose = handGrabPose.HandPose;
|
||||
if (userPose == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_puppet.SetJointRotations(userPose.JointRotations);
|
||||
SetRootPose(handGrabPose.RelativePose, handGrabPose.RelativeTo);
|
||||
}
|
||||
|
||||
public void SetPose(HandPose userPose, Pose rootPose)
|
||||
{
|
||||
_puppet.SetJointRotations(userPose.JointRotations);
|
||||
_puppet.SetRootPose(rootPose);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Moves the underlying puppet so the wrist point aligns with the given parameters
|
||||
/// </summary>
|
||||
/// <param name="rootPose">The relative wrist pose to align the hand to</param>
|
||||
/// <param name="relativeTo">The object to use as anchor</param>
|
||||
public void SetRootPose(Pose rootPose, Transform relativeTo)
|
||||
{
|
||||
Pose pose = rootPose;
|
||||
if (relativeTo != null)
|
||||
{
|
||||
pose = PoseUtils.GlobalPoseScaled(relativeTo, rootPose);
|
||||
}
|
||||
_puppet.SetRootPose(pose);
|
||||
}
|
||||
|
||||
#region Inject
|
||||
public void InjectAllHandGhost(HandPuppet puppet)
|
||||
{
|
||||
InjectHandPuppet(puppet);
|
||||
}
|
||||
public void InjectHandPuppet(HandPuppet puppet)
|
||||
{
|
||||
_puppet = puppet;
|
||||
}
|
||||
public void InjectOptionalHandGrabPose(HandGrabPose handGrabPose)
|
||||
{
|
||||
_handGrabPose = handGrabPose;
|
||||
}
|
||||
#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,55 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Licensed under the Oculus SDK License Agreement (the "License");
|
||||
* you may not use the Oculus SDK except in compliance with the License,
|
||||
* which is provided at the time of installation or download, or which
|
||||
* otherwise accompanies this software in either electronic or hard copy form.
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://developer.oculus.com/licenses/oculussdk/
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, the Oculus 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.HandGrab.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,202 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Licensed under the Oculus SDK License Agreement (the "License");
|
||||
* you may not use the Oculus SDK except in compliance with the License,
|
||||
* which is provided at the time of installation or download, or which
|
||||
* otherwise accompanies this software in either electronic or hard copy form.
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://developer.oculus.com/licenses/oculussdk/
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, the Oculus 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.HandGrab
|
||||
{
|
||||
/// <summary>
|
||||
/// Reads a HandGrabState and applies hand visual constraints to a SyntheticHand
|
||||
/// </summary>
|
||||
public class HandGrabStateVisual : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
[Interface(typeof(IHandGrabState))]
|
||||
private UnityEngine.Object _handGrabState;
|
||||
|
||||
private IHandGrabState HandGrabState;
|
||||
|
||||
[SerializeField]
|
||||
private SyntheticHand _syntheticHand;
|
||||
|
||||
private bool _areFingersFree = true;
|
||||
private bool _isWristFree = true;
|
||||
private bool _wasCompletelyFree = true;
|
||||
|
||||
protected bool _started = false;
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
HandGrabState = _handGrabState as IHandGrabState;
|
||||
}
|
||||
|
||||
protected virtual void Start()
|
||||
{
|
||||
this.BeginStart(ref _started);
|
||||
this.AssertField(HandGrabState, nameof(HandGrabState));
|
||||
this.AssertField(_syntheticHand, nameof(_syntheticHand));
|
||||
this.EndStart(ref _started);
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
ConstrainingForce(HandGrabState, out float fingersConstraint, out float wristConstraint);
|
||||
UpdateHandPose(HandGrabState, fingersConstraint, wristConstraint);
|
||||
|
||||
bool isCompletelyFree = _areFingersFree && _isWristFree;
|
||||
if (!isCompletelyFree
|
||||
|| isCompletelyFree && !_wasCompletelyFree)
|
||||
{
|
||||
_syntheticHand.MarkInputDataRequiresUpdate();
|
||||
}
|
||||
_wasCompletelyFree = isCompletelyFree;
|
||||
}
|
||||
|
||||
private void ConstrainingForce(IHandGrabState grabSource, out float fingersConstraint, out float wristConstraint)
|
||||
{
|
||||
HandGrabTarget grabData = grabSource.HandGrabTarget;
|
||||
|
||||
fingersConstraint = wristConstraint = 0;
|
||||
if (grabData == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool isGrabbing = grabSource.IsGrabbing;
|
||||
if (isGrabbing && grabData.HandAlignment != HandAlignType.None)
|
||||
{
|
||||
fingersConstraint = grabSource.FingersStrength;
|
||||
wristConstraint = grabSource.WristStrength;
|
||||
}
|
||||
else if (grabData.HandAlignment == HandAlignType.AttractOnHover)
|
||||
{
|
||||
fingersConstraint = grabSource.FingersStrength;
|
||||
wristConstraint = grabSource.WristStrength;
|
||||
}
|
||||
else if (grabData.HandAlignment == HandAlignType.AlignFingersOnHover)
|
||||
{
|
||||
fingersConstraint = grabSource.FingersStrength;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateHandPose(IHandGrabState grabSource, float fingersConstraint, float wristConstraint)
|
||||
{
|
||||
HandGrabTarget grabTarget = grabSource.HandGrabTarget;
|
||||
|
||||
if (grabTarget == null)
|
||||
{
|
||||
FreeFingers();
|
||||
FreeWrist();
|
||||
return;
|
||||
}
|
||||
|
||||
if (fingersConstraint > 0f
|
||||
&& grabTarget.HandPose != null)
|
||||
{
|
||||
UpdateFingers(grabTarget.HandPose, grabSource.GrabbingFingers(), fingersConstraint);
|
||||
_areFingersFree = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
FreeFingers();
|
||||
}
|
||||
|
||||
if (wristConstraint > 0f)
|
||||
{
|
||||
Pose wristPose = grabSource.GetVisualWristPose();
|
||||
_syntheticHand.LockWristPose(wristPose, wristConstraint,
|
||||
SyntheticHand.WristLockMode.Full, true);
|
||||
_isWristFree = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
FreeWrist();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the desired rotation values for each joint based on the provided HandGrabState.
|
||||
/// Apart from the rotations it also writes in the syntheticHand 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;
|
||||
_syntheticHand.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;
|
||||
}
|
||||
_syntheticHand.SetFingerFreedom((HandFinger)fingerIndex, fingerFreedom);
|
||||
}
|
||||
}
|
||||
|
||||
private bool FreeFingers()
|
||||
{
|
||||
if (!_areFingersFree)
|
||||
{
|
||||
_syntheticHand.FreeAllJoints();
|
||||
_areFingersFree = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool FreeWrist()
|
||||
{
|
||||
if (!_isWristFree)
|
||||
{
|
||||
_syntheticHand.FreeWrist();
|
||||
_isWristFree = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#region Inject
|
||||
|
||||
public void InjectAllHandGrabInteractorVisual(IHandGrabState handGrabState, SyntheticHand syntheticHand)
|
||||
{
|
||||
InjectHandGrabState(handGrabState);
|
||||
InjectSyntheticHand(syntheticHand);
|
||||
}
|
||||
|
||||
public void InjectHandGrabState(IHandGrabState handGrabState)
|
||||
{
|
||||
HandGrabState = handGrabState;
|
||||
_handGrabState = handGrabState as UnityEngine.Object;
|
||||
}
|
||||
|
||||
public void InjectSyntheticHand(SyntheticHand syntheticHand)
|
||||
{
|
||||
_syntheticHand = syntheticHand;
|
||||
}
|
||||
|
||||
#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,114 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Licensed under the Oculus SDK License Agreement (the "License");
|
||||
* you may not use the Oculus SDK except in compliance with the License,
|
||||
* which is provided at the time of installation or download, or which
|
||||
* otherwise accompanies this software in either electronic or hard copy form.
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://developer.oculus.com/licenses/oculussdk/
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, the Oculus 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.HandGrab.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,129 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Licensed under the Oculus SDK License Agreement (the "License");
|
||||
* you may not use the Oculus SDK except in compliance with the License,
|
||||
* which is provided at the time of installation or download, or which
|
||||
* otherwise accompanies this software in either electronic or hard copy form.
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://developer.oculus.com/licenses/oculussdk/
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, the Oculus 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.HandGrab.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