From 533bf45087382014b2ea1f35344f506fd7fa476c Mon Sep 17 00:00:00 2001 From: CrispyPin Date: Sat, 22 Apr 2023 17:49:07 +0200 Subject: [PATCH] resize overlays when grabbed with both controllers --- README.md | 2 +- src/app.h | 6 --- src/controller.cpp | 21 ++++++++- src/controller.h | 6 +++ src/overlay.cpp | 110 ++++++++++++++++++++++++++++++++------------- src/overlay.h | 9 +++- src/util.h | 7 +++ 7 files changed, 120 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index cd4dd5a..065bbd4 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# ovr-screen +# sinpin-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. diff --git a/src/app.h b/src/app.h index f6bd55d..c1508e8 100644 --- a/src/app.h +++ b/src/app.h @@ -24,12 +24,6 @@ struct InputHandles vr::VRActionHandle_t grab; }; -struct Ray -{ - Overlay *overlay; - float distance; -}; - class App { public: diff --git a/src/controller.cpp b/src/controller.cpp index a6df051..27dc871 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -57,6 +57,21 @@ void Controller::ReleaseOverlay() _grabbed_overlay = nullptr; } +Ray Controller::GetLastRay() +{ + return _last_ray; +} + +glm::vec3 Controller::GetLastPos() +{ + return _last_pos; +} + +glm::vec3 Controller::GetLastRot() +{ + return _last_rotation; +} + void Controller::Update() { UpdateStatus(); @@ -82,6 +97,10 @@ void Controller::UpdateLaser() auto ray = _app->IntersectRay(controller_pos, forward, 5.0f); float len = ray.distance; + _last_pos = controller_pos; + _last_rotation = forward; + _last_ray = ray; + auto hmd_global_pos = GetPos(_app->GetTrackerPose(0)); auto hmd_local_pos = glm::inverse(controller_pose) * glm::vec4(hmd_global_pos - controller_pos, 0); hmd_local_pos.z = 0; @@ -96,7 +115,7 @@ void Controller::UpdateLaser() { if (ray.overlay->IsHeld()) { - // TODO resize mode + ray.overlay->ControllerResize(this); } else { diff --git a/src/controller.h b/src/controller.h index a096c23..e5f49b8 100644 --- a/src/controller.h +++ b/src/controller.h @@ -20,6 +20,9 @@ class Controller ControllerSide Side(); bool IsConnected(); + Ray GetLastRay(); + glm::vec3 GetLastPos(); + glm::vec3 GetLastRot(); void SetHidden(bool state); @@ -39,4 +42,7 @@ class Controller bool _is_connected; bool _hidden; Overlay *_grabbed_overlay; + Ray _last_ray; + glm::vec3 _last_rotation; + glm::vec3 _last_pos; }; diff --git a/src/overlay.cpp b/src/overlay.cpp index 4b8bd5c..80f218f 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -14,6 +14,7 @@ Overlay::Overlay(App *app, std::string name) _name = name; _app = app; _holding_controller = nullptr; + _resize_controller = nullptr; _width_m = 1; _ratio = 1; _hidden = false; @@ -149,7 +150,7 @@ void Overlay::SetTargetWorld() Ray Overlay::IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len) { - float closest_dist = max_len; + float dist = max_len; auto end = origin + direction * max_len; auto panel_transform = GetTransformAbsolute(); @@ -166,46 +167,30 @@ Ray Overlay::IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len) if (b.z < a.z && b.z < 0 && glm::abs(p.x) < (_width_m * 0.5f) && glm::abs(p.y) < (_width_m * 0.5f * _ratio)) { - float dist = r * max_len; - if (dist < closest_dist) - { - closest_dist = dist; - } + dist = glm::min(r * max_len, max_len); } - return Ray{.overlay = this, .distance = closest_dist}; + return Ray{.overlay = this, .distance = dist}; } glm::mat4x4 Overlay::GetTransformAbsolute() { - if (_holding_controller != nullptr) + if (_target.type == TargetType::World) { VRMat pose; - TrackerID tracker; - auto err = _app->vr_overlay->GetOverlayTransformTrackedDeviceRelative(_id, &tracker, &pose); - assert(err == 0); - auto offset = ConvertMat(pose); - auto controller = _app->GetTrackerPose(_holding_controller->DeviceIndex()); - return controller * offset; + vr::ETrackingUniverseOrigin tracking_universe; + _app->vr_overlay->GetOverlayTransformAbsolute(_id, &tracking_universe, &pose); + return ConvertMat(pose); } - else + if (_target.type == TargetType::Tracker) { - switch (_target.type) - { - case TargetType::World: { - VRMat pose; - vr::ETrackingUniverseOrigin tracking_universe; - _app->vr_overlay->GetOverlayTransformAbsolute(_id, &tracking_universe, &pose); - return ConvertMat(pose); - } - case TargetType::Tracker: { - VRMat pose; - _app->vr_overlay->GetOverlayTransformTrackedDeviceRelative(_id, &_target.id, &pose); - auto offset = ConvertMat(pose); - auto tracker_pose = _app->GetTrackerPose(_target.id); - return tracker_pose * offset; - } - } + VRMat pose; + _app->vr_overlay->GetOverlayTransformTrackedDeviceRelative(_id, &_target.id, &pose); + auto offset = ConvertMat(pose); + auto tracker_pose = _app->GetTrackerPose(_target.id); + return tracker_pose * offset; } + printf("Error: overlay '%s' not set to a valid target", _name.c_str()); + return ConvertMat(VRMatIdentity); } Target *Overlay::GetTarget() @@ -223,7 +208,41 @@ void Overlay::Update() if (_holding_controller != nullptr) { - if (!_app->GetInputDigital(_app->_input_handles.grab, _holding_controller->InputHandle()).bState) + bool hold_controller_holding = _app->GetInputDigital(_app->_input_handles.grab, _holding_controller->InputHandle()).bState; + if (_resize_controller != nullptr) + { + bool resize_controller_holding = _app->GetInputDigital(_app->_input_handles.grab, _resize_controller->InputHandle()).bState; + if (!resize_controller_holding) + { + _resize_controller = nullptr; + } + else if (!hold_controller_holding) + { + _resize_controller = nullptr; + ControllerRelease(); + } + else + { + auto pos_a = _holding_controller->GetLastPos() + _holding_controller->GetLastRot() * _resize_length_a; + auto pos_b = _resize_controller->GetLastPos() + _resize_controller->GetLastRot() * _resize_length_b; + + float distance = glm::length(pos_a - pos_b); + float factor = (distance / _resize_base_distance); + float min_factor = 0.1f / _resize_original_size; + float max_factor = 5.0f / _resize_original_size; + factor = glm::clamp(factor, min_factor, max_factor); + float new_size = _resize_original_size * factor; + + SetWidth(new_size); + + auto transform = _target.transform; + auto pos = _resize_held_offset * factor; + transform.m[0][3] = pos.x; + transform.m[1][3] = pos.y; + SetTransformTracker(_holding_controller->DeviceIndex(), &transform); + } + } + else if (!hold_controller_holding) { ControllerRelease(); } @@ -264,6 +283,33 @@ void Overlay::ControllerRelease() _holding_controller = nullptr; } +void Overlay::ControllerResize(Controller *controller) +{ + if (_resize_controller || controller == _holding_controller) + { + return; + } + for (auto child : _children) + { + if (!child->IsHeld()) + { + child->SetTargetWorld(); + } + } + _resize_controller = controller; + _resize_original_size = _width_m; + + _resize_length_a = _holding_controller->GetLastRay().distance; + _resize_length_b = _resize_controller->GetLastRay().distance; + + auto pos_a = _holding_controller->GetLastPos() + _holding_controller->GetLastRot() * _resize_length_a; + auto pos_b = _resize_controller->GetLastPos() + _resize_controller->GetLastRot() * _resize_length_b; + + // distance between laser points + _resize_base_distance = glm::length(pos_a - pos_b); + _resize_held_offset = GetPos(_target.transform); +} + void Overlay::AddChildOverlay(Overlay *overlay) { _children.push_back(overlay); diff --git a/src/overlay.h b/src/overlay.h index 67dce7b..c2ff311 100644 --- a/src/overlay.h +++ b/src/overlay.h @@ -55,8 +55,9 @@ class Overlay Ray IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len); - void ControllerRelease(); void ControllerGrab(Controller *controller); + void ControllerRelease(); + void ControllerResize(Controller *controller); void AddChildOverlay(Overlay *child); void RemoveChildOverlay(Overlay *child); @@ -73,6 +74,12 @@ class Overlay float _alpha; float _ratio; Controller *_holding_controller; + Controller *_resize_controller; + float _resize_original_size; + float _resize_base_distance; + float _resize_length_a; + float _resize_length_b; + glm::vec3 _resize_held_offset; std::vector _children; diff --git a/src/util.h b/src/util.h index bd29e39..0cf4916 100644 --- a/src/util.h +++ b/src/util.h @@ -10,6 +10,13 @@ typedef vr::HmdMatrix34_t VRMat; const VRMat VRMatIdentity{{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}}}; const int MAX_TRACKERS = vr::k_unMaxTrackedDeviceCount; +class Overlay; +struct Ray +{ + Overlay *overlay; + float distance; +}; + inline void PrintVec(glm::vec3 v) { printf("(%.2f, %.2f, %.2f)\n", v.x, v.y, v.z);