Compare commits

...

2 commits

9 changed files with 184 additions and 134 deletions

View file

@ -1,4 +1,5 @@
#include "app.h" #include "app.h"
#include "controller.h"
#include "util.h" #include "util.h"
#include <X11/extensions/Xrandr.h> #include <X11/extensions/Xrandr.h>
#include <cassert> #include <cassert>
@ -13,6 +14,8 @@ App::App()
InitGLFW(); InitGLFW();
InitRootOverlay(); InitRootOverlay();
printf("\n"); printf("\n");
_controllers[0] = Controller(this, ControllerSide::Left);
_controllers[1] = Controller(this, ControllerSide::Right);
glGenTextures(1, &_gl_frame); glGenTextures(1, &_gl_frame);
glBindTexture(GL_TEXTURE_2D, _gl_frame); glBindTexture(GL_TEXTURE_2D, _gl_frame);
@ -122,19 +125,18 @@ void App::InitRootOverlay()
// clang-format on // clang-format on
_root_overlay.SetTransformWorld(&root_start_pose); _root_overlay.SetTransformWorld(&root_start_pose);
_root_overlay._GrabBeginCallback = [this](TrackerID controller) { _root_overlay._GrabBeginCallback = [this](Controller *controller) {
for (auto &panel : _panels) for (auto &panel : _panels)
{ {
panel.GetOverlay()->ControllerGrab(controller); panel.GetOverlay()->ControllerGrab(controller);
} }
}; };
_root_overlay._GrabEndCallback = [this](TrackerID controller) { _root_overlay._GrabEndCallback = [this]() {
for (auto &panel : _panels) for (auto &panel : _panels)
{ {
panel.GetOverlay()->ControllerRelease(); panel.GetOverlay()->ControllerRelease();
} }
}; };
printf("Created root overlay instance\n");
} }
void App::Update() void App::Update()
@ -156,44 +158,26 @@ void App::UpdateInput()
vr::VRActiveActionSet_t main; vr::VRActiveActionSet_t main;
main.ulActionSet = _input_handles.set; main.ulActionSet = _input_handles.set;
main.ulRestrictedToDevice = 0; main.ulRestrictedToDevice = 0;
vr_input->UpdateActionState(&main, sizeof(vr::VRActiveActionSet_t), 1); main.nPriority = 10;
vr::EVRInputError err = vr_input->UpdateActionState(&main, sizeof(vr::VRActiveActionSet_t), 1);
if (err)
{
printf("Error: (update action state): %d\n", err);
}
vr_sys->GetDeviceToAbsoluteTrackingPose(_tracking_origin, 0, _tracker_poses, MAX_TRACKERS); vr_sys->GetDeviceToAbsoluteTrackingPose(_tracking_origin, 0, _tracker_poses, MAX_TRACKERS);
for (unsigned int i = 0; i < MAX_TRACKERS; i++) if (IsInputJustPressed(_input_handles.toggle))
{ {
if (IsInputJustPressed(i, _input_handles.toggle)) _hidden = !_hidden;
_root_overlay.SetHidden(_hidden);
for (auto &panel : _panels)
{ {
_hidden = !_hidden; panel.SetHidden(_hidden);
_root_overlay.SetHidden(_hidden);
for (auto &panel : _panels)
{
panel.SetHidden(_hidden);
}
for (auto &laser : _lasers)
{
if (laser.has_value())
{
laser->SetHidden(_hidden);
}
}
break;
}
auto type = vr_sys->GetTrackedDeviceClass(i);
if (type == vr::TrackedDeviceClass_Controller)
{
if (!_lasers[i].has_value())
{
_lasers[i] = Laser(this, i);
}
_lasers[i]->SetHidden(_hidden);
_lasers[i]->Update();
}
else if (_lasers[i].has_value())
{
_lasers[i]->SetHidden(true);
} }
} }
_controllers[0]->Update();
_controllers[1]->Update();
} }
void App::UpdateFramebuffer() void App::UpdateFramebuffer()
@ -223,23 +207,23 @@ glm::mat4 App::GetTrackerPose(TrackerID tracker)
return ConvertMat(_tracker_poses[tracker].mDeviceToAbsoluteTracking); return ConvertMat(_tracker_poses[tracker].mDeviceToAbsoluteTracking);
} }
vr::InputDigitalActionData_t App::GetControllerInputDigital(TrackerID controller, vr::VRActionHandle_t action) vr::InputDigitalActionData_t App::GetInputDigital(vr::VRActionHandle_t action, vr::VRInputValueHandle_t controller)
{ {
vr::InputDigitalActionData_t state; vr::InputDigitalActionData_t state;
vr_input->GetDigitalActionData(action, &state, sizeof(vr::InputDigitalActionData_t), 0); vr_input->GetDigitalActionData(action, &state, sizeof(vr::InputDigitalActionData_t), controller);
return state; return state;
} }
vr::InputAnalogActionData_t App::GetControllerInputAnalog(TrackerID controller, vr::VRActionHandle_t action) vr::InputAnalogActionData_t App::GetInputAnalog(vr::VRActionHandle_t action, vr::VRInputValueHandle_t controller)
{ {
vr::InputAnalogActionData_t state; vr::InputAnalogActionData_t state;
vr_input->GetAnalogActionData(action, &state, sizeof(vr::InputAnalogActionData_t), 0); vr_input->GetAnalogActionData(action, &state, sizeof(vr::InputAnalogActionData_t), controller);
return state; return state;
} }
bool App::IsInputJustPressed(TrackerID controller, vr::VRActionHandle_t action) bool App::IsInputJustPressed(vr::VRActionHandle_t action, vr::VRInputValueHandle_t controller)
{ {
auto data = GetControllerInputDigital(controller, action); auto data = GetInputDigital(action, controller);
return data.bState && data.bChanged; return data.bState && data.bChanged;
} }

View file

@ -1,7 +1,7 @@
#pragma once #pragma once
#define GL_GLEXT_PROTOTYPES #define GL_GLEXT_PROTOTYPES
#include "laser.h" #include "controller.h"
#include "overlay.h" #include "overlay.h"
#include "panel.h" #include "panel.h"
#include "util.h" #include "util.h"
@ -39,9 +39,9 @@ class App
std::vector<TrackerID> GetControllers(); std::vector<TrackerID> GetControllers();
glm::mat4 GetTrackerPose(TrackerID tracker); glm::mat4 GetTrackerPose(TrackerID tracker);
vr::InputDigitalActionData_t GetControllerInputDigital(TrackerID controller, vr::VRActionHandle_t action); vr::InputDigitalActionData_t GetInputDigital(vr::VRActionHandle_t action, vr::VRInputValueHandle_t controller = 0);
vr::InputAnalogActionData_t GetControllerInputAnalog(TrackerID controller, vr::VRActionHandle_t action); vr::InputAnalogActionData_t GetInputAnalog(vr::VRActionHandle_t action, vr::VRInputValueHandle_t controller = 0);
bool IsInputJustPressed(TrackerID controller, vr::VRActionHandle_t action); bool IsInputJustPressed(vr::VRActionHandle_t action, vr::VRInputValueHandle_t controller = 0);
CursorPos GetCursorPosition(); CursorPos GetCursorPosition();
Ray IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len); Ray IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len);
@ -63,7 +63,7 @@ class App
InputHandles _input_handles; InputHandles _input_handles;
vr::TrackedDevicePose_t _tracker_poses[MAX_TRACKERS]; vr::TrackedDevicePose_t _tracker_poses[MAX_TRACKERS];
std::optional<Laser> _lasers[MAX_TRACKERS]; std::optional<Controller> _controllers[2];
Overlay _root_overlay; Overlay _root_overlay;
std::vector<Panel> _panels; std::vector<Panel> _panels;

95
src/controller.cpp Normal file
View file

@ -0,0 +1,95 @@
#include "controller.h"
#include "app.h"
#include "overlay.h"
#include "util.h"
#include <string>
const float width = 0.004f;
Controller::Controller(App *app, ControllerSide side)
{
_app = app;
_input_handle = 0;
_is_connected = false;
_side = side;
std::string laser_name = "controller_laser_";
if (side == ControllerSide::Left)
laser_name += "left";
else if (side == ControllerSide::Right)
laser_name += "right";
_laser = Overlay(app, laser_name);
UpdateStatus();
_laser.SetTextureToColor(255, 200, 255);
_laser.SetAlpha(0.2f);
}
TrackerID Controller::DeviceIndex()
{
return _device_index;
}
vr::VRInputValueHandle_t Controller::InputHandle()
{
return _input_handle;
}
ControllerSide Controller::Side()
{
return _side;
}
bool Controller::IsConnected()
{
return _is_connected;
}
void Controller::Update()
{
UpdateStatus();
if (!_is_connected)
return;
auto controller_pose = _app->GetTrackerPose(_device_index);
auto controller_pos = GetPos(controller_pose);
auto forward = -glm::vec3(controller_pose[2]);
auto ray = _app->IntersectRay(controller_pos, forward, 5.0f);
float len = ray.distance;
auto hmd_global_pos = GetPos(_app->GetTrackerPose(0));
auto hmd_local_pos = glm::inverse(controller_pose) * glm::vec4(hmd_global_pos - controller_pos, 0);
hmd_local_pos.z = 0;
auto hmd_dir = glm::normalize(hmd_local_pos);
VRMat transform = {{{width * hmd_dir.y, 0, width * hmd_dir.x, 0}, {width * -hmd_dir.x, 0, width * hmd_dir.y, 0}, {0, len, 0, len * -0.5f}}};
_laser.SetTransformTracker(_device_index, &transform);
if (ray.overlay != nullptr)
{
if (_app->IsInputJustPressed(_app->_input_handles.grab, _input_handle))
{
ray.overlay->ControllerGrab(this);
}
}
}
void Controller::UpdateStatus()
{
_is_connected = true;
if (_side == ControllerSide::Left)
{
auto err = _app->vr_input->GetInputSourceHandle("/user/hand/left", &_input_handle);
_is_connected &= (err == 0);
_device_index = _app->vr_sys->GetTrackedDeviceIndexForControllerRole(vr::TrackedControllerRole_LeftHand);
}
else if (_side == ControllerSide::Right)
{
auto err = _app->vr_input->GetInputSourceHandle("/user/hand/right", &_input_handle);
_is_connected &= (err == 0);
_device_index = _app->vr_sys->GetTrackedDeviceIndexForControllerRole(vr::TrackedControllerRole_RightHand);
}
_is_connected &= _device_index < MAX_TRACKERS;
_laser.SetHidden(!_is_connected);
}

33
src/controller.h Normal file
View file

@ -0,0 +1,33 @@
#pragma once
#include "overlay.h"
#include "util.h"
class App;
enum class ControllerSide
{
Left,
Right
};
class Controller
{
public:
Controller(App *app, ControllerSide hand);
TrackerID DeviceIndex();
vr::VRInputValueHandle_t InputHandle();
ControllerSide Side();
bool IsConnected();
void Update();
void UpdateStatus();
private:
App *_app;
Overlay _laser;
ControllerSide _side;
TrackerID _device_index;
vr::VRInputValueHandle_t _input_handle;
bool _is_connected;
};

View file

@ -1,45 +0,0 @@
#include "laser.h"
#include "app.h"
#include "util.h"
#include <string>
Laser::Laser(App *app, TrackerID index)
: _overlay(app, "laser_" + std::to_string(index)),
_app(app),
_controller(index)
{
_overlay.SetHidden(true);
_overlay.SetTransformTracker(index, &VRMatIdentity);
_overlay.SetTextureToColor(255, 200, 255);
_overlay.SetAlpha(0.2f);
}
void Laser::Update()
{
if (_overlay.IsHidden())
{
return;
}
const float width = 0.004f;
auto controller_pose = _app->GetTrackerPose(_controller);
auto origin = GetPos(controller_pose);
auto forward = -glm::vec3(controller_pose[2]);
auto ray = _app->IntersectRay(origin, forward, 5.0f);
float len = ray.distance;
VRMat transform = {{{width, 0, 0, 0}, {0, 0, width, 0}, {0, len, 0, len * -0.5f}}};
_overlay.SetTransformTracker(_controller, &transform);
if (ray.overlay != nullptr)
{
if (_app->IsInputJustPressed(_controller, _app->_input_handles.grab))
{
ray.overlay->ControllerGrab(_controller);
}
}
}
void Laser::SetHidden(bool state)
{
_overlay.SetHidden(state);
}

View file

@ -1,20 +0,0 @@
#pragma once
#include "overlay.h"
#include "util.h"
class App;
class Laser
{
public:
Laser(App *app, TrackerID index);
void Update();
void SetHidden(bool state);
private:
App *_app;
Overlay _overlay;
TrackerID _controller;
};

View file

@ -14,8 +14,7 @@ Overlay::Overlay(App *app, std::string name)
_initialized = true; _initialized = true;
_name = name; _name = name;
_app = app; _app = app;
_is_held = false; _holding_controller = nullptr;
_active_hand = 0;
_width_m = 1; _width_m = 1;
_ratio = 1; _ratio = 1;
@ -46,12 +45,12 @@ OverlayID Overlay::Id()
bool Overlay::IsHeld() bool Overlay::IsHeld()
{ {
return _is_held; return _holding_controller != nullptr;
} }
TrackerID Overlay::ActiveHand() Controller *Overlay::ActiveHand()
{ {
return _active_hand; return _holding_controller;
} }
bool Overlay::IsHidden() bool Overlay::IsHidden()
@ -168,13 +167,14 @@ float Overlay::IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len
glm::mat4x4 Overlay::GetTransformAbsolute() glm::mat4x4 Overlay::GetTransformAbsolute()
{ {
if (_is_held) if (_holding_controller != nullptr)
{ {
VRMat pose; VRMat pose;
auto err = _app->vr_overlay->GetOverlayTransformTrackedDeviceRelative(_id, &_active_hand, &pose); TrackerID tracker;
auto err = _app->vr_overlay->GetOverlayTransformTrackedDeviceRelative(_id, &tracker, &pose);
assert(err == 0); assert(err == 0);
auto offset = ConvertMat(pose); auto offset = ConvertMat(pose);
auto controller = _app->GetTrackerPose(_active_hand); auto controller = _app->GetTrackerPose(_holding_controller->DeviceIndex());
return controller * offset; return controller * offset;
} }
else else
@ -206,32 +206,31 @@ void Overlay::Update()
assert(_initialized); assert(_initialized);
} }
if (_is_held) if (_holding_controller != nullptr)
{ {
if (!_app->GetControllerInputDigital(_active_hand, _app->_input_handles.grab).bState) if (!_app->GetInputDigital(_app->_input_handles.grab, _holding_controller->InputHandle()).bState)
{ {
ControllerRelease(); ControllerRelease();
} }
} }
} }
void Overlay::ControllerGrab(TrackerID controller) void Overlay::ControllerGrab(Controller *controller)
{ {
_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); 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, &relative_pose); _app->vr_overlay->SetOverlayTransformTrackedDeviceRelative(_id, controller->DeviceIndex(), &relative_pose);
if (_GrabBeginCallback != nullptr) if (_GrabBeginCallback != nullptr)
{ {
_GrabBeginCallback(controller); _GrabBeginCallback(controller);
} }
_is_held = true; _holding_controller = controller;
_active_hand = controller;
} }
void Overlay::ControllerRelease() void Overlay::ControllerRelease()
@ -243,8 +242,7 @@ void Overlay::ControllerRelease()
if (_GrabEndCallback != nullptr) if (_GrabEndCallback != nullptr)
{ {
_GrabEndCallback(_active_hand); _GrabEndCallback();
} }
_is_held = false; _holding_controller = nullptr;
_active_hand = -1;
} }

View file

@ -5,6 +5,7 @@
#include <string> #include <string>
class App; class App;
class Controller;
enum class TargetType enum class TargetType
{ {
@ -29,7 +30,7 @@ class Overlay
OverlayID Id(); OverlayID Id();
bool IsHeld(); bool IsHeld();
bool IsHidden(); bool IsHidden();
TrackerID ActiveHand(); Controller *ActiveHand();
float Alpha(); float Alpha();
float Width(); float Width();
float Ratio(); float Ratio();
@ -51,11 +52,11 @@ class Overlay
float IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len); float IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len);
std::function<void(TrackerID)> _GrabBeginCallback; std::function<void(Controller *)> _GrabBeginCallback;
std::function<void(TrackerID)> _GrabEndCallback; std::function<void()> _GrabEndCallback;
void ControllerRelease(); void ControllerRelease();
void ControllerGrab(TrackerID controller); void ControllerGrab(Controller *controller);
private: private:
bool _initialized; bool _initialized;
@ -64,12 +65,11 @@ class Overlay
OverlayID _id; OverlayID _id;
std::string _name; std::string _name;
bool _is_held;
bool _hidden; bool _hidden;
float _width_m; float _width_m;
float _alpha; float _alpha;
float _ratio; float _ratio;
TrackerID _active_hand; Controller *_holding_controller;
Target _target; Target _target;
}; };

View file

@ -10,6 +10,11 @@ typedef vr::HmdMatrix34_t VRMat;
const VRMat VRMatIdentity{{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}}}; const VRMat VRMatIdentity{{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}}};
const int MAX_TRACKERS = vr::k_unMaxTrackedDeviceCount; const int MAX_TRACKERS = vr::k_unMaxTrackedDeviceCount;
inline void PrintVec(glm::vec3 v)
{
printf("(%.2f, %.2f, %.2f)\n", v.x, v.y, v.z);
}
inline void PrintMat(VRMat m) inline void PrintMat(VRMat 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[0][0], m.m[0][1], m.m[0][2], m.m[0][3]);