private void ProcessTouchControllers() { if (_oculusRiftVirtualRealityProvider == null) { return; } var sessionPtr = _oculusRiftVirtualRealityProvider.SessionPtr; var connectedControllerTypes = _ovr.GetConnectedControllerTypes(sessionPtr); if (connectedControllerTypes.HasFlag(ControllerType.LTouch)) // Is Left touch controller connected? { if (_leftControllerVisual3D == null) // If controller is not yet visible, show it { EnsureLeftControllerVisual3D(); _viewport3D.Children.Add(_leftControllerVisual3D); } } else { if (_leftControllerVisual3D != null) // If controller is visible, hide it { _viewport3D.Children.Remove(_leftControllerVisual3D); _leftControllerVisual3D = null; } } if (connectedControllerTypes.HasFlag(ControllerType.RTouch)) // Is Right touch controller connected? { if (_rightControllerVisual3D == null) // If controller is not yet visible, show it { EnsureRightControllerVisual3D(); _viewport3D.Children.Add(_rightControllerVisual3D); } } else { if (_rightControllerVisual3D != null) // If controller is visible, hide it { _viewport3D.Children.Remove(_rightControllerVisual3D); _rightControllerVisual3D = null; } } // If any controller is visible update its transformation if (_leftControllerVisual3D != null || _rightControllerVisual3D != null) { double displayMidpoint = _ovr.GetPredictedDisplayTime(sessionPtr, 0); TrackingState trackingState = _ovr.GetTrackingState(sessionPtr, displayMidpoint, true); var cameraPosition = _camera.GetCameraPosition(); if (_leftControllerVisual3D != null) { var handPose = trackingState.HandPoses[0].ThePose; var handPosePosition = handPose.Position; // Update transformations that are already assigned to _leftControllerVisual3D // First rotate the controller based on its rotation in our hand _leftControllerQuaternionRotation3D.Quaternion = new Quaternion(handPose.Orientation.X, handPose.Orientation.Y, handPose.Orientation.Z, handPose.Orientation.W); // NOTE: Quaternion is struct so no GC "harm" is done here // Now rotate because of our body rotation (the amount of rotation is defined in the _camera.Heading) // We also need to adjust the center of rotation _leftControllerBodyRotateTransform3D.CenterX = -handPosePosition.X; _leftControllerBodyRotateTransform3D.CenterY = -handPosePosition.Y; _leftControllerBodyRotateTransform3D.CenterZ = -handPosePosition.Z; ((AxisAngleRotation3D)_leftControllerBodyRotateTransform3D.Rotation).Angle = -_camera.Heading; // Finally move the controller model for the hand pose offset + body offset _leftControllerTranslateTransform3D.OffsetX = cameraPosition.X + handPosePosition.X; _leftControllerTranslateTransform3D.OffsetY = cameraPosition.Y + handPosePosition.Y; _leftControllerTranslateTransform3D.OffsetZ = cameraPosition.Z + handPosePosition.Z; } if (_rightControllerVisual3D != null) { var handPose = trackingState.HandPoses[1].ThePose; var handPosePosition = handPose.Position; // Update transformations that are already assigned to _rightControllerVisual3D // First rotate the controller based on its rotation in our hand _rightControllerQuaternionRotation3D.Quaternion = new Quaternion(handPose.Orientation.X, handPose.Orientation.Y, handPose.Orientation.Z, handPose.Orientation.W); // NOTE: Quaternion is struct so no GC "harm" is done here // Now rotate because of our body rotation (the amount of rotation is defined in the _camera.Heading) // We also need to adjust the center of rotation _rightControllerBodyRotateTransform3D.CenterX = -handPosePosition.X; _rightControllerBodyRotateTransform3D.CenterY = -handPosePosition.Y; _rightControllerBodyRotateTransform3D.CenterZ = -handPosePosition.Z; ((AxisAngleRotation3D)_rightControllerBodyRotateTransform3D.Rotation).Angle = -_camera.Heading; // Finally move the controller model for the hand pose offset + body offset _rightControllerTranslateTransform3D.OffsetX = cameraPosition.X + handPosePosition.X; _rightControllerTranslateTransform3D.OffsetY = cameraPosition.Y + handPosePosition.Y; _rightControllerTranslateTransform3D.OffsetZ = cameraPosition.Z + handPosePosition.Z; } // Check the state of the controller Thicksticks and move or rotate accordingly var leftControllerInputState = new InputState(); var rightControllerInputState = new InputState(); _ovr.GetInputState(sessionPtr, ControllerType.LTouch, ref leftControllerInputState); _ovr.GetInputState(sessionPtr, ControllerType.RTouch, ref rightControllerInputState); // Change camera angle _camera.Heading += rightControllerInputState.Thumbstick[1].X * _xInputCameraController.RotationSpeed; // Now move the camera (use strafe directions) double dx = leftControllerInputState.Thumbstick[0].X * _xInputCameraController.MovementSpeed; double dy = leftControllerInputState.Thumbstick[0].Y * _xInputCameraController.MovementSpeed; // strafeDirection is perpendicular to LookDirection and UpDirection var strafeDirection = Vector3D.CrossProduct(_camera.LookDirection, _camera.UpDirection); strafeDirection.Normalize(); Vector3D movementVector = strafeDirection * dx; // move left / right Vector3D usedLookDirection = _camera.LookDirection; if (_xInputCameraController.MoveOnlyHorizontally) { usedLookDirection.Y = 0; // Zero y direction when we move only horizontally } usedLookDirection.Normalize(); movementVector += usedLookDirection * dy; // move forward / backward _camera.Offset += movementVector; } }