Compare commits

...

3 commits

Author SHA1 Message Date
895bec3bd5 increase update rate 2023-04-16 18:58:45 +02:00
e73e9b12f8 cleanup 2023-04-16 18:40:44 +02:00
00566021a0 push&pull overlays while moving them 2023-04-16 18:23:00 +02:00
9 changed files with 100 additions and 33 deletions

View file

@ -1,3 +1,3 @@
# ovr-screen # ovr-screen
A SteamVR overlay for Linux+X11 that displays the screen in VR. A SteamVR overlay for Linux+X11 that displays all your screens in VR.

View file

@ -8,6 +8,7 @@
App::App() App::App()
{ {
_tracking_origin = vr::TrackingUniverseStanding; _tracking_origin = vr::TrackingUniverseStanding;
_frames_since_framebuffer = 999;
InitOVR(); InitOVR();
InitX11(); InitX11();
@ -115,7 +116,7 @@ void App::InitGLFW()
void App::InitRootOverlay() void App::InitRootOverlay()
{ {
_root_overlay = Overlay(this, "root"); _root_overlay = Overlay(this, "root");
_root_overlay.SetAlpha(0.2f); _root_overlay.SetAlpha(0.5f);
// clang-format off // clang-format off
VRMat root_start_pose = {{ VRMat root_start_pose = {{
{0.25f, 0.0f, 0.0f, 0}, {0.25f, 0.0f, 0.0f, 0},
@ -124,6 +125,7 @@ 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._GrabBeginCallback = [this](Controller *controller) { _root_overlay._GrabBeginCallback = [this](Controller *controller) {
for (auto &panel : _panels) for (auto &panel : _panels)
@ -151,6 +153,7 @@ void App::Update()
panel.Update(); panel.Update();
} }
} }
_frames_since_framebuffer += 1;
} }
void App::UpdateInput() void App::UpdateInput()
@ -175,6 +178,8 @@ void App::UpdateInput()
{ {
panel.SetHidden(_hidden); panel.SetHidden(_hidden);
} }
_controllers[0]->SetHidden(_hidden);
_controllers[1]->SetHidden(_hidden);
} }
_controllers[0]->Update(); _controllers[0]->Update();
_controllers[1]->Update(); _controllers[1]->Update();
@ -182,6 +187,11 @@ void App::UpdateInput()
void App::UpdateFramebuffer() void App::UpdateFramebuffer()
{ {
if (_frames_since_framebuffer < 2)
{
return;
}
_frames_since_framebuffer = 0;
auto frame = XGetImage( auto frame = XGetImage(
_xdisplay, _xdisplay,
_root_window, _root_window,
@ -232,22 +242,19 @@ Ray App::IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len)
Ray ray; Ray ray;
ray.distance = max_len; ray.distance = max_len;
ray.overlay = nullptr; ray.overlay = nullptr;
auto r_root = _root_overlay.IntersectRay(origin, direction, max_len);
if (r_root.distance < ray.distance)
{ {
float root_dist = _root_overlay.IntersectRay(origin, direction, max_len); ray = r_root;
if (root_dist < ray.distance)
{
ray.distance = root_dist;
ray.overlay = &_root_overlay;
}
} }
for (auto &panel : _panels) for (auto &panel : _panels)
{ {
float dist = panel.GetOverlay()->IntersectRay(origin, direction, max_len); auto r_panel = panel.GetOverlay()->IntersectRay(origin, direction, max_len);
if (dist < ray.distance) if (r_panel.distance < ray.distance)
{ {
ray.distance = dist; ray = r_panel;
ray.overlay = panel.GetOverlay();
} }
} }
return ray; return ray;

View file

@ -50,6 +50,7 @@ class App
Window _root_window; Window _root_window;
GLFWwindow *_gl_window; GLFWwindow *_gl_window;
GLuint _gl_frame; GLuint _gl_frame;
int _frames_since_framebuffer;
int _root_width; int _root_width;
int _root_height; int _root_height;

View file

@ -12,6 +12,7 @@ Controller::Controller(App *app, ControllerSide side)
_input_handle = 0; _input_handle = 0;
_is_connected = false; _is_connected = false;
_side = side; _side = side;
_hidden = false;
std::string laser_name = "controller_laser_"; std::string laser_name = "controller_laser_";
if (side == ControllerSide::Left) if (side == ControllerSide::Left)
@ -45,6 +46,28 @@ bool Controller::IsConnected()
return _is_connected; return _is_connected;
} }
void Controller::SetHidden(bool state)
{
_hidden = state;
}
void Controller::RegisterGrabbedOverlay(Overlay *overlay)
{
_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;
}
}
}
void Controller::Update() void Controller::Update()
{ {
UpdateStatus(); UpdateStatus();
@ -72,6 +95,25 @@ void Controller::Update()
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);
}
}
}
} }
void Controller::UpdateStatus() void Controller::UpdateStatus()
@ -91,5 +133,5 @@ void Controller::UpdateStatus()
_device_index = _app->vr_sys->GetTrackedDeviceIndexForControllerRole(vr::TrackedControllerRole_RightHand); _device_index = _app->vr_sys->GetTrackedDeviceIndexForControllerRole(vr::TrackedControllerRole_RightHand);
} }
_is_connected &= _device_index < MAX_TRACKERS; _is_connected &= _device_index < MAX_TRACKERS;
_laser.SetHidden(!_is_connected); _laser.SetHidden(!_is_connected || _hidden);
} }

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "overlay.h" #include "overlay.h"
#include "util.h" #include "util.h"
#include <vector>
class App; class App;
@ -20,6 +21,11 @@ class Controller
bool IsConnected(); bool IsConnected();
void SetHidden(bool state);
void RegisterGrabbedOverlay(Overlay *overlay);
void ReleaseOverlay(Overlay *overlay);
void Update(); void Update();
void UpdateStatus(); void UpdateStatus();
@ -30,4 +36,6 @@ class Controller
TrackerID _device_index; TrackerID _device_index;
vr::VRInputValueHandle_t _input_handle; vr::VRInputValueHandle_t _input_handle;
bool _is_connected; bool _is_connected;
bool _hidden;
std::vector<Overlay *> _grabbed_overlays;
}; };

View file

@ -1,7 +1,7 @@
#include "app.h" #include "app.h"
#include <signal.h> #include <signal.h>
#define FRAMERATE 30 #define UPDATE_RATE 60
bool should_exit = false; bool should_exit = false;
@ -19,7 +19,7 @@ int main()
while (!should_exit) while (!should_exit)
{ {
app.Update(); app.Update();
usleep(1000000 / FRAMERATE); usleep(1000000 / UPDATE_RATE);
} }
printf("\nShutting down\n"); printf("\nShutting down\n");
return 0; return 0;

View file

@ -2,7 +2,6 @@
#include "app.h" #include "app.h"
#include "util.h" #include "util.h"
#include <cstdint> #include <cstdint>
#include <glm/fwd.hpp>
Overlay::Overlay() Overlay::Overlay()
{ {
@ -17,25 +16,18 @@ Overlay::Overlay(App *app, std::string name)
_holding_controller = nullptr; _holding_controller = nullptr;
_width_m = 1; _width_m = 1;
_ratio = 1; _ratio = 1;
_hidden = false;
_target.type = TargetType::World; _target = Target{.type = TargetType::World, .transform = VRMatIdentity};
auto overlay_create_err = _app->vr_overlay->CreateOverlay(_name.c_str(), _name.c_str(), &_id); auto overlay_create_err = _app->vr_overlay->CreateOverlay(_name.c_str(), _name.c_str(), &_id);
assert(overlay_create_err == 0); assert(overlay_create_err == 0);
{
vr::ETrackingUniverseOrigin origin;
_app->vr_overlay->GetOverlayTransformAbsolute(_id, &origin, &_target.transform);
}
uint8_t col[4] = {20, 50, 50, 255};
_app->vr_overlay->SetOverlayRaw(_id, &col, 1, 1, 4);
printf("Created overlay instance %s\n", _name.c_str());
// (flipping uv on y axis because opengl and xorg are opposite) // (flipping uv on y axis because opengl and xorg are opposite)
vr::VRTextureBounds_t bounds{0, 1, 1, 0}; vr::VRTextureBounds_t bounds{0, 1, 1, 0};
_app->vr_overlay->SetOverlayTextureBounds(_id, &bounds); _app->vr_overlay->SetOverlayTextureBounds(_id, &bounds);
_hidden = false;
_app->vr_overlay->ShowOverlay(_id); _app->vr_overlay->ShowOverlay(_id);
printf("Created overlay instance %s\n", _name.c_str());
} }
OverlayID Overlay::Id() OverlayID Overlay::Id()
@ -133,11 +125,10 @@ void Overlay::SetTransformWorld(const VRMat *transform)
void Overlay::SetTargetWorld() void Overlay::SetTargetWorld()
{ {
auto abs_pose = ConvertMat(GetTransformAbsolute()); auto abs_pose = ConvertMat(GetTransformAbsolute());
_app->vr_overlay->SetOverlayTransformAbsolute(_id, vr::TrackingUniverseStanding, &abs_pose); SetTransformWorld(&abs_pose);
_target.type = TargetType::World;
} }
float Overlay::IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len) Ray Overlay::IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len)
{ {
float closest_dist = max_len; float closest_dist = max_len;
auto end = origin + direction * max_len; auto end = origin + direction * max_len;
@ -162,7 +153,7 @@ float Overlay::IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len
closest_dist = dist; closest_dist = dist;
} }
} }
return closest_dist; return Ray{.overlay = this, .distance = closest_dist};
} }
glm::mat4x4 Overlay::GetTransformAbsolute() glm::mat4x4 Overlay::GetTransformAbsolute()
@ -198,6 +189,11 @@ glm::mat4x4 Overlay::GetTransformAbsolute()
} }
} }
Target *Overlay::GetTarget()
{
return &_target;
}
void Overlay::Update() void Overlay::Update()
{ {
if (!_initialized) if (!_initialized)
@ -217,14 +213,20 @@ 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);
auto abs_mat = GetTransformAbsolute(); auto abs_mat = GetTransformAbsolute();
auto controller_mat = _app->GetTrackerPose(controller->DeviceIndex()); auto controller_mat = _app->GetTrackerPose(controller->DeviceIndex());
VRMat relative_pose = ConvertMat(glm::inverse(controller_mat) * abs_mat); VRMat relative_pose = ConvertMat(glm::inverse(controller_mat) * abs_mat);
_app->vr_overlay->SetOverlayTransformTrackedDeviceRelative(_id, controller->DeviceIndex(), &relative_pose); SetTransformTracker(controller->DeviceIndex(), &relative_pose);
controller->RegisterGrabbedOverlay(this);
if (_GrabBeginCallback != nullptr) if (_GrabBeginCallback != nullptr)
{ {
_GrabBeginCallback(controller); _GrabBeginCallback(controller);
@ -235,10 +237,14 @@ void Overlay::ControllerGrab(Controller *controller)
void Overlay::ControllerRelease() void Overlay::ControllerRelease()
{ {
if (_holding_controller != nullptr)
{
_holding_controller->ReleaseOverlay(this);
}
_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()); auto new_pose = ConvertMat(GetTransformAbsolute());
_app->vr_overlay->SetOverlayTransformAbsolute(_id, _app->_tracking_origin, &new_pose); SetTransformWorld(&new_pose);
if (_GrabEndCallback != nullptr) if (_GrabEndCallback != nullptr)
{ {

View file

@ -5,6 +5,7 @@
#include <string> #include <string>
class App; class App;
struct Ray;
class Controller; class Controller;
enum class TargetType enum class TargetType
@ -43,6 +44,7 @@ class Overlay
void SetTextureToColor(uint8_t r, uint8_t g, uint8_t b); void SetTextureToColor(uint8_t r, uint8_t g, uint8_t b);
glm::mat4x4 GetTransformAbsolute(); glm::mat4x4 GetTransformAbsolute();
Target *GetTarget();
void SetTransformTracker(TrackerID tracker, const VRMat *transform); void SetTransformTracker(TrackerID tracker, const VRMat *transform);
void SetTransformWorld(const VRMat *transform); void SetTransformWorld(const VRMat *transform);
@ -50,7 +52,7 @@ class Overlay
// void SetTargetTracker(TrackerID tracker); // void SetTargetTracker(TrackerID tracker);
void SetTargetWorld(); void SetTargetWorld();
float 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(Controller *)> _GrabBeginCallback;
std::function<void()> _GrabEndCallback; std::function<void()> _GrabEndCallback;

View file

@ -23,6 +23,7 @@ Panel::Panel(App *app, int index, int x, int y, int width, int height)
_texture.eType = vr::TextureType_OpenGL; _texture.eType = vr::TextureType_OpenGL;
_texture.handle = (void *)(uintptr_t)_gl_texture; _texture.handle = (void *)(uintptr_t)_gl_texture;
_overlay.SetRatio(height / (float)width); _overlay.SetRatio(height / (float)width);
_overlay.SetTextureToColor(50, 20, 50);
} }
void Panel::Update() void Panel::Update()