diff --git a/Makefile b/Makefile index e42894c..c88c265 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ build: - CPATH=. g++ -Wall -lX11 -lXrandr -lglfw -lGL openvr/libopenvr_api.so src/*.cpp -o overlay + g++ -Wall -lX11 -lXrandr -lglfw -lGL openvr/libopenvr_api.so src/*.cpp -o overlay run: build ./overlay diff --git a/bindings/action_manifest.json b/bindings/action_manifest.json new file mode 100644 index 0000000..ddd3886 --- /dev/null +++ b/bindings/action_manifest.json @@ -0,0 +1,40 @@ +{ + "default_bindings": [ + { + "controller_type": "knuckles", + "binding_url": "index_controller.json" + } + ], + "actions": [ + { + "name": "/actions/main/in/ToggleAll", + "requirement": "mandatory", + "type": "boolean" + }, + { + "name": "/actions/main/in/Grab", + "requirement": "mandatory", + "type": "boolean" + }, + { + "name": "/actions/main/in/Distance", + "requirement": "suggested", + "type": "vector2" + } + ], + "action_sets": [ + { + "name": "/actions/main", + "usage": "leftright" + } + ], + "localization": [ + { + "language_tag": "en_us", + "/actions/main": "Overlay actions", + "/actions/main/in/ToggleAll": "Toggle all", + "/actions/main/in/Grab": "Grab panel", + "/actions/main/in/Distance": "Move away" + } + ] +} \ No newline at end of file diff --git a/bindings/index_controller.json b/bindings/index_controller.json new file mode 100644 index 0000000..ebfb3c8 --- /dev/null +++ b/bindings/index_controller.json @@ -0,0 +1,33 @@ +{ + "/actions/main": { + "sources": [ + { + "path": "/user/hand/right/input/b", + "mode": "button", + "inputs": { + "long": { + "output": "/actions/main/in/toggleall" + } + } + }, + { + "path": "/user/hand/right/input/thumbstick", + "mode": "joystick", + "inputs": { + "position": { + "output": "/actions/main/in/distance" + } + } + }, + { + "path": "/user/hand/right/input/trigger", + "mode": "button", + "inputs": { + "click": { + "output": "/actions/main/in/grab" + } + } + } + ] + } +} \ No newline at end of file diff --git a/src/app.cpp b/src/app.cpp index 2381e78..3f8e005 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -1,6 +1,5 @@ #include "app.h" #include "panel.h" -#include "util.h" #include #include @@ -23,6 +22,7 @@ App::App() float pixels_per_meter = 1920; 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++) { @@ -34,6 +34,22 @@ App::App() 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 + auto exe_path = std::filesystem::read_symlink("/proc/self/exe"); + _actions_path = exe_path.parent_path().string() + "/bindings/action_manifest.json"; + printf("actions path: %s\n", _actions_path.c_str()); + vr_input->SetActionManifestPath(_actions_path.c_str()); + + auto action_err = vr_input->GetActionHandle("/actions/main/in/Grab", &_input_handles.grab); + assert(action_err == 0); + action_err = vr_input->GetActionHandle("/actions/main/in/ToggleAll", &_input_handles.toggle); + assert(action_err == 0); + action_err = vr_input->GetActionHandle("/actions/main/in/Distance", &_input_handles.distance); + assert(action_err == 0); + action_err = vr_input->GetActionSetHandle("/actions/main", &_input_handles.set); + assert(action_err == 0); + } } App::~App() @@ -72,6 +88,7 @@ void App::InitOVR() } printf("Initialized OpenVR\n"); vr_overlay = vr::VROverlay(); + vr_input = vr::VRInput(); } void App::InitGLFW() @@ -86,6 +103,42 @@ void App::InitGLFW() } void App::Update() +{ + UpdateInput(); + if (!_hidden) + { + UpdateFramebuffer(); + for (auto &panel : _panels) + { + panel.Update(); + } + } +} + +void App::UpdateInput() +{ + vr::VRActiveActionSet_t main; + main.ulActionSet = _input_handles.set; + main.ulRestrictedToDevice = 0; + vr_input->UpdateActionState(&main, sizeof(vr::VRActiveActionSet_t), 1); + + vr_sys->GetDeviceToAbsoluteTrackingPose(_tracking_origin, 0, _tracker_poses, vr::k_unMaxTrackedDeviceCount); + + for (unsigned int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) + { + if (IsInputJustPressed(i, _input_handles.toggle)) + { + _hidden = !_hidden; + for (auto &panel : _panels) + { + panel.SetHidden(_hidden); + } + break; + } + } +} + +void App::UpdateFramebuffer() { auto frame = XGetImage( _xdisplay, @@ -97,11 +150,6 @@ void App::Update() 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) - { - panel.Update(); - } } std::vector App::GetControllers() @@ -114,35 +162,27 @@ std::vector App::GetControllers() glm::mat4 App::GetTrackerPose(TrackerID tracker) { - vr::VRControllerState_t state; - vr::TrackedDevicePose_t tracked_pose; - vr_sys->GetControllerStateWithPose( - _tracking_origin, - tracker, - &state, - sizeof(vr::VRControllerState_t), - &tracked_pose); - return ConvertMat(tracked_pose.mDeviceToAbsoluteTracking); + return ConvertMat(_tracker_poses[tracker].mDeviceToAbsoluteTracking); } -vr::VRControllerState_t App::GetControllerState(TrackerID controller) +vr::InputDigitalActionData_t App::GetControllerInputDigital(TrackerID controller, vr::VRActionHandle_t action) { - 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); + vr::InputDigitalActionData_t state; + vr_input->GetDigitalActionData(action, &state, sizeof(vr::InputDigitalActionData_t), 0); return state; } -bool App::IsGrabActive(TrackerID controller) +vr::InputAnalogActionData_t App::GetControllerInputAnalog(TrackerID controller, vr::VRActionHandle_t action) { - vr::VRControllerState_t state; - auto get_state_err = vr_sys->GetControllerState(controller, &state, sizeof(vr::VRControllerState_t)); - if (get_state_err == false) - return false; + vr::InputAnalogActionData_t state; + vr_input->GetAnalogActionData(action, &state, sizeof(vr::InputAnalogActionData_t), 0); + return state; +} - auto trigger_mask = vr::ButtonMaskFromId(vr::k_EButton_SteamVR_Trigger); - return state.ulButtonPressed & trigger_mask; +bool App::IsInputJustPressed(TrackerID controller, vr::VRActionHandle_t action) +{ + auto data = GetControllerInputDigital(controller, action); + return data.bState && data.bChanged; } CursorPos App::GetCursorPosition() diff --git a/src/app.h b/src/app.h index d881b2e..32cc25e 100644 --- a/src/app.h +++ b/src/app.h @@ -1,7 +1,10 @@ +#pragma once #define GL_GLEXT_PROTOTYPES + #include "util.h" #include #include +#include #include class Panel; @@ -11,6 +14,14 @@ struct CursorPos int x, y; }; +struct InputHandles +{ + vr::VRActionSetHandle_t set; + vr::VRActionHandle_t toggle; + vr::VRActionHandle_t distance; + vr::VRActionHandle_t grab; +}; + class App { public: @@ -20,8 +31,9 @@ class App std::vector GetControllers(); glm::mat4 GetTrackerPose(TrackerID tracker); - vr::VRControllerState_t GetControllerState(TrackerID controller); - bool IsGrabActive(TrackerID controller); + vr::InputDigitalActionData_t GetControllerInputDigital(TrackerID controller, vr::VRActionHandle_t action); + vr::InputAnalogActionData_t GetControllerInputAnalog(TrackerID controller, vr::VRActionHandle_t action); + bool IsInputJustPressed(TrackerID controller, vr::VRActionHandle_t action); CursorPos GetCursorPosition(); Display *_xdisplay; @@ -33,14 +45,23 @@ class App int _root_height; vr::ETrackingUniverseOrigin _tracking_origin; + std::filesystem::path _actions_path; vr::IVRSystem *vr_sys; vr::IVROverlay *vr_overlay; + vr::IVRInput *vr_input; + + InputHandles _input_handles; + vr::TrackedDevicePose_t _tracker_poses[vr::k_unMaxTrackedDeviceCount]; std::vector _panels; + bool _hidden = false; private: void InitX11(); void InitOVR(); void InitGLFW(); + + void UpdateFramebuffer(); + void UpdateInput(); }; \ No newline at end of file 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/panel.cpp b/src/panel.cpp index ce2a910..ceba71d 100644 --- a/src/panel.cpp +++ b/src/panel.cpp @@ -1,10 +1,4 @@ #include "panel.h" -#include "app.h" -#include "util.h" - -#include -#include -#include Panel::Panel(App *app, vr::HmdMatrix34_t start_pose, int index, int x, int y, int width, int height) : _app(app), @@ -12,12 +6,13 @@ Panel::Panel(App *app, vr::HmdMatrix34_t start_pose, int index, int x, int y, in _x(x), _y(y), _width(width), - _height(height) + _height(height), + _grab_component(app) { _name = "screen_view_" + std::to_string(index); _alpha = 1.0f; _meters = 1.0f; - _active_hand = -1; + glGenTextures(1, &_gl_texture); glBindTexture(GL_TEXTURE_2D, _gl_texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -51,48 +46,7 @@ void Panel::Update() Render(); UpdateCursor(); - if (!_is_held) - { - for (auto controller : _app->GetControllers()) - { - if (_app->IsGrabActive(controller)) - { - 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->IsGrabActive(_active_hand)) - { - 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); - } - } + _grab_component.Update(_id, &_meters); } void Panel::Render() @@ -108,6 +62,15 @@ void Panel::Render() assert(set_texture_err == 0); } +void Panel::SetHidden(bool state) +{ + _hidden = state; + if (state) + _app->vr_overlay->HideOverlay(_id); + else + _app->vr_overlay->ShowOverlay(_id); +} + void Panel::UpdateCursor() { auto global_pos = _app->GetCursorPosition(); @@ -127,42 +90,3 @@ void Panel::UpdateCursor() auto pos = vr::HmdVector2_t{x, y}; _app->vr_overlay->SetOverlayCursorPositionOverride(_id, &pos); } - -void Panel::ControllerGrab(TrackerID controller) -{ - printf("Grabbed panel %d\n", _index); - _is_held = true; - _active_hand = controller; - - _app->vr_overlay->SetOverlayColor(_id, 0.6f, 1.0f, 1.0f); - - 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 Panel::ControllerRelease() -{ - printf("Released panel %d\n", _index); - _is_held = false; - - _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/panel.h b/src/panel.h index 4b3a3e2..43d0b42 100644 --- a/src/panel.h +++ b/src/panel.h @@ -1,7 +1,9 @@ +#pragma once #define GL_GLEXT_PROTOTYPES + +#include "grab_component.h" #include "util.h" #include -#include const vr::HmdMatrix34_t DEFAULT_POSE = {{{1, 0, 0, 0}, {0, 1, 0, 1}, {0, 0, 1, 0}}}; @@ -13,25 +15,24 @@ class Panel Panel(App *app, vr::HmdMatrix34_t start_pose, int index, int xmin, int xmax, int ymin, int ymax); void Update(); + void SetHidden(bool state); private: void Render(); void UpdateCursor(); - void ControllerGrab(TrackerID); - void ControllerRelease(); App *_app; OverlayID _id; int _index; std::string _name; - TrackerID _active_hand; - bool _is_held; - int _x, _y; int _width, _height; float _meters; float _alpha; + bool _hidden; + + GrabComponent _grab_component; vr::Texture_t _texture; GLuint _gl_texture;