diff --git a/src/overlaycontroller.cpp b/src/overlaycontroller.cpp index d5ceeb8..28a6e71 100644 --- a/src/overlaycontroller.cpp +++ b/src/overlaycontroller.cpp @@ -710,7 +710,7 @@ void OverlayController::mainEventLoop() LOG( INFO ) << "Received quit request."; vr::VRSystem()->AcknowledgeQuit_Exiting(); // Let us buy some // time just in case - m_moveCenterTabController.reset(); + m_moveCenterTabController.shutdown(); // Un-mute mic before Exiting VR, as it is set at system level Not // Vr level. m_audioTabController.setMicMuted( false, false ); @@ -748,6 +748,13 @@ void OverlayController::mainEventLoop() } break; + case vr::VREvent_SeatedZeroPoseReset: + { + m_moveCenterTabController.incomingSeatedReset(); + LOG( INFO ) << "Game Triggered Seated Zero-Position Reset"; + } + break; + // Multiple ChaperoneUniverseHasChanged are often emitted at the // same time (some with a little bit of delay) There is no sure way // to recognize redundant events, we can only exclude redundant diff --git a/src/overlaycontroller.h b/src/overlaycontroller.h index d9427cc..1cd94ab 100644 --- a/src/overlaycontroller.h +++ b/src/overlaycontroller.h @@ -61,7 +61,7 @@ namespace advsettings // Avoid setting values to the same numbers. constexpr int k_audioSettingsUpdateCounter = 89; constexpr int k_chaperoneSettingsUpdateCounter = 101; -constexpr int k_moveCenterSettingsUpdateCounter = 149; +constexpr int k_moveCenterSettingsUpdateCounter = 83; constexpr int k_reviveSettingsUpdateCounter = 139; constexpr int k_settingsTabSettingsUpdateCounter = 157; constexpr int k_steamVrSettingsUpdateCounter = 97; diff --git a/src/res/qml/PlayspacePage.qml b/src/res/qml/PlayspacePage.qml index a762f4f..f0b6e9c 100644 --- a/src/res/qml/PlayspacePage.qml +++ b/src/res/qml/PlayspacePage.qml @@ -340,6 +340,30 @@ MyStackViewPage { } } + Item { + Layout.fillWidth: true + } + + MyPushButton { + id: spaceLogMatrices + Layout.preferredWidth: 250 + visible: MoveCenterTabController.showLogMatricesButton + text: "Log Matrices" + onClicked: { + MoveCenterTabController.outputLogPoses() + } + } + + MyPushButton { + id: spaceSeatedRecenter + Layout.preferredWidth: 250 + visible: false + text: "Seated Recenter" + onClicked: { + MoveCenterTabController.updateSeatedResetData() + } + } + } } @@ -356,19 +380,14 @@ MyStackViewPage { lockXToggle.checked = MoveCenterTabController.lockXToggle lockYToggle.checked = MoveCenterTabController.lockYToggle lockZToggle.checked = MoveCenterTabController.lockZToggle + spaceLogMatrices.visible = MoveCenterTabController.showLogMatricesButton if (MoveCenterTabController.trackingUniverse === 0) { spaceModeText.text = "Sitting" - spaceRotationPlusButton.enabled = false - spaceRotationMinusButton.enabled = false - spaceRotationSlider.enabled = false - spaceRotationText.text = "-" + spaceSeatedRecenter.visible = true } else if (MoveCenterTabController.trackingUniverse === 1) { spaceModeText.text = "Standing" - spaceRotationPlusButton.enabled = true - spaceRotationMinusButton.enabled = true - spaceRotationSlider.enabled = true - spaceRotationText.text = "0°" + spaceSeatedRecenter.visible = false } else { spaceModeText.text = "Unknown(" + MoveCenterTabController.trackingUniverse + ")" } @@ -407,16 +426,10 @@ MyStackViewPage { onTrackingUniverseChanged: { if (MoveCenterTabController.trackingUniverse === 0) { spaceModeText.text = "Sitting" - spaceRotationPlusButton.enabled = false - spaceRotationMinusButton.enabled = false - spaceRotationSlider.enabled = false - spaceRotationText.text = "-" + spaceSeatedRecenter.visible = true } else if (MoveCenterTabController.trackingUniverse === 1) { spaceModeText.text = "Standing" - spaceRotationPlusButton.enabled = true - spaceRotationMinusButton.enabled = true - spaceRotationSlider.enabled = true - spaceRotationText.text = "0°" + spaceSeatedRecenter.visible = false } else { spaceModeText.text = "Unknown(" + MoveCenterTabController.trackingUniverse + ")" } diff --git a/src/res/qml/SettingsPage.qml b/src/res/qml/SettingsPage.qml index 79eb375..6fd4b17 100644 --- a/src/res/qml/SettingsPage.qml +++ b/src/res/qml/SettingsPage.qml @@ -26,6 +26,14 @@ MyStackViewPage { } } + MyToggleButton { + id: allowExternalEditsToggle + text: "Allow External App Chaperone Edits (Danger)" + onCheckedChanged: { + MoveCenterTabController.setAllowExternalEdits(checked, true) + } + } + Item { Layout.fillHeight: true } @@ -33,6 +41,7 @@ MyStackViewPage { Component.onCompleted: { settingsAutoStartToggle.checked = SettingsTabController.autoStartEnabled forceReviveToggle.checked = SettingsTabController.forceRevivePage + allowExternalEditsToggle.checked = MoveCenterTabController.allowExternalEdits } Connections { @@ -44,5 +53,12 @@ MyStackViewPage { forceReviveToggle.checked = SettingsTabController.forceRevivePage } } + + Connections { + target: MoveCenterTabController + onAllowExternalEditsChanged: { + allowExternalEditsToggle.checked = MoveCenterTabController.allowExternalEdits + } + } } } diff --git a/src/tabcontrollers/MoveCenterTabController.cpp b/src/tabcontrollers/MoveCenterTabController.cpp index c900d56..500b42f 100644 --- a/src/tabcontrollers/MoveCenterTabController.cpp +++ b/src/tabcontrollers/MoveCenterTabController.cpp @@ -118,6 +118,16 @@ void MoveCenterTabController::initStage1() { m_lockZToggle = value.toBool(); } + value = settings->value( "showLogMatricesButton", m_showLogMatricesButton ); + if ( value.isValid() && !value.isNull() ) + { + m_showLogMatricesButton = value.toBool(); + } + value = settings->value( "allowExternalEdits", m_allowExternalEdits ); + if ( value.isValid() && !value.isNull() ) + { + m_allowExternalEdits = value.toBool(); + } settings->endGroup(); m_lastDragUpdateTimePoint = std::chrono::steady_clock::now(); m_lastGravityUpdateTimePoint = std::chrono::steady_clock::now(); @@ -131,6 +141,109 @@ void MoveCenterTabController::initStage2( OverlayController* var_parent, this->widget = var_widget; } +void MoveCenterTabController::outputLogPoses() +{ + vr::TrackedDevicePose_t devicePosesStanding[vr::k_unMaxTrackedDeviceCount]; + + vr::VRSystem()->GetDeviceToAbsoluteTrackingPose( + vr::TrackingUniverseStanding, + 0.0f, + devicePosesStanding, + vr::k_unMaxTrackedDeviceCount ); + + vr::HmdMatrix34_t hmdStanding + = devicePosesStanding[0].mDeviceToAbsoluteTracking; + + LOG( INFO ) << "HMD POSE (standing universe)"; + outputLogHmdMatrix( hmdStanding ); + + vr::TrackedDevicePose_t devicePosesSeated[vr::k_unMaxTrackedDeviceCount]; + + vr::VRSystem()->GetDeviceToAbsoluteTrackingPose( + vr::TrackingUniverseSeated, + 0.0f, + devicePosesSeated, + vr::k_unMaxTrackedDeviceCount ); + + vr::HmdMatrix34_t hmdSeated + = devicePosesSeated[0].mDeviceToAbsoluteTracking; + + LOG( INFO ) << "HMD POSE (seated universe)"; + outputLogHmdMatrix( hmdSeated ); + + auto leftHand = vr::VRSystem()->GetTrackedDeviceIndexForControllerRole( + vr::TrackedControllerRole_LeftHand ); + auto rightHand = vr::VRSystem()->GetTrackedDeviceIndexForControllerRole( + vr::TrackedControllerRole_RightHand ); + + vr::HmdMatrix34_t leftHandMatrix + = devicePosesStanding[leftHand].mDeviceToAbsoluteTracking; + vr::HmdMatrix34_t rightHandMatrix + = devicePosesStanding[rightHand].mDeviceToAbsoluteTracking; + + LOG( INFO ) << "LEFT Hand Controller Pose (standing universe)"; + outputLogHmdMatrix( leftHandMatrix ); + + LOG( INFO ) << "RIGHT Hand Controller Pose (standing universe)"; + outputLogHmdMatrix( rightHandMatrix ); + + vr::HmdMatrix34_t standingZero; + vr::VRChaperoneSetup()->GetWorkingStandingZeroPoseToRawTrackingPose( + &standingZero ); + LOG( INFO ) << "GetWorkingStandingZeroPoseToRawTrackingPose"; + outputLogHmdMatrix( standingZero ); + + vr::HmdMatrix34_t seatedZero; + vr::VRChaperoneSetup()->GetWorkingSeatedZeroPoseToRawTrackingPose( + &seatedZero ); + LOG( INFO ) << "GetWorkingSeatedZeroPoseToRawTrackingPose"; + outputLogHmdMatrix( seatedZero ); + + vr::HmdMatrix34_t seatedZeroLive; + vr::VRChaperoneSetup()->GetLiveSeatedZeroPoseToRawTrackingPose( + &seatedZeroLive ); + LOG( INFO ) << "GetLiveSeatedZeroPoseToRawTrackingPose"; + outputLogHmdMatrix( seatedZeroLive ); + + vr::HmdMatrix34_t seatedToStandingAbsolute + = vr::VRSystem()->GetSeatedZeroPoseToStandingAbsoluteTrackingPose(); + LOG( INFO ) << "GetSeatedZeroPoseToStandingAbsoluteTrackingPose"; + outputLogHmdMatrix( seatedToStandingAbsolute ); + + LOG( INFO ) << "m_universeCenterForReset"; + outputLogHmdMatrix( m_universeCenterForReset ); + + LOG( INFO ) << "m_seatedCenterForReset"; + outputLogHmdMatrix( m_seatedCenterForReset ); +} + +void MoveCenterTabController::outputLogHmdMatrix( vr::HmdMatrix34_t hmdMatrix ) +{ + LOG( INFO ) << hmdMatrix.m[0][0] << "\t\t\t" << hmdMatrix.m[0][1] + << "\t\t\t" << hmdMatrix.m[0][2] << "\t\t\t" + << hmdMatrix.m[0][3]; + LOG( INFO ) << hmdMatrix.m[1][0] << "\t\t\t" << hmdMatrix.m[1][1] + << "\t\t\t" << hmdMatrix.m[1][2] << "\t\t\t" + << hmdMatrix.m[1][3]; + LOG( INFO ) << hmdMatrix.m[2][0] << "\t\t\t" << hmdMatrix.m[2][1] + << "\t\t\t" << hmdMatrix.m[2][2] << "\t\t\t" + << hmdMatrix.m[2][3]; + + float atan2Yaw = std::atan2( hmdMatrix.m[0][2], hmdMatrix.m[2][2] ); + LOG( INFO ) << "atan2 Yaw Calculation: " << atan2Yaw << "radians " + << ( ( static_cast( atan2Yaw ) + * k_radiansToCentidegrees ) + / 100 ) + << "degrees"; + + vr::HmdQuaternion_t hmdQuat = quaternion::fromHmdMatrix34( hmdMatrix ); + double hmdQuatYaw = quaternion::getYaw( hmdQuat ); + LOG( INFO ) << "Quaternion Yaw Calculation: " << hmdQuatYaw << "radians " + << ( ( hmdQuatYaw * k_radiansToCentidegrees ) / 100 ) + << "degrees"; + LOG( INFO ) << ""; +} + int MoveCenterTabController::trackingUniverse() const { return static_cast( m_trackingUniverse ); @@ -140,7 +253,12 @@ void MoveCenterTabController::setTrackingUniverse( int value, bool notify ) { if ( m_trackingUniverse != value ) { - reset(); + vr::VRChaperoneSetup()->HideWorkingSetPreview(); + if ( !m_roomSetupModeDetected && value == vr::TrackingUniverseStanding ) + { + reset(); + } + m_trackingUniverse = value; if ( notify ) { @@ -207,11 +325,25 @@ void MoveCenterTabController::setRotation( int value, bool notify ) // Get hmd pose matrix. vr::TrackedDevicePose_t devicePosesForRot[vr::k_unMaxTrackedDeviceCount]; - vr::VRSystem()->GetDeviceToAbsoluteTrackingPose( - vr::TrackingUniverseStanding, - 0.0f, - devicePosesForRot, - vr::k_unMaxTrackedDeviceCount ); + + // source must be current universe + if ( m_trackingUniverse == vr::TrackingUniverseSeated ) + { + vr::VRSystem()->GetDeviceToAbsoluteTrackingPose( + vr::TrackingUniverseSeated, + 0.0f, + devicePosesForRot, + vr::k_unMaxTrackedDeviceCount ); + } + else + { + vr::VRSystem()->GetDeviceToAbsoluteTrackingPose( + vr::TrackingUniverseStanding, + 0.0f, + devicePosesForRot, + vr::k_unMaxTrackedDeviceCount ); + } + vr::HmdMatrix34_t oldHmdPos = devicePosesForRot[0].mDeviceToAbsoluteTracking; @@ -626,6 +758,45 @@ void MoveCenterTabController::setLockZ( bool value, bool notify ) } } +bool MoveCenterTabController::showLogMatricesButton() const +{ + return m_showLogMatricesButton; +} + +void MoveCenterTabController::setShowLogMatricesButton( bool value, + bool notify ) +{ + m_showLogMatricesButton = value; + auto settings = OverlayController::appSettings(); + settings->beginGroup( "playspaceSettings" ); + settings->setValue( "showLogMatricesButton", m_showLogMatricesButton ); + settings->endGroup(); + settings->sync(); + if ( notify ) + { + emit showLogMatricesButtonChanged( m_showLogMatricesButton ); + } +} + +bool MoveCenterTabController::allowExternalEdits() const +{ + return m_allowExternalEdits; +} + +void MoveCenterTabController::setAllowExternalEdits( bool value, bool notify ) +{ + m_allowExternalEdits = value; + auto settings = OverlayController::appSettings(); + settings->beginGroup( "playspaceSettings" ); + settings->setValue( "allowExternalEdits", m_allowExternalEdits ); + settings->endGroup(); + settings->sync(); + if ( notify ) + { + emit allowExternalEditsChanged( m_allowExternalEdits ); + } +} + void MoveCenterTabController::modOffsetX( float value, bool notify ) { if ( !m_lockXToggle ) @@ -662,11 +833,22 @@ void MoveCenterTabController::modOffsetZ( float value, bool notify ) } } +void MoveCenterTabController::shutdown() +{ + reset(); + vr::VRChaperoneSetup()->HideWorkingSetPreview(); +} + +void MoveCenterTabController::incomingSeatedReset() +{ + updateSeatedResetData(); +} + void MoveCenterTabController::reset() { + vr::VRChaperoneSetup()->HideWorkingSetPreview(); m_heightToggle = false; emit heightToggleChanged( m_heightToggle ); - applyChaperoneResetData(); m_oldOffsetX = 0.0f; m_oldOffsetY = 0.0f; m_oldOffsetZ = 0.0f; @@ -675,6 +857,7 @@ void MoveCenterTabController::reset() m_offsetY = 0.0f; m_offsetZ = 0.0f; m_rotation = 0; + applyChaperoneResetData(); emit offsetXChanged( m_offsetX ); emit offsetYChanged( m_offsetY ); emit offsetZChanged( m_offsetZ ); @@ -700,9 +883,20 @@ void MoveCenterTabController::zeroOffsets() emit rotationChanged( m_rotation ); updateChaperoneResetData(); m_pendingZeroOffsets = false; + if ( m_roomSetupModeDetected ) + { + LOG( INFO ) << "room setup EXIT detected"; + m_roomSetupModeDetected = false; + } + + LOG( INFO ) << "SUCCESS: Chaperone Data Updated and Offsets zeroed out"; } else { + if ( !m_pendingZeroOffsets ) + { + LOG( INFO ) << "PENDING: Chaperone Data Update and Offsets zeroing"; + } m_pendingZeroOffsets = true; } } @@ -729,6 +923,46 @@ void MoveCenterTabController::clampVelocity( double* velocity ) } } +void MoveCenterTabController::updateSeatedResetData() +{ + reset(); + vr::VRChaperoneSetup()->RevertWorkingCopy(); + vr::TrackedDevicePose_t devicePosesStanding[vr::k_unMaxTrackedDeviceCount]; + vr::VRSystem()->GetDeviceToAbsoluteTrackingPose( + vr::TrackingUniverseStanding, + 0.0f, + devicePosesStanding, + vr::k_unMaxTrackedDeviceCount ); + vr::HmdMatrix34_t hmdMatrix + = devicePosesStanding[0].mDeviceToAbsoluteTracking; + + vr::HmdQuaternion_t hmdQuat = quaternion::fromHmdMatrix34( hmdMatrix ); + double hmdYaw = quaternion::getYaw( hmdQuat ); + int hmdYawCentideg = static_cast( hmdYaw * k_radiansToCentidegrees ); + // Keep angle within -18000 ~ 18000 centidegrees + if ( hmdYawCentideg > 18000 ) + { + hmdYawCentideg -= 36000; + } + else if ( hmdYawCentideg < -18000 ) + { + hmdYawCentideg += 36000; + } + + m_seatedCenterForReset = m_universeCenterForReset; + m_seatedHeight = hmdMatrix.m[1][3]; + m_seatedCenterForReset.m[1][3] += m_seatedHeight; + + m_offsetX = hmdMatrix.m[0][3]; + m_offsetY = 0.0f; + m_offsetZ = hmdMatrix.m[2][3]; + m_rotation = hmdYawCentideg; + emit offsetXChanged( m_offsetX ); + emit offsetYChanged( m_offsetY ); + emit offsetZChanged( m_offsetZ ); + emit rotationChanged( m_rotation ); +} + void MoveCenterTabController::updateChaperoneResetData() { vr::VRChaperoneSetup()->HideWorkingSetPreview(); @@ -741,50 +975,76 @@ void MoveCenterTabController::updateChaperoneResetData() m_collisionBoundsCountForReset = currentQuadCount; vr::VRChaperoneSetup()->GetWorkingCollisionBoundsInfo( m_collisionBoundsForReset, ¤tQuadCount ); + vr::VRChaperoneSetup()->GetWorkingStandingZeroPoseToRawTrackingPose( &m_universeCenterForReset ); - float universeCenterForResetYaw = std::atan2( - m_universeCenterForReset.m[0][2], m_universeCenterForReset.m[2][2] ); - // we want to store m_collisionBoundsForOffset as spacially relative to - // m_universeCenterForReset, so: + // update seated center to standing offset by current hmd Y value. + m_seatedCenterForReset = m_universeCenterForReset; + vr::TrackedDevicePose_t devicePosesStanding[vr::k_unMaxTrackedDeviceCount]; + vr::VRSystem()->GetDeviceToAbsoluteTrackingPose( + vr::TrackingUniverseStanding, + 0.0f, + devicePosesStanding, + vr::k_unMaxTrackedDeviceCount ); + vr::HmdMatrix34_t hmdMatrix + = devicePosesStanding[0].mDeviceToAbsoluteTracking; + m_seatedHeight = hmdMatrix.m[1][3]; + m_seatedCenterForReset.m[1][3] += m_seatedHeight; - // for every quad in the chaperone bounds... - for ( unsigned quad = 0; quad < m_collisionBoundsCountForReset; quad++ ) + if ( m_collisionBoundsCountForReset > 0 ) { - // at every corner in that quad... - for ( unsigned corner = 0; corner < 4; corner++ ) - { - // copy from m_collisionBoundsForReset - m_collisionBoundsForOffset[quad].vCorners[corner].v[0] - = m_collisionBoundsForReset[quad].vCorners[corner].v[0]; - m_collisionBoundsForOffset[quad].vCorners[corner].v[1] - = m_collisionBoundsForReset[quad].vCorners[corner].v[1]; - m_collisionBoundsForOffset[quad].vCorners[corner].v[2] - = m_collisionBoundsForReset[quad].vCorners[corner].v[2]; + float universeCenterForResetYaw + = std::atan2( m_universeCenterForReset.m[0][2], + m_universeCenterForReset.m[2][2] ); - // unrotate by universe center's yaw - rotateFloatCoordinates( - m_collisionBoundsForOffset[quad].vCorners[corner].v, - -universeCenterForResetYaw ); + // we want to store m_collisionBoundsForOffset as spacially relative to + // m_universeCenterForReset, so: + + // for every quad in the chaperone bounds... + for ( unsigned quad = 0; quad < m_collisionBoundsCountForReset; quad++ ) + { + // at every corner in that quad... + for ( unsigned corner = 0; corner < 4; corner++ ) + { + // copy from m_collisionBoundsForReset + m_collisionBoundsForOffset[quad].vCorners[corner].v[0] + = m_collisionBoundsForReset[quad].vCorners[corner].v[0]; + m_collisionBoundsForOffset[quad].vCorners[corner].v[1] + = m_collisionBoundsForReset[quad].vCorners[corner].v[1]; + m_collisionBoundsForOffset[quad].vCorners[corner].v[2] + = m_collisionBoundsForReset[quad].vCorners[corner].v[2]; + + // unrotate by universe center's yaw + rotateFloatCoordinates( + m_collisionBoundsForOffset[quad].vCorners[corner].v, + -universeCenterForResetYaw ); + } } } + // update the working set preview for potential Oculus and WMR issues - vr::VRChaperoneSetup()->ShowWorkingSetPreview(); + // vr::VRChaperoneSetup()->ShowWorkingSetPreview(); } void MoveCenterTabController::applyChaperoneResetData() { vr::VRChaperoneSetup()->HideWorkingSetPreview(); vr::VRChaperoneSetup()->RevertWorkingCopy(); - vr::VRChaperoneSetup()->SetWorkingCollisionBoundsInfo( - m_collisionBoundsForReset, m_collisionBoundsCountForReset ); + if ( m_collisionBoundsCountForReset > 0 ) + { + vr::VRChaperoneSetup()->SetWorkingCollisionBoundsInfo( + m_collisionBoundsForReset, m_collisionBoundsCountForReset ); + } vr::VRChaperoneSetup()->SetWorkingStandingZeroPoseToRawTrackingPose( &m_universeCenterForReset ); + vr::VRChaperoneSetup()->SetWorkingSeatedZeroPoseToRawTrackingPose( + &m_seatedCenterForReset ); + vr::VRChaperoneSetup()->CommitWorkingCopy( vr::EChaperoneConfigFile_Live ); // update the working set preview otherwise Oculus and WMR users may not see // results of the reset - vr::VRChaperoneSetup()->ShowWorkingSetPreview(); + // vr::VRChaperoneSetup()->ShowWorkingSetPreview(); } // START of drag bindings: @@ -1492,10 +1752,14 @@ void MoveCenterTabController::saveUncommittedChaperone() { if ( !m_chaperoneCommitted ) { + // double commit... once to ensure before we HideWorkingSetPreview the + // working set is synced. Commit a second time as a workaround for WMR + // and Rift not getting the commit during active ShowWorkingSetPreview + vr::VRChaperoneSetup()->CommitWorkingCopy( + vr::EChaperoneConfigFile_Live ); + vr::VRChaperoneSetup()->HideWorkingSetPreview(); vr::VRChaperoneSetup()->CommitWorkingCopy( vr::EChaperoneConfigFile_Live ); - // test removal for oculus and WMR users - // vr::VRChaperoneSetup()->HideWorkingSetPreview(); m_chaperoneCommitted = true; } } @@ -1855,6 +2119,15 @@ void MoveCenterTabController::updateSpace() return; } + if ( m_allowExternalEdits && m_oldOffsetX == 0.0f && m_oldOffsetY == 0.0f + && m_oldOffsetZ == 0.0f && m_oldRotation == 0 ) + { + vr::VRChaperoneSetup()->ReloadFromDisk( vr::EChaperoneConfigFile_Live ); + vr::VRChaperoneSetup()->CommitWorkingCopy( + vr::EChaperoneConfigFile_Live ); + updateChaperoneResetData(); + } + vr::HmdMatrix34_t offsetUniverseCenter; // set offsetUniverseCenter to the current angle @@ -1892,6 +2165,17 @@ void MoveCenterTabController::updateSpace() offsetUniverseCenter.m[2][3] += m_universeCenterForReset.m[2][2] * m_offsetZ; + // keep the seated origin synced with offsets if in seated mode + if ( m_trackingUniverse == vr::TrackingUniverseSeated ) + { + vr::HmdMatrix34_t offsetSeatedCenter = offsetUniverseCenter; + + offsetSeatedCenter.m[1][3] += m_seatedHeight; + + vr::VRChaperoneSetup()->SetWorkingSeatedZeroPoseToRawTrackingPose( + &offsetSeatedCenter ); + } + if ( m_adjustChaperone ) { // make a copy of our bounds and @@ -1950,9 +2234,14 @@ void MoveCenterTabController::updateSpace() } vr::VRChaperoneSetup()->SetWorkingStandingZeroPoseToRawTrackingPose( &offsetUniverseCenter ); + vr::VRChaperoneSetup()->ShowWorkingSetPreview(); m_chaperoneCommitted = false; + // loadChaperoneData( false ), false so that we don't load live data, and + // reference the working set instead. + parent->chaperoneUtils().loadChaperoneData( false ); + m_oldOffsetX = m_offsetX; m_oldOffsetY = m_offsetY; m_oldOffsetZ = m_offsetZ; @@ -1964,28 +2253,58 @@ void MoveCenterTabController::eventLoopTick( vr::TrackedDevicePose_t* devicePoses ) { - if ( settingsUpdateCounter >= k_moveCenterSettingsUpdateCounter ) + // detect if room setup is running + if ( universe == vr::TrackingUniverseRawAndUncalibrated ) { - if ( parent->isDashboardVisible() ) + if ( !m_roomSetupModeDetected ) { - setTrackingUniverse( int( universe ) ); + m_roomSetupModeDetected = true; + + // give up on any pending zero offsets so they aren't applied in the + // middle of room setup. + m_pendingZeroOffsets = false; + + LOG( INFO ) << "room setup ENTRY detected"; + vr::VRChaperoneSetup()->HideWorkingSetPreview(); + reset(); + vr::VRChaperoneSetup()->RevertWorkingCopy(); } - settingsUpdateCounter = 0; + setTrackingUniverse( int( universe ) ); + return; } - else + + // detect entering seated mode + if ( universe == vr::TrackingUniverseSeated && !m_seatedModeDetected ) { - settingsUpdateCounter++; + m_seatedModeDetected = true; + LOG( INFO ) << "seated mode ENTRY detected"; + } + + // detect exiting seated mode + if ( universe == vr::TrackingUniverseStanding && m_seatedModeDetected ) + { + m_seatedModeDetected = false; + reset(); + LOG( INFO ) << "seated mode EXIT detected"; } // If we're trying to redifine the origin point, but can't becaues of bad // chaperone calibration, we keep trying and hold off on motion features // until we get ChaperoneCalibrationState_OK - if ( m_pendingZeroOffsets ) + + // if we were in room setup, but got this far in the loop, universe is no + // longer raw mode and we detect room setup exit and zeroOffsets() to apply + // new setup. + if ( m_pendingZeroOffsets || m_roomSetupModeDetected ) { zeroOffsets(); + // m_roomSetupModeDetected is set to false in zeroOffsets() if it's + // successful. } else { + setTrackingUniverse( int( universe ) ); + // get current space rotation in radians double angle = m_rotation * k_centidegreesToRadians; diff --git a/src/tabcontrollers/MoveCenterTabController.h b/src/tabcontrollers/MoveCenterTabController.h index ac1018a..b715331 100644 --- a/src/tabcontrollers/MoveCenterTabController.h +++ b/src/tabcontrollers/MoveCenterTabController.h @@ -68,6 +68,11 @@ class MoveCenterTabController : public QObject requireLockYChanged ) Q_PROPERTY( bool lockZToggle READ lockZToggle WRITE setLockZ NOTIFY requireLockZChanged ) + Q_PROPERTY( + bool showLogMatricesButton READ showLogMatricesButton WRITE + setShowLogMatricesButton NOTIFY showLogMatricesButtonChanged ) + Q_PROPERTY( bool allowExternalEdits READ allowExternalEdits WRITE + setAllowExternalEdits NOTIFY allowExternalEditsChanged ) private: OverlayController* parent; @@ -100,6 +105,7 @@ private: float m_gravityFloor = 0.0f; float m_gravityStrength = 9.8f; float m_flingStrength = 1.0f; + float m_seatedHeight = 1.0f; bool m_momentumSave = false; bool m_lockXToggle = false; bool m_lockYToggle = false; @@ -138,6 +144,10 @@ private: bool m_chaperoneCommitted = true; bool m_pendingZeroOffsets = true; bool m_dashWasOpenPreviousFrame = false; + bool m_roomSetupModeDetected = false; + bool m_seatedModeDetected = false; + bool m_showLogMatricesButton = false; + bool m_allowExternalEdits = false; unsigned settingsUpdateCounter = 0; int m_hmdRotationStatsUpdateCounter = 0; unsigned m_dragComfortFrameSkipCounter = 0; @@ -148,6 +158,7 @@ private: vr::HmdQuad_t* m_collisionBoundsForReset; uint32_t m_collisionBoundsCountForReset = 0; vr::HmdMatrix34_t m_universeCenterForReset; + vr::HmdMatrix34_t m_seatedCenterForReset; vr::HmdQuad_t* m_collisionBoundsForOffset; void updateHmdRotationCounter( vr::TrackedDevicePose_t hmdPose, @@ -160,6 +171,7 @@ private: void updateChaperoneResetData(); void applyChaperoneResetData(); void saveUncommittedChaperone(); + void outputLogHmdMatrix( vr::HmdMatrix34_t hmdMatrix ); public: void initStage1(); @@ -190,8 +202,11 @@ public: bool lockXToggle() const; bool lockYToggle() const; bool lockZToggle() const; + bool showLogMatricesButton() const; + bool allowExternalEdits() const; double getHmdYawTotal(); void resetHmdYawTotal(); + void incomingSeatedReset(); // actions: void leftHandSpaceDrag( bool leftHandDragActive ); @@ -247,8 +262,13 @@ public slots: void setLockX( bool value, bool notify = true ); void setLockY( bool value, bool notify = true ); void setLockZ( bool value, bool notify = true ); + void setShowLogMatricesButton( bool value, bool notify = true ); + void setAllowExternalEdits( bool value, bool notify = true ); + void shutdown(); void reset(); + void updateSeatedResetData(); + void outputLogPoses(); void zeroOffsets(); signals: @@ -275,6 +295,8 @@ signals: void requireLockXChanged( bool value ); void requireLockYChanged( bool value ); void requireLockZChanged( bool value ); + void showLogMatricesButtonChanged( bool value ); + void allowExternalEditsChanged( bool value ); }; } // namespace advsettings diff --git a/src/utils/ChaperoneUtils.cpp b/src/utils/ChaperoneUtils.cpp index 3945694..63d25a6 100644 --- a/src/utils/ChaperoneUtils.cpp +++ b/src/utils/ChaperoneUtils.cpp @@ -74,10 +74,21 @@ float ChaperoneUtils::_getDistanceToChaperone( return distance; } -void ChaperoneUtils::loadChaperoneData() +void ChaperoneUtils::loadChaperoneData( bool fromLiveBounds ) { std::lock_guard lock( _mutex ); - vr::VRChaperoneSetup()->GetLiveCollisionBoundsInfo( nullptr, &_quadsCount ); + + if ( fromLiveBounds ) + { + vr::VRChaperoneSetup()->GetLiveCollisionBoundsInfo( nullptr, + &_quadsCount ); + } + else + { + vr::VRChaperoneSetup()->GetWorkingCollisionBoundsInfo( nullptr, + &_quadsCount ); + } + if ( _quadsCount > 0 ) { std::unique_ptr quadsBuffer( @@ -86,8 +97,17 @@ void ChaperoneUtils::loadChaperoneData() _corners.reset( reinterpret_cast( new vr::HmdQuad_t[_quadsCount] ) ); vr::HmdVector3_t* _cornersPtr = _corners.get(); - vr::VRChaperoneSetup()->GetLiveCollisionBoundsInfo( quadsBufferPtr, - &_quadsCount ); + if ( fromLiveBounds ) + { + vr::VRChaperoneSetup()->GetLiveCollisionBoundsInfo( quadsBufferPtr, + &_quadsCount ); + } + else + { + vr::VRChaperoneSetup()->GetWorkingCollisionBoundsInfo( + quadsBufferPtr, &_quadsCount ); + } + for ( uint32_t i = 0; i < _quadsCount; i++ ) { _cornersPtr[i] = quadsBufferPtr[i].vCorners[0]; diff --git a/src/utils/ChaperoneUtils.h b/src/utils/ChaperoneUtils.h index 9a1176e..636c344 100644 --- a/src/utils/ChaperoneUtils.h +++ b/src/utils/ChaperoneUtils.h @@ -32,7 +32,7 @@ public: return _mutex; } - void loadChaperoneData(); + void loadChaperoneData( bool fromLiveBounds = true ); float getDistanceToChaperone( const vr::HmdVector3_t& point, vr::HmdVector3_t* projectedPoint = nullptr,