Blue Brain BioExplorer
VRPNPlugin.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018-2024, EPFL/Blue Brain Project
3  * All rights reserved. Do not distribute without permission.
4  *
5  * This file is part of Blue Brain BioExplorer <https://github.com/BlueBrain/BioExplorer>
6  *
7  * This library is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU Lesser General Public License version 3.0 as published
9  * by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
14  * details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this library; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20 
21 #include "VRPNPlugin.h"
22 
26 
27 namespace core
28 {
29 namespace
30 {
31 constexpr vrpn_int32 HEAD_SENSOR_ID = 0;
32 constexpr vrpn_int32 FLYSTICK_SENSOR_ID = 1;
33 constexpr double MOVING_SPEED = 1.0f;
34 const std::string DEFAULT_VRPN_NAME = "DTrack@cave1";
35 #ifdef BRAYNSVRPN_USE_LIBUV
36 constexpr int VRPN_IDLE_TIMEOUT_MS = 5000;
37 constexpr int VRPN_REPEAT_TIMEOUT_MS = 16;
38 #endif
39 
40 const std::string HEAD_POSITION_PROP = "headPosition";
41 const std::string HEAD_ROTATION_PROP = "headRotation";
42 
43 constexpr std::array<double, 3> to_array_3d(const vrpn_float64* pos)
44 {
45  return {{pos[0], pos[1], pos[2]}};
46 }
47 constexpr std::array<double, 4> to_array_4d(const vrpn_float64* quat)
48 {
49  return {{quat[0], quat[1], quat[2], quat[3]}};
50 }
51 
52 void trackerCallback(void* userData, const vrpn_TRACKERCB tracker)
53 {
54  auto camera = static_cast<Camera*>(userData);
55  camera->updateProperty(HEAD_POSITION_PROP, to_array_3d(tracker.pos));
56  camera->updateProperty(HEAD_ROTATION_PROP, to_array_4d(tracker.quat));
57 }
58 
59 void flyStickCallback(void* userData, const vrpn_TRACKERCB tracker)
60 {
61  VrpnStates* states = static_cast<VrpnStates*>(userData);
62  states->flyStickOrientation = glm::quat(tracker.quat[3], tracker.quat[0], tracker.quat[1], tracker.quat[2]);
63 }
64 
65 void joystickCallback(void* userData, const vrpn_ANALOGCB joystick)
66 {
67  VrpnStates* states = static_cast<VrpnStates*>(userData);
68  states->axisX = joystick.channel[0];
69  states->axisZ = joystick.channel[1];
70 }
71 } // namespace
72 
73 VRPNPlugin::VRPNPlugin(const std::string& vrpnName)
74  : _vrpnName(vrpnName)
75 {
76 }
77 
79 {
80  _vrpnTracker->unregister_change_handler(&(_api->getCamera()), trackerCallback, HEAD_SENSOR_ID);
81 }
82 
84 {
85  _vrpnTracker = std::make_unique<vrpn_Tracker_Remote>(_vrpnName.c_str());
86  if (!_vrpnTracker->connectionPtr()->doing_okay())
87  throw std::runtime_error("VRPN couldn't connect to: " + _vrpnName + " tracker");
88 
89  _vrpnAnalog = std::make_unique<vrpn_Analog_Remote>(_vrpnName.c_str());
90  if (!_vrpnAnalog->connectionPtr()->doing_okay())
91  throw std::runtime_error("VRPN couldn't connect to: " + _vrpnName + " analog");
92 
93  CORE_INFO("VRPN successfully connected to " << _vrpnName);
94 
95 #ifdef BRAYNSVRPN_USE_LIBUV
96  _setupIdleTimer();
97 #endif
98 
99  _vrpnTracker->register_change_handler(&(_api->getCamera()), trackerCallback, HEAD_SENSOR_ID);
100  _vrpnTracker->register_change_handler(&_states, flyStickCallback, FLYSTICK_SENSOR_ID);
101  _vrpnAnalog->register_change_handler(&_states, joystickCallback);
102 }
103 
105 {
106  _timer.stop();
107  _vrpnTracker->mainloop();
108 
109  double frameTime = _timer.seconds();
110 
111  Camera& camera = _api->getCamera();
112  Vector3d pos = camera.getPosition();
113  pos += _states.axisX * MOVING_SPEED * glm::rotate(_states.flyStickOrientation, Vector3f(1.0, 0.0, 0.0)) * frameTime;
114  pos +=
115  _states.axisZ * MOVING_SPEED * glm::rotate(_states.flyStickOrientation, Vector3f(0.0, 0.0, -1.0)) * frameTime;
116  camera.setPosition(pos);
117 
118  _timer.start();
119 }
120 
121 #ifdef BRAYNSVRPN_USE_LIBUV
122 void VRPNPlugin::resumeRenderingIfTrackerIsActive()
123 {
124  _vrpnTracker->mainloop();
125  if (_api->getCamera().isModified())
126  _api->triggerRender();
127 }
128 
129 void VRPNPlugin::_setupIdleTimer()
130 {
131  if (auto uvLoop = uv_default_loop())
132  {
133  _idleTimer.reset(new uv_timer_t);
134  uv_timer_init(uvLoop, _idleTimer.get());
135  _idleTimer->data = this;
136 
137  uv_timer_start(
138  _idleTimer.get(),
139  [](uv_timer_t* timer) {
140  auto plugin = static_cast<VRPNPlugin*>(timer->data);
141  plugin->resumeRenderingIfTrackerIsActive();
142  },
143  VRPN_IDLE_TIMEOUT_MS, VRPN_REPEAT_TIMEOUT_MS);
144  }
145 }
146 #endif
147 } // namespace core
148 
149 extern "C" core::ExtensionPlugin* brayns_plugin_create(const int argc, const char** argv)
150 {
151  if (argc > 2)
152  {
153  throw std::runtime_error(
154  "VRPN plugin expects at most one argument, the name of the VRPN "
155  "device to connect to (eg: Tracker0@localhost)");
156  }
157 
158  const auto vrpnName = (argc >= 2) ? argv[1] : core::DEFAULT_VRPN_NAME;
159  return new core::VRPNPlugin(vrpnName);
160 }
core::ExtensionPlugin * brayns_plugin_create(const int argc, const char **argv)
Definition: VRPNPlugin.cpp:149
bool isModified() const
Definition: BaseObject.h:60
The Camera class is an abstract interface for a camera in a 3D graphics application....
Definition: Camera.h:41
PLATFORM_API void setPosition(const Vector3d &position)
Sets the camera position.
Definition: Camera.h:94
PLATFORM_API const Vector3d & getPosition() const
Gets the camera position.
Definition: Camera.h:108
virtual Camera & getCamera()=0
virtual void triggerRender()=0
void start()
Definition: Timer.cpp:34
void stop()
Definition: Timer.cpp:44
double seconds() const
Definition: Timer.cpp:70
void preRender() final
Definition: VRPNPlugin.cpp:104
VRPNPlugin(const std::string &vrpnName)
Definition: VRPNPlugin.cpp:73
void init() final
Definition: VRPNPlugin.cpp:83
glm::vec3 Vector3f
Definition: MathTypes.h:137
glm::vec< 3, double > Vector3d
Definition: MathTypes.h:143
#define CORE_INFO(__msg)
Definition: Logs.h:33
glm::quat flyStickOrientation
Definition: VRPNPlugin.h:42