first commit
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
// Copyright (C) 2014-2024 Gleechi Technology AB. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VirtualGrasp.Controllers
|
||||
{
|
||||
/**
|
||||
* This is an external controller class that supports a Mouse controller as an external controller.
|
||||
* Please refer to https://docs.virtualgrasp.com/controllers.html for the definition of an external controller for VG.
|
||||
*/
|
||||
[LIBVIRTUALGRASP_UNITY_SCRIPT]
|
||||
[HelpURL("https://docs.virtualgrasp.com/unity_vg_cp_generic." + VG_Version.__VG_VERSION__ + ".html")]
|
||||
public class VG_EC_Generic : VG_ExternalController
|
||||
{
|
||||
[Serializable]
|
||||
public class HandMapping : VG_BoneMapping
|
||||
{
|
||||
public override void Initialize(int avatarID, VG_HandSide side)
|
||||
{
|
||||
base.Initialize(avatarID, side);
|
||||
m_BoneToTransform = new Dictionary<int, Transform>()
|
||||
{
|
||||
{ 0, Hand_WristRoot },
|
||||
{ 1, Hand_Thumb1 },
|
||||
{ 2, Hand_Thumb2 },
|
||||
{ 3, Hand_Thumb3 },
|
||||
{ 4, Hand_Index1 },
|
||||
{ 5, Hand_Index2 },
|
||||
{ 6, Hand_Index3 },
|
||||
{ 7, Hand_Middle1 },
|
||||
{ 8, Hand_Middle2 },
|
||||
{ 9, Hand_Middle3 },
|
||||
{ 10, Hand_Ring1 },
|
||||
{ 11, Hand_Ring2 },
|
||||
{ 12, Hand_Ring3 },
|
||||
{ 13, Hand_Pinky1 },
|
||||
{ 14, Hand_Pinky2 },
|
||||
{ 15, Hand_Pinky3 }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public VG_EC_Generic(int avatarID, VG_HandSide side, Transform origin)
|
||||
{
|
||||
m_avatarID = avatarID;
|
||||
m_handType = side;
|
||||
m_origin = origin;
|
||||
m_zeroOffsets = true; // the generic hand works on the Unity transforms, so it can't use offsets.
|
||||
Initialize();
|
||||
}
|
||||
|
||||
public new void Initialize()
|
||||
{
|
||||
m_mapping = new HandMapping();
|
||||
base.Initialize();
|
||||
m_enabled = true;
|
||||
}
|
||||
|
||||
public override bool Compute()
|
||||
{
|
||||
for (int bone = 0; bone < m_mapping.GetNumBones(); bone++)
|
||||
{
|
||||
if (!m_mapping.GetTransform(bone, out Transform pose)) continue;
|
||||
SetPose(bone, Matrix4x4.TRS(pose.position, pose.rotation, Vector3.one));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override float GetGrabStrength()
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
public override Color GetConfidence()
|
||||
{
|
||||
return Color.yellow;
|
||||
}
|
||||
|
||||
public override void HapticPulse(VG_HandStatus hand, float amplitude = 0.5F, float duration = 0.015F, int finger = 5)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8ba28b8b076ea2a45a4f03b9f332ec23
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,205 @@
|
||||
// Copyright (C) 2014-2024 Gleechi Technology AB. All rights reserved.
|
||||
|
||||
//#define VG_USE_LEAP_CONTROLLER
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
#if VG_USE_LEAP_CONTROLLER
|
||||
using Leap.Unity;
|
||||
#endif
|
||||
|
||||
namespace VirtualGrasp.Controllers
|
||||
{
|
||||
/**
|
||||
* This is an external controller class that supports the LeapMotion controller as an external controller.
|
||||
* Please refer to https://docs.virtualgrasp.com/controllers.html for the definition of an external controller for VG.
|
||||
*
|
||||
* The following requirements have to be met to be able to enable the #define VG_USE_LEAP_CONTROLLER above and use the controller:
|
||||
* - You have a Core Assets plugin from https://developer.leapmotion.com/unity imported into your Unity project.
|
||||
* - Note that Core Assets > 4.4.0 are for LeapMotion SDK 4, older are for LeapMotion SDK 3 (lastest CA 4.3.4).
|
||||
* - You have the corresponding LeapMotion SDK (https://developer.leapmotion.com/sdk-leap-motion-controller/) installed on your computer.
|
||||
*/
|
||||
[LIBVIRTUALGRASP_UNITY_SCRIPT]
|
||||
[HelpURL("https://docs.virtualgrasp.com/unity_vg_ec_leap." + VG_Version.__VG_VERSION__ + ".html")]
|
||||
public class VG_EC_Leap : VG_ExternalController
|
||||
{
|
||||
#if VG_USE_LEAP_CONTROLLER
|
||||
static LeapProvider m_provider = null;
|
||||
Leap.Hand m_hand = null;
|
||||
|
||||
static public int LeapBoneToInt(int finger, int bone)
|
||||
{
|
||||
return 4 * finger + bone + 1;
|
||||
}
|
||||
|
||||
static public int LeapBoneToInt(Leap.Finger.FingerType finger, Leap.Bone.BoneType bone)
|
||||
{
|
||||
return LeapBoneToInt((int)finger, (int)bone);
|
||||
}
|
||||
|
||||
static public void IntToLeapBone(int id, out int finger, out Leap.Bone.BoneType bone)
|
||||
{
|
||||
bone = (Leap.Bone.BoneType)((id - 1) % 4);
|
||||
finger = (id - (int)bone) / 4;
|
||||
}
|
||||
#endif
|
||||
|
||||
[Serializable]
|
||||
public class HandMapping : VG_BoneMapping
|
||||
{
|
||||
public override void Initialize(int avatarID, VG_HandSide side)
|
||||
{
|
||||
base.Initialize(avatarID, side);
|
||||
m_BoneToTransform = new Dictionary<int, Transform>()
|
||||
{
|
||||
#if VG_USE_LEAP_CONTROLLER
|
||||
{ 0, Hand_WristRoot },
|
||||
{ LeapBoneToInt(0, 0), null },
|
||||
{ LeapBoneToInt(0, 1), Hand_Thumb1 },
|
||||
{ LeapBoneToInt(0, 2), Hand_Thumb2 },
|
||||
{ LeapBoneToInt(0, 3), Hand_Thumb3 },
|
||||
{ LeapBoneToInt(1, 0), null },
|
||||
{ LeapBoneToInt(1, 1), Hand_Index1 },
|
||||
{ LeapBoneToInt(1, 2), Hand_Index2 },
|
||||
{ LeapBoneToInt(1, 3), Hand_Index3 },
|
||||
{ LeapBoneToInt(2, 0), null },
|
||||
{ LeapBoneToInt(2, 1), Hand_Middle1 },
|
||||
{ LeapBoneToInt(2, 2), Hand_Middle2 },
|
||||
{ LeapBoneToInt(2, 3), Hand_Middle3 },
|
||||
{ LeapBoneToInt(3, 0), null },
|
||||
{ LeapBoneToInt(3, 1), Hand_Ring1 },
|
||||
{ LeapBoneToInt(3, 2), Hand_Ring2 },
|
||||
{ LeapBoneToInt(3, 3), Hand_Ring3 },
|
||||
{ LeapBoneToInt(4, 0), null },
|
||||
{ LeapBoneToInt(4, 1), Hand_Pinky1 },
|
||||
{ LeapBoneToInt(4, 2), Hand_Pinky2 },
|
||||
{ LeapBoneToInt(4, 3), Hand_Pinky3 }
|
||||
#endif
|
||||
};
|
||||
|
||||
m_BoneToParent = new Dictionary<int, int>()
|
||||
{
|
||||
};
|
||||
#if VG_USE_LEAP_CONTROLLER
|
||||
m_BoneToParent[LeapBoneToInt(0, 0)] = 0;
|
||||
m_BoneToParent[LeapBoneToInt(0, 1)] = LeapBoneToInt(0, 0);
|
||||
m_BoneToParent[LeapBoneToInt(0, 2)] = LeapBoneToInt(0, 1);
|
||||
m_BoneToParent[LeapBoneToInt(0, 3)] = LeapBoneToInt(0, 2);
|
||||
m_BoneToParent[LeapBoneToInt(1, 0)] = 0;
|
||||
m_BoneToParent[LeapBoneToInt(1, 1)] = LeapBoneToInt(1, 0);
|
||||
m_BoneToParent[LeapBoneToInt(1, 2)] = LeapBoneToInt(1, 1);
|
||||
m_BoneToParent[LeapBoneToInt(1, 3)] = LeapBoneToInt(1, 2);
|
||||
m_BoneToParent[LeapBoneToInt(2, 0)] = 0;
|
||||
m_BoneToParent[LeapBoneToInt(2, 1)] = LeapBoneToInt(2, 0);
|
||||
m_BoneToParent[LeapBoneToInt(2, 2)] = LeapBoneToInt(2, 1);
|
||||
m_BoneToParent[LeapBoneToInt(2, 3)] = LeapBoneToInt(2, 2);
|
||||
m_BoneToParent[LeapBoneToInt(3, 0)] = 0;
|
||||
m_BoneToParent[LeapBoneToInt(3, 1)] = LeapBoneToInt(3, 0);
|
||||
m_BoneToParent[LeapBoneToInt(3, 2)] = LeapBoneToInt(3, 1);
|
||||
m_BoneToParent[LeapBoneToInt(3, 3)] = LeapBoneToInt(3, 2);
|
||||
m_BoneToParent[LeapBoneToInt(4, 0)] = 0;
|
||||
m_BoneToParent[LeapBoneToInt(4, 1)] = LeapBoneToInt(4, 0);
|
||||
m_BoneToParent[LeapBoneToInt(4, 2)] = LeapBoneToInt(4, 1);
|
||||
m_BoneToParent[LeapBoneToInt(4, 3)] = LeapBoneToInt(4, 2);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public VG_EC_Leap(int avatarID, VG_HandSide side, Transform origin)
|
||||
{
|
||||
m_avatarID = avatarID;
|
||||
m_handType = side;
|
||||
m_origin = origin;
|
||||
m_enablingDefine = "VG_USE_LEAP_CONTROLLER";
|
||||
|
||||
#if VG_USE_LEAP_CONTROLLER
|
||||
m_enabled = true;
|
||||
#else
|
||||
PrintNotEnabledError();
|
||||
m_enabled = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public new void Initialize()
|
||||
{
|
||||
#if VG_USE_LEAP_CONTROLLER
|
||||
if (m_provider == null)
|
||||
{
|
||||
m_provider = GameObject.FindObjectOfType<VG_MainScript>().gameObject.AddComponent<LeapServiceProvider>();
|
||||
}
|
||||
|
||||
if (m_provider != null)
|
||||
{
|
||||
m_mapping = new HandMapping();
|
||||
base.Initialize();
|
||||
}
|
||||
|
||||
m_initialized = (m_provider != null);
|
||||
#endif
|
||||
}
|
||||
|
||||
public override bool Compute()
|
||||
{
|
||||
#if VG_USE_LEAP_CONTROLLER
|
||||
if (!m_enabled) return false;
|
||||
if (!m_initialized || m_mapping == null) { Initialize(); return false; }
|
||||
if (m_provider == null) return false;
|
||||
|
||||
Leap.Frame frame = m_provider.CurrentFrame;
|
||||
if (frame == null) return false;
|
||||
|
||||
m_hand = null;
|
||||
foreach (Leap.Hand hand in frame.Hands)
|
||||
{
|
||||
if (hand.IsLeft && m_handType == VG_HandSide.LEFT) { m_hand = hand; break; }
|
||||
if (!hand.IsLeft && m_handType == VG_HandSide.RIGHT) { m_hand = hand; break; }
|
||||
}
|
||||
if (m_hand == null) return false;
|
||||
|
||||
for (int boneId = 0; boneId < GetNumBones(); boneId++)
|
||||
{
|
||||
if (boneId == 0)
|
||||
{
|
||||
SetPose(boneId, Matrix4x4.TRS(m_hand.WristPosition, m_hand.Rotation, Vector3.one));
|
||||
}
|
||||
else
|
||||
{
|
||||
IntToLeapBone(boneId, out int finger, out Leap.Bone.BoneType bone);
|
||||
Leap.Bone b = m_hand.Fingers[finger].Bone(bone);
|
||||
SetPose(boneId, Matrix4x4.TRS(b.NextJoint, b.Rotation, Vector3.one));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public override float GetGrabStrength()
|
||||
{
|
||||
#if VG_USE_LEAP_CONTROLLER
|
||||
// Get grab strength from Leap if available
|
||||
//return m_hand != null ? m_hand.GrabStrength : 0.0f;
|
||||
return -1.0f; // let VG decide from full DOF
|
||||
#else
|
||||
return 0.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
public override Color GetConfidence()
|
||||
{
|
||||
#if VG_USE_LEAP_CONTROLLER
|
||||
if (m_hand != null) return Color.black;
|
||||
return m_hand.Confidence > 0.5f ? Color.green : Color.red;
|
||||
#else
|
||||
return Color.yellow;
|
||||
#endif
|
||||
}
|
||||
|
||||
public override void HapticPulse(VG_HandStatus hand, float amplitude = 0.5F, float duration = 0.015F, int finger = 5)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c735f357c234e0b4e9a5c8db5e88f37c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,413 @@
|
||||
// Copyright (C) 2014-2024 Gleechi Technology AB. All rights reserved.
|
||||
|
||||
//#define VG_USE_MANUS_CONTROLLER
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
#if VG_USE_MANUS_CONTROLLER
|
||||
using System.Linq;
|
||||
using Manus;
|
||||
using Manus.Skeletons;
|
||||
using Manus.Utility;
|
||||
#endif
|
||||
|
||||
namespace VirtualGrasp.Controllers
|
||||
{
|
||||
/**
|
||||
* This is an external controller class that supports the Manus Glove controller as an external controller.
|
||||
* Please refer to https://docs.virtualgrasp.com/controllers.html for the definition of an external controller for VG.
|
||||
*
|
||||
* The following requirements have to be met to be able to enable the #define VG_USE_MANUS_CONTROLLER above and use the controller:
|
||||
* - You have the corresponding Manus Core SDK (https://resources.manus-meta.com/downloads) installed on your computer.
|
||||
* - You have the Unity Plugin for Manus Core from https://resources.manus-meta.com/downloads imported into your Unity project.
|
||||
* - You have a Manus Pro License assigned to your SDK to use the Unity Plugin.
|
||||
*/
|
||||
[LIBVIRTUALGRASP_UNITY_SCRIPT]
|
||||
[HelpURL("https://docs.virtualgrasp.com/unity_vg_ec_manus." + VG_Version.__VG_VERSION__ + ".html")]
|
||||
public class VG_EC_Manus : VG_ExternalController
|
||||
{
|
||||
#if VG_USE_MANUS_CONTROLLER
|
||||
private Skeleton m_skeleton = null;
|
||||
private CoreSDK.SkeletonStream m_skeletonData;
|
||||
private int m_id = -1;
|
||||
private static uint MANUS_SKELETON_ID = 0;
|
||||
|
||||
private void onSkeletonData(CoreSDK.SkeletonStream data)
|
||||
{
|
||||
m_skeletonData = data;
|
||||
}
|
||||
|
||||
protected void IntFromManusBone(uint nodeId, out int boneId)
|
||||
{
|
||||
boneId = (int)nodeId;
|
||||
}
|
||||
|
||||
static private void PrintNode(CoreSDK.SkeletonNode node)
|
||||
{
|
||||
Debug.Log("CNode " + node.ToString());
|
||||
}
|
||||
|
||||
static private void PrintNode(Node node)
|
||||
{
|
||||
Debug.Log("Node " + node.id + " (" + node.name + "|" + node.nodeName + ")" +
|
||||
node.unityTransform.name + " (type: " + node.type + "; parent: " + node.parentID + ")"
|
||||
);
|
||||
}
|
||||
static private void PrintChain(Chain chain)
|
||||
{
|
||||
string str = "";
|
||||
foreach (uint id in chain.nodeIds)
|
||||
str += id + ",";
|
||||
Debug.Log("Chain " + chain.id + " (" + chain.name + "|" + chain.dataSide + ")"
|
||||
+ " (type: " + chain.type + "; hand: " + chain.settings.finger.handChainId + "); meta " + chain.settings.finger.metacarpalBoneId
|
||||
+ "; " + str);
|
||||
}
|
||||
#endif
|
||||
|
||||
[Serializable]
|
||||
public class HandMapping : VG_BoneMapping
|
||||
{
|
||||
public override void Initialize(int avatarID, VG_HandSide side)
|
||||
{
|
||||
base.Initialize(avatarID, side);
|
||||
m_BoneToTransform = new Dictionary<int, Transform>()
|
||||
{
|
||||
#if VG_USE_MANUS_CONTROLLER
|
||||
{ 0, Hand_WristRoot },
|
||||
|
||||
{ 1, Hand_Thumb1 },
|
||||
{ 2, Hand_Thumb2 },
|
||||
{ 3, Hand_Thumb3 },
|
||||
{ 4, null },
|
||||
|
||||
{ 5, null },
|
||||
{ 6, Hand_Index1 },
|
||||
{ 7, Hand_Index2 },
|
||||
{ 8, Hand_Index3 },
|
||||
{ 9, null },
|
||||
|
||||
{ 10, null },
|
||||
{ 11, Hand_Middle1 },
|
||||
{ 12, Hand_Middle2 },
|
||||
{ 13, Hand_Middle3 },
|
||||
{ 14, null },
|
||||
|
||||
{ 15, null },
|
||||
{ 16, Hand_Ring1 },
|
||||
{ 17, Hand_Ring2 },
|
||||
{ 18, Hand_Ring3 },
|
||||
{ 19, null },
|
||||
|
||||
{ 20, null },
|
||||
{ 21, Hand_Pinky1 },
|
||||
{ 22, Hand_Pinky2 },
|
||||
{ 23, Hand_Pinky3 },
|
||||
{ 24, null },
|
||||
#endif
|
||||
};
|
||||
|
||||
m_BoneToParent = new Dictionary<int, int>()
|
||||
{
|
||||
};
|
||||
#if VG_USE_MANUS_CONTROLLER
|
||||
m_BoneToParent[0] = -1;
|
||||
|
||||
m_BoneToParent[1] = 0;
|
||||
m_BoneToParent[2] = 1;
|
||||
m_BoneToParent[3] = 2;
|
||||
m_BoneToParent[4] = 3;
|
||||
|
||||
m_BoneToParent[5] = 0;
|
||||
m_BoneToParent[6] = 5;
|
||||
m_BoneToParent[7] = 6;
|
||||
m_BoneToParent[8] = 7;
|
||||
m_BoneToParent[9] = 8;
|
||||
|
||||
m_BoneToParent[10] = 0;
|
||||
m_BoneToParent[11] = 10;
|
||||
m_BoneToParent[12] = 11;
|
||||
m_BoneToParent[13] = 12;
|
||||
m_BoneToParent[14] = 13;
|
||||
|
||||
m_BoneToParent[15] = 0;
|
||||
m_BoneToParent[16] = 15;
|
||||
m_BoneToParent[17] = 16;
|
||||
m_BoneToParent[18] = 17;
|
||||
m_BoneToParent[19] = 18;
|
||||
|
||||
m_BoneToParent[20] = 0;
|
||||
m_BoneToParent[21] = 20;
|
||||
m_BoneToParent[22] = 21;
|
||||
m_BoneToParent[23] = 22;
|
||||
m_BoneToParent[24] = 23;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if VG_USE_MANUS_CONTROLLER
|
||||
// Function to setup nodes for metacarpals and tips properly in Manus SDK.
|
||||
// (They are not considered in VG controllers.)
|
||||
private void FillUnassignedNodes(List<Node> nodes)
|
||||
{
|
||||
for (int nodeId = 0; nodeId < nodes.Count; nodeId++)
|
||||
{
|
||||
Node node = nodes[nodeId];
|
||||
if (node.unityTransform == null)
|
||||
{
|
||||
// metacarpals
|
||||
if (new List<int>() { 5, 10, 15, 20 }.Contains(nodeId))
|
||||
{
|
||||
Node next_node = nodes[nodeId + 1];
|
||||
node.unityTransform = next_node.unityTransform.parent;
|
||||
node.nodeName = (node.unityTransform == null) ? "n/a" : node.unityTransform.name;
|
||||
node.name = node.nodeName;
|
||||
}
|
||||
else // tips
|
||||
{
|
||||
Node prev_node = nodes[nodeId - 1];
|
||||
node.unityTransform = prev_node.unityTransform.GetChild(0);
|
||||
node.nodeName = (node.unityTransform == null) ? "n/a" : node.unityTransform.name;
|
||||
node.name = node.nodeName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool ComputeFingerChainIds(out List<uint> chainIds)
|
||||
{
|
||||
chainIds = new List<uint>();
|
||||
foreach (Transform child in Hand_WristRoot.transform)
|
||||
{
|
||||
List<Transform> children = child.GetComponentsInChildren<Transform>().ToList<Transform>();
|
||||
if (children.Contains(Hand_Thumb1))
|
||||
chainIds.Add(2);
|
||||
else if (children.Contains(Hand_Index1))
|
||||
chainIds.Add(3);
|
||||
else if (children.Contains(Hand_Middle1))
|
||||
chainIds.Add(4);
|
||||
else if (children.Contains(Hand_Ring1))
|
||||
chainIds.Add(5);
|
||||
else if (children.Contains(Hand_Pinky1))
|
||||
chainIds.Add(6);
|
||||
|
||||
// Check if we have properly ordered fingers.
|
||||
int count = chainIds.Count;
|
||||
if (count > 1 && chainIds[count - 1] < chainIds[count - 2])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool FillSkeletonFromMapping(Skeleton skeleton, VG_HandSide side)
|
||||
{
|
||||
skeleton.skeletonData = new SkeletonData();
|
||||
skeleton.skeletonData.type = CoreSDK.SkeletonType.Hand;
|
||||
skeleton.skeletonData.name = skeleton.name;
|
||||
skeleton.skeletonData.settings.targetType = CoreSDK.SkeletonTargetType.UserIndexData;
|
||||
skeleton.skeletonData.nodes.Clear();
|
||||
skeleton.skeletonData.chains.Clear();
|
||||
|
||||
// Hand chain
|
||||
Chain chain1 = new Chain();
|
||||
chain1.id = 1;
|
||||
chain1.type = CoreSDK.ChainType.Hand;
|
||||
chain1.appliedDataType = chain1.type;
|
||||
chain1.dataSide = (side == VG_HandSide.LEFT) ? CoreSDK.Side.Left : CoreSDK.Side.Right;
|
||||
chain1.nodeIds.Add(0);
|
||||
chain1.settings.finger.handChainId = 0;
|
||||
chain1.settings.finger.metacarpalBoneId = 0;
|
||||
chain1.settings.hand.fingerChainIds = new[] { 2, 3, 4, 5, 6 };
|
||||
skeleton.skeletonData.chains.Add(chain1);
|
||||
|
||||
// Add all nodes from VG mapping.
|
||||
foreach (KeyValuePair<int, Transform> boneTransform in m_BoneToTransform)
|
||||
{
|
||||
Node node = new Node();
|
||||
node.unityTransform = boneTransform.Value;
|
||||
node.nodeName = (node.unityTransform == null) ? "n/a" : node.unityTransform.name;
|
||||
node.name = node.nodeName;
|
||||
node.type = CoreSDK.NodeType.Joint;
|
||||
node.id = (uint)boneTransform.Key;
|
||||
node.parentID = m_BoneToParent.ContainsKey(boneTransform.Key) ?
|
||||
(uint)m_BoneToParent[boneTransform.Key] : 0;
|
||||
node.transform = new TransformValues();
|
||||
node.transform.scale = Vector3.one;
|
||||
skeleton.skeletonData.nodes.Add(node);
|
||||
}
|
||||
|
||||
// Fill in nodes for bones that don't exist in VG skeleton
|
||||
FillUnassignedNodes(skeleton.skeletonData.nodes);
|
||||
|
||||
// Finger chains (chain to bones)
|
||||
// Note: the chains need to be exactly ordered as in the hierarchy.
|
||||
|
||||
if (!ComputeFingerChainIds(out List<uint> chainIds))
|
||||
{
|
||||
Debug.LogError($"Please assure that the finger chains (children of {Hand_WristRoot.name}) are sorted as:" +
|
||||
"(Thumb, Index, Middle, Ring, Pinky)", Hand_WristRoot);
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (uint chainId in chainIds)
|
||||
{
|
||||
Chain chain = new Chain();
|
||||
chain.name = "Finger " + chainId;
|
||||
chain.id = chainId;
|
||||
chain.type = (CoreSDK.ChainType)chainId + 3;
|
||||
chain.appliedDataType = chain.type;
|
||||
chain.dataSide = (side == VG_HandSide.LEFT) ? CoreSDK.Side.Left : CoreSDK.Side.Right;
|
||||
chain.nodeIds = new List<uint>();
|
||||
chain.settings.finger.handChainId = 1;
|
||||
if (chainId == 2) // thumb
|
||||
{
|
||||
chain.settings.finger.metacarpalBoneId = -1;
|
||||
chain.nodeIds = new List<uint> { 1, 2, 3, 4 };
|
||||
}
|
||||
else
|
||||
{
|
||||
chain.settings.finger.metacarpalBoneId = (int)(5 * (chainId - 2));
|
||||
chain.nodeIds = new List<uint>();
|
||||
for (int i = chain.settings.finger.metacarpalBoneId; i < chain.settings.finger.metacarpalBoneId + 5; i++)
|
||||
chain.nodeIds.Add((uint)i);
|
||||
}
|
||||
|
||||
skeleton.skeletonData.chains.Add(chain);
|
||||
}
|
||||
|
||||
/*
|
||||
// Just for debugging
|
||||
foreach (Node node in skeleton.skeletonData.nodes)
|
||||
PrintNode(node);
|
||||
foreach (Chain chain in skeleton.skeletonData.chains)
|
||||
PrintChain(chain);
|
||||
*/
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public VG_EC_Manus(int avatarID, VG_HandSide side, Transform origin)
|
||||
{
|
||||
m_avatarID = avatarID;
|
||||
m_handType = side;
|
||||
m_origin = origin;
|
||||
m_enablingDefine = "VG_USE_MANUS_CONTROLLER";
|
||||
|
||||
#if VG_USE_MANUS_CONTROLLER
|
||||
m_enabled = true;
|
||||
#else
|
||||
PrintNotEnabledError();
|
||||
m_enabled = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public new void Initialize()
|
||||
{
|
||||
#if VG_USE_MANUS_CONTROLLER
|
||||
if (m_mapping == null)
|
||||
{
|
||||
m_mapping = new HandMapping();
|
||||
base.Initialize();
|
||||
}
|
||||
|
||||
// Note: need to disable GO first so Skeleton constructor does not fail
|
||||
// due to uninitialized data structures (FillSkeletonFromMapping).
|
||||
GameObject go = m_mapping.Hand_WristRoot.gameObject;
|
||||
bool oldActive = go.activeSelf;
|
||||
go.SetActive(false);
|
||||
if (!go.TryGetComponent<Skeleton>(out m_skeleton))
|
||||
m_skeleton = go.AddComponent<Skeleton>();
|
||||
|
||||
// Note: paused needs to be modified to public so Manus API does not apply bone poses,
|
||||
// but let's VG do this.
|
||||
m_skeleton.m_Paused = true;
|
||||
|
||||
m_initialized = false;
|
||||
if (!(m_mapping as HandMapping).FillSkeletonFromMapping(m_skeleton, m_handType))
|
||||
{
|
||||
this.m_enabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
try { go.SetActive(oldActive); }
|
||||
catch (Exception) { return; }
|
||||
|
||||
// Note: ManusManager is static and managing the gloves
|
||||
m_skeleton.SetupMeshes();
|
||||
m_skeleton.SetupNodes();
|
||||
m_skeleton.SendSkeleton();
|
||||
m_skeleton.skeletonData.id = MANUS_SKELETON_ID++;
|
||||
m_id = (int)m_skeleton.skeletonData.id;
|
||||
ManusManager.communicationHub?.onSkeletonData.AddListener(this.onSkeletonData);
|
||||
|
||||
m_initialized = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
public override bool Compute()
|
||||
{
|
||||
#if VG_USE_MANUS_CONTROLLER
|
||||
if (!m_enabled) return false;
|
||||
if (!m_initialized || m_mapping == null) { Initialize(); return false; }
|
||||
if (m_skeletonData.skeletons == null || m_skeletonData.skeletons.Count == 0) return false;
|
||||
|
||||
foreach (CoreSDK.SkeletonNode node in m_skeletonData.skeletons[m_id].nodes)
|
||||
{
|
||||
IntFromManusBone(node.id, out int boneId);
|
||||
//Debug.Log("VG " + m_handType + ":" + m_id + " (" + boneId + "/" + GetNumBones() + "); MAN: " + node.id + "/" + m_skeletonData.skeletons[0].nodes.Length + "):\n" + node.transform.rotation.FromManus());
|
||||
|
||||
if (boneId == 0)
|
||||
{
|
||||
SetPose(boneId, Matrix4x4.TRS(
|
||||
node.transform.position.FromManus(),
|
||||
node.transform.rotation.FromManus().normalized,
|
||||
Vector3.one));
|
||||
}
|
||||
else
|
||||
{
|
||||
SetPose(boneId, m_poses[m_mapping.GetParent(boneId)] *
|
||||
Matrix4x4.TRS(
|
||||
node.transform.position.FromManus(),
|
||||
node.transform.rotation.FromManus().normalized,
|
||||
Vector3.one));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public override float GetGrabStrength()
|
||||
{
|
||||
#if VG_USE_MANUS_CONTROLLER
|
||||
// No grab strength from Manus API is available, so
|
||||
// let VG decide from full DOF.
|
||||
return -1.0f;
|
||||
#else
|
||||
return 0.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
public override Color GetConfidence()
|
||||
{
|
||||
#if VG_USE_MANUS_CONTROLLER
|
||||
// No confidence value of the tracked data in Manus API.
|
||||
return Color.yellow;
|
||||
#else
|
||||
return Color.yellow;
|
||||
#endif
|
||||
}
|
||||
|
||||
public override void HapticPulse(VG_HandStatus hand, float amplitude = 0.5F, float duration = 0.015F, int finger = 5)
|
||||
{
|
||||
#if VG_USE_MANUS_CONTROLLER
|
||||
float[] amplitudes = new float[] { amplitude, amplitude, amplitude, amplitude, amplitude};
|
||||
ManusManager.communicationHub?.SendHapticDataForSkeleton(m_skeleton.skeletonData.id, m_handType == VG_HandSide.LEFT ? CoreSDK.Side.Left : CoreSDK.Side.Right, amplitudes);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 506abf992f64c0845b2a9c27d0f3e8fc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,109 @@
|
||||
// Copyright (C) 2014-2024 Gleechi Technology AB. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
#if VG_ENABLE_INPUT_SYSTEM // && !ENABLE_LEGACY_INPUT_MANAGER
|
||||
using UnityEngine.InputSystem;
|
||||
#endif
|
||||
|
||||
namespace VirtualGrasp.Controllers
|
||||
{
|
||||
/**
|
||||
* This is an external controller class that supports a Mouse controller as an external controller.
|
||||
* Please refer to https://docs.virtualgrasp.com/controllers.html for the definition of an external controller for VG.
|
||||
*/
|
||||
[LIBVIRTUALGRASP_UNITY_SCRIPT]
|
||||
[HelpURL("https://docs.virtualgrasp.com/unity_vg_ec_mouse." + VG_Version.__VG_VERSION__ + ".html")]
|
||||
public class VG_EC_Mouse : VG_ExternalController
|
||||
{
|
||||
private int mouse_held = 0;
|
||||
private int filter = 15;
|
||||
private float depth = .5f;
|
||||
private Vector3 rotation = Vector3.zero;
|
||||
#if VG_ENABLE_INPUT_SYSTEM
|
||||
private float rotationSpeed = 0.5f;
|
||||
#endif
|
||||
|
||||
[Serializable]
|
||||
public class HandMapping : VG_BoneMapping
|
||||
{
|
||||
public override void Initialize(int avatarID, VG_HandSide side)
|
||||
{
|
||||
base.Initialize(avatarID, side);
|
||||
m_BoneToTransform = new Dictionary<int, Transform>()
|
||||
{
|
||||
{ 0, Hand_WristRoot }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public VG_EC_Mouse(int avatarID, VG_HandSide side, Transform origin)
|
||||
{
|
||||
m_avatarID = avatarID;
|
||||
m_handType = side;
|
||||
m_origin = origin;
|
||||
|
||||
m_enabled = true;
|
||||
}
|
||||
|
||||
public new void Initialize()
|
||||
{
|
||||
m_initialized = (Camera.main != null);
|
||||
if (!m_initialized) return;
|
||||
|
||||
m_mapping = new HandMapping();
|
||||
base.Initialize();
|
||||
if (Camera.main.stereoTargetEye != StereoTargetEyeMask.None)
|
||||
{
|
||||
Debug.LogWarning("VG_EC_MouseHand uses single GameView camera, but a stereo camera is activated. Deactivating Stereo view.");
|
||||
Camera.main.stereoTargetEye = StereoTargetEyeMask.None;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Compute()
|
||||
{
|
||||
if (!m_enabled || !Application.isFocused) return false;
|
||||
if (!m_initialized || m_mapping == null) { Initialize(); return false; }
|
||||
|
||||
#if VG_ENABLE_INPUT_SYSTEM // && !ENABLE_LEGACY_INPUT_MANAGER
|
||||
if (Keyboard.current.leftShiftKey.isPressed && m_handType == VG_HandSide.RIGHT ||
|
||||
Keyboard.current.rightShiftKey.isPressed && m_handType == VG_HandSide.LEFT)
|
||||
return true;
|
||||
|
||||
if (Keyboard.current.xKey.IsPressed()) rotation.x += rotationSpeed;
|
||||
if (Keyboard.current.yKey.IsPressed()) rotation.y += rotationSpeed;
|
||||
if (Keyboard.current.zKey.IsPressed()) rotation.z += rotationSpeed;
|
||||
|
||||
if (m_handType == VirtualGrasp.VG_HandSide.LEFT ? Mouse.current.leftButton.isPressed : Mouse.current.rightButton.isPressed)
|
||||
mouse_held = Mathf.Min(filter, mouse_held + 1);
|
||||
else mouse_held = Mathf.Max(0, mouse_held - 1);
|
||||
depth = Mathf.Clamp(depth + Mouse.current.scroll.y.ReadValue() / 100.0f, .01f, 1.0f);
|
||||
Ray ray = Camera.main.ScreenPointToRay(Mouse.current.position.ReadValue());
|
||||
#else
|
||||
if (Input.GetMouseButton(m_handType == VirtualGrasp.VG_HandSide.LEFT ? 0 : 1)) mouse_held = Mathf.Min(filter, mouse_held + 1);
|
||||
else mouse_held = Mathf.Max(0, mouse_held - 1);
|
||||
depth = Mathf.Clamp(depth + Input.mouseScrollDelta.y / 10.0f, .5f, 3.0f);
|
||||
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
|
||||
#endif
|
||||
Quaternion q = Camera.main.transform.rotation;
|
||||
Vector3 p = ray.origin + depth * ray.direction + q * (m_handType == VirtualGrasp.VG_HandSide.LEFT ? Vector3.left : Vector3.right) * .1f;
|
||||
q = q * Quaternion.Euler(rotation);
|
||||
SetPose(0, Matrix4x4.TRS(p, q, Vector3.one));
|
||||
return true;
|
||||
}
|
||||
|
||||
public override float GetGrabStrength()
|
||||
{
|
||||
return (float)mouse_held / filter;
|
||||
}
|
||||
|
||||
public override Color GetConfidence()
|
||||
{
|
||||
return Color.yellow;
|
||||
}
|
||||
public override void HapticPulse(VG_HandStatus hand, float amplitude = 0.5F, float duration = 0.015F, int finger = 5)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fb4ba4cb1ca48424ca180c73ac0d42cc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,115 @@
|
||||
// Copyright (C) 2014-2024 Gleechi Technology AB. All rights reserved.
|
||||
|
||||
//#define VG_USE_OVRHAND_CONTROLLER // Please read below instructions and requirements before activating.
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace VirtualGrasp.Controllers
|
||||
{
|
||||
/**
|
||||
* NOTE: this is an experimental controller only for the OculusIntegration sample.
|
||||
* We recommend to not use OVRHand / OVRCustomSkeleton but use one of the
|
||||
* various finger controllers that come with VirtualGrasp.
|
||||
*
|
||||
* This is an external controller class that supports a generic overlay controller for the OVRHand class as an external controller.
|
||||
* Please refer to https://docs.virtualgrasp.com/controllers.html for the definition of an external controller for VG.
|
||||
*
|
||||
* The following requirements have to be met to be able to enable the #define VG_USE_OVRHAND_CONTROLLER above and use the controller:
|
||||
* - You have the Oculus SDK (https://www.oculus.com/setup/) installed on your computer.
|
||||
* - You have the Oculus Integration plugin from https://developer.oculus.com/downloads/package/unity-integration/ imported into your Unity project.
|
||||
* - You are using a handmodel / rig that is based on the OVRHand / OVRCustomSkeleton classes.
|
||||
*/
|
||||
|
||||
[LIBVIRTUALGRASP_UNITY_SCRIPT]
|
||||
[HelpURL("https://docs.virtualgrasp.com/unity_vg_ec_ovr." + VG_Version.__VG_VERSION__ + ".html")]
|
||||
public class VG_EC_OVR : VG_ExternalController
|
||||
{
|
||||
#if VG_USE_OVRHAND_CONTROLLER
|
||||
private OVRCustomSkeleton m_skeleton = null;
|
||||
private OVRHand m_hand = null;
|
||||
#endif
|
||||
|
||||
public VG_EC_OVR(int avatarID, VG_HandSide side, Transform origin)
|
||||
{
|
||||
m_avatarID = avatarID;
|
||||
m_handType = side;
|
||||
m_zeroOffsets = true; // the generic hand works on the Unity transforms, so it can't use offsets.
|
||||
m_origin = origin;
|
||||
m_enablingDefine = "VG_USE_OVRHAND_CONTROLLER";
|
||||
|
||||
#if VG_USE_OVRHAND_CONTROLLER
|
||||
Initialize();
|
||||
m_enabled = true;
|
||||
#else
|
||||
PrintNotEnabledError();
|
||||
m_enabled = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public new void Initialize()
|
||||
{
|
||||
m_mapping = new VG_EC_Oculus.HandMapping();
|
||||
|
||||
#if VG_USE_OVRHAND_CONTROLLER
|
||||
foreach (OVRCustomSkeleton hand in GameObject.FindObjectsOfType<OVRCustomSkeleton>()) {
|
||||
if (hand.GetSkeletonType() == OVRSkeleton.SkeletonType.HandLeft && m_handType == VG_HandSide.LEFT ||
|
||||
hand.GetSkeletonType() == OVRSkeleton.SkeletonType.HandRight && m_handType == VG_HandSide.RIGHT) {
|
||||
m_skeleton = hand;
|
||||
m_hand = hand.gameObject.GetComponent<OVRHand>();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_skeleton == null)
|
||||
{
|
||||
m_initialized = false;
|
||||
return;
|
||||
}
|
||||
|
||||
base.Initialize();
|
||||
m_initialized = true;
|
||||
#else
|
||||
m_initialized = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public override bool Compute()
|
||||
{
|
||||
if (!m_enabled) return false;
|
||||
if (!m_initialized) { Initialize(); return false; }
|
||||
|
||||
#if VG_USE_OVRHAND_CONTROLLER
|
||||
if (!m_skeleton.IsDataValid) return false;
|
||||
int offset = (int)m_skeleton.GetCurrentStartBoneId();
|
||||
for (int bone = 0; bone < m_mapping.GetNumBones(); bone++)
|
||||
{
|
||||
Transform pose = (bone != 1) ?
|
||||
m_skeleton.CustomBones[offset + bone].transform :
|
||||
m_skeleton.CustomBones[offset].transform; // we map forearm stub to wrist
|
||||
SetPose(bone, Matrix4x4.TRS(pose.position, pose.rotation, Vector3.one));
|
||||
}
|
||||
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public override float GetGrabStrength() {
|
||||
|
||||
#if VG_USE_OVRHAND_CONTROLLER
|
||||
return -1.0f;
|
||||
//return m_hand.GetFingerPinchStrength(OVRHand.HandFinger.Index);
|
||||
#else
|
||||
return -1.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
public override Color GetConfidence()
|
||||
{
|
||||
return Color.yellow;
|
||||
}
|
||||
|
||||
public override void HapticPulse(VG_HandStatus hand, float amplitude = 0.5F, float duration = 0.015F, int finger = 5) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 65dd4ebfbffd7b740a91055a7bf4353f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,200 @@
|
||||
// Copyright (C) 2014-2024 Gleechi Technology AB. All rights reserved.
|
||||
|
||||
//#define VG_USE_OCULUS_CONTROLLER // Please read below instructions and requirements before activating.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VirtualGrasp.Controllers
|
||||
{
|
||||
/**
|
||||
* This is an external controller class that supports the Oculus Finger Tracking controller as an external controller.
|
||||
* Please refer to https://docs.virtualgrasp.com/controllers.html for the definition of an external controller for VG.
|
||||
*
|
||||
* The following requirements have to be met to be able to enable the #define VG_USE_OCULUS_CONTROLLER above and use the controller:
|
||||
* - You have the Oculus SDK (https://www.oculus.com/setup/) installed on your computer.
|
||||
* - You have the Oculus Integration plugin from https://developer.oculus.com/downloads/package/unity-integration/ imported into your Unity project.
|
||||
* - You have the same Oculus Integration plugin version as the one on your headset AND Oculus App.
|
||||
* - You use Oculus through "Legacy OVR" (Oculus -> Tools -> OVR Utilitites Plugin -> Set OVR to Legacy LibOVR)
|
||||
* - You have setup the AndroidManifest.xml properly, i.e. they need to include
|
||||
* <uses-permission android:name="com.oculus.permission.HAND_TRACKING" />
|
||||
* <uses-feature android:name="oculus.software.handtracking" android:required="false" />
|
||||
*/
|
||||
|
||||
[LIBVIRTUALGRASP_UNITY_SCRIPT]
|
||||
[HelpURL("https://docs.virtualgrasp.com/unity_vg_ec_oculus." + VG_Version.__VG_VERSION__ + ".html")]
|
||||
public class VG_EC_Oculus : VG_ExternalController
|
||||
{
|
||||
#if VG_USE_OCULUS_CONTROLLER
|
||||
private OVRPlugin.Skeleton m_skeleton = new OVRPlugin.Skeleton();
|
||||
private OVRPlugin.HandState m_currentState = new OVRPlugin.HandState();
|
||||
#endif
|
||||
|
||||
[Serializable]
|
||||
public class HandMapping : VG_BoneMapping
|
||||
{
|
||||
public override void Initialize(int avatarID, VG_HandSide side)
|
||||
{
|
||||
base.Initialize(avatarID, side);
|
||||
m_BoneToTransform = new Dictionary<int, Transform>() {
|
||||
#if VG_USE_OCULUS_CONTROLLER
|
||||
{ (int)OVRPlugin.BoneId.Hand_WristRoot, Hand_WristRoot },
|
||||
{ (int)OVRPlugin.BoneId.Hand_ForearmStub, null }, // this is a child of wrist, but towards the arm
|
||||
{ (int)OVRPlugin.BoneId.Hand_Thumb0, null },
|
||||
{ (int)OVRPlugin.BoneId.Hand_Thumb1, Hand_Thumb1 },
|
||||
{ (int)OVRPlugin.BoneId.Hand_Thumb2, Hand_Thumb2 },
|
||||
{ (int)OVRPlugin.BoneId.Hand_Thumb3, Hand_Thumb3 },
|
||||
{ (int)OVRPlugin.BoneId.Hand_Index1, Hand_Index1 },
|
||||
{ (int)OVRPlugin.BoneId.Hand_Index2, Hand_Index2 },
|
||||
{ (int)OVRPlugin.BoneId.Hand_Index3, Hand_Index3 },
|
||||
{ (int)OVRPlugin.BoneId.Hand_Middle1, Hand_Middle1 },
|
||||
{ (int)OVRPlugin.BoneId.Hand_Middle2, Hand_Middle2 },
|
||||
{ (int)OVRPlugin.BoneId.Hand_Middle3, Hand_Middle3 },
|
||||
{ (int)OVRPlugin.BoneId.Hand_Ring1, Hand_Ring1 },
|
||||
{ (int)OVRPlugin.BoneId.Hand_Ring2, Hand_Ring2 },
|
||||
{ (int)OVRPlugin.BoneId.Hand_Ring3, Hand_Ring3 },
|
||||
{ (int)OVRPlugin.BoneId.Hand_Pinky0, null },
|
||||
{ (int)OVRPlugin.BoneId.Hand_Pinky1, Hand_Pinky1 },
|
||||
{ (int)OVRPlugin.BoneId.Hand_Pinky2, Hand_Pinky2 },
|
||||
{ (int)OVRPlugin.BoneId.Hand_Pinky3, Hand_Pinky3 },
|
||||
{ (int)OVRPlugin.BoneId.Hand_ThumbTip, null },
|
||||
{ (int)OVRPlugin.BoneId.Hand_IndexTip, null },
|
||||
{ (int)OVRPlugin.BoneId.Hand_MiddleTip, null },
|
||||
{ (int)OVRPlugin.BoneId.Hand_RingTip, null },
|
||||
{ (int)OVRPlugin.BoneId.Hand_PinkyTip, null }
|
||||
#endif
|
||||
};
|
||||
|
||||
m_BoneToParent = new Dictionary<int, int>();
|
||||
#if VG_USE_OCULUS_CONTROLLER
|
||||
m_BoneToParent[(int)OVRPlugin.BoneId.Hand_ForearmStub] = (int)OVRPlugin.BoneId.Hand_WristRoot;
|
||||
m_BoneToParent[(int)OVRPlugin.BoneId.Hand_Thumb0] = (int)OVRPlugin.BoneId.Hand_WristRoot;
|
||||
m_BoneToParent[(int)OVRPlugin.BoneId.Hand_Thumb1] = (int)OVRPlugin.BoneId.Hand_Thumb0;
|
||||
m_BoneToParent[(int)OVRPlugin.BoneId.Hand_Thumb2] = (int)OVRPlugin.BoneId.Hand_Thumb1;
|
||||
m_BoneToParent[(int)OVRPlugin.BoneId.Hand_Thumb3] = (int)OVRPlugin.BoneId.Hand_Thumb2;
|
||||
m_BoneToParent[(int)OVRPlugin.BoneId.Hand_ThumbTip] = (int)OVRPlugin.BoneId.Hand_Thumb3;
|
||||
m_BoneToParent[(int)OVRPlugin.BoneId.Hand_Index1] = (int)OVRPlugin.BoneId.Hand_WristRoot;
|
||||
m_BoneToParent[(int)OVRPlugin.BoneId.Hand_Index2] = (int)OVRPlugin.BoneId.Hand_Index1;
|
||||
m_BoneToParent[(int)OVRPlugin.BoneId.Hand_Index3] = (int)OVRPlugin.BoneId.Hand_Index2;
|
||||
m_BoneToParent[(int)OVRPlugin.BoneId.Hand_IndexTip] = (int)OVRPlugin.BoneId.Hand_Index3;
|
||||
m_BoneToParent[(int)OVRPlugin.BoneId.Hand_Middle1] = (int)OVRPlugin.BoneId.Hand_WristRoot;
|
||||
m_BoneToParent[(int)OVRPlugin.BoneId.Hand_Middle2] = (int)OVRPlugin.BoneId.Hand_Middle1;
|
||||
m_BoneToParent[(int)OVRPlugin.BoneId.Hand_Middle3] = (int)OVRPlugin.BoneId.Hand_Middle2;
|
||||
m_BoneToParent[(int)OVRPlugin.BoneId.Hand_MiddleTip] = (int)OVRPlugin.BoneId.Hand_Middle3;
|
||||
m_BoneToParent[(int)OVRPlugin.BoneId.Hand_Ring1] = (int)OVRPlugin.BoneId.Hand_WristRoot;
|
||||
m_BoneToParent[(int)OVRPlugin.BoneId.Hand_Ring2] = (int)OVRPlugin.BoneId.Hand_Ring1;
|
||||
m_BoneToParent[(int)OVRPlugin.BoneId.Hand_Ring3] = (int)OVRPlugin.BoneId.Hand_Ring2;
|
||||
m_BoneToParent[(int)OVRPlugin.BoneId.Hand_RingTip] = (int)OVRPlugin.BoneId.Hand_Ring3;
|
||||
m_BoneToParent[(int)OVRPlugin.BoneId.Hand_Pinky0] = (int)OVRPlugin.BoneId.Hand_WristRoot;
|
||||
m_BoneToParent[(int)OVRPlugin.BoneId.Hand_Pinky1] = (int)OVRPlugin.BoneId.Hand_Pinky0;
|
||||
m_BoneToParent[(int)OVRPlugin.BoneId.Hand_Pinky2] = (int)OVRPlugin.BoneId.Hand_Pinky1;
|
||||
m_BoneToParent[(int)OVRPlugin.BoneId.Hand_Pinky3] = (int)OVRPlugin.BoneId.Hand_Pinky2;
|
||||
m_BoneToParent[(int)OVRPlugin.BoneId.Hand_PinkyTip] = (int)OVRPlugin.BoneId.Hand_Pinky3;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public VG_EC_Oculus(int avatarID, VG_HandSide side, Transform origin)
|
||||
{
|
||||
m_avatarID = avatarID;
|
||||
m_handType = side;
|
||||
m_origin = origin;
|
||||
m_enablingDefine = "VG_USE_OCULUS_CONTROLLER";
|
||||
|
||||
#if VG_USE_OCULUS_CONTROLLER
|
||||
m_enabled = true;
|
||||
#else
|
||||
PrintNotEnabledError();
|
||||
m_enabled = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public new void Initialize()
|
||||
{
|
||||
#if VG_USE_OCULUS_CONTROLLER
|
||||
m_mapping = new HandMapping();
|
||||
|
||||
if (OVRPlugin.GetSkeleton(
|
||||
(m_handType == VG_HandSide.LEFT) ? OVRPlugin.SkeletonType.HandLeft :
|
||||
(m_handType == VG_HandSide.RIGHT) ? OVRPlugin.SkeletonType.HandRight : OVRPlugin.SkeletonType.None,
|
||||
out m_skeleton))
|
||||
{
|
||||
base.Initialize();
|
||||
m_initialized = true;
|
||||
}
|
||||
else m_initialized = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public override float GetGrabStrength()
|
||||
{
|
||||
#if VG_USE_OCULUS_CONTROLLER
|
||||
if (m_initialized && m_currentState.Status.HasFlag(OVRPlugin.HandStatus.HandTracked))
|
||||
return -1.0f; // let VG decide from full DOF
|
||||
//return (m_currentState.PinchStrength[0] + m_currentState.PinchStrength[1] + m_currentState.PinchStrength[2]) / 3.0f;
|
||||
#endif
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
private bool IsTracking()
|
||||
{
|
||||
#if VG_USE_OCULUS_CONTROLLER
|
||||
return OVRPlugin.GetHandState(OVRPlugin.Step.Render, m_handType == VG_HandSide.LEFT ? OVRPlugin.Hand.HandLeft : OVRPlugin.Hand.HandRight, ref m_currentState)
|
||||
&& m_currentState.Status.HasFlag(OVRPlugin.HandStatus.HandTracked);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public override bool Compute()
|
||||
{
|
||||
if (!m_enabled) return false;
|
||||
if (!m_initialized) { Initialize(); return false; }
|
||||
|
||||
#if VG_USE_OCULUS_CONTROLLER
|
||||
if (!IsTracking()) return false;
|
||||
|
||||
for (int boneId = 0; boneId < GetNumBones(); ++boneId)
|
||||
{
|
||||
if (boneId == 0)
|
||||
{
|
||||
SetPose(boneId, Matrix4x4.TRS(
|
||||
m_currentState.RootPose.Position.FromFlippedZVector3f(),
|
||||
m_currentState.RootPose.Orientation.FromFlippedZQuatf(),
|
||||
Vector3.one));
|
||||
}
|
||||
else SetPose(boneId, m_poses[m_mapping.GetParent(boneId)] *
|
||||
Matrix4x4.TRS(
|
||||
m_skeleton.Bones[boneId].Pose.Position.FromFlippedZVector3f(),
|
||||
m_currentState.BoneRotations[boneId].FromFlippedZQuatf(),
|
||||
Vector3.one));
|
||||
}
|
||||
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public override Color GetConfidence()
|
||||
{
|
||||
#if VG_USE_OCULUS_CONTROLLER
|
||||
if (!m_initialized) return Color.black;
|
||||
|
||||
switch (m_currentState.HandConfidence)
|
||||
{
|
||||
case OVRPlugin.TrackingConfidence.High:
|
||||
return Color.green;
|
||||
case OVRPlugin.TrackingConfidence.Low:
|
||||
return Color.red;
|
||||
}
|
||||
#endif
|
||||
return Color.black;
|
||||
}
|
||||
|
||||
public override void HapticPulse(VG_HandStatus hand, float amplitude = 0.5F, float duration = 0.015F, int finger = 5)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a6adfc75fbb3e8944a213eb006c326c6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,90 @@
|
||||
// Copyright (C) 2014-2024 Gleechi Technology AB. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VirtualGrasp.Controllers
|
||||
{
|
||||
/**
|
||||
* This is an external controller class that supports a Script/GUI controller as an external controller.
|
||||
* Please refer to https://docs.virtualgrasp.com/controllers.html for the definition of an external controller for VG.
|
||||
*/
|
||||
[LIBVIRTUALGRASP_UNITY_SCRIPT]
|
||||
[HelpURL("https://docs.virtualgrasp.com/unity_vg_ec_script." + VG_Version.__VG_VERSION__ + ".html")]
|
||||
public class VG_EC_Script : VG_ExternalController
|
||||
{
|
||||
private Transform m_wrist = null;
|
||||
private float m_grabStrength = 0.0f;
|
||||
|
||||
/**
|
||||
* The wrist transform strength can be set and received from another Script/GUI.
|
||||
* Changes in the wrist transform will affect the controller through Compute().
|
||||
*/
|
||||
public Transform WristTransform
|
||||
{
|
||||
get { return m_wrist; }
|
||||
set { m_wrist = value; }
|
||||
}
|
||||
|
||||
/**
|
||||
* The grab strength can be set and received from another Script/GUI.
|
||||
* Changes in the grab strength will affect the controller through GetGrabStrength().
|
||||
*/
|
||||
public float GrabStrength
|
||||
{
|
||||
get { return m_grabStrength; }
|
||||
set { m_grabStrength = Mathf.Clamp01(value); }
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class HandMapping : VG_BoneMapping
|
||||
{
|
||||
public override void Initialize(int avatarID, VG_HandSide side)
|
||||
{
|
||||
base.Initialize(avatarID, side);
|
||||
m_BoneToTransform = new Dictionary<int, Transform>()
|
||||
{
|
||||
{ 0, Hand_WristRoot }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public VG_EC_Script(int avatarID, VG_HandSide side, Transform origin)
|
||||
{
|
||||
m_avatarID = avatarID;
|
||||
m_handType = side;
|
||||
m_origin = origin;
|
||||
m_enabled = true;
|
||||
Initialize();
|
||||
}
|
||||
|
||||
public new void Initialize()
|
||||
{
|
||||
m_mapping = new HandMapping();
|
||||
base.Initialize();
|
||||
}
|
||||
|
||||
public override bool Compute()
|
||||
{
|
||||
if (!m_enabled || m_wrist == null) return false;
|
||||
SetPose(0, Matrix4x4.TRS(m_wrist.position, m_wrist.rotation, Vector3.one));
|
||||
return true;
|
||||
}
|
||||
|
||||
public override float GetGrabStrength()
|
||||
{
|
||||
return m_grabStrength;
|
||||
}
|
||||
|
||||
public override Color GetConfidence()
|
||||
{
|
||||
return Color.yellow;
|
||||
}
|
||||
|
||||
public override void HapticPulse(VG_HandStatus hand, float amplitude = 0.5F, float duration = 0.015F, int finger = 5)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7187da2e8079f68459c7737612322b4e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,214 @@
|
||||
// Copyright (C) 2014-2024 Gleechi Technology AB. All rights reserved.
|
||||
|
||||
//#define VG_USE_STEAMVR_CONTROLLER
|
||||
|
||||
#if UNITY_ANDROID && !UNITY_EDITOR // SteamVR is not supported on Android
|
||||
#undef VG_USE_STEAMVR_CONTROLLER
|
||||
#endif
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
#if VG_USE_STEAMVR_CONTROLLER
|
||||
using Valve.VR;
|
||||
#endif
|
||||
|
||||
namespace VirtualGrasp.Controllers
|
||||
{
|
||||
/**
|
||||
* This is an external controller class that supports the Steam Knuckles controller as an external controller.
|
||||
* Please refer to https://docs.virtualgrasp.com/controllers.html for the definition of an external controller for VG.
|
||||
*
|
||||
* The following requirements have to be met to be able to enable the #define VG_USE_STEAMVR_CONTROLLER above and use the controller:
|
||||
* - You have the SteamVR Unity plugin from https://assetstore.unity.com/packages/tools/integration/steamvr-plugin-32647 imported into your Unity project.
|
||||
* - You have Steam and the corresponding SteamVR SDK (https://store.steampowered.com/app/250820/SteamVR/) installed on your computer.
|
||||
* - You have OpenVR Loader selected in Unity XR Management Project Settings.
|
||||
*/
|
||||
|
||||
[LIBVIRTUALGRASP_UNITY_SCRIPT]
|
||||
[HelpURL("https://docs.virtualgrasp.com/unity_vg_ec_steam." + VG_Version.__VG_VERSION__ + ".html")]
|
||||
|
||||
public class VG_EC_Steam : VG_ExternalController
|
||||
{
|
||||
#if VG_USE_STEAMVR_CONTROLLER
|
||||
private SteamVR_Action_Skeleton m_skeleton = null;
|
||||
private bool m_skeletonActive = false;
|
||||
#endif
|
||||
|
||||
[Serializable]
|
||||
public class SteamHandMapping : VG_BoneMapping
|
||||
{
|
||||
public override void Initialize(int avatarID, VG_HandSide side)
|
||||
{
|
||||
base.Initialize(avatarID, side);
|
||||
m_BoneToTransform = new Dictionary<int, Transform>()
|
||||
{
|
||||
#if VG_USE_STEAMVR_CONTROLLER
|
||||
{ SteamVR_Skeleton_JointIndexes.root, null },
|
||||
{ SteamVR_Skeleton_JointIndexes.wrist, Hand_WristRoot },
|
||||
{ SteamVR_Skeleton_JointIndexes.thumbProximal, Hand_Thumb1 },
|
||||
{ SteamVR_Skeleton_JointIndexes.thumbMiddle, Hand_Thumb2 },
|
||||
{ SteamVR_Skeleton_JointIndexes.thumbDistal, Hand_Thumb3 },
|
||||
{ SteamVR_Skeleton_JointIndexes.thumbTip, null },
|
||||
{ SteamVR_Skeleton_JointIndexes.indexMetacarpal, null },
|
||||
{ SteamVR_Skeleton_JointIndexes.indexProximal, Hand_Index1 },
|
||||
{ SteamVR_Skeleton_JointIndexes.indexMiddle, Hand_Index2 },
|
||||
{ SteamVR_Skeleton_JointIndexes.indexDistal, Hand_Index3 },
|
||||
{ SteamVR_Skeleton_JointIndexes.indexTip, null },
|
||||
{ SteamVR_Skeleton_JointIndexes.middleMetacarpal, null },
|
||||
{ SteamVR_Skeleton_JointIndexes.middleProximal, Hand_Middle1 },
|
||||
{ SteamVR_Skeleton_JointIndexes.middleMiddle, Hand_Middle2 },
|
||||
{ SteamVR_Skeleton_JointIndexes.middleDistal, Hand_Middle3 },
|
||||
{ SteamVR_Skeleton_JointIndexes.middleTip, null },
|
||||
{ SteamVR_Skeleton_JointIndexes.ringMetacarpal, null },
|
||||
{ SteamVR_Skeleton_JointIndexes.ringProximal, Hand_Ring1 },
|
||||
{ SteamVR_Skeleton_JointIndexes.ringMiddle, Hand_Ring2 },
|
||||
{ SteamVR_Skeleton_JointIndexes.ringDistal, Hand_Ring3 },
|
||||
{ SteamVR_Skeleton_JointIndexes.ringTip, null },
|
||||
{ SteamVR_Skeleton_JointIndexes.pinkyMetacarpal, null },
|
||||
{ SteamVR_Skeleton_JointIndexes.pinkyProximal, Hand_Pinky1 },
|
||||
{ SteamVR_Skeleton_JointIndexes.pinkyMiddle, Hand_Pinky2 },
|
||||
{ SteamVR_Skeleton_JointIndexes.pinkyDistal, Hand_Pinky3 },
|
||||
{ SteamVR_Skeleton_JointIndexes.pinkyTip, null }
|
||||
#endif
|
||||
};
|
||||
|
||||
m_BoneToParent = new Dictionary<int, int>()
|
||||
{
|
||||
};
|
||||
#if VG_USE_STEAMVR_CONTROLLER
|
||||
m_BoneToParent[SteamVR_Skeleton_JointIndexes.wrist] = SteamVR_Skeleton_JointIndexes.root;
|
||||
m_BoneToParent[SteamVR_Skeleton_JointIndexes.thumbProximal] = SteamVR_Skeleton_JointIndexes.wrist;
|
||||
m_BoneToParent[SteamVR_Skeleton_JointIndexes.thumbMiddle] = SteamVR_Skeleton_JointIndexes.thumbProximal;
|
||||
m_BoneToParent[SteamVR_Skeleton_JointIndexes.thumbDistal] = SteamVR_Skeleton_JointIndexes.thumbMiddle;
|
||||
m_BoneToParent[SteamVR_Skeleton_JointIndexes.thumbTip] = SteamVR_Skeleton_JointIndexes.thumbDistal;
|
||||
m_BoneToParent[SteamVR_Skeleton_JointIndexes.indexMetacarpal] = SteamVR_Skeleton_JointIndexes.wrist;
|
||||
m_BoneToParent[SteamVR_Skeleton_JointIndexes.indexProximal] = SteamVR_Skeleton_JointIndexes.indexMetacarpal;
|
||||
m_BoneToParent[SteamVR_Skeleton_JointIndexes.indexMiddle] = SteamVR_Skeleton_JointIndexes.indexProximal;
|
||||
m_BoneToParent[SteamVR_Skeleton_JointIndexes.indexDistal] = SteamVR_Skeleton_JointIndexes.indexMiddle;
|
||||
m_BoneToParent[SteamVR_Skeleton_JointIndexes.indexTip] = SteamVR_Skeleton_JointIndexes.indexDistal;
|
||||
m_BoneToParent[SteamVR_Skeleton_JointIndexes.middleMetacarpal] = SteamVR_Skeleton_JointIndexes.wrist;
|
||||
m_BoneToParent[SteamVR_Skeleton_JointIndexes.middleProximal] = SteamVR_Skeleton_JointIndexes.middleMetacarpal;
|
||||
m_BoneToParent[SteamVR_Skeleton_JointIndexes.middleMiddle] = SteamVR_Skeleton_JointIndexes.middleProximal;
|
||||
m_BoneToParent[SteamVR_Skeleton_JointIndexes.middleDistal] = SteamVR_Skeleton_JointIndexes.middleMiddle;
|
||||
m_BoneToParent[SteamVR_Skeleton_JointIndexes.middleTip] = SteamVR_Skeleton_JointIndexes.middleDistal;
|
||||
m_BoneToParent[SteamVR_Skeleton_JointIndexes.ringMetacarpal] = SteamVR_Skeleton_JointIndexes.wrist;
|
||||
m_BoneToParent[SteamVR_Skeleton_JointIndexes.ringProximal] = SteamVR_Skeleton_JointIndexes.ringMetacarpal;
|
||||
m_BoneToParent[SteamVR_Skeleton_JointIndexes.ringMiddle] = SteamVR_Skeleton_JointIndexes.ringProximal;
|
||||
m_BoneToParent[SteamVR_Skeleton_JointIndexes.ringDistal] = SteamVR_Skeleton_JointIndexes.ringMiddle;
|
||||
m_BoneToParent[SteamVR_Skeleton_JointIndexes.ringTip] = SteamVR_Skeleton_JointIndexes.ringDistal;
|
||||
m_BoneToParent[SteamVR_Skeleton_JointIndexes.pinkyMetacarpal] = SteamVR_Skeleton_JointIndexes.wrist;
|
||||
m_BoneToParent[SteamVR_Skeleton_JointIndexes.pinkyProximal] = SteamVR_Skeleton_JointIndexes.pinkyMetacarpal;
|
||||
m_BoneToParent[SteamVR_Skeleton_JointIndexes.pinkyMiddle] = SteamVR_Skeleton_JointIndexes.pinkyProximal;
|
||||
m_BoneToParent[SteamVR_Skeleton_JointIndexes.pinkyDistal] = SteamVR_Skeleton_JointIndexes.pinkyMiddle;
|
||||
m_BoneToParent[SteamVR_Skeleton_JointIndexes.pinkyTip] = SteamVR_Skeleton_JointIndexes.pinkyDistal;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public VG_EC_Steam(int avatarID, VG_HandSide side, Transform origin)
|
||||
{
|
||||
m_avatarID = avatarID;
|
||||
m_handType = side;
|
||||
m_origin = origin;
|
||||
m_enablingDefine = "VG_USE_STEAMVR_CONTROLLER";
|
||||
|
||||
#if VG_USE_STEAMVR_CONTROLLER
|
||||
m_enabled = true;
|
||||
#else
|
||||
PrintNotEnabledError();
|
||||
m_enabled = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public new void Initialize()
|
||||
{
|
||||
#if VG_USE_STEAMVR_CONTROLLER
|
||||
m_mapping = new SteamHandMapping();
|
||||
base.Initialize();
|
||||
|
||||
SteamVR.Initialize();
|
||||
m_skeleton = SteamVR_Input.GetAction<SteamVR_Action_Skeleton>(m_handType == VG_HandSide.LEFT ? "SkeletonLeftHand" : "SkeletonRightHand");
|
||||
m_skeleton.SetRangeOfMotion(EVRSkeletalMotionRange.WithoutController);
|
||||
//m_skeleton.SetSkeletalTransformSpace(Valve.VR.EVRSkeletalTransformSpace.Model);
|
||||
|
||||
m_initialized = true;
|
||||
if (GetNumBones() == 0)
|
||||
{
|
||||
Debug.LogError("Could not find bone skeleton root (boneCount=" + GetNumBones() + "; skeleton active=" + m_skeletonActive + ").");
|
||||
m_initialized = false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public override float GetGrabStrength()
|
||||
{
|
||||
#if VG_USE_STEAMVR_CONTROLLER
|
||||
if (m_skeleton == null) return 0.0f;
|
||||
return (m_skeleton.fingerCurls[0] + m_skeleton.fingerCurls[1] + m_skeleton.fingerCurls[2]) / 3.0f;
|
||||
#else
|
||||
return 0.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
public override bool Compute()
|
||||
{
|
||||
|
||||
#if VG_USE_STEAMVR_CONTROLLER
|
||||
if (!m_enabled) return false;
|
||||
if (!m_initialized) { Initialize(); return false; }
|
||||
|
||||
ETrackingResult res = m_skeleton.GetTrackingResult(m_handType == VG_HandSide.LEFT ? SteamVR_Input_Sources.LeftHand : SteamVR_Input_Sources.RightHand);
|
||||
if (res == 0) return false;
|
||||
m_skeletonActive = m_skeleton.GetActive();
|
||||
|
||||
for (int boneId = 0; boneId < (m_skeletonActive ? GetNumBones() : 2); ++boneId)
|
||||
{
|
||||
if (boneId == 0) // root
|
||||
{
|
||||
SetPose(boneId, Matrix4x4.identity);
|
||||
}
|
||||
else if (boneId == 1) // wrist
|
||||
{
|
||||
SetPose(boneId, Matrix4x4.TRS(m_skeleton.GetLocalPosition(), m_skeleton.GetLocalRotation(), Vector3.one));
|
||||
}
|
||||
else
|
||||
{
|
||||
SetPose(boneId, m_poses[m_mapping.GetParent(boneId)] * // When transform space is local / Parent
|
||||
Matrix4x4.TRS(m_skeleton.bonePositions[boneId], m_skeleton.boneRotations[boneId], Vector3.one));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void HapticPulse(VG_HandStatus hand, float amplitude = 0.5F, float duration = 0.01F, int finger = 5)
|
||||
{
|
||||
#if VG_USE_STEAMVR_CONTROLLER
|
||||
SteamVR_Actions.default_Haptic[hand.m_side == VG_HandSide.LEFT ? SteamVR_Input_Sources.LeftHand : SteamVR_Input_Sources.RightHand].Execute(0, duration, 10, amplitude);
|
||||
#endif
|
||||
}
|
||||
|
||||
public override Color GetConfidence()
|
||||
{
|
||||
#if VG_USE_STEAMVR_CONTROLLER
|
||||
EVRSkeletalTrackingLevel skeletalTrackingLevel = EVRSkeletalTrackingLevel.VRSkeletalTracking_Estimated;
|
||||
if (m_skeleton == null || OpenVR.Input.GetSkeletalTrackingLevel(m_skeleton.handle, ref skeletalTrackingLevel) != EVRInputError.None)
|
||||
return Color.black;
|
||||
|
||||
switch (skeletalTrackingLevel)
|
||||
{
|
||||
case EVRSkeletalTrackingLevel.VRSkeletalTracking_Full:
|
||||
return Color.green;
|
||||
case EVRSkeletalTrackingLevel.VRSkeletalTracking_Partial:
|
||||
return Color.yellow;
|
||||
case EVRSkeletalTrackingLevel.VRSkeletalTracking_Estimated:
|
||||
return Color.red;
|
||||
}
|
||||
#endif
|
||||
return Color.black;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 35987637c5dd86e4082679c5c048d825
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,107 @@
|
||||
// Copyright (C) 2014-2024 Gleechi Technology AB. All rights reserved.
|
||||
|
||||
//#define VG_USE_UNITYXR_CONTROLLER
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR;
|
||||
|
||||
namespace VirtualGrasp.Controllers
|
||||
{
|
||||
/**
|
||||
* This is an external controller class that supports the UnityXR controller (such as provided by Pico or Oculus integrations) as an external controller.
|
||||
* Please refer to https://docs.virtualgrasp.com/controllers.html for the definition of an external controller for VG.
|
||||
*
|
||||
* The following requirements have to be met to be able to enable the #define VG_USE_UNITYXR_CONTROLLER above and use the controller:
|
||||
* - You have the Unity XR Management package installed into your Unity project.
|
||||
*/
|
||||
[LIBVIRTUALGRASP_UNITY_SCRIPT]
|
||||
[HelpURL("https://docs.virtualgrasp.com/unity_vg_ec_unityxr." + VG_Version.__VG_VERSION__ + ".html")]
|
||||
public class VG_EC_UnityXR : VG_ExternalController
|
||||
{
|
||||
private InputDevice m_device;
|
||||
|
||||
[Serializable]
|
||||
public class HandMapping : VG_BoneMapping
|
||||
{
|
||||
public override void Initialize(int avatarID, VG_HandSide side)
|
||||
{
|
||||
base.Initialize(avatarID, side);
|
||||
m_BoneToTransform = new Dictionary<int, Transform>()
|
||||
{
|
||||
{ 0, Hand_WristRoot }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public VG_EC_UnityXR(int avatarID, VG_HandSide side, Transform origin)
|
||||
{
|
||||
m_avatarID = avatarID;
|
||||
m_handType = side;
|
||||
m_origin = origin;
|
||||
m_enabled = true;
|
||||
Initialize();
|
||||
}
|
||||
|
||||
public new void Initialize()
|
||||
{
|
||||
m_mapping = new HandMapping();
|
||||
base.Initialize();
|
||||
m_initialized = true;
|
||||
}
|
||||
|
||||
public override bool Compute()
|
||||
{
|
||||
if (!m_enabled) return false;
|
||||
if (!m_initialized) { Initialize(); return false; }
|
||||
|
||||
if (!m_device.isValid)
|
||||
{
|
||||
m_device = InputDevices.GetDeviceAtXRNode(m_handType == VG_HandSide.LEFT ? XRNode.LeftHand : XRNode.RightHand);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_device.TryGetFeatureValue(CommonUsages.devicePosition, out Vector3 p) &&
|
||||
m_device.TryGetFeatureValue(CommonUsages.deviceRotation, out Quaternion q))
|
||||
{
|
||||
SetPose(0, Matrix4x4.TRS(p, q, Vector3.one));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override float GetGrabStrength()
|
||||
{
|
||||
if (!m_initialized || !m_device.isValid) return 0.0f;
|
||||
float trigger = 0.0f;
|
||||
switch (VG_Controller.GetGraspButton())
|
||||
{
|
||||
case VG_VrButton.TRIGGER:
|
||||
m_device.TryGetFeatureValue(CommonUsages.trigger, out trigger); break;
|
||||
case VG_VrButton.GRIP:
|
||||
m_device.TryGetFeatureValue(CommonUsages.grip, out trigger); break;
|
||||
case VG_VrButton.GRIP_OR_TRIGGER:
|
||||
m_device.TryGetFeatureValue(CommonUsages.trigger, out trigger);
|
||||
m_device.TryGetFeatureValue(CommonUsages.grip, out float trigger2);
|
||||
trigger = Mathf.Max(trigger, trigger2);
|
||||
break;
|
||||
}
|
||||
return trigger;
|
||||
}
|
||||
|
||||
public override Color GetConfidence()
|
||||
{
|
||||
return Color.yellow;
|
||||
}
|
||||
|
||||
public override void HapticPulse(VG_HandStatus hand, float amplitude = 0.5F, float duration = 0.015F, int finger = 5)
|
||||
{
|
||||
if (!m_initialized || !m_device.isValid) return;
|
||||
HapticCapabilities capabilities;
|
||||
if (m_device.TryGetHapticCapabilities(out capabilities) && capabilities.supportsImpulse)
|
||||
m_device.SendHapticImpulse(0, amplitude, duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 482d610d95177f04a9bb38d20d6539c8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,193 @@
|
||||
// Copyright (C) 2014-2024 Gleechi Technology AB. All rights reserved.
|
||||
|
||||
//#define VG_USE_XRHANDS_CONTROLLER
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
#if VG_USE_XRHANDS_CONTROLLER
|
||||
using UnityEngine.XR.Hands;
|
||||
using UnityEngine.XR.Management;
|
||||
#endif
|
||||
|
||||
namespace VirtualGrasp.Controllers
|
||||
{
|
||||
/**
|
||||
* This is an external controller class that supports the Unity XRHands controller as an external controller.
|
||||
* Please refer to https://docs.virtualgrasp.com/controllers.html for the definition of an external controller for VG.
|
||||
*
|
||||
* The following requirements have to be met to be able to enable the #define VG_USE_XRHANDS_CONTROLLER above and use the controller:
|
||||
* - You have followed the installation instructions of the Unity XRHands package,
|
||||
* from https://docs.unity3d.com/Packages/com.unity.xr.hands@1.1/manual/
|
||||
*/
|
||||
[LIBVIRTUALGRASP_UNITY_SCRIPT]
|
||||
[HelpURL("https://docs.virtualgrasp.com/unity_vg_ec_unityxrhands." + VG_Version.__VG_VERSION__ + ".html")]
|
||||
|
||||
public class VG_EC_UnityXRHands : VG_ExternalController
|
||||
{
|
||||
#if VG_USE_XRHANDS_CONTROLLER
|
||||
XRHandSubsystem m_Subsystem = null;
|
||||
XRHand m_hand;
|
||||
XRHandSubsystem.UpdateSuccessFlags m_updateSuccessFlags = XRHandSubsystem.UpdateSuccessFlags.None;
|
||||
#endif
|
||||
|
||||
[Serializable]
|
||||
public class OpenXRHandMapping : VG_BoneMapping
|
||||
{
|
||||
public override void Initialize(int avatarID, VG_HandSide side)
|
||||
{
|
||||
base.Initialize(avatarID, side);
|
||||
m_BoneToTransform = new Dictionary<int, Transform>()
|
||||
{
|
||||
#if VG_USE_XRHANDS_CONTROLLER
|
||||
{ XRHandJointID.Wrist.ToIndex(), Hand_WristRoot },
|
||||
{ XRHandJointID.Palm.ToIndex(), null },
|
||||
{ XRHandJointID.ThumbMetacarpal.ToIndex(), Hand_Thumb1 },
|
||||
{ XRHandJointID.ThumbProximal.ToIndex(), Hand_Thumb2 },
|
||||
{ XRHandJointID.ThumbDistal.ToIndex(), Hand_Thumb3 },
|
||||
{ XRHandJointID.ThumbTip.ToIndex(), null },
|
||||
{ XRHandJointID.IndexMetacarpal.ToIndex(), null },
|
||||
{ XRHandJointID.IndexProximal.ToIndex(), Hand_Index1 },
|
||||
{ XRHandJointID.IndexIntermediate.ToIndex(), Hand_Index2 },
|
||||
{ XRHandJointID.IndexDistal.ToIndex(), Hand_Index3 },
|
||||
{ XRHandJointID.IndexTip.ToIndex(), null },
|
||||
{ XRHandJointID.MiddleMetacarpal.ToIndex(), null },
|
||||
{ XRHandJointID.MiddleProximal.ToIndex(), Hand_Middle1 },
|
||||
{ XRHandJointID.MiddleIntermediate.ToIndex(), Hand_Middle2 },
|
||||
{ XRHandJointID.MiddleDistal.ToIndex(), Hand_Middle3 },
|
||||
{ XRHandJointID.MiddleTip.ToIndex(), null },
|
||||
{ XRHandJointID.RingMetacarpal.ToIndex(), null },
|
||||
{ XRHandJointID.RingProximal.ToIndex(), Hand_Ring1 },
|
||||
{ XRHandJointID.RingIntermediate.ToIndex(), Hand_Ring2 },
|
||||
{ XRHandJointID.RingDistal.ToIndex(), Hand_Ring3 },
|
||||
{ XRHandJointID.RingTip.ToIndex(), null },
|
||||
{ XRHandJointID.LittleMetacarpal.ToIndex(), null },
|
||||
{ XRHandJointID.LittleProximal.ToIndex(), Hand_Pinky1 },
|
||||
{ XRHandJointID.LittleIntermediate.ToIndex(), Hand_Pinky2 },
|
||||
{ XRHandJointID.LittleDistal.ToIndex(), Hand_Pinky3 },
|
||||
{ XRHandJointID.LittleTip.ToIndex(), null }
|
||||
#endif
|
||||
};
|
||||
|
||||
m_BoneToParent = new Dictionary<int, int>()
|
||||
{
|
||||
};
|
||||
|
||||
#if VG_USE_XRHANDS_CONTROLLER
|
||||
m_BoneToParent[XRHandJointID.Palm.ToIndex()] = XRHandJointID.Wrist.ToIndex();
|
||||
m_BoneToParent[XRHandJointID.ThumbMetacarpal.ToIndex()] = XRHandJointID.Wrist.ToIndex();
|
||||
m_BoneToParent[XRHandJointID.ThumbProximal.ToIndex()] = XRHandJointID.ThumbMetacarpal.ToIndex();
|
||||
m_BoneToParent[XRHandJointID.ThumbDistal.ToIndex()] = XRHandJointID.ThumbProximal.ToIndex();
|
||||
m_BoneToParent[XRHandJointID.ThumbTip.ToIndex()] = XRHandJointID.ThumbDistal.ToIndex();
|
||||
m_BoneToParent[XRHandJointID.IndexMetacarpal.ToIndex()] = XRHandJointID.Wrist.ToIndex();
|
||||
m_BoneToParent[XRHandJointID.IndexProximal.ToIndex()] = XRHandJointID.IndexMetacarpal.ToIndex();
|
||||
m_BoneToParent[XRHandJointID.IndexIntermediate.ToIndex()] = XRHandJointID.IndexProximal.ToIndex();
|
||||
m_BoneToParent[XRHandJointID.IndexDistal.ToIndex()] = XRHandJointID.IndexIntermediate.ToIndex();
|
||||
m_BoneToParent[XRHandJointID.IndexTip.ToIndex()] = XRHandJointID.IndexDistal.ToIndex();
|
||||
m_BoneToParent[XRHandJointID.MiddleMetacarpal.ToIndex()] = XRHandJointID.Wrist.ToIndex();
|
||||
m_BoneToParent[XRHandJointID.MiddleProximal.ToIndex()] = XRHandJointID.MiddleMetacarpal.ToIndex();
|
||||
m_BoneToParent[XRHandJointID.MiddleIntermediate.ToIndex()] = XRHandJointID.MiddleProximal.ToIndex();
|
||||
m_BoneToParent[XRHandJointID.MiddleDistal.ToIndex()] = XRHandJointID.MiddleIntermediate.ToIndex();
|
||||
m_BoneToParent[XRHandJointID.MiddleTip.ToIndex()] = XRHandJointID.MiddleDistal.ToIndex();
|
||||
m_BoneToParent[XRHandJointID.RingMetacarpal.ToIndex()] = XRHandJointID.Wrist.ToIndex();
|
||||
m_BoneToParent[XRHandJointID.RingProximal.ToIndex()] = XRHandJointID.RingMetacarpal.ToIndex();
|
||||
m_BoneToParent[XRHandJointID.RingIntermediate.ToIndex()] = XRHandJointID.RingProximal.ToIndex();
|
||||
m_BoneToParent[XRHandJointID.RingDistal.ToIndex()] = XRHandJointID.RingIntermediate.ToIndex();
|
||||
m_BoneToParent[XRHandJointID.RingTip.ToIndex()] = XRHandJointID.RingDistal.ToIndex();
|
||||
m_BoneToParent[XRHandJointID.LittleMetacarpal.ToIndex()] = XRHandJointID.Wrist.ToIndex();
|
||||
m_BoneToParent[XRHandJointID.LittleProximal.ToIndex()] = XRHandJointID.LittleMetacarpal.ToIndex();
|
||||
m_BoneToParent[XRHandJointID.LittleIntermediate.ToIndex()] = XRHandJointID.LittleProximal.ToIndex();
|
||||
m_BoneToParent[XRHandJointID.LittleDistal.ToIndex()] = XRHandJointID.LittleIntermediate.ToIndex();
|
||||
m_BoneToParent[XRHandJointID.LittleTip.ToIndex()] = XRHandJointID.LittleDistal.ToIndex();
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public VG_EC_UnityXRHands(int avatarID, VG_HandSide side, Transform origin)
|
||||
{
|
||||
m_avatarID = avatarID;
|
||||
m_handType = side;
|
||||
m_origin = origin;
|
||||
m_enablingDefine = "VG_USE_XRHANDS_CONTROLLER";
|
||||
|
||||
#if VG_USE_XRHANDS_CONTROLLER
|
||||
m_enabled = true;
|
||||
#else
|
||||
PrintNotEnabledError();
|
||||
m_enabled = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public new void Initialize()
|
||||
{
|
||||
#if VG_USE_XRHANDS_CONTROLLER
|
||||
m_mapping = new OpenXRHandMapping();
|
||||
base.Initialize();
|
||||
|
||||
m_Subsystem = XRGeneralSettings.Instance?.Manager?.activeLoader?.GetLoadedSubsystem<XRHandSubsystem>();
|
||||
if (m_Subsystem != null)
|
||||
{
|
||||
if (m_handType == VG_HandSide.LEFT)
|
||||
{
|
||||
m_hand = m_Subsystem.leftHand;
|
||||
m_updateSuccessFlags = XRHandSubsystem.UpdateSuccessFlags.LeftHandRootPose | XRHandSubsystem.UpdateSuccessFlags.LeftHandJoints;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_hand = m_Subsystem.rightHand;
|
||||
m_updateSuccessFlags = XRHandSubsystem.UpdateSuccessFlags.RightHandRootPose | XRHandSubsystem.UpdateSuccessFlags.RightHandJoints;
|
||||
}
|
||||
|
||||
if (!m_Subsystem.running) m_Subsystem.Start();
|
||||
|
||||
base.Initialize();
|
||||
m_initialized = true;
|
||||
}
|
||||
else m_initialized = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public override float GetGrabStrength()
|
||||
{
|
||||
return -1.0f; // let VG decide from full DOF
|
||||
}
|
||||
|
||||
public override bool Compute()
|
||||
{
|
||||
if (!m_enabled) return false;
|
||||
if (!m_initialized) { Initialize(); return false; }
|
||||
#if VG_USE_XRHANDS_CONTROLLER
|
||||
if (!m_Subsystem.running) return false;
|
||||
if (!m_Subsystem.TryUpdateHands(XRHandSubsystem.UpdateType.Dynamic).HasFlag(m_updateSuccessFlags))
|
||||
return false;
|
||||
|
||||
for (int boneId = 0; boneId < GetNumBones(); ++boneId)
|
||||
{
|
||||
if (m_hand.GetJoint(XRHandJointIDUtility.FromIndex(boneId)).TryGetPose(out Pose pose))
|
||||
{
|
||||
//if (m_origin != null) pose = pose.GetTransformedBy(m_origin);
|
||||
SetPose(boneId, Matrix4x4.TRS(
|
||||
pose.position,
|
||||
pose.rotation, Vector3.one));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public override void HapticPulse(VG_HandStatus hand, float amplitude = 0.5F, float duration = 0.01F, int finger = 5)
|
||||
{
|
||||
}
|
||||
|
||||
public override Color GetConfidence()
|
||||
{
|
||||
if (!m_initialized) return Color.black;
|
||||
|
||||
return Color.yellow;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f9e2dc4556c290f4a88a6b4573b61556
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,201 @@
|
||||
// Copyright (C) 2014-2024 Gleechi Technology AB. All rights reserved.
|
||||
|
||||
//#define VG_USE_UNITYXRINTERACTION_HAND
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
#if VG_USE_UNITYXRINTERACTION_HAND
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.XR.Interaction.Toolkit;
|
||||
using UnityEngine.XR.Interaction.Toolkit.Inputs;
|
||||
#endif
|
||||
|
||||
namespace VirtualGrasp.Controllers
|
||||
{
|
||||
/**
|
||||
* This is an external controller class that supports the action-based Unity XR Interaction toolkit controller as an external controller.
|
||||
* Please refer to https://docs.virtualgrasp.com/controllers.html for the definition of an external controller for VG, and to
|
||||
* https://docs.unity3d.com/Packages/com.unity.xr.interaction.toolkit@2.0/manual/index.html for the plugin itself.
|
||||
*
|
||||
* The following requirements have to be met to be able to enable the #define VG_USE_UNITYINTERACTION_HAND above and use the controller:
|
||||
* - You have the "XR Plugin Management" package installed into your Unity project.
|
||||
* - You have the "XR Interaction Toolkit" package installed into your Unity project.
|
||||
* - The current setup does not seem to work for OpenXR as an XR plugin provider, you must have Oculus XR package installed into your Unity project.
|
||||
* - if you use Oculus, you use it through "OpenXR" (Oculus -> Tools -> OVR Utilities Plugin -> Set OVR to OpenXR)
|
||||
*/
|
||||
|
||||
[LIBVIRTUALGRASP_UNITY_SCRIPT]
|
||||
[HelpURL("https://docs.virtualgrasp.com/unity_vg_ec_unityxrinteraction." + VG_Version.__VG_VERSION__ + ".html")]
|
||||
public class VG_EC_UnityXRInteraction : VG_ExternalController
|
||||
{
|
||||
|
||||
#if VG_USE_UNITYXRINTERACTION_HAND
|
||||
private const string XRI_RESOURCE = "VG_XRI_Entries"; //"XRI Default Input Actions";
|
||||
private const string XRI_ACTIONMAP = "Player";
|
||||
private static VG_XRI_Entries m_xriEntries = null;
|
||||
static InputActionManager m_provider = null;
|
||||
private ActionBasedController m_controller = null;
|
||||
#endif
|
||||
|
||||
[Serializable]
|
||||
public class HandMapping : VG_BoneMapping
|
||||
{
|
||||
public override void Initialize(int avatarID, VG_HandSide side)
|
||||
{
|
||||
base.Initialize(avatarID, side);
|
||||
m_BoneToTransform = new Dictionary<int, Transform>()
|
||||
{
|
||||
{ 0, Hand_WristRoot }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public VG_EC_UnityXRInteraction(int avatarID, VG_HandSide side, Transform origin)
|
||||
{
|
||||
m_avatarID = avatarID;
|
||||
m_handType = side;
|
||||
m_origin = origin;
|
||||
m_enabled = true;
|
||||
m_enablingDefine = "VG_USE_UNITYXRINTERACTION_HAND";
|
||||
|
||||
#if VG_USE_UNITYXRINTERACTION_HAND
|
||||
m_enabled = true;
|
||||
#else
|
||||
PrintNotEnabledError();
|
||||
m_enabled = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public void DisposeController()
|
||||
{
|
||||
#if VG_USE_UNITYXRINTERACTION_HAND
|
||||
if (m_controller != null)
|
||||
GameObject.Destroy(m_controller.gameObject);
|
||||
#endif
|
||||
}
|
||||
|
||||
public new void Initialize()
|
||||
{
|
||||
#if VG_USE_UNITYXRINTERACTION_HAND
|
||||
if (m_provider == null) m_provider = GameObject.FindObjectOfType<InputActionManager>();
|
||||
if (m_xriEntries == null)
|
||||
m_xriEntries = Resources.Load<VG_XRI_Entries>(XRI_RESOURCE);
|
||||
if (m_xriEntries == null)
|
||||
{
|
||||
Debug.LogError("Could not find " + XRI_RESOURCE);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_xriEntries.Initialize();
|
||||
//Debug.Log(m_xriEntries);
|
||||
}
|
||||
|
||||
InputActionAsset inputActionAsset = null;
|
||||
if (m_provider == null)
|
||||
{
|
||||
m_provider = GameObject.FindObjectOfType<VG_MainScript>().gameObject.AddComponent<InputActionManager>();
|
||||
inputActionAsset = Resources.Load<InputActionAsset>(m_xriEntries.Get(VG_XRI_Entries.XRI_Entry.RESOURCE));
|
||||
if (inputActionAsset != null)
|
||||
{
|
||||
m_provider.actionAssets = new List<InputActionAsset>{ inputActionAsset };
|
||||
m_provider.EnableInput();
|
||||
}
|
||||
else Debug.Log("Could not load input actions.");
|
||||
}
|
||||
|
||||
if (m_provider != null && m_provider.actionAssets.Count > 0 && m_provider.actionAssets[0] != null)
|
||||
{
|
||||
m_mapping = new HandMapping();
|
||||
base.Initialize();
|
||||
|
||||
string handSide = (m_handType == VG_HandSide.LEFT) ? "Left" : "Right";
|
||||
|
||||
// We put the ActionBasedController components on dummy GameObjects so they do not
|
||||
// affect the wrist transforms per se (this can't be disabled in the XRController it seems).
|
||||
GameObject controller = new(handSide + "Controller_ID" + m_avatarID);
|
||||
controller.transform.SetParent(m_provider.transform);
|
||||
m_controller = controller.AddComponent<ActionBasedController>();
|
||||
|
||||
// Bind Position and Rotation Signals
|
||||
InputActionMap inputMap = m_provider.actionAssets[0].FindActionMap(XRI_ACTIONMAP);
|
||||
if (inputMap == null) Debug.LogError("Could not find map " + XRI_ACTIONMAP);
|
||||
else
|
||||
{
|
||||
m_controller.enableInputTracking = true;
|
||||
m_controller.updateTrackingType = XRBaseController.UpdateType.Update;
|
||||
|
||||
foreach (VG_XRI_Entries.XRI_Entry entry in new List<VG_XRI_Entries.XRI_Entry> { VG_XRI_Entries.XRI_Entry.POSITION, VG_XRI_Entries.XRI_Entry.ROTATION, VG_XRI_Entries.XRI_Entry.TRIGGER, VG_XRI_Entries.XRI_Entry.GRAB, VG_XRI_Entries.XRI_Entry.HAPTICS })
|
||||
{
|
||||
string actionName = m_xriEntries.Get(entry, handSide);
|
||||
InputAction inputAction = inputMap.FindAction(actionName);
|
||||
if (inputAction == null)
|
||||
{
|
||||
Debug.LogWarning("Could not find action " + actionName + " in " + XRI_ACTIONMAP + ".");
|
||||
continue;
|
||||
}
|
||||
switch (entry)
|
||||
{
|
||||
case VG_XRI_Entries.XRI_Entry.POSITION:
|
||||
m_controller.positionAction = new InputActionProperty(inputAction); break;
|
||||
case VG_XRI_Entries.XRI_Entry.ROTATION:
|
||||
m_controller.rotationAction = new InputActionProperty(inputAction); break;
|
||||
case VG_XRI_Entries.XRI_Entry.TRIGGER:
|
||||
m_controller.activateAction = new InputActionProperty(inputAction); break;
|
||||
case VG_XRI_Entries.XRI_Entry.GRAB:
|
||||
m_controller.selectAction = new InputActionProperty(inputAction); break;
|
||||
case VG_XRI_Entries.XRI_Entry.HAPTICS:
|
||||
m_controller.hapticDeviceAction = new InputActionProperty(inputAction); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_initialized = (m_provider != null && m_controller != null);
|
||||
#endif
|
||||
}
|
||||
|
||||
public override bool Compute()
|
||||
{
|
||||
#if VG_USE_UNITYXRINTERACTION_HAND
|
||||
if (!m_enabled) return false;
|
||||
if (!m_initialized) { Initialize(); return false; }
|
||||
SetPose(0, Matrix4x4.TRS(m_controller.currentControllerState.position, m_controller.currentControllerState.rotation, Vector3.one));
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
public override float GetGrabStrength()
|
||||
{
|
||||
float trigger = 0.0f;
|
||||
#if VG_USE_UNITYXRINTERACTION_HAND
|
||||
if (!m_initialized) return 0.0f;
|
||||
switch (VG_Controller.GetGraspButton())
|
||||
{
|
||||
case VG_VrButton.TRIGGER:
|
||||
trigger = m_controller.currentControllerState.activateInteractionState.value; break;
|
||||
case VG_VrButton.GRIP:
|
||||
trigger = m_controller.currentControllerState.selectInteractionState.value; break;
|
||||
case VG_VrButton.GRIP_OR_TRIGGER:
|
||||
trigger = Mathf.Max(m_controller.currentControllerState.activateInteractionState.value,
|
||||
m_controller.currentControllerState.selectInteractionState.value);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
return trigger;
|
||||
}
|
||||
|
||||
public override Color GetConfidence()
|
||||
{
|
||||
return Color.yellow;
|
||||
}
|
||||
|
||||
public override void HapticPulse(VG_HandStatus hand, float amplitude = 0.5F, float duration = 0.015F, int finger = 5)
|
||||
{
|
||||
#if VG_USE_UNITYXRINTERACTION_HAND
|
||||
m_controller.SendHapticImpulse(amplitude, duration);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8ec2bbae109cbf34b994dac2f101fb30
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,63 @@
|
||||
// Copyright (C) 2014-2024 Gleechi Technology AB. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VirtualGrasp.Controllers
|
||||
{
|
||||
|
||||
[Serializable, CreateAssetMenu(fileName = "VG_XRI_Entries", menuName = "VirtualGrasp/VG_XRI_Entries")]
|
||||
public class VG_XRI_Entries : ScriptableObject
|
||||
{
|
||||
public enum XRI_Entry
|
||||
{
|
||||
RESOURCE,
|
||||
POSITION,
|
||||
ROTATION,
|
||||
TRIGGER,
|
||||
GRAB,
|
||||
HAPTICS
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
m_entries.Clear();
|
||||
TryAdd(XRI_Entry.RESOURCE, m_resourceName);
|
||||
TryAdd(XRI_Entry.POSITION, m_positionAction);
|
||||
TryAdd(XRI_Entry.ROTATION, m_rotationAction);
|
||||
TryAdd(XRI_Entry.TRIGGER, m_triggerAction);
|
||||
TryAdd(XRI_Entry.GRAB, m_grabAction);
|
||||
TryAdd(XRI_Entry.HAPTICS, m_hapticsAction);
|
||||
}
|
||||
|
||||
public void TryAdd(XRI_Entry key, string value)
|
||||
{
|
||||
if (value != "")
|
||||
m_entries.Add(key, value);
|
||||
}
|
||||
|
||||
public string Get(XRI_Entry key, string suffix = "")
|
||||
{
|
||||
if (!m_entries.TryGetValue(key, out string value))
|
||||
return "null";
|
||||
return value + suffix;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
string str = "Valid Entries:\n";
|
||||
foreach (var entry in m_entries) { str += entry.ToString() + "\n"; }
|
||||
return str;
|
||||
}
|
||||
|
||||
public string m_resourceName = "";
|
||||
public string m_positionAction = "";
|
||||
public string m_rotationAction = "";
|
||||
public string m_triggerAction = "";
|
||||
public string m_grabAction = "";
|
||||
public string m_hapticsAction = "";
|
||||
|
||||
private Dictionary<XRI_Entry, string> m_entries = new();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7f5008351c8d5fa4590d077c163cd0cc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user