mirror of
https://github.com/CrispyPin/sinpin-vr.git
synced 2024-11-10 04:20:25 +01:00
move cursor with lasers
This commit is contained in:
parent
0042ee3b58
commit
d204387e19
10 changed files with 139 additions and 50 deletions
|
@ -21,6 +21,11 @@
|
||||||
"requirement": "mandatory",
|
"requirement": "mandatory",
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "/actions/main/in/activate_cursor",
|
||||||
|
"requirement": "suggested",
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "/actions/main/in/reset",
|
"name": "/actions/main/in/reset",
|
||||||
"requirement": "suggested",
|
"requirement": "suggested",
|
||||||
|
@ -42,11 +47,12 @@
|
||||||
{
|
{
|
||||||
"language_tag": "en_us",
|
"language_tag": "en_us",
|
||||||
"/actions/main": "Overlay actions",
|
"/actions/main": "Overlay actions",
|
||||||
"/actions/main/in/toggle_visibility": "Toggle visibility",
|
"/actions/main/in/toggle_visibility": "toggle visibility",
|
||||||
"/actions/main/in/edit_mode": "Toggle edit mode",
|
"/actions/main/in/edit_mode": "toggle edit mode",
|
||||||
"/actions/main/in/grab": "grab panel",
|
"/actions/main/in/grab": "grab panel",
|
||||||
"/actions/main/in/distance": "Move away",
|
"/actions/main/in/activate_cursor": "activate cursor",
|
||||||
"/actions/main/in/reset": "Reset positions"
|
"/actions/main/in/distance": "move away",
|
||||||
|
"/actions/main/in/reset": "reset positions"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -650,6 +650,24 @@
|
||||||
},
|
},
|
||||||
"mode" : "button",
|
"mode" : "button",
|
||||||
"path" : "/user/hand/left/input/a"
|
"path" : "/user/hand/left/input/a"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs" : {
|
||||||
|
"click" : {
|
||||||
|
"output" : "/actions/main/in/activate_cursor"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mode" : "button",
|
||||||
|
"path" : "/user/hand/right/input/trigger"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs" : {
|
||||||
|
"click" : {
|
||||||
|
"output" : "/actions/main/in/activate_cursor"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mode" : "button",
|
||||||
|
"path" : "/user/hand/left/input/trigger"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -658,7 +676,7 @@
|
||||||
"controller_type" : "knuckles",
|
"controller_type" : "knuckles",
|
||||||
"description" : "yes",
|
"description" : "yes",
|
||||||
"interaction_profile" : "",
|
"interaction_profile" : "",
|
||||||
"name" : "Saved sinpin_vr bindings",
|
"name" : "Default sinpin_vr bindings",
|
||||||
"options" : {
|
"options" : {
|
||||||
"mirror_actions" : true,
|
"mirror_actions" : true,
|
||||||
"simulated_controller_type" : "none"
|
"simulated_controller_type" : "none"
|
||||||
|
|
18
src/app.cpp
18
src/app.cpp
|
@ -1,6 +1,7 @@
|
||||||
#include "app.h"
|
#include "app.h"
|
||||||
#include "controller.h"
|
#include "controller.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include <X11/Xlib.h>
|
||||||
#include <X11/extensions/Xrandr.h>
|
#include <X11/extensions/Xrandr.h>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <glm/matrix.hpp>
|
#include <glm/matrix.hpp>
|
||||||
|
@ -55,6 +56,8 @@ App::App()
|
||||||
assert(action_err == 0);
|
assert(action_err == 0);
|
||||||
action_err = vr_input->GetActionHandle("/actions/main/in/toggle_visibility", &_input_handles.toggle_hidden);
|
action_err = vr_input->GetActionHandle("/actions/main/in/toggle_visibility", &_input_handles.toggle_hidden);
|
||||||
assert(action_err == 0);
|
assert(action_err == 0);
|
||||||
|
action_err = vr_input->GetActionHandle("/actions/main/in/activate_cursor", &_input_handles.activate_cursor);
|
||||||
|
assert(action_err == 0);
|
||||||
action_err = vr_input->GetActionHandle("/actions/main/in/edit_mode", &_input_handles.edit_mode);
|
action_err = vr_input->GetActionHandle("/actions/main/in/edit_mode", &_input_handles.edit_mode);
|
||||||
assert(action_err == 0);
|
assert(action_err == 0);
|
||||||
action_err = vr_input->GetActionHandle("/actions/main/in/reset", &_input_handles.reset);
|
action_err = vr_input->GetActionHandle("/actions/main/in/reset", &_input_handles.reset);
|
||||||
|
@ -180,20 +183,15 @@ void App::UpdateInput()
|
||||||
_edit_mode = !_edit_mode;
|
_edit_mode = !_edit_mode;
|
||||||
UpdateUIVisibility();
|
UpdateUIVisibility();
|
||||||
}
|
}
|
||||||
if (_edit_mode)
|
}
|
||||||
{
|
|
||||||
_controllers[0]->Update();
|
_controllers[0]->Update();
|
||||||
_controllers[1]->Update();
|
_controllers[1]->Update();
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::UpdateUIVisibility()
|
void App::UpdateUIVisibility()
|
||||||
{
|
{
|
||||||
bool state = _hidden || !_edit_mode;
|
bool state = _hidden || !_edit_mode;
|
||||||
_root_overlay.SetHidden(state);
|
_root_overlay.SetHidden(state);
|
||||||
_controllers[0]->SetHidden(state);
|
|
||||||
_controllers[1]->SetHidden(state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::UpdateFramebuffer()
|
void App::UpdateFramebuffer()
|
||||||
|
@ -262,7 +260,7 @@ Ray App::IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len)
|
||||||
|
|
||||||
for (auto &panel : _panels)
|
for (auto &panel : _panels)
|
||||||
{
|
{
|
||||||
auto r_panel = panel.GetOverlay()->IntersectRay(origin, direction, max_len);
|
auto r_panel = panel.IntersectRay(origin, direction, max_len);
|
||||||
if (r_panel.distance < ray.distance)
|
if (r_panel.distance < ray.distance)
|
||||||
{
|
{
|
||||||
ray = r_panel;
|
ray = r_panel;
|
||||||
|
@ -288,3 +286,9 @@ CursorPos App::GetCursorPosition()
|
||||||
&buttons);
|
&buttons);
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void App::SetCursor(int x, int y)
|
||||||
|
{
|
||||||
|
// I don't know what the return value of XWarpPointer means, it seems to be 1 on success.
|
||||||
|
XWarpPointer(_xdisplay, _root_window, _root_window, 0, 0, _root_width, _root_height, x, y);
|
||||||
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ struct InputHandles
|
||||||
vr::VRActionHandle_t toggle_hidden;
|
vr::VRActionHandle_t toggle_hidden;
|
||||||
vr::VRActionHandle_t distance;
|
vr::VRActionHandle_t distance;
|
||||||
vr::VRActionHandle_t grab;
|
vr::VRActionHandle_t grab;
|
||||||
|
vr::VRActionHandle_t activate_cursor;
|
||||||
vr::VRActionHandle_t edit_mode;
|
vr::VRActionHandle_t edit_mode;
|
||||||
vr::VRActionHandle_t reset;
|
vr::VRActionHandle_t reset;
|
||||||
};
|
};
|
||||||
|
@ -41,6 +42,7 @@ class App
|
||||||
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);
|
||||||
|
void SetCursor(int x, int y);
|
||||||
|
|
||||||
Display *_xdisplay;
|
Display *_xdisplay;
|
||||||
Window _root_window;
|
Window _root_window;
|
||||||
|
@ -69,6 +71,7 @@ class App
|
||||||
std::vector<Panel> _panels;
|
std::vector<Panel> _panels;
|
||||||
bool _hidden = false;
|
bool _hidden = false;
|
||||||
bool _edit_mode = false;
|
bool _edit_mode = false;
|
||||||
|
std::optional<Controller *> _active_cursor;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void InitX11();
|
void InitX11();
|
||||||
|
|
|
@ -13,7 +13,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;
|
_cursor_active = false;
|
||||||
|
|
||||||
std::string laser_name = "controller_laser_";
|
std::string laser_name = "controller_laser_";
|
||||||
if (side == ControllerSide::Left)
|
if (side == ControllerSide::Left)
|
||||||
|
@ -48,12 +48,6 @@ bool Controller::IsConnected()
|
||||||
return _is_connected;
|
return _is_connected;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::SetHidden(bool state)
|
|
||||||
{
|
|
||||||
_hidden = state;
|
|
||||||
_laser.SetHidden(_hidden);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Controller::ReleaseOverlay()
|
void Controller::ReleaseOverlay()
|
||||||
{
|
{
|
||||||
_grabbed_overlay = nullptr;
|
_grabbed_overlay = nullptr;
|
||||||
|
@ -77,18 +71,72 @@ glm::vec3 Controller::GetLastRot()
|
||||||
void Controller::Update()
|
void Controller::Update()
|
||||||
{
|
{
|
||||||
UpdateStatus();
|
UpdateStatus();
|
||||||
if (!_is_connected || _hidden)
|
if (!_is_connected)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
UpdateLaser();
|
UpdateLaser();
|
||||||
|
|
||||||
|
if (_app->_edit_mode)
|
||||||
|
{
|
||||||
|
if (_last_ray.overlay != nullptr)
|
||||||
|
{
|
||||||
|
auto ray = _last_ray;
|
||||||
|
if (_app->IsInputJustPressed(_app->_input_handles.grab, _input_handle))
|
||||||
|
{
|
||||||
|
if (ray.overlay->IsHeld())
|
||||||
|
{
|
||||||
|
ray.overlay->ControllerResize(this);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_grabbed_overlay = ray.overlay;
|
||||||
|
ray.overlay->ControllerGrab(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_grabbed_overlay != nullptr)
|
||||||
|
{
|
||||||
float move = _app->GetInputAnalog(_app->_input_handles.distance, _input_handle).y * 0.1; // TODO use frame time
|
float move = _app->GetInputAnalog(_app->_input_handles.distance, _input_handle).y * 0.1; // TODO use frame time
|
||||||
if (_grabbed_overlay && move != 0.0f)
|
if (move != 0.0f)
|
||||||
{
|
{
|
||||||
auto transform = _grabbed_overlay->GetTarget()->transform;
|
auto transform = _grabbed_overlay->GetTarget()->transform;
|
||||||
transform.m[2][3] = glm::clamp(transform.m[2][3] - move, -5.0f, -0.1f); // moving along z axis
|
transform.m[2][3] = glm::clamp(transform.m[2][3] - move, -5.0f, -0.1f); // moving along z axis
|
||||||
_grabbed_overlay->SetTransformTracker(_device_index, &transform);
|
_grabbed_overlay->SetTransformTracker(_device_index, &transform);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else //view mode
|
||||||
|
{
|
||||||
|
if (_app->IsInputJustPressed(_app->_input_handles.activate_cursor, _input_handle))
|
||||||
|
{
|
||||||
|
if (!_cursor_active && _app->_active_cursor.has_value())
|
||||||
|
{
|
||||||
|
_app->_active_cursor.value()->_cursor_active = false;
|
||||||
|
_app->_active_cursor = this;
|
||||||
|
}
|
||||||
|
_cursor_active = !_cursor_active;
|
||||||
|
_app->_active_cursor = this;
|
||||||
|
}
|
||||||
|
if (_cursor_active)
|
||||||
|
{
|
||||||
|
// printf("update cursor on hand %d\n", _side);
|
||||||
|
if (_last_ray.overlay != nullptr && _last_ray.hit_panel != nullptr)
|
||||||
|
{
|
||||||
|
auto pos = glm::vec2(_last_ray.local_pos.x, _last_ray.local_pos.y);
|
||||||
|
// normalize positions to +-0.5
|
||||||
|
pos /= _last_ray.overlay->Width();
|
||||||
|
pos.y *= -1;
|
||||||
|
|
||||||
|
// shift to 0-1
|
||||||
|
pos.x += 0.5f;
|
||||||
|
pos.y += 0.5f * _last_ray.overlay->Ratio();
|
||||||
|
|
||||||
|
pos *= _last_ray.hit_panel->Width();
|
||||||
|
_last_ray.hit_panel->SetCursor(pos.x, pos.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::UpdateLaser()
|
void Controller::UpdateLaser()
|
||||||
|
@ -110,22 +158,7 @@ void Controller::UpdateLaser()
|
||||||
|
|
||||||
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}}};
|
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);
|
_laser.SetTransformTracker(_device_index, &transform);
|
||||||
|
_laser.SetHidden(!_is_connected || _app->_hidden || (!_app->_edit_mode && !_cursor_active));
|
||||||
if (ray.overlay != nullptr)
|
|
||||||
{
|
|
||||||
if (_app->IsInputJustPressed(_app->_input_handles.grab, _input_handle))
|
|
||||||
{
|
|
||||||
if (ray.overlay->IsHeld())
|
|
||||||
{
|
|
||||||
ray.overlay->ControllerResize(this);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_grabbed_overlay = ray.overlay;
|
|
||||||
ray.overlay->ControllerGrab(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::UpdateStatus()
|
void Controller::UpdateStatus()
|
||||||
|
@ -145,8 +178,4 @@ 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;
|
||||||
if (!_is_connected)
|
|
||||||
{
|
|
||||||
_laser.SetHidden(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,6 @@ class Controller
|
||||||
glm::vec3 GetLastPos();
|
glm::vec3 GetLastPos();
|
||||||
glm::vec3 GetLastRot();
|
glm::vec3 GetLastRot();
|
||||||
|
|
||||||
void SetHidden(bool state);
|
|
||||||
|
|
||||||
void ReleaseOverlay();
|
void ReleaseOverlay();
|
||||||
|
|
||||||
void Update();
|
void Update();
|
||||||
|
@ -39,9 +37,12 @@ class Controller
|
||||||
ControllerSide _side;
|
ControllerSide _side;
|
||||||
TrackerID _device_index;
|
TrackerID _device_index;
|
||||||
vr::VRInputValueHandle_t _input_handle;
|
vr::VRInputValueHandle_t _input_handle;
|
||||||
|
|
||||||
bool _is_connected;
|
bool _is_connected;
|
||||||
bool _hidden;
|
|
||||||
|
bool _cursor_active;
|
||||||
Overlay *_grabbed_overlay;
|
Overlay *_grabbed_overlay;
|
||||||
|
|
||||||
Ray _last_ray;
|
Ray _last_ray;
|
||||||
glm::vec3 _last_rotation;
|
glm::vec3 _last_rotation;
|
||||||
glm::vec3 _last_pos;
|
glm::vec3 _last_pos;
|
||||||
|
|
|
@ -169,7 +169,7 @@ Ray Overlay::IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len)
|
||||||
{
|
{
|
||||||
dist = glm::min(r * max_len, max_len);
|
dist = glm::min(r * max_len, max_len);
|
||||||
}
|
}
|
||||||
return Ray{.overlay = this, .distance = dist};
|
return Ray{.overlay = this, .distance = dist, .local_pos = p, .hit_panel = nullptr};
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::mat4x4 Overlay::GetTransformAbsolute()
|
glm::mat4x4 Overlay::GetTransformAbsolute()
|
||||||
|
|
|
@ -68,6 +68,18 @@ void Panel::SetHidden(bool state)
|
||||||
_overlay.SetHidden(state);
|
_overlay.SetHidden(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ray Panel::IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len)
|
||||||
|
{
|
||||||
|
auto ray = _overlay.IntersectRay(origin, direction, max_len);
|
||||||
|
ray.hit_panel = this;
|
||||||
|
return ray;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Panel::SetCursor(int x, int y)
|
||||||
|
{
|
||||||
|
_app->SetCursor(x + _x, y + _y);
|
||||||
|
}
|
||||||
|
|
||||||
void Panel::UpdateCursor()
|
void Panel::UpdateCursor()
|
||||||
{
|
{
|
||||||
auto global_pos = _app->GetCursorPosition();
|
auto global_pos = _app->GetCursorPosition();
|
||||||
|
|
13
src/panel.h
13
src/panel.h
|
@ -19,6 +19,19 @@ class Panel
|
||||||
void SetHidden(bool state);
|
void SetHidden(bool state);
|
||||||
void ResetTransform();
|
void ResetTransform();
|
||||||
|
|
||||||
|
int Width()
|
||||||
|
{
|
||||||
|
return _width;
|
||||||
|
}
|
||||||
|
int Height()
|
||||||
|
{
|
||||||
|
return _height;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetCursor(int x, int y);
|
||||||
|
|
||||||
|
Ray IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len);
|
||||||
|
|
||||||
Overlay *GetOverlay();
|
Overlay *GetOverlay();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -11,10 +11,13 @@ 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;
|
||||||
|
|
||||||
class Overlay;
|
class Overlay;
|
||||||
|
class Panel;
|
||||||
struct Ray
|
struct Ray
|
||||||
{
|
{
|
||||||
Overlay *overlay;
|
Overlay *overlay;
|
||||||
float distance;
|
float distance;
|
||||||
|
glm::vec3 local_pos;
|
||||||
|
Panel *hit_panel;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void PrintVec(glm::vec3 v)
|
inline void PrintVec(glm::vec3 v)
|
||||||
|
|
Loading…
Reference in a new issue