diff --git a/.gitignore b/.gitignore index 0c01b56..08047cf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1 @@ overlay -.vscode/ diff --git a/Makefile b/Makefile index 926840c..c88c265 100644 --- a/Makefile +++ b/Makefile @@ -1,17 +1,7 @@ -# CC := g++ -CC := clang++ -LFLAGS := -lX11 -lXrandr -lglfw -lGL -LIBS := openvr/libopenvr_api.so -SRC := src/*.cpp -OUT := ./overlay -CPPFLAGS := -Wall -std=c++17 $(LFLAGS) $(LIBS) $(SRC) -o $(OUT) build: - $(CC) -g $(CPPFLAGS) - -release: - $(CC) $(CPPFLAGS) + g++ -Wall -lX11 -lXrandr -lglfw -lGL openvr/libopenvr_api.so src/*.cpp -o overlay run: build ./overlay diff --git a/src/app.cpp b/src/app.cpp index 73aece3..3f8e005 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -1,4 +1,5 @@ #include "app.h" +#include "panel.h" #include #include @@ -9,7 +10,6 @@ App::App() InitOVR(); InitX11(); InitGLFW(); - InitRootOverlay(); printf("\n"); glGenTextures(1, &_gl_frame); @@ -21,23 +21,18 @@ App::App() printf("found %d monitors:\n", monitor_count); float pixels_per_meter = 1920; - float total_width_meters = _root_width / pixels_per_meter; - float total_height_meters = _root_height / pixels_per_meter; + float x_min = -(monitor_info[0].x + monitor_info[0].width / 2.0f); + // float x_min = _root_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); - _panels.push_back(Panel(this, i, mon.x, mon.y, mon.width, mon.height)); - - float width = mon.width / pixels_per_meter; - float pos_x = mon.x / pixels_per_meter + width / 2.0f - total_width_meters / 2.0f; - float height = mon.height / pixels_per_meter; - float pos_y = 1.2f + mon.y / pixels_per_meter - height / 2.0f + total_height_meters / 2.0f; - VRMat start_pose = {{{1, 0, 0, pos_x}, {0, 1, 0, pos_y}, {0, 0, 1, 0}}}; - _panels[i].GetOverlay()->SetTransformWorld(&start_pose); - _panels[i].GetOverlay()->SetWidth(width); + 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)); } { // initialize SteamVR input @@ -107,40 +102,11 @@ void App::InitGLFW() printf("Created GLFW context\n"); } -void App::InitRootOverlay() -{ - _root_overlay = Overlay(this, "root"); - _root_overlay.SetAlpha(0.2f); - // clang-format off - VRMat root_start_pose = {{ - {0.25f, 0.0f, 0.0f, 0}, - {0.0f, 0.25f, 0.0f, 0.8f}, - {0.0f, 0.0f, 1.0f, 0} - }}; - // clang-format on - _root_overlay.SetTransformWorld(&root_start_pose); - - _root_overlay._GrabBeginCallback = [this](TrackerID controller) { - for (auto &panel : _panels) - { - panel.GetOverlay()->ControllerGrab(controller); - } - }; - _root_overlay._GrabEndCallback = [this](TrackerID controller) { - for (auto &panel : _panels) - { - panel.GetOverlay()->ControllerRelease(); - } - }; - printf("Created root overlay instance\n"); -} - void App::Update() { UpdateInput(); if (!_hidden) { - _root_overlay.Update(); UpdateFramebuffer(); for (auto &panel : _panels) { @@ -163,7 +129,6 @@ void App::UpdateInput() if (IsInputJustPressed(i, _input_handles.toggle)) { _hidden = !_hidden; - _root_overlay.SetHidden(_hidden); for (auto &panel : _panels) { panel.SetHidden(_hidden); diff --git a/src/app.h b/src/app.h index ba92649..32cc25e 100644 --- a/src/app.h +++ b/src/app.h @@ -1,14 +1,14 @@ #pragma once #define GL_GLEXT_PROTOTYPES -#include "overlay.h" -#include "panel.h" #include "util.h" #include #include #include #include +class Panel; + struct CursorPos { int x, y; @@ -54,7 +54,6 @@ class App InputHandles _input_handles; vr::TrackedDevicePose_t _tracker_poses[vr::k_unMaxTrackedDeviceCount]; - Overlay _root_overlay; std::vector _panels; bool _hidden = false; @@ -62,7 +61,6 @@ class App void InitX11(); void InitOVR(); void InitGLFW(); - void InitRootOverlay(); void UpdateFramebuffer(); void UpdateInput(); diff --git a/src/grab_component.cpp b/src/grab_component.cpp new file mode 100644 index 0000000..fe1ab5b --- /dev/null +++ b/src/grab_component.cpp @@ -0,0 +1,94 @@ +#include "grab_component.h" + +GrabComponent::GrabComponent(App *app) +{ + _app = app; + _is_held = false; + _active_hand = 0; +} + +void GrabComponent::Update(OverlayID id, float *meters) +{ + _id = id; + + if (!_is_held) + { + for (auto controller : _app->GetControllers()) + { + if (_app->IsInputJustPressed(controller, _app->_input_handles.grab)) + { + vr::HmdMatrix34_t overlay_pose; + 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); + } + } + } + } + else + { + if (!_app->GetControllerInputDigital(_active_hand, _app->_input_handles.grab).bState) + { + ControllerRelease(); + } + } +} + +bool GrabComponent::IsHeld() +{ + return _is_held; +} + +TrackerID GrabComponent::ActiveHand() +{ + return _active_hand; +} + +void GrabComponent::ControllerGrab(TrackerID controller) +{ + _is_held = true; + _active_hand = controller; + + _app->vr_overlay->SetOverlayColor(_id, 0.6f, 0.8f, 0.8f); + + vr::HmdMatrix34_t abs_pose; + vr::ETrackingUniverseOrigin tracking_universe; + _app->vr_overlay->GetOverlayTransformAbsolute(_id, &tracking_universe, &abs_pose); + + auto abs_mat = ConvertMat(abs_pose); + auto controller_mat = _app->GetTrackerPose(controller); + + vr::HmdMatrix34_t relative_pose = ConvertMat(glm::inverse(controller_mat) * (abs_mat)); + + _app->vr_overlay->SetOverlayTransformTrackedDeviceRelative(_id, controller, &relative_pose); +} + +void GrabComponent::ControllerRelease() +{ + _is_held = false; + _active_hand = -1; + + _app->vr_overlay->SetOverlayColor(_id, 1.0f, 1.0f, 1.0f); + + vr::HmdMatrix34_t relative_pose; + _app->vr_overlay->GetOverlayTransformTrackedDeviceRelative(_id, &_active_hand, &relative_pose); + auto relative_mat = ConvertMat(relative_pose); + + auto controller_mat = _app->GetTrackerPose(_active_hand); + + vr::HmdMatrix34_t new_pose = ConvertMat(controller_mat * relative_mat); + + _app->vr_overlay->SetOverlayTransformAbsolute(_id, _app->_tracking_origin, &new_pose); +} \ No newline at end of file diff --git a/src/grab_component.h b/src/grab_component.h new file mode 100644 index 0000000..d746450 --- /dev/null +++ b/src/grab_component.h @@ -0,0 +1,23 @@ +#pragma once + +#include "app.h" +#include "util.h" + +class GrabComponent +{ + public: + GrabComponent(App *app); + bool IsHeld(); + TrackerID ActiveHand(); + void Update(OverlayID id, float *meters); + + private: + void ControllerRelease(); + void ControllerGrab(TrackerID controller); + + App *_app; + OverlayID _id; + + bool _is_held; + TrackerID _active_hand; +}; \ No newline at end of file diff --git a/src/overlay.cpp b/src/overlay.cpp deleted file mode 100644 index 74812e7..0000000 --- a/src/overlay.cpp +++ /dev/null @@ -1,222 +0,0 @@ -#include "overlay.h" -#include "app.h" -#include "util.h" -#include - -Overlay::Overlay() -{ - _initialized = false; -} - -Overlay::Overlay(App *app, std::string name) -{ - _initialized = true; - _name = name; - _app = app; - _is_held = false; - _active_hand = 0; - _width_m = 1; - - _target.type = TargetType::World; - - auto overlay_create_err = _app->vr_overlay->CreateOverlay(_name.c_str(), _name.c_str(), &_id); - 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) - vr::VRTextureBounds_t bounds{0, 1, 1, 0}; - _app->vr_overlay->SetOverlayTextureBounds(_id, &bounds); - SetHidden(false); -} - -OverlayID Overlay::Id() -{ - return _id; -} - -bool Overlay::IsHeld() -{ - return _is_held; -} - -TrackerID Overlay::ActiveHand() -{ - return _active_hand; -} - -bool Overlay::IsHidden() -{ - return _hidden; -} - -float Overlay::Alpha() -{ - return _alpha; -} - -float Overlay::Width() -{ - return _width_m; -} - -void Overlay::SetWidth(float width_meters) -{ - _width_m = width_meters; - _app->vr_overlay->SetOverlayWidthInMeters(_id, _width_m); -} - -void Overlay::SetHidden(bool state) -{ - _hidden = state; - if (_hidden) - _app->vr_overlay->HideOverlay(_id); - else - _app->vr_overlay->ShowOverlay(_id); -} - -void Overlay::SetAlpha(float alpha) -{ - _alpha = alpha; - _app->vr_overlay->SetOverlayAlpha(_id, alpha); -} - -void Overlay::SetTexture(vr::Texture_t *texture) -{ - auto set_texture_err = _app->vr_overlay->SetOverlayTexture(_id, texture); - assert(set_texture_err == 0); -} - -void Overlay::SetTransformTracker(TrackerID tracker, VRMat *transform) -{ - _app->vr_overlay->SetOverlayTransformTrackedDeviceRelative(_id, tracker, transform); - _target.type = TargetType::Tracker; - _target.id = tracker; - _target.transform = *transform; -} - -void Overlay::SetTransformWorld(VRMat *transform) -{ - _app->vr_overlay->SetOverlayTransformAbsolute(_id, vr::TrackingUniverseStanding, transform); - _target.type = TargetType::World; - _target.transform = *transform; -} - -void Overlay::SetTargetWorld() -{ - auto abs_pose = ConvertMat(GetTransformAbsolute()); - _app->vr_overlay->SetOverlayTransformAbsolute(_id, vr::TrackingUniverseStanding, &abs_pose); - _target.type = TargetType::World; -} - -glm::mat4x4 Overlay::GetTransformAbsolute() -{ - if (_is_held) - { - VRMat pose; - auto err = _app->vr_overlay->GetOverlayTransformTrackedDeviceRelative(_id, &_active_hand, &pose); - assert(err == 0); - auto offset = ConvertMat(pose); - auto controller = _app->GetTrackerPose(_active_hand); - return controller * offset; - } - else - { - 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; - } - } - } -} - -void Overlay::Update() -{ - if (!_initialized) - { - printf("Error: overlay %s is not initialized.\n", _name.c_str()); - assert(_initialized); - } - - if (!_is_held) - { - for (auto controller : _app->GetControllers()) - { - if (_app->IsInputJustPressed(controller, _app->_input_handles.grab)) - { - auto overlay_pose = GetTransformAbsolute(); - auto controller_pos = GetPos(_app->GetTrackerPose(controller)); - - auto local_pos = glm::inverse(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) < _width_m / 2.0f; - close_enough &= glm::abs(local_pos.y) < _width_m / 2.0f; - - if (close_enough) - { - ControllerGrab(controller); - } - } - } - } - else - { - if (!_app->GetControllerInputDigital(_active_hand, _app->_input_handles.grab).bState) - { - ControllerRelease(); - } - } -} - -void Overlay::ControllerGrab(TrackerID controller) -{ - _app->vr_overlay->SetOverlayColor(_id, 0.6f, 0.8f, 0.8f); - - auto abs_mat = GetTransformAbsolute(); - auto controller_mat = _app->GetTrackerPose(controller); - VRMat relative_pose = ConvertMat(glm::inverse(controller_mat) * abs_mat); - - _app->vr_overlay->SetOverlayTransformTrackedDeviceRelative(_id, controller, &relative_pose); - - if (_GrabBeginCallback != nullptr) - { - _GrabBeginCallback(controller); - } - - _is_held = true; - _active_hand = controller; -} - -void Overlay::ControllerRelease() -{ - _app->vr_overlay->SetOverlayColor(_id, 1.0f, 1.0f, 1.0f); - - auto new_pose = ConvertMat(GetTransformAbsolute()); - _app->vr_overlay->SetOverlayTransformAbsolute(_id, _app->_tracking_origin, &new_pose); - - if (_GrabEndCallback != nullptr) - { - _GrabEndCallback(_active_hand); - } - _is_held = false; - _active_hand = -1; -} diff --git a/src/overlay.h b/src/overlay.h deleted file mode 100644 index 8dd7aea..0000000 --- a/src/overlay.h +++ /dev/null @@ -1,69 +0,0 @@ -#pragma once - -#include "util.h" -#include -#include - -class App; - -enum class TargetType -{ - World, - Tracker, -}; - -struct Target -{ - TargetType type; - TrackerID id; - VRMat transform; -}; - -class Overlay -{ - public: - Overlay(); - Overlay(App *app, std::string name); - void Update(); - - OverlayID Id(); - bool IsHeld(); - bool IsHidden(); - TrackerID ActiveHand(); - float Width(); - float Alpha(); - - void SetWidth(float meters); - void SetHidden(bool state); - void SetAlpha(float alpha); - void SetTexture(vr::Texture_t *texture); - - void SetTransformTracker(TrackerID tracker, VRMat *transform); - void SetTransformWorld(VRMat *transform); - - // void SetTargetTracker(TrackerID tracker); - void SetTargetWorld(); - - std::function _GrabBeginCallback; - std::function _GrabEndCallback; - - void ControllerRelease(); - void ControllerGrab(TrackerID controller); - - private: - glm::mat4x4 GetTransformAbsolute(); - - bool _initialized; - - App *_app; - OverlayID _id; - - std::string _name; - bool _is_held; - bool _hidden; - float _width_m; - float _alpha; - TrackerID _active_hand; - - Target _target; -}; \ No newline at end of file diff --git a/src/panel.cpp b/src/panel.cpp index 36573f5..ceba71d 100644 --- a/src/panel.cpp +++ b/src/panel.cpp @@ -1,16 +1,18 @@ #include "panel.h" -#include "app.h" -#include "overlay.h" -Panel::Panel(App *app, int index, int x, int y, int width, int height) +Panel::Panel(App *app, vr::HmdMatrix34_t start_pose, int index, int x, int y, int width, int height) : _app(app), _index(index), _x(x), _y(y), _width(width), _height(height), - _overlay(app, "screen_view_" + std::to_string(index)) + _grab_component(app) { + _name = "screen_view_" + std::to_string(index); + _alpha = 1.0f; + _meters = 1.0f; + glGenTextures(1, &_gl_texture); glBindTexture(GL_TEXTURE_2D, _gl_texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -23,7 +25,20 @@ Panel::Panel(App *app, int index, int x, int y, int width, int height) _texture.eType = vr::TextureType_OpenGL; _texture.handle = (void *)(uintptr_t)_gl_texture; - // _overlay; + // create overlay + { + auto overlay_create_err = _app->vr_overlay->CreateOverlay(_name.c_str(), _name.c_str(), &_id); + assert(overlay_create_err == 0); + _app->vr_overlay->ShowOverlay(_id); + uint8_t col[4] = {20, 50, 50, 255}; + _app->vr_overlay->SetOverlayRaw(_id, &col, 1, 1, 4); + printf("Created overlay instance %d\n", _index); + + // (flipping uv on y axis because opengl and xorg are opposite) + vr::VRTextureBounds_t bounds{0, 1, 1, 0}; + _app->vr_overlay->SetOverlayTextureBounds(_id, &bounds); + _app->vr_overlay->SetOverlayTransformAbsolute(_id, _app->_tracking_origin, &start_pose); + } } void Panel::Update() @@ -31,12 +46,7 @@ void Panel::Update() Render(); UpdateCursor(); - _overlay.Update(); -} - -Overlay *Panel::GetOverlay() -{ - return &_overlay; + _grab_component.Update(_id, &_meters); } void Panel::Render() @@ -48,12 +58,17 @@ void Panel::Render() 0, 0, 0, _width, _height, 1); - _overlay.SetTexture(&_texture); + auto set_texture_err = _app->vr_overlay->SetOverlayTexture(_id, &_texture); + assert(set_texture_err == 0); } void Panel::SetHidden(bool state) { - _overlay.SetHidden(state); + _hidden = state; + if (state) + _app->vr_overlay->HideOverlay(_id); + else + _app->vr_overlay->ShowOverlay(_id); } void Panel::UpdateCursor() @@ -61,7 +76,7 @@ void Panel::UpdateCursor() auto global_pos = _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(_overlay.Id()); + _app->vr_overlay->ClearOverlayCursorPositionOverride(_id); return; } int local_x = global_pos.x - _x; @@ -73,5 +88,5 @@ void Panel::UpdateCursor() float x = local_x / (float)_width; float y = 1.0f - (local_y / (float)_width + top_edge); auto pos = vr::HmdVector2_t{x, y}; - _app->vr_overlay->SetOverlayCursorPositionOverride(_overlay.Id(), &pos); + _app->vr_overlay->SetOverlayCursorPositionOverride(_id, &pos); } diff --git a/src/panel.h b/src/panel.h index eb635db..43d0b42 100644 --- a/src/panel.h +++ b/src/panel.h @@ -1,36 +1,38 @@ #pragma once -#include "overlay.h" #define GL_GLEXT_PROTOTYPES +#include "grab_component.h" #include "util.h" #include -const VRMat 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 Overlay; class Panel { public: - Panel(App *app, int index, int xmin, int xmax, int ymin, int ymax); + Panel(App *app, vr::HmdMatrix34_t start_pose, int index, int xmin, int xmax, int ymin, int ymax); void Update(); void SetHidden(bool state); - Overlay *GetOverlay(); - private: void Render(); void UpdateCursor(); App *_app; + OverlayID _id; int _index; + std::string _name; int _x, _y; int _width, _height; + float _meters; + float _alpha; + bool _hidden; - Overlay _overlay; + GrabComponent _grab_component; vr::Texture_t _texture; GLuint _gl_texture; diff --git a/src/util.h b/src/util.h index 739e065..4b52b6a 100644 --- a/src/util.h +++ b/src/util.h @@ -5,9 +5,8 @@ typedef vr::TrackedDeviceIndex_t TrackerID; typedef vr::VROverlayHandle_t OverlayID; -typedef vr::HmdMatrix34_t VRMat; -inline void PrintMat(VRMat m) +inline void PrintMat(vr::HmdMatrix34_t m) { printf("[%.2f, %.2f, %.2f, %.2f]\n", m.m[0][0], m.m[0][1], m.m[0][2], m.m[0][3]); printf("[%.2f, %.2f, %.2f, %.2f]\n", m.m[1][0], m.m[1][1], m.m[1][2], m.m[1][3]); @@ -22,7 +21,7 @@ inline void PrintMat(glm::mat4x4 m) printf("[%.2f, %.2f, %.2f, %.2f]\n", m[3][0], m[3][1], m[3][2], m[3][3]); } -inline glm::mat4x4 ConvertMat(VRMat mat) +inline glm::mat4x4 ConvertMat(vr::HmdMatrix34_t mat) { auto m = mat.m; return glm::mat4x4( @@ -32,10 +31,10 @@ inline glm::mat4x4 ConvertMat(VRMat mat) m[0][3], m[1][3], m[2][3], 1); } -inline VRMat ConvertMat(glm::mat4x4 m) +inline vr::HmdMatrix34_t ConvertMat(glm::mat4x4 m) { // clang-format off - return VRMat{{ + return vr::HmdMatrix34_t{{ {m[0][0], m[1][0], m[2][0], m[3][0]}, {m[0][1], m[1][1], m[2][1], m[3][1]}, {m[0][2], m[1][2], m[2][2], m[3][2]} @@ -48,7 +47,7 @@ inline glm::vec3 GetPos(glm::mat4x4 mat) return glm::vec3(mat[3][0], mat[3][1], mat[3][2]); } -inline glm::vec3 GetPos(VRMat mat) +inline glm::vec3 GetPos(vr::HmdMatrix34_t mat) { return glm::vec3(mat.m[0][3], mat.m[1][3], mat.m[2][3]); }