diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Custom.meta b/Runtime/HumanoidControl/Scripts/Extensions/Custom.meta
new file mode 100644
index 0000000..bb3aec7
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Custom.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 36ebb5083c03e91419dc11acc8fd6aa7
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Custom/CustomArm.cs b/Runtime/HumanoidControl/Scripts/Extensions/Custom/CustomArm.cs
new file mode 100644
index 0000000..d60ae6c
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Custom/CustomArm.cs
@@ -0,0 +1,209 @@
+using UnityEngine;
+
+namespace Passer.Humanoid {
+ using Passer.Tracking;
+
+ ///
+ /// A custom sensor used on the arm of a humanoid
+ ///
+ /// This tracking option supports a custom developed ControllerComponent or HandSkeleton for the hand and/or arm.
+ [System.Serializable]
+ public class CustomArm : Passer.Humanoid.ArmSensor {
+
+ ///
+ /// The name of this sensor
+ ///
+ public override string name => "Custom Sensor";
+
+ ///
+ /// THe tracker for this sensor
+ ///
+#if hCUSTOM
+ public override HumanoidTracker tracker => humanoid.custom;
+#endif
+
+ ///
+ /// The tracker controller to use for this arm
+ ///
+ protected ControllerComponent controllerComponent;
+
+ ///
+ /// The bone on the arm controlled by the sensor
+ ///
+ public ArmBones attachedBone = ArmBones.Hand;
+
+ ///
+ /// The controller input for this humanoid
+ ///
+ protected Controller controllerInput;
+
+ #region Manage
+
+ ///
+ /// Updates the arm targets based on the current sensor position and rotation
+ ///
+ public override void SetSensor2Target() {
+ if (sensorComponent == null)
+ return;
+
+ HumanoidTarget.TargetedBone targetBone = handTarget.GetTargetBone(attachedBone);
+ if (targetBone == null)
+ return;
+
+ sensor2TargetRotation = Quaternion.Inverse(sensorComponent.transform.rotation) * targetBone.target.transform.rotation;
+ sensor2TargetPosition = -targetBone.target.transform.InverseTransformPoint(sensorComponent.transform.position);
+ }
+
+ ///
+ /// Updates the sensor position and rotation based on the current position of the arm targets.
+ ///
+ /// Not used
+ public override void UpdateSensorTransformFromTarget(Transform _) {
+ if (handTarget == null)
+ return;
+
+ HumanoidTarget.TargetedBone targetBone = handTarget.GetTargetBone(attachedBone);
+ base.UpdateSensorTransformFromTarget(targetBone.target.transform);
+ }
+
+ #endregion Manage
+
+ #region Start
+
+ ///
+ /// Prepares the arm for tracking with the tracked controller and/or skeleton
+ ///
+ /// The humanoid for which this arm is tracked
+ /// The transform of the hand target
+ /// This will find and initialize the controllerInput for the given humanoid.
+ /// It will initialize the sensor2TargetPosition and sensor2TargetRotation values.
+ /// It will determine whether the sensor should be shown and rendered.
+ /// It will start the tracking for the controller and/or hand skeleton.
+ public override void Start(HumanoidControl _humanoid, Transform targetTransform) {
+ base.Start(_humanoid, targetTransform);
+
+ if (tracker == null || !tracker.enabled || !enabled)
+ return;
+
+ controllerComponent = sensorComponent as ControllerComponent;
+ controllerInput = Controllers.GetController(0);
+
+ handSkeleton = sensorComponent as HandSkeleton;
+
+ SetSensor2Target();
+ ShowSensor(handTarget.humanoid.showRealObjects && target.showRealObjects);
+
+ if (controllerComponent != null) {
+ if (tracker.trackerComponent != null)
+ controllerComponent.StartComponent(tracker.trackerComponent.transform, handTarget.isLeft);
+ else
+ controllerComponent.StartComponent(controllerComponent.transform.parent, handTarget.isLeft);
+ }
+ if (handSkeleton != null) {
+ if (tracker.trackerComponent != null)
+ handSkeleton.StartComponent(tracker.trackerComponent.transform);
+ else
+ handSkeleton.StartComponent(handSkeleton.transform.parent);
+ }
+ }
+
+ #endregion Start
+
+ #region Update
+
+ ///
+ /// Updates the arm target based on the status of the tracked controller and/or skeleton
+ ///
+ public override void Update() {
+ status = Tracker.Status.Unavailable;
+ if (tracker == null || !tracker.enabled || !enabled)
+ return;
+
+ if (sensorComponent == null)
+ return;
+
+ sensorComponent.UpdateComponent();
+ status = sensorComponent.status;
+ if (status != Tracker.Status.Tracking)
+ return;
+
+ HumanoidTarget.TargetedBone targetBone = handTarget.GetTargetBone(attachedBone);
+
+ UpdateTarget(targetBone.target, sensorComponent);
+
+ UpdateControllerInput();
+
+ UpdateHandFromSkeleton();
+ }
+
+ #region Controller
+
+ ///
+ /// Updates the Controller Input for this side
+ ///
+ protected void UpdateControllerInput() {
+ if (handTarget.isLeft)
+ UpdateControllerInput(controllerInput.left);
+ else
+ UpdateControllerInput(controllerInput.right);
+ }
+
+ ///
+ /// Updates one side of the ControllerInput from the values of the tracked ControllerComponent
+ ///
+ /// The controller side to update
+ /// This function does nothing when the controller is not available or not tracking.
+ protected virtual void UpdateControllerInput(ControllerSide controllerSide) {
+ if (controllerSide == null)
+ return;
+
+ if (controllerComponent == null || controllerComponent.status != Tracker.Status.Tracking)
+ return;
+
+ controllerSide.stickHorizontal += controllerComponent.primaryAxis.x;
+ controllerSide.stickVertical += controllerComponent.primaryAxis.y;
+ controllerSide.stickButton |= (controllerComponent.primaryAxis.z > 0.5F);
+ controllerSide.stickTouch = true;
+
+ controllerSide.buttons[0] |= controllerComponent.button1 > 0.5F;
+ controllerSide.buttons[1] |= controllerComponent.button2 > 0.5F;
+ controllerSide.buttons[2] |= controllerComponent.button3 > 0.5F;
+ controllerSide.buttons[3] |= controllerComponent.button4 > 0.5F;
+
+ controllerSide.trigger1 += controllerComponent.trigger1;
+ controllerSide.trigger2 += controllerComponent.trigger2;
+
+ controllerSide.option |= controllerComponent.option > 0.5F;
+ }
+
+ #endregion Controller
+
+ #region Skeleton
+
+ ///
+ /// This function uses the tracked HandSkeleton to update the pose of the hand
+ ///
+ /// This function does nothing when the hand skeleton is not available or not tracking.
+ protected override void UpdateHandFromSkeleton() {
+ if (handSkeleton == null || handSkeleton.status != Tracker.Status.Tracking)
+ return;
+
+ Transform wristBone = handSkeleton.GetWristBone();
+ handTarget.hand.target.transform.position = wristBone.transform.position;
+ if (handTarget.isLeft)
+ handTarget.hand.target.transform.rotation = wristBone.transform.rotation * Quaternion.Euler(-90, 0, 90);
+ else
+ handTarget.hand.target.transform.rotation = wristBone.transform.rotation * Quaternion.Euler(-90, 0, -90);
+
+ UpdateThumbFromSkeleton();
+ UpdateIndexFingerFromSkeleton();
+ UpdateMiddleFingerFromSkeleton();
+ UpdateRingFingerFromSkeleton();
+ UpdateLittleFingerFromSkeleton();
+ }
+
+ #endregion Skeleton
+
+ #endregion Update
+ }
+}
\ No newline at end of file
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Custom/CustomArm.cs.meta b/Runtime/HumanoidControl/Scripts/Extensions/Custom/CustomArm.cs.meta
new file mode 100644
index 0000000..23f6323
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Custom/CustomArm.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: b1d7b6728893ceb4bb7e73e43cace60b
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Custom/CustomHead.cs b/Runtime/HumanoidControl/Scripts/Extensions/Custom/CustomHead.cs
new file mode 100644
index 0000000..8ae5239
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Custom/CustomHead.cs
@@ -0,0 +1,79 @@
+using UnityEngine;
+using Passer.Tracking;
+
+namespace Passer.Humanoid {
+
+ ///
+ /// A custom sensor used on the head of a humanoid.
+ ///
+ /// This tracking option supports a custom developed SensorComponent for the head.
+ [System.Serializable]
+ public class CustomHead : HeadSensor {
+ public override string name => "Custom Sensor";
+
+#if hCUSTOM
+ public override HumanoidTracker tracker => humanoid.custom;
+#endif
+
+ //private static readonly Vector3 defaultLocalTrackerPosition = Vector3.zero;
+ //private static readonly Quaternion defaultLocalTrackerRotation = Quaternion.identity;
+
+ #region Manage
+
+ #endregion Manage
+
+ #region Start
+
+ ///
+ /// Prepares the head for tracking with the tracked sensor
+ ///
+ /// The humanoid for which this head is tracked
+ /// The transform of the head target
+ /// It will initialize the sensor2TargetPosition and sensor2TargetRotation values.
+ /// It will determine whether the sensor should be shown and rendered.
+ /// It will start the tracking of the sensor.
+ public override void Start(HumanoidControl _humanoid, Transform targetTransform) {
+ base.Start(_humanoid, targetTransform);
+
+ if (tracker == null || !tracker.enabled || !enabled)
+ return;
+
+ SetSensor2Target();
+ ShowSensor(headTarget.humanoid.showRealObjects && target.showRealObjects);
+
+ if (sensorComponent != null) {
+ if (tracker.trackerComponent != null)
+ sensorComponent.StartComponent(tracker.trackerComponent.transform);
+ else
+ sensorComponent.StartComponent(sensorComponent.transform.parent);
+ }
+ }
+
+ #endregion Start
+
+ #region Update
+
+ ///
+ /// Updates the head target based on the status of the tracke sensor
+ ///
+ public override void Update() {
+ status = Tracker.Status.Unavailable;
+ if (tracker == null || !tracker.enabled || !enabled)
+ return;
+
+ if (sensorComponent == null)
+ return;
+
+ sensorComponent.UpdateComponent();
+ status = sensorComponent.status;
+ if (status != Tracker.Status.Tracking)
+ return;
+
+ UpdateTarget(headTarget.head.target, sensorComponent);
+
+ UpdateNeckTargetFromHead();
+ }
+
+ #endregion Update
+ }
+}
\ No newline at end of file
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Custom/CustomHead.cs.meta b/Runtime/HumanoidControl/Scripts/Extensions/Custom/CustomHead.cs.meta
new file mode 100644
index 0000000..b9f91d1
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Custom/CustomHead.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 33addd0b8cb0bbb41b80554896116e1e
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Custom/CustomLeg.cs b/Runtime/HumanoidControl/Scripts/Extensions/Custom/CustomLeg.cs
new file mode 100644
index 0000000..e1aba52
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Custom/CustomLeg.cs
@@ -0,0 +1,105 @@
+using UnityEngine;
+
+namespace Passer.Humanoid {
+ using Passer.Tracking;
+
+ ///
+ /// A custom sensor used on the leg of a humanoid.
+ ///
+ /// This tracking option supports a custom developed SensorComponent on the leg or foot.
+ [System.Serializable]
+ public class CustomLeg : LegSensor {
+
+ public override string name => "Custom Sensor";
+
+ ///
+ /// The bone on the leg controlled by the sensor
+ ///
+ public LegBones attachedBone = LegBones.Foot;
+
+#if hCUSTOM
+ public override HumanoidTracker tracker => humanoid.custom;
+#endif
+
+ #region Manage
+
+ ///
+ /// Updates the leg targets based on the current sensor position and rotation
+ ///
+ public override void SetSensor2Target() {
+ if (sensorComponent == null)
+ return;
+
+ HumanoidTarget.TargetedBone targetBone = footTarget.GetTargetBone(attachedBone);
+ if (targetBone == null)
+ return;
+
+ sensor2TargetRotation = Quaternion.Inverse(sensorComponent.transform.rotation) * targetBone.target.transform.rotation;
+ sensor2TargetPosition = -targetBone.target.transform.InverseTransformPoint(sensorComponent.transform.position);
+
+ }
+
+ ///
+ /// Updates the sensor position and rotation based on the current position of the leg targets
+ ///
+ /// Not used
+ public override void UpdateSensorTransformFromTarget(Transform _) {
+ HumanoidTarget.TargetedBone targetBone = footTarget.GetTargetBone(attachedBone);
+ base.UpdateSensorTransformFromTarget(targetBone.target.transform);
+ }
+
+ #endregion Manage
+
+ #region Start
+
+ ///
+ /// Prepares the leg for tracking with the sensor
+ ///
+ /// The humanoid for which this leg is tracked
+ /// The transform of the foot target
+ /// It will initialze the sensor2TargetPosition and sensor2TargetRotation values.
+ /// It will determine whether the sensor should be shown and rendered.
+ /// It will start the tracking of the sensor.
+ public override void Start(HumanoidControl _humanoid, Transform targetTransform) {
+ base.Start(_humanoid, targetTransform);
+
+ SetSensor2Target();
+ ShowSensor(footTarget.humanoid.showRealObjects && target.showRealObjects);
+
+ if (sensorComponent != null) {
+ if (tracker.trackerComponent != null)
+ sensorComponent.StartComponent(tracker.trackerComponent.transform);
+ else
+ sensorComponent.StartComponent(sensorComponent.transform.parent);
+ }
+ }
+
+ #endregion Start
+
+ #region Update
+
+ ///
+ /// Updates the leg target based on the status of the tracked sensor
+ ///
+ public override void Update() {
+ status = Tracker.Status.Unavailable;
+ if (tracker == null || !tracker.enabled || !enabled)
+ return;
+
+ if (sensorComponent == null)
+ return;
+
+ sensorComponent.UpdateComponent();
+ status = sensorComponent.status;
+ if (status != Tracker.Status.Tracking)
+ return;
+
+ HumanoidTarget.TargetedBone targetBone = footTarget.GetTargetBone(attachedBone);
+
+ UpdateTarget(targetBone.target, sensorComponent);
+ }
+
+ #endregion Update
+ }
+
+}
\ No newline at end of file
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Custom/CustomLeg.cs.meta b/Runtime/HumanoidControl/Scripts/Extensions/Custom/CustomLeg.cs.meta
new file mode 100644
index 0000000..d772296
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Custom/CustomLeg.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: cb5d7cb45eac0e6468fa4b91fc6a1480
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Custom/CustomTorso.cs b/Runtime/HumanoidControl/Scripts/Extensions/Custom/CustomTorso.cs
new file mode 100644
index 0000000..6eeab37
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Custom/CustomTorso.cs
@@ -0,0 +1,105 @@
+using UnityEngine;
+
+namespace Passer.Humanoid {
+ using Passer.Tracking;
+
+ ///
+ /// A custom sensor used on the torso of a humanoid.
+ ///
+ /// This tracking option supports a custom developed SensorComponent for the torso.
+ [System.Serializable]
+ public class CustomTorso : TorsoSensor {
+
+ public override string name => "Custom Sensor";
+
+#if hCUSTOM
+ public override HumanoidTracker tracker => humanoid.custom;
+#endif
+
+ ///
+ /// The bone on the torso controlled by the sensor
+ ///
+ public TorsoBones attachedBone = TorsoBones.Hips;
+
+ #region Manage
+
+ ///
+ /// Updates the torso targets based on the current sensor position and rotation
+ ///
+ public override void SetSensor2Target() {
+ if (sensorComponent == null)
+ return;
+
+ HumanoidTarget.TargetedBone targetBone = hipsTarget.GetTargetBone(attachedBone);
+ if (targetBone == null)
+ return;
+
+ sensor2TargetRotation = Quaternion.Inverse(sensorComponent.transform.rotation) * targetBone.target.transform.rotation;
+ sensor2TargetPosition = -targetBone.target.transform.InverseTransformPoint(sensorComponent.transform.position);
+ }
+
+ ///
+ /// Updates the sensor position and rotation based on the current position of the torso targets
+ ///
+ /// Not used
+ public override void UpdateSensorTransformFromTarget(Transform _) {
+ HumanoidTarget.TargetedBone targetBone = hipsTarget.GetTargetBone(attachedBone);
+ base.UpdateSensorTransformFromTarget(targetBone.target.transform);
+ }
+
+ #endregion Manage
+
+ #region Start
+
+ ///
+ /// Prepares the torso for tracking with the sensor
+ ///
+ /// The humanoid for which this torso is tracked
+ /// The transform of the hips target
+ /// It will initialze the sensor2TargetPosition and sensor2TargetRotation values.
+ /// It will determine whether the sensor should be shown and rendered.
+ /// It will start the tracking of the sensor.
+ public override void Start(HumanoidControl _humanoid, Transform targetTransform) {
+ base.Start(_humanoid, targetTransform);
+
+ SetSensor2Target();
+ ShowSensor(hipsTarget.humanoid.showRealObjects && target.showRealObjects);
+
+ if (sensorComponent != null) {
+ if (tracker.trackerComponent != null)
+ sensorComponent.StartComponent(tracker.trackerComponent.transform);
+ else
+ sensorComponent.StartComponent(sensorComponent.transform.parent);
+ }
+ }
+
+ #endregion Start
+
+ #region Update
+
+ ///
+ /// Updates the torso targets based on the status of the tracked sensor
+ ///
+ public override void Update() {
+ status = Tracker.Status.Unavailable;
+ if (tracker == null || !tracker.enabled || !enabled)
+ return;
+
+ if (sensorComponent == null)
+ return;
+
+ sensorComponent.UpdateComponent();
+ status = sensorComponent.status;
+ if (status != Tracker.Status.Tracking)
+ return;
+
+ HumanoidTarget.TargetedBone targetBone = hipsTarget.GetTargetBone(attachedBone);
+
+ UpdateTarget(targetBone.target, sensorComponent);
+
+ }
+
+ #endregion Update
+ }
+
+}
\ No newline at end of file
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Custom/CustomTorso.cs.meta b/Runtime/HumanoidControl/Scripts/Extensions/Custom/CustomTorso.cs.meta
new file mode 100644
index 0000000..a358625
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Custom/CustomTorso.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: d0a97dd438bd4674fb64e76753a4bbc9
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Custom/CustomTracker.cs b/Runtime/HumanoidControl/Scripts/Extensions/Custom/CustomTracker.cs
new file mode 100644
index 0000000..81d3e59
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Custom/CustomTracker.cs
@@ -0,0 +1,116 @@
+using Passer.Tracking;
+
+namespace Passer.Humanoid {
+
+
+ ///
+ /// A tracker wich can be used for custom tracking solutions
+ ///
+ /// THis tracking option supports custom trackers and sensors for a humanoid.
+ [System.Serializable]
+ public class CustomTracker : HumanoidTracker {
+
+ /// \copydoc HumanoidTracker::name
+ public override string name => "Custom Tracker";
+
+ #region Manage
+
+ ///
+ /// A skeleton for the body
+ ///
+ /// When this is set, the tracking will be taken from this skeleton
+ public BodySkeleton bodySkeleton;
+
+ #endregion Manage
+
+ #region Update
+
+ public override void UpdateTracker() {
+ base.UpdateTracker();
+
+ if (bodySkeleton != null) {
+ status = bodySkeleton.status;
+
+ UpdateBodyFromSkeleton();
+ }
+ }
+
+ protected void UpdateBodyFromSkeleton() {
+ if (bodySkeleton == null || bodySkeleton.status != Tracker.Status.Tracking)
+ return;
+
+ UpdateTorso();
+ UpdateLeftArm();
+ UpdateRightArm();
+ UpdateLeftLeg();
+ UpdateRightLeg();
+
+ humanoid.CopyRigToTargets();
+ }
+
+ protected virtual void UpdateTorso() {
+ UpdateBone(humanoid.hipsTarget.hips.target, Tracking.Bone.Hips);
+ UpdateBoneRotation(humanoid.hipsTarget.spine.target, Tracking.Bone.Spine);
+ UpdateBoneRotation(humanoid.hipsTarget.chest.target, Tracking.Bone.Chest);
+ UpdateBoneRotation(humanoid.headTarget.head.target, Tracking.Bone.Head);
+ }
+
+ protected virtual void UpdateLeftArm() {
+ UpdateBoneRotation(humanoid.leftHandTarget.shoulder.target, Tracking.Bone.LeftShoulder);
+ UpdateBoneRotation(humanoid.leftHandTarget.upperArm.target, Tracking.Bone.LeftUpperArm);
+ UpdateBoneRotation(humanoid.leftHandTarget.forearm.target, Tracking.Bone.LeftForearm);
+ UpdateBoneRotation(humanoid.leftHandTarget.hand.target, Tracking.Bone.LeftHand);
+ }
+
+ protected virtual void UpdateRightArm() {
+ UpdateBoneRotation(humanoid.rightHandTarget.shoulder.target, Tracking.Bone.RightShoulder);
+ UpdateBoneRotation(humanoid.rightHandTarget.upperArm.target, Tracking.Bone.RightUpperArm);
+ UpdateBoneRotation(humanoid.rightHandTarget.forearm.target, Tracking.Bone.RightForearm);
+ UpdateBoneRotation(humanoid.rightHandTarget.hand.target, Tracking.Bone.RightHand);
+ }
+
+ protected virtual void UpdateLeftLeg() {
+ UpdateBoneRotation(humanoid.leftFootTarget.upperLeg.target, Tracking.Bone.LeftUpperLeg);
+ UpdateBoneRotation(humanoid.leftFootTarget.lowerLeg.target, Tracking.Bone.LeftLowerLeg);
+ UpdateBoneRotation(humanoid.leftFootTarget.foot.target, Tracking.Bone.LeftFoot);
+ }
+
+ protected virtual void UpdateRightLeg() {
+ UpdateBoneRotation(humanoid.rightFootTarget.upperLeg.target, Tracking.Bone.RightUpperLeg);
+ UpdateBoneRotation(humanoid.rightFootTarget.lowerLeg.target, Tracking.Bone.RightLowerLeg);
+ UpdateBoneRotation(humanoid.rightFootTarget.foot.target, Tracking.Bone.RightFoot);
+ }
+
+ private void UpdateBone(HumanoidTarget.TargetTransform target, Tracking.Bone boneId) {
+ TrackedBone trackedBone = bodySkeleton.GetBone(boneId);
+ if (trackedBone == null)
+ return;
+
+ float confidence = trackedBone.rotationConfidence;
+ if (confidence > 0) {
+ target.confidence.rotation = confidence;
+ target.transform.rotation = bodySkeleton.transform.rotation * trackedBone.transform.rotation;
+ }
+
+ confidence = trackedBone.positionConfidence;
+ if (confidence > 0) {
+ target.confidence.position = confidence;
+ target.transform.position = bodySkeleton.transform.TransformPoint(trackedBone.transform.position);
+ }
+ }
+
+ private void UpdateBoneRotation(HumanoidTarget.TargetTransform target, Tracking.Bone boneId) {
+ TrackedBone trackedBone = bodySkeleton.GetBone(boneId);
+ if (trackedBone == null)
+ return;
+
+ float confidence = trackedBone.rotationConfidence;
+ if (confidence > 0) {
+ target.confidence.rotation = confidence;
+ target.transform.rotation = bodySkeleton.transform.rotation * trackedBone.transform.rotation;
+ }
+ }
+
+ #endregion Update
+ }
+}
\ No newline at end of file
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Custom/CustomTracker.cs.meta b/Runtime/HumanoidControl/Scripts/Extensions/Custom/CustomTracker.cs.meta
new file mode 100644
index 0000000..b2fd337
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Custom/CustomTracker.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a17001cc5e526574f94bf4961b36c64a
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus.meta b/Runtime/HumanoidControl/Scripts/Extensions/Oculus.meta
new file mode 100644
index 0000000..45e0bf4
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Oculus.meta
@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: 5d6f8e7a6e99d0444b2d51573a7ef8fa
+folderAsset: yes
+timeCreated: 1472626649
+licenseType: Free
+DefaultImporter:
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model.meta b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model.meta
new file mode 100644
index 0000000..45ae1d7
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 88b72ecc7f08a2543950b600aad6ae0a
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Left Touch Controller.fbx b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Left Touch Controller.fbx
new file mode 100644
index 0000000..777f3d4
Binary files /dev/null and b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Left Touch Controller.fbx differ
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Left Touch Controller.fbx.meta b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Left Touch Controller.fbx.meta
new file mode 100644
index 0000000..fcd8e49
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Left Touch Controller.fbx.meta
@@ -0,0 +1,97 @@
+fileFormatVersion: 2
+guid: ab7fa14a16d2d4d46a58646bef481bfc
+ModelImporter:
+ serializedVersion: 19301
+ internalIDToNameTable: []
+ externalObjects: {}
+ materials:
+ materialImportMode: 1
+ materialName: 0
+ materialSearch: 1
+ materialLocation: 1
+ animations:
+ legacyGenerateAnimations: 4
+ bakeSimulation: 0
+ resampleCurves: 1
+ optimizeGameObjects: 0
+ motionNodeName:
+ rigImportErrors:
+ rigImportWarnings:
+ animationImportErrors:
+ animationImportWarnings:
+ animationRetargetingWarnings:
+ animationDoRetargetingWarnings: 0
+ importAnimatedCustomProperties: 0
+ importConstraints: 0
+ animationCompression: 1
+ animationRotationError: 0.5
+ animationPositionError: 0.5
+ animationScaleError: 0.5
+ animationWrapMode: 0
+ extraExposedTransformPaths: []
+ extraUserProperties: []
+ clipAnimations: []
+ isReadable: 0
+ meshes:
+ lODScreenPercentages: []
+ globalScale: 1
+ meshCompression: 0
+ addColliders: 0
+ useSRGBMaterialColor: 1
+ sortHierarchyByName: 1
+ importVisibility: 1
+ importBlendShapes: 1
+ importCameras: 1
+ importLights: 1
+ fileIdsGeneration: 2
+ swapUVChannels: 0
+ generateSecondaryUV: 0
+ useFileUnits: 1
+ keepQuads: 0
+ weldVertices: 1
+ preserveHierarchy: 0
+ skinWeightsMode: 0
+ maxBonesPerVertex: 4
+ minBoneWeight: 0.001
+ meshOptimizationFlags: -1
+ indexFormat: 0
+ secondaryUVAngleDistortion: 8
+ secondaryUVAreaDistortion: 15.000001
+ secondaryUVHardAngle: 88
+ secondaryUVPackMargin: 4
+ useFileScale: 1
+ tangentSpace:
+ normalSmoothAngle: 60
+ normalImportMode: 0
+ tangentImportMode: 3
+ normalCalculationMode: 4
+ legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0
+ blendShapeNormalImportMode: 1
+ normalSmoothingSource: 0
+ referencedClips: []
+ importAnimation: 1
+ humanDescription:
+ serializedVersion: 3
+ human: []
+ skeleton: []
+ armTwist: 0.5
+ foreArmTwist: 0.5
+ upperLegTwist: 0.5
+ legTwist: 0.5
+ armStretch: 0.05
+ legStretch: 0.05
+ feetSpacing: 0
+ globalScale: 1
+ rootMotionBoneName:
+ hasTranslationDoF: 0
+ hasExtraRoot: 0
+ skeletonHasParents: 1
+ lastHumanDescriptionAvatarSource: {instanceID: 0}
+ autoGenerateAvatarMappingIfUnspecified: 1
+ animationType: 2
+ humanoidOversampling: 1
+ avatarSetup: 0
+ additionalBone: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Materials.meta b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Materials.meta
new file mode 100644
index 0000000..1280f3d
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Materials.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 2c77587d2814bad4a9ffe3b544de6df9
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Materials/Textures.meta b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Materials/Textures.meta
new file mode 100644
index 0000000..956f0e1
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Materials/Textures.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 4a2726a32de8b234d953bcc51778579d
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Materials/Textures/L_controller_DIF.psd b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Materials/Textures/L_controller_DIF.psd
new file mode 100644
index 0000000..8f04736
Binary files /dev/null and b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Materials/Textures/L_controller_DIF.psd differ
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Materials/Textures/L_controller_DIF.psd.meta b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Materials/Textures/L_controller_DIF.psd.meta
new file mode 100644
index 0000000..25960a3
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Materials/Textures/L_controller_DIF.psd.meta
@@ -0,0 +1,92 @@
+fileFormatVersion: 2
+guid: 196a35482dee8af47bede1110e5238d3
+TextureImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 11
+ mipmaps:
+ mipMapMode: 0
+ enableMipMap: 1
+ sRGBTexture: 1
+ linearTexture: 0
+ fadeOut: 0
+ borderMipMap: 0
+ mipMapsPreserveCoverage: 0
+ alphaTestReferenceValue: 0.5
+ mipMapFadeDistanceStart: 1
+ mipMapFadeDistanceEnd: 3
+ bumpmap:
+ convertToNormalMap: 0
+ externalNormalMap: 0
+ heightScale: 0.25
+ normalMapFilter: 0
+ isReadable: 0
+ streamingMipmaps: 0
+ streamingMipmapsPriority: 0
+ grayScaleToAlpha: 0
+ generateCubemap: 6
+ cubemapConvolution: 0
+ seamlessCubemap: 0
+ textureFormat: 1
+ maxTextureSize: 2048
+ textureSettings:
+ serializedVersion: 2
+ filterMode: -1
+ aniso: -1
+ mipBias: -100
+ wrapU: -1
+ wrapV: -1
+ wrapW: -1
+ nPOTScale: 1
+ lightmap: 0
+ compressionQuality: 50
+ spriteMode: 0
+ spriteExtrude: 1
+ spriteMeshType: 1
+ alignment: 0
+ spritePivot: {x: 0.5, y: 0.5}
+ spritePixelsToUnits: 100
+ spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+ spriteGenerateFallbackPhysicsShape: 1
+ alphaUsage: 1
+ alphaIsTransparency: 0
+ spriteTessellationDetail: -1
+ textureType: 0
+ textureShape: 1
+ singleChannelComponent: 0
+ maxTextureSizeSet: 0
+ compressionQualitySet: 0
+ textureFormatSet: 0
+ applyGammaDecoding: 0
+ platformSettings:
+ - serializedVersion: 3
+ buildTarget: DefaultTexturePlatform
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ spriteSheet:
+ serializedVersion: 2
+ sprites: []
+ outline: []
+ physicsShape: []
+ bones: []
+ spriteID:
+ internalID: 0
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ secondaryTextures: []
+ spritePackingTag:
+ pSDRemoveMatte: 0
+ pSDShowRemoveMatteOption: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Materials/Textures/R_controller_DIF.psd b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Materials/Textures/R_controller_DIF.psd
new file mode 100644
index 0000000..50de6fc
Binary files /dev/null and b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Materials/Textures/R_controller_DIF.psd differ
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Materials/Textures/R_controller_DIF.psd.meta b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Materials/Textures/R_controller_DIF.psd.meta
new file mode 100644
index 0000000..580bd0d
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Materials/Textures/R_controller_DIF.psd.meta
@@ -0,0 +1,92 @@
+fileFormatVersion: 2
+guid: 74344c43925f4b84e99b2ffd9d85c035
+TextureImporter:
+ internalIDToNameTable: []
+ externalObjects: {}
+ serializedVersion: 11
+ mipmaps:
+ mipMapMode: 0
+ enableMipMap: 1
+ sRGBTexture: 1
+ linearTexture: 0
+ fadeOut: 0
+ borderMipMap: 0
+ mipMapsPreserveCoverage: 0
+ alphaTestReferenceValue: 0.5
+ mipMapFadeDistanceStart: 1
+ mipMapFadeDistanceEnd: 3
+ bumpmap:
+ convertToNormalMap: 0
+ externalNormalMap: 0
+ heightScale: 0.25
+ normalMapFilter: 0
+ isReadable: 0
+ streamingMipmaps: 0
+ streamingMipmapsPriority: 0
+ grayScaleToAlpha: 0
+ generateCubemap: 6
+ cubemapConvolution: 0
+ seamlessCubemap: 0
+ textureFormat: 1
+ maxTextureSize: 2048
+ textureSettings:
+ serializedVersion: 2
+ filterMode: -1
+ aniso: -1
+ mipBias: -100
+ wrapU: -1
+ wrapV: -1
+ wrapW: -1
+ nPOTScale: 1
+ lightmap: 0
+ compressionQuality: 50
+ spriteMode: 0
+ spriteExtrude: 1
+ spriteMeshType: 1
+ alignment: 0
+ spritePivot: {x: 0.5, y: 0.5}
+ spritePixelsToUnits: 100
+ spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+ spriteGenerateFallbackPhysicsShape: 1
+ alphaUsage: 1
+ alphaIsTransparency: 0
+ spriteTessellationDetail: -1
+ textureType: 0
+ textureShape: 1
+ singleChannelComponent: 0
+ maxTextureSizeSet: 0
+ compressionQualitySet: 0
+ textureFormatSet: 0
+ applyGammaDecoding: 0
+ platformSettings:
+ - serializedVersion: 3
+ buildTarget: DefaultTexturePlatform
+ maxTextureSize: 2048
+ resizeAlgorithm: 0
+ textureFormat: -1
+ textureCompression: 1
+ compressionQuality: 50
+ crunchedCompression: 0
+ allowsAlphaSplitting: 0
+ overridden: 0
+ androidETC2FallbackOverride: 0
+ forceMaximumCompressionQuality_BC6H_BC7: 0
+ spriteSheet:
+ serializedVersion: 2
+ sprites: []
+ outline: []
+ physicsShape: []
+ bones: []
+ spriteID:
+ internalID: 0
+ vertices: []
+ indices:
+ edges: []
+ weights: []
+ secondaryTextures: []
+ spritePackingTag:
+ pSDRemoveMatte: 0
+ pSDShowRemoveMatteOption: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Materials/body.mat b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Materials/body.mat
new file mode 100644
index 0000000..735e25d
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Materials/body.mat
@@ -0,0 +1,77 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!21 &2100000
+Material:
+ serializedVersion: 6
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_Name: body
+ m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
+ m_ShaderKeywords:
+ m_LightmapFlags: 4
+ m_EnableInstancingVariants: 0
+ m_DoubleSidedGI: 0
+ m_CustomRenderQueue: -1
+ stringTagMap: {}
+ disabledShaderPasses: []
+ m_SavedProperties:
+ serializedVersion: 3
+ m_TexEnvs:
+ - _BumpMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _DetailAlbedoMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _DetailMask:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _DetailNormalMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _EmissionMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _MainTex:
+ m_Texture: {fileID: 2800000, guid: 196a35482dee8af47bede1110e5238d3, type: 3}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _MetallicGlossMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _OcclusionMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _ParallaxMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ m_Floats:
+ - _BumpScale: 1
+ - _Cutoff: 0.5
+ - _DetailNormalMapScale: 1
+ - _DstBlend: 0
+ - _GlossMapScale: 1
+ - _Glossiness: 0
+ - _GlossyReflections: 1
+ - _Metallic: 0
+ - _Mode: 0
+ - _OcclusionStrength: 1
+ - _Parallax: 0.02
+ - _SmoothnessTextureChannel: 0
+ - _SpecularHighlights: 1
+ - _SrcBlend: 1
+ - _UVSec: 0
+ - _ZWrite: 1
+ m_Colors:
+ - _Color: {r: 1, g: 1, b: 1, a: 1}
+ - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Materials/body.mat.meta b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Materials/body.mat.meta
new file mode 100644
index 0000000..e8ded53
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Materials/body.mat.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: dc4ce78998ea26f49ae2822739896d1f
+NativeFormatImporter:
+ externalObjects: {}
+ mainObjectFileID: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Materials/gloss.mat b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Materials/gloss.mat
new file mode 100644
index 0000000..5e84ac6
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Materials/gloss.mat
@@ -0,0 +1,78 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!21 &2100000
+Material:
+ serializedVersion: 6
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_Name: gloss
+ m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
+ m_ShaderKeywords: _ALPHAPREMULTIPLY_ON
+ m_LightmapFlags: 4
+ m_EnableInstancingVariants: 0
+ m_DoubleSidedGI: 0
+ m_CustomRenderQueue: 3000
+ stringTagMap:
+ RenderType: Transparent
+ disabledShaderPasses: []
+ m_SavedProperties:
+ serializedVersion: 3
+ m_TexEnvs:
+ - _BumpMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _DetailAlbedoMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _DetailMask:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _DetailNormalMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _EmissionMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _MainTex:
+ m_Texture: {fileID: 2800000, guid: 196a35482dee8af47bede1110e5238d3, type: 3}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _MetallicGlossMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _OcclusionMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _ParallaxMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ m_Floats:
+ - _BumpScale: 1
+ - _Cutoff: 0.5
+ - _DetailNormalMapScale: 1
+ - _DstBlend: 10
+ - _GlossMapScale: 1
+ - _Glossiness: 0
+ - _GlossyReflections: 1
+ - _Metallic: 0
+ - _Mode: 3
+ - _OcclusionStrength: 1
+ - _Parallax: 0.02
+ - _SmoothnessTextureChannel: 0
+ - _SpecularHighlights: 1
+ - _SrcBlend: 1
+ - _UVSec: 0
+ - _ZWrite: 0
+ m_Colors:
+ - _Color: {r: 1, g: 1, b: 1, a: 1}
+ - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Materials/gloss.mat.meta b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Materials/gloss.mat.meta
new file mode 100644
index 0000000..967cdbd
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Materials/gloss.mat.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 81d6471de7ed0204a98dd3ca034c3292
+NativeFormatImporter:
+ externalObjects: {}
+ mainObjectFileID: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Right Touch Controller.fbx b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Right Touch Controller.fbx
new file mode 100644
index 0000000..ceddbde
Binary files /dev/null and b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Right Touch Controller.fbx differ
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Right Touch Controller.fbx.meta b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Right Touch Controller.fbx.meta
new file mode 100644
index 0000000..3f15197
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Model/Right Touch Controller.fbx.meta
@@ -0,0 +1,97 @@
+fileFormatVersion: 2
+guid: 58377a2584075f6419ab14f150c33273
+ModelImporter:
+ serializedVersion: 19301
+ internalIDToNameTable: []
+ externalObjects: {}
+ materials:
+ materialImportMode: 1
+ materialName: 0
+ materialSearch: 1
+ materialLocation: 1
+ animations:
+ legacyGenerateAnimations: 4
+ bakeSimulation: 0
+ resampleCurves: 1
+ optimizeGameObjects: 0
+ motionNodeName:
+ rigImportErrors:
+ rigImportWarnings:
+ animationImportErrors:
+ animationImportWarnings:
+ animationRetargetingWarnings:
+ animationDoRetargetingWarnings: 0
+ importAnimatedCustomProperties: 0
+ importConstraints: 0
+ animationCompression: 1
+ animationRotationError: 0.5
+ animationPositionError: 0.5
+ animationScaleError: 0.5
+ animationWrapMode: 0
+ extraExposedTransformPaths: []
+ extraUserProperties: []
+ clipAnimations: []
+ isReadable: 0
+ meshes:
+ lODScreenPercentages: []
+ globalScale: 1
+ meshCompression: 0
+ addColliders: 0
+ useSRGBMaterialColor: 1
+ sortHierarchyByName: 1
+ importVisibility: 1
+ importBlendShapes: 1
+ importCameras: 1
+ importLights: 1
+ fileIdsGeneration: 2
+ swapUVChannels: 0
+ generateSecondaryUV: 0
+ useFileUnits: 1
+ keepQuads: 0
+ weldVertices: 1
+ preserveHierarchy: 0
+ skinWeightsMode: 0
+ maxBonesPerVertex: 4
+ minBoneWeight: 0.001
+ meshOptimizationFlags: -1
+ indexFormat: 0
+ secondaryUVAngleDistortion: 8
+ secondaryUVAreaDistortion: 15.000001
+ secondaryUVHardAngle: 88
+ secondaryUVPackMargin: 4
+ useFileScale: 1
+ tangentSpace:
+ normalSmoothAngle: 60
+ normalImportMode: 0
+ tangentImportMode: 3
+ normalCalculationMode: 4
+ legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0
+ blendShapeNormalImportMode: 1
+ normalSmoothingSource: 0
+ referencedClips: []
+ importAnimation: 1
+ humanDescription:
+ serializedVersion: 3
+ human: []
+ skeleton: []
+ armTwist: 0.5
+ foreArmTwist: 0.5
+ upperLegTwist: 0.5
+ legTwist: 0.5
+ armStretch: 0.05
+ legStretch: 0.05
+ feetSpacing: 0
+ globalScale: 1
+ rootMotionBoneName:
+ hasTranslationDoF: 0
+ hasExtraRoot: 0
+ skeletonHasParents: 1
+ lastHumanDescriptionAvatarSource: {instanceID: 0}
+ autoGenerateAvatarMappingIfUnspecified: 1
+ animationType: 2
+ humanoidOversampling: 1
+ avatarSetup: 0
+ additionalBone: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Oculus.cs b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Oculus.cs
new file mode 100644
index 0000000..a66e469
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Oculus.cs
@@ -0,0 +1,314 @@
+using UnityEngine;
+using Passer.Humanoid;
+
+namespace Passer.Tracking {
+
+ ///
+ /// The Oculus Device
+ ///
+ public class Oculus : TrackerComponent {
+#if hOCULUS
+ public bool persistentTracking;
+ public RealWorldConfiguration realWorldConfiguration;
+
+ #region Manage
+ /*
+ ///
+ /// Find an Oculus Tracker
+ ///
+ ///
+ ///
+ public static OculusTracker Find(Transform parentTransform) {
+ OculusTracker oculus = parentTransform.GetComponentInChildren();
+ if (oculus != null)
+ return oculus;
+
+ oculus = FindObjectOfType();
+ return oculus;
+ }
+
+ ///
+ /// Find or create a new Oculus Tracker
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static OculusTracker Get(Transform parentTransform, Vector3 position, Quaternion rotation) {
+ OculusTracker oculus = Find(parentTransform);
+ if (oculus != null)
+ return oculus;
+
+ if (Application.isPlaying) {
+ Debug.LogError("Oculus is missing");
+ return null;
+ }
+ #if UNITY_EDITOR
+ GameObject trackerObj = new GameObject("Oculus");
+ Transform trackerTransform = trackerObj.transform;
+
+ trackerTransform.parent = parentTransform;
+ trackerTransform.position = position;
+ trackerTransform.rotation = rotation;
+
+ oculus = trackerTransform.gameObject.AddComponent();
+ oculus.realWorld = parentTransform;
+
+ #endif
+ return oculus;
+ }
+ */
+#if hOCHAND
+ public HandSkeleton FindHandTrackingSkeleton(bool isLeft) {
+ HandSkeleton[] handSkeletons = GetComponentsInChildren();
+ foreach (HandSkeleton handSkeleton in handSkeletons) {
+ if (handSkeleton.isLeft == isLeft)
+ return handSkeleton;
+ }
+ return null;
+ }
+
+
+ public HandSkeleton leftHandSkeleton {
+ get { return FindHandTrackingSkeleton(true); }
+ }
+ public HandSkeleton rightHandSkeleton {
+ get { return FindHandTrackingSkeleton(false); }
+ }
+#endif
+ public override void ShowSkeleton(bool shown) {
+#if hOCHAND
+ if (leftHandSkeleton != null)
+ leftHandSkeleton.show = shown;
+ if (rightHandSkeleton != null)
+ rightHandSkeleton.show = shown;
+#endif
+ }
+
+ ///
+ /// Find an Oculus tracker
+ ///
+ /// The parent transform of the tracker
+ /// The tracker
+ public static Oculus Find(Transform parentTransform) {
+ Oculus oculus = parentTransform.GetComponentInChildren();
+ if (oculus != null)
+ return oculus;
+
+ return null;
+ }
+
+ ///
+ /// Find or create a new SteamVR tracker
+ ///
+ /// The parent transform for the tracker
+ /// The world position of the tracker
+ /// The world rotation of the tracker
+ /// The tracker
+ public static Oculus Get(Transform parentTransform, Vector3 position, Quaternion rotation) {
+ Oculus oculus = Find(parentTransform);
+ if (oculus == null) {
+ GameObject trackerObj = new GameObject(nameof(Oculus));
+ Transform trackerTransform = trackerObj.transform;
+
+ trackerTransform.parent = parentTransform;
+ trackerTransform.position = position;
+ trackerTransform.rotation = rotation;
+
+ oculus = trackerObj.AddComponent();
+ oculus.realWorld = parentTransform;
+ }
+ return oculus;
+ }
+
+ #region Hmd
+
+ protected OculusHmd _hmd;
+ public OculusHmd hmd {
+ get {
+ if (_hmd != null)
+ return _hmd;
+
+ _hmd = this.GetComponentInChildren();
+ if (_hmd != null)
+ return _hmd;
+
+ _hmd = FindObjectOfType();
+ return _hmd;
+ }
+ }
+
+ public OculusHmd GetHmd(Vector3 position, Quaternion rotation) {
+ if (hmd == null) {
+ GameObject sensorObj = new GameObject("Hmd");
+ Transform sensorTransform = sensorObj.transform;
+
+ sensorTransform.parent = this.transform;
+ sensorTransform.position = position;
+ sensorTransform.rotation = rotation;
+
+ _hmd = sensorTransform.gameObject.AddComponent();
+
+ _hmd.unityCamera = _hmd.GetComponent();
+ if (_hmd.unityCamera == null) {
+ _hmd.unityCamera = _hmd.gameObject.AddComponent();
+ _hmd.unityCamera.nearClipPlane = 0.05F;
+
+ _hmd.gameObject.AddComponent();
+ }
+ AddScreenFader(_hmd.unityCamera);
+ }
+
+ return _hmd;
+ }
+
+ protected static void AddScreenFader(Camera camera) {
+ if (camera == null)
+ return;
+
+ Transform planeTransform = camera.transform.Find("Fader");
+ if (planeTransform != null)
+ return;
+
+ GameObject plane = GameObject.CreatePrimitive(PrimitiveType.Plane);
+ plane.transform.name = "Fader";
+ plane.transform.parent = camera.transform;
+ plane.transform.localEulerAngles = new Vector3(-90, 0, 0);
+ plane.transform.localPosition = new Vector3(0, 0, camera.nearClipPlane + 0.01F);
+
+ Renderer renderer = plane.GetComponent();
+ if (renderer != null) {
+ Shader fadeShader = Shader.Find("Standard");
+ Material fadeMaterial = new Material(fadeShader);
+ fadeMaterial.name = "FadeMaterial";
+ fadeMaterial.SetFloat("_Mode", 2);
+ fadeMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
+ fadeMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
+ fadeMaterial.SetInt("_ZWrite", 0);
+ fadeMaterial.DisableKeyword("_ALPHATEST_ON");
+ fadeMaterial.EnableKeyword("_ALPHABLEND_ON");
+ fadeMaterial.DisableKeyword("_ALPHAPREMULTIPLY_ON");
+ fadeMaterial.renderQueue = 3000;
+ Color color = Color.black;
+ color.a = 0.0F;
+ fadeMaterial.SetColor("_Color", new Color(0, 0, 0, 0));
+ renderer.material = fadeMaterial;
+ renderer.enabled = false;
+ }
+
+ Collider c = plane.GetComponent();
+ Object.DestroyImmediate(c);
+ }
+
+ #endregion
+
+
+ #region Controller
+
+ ///
+ /// Find an OpenVR Controller
+ ///
+ /// Looking for the left-handed controller?
+ /// The controller or null when it has not been found
+ public OculusController FindController(bool isLeft) {
+ OculusController[] controllers = GetComponentsInChildren();
+ foreach (OculusController controller in controllers) {
+ if (controller.isLeft == isLeft)
+ return controller;
+ }
+ return null;
+ }
+
+ public OculusController GetController(bool isLeft, Vector3 position, Quaternion rotation) {
+ OculusController controller = FindController(isLeft);
+ if (controller == null) {
+ GameObject controllerObject = new GameObject(isLeft ? "Left Oculus Controller" : "Right Oculus Controller");
+ Transform controllerTransform = controllerObject.transform;
+
+ controllerTransform.parent = this.transform;
+ controllerTransform.position = position;
+ controllerTransform.rotation = rotation;
+
+ controller = controllerObject.AddComponent();
+ controller.tracker = this;
+ controller.isLeft = isLeft;
+
+ string prefabLeftName = "Left Touch Controller";
+ string prefabRightName = "Right Touch Controller";
+ string resourceName = isLeft ? prefabLeftName : prefabRightName;
+ Object controllerPrefab = Resources.Load(resourceName);
+ if (controllerPrefab != null) {
+ GameObject sensorObject = (GameObject)Object.Instantiate(controllerPrefab);
+ sensorObject.transform.parent = controllerTransform;
+ sensorObject.transform.localPosition = Vector3.zero;
+ sensorObject.transform.localRotation = Quaternion.identity;
+ }
+ else
+ Debug.LogWarning("Oculus Controller model could not be found in the Resources");
+ }
+ return controller;
+ }
+
+ #endregion Controller
+
+ #endregion
+
+ #region Start
+
+ protected override void Start() {
+ base.Start();
+
+ OculusDevice.Start();
+ }
+ /*
+ protected override void Start() {
+ if (!persistentTracking)
+ transform.localPosition = new Vector3(0, Humanoid.Tracking.OculusDevice.eyeHeight, 0);
+ }
+
+ protected virtual void OnEnable() {
+ if (!persistentTracking)
+ return;
+
+ if (realWorldConfiguration == null) {
+ Debug.LogError("Could not find Real World Configuration");
+ return;
+ }
+
+ RealWorldConfiguration.TrackingSpace trackingSpace =
+ realWorldConfiguration.trackers.Find(space => space.trackerId == TrackerId.Oculus);
+
+ if (trackingSpace == null)
+ return;
+
+ transform.position = trackingSpace.position;
+ transform.rotation = trackingSpace.rotation;
+ }
+
+ protected virtual void OnDestroy() {
+ if (!persistentTracking)
+ return;
+
+ if (realWorldConfiguration == null) {
+ Debug.LogError("Could not find Real World Configuration");
+ return;
+ }
+
+ RealWorldConfiguration.TrackingSpace trackingSpace =
+ realWorldConfiguration.trackers.Find(space => space.trackerId == TrackerId.Oculus);
+
+ if (trackingSpace == null) {
+ trackingSpace = new RealWorldConfiguration.TrackingSpace();
+ realWorldConfiguration.trackers.Add(trackingSpace);
+ }
+ trackingSpace.position = transform.position;
+ trackingSpace.rotation = transform.rotation;
+ }
+ */
+
+ #endregion
+
+#endif
+ }
+
+}
\ No newline at end of file
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Oculus.cs.meta b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Oculus.cs.meta
new file mode 100644
index 0000000..9d0cac9
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Oculus.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 57a3d484a71616f4aab0563d70ea65ef
+timeCreated: 1557221210
+licenseType: Free
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/OculusController.cs b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/OculusController.cs
new file mode 100644
index 0000000..e29e856
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/OculusController.cs
@@ -0,0 +1,176 @@
+using UnityEngine;
+
+namespace Passer.Tracking {
+ using Passer.Humanoid;
+ using Passer.Humanoid.Tracking;
+
+ ///
+ /// An Oculus controller
+ ///
+ // Base this on UnityXRController in the future?
+ public class OculusController : ControllerComponent {
+#if hOCULUS
+ public TrackerComponent tracker;
+
+ //public bool isLeft;
+
+ //public Vector3 joystick;
+ //public float indexTrigger;
+ //public float handTrigger;
+ //public float buttonAX;
+ //public float buttonBY;
+ //public float option;
+ //public float thumbrest;
+
+ public bool positionalTracking = true;
+
+ public override bool show {
+ set {
+ if (value == true && !_show) {
+ Renderer[] renderers = this.GetComponentsInChildren();
+ foreach (Renderer renderer in renderers) {
+ if (!(renderer is LineRenderer))
+ renderer.enabled = true;
+ }
+
+ _show = true;
+ }
+ else if (value == false && _show) {
+ Renderer[] renderers = this.GetComponentsInChildren();
+ foreach (Renderer renderer in renderers) {
+ if (!(renderer is LineRenderer))
+ renderer.enabled = false;
+ }
+
+ _show = false;
+ }
+ }
+ get {
+ return _show;
+ }
+ }
+
+ public override void UpdateComponent() {
+ status = Tracker.Status.Tracking;
+ if (OculusDevice.status == Tracker.Status.Unavailable)
+ status = Tracker.Status.Unavailable;
+
+ if (trackerTransform == null)
+ trackerTransform = this.trackerTransform.parent;
+
+ Sensor.ID sensorID = isLeft ? Sensor.ID.LeftHand : Sensor.ID.RightHand;
+
+ if (OculusDevice.GetRotationalConfidence(sensorID) == 0)
+ status = Tracker.Status.Present;
+
+ if (status == Tracker.Status.Present || status == Tracker.Status.Unavailable) {
+ positionConfidence = 0;
+ rotationConfidence = 0;
+ //gameObject.SetActive(false);
+ show = false;
+ return;
+ }
+
+ Vector3 localSensorPosition = HumanoidTarget.ToVector3(OculusDevice.GetPosition(sensorID));
+ transform.position = trackerTransform.TransformPoint(localSensorPosition);
+
+ Quaternion localSensorRotation = HumanoidTarget.ToQuaternion(OculusDevice.GetRotation(sensorID));
+ transform.rotation = trackerTransform.rotation * localSensorRotation;
+
+ positionConfidence = OculusDevice.GetPositionalConfidence(sensorID);
+ rotationConfidence = OculusDevice.GetRotationalConfidence(sensorID);
+ //gameObject.SetActive(true);
+ show = true;
+
+ UpdateInput(sensorID);
+ }
+
+ private void UpdateInput(Sensor.ID sensorID) {
+ switch (sensorID) {
+ case Sensor.ID.LeftHand:
+ UpdateLeftInput();
+ return;
+ case Sensor.ID.RightHand:
+ UpdateRightInput();
+ return;
+ default:
+ return;
+ }
+ }
+
+ private void UpdateLeftInput() {
+ OculusDevice.Controller controllerMask;
+
+#if !UNITY_EDITOR
+ if (!positionalTracking)
+ controllerMask = OculusDevice.Controller.LTrackedRemote;
+ else
+#endif
+ controllerMask = OculusDevice.Controller.LTouch;
+
+ OculusDevice.ControllerState4 controllerState = OculusDevice.GetControllerState(controllerMask);
+
+ float stickButton =
+ OculusDevice.GetStickPress(controllerState) ? 1 : (
+ OculusDevice.GetStickTouch(controllerState) ? 0 : -1);
+ primaryAxis = new Vector3(
+ OculusDevice.GetHorizontalStick(controllerState, true),
+ OculusDevice.GetVerticalStick(controllerState, true),
+ stickButton);
+
+ trigger1 = OculusDevice.GetTrigger1(controllerState, true);
+ trigger2 = OculusDevice.GetTrigger2(controllerState, true);
+
+ button1 =
+ OculusDevice.GetButton1Press(controllerState) ? 1 : (
+ OculusDevice.GetButton1Touch(controllerState) ? 0 : -1);
+ button2 =
+ OculusDevice.GetButton2Press(controllerState) ? 1 : (
+ OculusDevice.GetButton2Touch(controllerState) ? 0 : -1);
+ button3 =
+ OculusDevice.GetThumbRest(controllerState) ? 0 : -1;
+ option =
+ OculusDevice.GetButtonOptionPress(controllerState) ? 1 : 0;
+ }
+
+ private void UpdateRightInput() {
+ OculusDevice.Controller controllerMask;
+#if !UNITY_EDITOR
+ if (!positionalTracking)
+ controllerMask = OculusDevice.Controller.RTrackedRemote;
+ else
+#endif
+ controllerMask = OculusDevice.Controller.RTouch;
+
+ OculusDevice.ControllerState4 controllerState = OculusDevice.GetControllerState(controllerMask);
+
+ float stickButton =
+ OculusDevice.GetStickPress(controllerState) ? 1 : (
+ OculusDevice.GetStickTouch(controllerState) ? 0 : -1);
+ primaryAxis = new Vector3(
+ OculusDevice.GetHorizontalStick(controllerState, false),
+ OculusDevice.GetVerticalStick(controllerState, false),
+ stickButton);
+
+ trigger1 = OculusDevice.GetTrigger1(controllerState, false);
+ trigger2 = OculusDevice.GetTrigger2(controllerState, false);
+
+ button1 =
+ OculusDevice.GetButton1Press(controllerState) ? 1 : (
+ OculusDevice.GetButton1Touch(controllerState) ? 0 : -1);
+ button2 =
+ OculusDevice.GetButton2Press(controllerState) ? 1 : (
+ OculusDevice.GetButton2Touch(controllerState) ? 0 : -1);
+ option =
+ 0;
+ button3 =
+ OculusDevice.GetThumbRest(controllerState) ? 0 : -1;
+ }
+
+ public void Vibrate(float length, float strength) {
+ Sensor.ID sensorID = isLeft ? Sensor.ID.LeftHand : Sensor.ID.RightHand;
+ OculusDevice.Vibrate(sensorID, length, strength);
+ }
+#endif
+ }
+}
\ No newline at end of file
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/OculusController.cs.meta b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/OculusController.cs.meta
new file mode 100644
index 0000000..d9d5db8
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/OculusController.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 6235e438f770bf44285b28080c623d34
+timeCreated: 1536227072
+licenseType: Free
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/OculusDevice.cs b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/OculusDevice.cs
new file mode 100644
index 0000000..402e65e
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/OculusDevice.cs
@@ -0,0 +1,1079 @@
+using System.IO;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+
+namespace Passer.Tracking {
+ using Passer.Humanoid;
+ using Passer.Humanoid.Tracking;
+
+ public static class OculusDevice {
+ public const string name = "Oculus";
+
+ #region Versions
+
+ private static System.Version _version;
+ public static System.Version version {
+ get {
+ string pluginVersion = ovrp_GetVersion();
+
+ if (pluginVersion != null) {
+ // Truncate unsupported trailing version info for System.Version. Original string is returned if not present.
+ pluginVersion = pluginVersion.Split('-')[0];
+ _version = new System.Version(pluginVersion);
+ }
+ else
+ _version = new System.Version(0, 0, 0);
+ return _version;
+ }
+
+ }
+
+ public static readonly System.Version version_1_16_0 = new System.Version(1, 16, 0);
+
+ #endregion
+
+ public static Tracking.Tracker.Status status;
+
+ private static Sensor.State[] sensorStates;
+
+ public static void Start() {
+ status = Tracking.Tracker.Status.Unavailable;
+
+ string pluginVersion = ovrp_GetVersion();
+
+ if (pluginVersion != null) {
+ // Truncate unsupported trailing version info for System.Version. Original string is returned if not present.
+ pluginVersion = pluginVersion.Split('-')[0];
+ _version = new System.Version(pluginVersion);
+ }
+ else
+ _version = new System.Version(0, 0, 0);
+ UnityEngine.Debug.Log("oculus version: " + _version);
+
+ sensorStates = new Sensor.State[(int)Sensor.ID.Count];
+ sensorStates[(int)Sensor.ID.Head].sensorID = (int)Node.Head;
+ sensorStates[(int)Sensor.ID.LeftHand].sensorID = (int)Node.HandLeft;
+ sensorStates[(int)Sensor.ID.RightHand].sensorID = (int)Node.HandRight;
+ sensorStates[(int)Sensor.ID.Hips].sensorID = -1;
+ sensorStates[(int)Sensor.ID.LeftFoot].sensorID = -1;
+ sensorStates[(int)Sensor.ID.RightFoot].sensorID = -1;
+ sensorStates[(int)Sensor.ID.Tracker1].sensorID = (int)Node.TrackerZero;
+ sensorStates[(int)Sensor.ID.Tracker2].sensorID = (int)Node.TrackerOne;
+ sensorStates[(int)Sensor.ID.Tracker3].sensorID = (int)Node.TrackerTwo;
+ sensorStates[(int)Sensor.ID.Tracker4].sensorID = (int)Node.TrackerThree;
+
+ // Initial filling of values
+ Update();
+ }
+
+ public static void Update() {
+ if (sensorStates == null)
+ return;
+
+ for (int i = 0; i < sensorStates.Length; i++) {
+ if (sensorStates[i].sensorID < 0)
+ continue;
+
+ sensorStates[i].present = (ovrp_GetNodePresent(sensorStates[i].sensorID) == Bool.True);
+ sensorStates[i].confidence = (ovrp_GetNodeOrientationTracked(sensorStates[i].sensorID) == Bool.True) ? 1 : 0;
+
+ if (sensorStates[i].confidence > 0)
+ status = Tracking.Tracker.Status.Tracking;
+
+ Pose pose = ovrp_GetNodePoseState(Step.Render, sensorStates[i].sensorID).Pose;
+ sensorStates[i].position = new Vector(pose.Position.x, pose.Position.y + eyeHeight, -pose.Position.z);
+ sensorStates[i].rotation = new Rotation(-pose.Orientation.x, -pose.Orientation.y, pose.Orientation.z, pose.Orientation.w);
+ }
+ }
+
+ public static bool userPresent {
+ get {
+ return ovrp_GetUserPresent() == Bool.True;
+ }
+ }
+
+ public static bool positionalTracking {
+ set {
+ ovrp_SetTrackingPositionEnabled(value ? Bool.True : Bool.False);
+ }
+ }
+ public static Pose GetPose(int sensorID) {
+ return ovrp_GetNodePoseState(Step.Render, sensorID).Pose;
+ }
+
+ public static Vector GetPosition(Sensor.ID sensorID) {
+ if (sensorStates == null)
+ return Vector.zero;
+
+ return sensorStates[(int)sensorID].position;
+ }
+
+ public static Rotation GetRotation(Sensor.ID sensorID) {
+ if (sensorStates == null)
+ return Rotation.identity;
+
+ return sensorStates[(int)sensorID].rotation;
+ }
+
+ public static float GetPositionalConfidence(Sensor.ID sensorID) {
+ if (sensorStates == null)
+ return 0;
+
+ return (ovrp_GetNodePositionTracked(sensorStates[(int)sensorID].sensorID) == Bool.True) ? 0.99F : 0;
+ }
+
+ public static float GetRotationalConfidence(Sensor.ID sensorID) {
+ if (sensorStates == null)
+ return 0;
+
+ if (ovrp_GetNodePositionTracked(sensorStates[(int)sensorID].sensorID) == Bool.True)
+ return sensorStates[(int)sensorID].confidence;
+ else
+ return sensorStates[(int)sensorID].confidence * 0.9F; // without positional tracking, there is no drift correction
+ }
+
+ public static bool IsPresent(Sensor.ID sensorID) {
+ if (sensorStates == null)
+ return false;
+
+ return sensorStates[(int)sensorID].present;
+ }
+
+ public static float GetConfidence(int sensorID) {
+ return (ovrp_GetNodeOrientationTracked(sensorID) == Bool.True) ? 1 : 0;
+ }
+
+ public static void GetControllerInput(Sensor.ID sensorID, ref ControllerButtons input) {
+ Controller controllerMask;
+ switch (sensorID) {
+ case Sensor.ID.LeftHand:
+#if UNITY_ANDROID
+ controllerMask = Controller.LTrackedRemote;
+#else
+ controllerMask = Controller.LTouch;
+#endif
+ break;
+ case Sensor.ID.RightHand:
+#if UNITY_ANDROID
+ controllerMask = Controller.RTrackedRemote;
+#else
+ controllerMask = Controller.RTouch;
+#endif
+ break;
+ default:
+ return;
+ }
+ bool isLeft = (sensorID == Sensor.ID.LeftHand);
+
+ ControllerState4 controllerState = GetControllerState(controllerMask);
+
+ input.stickHorizontal = GetHorizontalStick(controllerState, isLeft);
+ input.stickVertical = GetVerticalStick(controllerState, isLeft);
+ input.stickPress = GetStickPress(controllerState);
+ input.stickTouch = GetStickTouch(controllerState);
+
+ input.buttons[0] = GetButton1Press(controllerState);
+ input.buttons[1] = GetButton2Press(controllerState);
+
+ input.trigger1 = GetTrigger1(controllerState, isLeft);
+ input.trigger2 = GetTrigger2(controllerState, isLeft);
+
+ input.up = (input.stickVertical > 0.3F);
+ input.down = (input.stickVertical < -0.3F);
+ input.left = (input.stickHorizontal < -0.3F);
+ input.right = (input.stickHorizontal > 0.3F);
+ }
+
+ public static ControllerState4 GetControllerState(OculusDevice.Controller controllerMask) {
+ ControllerState4 controllerState;
+ if (_version < version_1_16_0) {
+ ControllerState2 controllerState2 = ovrp_GetControllerState2((uint)controllerMask);
+ controllerState = new ControllerState4(controllerState2);
+ }
+ else {
+ controllerState = new ControllerState4();
+ ovrp_GetControllerState4((uint)controllerMask, ref controllerState);
+ }
+ return controllerState;
+ }
+
+ public static float GetHorizontalStick(ControllerState4 controllerState, bool isLeft) {
+ float stickHorizontalValue = isLeft ? controllerState.LThumbstick.x : controllerState.RThumbstick.x;
+ return stickHorizontalValue;
+ }
+
+ public static float GetVerticalStick(ControllerState4 controllerState, bool isLeft) {
+ float stickVerticalValue = isLeft ? controllerState.LThumbstick.y : controllerState.RThumbstick.y;
+ return stickVerticalValue;
+ }
+
+ public static float GetHorizontalTouch(ControllerState4 controllerState, bool isLeft) {
+ float stickHorizontalValue = isLeft ? controllerState.LTouchpad.x : controllerState.RTouchpad.x;
+ return stickHorizontalValue;
+ }
+
+ public static float GetVerticalTouch(ControllerState4 controllerState, bool isLeft) {
+ float stickVerticalValue = isLeft ? controllerState.LTouchpad.y : controllerState.RTouchpad.y;
+ return stickVerticalValue;
+ }
+ public static bool GetStickPress(ControllerState4 controllerState) {
+ RawButton stickButton = RawButton.LThumbstick | RawButton.RThumbstick;
+ bool stickButtonValue = (controllerState.Buttons & (uint)stickButton) != 0;
+ return stickButtonValue;
+ }
+
+ public static bool GetStickTouch(ControllerState4 controllerState) {
+ RawTouch stickTouch = RawTouch.LThumbstick | RawTouch.RThumbstick;
+ bool stickTouchValue = (controllerState.Touches & (uint)stickTouch) != 0;
+ return stickTouchValue;
+ }
+
+ public static bool GetButton1Press(ControllerState4 controllerState) {
+ uint button = (uint)RawButton.X | (uint)RawButton.A;
+ bool buttonValue = (controllerState.Buttons & button) != 0;
+ return buttonValue;
+ }
+
+ public static bool GetButton1Touch(ControllerState4 controllerState) {
+ uint button = (uint)RawTouch.X | (uint)RawTouch.A;
+ bool buttonTouchValue = (controllerState.Touches & button) != 0;
+ return buttonTouchValue;
+ }
+
+ public static bool GetButton2Press(ControllerState4 controllerState) {
+ uint button = (uint)RawButton.Y | (uint)RawButton.B;
+ bool buttonValue = (controllerState.Buttons & button) != 0;
+ return buttonValue;
+ }
+
+ public static bool GetButton2Touch(ControllerState4 controllerState) {
+ uint button = (uint)RawTouch.Y | (uint)RawTouch.B;
+ bool buttonTouchValue = (controllerState.Touches & button) != 0;
+ return buttonTouchValue;
+ }
+
+ // always give true... Maybe because I'm using an engineering sample?
+ public static bool GetButton2Near(ControllerState4 controllerState) {
+ uint mask = (uint)RawNearTouch.LThumbButtons | (uint)RawNearTouch.RThumbButtons;
+ bool isNear = (controllerState.NearTouches & mask) != 0;
+ return isNear;
+ }
+
+ public static bool GetButtonOptionPress(ControllerState4 controllerState) {
+ uint button = (uint)RawButton.Back | (uint)RawButton.Start;
+ bool buttonValue = (controllerState.Buttons & button) != 0;
+ return buttonValue;
+ }
+
+ public static float GetTrigger1(ControllerState4 controllerState, bool isLeft) {
+ float trigger1Value = isLeft ? controllerState.LIndexTrigger : controllerState.RIndexTrigger;
+
+ // always give true... Maybe because I'm using an engineering sample?
+ //uint nearId = (uint)RawNearTouch.LIndexTrigger | (uint)RawNearTouch.RIndexTrigger;
+ //bool trigger1Near = (controllerState.NearTouches & nearId) != 0;
+
+ uint touchId = (uint)RawTouch.LIndexTrigger | (uint)RawTouch.RIndexTrigger;
+ bool trigger1Touch = (controllerState.Touches & touchId) != 0;
+ if (!trigger1Touch)
+ trigger1Value = -1F;
+
+ return trigger1Value;
+ }
+
+ public static float GetTrigger2(ControllerState4 controllerState, bool isLeft) {
+ float trigger2Value = isLeft ? controllerState.LHandTrigger : controllerState.RHandTrigger;
+ return trigger2Value;
+ }
+
+ public static bool GetThumbRest(ControllerState4 controllerState) {
+ RawTouch touchMask = RawTouch.LThumbRest | RawTouch.RThumbRest;
+ bool touch = (controllerState.Touches & (uint)touchMask) != 0;
+ return touch;
+ }
+
+ public static bool GetSkeleton(bool isLeft, out Skeleton skeleton) {
+ return GetSkeleton(isLeft ? SkeletonType.HandLeft : SkeletonType.HandRight, out skeleton);
+ }
+ public static bool GetSkeleton(SkeletonType skeletonType, out Skeleton skeleton) {
+#if OVRPLUGIN_UNSUPPORTED_PLATFORM
+ skeleton = default(Skeleton);
+ return false;
+#else
+ if (_version >= OVRP_1_44_0.version) {
+ return OVRP_1_44_0.ovrp_GetSkeleton(skeletonType, out skeleton) == Result.Success;
+ }
+ else {
+ skeleton = default(Skeleton);
+ return false;
+ }
+#endif
+ }
+
+ public static UnityEngine.Quaternion GetSkeletonBoneRotation(Bone bone) {
+ return new UnityEngine.Quaternion(-bone.Pose.Orientation.x, -bone.Pose.Orientation.y, bone.Pose.Orientation.z, bone.Pose.Orientation.w);
+ }
+
+ public static UnityEngine.Vector3 GetSkeletonBonePosition(Bone bone) {
+ return new UnityEngine.Vector3(bone.Pose.Position.x, bone.Pose.Position.y, -bone.Pose.Position.z);
+ }
+
+ private static HandStateInternal cachedHandState = new HandStateInternal();
+ public static bool GetHandState(Step stepId, Hand hand, ref HandState handState) {
+#if OVRPLUGIN_UNSUPPORTED_PLATFORM
+ return false;
+#else
+ if (_version >= OVRP_1_44_0.version) {
+ Result res = OVRP_1_44_0.ovrp_GetHandState(stepId, hand, out cachedHandState);
+ if (res == Result.Success) {
+ // attempt to avoid allocations if client provides appropriately pre-initialized HandState
+ if (handState.BoneRotations == null || handState.BoneRotations.Length != ((int)BoneId.Hand_End - (int)BoneId.Hand_Start)) {
+ handState.BoneRotations = new Quatf[(int)BoneId.Hand_End - (int)BoneId.Hand_Start];
+ }
+ if (handState.PinchStrength == null || handState.PinchStrength.Length != (int)HandFinger.Max) {
+ handState.PinchStrength = new float[(int)HandFinger.Max];
+ }
+ if (handState.FingerConfidences == null || handState.FingerConfidences.Length != (int)HandFinger.Max) {
+ handState.FingerConfidences = new TrackingConfidence[(int)HandFinger.Max];
+ }
+
+ // unrolling the arrays is necessary to avoid per-frame allocations during marshaling
+ handState.Status = cachedHandState.Status;
+ handState.RootPose = cachedHandState.RootPose;
+ handState.BoneRotations[0] = cachedHandState.BoneRotations_0;
+ handState.BoneRotations[1] = cachedHandState.BoneRotations_1;
+ handState.BoneRotations[2] = cachedHandState.BoneRotations_2;
+ handState.BoneRotations[3] = cachedHandState.BoneRotations_3;
+ handState.BoneRotations[4] = cachedHandState.BoneRotations_4;
+ handState.BoneRotations[5] = cachedHandState.BoneRotations_5;
+ handState.BoneRotations[6] = cachedHandState.BoneRotations_6;
+ handState.BoneRotations[7] = cachedHandState.BoneRotations_7;
+ handState.BoneRotations[8] = cachedHandState.BoneRotations_8;
+ handState.BoneRotations[9] = cachedHandState.BoneRotations_9;
+ handState.BoneRotations[10] = cachedHandState.BoneRotations_10;
+ handState.BoneRotations[11] = cachedHandState.BoneRotations_11;
+ handState.BoneRotations[12] = cachedHandState.BoneRotations_12;
+ handState.BoneRotations[13] = cachedHandState.BoneRotations_13;
+ handState.BoneRotations[14] = cachedHandState.BoneRotations_14;
+ handState.BoneRotations[15] = cachedHandState.BoneRotations_15;
+ handState.BoneRotations[16] = cachedHandState.BoneRotations_16;
+ handState.BoneRotations[17] = cachedHandState.BoneRotations_17;
+ handState.BoneRotations[18] = cachedHandState.BoneRotations_18;
+ handState.BoneRotations[19] = cachedHandState.BoneRotations_19;
+ handState.BoneRotations[20] = cachedHandState.BoneRotations_20;
+ handState.BoneRotations[21] = cachedHandState.BoneRotations_21;
+ handState.BoneRotations[22] = cachedHandState.BoneRotations_22;
+ handState.BoneRotations[23] = cachedHandState.BoneRotations_23;
+ handState.Pinches = cachedHandState.Pinches;
+ handState.PinchStrength[0] = cachedHandState.PinchStrength_0;
+ handState.PinchStrength[1] = cachedHandState.PinchStrength_1;
+ handState.PinchStrength[2] = cachedHandState.PinchStrength_2;
+ handState.PinchStrength[3] = cachedHandState.PinchStrength_3;
+ handState.PinchStrength[4] = cachedHandState.PinchStrength_4;
+ handState.PointerPose = cachedHandState.PointerPose;
+ handState.HandScale = cachedHandState.HandScale;
+ handState.HandConfidence = cachedHandState.HandConfidence;
+ handState.FingerConfidences[0] = cachedHandState.FingerConfidences_0;
+ handState.FingerConfidences[1] = cachedHandState.FingerConfidences_1;
+ handState.FingerConfidences[2] = cachedHandState.FingerConfidences_2;
+ handState.FingerConfidences[3] = cachedHandState.FingerConfidences_3;
+ handState.FingerConfidences[4] = cachedHandState.FingerConfidences_4;
+ handState.RequestedTimeStamp = cachedHandState.RequestedTimeStamp;
+ handState.SampleTimeStamp = cachedHandState.SampleTimeStamp;
+
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ else {
+ return false;
+ }
+#endif
+ }
+
+ public static void Vibrate(Sensor.ID sensorID, float length, float strength) {
+ Controller controllerMask;
+ switch (sensorID) {
+ case Sensor.ID.LeftHand:
+ controllerMask = Controller.LTouch;
+ break;
+ case Sensor.ID.RightHand:
+ controllerMask = Controller.RTouch;
+ break;
+ default:
+ return;
+ }
+ ovrp_SetControllerVibration((uint)controllerMask, 0.5F, strength);
+ }
+
+ public static float eyeHeight {
+ get { return ovrp_GetUserEyeHeight(); }
+ }
+
+ #region DataTypes
+ public enum RawNearTouch {
+ None = 0, ///< Maps to Physical NearTouch: [Gamepad, Touch, LTouch, RTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: None]
+ LIndexTrigger = 0x00000001, ///< Maps to Physical NearTouch: [Touch, LTouch: Implies finger is in close proximity to LIndexTrigger.], [Gamepad, RTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: None]
+ LThumbButtons = 0x00000002, ///< Maps to Physical NearTouch: [Touch, LTouch: Implies thumb is in close proximity to LThumbstick OR X/Y buttons.], [Gamepad, RTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: None]
+ RIndexTrigger = 0x00000004, ///< Maps to Physical NearTouch: [Touch, RTouch: Implies finger is in close proximity to RIndexTrigger.], [Gamepad, LTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: None]
+ RThumbButtons = 0x00000008, ///< Maps to Physical NearTouch: [Touch, RTouch: Implies thumb is in close proximity to RThumbstick OR A/B buttons.], [Gamepad, LTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: None]
+ Any = ~None, ///< Maps to Physical NearTouch: [Touch, LTouch, RTouch: Any], [Gamepad, LTrackedRemote, RTrackedRemote, Touchpad, Remote: None]
+ }
+
+ public enum RawTouch {
+ None = 0, ///< Maps to Physical Touch: [Gamepad, Touch, LTouch, RTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: None]
+ A = RawButton.A, ///< Maps to Physical Touch: [Touch, RTouch: A], [Gamepad, LTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: None]
+ B = RawButton.B, ///< Maps to Physical Touch: [Touch, RTouch: B], [Gamepad, LTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: None]
+ X = RawButton.X, ///< Maps to Physical Touch: [Touch, LTouch: X], [Gamepad, RTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: None]
+ Y = RawButton.Y, ///< Maps to Physical Touch: [Touch, LTouch: Y], [Gamepad, RTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: None]
+ LIndexTrigger = 0x00001000, ///< Maps to Physical Touch: [Touch, LTouch: LIndexTrigger], [Gamepad, RTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: None]
+ LThumbstick = RawButton.LThumbstick, ///< Maps to Physical Touch: [Touch, LTouch: LThumbstick], [Gamepad, RTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: None]
+ LThumbRest = 0x00000800, ///< Maps to Physical Touch: [Touch, LTouch: LThumbRest], [Gamepad, RTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: None]
+ LTouchpad = RawButton.LTouchpad, ///< Maps to Physical Touch: [LTrackedRemote, Touchpad: LTouchpad], [Gamepad, Touch, LTouch, RTouch, RTrackedRemote, Remote: None]
+ RIndexTrigger = 0x00000010, ///< Maps to Physical Touch: [Touch, RTouch: RIndexTrigger], [Gamepad, LTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: None]
+ RThumbstick = RawButton.RThumbstick, ///< Maps to Physical Touch: [Touch, RTouch: RThumbstick], [Gamepad, LTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: None]
+ RThumbRest = 0x00000008, ///< Maps to Physical Touch: [Touch, RTouch: RThumbRest], [Gamepad, LTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: None]
+ RTouchpad = RawButton.RTouchpad, ///< Maps to Physical Touch: [RTrackedRemote: RTouchpad], [Gamepad, Touch, LTouch, RTouch, LTrackedRemote, Touchpad, Remote: None]
+ Any = ~None, ///< Maps to Physical Touch: [Touch, LTouch, RTouch, LTrackedRemote, RTrackedRemote, Touchpad: Any], [Gamepad, Remote: None]
+ }
+
+ public enum RawButton {
+ None = 0, ///< Maps to Physical Button: [Gamepad, Touch, LTouch, RTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: None]
+ A = 0x00000001, ///< Maps to Physical Button: [Gamepad, Touch, RTouch: A], [LTrackedRemote: LIndexTrigger], [RTrackedRemote: RIndexTrigger], [LTouch, Touchpad, Remote: None]
+ B = 0x00000002, ///< Maps to Physical Button: [Gamepad, Touch, RTouch: B], [LTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: None]
+ X = 0x00000100, ///< Maps to Physical Button: [Gamepad, Touch, LTouch: X], [RTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: None]
+ Y = 0x00000200, ///< Maps to Physical Button: [Gamepad, Touch, LTouch: Y], [RTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: None]
+ Start = 0x00100000, ///< Maps to Physical Button: [Gamepad, Touch, LTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: Start], [RTouch: None]
+ Back = 0x00200000, ///< Maps to Physical Button: [Gamepad, LTrackedRemote, RTrackedRemote, Touchpad, Remote: Back], [Touch, LTouch, RTouch: None]
+ LShoulder = 0x00000800, ///< Maps to Physical Button: [Gamepad: LShoulder], [Touch, LTouch, RTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: None]
+ LIndexTrigger = 0x10000000, ///< Maps to Physical Button: [Gamepad, Touch, LTouch, LTrackedRemote: LIndexTrigger], [RTouch, RTrackedRemote, Touchpad, Remote: None]
+ LHandTrigger = 0x20000000, ///< Maps to Physical Button: [Touch, LTouch: LHandTrigger], [Gamepad, RTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: None]
+ LThumbstick = 0x00000400, ///< Maps to Physical Button: [Gamepad, Touch, LTouch: LThumbstick], [RTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: None]
+ LThumbstickUp = 0x00000010, ///< Maps to Physical Button: [Gamepad, Touch, LTouch: LThumbstickUp], [RTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: None]
+ LThumbstickDown = 0x00000020, ///< Maps to Physical Button: [Gamepad, Touch, LTouch: LThumbstickDown], [RTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: None]
+ LThumbstickLeft = 0x00000040, ///< Maps to Physical Button: [Gamepad, Touch, LTouch: LThumbstickLeft], [RTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: None]
+ LThumbstickRight = 0x00000080, ///< Maps to Physical Button: [Gamepad, Touch, LTouch: LThumbstickRight], [RTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: None]
+ LTouchpad = 0x40000000, ///< Maps to Physical Button: [LTrackedRemote: LTouchpad], [Gamepad, Touch, LTouch, RTouch, RTrackedRemote, Touchpad, Remote: None]
+ RShoulder = 0x00000008, ///< Maps to Physical Button: [Gamepad: RShoulder], [Touch, LTouch, RTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: None]
+ RIndexTrigger = 0x04000000, ///< Maps to Physical Button: [Gamepad, Touch, RTouch, RTrackedRemote: RIndexTrigger], [LTouch, LTrackedRemote, Touchpad, Remote: None]
+ RHandTrigger = 0x08000000, ///< Maps to Physical Button: [Touch, RTouch: RHandTrigger], [Gamepad, LTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: None]
+ RThumbstick = 0x00000004, ///< Maps to Physical Button: [Gamepad, Touch, RTouch: RThumbstick], [LTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: None]
+ RThumbstickUp = 0x00001000, ///< Maps to Physical Button: [Gamepad, Touch, RTouch: RThumbstickUp], [LTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: None]
+ RThumbstickDown = 0x00002000, ///< Maps to Physical Button: [Gamepad, Touch, RTouch: RThumbstickDown], [LTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: None]
+ RThumbstickLeft = 0x00004000, ///< Maps to Physical Button: [Gamepad, Touch, RTouch: RThumbstickLeft], [LTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: None]
+ RThumbstickRight = 0x00008000, ///< Maps to Physical Button: [Gamepad, Touch, RTouch: RThumbstickRight], [LTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: None]
+ RTouchpad = unchecked((int)0x80000000),///< Maps to Physical Button: [Gamepad, Touch, LTouch, RTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: None]
+ DpadUp = 0x00010000, ///< Maps to Physical Button: [Gamepad, LTrackedRemote, RTrackedRemote, Touchpad, Remote: DpadUp], [Touch, LTouch, RTouch: None]
+ DpadDown = 0x00020000, ///< Maps to Physical Button: [Gamepad, LTrackedRemote, RTrackedRemote, Touchpad, Remote: DpadDown], [Touch, LTouch, RTouch: None]
+ DpadLeft = 0x00040000, ///< Maps to Physical Button: [Gamepad, LTrackedRemote, RTrackedRemote, Touchpad, Remote: DpadLeft], [Touch, LTouch, RTouch: None]
+ DpadRight = 0x00080000, ///< Maps to Physical Button: [Gamepad, LTrackedRemote, RTrackedRemote, Touchpad, Remote: DpadRight], [Touch, LTouch, RTouch: None]
+ Any = ~None, ///< Maps to Physical Button: [Gamepad, Touch, LTouch, RTouch, LTrackedRemote, RTrackedRemote, Touchpad, Remote: Any]
+ }
+
+ public enum Bool {
+ False = 0,
+ True
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct Vector2f {
+ public float x;
+ public float y;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct Vector3f {
+ public float x;
+ public float y;
+ public float z;
+ public static readonly Vector3f zero = new Vector3f { x = 0.0f, y = 0.0f, z = 0.0f };
+ public override string ToString() {
+ return string.Format("{0}, {1}, {2}", x, y, z);
+ }
+ public UnityEngine.Vector3 ToVector3() {
+ return new UnityEngine.Vector3(x, y, -z);
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct Quatf {
+ public float x;
+ public float y;
+ public float z;
+ public float w;
+ public static readonly Quatf identity = new Quatf { x = 0.0f, y = 0.0f, z = 0.0f, w = 1.0f };
+ public override string ToString() {
+ return string.Format("{0}, {1}, {2}, {3}", x, y, z, w);
+ }
+
+ public UnityEngine.Quaternion ToQuaternion() {
+ return new UnityEngine.Quaternion(-x, -y, z, w);
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct Pose {
+ public Quatf Orientation;
+ public Vector3f Position;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct PoseStatef {
+ public Pose Pose;
+ public Vector3f Velocity;
+ public Vector3f Acceleration;
+ public Vector3f AngularVelocity;
+ public Vector3f AngularAcceleration;
+ double Time;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct ControllerState2 {
+ public uint ConnectedControllers;
+ public uint Buttons;
+ public uint Touches;
+ public uint NearTouches;
+ public float LIndexTrigger;
+ public float RIndexTrigger;
+ public float LHandTrigger;
+ public float RHandTrigger;
+ public Vector2f LThumbstick;
+ public Vector2f RThumbstick;
+ public Vector2f LTouchpad;
+ public Vector2f RTouchpad;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct ControllerState4 {
+ public uint ConnectedControllers;
+ public uint Buttons;
+ public uint Touches;
+ public uint NearTouches;
+ public float LIndexTrigger;
+ public float RIndexTrigger;
+ public float LHandTrigger;
+ public float RHandTrigger;
+ public Vector2f LThumbstick;
+ public Vector2f RThumbstick;
+ public Vector2f LTouchpad;
+ public Vector2f RTouchpad;
+ public byte LBatteryPercentRemaining;
+ public byte RBatteryPercentRemaining;
+ public byte LRecenterCount;
+ public byte RRecenterCount;
+ public byte Reserved_27;
+ public byte Reserved_26;
+ public byte Reserved_25;
+ public byte Reserved_24;
+ public byte Reserved_23;
+ public byte Reserved_22;
+ public byte Reserved_21;
+ public byte Reserved_20;
+ public byte Reserved_19;
+ public byte Reserved_18;
+ public byte Reserved_17;
+ public byte Reserved_16;
+ public byte Reserved_15;
+ public byte Reserved_14;
+ public byte Reserved_13;
+ public byte Reserved_12;
+ public byte Reserved_11;
+ public byte Reserved_10;
+ public byte Reserved_09;
+ public byte Reserved_08;
+ public byte Reserved_07;
+ public byte Reserved_06;
+ public byte Reserved_05;
+ public byte Reserved_04;
+ public byte Reserved_03;
+ public byte Reserved_02;
+ public byte Reserved_01;
+ public byte Reserved_00;
+
+ public ControllerState4(ControllerState2 cs) {
+ ConnectedControllers = cs.ConnectedControllers;
+ Buttons = cs.Buttons;
+ Touches = cs.Touches;
+ NearTouches = cs.NearTouches;
+ LIndexTrigger = cs.LIndexTrigger;
+ RIndexTrigger = cs.RIndexTrigger;
+ LHandTrigger = cs.LHandTrigger;
+ RHandTrigger = cs.RHandTrigger;
+ LThumbstick = cs.LThumbstick;
+ RThumbstick = cs.RThumbstick;
+ LTouchpad = cs.LTouchpad;
+ RTouchpad = cs.RTouchpad;
+ LBatteryPercentRemaining = 0;
+ RBatteryPercentRemaining = 0;
+ LRecenterCount = 0;
+ RRecenterCount = 0;
+ Reserved_27 = 0;
+ Reserved_26 = 0;
+ Reserved_25 = 0;
+ Reserved_24 = 0;
+ Reserved_23 = 0;
+ Reserved_22 = 0;
+ Reserved_21 = 0;
+ Reserved_20 = 0;
+ Reserved_19 = 0;
+ Reserved_18 = 0;
+ Reserved_17 = 0;
+ Reserved_16 = 0;
+ Reserved_15 = 0;
+ Reserved_14 = 0;
+ Reserved_13 = 0;
+ Reserved_12 = 0;
+ Reserved_11 = 0;
+ Reserved_10 = 0;
+ Reserved_09 = 0;
+ Reserved_08 = 0;
+ Reserved_07 = 0;
+ Reserved_06 = 0;
+ Reserved_05 = 0;
+ Reserved_04 = 0;
+ Reserved_03 = 0;
+ Reserved_02 = 0;
+ Reserved_01 = 0;
+ Reserved_00 = 0;
+ }
+ }
+
+ public enum Tracker {
+ None = -1,
+ Zero = 0,
+ One = 1,
+ Two = 2,
+ Three = 3,
+ Count,
+ }
+
+ public enum Node {
+ None = -1,
+ EyeLeft = 0,
+ EyeRight = 1,
+ EyeCenter = 2,
+ HandLeft = 3,
+ HandRight = 4,
+ TrackerZero = 5,
+ TrackerOne = 6,
+ TrackerTwo = 7,
+ TrackerThree = 8,
+ Head = 9,
+ Count,
+ }
+
+ public enum Controller {
+ None = 0,
+ LTouch = 0x00000001,
+ RTouch = 0x00000002,
+ Touch = LTouch | RTouch,
+ Remote = 0x00000004,
+ Gamepad = 0x00000010,
+ Touchpad = 0x08000000,
+ LTrackedRemote = 0x01000000,
+ RTrackedRemote = 0x02000000,
+ Active = unchecked((int)0x80000000),
+ All = ~None,
+ }
+
+ public enum Step {
+ Render = -1,
+ Physics = 0,
+ }
+
+ public enum TrackingConfidence {
+ Low = 0,
+ High = 0x3f800000,
+ }
+
+ public enum Hand {
+ None = -1,
+ HandLeft = 0,
+ HandRight = 1,
+ }
+
+ //[Flags]
+ public enum HandStatus {
+ HandTracked = (1 << 0), // if this is set the hand pose and bone rotations data is usable
+ InputStateValid = (1 << 1), // if this is set the pointer pose and pinch data is usable
+ SystemGestureInProgress = (1 << 6), // if this is set the hand is currently processing a system gesture
+ }
+
+ public enum BoneId {
+ Invalid = -1,
+
+ Hand_Start = 0,
+ Hand_WristRoot = Hand_Start + 0, // root frame of the hand, where the wrist is located
+ Hand_ForearmStub = Hand_Start + 1, // frame for user's forearm
+ Hand_Thumb0 = Hand_Start + 2, // thumb trapezium bone
+ Hand_Thumb1 = Hand_Start + 3, // thumb metacarpal bone
+ Hand_Thumb2 = Hand_Start + 4, // thumb proximal phalange bone
+ Hand_Thumb3 = Hand_Start + 5, // thumb distal phalange bone
+ Hand_Index1 = Hand_Start + 6, // index proximal phalange bone
+ Hand_Index2 = Hand_Start + 7, // index intermediate phalange bone
+ Hand_Index3 = Hand_Start + 8, // index distal phalange bone
+ Hand_Middle1 = Hand_Start + 9, // middle proximal phalange bone
+ Hand_Middle2 = Hand_Start + 10, // middle intermediate phalange bone
+ Hand_Middle3 = Hand_Start + 11, // middle distal phalange bone
+ Hand_Ring1 = Hand_Start + 12, // ring proximal phalange bone
+ Hand_Ring2 = Hand_Start + 13, // ring intermediate phalange bone
+ Hand_Ring3 = Hand_Start + 14, // ring distal phalange bone
+ Hand_Pinky0 = Hand_Start + 15, // pinky metacarpal bone
+ Hand_Pinky1 = Hand_Start + 16, // pinky proximal phalange bone
+ Hand_Pinky2 = Hand_Start + 17, // pinky intermediate phalange bone
+ Hand_Pinky3 = Hand_Start + 18, // pinky distal phalange bone
+ Hand_MaxSkinnable = Hand_Start + 19,
+ // Bone tips are position only. They are not used for skinning but are useful for hit-testing.
+ // NOTE: Hand_ThumbTip == Hand_MaxSkinnable since the extended tips need to be contiguous
+ Hand_ThumbTip = Hand_Start + Hand_MaxSkinnable + 0, // tip of the thumb
+ Hand_IndexTip = Hand_Start + Hand_MaxSkinnable + 1, // tip of the index finger
+ Hand_MiddleTip = Hand_Start + Hand_MaxSkinnable + 2, // tip of the middle finger
+ Hand_RingTip = Hand_Start + Hand_MaxSkinnable + 3, // tip of the ring finger
+ Hand_PinkyTip = Hand_Start + Hand_MaxSkinnable + 4, // tip of the pinky
+ Hand_End = Hand_Start + Hand_MaxSkinnable + 5,
+
+ // add new bones here
+
+ Max = Hand_End + 0,
+ }
+
+ private readonly static BoneId[] thumbBones = {
+ BoneId.Hand_Thumb0, // metacarpal
+ BoneId.Hand_Thumb1, // proximal,
+ BoneId.Hand_Thumb2, // intermediate
+ BoneId.Hand_Thumb3, // distal
+ BoneId.Hand_ThumbTip, // tip
+ };
+
+ private readonly static BoneId[] indexBones = {
+ BoneId.Invalid, // metacarpal
+ BoneId.Hand_Index1, // proximal,
+ BoneId.Hand_Index2, // intermediate
+ BoneId.Hand_Index3, // distal
+ BoneId.Hand_IndexTip, // tip
+ };
+
+ private readonly static BoneId[] middleBones = {
+ BoneId.Invalid, // metacarpal
+ BoneId.Hand_Middle1, // proximal,
+ BoneId.Hand_Middle2, // intermediate
+ BoneId.Hand_Middle3, // distal
+ BoneId.Hand_MiddleTip, // tip
+ };
+
+ private readonly static BoneId[] ringBones = {
+ BoneId.Invalid, // metacarpal
+ BoneId.Hand_Ring1, // proximal,
+ BoneId.Hand_Ring2, // intermediate
+ BoneId.Hand_Ring3, // distal
+ BoneId.Hand_RingTip, // tip
+ };
+
+ private readonly static BoneId[] littleBones = {
+ BoneId.Invalid, // metacarpal
+ BoneId.Hand_Pinky1, // proximal,
+ BoneId.Hand_Pinky2, // intermediate
+ BoneId.Hand_Pinky3, // distal
+ BoneId.Hand_PinkyTip, // tip
+ };
+
+ public static BoneId GetBoneId(Finger finger, FingerBone fingerBone) {
+ switch (finger) {
+ case Finger.Thumb:
+ return thumbBones[(int)fingerBone];
+ case Finger.Index:
+ return indexBones[(int)fingerBone];
+ case Finger.Middle:
+ return middleBones[(int)fingerBone];
+ case Finger.Ring:
+ return ringBones[(int)fingerBone];
+ case Finger.Little:
+ return littleBones[(int)fingerBone];
+ default:
+ return BoneId.Invalid;
+ }
+ }
+
+ public enum HandFinger {
+ Thumb = 0,
+ Index = 1,
+ Middle = 2,
+ Ring = 3,
+ Pinky = 4,
+ Max = 5,
+ }
+
+ //[Flags]
+ public enum HandFingerPinch {
+ Thumb = (1 << HandFinger.Thumb),
+ Index = (1 << HandFinger.Index),
+ Middle = (1 << HandFinger.Middle),
+ Ring = (1 << HandFinger.Ring),
+ Pinky = (1 << HandFinger.Pinky),
+ }
+
+ public static UnityEngine.Transform GetHandBoneTarget(HandTarget handTarget, BoneId boneId) {
+ switch (boneId) {
+ case BoneId.Hand_WristRoot:
+ return handTarget.hand.target.transform;
+ case BoneId.Hand_Thumb0:
+ return handTarget.fingers.thumb.proximal.target.transform;
+ case BoneId.Hand_Thumb2:
+ return handTarget.fingers.thumb.intermediate.target.transform;
+ case BoneId.Hand_Thumb3:
+ return handTarget.fingers.thumb.distal.target.transform;
+ case BoneId.Hand_Index1:
+ return handTarget.fingers.index.proximal.target.transform;
+ case BoneId.Hand_Index2:
+ return handTarget.fingers.index.intermediate.target.transform;
+ case BoneId.Hand_Index3:
+ return handTarget.fingers.index.distal.target.transform;
+ case BoneId.Hand_Middle1:
+ return handTarget.fingers.middle.proximal.target.transform;
+ case BoneId.Hand_Middle2:
+ return handTarget.fingers.middle.intermediate.target.transform;
+ case BoneId.Hand_Middle3:
+ return handTarget.fingers.middle.distal.target.transform;
+ case BoneId.Hand_Ring1:
+ return handTarget.fingers.ring.proximal.target.transform;
+ case BoneId.Hand_Ring2:
+ return handTarget.fingers.ring.intermediate.target.transform;
+ case BoneId.Hand_Ring3:
+ return handTarget.fingers.ring.distal.target.transform;
+ case BoneId.Hand_Pinky1:
+ return handTarget.fingers.little.proximal.target.transform;
+ case BoneId.Hand_Pinky2:
+ return handTarget.fingers.little.intermediate.target.transform;
+ case BoneId.Hand_Pinky3:
+ return handTarget.fingers.little.distal.target.transform;
+ }
+ return null;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct Posef {
+ public Quatf Orientation;
+ public Vector3f Position;
+ public static readonly Posef identity = new Posef { Orientation = Quatf.identity, Position = Vector3f.zero };
+ public override string ToString() {
+ return string.Format("Position ({0}), Orientation({1})", Position, Orientation);
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct BoneCapsule {
+ public short BoneIndex;
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
+ public Vector3f[] Points;
+ public float Radius;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct Bone {
+ public BoneId Id;
+ public short ParentBoneIndex;
+ public Posef Pose;
+ }
+
+ public enum SkeletonConstants {
+ MaxBones = BoneId.Max,
+ MaxBoneCapsules = 19,
+ }
+
+ public enum SkeletonType {
+ None = -1,
+ HandLeft = 0,
+ HandRight = 1,
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct Skeleton {
+ public SkeletonType Type;
+ public uint NumBones;
+ public uint NumBoneCapsules;
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int)SkeletonConstants.MaxBones)]
+ public Bone[] Bones;
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int)SkeletonConstants.MaxBoneCapsules)]
+ public BoneCapsule[] BoneCapsules;
+ }
+
+ public class SkeletonBone {
+ public OculusDevice.BoneId Id { get; private set; }
+ public short ParentBoneIndex { get; private set; }
+ public UnityEngine.Transform Transform { get; private set; }
+
+ public SkeletonBone(OculusDevice.BoneId id, short parentBoneIndex, UnityEngine.Transform trans) {
+ Id = id;
+ ParentBoneIndex = parentBoneIndex;
+ Transform = trans;
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct HandState {
+ public HandStatus Status;
+ public Posef RootPose;
+ public Quatf[] BoneRotations;
+ public HandFingerPinch Pinches;
+ public float[] PinchStrength;
+ public Posef PointerPose;
+ public float HandScale;
+ public TrackingConfidence HandConfidence;
+ public TrackingConfidence[] FingerConfidences;
+ public double RequestedTimeStamp;
+ public double SampleTimeStamp;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct HandStateInternal {
+ public HandStatus Status;
+ public Posef RootPose;
+ public Quatf BoneRotations_0;
+ public Quatf BoneRotations_1;
+ public Quatf BoneRotations_2;
+ public Quatf BoneRotations_3;
+ public Quatf BoneRotations_4;
+ public Quatf BoneRotations_5;
+ public Quatf BoneRotations_6;
+ public Quatf BoneRotations_7;
+ public Quatf BoneRotations_8;
+ public Quatf BoneRotations_9;
+ public Quatf BoneRotations_10;
+ public Quatf BoneRotations_11;
+ public Quatf BoneRotations_12;
+ public Quatf BoneRotations_13;
+ public Quatf BoneRotations_14;
+ public Quatf BoneRotations_15;
+ public Quatf BoneRotations_16;
+ public Quatf BoneRotations_17;
+ public Quatf BoneRotations_18;
+ public Quatf BoneRotations_19;
+ public Quatf BoneRotations_20;
+ public Quatf BoneRotations_21;
+ public Quatf BoneRotations_22;
+ public Quatf BoneRotations_23;
+ public HandFingerPinch Pinches;
+ public float PinchStrength_0;
+ public float PinchStrength_1;
+ public float PinchStrength_2;
+ public float PinchStrength_3;
+ public float PinchStrength_4;
+ public Posef PointerPose;
+ public float HandScale;
+ public TrackingConfidence HandConfidence;
+ public TrackingConfidence FingerConfidences_0;
+ public TrackingConfidence FingerConfidences_1;
+ public TrackingConfidence FingerConfidences_2;
+ public TrackingConfidence FingerConfidences_3;
+ public TrackingConfidence FingerConfidences_4;
+ public double RequestedTimeStamp;
+ public double SampleTimeStamp;
+ }
+
+ #endregion
+
+ #region Native Interface
+
+ private const string pluginName = "OVRPlugin";
+
+ [DllImport(pluginName, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ovrp_GetVersion")]
+ private static extern System.IntPtr _ovrp_GetVersion();
+ public static string ovrp_GetVersion() { return Marshal.PtrToStringAnsi(_ovrp_GetVersion()); }
+
+ [DllImport(pluginName, CallingConvention = CallingConvention.Cdecl)]
+ public static extern Bool ovrp_GetUserPresent();
+
+ [DllImport(pluginName, CallingConvention = CallingConvention.Cdecl)]
+ public static extern Bool ovrp_SetTrackingPositionEnabled(Bool value);
+
+ [DllImport(pluginName, CallingConvention = CallingConvention.Cdecl)]
+ public static extern Bool ovrp_GetNodeOrientationTracked(int nodeId);
+
+ [DllImport(pluginName, CallingConvention = CallingConvention.Cdecl)]
+ public static extern Bool ovrp_GetNodePositionTracked(int nodeId);
+
+ [DllImport(pluginName, CallingConvention = CallingConvention.Cdecl)]
+ public static extern PoseStatef ovrp_GetNodePoseState(Step stepId, int nodeId);
+
+ [DllImport(pluginName, CallingConvention = CallingConvention.Cdecl)]
+ public static extern ControllerState2 ovrp_GetControllerState2(uint controllerMask);
+
+ public enum Result {
+ /// Success
+ Success = 0,
+
+ /// Failure
+ Failure = -1000,
+ Failure_InvalidParameter = -1001,
+ Failure_NotInitialized = -1002,
+ Failure_InvalidOperation = -1003,
+ Failure_Unsupported = -1004,
+ Failure_NotYetImplemented = -1005,
+ Failure_OperationFailed = -1006,
+ Failure_InsufficientSize = -1007,
+ }
+
+ [DllImport(pluginName, CallingConvention = CallingConvention.Cdecl)]
+ public static extern Result ovrp_GetControllerState4(uint controllerMask, ref ControllerState4 controllerState);
+
+ [DllImport(pluginName, CallingConvention = CallingConvention.Cdecl)]
+ public static extern Bool ovrp_SetControllerVibration(uint controllerMask, float frequency, float amplitude);
+
+ [DllImport(pluginName, CallingConvention = CallingConvention.Cdecl)]
+ public static extern Bool ovrp_GetNodePresent(int nodeId);
+
+ [DllImport(pluginName, CallingConvention = CallingConvention.Cdecl)]
+ public static extern float ovrp_GetUserEyeHeight();
+
+ [DllImport(pluginName, CallingConvention = CallingConvention.Cdecl)]
+ public static extern Bool ovrp_GetAppShouldRecenter();
+
+ public enum RecenterFlags {
+ Default = 0,
+ Controllers = 0x40000000,
+ IgnoreAll = unchecked((int)0x80000000),
+ Count,
+ }
+
+ [DllImport(pluginName, CallingConvention = CallingConvention.Cdecl)]
+ public static extern Bool ovrp_RecenterTrackingOrigin(uint flags);
+
+ private static class OVRP_1_44_0 {
+ public static readonly System.Version version = new System.Version(1, 44, 0);
+
+ //[DllImport(pluginName, CallingConvention = CallingConvention.Cdecl)]
+ //public static extern Result ovrp_GetHandTrackingEnabled(ref Bool handTrackingEnabled);
+
+ [DllImport(pluginName, CallingConvention = CallingConvention.Cdecl)]
+ public static extern Result ovrp_GetHandState(Step stepId, Hand hand, out HandStateInternal handState);
+
+ [DllImport(pluginName, CallingConvention = CallingConvention.Cdecl)]
+ public static extern Result ovrp_GetSkeleton(SkeletonType skeletonType, out Skeleton skeleton);
+
+ //[DllImport(pluginName, CallingConvention = CallingConvention.Cdecl)]
+ //public static extern Result ovrp_GetMesh(MeshType meshType, out Mesh mesh);
+
+ //[DllImport(pluginName, CallingConvention = CallingConvention.Cdecl)]
+ //public static extern Result ovrp_OverrideExternalCameraFov(int cameraId, Bool useOverriddenFov, ref Fovf fov);
+
+ //[DllImport(pluginName, CallingConvention = CallingConvention.Cdecl)]
+ //public static extern Result ovrp_GetUseOverriddenExternalCameraFov(int cameraId, out Bool useOverriddenFov);
+
+ //[DllImport(pluginName, CallingConvention = CallingConvention.Cdecl)]
+ //public static extern Result ovrp_OverrideExternalCameraStaticPose(int cameraId, Bool useOverriddenPose, ref Posef pose);
+
+ //[DllImport(pluginName, CallingConvention = CallingConvention.Cdecl)]
+ //public static extern Result ovrp_GetUseOverriddenExternalCameraStaticPose(int cameraId, out Bool useOverriddenStaticPose);
+
+ //[DllImport(pluginName, CallingConvention = CallingConvention.Cdecl)]
+ //public static extern Result ovrp_ResetDefaultExternalCamera();
+
+ //[DllImport(pluginName, CallingConvention = CallingConvention.Cdecl)]
+ //public static extern Result ovrp_SetDefaultExternalCamera(string cameraName, ref CameraIntrinsics cameraIntrinsics, ref CameraExtrinsics cameraExtrinsics);
+
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/OculusDevice.cs.meta b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/OculusDevice.cs.meta
new file mode 100644
index 0000000..0144341
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/OculusDevice.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: d2084571fbdffea4c96208bf6dd9fc4b
+timeCreated: 1497033524
+licenseType: Free
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/OculusHandSkeleton.cs b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/OculusHandSkeleton.cs
new file mode 100644
index 0000000..28ce1e7
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/OculusHandSkeleton.cs
@@ -0,0 +1,122 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace Passer.Tracking {
+ using Passer.Humanoid.Tracking;
+
+ ///
+ /// A hand from Oculus hand tracking
+ ///
+ public class OculusHandSkeleton : HandSkeleton {
+
+#if hOCHAND
+
+ private OculusDevice.HandState handState = new OculusDevice.HandState();
+
+ #region Manage
+
+ public static OculusHandSkeleton Find(Transform trackerTransform, bool isLeft) {
+ OculusHandSkeleton[] handSkeletons = trackerTransform.GetComponentsInChildren();
+ foreach (OculusHandSkeleton handSkeleton in handSkeletons) {
+ if (handSkeleton.isLeft == isLeft)
+ return handSkeleton;
+ }
+ return null;
+ }
+
+ public static OculusHandSkeleton Get(Transform trackerTransform, bool isLeft) {
+ OculusHandSkeleton handSkeleton = Find(trackerTransform, isLeft);
+ if (handSkeleton == null) {
+ GameObject skeletonObj = new GameObject(isLeft ? "Left Hand Skeleton" : "Right Hand Skeleton");
+ skeletonObj.transform.parent = trackerTransform;
+ skeletonObj.transform.localPosition = Vector3.zero;
+ skeletonObj.transform.localRotation = Quaternion.identity;
+
+ handSkeleton = skeletonObj.AddComponent();
+ handSkeleton.isLeft = isLeft;
+ }
+ return handSkeleton;
+ }
+
+ #endregion
+
+ #region Start
+
+ protected override void InitializeSkeleton() {
+ OculusDevice.Skeleton skeleton;
+ if (OculusDevice.GetSkeleton(isLeft, out skeleton)) {
+
+ bones = new List(new TrackedBone[skeleton.NumBones]);
+
+ // pre-populate bones list before attempting to apply bone hierarchy
+ for (int i = 0; i < skeleton.NumBones; ++i) {
+ OculusDevice.BoneId id = (OculusDevice.BoneId)skeleton.Bones[i].Id;
+ Vector3 pos = skeleton.Bones[i].Pose.Position.ToVector3();
+ Quaternion rot = skeleton.Bones[i].Pose.Orientation.ToQuaternion();
+
+ bones[i] = TrackedBone.Create(id.ToString(), null);
+ bones[i].transform.localPosition = pos;
+ bones[i].transform.localRotation = rot;
+ }
+
+ // Now apply bone hierarchy
+ for (int i = 0; i < skeleton.NumBones; i++) {
+ if (((OculusDevice.BoneId)skeleton.Bones[i].ParentBoneIndex) == OculusDevice.BoneId.Invalid)
+ bones[i].transform.SetParent(this.transform, false);
+ else
+ bones[i].transform.SetParent(bones[skeleton.Bones[i].ParentBoneIndex].transform, false);
+ }
+ }
+ }
+
+ #endregion
+
+ #region Update
+ private Quaternion orientationCorrection;
+
+ public override void UpdateComponent() {
+ base.UpdateComponent();
+
+ if (bones == null)
+ InitializeSkeleton();
+ if (bones == null) {
+ status = Tracker.Status.Unavailable;
+ DisableRenderer();
+ return;
+ }
+
+ if (OculusDevice.GetHandState(OculusDevice.Step.Render, isLeft ? OculusDevice.Hand.HandLeft : OculusDevice.Hand.HandRight, ref handState)) {
+ if (handState.Status == 0) {
+ status = Tracker.Status.Present;
+ DisableRenderer();
+ return;
+ }
+ else {
+ status = Tracker.Status.Tracking;
+ this.transform.position = trackerTransform.TransformPoint(handState.RootPose.Position.ToVector3());
+ this.transform.rotation = trackerTransform.rotation * handState.RootPose.Orientation.ToQuaternion();
+ this.positionConfidence = 0.9F;
+ this.rotationConfidence = 0.9F;
+ }
+ for (int i = 0; i < bones.Count; i++)
+ bones[i].transform.localRotation = handState.BoneRotations[i].ToQuaternion();
+ }
+ else {
+ status = Tracker.Status.Present;
+ DisableRenderer();
+ return;
+ }
+
+ EnableRenderer();
+ UpdateSkeletonRender();
+ }
+
+ public override int GetBoneId(Finger finger, FingerBone fingerBone) {
+ OculusDevice.BoneId boneId = OculusDevice.GetBoneId(finger, fingerBone);
+ return (int)boneId;
+ }
+
+ #endregion
+#endif
+ }
+}
\ No newline at end of file
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/OculusHandSkeleton.cs.meta b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/OculusHandSkeleton.cs.meta
new file mode 100644
index 0000000..2556a10
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/OculusHandSkeleton.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 82ebe6b5f7e4a8b498b7c3c2e50fa997
+timeCreated: 1578586092
+licenseType: Free
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/OculusHmd.cs b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/OculusHmd.cs
new file mode 100644
index 0000000..b79652f
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/OculusHmd.cs
@@ -0,0 +1,125 @@
+using UnityEngine;
+
+namespace Passer.Tracking {
+ using Humanoid.Tracking;
+
+ ///
+ /// The Oculus Head Mounted Device
+ ///
+ public class OculusHmd : SensorComponent {
+
+ public Camera unityCamera;
+#if hOCULUS
+
+ private Humanoid.Tracking.Sensor.ID sensorId = Humanoid.Tracking.Sensor.ID.Head;
+
+ bool wasTracking = true;
+ Vector3 lastTrackingPosition;
+
+ #region Start
+
+ ///
+ /// Find the Oculus Hmd
+ ///
+ ///
+ ///
+ public static OculusHmd FindHmd(Transform oculusTransform) {
+ OculusHmd[] tags = oculusTransform.GetComponentsInChildren();
+ if (tags.Length > 0)
+ return tags[0];
+
+ return null;
+ }
+
+ /// Find or Create a new Antilatency Sensor
+ public static OculusHmd Get(Transform oculusTransform, Vector3 position, Quaternion rotation) {
+ if (oculusTransform == null)
+ return null;
+
+ OculusHmd hmd = FindHmd(oculusTransform);
+ if (hmd == null) {
+ GameObject sensorObject = new GameObject("Oculus HMD");
+ Transform sensorTransform = sensorObject.transform;
+
+ sensorTransform.parent = oculusTransform.transform;
+ sensorTransform.position = position;
+ sensorTransform.rotation = rotation;
+
+ hmd = sensorTransform.gameObject.AddComponent();
+ //hmd.oculus = oculus;
+ }
+ return hmd;
+ }
+
+ #endregion
+
+ #region Update
+
+ public override void UpdateComponent() {
+ if (OculusDevice.GetRotationalConfidence(sensorId) == 0) {
+ status = OculusDevice.IsPresent(0) ? Tracker.Status.Present : Tracker.Status.Unavailable;
+ positionConfidence = 0;
+ rotationConfidence = 0;
+ gameObject.SetActive(false);
+ OculusDevice.positionalTracking = false;
+ wasTracking = false;
+ return;
+ }
+
+ if (!OculusDevice.userPresent) {
+ status = Tracker.Status.Present;
+ positionConfidence = 0;
+ rotationConfidence = 0;
+ gameObject.SetActive(false);
+ OculusDevice.positionalTracking = false;
+ wasTracking = false;
+ return;
+ }
+
+ OculusDevice.positionalTracking = true;
+ if (!wasTracking)
+ ResetTrackingPosition();
+
+ status = Tracker.Status.Tracking;
+
+ Vector3 localPosition = Humanoid.HumanoidTarget.ToVector3(OculusDevice.GetPosition(sensorId));
+ Quaternion localRotation = Humanoid.HumanoidTarget.ToQuaternion(OculusDevice.GetRotation(sensorId));
+ transform.position = trackerTransform.TransformPoint(localPosition);
+ transform.rotation = trackerTransform.rotation * localRotation;
+
+ positionConfidence = OculusDevice.GetPositionalConfidence(sensorId);
+ rotationConfidence = OculusDevice.GetRotationalConfidence(sensorId);
+ gameObject.SetActive(true);
+
+ FuseWithUnityCamera();
+
+ wasTracking = true;
+ lastTrackingPosition = transform.position;
+ }
+
+ protected virtual void FuseWithUnityCamera() {
+ if (Camera.main == null)
+ return;
+
+ Vector3 deltaPos = Camera.main.transform.position - transform.position;
+ if (deltaPos.sqrMagnitude > 0.00001) {
+ Camera.main.transform.parent.position -= deltaPos;
+ }
+ }
+
+ // Reset tracking position to the last position when it was tracking
+ // This is needed to prevent the camera/avatar move while the headset is off
+ // But then the tracking origin changes while you probably want to have it fixed
+ // (that is: repeatable).
+ protected virtual void ResetTrackingPosition() {
+ if (lastTrackingPosition.sqrMagnitude == 0)
+ return;
+
+ Vector3 deltaPos = Camera.main.transform.position - lastTrackingPosition;
+ trackerTransform.position -= deltaPos;
+ }
+
+ #endregion
+#endif
+ }
+}
\ No newline at end of file
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/OculusHmd.cs.meta b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/OculusHmd.cs.meta
new file mode 100644
index 0000000..59f4157
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/OculusHmd.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: dd3d72f0140b14b409d9414461439116
+timeCreated: 1536136694
+licenseType: Free
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Oculus_Doc.cs b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Oculus_Doc.cs
new file mode 100644
index 0000000..4b2ad20
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Oculus_Doc.cs
@@ -0,0 +1,55 @@
+namespace Passer.Humanoid {
+ /// \page OculusDoc Meta/Oculus
+ ///
+ /// Oculus Rift and Quest are supported using the \ref UnityXRTracker "UnityXR" component.
+ /// This pages gives additional specific information for using the Oculus devices
+ ///
+ /// Unity XR Plugin
+ /// ===============
+ /// Oculus devices can be used with both the Oculus and OpenXR plugin for Unity XR.
+ /// However, it should be mentioned that hand tracking with the Oculus Quest is only
+ /// supported using the Oculus plugin.
+ ///
+ /// Hand%Tracking (Plus & Pro)
+ /// ==========================
+ /// For hand tracking, make sure the Unity XR plugin is set to Oculus.
+ /// Hand tracking is currently not supported for OpenXR.
+ /// When the platform is Android, an additional option will appear in the inspector
+ /// \image html OculusHandTracking.png
+ /// \image rtf OculusHandTracking.png
+ ///
+ /// Please make sure that for hand tracking, ‘Use Hands’ is enabled in the
+ /// Settings of the Oculus Quest itself or hand tracking will not work.
+ ///
+ /// Controller Buttons
+ /// ==================
+ /// The buttons of the Oculus controller can be accessed using ControllerInput.
+ /// The buttons are mapped as follows:
+ ///
+ /// Left Controller
+ /// ---------------
+ ///
+ /// Button | ControllerInput
+ /// ---------| --------
+ /// X button | controller.left.button[0]
+ /// Y button | controller.left.button[1]
+ /// Thumbstick touch | controller.left.stickTouch
+ /// Thumbstick press | controller.left.stickPress
+ /// Thumbstick movements | controller.left.stickHorizontal & .stickVertical
+ /// Index trigger | controller.left.trigger1
+ /// Hand trigger | controller.left.trigger2
+ /// Menu button | controller.left.option
+ ///
+ /// Right Controller
+ /// ----------------
+ ///
+ /// Button | ControllerInput
+ /// -------|-----------------
+ /// A button | controller.right.button[0]
+ /// B button | controller.right.button[1]
+ /// Thumbstick touch | controller.right.stickTouch
+ /// Thumbstick press | controller.right.stickPress
+ /// Thumbstick movements | controller.right.stickHorizontal & .stickVertical
+ /// Index trigger | controller.right.trigger1
+ /// Hand trigger | controller.right.trigger2
+}
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Oculus_Doc.cs.meta b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Oculus_Doc.cs.meta
new file mode 100644
index 0000000..4484526
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Oculus_Doc.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 291b0f046e30b1b40a1c43008404f1aa
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/QuestManifest.xml b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/QuestManifest.xml
new file mode 100644
index 0000000..072624f
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/QuestManifest.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/QuestManifest.xml.meta b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/QuestManifest.xml.meta
new file mode 100644
index 0000000..9292966
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/QuestManifest.xml.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 69408a8f6035027499aba652fd716f25
+timeCreated: 1567755345
+licenseType: Free
+TextScriptImporter:
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Resources.meta b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Resources.meta
new file mode 100644
index 0000000..4d93ed8
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Resources.meta
@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: 8e34c89789a76b4429fd342bbe8a7f6b
+folderAsset: yes
+timeCreated: 1472986387
+licenseType: Free
+DefaultImporter:
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Resources/Left Oculus Controller.prefab b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Resources/Left Oculus Controller.prefab
new file mode 100644
index 0000000..55d9d05
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Resources/Left Oculus Controller.prefab
@@ -0,0 +1,84 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!1001 &100100000
+Prefab:
+ m_ObjectHideFlags: 1
+ serializedVersion: 2
+ m_Modification:
+ m_TransformParent: {fileID: 0}
+ m_Modifications: []
+ m_RemovedComponents: []
+ m_ParentPrefab: {fileID: 0}
+ m_RootGameObject: {fileID: 1103073703406032}
+ m_IsPrefabParent: 1
+--- !u!1 &1103073703406032
+GameObject:
+ m_ObjectHideFlags: 0
+ m_PrefabParentObject: {fileID: 0}
+ m_PrefabInternal: {fileID: 100100000}
+ serializedVersion: 5
+ m_Component:
+ - component: {fileID: 4808734570168326}
+ - component: {fileID: 33781626903072926}
+ - component: {fileID: 23539047341558740}
+ m_Layer: 0
+ m_Name: Left Quest Controller
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!4 &4808734570168326
+Transform:
+ m_ObjectHideFlags: 1
+ m_PrefabParentObject: {fileID: 0}
+ m_PrefabInternal: {fileID: 100100000}
+ m_GameObject: {fileID: 1103073703406032}
+ m_LocalRotation: {x: 0, y: -0, z: -0, w: 1}
+ m_LocalPosition: {x: -0, y: 0, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_Children: []
+ m_Father: {fileID: 0}
+ m_RootOrder: 0
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!23 &23539047341558740
+MeshRenderer:
+ m_ObjectHideFlags: 1
+ m_PrefabParentObject: {fileID: 0}
+ m_PrefabInternal: {fileID: 100100000}
+ m_GameObject: {fileID: 1103073703406032}
+ m_Enabled: 1
+ m_CastShadows: 1
+ m_ReceiveShadows: 1
+ m_DynamicOccludee: 1
+ m_MotionVectors: 1
+ m_LightProbeUsage: 1
+ m_ReflectionProbeUsage: 1
+ m_Materials:
+ - {fileID: 2100000, guid: dc3b3568b7c54234f9d6a9f7297c3425, type: 2}
+ m_StaticBatchInfo:
+ firstSubMesh: 0
+ subMeshCount: 0
+ m_StaticBatchRoot: {fileID: 0}
+ m_ProbeAnchor: {fileID: 0}
+ m_LightProbeVolumeOverride: {fileID: 0}
+ m_ScaleInLightmap: 1
+ m_PreserveUVs: 0
+ m_IgnoreNormalsForChartDetection: 0
+ m_ImportantGI: 0
+ m_StitchLightmapSeams: 0
+ m_SelectedEditorRenderState: 3
+ m_MinimumChartSize: 4
+ m_AutoUVMaxDistance: 0.5
+ m_AutoUVMaxAngle: 89
+ m_LightmapParameters: {fileID: 0}
+ m_SortingLayerID: 0
+ m_SortingLayer: 0
+ m_SortingOrder: 0
+--- !u!33 &33781626903072926
+MeshFilter:
+ m_ObjectHideFlags: 1
+ m_PrefabParentObject: {fileID: 0}
+ m_PrefabInternal: {fileID: 100100000}
+ m_GameObject: {fileID: 1103073703406032}
+ m_Mesh: {fileID: 4300000, guid: a533ecc148345874ca68507932792b9e, type: 3}
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Resources/Left Oculus Controller.prefab.meta b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Resources/Left Oculus Controller.prefab.meta
new file mode 100644
index 0000000..2c88177
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Resources/Left Oculus Controller.prefab.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 0e0e467473c4c304691fb218ad5d5411
+timeCreated: 1562924722
+licenseType: Free
+NativeFormatImporter:
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Resources/Left Touch Controller.prefab b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Resources/Left Touch Controller.prefab
new file mode 100644
index 0000000..e861bea
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Resources/Left Touch Controller.prefab
@@ -0,0 +1,71 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!1001 &6393815153189425683
+PrefabInstance:
+ m_ObjectHideFlags: 0
+ serializedVersion: 2
+ m_Modification:
+ m_TransformParent: {fileID: 0}
+ m_Modifications:
+ - target: {fileID: -8679921383154817045, guid: ab7fa14a16d2d4d46a58646bef481bfc,
+ type: 3}
+ propertyPath: m_RootOrder
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: -8679921383154817045, guid: ab7fa14a16d2d4d46a58646bef481bfc,
+ type: 3}
+ propertyPath: m_LocalPosition.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: -8679921383154817045, guid: ab7fa14a16d2d4d46a58646bef481bfc,
+ type: 3}
+ propertyPath: m_LocalPosition.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: -8679921383154817045, guid: ab7fa14a16d2d4d46a58646bef481bfc,
+ type: 3}
+ propertyPath: m_LocalPosition.z
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: -8679921383154817045, guid: ab7fa14a16d2d4d46a58646bef481bfc,
+ type: 3}
+ propertyPath: m_LocalRotation.w
+ value: 1
+ objectReference: {fileID: 0}
+ - target: {fileID: -8679921383154817045, guid: ab7fa14a16d2d4d46a58646bef481bfc,
+ type: 3}
+ propertyPath: m_LocalRotation.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: -8679921383154817045, guid: ab7fa14a16d2d4d46a58646bef481bfc,
+ type: 3}
+ propertyPath: m_LocalRotation.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: -8679921383154817045, guid: ab7fa14a16d2d4d46a58646bef481bfc,
+ type: 3}
+ propertyPath: m_LocalRotation.z
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: -8679921383154817045, guid: ab7fa14a16d2d4d46a58646bef481bfc,
+ type: 3}
+ propertyPath: m_LocalEulerAnglesHint.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: -8679921383154817045, guid: ab7fa14a16d2d4d46a58646bef481bfc,
+ type: 3}
+ propertyPath: m_LocalEulerAnglesHint.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: -8679921383154817045, guid: ab7fa14a16d2d4d46a58646bef481bfc,
+ type: 3}
+ propertyPath: m_LocalEulerAnglesHint.z
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 919132149155446097, guid: ab7fa14a16d2d4d46a58646bef481bfc,
+ type: 3}
+ propertyPath: m_Name
+ value: Left Touch Controller
+ objectReference: {fileID: 0}
+ m_RemovedComponents: []
+ m_SourcePrefab: {fileID: 100100000, guid: ab7fa14a16d2d4d46a58646bef481bfc, type: 3}
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Resources/Left Touch Controller.prefab.meta b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Resources/Left Touch Controller.prefab.meta
new file mode 100644
index 0000000..27d043e
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Resources/Left Touch Controller.prefab.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 8a23cce4874e0a54a83502ef5405163c
+PrefabImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Resources/Right Oculus Controller.prefab b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Resources/Right Oculus Controller.prefab
new file mode 100644
index 0000000..1b22b46
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Resources/Right Oculus Controller.prefab
@@ -0,0 +1,84 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!1001 &100100000
+Prefab:
+ m_ObjectHideFlags: 1
+ serializedVersion: 2
+ m_Modification:
+ m_TransformParent: {fileID: 0}
+ m_Modifications: []
+ m_RemovedComponents: []
+ m_ParentPrefab: {fileID: 0}
+ m_RootGameObject: {fileID: 1038420493408916}
+ m_IsPrefabParent: 1
+--- !u!1 &1038420493408916
+GameObject:
+ m_ObjectHideFlags: 0
+ m_PrefabParentObject: {fileID: 0}
+ m_PrefabInternal: {fileID: 100100000}
+ serializedVersion: 5
+ m_Component:
+ - component: {fileID: 4210319229959686}
+ - component: {fileID: 33256649974969318}
+ - component: {fileID: 23472074526415768}
+ m_Layer: 0
+ m_Name: Right Quest Controller
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!4 &4210319229959686
+Transform:
+ m_ObjectHideFlags: 1
+ m_PrefabParentObject: {fileID: 0}
+ m_PrefabInternal: {fileID: 100100000}
+ m_GameObject: {fileID: 1038420493408916}
+ m_LocalRotation: {x: 0, y: -0, z: -0, w: 1}
+ m_LocalPosition: {x: -0, y: 0, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_Children: []
+ m_Father: {fileID: 0}
+ m_RootOrder: 0
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!23 &23472074526415768
+MeshRenderer:
+ m_ObjectHideFlags: 1
+ m_PrefabParentObject: {fileID: 0}
+ m_PrefabInternal: {fileID: 100100000}
+ m_GameObject: {fileID: 1038420493408916}
+ m_Enabled: 1
+ m_CastShadows: 1
+ m_ReceiveShadows: 1
+ m_DynamicOccludee: 1
+ m_MotionVectors: 1
+ m_LightProbeUsage: 1
+ m_ReflectionProbeUsage: 1
+ m_Materials:
+ - {fileID: 2100000, guid: dc3b3568b7c54234f9d6a9f7297c3425, type: 2}
+ m_StaticBatchInfo:
+ firstSubMesh: 0
+ subMeshCount: 0
+ m_StaticBatchRoot: {fileID: 0}
+ m_ProbeAnchor: {fileID: 0}
+ m_LightProbeVolumeOverride: {fileID: 0}
+ m_ScaleInLightmap: 1
+ m_PreserveUVs: 0
+ m_IgnoreNormalsForChartDetection: 0
+ m_ImportantGI: 0
+ m_StitchLightmapSeams: 0
+ m_SelectedEditorRenderState: 3
+ m_MinimumChartSize: 4
+ m_AutoUVMaxDistance: 0.5
+ m_AutoUVMaxAngle: 89
+ m_LightmapParameters: {fileID: 0}
+ m_SortingLayerID: 0
+ m_SortingLayer: 0
+ m_SortingOrder: 0
+--- !u!33 &33256649974969318
+MeshFilter:
+ m_ObjectHideFlags: 1
+ m_PrefabParentObject: {fileID: 0}
+ m_PrefabInternal: {fileID: 100100000}
+ m_GameObject: {fileID: 1038420493408916}
+ m_Mesh: {fileID: 4300000, guid: 6d5af71f44006e9478341b87a6c2867b, type: 3}
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Resources/Right Oculus Controller.prefab.meta b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Resources/Right Oculus Controller.prefab.meta
new file mode 100644
index 0000000..43e7d58
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Resources/Right Oculus Controller.prefab.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: f78c353d457baeb44987e0ae9bc0a529
+timeCreated: 1562924724
+licenseType: Free
+NativeFormatImporter:
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Resources/Right Touch Controller.prefab b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Resources/Right Touch Controller.prefab
new file mode 100644
index 0000000..4b45d97
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Resources/Right Touch Controller.prefab
@@ -0,0 +1,71 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!1001 &2748244689839952348
+PrefabInstance:
+ m_ObjectHideFlags: 0
+ serializedVersion: 2
+ m_Modification:
+ m_TransformParent: {fileID: 0}
+ m_Modifications:
+ - target: {fileID: -8679921383154817045, guid: 58377a2584075f6419ab14f150c33273,
+ type: 3}
+ propertyPath: m_RootOrder
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: -8679921383154817045, guid: 58377a2584075f6419ab14f150c33273,
+ type: 3}
+ propertyPath: m_LocalPosition.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: -8679921383154817045, guid: 58377a2584075f6419ab14f150c33273,
+ type: 3}
+ propertyPath: m_LocalPosition.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: -8679921383154817045, guid: 58377a2584075f6419ab14f150c33273,
+ type: 3}
+ propertyPath: m_LocalPosition.z
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: -8679921383154817045, guid: 58377a2584075f6419ab14f150c33273,
+ type: 3}
+ propertyPath: m_LocalRotation.w
+ value: 1
+ objectReference: {fileID: 0}
+ - target: {fileID: -8679921383154817045, guid: 58377a2584075f6419ab14f150c33273,
+ type: 3}
+ propertyPath: m_LocalRotation.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: -8679921383154817045, guid: 58377a2584075f6419ab14f150c33273,
+ type: 3}
+ propertyPath: m_LocalRotation.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: -8679921383154817045, guid: 58377a2584075f6419ab14f150c33273,
+ type: 3}
+ propertyPath: m_LocalRotation.z
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: -8679921383154817045, guid: 58377a2584075f6419ab14f150c33273,
+ type: 3}
+ propertyPath: m_LocalEulerAnglesHint.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: -8679921383154817045, guid: 58377a2584075f6419ab14f150c33273,
+ type: 3}
+ propertyPath: m_LocalEulerAnglesHint.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: -8679921383154817045, guid: 58377a2584075f6419ab14f150c33273,
+ type: 3}
+ propertyPath: m_LocalEulerAnglesHint.z
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 919132149155446097, guid: 58377a2584075f6419ab14f150c33273,
+ type: 3}
+ propertyPath: m_Name
+ value: Right Touch Controller
+ objectReference: {fileID: 0}
+ m_RemovedComponents: []
+ m_SourcePrefab: {fileID: 100100000, guid: 58377a2584075f6419ab14f150c33273, type: 3}
diff --git a/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Resources/Right Touch Controller.prefab.meta b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Resources/Right Touch Controller.prefab.meta
new file mode 100644
index 0000000..619a19c
--- /dev/null
+++ b/Runtime/HumanoidControl/Scripts/Extensions/Oculus/Resources/Right Touch Controller.prefab.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 464a2f1ee1e88d94aa41de880913bd4f
+PrefabImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/HumanoidControl/Scripts/HumanoidControl_Doc.cs b/Runtime/HumanoidControl/Scripts/HumanoidControl_Doc.cs
index 86b9e83..cf9d558 100644
--- a/Runtime/HumanoidControl/Scripts/HumanoidControl_Doc.cs
+++ b/Runtime/HumanoidControl/Scripts/HumanoidControl_Doc.cs
@@ -9,16 +9,11 @@
/// Main components
/// ---------------
/// * \ref HumanoidControl "Humanoid Control"
- /// * \ref Site "Humanoid Site"
- /// * \ref Visitor "Humanoid Visitor"
///
/// Devices
/// -------
/// * \ref UnityXRTracker "UnityXR"
/// * \ref OculusDoc "Oculus"
- /// * \ref LeapTracker "Leap Motion"
- /// * \ref ViveTrackerDoc "Vive Tracker"
- /// * \ref NeuronTracker "Perception Neuron"
///
/// Input
/// -----