internal void CalibrateFullBodyTrackingManual(SpawnedAvatar spawnedAvatar) { _logger.Info("Running manual full body tracking calibration"); CalibrationData.FullBodyCalibration fullBodyCalibration = _calibrationData.GetAvatarManualCalibration(spawnedAvatar.avatar.fileName); if (TryGetUncalibratedPoseForAvatar(DeviceUse.Waist, spawnedAvatar, out Pose waist)) { Vector3 positionOffset = Quaternion.Inverse(waist.rotation) * (spawnedAvatar.pelvis.position - waist.position); Quaternion rotationOffset = Quaternion.Inverse(waist.rotation) * spawnedAvatar.pelvis.rotation; fullBodyCalibration.waist = new Pose(positionOffset, rotationOffset); _logger.Info("Set waist pose correction " + fullBodyCalibration.waist); } if (TryGetUncalibratedPoseForAvatar(DeviceUse.LeftFoot, spawnedAvatar, out Pose leftFoot)) { Vector3 positionOffset = Quaternion.Inverse(leftFoot.rotation) * (spawnedAvatar.leftLeg.position - leftFoot.position); Quaternion rotationOffset = Quaternion.Inverse(leftFoot.rotation) * spawnedAvatar.leftLeg.rotation; fullBodyCalibration.leftFoot = new Pose(positionOffset, rotationOffset); _logger.Info("Set left foot pose correction " + fullBodyCalibration.leftFoot); } if (TryGetUncalibratedPoseForAvatar(DeviceUse.RightFoot, spawnedAvatar, out Pose rightFoot)) { Vector3 positionOffset = Quaternion.Inverse(rightFoot.rotation) * (spawnedAvatar.rightLeg.position - rightFoot.position); Quaternion rotationOffset = Quaternion.Inverse(rightFoot.rotation) * spawnedAvatar.rightLeg.rotation; fullBodyCalibration.rightFoot = new Pose(positionOffset, rotationOffset); _logger.Info("Set right foot pose correction " + fullBodyCalibration.rightFoot); } inputChanged?.Invoke(); }
private void UpdateUI(LoadedAvatar avatar) { DisableCalibrationMode(false); if (avatar == null) { _clearButton.interactable = false; _calibrateButton.interactable = false; _automaticCalibrationSetting.checkbox.interactable = false; _automaticCalibrationHoverHint.text = "No avatar selected"; return; } _currentAvatarSettings = _settings.GetAvatarSettings(avatar.fileName); _currentAvatarManualCalibration = _calibrationData.GetAvatarManualCalibration(avatar.fileName); UpdateCalibrationButtons(avatar); _ignoreExclusionsSetting.CheckboxValue = _currentAvatarSettings.ignoreExclusions; _bypassCalibration.CheckboxValue = _currentAvatarSettings.bypassCalibration; _bypassCalibration.checkbox.interactable = avatar.supportsFullBodyTracking; _bypassCalibrationHoverHint.text = avatar.supportsFullBodyTracking ? "Disable the need for calibration before full body tracking is applied." : "Not supported by current avatar"; _automaticCalibrationSetting.CheckboxValue = _currentAvatarSettings.useAutomaticCalibration; _automaticCalibrationSetting.checkbox.interactable = avatar.descriptor.supportsAutomaticCalibration; _automaticCalibrationHoverHint.text = avatar.descriptor.supportsAutomaticCalibration ? "Use automatic calibration instead of manual calibration." : "Not supported by current avatar"; }
private void UpdateUI(LoadedAvatar avatar) { SetInteractableRecursively(avatar != null); UpdateCalibrationButtons(avatar); if (avatar == null) { _clearButton.interactable = false; _calibrateButton.interactable = false; _automaticCalibrationSetting.interactable = false; _automaticCalibrationHoverHint.text = "No avatar selected"; return; } _currentAvatarSettings = _settings.GetAvatarSettings(avatar.fileName); _currentAvatarManualCalibration = _calibrationData.GetAvatarManualCalibration(avatar.fileName); _ignoreExclusionsSetting.Value = _currentAvatarSettings.ignoreExclusions; _bypassCalibration.Value = _currentAvatarSettings.bypassCalibration; _automaticCalibrationSetting.Value = _currentAvatarSettings.useAutomaticCalibration; _automaticCalibrationSetting.interactable = avatar.descriptor.supportsAutomaticCalibration; _automaticCalibrationHoverHint.text = avatar.descriptor.supportsAutomaticCalibration ? "Use automatic calibration instead of manual calibration." : "Not supported by current avatar"; }
public void UpdateUI(SpawnedAvatar avatar) { if (_currentAvatarSettings != null) { _currentAvatarSettings.useAutomaticCalibration.changed -= OnUseAutomaticCalibrationChanged; } UpdateCalibrationButtons(avatar); if (!avatar) { _clearButton.interactable = false; _calibrateButton.interactable = false; _automaticCalibrationSetting.interactable = false; _automaticCalibrationHoverHint.text = "No avatar selected"; return; } _currentAvatarSettings = _settings.GetAvatarSettings(avatar.prefab.fileName); _currentAvatarManualCalibration = _calibrationData.GetAvatarManualCalibration(avatar.prefab.fileName); _currentAvatarSettings.useAutomaticCalibration.changed += OnUseAutomaticCalibrationChanged; _ignoreExclusionsSetting.Value = _currentAvatarSettings.ignoreExclusions; _bypassCalibration.Value = _currentAvatarSettings.bypassCalibration; _automaticCalibrationSetting.Value = _currentAvatarSettings.useAutomaticCalibration; _automaticCalibrationSetting.interactable = avatar.prefab.descriptor.supportsAutomaticCalibration; _automaticCalibrationHoverHint.text = avatar.prefab.descriptor.supportsAutomaticCalibration ? "Use automatic calibration instead of manual calibration." : "Not supported by current avatar"; }
public void ClearAutomaticFullBodyTrackingData() { CalibrationData.FullBodyCalibration fullBodyCalibration = _calibrationData.automaticCalibration; fullBodyCalibration.leftFoot = Pose.identity; fullBodyCalibration.rightFoot = Pose.identity; fullBodyCalibration.waist = Pose.identity; }
public void ClearManualFullBodyTrackingData(SpawnedAvatar spawnedAvatar) { CalibrationData.FullBodyCalibration fullBodyCalibration = _calibrationData.GetAvatarManualCalibration(spawnedAvatar.avatar.fileName); fullBodyCalibration.leftFoot = Pose.identity; fullBodyCalibration.rightFoot = Pose.identity; fullBodyCalibration.waist = Pose.identity; }
internal void ClearAutomaticFullBodyTrackingData() { CalibrationData.FullBodyCalibration fullBodyCalibration = _calibrationData.automaticCalibration; fullBodyCalibration.leftFoot = Pose.identity; fullBodyCalibration.rightFoot = Pose.identity; fullBodyCalibration.waist = Pose.identity; inputChanged?.Invoke(); }
internal void ClearManualFullBodyTrackingData(SpawnedAvatar spawnedAvatar) { CalibrationData.FullBodyCalibration fullBodyCalibration = _calibrationData.GetAvatarManualCalibration(spawnedAvatar.avatar.fileName); fullBodyCalibration.leftFoot = Pose.identity; fullBodyCalibration.rightFoot = Pose.identity; fullBodyCalibration.waist = Pose.identity; inputChanged?.Invoke(); }
public void CalibrateFullBodyTrackingAuto() { _logger.Info("Calibrating full body tracking"); CalibrationData.FullBodyCalibration fullBodyCalibration = _calibrationData.automaticCalibration; Vector3 floorNormal = Vector3.up; float floorPosition = _settings.moveFloorWithRoomAdjust ? _roomCenter.y : 0; if (_trackedDeviceManager.leftFoot.tracked) { TrackedDeviceState leftFoot = _trackedDeviceManager.leftFoot; Vector3 leftFootForward = leftFoot.rotation * Vector3.up; // forward on feet trackers is y (up) Vector3 leftFootStraightForward = Vector3.ProjectOnPlane(leftFootForward, floorNormal); // get projection of forward vector on xz plane (floor) Quaternion leftRotationCorrection = Quaternion.Inverse(leftFoot.rotation) * Quaternion.LookRotation(Vector3.up, leftFootStraightForward); // get difference between world rotation and flat forward rotation fullBodyCalibration.leftFoot = new Pose((leftFoot.position.y - floorPosition) * Vector3.back, leftRotationCorrection); _logger.Info("Set left foot pose correction " + fullBodyCalibration.leftFoot); } if (_trackedDeviceManager.rightFoot.tracked) { TrackedDeviceState rightFoot = _trackedDeviceManager.rightFoot; Vector3 rightFootForward = rightFoot.rotation * Vector3.up; Vector3 rightFootStraightForward = Vector3.ProjectOnPlane(rightFootForward, floorNormal); Quaternion rightRotationCorrection = Quaternion.Inverse(rightFoot.rotation) * Quaternion.LookRotation(Vector3.up, rightFootStraightForward); fullBodyCalibration.rightFoot = new Pose((rightFoot.position.y - floorPosition) * Vector3.back, rightRotationCorrection); _logger.Info("Set right foot pose correction " + fullBodyCalibration.rightFoot); } if (_trackedDeviceManager.head.tracked && _trackedDeviceManager.waist.tracked) { TrackedDeviceState head = _trackedDeviceManager.head; TrackedDeviceState pelvis = _trackedDeviceManager.waist; // using "standard" 8 head high body proportions w/ eyes at 1/2 head height // reference: https://miro.medium.com/max/3200/1*cqTRyEGl26l4CImEmWz68Q.jpeg float eyeHeight = head.position.y - floorPosition; Vector3 wantedPelvisPosition = new Vector3(0, eyeHeight / 22.5f * 14f, 0); Vector3 pelvisPositionCorrection = wantedPelvisPosition - Vector3.up * (pelvis.position.y - floorPosition); Vector3 pelvisForward = pelvis.rotation * Vector3.forward; Vector3 pelvisStraightForward = Vector3.ProjectOnPlane(pelvisForward, floorNormal); Quaternion pelvisRotationCorrection = Quaternion.Inverse(pelvis.rotation) * Quaternion.LookRotation(pelvisStraightForward, Vector3.up); fullBodyCalibration.waist = new Pose(pelvisPositionCorrection, pelvisRotationCorrection); _logger.Info("Set waist pose correction " + fullBodyCalibration.waist); } }
internal VRPlayerInput(TrackedDeviceManager trackedDeviceManager, LoadedAvatar avatar, Settings settings, CalibrationData calibrationData) { _deviceManager = trackedDeviceManager; _settings = settings; _avatarSettings = settings.GetAvatarSettings(avatar.fileName); _calibrationData = calibrationData; _manualCalibration = calibrationData.GetAvatarManualCalibration(avatar.fileName); _deviceManager.deviceAdded += OnDevicesUpdated; _deviceManager.deviceRemoved += OnDevicesUpdated; _deviceManager.deviceTrackingAcquired += OnDevicesUpdated; _deviceManager.deviceTrackingLost += OnDevicesUpdated; _leftHandAnimAction = new SkeletalInput("/actions/customavatars/in/lefthandanim"); _rightHandAnimAction = new SkeletalInput("/actions/customavatars/in/righthandanim"); }
internal void CalibrateFullBodyTrackingAuto() { _logger.Info("Running automatic full body tracking calibration"); CalibrationData.FullBodyCalibration fullBodyCalibration = _calibrationData.automaticCalibration; Vector3 floorNormal = Vector3.up; if (TryGetUncalibratedPose(DeviceUse.LeftFoot, out Pose leftFoot)) { Vector3 leftFootForward = leftFoot.rotation * Vector3.up; // forward on feet trackers is y (up) Vector3 leftFootStraightForward = Vector3.ProjectOnPlane(leftFootForward, floorNormal); // get projection of forward vector on xz plane (floor) Quaternion leftRotationCorrection = Quaternion.Inverse(leftFoot.rotation) * Quaternion.LookRotation(Vector3.up, leftFootStraightForward); // get difference between world rotation and flat forward rotation fullBodyCalibration.leftFoot = new Pose(leftFoot.position.y * Vector3.back, leftRotationCorrection); _logger.Info("Set left foot pose correction " + fullBodyCalibration.leftFoot); } if (TryGetUncalibratedPose(DeviceUse.RightFoot, out Pose rightFoot)) { Vector3 rightFootForward = rightFoot.rotation * Vector3.up; Vector3 rightFootStraightForward = Vector3.ProjectOnPlane(rightFootForward, floorNormal); Quaternion rightRotationCorrection = Quaternion.Inverse(rightFoot.rotation) * Quaternion.LookRotation(Vector3.up, rightFootStraightForward); fullBodyCalibration.rightFoot = new Pose(rightFoot.position.y * Vector3.back, rightRotationCorrection); _logger.Info("Set right foot pose correction " + fullBodyCalibration.rightFoot); } if (TryGetUncalibratedPose(DeviceUse.Head, out Pose head) && TryGetUncalibratedPose(DeviceUse.Waist, out Pose waist)) { // using "standard" 8 head high body proportions w/ eyes at 1/2 head height // reference: https://miro.medium.com/max/3200/1*cqTRyEGl26l4CImEmWz68Q.jpeg float eyeHeight = head.position.y; Vector3 wantedWaistPosition = new Vector3(0, eyeHeight / 22.5f * 14f, 0); Vector3 waistPositionCorrection = wantedWaistPosition - Vector3.up * waist.position.y; Vector3 waistForward = waist.rotation * Vector3.forward; Vector3 waistStraightForward = Vector3.ProjectOnPlane(waistForward, floorNormal); Quaternion waistRotationCorrection = Quaternion.Inverse(waist.rotation) * Quaternion.LookRotation(waistStraightForward, Vector3.up); fullBodyCalibration.waist = new Pose(waistPositionCorrection, waistRotationCorrection); _logger.Info("Set waist pose correction " + fullBodyCalibration.waist); _beatSaberUtilities.SetPlayerHeight(eyeHeight + MainSettingsModelSO.kHeadPosToPlayerHeightOffset); } inputChanged?.Invoke(); }
private void OnAvatarChanged(SpawnedAvatar spawnedAvatar) { if (_avatarSettings != null) { _avatarSettings.useAutomaticCalibration.changed -= OnUseAutomaticCalibrationChanged; _avatarSettings.bypassCalibration.changed -= OnBypassCalibrationChanged; } if (!spawnedAvatar) { _avatarSettings = null; _manualCalibration = null; return; } _avatarSettings = _settings.GetAvatarSettings(spawnedAvatar.avatar.fileName); _manualCalibration = _calibrationData.GetAvatarManualCalibration(spawnedAvatar.avatar.fileName); _avatarSettings.useAutomaticCalibration.changed += OnUseAutomaticCalibrationChanged; _avatarSettings.bypassCalibration.changed += OnBypassCalibrationChanged; }
public void CalibrateFullBodyTrackingManual(SpawnedAvatar spawnedAvatar) { CalibrationData.FullBodyCalibration fullBodyCalibration = _calibrationData.GetAvatarManualCalibration(spawnedAvatar.avatar.fileName); if (_trackedDeviceManager.waist.tracked) { TrackedDeviceState pelvis = _trackedDeviceManager.waist; Vector3 positionOffset = Quaternion.Inverse(spawnedAvatar.pelvis.rotation) * (spawnedAvatar.pelvis.position - ApplyTrackedPointFloorOffset(spawnedAvatar, pelvis.position)); Quaternion rotationOffset = Quaternion.Inverse(pelvis.rotation) * spawnedAvatar.pelvis.rotation; fullBodyCalibration.waist = new Pose(positionOffset, rotationOffset); _logger.Info("Set waist pose correction " + fullBodyCalibration.waist); } if (_trackedDeviceManager.leftFoot.tracked) { TrackedDeviceState leftFoot = _trackedDeviceManager.leftFoot; Vector3 positionOffset = Quaternion.Inverse(spawnedAvatar.leftLeg.rotation) * (spawnedAvatar.leftLeg.position - ApplyTrackedPointFloorOffset(spawnedAvatar, leftFoot.position)); Quaternion rotationOffset = Quaternion.Inverse(leftFoot.rotation) * spawnedAvatar.leftLeg.rotation; fullBodyCalibration.leftFoot = new Pose(positionOffset, rotationOffset); _logger.Info("Set left foot pose correction " + fullBodyCalibration.leftFoot); } if (_trackedDeviceManager.rightFoot.tracked) { TrackedDeviceState rightFoot = _trackedDeviceManager.rightFoot; Vector3 positionOffset = Quaternion.Inverse(spawnedAvatar.rightLeg.rotation) * (spawnedAvatar.rightLeg.position - ApplyTrackedPointFloorOffset(spawnedAvatar, rightFoot.position)); Quaternion rotationOffset = Quaternion.Inverse(rightFoot.rotation) * spawnedAvatar.rightLeg.rotation; fullBodyCalibration.rightFoot = new Pose(positionOffset, rotationOffset); _logger.Info("Set right foot pose correction " + fullBodyCalibration.rightFoot); } }