Introduce 'View ratchetting', cleanup/improve vestibular motion (#510)

* vestibular motion cleanup

* Fix environment jumping when autoturn is enabled

* Restrict vestibular motion to forward movement

* Revert "vestibular motion cleanup"

This reverts commit 3d6b293ad2d6a0df41756c67f7e80c4b2be8b6fd.

* Experimental: dynamic redirection. very subtle effect

* formatting...

* swap centidegrees for millidegrees

* Experimental: introduce view ratchetting

* more cleanup

* Revert "Experimental: dynamic redirection. very subtle effect"

This reverts commit d6c8e5cdedf1b11013f25340c2e9be64ec1359b8.

* vestibular motion cleanup

* view ratchetting settings

* cleanup and formatting

* Resolve drift, improve accuracy of vestibular motion/autoturn

* updated UI first pass

* UI first pass

* Hide Unset Errors After encountering one

* fix synch issue add ratchet box

* moved view ratchet ui to own file

* minor format changes to fit

* fixed REALLY 3% minimum

* fixed vestib motion default

Co-authored-by: ykeara <ykeara1@gmail.com>
This commit is contained in:
Chelsea Jaggi
2020-09-08 14:19:50 -07:00
committed by GitHub
co-authored by ykeara
parent 4fb026958e
commit 12344a86bc
13 changed files with 305 additions and 59 deletions
+1
View File
@@ -60,6 +60,7 @@ DISTFILES += \
src/res/qml/rotation_page/redirected/* \ src/res/qml/rotation_page/redirected/* \
src/res/qml/rotation_page/snap_turn/* \ src/res/qml/rotation_page/snap_turn/* \
src/res/qml/rotation_page/space_turn/* \ src/res/qml/rotation_page/space_turn/* \
src/res/qml/rotation_page/view_ratchet/* \
src/res/qml/common/* src/res/qml/common/*
win32:RC_ICONS += src/res/img/icons/advicon256px.ico win32:RC_ICONS += src/res/img/icons/advicon256px.ico
+16
View File
@@ -2,15 +2,31 @@
namespace ovr_settings_wrapper namespace ovr_settings_wrapper
{ {
// cludgey solution, long term solution we should apply defaults that make sense
// (most likely false)
bool unsetSettingErrorEnabled = true;
SettingsError handleErrors( std::string settingsKey, SettingsError handleErrors( std::string settingsKey,
vr::EVRSettingsError error, vr::EVRSettingsError error,
std::string customErrorMsg ) std::string customErrorMsg )
{ {
if ( error != vr::VRSettingsError_None ) if ( error != vr::VRSettingsError_None )
{ {
if ( !unsetSettingErrorEnabled
&& error
== vr::EVRSettingsError::
VRSettingsError_UnsetSettingHasNoDefault )
{
return SettingsError::UndefinedError;
}
LOG( ERROR ) << "Could not access \"" << settingsKey << "\" setting: " LOG( ERROR ) << "Could not access \"" << settingsKey << "\" setting: "
<< vr::VRSettings()->GetSettingsErrorNameFromEnum( error ) << vr::VRSettings()->GetSettingsErrorNameFromEnum( error )
<< " " << customErrorMsg; << " " << customErrorMsg;
if ( error
== vr::EVRSettingsError::VRSettingsError_UnsetSettingHasNoDefault )
{
unsetSettingErrorEnabled = false;
}
return SettingsError::UndefinedError; return SettingsError::UndefinedError;
} }
+2
View File
@@ -64,5 +64,7 @@ SettingsError handleErrors( std::string settingsKey,
vr::EVRSettingsError, vr::EVRSettingsError,
std::string customErrorMsg ); std::string customErrorMsg );
extern bool unsetSettingErrorEnabled;
void resetAllSettings(); void resetAllSettings();
} // namespace ovr_settings_wrapper } // namespace ovr_settings_wrapper
+5 -2
View File
@@ -6,13 +6,14 @@ import "../common"
import "redirected" import "redirected"
import "space_turn" import "space_turn"
import "snap_turn" import "snap_turn"
import "view_ratchet"
MyStackViewPage { MyStackViewPage {
width: 1200 width: 1200
headerText: "Rotation Settings" headerText: "Rotation Settings"
content: ColumnLayout { content: ColumnLayout {
spacing: 10 spacing: 8
AutoTurnGroupBox{ AutoTurnGroupBox{
id: autoTurnGroupBox id: autoTurnGroupBox
} }
@@ -20,7 +21,9 @@ MyStackViewPage {
RedirectedGroupBox{ RedirectedGroupBox{
id: redirectedGroupBox id: redirectedGroupBox
} }
ViewRatchetGroupBox{
id: vgiiewRatchetGroupBox
}
SpaceTurnGroupBox{ SpaceTurnGroupBox{
id:spaceTurnGroupBox id:spaceTurnGroupBox
} }
@@ -11,7 +11,7 @@ GroupBox {
label: MyText { label: MyText {
leftPadding: 10 leftPadding: 10
text: "Auto-Turn (for discrete redirected walking)" text: "Auto-Turn (for discrete redirected walking)"
bottomPadding: -10 bottomPadding: -12
} }
background: Rectangle { background: Rectangle {
color: "transparent" color: "transparent"
@@ -26,7 +26,7 @@ GroupBox {
color: "#ffffff" color: "#ffffff"
height: 1 height: 1
Layout.fillWidth: true Layout.fillWidth: true
Layout.bottomMargin: 5 Layout.bottomMargin: 3
} }
RowLayout { RowLayout {
@@ -11,7 +11,7 @@ GroupBox {
label: MyText { label: MyText {
leftPadding: 10 leftPadding: 10
text: "Vestibular Motion (for continuous redirected walking)" text: "Vestibular Motion (for continuous redirected walking)"
bottomPadding: -10 bottomPadding: -12
} }
background: Rectangle { background: Rectangle {
color: "transparent" color: "transparent"
@@ -26,13 +26,13 @@ GroupBox {
color: "#ffffff" color: "#ffffff"
height: 1 height: 1
Layout.fillWidth: true Layout.fillWidth: true
Layout.bottomMargin: 5 Layout.bottomMargin: 3
} }
RowLayout{ RowLayout{
MyToggleButton { MyToggleButton {
id: redirectedModeToggle id: redirectedModeToggle
text: "On" text: "Toggle On/Off"
Layout.preferredWidth: 225 Layout.preferredWidth: 225
onCheckedChanged: { onCheckedChanged: {
RotationTabController.setVestibularMotionEnabled(this.checked, true); RotationTabController.setVestibularMotionEnabled(this.checked, true);
@@ -106,6 +106,7 @@ GroupBox {
} }
} }
Component.onCompleted: { Component.onCompleted: {
redirectedWalkingRadiusText.text = ((RotationTabController.vestibularMotionRadius).toFixed(2)) redirectedWalkingRadiusText.text = ((RotationTabController.vestibularMotionRadius).toFixed(2))
redirectedModeToggle.checked = RotationTabController.vestibularMotionEnabled redirectedModeToggle.checked = RotationTabController.vestibularMotionEnabled
@@ -11,7 +11,7 @@ GroupBox {
label: MyText { label: MyText {
leftPadding: 10 leftPadding: 10
text: "Space Turn (for manual redirected walking)" text: "Space Turn (for manual redirected walking)"
bottomPadding: -10 bottomPadding: -12
} }
background: Rectangle { background: Rectangle {
color: "transparent" color: "transparent"
@@ -26,7 +26,7 @@ GroupBox {
color: "#ffffff" color: "#ffffff"
height: 1 height: 1
Layout.fillWidth: true Layout.fillWidth: true
Layout.bottomMargin: 5 Layout.bottomMargin: 3
} }
RowLayout { RowLayout {
@@ -0,0 +1,88 @@
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3
import ovras.advsettings 1.0
import "../../common"
GroupBox {
id: viewRatchetGroupBox
Layout.fillWidth: true
ColumnLayout {
anchors.fill: parent
RowLayout {
Layout.fillWidth: true
MyToggleButton{
id: viewRatchetToggleBtn
text: "View Ratchetting"
Layout.preferredWidth: 275
onCheckedChanged: {
RotationTabController.setViewRatchettingEnabled(this.checked, true);
}
}
Item{
Layout.preferredWidth: 25
}
MySlider {
id: viewRatchetSlider
from: 0.00
to: 0.1
stepSize: 0.01
Layout.fillWidth: true
onMoved: {
viewRatchetText.text = this.value.toFixed(2)
RotationTabController.setViewRatchettingPercent(this.value, true)
}
}
MyTextField {
id: viewRatchetText
text: "0.05"
keyBoardUID: 1007
Layout.preferredWidth: 100
Layout.leftMargin: 10
horizontalAlignment: Text.AlignHCenter
function onInputEvent(input) {
var val = parseFloat(input)
if (!isNaN(val)) {
if (val < 0) {
val = 0
} else if (val > 1) {
val = 1
}
RotationTabController.setViewRatchettingPercent(val.toFixed(2), true)
if(val > 0.1){
viewRatchetSlider.value = 0.1
}else{
viewRatchetSlider.value = val
}
}
text = RotationTabController.viewRatchettingPercent.toFixed(2);
}
}
}
}
Component.onCompleted: {
viewRatchetToggleBtn.checked = RotationTabController.viewRatchettingEnabled
var ratchetPercVal = RotationTabController.viewRatchettingPercent
viewRatchetSlider.value = ratchetPercVal
viewRatchetText.text = ratchetPercVal.toFixed(2)
}
Connections {
target: RotationTabController
onViewRatchettingEnabledChanged:{
viewRatchetToggleBtn.checked = RotationTabController.viewRatchettingEnabled
}
onViewRatchettingPercentChanged:{
var ratchetPercVal = RotationTabController.viewRatchettingPercent
viewRatchetSlider.value = ratchetPercVal
viewRatchetText.text = ratchetPercVal.toFixed(2)
}
}
}
@@ -56,7 +56,7 @@ GroupBox {
stepSize: 0.01 stepSize: 0.01
value: 1.0 value: 1.0
Layout.fillWidth: true Layout.fillWidth: true
onPositionChanged: { onMoved: {
var val = (this.value * 100) var val = (this.value * 100)
brightnessValueText.text = Math.round(val) + "%" brightnessValueText.text = Math.round(val) + "%"
VideoTabController.setBrightnessOpacityValue(value.toFixed(2), true) VideoTabController.setBrightnessOpacityValue(value.toFixed(2), true)
@@ -80,6 +80,9 @@ GroupBox {
} }
var v = (val/100) var v = (val/100)
VideoTabController.setBrightnessOpacityValue(v.toFixed(2), true) VideoTabController.setBrightnessOpacityValue(v.toFixed(2), true)
if(v<.05){
v = .05
}
brightnessSlider.value = v brightnessSlider.value = v
} }
text = Math.round(VideoTabController.brightnessOpacityValue * 100) + "%" text = Math.round(VideoTabController.brightnessOpacityValue * 100) + "%"
+9 -1
View File
@@ -396,6 +396,10 @@ private:
SettingCategory::Rotation, SettingCategory::Rotation,
QtInfo{ "autoturnVestibularMotionEnabled" }, QtInfo{ "autoturnVestibularMotionEnabled" },
false }, false },
BoolSettingValue{ BoolSetting::ROTATION_autoturnViewRatchettingEnabled,
SettingCategory::Rotation,
QtInfo{ "autoturnViewRatchettingEnabled" },
false },
BoolSettingValue{ BoolSetting::ROTATION_autoturnShowNotification, BoolSettingValue{ BoolSetting::ROTATION_autoturnShowNotification,
SettingCategory::Rotation, SettingCategory::Rotation,
QtInfo{ "autoturnShowNotification" }, QtInfo{ "autoturnShowNotification" },
@@ -488,7 +492,11 @@ private:
SettingCategory::Rotation, SettingCategory::Rotation,
QtInfo{ "autoturnVestibularMotionRadius" }, QtInfo{ "autoturnVestibularMotionRadius" },
22.0 }, 22.0 },
DoubleSettingValue{
DoubleSetting::ROTATION_autoturnViewRatchettingPercent,
SettingCategory::Rotation,
QtInfo{ "autoturnViewRatchettingPercent" },
0.05 },
}; };
constexpr static auto stringSettingsSize constexpr static auto stringSettingsSize
+3 -1
View File
@@ -56,6 +56,7 @@ enum class BoolSetting
ROTATION_autoturnEnabled, ROTATION_autoturnEnabled,
ROTATION_autoturnUseCornerAngle, ROTATION_autoturnUseCornerAngle,
ROTATION_autoturnVestibularMotionEnabled, ROTATION_autoturnVestibularMotionEnabled,
ROTATION_autoturnViewRatchettingEnabled,
ROTATION_autoturnShowNotification, ROTATION_autoturnShowNotification,
// LAST_ENUMERATOR must always be set to the last value // LAST_ENUMERATOR must always be set to the last value
LAST_ENUMERATOR = ROTATION_autoturnShowNotification, LAST_ENUMERATOR = ROTATION_autoturnShowNotification,
@@ -84,8 +85,9 @@ enum class DoubleSetting
ROTATION_cordDetanglingAngle, ROTATION_cordDetanglingAngle,
ROTATION_autoturnMinCordTangle, ROTATION_autoturnMinCordTangle,
ROTATION_autoturnVestibularMotionRadius, ROTATION_autoturnVestibularMotionRadius,
ROTATION_autoturnViewRatchettingPercent,
// LAST_ENUMERATOR must always be set to the last value // LAST_ENUMERATOR must always be set to the last value
LAST_ENUMERATOR = ROTATION_autoturnVestibularMotionRadius, LAST_ENUMERATOR = ROTATION_autoturnViewRatchettingPercent,
}; };
enum class StringSetting enum class StringSetting
+152 -46
View File
@@ -94,7 +94,6 @@ void RotationTabController::eventLoopTick(
{ {
m_isHMDActive = true; m_isHMDActive = true;
} }
// TODO: this doesn't need to run if both are off
if ( poseHmd.bPoseIsValid && poseHmd.bDeviceIsConnected if ( poseHmd.bPoseIsValid && poseHmd.bDeviceIsConnected
&& poseHmd.eTrackingResult == vr::TrackingResult_Running_OK ) && poseHmd.eTrackingResult == vr::TrackingResult_Running_OK )
{ {
@@ -116,6 +115,12 @@ void RotationTabController::eventLoopTick(
doVestibularMotion( poseHmd, chaperoneDistances ); doVestibularMotion( poseHmd, chaperoneDistances );
} }
if ( RotationTabController::viewRatchettingEnabled() )
{
doViewRatchetting( poseHmd, chaperoneDistances );
}
m_autoTurnLastHmdUpdate = poseHmd.mDeviceToAbsoluteTracking;
m_autoTurnChaperoneDistancesLast = std::move( chaperoneDistances ); m_autoTurnChaperoneDistancesLast = std::move( chaperoneDistances );
} }
} }
@@ -144,6 +149,85 @@ void RotationTabController::eventLoopTick(
} }
} }
void RotationTabController::doViewRatchetting(
const vr::TrackedDevicePose_t& poseHmd,
const std::vector<utils::ChaperoneQuadData>& chaperoneDistances )
{
if ( m_isHMDActive && poseHmd.bPoseIsValid && poseHmd.bDeviceIsConnected
&& poseHmd.eTrackingResult == vr::TrackingResult_Running_OK
&& !chaperoneDistances.empty() )
{
if ( chaperoneDistances.size()
!= m_autoTurnChaperoneDistancesLast.size() )
{
m_autoTurnChaperoneDistancesLast = chaperoneDistances;
m_autoTurnLastHmdUpdate = poseHmd.mDeviceToAbsoluteTracking;
}
// Find the (index of the) nearest wall
size_t nearestWallIdx = 0;
for ( size_t i = 0; i < chaperoneDistances.size(); i++ )
{
if ( chaperoneDistances[i].distance
< chaperoneDistances[nearestWallIdx].distance )
{
nearestWallIdx = i;
}
}
const auto& nearestWall = chaperoneDistances[nearestWallIdx];
// Convert pose matrix to quaternion
auto hmdQuaternion
= quaternion::fromHmdMatrix34( poseHmd.mDeviceToAbsoluteTracking );
// Get HMD raw yaw
double hmdYaw = quaternion::getYaw( hmdQuaternion );
// Get angle between HMD position and nearest point on
// wall
double hmdPositionToWallYaw = static_cast<double>(
std::atan2( nearestWall.nearestPoint.v[0]
- poseHmd.mDeviceToAbsoluteTracking.m[0][3],
nearestWall.nearestPoint.v[2]
- poseHmd.mDeviceToAbsoluteTracking.m[2][3] ) );
// Get angle between HMD and wall
double hmdToWallYaw
= reduceAngle<>( hmdYaw - hmdPositionToWallYaw, -M_PI, M_PI );
do
{
// if we change walls, ignore
if ( nearestWallIdx != m_ratchettingLastWall )
{
break;
}
// Facing away from the wall is 0, |facing towards the wall| is M_PI
// Ignore turning towards the wall (e.g. change in magnitude is
// greater than 0)
if ( std::abs( hmdToWallYaw )
- std::abs( m_ratchettingLastHmdRotation )
> 0.0 )
{
break;
}
// Magnify that change
double delta_degrees
= reduceAngle<>(
hmdToWallYaw - m_ratchettingLastHmdRotation, -M_PI, M_PI )
* viewRatchettingPercent();
parent->m_moveCenterTabController.setRotation(
parent->m_moveCenterTabController.rotation()
+ static_cast<int>( delta_degrees * k_radiansToCentidegrees ) );
} while ( false );
m_ratchettingLastHmdRotation = hmdToWallYaw;
m_ratchettingLastWall = nearestWallIdx;
}
}
void RotationTabController::doVestibularMotion( void RotationTabController::doVestibularMotion(
const vr::TrackedDevicePose_t& poseHmd, const vr::TrackedDevicePose_t& poseHmd,
const std::vector<utils::ChaperoneQuadData>& chaperoneDistances ) const std::vector<utils::ChaperoneQuadData>& chaperoneDistances )
@@ -158,37 +242,20 @@ void RotationTabController::doVestibularMotion(
m_autoTurnChaperoneDistancesLast = chaperoneDistances; m_autoTurnChaperoneDistancesLast = chaperoneDistances;
m_autoTurnLastHmdUpdate = poseHmd.mDeviceToAbsoluteTracking; m_autoTurnLastHmdUpdate = poseHmd.mDeviceToAbsoluteTracking;
} }
// Find the nearest wall we're moving TOWARDS and rotate // Rotate dist/(2*pi*r) where r is
// away from it Rotate dist/(2*pi*r) where r is
// m_autoTurnVestibularMotionRadius, as if we had walked // m_autoTurnVestibularMotionRadius, as if we had walked
// however many inches along a circle and the world was // however many inches along a circle and the world was
// turning to compensate // turning to compensate
do do
{ {
// find nearest wall we're moving towards // Find the nearest wall
auto nearestWall = chaperoneDistances.end(); const auto& nearestWall
auto itrLast = m_autoTurnChaperoneDistancesLast.begin(); = std::min_element( chaperoneDistances.begin(),
for ( auto itr = chaperoneDistances.begin(); chaperoneDistances.end(),
itr != chaperoneDistances.end(); []( const auto& quadA, const auto& quadB ) {
itr++ ) return quadA.distance < quadB.distance;
{ } );
itrLast++;
// if ( itr->distance > itrLast->distance )
//{
// continue;
//}
if ( nearestWall == chaperoneDistances.end()
|| itr->distance < nearestWall->distance )
{
nearestWall = itr;
}
}
if ( nearestWall == chaperoneDistances.end() )
{
break;
}
// Convert pose matrix to quaternion // Convert pose matrix to quaternion
auto hmdQuaternion = quaternion::fromHmdMatrix34( auto hmdQuaternion = quaternion::fromHmdMatrix34(
@@ -210,6 +277,19 @@ void RotationTabController::doVestibularMotion(
= reduceAngle<>( hmdYaw - hmdPositionToWallYaw, -M_PI, M_PI ); = reduceAngle<>( hmdYaw - hmdPositionToWallYaw, -M_PI, M_PI );
bool turnLeft = hmdToWallYaw > 0.0; bool turnLeft = hmdToWallYaw > 0.0;
// Only turn if moving forward
double hmdMovementDirection = static_cast<double>(
std::atan2( m_autoTurnLastHmdUpdate.m[0][3]
- poseHmd.mDeviceToAbsoluteTracking.m[0][3],
m_autoTurnLastHmdUpdate.m[2][3]
- poseHmd.mDeviceToAbsoluteTracking.m[2][3] ) );
if ( std::abs( hmdYaw - hmdMovementDirection )
* k_radiansToCentidegrees
>= 7000 )
{
break;
}
// Get the distance between previous and current // Get the distance between previous and current
// position // position
double distanceChange = static_cast<double>( double distanceChange = static_cast<double>(
@@ -229,20 +309,16 @@ void RotationTabController::doVestibularMotion(
} }
double rotationAmount = arcLength * ( turnLeft ? 1 : -1 ); double rotationAmount = arcLength * ( turnLeft ? 1 : -1 );
int newRotationAngle = reduceAngle<>(
parent->m_moveCenterTabController.rotation()
+ static_cast<int>( rotationAmount
* k_radiansToCentidegrees ),
0,
36000 );
double newRotationAngleDeg parent->m_moveCenterTabController.setRotation( newRotationAngle );
= std::fmod( parent->m_moveCenterTabController.rotation()
+ ( rotationAmount * k_radiansToCentidegrees )
+ m_autoTurnRoundingError,
360000.0 );
int newRotationAngleInt = static_cast<int>( newRotationAngleDeg );
m_autoTurnRoundingError = newRotationAngleDeg - newRotationAngleInt;
parent->m_moveCenterTabController.setRotation(
newRotationAngleInt );
} while ( false ); } while ( false );
m_autoTurnLastHmdUpdate = poseHmd.mDeviceToAbsoluteTracking;
} }
} }
@@ -272,7 +348,6 @@ void RotationTabController::doAutoTurn(
== AutoTurnModes::LINEAR_SMOOTH_TURN == AutoTurnModes::LINEAR_SMOOTH_TURN
&& m_autoTurnLinearSmoothTurnRemaining != 0 ) && m_autoTurnLinearSmoothTurnRemaining != 0 )
{ {
// TODO: implement angular acceleration max?
double deltaSeconds double deltaSeconds
= FrameRates::toDoubleSeconds( m_estimatedFrameRate ); = FrameRates::toDoubleSeconds( m_estimatedFrameRate );
auto miniDeltaAngle = static_cast<int>( auto miniDeltaAngle = static_cast<int>(
@@ -284,11 +359,11 @@ void RotationTabController::doAutoTurn(
{ {
miniDeltaAngle = m_autoTurnLinearSmoothTurnRemaining; miniDeltaAngle = m_autoTurnLinearSmoothTurnRemaining;
} }
int newRotationAngleDeg = reduceAngle<>( int newRotationAngleDeg
static_cast<int>( parent->m_moveCenterTabController.rotation() = reduceAngle<>( parent->m_moveCenterTabController.rotation()
+ miniDeltaAngle ), + static_cast<int>( miniDeltaAngle ),
0, 0,
36000 ); 36000 );
parent->m_moveCenterTabController.setRotation( parent->m_moveCenterTabController.setRotation(
newRotationAngleDeg ); newRotationAngleDeg );
@@ -428,9 +503,8 @@ void RotationTabController::doAutoTurn(
{ {
case AutoTurnModes::SNAP: case AutoTurnModes::SNAP:
parent->m_moveCenterTabController.setRotation( parent->m_moveCenterTabController.setRotation(
static_cast<int>( parent->m_moveCenterTabController.rotation()
parent->m_moveCenterTabController.rotation() + static_cast<int>( delta_degrees ) );
+ delta_degrees ) );
break; break;
case AutoTurnModes::LINEAR_SMOOTH_TURN: case AutoTurnModes::LINEAR_SMOOTH_TURN:
m_autoTurnLinearSmoothTurnRemaining m_autoTurnLinearSmoothTurnRemaining
@@ -577,6 +651,18 @@ double RotationTabController::vestibularMotionRadius() const
settings::DoubleSetting::ROTATION_autoturnVestibularMotionRadius ); settings::DoubleSetting::ROTATION_autoturnVestibularMotionRadius );
} }
bool RotationTabController::viewRatchettingEnabled() const
{
return settings::getSetting(
settings::BoolSetting::ROTATION_autoturnViewRatchettingEnabled );
}
double RotationTabController::viewRatchettingPercent() const
{
return settings::getSetting(
settings::DoubleSetting::ROTATION_autoturnViewRatchettingPercent );
}
// Setters // Setters
void RotationTabController::setAutoTurnEnabled( bool value, bool notify ) void RotationTabController::setAutoTurnEnabled( bool value, bool notify )
@@ -711,5 +797,25 @@ void RotationTabController::setVestibularMotionRadius( double value,
emit vestibularMotionRadiusChanged( value ); emit vestibularMotionRadiusChanged( value );
} }
} }
void RotationTabController::setViewRatchettingEnabled( bool value, bool notify )
{
settings::setSetting(
settings::BoolSetting::ROTATION_autoturnViewRatchettingEnabled, value );
if ( notify )
{
emit viewRatchettingEnabledChanged( value );
}
}
void RotationTabController::setViewRatchettingPercent( double value,
bool notify )
{
settings::setSetting(
settings::DoubleSetting::ROTATION_autoturnViewRatchettingPercent,
value );
if ( notify )
{
emit viewRatchettingPercentChanged( value );
}
}
} // namespace advsettings } // namespace advsettings
+17 -1
View File
@@ -83,6 +83,12 @@ class RotationTabController : public QObject
Q_PROPERTY( Q_PROPERTY(
double vestibularMotionRadius READ vestibularMotionRadius WRITE double vestibularMotionRadius READ vestibularMotionRadius WRITE
setVestibularMotionRadius NOTIFY vestibularMotionRadiusChanged ) setVestibularMotionRadius NOTIFY vestibularMotionRadiusChanged )
Q_PROPERTY(
bool viewRatchettingEnabled READ viewRatchettingEnabled WRITE
setViewRatchettingEnabled NOTIFY viewRatchettingEnabledChanged )
Q_PROPERTY(
double viewRatchettingPercent READ viewRatchettingPercent WRITE
setViewRatchettingPercent NOTIFY viewRatchettingPercentChanged )
Q_PROPERTY( Q_PROPERTY(
bool autoTurnShowNotification READ autoTurnShowNotification WRITE bool autoTurnShowNotification READ autoTurnShowNotification WRITE
setAutoTurnShowNotification NOTIFY autoTurnShowNotificationChanged ) setAutoTurnShowNotification NOTIFY autoTurnShowNotificationChanged )
@@ -108,8 +114,9 @@ private:
std::vector<bool> m_autoTurnWallActive; std::vector<bool> m_autoTurnWallActive;
vr::HmdMatrix34_t m_autoTurnLastHmdUpdate; vr::HmdMatrix34_t m_autoTurnLastHmdUpdate;
std::vector<utils::ChaperoneQuadData> m_autoTurnChaperoneDistancesLast; std::vector<utils::ChaperoneQuadData> m_autoTurnChaperoneDistancesLast;
double m_autoTurnRoundingError = 0.0;
std::chrono::steady_clock::time_point::duration m_estimatedFrameRate; std::chrono::steady_clock::time_point::duration m_estimatedFrameRate;
double m_ratchettingLastHmdRotation = 0.0;
size_t m_ratchettingLastWall = 0;
std::optional<std::chrono::steady_clock::time_point> std::optional<std::chrono::steady_clock::time_point>
m_autoTurnNotificationTimestamp; m_autoTurnNotificationTimestamp;
@@ -122,6 +129,9 @@ private:
void doVestibularMotion( void doVestibularMotion(
const vr::TrackedDevicePose_t& poseHmd, const vr::TrackedDevicePose_t& poseHmd,
const std::vector<utils::ChaperoneQuadData>& chaperoneDistances ); const std::vector<utils::ChaperoneQuadData>& chaperoneDistances );
void doViewRatchetting(
const vr::TrackedDevicePose_t& poseHmd,
const std::vector<utils::ChaperoneQuadData>& chaperoneDistances );
public: public:
void initStage1(); void initStage1();
@@ -143,6 +153,8 @@ public:
int autoTurnMode() const; int autoTurnMode() const;
bool vestibularMotionEnabled() const; bool vestibularMotionEnabled() const;
double vestibularMotionRadius() const; double vestibularMotionRadius() const;
bool viewRatchettingEnabled() const;
double viewRatchettingPercent() const;
public slots: public slots:
void setAutoTurnEnabled( bool value, bool notify = true ); void setAutoTurnEnabled( bool value, bool notify = true );
@@ -156,6 +168,8 @@ public slots:
void setAutoTurnMode( int value, bool notify = true ); void setAutoTurnMode( int value, bool notify = true );
void setVestibularMotionEnabled( bool value, bool notify = true ); void setVestibularMotionEnabled( bool value, bool notify = true );
void setVestibularMotionRadius( double value, bool notify = true ); void setVestibularMotionRadius( double value, bool notify = true );
void setViewRatchettingEnabled( bool value, bool notify = true );
void setViewRatchettingPercent( double value, bool notify = true );
signals: signals:
@@ -171,6 +185,8 @@ signals:
void autoTurnModeChanged( int value ); void autoTurnModeChanged( int value );
void vestibularMotionEnabledChanged( bool value ); void vestibularMotionEnabledChanged( bool value );
void vestibularMotionRadiusChanged( double value ); void vestibularMotionRadiusChanged( double value );
void viewRatchettingEnabledChanged( bool value );
void viewRatchettingPercentChanged( double value );
}; };
// Would be nice to do <typename T, T min, T max> but the standard doesn't allow // Would be nice to do <typename T, T min, T max> but the standard doesn't allow