private void UpdateSingleAxisData(MixedRealityInteractionMapping interactionMapping) { Debug.Assert(interactionMapping.AxisType == AxisType.SingleAxis); OculusApi.RawAxis1D interactionAxis1D = OculusApi.RawAxis1D.None; OculusInteractionMapping.TryParseRawAxis1D(interactionMapping, out interactionAxis1D); //Enum.TryParse<OculusApi.RawAxis1D>(interactionMapping.InputName, out interactionAxis1D); if (interactionAxis1D != OculusApi.RawAxis1D.None) { switch (interactionAxis1D) { case OculusApi.RawAxis1D.LIndexTrigger: singleAxisValue = currentState.LIndexTrigger; //if (shouldApplyDeadzone) // singleAxisValue = OculusApi.CalculateDeadzone(singleAxisValue, OculusApi.AXIS_DEADZONE_THRESHOLD); singleAxisValue = OculusApi.CalculateAbsMax(0, singleAxisValue); break; case OculusApi.RawAxis1D.LHandTrigger: singleAxisValue = currentState.LHandTrigger; //if (shouldApplyDeadzone) // singleAxisValue = OculusApi.CalculateDeadzone(singleAxisValue, OculusApi.AXIS_DEADZONE_THRESHOLD); singleAxisValue = OculusApi.CalculateAbsMax(0, singleAxisValue); break; case OculusApi.RawAxis1D.RIndexTrigger: singleAxisValue = currentState.RIndexTrigger; //if (shouldApplyDeadzone) // singleAxisValue = OculusApi.CalculateDeadzone(singleAxisValue, OculusApi.AXIS_DEADZONE_THRESHOLD); singleAxisValue = OculusApi.CalculateAbsMax(0, singleAxisValue); break; case OculusApi.RawAxis1D.RHandTrigger: singleAxisValue = currentState.RHandTrigger; //if (shouldApplyDeadzone) // singleAxisValue = OculusApi.CalculateDeadzone(singleAxisValue, OculusApi.AXIS_DEADZONE_THRESHOLD); singleAxisValue = OculusApi.CalculateAbsMax(0, singleAxisValue); break; } } // Update the interaction data source interactionMapping.FloatData = singleAxisValue; //interactionMapping.UpdateInteractionMappingFloat(InputSource, ControllerHandedness); if (interactionMapping.Changed) { InputSystem?.RaiseFloatInputChanged(InputSource, ControllerHandedness, interactionMapping.MixedRealityInputAction, interactionMapping.FloatData); } }
/// <inheritdoc /> public override void FixedUpdate() { base.FixedUpdate(); OculusApi.stepType = OculusApi.Step.Physics; double predictionSeconds = (double)fixedUpdateCount * Time.fixedDeltaTime / Mathf.Max(Time.timeScale, 1e-6f); fixedUpdateCount++; OculusApi.UpdateNodePhysicsPoses(0, predictionSeconds); }
/// <summary> /// Returns an array of 3d points (in clockwise order) that define the specified boundary type. /// All points are returned in local tracking space shared by tracked nodes and accessible through OVRCameraRig's trackingSpace anchor. /// </summary> private Vector3[] GetGeometry(OculusApi.BoundaryType boundaryType) { int pointsCount = 0; if (OculusApi.GetBoundaryGeometry(boundaryType, IntPtr.Zero, ref pointsCount)) { //Assume if the number of points returned in the boundary is the same, it is the same boundary. if (cachedPoints.Length == pointsCount) { return(cachedPoints); } if (pointsCount > 0) { int requiredNativeBufferCapacity = pointsCount * cachedVector3fSize; if (cachedGeometryNativeBuffer.GetCapacity() < requiredNativeBufferCapacity) { cachedGeometryNativeBuffer.Reset(requiredNativeBufferCapacity); } int requiredManagedBufferCapacity = pointsCount * 3; if (cachedGeometryManagedBuffer.Length < requiredManagedBufferCapacity) { cachedGeometryManagedBuffer = new float[requiredManagedBufferCapacity]; } if (OculusApi.GetBoundaryGeometry(boundaryType, cachedGeometryNativeBuffer.GetPointer(), ref pointsCount)) { Marshal.Copy(cachedGeometryNativeBuffer.GetPointer(), cachedGeometryManagedBuffer, 0, requiredManagedBufferCapacity); cachedPoints = new Vector3[pointsCount]; for (int i = 0; i < pointsCount; i++) { cachedPoints[i] = new OculusApi.Vector3f { x = cachedGeometryManagedBuffer[3 * i + 0], y = cachedGeometryManagedBuffer[3 * i + 1], z = cachedGeometryManagedBuffer[3 * i + 2], }; } } } } return(cachedPoints); }
private void UpdateDualAxisData(MixedRealityInteractionMapping interactionMapping) { Debug.Assert(interactionMapping.AxisType == AxisType.DualAxis); OculusApi.RawAxis2D interactionAxis2D = OculusApi.RawAxis2D.None; Enum.TryParse <OculusApi.RawAxis2D>(interactionMapping.InputName, out interactionAxis2D); if (interactionAxis2D != OculusApi.RawAxis2D.None) { switch (interactionAxis2D) { case OculusApi.RawAxis2D.LThumbstick: dualAxisPosition.x = currentState.LThumbstick.x; dualAxisPosition.y = currentState.LThumbstick.y; dualAxisPosition = OculusApi.CalculateAbsMax(Vector2.zero, dualAxisPosition); break; case OculusApi.RawAxis2D.LTouchpad: dualAxisPosition.x = currentState.LTouchpad.x; dualAxisPosition.y = currentState.LTouchpad.y; dualAxisPosition = OculusApi.CalculateAbsMax(Vector2.zero, dualAxisPosition); break; case OculusApi.RawAxis2D.RThumbstick: dualAxisPosition.x = currentState.RThumbstick.x; dualAxisPosition.y = currentState.RThumbstick.y; dualAxisPosition = OculusApi.CalculateAbsMax(Vector2.zero, dualAxisPosition); break; case OculusApi.RawAxis2D.RTouchpad: dualAxisPosition.x = currentState.RTouchpad.x; dualAxisPosition.y = currentState.RTouchpad.y; dualAxisPosition = OculusApi.CalculateAbsMax(Vector2.zero, dualAxisPosition); break; } } // Update the interaction data source interactionMapping.Vector2Data = dualAxisPosition; interactionMapping.UpdateInteractionMappingVector2(InputSource, ControllerHandedness); }
private void UpdateSingleAxisData(MixedRealityInteractionMapping interactionMapping) { Debug.Assert(interactionMapping.AxisType == AxisType.SingleAxis); OculusApi.RawAxis1D interactionAxis1D = OculusApi.RawAxis1D.None; Enum.TryParse <OculusApi.RawAxis1D>(interactionMapping.InputName, out interactionAxis1D); if (interactionAxis1D != OculusApi.RawAxis1D.None) { switch (interactionAxis1D) { case OculusApi.RawAxis1D.LIndexTrigger: singleAxisValue = currentState.LIndexTrigger; singleAxisValue = OculusApi.CalculateAbsMax(0, singleAxisValue); break; case OculusApi.RawAxis1D.LHandTrigger: singleAxisValue = currentState.LHandTrigger; singleAxisValue = OculusApi.CalculateAbsMax(0, singleAxisValue); break; case OculusApi.RawAxis1D.RIndexTrigger: singleAxisValue = currentState.RIndexTrigger; singleAxisValue = OculusApi.CalculateAbsMax(0, singleAxisValue); break; case OculusApi.RawAxis1D.RHandTrigger: singleAxisValue = currentState.RHandTrigger; singleAxisValue = OculusApi.CalculateAbsMax(0, singleAxisValue); break; } } // Update the interaction data source interactionMapping.FloatData = singleAxisValue; interactionMapping.UpdateInteractionMappingFloat(InputSource, ControllerHandedness); }
/// <summary> /// Reads hand APIs for the current frame and converts it to agnostic <see cref="HandData"/>. /// </summary> /// <param name="handedness">The handedness of the hand to get <see cref="HandData"/> for.</param> /// <param name="includeMeshData">If set, hand mesh information will be included in <see cref="HandData.Mesh"/>.</param> /// <param name="minTrackingConfidence">The minimum <see cref="OculusApi.TrackingConfidence"/> required to consider hands tracked.</param> /// <param name="handData">The output <see cref="HandData"/>.</param> /// <returns>True, if data conversion was a success.</returns> public bool TryGetHandData(Handedness handedness, bool includeMeshData, OculusApi.TrackingConfidence minTrackingConfidence, out HandData handData) { // Here we check whether the hand is being tracked at all by the Oculus system. if (!(OculusApi.GetHandState(OculusApi.Step.Render, handedness.ToHand(), ref handState) && OculusApi.GetSkeleton(handedness.ToSkeletonType(), out handSkeleton))) { handData = default; return(false); } // The hand is being tracked, next we verify it meets our confidence requirements to consider // it tracked. handData = new HandData { TrackingState = (handState.HandConfidence >= minTrackingConfidence && (handState.Status & OculusApi.HandStatus.HandTracked) != 0) ? TrackingState.Tracked : TrackingState.NotTracked, UpdatedAt = DateTimeOffset.UtcNow.Ticks }; // If the hand is tracked per requirements, we get updated joint data // and other data needed for updating the hand controller's state. if (handData.TrackingState == TrackingState.Tracked) { handData.RootPose = GetHandRootPose(handedness); handData.Joints = GetJointPoses(handedness); handData.PointerPose = GetPointerPose(handedness); if (includeMeshData && TryGetUpdatedHandMeshData(handedness, out HandMeshData data)) { handData.Mesh = data; } else { handData.Mesh = HandMeshData.Empty; } } // Even if the hand is being tracked by the system but the confidence did not // meet our requirements, we return true. This allows the hand controller and visualizers // to react to tracking loss and keep the hand up for a given time before destroying the controller. return(true); }
/// <summary> /// Attempts to get updated hand mesh data. /// </summary> /// <param name="handedness">The handedness of the hand to get mesh data for.</param> /// <param name="data">Mesh information retrieved in case of success.</param> /// <returns>True, if mesh data could be loaded.</returns> private bool TryGetUpdatedHandMeshData(Handedness handedness, out HandMeshData data) { if (OculusApi.GetMesh(handedness.ToMeshType(), out handMesh)) { var vertices = new Vector3[handMesh.NumVertices]; for (int i = 0; i < handMesh.NumVertices; ++i) { vertices[i] = handMesh.VertexPositions[i]; } var uvs = new Vector2[handMesh.NumVertices]; for (int i = 0; i < handMesh.NumVertices; ++i) { uvs[i] = new Vector2(handMesh.VertexUV0[i].x, -handMesh.VertexUV0[i].y); } var triangles = new int[handMesh.NumIndices]; for (int i = 0; i < handMesh.NumIndices; ++i) { triangles[i] = handMesh.Indices[handMesh.NumIndices - i - 1]; } var normals = new Vector3[handMesh.NumVertices]; for (int i = 0; i < handMesh.NumVertices; ++i) { normals[i] = handMesh.VertexNormals[i]; } data = new HandMeshData(vertices, triangles, normals, uvs); return(true); } data = default; return(false); }
private void UpdateControllerData() { var lastState = TrackingState; lastControllerPose = currentControllerPose; previousState = currentState; currentState = OculusApi.GetControllerState4((uint)controllerType); if (currentState.LIndexTrigger >= OculusApi.AXIS_AS_BUTTON_THRESHOLD) { currentState.Buttons |= (uint)OculusApi.RawButton.LIndexTrigger; } if (currentState.LHandTrigger >= OculusApi.AXIS_AS_BUTTON_THRESHOLD) { currentState.Buttons |= (uint)OculusApi.RawButton.LHandTrigger; } if (currentState.LThumbstick.y >= OculusApi.AXIS_AS_BUTTON_THRESHOLD) { currentState.Buttons |= (uint)OculusApi.RawButton.LThumbstickUp; } if (currentState.LThumbstick.y <= -OculusApi.AXIS_AS_BUTTON_THRESHOLD) { currentState.Buttons |= (uint)OculusApi.RawButton.LThumbstickDown; } if (currentState.LThumbstick.x <= -OculusApi.AXIS_AS_BUTTON_THRESHOLD) { currentState.Buttons |= (uint)OculusApi.RawButton.LThumbstickLeft; } if (currentState.LThumbstick.x >= OculusApi.AXIS_AS_BUTTON_THRESHOLD) { currentState.Buttons |= (uint)OculusApi.RawButton.LThumbstickRight; } if (currentState.RIndexTrigger >= OculusApi.AXIS_AS_BUTTON_THRESHOLD) { currentState.Buttons |= (uint)OculusApi.RawButton.RIndexTrigger; } if (currentState.RHandTrigger >= OculusApi.AXIS_AS_BUTTON_THRESHOLD) { currentState.Buttons |= (uint)OculusApi.RawButton.RHandTrigger; } if (currentState.RThumbstick.y >= OculusApi.AXIS_AS_BUTTON_THRESHOLD) { currentState.Buttons |= (uint)OculusApi.RawButton.RThumbstickUp; } if (currentState.RThumbstick.y <= -OculusApi.AXIS_AS_BUTTON_THRESHOLD) { currentState.Buttons |= (uint)OculusApi.RawButton.RThumbstickDown; } if (currentState.RThumbstick.x <= -OculusApi.AXIS_AS_BUTTON_THRESHOLD) { currentState.Buttons |= (uint)OculusApi.RawButton.RThumbstickLeft; } if (currentState.RThumbstick.x >= OculusApi.AXIS_AS_BUTTON_THRESHOLD) { currentState.Buttons |= (uint)OculusApi.RawButton.RThumbstickRight; } if (IsTrackedController(controllerType)) { // The source is either a hand or a controller that supports pointing. // We can now check for position and rotation. IsPositionAvailable = OculusApi.GetNodePositionTracked(NodeType); if (IsPositionAvailable) { IsPositionApproximate = OculusApi.GetNodePositionValid(NodeType); } else { IsPositionApproximate = false; } IsRotationAvailable = OculusApi.GetNodeOrientationTracked(NodeType); // Devices are considered tracked if we receive position OR rotation data from the sensors. TrackingState = (IsPositionAvailable || IsRotationAvailable) ? TrackingState.Tracked : TrackingState.NotTracked; } else { // The input source does not support tracking. TrackingState = TrackingState.NotApplicable; } var pose = OculusApi.GetNodePose(NodeType, OculusApi.stepType); currentControllerPose = pose.ToMixedRealityPose(); // Raise input system events if it is enabled. if (lastState != TrackingState) { MixedRealityToolkit.InputSystem?.RaiseSourceTrackingStateChanged(InputSource, this, TrackingState); } if (TrackingState == TrackingState.Tracked && lastControllerPose != currentControllerPose) { if (IsPositionAvailable && IsRotationAvailable) { MixedRealityToolkit.InputSystem?.RaiseSourcePoseChanged(InputSource, this, currentControllerPose); } else if (IsPositionAvailable && !IsRotationAvailable) { MixedRealityToolkit.InputSystem?.RaiseSourcePositionChanged(InputSource, this, currentControllerPose.Position); } else if (!IsPositionAvailable && IsRotationAvailable) { MixedRealityToolkit.InputSystem?.RaiseSourceRotationChanged(InputSource, this, currentControllerPose.Rotation); } } }
/// <remarks> /// Noticed that the "active" controllers also mark the Tracked state. /// </remarks> private void RefreshDevices() { // override locally derived active and connected controllers if plugin provides more accurate data OculusApi.connectedControllerTypes = OculusApi.GetConnectedControllers(); OculusApi.activeControllerType = OculusApi.GetActiveController(); if (OculusApi.connectedControllerTypes == OculusApi.Controller.None) { return; } if (activeControllers.Count > 0) { var controllers = new OculusApi.Controller[activeControllers.Count]; activeControllers.Keys.CopyTo(controllers, 0); if (lastDeviceList != OculusApi.Controller.None && OculusApi.connectedControllerTypes != lastDeviceList) { for (var i = 0; i < controllers.Length; i++) { var activeController = controllers[i]; switch (activeController) { case OculusApi.Controller.Touch when((OculusApi.Controller.LTouch & OculusApi.connectedControllerTypes) != OculusApi.Controller.LTouch): RaiseSourceLost(OculusApi.Controller.LTouch); break; case OculusApi.Controller.Touch when((OculusApi.Controller.RTouch & OculusApi.connectedControllerTypes) != OculusApi.Controller.RTouch): RaiseSourceLost(OculusApi.Controller.RTouch); break; default: if ((activeController & OculusApi.connectedControllerTypes) != activeController) { RaiseSourceLost(activeController); } break; } } } } for (var i = 0; i < OculusApi.Controllers.Length; i++) { if (OculusApi.ShouldResolveController(OculusApi.Controllers[i].controllerType, OculusApi.connectedControllerTypes)) { if (OculusApi.Controllers[i].controllerType == OculusApi.Controller.Touch) { if (!activeControllers.ContainsKey(OculusApi.Controller.LTouch)) { RaiseSourceDetected(OculusApi.Controller.LTouch); } if (!activeControllers.ContainsKey(OculusApi.Controller.RTouch)) { RaiseSourceDetected(OculusApi.Controller.RTouch); } } else if (!activeControllers.ContainsKey(OculusApi.Controllers[i].controllerType)) { RaiseSourceDetected(OculusApi.Controllers[i].controllerType); } } } lastDeviceList = OculusApi.connectedControllerTypes; }
private void UpdateDualAxisData(MixedRealityInteractionMapping interactionMapping) { Debug.Assert(interactionMapping.AxisType == AxisType.DualAxis); OculusApi.RawAxis2D interactionAxis2D = OculusApi.RawAxis2D.None; OculusInteractionMapping.TryParseRawAxis2D(interactionMapping, out interactionAxis2D); //Enum.TryParse<OculusApi.RawAxis2D>(interactionMapping.InputName, out interactionAxis2D); if (interactionAxis2D != OculusApi.RawAxis2D.None) { switch (interactionAxis2D) { case OculusApi.RawAxis2D.LThumbstick: dualAxisPosition.x = currentState.LThumbstick.x; dualAxisPosition.y = currentState.LThumbstick.y; //if (shouldApplyDeadzone) // dualAxisPosition = OculusApi.CalculateDeadzone(dualAxisPosition, OculusApi.AXIS_DEADZONE_THRESHOLD); dualAxisPosition = OculusApi.CalculateAbsMax(Vector2.zero, dualAxisPosition); break; case OculusApi.RawAxis2D.LTouchpad: dualAxisPosition.x = currentState.LTouchpad.x; dualAxisPosition.y = currentState.LTouchpad.y; //if (shouldApplyDeadzone) // dualAxisPosition = OculusApi.CalculateDeadzone(dualAxisPosition, OculusApi.AXIS_DEADZONE_THRESHOLD); dualAxisPosition = OculusApi.CalculateAbsMax(Vector2.zero, dualAxisPosition); break; case OculusApi.RawAxis2D.RThumbstick: dualAxisPosition.x = currentState.RThumbstick.x; dualAxisPosition.y = currentState.RThumbstick.y; //if (shouldApplyDeadzone) // dualAxisPosition = OculusApi.CalculateDeadzone(dualAxisPosition, OculusApi.AXIS_DEADZONE_THRESHOLD); dualAxisPosition = OculusApi.CalculateAbsMax(Vector2.zero, dualAxisPosition); break; case OculusApi.RawAxis2D.RTouchpad: dualAxisPosition.x = currentState.RTouchpad.x; dualAxisPosition.y = currentState.RTouchpad.y; //if (shouldApplyDeadzone) // dualAxisPosition = OculusApi.CalculateDeadzone(dualAxisPosition, OculusApi.AXIS_DEADZONE_THRESHOLD); dualAxisPosition = OculusApi.CalculateAbsMax(Vector2.zero, dualAxisPosition); break; } } // Update the interaction data source interactionMapping.Vector2Data = dualAxisPosition; //interactionMapping.UpdateInteractionMappingVector2(InputSource, ControllerHandedness); if (interactionMapping.Changed) { InputSystem?.RaisePositionInputChanged(InputSource, ControllerHandedness, interactionMapping.MixedRealityInputAction, interactionMapping.Vector2Data); } }
/// <inheritdoc /> public override void Update() { OculusApi.UpdateHMDEvents(); OculusApi.UpdateUserEvents(); }
private void RefreshDevices() { // override locally derived active and connected controllers if plugin provides more accurate data OculusApi.connectedControllerTypes = (OculusApi.Controller)OculusApi.GetConnectedControllers(); OculusApi.activeControllerType = (OculusApi.Controller)OculusApi.GetActiveController(); //Noticed that the "active" controllers also mark the Tracked state. //Debug.LogError($"Connected =[{OculusApi.connectedControllerTypes}] - Active = [{OculusApi.activeControllerType}]"); if (OculusApi.connectedControllerTypes == OculusApi.Controller.None) { return; } if (ActiveControllers.Count > 0) { OculusApi.Controller[] activeControllers = new OculusApi.Controller[ActiveControllers.Count]; ActiveControllers.Keys.CopyTo(activeControllers, 0); if (lastDeviceList != OculusApi.Controller.None && OculusApi.connectedControllerTypes != lastDeviceList) { foreach (var activeController in activeControllers) { if (activeController == OculusApi.Controller.Touch && ((OculusApi.Controller.LTouch & OculusApi.connectedControllerTypes) != OculusApi.Controller.LTouch)) { RaiseSourceLost(OculusApi.Controller.LTouch); } else if (activeController == OculusApi.Controller.Touch && ((OculusApi.Controller.RTouch & OculusApi.connectedControllerTypes) != OculusApi.Controller.RTouch)) { RaiseSourceLost(OculusApi.Controller.RTouch); } else if ((activeController & OculusApi.connectedControllerTypes) != activeController) { RaiseSourceLost(activeController); } } } } for (var i = 0; i < OculusApi.Controllers.Length; i++) { if (OculusApi.ShouldResolveController(OculusApi.Controllers[i].controllerType, OculusApi.connectedControllerTypes)) { if (OculusApi.Controllers[i].controllerType == OculusApi.Controller.Touch) { if (!ActiveControllers.ContainsKey(OculusApi.Controller.LTouch)) { RaiseSourceDetected(OculusApi.Controller.LTouch); } if (!ActiveControllers.ContainsKey(OculusApi.Controller.RTouch)) { RaiseSourceDetected(OculusApi.Controller.RTouch); } } else if (!ActiveControllers.ContainsKey(OculusApi.Controllers[i].controllerType)) { RaiseSourceDetected(OculusApi.Controllers[i].controllerType); } } } lastDeviceList = OculusApi.connectedControllerTypes; }
/// <summary> /// Returns a vector that indicates the spatial dimensions of the specified boundary type. (x = width, y = height, z = depth) /// </summary> /// <remarks> /// Reserved for Future use. /// </remarks> private Vector3 GetDimensions(OculusApi.BoundaryType boundaryType) { return(OculusApi.GetBoundaryDimensions(boundaryType).ToVector3FlippedZ()); }