Compare commits

..

No commits in common. "4bc69f2e53dab10cbc6a02abeaeb271a52ea8d62" and "e4a79eefd316b4ca7ceac90bf958bc707c47b0cb" have entirely different histories.

6 changed files with 52 additions and 136 deletions

View file

@ -1,7 +1,7 @@
build: build:
CPATH=. g++ -Wall -lX11 -lXrandr -lglfw -lGL openvr/libopenvr_api.so src/*.cpp -o overlay CPATH=. g++ -Wall -lX11 -lglfw -lGL openvr/libopenvr_api.so src/*.cpp -o overlay
run: build run: build
./overlay ./overlay

View file

@ -1,39 +1,17 @@
#include "app.h" #include "app.h"
#include "panel.h" #include "panel.h"
#include "util.h" #include "util.h"
#include <X11/extensions/Xrandr.h>
#include <cassert> #include <cassert>
App::App() App::App()
{ {
_tracking_origin = vr::TrackingUniverseStanding; _tracking_origin = vr::ETrackingUniverseOrigin::TrackingUniverseStanding;
InitOVR(); InitOVR();
InitX11(); InitX11();
InitGLFW(); InitGLFW();
printf("\n");
glGenTextures(1, &_gl_frame); _panels.push_back(Panel(this, 0, 0, 0, _root_width, _root_height));
glBindTexture(GL_TEXTURE_2D, _gl_frame);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
int monitor_count;
XRRMonitorInfo *monitor_info = XRRGetMonitors(_xdisplay, _root_window, 1, &monitor_count);
printf("found %d monitors:\n", monitor_count);
float pixels_per_meter = 1920;
float x_min = -(monitor_info[0].x + monitor_info[0].width / 2.0f);
for (int i = 0; i < monitor_count; i++)
{
XRRMonitorInfo mon = monitor_info[i];
printf("screen %d: pos(%d, %d) %dx%d\n", i, mon.x, mon.y, mon.width, mon.height);
float pos_x = (x_min + mon.x) / pixels_per_meter;
float pos_y = 1.2f;
vr::HmdMatrix34_t start_pose = {{{1, 0, 0, pos_x}, {0, 1, 0, pos_y}, {0, 0, 1, 0}}};
_panels.push_back(Panel(this, start_pose, i, mon.x, mon.y, mon.width, mon.height));
}
} }
App::~App() App::~App()
@ -58,9 +36,8 @@ void App::InitX11()
void App::InitOVR() void App::InitOVR()
{ {
vr::EVRInitError init_err; vr::EVRInitError init_err;
// would normally be using VRApplication_Overlay, but Background allows it to quit if steamvr is not running, instead of opening steamvr. vr_sys = vr::VR_Init(&init_err, vr::EVRApplicationType::VRApplication_Background);
vr_sys = vr::VR_Init(&init_err, vr::VRApplication_Background); if (init_err == vr::EVRInitError::VRInitError_Init_NoServerForBackgroundApp)
if (init_err == vr::VRInitError_Init_NoServerForBackgroundApp)
{ {
printf("SteamVR is not running\n"); printf("SteamVR is not running\n");
exit(1); exit(1);
@ -78,7 +55,7 @@ void App::InitGLFW()
{ {
assert(glfwInit() == true); assert(glfwInit() == true);
glfwWindowHint(GLFW_VISIBLE, false); glfwWindowHint(GLFW_VISIBLE, false);
// creating a 1x1 window, since it is hidden anyway // TODO this is creating a 1x1 window, should it be bigger?
_gl_window = glfwCreateWindow(1, 1, "Overlay", nullptr, nullptr); _gl_window = glfwCreateWindow(1, 1, "Overlay", nullptr, nullptr);
assert(_gl_window != nullptr); assert(_gl_window != nullptr);
glfwMakeContextCurrent(_gl_window); glfwMakeContextCurrent(_gl_window);
@ -87,31 +64,12 @@ void App::InitGLFW()
void App::Update() void App::Update()
{ {
auto frame = XGetImage(
_xdisplay,
_root_window,
0, 0,
_root_width, _root_height,
AllPlanes,
ZPixmap);
glBindTexture(GL_TEXTURE_2D, _gl_frame);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _root_width, _root_height, 0, GL_BGRA, GL_UNSIGNED_BYTE, frame->data);
XDestroyImage(frame);
for (auto &panel : _panels) for (auto &panel : _panels)
{ {
panel.Update(); panel.Update();
} }
} }
std::vector<TrackerID> App::GetControllers()
{
static const auto max_len = 64;
TrackerID controllers[max_len];
int controller_count = vr_sys->GetSortedTrackedDeviceIndicesOfClass(vr::TrackedDeviceClass_Controller, controllers, max_len);
return std::vector<TrackerID>(controllers, controllers + controller_count);
}
glm::mat4 App::GetTrackerPose(TrackerID tracker) glm::mat4 App::GetTrackerPose(TrackerID tracker)
{ {
vr::VRControllerState_t state; vr::VRControllerState_t state;
@ -125,24 +83,21 @@ glm::mat4 App::GetTrackerPose(TrackerID tracker)
return ConvertMat(tracked_pose.mDeviceToAbsoluteTracking); return ConvertMat(tracked_pose.mDeviceToAbsoluteTracking);
} }
vr::VRControllerState_t App::GetControllerState(TrackerID controller) bool App::IsGrabActive(vr::TrackedDeviceIndex_t controller)
{
vr::VRControllerState_t state;
auto get_state_err = vr_sys->GetControllerState(controller, &state, sizeof(vr::VRControllerState_t));
if (get_state_err == false)
printf("failed to get state of controller %d\n", controller);
return state;
}
bool App::IsGrabActive(TrackerID controller)
{ {
vr::VRControllerState_t state; vr::VRControllerState_t state;
auto get_state_err = vr_sys->GetControllerState(controller, &state, sizeof(vr::VRControllerState_t)); auto get_state_err = vr_sys->GetControllerState(controller, &state, sizeof(vr::VRControllerState_t));
if (get_state_err == false) if (get_state_err == false)
{
printf("Error getting controller state: %d\n", get_state_err);
return false; return false;
}
// printf("got state\n");
auto trigger_mask = vr::ButtonMaskFromId(vr::k_EButton_SteamVR_Trigger); auto trigger_mask = vr::ButtonMaskFromId(vr::EVRButtonId::k_EButton_SteamVR_Trigger);
return state.ulButtonPressed & trigger_mask; auto b_mask = vr::ButtonMaskFromId(vr::EVRButtonId::k_EButton_IndexController_B);
auto mask = trigger_mask | b_mask;
return (state.ulButtonPressed & mask) == mask;
} }
CursorPos App::GetCursorPosition() CursorPos App::GetCursorPosition()

View file

@ -1,4 +1,3 @@
#define GL_GLEXT_PROTOTYPES
#include "util.h" #include "util.h"
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <X11/Xutil.h> #include <X11/Xutil.h>
@ -18,16 +17,13 @@ class App
~App(); ~App();
void Update(); void Update();
std::vector<TrackerID> GetControllers();
glm::mat4 GetTrackerPose(TrackerID tracker); glm::mat4 GetTrackerPose(TrackerID tracker);
vr::VRControllerState_t GetControllerState(TrackerID controller); bool IsGrabActive(vr::TrackedDeviceIndex_t controller);
bool IsGrabActive(TrackerID controller);
CursorPos GetCursorPosition(); CursorPos GetCursorPosition();
Display *_xdisplay; Display *_xdisplay;
Window _root_window; Window _root_window;
GLFWwindow *_gl_window; GLFWwindow *_gl_window;
GLuint _gl_frame;
int _root_width; int _root_width;
int _root_height; int _root_height;

View file

@ -2,11 +2,11 @@
#include "app.h" #include "app.h"
#include "util.h" #include "util.h"
#include <GLFW/glfw3.h>
#include <X11/Xutil.h> #include <X11/Xutil.h>
#include <glm/common.hpp>
#include <glm/glm.hpp> #include <glm/glm.hpp>
Panel::Panel(App *app, vr::HmdMatrix34_t start_pose, int index, int x, int y, int width, int height) Panel::Panel(App *app, int index, int x, int y, int width, int height)
: _app(app), : _app(app),
_index(index), _index(index),
_x(x), _x(x),
@ -16,18 +16,12 @@ Panel::Panel(App *app, vr::HmdMatrix34_t start_pose, int index, int x, int y, in
{ {
_name = "screen_view_" + std::to_string(index); _name = "screen_view_" + std::to_string(index);
_alpha = 1.0f; _alpha = 1.0f;
_meters = 1.0f;
_active_hand = -1; _active_hand = -1;
glGenTextures(1, &_gl_texture); glGenTextures(1, &_gl_texture);
glBindTexture(GL_TEXTURE_2D, _gl_texture); glBindTexture(GL_TEXTURE_2D, _gl_texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(
GL_TEXTURE_2D, 0, GL_RGB,
_width, _height, 0,
GL_BGRA, GL_UNSIGNED_BYTE, 0);
_texture.eColorSpace = vr::ColorSpace_Auto; _texture.eColorSpace = vr::EColorSpace::ColorSpace_Auto;
_texture.eType = vr::TextureType_OpenGL; _texture.eType = vr::ETextureType::TextureType_OpenGL;
_texture.handle = (void *)(uintptr_t)_gl_texture; _texture.handle = (void *)(uintptr_t)_gl_texture;
// create overlay // create overlay
@ -35,6 +29,7 @@ Panel::Panel(App *app, vr::HmdMatrix34_t start_pose, int index, int x, int y, in
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);
_app->vr_overlay->ShowOverlay(_id); _app->vr_overlay->ShowOverlay(_id);
_app->vr_overlay->SetOverlayWidthInMeters(_id, 2.5f);
uint8_t col[4] = {20, 50, 50, 255}; uint8_t col[4] = {20, 50, 50, 255};
_app->vr_overlay->SetOverlayRaw(_id, &col, 1, 1, 4); _app->vr_overlay->SetOverlayRaw(_id, &col, 1, 1, 4);
printf("Created overlay instance %d\n", _index); printf("Created overlay instance %d\n", _index);
@ -42,7 +37,8 @@ Panel::Panel(App *app, vr::HmdMatrix34_t start_pose, int index, int x, int y, in
// (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);
_app->vr_overlay->SetOverlayTransformAbsolute(_id, _app->_tracking_origin, &start_pose);
_app->vr_overlay->SetOverlayTransformAbsolute(_id, _app->_tracking_origin, &DEFAULT_POSE);
} }
} }
@ -53,27 +49,27 @@ void Panel::Update()
if (!_is_held) if (!_is_held)
{ {
for (auto controller : _app->GetControllers()) vr::TrackedDeviceIndex_t controllers[8];
auto controller_count = _app->vr_sys->GetSortedTrackedDeviceIndicesOfClass(vr::ETrackedDeviceClass::TrackedDeviceClass_Controller, controllers, 8);
for (unsigned int i = 0; i < controller_count; i++)
{ {
if (_app->IsGrabActive(controller)) auto controller = controllers[i];
vr::HmdMatrix34_t overlay_pose;
vr::ETrackingUniverseOrigin tracking_universe;
_app->vr_overlay->GetOverlayTransformAbsolute(_id, &tracking_universe, &overlay_pose);
auto controller_pose = _app->GetTrackerPose(controller);
auto controller_pos = glm::vec3(controller_pose[3]);
auto overlay_pos = glm::vec3(ConvertMat(overlay_pose)[3]);
bool close_enough = glm::length(overlay_pos - controller_pos) < 1.0f;
// close_enough = true;
if (close_enough && _app->IsGrabActive(controller))
{ {
vr::HmdMatrix34_t overlay_pose; ControllerGrab(controller);
vr::ETrackingUniverseOrigin tracking_universe;
_app->vr_overlay->GetOverlayTransformAbsolute(_id, &tracking_universe, &overlay_pose);
auto controller_pos = GetPos(_app->GetTrackerPose(controller));
auto local_pos = glm::inverse(ConvertMat(overlay_pose)) * glm::vec4(controller_pos - GetPos(overlay_pose), 0);
float grab_area_thickness = 0.3f;
bool close_enough = glm::abs(local_pos.z) < grab_area_thickness;
close_enough &= glm::abs(local_pos.x) < _meters / 2.0f;
close_enough &= glm::abs(local_pos.y) < _meters / 2.0f;
if (close_enough)
{
ControllerGrab(controller);
}
} }
} }
} }
@ -83,26 +79,14 @@ void Panel::Update()
{ {
ControllerRelease(); ControllerRelease();
} }
auto state = _app->GetControllerState(_active_hand);
auto touchpad = state.rAxis[0];
if (touchpad.x != 0.0f)
{
// TODO take into account the current framerate
_alpha += touchpad.x * 0.05;
_alpha = glm::clamp(_alpha, 0.1f, 1.0f);
_app->vr_overlay->SetOverlayAlpha(_id, _alpha);
}
} }
} }
void Panel::Render() void Panel::Render()
{ {
glCopyImageSubData( auto frame = XGetImage(_app->_xdisplay, _app->_root_window, _x, _y, _width, _height, AllPlanes, ZPixmap);
_app->_gl_frame, GL_TEXTURE_2D, 0, glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _width, _height, 0, GL_BGRA, GL_UNSIGNED_BYTE, frame->data);
_x, _y, 0, XDestroyImage(frame);
_gl_texture, GL_TEXTURE_2D, 0,
0, 0, 0,
_width, _height, 1);
auto set_texture_err = _app->vr_overlay->SetOverlayTexture(_id, &_texture); auto set_texture_err = _app->vr_overlay->SetOverlayTexture(_id, &_texture);
assert(set_texture_err == 0); assert(set_texture_err == 0);
@ -110,20 +94,13 @@ void Panel::Render()
void Panel::UpdateCursor() void Panel::UpdateCursor()
{ {
auto global_pos = _app->GetCursorPosition(); auto global = _app->GetCursorPosition();
if (global_pos.x < _x || global_pos.x >= _x + _width || global_pos.y < _y || global_pos.y >= _y + _height)
{
_app->vr_overlay->ClearOverlayCursorPositionOverride(_id);
return;
}
int local_x = global_pos.x - _x;
int local_y = global_pos.y - _y;
// TODO: make this work when aspect ratio is >1 (root window is taller than it is wide) // TODO: make this work when aspect ratio is >1 (root window is taller than it is wide)
// TODO take into account that the panel is smaller than the root window
float ratio = (float)_height / (float)_width; float ratio = (float)_height / (float)_width;
float top_edge = 0.5f - ratio / 2.0f; float top_edge = 0.5f - ratio / 2.0f;
float x = local_x / (float)_width; float x = global.x / (float)_width;
float y = 1.0f - (local_y / (float)_width + top_edge); float y = 1.0f - (global.y / (float)_width + top_edge);
auto pos = vr::HmdVector2_t{x, y}; auto pos = vr::HmdVector2_t{x, y};
_app->vr_overlay->SetOverlayCursorPositionOverride(_id, &pos); _app->vr_overlay->SetOverlayCursorPositionOverride(_id, &pos);
} }
@ -134,8 +111,6 @@ void Panel::ControllerGrab(TrackerID controller)
_is_held = true; _is_held = true;
_active_hand = controller; _active_hand = controller;
_app->vr_overlay->SetOverlayColor(_id, 0.6f, 1.0f, 1.0f);
vr::HmdMatrix34_t abs_pose; vr::HmdMatrix34_t abs_pose;
vr::ETrackingUniverseOrigin tracking_universe; vr::ETrackingUniverseOrigin tracking_universe;
@ -154,8 +129,6 @@ void Panel::ControllerRelease()
printf("Released panel %d\n", _index); printf("Released panel %d\n", _index);
_is_held = false; _is_held = false;
_app->vr_overlay->SetOverlayColor(_id, 1.0f, 1.0f, 1.0f);
vr::HmdMatrix34_t relative_pose; vr::HmdMatrix34_t relative_pose;
_app->vr_overlay->GetOverlayTransformTrackedDeviceRelative(_id, &_active_hand, &relative_pose); _app->vr_overlay->GetOverlayTransformTrackedDeviceRelative(_id, &_active_hand, &relative_pose);
auto relative_mat = ConvertMat(relative_pose); auto relative_mat = ConvertMat(relative_pose);

View file

@ -1,16 +1,14 @@
#define GL_GLEXT_PROTOTYPES
#include "util.h" #include "util.h"
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <string> #include <string>
const vr::HmdMatrix34_t DEFAULT_POSE = {{{1, 0, 0, 0}, {0, 1, 0, 1}, {0, 0, 1, 0}}}; const vr::HmdMatrix34_t DEFAULT_POSE = {{{1, 0, 0, 0}, {0, 1, 0, 1}, {0, 0, 1, 0}}};
class App; class App;
class Panel class Panel
{ {
public: public:
Panel(App *app, vr::HmdMatrix34_t start_pose, int index, int xmin, int xmax, int ymin, int ymax); Panel(App *app, int index, int xmin, int xmax, int ymin, int ymax);
void Update(); void Update();
@ -28,9 +26,8 @@ class Panel
TrackerID _active_hand; TrackerID _active_hand;
bool _is_held; bool _is_held;
int _x, _y; unsigned int _x, _y;
int _width, _height; unsigned int _width, _height;
float _meters;
float _alpha; float _alpha;
vr::Texture_t _texture; vr::Texture_t _texture;

View file

@ -46,8 +46,3 @@ inline glm::vec3 GetPos(glm::mat4x4 mat)
{ {
return glm::vec3(mat[3][0], mat[3][1], mat[3][2]); return glm::vec3(mat[3][0], mat[3][1], mat[3][2]);
} }
inline glm::vec3 GetPos(vr::HmdMatrix34_t mat)
{
return glm::vec3(mat.m[0][3], mat.m[1][3], mat.m[2][3]);
}