-
Notifications
You must be signed in to change notification settings - Fork 0
/
IvryCustomTrackingApp.cpp
264 lines (210 loc) · 6.28 KB
/
IvryCustomTrackingApp.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
/*************************************************************************
*
* Copyright (C) 2016-2020 Mediator Software and/or its subsidiary(-ies).
* All rights reserved.
* Contact: Mediator Software ([email protected])
*
* NOTICE: All information contained herein is, and remains the property of
* Mediator Software and its suppliers, if any.
* The intellectual and technical concepts contained herein are proprietary
* to Mediator Software and its suppliers and may be covered by U.S. and
* Foreign Patents, patents in process, and are protected by trade secret or
* copyright law. Dissemination of this information or reproduction of this
* material is strictly forbidden unless prior written permission is obtained
* from Mediator Software.
*
* If you have questions regarding the use of this file, please contact
* Mediator Software ([email protected]).
*
***************************************************************************/
#include <winsock2.h>
#include <Ws2tcpip.h>
#include "IvryCustomTrackingApp.h"
// Socket prerequisites
// ==========================================
#pragma comment(lib, "Ws2_32.lib")
int WinsockInit(void) {
WSADATA wsa_data;
return WSAStartup(MAKEWORD(1, 1), &wsa_data);
}
int WinsockQuit(void) {
return WSACleanup();
}
SOCKET udp_socket;
int ReadAvail() {
int status;
u_long n = 0;
status = ioctlsocket(udp_socket, FIONREAD, &n);
if (status != 0)
return 0;
return (int)n;
}
// ==========================================
// Global variables that will override the position
double XPosOverride = 0;
double YPosOverride = 1;
double ZPosOverride = 0;
// Axis multipliers
double XMultiplier = 0.1;
double YMultiplier = 0.1;
double ZMultiplier = -0.1;
// Port number
int udp_port = 8021;
// Config file handling
// ==========================================
void WriteDefaultConfig() {
FILE* cfg_file = fopen("udp_bridge_config.ini", "w");
// Quietly exit if write failed
if (!cfg_file)
return;
fprintf(cfg_file, "%d %lf %lf %lf", udp_port, XMultiplier, YMultiplier, ZMultiplier);
fclose(cfg_file);
}
void LoadConfigFile() {
FILE* cfg_file = fopen("udp_bridge_config.ini", "r");
// Attempt to create the config file if we couldn't open it
if (!cfg_file) {
WriteDefaultConfig();
return;
}
fscanf(cfg_file, "%d %lf %lf %lf", &udp_port, &XMultiplier, &YMultiplier, &ZMultiplier);
fclose(cfg_file);
}
// ==========================================
IvryCustomTrackingApp::IvryCustomTrackingApp()
: m_hQuitEvent(INVALID_HANDLE_VALUE)
, m_bUseDeviceOrientation(true)
{
// Start position 1m off the ground at origin
m_afPosition[0] = m_afPosition[2] = 0;
m_afPosition[1] = 1;
}
IvryCustomTrackingApp::~IvryCustomTrackingApp()
{
if (m_hQuitEvent != INVALID_HANDLE_VALUE)
{
// Make sure event is signalled before deleting
::SetEvent(m_hQuitEvent);
::CloseHandle(m_hQuitEvent);
}
}
/** Run tracker **/
DWORD IvryCustomTrackingApp::Run()
{
DWORD result = ERROR_SUCCESS;
// Attempt to load the config file
LoadConfigFile();
// Init our socket subsystem
WinsockInit();
// Create a UDP socket
udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
// Bind it (messy)
struct addrinfo addr;
struct addrinfo *addr_result;
memset(&addr, 0, sizeof(addr));
addr.ai_family = AF_INET;
addr.ai_socktype = SOCK_DGRAM;
//addr.ai_protocol = 0;
addr.ai_flags = AI_PASSIVE;
// We need to convert port int to port string
// Use snprintf() to do so
char port_string[8];
snprintf(&port_string[0], 8, "%d", udp_port);
getaddrinfo(NULL, &port_string[0], &addr, &addr_result);
int status = bind(udp_socket, addr_result->ai_addr, (int)addr_result->ai_addrlen);
if (status == SOCKET_ERROR) {
LogMessage("UDP bridge: failed to bind to port ");
LogMessage(&port_string[0]);
LogMessage("\n");
}
int length = 0;
double position_data[6] = { 0.0 };
// 0 - X
// 1 - Y
// 2 - Z
// 3 - Pitch?
// 4 - Yaw?
// 6 - Roll?
// Open connection to driver
if (Open())
{
// Create 'exiting' event
m_hQuitEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
if (m_hQuitEvent != INVALID_HANDLE_VALUE)
{
// NOTE: in an external tracking process disabling device orientation and
// enabling external tracking would normally be done once the external
// tracking had actually begun, to avoid no tracking being active
// Disable device orientation
EnableDeviceOrientation(false);
// Enable external tracking
TrackingEnabled(true);
while (1) {
// Wait 10 ms for quit event on each iteration
if (::WaitForSingleObject(m_hQuitEvent, 10) != WAIT_TIMEOUT)
break;
// Loop to consume all available data in the socket
// We'll end up with the last and the most recent message
while (ReadAvail())
length = recv(udp_socket, (char *)&position_data[0], sizeof(double) * 6, 0);
if (length == sizeof(double) * 6) {
// If the length checks out, apply the values
XPosOverride = position_data[0] * XMultiplier;
YPosOverride = position_data[1] * YMultiplier;
ZPosOverride = position_data[2] * ZMultiplier;
}
}
// Disable external tracking
TrackingEnabled(false);
// Enable device orientation
EnableDeviceOrientation(true);
}
else
{
// Get last error code from Windows
result = ::GetLastError();
}
// Close connection to driver
Close();
}
else
{
// Get last error code from library
result = this->GetLastError();
}
// Socket cleanup
WinsockQuit();
return result;
}
/** Pose has been recevied from driver **/
void IvryCustomTrackingApp::OnDevicePoseUpdated(const vr::DriverPose_t &pose)
{
vr::DriverPose_t updatedPose = pose;
// Not using device orientation?
if (!m_bUseDeviceOrientation)
{
// Use tracker orientation
updatedPose.qRotation = { 1, 0, 0, 0 };
}
// Use the overriden positions
updatedPose.vecPosition[0] = XPosOverride;
updatedPose.vecPosition[1] = YPosOverride;
updatedPose.vecPosition[2] = ZPosOverride;
// Send tracker pose to driver
PoseUpdated(updatedPose);
}
/** Device orientation has been enabled/disabled by user **/
void IvryCustomTrackingApp::OnDeviceOrientationEnabled(bool enable)
{
m_bUseDeviceOrientation = enable;
}
/** Driver is requesting tracking process quit **/
void IvryCustomTrackingApp::OnQuit()
{
if (m_hQuitEvent != INVALID_HANDLE_VALUE)
{
// Signal that Run() can exit
::SetEvent(m_hQuitEvent);
}
LogMessage("Shutting down\n");
}