From f7b78a93027ebe4d21c5d992c64ff15777c88768 Mon Sep 17 00:00:00 2001 From: "Garcia-Hernandez, Ruben Jesus (rgarcia)" Date: Mon, 30 Jul 2018 16:34:01 +0200 Subject: [PATCH] Multiuser OpenVR NOMAD VR functionality: show remote user position and orientation of head and controllers. Enable atom drag-and-drop functionality (with external helper). --- NOMADVRLib/ConfigFile.cpp | 3 + OpenVR/TimestepData/hellovr_opengl_main.cpp | 537 ++++++++++++++++++-- RemoteVisualization/Makefile | 2 +- RemoteVisualization/exportXYZ.cpp | 22 + RemoteVisualization/exportXYZ.h | 6 + RemoteVisualization/main.cpp | 22 +- proxy/MD-driver/Makefile | 16 + proxy/MD-driver/PT.xyz | 120 +++++ proxy/MD-driver/PeriodicTable.cpp | 89 ++++ proxy/MD-driver/PeriodicTable.h | 3 + proxy/MD-driver/PeriodicTableMain.cpp | 27 + proxy/MD-driver/Readme | 19 + proxy/MD-driver/SimpleMove.cpp | 220 ++++++++ proxy/MD-driver/eprintf.cpp | 32 ++ proxy/MD-driver/exportXYZ.cpp | 23 + proxy/MD-driver/exportXYZ.h | 6 + proxy/MD-driver/myrecv.cpp | 18 + proxy/MD-driver/myrecv.h | 2 + proxy/MD-driver/state.h | 11 + proxy/Makefile | 6 +- proxy/proxy.cpp | 210 +++++++- 21 files changed, 1294 insertions(+), 100 deletions(-) create mode 100644 RemoteVisualization/exportXYZ.cpp create mode 100644 RemoteVisualization/exportXYZ.h create mode 100644 proxy/MD-driver/Makefile create mode 100644 proxy/MD-driver/PT.xyz create mode 100644 proxy/MD-driver/PeriodicTable.cpp create mode 100644 proxy/MD-driver/PeriodicTable.h create mode 100644 proxy/MD-driver/PeriodicTableMain.cpp create mode 100644 proxy/MD-driver/Readme create mode 100644 proxy/MD-driver/SimpleMove.cpp create mode 100644 proxy/MD-driver/eprintf.cpp create mode 100644 proxy/MD-driver/exportXYZ.cpp create mode 100644 proxy/MD-driver/exportXYZ.h create mode 100644 proxy/MD-driver/myrecv.cpp create mode 100644 proxy/MD-driver/myrecv.h create mode 100644 proxy/MD-driver/state.h diff --git a/NOMADVRLib/ConfigFile.cpp b/NOMADVRLib/ConfigFile.cpp index ef19a3b..365a442 100644 --- a/NOMADVRLib/ConfigFile.cpp +++ b/NOMADVRLib/ConfigFile.cpp @@ -213,6 +213,9 @@ void cleanConfig() numAtoms=nullptr; atoms=nullptr; } + + delete[] server; + server=nullptr; } void initState() diff --git a/OpenVR/TimestepData/hellovr_opengl_main.cpp b/OpenVR/TimestepData/hellovr_opengl_main.cpp index 8f8eeda..2bc4e31 100644 --- a/OpenVR/TimestepData/hellovr_opengl_main.cpp +++ b/OpenVR/TimestepData/hellovr_opengl_main.cpp @@ -42,6 +42,8 @@ #include #include #include +#include +#include #include @@ -84,6 +86,17 @@ #define NUMPLY (TIMESTEPS * ISOS) + +typedef struct remotes { + int id; + bool valid[3]; + float head[16]; + vr::HmdMatrix34_t c1, c2; + Vector3 UserPos; + unsigned char colour[3]; +} remotes_t; + + class CGLRenderModel { public: @@ -352,16 +365,33 @@ private: // OpenGL bookkeeping char **myargv; int currentConfig; - std::thread *tcpconn; + std::thread *tcpconn, *udpconn; void connectTCP(); - int sock; + void UDP(); + int UDPContr(SOCKET s, char c, int device); + int UDPHead(SOCKET s); + int sock, s; + struct sockaddr_in serv_addr; void Send(char c, int32_t value); void Send(char c, bool value); void SendConfigFile(); void SendTimestep(); void SendIso(); void SendShowAtoms(); + void SendUserPos(); + void SendDragDrop(Vector3 pos); + + std::vector remotes; + int32_t identifier; + int FindRemote(int32_t remote); + Vector3 initDrag; + Uint32 msDrag; + char whenDrag;// whenDrag=0: start; 1: middle; 2: end; 3: not sending + + char cleanup; //synch TCP and drawing thread on scene load + std::mutex cleanupmutex; + std::condition_variable cleanupcond; }; const float CMainApplication::videospeed = 0.01f; @@ -456,10 +486,155 @@ int CMainApplication::LoadConfigFile (const char *c) return r; } +int CMainApplication::UDPHead(SOCKET s) +{ + int n=0; + char buff[sizeof(float)*16+5]; + if ( m_rTrackedDevicePose[vr::k_unTrackedDeviceIndex_Hmd].bPoseIsValid ) { + buff[0]='h'; + memcpy(buff+1, &identifier, 4); + memcpy (buff+5, (char*)m_mat4HMDPose.get(), sizeof(float)*16); + n=send(s, buff, sizeof(float)*16+5, 0); + if (n<0) { + closesocket (s); + s=INVALID_SOCKET; + } + } + return n; +} + +int CMainApplication::UDPContr(SOCKET s, char c, int device) +{ +//datagrams can be reordered, so we cannot split type and payload +//reading a subset of the datagrams discards the rest, so we need to listen to the largest possible. + int n=0; + vr::VRControllerState_t cs; + vr::TrackedDevicePose_t dp; + char buff[sizeof(vr::HmdMatrix34_t) +5]; + if (!m_pHMD) + return -1; + m_pHMD->GetControllerStateWithPose( vr::TrackingUniverseStanding, device, &cs, &dp ); + if (dp.bPoseIsValid) { + vr::HmdMatrix34_t mat=dp.mDeviceToAbsoluteTracking; + buff[0]=c; + memcpy(buff+1, &identifier, 4); + memcpy(buff+5, mat.m, sizeof(mat.m)); + n=send(s, buff, sizeof(mat.m)+5, 0); + if (n<0) { + closesocket (s); + } + } + return n; +} + +void CMainApplication::UDP() +{ + //struct hostent *he; + //if ( (he = gethostbyname(server) ) == nullptr ) { + // eprintf ("Connect to server, could not get host name %s\n", server); + // return; /* error */ + //} + //memset((char *) &serv_addr, 0, sizeof(serv_addr)); + //memcpy(&serv_addr.sin_addr, he->h_addr_list[0], he->h_length); + //serv_addr.sin_family = AF_INET; + //serv_addr.sin_port = htons(port); + s=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); + if (s==INVALID_SOCKET) { + eprintf ("udp socket creation error %d, closing\n", WSAGetLastError()); + return; + } + if ( connect(s, (struct sockaddr *)&serv_addr, sizeof(serv_addr))) { + eprintf ("Udp Connect to server, could not get connection %s, got error %d\n", server, WSAGetLastError()); + return; /* error */ + } + + char buf[100]; + while (true) { + int n; + //Sleep(2000); //rgh fixme, should be approx one frame + Sleep (10); + if (sock==INVALID_SOCKET || s==INVALID_SOCKET) + return; + + struct sockaddr_in sin; + int addrlen = sizeof(sin); + if(getsockname(s, (struct sockaddr *)&sin, &addrlen) == 0 && + sin.sin_family == AF_INET && + addrlen == sizeof(sin)) { + int local_port = sin.sin_port; + } + //send head and controllerpos + n=0; + if (identifier==0) + continue; + if (firstdevice!=-1 ) { + n=UDPContr(s, '1', firstdevice); + if (n<0) + return; + } + if (seconddevice!=-1) { + n=UDPContr(s, '2', seconddevice); + if (n<0) + return; + } + + if ( UDPHead(s)<0 ) { + return; + } + //receive head and controllers + unsigned long l; + do { + ioctlsocket(s, FIONREAD, &l); + if (l>0) { //we have data + int32_t remote; + n=recv(s, buf, 5*4*4*sizeof(float), 0); + if (n<0) { //disconnected + eprintf ("udp disconnect\n"); + return; + } + //Beep( 750, 300 ); //rgh fixme + memcpy (&remote, buf+1, 4); + int i=FindRemote(remote); + if (buf[0]=='h') { + memcpy ((char*)&(remotes[i].head[0]), buf+5, sizeof(float)*16); + remotes[i].valid[0]=true; + } else if (buf[0]=='1') { + memcpy ((char*)remotes[i].c1.m, buf+5, sizeof(float)*12); + remotes[i].valid[1]=true; + } else if (buf[0]=='2') { + memcpy ((char*)remotes[i].c2.m, buf+5, sizeof(float)*12); + remotes[i].valid[2]=true; + } else { + eprintf ("Unknown udp command '%c'", buf[0]); + } + + } + } while (l>0); + } +} + +int CMainApplication::FindRemote(int32_t remote) +{ + int found=-1; + for (int i=0;i