mirror of
https://github.com/CrispyPin/sinpin-vr.git
synced 2024-11-22 10:00:25 +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
|
||||
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);
|
||||
}
|
||||
|
||||
for (auto &panel : _panels)
|
||||
{
|
||||
_root_overlay.AddChildOverlay(panel.GetOverlay());
|
||||
}
|
||||
|
||||
{ // initialize SteamVR input
|
||||
auto exe_path = std::filesystem::read_symlink("/proc/self/exe");
|
||||
_actions_path = exe_path.parent_path().string() + "/bindings/action_manifest.json";
|
||||
|
@ -126,19 +131,6 @@ void App::InitRootOverlay()
|
|||
// clang-format on
|
||||
_root_overlay.SetTransformWorld(&root_start_pose);
|
||||
_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()
|
||||
|
|
|
@ -8,6 +8,7 @@ const float width = 0.004f;
|
|||
|
||||
Controller::Controller(App *app, ControllerSide side)
|
||||
{
|
||||
_grabbed_overlay = nullptr;
|
||||
_app = app;
|
||||
_input_handle = 0;
|
||||
_is_connected = false;
|
||||
|
@ -51,29 +52,30 @@ void Controller::SetHidden(bool state)
|
|||
_hidden = state;
|
||||
}
|
||||
|
||||
void Controller::RegisterGrabbedOverlay(Overlay *overlay)
|
||||
void Controller::ReleaseOverlay()
|
||||
{
|
||||
_grabbed_overlays.push_back(overlay);
|
||||
}
|
||||
|
||||
void Controller::ReleaseOverlay(Overlay *overlay)
|
||||
{
|
||||
for (auto i = _grabbed_overlays.begin(); i != _grabbed_overlays.end(); i++)
|
||||
{
|
||||
if (*i == overlay)
|
||||
{
|
||||
_grabbed_overlays.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
_grabbed_overlay = nullptr;
|
||||
}
|
||||
|
||||
void Controller::Update()
|
||||
{
|
||||
UpdateStatus();
|
||||
if (!_is_connected)
|
||||
if (!_is_connected || _hidden)
|
||||
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_pos = GetPos(controller_pose);
|
||||
auto forward = -glm::vec3(controller_pose[2]);
|
||||
|
@ -92,25 +94,14 @@ void Controller::Update()
|
|||
{
|
||||
if (_app->IsInputJustPressed(_app->_input_handles.grab, _input_handle))
|
||||
{
|
||||
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)
|
||||
if (ray.overlay->IsHeld())
|
||||
{
|
||||
auto transform = overlay->GetTarget()->transform;
|
||||
transform.m[2][3] += real_delta;
|
||||
overlay->SetTransformTracker(_device_index, &transform);
|
||||
// TODO resize mode
|
||||
}
|
||||
else
|
||||
{
|
||||
_grabbed_overlay = ray.overlay;
|
||||
ray.overlay->ControllerGrab(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,13 +23,14 @@ class Controller
|
|||
|
||||
void SetHidden(bool state);
|
||||
|
||||
void RegisterGrabbedOverlay(Overlay *overlay);
|
||||
void ReleaseOverlay(Overlay *overlay);
|
||||
void ReleaseOverlay();
|
||||
|
||||
void Update();
|
||||
void UpdateStatus();
|
||||
|
||||
private:
|
||||
void UpdateStatus();
|
||||
void UpdateLaser();
|
||||
|
||||
App *_app;
|
||||
Overlay _laser;
|
||||
ControllerSide _side;
|
||||
|
@ -37,5 +38,5 @@ class Controller
|
|||
vr::VRInputValueHandle_t _input_handle;
|
||||
bool _is_connected;
|
||||
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)
|
||||
{
|
||||
auto original_pose = _target.transform;
|
||||
_app->vr_overlay->SetOverlayTransformTrackedDeviceRelative(_id, tracker, transform);
|
||||
_target.type = TargetType::Tracker;
|
||||
_target.id = tracker;
|
||||
_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)
|
||||
|
@ -122,6 +133,14 @@ void Overlay::SetTransformWorld(const VRMat *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()
|
||||
{
|
||||
auto abs_pose = ConvertMat(GetTransformAbsolute());
|
||||
|
@ -213,25 +232,16 @@ void Overlay::Update()
|
|||
|
||||
void Overlay::ControllerGrab(Controller *controller)
|
||||
{
|
||||
if (_holding_controller != nullptr)
|
||||
{
|
||||
_holding_controller->ReleaseOverlay(this);
|
||||
}
|
||||
|
||||
_app->vr_overlay->SetOverlayColor(_id, 0.6f, 0.8f, 0.8f);
|
||||
SetTargetTracker(controller->DeviceIndex());
|
||||
|
||||
auto abs_mat = GetTransformAbsolute();
|
||||
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)
|
||||
for (auto child : _children)
|
||||
{
|
||||
_GrabBeginCallback(controller);
|
||||
if (!child->IsHeld()) // overlay may have been picked up by other controller
|
||||
{
|
||||
child->SetTargetTracker(controller->DeviceIndex());
|
||||
}
|
||||
}
|
||||
|
||||
_holding_controller = controller;
|
||||
}
|
||||
|
||||
|
@ -239,16 +249,34 @@ void Overlay::ControllerRelease()
|
|||
{
|
||||
if (_holding_controller != nullptr)
|
||||
{
|
||||
_holding_controller->ReleaseOverlay(this);
|
||||
_holding_controller->ReleaseOverlay();
|
||||
}
|
||||
_app->vr_overlay->SetOverlayColor(_id, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
auto new_pose = ConvertMat(GetTransformAbsolute());
|
||||
SetTransformWorld(&new_pose);
|
||||
|
||||
if (_GrabEndCallback != nullptr)
|
||||
SetTargetWorld();
|
||||
for (auto child : _children)
|
||||
{
|
||||
_GrabEndCallback();
|
||||
if (!child->IsHeld()) // overlay may have been picked up by other controller
|
||||
{
|
||||
child->SetTargetWorld();
|
||||
}
|
||||
}
|
||||
_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 <functional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class App;
|
||||
struct Ray;
|
||||
|
@ -49,17 +50,17 @@ class Overlay
|
|||
void SetTransformTracker(TrackerID tracker, const VRMat *transform);
|
||||
void SetTransformWorld(const VRMat *transform);
|
||||
|
||||
// void SetTargetTracker(TrackerID tracker);
|
||||
void SetTargetTracker(TrackerID tracker);
|
||||
void SetTargetWorld();
|
||||
|
||||
Ray IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len);
|
||||
|
||||
std::function<void(Controller *)> _GrabBeginCallback;
|
||||
std::function<void()> _GrabEndCallback;
|
||||
|
||||
void ControllerRelease();
|
||||
void ControllerGrab(Controller *controller);
|
||||
|
||||
void AddChildOverlay(Overlay *child);
|
||||
void RemoveChildOverlay(Overlay *child);
|
||||
|
||||
private:
|
||||
bool _initialized;
|
||||
|
||||
|
@ -73,5 +74,7 @@ class Overlay
|
|||
float _ratio;
|
||||
Controller *_holding_controller;
|
||||
|
||||
std::vector<Overlay *> _children;
|
||||
|
||||
Target _target;
|
||||
};
|
Loading…
Reference in a new issue