Multiuser OpenVR NOMAD VR functionality: show remote user position and

orientation of head and controllers.
Enable atom drag-and-drop functionality (with external helper).
parent c24926c9
......@@ -213,6 +213,9 @@ void cleanConfig()
numAtoms=nullptr;
atoms=nullptr;
}
delete[] server;
server=nullptr;
}
void initState()
......
This diff is collapsed.
all: NOMADVRLib/atoms.o eprintf.o happyhttp/happyhttp.o NOMADVRLib/ConfigFileAtoms.o main.o
all: NOMADVRLib/atoms.o eprintf.o happyhttp/happyhttp.o NOMADVRLib/ConfigFileAtoms.o main.o exportXYZ.o
g++ $^ -o nomad2xyz
.cpp.o:
......
#include <stdio.h>
#include "NOMADVRLib/ConfigFileAtoms.h"
#include "NOMADVRLib/atoms.hpp"
#include "exportXYZ.h"
void exportXYZ(const char * file, const char *mat, int timesteps)
{
FILE * f=fopen (file, "w");
for (int i=0;i<timesteps;i++) {
fprintf (f, "%d\n", numAtoms[i]);
fprintf (f, "Comment: Material=%s\n", mat);
for (int j=0;j<numAtoms[i];j++) {
fprintf (f, "%s\t%f\t%f\t%f\n", atomNames[(int)(atoms[i][j*4+3])],
atoms[i][j*4+0], atoms[i][j*4+1], atoms[i][j*4+2]);
}
}
}
#ifndef __EXPORTXYZ_H
#define __EXPORTXYZ_H
void exportXYZ(const char * file, const char *mat, int timesteps);
#endif
......@@ -17,26 +17,10 @@
#include "NOMADVRLib/eprintf.h"
#include "NOMADVRLib/ConfigFileAtoms.h"
#include "NOMADVRLib/atoms.hpp"
#include "exportXYZ.h"
int timesteps;
void exportXYZ(const char * file, const char *mat)
{
FILE * f=fopen (file, "w");
for (int i=0;i<timesteps;i++) {
fprintf (f, "%d\n", numAtoms[i]);
fprintf (f, "Comment: Material=%s\n", mat);
for (int j=0;j<numAtoms[i];j++) {
fprintf (f, "%s\t%f\t%f\t%f\n", atomNames[(int)(atoms[i][j*4+3])],
atoms[i][j*4+0], atoms[i][j*4+1], atoms[i][j*4+2]);
}
}
}
void usage (const char * argv0)
{
eprintf ("Usage: \n%s e <basename for encyclopedia json> xyz", argv0);
......@@ -56,10 +40,10 @@ int main (int argc, char **argv) {
readAtomsJson (argv[2], &numAtoms, &timesteps, &atoms, abc, &clonedAtoms);
//now export xyz
exportXYZ(argv[3], argv[2]);
exportXYZ(argv[3], argv[2], timesteps);
} else if (argv[1][0]=='a') {
readAtomsAnalyticsJson (argv[2], &numAtoms, &timesteps, &atoms, abc, &clonedAtoms);
exportXYZ (argv[3], argv[2]);
exportXYZ (argv[3], argv[2], timesteps);
} else {
usage(argv[0]);
return 2;
......
all: PeriodicTable SimpleMove
SimpleMove: SimpleMove.o PeriodicTable.o exportXYZ.o NOMADVRLib/ConfigFileAtoms.o NOMADVRLib/atoms.o \
happyhttp/happyhttp.o eprintf.o myrecv.o
g++ -g $^ -o $@
PeriodicTable: PeriodicTable.o NOMADVRLib/ConfigFileAtoms.o NOMADVRLib/atoms.o exportXYZ.o happyhttp/happyhttp.o \
eprintf.o PeriodicTableMain.o
g++ -g $^ -o $@
.cpp.o:
g++ -g -I. -std=c++11 $< -c -o $*.o
clean:
rm -f *.o PeriodicTable SimpleMove
118
Comment: Material=PeriodicTable
H 0.000000 0.000000 0.000000
He 17.000000 0.000000 0.000000
Li 0.000000 0.000000 1.000000
Be 1.000000 0.000000 1.000000
B 10.000000 0.000000 1.000000
C 11.000000 0.000000 1.000000
N 12.000000 0.000000 1.000000
O 13.000000 0.000000 1.000000
F 14.000000 0.000000 1.000000
Ne 15.000000 0.000000 1.000000
Na 0.000000 0.000000 2.000000
Mg 1.000000 0.000000 2.000000
Al 10.000000 0.000000 2.000000
Si 11.000000 0.000000 2.000000
P 12.000000 0.000000 2.000000
S 13.000000 0.000000 2.000000
Cl 14.000000 0.000000 2.000000
Ar 15.000000 0.000000 2.000000
K 0.000000 0.000000 3.000000
Ca 1.000000 0.000000 3.000000
Sc 2.000000 0.000000 3.000000
Ti 3.000000 0.000000 3.000000
V 4.000000 0.000000 3.000000
Cr 5.000000 0.000000 3.000000
Mn 6.000000 0.000000 3.000000
Fe 7.000000 0.000000 3.000000
Co 8.000000 0.000000 3.000000
Ni 9.000000 0.000000 3.000000
Cu 10.000000 0.000000 3.000000
Zn 11.000000 0.000000 3.000000
Ga 12.000000 0.000000 3.000000
Ge 13.000000 0.000000 3.000000
As 14.000000 0.000000 3.000000
Se 15.000000 0.000000 3.000000
Br 16.000000 0.000000 3.000000
Kr 17.000000 0.000000 3.000000
Rb 0.000000 0.000000 4.000000
Sr 1.000000 0.000000 4.000000
Y 2.000000 0.000000 4.000000
Zr 3.000000 0.000000 4.000000
Nb 4.000000 0.000000 4.000000
Mo 5.000000 0.000000 4.000000
Tc 6.000000 0.000000 4.000000
Ru 7.000000 0.000000 4.000000
Rh 8.000000 0.000000 4.000000
Pd 9.000000 0.000000 4.000000
Ag 10.000000 0.000000 4.000000
Cd 11.000000 0.000000 4.000000
In 12.000000 0.000000 4.000000
Sn 13.000000 0.000000 4.000000
Sb 14.000000 0.000000 4.000000
Te 15.000000 0.000000 4.000000
I 16.000000 0.000000 4.000000
Xe 17.000000 0.000000 4.000000
Cs 0.000000 0.000000 5.000000
Ba 1.000000 0.000000 5.000000
La 2.000000 0.000000 5.000000
Ce 4.000000 0.000000 9.000000
Pr 5.000000 0.000000 9.000000
Nd 6.000000 0.000000 9.000000
Pm 7.000000 0.000000 9.000000
Sm 8.000000 0.000000 9.000000
Eu 9.000000 0.000000 9.000000
Gd 10.000000 0.000000 9.000000
Tb 11.000000 0.000000 9.000000
Dy 12.000000 0.000000 9.000000
Ho 13.000000 0.000000 9.000000
Er 14.000000 0.000000 9.000000
Tm 15.000000 0.000000 9.000000
Yb 16.000000 0.000000 9.000000
Lu 17.000000 0.000000 9.000000
Hf 3.000000 0.000000 5.000000
Ta 4.000000 0.000000 5.000000
W 5.000000 0.000000 5.000000
Re 6.000000 0.000000 5.000000
Os 7.000000 0.000000 5.000000
Ir 8.000000 0.000000 5.000000
Pt 9.000000 0.000000 5.000000
Au 10.000000 0.000000 5.000000
Hg 11.000000 0.000000 5.000000
Tl 12.000000 0.000000 5.000000
Pb 13.000000 0.000000 5.000000
Bi 14.000000 0.000000 5.000000
Po 15.000000 0.000000 5.000000
At 16.000000 0.000000 5.000000
Rn 17.000000 0.000000 5.000000
Fr 0.000000 0.000000 6.000000
Ra 1.000000 0.000000 6.000000
Ac 2.000000 0.000000 6.000000
Th 4.000000 0.000000 10.000000
Pa 5.000000 0.000000 10.000000
U 6.000000 0.000000 10.000000
Np 7.000000 0.000000 10.000000
Pu 8.000000 0.000000 10.000000
Am 9.000000 0.000000 10.000000
Cm 10.000000 0.000000 10.000000
Bk 11.000000 0.000000 10.000000
Cf 12.000000 0.000000 10.000000
Es 13.000000 0.000000 10.000000
Fm 14.000000 0.000000 10.000000
Md 15.000000 0.000000 10.000000
No 16.000000 0.000000 10.000000
Lr 17.000000 0.000000 10.000000
Rf 3.000000 0.000000 6.000000
Ha 4.000000 0.000000 6.000000
Sg 5.000000 0.000000 6.000000
Ns 6.000000 0.000000 6.000000
Hs 7.000000 0.000000 6.000000
Mt 8.000000 0.000000 6.000000
Ds 9.000000 0.000000 6.000000
Rg 10.000000 0.000000 6.000000
Cn 11.000000 0.000000 6.000000
Nh 12.000000 0.000000 6.000000
Fl 13.000000 0.000000 6.000000
Mc 14.000000 0.000000 6.000000
Lv 15.000000 0.000000 6.000000
Ts 16.000000 0.000000 6.000000
Og 17.000000 0.000000 6.000000
#include "PeriodicTable.h"
void CreatePeriodicTable (float * atoms, float scaling)
{
atoms[0]=0; //H
atoms[1]=0;
atoms[2]=0;
atoms[3]=0;
atoms[4]=17*scaling; //He
atoms[5]=0;
atoms[6]=0;
atoms[7]=1;
int currentAtom=2;
for (int row=1;row<3;row ++) {
for (int j=0; j<2;j++) {//left
atoms[currentAtom*4]=j*scaling;
atoms[currentAtom*4+1]=0;
atoms[currentAtom*4+2]=-row*scaling;
atoms[currentAtom*4+3]=currentAtom;
currentAtom++;
}
for (int j=0; j<6;j++) {//right
atoms[currentAtom*4]=(j+12)*scaling;
atoms[currentAtom*4+1]=0;
atoms[currentAtom*4+2]=-row*scaling;
atoms[currentAtom*4+3]=currentAtom;
currentAtom++;
}
}
for (int row=3;row<5;row ++) {
for (int j=0; j<18;j++) {//left
atoms[currentAtom*4]=j*scaling;
atoms[currentAtom*4+1]=0;
atoms[currentAtom*4+2]=-row*scaling;
atoms[currentAtom*4+3]=currentAtom;
currentAtom++;
}
}
for (int row=5;row<7;row ++) {
for (int j=0; j<3;j++) {//left
atoms[currentAtom*4]=j*scaling;
atoms[currentAtom*4+1]=0;
atoms[currentAtom*4+2]=-row*scaling;
atoms[currentAtom*4+3]=currentAtom;
currentAtom++;
}
currentAtom+=14;
for (int j=0; j<15;j++) {//right
atoms[currentAtom*4]=(j+3)*scaling;
atoms[currentAtom*4+1]=0;
atoms[currentAtom*4+2]=-row*scaling;
atoms[currentAtom*4+3]=currentAtom;
currentAtom++;
}
}
//rare earths
currentAtom=57;
for (int row=0;row<2;row ++) {
for (int j=0; j<14;j++) {
atoms[currentAtom*4]=(j+4)*scaling;
atoms[currentAtom*4+1]=0;
atoms[currentAtom*4+2]=(-row-8)*scaling;
atoms[currentAtom*4+3]=currentAtom;
currentAtom++;
}
currentAtom=89;
}
}
void CreatePeriodicTable (float * atoms, float scaling);
#include "NOMADVRLib/ConfigFileAtoms.h"
#include "NOMADVRLib/atoms.hpp"
#include "exportXYZ.h"
#include "PeriodicTable.h"
int main (int argc, char ** argv)
{
//create periodic table
if (argc!=2) {
fprintf (stderr, "Required argument, XYZ filename\n");
return 1;
}
numAtoms=new int[1];
numAtoms[0]=118;
atoms=new float* [1];
atoms[0]=new float[118*4];
CreatePeriodicTable(atoms[0], 5);
exportXYZ(argv[1], "PeriodicTable", 1);
return 0;
}
Programs:
PeriodicTable
takes one filename as input and generates an XYZ with the atoms at the standard periodic table positions.
Simplemove
Parameters: <server> <port> <secret>
Usage:
Run the program in a shared filesystem folder.
The program connects to a NOMADVR proxy server, then generates config and xyz files
Other OpenVR NOMADVR instances can use these config files to enable atom Drag-and-drop functionality,
using the touchpad in the second controller.
The XYZ file in the disk contains the latest atom configuration.
Simplemove can be used as a sample program to interface OpenVR NOMAD VR with interactive molecular dynamics codes.
Compilation:
Requires: happyhttp NOMADVRLib rapidjson
Copy these folders here and run "make".
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include "NOMADVRLib/ConfigFileAtoms.h"
#include "NOMADVRLib/atoms.hpp"
#include "PeriodicTable.h"
#include "exportXYZ.h"
#include "state.h"
#include "myrecv.h"
#ifndef INVALID_SOCKET
#define INVALID_SOCKET -1
#define closesocket close
#endif
const int NUMATOMS=118;
int main (int argc, char ** argv)
{
if (argc!=4) {
fprintf (stderr, "Parameters: <server> <port> <secret>\n");
return 1;
}
state_t state;
numAtoms=new int[1];
numAtoms[0]=NUMATOMS;
atoms=new float* [1];
atoms[0]=new float[NUMATOMS*4];
CreatePeriodicTable(atoms[0], 5);
exportXYZ("A.xyz", "PeriodicTable", 1);
FILE *ncfg=fopen ("A.ncfg", "w");
fprintf (ncfg, "xyzfile A.xyz\n"
"server %s %s %s\n"
"menubutton Infobox\n"
"sidebuttontimestep 0\n", argv[1], argv[2], argv[3]);
fclose (ncfg);
//connect to server, TCP
int sock;
struct hostent *he;
struct sockaddr_in serv_addr;
if ( (he = gethostbyname(argv[1]) ) == nullptr ) {
fprintf (stderr, "Connect to server, could not get host name %s\n", argv[1]);
return 2; /* 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(atoi(argv[2]));
sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if ( connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr))) {
fprintf (stderr, "Connect to server, could not get connection %s\n", argv[1]);
return 3; /* error */
}
int n;
int32_t tmp;
tmp=htonl (atoi(argv[3])); //secret
n = send(sock, (char*)&tmp , sizeof(tmp), 0);
if (n<sizeof(tmp)) {
closesocket(sock);
sock=INVALID_SOCKET;
fprintf (stderr, "couldn't send secret\n");
return 4;
}
char buffer[100];
uint32_t ID;
int found;
while (true) {
n=myrecv(sock, buffer, 1, 0);
if (n<1) {
fprintf (stderr, "couldn't receive data command");
return 5;
}
printf ("received order %c\n", buffer[0]);
switch (buffer[0]) {
case 'X': // ID
n=myrecv(sock, &ID, 4, 0);
if (n<4) {
fprintf (stderr, "couldn't receive data X");
return 5;
}
break;
case 't':
n=myrecv(sock, &state.timestep, 4, 0);
if (n<4)
{
fprintf (stderr, "couldn't receive data t");
return 5;
}
break;
case 'i':
n=myrecv(sock, &state.iso, 4, 0);
if (n<4)
{
fprintf (stderr, "couldn't receive data i\n");
return 5;
}
break;
case 's':
n=myrecv(sock, &state.showatoms, 1, 0);
if (n<1)
{
fprintf (stderr, "couldn't receive data s\n");
return 5;
}
break;
case 'n':
n=myrecv(sock, &state.ncfg, 4, 0);
if (n<4)
{
fprintf (stderr, "couldn't receive data n\n");
return 5;
}
break;
case 'p': // user position
n=myrecv (sock, buffer+1, sizeof(float)*3 + 4, 0);
if (n<sizeof(float)*3 + 4) {
fprintf (stderr, "couldn't receive data p\n");
return 5;
}
break;
case 'd': //disconnect
n=myrecv (sock, buffer+1, 4, 0);
if (n<4)
{
fprintf (stderr, "couldn't receive data d\n");
return 5;
}
break;
case 'D': //Drag
n=myrecv (sock, buffer+1, 6*sizeof(float) + 4*2 +1, 0);
if (n<6*sizeof(float) + 4*2 +1)
{
fprintf (stderr, "couldn't receive data D\n");
return 5;
}
//find the nearest atom
//test, use atom 0
float orig[3];
float dest[3];
uint32_t ID, time;
char button;
memcpy (&ID, buffer+1, 4);
memcpy (orig, buffer+5, 3*sizeof(float));
memcpy (dest, buffer+5+3*sizeof(float), 3*sizeof(float));
memcpy (&time, buffer+5+6*sizeof(float), 4);
button=buffer[1+6*sizeof(float)+8];
if (button!=2) {
printf ("intermediate, discarding\n");
continue;
}
found=-1;
for (int i=0;i<NUMATOMS;i++) {
float sum=0;
for (int j=0;j<3;j++) {
const float tmp=atoms[0][i*4+j]-orig[j];
sum+=tmp*tmp;
}
const float r=atomRadius(static_cast<int>(atoms[0][i*4+3]));
if (sum < r*r) {
found=i;
break;
}
}
if (found!=-1) {
printf ("Starting Drag atom %d\n", found);
//drag it
for (int i=0;i<3;i++)
atoms[0][found*4+i]+=dest[i]-orig[i];
exportXYZ("A.xyz", "PeriodicTable", 1);
//reload scene
buffer[0]='n';
memcpy(buffer+1, (char*)&state.ncfg, 4);
n=send (sock, buffer, 5, 0);
if (n<5) {
fprintf (stderr, "could not send reload command\n");
return 6;
}
printf ("Reload sent\n");
}
break;
default:
fprintf (stderr, "Unknown command received: '%c', %d\n", buffer[0], buffer[0]);
return -5;
}
}
return 0;
}
/*
# Copyright 2016-2018 Ruben Jesus Garcia Hernandez
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
*/
#include <stdarg.h>
#include <stdio.h>
#include "NOMADVRLib/eprintf.h"
void eprintf( const char *fmt, ... )
{
va_list args;
char buffer[ 2048 ];
va_start( args, fmt );
vsprintf( buffer, fmt, args );
va_end( args );
fprintf(stderr, "%s\n", buffer );
}
#include <stdio.h>
#include "NOMADVRLib/ConfigFileAtoms.h"
#include "NOMADVRLib/atoms.hpp"
#include "exportXYZ.h"
void exportXYZ(const char * file, const char *mat, int timesteps)
{
FILE * f=fopen (file, "w");
for (int i=0;i<timesteps;i++) {
fprintf (f, "%d\n", numAtoms[i]);
fprintf (f, "Comment: Material=%s\n", mat);
for (int j=0;j<numAtoms[i];j++) {
fprintf (f, "%s\t%f\t%f\t%f\n", atomNames[(int)(atoms[i][j*4+3])],
atoms[i][j*4+0], atoms[i][j*4+1], atoms[i][j*4+2]);
}
}
fclose(f);
}
#ifndef __EXPORTXYZ_H
#define __EXPORTXYZ_H
void exportXYZ(const char * file, const char *mat, int timesteps);
#endif
#include <sys/socket.h>
#include "myrecv.h"
int myrecv(int sock,void *buffer,int len, int flags) {
int n=len;
char *mybuff=(char*)buffer;
int r;
do {
r=recv (sock, mybuff, n, flags);
if (r<0)
return r;
mybuff+=r;
n-=r;
} while (n>0);
return len;
}
int myrecv(int sock,void *buffer,int len, int flags);
#ifndef __STATE_H
#define __STATE_H
struct state_t {
int32_t timestep;
int32_t iso;
bool showatoms;
int32_t ncfg;
} state;
#endif
proxy: proxy.cpp Makefile
g++ -std=c++11 -g proxy.cpp -o proxy
NOMADVRproxy: proxy.cpp Makefile
g++ -std=c++11 -g proxy.cpp -o NOMADVRproxy
clean:
rm -f proxy.o proxy
rm -f proxy.o proxy NOMADVRproxy
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment