808 lines
31 KiB
C++
808 lines
31 KiB
C++
#include "RotationTabController.h"
|
|
#include <QQuickWindow>
|
|
#include <QtLogging>
|
|
#include <QtDebug>
|
|
#include "../overlaycontroller.h"
|
|
#include "../settings/settings.h"
|
|
#include "../utils/Matrix.h"
|
|
#include "../quaternion/quaternion.h"
|
|
#include <cmath>
|
|
|
|
// application namespace
|
|
namespace advsettings
|
|
{
|
|
void RotationTabController::initStage1()
|
|
{ // TODO adjust update rate
|
|
// m_chaperoneSettingsUpdateCounter
|
|
// = utils::adjustUpdateRate( k_chaperoneSettingsUpdateCounter );
|
|
}
|
|
|
|
void RotationTabController::initStage2( OverlayController* var_parent )
|
|
{
|
|
this->parent = var_parent;
|
|
|
|
const auto autoturnOverlayKey
|
|
= std::string( application_strings::applicationKey )
|
|
+ ".autoturnnotification";
|
|
|
|
const auto overlayError
|
|
= vr::VROverlay()->CreateOverlay( autoturnOverlayKey.c_str(),
|
|
autoturnOverlayKey.c_str(),
|
|
&m_autoturnValues.overlayHandle );
|
|
if ( overlayError != vr::VROverlayError_None )
|
|
{
|
|
qCritical() << "Could not create autoturn notification overlay: "
|
|
<< vr::VROverlay()->GetOverlayErrorNameFromEnum(
|
|
overlayError );
|
|
|
|
emit defaultProfileDisplay();
|
|
|
|
return;
|
|
}
|
|
m_autoturnValues.autoturnImg.reset(
|
|
new QImage( ":qt/qml/AdvancedSettings/src/res/img/rotation/autoturn.png" ) );
|
|
m_autoturnValues.noautoturnImg.reset(
|
|
new QImage( ":qt/qml/AdvancedSettings/src/res/img/rotation/noautoturn.png" ) );
|
|
|
|
ovr_overlay_wrapper::setOverlayFromQImage( m_autoturnValues.overlayHandle,
|
|
*m_autoturnValues.autoturnImg );
|
|
|
|
vr::VROverlay()->SetOverlayWidthInMeters( m_autoturnValues.overlayHandle,
|
|
0.02f );
|
|
vr::HmdMatrix34_t notificationTransform
|
|
= { { { 1.0f, 0.0f, 0.0f, 0.12f },
|
|
{ 0.0f, 1.0f, 0.0f, 0.08f },
|
|
{ 0.0f, 0.0f, 1.0f, -0.3f } } };
|
|
vr::VROverlay()->SetOverlayTransformTrackedDeviceRelative(
|
|
m_autoturnValues.overlayHandle,
|
|
vr::k_unTrackedDeviceIndex_Hmd,
|
|
¬ificationTransform );
|
|
|
|
emit defaultProfileDisplay();
|
|
}
|
|
|
|
void RotationTabController::eventLoopTick(
|
|
vr::TrackedDevicePose_t* devicePoses )
|
|
{
|
|
if ( devicePoses )
|
|
{
|
|
m_isHMDActive = false;
|
|
std::lock_guard<std::recursive_mutex> lock(
|
|
parent->chaperoneUtils().mutex() );
|
|
auto& poseHmd = devicePoses[vr::k_unTrackedDeviceIndex_Hmd];
|
|
|
|
// m_isHMDActive is true when prox sensor OR HMD is moving (~10 seconds
|
|
// to update from OVR)
|
|
// THIS IS A WORK-AROUND Until proper binding support/calls are made
|
|
// availble for prox sensor
|
|
if ( vr::VRSystem()->GetTrackedDeviceActivityLevel(
|
|
vr::k_unTrackedDeviceIndex_Hmd )
|
|
== vr::k_EDeviceActivityLevel_UserInteraction )
|
|
{
|
|
m_isHMDActive = true;
|
|
}
|
|
if ( poseHmd.bPoseIsValid && poseHmd.bDeviceIsConnected
|
|
&& poseHmd.eTrackingResult == vr::TrackingResult_Running_OK )
|
|
{
|
|
auto chaperoneDistances
|
|
= parent->chaperoneUtils().getDistancesToChaperone(
|
|
{ poseHmd.mDeviceToAbsoluteTracking.m[0][3],
|
|
poseHmd.mDeviceToAbsoluteTracking.m[1][3],
|
|
poseHmd.mDeviceToAbsoluteTracking.m[2][3] } );
|
|
|
|
// Autoturn mode
|
|
if ( RotationTabController::autoTurnEnabled() )
|
|
{
|
|
doAutoTurn( poseHmd, chaperoneDistances );
|
|
}
|
|
// Vestibular motion. Dependent on autoTurn so the playspace
|
|
// doesn't move when you use the keybind
|
|
if ( RotationTabController::vestibularMotionEnabled() )
|
|
{
|
|
doVestibularMotion( poseHmd, chaperoneDistances );
|
|
}
|
|
|
|
if ( RotationTabController::viewRatchettingEnabled() )
|
|
{
|
|
doViewRatchetting( poseHmd, chaperoneDistances );
|
|
}
|
|
|
|
m_autoTurnLastHmdUpdate = poseHmd.mDeviceToAbsoluteTracking;
|
|
m_autoTurnChaperoneDistancesLast = std::move( chaperoneDistances );
|
|
}
|
|
}
|
|
if ( m_autoTurnNotificationTimestamp )
|
|
{
|
|
auto count = std::chrono::duration_cast<std::chrono::milliseconds>(
|
|
std::chrono::steady_clock::now()
|
|
- *m_autoTurnNotificationTimestamp )
|
|
.count();
|
|
if ( count > 1500 )
|
|
{
|
|
m_autoTurnNotificationTimestamp.reset();
|
|
if ( getNotificationOverlayHandle()
|
|
!= vr::k_ulOverlayHandleInvalid )
|
|
{
|
|
vr::VROverlay()->HideOverlay( getNotificationOverlayHandle() );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
float pct
|
|
= std::min( 1.0f, 3.0f - static_cast<float>( count ) / 500.0f );
|
|
vr::VROverlay()->SetOverlayAlpha( getNotificationOverlayHandle(),
|
|
pct );
|
|
}
|
|
}
|
|
}
|
|
|
|
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(
|
|
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;
|
|
}
|
|
// Rotate dist/(2*pi*r) where r is
|
|
// m_autoTurnVestibularMotionRadius, as if we had walked
|
|
// however many inches along a circle and the world was
|
|
// turning to compensate
|
|
|
|
do
|
|
{
|
|
// Find the nearest wall
|
|
const auto& nearestWall
|
|
= std::min_element( chaperoneDistances.begin(),
|
|
chaperoneDistances.end(),
|
|
[]( const auto& quadA, const auto& quadB ) {
|
|
return quadA.distance < quadB.distance;
|
|
} );
|
|
|
|
// 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( poseHmd.mDeviceToAbsoluteTracking.m[0][3]
|
|
- nearestWall->nearestPoint.v[0],
|
|
poseHmd.mDeviceToAbsoluteTracking.m[2][3]
|
|
- nearestWall->nearestPoint.v[2] ) );
|
|
|
|
// Get angle between HMD and wall
|
|
double hmdToWallYaw
|
|
= reduceAngle<>( hmdYaw - hmdPositionToWallYaw, -M_PI, M_PI );
|
|
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
|
|
// position
|
|
double distanceChange = static_cast<double>(
|
|
std::hypot( poseHmd.mDeviceToAbsoluteTracking.m[0][3]
|
|
- m_autoTurnLastHmdUpdate.m[0][3],
|
|
poseHmd.mDeviceToAbsoluteTracking.m[2][3]
|
|
- m_autoTurnLastHmdUpdate.m[2][3] ) );
|
|
|
|
// Get the arc length between the previous point and current point
|
|
// 2 sin-1( (d/2)/r ) (in radians)
|
|
double arcLength = 2
|
|
* std::asin( ( distanceChange / 2 )
|
|
/ vestibularMotionRadius() );
|
|
if ( std::isnan( arcLength ) )
|
|
{
|
|
break;
|
|
}
|
|
|
|
double rotationAmount = arcLength * ( turnLeft ? 1 : -1 );
|
|
int newRotationAngle = reduceAngle<>(
|
|
parent->m_moveCenterTabController.rotation()
|
|
+ static_cast<int>( rotationAmount
|
|
* k_radiansToCentidegrees ),
|
|
0,
|
|
36000 );
|
|
|
|
parent->m_moveCenterTabController.setRotation( newRotationAngle );
|
|
|
|
} while ( false );
|
|
}
|
|
}
|
|
|
|
void RotationTabController::doAutoTurn(
|
|
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() )
|
|
{
|
|
auto currentTime = std::chrono::steady_clock::now();
|
|
|
|
if ( m_autoTurnWallActive.size() != chaperoneDistances.size() )
|
|
{
|
|
// Chaperone changed
|
|
m_autoTurnWallActive.clear();
|
|
// Initialize all to 'true' so we don't rotate on startup if
|
|
// the user is outside of the play area.
|
|
m_autoTurnWallActive.resize( chaperoneDistances.size(), true );
|
|
m_autoTurnLastUpdate = currentTime;
|
|
}
|
|
|
|
// Apply smooth rotation per-frame: get the time since last frame,
|
|
// multiply by speed
|
|
if ( RotationTabController::autoTurnModeType()
|
|
== AutoTurnModes::LINEAR_SMOOTH_TURN
|
|
&& m_autoTurnLinearSmoothTurnRemaining != 0 )
|
|
{
|
|
double deltaSeconds
|
|
= FrameRates::toDoubleSeconds( m_estimatedFrameRate );
|
|
auto miniDeltaAngle = static_cast<int>(
|
|
std::abs(
|
|
( deltaSeconds * RotationTabController::autoTurnSpeed() ) )
|
|
* ( m_autoTurnLinearSmoothTurnRemaining < 0 ? -1 : 1 ) );
|
|
if ( std::abs( m_autoTurnLinearSmoothTurnRemaining )
|
|
< std::abs( miniDeltaAngle ) )
|
|
{
|
|
miniDeltaAngle = m_autoTurnLinearSmoothTurnRemaining;
|
|
}
|
|
int newRotationAngleDeg
|
|
= reduceAngle<>( parent->m_moveCenterTabController.rotation()
|
|
+ static_cast<int>( miniDeltaAngle ),
|
|
0,
|
|
36000 );
|
|
|
|
parent->m_moveCenterTabController.setRotation(
|
|
newRotationAngleDeg );
|
|
m_autoTurnLinearSmoothTurnRemaining -= miniDeltaAngle;
|
|
}
|
|
|
|
for ( size_t i = 0; i < chaperoneDistances.size(); i++ )
|
|
{
|
|
const auto& chaperoneQuad = chaperoneDistances[i];
|
|
if ( chaperoneQuad.distance
|
|
<= RotationTabController::autoTurnActivationDistance()
|
|
&& !m_autoTurnWallActive[i] )
|
|
{
|
|
// 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( poseHmd.mDeviceToAbsoluteTracking.m[0][3]
|
|
- chaperoneQuad.nearestPoint.v[0],
|
|
poseHmd.mDeviceToAbsoluteTracking.m[2][3]
|
|
- chaperoneQuad.nearestPoint.v[2] ) );
|
|
|
|
// Get angle between HMD and wall
|
|
double hmdToWallYaw = reduceAngle<>(
|
|
hmdYaw - hmdPositionToWallYaw, -M_PI, M_PI );
|
|
|
|
do
|
|
{
|
|
// Ignore if the wall we encountered is behind us
|
|
if ( std::abs( hmdToWallYaw ) >= M_PI / 2 )
|
|
{
|
|
qDebug() << "Ignoring turn in opposite "
|
|
"direction (angle "
|
|
<< std::abs( hmdToWallYaw ) << ")";
|
|
break;
|
|
}
|
|
|
|
// If the closest corner shares a wall with the last
|
|
// wall we turned at, turn relative to that corner
|
|
bool cornerShared
|
|
= m_autoTurnWallActive[circularIndex(
|
|
i, true, chaperoneDistances.size() )]
|
|
|| m_autoTurnWallActive[circularIndex(
|
|
i, false, chaperoneDistances.size() )];
|
|
|
|
bool turnLeft = true;
|
|
// Turn away from corner
|
|
if ( cornerShared )
|
|
{
|
|
// Turn left or right depending on which corner
|
|
// it is. If we go based on yaw, we could end up
|
|
// turning the wrong way if it's large obtuse
|
|
// angle and we're facing more towards the
|
|
// previous wall than the left.
|
|
turnLeft = m_autoTurnWallActive[circularIndex(
|
|
i, false, chaperoneDistances.size() )];
|
|
qDebug() << "turning away from shared corner";
|
|
}
|
|
// If within m_cordDetanglingAngle degrees of
|
|
// 'straight at a wall', start in whatever direction
|
|
// will start untangling your cord
|
|
else if ( ( std::abs( hmdToWallYaw )
|
|
<= RotationTabController::cordDetangleAngle() )
|
|
&& ( std::abs( parent->m_moveCenterTabController
|
|
.getHmdYawTotal() )
|
|
> RotationTabController::minCordTangle() ) )
|
|
{
|
|
turnLeft = ( parent->m_moveCenterTabController
|
|
.getHmdYawTotal()
|
|
< 0.0 );
|
|
qDebug() << "turning to detangle cord";
|
|
}
|
|
// Turn the closest angle to the wall
|
|
else
|
|
{
|
|
turnLeft = hmdToWallYaw > 0.0;
|
|
qDebug() << "turning closest angle to wall";
|
|
}
|
|
|
|
qDebug() << "hmd yaw " << hmdYaw
|
|
<< ", hmd position to wall angle "
|
|
<< hmdPositionToWallYaw;
|
|
qDebug() << "hmd to wall angle " << hmdToWallYaw;
|
|
// Positive hmd-to-wall is facing left, negative is
|
|
// facing right (relative to the wall)
|
|
double delta_degrees
|
|
= ( ( turnLeft ? M_PI / 2 : -M_PI / 2 ) - hmdToWallYaw )
|
|
* k_radiansToCentidegrees;
|
|
if ( RotationTabController::autoTurnUseCornerAngle()
|
|
&& cornerShared )
|
|
{
|
|
// Turn the angle of the corner
|
|
// Three relevant points - the far corner wall
|
|
// we're currently touching, the far corner on
|
|
// the wall we've just touched, and the corner
|
|
// between them
|
|
const size_t cornerCnt
|
|
= parent->chaperoneUtils().quadsCount();
|
|
const size_t middleCornerIdx
|
|
= turnLeft ? i
|
|
: circularIndex( i, true, cornerCnt );
|
|
const auto& middleCorner
|
|
= parent->chaperoneUtils().getCorner(
|
|
middleCornerIdx );
|
|
const auto& newWallCorner
|
|
= parent->chaperoneUtils().getCorner( circularIndex(
|
|
middleCornerIdx, turnLeft, cornerCnt ) );
|
|
const auto& touchingWallCorner
|
|
= parent->chaperoneUtils().getCorner( circularIndex(
|
|
middleCornerIdx, !turnLeft, cornerCnt ) );
|
|
|
|
double newWallAngle = static_cast<double>( std::atan2(
|
|
middleCorner.v[0] - newWallCorner.v[0],
|
|
middleCorner.v[2] - newWallCorner.v[2] ) );
|
|
double touchingWallAngle
|
|
= static_cast<double>( std::atan2(
|
|
middleCorner.v[0] - touchingWallCorner.v[0],
|
|
middleCorner.v[2] - touchingWallCorner.v[2] ) );
|
|
qDebug() << "twa: " << touchingWallAngle
|
|
<< ", nwa: " << newWallAngle << ", diff: "
|
|
<< ( newWallAngle - touchingWallAngle );
|
|
delta_degrees = ( newWallAngle - touchingWallAngle
|
|
+ ( turnLeft ? M_PI : -M_PI ) )
|
|
* k_radiansToCentidegrees;
|
|
delta_degrees
|
|
= reduceAngle<>( delta_degrees, -18000.0, 18000.0 );
|
|
}
|
|
qDebug() << "rotating space " << ( delta_degrees / 100 )
|
|
<< " degrees";
|
|
switch ( RotationTabController::autoTurnModeType() )
|
|
{
|
|
case AutoTurnModes::SNAP:
|
|
parent->m_moveCenterTabController.setRotation(
|
|
parent->m_moveCenterTabController.rotation()
|
|
+ static_cast<int>( delta_degrees ) );
|
|
break;
|
|
case AutoTurnModes::LINEAR_SMOOTH_TURN:
|
|
m_autoTurnLinearSmoothTurnRemaining
|
|
+= static_cast<int>( delta_degrees );
|
|
break;
|
|
}
|
|
} while ( false );
|
|
|
|
m_autoTurnWallActive[i] = true;
|
|
auto delta = currentTime - m_autoTurnLastUpdate;
|
|
if ( delta
|
|
< ( FrameRates::RATE_144HZ + FrameRates::RATE_120HZ ) / 2 )
|
|
{
|
|
m_estimatedFrameRate = FrameRates::RATE_144HZ;
|
|
}
|
|
else if ( ( delta >= ( FrameRates::RATE_144HZ
|
|
+ FrameRates::RATE_120HZ )
|
|
/ 2 )
|
|
&& ( delta < ( FrameRates::RATE_120HZ
|
|
+ FrameRates::RATE_90HZ )
|
|
/ 2 ) )
|
|
{
|
|
m_estimatedFrameRate = FrameRates::RATE_120HZ;
|
|
}
|
|
else if ( ( delta >= ( FrameRates::RATE_120HZ
|
|
+ FrameRates::RATE_90HZ )
|
|
/ 2 )
|
|
&& ( delta < ( FrameRates::RATE_90HZ
|
|
+ FrameRates::RATE_72HZ )
|
|
/ 2 ) )
|
|
{
|
|
m_estimatedFrameRate = FrameRates::RATE_90HZ;
|
|
}
|
|
else if ( ( delta
|
|
>= ( FrameRates::RATE_90HZ + FrameRates::RATE_72HZ )
|
|
/ 2 )
|
|
&& ( delta < ( FrameRates::RATE_72HZ
|
|
+ FrameRates::RATE_60HZ )
|
|
/ 2 ) )
|
|
{
|
|
m_estimatedFrameRate = FrameRates::RATE_72HZ;
|
|
}
|
|
else if ( ( delta
|
|
>= ( FrameRates::RATE_72HZ + FrameRates::RATE_60HZ )
|
|
/ 2 )
|
|
&& ( delta < ( FrameRates::RATE_60HZ
|
|
+ FrameRates::RATE_45HZ )
|
|
/ 2 ) )
|
|
{
|
|
m_estimatedFrameRate = FrameRates::RATE_60HZ;
|
|
}
|
|
else
|
|
{
|
|
m_estimatedFrameRate = FrameRates::RATE_45HZ;
|
|
}
|
|
}
|
|
else if ( ( chaperoneQuad.distance
|
|
> ( RotationTabController::autoTurnActivationDistance()
|
|
+ RotationTabController::
|
|
autoTurnDeactivationDistance() ) )
|
|
&& m_autoTurnWallActive[i] )
|
|
{
|
|
m_autoTurnWallActive[i] = false;
|
|
}
|
|
}
|
|
m_autoTurnLastUpdate = currentTime;
|
|
}
|
|
else
|
|
{
|
|
m_autoTurnWallActive.clear();
|
|
}
|
|
}
|
|
|
|
// getters
|
|
|
|
bool RotationTabController::autoTurnEnabled() const
|
|
{
|
|
return settings::getSetting(
|
|
settings::BoolSetting::ROTATION_autoturnEnabled );
|
|
}
|
|
|
|
float RotationTabController::autoTurnActivationDistance() const
|
|
{
|
|
return static_cast<float>( settings::getSetting(
|
|
settings::DoubleSetting::ROTATION_activationDistance ) );
|
|
}
|
|
|
|
float RotationTabController::autoTurnDeactivationDistance() const
|
|
{
|
|
return static_cast<float>( settings::getSetting(
|
|
settings::DoubleSetting::ROTATION_deactivateDistance ) );
|
|
}
|
|
|
|
bool RotationTabController::autoTurnUseCornerAngle() const
|
|
{
|
|
return settings::getSetting(
|
|
settings::BoolSetting::ROTATION_autoturnUseCornerAngle );
|
|
}
|
|
|
|
bool RotationTabController::autoTurnShowNotification() const
|
|
{
|
|
return settings::getSetting(
|
|
settings::BoolSetting::ROTATION_autoturnShowNotification );
|
|
}
|
|
|
|
double RotationTabController::cordDetangleAngle() const
|
|
{
|
|
return settings::getSetting(
|
|
settings::DoubleSetting::ROTATION_cordDetanglingAngle );
|
|
}
|
|
|
|
double RotationTabController::minCordTangle() const
|
|
{
|
|
return settings::getSetting(
|
|
settings::DoubleSetting::ROTATION_autoturnMinCordTangle );
|
|
}
|
|
|
|
int RotationTabController::autoTurnSpeed() const
|
|
{
|
|
return settings::getSetting(
|
|
settings::IntSetting::ROTATION_autoturnLinearTurnSpeed );
|
|
}
|
|
|
|
AutoTurnModes RotationTabController::autoTurnModeType() const
|
|
{
|
|
return static_cast<AutoTurnModes>(
|
|
settings::getSetting( settings::IntSetting::ROTATION_autoturnMode ) );
|
|
}
|
|
|
|
int RotationTabController::autoTurnMode() const
|
|
{
|
|
return settings::getSetting( settings::IntSetting::ROTATION_autoturnMode );
|
|
}
|
|
|
|
bool RotationTabController::vestibularMotionEnabled() const
|
|
{
|
|
return settings::getSetting(
|
|
settings::BoolSetting::ROTATION_autoturnVestibularMotionEnabled );
|
|
}
|
|
|
|
double RotationTabController::vestibularMotionRadius() const
|
|
{
|
|
return settings::getSetting(
|
|
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
|
|
|
|
void RotationTabController::setAutoTurnEnabled( bool value, bool notify )
|
|
{
|
|
settings::setSetting( settings::BoolSetting::ROTATION_autoturnEnabled,
|
|
value );
|
|
|
|
if ( notify )
|
|
{
|
|
emit autoTurnEnabledChanged( value );
|
|
}
|
|
|
|
if ( autoTurnShowNotification()
|
|
&& getNotificationOverlayHandle() != vr::k_ulOverlayHandleInvalid )
|
|
{
|
|
if ( !value )
|
|
{
|
|
ovr_overlay_wrapper::setOverlayFromQImage(
|
|
m_autoturnValues.overlayHandle,
|
|
*m_autoturnValues.noautoturnImg );
|
|
}
|
|
else
|
|
{
|
|
ovr_overlay_wrapper::setOverlayFromQImage(
|
|
m_autoturnValues.overlayHandle, *m_autoturnValues.autoturnImg );
|
|
}
|
|
|
|
vr::VROverlay()->SetOverlayAlpha( getNotificationOverlayHandle(),
|
|
1.0f );
|
|
vr::VROverlay()->ShowOverlay( getNotificationOverlayHandle() );
|
|
m_autoTurnNotificationTimestamp.emplace(
|
|
std::chrono::steady_clock::now() );
|
|
}
|
|
}
|
|
void RotationTabController::setAutoTurnShowNotification( bool value,
|
|
bool notify )
|
|
{
|
|
settings::setSetting(
|
|
settings::BoolSetting::ROTATION_autoturnShowNotification, value );
|
|
if ( notify )
|
|
{
|
|
emit autoTurnShowNotificationChanged( value );
|
|
}
|
|
}
|
|
void RotationTabController::setAutoTurnActivationDistance( float value,
|
|
bool notify )
|
|
{
|
|
settings::setSetting( settings::DoubleSetting::ROTATION_activationDistance,
|
|
static_cast<double>( value ) );
|
|
if ( notify )
|
|
{
|
|
emit autoTurnActivationDistanceChanged( value );
|
|
}
|
|
}
|
|
void RotationTabController::setAutoTurnDeactivationDistance( float value,
|
|
bool notify )
|
|
{
|
|
settings::setSetting( settings::DoubleSetting::ROTATION_deactivateDistance,
|
|
static_cast<double>( value ) );
|
|
if ( notify )
|
|
{
|
|
emit autoTurnDeactivationDistanceChanged( value );
|
|
}
|
|
}
|
|
|
|
void RotationTabController::setAutoTurnUseCornerAngle( bool value, bool notify )
|
|
{
|
|
settings::setSetting(
|
|
settings::BoolSetting::ROTATION_autoturnUseCornerAngle, value );
|
|
if ( notify )
|
|
{
|
|
emit autoTurnUseCornerAngleChanged( value );
|
|
}
|
|
}
|
|
|
|
void RotationTabController::setCordDetangleAngle( double value, bool notify )
|
|
{
|
|
settings::setSetting( settings::DoubleSetting::ROTATION_cordDetanglingAngle,
|
|
value );
|
|
if ( notify )
|
|
{
|
|
emit cordDetangleAngleChanged( value );
|
|
}
|
|
}
|
|
|
|
void RotationTabController::setMinCordTangle( double value, bool notify )
|
|
{
|
|
settings::setSetting(
|
|
settings::DoubleSetting::ROTATION_autoturnMinCordTangle, value );
|
|
if ( notify )
|
|
{
|
|
emit minCordTangleChanged( value );
|
|
}
|
|
}
|
|
void RotationTabController::setAutoTurnSpeed( int value, bool notify )
|
|
{
|
|
settings::setSetting(
|
|
settings::IntSetting::ROTATION_autoturnLinearTurnSpeed, value );
|
|
if ( notify )
|
|
{
|
|
emit autoTurnSpeedChanged( value );
|
|
}
|
|
}
|
|
void RotationTabController::setAutoTurnMode( int value, bool notify )
|
|
{
|
|
settings::setSetting( settings::IntSetting::ROTATION_autoturnMode, value );
|
|
if ( notify )
|
|
{
|
|
emit autoTurnModeChanged( value );
|
|
}
|
|
}
|
|
void RotationTabController::setVestibularMotionEnabled( bool value,
|
|
bool notify )
|
|
{
|
|
settings::setSetting(
|
|
settings::BoolSetting::ROTATION_autoturnVestibularMotionEnabled,
|
|
value );
|
|
if ( notify )
|
|
{
|
|
emit vestibularMotionEnabledChanged( value );
|
|
}
|
|
}
|
|
void RotationTabController::setVestibularMotionRadius( double value,
|
|
bool notify )
|
|
{
|
|
settings::setSetting(
|
|
settings::DoubleSetting::ROTATION_autoturnVestibularMotionRadius,
|
|
value );
|
|
if ( notify )
|
|
{
|
|
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
|