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 /// -----