mirror of
https://github.com/CrispyPin/sinpin-vr.git
synced 2024-11-22 18:10:26 +01:00
refactor how multiple overlays get grabbed at the same time
This commit is contained in:
parent
895bec3bd5
commit
286c1d08a7
6 changed files with 92 additions and 75 deletions
|
@ -1,3 +1,5 @@
|
||||||
# ovr-screen
|
# ovr-screen
|
||||||
A SteamVR overlay for Linux+X11 that displays all your screens in VR.
|
A SteamVR overlay for Linux+X11 that displays all your screens in VR.
|
||||||
|
|
||||||
|
From my limited testing, this uses about half the CPU performance of Steam's built-in desktop overlay, if running at 60 FPS. Currently the default is 30 FPS which brings the factor to 3-4x. On my machine, the Steam desktop view increases cpu usage by about 100% of a CPU thread (looking only at the `steam` process), while this overlay uses around 25% at 30 FPS and 45% at 60 FPS.
|
||||||
|
|
||||||
|
|
18
src/app.cpp
18
src/app.cpp
|
@ -46,6 +46,11 @@ App::App()
|
||||||
_panels[i].GetOverlay()->SetWidth(width);
|
_panels[i].GetOverlay()->SetWidth(width);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto &panel : _panels)
|
||||||
|
{
|
||||||
|
_root_overlay.AddChildOverlay(panel.GetOverlay());
|
||||||
|
}
|
||||||
|
|
||||||
{ // initialize SteamVR input
|
{ // initialize SteamVR input
|
||||||
auto exe_path = std::filesystem::read_symlink("/proc/self/exe");
|
auto exe_path = std::filesystem::read_symlink("/proc/self/exe");
|
||||||
_actions_path = exe_path.parent_path().string() + "/bindings/action_manifest.json";
|
_actions_path = exe_path.parent_path().string() + "/bindings/action_manifest.json";
|
||||||
|
@ -126,19 +131,6 @@ void App::InitRootOverlay()
|
||||||
// clang-format on
|
// clang-format on
|
||||||
_root_overlay.SetTransformWorld(&root_start_pose);
|
_root_overlay.SetTransformWorld(&root_start_pose);
|
||||||
_root_overlay.SetTextureToColor(110, 30, 190);
|
_root_overlay.SetTextureToColor(110, 30, 190);
|
||||||
|
|
||||||
_root_overlay._GrabBeginCallback = [this](Controller *controller) {
|
|
||||||
for (auto &panel : _panels)
|
|
||||||
{
|
|
||||||
panel.GetOverlay()->ControllerGrab(controller);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
_root_overlay._GrabEndCallback = [this]() {
|
|
||||||
for (auto &panel : _panels)
|
|
||||||
{
|
|
||||||
panel.GetOverlay()->ControllerRelease();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::Update()
|
void App::Update()
|
||||||
|
|
|
@ -8,6 +8,7 @@ const float width = 0.004f;
|
||||||
|
|
||||||
Controller::Controller(App *app, ControllerSide side)
|
Controller::Controller(App *app, ControllerSide side)
|
||||||
{
|
{
|
||||||
|
_grabbed_overlay = nullptr;
|
||||||
_app = app;
|
_app = app;
|
||||||
_input_handle = 0;
|
_input_handle = 0;
|
||||||
_is_connected = false;
|
_is_connected = false;
|
||||||
|
@ -51,29 +52,30 @@ void Controller::SetHidden(bool state)
|
||||||
_hidden = state;
|
_hidden = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::RegisterGrabbedOverlay(Overlay *overlay)
|
void Controller::ReleaseOverlay()
|
||||||
{
|
{
|
||||||
_grabbed_overlays.push_back(overlay);
|
_grabbed_overlay = nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
void Controller::ReleaseOverlay(Overlay *overlay)
|
|
||||||
{
|
|
||||||
for (auto i = _grabbed_overlays.begin(); i != _grabbed_overlays.end(); i++)
|
|
||||||
{
|
|
||||||
if (*i == overlay)
|
|
||||||
{
|
|
||||||
_grabbed_overlays.erase(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::Update()
|
void Controller::Update()
|
||||||
{
|
{
|
||||||
UpdateStatus();
|
UpdateStatus();
|
||||||
if (!_is_connected)
|
if (!_is_connected || _hidden)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
UpdateLaser();
|
||||||
|
|
||||||
|
float move = _app->GetInputAnalog(_app->_input_handles.distance, _input_handle).y * 0.1; // TODO use frame time
|
||||||
|
if (_grabbed_overlay && move != 0.0f)
|
||||||
|
{
|
||||||
|
auto transform = _grabbed_overlay->GetTarget()->transform;
|
||||||
|
transform.m[2][3] = glm::clamp(transform.m[2][3] - move, -5.0f, -0.1f); // moving along z axis
|
||||||
|
_grabbed_overlay->SetTransformTracker(_device_index, &transform);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::UpdateLaser()
|
||||||
|
{
|
||||||
auto controller_pose = _app->GetTrackerPose(_device_index);
|
auto controller_pose = _app->GetTrackerPose(_device_index);
|
||||||
auto controller_pos = GetPos(controller_pose);
|
auto controller_pos = GetPos(controller_pose);
|
||||||
auto forward = -glm::vec3(controller_pose[2]);
|
auto forward = -glm::vec3(controller_pose[2]);
|
||||||
|
@ -92,27 +94,16 @@ void Controller::Update()
|
||||||
{
|
{
|
||||||
if (_app->IsInputJustPressed(_app->_input_handles.grab, _input_handle))
|
if (_app->IsInputJustPressed(_app->_input_handles.grab, _input_handle))
|
||||||
{
|
{
|
||||||
|
if (ray.overlay->IsHeld())
|
||||||
|
{
|
||||||
|
// TODO resize mode
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_grabbed_overlay = ray.overlay;
|
||||||
ray.overlay->ControllerGrab(this);
|
ray.overlay->ControllerGrab(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_grabbed_overlays.empty())
|
|
||||||
{
|
|
||||||
float move = _app->GetInputAnalog(_app->_input_handles.distance, _input_handle).y * 0.1; // TODO use frame time
|
|
||||||
if (move != 0.0f)
|
|
||||||
{
|
|
||||||
// delta is calculated & clamped for first overlay so that child overlays don't move further than the root
|
|
||||||
float main_z = _grabbed_overlays[0]->GetTarget()->transform.m[2][3];
|
|
||||||
float new_main_z = glm::clamp(main_z - move, -5.0f, -0.1f);
|
|
||||||
float real_delta = new_main_z - main_z;
|
|
||||||
|
|
||||||
for (auto overlay : _grabbed_overlays)
|
|
||||||
{
|
|
||||||
auto transform = overlay->GetTarget()->transform;
|
|
||||||
transform.m[2][3] += real_delta;
|
|
||||||
overlay->SetTransformTracker(_device_index, &transform);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,13 +23,14 @@ class Controller
|
||||||
|
|
||||||
void SetHidden(bool state);
|
void SetHidden(bool state);
|
||||||
|
|
||||||
void RegisterGrabbedOverlay(Overlay *overlay);
|
void ReleaseOverlay();
|
||||||
void ReleaseOverlay(Overlay *overlay);
|
|
||||||
|
|
||||||
void Update();
|
void Update();
|
||||||
void UpdateStatus();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void UpdateStatus();
|
||||||
|
void UpdateLaser();
|
||||||
|
|
||||||
App *_app;
|
App *_app;
|
||||||
Overlay _laser;
|
Overlay _laser;
|
||||||
ControllerSide _side;
|
ControllerSide _side;
|
||||||
|
@ -37,5 +38,5 @@ class Controller
|
||||||
vr::VRInputValueHandle_t _input_handle;
|
vr::VRInputValueHandle_t _input_handle;
|
||||||
bool _is_connected;
|
bool _is_connected;
|
||||||
bool _hidden;
|
bool _hidden;
|
||||||
std::vector<Overlay *> _grabbed_overlays;
|
Overlay *_grabbed_overlay;
|
||||||
};
|
};
|
||||||
|
|
|
@ -109,10 +109,21 @@ void Overlay::SetTextureToColor(uint8_t r, uint8_t g, uint8_t b)
|
||||||
|
|
||||||
void Overlay::SetTransformTracker(TrackerID tracker, const VRMat *transform)
|
void Overlay::SetTransformTracker(TrackerID tracker, const VRMat *transform)
|
||||||
{
|
{
|
||||||
|
auto original_pose = _target.transform;
|
||||||
_app->vr_overlay->SetOverlayTransformTrackedDeviceRelative(_id, tracker, transform);
|
_app->vr_overlay->SetOverlayTransformTrackedDeviceRelative(_id, tracker, transform);
|
||||||
_target.type = TargetType::Tracker;
|
_target.type = TargetType::Tracker;
|
||||||
_target.id = tracker;
|
_target.id = tracker;
|
||||||
_target.transform = *transform;
|
_target.transform = *transform;
|
||||||
|
|
||||||
|
auto relative_transform = ConvertMat(*transform) * glm::inverse(ConvertMat(original_pose));
|
||||||
|
for (auto child : _children)
|
||||||
|
{
|
||||||
|
if (!child->IsHeld() && child->_target.type == TargetType::Tracker)
|
||||||
|
{
|
||||||
|
VRMat local_transform = ConvertMat(relative_transform * ConvertMat(child->_target.transform));
|
||||||
|
child->SetTransformTracker(tracker, &local_transform);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Overlay::SetTransformWorld(const VRMat *transform)
|
void Overlay::SetTransformWorld(const VRMat *transform)
|
||||||
|
@ -122,6 +133,14 @@ void Overlay::SetTransformWorld(const VRMat *transform)
|
||||||
_target.transform = *transform;
|
_target.transform = *transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Overlay::SetTargetTracker(TrackerID tracker)
|
||||||
|
{
|
||||||
|
auto abs_mat = GetTransformAbsolute();
|
||||||
|
auto controller_mat = _app->GetTrackerPose(tracker);
|
||||||
|
VRMat relative_pose = ConvertMat(glm::inverse(controller_mat) * abs_mat);
|
||||||
|
SetTransformTracker(tracker, &relative_pose);
|
||||||
|
}
|
||||||
|
|
||||||
void Overlay::SetTargetWorld()
|
void Overlay::SetTargetWorld()
|
||||||
{
|
{
|
||||||
auto abs_pose = ConvertMat(GetTransformAbsolute());
|
auto abs_pose = ConvertMat(GetTransformAbsolute());
|
||||||
|
@ -213,25 +232,16 @@ void Overlay::Update()
|
||||||
|
|
||||||
void Overlay::ControllerGrab(Controller *controller)
|
void Overlay::ControllerGrab(Controller *controller)
|
||||||
{
|
{
|
||||||
if (_holding_controller != nullptr)
|
|
||||||
{
|
|
||||||
_holding_controller->ReleaseOverlay(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
_app->vr_overlay->SetOverlayColor(_id, 0.6f, 0.8f, 0.8f);
|
_app->vr_overlay->SetOverlayColor(_id, 0.6f, 0.8f, 0.8f);
|
||||||
|
SetTargetTracker(controller->DeviceIndex());
|
||||||
|
|
||||||
auto abs_mat = GetTransformAbsolute();
|
for (auto child : _children)
|
||||||
auto controller_mat = _app->GetTrackerPose(controller->DeviceIndex());
|
|
||||||
VRMat relative_pose = ConvertMat(glm::inverse(controller_mat) * abs_mat);
|
|
||||||
|
|
||||||
SetTransformTracker(controller->DeviceIndex(), &relative_pose);
|
|
||||||
|
|
||||||
controller->RegisterGrabbedOverlay(this);
|
|
||||||
if (_GrabBeginCallback != nullptr)
|
|
||||||
{
|
{
|
||||||
_GrabBeginCallback(controller);
|
if (!child->IsHeld()) // overlay may have been picked up by other controller
|
||||||
|
{
|
||||||
|
child->SetTargetTracker(controller->DeviceIndex());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_holding_controller = controller;
|
_holding_controller = controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,16 +249,34 @@ void Overlay::ControllerRelease()
|
||||||
{
|
{
|
||||||
if (_holding_controller != nullptr)
|
if (_holding_controller != nullptr)
|
||||||
{
|
{
|
||||||
_holding_controller->ReleaseOverlay(this);
|
_holding_controller->ReleaseOverlay();
|
||||||
}
|
}
|
||||||
_app->vr_overlay->SetOverlayColor(_id, 1.0f, 1.0f, 1.0f);
|
_app->vr_overlay->SetOverlayColor(_id, 1.0f, 1.0f, 1.0f);
|
||||||
|
|
||||||
auto new_pose = ConvertMat(GetTransformAbsolute());
|
SetTargetWorld();
|
||||||
SetTransformWorld(&new_pose);
|
for (auto child : _children)
|
||||||
|
|
||||||
if (_GrabEndCallback != nullptr)
|
|
||||||
{
|
{
|
||||||
_GrabEndCallback();
|
if (!child->IsHeld()) // overlay may have been picked up by other controller
|
||||||
|
{
|
||||||
|
child->SetTargetWorld();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_holding_controller = nullptr;
|
_holding_controller = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Overlay::AddChildOverlay(Overlay *overlay)
|
||||||
|
{
|
||||||
|
_children.push_back(overlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Overlay::RemoveChildOverlay(Overlay *overlay)
|
||||||
|
{
|
||||||
|
for (auto i = _children.begin(); i != _children.end(); i++)
|
||||||
|
{
|
||||||
|
if (*i == overlay)
|
||||||
|
{
|
||||||
|
_children.erase(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class App;
|
class App;
|
||||||
struct Ray;
|
struct Ray;
|
||||||
|
@ -49,17 +50,17 @@ class Overlay
|
||||||
void SetTransformTracker(TrackerID tracker, const VRMat *transform);
|
void SetTransformTracker(TrackerID tracker, const VRMat *transform);
|
||||||
void SetTransformWorld(const VRMat *transform);
|
void SetTransformWorld(const VRMat *transform);
|
||||||
|
|
||||||
// void SetTargetTracker(TrackerID tracker);
|
void SetTargetTracker(TrackerID tracker);
|
||||||
void SetTargetWorld();
|
void SetTargetWorld();
|
||||||
|
|
||||||
Ray IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len);
|
Ray IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len);
|
||||||
|
|
||||||
std::function<void(Controller *)> _GrabBeginCallback;
|
|
||||||
std::function<void()> _GrabEndCallback;
|
|
||||||
|
|
||||||
void ControllerRelease();
|
void ControllerRelease();
|
||||||
void ControllerGrab(Controller *controller);
|
void ControllerGrab(Controller *controller);
|
||||||
|
|
||||||
|
void AddChildOverlay(Overlay *child);
|
||||||
|
void RemoveChildOverlay(Overlay *child);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _initialized;
|
bool _initialized;
|
||||||
|
|
||||||
|
@ -73,5 +74,7 @@ class Overlay
|
||||||
float _ratio;
|
float _ratio;
|
||||||
Controller *_holding_controller;
|
Controller *_holding_controller;
|
||||||
|
|
||||||
|
std::vector<Overlay *> _children;
|
||||||
|
|
||||||
Target _target;
|
Target _target;
|
||||||
};
|
};
|
Loading…
Reference in a new issue