mirror of
https://github.com/CrispyPin/sinpin-vr.git
synced 2024-11-23 02:20:26 +01:00
Compare commits
3 commits
14b5c8f745
...
895bec3bd5
Author | SHA1 | Date | |
---|---|---|---|
895bec3bd5 | |||
e73e9b12f8 | |||
00566021a0 |
9 changed files with 100 additions and 33 deletions
|
@ -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.
|
||||||
|
|
||||||
|
|
29
src/app.cpp
29
src/app.cpp
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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()
|
||||||
|
|
Loading…
Reference in a new issue