New Feature: Control rotation during virtual move

It's now possible to rotate the playspace by turning the controller during a virtual move playspace drag. The feature is activated via a checkbox on the playspace tab. If X Y Z axis lock checkboxes are also checked only rotation will be applied. Offsets will still accumulate as the user swings the playspace around because rotation is now centered at head. This feature is intended for use with manual redirected walking (allowing the user to virtually walk in a straight line while walking circles in physical space). This distance walked is reflected in the X,Z offsets.
This commit is contained in:
Kung-vr
2019-01-13 00:43:21 +09:00
parent fca227f9c7
commit 58ef2e02b4
3 changed files with 407 additions and 153 deletions
+84 -38
View File
@@ -47,11 +47,16 @@ MyStackViewPage {
} }
GridLayout { GridLayout {
columns: 5 columns: 6
MyText { MyText {
text: "X-Axis (Left/Right):" text: "X-Axis (Left/Right):"
Layout.preferredWidth: 500 Layout.preferredWidth: 340
}
MyText {
text: " "
Layout.preferredWidth: 40
} }
MyPushButton2 { MyPushButton2 {
@@ -59,7 +64,7 @@ MyStackViewPage {
Layout.preferredWidth: 40 Layout.preferredWidth: 40
text: "-" text: "-"
onClicked: { onClicked: {
MoveCenterTabController.modOffsetX(-0.5) MoveCenterTabController.modOffsetX(-0.1)
} }
} }
@@ -87,12 +92,11 @@ MyStackViewPage {
Layout.preferredWidth: 40 Layout.preferredWidth: 40
text: "+" text: "+"
onClicked: { onClicked: {
MoveCenterTabController.modOffsetX(0.5) MoveCenterTabController.modOffsetX(0.1)
} }
} }
MyToggleButton { MyToggleButton {
Layout.preferredWidth: 240
id: lockXToggle id: lockXToggle
text: "Lock X" text: "Lock X"
onCheckedChanged: { onCheckedChanged: {
@@ -102,14 +106,22 @@ MyStackViewPage {
MyText { MyText {
text: "Y-Axis (Down/Up):" text: "Y-Axis (Down/Up):"
Layout.preferredWidth: 380 Layout.preferredWidth: 340
}
MyPushButton2 {
Layout.preferredWidth: 40
text: "0"
onClicked: {
MoveCenterTabController.offsetY = 0
}
} }
MyPushButton2 { MyPushButton2 {
Layout.preferredWidth: 40 Layout.preferredWidth: 40
text: "-" text: "-"
onClicked: { onClicked: {
MoveCenterTabController.modOffsetY(-0.5) MoveCenterTabController.modOffsetY(-0.1)
} }
} }
@@ -136,13 +148,12 @@ MyStackViewPage {
Layout.preferredWidth: 40 Layout.preferredWidth: 40
text: "+" text: "+"
onClicked: { onClicked: {
MoveCenterTabController.modOffsetY(0.5) MoveCenterTabController.modOffsetY(0.1)
} }
} }
MyToggleButton { MyToggleButton {
Layout.preferredWidth: 240
id: lockYToggle id: lockYToggle
text: "Lock Y" text: "Lock Y"
onCheckedChanged: { onCheckedChanged: {
@@ -152,14 +163,19 @@ MyStackViewPage {
MyText { MyText {
text: "Z-Axis (Forth/Back):" text: "Z-Axis (Forth/Back):"
Layout.preferredWidth: 380 Layout.preferredWidth: 340
}
MyText {
text: " "
Layout.preferredWidth: 40
} }
MyPushButton2 { MyPushButton2 {
Layout.preferredWidth: 40 Layout.preferredWidth: 40
text: "-" text: "-"
onClicked: { onClicked: {
MoveCenterTabController.modOffsetZ(-0.5) MoveCenterTabController.modOffsetZ(-0.1)
} }
} }
@@ -186,13 +202,12 @@ MyStackViewPage {
Layout.preferredWidth: 40 Layout.preferredWidth: 40
text: "+" text: "+"
onClicked: { onClicked: {
MoveCenterTabController.modOffsetZ(0.5) MoveCenterTabController.modOffsetZ(0.1)
} }
} }
MyToggleButton { MyToggleButton {
Layout.preferredWidth: 240
id: lockZToggle id: lockZToggle
text: "Lock Z" text: "Lock Z"
onCheckedChanged: { onCheckedChanged: {
@@ -216,6 +231,7 @@ MyStackViewPage {
border.color: "#ffffff" border.color: "#ffffff"
radius: 8 radius: 8
} }
ColumnLayout { ColumnLayout {
anchors.fill: parent anchors.fill: parent
@@ -233,11 +249,11 @@ MyStackViewPage {
Layout.preferredWidth: 40 Layout.preferredWidth: 40
text: "-" text: "-"
onClicked: { onClicked: {
var val = MoveCenterTabController.rotation - 45 var val = MoveCenterTabController.tempRotation - 45
if (val < -180) { if (val < -180) {
val = val + 360; val = val + 360;
} }
MoveCenterTabController.rotation = val MoveCenterTabController.tempRotation = val
} }
} }
@@ -250,11 +266,11 @@ MyStackViewPage {
Layout.fillWidth: true Layout.fillWidth: true
onPositionChanged: { onPositionChanged: {
var val = this.from + ( this.position * (this.to - this.from)) var val = this.from + ( this.position * (this.to - this.from))
playspaceRotationText.text = Math.round(val) + "°" MoveCenterTabController.tempRotation = Math.round(val)
} }
onValueChanged: { onValueChanged: {
MoveCenterTabController.rotation = playspaceRotationSlider.value MoveCenterTabController.tempRotation = Math.round(playspaceRotationSlider.value)
playspaceRotationText.text = Math.round(playspaceRotationSlider.value) + "°" //playspaceRotationText.text = Math.round(playspaceRotationSlider.value) + "°"
} }
} }
@@ -263,11 +279,11 @@ MyStackViewPage {
Layout.preferredWidth: 40 Layout.preferredWidth: 40
text: "+" text: "+"
onClicked: { onClicked: {
var val = MoveCenterTabController.rotation + 45 var val = MoveCenterTabController.tempRotation + 45
if (val > 180) { if (val > 180) {
val = val -360; val = val -360;
} }
MoveCenterTabController.rotation = val MoveCenterTabController.tempRotation = val
} }
} }
@@ -282,10 +298,10 @@ MyStackViewPage {
var val = parseInt(input) var val = parseInt(input)
if (!isNaN(val)) { if (!isNaN(val)) {
val = val % 180 val = val % 180
MoveCenterTabController.rotation = val MoveCenterTabController.tempRotation = val
text = MoveCenterTabController.rotation + "°" text = MoveCenterTabController.tempRotation + "°"
} else { } else {
text = MoveCenterTabController.rotation + "°" text = MoveCenterTabController.tempRotation + "°"
} }
} }
} }
@@ -294,11 +310,23 @@ MyStackViewPage {
Layout.preferredWidth: 145 Layout.preferredWidth: 145
text:"Apply" text:"Apply"
onClicked: { onClicked: {
MoveCenterTabController.applyRotation() MoveCenterTabController.rotation = MoveCenterTabController.tempRotation
} }
}
}
MyToggleButton {
id: playspaceRotateHandToggle
text: "Virtual Move Shortcut Controls Rotation !ALPHA TEST!"
onCheckedChanged: {
MoveCenterTabController.rotateHand = this.checked
} }
} }
MyText {
text: "Note: Stats page / TurnSignal will ignore turning during virtual move rotation."
font.pointSize: 15.0
}
} }
} }
} }
@@ -318,6 +346,7 @@ MyStackViewPage {
} }
ColumnLayout { ColumnLayout {
RowLayout { RowLayout {
anchors.fill: parent
MyToggleButton { MyToggleButton {
id: moveShortcutLeft id: moveShortcutLeft
@@ -346,27 +375,37 @@ MyStackViewPage {
} }
} }
MyToggleButton { ColumnLayout {
id: playspaceAdjustChaperoneToggle RowLayout {
text: "Adjust Chaperone" anchors.fill: parent
onCheckedChanged: {
MoveCenterTabController.adjustChaperone = this.checked MyPushButton {
id: playspaceResetButton
Layout.preferredWidth: 250
text: "Reset"
onClicked: {
MoveCenterTabController.reset()
}
}
MyToggleButton {
id: playspaceAdjustChaperoneToggle
text: "Adjust Chaperone"
onCheckedChanged: {
MoveCenterTabController.adjustChaperone = this.checked
}
}
} }
} }
Item { Layout.fillHeight: true; Layout.fillWidth: true} Item { Layout.fillHeight: true; Layout.fillWidth: true}
MyPushButton {
id: playspaceResetButton
Layout.preferredWidth: 250
text: "Reset"
onClicked: {
MoveCenterTabController.reset()
}
}
Component.onCompleted: { Component.onCompleted: {
playspaceAdjustChaperoneToggle.checked = MoveCenterTabController.adjustChaperone playspaceAdjustChaperoneToggle.checked = MoveCenterTabController.adjustChaperone
playspaceRotateHandToggle.checked = MoveCenterTabController.rotateHand
playSpaceMoveXText.text = MoveCenterTabController.offsetX.toFixed(2) playSpaceMoveXText.text = MoveCenterTabController.offsetX.toFixed(2)
playSpaceMoveYText.text = MoveCenterTabController.offsetY.toFixed(2) playSpaceMoveYText.text = MoveCenterTabController.offsetY.toFixed(2)
playSpaceMoveZText.text = MoveCenterTabController.offsetZ.toFixed(2) playSpaceMoveZText.text = MoveCenterTabController.offsetZ.toFixed(2)
@@ -409,9 +448,16 @@ MyStackViewPage {
onRotationChanged: { onRotationChanged: {
playspaceRotationSlider.value = MoveCenterTabController.rotation playspaceRotationSlider.value = MoveCenterTabController.rotation
} }
onTempRotationChanged: {
playspaceRotationSlider.value = MoveCenterTabController.tempRotation
playspaceRotationText.text = MoveCenterTabController.tempRotation + "°"
}
onAdjustChaperoneChanged: { onAdjustChaperoneChanged: {
playspaceAdjustChaperoneToggle.checked = MoveCenterTabController.adjustChaperone playspaceAdjustChaperoneToggle.checked = MoveCenterTabController.adjustChaperone
} }
onRotateHandChanged: {
playspaceRotateHandToggle.checked = MoveCenterTabController.rotateHand
}
onMoveShortcutRightChanged: { onMoveShortcutRightChanged: {
moveShortcutRight.checked = MoveCenterTabController.moveShortcutRight moveShortcutRight.checked = MoveCenterTabController.moveShortcutRight
} }
+306 -113
View File
@@ -1,17 +1,18 @@
#include "MoveCenterTabController.h" #include "MoveCenterTabController.h"
#include <QQuickWindow> #include <QQuickWindow>
#include "../overlaycontroller.h" #include "../overlaycontroller.h"
#include "../utils/Matrix.h"
void rotateCoordinates( float coordinates[3], float angle ) void rotateCoordinates( double coordinates[3], double angle )
{ {
if ( angle == 0 ) if ( angle == 0 )
{ {
return; return;
} }
float s = sin( angle ); double s = sin( angle );
float c = cos( angle ); double c = cos( angle );
float newX = coordinates[0] * c - coordinates[2] * s; double newX = coordinates[0] * c - coordinates[2] * s;
float newZ = coordinates[0] * s + coordinates[2] * c; double newZ = coordinates[0] * s + coordinates[2] * c;
coordinates[0] = newX; coordinates[0] = newX;
coordinates[2] = newZ; coordinates[2] = newZ;
} }
@@ -33,6 +34,11 @@ void MoveCenterTabController::initStage1()
{ {
m_adjustChaperone = value.toBool(); m_adjustChaperone = value.toBool();
} }
value = settings->value( "rotateHand", m_rotateHand );
if ( value.isValid() && !value.isNull() )
{
m_rotateHand = value.toBool();
}
value = settings->value( "moveShortcutRight", m_moveShortcutRightEnabled ); value = settings->value( "moveShortcutRight", m_moveShortcutRightEnabled );
if ( value.isValid() && !value.isNull() ) if ( value.isValid() && !value.isNull() )
{ {
@@ -76,7 +82,7 @@ void MoveCenterTabController::initStage2( OverlayController* var_parent,
int MoveCenterTabController::trackingUniverse() const int MoveCenterTabController::trackingUniverse() const
{ {
return ( int ) m_trackingUniverse; return static_cast<int>( m_trackingUniverse );
} }
void MoveCenterTabController::setTrackingUniverse( int value, bool notify ) void MoveCenterTabController::setTrackingUniverse( int value, bool notify )
@@ -136,31 +142,111 @@ int MoveCenterTabController::rotation() const
return m_rotation; return m_rotation;
} }
int MoveCenterTabController::tempRotation() const
{
return m_tempRotation;
}
void MoveCenterTabController::setRotation( int value, bool notify ) void MoveCenterTabController::setRotation( int value, bool notify )
{ {
if ( m_rotation != value ) if ( m_rotation != value )
{ {
// float angle = (value - m_rotation) * 2 * M_PI / 360.0; double angle = ( value - m_rotation ) * 2 * M_PI / 360.0;
// parent->RotateUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse,
// angle, m_adjustChaperone); // Revert now because we don't commit in RotateUniverseCenter and
// AddOffsetToUniverseCenter. We do this so rotation and offset can
// happen in one go, avoiding positional judder.
vr::VRChaperoneSetup()->RevertWorkingCopy();
// Get hmd pose matrix.
vr::TrackedDevicePose_t
devicePosesForRot[vr::k_unMaxTrackedDeviceCount];
vr::VRSystem()->GetDeviceToAbsoluteTrackingPose(
vr::TrackingUniverseStanding,
0.0f,
devicePosesForRot,
vr::k_unMaxTrackedDeviceCount );
vr::HmdMatrix34_t oldHmdPos
= devicePosesForRot[0].mDeviceToAbsoluteTracking;
// Set up xyz coordinate values from pose matrix.
double oldHmdXyz[3]
= { oldHmdPos.m[0][3], oldHmdPos.m[1][3], oldHmdPos.m[2][3] };
double newHmdXyz[3]
= { oldHmdPos.m[0][3], oldHmdPos.m[1][3], oldHmdPos.m[2][3] };
// Convert oldHmdXyz into un-rotated coordinates.
double oldAngle = -m_rotation * 2 * M_PI / 360.0;
rotateCoordinates( oldHmdXyz, oldAngle );
// Set newHmdXyz to have additional rotation from incoming angle change.
rotateCoordinates( newHmdXyz, 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] };
// Rotate the tracking univese center without committing.
parent->RotateUniverseCenter(
vr::TrackingUniverseOrigin( m_trackingUniverse ),
static_cast<float>( angle ),
m_adjustChaperone,
false );
m_rotation = value; m_rotation = value;
if ( notify ) if ( notify )
{ {
emit rotationChanged( m_rotation ); emit rotationChanged( m_rotation );
} }
// Get rotated offset to apply to universe center.
// We use rotated coordinates here because we have already applied
// RotateUniverseCenter. This will be the final offset ready to apply,
// so it must match the current universe axis rotation.
double finalAngle = m_rotation * 2 * M_PI / 360.0;
double finalHmdRotDiff[3] = { hmdRotDiff[0], 0, hmdRotDiff[2] };
rotateCoordinates( finalHmdRotDiff, finalAngle );
// We're done with calculations now so we can down-cast the double
// values to float for compatilibilty with openvr format
float finalHmdRotDiffFloat[3]
= { static_cast<float>( finalHmdRotDiff[0] ),
static_cast<float>( finalHmdRotDiff[1] ),
static_cast<float>( finalHmdRotDiff[2] ) };
// Apply the offset (in rotated coordinates) without commit.
// We still can't commit yet because it would call
// vr::VRChaperoneSetup()->RevertWorkingCopy() and we'd lose our
// uncommitted RotateUniverseCenter.
parent->AddOffsetToUniverseCenter(
vr::TrackingUniverseOrigin( m_trackingUniverse ),
finalHmdRotDiffFloat,
m_adjustChaperone,
false );
// Commit here because we didn't in RotateUniverseCenter and
// AddOffsetToUniverseCenter to combine into one go.
vr::VRChaperoneSetup()->CommitWorkingCopy(
vr::EChaperoneConfigFile_Live );
// Update UI offsets.
m_offsetX += hmdRotDiff[0];
m_offsetZ += hmdRotDiff[2];
if ( notify )
{
emit offsetXChanged( m_offsetX );
emit offsetZChanged( m_offsetZ );
}
} }
} }
void MoveCenterTabController::applyRotation() void MoveCenterTabController::setTempRotation( int value, bool notify )
{ {
if ( m_rotation != m_rotationOld ) m_tempRotation = value;
if ( notify )
{ {
float angle = ( m_rotationOld - m_rotation ) * 2 * M_PI / 360.0; emit tempRotationChanged( m_tempRotation );
parent->RotateUniverseCenter(
( vr::TrackingUniverseOrigin ) m_trackingUniverse,
angle,
m_adjustChaperone );
m_rotationOld = m_rotation;
} }
} }
@@ -176,14 +262,21 @@ void MoveCenterTabController::setAdjustChaperone( bool value, bool notify )
m_adjustChaperone = value; m_adjustChaperone = value;
if ( m_trackingUniverse == vr::TrackingUniverseStanding ) if ( m_trackingUniverse == vr::TrackingUniverseStanding )
{ {
auto angle = m_rotation * 2 * M_PI / 360.0; double angle = m_rotation * 2 * M_PI / 360.0;
float offsetdir = m_adjustChaperone ? -1.0 : 1.0; double offsetdir = m_adjustChaperone ? -1.0 : 1.0;
float offset[3] = { offsetdir * m_offsetX, double offset[3] = { offsetdir * m_offsetX,
offsetdir * m_offsetY, offsetdir * m_offsetY,
offsetdir * m_offsetZ }; offsetdir * m_offsetZ };
rotateCoordinates( offset, angle ); rotateCoordinates( offset, angle );
parent->AddOffsetToCollisionBounds( offset ); // We're done with calculations so down-cast to float for
// compatibility with openvr format
float offsetFloat[3] = { static_cast<float>( offset[0] ),
static_cast<float>( offset[1] ),
static_cast<float>( offset[2] ) };
parent->AddOffsetToCollisionBounds( offsetFloat );
} }
auto settings = OverlayController::appSettings(); auto settings = OverlayController::appSettings();
settings->beginGroup( "playspaceSettings" ); settings->beginGroup( "playspaceSettings" );
@@ -197,6 +290,25 @@ void MoveCenterTabController::setAdjustChaperone( bool value, bool notify )
} }
} }
bool MoveCenterTabController::rotateHand() const
{
return m_rotateHand;
}
void MoveCenterTabController::setRotateHand( bool value, bool notify )
{
m_rotateHand = value;
auto settings = OverlayController::appSettings();
settings->beginGroup( "playspaceSettings" );
settings->setValue( "rotateHand", m_rotateHand );
settings->endGroup();
settings->sync();
if ( notify )
{
emit rotateHandChanged( m_rotateHand );
}
}
bool MoveCenterTabController::moveShortcutRight() const bool MoveCenterTabController::moveShortcutRight() const
{ {
return m_moveShortcutRightEnabled; return m_moveShortcutRightEnabled;
@@ -316,12 +428,15 @@ void MoveCenterTabController::modOffsetX( float value, bool notify )
// TODO ? possible issue with locking position this way // TODO ? possible issue with locking position this way
if ( !m_lockXToggle ) if ( !m_lockXToggle )
{ {
auto angle = m_rotation * 2 * M_PI / 360.0; double angle = m_rotation * 2 * M_PI / 360.0;
float offset[3] = { value, 0, 0 }; double offset[3] = { value, 0, 0 };
rotateCoordinates( offset, angle ); rotateCoordinates( offset, angle );
float offsetFloat[3] = { static_cast<float>( offset[0] ),
static_cast<float>( offset[1] ),
static_cast<float>( offset[2] ) };
parent->AddOffsetToUniverseCenter( parent->AddOffsetToUniverseCenter(
( vr::TrackingUniverseOrigin ) m_trackingUniverse, vr::TrackingUniverseOrigin( m_trackingUniverse ),
offset, offsetFloat,
m_adjustChaperone ); m_adjustChaperone );
m_offsetX += value; m_offsetX += value;
if ( notify ) if ( notify )
@@ -336,7 +451,7 @@ void MoveCenterTabController::modOffsetY( float value, bool notify )
if ( !m_lockYToggle ) if ( !m_lockYToggle )
{ {
parent->AddOffsetToUniverseCenter( parent->AddOffsetToUniverseCenter(
( vr::TrackingUniverseOrigin ) m_trackingUniverse, vr::TrackingUniverseOrigin( m_trackingUniverse ),
1, 1,
value, value,
m_adjustChaperone ); m_adjustChaperone );
@@ -352,12 +467,15 @@ void MoveCenterTabController::modOffsetZ( float value, bool notify )
{ {
if ( !m_lockZToggle ) if ( !m_lockZToggle )
{ {
auto angle = m_rotation * 2 * M_PI / 360.0; double angle = m_rotation * 2 * M_PI / 360.0;
float offset[3] = { 0, 0, value }; double offset[3] = { 0, 0, value };
rotateCoordinates( offset, angle ); rotateCoordinates( offset, angle );
float offsetFloat[3] = { static_cast<float>( offset[0] ),
static_cast<float>( offset[1] ),
static_cast<float>( offset[2] ) };
parent->AddOffsetToUniverseCenter( parent->AddOffsetToUniverseCenter(
( vr::TrackingUniverseOrigin ) m_trackingUniverse, vr::TrackingUniverseOrigin( m_trackingUniverse ),
offset, offsetFloat,
m_adjustChaperone ); m_adjustChaperone );
m_offsetZ += value; m_offsetZ += value;
if ( notify ) if ( notify )
@@ -371,13 +489,13 @@ void MoveCenterTabController::reset()
{ {
vr::VRChaperoneSetup()->RevertWorkingCopy(); vr::VRChaperoneSetup()->RevertWorkingCopy();
parent->RotateUniverseCenter( parent->RotateUniverseCenter(
( vr::TrackingUniverseOrigin ) m_trackingUniverse, vr::TrackingUniverseOrigin( m_trackingUniverse ),
-m_rotation * 2 * M_PI / 360.0, -m_rotation * 2 * M_PI / 360.0,
m_adjustChaperone, m_adjustChaperone,
false ); false );
float offset[3] = { -m_offsetX, -m_offsetY, -m_offsetZ }; float offset[3] = { -m_offsetX, -m_offsetY, -m_offsetZ };
parent->AddOffsetToUniverseCenter( parent->AddOffsetToUniverseCenter(
( vr::TrackingUniverseOrigin ) m_trackingUniverse, vr::TrackingUniverseOrigin( m_trackingUniverse ),
offset, offset,
m_adjustChaperone, m_adjustChaperone,
false ); false );
@@ -486,104 +604,179 @@ void MoveCenterTabController::eventLoopTick(
vr::ETrackingUniverseOrigin universe, vr::ETrackingUniverseOrigin universe,
vr::TrackedDevicePose_t* devicePoses ) vr::TrackedDevicePose_t* devicePoses )
{ {
if ( settingsUpdateCounter >= 50 ) if ( settingsUpdateCounter >= 100 )
{ {
setTrackingUniverse( ( int ) universe ); setTrackingUniverse( int( universe ) );
settingsUpdateCounter = 0; settingsUpdateCounter = 0;
} }
else else
{ {
settingsUpdateCounter++; settingsUpdateCounter++;
auto oldMoveHand = m_activeMoveController; }
auto newMoveHand = getMoveShortcutHand(); auto oldMoveHand = m_activeMoveController;
if ( newMoveHand == vr::TrackedControllerRole_Invalid ) auto newMoveHand = getMoveShortcutHand();
if ( newMoveHand == vr::TrackedControllerRole_Invalid )
{
emit offsetXChanged( m_offsetX );
emit offsetYChanged( m_offsetY );
emit offsetZChanged( m_offsetZ );
// Set lastHandYaw to placeholder value for invalid (-10.0) when we
// release move shortcut.
if ( m_rotateHand )
{
lastHandYaw = -10.0;
}
return;
}
auto handId
= vr::VRSystem()->GetTrackedDeviceIndexForControllerRole( newMoveHand );
if ( newMoveHand == vr::TrackedControllerRole_Invalid
|| handId == vr::k_unTrackedDeviceIndexInvalid
|| handId >= vr::k_unMaxTrackedDeviceCount )
{
if ( oldMoveHand != vr::TrackedControllerRole_Invalid )
{ {
emit offsetXChanged( m_offsetX ); emit offsetXChanged( m_offsetX );
emit offsetYChanged( m_offsetY ); emit offsetYChanged( m_offsetY );
emit offsetZChanged( m_offsetZ ); emit offsetZChanged( m_offsetZ );
return;
}
auto handId = vr::VRSystem()->GetTrackedDeviceIndexForControllerRole(
newMoveHand );
if ( newMoveHand == vr::TrackedControllerRole_Invalid
|| handId == vr::k_unTrackedDeviceIndexInvalid
|| handId >= vr::k_unMaxTrackedDeviceCount )
{
if ( oldMoveHand != vr::TrackedControllerRole_Invalid )
{
emit offsetXChanged( m_offsetX );
emit offsetYChanged( m_offsetY );
emit offsetZChanged( m_offsetZ );
}
return;
}
vr::TrackedDevicePose_t* pose = devicePoses + handId;
if ( !pose->bPoseIsValid || !pose->bDeviceIsConnected
|| pose->eTrackingResult != vr::TrackingResult_Running_OK )
{
return;
}
float relativeControllerPosition[]
= { pose->mDeviceToAbsoluteTracking.m[0][3],
pose->mDeviceToAbsoluteTracking.m[1][3],
pose->mDeviceToAbsoluteTracking.m[2][3] };
auto angle = m_rotation * 2 * M_PI / 360.0; if ( m_rotateHand )
rotateCoordinates( relativeControllerPosition, -angle ); {
float absoluteControllerPosition[] = { lastHandYaw = -10.0;
relativeControllerPosition[0] + m_offsetX, }
relativeControllerPosition[1] + m_offsetY, }
relativeControllerPosition[2] + m_offsetZ, return;
}
vr::TrackedDevicePose_t* pose = devicePoses + handId;
if ( !pose->bPoseIsValid || !pose->bDeviceIsConnected
|| pose->eTrackingResult != vr::TrackingResult_Running_OK )
{
return;
}
double relativeControllerPosition[]
= { pose->mDeviceToAbsoluteTracking.m[0][3],
pose->mDeviceToAbsoluteTracking.m[1][3],
pose->mDeviceToAbsoluteTracking.m[2][3] };
double angle = m_rotation * 2 * M_PI / 360.0;
rotateCoordinates( relativeControllerPosition, -angle );
float absoluteControllerPosition[] = {
static_cast<float>( relativeControllerPosition[0] ) + m_offsetX,
static_cast<float>( relativeControllerPosition[1] ) + m_offsetY,
static_cast<float>( relativeControllerPosition[2] ) + m_offsetZ,
};
// Get hand's rotation.
if ( m_rotateHand )
{
// handMatrix is in rotated coordinates.
vr::HmdMatrix34_t handMatrix = pose->mDeviceToAbsoluteTracking;
// We need un-rotated coordinates for valid comparison between
// handYaw and lastHandYaw. Set up (un)rotation matrix.
vr::HmdMatrix34_t handMatrixRotMat;
vr::HmdMatrix34_t handMatrixAbsolute;
utils::initRotationMatrix(
handMatrixRotMat, 1, static_cast<float>( angle ) );
// Get handMatrixAbsolute in un-rotated coordinates.
utils::matMul33( handMatrixAbsolute, handMatrixRotMat, handMatrix );
// Convert pose matrix to yaw.
handYaw = std::atan2( handMatrixAbsolute.m[0][2],
handMatrixAbsolute.m[2][2] );
}
if ( oldMoveHand == newMoveHand )
{
double diff[3] = {
absoluteControllerPosition[0] - m_lastControllerPosition[0],
absoluteControllerPosition[1] - m_lastControllerPosition[1],
absoluteControllerPosition[2] - m_lastControllerPosition[2],
}; };
if ( oldMoveHand == newMoveHand ) // offset is un-rotated coordinates
// prevents UI from updating if axis movement is locked
if ( !m_lockXToggle )
{ {
float diff[3] = { m_offsetX += diff[0];
absoluteControllerPosition[0] - m_lastControllerPosition[0], }
absoluteControllerPosition[1] - m_lastControllerPosition[1], if ( !m_lockYToggle )
absoluteControllerPosition[2] - m_lastControllerPosition[2], {
}; m_offsetY += diff[1];
}
if ( !m_lockZToggle )
{
m_offsetZ += diff[2];
}
// offset is un-rotated coordinates rotateCoordinates( diff, angle );
// prevents UI from updating if axis movement is locked // Done calculating rotation so we down-cast double to float for openvr
if ( !m_lockXToggle ) // format
{ float diffFloat[3] = { static_cast<float>( diff[0] ),
m_offsetX += diff[0]; static_cast<float>( diff[1] ),
} static_cast<float>( diff[2] ) };
if ( !m_lockYToggle ) // If locked removes movement
{ if ( m_lockXToggle )
m_offsetY += diff[1]; {
} diffFloat[0] = 0;
if ( !m_lockZToggle ) }
{ if ( m_lockYToggle )
m_offsetZ += diff[2]; {
} diffFloat[1] = 0;
}
rotateCoordinates( diff, angle ); if ( m_lockZToggle )
// If locked removes movement {
if ( m_lockXToggle ) diffFloat[2] = 0;
{ }
diff[0] = 0;
}
if ( m_lockYToggle )
{
diff[1] = 0;
}
if ( m_lockZToggle )
{
diff[2] = 0;
}
// Check if diffFloat is anything before comitting.
if ( diffFloat[0] != 0 || diffFloat[1] != 0 || diffFloat[2] != 0 )
{
parent->AddOffsetToUniverseCenter( parent->AddOffsetToUniverseCenter(
( vr::TrackingUniverseOrigin ) m_trackingUniverse, vr::TrackingUniverseOrigin( m_trackingUniverse ),
diff, diffFloat,
m_adjustChaperone ); m_adjustChaperone );
} }
m_lastControllerPosition[0] = absoluteControllerPosition[0];
m_lastControllerPosition[1] = absoluteControllerPosition[1];
m_lastControllerPosition[2] = absoluteControllerPosition[2];
}
}
// Get rotation change of hand.
if ( m_rotateHand )
{
// Checking if set to -10.0 placeholder for invalid hand.
if ( lastHandYaw < -9.0 )
{
lastHandYaw = handYaw;
}
else
{
double handYawDiff = handYaw - lastHandYaw;
// TODO: Increase angular granularity beyond 1 degree.
int newRotationAngleDeg = static_cast<int>(
round( handYawDiff * 180.0 / M_PI ) + m_rotation );
// Keep angle within -180 ~ 180
if ( newRotationAngleDeg > 180 )
{
newRotationAngleDeg -= 360;
}
else if ( newRotationAngleDeg < -180 )
{
newRotationAngleDeg += 360;
}
setRotation( newRotationAngleDeg );
}
}
}
m_lastControllerPosition[0] = absoluteControllerPosition[0];
m_lastControllerPosition[1] = absoluteControllerPosition[1];
m_lastControllerPosition[2] = absoluteControllerPosition[2];
lastHandYaw = handYaw;
}
} // namespace advsettings } // namespace advsettings
+17 -2
View File
@@ -25,6 +25,8 @@ class MoveCenterTabController : public QObject
float offsetZ READ offsetZ WRITE setOffsetZ NOTIFY offsetZChanged ) float offsetZ READ offsetZ WRITE setOffsetZ NOTIFY offsetZChanged )
Q_PROPERTY( Q_PROPERTY(
int rotation READ rotation WRITE setRotation NOTIFY rotationChanged ) int rotation READ rotation WRITE setRotation NOTIFY rotationChanged )
Q_PROPERTY( int tempRotation READ tempRotation WRITE setTempRotation NOTIFY
tempRotationChanged )
Q_PROPERTY( bool adjustChaperone READ adjustChaperone WRITE Q_PROPERTY( bool adjustChaperone READ adjustChaperone WRITE
setAdjustChaperone NOTIFY adjustChaperoneChanged ) setAdjustChaperone NOTIFY adjustChaperoneChanged )
Q_PROPERTY( bool moveShortcutRight READ moveShortcutRight WRITE Q_PROPERTY( bool moveShortcutRight READ moveShortcutRight WRITE
@@ -39,6 +41,8 @@ class MoveCenterTabController : public QObject
requireLockYChanged ) requireLockYChanged )
Q_PROPERTY( bool lockZToggle READ lockZToggle WRITE setLockZ NOTIFY Q_PROPERTY( bool lockZToggle READ lockZToggle WRITE setLockZ NOTIFY
requireLockZChanged ) requireLockZChanged )
Q_PROPERTY( bool rotateHand READ rotateHand WRITE setRotateHand NOTIFY
rotateHandChanged )
private: private:
OverlayController* parent; OverlayController* parent;
@@ -49,8 +53,9 @@ private:
float m_offsetY = 0.0f; float m_offsetY = 0.0f;
float m_offsetZ = 0.0f; float m_offsetZ = 0.0f;
int m_rotation = 0; int m_rotation = 0;
int m_rotationOld = 0; int m_tempRotation = 0;
bool m_adjustChaperone = true; bool m_adjustChaperone = true;
bool m_rotateHand = false;
bool m_moveShortcutRightPressed = false; bool m_moveShortcutRightPressed = false;
bool m_moveShortcutLeftPressed = false; bool m_moveShortcutLeftPressed = false;
vr::ETrackedControllerRole m_activeMoveController; vr::ETrackedControllerRole m_activeMoveController;
@@ -62,6 +67,9 @@ private:
bool m_lockYToggle = false; bool m_lockYToggle = false;
bool m_lockZToggle = false; bool m_lockZToggle = false;
std::chrono::system_clock::time_point lastMoveButtonClick[2]; std::chrono::system_clock::time_point lastMoveButtonClick[2];
// Set to -10.0 when last hand is invalid.
double lastHandYaw = -10.0;
double handYaw;
unsigned settingsUpdateCounter = 0; unsigned settingsUpdateCounter = 0;
@@ -78,7 +86,9 @@ public:
float offsetY() const; float offsetY() const;
float offsetZ() const; float offsetZ() const;
int rotation() const; int rotation() const;
int tempRotation() const;
bool adjustChaperone() const; bool adjustChaperone() const;
bool rotateHand() const;
bool moveShortcutRight() const; bool moveShortcutRight() const;
bool moveShortcutLeft() const; bool moveShortcutLeft() const;
bool requireDoubleClick() const; bool requireDoubleClick() const;
@@ -96,8 +106,12 @@ public slots:
void setRotation( int value, bool notify = true ); void setRotation( int value, bool notify = true );
void setTempRotation( int value, bool notify = true );
void setAdjustChaperone( bool value, bool notify = true ); void setAdjustChaperone( bool value, bool notify = true );
void setRotateHand( bool value, bool notify = true );
void setMoveShortcutRight( bool value, bool notify = true ); void setMoveShortcutRight( bool value, bool notify = true );
void setMoveShortcutLeft( bool value, bool notify = true ); void setMoveShortcutLeft( bool value, bool notify = true );
void setRequireDoubleClick( bool value, bool notify = true ); void setRequireDoubleClick( bool value, bool notify = true );
@@ -110,7 +124,6 @@ public slots:
void setLockY( bool value, bool notify = true ); void setLockY( bool value, bool notify = true );
void setLockZ( bool value, bool notify = true ); void setLockZ( bool value, bool notify = true );
void applyRotation();
void reset(); void reset();
signals: signals:
@@ -119,7 +132,9 @@ signals:
void offsetYChanged( float value ); void offsetYChanged( float value );
void offsetZChanged( float value ); void offsetZChanged( float value );
void rotationChanged( int value ); void rotationChanged( int value );
void tempRotationChanged( int value );
void adjustChaperoneChanged( bool value ); void adjustChaperoneChanged( bool value );
void rotateHandChanged( bool value );
void moveShortcutRightChanged( bool value ); void moveShortcutRightChanged( bool value );
void moveShortcutLeftChanged( bool value ); void moveShortcutLeftChanged( bool value );
void requireDoubleClickChanged( bool value ); void requireDoubleClickChanged( bool value );