diff --git a/src/openvr/ivrinput.cpp b/src/openvr/ivrinput.cpp index 7a42b325..e4d5c4e2 100644 --- a/src/openvr/ivrinput.cpp +++ b/src/openvr/ivrinput.cpp @@ -132,6 +132,8 @@ SteamIVRInput::SteamIVRInput() m_smoothTurnLeft( action_keys::smoothTurnLeft ), m_smoothTurnRight( action_keys::smoothTurnRight ), m_autoTurnToggle( action_keys::autoTurnToggle ), + m_addAutoAlignPointLeft( action_keys::addAutoAlignPointLeft ), + m_addAutoAlignPointRight( action_keys::addAutoAlignPointRight ), m_xAxisLockToggle( action_keys::xAxisLockToggle ), m_yAxisLockToggle( action_keys::yAxisLockToggle ), m_zAxisLockToggle( action_keys::zAxisLockToggle ), @@ -300,6 +302,15 @@ bool SteamIVRInput::autoTurnToggle() { return isDigitalActionActivatedOnce( m_autoTurnToggle ); } +bool SteamIVRInput::addAutoAlignPointLeft() +{ + return isDigitalActionActivatedOnce( m_addAutoAlignPointLeft ); +} + +bool SteamIVRInput::addAutoAlignPointRight() +{ + return isDigitalActionActivatedOnce( m_addAutoAlignPointRight ); +} bool SteamIVRInput::xAxisLockToggle() { diff --git a/src/openvr/ivrinput.h b/src/openvr/ivrinput.h index 91289a84..84248a00 100644 --- a/src/openvr/ivrinput.h +++ b/src/openvr/ivrinput.h @@ -47,6 +47,10 @@ namespace action_keys constexpr auto smoothTurnLeft = "/actions/motion/in/SmoothTurnLeft"; constexpr auto smoothTurnRight = "/actions/motion/in/SmoothTurnRight"; constexpr auto autoTurnToggle = "/actions/motion/in/AutoTurnToggle"; + constexpr auto addAutoAlignPointLeft + = "/actions/motion/in/AddAutoAlignPointLeft"; + constexpr auto addAutoAlignPointRight + = "/actions/motion/in/AddAutoAlignPointRight"; constexpr auto xAxisLockToggle = "/actions/misc/in/XAxisLockToggle"; constexpr auto yAxisLockToggle = "/actions/misc/in/YAxisLockToggle"; @@ -151,6 +155,8 @@ class SteamIVRInput bool smoothTurnLeft(); bool smoothTurnRight(); bool autoTurnToggle(); + bool addAutoAlignPointLeft(); + bool addAutoAlignPointRight(); bool xAxisLockToggle(); bool yAxisLockToggle(); bool zAxisLockToggle(); @@ -233,6 +239,8 @@ class SteamIVRInput DigitalAction m_smoothTurnLeft; DigitalAction m_smoothTurnRight; DigitalAction m_autoTurnToggle; + DigitalAction m_addAutoAlignPointLeft; + DigitalAction m_addAutoAlignPointRight; DigitalAction m_xAxisLockToggle; DigitalAction m_yAxisLockToggle; DigitalAction m_zAxisLockToggle; diff --git a/src/overlaycontroller.cpp b/src/overlaycontroller.cpp index bec9952b..a8f921e0 100644 --- a/src/overlaycontroller.cpp +++ b/src/overlaycontroller.cpp @@ -755,6 +755,14 @@ void OverlayController::processRotationBindings() m_rotationTabController.setAutoTurnEnabled( !( m_rotationTabController.autoTurnEnabled() ) ); } + if ( m_actions.addAutoAlignPointLeft() ) + { + m_rotationTabController.addAutoAlignPoint( false ); + } + if ( m_actions.addAutoAlignPointRight() ) + { + m_rotationTabController.addAutoAlignPoint( true ); + } } /*! Checks if an action has been activated and dispatches the related action if diff --git a/src/package_files/action_manifest.json b/src/package_files/action_manifest.json index 43ffb181..f43ef04a 100644 --- a/src/package_files/action_manifest.json +++ b/src/package_files/action_manifest.json @@ -163,7 +163,16 @@ "requirement": "optional", "type": "boolean" }, - + { + "name": "/actions/motion/in/AddAutoAlignPointLeft", + "requirement": "optional", + "type": "boolean" + }, + { + "name": "/actions/motion/in/AddAutoAlignPointRight", + "requirement": "optional", + "type": "boolean" + }, { "name": "/actions/misc/in/XAxisLockToggle", "requirement": "optional", @@ -288,6 +297,8 @@ "/actions/motion/in/SmoothTurnLeft" : "Smooth-Turn Left", "/actions/motion/in/SmoothTurnRight" : "Smooth-Turn Right", "/actions/motion/in/AutoTurnToggle" : "Auto-Turn Toggle", + "/actions/motion/in/AddAutoAlignPointLeft" : "Add Auto Align Point (Left Hand)", + "/actions/motion/in/AddAutoAlignPointRight" : "Add Auto Align Point (Right Hand)", "/actions/misc/in/XAxisLockToggle" : "X-Axis Lock Toggle", "/actions/misc/in/YAxisLockToggle" : "Y-Axis Lock Toggle", @@ -303,4 +314,4 @@ "/actions/system/in/KeyPressSystem": "Key Press System" } ] -} \ No newline at end of file +} diff --git a/src/res/img/rotation/autoalign.svg b/src/res/img/rotation/autoalign.svg new file mode 100644 index 00000000..8b933753 --- /dev/null +++ b/src/res/img/rotation/autoalign.svg @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + image/svg+xml + + + + + + + A + + + + + + + diff --git a/src/res/img/rotation/autoalign1.png b/src/res/img/rotation/autoalign1.png new file mode 100644 index 00000000..98a50304 Binary files /dev/null and b/src/res/img/rotation/autoalign1.png differ diff --git a/src/res/img/rotation/autoalign2.png b/src/res/img/rotation/autoalign2.png new file mode 100644 index 00000000..1e7d35dc Binary files /dev/null and b/src/res/img/rotation/autoalign2.png differ diff --git a/src/res/img/rotation/autoalign3.png b/src/res/img/rotation/autoalign3.png new file mode 100644 index 00000000..57367aca Binary files /dev/null and b/src/res/img/rotation/autoalign3.png differ diff --git a/src/res/img/rotation/autoalign4.png b/src/res/img/rotation/autoalign4.png new file mode 100644 index 00000000..ec7c5b84 Binary files /dev/null and b/src/res/img/rotation/autoalign4.png differ diff --git a/src/tabcontrollers/MoveCenterTabController.cpp b/src/tabcontrollers/MoveCenterTabController.cpp index 1b52497b..073e5422 100644 --- a/src/tabcontrollers/MoveCenterTabController.cpp +++ b/src/tabcontrollers/MoveCenterTabController.cpp @@ -330,8 +330,6 @@ void MoveCenterTabController::setRotation( int value, bool notify ) return; } - double angle = ( value - m_rotation ) * k_centidegreesToRadians; - // Get hmd pose matrix. vr::TrackedDevicePose_t devicePosesForRot[vr::k_unMaxTrackedDeviceCount]; @@ -356,26 +354,39 @@ void MoveCenterTabController::setRotation( int value, bool notify ) vr::HmdMatrix34_t oldHmdPos = devicePosesForRot[0].mDeviceToAbsoluteTracking; + vr::HmdVector3_t oldHmdPos3 + = { oldHmdPos.m[0][3], oldHmdPos.m[1][3], oldHmdPos.m[2][3] }; + setRotationAroundPivot( value, notify, oldHmdPos3 ); + } +} +void MoveCenterTabController::setRotationAroundPivot( + int value, + bool notify, + const vr::HmdVector3_t& pivot ) +{ + if ( m_rotation != value ) + { + double angle = ( value - m_rotation ) * k_centidegreesToRadians; // Set up xyz coordinate values from pose matrix. - double oldHmdXyz[3] = { static_cast( oldHmdPos.m[0][3] ), - static_cast( oldHmdPos.m[1][3] ), - static_cast( oldHmdPos.m[2][3] ) }; - double newHmdXyz[3] = { static_cast( oldHmdPos.m[0][3] ), - static_cast( oldHmdPos.m[1][3] ), - static_cast( oldHmdPos.m[2][3] ) }; - - // Convert oldHmdXyz into un-rotated coordinates. + double oldXyz[3] = { static_cast( pivot.v[0] ), + static_cast( pivot.v[1] ), + static_cast( pivot.v[2] ) }; + double newXyz[3] = { static_cast( pivot.v[0] ), + static_cast( pivot.v[1] ), + static_cast( pivot.v[2] ) }; + + // Convert oldXyz into un-rotated coordinates. double oldAngle = -m_rotation * k_centidegreesToRadians; - rotateCoordinates( oldHmdXyz, oldAngle ); + rotateCoordinates( oldXyz, oldAngle ); - // Set newHmdXyz to have additional rotation from incoming angle change. - rotateCoordinates( newHmdXyz, oldAngle - angle ); + // Set newXyz to have additional rotation from incoming angle change. + rotateCoordinates( newXyz, oldAngle - angle ); // find difference in x,z offset due to incoming angle change // (coordinates are in un-rotated axis). double hmdRotDiff[3] - = { oldHmdXyz[0] - newHmdXyz[0], 0, oldHmdXyz[2] - newHmdXyz[2] }; + = { oldXyz[0] - newXyz[0], 0, oldXyz[2] - newXyz[2] }; m_rotation = value; if ( notify ) @@ -999,12 +1010,10 @@ void MoveCenterTabController::reset() m_offsetY = 0.0f; m_offsetZ = 0.0f; m_rotation = 0; - m_lastControllerPosition[0] = 0.0f; - m_lastControllerPosition[1] = 0.0f; - m_lastControllerPosition[2] = 0.0f; m_lastMoveHand = vr::TrackedControllerRole_Invalid; m_lastRotateHand = vr::TrackedControllerRole_Invalid; applyChaperoneResetData(); + m_lastControllerPosition = { 0.0f, 0.0f, 0.0f }; // For Center Marker // Needs to happen after apply chaperone @@ -2211,9 +2220,91 @@ void MoveCenterTabController::updateHmdRotationCounter( m_lastHmdQuaternion = m_hmdQuaternion; } +vr::HmdVector3_t MoveCenterTabController::relativeToAbsolute( + const vr::HmdVector3_t& relative ) const +{ + double relativeControllerPosition[] + = { static_cast( relative.v[0] ), + static_cast( relative.v[1] ), + static_cast( relative.v[2] ) }; + rotateCoordinates( relativeControllerPosition, + -m_rotation * k_centidegreesToRadians ); + vr::HmdVector3_t absoluteControllerPosition = { + static_cast( relativeControllerPosition[0] ) + m_offsetX, + static_cast( relativeControllerPosition[1] ) + m_offsetY, + static_cast( relativeControllerPosition[2] ) + m_offsetZ, + }; + return absoluteControllerPosition; +} + +vr::HmdVector3_t MoveCenterTabController::absoluteToRelative( + const vr::HmdVector3_t& absolute ) const +{ + double absoluteControllerPosition[] + = { static_cast( absolute.v[0] - m_offsetX ), + static_cast( absolute.v[1] - m_offsetY ), + static_cast( absolute.v[2] - m_offsetZ ) }; + rotateCoordinates( absoluteControllerPosition, + m_rotation * k_centidegreesToRadians ); + vr::HmdVector3_t relativeControllerPosition + = { static_cast( absoluteControllerPosition[0] ), + static_cast( absoluteControllerPosition[1] ), + static_cast( absoluteControllerPosition[2] ) }; + return relativeControllerPosition; +} + +// Displace the entire universe by some difference. Both 'from' and 'to' are in +// absolute coordinates. +void MoveCenterTabController::displaceUniverse( const vr::HmdVector3_t& from, + const vr::HmdVector3_t& to ) +{ + double diff[3] = { + static_cast( to.v[0] - from.v[0] ), + static_cast( to.v[1] - from.v[1] ), + static_cast( to.v[2] - from.v[2] ), + }; + + // offset is un-rotated coordinates + + // prevent positional glitches from exceeding max openvr offset clamps. + // We do this by detecting a drag larger than 100m in a single frame. + if ( abs( diff[0] ) > 100.0 || abs( diff[1] ) > 100.0 + || abs( diff[2] ) > 100.0 ) + { + reset(); + } + + // prevents updating if axis movement is locked + if ( !lockXToggle() ) + { + m_offsetX += static_cast( diff[0] ); + } + if ( !lockYToggle() ) + { + m_offsetY += static_cast( diff[1] ); + } + if ( !lockZToggle() ) + { + m_offsetZ += static_cast( diff[2] ); + } + + double secondsSinceLastDragUpdate + = std::chrono::duration( std::chrono::steady_clock::now() + - m_lastDragUpdateTimePoint ) + .count(); + + // TODO: Add 'effects fling' boolean? or simply return diff[] as a + // HmdVect3_t + m_velocity[0] = ( diff[0] / secondsSinceLastDragUpdate ) + * static_cast( flingStrength() ); + m_velocity[1] = ( diff[1] / secondsSinceLastDragUpdate ) + * static_cast( flingStrength() ); + m_velocity[2] = ( diff[2] / secondsSinceLastDragUpdate ) + * static_cast( flingStrength() ); +} + void MoveCenterTabController::updateHandDrag( - vr::TrackedDevicePose_t* devicePoses, - double angle ) + vr::TrackedDevicePose_t* devicePoses ) { auto moveHandId = vr::VRSystem()->GetTrackedDeviceIndexForControllerRole( m_activeDragHand ); @@ -2261,69 +2352,20 @@ void MoveCenterTabController::updateHandDrag( return; } - double relativeControllerPosition[] = { - static_cast( movePose->mDeviceToAbsoluteTracking.m[0][3] ), - static_cast( movePose->mDeviceToAbsoluteTracking.m[1][3] ), - static_cast( movePose->mDeviceToAbsoluteTracking.m[2][3] ) - }; - - rotateCoordinates( relativeControllerPosition, -angle ); - float absoluteControllerPosition[] = { - static_cast( relativeControllerPosition[0] ) + m_offsetX, - static_cast( relativeControllerPosition[1] ) + m_offsetY, - static_cast( relativeControllerPosition[2] ) + m_offsetZ, - }; + vr::HmdVector3_t relativeControllerPosition + = { movePose->mDeviceToAbsoluteTracking.m[0][3], + movePose->mDeviceToAbsoluteTracking.m[1][3], + movePose->mDeviceToAbsoluteTracking.m[2][3] }; + auto absoluteControllerPosition + = relativeToAbsolute( relativeControllerPosition ); if ( m_lastMoveHand == m_activeDragHand ) { - double diff[3] = { - static_cast( absoluteControllerPosition[0] - - m_lastControllerPosition[0] ), - static_cast( absoluteControllerPosition[1] - - m_lastControllerPosition[1] ), - static_cast( absoluteControllerPosition[2] - - m_lastControllerPosition[2] ), - }; - - // offset is un-rotated coordinates - - // prevent positional glitches from exceeding max openvr offset clamps. - // We do this by detecting a drag larger than 100m in a single frame. - if ( abs( diff[0] ) > 100.0 || abs( diff[1] ) > 100.0 - || abs( diff[2] ) > 100.0 ) - { - reset(); - } - - // prevents updating if axis movement is locked - if ( !lockXToggle() ) - { - m_offsetX += static_cast( diff[0] ); - } - if ( !lockYToggle() ) - { - m_offsetY += static_cast( diff[1] ); - } - if ( !lockZToggle() ) - { - m_offsetZ += static_cast( diff[2] ); - } - - double secondsSinceLastDragUpdate - = std::chrono::duration( std::chrono::steady_clock::now() - - m_lastDragUpdateTimePoint ) - .count(); - - m_velocity[0] = ( diff[0] / secondsSinceLastDragUpdate ) - * static_cast( flingStrength() ); - m_velocity[1] = ( diff[1] / secondsSinceLastDragUpdate ) - * static_cast( flingStrength() ); - m_velocity[2] = ( diff[2] / secondsSinceLastDragUpdate ) - * static_cast( flingStrength() ); + // Displace from last controller position to current + displaceUniverse( m_lastControllerPosition, + absoluteControllerPosition ); } - m_lastControllerPosition[0] = absoluteControllerPosition[0]; - m_lastControllerPosition[1] = absoluteControllerPosition[1]; - m_lastControllerPosition[2] = absoluteControllerPosition[2]; + m_lastControllerPosition = absoluteControllerPosition; m_lastMoveHand = m_activeDragHand; } @@ -3041,7 +3083,7 @@ void MoveCenterTabController::eventLoopTick( if ( m_dragComfortFrameSkipCounter >= static_cast( ( dragComfortFactor() * dragComfortFactor() ) ) ) { - updateHandDrag( devicePoses, angle ); + updateHandDrag( devicePoses ); m_lastDragUpdateTimePoint = std::chrono::steady_clock::now(); m_dragComfortFrameSkipCounter = 0; } diff --git a/src/tabcontrollers/MoveCenterTabController.h b/src/tabcontrollers/MoveCenterTabController.h index 6759c552..104591ba 100644 --- a/src/tabcontrollers/MoveCenterTabController.h +++ b/src/tabcontrollers/MoveCenterTabController.h @@ -158,7 +158,7 @@ class MoveCenterTabController : public QObject bool m_moveShortcutRightPressed = false; bool m_moveShortcutLeftPressed = false; vr::TrackedDeviceIndex_t m_activeMoveController; - float m_lastControllerPosition[3]; + vr::HmdVector3_t m_lastControllerPosition; bool m_heightToggle = false; float m_gravityFloor = 0.0f; // Set lastHandQuaternion.w to -1000.0 when last hand is invalid. @@ -227,7 +227,7 @@ class MoveCenterTabController : public QObject void updateHmdRotationCounter( vr::TrackedDevicePose_t hmdPose, double angle ); - void updateHandDrag( vr::TrackedDevicePose_t* devicePoses, double angle ); + void updateHandDrag( vr::TrackedDevicePose_t* devicePoses ); void updateHandTurn( vr::TrackedDevicePose_t* devicePoses, double angle ); void updateGravity(); void updateSpace( bool forceUpdate = false ); @@ -283,6 +283,16 @@ class MoveCenterTabController : public QObject void incomingSeatedReset(); void setBoundsBasisHeight( float newHeight ); float getBoundsBasisMaxY(); + void setRotationAroundPivot( int value, + bool notify, + const vr::HmdVector3_t& pivot ); + void displaceUniverse( const vr::HmdVector3_t& from, + const vr::HmdVector3_t& to ); + + vr::HmdVector3_t + relativeToAbsolute( const vr::HmdVector3_t& coordinates_in ) const; + vr::HmdVector3_t + absoluteToRelative( const vr::HmdVector3_t& absolute ) const; void updateChaperoneResetData(); diff --git a/src/tabcontrollers/RotationTabController.cpp b/src/tabcontrollers/RotationTabController.cpp index 07301f9f..d0b4c195 100644 --- a/src/tabcontrollers/RotationTabController.cpp +++ b/src/tabcontrollers/RotationTabController.cpp @@ -38,11 +38,27 @@ void RotationTabController::initStage2( OverlayController* var_parent ) constexpr auto autoturnIconFilepath = "/res/img/rotation/autoturn.png"; constexpr auto noautoturnIconFilepath = "/res/img/rotation/noautoturn.png"; + constexpr auto alignPointOneIconFilepath + = "/res/img/rotation/autoalign1.png"; + constexpr auto alignPointTwoIconFilepath + = "/res/img/rotation/autoalign2.png"; + constexpr auto alignPointThreeIconFilepath + = "/res/img/rotation/autoalign3.png"; + constexpr auto alignPointFourIconFilepath + = "/res/img/rotation/autoalign4.png"; const auto autoturnIconFilePath = paths::verifyIconFilePath( autoturnIconFilepath ); const auto noautoturnIconFilePath = paths::verifyIconFilePath( noautoturnIconFilepath ); + const auto alignPointOneIconFilePath + = paths::verifyIconFilePath( alignPointOneIconFilepath ); + const auto alignPointTwoIconFilePath + = paths::verifyIconFilePath( alignPointTwoIconFilepath ); + const auto alignPointThreeIconFilePath + = paths::verifyIconFilePath( alignPointThreeIconFilepath ); + const auto alignPointFourIconFilePath + = paths::verifyIconFilePath( alignPointFourIconFilepath ); if ( !autoturnIconFilePath.has_value() || !noautoturnIconFilePath.has_value() ) @@ -53,6 +69,10 @@ void RotationTabController::initStage2( OverlayController* var_parent ) m_autoturnValues.autoturnPath = *autoturnIconFilePath; m_autoturnValues.noautoturnPath = *noautoturnIconFilePath; + m_autoturnValues.alignPointOnePath = *alignPointOneIconFilePath; + m_autoturnValues.alignPointTwoPath = *alignPointTwoIconFilePath; + m_autoturnValues.alignPointThreePath = *alignPointThreeIconFilePath; + m_autoturnValues.alignPointFourPath = *alignPointFourIconFilePath; auto pushToPath = m_autoturnValues.autoturnPath.c_str(); @@ -79,6 +99,27 @@ void RotationTabController::eventLoopTick( { if ( devicePoses ) { + auto leftHandId + = vr::VRSystem()->GetTrackedDeviceIndexForControllerRole( + vr::TrackedControllerRole_LeftHand ); + if ( vr::k_unTrackedDeviceIndexInvalid + && devicePoses[leftHandId].bPoseIsValid + && devicePoses[leftHandId].eTrackingResult + == vr::TrackingResult_Running_OK ) + { + lastLeftHandPose = devicePoses[leftHandId]; + } + auto rightHandId + = vr::VRSystem()->GetTrackedDeviceIndexForControllerRole( + vr::TrackedControllerRole_RightHand ); + if ( vr::k_unTrackedDeviceIndexInvalid + && devicePoses[rightHandId].bPoseIsValid + && devicePoses[rightHandId].eTrackingResult + == vr::TrackingResult_Running_OK ) + { + lastRightHandPose = devicePoses[rightHandId]; + } + m_isHMDActive = false; std::lock_guard lock( parent->chaperoneUtils().mutex() ); @@ -578,6 +619,104 @@ void RotationTabController::doAutoTurn( } } +void RotationTabController::addAutoAlignPoint( bool rightHanded ) +{ + // TODO: State machine: if we have >2 align points, freeze vestibular + // motion/ratchetting/etc remain frozen until after we move away from the + // aligned area + const auto& lastHandPose + = rightHanded ? lastRightHandPose : lastLeftHandPose; + + LOG( DEBUG ) << "point added: " << autoAlignPoints.size(); + // get the location of hand, push_back onto autoAlignPoints + vr::HmdVector3_t new_point + = { lastHandPose.mDeviceToAbsoluteTracking.m[0][3], + lastHandPose.mDeviceToAbsoluteTracking.m[1][3], + lastHandPose.mDeviceToAbsoluteTracking.m[2][3] }; + // TODO: Probably smarter to actually just keep the virtual points as + // virtual until we use them. Then if they drift we don't care. + vr::HmdVector3_t absolute_point + = parent->m_moveCenterTabController.relativeToAbsolute( new_point ); + autoAlignPoints.push_back( absolute_point ); + + switch ( autoAlignPoints.size() ) + { + case 1: + vr::VROverlay()->SetOverlayFromFile( + m_autoturnValues.overlayHandle, + m_autoturnValues.alignPointOnePath.c_str() ); + break; + case 2: + vr::VROverlay()->SetOverlayFromFile( + m_autoturnValues.overlayHandle, + m_autoturnValues.alignPointTwoPath.c_str() ); + break; + case 3: + vr::VROverlay()->SetOverlayFromFile( + m_autoturnValues.overlayHandle, + m_autoturnValues.alignPointThreePath.c_str() ); + break; + case 4: + vr::VROverlay()->SetOverlayFromFile( + m_autoturnValues.overlayHandle, + m_autoturnValues.alignPointFourPath.c_str() ); + break; + } + + // TODO: configure whether auto-align has HUD popup independently + if ( autoTurnShowNotification() + && getNotificationOverlayHandle() != vr::k_ulOverlayHandleInvalid ) + { + vr::VROverlay()->SetOverlayAlpha( getNotificationOverlayHandle(), + 1.0f ); + vr::VROverlay()->ShowOverlay( getNotificationOverlayHandle() ); + m_autoTurnNotificationTimestamp.emplace( + std::chrono::steady_clock::now() ); + } + + // if we have exactly 4 points, go into main loop + if ( autoAlignPoints.size() == 4 ) + { + vr::HmdVector3_t realFirstPoint = autoAlignPoints[0]; + vr::HmdVector3_t realSecondPoint = autoAlignPoints[1]; + vr::HmdVector3_t virtualFirstPoint = autoAlignPoints[2]; + vr::HmdVector3_t virtualSecondPoint = autoAlignPoints[3]; + + // Rotate the universe to align, pivoting around the real point + double realEdgeAngle = static_cast( + std::atan2( realFirstPoint.v[0] - realSecondPoint.v[0], + realFirstPoint.v[2] - realSecondPoint.v[2] ) ); + double virtualEdgeAngle = static_cast( + std::atan2( virtualFirstPoint.v[0] - virtualSecondPoint.v[0], + virtualFirstPoint.v[2] - virtualSecondPoint.v[2] ) ); + double delta_degrees + = ( realEdgeAngle - virtualEdgeAngle ) * k_radiansToCentidegrees; + int newRotationAngleDeg = static_cast( + parent->m_moveCenterTabController.rotation() + delta_degrees ); + + // these need to be in the new, offset position. TODO: needs to be + // converted into new relative position? + vr::HmdVector3_t autoAlignPivot = realFirstPoint; + autoAlignPivot.v[0] -= realFirstPoint.v[0] - virtualFirstPoint.v[0]; + autoAlignPivot.v[1] -= realFirstPoint.v[1] - virtualFirstPoint.v[1]; + autoAlignPivot.v[2] -= realFirstPoint.v[2] - virtualFirstPoint.v[2]; + + // TODO: if centered, use the center of both points as the pivot + parent->m_moveCenterTabController.setRotationAroundPivot( + newRotationAngleDeg, + true, + parent->m_moveCenterTabController.absoluteToRelative( + virtualFirstPoint ) ); + + // Align the first of VR points (points[2]) with the first of the real + // points (points[0]) purely in position + parent->m_moveCenterTabController.displaceUniverse( virtualFirstPoint, + realFirstPoint ); + + // end of main loop, clear autoAlignPoints + autoAlignPoints.clear(); + } +} // getters bool RotationTabController::autoTurnEnabled() const diff --git a/src/tabcontrollers/RotationTabController.h b/src/tabcontrollers/RotationTabController.h index de8253a5..3113e06b 100644 --- a/src/tabcontrollers/RotationTabController.h +++ b/src/tabcontrollers/RotationTabController.h @@ -101,6 +101,10 @@ class RotationTabController : public QObject vr::VROverlayHandle_t overlayHandle = vr::k_ulOverlayHandleInvalid; std::string autoturnPath; std::string noautoturnPath; + std::string alignPointOnePath; + std::string alignPointTwoPath; + std::string alignPointThreePath; + std::string alignPointFourPath; } m_autoturnValues; virtual vr::VROverlayHandle_t getNotificationOverlayHandle() @@ -121,6 +125,9 @@ class RotationTabController : public QObject std::optional m_autoTurnNotificationTimestamp; + std::vector autoAlignPoints; + vr::TrackedDevicePose_t lastLeftHandPose, lastRightHandPose; + bool m_isHMDActive = false; void doAutoTurn( @@ -171,6 +178,9 @@ public slots: void setViewRatchettingEnabled( bool value, bool notify = true ); void setViewRatchettingPercent( double value, bool notify = true ); + // Experimental - auto-align + void addAutoAlignPoint( bool rightHanded ); + signals: void defaultProfileDisplay();