/// <summary> /// Capture a snapshot of simulated hand data based on current state. /// </summary> public bool UpdateHandData(SimulatedHandData handDataLeft, SimulatedHandData handDataRight) { SimulateUserInput(); bool handDataChanged = false; // TODO: DateTime.UtcNow can be quite imprecise, better use Stopwatch.GetTimestamp // https://stackoverflow.com/questions/2143140/c-sharp-datetime-now-precision long timestamp = DateTime.UtcNow.Ticks; // Cache the generator delegates so we don't gc alloc every frame if (generatorLeft == null) { generatorLeft = HandStateLeft.FillCurrentFrame; } if (generatorRight == null) { generatorRight = HandStateRight.FillCurrentFrame; } handDataChanged |= handDataLeft.UpdateWithTimestamp(timestamp, HandStateLeft.IsTracked, HandStateLeft.IsPinching, generatorLeft); handDataChanged |= handDataRight.UpdateWithTimestamp(timestamp, HandStateRight.IsTracked, HandStateRight.IsPinching, generatorRight); return(handDataChanged); }
public void UpdateState(SimulatedHandData handData) { UpdateHandJoints(handData); UpdateVelocity(); UpdateInteractions(handData); }
/// <summary> /// Capture a snapshot of simulated hand data based on current state. /// </summary> public bool UpdateHandData(SimulatedHandData handDataLeft, SimulatedHandData handDataRight, SimulatedHandData handDataGaze, MouseDelta mouseDelta) { SimulateUserInput(mouseDelta); HandStateLeft.Update(); HandStateRight.Update(); HandStateGaze.Update(); bool handDataChanged = false; // Cache the generator delegates so we don't gc alloc every frame if (generatorLeft == null) { generatorLeft = HandStateLeft.FillCurrentFrame; } if (generatorRight == null) { generatorRight = HandStateRight.FillCurrentFrame; } if (generatorGaze == null) { generatorGaze = HandStateGaze.FillCurrentFrame; } handDataChanged |= handDataLeft.Update(HandStateLeft.IsTracked, HandStateLeft.IsPinching, generatorLeft); handDataChanged |= handDataRight.Update(HandStateRight.IsTracked, HandStateRight.IsPinching, generatorRight); handDataChanged |= handDataGaze.Update(HandStateGaze.IsTracked, HandStateGaze.IsPinching, generatorGaze); return(handDataChanged); }
private bool UpdateHandDataFromState(SimulatedHandData frame, SimulatedHandState state) { bool handDataChanged = false; bool wasTracked = frame.IsTracked; bool wasPinching = frame.IsPinching; frame.IsTracked = state.IsVisible; frame.IsPinching = state.IsPinching; if (wasTracked != frame.IsTracked || wasPinching != frame.IsPinching) { handDataChanged = true; } if (frame.IsTracked) { var prevTime = frame.Timestamp; frame.Timestamp = DateTime.UtcNow.Ticks; if (frame.Timestamp != prevTime) { state.FillCurrentFrame(frame.Joints); handDataChanged = true; } } else { // If frame is not tracked, set timestamp to zero frame.Timestamp = 0; } return(handDataChanged); }
public void UpdateState(SimulatedHandData handData) { Array.Copy(handData.Joints, jointPositions, jointCount); SimulatedHandUtils.CalculateJointRotations(ControllerHandedness, jointPositions, jointOrientations); for (int i = 0; i < jointPositions.Length; i++) { TrackedHandJoint handJoint = (TrackedHandJoint)i; if (!jointPoses.ContainsKey(handJoint)) { jointPoses.Add(handJoint, new MixedRealityPose(jointPositions[i], jointOrientations[i])); } else { jointPoses[handJoint] = new MixedRealityPose(jointPositions[i], jointOrientations[i]); } } MixedRealityToolkit.InputSystem?.RaiseHandJointsUpdated(InputSource, ControllerHandedness, jointPoses); UpdateVelocity(); UpdateInteractions(handData); }
public void Copy(SimulatedHandData other) { isTracked = other.isTracked; isPinching = other.isPinching; for (int i = 0; i < jointCount; ++i) { joints[i] = other.joints[i]; } }
private void EvaluateHandData(SimulatedHandData handData, Handedness handedness) { animation.EvaluateHandState(localTime, handedness, out bool isTracked, out bool isPinching); handData.Update(isTracked, isPinching, (MixedRealityPose[] joints) => { for (int i = 0; i < jointCount; ++i) { joints[i] = animation.EvaluateHandJoint(localTime, handedness, (TrackedHandJoint)i); } }); }
private void EvaluateHandData(SimulatedHandData handData, Handedness handedness) { animation.EvaluateHandState(localTime, handedness, out bool isTracked, out bool isPinching); if (handData.Update(isTracked, isPinching, (MixedRealityPose[] joints) => { for (int i = 0; i < ArticulatedHandPose.JointCount; ++i) { joints[i] = animation.EvaluateHandJoint(localTime, handedness, (TrackedHandJoint)i); } })) { UpdateControllerDevice(ControllerSimulationMode.ArticulatedHand, handedness, handData); } }
/// <inheritdoc /> protected override void UpdateHandJoints(SimulatedHandData handData) { for (int i = 0; i < jointCount; i++) { TrackedHandJoint handJoint = (TrackedHandJoint)i; if (!jointPoses.ContainsKey(handJoint)) { jointPoses.Add(handJoint, handData.Joints[i]); } else { jointPoses[handJoint] = handData.Joints[i]; } } handDefinition?.UpdateHandJoints(jointPoses); }
/// <inheritdoc /> protected override void UpdateHandJoints(SimulatedHandData handData) { for (int i = 0; i < ArticulatedHandPose.JointCount; i++) { TrackedHandJoint handJoint = (TrackedHandJoint)i; if (!jointPoses.ContainsKey(handJoint)) { jointPoses.Add(handJoint, handData.Joints[i]); } else { jointPoses[handJoint] = handData.Joints[i]; } } CoreServices.InputSystem?.RaiseHandJointsUpdated(InputSource, ControllerHandedness, jointPoses); }
// Register input sources for hands based on changes of the data provider private void UpdateHandInputSource(Handedness handedness, SimulatedHandData handData) { var profile = InputSimulationProfile; if (profile.HandSimulationMode == HandSimulationMode.Disabled) { RemoveAllHandDevices(); } else { if (handData != null && handData.IsTracked) { SimulatedHand controller = GetOrAddHandDevice(handedness, profile.HandSimulationMode); controller.UpdateState(handData); } else { RemoveHandDevice(handedness); } } }
public void UpdateState(SimulatedHandData handData) { for (int i = 0; i < jointCount; i++) { TrackedHandJoint handJoint = (TrackedHandJoint)i; if (!jointPoses.ContainsKey(handJoint)) { jointPoses.Add(handJoint, handData.Joints[i]); } else { jointPoses[handJoint] = handData.Joints[i]; } } CoreServices.InputSystem?.RaiseHandJointsUpdated(InputSource, ControllerHandedness, jointPoses); UpdateVelocity(); UpdateInteractions(handData); }
// Register input sources for hands based on hand data protected void UpdateHandDevice(HandSimulationMode simulationMode, Handedness handedness, SimulatedHandData handData) { if (handData != null && handData.IsTracked) { SimulatedHand controller = GetOrAddHandDevice(handedness, simulationMode); controller.UpdateState(handData); } else { RemoveHandDevice(handedness); } }
/// <inheritdoc /> protected override void UpdateInteractions(SimulatedHandData handData) { EnsureProfileSettings(); Vector3 lastPosition = currentPosition; currentPosition = jointPoses[TrackedHandJoint.IndexTip].Position; cumulativeDelta += currentPosition - lastPosition; currentGripPose.Position = currentPosition; if (lastPosition != currentPosition) { CoreServices.InputSystem?.RaiseSourcePositionChanged(InputSource, this, currentPosition); } for (int i = 0; i < Interactions?.Length; i++) { switch (Interactions[i].InputType) { case DeviceInputType.SpatialGrip: Interactions[i].PoseData = currentGripPose; if (Interactions[i].Changed) { CoreServices.InputSystem?.RaisePoseInputChanged(InputSource, ControllerHandedness, Interactions[i].MixedRealityInputAction, currentGripPose); } break; case DeviceInputType.Select: Interactions[i].BoolData = handData.IsPinching; if (Interactions[i].Changed) { if (Interactions[i].BoolData) { CoreServices.InputSystem?.RaiseOnInputDown(InputSource, ControllerHandedness, Interactions[i].MixedRealityInputAction); SelectDownStartTime = Time.time; cumulativeDelta = Vector3.zero; } else { CoreServices.InputSystem?.RaiseOnInputUp(InputSource, ControllerHandedness, Interactions[i].MixedRealityInputAction); // Stop active gestures TryCompleteSelect(); TryCompleteHold(); TryCompleteManipulation(); TryCompleteNavigation(); } } else if (Interactions[i].BoolData) { if (manipulationInProgress) { UpdateManipulation(); } if (navigationInProgress) { UpdateNavigation(); } if (cumulativeDelta.magnitude > navigationStartThreshold) { TryCancelHold(); TryStartNavigation(); TryStartManipulation(); } else if (Time.time >= SelectDownStartTime + holdStartDuration) { TryStartHold(); } } break; } } }
/// <summary> /// Updates the positions and orientations of the hand joints of the simulated hand /// </summary> /// <param name="handData">hand data provided by the simulation</param> protected abstract void UpdateHandJoints(SimulatedHandData handData);
/// <inheritdoc /> protected override void UpdateInteractions(SimulatedHandData handData) { lastPointerPose = currentPointerPose; lastGripPose = currentGripPose; // For convenience of simulating in Unity Editor, make the ray use the index // finger position instead of knuckle, since the index finger doesn't move when we press. Vector3 pointerPosition = jointPoses[TrackedHandJoint.IndexTip].Position; IsPositionAvailable = IsRotationAvailable = pointerPosition != Vector3.zero; if (IsPositionAvailable) { HandRay.Update(pointerPosition, GetPalmNormal(), CameraCache.Main.transform, ControllerHandedness); Ray ray = HandRay.Ray; currentPointerPose.Position = ray.origin; currentPointerPose.Rotation = Quaternion.LookRotation(ray.direction); currentGripPose = jointPoses[TrackedHandJoint.Palm]; currentIndexPose = jointPoses[TrackedHandJoint.IndexTip]; } if (lastGripPose != currentGripPose) { if (IsPositionAvailable && IsRotationAvailable) { InputSystem?.RaiseSourcePoseChanged(InputSource, this, currentGripPose); } else if (IsPositionAvailable && !IsRotationAvailable) { InputSystem?.RaiseSourcePositionChanged(InputSource, this, currentPointerPosition); } else if (!IsPositionAvailable && IsRotationAvailable) { InputSystem?.RaiseSourceRotationChanged(InputSource, this, currentPointerRotation); } } for (int i = 0; i < Interactions?.Length; i++) { switch (Interactions[i].InputType) { case DeviceInputType.SpatialPointer: Interactions[i].PoseData = currentPointerPose; if (Interactions[i].Changed) { InputSystem?.RaisePoseInputChanged(InputSource, ControllerHandedness, Interactions[i].MixedRealityInputAction, currentPointerPose); } break; case DeviceInputType.SpatialGrip: Interactions[i].PoseData = currentGripPose; if (Interactions[i].Changed) { InputSystem?.RaisePoseInputChanged(InputSource, ControllerHandedness, Interactions[i].MixedRealityInputAction, currentGripPose); } break; case DeviceInputType.Select: Interactions[i].BoolData = handData.IsPinching; if (Interactions[i].Changed) { if (Interactions[i].BoolData) { InputSystem?.RaiseOnInputDown(InputSource, ControllerHandedness, Interactions[i].MixedRealityInputAction); } else { InputSystem?.RaiseOnInputUp(InputSource, ControllerHandedness, Interactions[i].MixedRealityInputAction); } } break; case DeviceInputType.TriggerPress: Interactions[i].BoolData = handData.IsPinching; if (Interactions[i].Changed) { if (Interactions[i].BoolData) { InputSystem?.RaiseOnInputDown(InputSource, ControllerHandedness, Interactions[i].MixedRealityInputAction); } else { InputSystem?.RaiseOnInputUp(InputSource, ControllerHandedness, Interactions[i].MixedRealityInputAction); } } break; case DeviceInputType.IndexFinger: Interactions[i].PoseData = currentIndexPose; if (Interactions[i].Changed) { InputSystem?.RaisePoseInputChanged(InputSource, ControllerHandedness, Interactions[i].MixedRealityInputAction, currentIndexPose); } break; } } }
protected override void UpdateInteractions(SimulatedHandData handData) { lastPosition = currentPosition; currentPosition = jointPositions[(int)TrackedHandJoint.IndexTip]; currentGripPose.Position = currentPosition; if (lastPosition != currentPosition) { MixedRealityToolkit.InputSystem?.RaiseSourcePositionChanged(InputSource, this, currentPosition); } for (int i = 0; i < Interactions?.Length; i++) { switch (Interactions[i].InputType) { case DeviceInputType.SpatialGrip: Interactions[i].PoseData = currentGripPose; if (Interactions[i].Changed) { MixedRealityToolkit.InputSystem?.RaisePoseInputChanged(InputSource, ControllerHandedness, Interactions[i].MixedRealityInputAction, currentGripPose); } break; case DeviceInputType.Select: Interactions[i].BoolData = handData.IsPinching; if (Interactions[i].Changed) { if (Interactions[i].BoolData) { MixedRealityToolkit.InputSystem?.RaiseOnInputDown(InputSource, ControllerHandedness, Interactions[i].MixedRealityInputAction); SelectDownStartTime = Time.time; cumulativeDelta = Vector3.zero; } else { MixedRealityToolkit.InputSystem?.RaiseOnInputUp(InputSource, ControllerHandedness, Interactions[i].MixedRealityInputAction); // Stop gestures CompleteHoldGesture(); CompleteManipulationNavigationGesture(); } } else if (Interactions[i].BoolData) { // For convenience of simulating in Unity Editor, make the ray use the index // finger position instead of knuckle, since the index finger doesn't move when we press. Vector3 newPosition = jointPositions[(int)TrackedHandJoint.IndexTip]; cumulativeDelta += newPosition - currentPosition; currentPosition = newPosition; if (!manipulationInProgress) { if (cumulativeDelta.magnitude > manipulationStartThreshold) { CancelHoldGesture(); StartManipulationNavigationGesture(); } else if (!holdInProgress) { float time = Time.time; if (time >= SelectDownStartTime + holdStartDuration) { StartHoldGesture(); } } } else { UpdateManipulationNavigationGesture(); } } break; } } }
protected abstract void UpdateInteractions(SimulatedHandData handData);