Updated Readme and added files missing from last commit.

This commit is contained in:
2016-09-16 21:52:34 +02:00
parent b8cac9fb69
commit af956a8702
5 changed files with 1097 additions and 452 deletions
+25 -1
View File
@@ -6,25 +6,49 @@
Adds an overlay to the OpenVR dashboard that allows access to advanced settings. Adds an overlay to the OpenVR dashboard that allows access to advanced settings.
# Features # Features
## - SteamVR Settings Tab:
- **Supersampling**: Allows to change SteamVR's supersampling setting (Requires restart).
- **Allow Reprojection**: Enable/disable reprojection (Requires restart).
- **Force Reprojection**: Enable/disable forced reprojection (Requires restart).
- **Restart SteamVR**: Restart SteamVR.
## - Chaperone Settings Tab: ## - Chaperone Settings Tab:
- **Center Marker**: Displays a marker that represents the center of the playspace. - **Center Marker**: Displays a marker that represents the center of the playspace.
- **Play Space Maker**: Displays the outlines of the rectangle representing the playspace. - **Play Space Maker**: Displays the outlines of the rectangle representing the playspace.
- **Force Bounds**: Force chaperone bounds always on. - **Force Bounds**: Force chaperone bounds always on.
- **Flip Orientation**: Flips the orientation of the play space.
- **Fade Distance**: Allows to configure the distance at which the chaperone bounds are shown. When set to 0 chaperone bounds are completely invisible. - **Fade Distance**: Allows to configure the distance at which the chaperone bounds are shown. When set to 0 chaperone bounds are completely invisible.
- **Chaperone Bounds Visibility**: Allows to configure the visibility of the chaperone bounds. Unlike the slider in the chaperone settings, this one is not capped at 30%. When set to 0 chaperone bounds are completely invisible. - **Chaperone Bounds Visibility**: Allows to configure the visibility of the chaperone bounds. Unlike the slider in the chaperone settings, this one is not capped at 30%. When set to 0 chaperone bounds are completely invisible.
- **Reload from Disk**: Reloads the chaperone bounds from disk.
## - Move Center Tab: ## - Move Center Tab:
Allows to temporarily move the center of the playspace. This allows to reach interaction elements that are just inside our real-world walls or otherwise inaccessible (e.g. when your playspace is smaller than the recommended one). Can also be used to discover the terrors that lie outside of the intended playspace (ever wondered what's behind the door in The Lab?).
Allows to temporarily move and rotate the center of the playspace. This allows to reach interaction elements that are just inside our real-world walls or otherwise inaccessible (e.g. when your playspace is smaller than the recommended one). Can also be used to discover the terrors that lie outside of the intended playspace (ever wondered what's behind the door in The Lab?).
The chaperone bounds stay in place when the playspace is moved or rotated (I don't want anyone to get hurt. Unfortunately this does not work when moving up/down).
## - Fix Floor Tab: ## - Fix Floor Tab:
Allows you to fix the height of your floor. Just place one controller on your floor and press the button. Allows you to fix the height of your floor. Just place one controller on your floor and press the button.
## - Statistics Tab:
- **HMD Distance Moved**: Shows the distance the headset has moved on the xz-plane.
- **HMD Rotations**: Shows the number of rotations around the y-axis (Useful for untangling the cord).
- **Left Controller Max Speed**: Shows the max speed of the left controller.
- **Right Controller Max Speed**: Shows the max speed of the right controller.
- **Dropped Frames**: Number of frames dropped in the currently running application.
- **Reprojected Frames**: Number of frames reprojected in the currently running application.
- **Reprojected Frames**: Number of times the currently running application timed out.
## - Settings Tab: ## - Settings Tab:
- **Auto Start Toggle:** Allows you to enable/disable auto start. - **Auto Start Toggle:** Allows you to enable/disable auto start.
# Notes: # Notes:
- The center marker and the play space marker are provided by the chaperone subsystem, and therefore they will have the same color and visibility settings as the chaperone bounds. - The center marker and the play space marker are provided by the chaperone subsystem, and therefore they will have the same color and visibility settings as the chaperone bounds.
# Usage # Usage
+15 -3
View File
@@ -14,11 +14,23 @@ TEMPLATE = app
SOURCES += src/main.cpp\ SOURCES += src/main.cpp\
src/overlaywidget.cpp \ src/overlaywidget.cpp \
src/overlaycontroller.cpp src/overlaycontroller.cpp \
src/tabcontrollers/ChaperoneTabController.cpp \
src/tabcontrollers/FixFloorTabController.cpp \
src/tabcontrollers/MoveCenterTabController.cpp \
src/tabcontrollers/SettingsTabController.cpp \
src/tabcontrollers/StatisticsTabController.cpp \
src/tabcontrollers/SteamVRTabController.cpp
HEADERS += src/overlaywidget.h \ HEADERS += src/overlaywidget.h \
src/overlaycontroller.h src/overlaycontroller.h \
src/logging.h src/logging.h \
src/tabcontrollers/ChaperoneTabController.h \
src/tabcontrollers/FixFloorTabController.h \
src/tabcontrollers/MoveCenterTabController.h \
src/tabcontrollers/SettingsTabController.h \
src/tabcontrollers/StatisticsTabController.h \
src/tabcontrollers/SteamVRTabController.h
FORMS += ui/overlaywidget.ui FORMS += ui/overlaywidget.ui
+154 -321
View File
@@ -12,8 +12,11 @@
#include <QtWidgets/QGraphicsEllipseItem> #include <QtWidgets/QGraphicsEllipseItem>
#include <QOpenGLExtraFunctions> #include <QOpenGLExtraFunctions>
#include <QCursor> #include <QCursor>
#include <QProcess>
#include <QMessageBox>
#include <exception> #include <exception>
#include <iostream> #include <iostream>
#include <cmath>
#include <openvr.h> #include <openvr.h>
#include "logging.h" #include "logging.h"
@@ -65,15 +68,20 @@ void OverlayController::SetWidget(OverlayWidget *pWidget, const std::string& nam
pWidget->move(0, 0); pWidget->move(0, 0);
m_pScene->addWidget(pWidget); m_pScene->addWidget(pWidget);
m_pWidget = pWidget; m_pWidget = pWidget;
pWidget->ui->VersionLabel->setText(OverlayController::applicationVersionString);
if (!vr::VROverlay()) { if (!vr::VROverlay()) {
QMessageBox::critical(nullptr, "OpenVR Advanced Settings Overlay", "Is OpenVR running?");
throw std::runtime_error(std::string("No Overlay interface")); throw std::runtime_error(std::string("No Overlay interface"));
} }
vr::VROverlayError overlayError = vr::VROverlay()->CreateDashboardOverlay(key.c_str(), name.c_str(), &m_ulOverlayHandle, &m_ulOverlayThumbnailHandle); vr::VROverlayError overlayError = vr::VROverlay()->CreateDashboardOverlay(key.c_str(), name.c_str(), &m_ulOverlayHandle, &m_ulOverlayThumbnailHandle);
if (overlayError != vr::VROverlayError_None) { if (overlayError != vr::VROverlayError_None) {
if (overlayError == vr::VROverlayError_KeyInUse) {
QMessageBox::critical(nullptr, "OpenVR Advanced Settings Overlay", "Another instance is already running.");
}
throw std::runtime_error(std::string("Failed to create Overlay: " + std::string(vr::VROverlay()->GetOverlayErrorNameFromEnum(overlayError)))); throw std::runtime_error(std::string("Failed to create Overlay: " + std::string(vr::VROverlay()->GetOverlayErrorNameFromEnum(overlayError))));
} }
vr::VROverlay()->SetOverlayWidthInMeters(m_ulOverlayHandle, 2.0f); vr::VROverlay()->SetOverlayWidthInMeters(m_ulOverlayHandle, 2.5f);
vr::VROverlay()->SetOverlayInputMethod(m_ulOverlayHandle, vr::VROverlayInputMethod_Mouse); vr::VROverlay()->SetOverlayInputMethod(m_ulOverlayHandle, vr::VROverlayInputMethod_Mouse);
std::string thumbIconPath = QApplication::applicationDirPath().toStdString() + "\\res\\thumbicon.png"; std::string thumbIconPath = QApplication::applicationDirPath().toStdString() + "\\res\\thumbicon.png";
if (QFile::exists(QString::fromStdString(thumbIconPath))) { if (QFile::exists(QString::fromStdString(thumbIconPath))) {
@@ -95,9 +103,11 @@ void OverlayController::SetWidget(OverlayWidget *pWidget, const std::string& nam
}; };
vr::VROverlay()->SetOverlayMouseScale(m_ulOverlayHandle, &vecWindowSize); vr::VROverlay()->SetOverlayMouseScale(m_ulOverlayHandle, &vecWindowSize);
steamVRTabController.init(this, pWidget);
chaperoneTabController.init(this, pWidget); chaperoneTabController.init(this, pWidget);
moveCenterTabController.init(this, pWidget); moveCenterTabController.init(this, pWidget);
fixFloorTabController.init(this, pWidget); fixFloorTabController.init(this, pWidget);
statisticsTabController.init(this, pWidget);
settingsTabController.init(this, pWidget); settingsTabController.init(this, pWidget);
} }
@@ -144,7 +154,11 @@ void OverlayController::OnTimeoutPumpEvents() {
} }
*/ */
fixFloorTabController.eventLoopTick(); vr::TrackedDevicePose_t devicePoses[vr::k_unMaxTrackedDeviceCount];
vr::VRSystem()->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseStanding, 0.0f, devicePoses, vr::k_unMaxTrackedDeviceCount);
fixFloorTabController.eventLoopTick(devicePoses);
statisticsTabController.eventLoopTick(devicePoses);
moveCenterTabController.eventLoopTick(vr::VRCompositor()->GetTrackingSpace());
vr::VREvent_t vrEvent; vr::VREvent_t vrEvent;
while( vr::VROverlay()->PollNextOverlayEvent( m_ulOverlayHandle, &vrEvent, sizeof( vrEvent ) ) ) { while( vr::VROverlay()->PollNextOverlayEvent( m_ulOverlayHandle, &vrEvent, sizeof( vrEvent ) ) ) {
@@ -198,7 +212,7 @@ void OverlayController::OnTimeoutPumpEvents() {
} }
break; break;
case vr::VREvent_MouseButtonUp: { case vr::VREvent_MouseButtonUp: {
Qt::MouseButton button = vrEvent.data.mouse.button == vr::VRMouseButton_Right ? Qt::RightButton : Qt::LeftButton; Qt::MouseButton button = vrEvent.data.mouse.button == vr::VRMouseButton_Right ? Qt::RightButton : Qt::LeftButton;
m_lastMouseButtons &= ~button; m_lastMouseButtons &= ~button;
@@ -220,18 +234,31 @@ void OverlayController::OnTimeoutPumpEvents() {
} }
break; break;
case vr::VREvent_OverlayShown: { case vr::VREvent_OverlayShown: {
m_pWidget->repaint(); m_pWidget->repaint();
UpdateWidget(); UpdateWidget();
} }
break; break;
case vr::VREvent_Quit: case vr::VREvent_Quit: {
LOG(INFO) << "Received quit request."; LOG(INFO) << "Received quit request.";
vr::VRSystem()->AcknowledgeQuit_Exiting(); // Let us buy some time just in case vr::VRSystem()->AcknowledgeQuit_Exiting(); // Let us buy some time just in case
moveCenterTabController.MoveCenterResetClicked(); moveCenterTabController.MoveCenterResetClicked();
QApplication::exit(); QApplication::exit();
break; }
break;
case vr::VREvent_DashboardActivated: {
LOG(INFO) << "Dashboard activated";
dashboardVisible = true;
}
break;
case vr::VREvent_DashboardDeactivated: {
LOG(INFO) << "Dashboard deactivated";
dashboardVisible = false;
}
break;
} }
} }
@@ -249,337 +276,143 @@ void OverlayController::OnTimeoutPumpEvents() {
} }
void OverlayController::UpdateWidget() { void OverlayController::UpdateWidget() {
steamVRTabController.UpdateTab();
chaperoneTabController.UpdateTab(); chaperoneTabController.UpdateTab();
moveCenterTabController.UpdateTab(); moveCenterTabController.UpdateTab();
fixFloorTabController.UpdateTab(); fixFloorTabController.UpdateTab();
statisticsTabController.UpdateTab();
settingsTabController.UpdateTab(); settingsTabController.UpdateTab();
} }
void OverlayController::AddOffsetToStandingPosition(unsigned axisId, float offset) { void OverlayController::AddOffsetToUniverseCenter(vr::ETrackingUniverseOrigin universe, unsigned axisId, float offset, bool adjustBounds, bool commit) {
vr::VRChaperoneSetup()->RevertWorkingCopy(); if (offset != 0.0f) {
vr::HmdMatrix34_t curPos; if (commit) {
vr::VRChaperoneSetup()->GetWorkingStandingZeroPoseToRawTrackingPose(&curPos); vr::VRChaperoneSetup()->RevertWorkingCopy();
curPos.m[0][3] += curPos.m[0][axisId] * offset;
curPos.m[1][3] += curPos.m[1][axisId] * offset;
curPos.m[2][3] += curPos.m[2][axisId] * offset;
vr::VRChaperoneSetup()->SetWorkingStandingZeroPoseToRawTrackingPose(&curPos);
vr::VRChaperoneSetup()->CommitWorkingCopy(vr::EChaperoneConfigFile_Live);
}
void ChaperoneTabController::init(OverlayController * parent, OverlayWidget * widget) {
this->parent = parent;
this->widget = widget;
connect(widget->ui->CenterMarkerToggle, SIGNAL(toggled(bool)), this, SLOT(CenterMarkerToggled(bool)));
connect(widget->ui->PlaySpaceToggle, SIGNAL(toggled(bool)), this, SLOT(PlaySpaceToggled(bool)));
connect(widget->ui->ForceBoundsToggle, SIGNAL(toggled(bool)), this, SLOT(ForceBoundsToggled(bool)));
connect(widget->ui->FadeDistanceSlider, SIGNAL(valueChanged(int)), this, SLOT(FadeDistanceChanged(int)));
connect(widget->ui->ColorAlphaSlider, SIGNAL(valueChanged(int)), this, SLOT(ColorAlphaChanged(int)));
connect(widget->ui->ResetDefaultsToggle, SIGNAL(clicked()), this, SLOT(ResetDefaultsClicked()));
}
void ChaperoneTabController::UpdateTab() {
if (widget && vr::VRSettings()) {
widget->ui->CenterMarkerToggle->blockSignals(true);
widget->ui->PlaySpaceToggle->blockSignals(true);
widget->ui->ForceBoundsToggle->blockSignals(true);
widget->ui->FadeDistanceSlider->blockSignals(true);
widget->ui->ColorAlphaSlider->blockSignals(true);
auto centerMarkerOn = vr::VRSettings()->GetBool(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_CenterMarkerOn_Bool, false);
widget->ui->CenterMarkerToggle->setChecked(centerMarkerOn);
auto playSpaceOn = vr::VRSettings()->GetBool(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_PlaySpaceOn_Bool, false);
widget->ui->PlaySpaceToggle->setChecked(playSpaceOn);
widget->ui->ForceBoundsToggle->setChecked(forceBoundsFlag);
auto fadeDistance = vr::VRSettings()->GetFloat(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_FadeDistance_Float, 0.7f);
widget->ui->FadeDistanceSlider->setValue(fadeDistance*100);
widget->ui->FadeDistanceLabel->setText(QString::asprintf("%.2f", fadeDistance));
auto colorAlpha = vr::VRSettings()->GetInt32(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_ColorGammaA_Int32, 255);
widget->ui->ColorAlphaSlider->setValue(colorAlpha*100/255);
widget->ui->ColorAlphaLabel->setText(QString::asprintf("%i%%", colorAlpha*100/255));
widget->ui->CenterMarkerToggle->blockSignals(false);
widget->ui->PlaySpaceToggle->blockSignals(false);
widget->ui->ForceBoundsToggle->blockSignals(false);
widget->ui->FadeDistanceSlider->blockSignals(false);
widget->ui->ColorAlphaSlider->blockSignals(false);
}
}
void ChaperoneTabController::CenterMarkerToggled(bool value) {
if (vr::VRSettings()) {
vr::VRSettings()->SetBool(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_CenterMarkerOn_Bool, value);
vr::VRSettings()->Sync();
}
}
void ChaperoneTabController::PlaySpaceToggled(bool value) {
if (vr::VRSettings()) {
vr::VRSettings()->SetBool(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_PlaySpaceOn_Bool, value);
vr::VRSettings()->Sync();
}
}
void ChaperoneTabController::ForceBoundsToggled(bool value) {
if (vr::VRChaperone()) {
forceBoundsFlag = value;
vr::VRChaperone()->ForceBoundsVisible(value);
}
}
void ChaperoneTabController::FadeDistanceChanged(int value) {
if (vr::VRSettings()) {
float fval= (float)value / 100;
vr::VRSettings()->SetFloat(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_FadeDistance_Float, fval);
vr::VRSettings()->Sync();
widget->ui->FadeDistanceLabel->setText(QString::asprintf("%.2f", fval));
}
}
void ChaperoneTabController::ColorAlphaChanged(int value) {
if (vr::VRSettings()) {
float fval = (float)value / 100;
vr::VRSettings()->SetInt32(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_ColorGammaA_Int32, 255*fval);
vr::VRSettings()->Sync();
widget->ui->ColorAlphaLabel->setText(QString::asprintf("%i%%", value));
}
}
void ChaperoneTabController::ResetDefaultsClicked() {
widget->ui->CenterMarkerToggle->setChecked(false);
widget->ui->PlaySpaceToggle->setChecked(false);
widget->ui->ForceBoundsToggle->setChecked(false);
widget->ui->FadeDistanceSlider->setValue(70);
widget->ui->ColorAlphaSlider->setValue(100);
}
void MoveCenterTabController::init(OverlayController * parent, OverlayWidget * widget) {
this->parent = parent;
this->widget = widget;
xOffset = 0.0f;
yOffset = 0.0f;
zOffset = 0.0f;
connect(widget->ui->XMinusButton, SIGNAL(clicked()), this, SLOT(XMinusClicked()));
connect(widget->ui->XPlusButton, SIGNAL(clicked()), this, SLOT(XPlusClicked()));
connect(widget->ui->YMinusButton, SIGNAL(clicked()), this, SLOT(YMinusClicked()));
connect(widget->ui->YPlusButton, SIGNAL(clicked()), this, SLOT(YPlusClicked()));
connect(widget->ui->ZMinusButton, SIGNAL(clicked()), this, SLOT(ZMinusClicked()));
connect(widget->ui->ZPlusButton, SIGNAL(clicked()), this, SLOT(ZPlusClicked()));
connect(widget->ui->MoveCenterResetButton, SIGNAL(clicked()), this, SLOT(MoveCenterResetClicked()));
}
void MoveCenterTabController::UpdateTab() {
if (widget) {
widget->ui->XOffsetLabel->setText(QString::asprintf("%.1f", xOffset));
widget->ui->YOffsetLabel->setText(QString::asprintf("%.1f", yOffset));
widget->ui->ZOffsetLabel->setText(QString::asprintf("%.1f", zOffset));
}
}
void MoveCenterTabController::XMinusClicked() {
if (widget) {
parent->AddOffsetToStandingPosition(0, -0.5f);
xOffset -= 0.5f;
widget->ui->XOffsetLabel->setText(QString::asprintf("%.1f", xOffset));
}
}
void MoveCenterTabController::XPlusClicked() {
if (widget) {
parent->AddOffsetToStandingPosition(0, 0.5f);
xOffset += 0.5f;
widget->ui->XOffsetLabel->setText(QString::asprintf("%.1f", xOffset));
}
}
void MoveCenterTabController::YMinusClicked() {
if (widget) {
parent->AddOffsetToStandingPosition(1, -0.5f);
yOffset -= 0.5f;
widget->ui->YOffsetLabel->setText(QString::asprintf("%.1f", yOffset));
}
}
void MoveCenterTabController::YPlusClicked() {
if (widget) {
parent->AddOffsetToStandingPosition(1, 0.5f);
yOffset += 0.5f;
widget->ui->YOffsetLabel->setText(QString::asprintf("%.1f", yOffset));
}
}
void MoveCenterTabController::ZMinusClicked() {
if (widget) {
parent->AddOffsetToStandingPosition(2, -0.5f);
zOffset -= 0.5f;
widget->ui->ZOffsetLabel->setText(QString::asprintf("%.1f", zOffset));
}
}
void MoveCenterTabController::ZPlusClicked() {
if (widget) {
parent->AddOffsetToStandingPosition(2, 0.5f);
zOffset += 0.5f;
widget->ui->ZOffsetLabel->setText(QString::asprintf("%.1f", zOffset));
}
}
void MoveCenterTabController::MoveCenterResetClicked() {
if (widget) {
parent->AddOffsetToStandingPosition(0, -xOffset);
parent->AddOffsetToStandingPosition(1, -yOffset);
parent->AddOffsetToStandingPosition(2, -zOffset);
xOffset = 0.0f;
yOffset = 0.0f;
zOffset = 0.0f;
widget->ui->XOffsetLabel->setText(QString::asprintf("%.1f", xOffset));
widget->ui->YOffsetLabel->setText(QString::asprintf("%.1f", yOffset));
widget->ui->ZOffsetLabel->setText(QString::asprintf("%.1f", zOffset));
}
}
void FixFloorTabController::init(OverlayController * parent, OverlayWidget * widget) {
this->parent = parent;
this->widget = widget;
connect(widget->ui->FixFloorButton, SIGNAL(clicked()), this, SLOT(FixFloorClicked()));
connect(widget->ui->UndoFixFloorButton, SIGNAL(clicked()), this, SLOT(UndoFixFloorClicked()));
}
void FixFloorTabController::UpdateTab() {
if (widget) {
if (state == 1) {
widget->ui->FixFloorButton->setEnabled(false);
} else {
widget->ui->FixFloorButton->setEnabled(true);
} }
if (floorOffset != 0.0f) { vr::HmdMatrix34_t curPos;
widget->ui->UndoFixFloorButton->setEnabled(true); if (universe == vr::TrackingUniverseStanding) {
vr::VRChaperoneSetup()->GetWorkingStandingZeroPoseToRawTrackingPose(&curPos);
} else { } else {
widget->ui->UndoFixFloorButton->setEnabled(false); vr::VRChaperoneSetup()->GetWorkingSeatedZeroPoseToRawTrackingPose(&curPos);
}
curPos.m[0][3] += curPos.m[0][axisId] * offset;
curPos.m[1][3] += curPos.m[1][axisId] * offset;
curPos.m[2][3] += curPos.m[2][axisId] * offset;
if (universe == vr::TrackingUniverseStanding) {
vr::VRChaperoneSetup()->SetWorkingStandingZeroPoseToRawTrackingPose(&curPos);
} else {
vr::VRChaperoneSetup()->SetWorkingSeatedZeroPoseToRawTrackingPose(&curPos);
}
if (adjustBounds && universe == vr::TrackingUniverseStanding) {
AddOffsetToCollisionBounds(axisId, -offset, false);
}
if (commit) {
vr::VRChaperoneSetup()->CommitWorkingCopy(vr::EChaperoneConfigFile_Live);
} }
} }
} }
void FixFloorTabController::eventLoopTick() { void OverlayController::RotateUniverseCenter(vr::ETrackingUniverseOrigin universe, float yAngle, bool adjustBounds, bool commit) {
if (state == 1) { if (yAngle != 0.0f) {
if (measurementCount == 0) { if (commit) {
// Get Controller ids for left/right hand vr::VRChaperoneSetup()->RevertWorkingCopy();
auto leftId = vr::VRSystem()->GetTrackedDeviceIndexForControllerRole(vr::TrackedControllerRole_LeftHand); }
if (leftId == vr::k_unTrackedDeviceIndexInvalid) { vr::HmdMatrix34_t curPos;
widget->ui->FixFloorStatusLabel->setText("No left controller found."); if (universe == vr::TrackingUniverseStanding) {
statusMessageTimeout = 100; vr::VRChaperoneSetup()->GetWorkingStandingZeroPoseToRawTrackingPose(&curPos);
state = 2; } else {
UpdateTab(); vr::VRChaperoneSetup()->GetWorkingSeatedZeroPoseToRawTrackingPose(&curPos);
return; }
} vr::HmdMatrix34_t newPos;
auto rightId = vr::VRSystem()->GetTrackedDeviceIndexForControllerRole(vr::TrackedControllerRole_RightHand); float yRot[3][3] = {
if (rightId == vr::k_unTrackedDeviceIndexInvalid) { { std::cos(yAngle), 0, std::sin(yAngle) },
widget->ui->FixFloorStatusLabel->setText("No right controller found."); { 0, 1, 0 },
statusMessageTimeout = 100; { -std::sin(yAngle), 0, std::cos(yAngle) }
state = 2; };
UpdateTab(); for (unsigned i = 0; i < 3; i++) {
return; for (unsigned j = 0; j < 3; j++) {
} newPos.m[i][j] = 0.0f;
// Get poses for (unsigned k = 0; k < 3; k++) {
vr::TrackedDevicePose_t devicePoses[vr::k_unMaxTrackedDeviceCount]; newPos.m[i][j] += yRot[i][k] * curPos.m[k][j];
vr::VRSystem()->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseStanding, 0.0f, devicePoses, vr::k_unMaxTrackedDeviceCount);
vr::TrackedDevicePose_t* leftPose = devicePoses + leftId;
vr::TrackedDevicePose_t* rightPose = devicePoses + rightId;
if (!leftPose->bPoseIsValid || !leftPose->bDeviceIsConnected || leftPose->eTrackingResult != vr::TrackingResult_Running_OK) {
widget->ui->FixFloorStatusLabel->setText("Left controller tracking problems.");
statusMessageTimeout = 100;
state = 2;
UpdateTab();
return;
} else if (!rightPose->bPoseIsValid || !rightPose->bDeviceIsConnected || rightPose->eTrackingResult != vr::TrackingResult_Running_OK) {
widget->ui->FixFloorStatusLabel->setText("Right controller tracking problems.");
statusMessageTimeout = 100;
state = 2;
UpdateTab();
return;
} else {
// The controller with the lowest y-pos is the floor fix reference
if (leftPose->mDeviceToAbsoluteTracking.m[1][3] < rightPose->mDeviceToAbsoluteTracking.m[1][3]) {
referenceController = leftId;
} else {
referenceController = rightId;
} }
tempOffset = (double)devicePoses[referenceController].mDeviceToAbsoluteTracking.m[1][3];
measurementCount = 1;
} }
} else if (measurementCount >= 50) {
floorOffset = -controllerUpOffsetCorrection + (float)(tempOffset / (double)measurementCount);
LOG(INFO) << "Fix Floor: Floor Offset = " << floorOffset;
parent->AddOffsetToStandingPosition(1, floorOffset);
widget->ui->FixFloorStatusLabel->setText("Fixing ... OK");
statusMessageTimeout = 50;
state = 2;
UpdateTab();
} else {
vr::TrackedDevicePose_t devicePoses[vr::k_unMaxTrackedDeviceCount];
vr::VRSystem()->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseStanding, 0.0f, devicePoses, vr::k_unMaxTrackedDeviceCount);
tempOffset += (double)devicePoses[referenceController].mDeviceToAbsoluteTracking.m[1][3];
measurementCount++;
} }
} else if (state == 2) { newPos.m[0][3] = curPos.m[0][3];
if (statusMessageTimeout == 0) { newPos.m[1][3] = curPos.m[1][3];
if (widget) { newPos.m[2][3] = curPos.m[2][3];
widget->ui->FixFloorStatusLabel->setText(""); vr::VRChaperoneSetup()->SetWorkingStandingZeroPoseToRawTrackingPose(&newPos);
if (universe == vr::TrackingUniverseStanding) {
vr::VRChaperoneSetup()->SetWorkingStandingZeroPoseToRawTrackingPose(&newPos);
} else {
vr::VRChaperoneSetup()->SetWorkingSeatedZeroPoseToRawTrackingPose(&newPos);
}
if (adjustBounds && universe == vr::TrackingUniverseStanding) {
RotateCollisionBounds(-yAngle, false);
}
if (commit) {
vr::VRChaperoneSetup()->CommitWorkingCopy(vr::EChaperoneConfigFile_Live);
}
}
}
void OverlayController::AddOffsetToCollisionBounds(unsigned axisId, float offset, bool commit) {
// Apparently Valve sanity-checks the y-coordinates of the collision bounds (and only the y-coordinates)
// I can move the bounds on the xz-plane, I can make the "ceiling" of the chaperone cage lower/higher, but when I
// dare to set one single lower corner to something non-zero, every corner gets its y-coordinates reset to the defaults.
// I do it anyway, maybe it gets fixed in the future.
if (commit) {
vr::VRChaperoneSetup()->RevertWorkingCopy();
}
unsigned collisionBoundsCount = 0;
vr::VRChaperoneSetup()->GetWorkingCollisionBoundsInfo(nullptr, &collisionBoundsCount);
if (collisionBoundsCount > 0) {
vr::HmdQuad_t* collisionBounds = new vr::HmdQuad_t[collisionBoundsCount];
vr::VRChaperoneSetup()->GetWorkingCollisionBoundsInfo(collisionBounds, &collisionBoundsCount);
for (unsigned b = 0; b < collisionBoundsCount; b++) {
for (unsigned c = 0; c < 4; c++) {
collisionBounds[b].vCorners[c].v[axisId] += offset;
} }
state = 0;
UpdateTab();
} else {
statusMessageTimeout--;
}
}
}
void FixFloorTabController::FixFloorClicked() {
if (widget) {
widget->ui->FixFloorStatusLabel->setText("Fixing ...");
widget->ui->FixFloorButton->setEnabled(false);
widget->ui->UndoFixFloorButton->setEnabled(false);
measurementCount = 0;
state = 1;
}
}
void FixFloorTabController::UndoFixFloorClicked() {
parent->AddOffsetToStandingPosition(1, -floorOffset);
LOG(INFO) << "Fix Floor: Undo Floor Offset = " << -floorOffset;
floorOffset = 0.0f;
widget->ui->FixFloorStatusLabel->setText("Undo ... OK");
statusMessageTimeout = 100;
state = 2;
UpdateTab();
}
void SettingsTabController::init(OverlayController * parent, OverlayWidget * widget) {
this->parent = parent;
this->widget = widget;
connect(widget->ui->AutoStartToggle, SIGNAL(toggled(bool)), this, SLOT(AutoStartToggled(bool)));
}
void SettingsTabController::UpdateTab() {
if (widget) {
widget->ui->AutoStartToggle->blockSignals(true);
if (vr::VRApplications()->GetApplicationAutoLaunch(OverlayController::applicationKey)) {
widget->ui->AutoStartToggle->setChecked(true);
} else {
widget->ui->AutoStartToggle->setChecked(false);
} }
widget->ui->AutoStartToggle->blockSignals(false); vr::VRChaperoneSetup()->SetWorkingCollisionBoundsInfo(collisionBounds, collisionBoundsCount);
delete collisionBounds;
}
if (commit && collisionBoundsCount > 0) {
vr::VRChaperoneSetup()->CommitWorkingCopy(vr::EChaperoneConfigFile_Live);
} }
} }
void SettingsTabController::AutoStartToggled(bool value) { void OverlayController::RotateCollisionBounds(float angle, bool commit) {
LOG(INFO) << "Setting auto start: " << value; if (commit) {
auto apperror = vr::VRApplications()->SetApplicationAutoLaunch(OverlayController::applicationKey, value); vr::VRChaperoneSetup()->RevertWorkingCopy();
if (apperror != vr::VRApplicationError_None) { }
LOG(ERROR) << "Could not set auto start: " << vr::VRApplications()->GetApplicationsErrorNameFromEnum(apperror); unsigned collisionBoundsCount = 0;
vr::VRChaperoneSetup()->GetWorkingCollisionBoundsInfo(nullptr, &collisionBoundsCount);
if (collisionBoundsCount > 0) {
vr::HmdQuad_t* collisionBounds = new vr::HmdQuad_t[collisionBoundsCount];
vr::VRChaperoneSetup()->GetWorkingCollisionBoundsInfo(collisionBounds, &collisionBoundsCount);
float yRot[3][3] = {
{ std::cos(angle), 0, std::sin(angle) },
{ 0, 1, 0 },
{ -std::sin(angle), 0, std::cos(angle) }
};
for (unsigned b = 0; b < collisionBoundsCount; b++) {
for (unsigned c = 0; c < 4; c++) {
auto& corner = collisionBounds[b].vCorners[c];
vr::HmdVector3_t newVal;
for (unsigned i = 0; i < 3; i++) {
newVal.v[i] = 0.0f;
for (unsigned k = 0; k < 3; k++) {
newVal.v[i] += corner.v[k] * yRot[i][k];
};
}
corner = newVal;
}
}
vr::VRChaperoneSetup()->SetWorkingCollisionBoundsInfo(collisionBounds, collisionBoundsCount);
delete collisionBounds;
}
if (commit && collisionBoundsCount > 0) {
vr::VRChaperoneSetup()->CommitWorkingCopy(vr::EChaperoneConfigFile_Live);
} }
} }
+22 -102
View File
@@ -1,7 +1,7 @@
#pragma once #pragma once
#include "openvr.h" #include <openvr.h>
#include <QtCore/QtCore> #include <QtCore/QtCore>
// because of incompatibilities with QtOpenGL and GLEW we need to cherry pick includes // because of incompatibilities with QtOpenGL and GLEW we need to cherry pick includes
#include <QVector2D> #include <QVector2D>
@@ -14,111 +14,21 @@
#include <QOffscreenSurface> #include <QOffscreenSurface>
#include <QOpenGLFramebufferObject> #include <QOpenGLFramebufferObject>
#include <memory> #include <memory>
#include "logging.h"
#include "tabcontrollers/SteamVRTabController.h"
#include "tabcontrollers/ChaperoneTabController.h"
#include "tabcontrollers/MoveCenterTabController.h"
#include "tabcontrollers/FixFloorTabController.h"
#include "tabcontrollers/StatisticsTabController.h"
#include "tabcontrollers/SettingsTabController.h"
// application namespace // application namespace
namespace advsettings { namespace advsettings {
// forward declaration // forward declaration
class OverlayWidget; class OverlayWidget;
class OverlayController;
class ChaperoneTabController : public QObject {
Q_OBJECT
private:
OverlayController* parent;
OverlayWidget* widget;
bool forceBoundsFlag = false;
public:
void init(OverlayController* parent, OverlayWidget* widget);
public slots:
void UpdateTab();
void CenterMarkerToggled(bool value);
void PlaySpaceToggled(bool value);
void ForceBoundsToggled(bool value);
void FadeDistanceChanged(int value);
void ColorAlphaChanged(int value);
void ResetDefaultsClicked();
};
class MoveCenterTabController : public QObject {
Q_OBJECT
private:
OverlayController* parent;
OverlayWidget* widget;
float xOffset = 0.0f;
float yOffset = 0.0f;
float zOffset = 0.0f;
public:
void init(OverlayController* parent, OverlayWidget* widget);
public slots:
void UpdateTab();
void XMinusClicked();
void XPlusClicked();
void YMinusClicked();
void YPlusClicked();
void ZMinusClicked();
void ZPlusClicked();
void MoveCenterResetClicked();
};
class FixFloorTabController : public QObject {
Q_OBJECT
private:
OverlayController* parent;
OverlayWidget* widget;
float controllerUpOffsetCorrection = 0.06f; // Controller touchpad facing upwards
float controllerDownOffsetCorrection = 0.0f; // Controller touchpad facing downwards (not implemented yet)
int state = 0; // 0 .. idle, 1 .. measurement in progress, 2 .. waiting for status message timeout
vr::TrackedDeviceIndex_t referenceController = vr::k_unTrackedDeviceIndexInvalid;
unsigned measurementCount = 0;
double tempOffset = 0.0;
unsigned statusMessageTimeout = 0;
float floorOffset = 0.0f;
public:
void init(OverlayController* parent, OverlayWidget* widget);
public slots:
void UpdateTab();
void eventLoopTick();
void FixFloorClicked();
void UndoFixFloorClicked();
};
class SettingsTabController : public QObject {
Q_OBJECT
private:
OverlayController* parent;
OverlayWidget* widget;
public:
void init(OverlayController* parent, OverlayWidget* widget);
public slots:
void UpdateTab();
void AutoStartToggled(bool value);
};
class OverlayController : public QObject { class OverlayController : public QObject {
Q_OBJECT Q_OBJECT
@@ -126,6 +36,7 @@ class OverlayController : public QObject {
public: public:
static constexpr const char* applicationKey = "matzman666.AdvancedSettings"; static constexpr const char* applicationKey = "matzman666.AdvancedSettings";
static constexpr const char* applicationName = "Advanced Settings"; static constexpr const char* applicationName = "Advanced Settings";
static constexpr const char* applicationVersionString = "v1.1";
private: private:
OverlayWidget *m_pWidget; OverlayWidget *m_pWidget;
@@ -139,13 +50,16 @@ private:
std::unique_ptr<QOffscreenSurface> m_pOffscreenSurface; std::unique_ptr<QOffscreenSurface> m_pOffscreenSurface;
std::unique_ptr<QTimer> m_pPumpEventsTimer; std::unique_ptr<QTimer> m_pPumpEventsTimer;
bool dashboardVisible = false;
QPointF m_ptLastMouse; QPointF m_ptLastMouse;
Qt::MouseButtons m_lastMouseButtons = 0; Qt::MouseButtons m_lastMouseButtons = 0;
SteamVRTabController steamVRTabController;
ChaperoneTabController chaperoneTabController; ChaperoneTabController chaperoneTabController;
MoveCenterTabController moveCenterTabController; MoveCenterTabController moveCenterTabController;
FixFloorTabController fixFloorTabController; FixFloorTabController fixFloorTabController;
StatisticsTabController statisticsTabController;
SettingsTabController settingsTabController; SettingsTabController settingsTabController;
public: public:
@@ -154,16 +68,22 @@ public:
void Init(); void Init();
bool isDashboardVisible() {
return dashboardVisible;
}
void SetWidget(OverlayWidget *pWidget, const std::string& name, const std::string& key = ""); void SetWidget(OverlayWidget *pWidget, const std::string& name, const std::string& key = "");
void AddOffsetToStandingPosition(unsigned axisId, float offset); void AddOffsetToUniverseCenter(vr::ETrackingUniverseOrigin universe, unsigned axisId, float offset, bool adjustBounds = true, bool commit = true);
void RotateUniverseCenter(vr::ETrackingUniverseOrigin universe, float yAngle, bool adjustBounds = true, bool commit = true); // around y axis
void AddOffsetToCollisionBounds(unsigned axisId, float offset, bool commit = true);
void RotateCollisionBounds(float angle, bool commit = true); // around y axis
public slots: public slots:
void OnSceneChanged( const QList<QRectF>& ); void OnSceneChanged( const QList<QRectF>& );
void OnTimeoutPumpEvents(); void OnTimeoutPumpEvents();
void UpdateWidget(); void UpdateWidget();
}; };
} // namespace advsettings } // namespace advsettings
+881 -25
View File
File diff suppressed because it is too large Load Diff