mirror of
https://github.com/CrispyPin/sinpin-vr.git
synced 2024-11-22 18:10:26 +01:00
Compare commits
6 commits
e4a79eefd3
...
4bc69f2e53
Author | SHA1 | Date | |
---|---|---|---|
4bc69f2e53 | |||
2c120f462f | |||
1770dd6e26 | |||
03d15b42bd | |||
54ea68da6b | |||
74d2c71c53 |
6 changed files with 137 additions and 53 deletions
2
Makefile
2
Makefile
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
|
|
||||||
build:
|
build:
|
||||||
CPATH=. g++ -Wall -lX11 -lglfw -lGL openvr/libopenvr_api.so src/*.cpp -o overlay
|
CPATH=. g++ -Wall -lX11 -lXrandr -lglfw -lGL openvr/libopenvr_api.so src/*.cpp -o overlay
|
||||||
|
|
||||||
run: build
|
run: build
|
||||||
./overlay
|
./overlay
|
||||||
|
|
75
src/app.cpp
75
src/app.cpp
|
@ -1,17 +1,39 @@
|
||||||
#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::ETrackingUniverseOrigin::TrackingUniverseStanding;
|
_tracking_origin = vr::TrackingUniverseStanding;
|
||||||
|
|
||||||
InitOVR();
|
InitOVR();
|
||||||
InitX11();
|
InitX11();
|
||||||
InitGLFW();
|
InitGLFW();
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
_panels.push_back(Panel(this, 0, 0, 0, _root_width, _root_height));
|
glGenTextures(1, &_gl_frame);
|
||||||
|
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()
|
||||||
|
@ -36,8 +58,9 @@ void App::InitX11()
|
||||||
void App::InitOVR()
|
void App::InitOVR()
|
||||||
{
|
{
|
||||||
vr::EVRInitError init_err;
|
vr::EVRInitError init_err;
|
||||||
vr_sys = vr::VR_Init(&init_err, vr::EVRApplicationType::VRApplication_Background);
|
// would normally be using VRApplication_Overlay, but Background allows it to quit if steamvr is not running, instead of opening steamvr.
|
||||||
if (init_err == vr::EVRInitError::VRInitError_Init_NoServerForBackgroundApp)
|
vr_sys = vr::VR_Init(&init_err, vr::VRApplication_Background);
|
||||||
|
if (init_err == vr::VRInitError_Init_NoServerForBackgroundApp)
|
||||||
{
|
{
|
||||||
printf("SteamVR is not running\n");
|
printf("SteamVR is not running\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -55,7 +78,7 @@ void App::InitGLFW()
|
||||||
{
|
{
|
||||||
assert(glfwInit() == true);
|
assert(glfwInit() == true);
|
||||||
glfwWindowHint(GLFW_VISIBLE, false);
|
glfwWindowHint(GLFW_VISIBLE, false);
|
||||||
// TODO this is creating a 1x1 window, should it be bigger?
|
// creating a 1x1 window, since it is hidden anyway
|
||||||
_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);
|
||||||
|
@ -64,12 +87,31 @@ 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;
|
||||||
|
@ -83,21 +125,24 @@ glm::mat4 App::GetTrackerPose(TrackerID tracker)
|
||||||
return ConvertMat(tracked_pose.mDeviceToAbsoluteTracking);
|
return ConvertMat(tracked_pose.mDeviceToAbsoluteTracking);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool App::IsGrabActive(vr::TrackedDeviceIndex_t controller)
|
vr::VRControllerState_t App::GetControllerState(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("failed to get state of controller %d\n", controller);
|
||||||
printf("Error getting controller state: %d\n", get_state_err);
|
return state;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
// printf("got state\n");
|
|
||||||
|
|
||||||
auto trigger_mask = vr::ButtonMaskFromId(vr::EVRButtonId::k_EButton_SteamVR_Trigger);
|
bool App::IsGrabActive(TrackerID controller)
|
||||||
auto b_mask = vr::ButtonMaskFromId(vr::EVRButtonId::k_EButton_IndexController_B);
|
{
|
||||||
auto mask = trigger_mask | b_mask;
|
vr::VRControllerState_t state;
|
||||||
return (state.ulButtonPressed & mask) == mask;
|
auto get_state_err = vr_sys->GetControllerState(controller, &state, sizeof(vr::VRControllerState_t));
|
||||||
|
if (get_state_err == false)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto trigger_mask = vr::ButtonMaskFromId(vr::k_EButton_SteamVR_Trigger);
|
||||||
|
return state.ulButtonPressed & trigger_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
CursorPos App::GetCursorPosition()
|
CursorPos App::GetCursorPosition()
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#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>
|
||||||
|
@ -17,13 +18,16 @@ class App
|
||||||
~App();
|
~App();
|
||||||
void Update();
|
void Update();
|
||||||
|
|
||||||
|
std::vector<TrackerID> GetControllers();
|
||||||
glm::mat4 GetTrackerPose(TrackerID tracker);
|
glm::mat4 GetTrackerPose(TrackerID tracker);
|
||||||
bool IsGrabActive(vr::TrackedDeviceIndex_t controller);
|
vr::VRControllerState_t GetControllerState(TrackerID 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;
|
||||||
|
|
|
@ -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, 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),
|
: _app(app),
|
||||||
_index(index),
|
_index(index),
|
||||||
_x(x),
|
_x(x),
|
||||||
|
@ -16,12 +16,18 @@ Panel::Panel(App *app, int index, int x, int y, int width, int height)
|
||||||
{
|
{
|
||||||
_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::EColorSpace::ColorSpace_Auto;
|
_texture.eColorSpace = vr::ColorSpace_Auto;
|
||||||
_texture.eType = vr::ETextureType::TextureType_OpenGL;
|
_texture.eType = vr::TextureType_OpenGL;
|
||||||
_texture.handle = (void *)(uintptr_t)_gl_texture;
|
_texture.handle = (void *)(uintptr_t)_gl_texture;
|
||||||
|
|
||||||
// create overlay
|
// create overlay
|
||||||
|
@ -29,7 +35,6 @@ Panel::Panel(App *app, int index, int x, int y, int width, int height)
|
||||||
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);
|
||||||
|
@ -37,8 +42,7 @@ Panel::Panel(App *app, int index, int x, int y, int width, int height)
|
||||||
// (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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,44 +53,56 @@ void Panel::Update()
|
||||||
|
|
||||||
if (!_is_held)
|
if (!_is_held)
|
||||||
{
|
{
|
||||||
vr::TrackedDeviceIndex_t controllers[8];
|
for (auto controller : _app->GetControllers())
|
||||||
auto controller_count = _app->vr_sys->GetSortedTrackedDeviceIndicesOfClass(vr::ETrackedDeviceClass::TrackedDeviceClass_Controller, controllers, 8);
|
{
|
||||||
|
if (_app->IsGrabActive(controller))
|
||||||
for (unsigned int i = 0; i < controller_count; i++)
|
|
||||||
{
|
{
|
||||||
auto controller = controllers[i];
|
|
||||||
|
|
||||||
vr::HmdMatrix34_t overlay_pose;
|
vr::HmdMatrix34_t overlay_pose;
|
||||||
vr::ETrackingUniverseOrigin tracking_universe;
|
vr::ETrackingUniverseOrigin tracking_universe;
|
||||||
_app->vr_overlay->GetOverlayTransformAbsolute(_id, &tracking_universe, &overlay_pose);
|
_app->vr_overlay->GetOverlayTransformAbsolute(_id, &tracking_universe, &overlay_pose);
|
||||||
|
|
||||||
auto controller_pose = _app->GetTrackerPose(controller);
|
auto controller_pos = GetPos(_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;
|
auto local_pos = glm::inverse(ConvertMat(overlay_pose)) * glm::vec4(controller_pos - GetPos(overlay_pose), 0);
|
||||||
// close_enough = true;
|
|
||||||
|
|
||||||
if (close_enough && _app->IsGrabActive(controller))
|
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);
|
ControllerGrab(controller);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!_app->IsGrabActive(_active_hand))
|
if (!_app->IsGrabActive(_active_hand))
|
||||||
{
|
{
|
||||||
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()
|
||||||
{
|
{
|
||||||
auto frame = XGetImage(_app->_xdisplay, _app->_root_window, _x, _y, _width, _height, AllPlanes, ZPixmap);
|
glCopyImageSubData(
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _width, _height, 0, GL_BGRA, GL_UNSIGNED_BYTE, frame->data);
|
_app->_gl_frame, GL_TEXTURE_2D, 0,
|
||||||
XDestroyImage(frame);
|
_x, _y, 0,
|
||||||
|
_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);
|
||||||
|
@ -94,13 +110,20 @@ void Panel::Render()
|
||||||
|
|
||||||
void Panel::UpdateCursor()
|
void Panel::UpdateCursor()
|
||||||
{
|
{
|
||||||
auto global = _app->GetCursorPosition();
|
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(_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 = global.x / (float)_width;
|
float x = local_x / (float)_width;
|
||||||
float y = 1.0f - (global.y / (float)_width + top_edge);
|
float y = 1.0f - (local_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);
|
||||||
}
|
}
|
||||||
|
@ -111,6 +134,8 @@ 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;
|
||||||
|
|
||||||
|
@ -129,6 +154,8 @@ 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);
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
|
#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, 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 Update();
|
||||||
|
|
||||||
|
@ -26,8 +28,9 @@ class Panel
|
||||||
TrackerID _active_hand;
|
TrackerID _active_hand;
|
||||||
bool _is_held;
|
bool _is_held;
|
||||||
|
|
||||||
unsigned int _x, _y;
|
int _x, _y;
|
||||||
unsigned int _width, _height;
|
int _width, _height;
|
||||||
|
float _meters;
|
||||||
float _alpha;
|
float _alpha;
|
||||||
|
|
||||||
vr::Texture_t _texture;
|
vr::Texture_t _texture;
|
||||||
|
|
|
@ -46,3 +46,8 @@ 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]);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue