99#include < chrono>
1010
1111#if defined( _WINDOWS )
12- #include < windows.h>
12+ // #include <windows.h>
13+ #include < winsock2.h>
14+ #pragma comment (lib, "WSock32.Lib")
1315#endif
1416
1517using namespace vr ;
@@ -74,57 +76,35 @@ static const char * const k_pch_Sample_ScreenOffsetX_Int32 = "ScreenOffsetX";
7476static const char * const k_pch_Sample_DebugMode_Bool = " DebugMode" ;
7577
7678
77- #define FREETRACK_HEAP " FT_SharedMem"
78- #define FREETRACK_MUTEX " FT_Mutext"
79-
80- /* only 6 headpose floats and the data id are filled -sh */
81- typedef struct FTData__ {
82- uint32_t DataID;
83- int32_t CamWidth;
84- int32_t CamHeight;
85- /* virtual pose */
86- float Yaw; /* positive yaw to the left */
87- float Pitch; /* positive pitch up */
88- float Roll; /* positive roll to the left */
89- float X;
90- float Y;
91- float Z;
92- /* raw pose with no smoothing, sensitivity, response curve etc. */
93- float RawYaw;
94- float RawPitch;
95- float RawRoll;
96- float RawX;
97- float RawY;
98- float RawZ;
99- /* raw points, sorted by Y, origin top left corner */
100- float X1;
101- float Y1;
102- float X2;
103- float Y2;
104- float X3;
105- float Y3;
106- float X4;
107- float Y4;
108- } volatile FTData;
109-
110- typedef struct FTHeap__ {
111- FTData data;
112- int32_t GameID;
113- union
114- {
115- unsigned char table[8 ];
116- int32_t table_ints[2 ];
117- };
118- int32_t GameID2;
119- } volatile FTHeap;
79+ // OpenTrack vars
80+ double Yaw = 0 , Pitch = 0 , Roll = 0 ;
81+ double pX = 0 , pY = 0 , pZ = 0 ;
82+ struct TOpenTrack {
83+ double X;
84+ double Y;
85+ double Z;
86+ double Yaw;
87+ double Pitch;
88+ double Roll;
89+ };
90+ TOpenTrack OpenTrack;
91+ // WinSock
92+ SOCKET socketS;
93+ int bytes_read;
94+ struct sockaddr_in from;
95+ int fromlen;
96+ bool SocketActivated = false ;
97+ bool bKeepReading = false ;
12098
121- static HANDLE hFTMemMap = 0 ;
122- static FTHeap *ipc_heap = 0 ;
123- static HANDLE ipc_mutex = 0 ;
99+ std::thread *pSocketThread = NULL ;
124100
125- FTData *FreeTrack;
126- bool HMDConnected = false ;
127- std::thread *pFTthread = NULL ;
101+ // -----------------------------------------------------------------------------
102+ // Purpose:
103+ // -----------------------------------------------------------------------------
104+
105+ double DegToRad (double f) {
106+ return f * (3.14159265358979323846 / 180 );
107+ }
128108
129109inline vr::HmdQuaternion_t EulerAngleToQuaternion (double Yaw, double Pitch, double Roll)
130110{
@@ -145,43 +125,30 @@ inline vr::HmdQuaternion_t EulerAngleToQuaternion(double Yaw, double Pitch, doub
145125 return q;
146126}
147127
148- // FreeTrack implementation from OpenTrack (https://github.com/opentrack/opentrack/tree/unstable/freetrackclient)
149- static BOOL impl_create_mapping (void )
128+ void WinSockReadFunc ()
150129{
151- if (ipc_heap != NULL )
152- return TRUE ;
153-
154- hFTMemMap = CreateFileMappingA (INVALID_HANDLE_VALUE,
155- NULL ,
156- PAGE_READWRITE,
157- 0 ,
158- sizeof (FTHeap),
159- (LPCSTR)FREETRACK_HEAP);
160-
161- if (hFTMemMap == NULL )
162- return (ipc_heap = NULL ), FALSE ;
163-
164- ipc_heap = (FTHeap*)MapViewOfFile (hFTMemMap, FILE_MAP_WRITE, 0 , 0 , sizeof (FTHeap));
165- ipc_mutex = CreateMutexA (NULL , FALSE , FREETRACK_MUTEX);
166-
167- return TRUE ;
168- }
169-
170- void FTRead ()
171- {
172- while (HMDConnected) {
173- if (ipc_mutex && WaitForSingleObject (ipc_mutex, 16 ) == WAIT_OBJECT_0) {
174- memcpy (&FreeTrack, &ipc_heap, sizeof (FreeTrack));
175- if (ipc_heap->data .DataID > (1 << 29 ))
176- ipc_heap->data .DataID = 0 ;
177- ReleaseMutex (ipc_mutex);
130+ while (SocketActivated) {
131+ // Read UDP socket with OpenTrack data
132+ bKeepReading = true ;
133+ while (bKeepReading) {
134+ memset (&OpenTrack, 0 , sizeof (OpenTrack));
135+ bytes_read = recvfrom (socketS, (char *)(&OpenTrack), sizeof (OpenTrack), 0 , (sockaddr*)&from, &fromlen);
136+
137+ if (bytes_read > 0 ) {
138+ Yaw = DegToRad (OpenTrack.Yaw );
139+ Pitch = DegToRad (OpenTrack.Pitch );
140+ Roll = DegToRad (OpenTrack.Roll );
141+ pX = OpenTrack.X ;
142+ pY = OpenTrack.Y ;
143+ pZ = OpenTrack.Z ;
144+ }
145+ else {
146+ bKeepReading = false ;
147+ }
178148 }
179149 }
180150}
181151
182- // -----------------------------------------------------------------------------
183- // Purpose:
184- // -----------------------------------------------------------------------------
185152class CSampleDeviceDriver : public vr ::ITrackedDeviceServerDriver, public vr::IVRDisplayComponent
186153{
187154public:
@@ -405,12 +372,14 @@ class CSampleDeviceDriver : public vr::ITrackedDeviceServerDriver, public vr::IV
405372 virtual DriverPose_t GetPose ()
406373 {
407374 DriverPose_t pose = { 0 };
408- if (HMDConnected) {
375+
376+ if (SocketActivated) {
409377 pose.poseIsValid = true ;
410378 pose.result = TrackingResult_Running_OK;
411379 pose.deviceIsConnected = true ;
412380 }
413- else {
381+ else
382+ {
414383 pose.poseIsValid = false ;
415384 pose.result = TrackingResult_Uninitialized;
416385 pose.deviceIsConnected = false ;
@@ -419,15 +388,13 @@ class CSampleDeviceDriver : public vr::ITrackedDeviceServerDriver, public vr::IV
419388 pose.qWorldFromDriverRotation = HmdQuaternion_Init (1 , 0 , 0 , 0 );
420389 pose.qDriverFromHeadRotation = HmdQuaternion_Init (1 , 0 , 0 , 0 );
421390
422- if (HMDConnected) {
423- // Set head tracking rotation
424- pose.qRotation = EulerAngleToQuaternion (FreeTrack->Roll , -FreeTrack->Yaw , FreeTrack->Pitch );
391+ // Set head tracking rotation
392+ pose.qRotation = EulerAngleToQuaternion (Roll, -Yaw, Pitch);
425393
426- // Set position tracking
427- pose.vecPosition [0 ] = FreeTrack->X * 0.001 ; // millimeters to meters
428- pose.vecPosition [1 ] = FreeTrack->Z * 0.001 ; // millimeters to meters
429- pose.vecPosition [2 ] = FreeTrack->Y * 0.001 ; // millimeters to meters
430- }
394+ // Set position tracking
395+ pose.vecPosition [0 ] = pX * 0.01 ;
396+ pose.vecPosition [1 ] = pZ * 0.01 ;
397+ pose.vecPosition [2 ] = pY * 0.01 ;
431398
432399 return pose;
433400 }
@@ -498,12 +465,46 @@ EVRInitError CServerDriver_Sample::Init( vr::IVRDriverContext *pDriverContext )
498465 VR_INIT_SERVER_DRIVER_CONTEXT ( pDriverContext );
499466 // InitDriverLog( vr::VRDriverLog() );
500467
501- if (impl_create_mapping () == false ) {
502- HMDConnected = false ;
468+ // Open UDP port for receive data from OpenTrack ("UDP over network", 127.0.0.1, 4242)
469+ WSADATA wsaData;
470+ int iResult;
471+ iResult = WSAStartup (MAKEWORD (2 , 2 ), &wsaData);
472+ if (iResult == 0 ) {
473+ struct sockaddr_in local;
474+ fromlen = sizeof (from);
475+ local.sin_family = AF_INET;
476+ local.sin_port = htons (4242 );
477+ local.sin_addr .s_addr = INADDR_ANY;
478+
479+ socketS = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
480+
481+ u_long nonblocking_enabled = true ;
482+ ioctlsocket (socketS, FIONBIO, &nonblocking_enabled);
483+
484+ if (socketS != INVALID_SOCKET) {
485+
486+ iResult = bind (socketS, (sockaddr*)&local, sizeof (local));
487+
488+ if (iResult != SOCKET_ERROR) {
489+ SocketActivated = true ;
490+ pSocketThread = new std::thread (WinSockReadFunc);
491+ }
492+ else {
493+ WSACleanup ();
494+ SocketActivated = false ;
495+ }
496+
497+ }
498+ else {
499+ WSACleanup ();
500+ SocketActivated = false ;
501+ }
502+
503503 }
504- else {
505- HMDConnected = true ;
506- pFTthread = new std::thread (FTRead);
504+ else
505+ {
506+ WSACleanup ();
507+ SocketActivated = false ;
507508 }
508509
509510 m_pNullHmdLatest = new CSampleDeviceDriver ();
@@ -514,13 +515,15 @@ EVRInitError CServerDriver_Sample::Init( vr::IVRDriverContext *pDriverContext )
514515
515516void CServerDriver_Sample::Cleanup ()
516517{
517- if (HMDConnected ) {
518- HMDConnected = false ;
519- if (pFTthread ) {
520- pFTthread ->join ();
521- delete pFTthread ;
522- pFTthread = nullptr ;
518+ if (SocketActivated ) {
519+ SocketActivated = false ;
520+ if (pSocketThread ) {
521+ pSocketThread ->join ();
522+ delete pSocketThread ;
523+ pSocketThread = nullptr ;
523524 }
525+ closesocket (socketS);
526+ WSACleanup ();
524527 }
525528 // CleanupDriverLog();
526529 delete m_pNullHmdLatest;
0 commit comments