Start work on client/server.

Vive: Display iso and timestep, fix cleanup
parent 1feeb8ca
...@@ -82,6 +82,10 @@ menubutton_t menubutton; ...@@ -82,6 +82,10 @@ menubutton_t menubutton;
std::vector<information> info; std::vector<information> info;
int secret;
const char * server;
int port;
const char * loadConfigFileErrors[] = const char * loadConfigFileErrors[] =
{ {
"All Ok",//0 "All Ok",//0
...@@ -290,6 +294,10 @@ void initState() ...@@ -290,6 +294,10 @@ void initState()
bondscaling = 0.7f; bondscaling = 0.7f;
bondThickness = 1.0f; bondThickness = 1.0f;
secret=0;
server=nullptr;
port=-1;
} }
int loadConfigFile(const char * f) int loadConfigFile(const char * f)
...@@ -530,7 +538,7 @@ int loadConfigFile(const char * f) ...@@ -530,7 +538,7 @@ int loadConfigFile(const char * f)
return -11; return -11;
} }
} else if (!strcmp(s, "atomglyph")) { } else if (!strcmp(s, "atomglyph")) {
r=fscanf (F, "%s", s); r=fscanf (F, "%99s", s);
if (r==0) if (r==0)
return -15; return -15;
if (!strcmp(s, "icosahedron")) if (!strcmp(s, "icosahedron"))
...@@ -606,7 +614,7 @@ int loadConfigFile(const char * f) ...@@ -606,7 +614,7 @@ int loadConfigFile(const char * f)
} else if (!strcmp (s, "atomcolour")) { } else if (!strcmp (s, "atomcolour")) {
char atom [100]; char atom [100];
float rgb[3]; float rgb[3];
r = fscanf(F, "%s %f %f %f", atom, rgb, rgb + 1, rgb + 2); r = fscanf(F, "%99s %f %f %f", atom, rgb, rgb + 1, rgb + 2);
if (r!=4) { if (r!=4) {
eprintf ("Error loading atom colour"); eprintf ("Error loading atom colour");
return -19; return -19;
...@@ -622,7 +630,7 @@ int loadConfigFile(const char * f) ...@@ -622,7 +630,7 @@ int loadConfigFile(const char * f)
char atom [100]; char atom [100];
float rgb[3]; float rgb[3];
float size; float size;
r = fscanf(F, "%s %f %f %f %f", atom, rgb, rgb + 1, rgb + 2, &size); r = fscanf(F, "%99s %f %f %f %f", atom, rgb, rgb + 1, rgb + 2, &size);
if (r!=5) { if (r!=5) {
eprintf ("Error loading newatom"); eprintf ("Error loading newatom");
return -20; return -20;
...@@ -711,7 +719,7 @@ int loadConfigFile(const char * f) ...@@ -711,7 +719,7 @@ int loadConfigFile(const char * f)
eprintf("Error reading bondthickness"); eprintf("Error reading bondthickness");
} }
else if (!strcmp(s, "menubutton")) { else if (!strcmp(s, "menubutton")) {
r = fscanf(F, "%s", s); r = fscanf(F, "%99s", s);
if (!strcmp(s, "Record")) if (!strcmp(s, "Record"))
menubutton = Record; menubutton = Record;
else if (!strcmp(s, "Infobox")) else if (!strcmp(s, "Infobox"))
...@@ -743,6 +751,15 @@ int loadConfigFile(const char * f) ...@@ -743,6 +751,15 @@ int loadConfigFile(const char * f)
#endif #endif
} else if (!strcmp (s, "\x0d")) { //discard windows newline (problem in Sebastian Kokott's phone (?!) } else if (!strcmp (s, "\x0d")) { //discard windows newline (problem in Sebastian Kokott's phone (?!)
continue; continue;
} else if (!strcmp (s, "server")) { //multiuser support
int r;
if (server)
delete(server);
server=new char[100];
r=fscanf (F, "%99s %d %d", server, &port, &secret);
if (r<3) {
eprintf ("Error reading server paramters");
}
} else { } else {
eprintf( "Unrecognized parameter %s\n", s); eprintf( "Unrecognized parameter %s\n", s);
for (int i=0;i<strlen(s);i++) for (int i=0;i<strlen(s);i++)
......
...@@ -83,6 +83,11 @@ extern const char * loadConfigFileErrors[]; ...@@ -83,6 +83,11 @@ extern const char * loadConfigFileErrors[];
void cleanConfig(); void cleanConfig();
int loadConfigFile(const char * f); int loadConfigFile(const char * f);
//for multiuser
extern int secret;
extern const char * server;
extern int port;
struct information { struct information {
float pos[3]; float pos[3];
float size; float size;
......
...@@ -674,6 +674,8 @@ GLenum SetupMarker(GLuint *MarkerVAO, GLuint *MarkerVertBuffer) ...@@ -674,6 +674,8 @@ GLenum SetupMarker(GLuint *MarkerVAO, GLuint *MarkerVertBuffer)
void CleanUnitCell (GLuint *UnitCellVAO, GLuint *UnitCellVertBuffer, GLuint *UnitCellIndexBuffer) void CleanUnitCell (GLuint *UnitCellVAO, GLuint *UnitCellVertBuffer, GLuint *UnitCellIndexBuffer)
{ {
if (!has_abc)
return;
glDeleteVertexArrays(1, UnitCellVAO); glDeleteVertexArrays(1, UnitCellVAO);
glDeleteBuffers(1, UnitCellVertBuffer); glDeleteBuffers(1, UnitCellVertBuffer);
glDeleteBuffers(1, UnitCellIndexBuffer); glDeleteBuffers(1, UnitCellIndexBuffer);
......
/* /*
# Copyright 2016-2018 Ruben Jesus Garcia Hernandez # Copyright 2016-2018 Ruben Jesus Garcia-Hernandez
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
...@@ -16,19 +16,24 @@ ...@@ -16,19 +16,24 @@
#include <vector> #include <vector>
#include "LoadPNG.h" #include "LoadPNG.h"
#include "NOMADVRLib/eprintf.h"
#include "shared/lodepng.h" #include "shared/lodepng.h"
GLuint LoadPNG (const char *image) GLuint LoadPNG(const char *image, int renderMode)
{ {
GLuint m_iTexture;
glGenTextures(1, &m_iTexture);
glBindTexture(GL_TEXTURE_2D, m_iTexture);
std::vector<unsigned char> imageRGBA; std::vector<unsigned char> imageRGBA;
unsigned nImageWidth, nImageHeight; unsigned nImageWidth, nImageHeight;
unsigned nError = lodepng::decode(imageRGBA, nImageWidth, nImageHeight, unsigned nError = lodepng::decode(imageRGBA, nImageWidth, nImageHeight,
image); image);
if (nError!=0) {
eprintf ("Error loading texture %s, lodepng::decode error %d", image, nError);
return 0;
}
GLuint m_iTexture;
glGenTextures(1, &m_iTexture);
glBindTexture(GL_TEXTURE_2D, m_iTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, nImageWidth, nImageHeight, glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, nImageWidth, nImageHeight,
0, GL_RGBA, GL_UNSIGNED_BYTE, &imageRGBA[0]); 0, GL_RGBA, GL_UNSIGNED_BYTE, &imageRGBA[0]);
...@@ -36,9 +41,19 @@ GLuint LoadPNG (const char *image) ...@@ -36,9 +41,19 @@ GLuint LoadPNG (const char *image)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); switch (renderMode) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); case linear:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
break;
case nearest:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
break;
default:
eprintf("Error, unknown render mode in LoadPNG");
return 0;
}
//rgh fixme: revise this if texture sampling is too slow //rgh fixme: revise this if texture sampling is too slow
GLfloat fLargest; GLfloat fLargest;
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &fLargest); glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &fLargest);
......
/* /*
# Copyright 2016-2018 Ruben Jesus Garcia Hernandez # Copyright 2016-2018 Ruben Jesus Garcia-Hernandez
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
...@@ -18,6 +18,12 @@ ...@@ -18,6 +18,12 @@
#define LOADPNG_H #define LOADPNG_H
#include "NOMADVRLib/MyGL.h" #include "NOMADVRLib/MyGL.h"
GLuint LoadPNG (const char *image); enum RenderMode {
linear = 0,
nearest = 1,
error = 2
};
GLuint LoadPNG(const char *image, int renderMode=linear);
#endif #endif
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#define new DEBUG_NEW #define new DEBUG_NEW
#include <vector> #include <vector>
#include <thread>
#include <SDL.h> #include <SDL.h>
#include <GL/glew.h> #include <GL/glew.h>
...@@ -348,6 +349,10 @@ private: // OpenGL bookkeeping ...@@ -348,6 +349,10 @@ private: // OpenGL bookkeeping
int myargc; int myargc;
char **myargv; char **myargv;
int currentConfig; int currentConfig;
std::thread *tcpconn;
void connectTCP();
int sock;
}; };
const float CMainApplication::videospeed = 0.01f; const float CMainApplication::videospeed = 0.01f;
...@@ -429,9 +434,85 @@ int CMainApplication::LoadConfigFile (const char *c) ...@@ -429,9 +434,85 @@ int CMainApplication::LoadConfigFile (const char *c)
if (solid) if (solid)
MessageBoxA(0, "Only spheres implemented as atom glyphs in HTC Vive", "Atom Glyph", 0); MessageBoxA(0, "Only spheres implemented as atom glyphs in HTC Vive", "Atom Glyph", 0);
//change currentiso if needed
if (currentiso > ISOS || currentiso <0)
currentiso = (currentiso + ISOS + 1) % (ISOS+1); //beware of (-1)
//add multiuser support
if (port!=-1 && tcpconn==nullptr) { //do not change servers as we change config file for now
tcpconn=new std::thread(&CMainApplication::connectTCP, this);
}
return r; return r;
} }
void CMainApplication::connectTCP()
{
//https://stackoverflow.com/questions/5444197/converting-host-to-ip-by-sockaddr-in-gethostname-etc
struct sockaddr_in serv_addr;
struct hostent *he;
if ( (he = gethostbyname(server) ) == nullptr ) {
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);
sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if ( connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr))) {
return; /* error */
}
//read state
int n;
int32_t tmp;
tmp=htonl (secret);
n = send(sock, (char*)&tmp , sizeof(tmp), 0);
if (n<sizeof(tmp))
return;
char what;
while (true) {
n=recv(sock, &what, sizeof(what), 0);
if (n<1)
return;
switch (what) {
case 't':
n=recv (sock, (char*)&tmp, sizeof(tmp), 0);
if (n<sizeof(tmp))
return;
currentset=ntohl(tmp)%TIMESTEPS;
break;
case 'i':
n=recv (sock, (char*)&tmp, sizeof(tmp), 0);
if (n<sizeof(tmp))
return;
currentiso=ntohl(tmp)%(ISOS+1);
break;
case 's':
char s;
n=recv (sock, &s, sizeof(s), 0);
if (n<sizeof(s))
return;
showAtoms=(bool)s;
break;
case 'n':
n=recv (sock, (char*)&tmp, sizeof(tmp), 0);
if (n<sizeof(tmp))
return;
//load config file
if (currentConfig!=ntohl(tmp)%myargc) {
currentConfig=ntohl(tmp)%myargc;
CleanScene();
LoadConfigFile(myargv[currentConfig]);
SetupScene();
}
break;
default:
eprintf ("Unknown state sent from server: %c\n", what);
}
}
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: Constructor // Purpose: Constructor
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
...@@ -480,7 +561,7 @@ CMainApplication::CMainApplication(int argc, char *argv[]) ...@@ -480,7 +561,7 @@ CMainApplication::CMainApplication(int argc, char *argv[])
, m_bShowCubes(true) , m_bShowCubes(true)
, currentset(0) , currentset(0)
, elapsedtime(videospeed*float(SDL_GetTicks())) , elapsedtime(videospeed*float(SDL_GetTicks()))
, currentiso(ISOS) , currentiso(-1) // (-> ISOS, but at this point ISOS is not yet initialized)
, firstdevice(-1) , firstdevice(-1)
, seconddevice(-1) , seconddevice(-1)
, m_iTexture(0) , m_iTexture(0)
...@@ -500,6 +581,8 @@ CMainApplication::CMainApplication(int argc, char *argv[]) ...@@ -500,6 +581,8 @@ CMainApplication::CMainApplication(int argc, char *argv[])
, myargc(argc) , myargc(argc)
, myargv(argv) , myargv(argv)
, currentConfig(1) , currentConfig(1)
, tcpconn(0)
, sock(-1)
{ {
LoadConfigFile(argv[currentConfig]); LoadConfigFile(argv[currentConfig]);
for (int j=0;j<3;j++) for (int j=0;j<3;j++)
...@@ -1006,6 +1089,22 @@ bool CMainApplication::HandleInput() ...@@ -1006,6 +1089,22 @@ bool CMainApplication::HandleInput()
currentConfig++; currentConfig++;
if (currentConfig>=myargc) if (currentConfig>=myargc)
currentConfig=1; currentConfig=1;
if (sock>=0) {
char w='c';
int32_t tmp;
tmp=htonl(currentConfig);
int n;
n=send(sock, &w, sizeof(w), 0);
if (n<sizeof(w)) {
closesocket(sock);
sock=-1;
}
n=send(sock, (char*)&tmp, sizeof(tmp), 0);
if (n<sizeof(tmp)) {
closesocket(sock);
sock=-1;
}
}
CleanScene(); CleanScene();
LoadConfigFile(myargv[currentConfig]); LoadConfigFile(myargv[currentConfig]);
SetupScene(); SetupScene();
...@@ -1492,6 +1591,8 @@ bool CMainApplication::SetupTexturemaps() ...@@ -1492,6 +1591,8 @@ bool CMainApplication::SetupTexturemaps()
else else
path=s.substr(0, l)+"\\"+NUMBERTEXTURE; path=s.substr(0, l)+"\\"+NUMBERTEXTURE;
numbersTexture=LoadPNG(path.c_str(), nearest); numbersTexture=LoadPNG(path.c_str(), nearest);
if (numbersTexture==0)
eprintf ("Error loading %s\n", path);
return ( m_iTexture != 0 && e==GL_NO_ERROR); return ( m_iTexture != 0 && e==GL_NO_ERROR);
} }
...@@ -1535,8 +1636,10 @@ void CMainApplication::CleanScene() ...@@ -1535,8 +1636,10 @@ void CMainApplication::CleanScene()
ISOS=0; ISOS=0;
} }
//atoms //atoms
::CleanAtoms(&m_unAtomVAO, &m_glAtomVertBuffer, &BondIndices); if (atoms) {
::cleanAtoms(&numAtoms, TIMESTEPS, &atoms); ::CleanAtoms(&m_unAtomVAO, &m_glAtomVertBuffer, &BondIndices);
::cleanAtoms(&numAtoms, TIMESTEPS, &atoms);
}
//unit cell //unit cell
::CleanUnitCell(&m_unUnitCellVAO, &m_glUnitCellVertBuffer, &m_glUnitCellIndexBuffer); ::CleanUnitCell(&m_unUnitCellVAO, &m_glUnitCellVertBuffer, &m_glUnitCellIndexBuffer);
//marker //marker
...@@ -1739,49 +1842,39 @@ float GetTextureCoordinate (char c) ...@@ -1739,49 +1842,39 @@ float GetTextureCoordinate (char c)
return u; return u;
} }
//if selected atom, display atom # and distance.
//Otherwise, display timestep in firstdevice and iso in seconddevice
void CMainApplication::RenderControllerGlyph (const vr::Hmd_Eye nEye, const int controller) void CMainApplication::RenderControllerGlyph (const vr::Hmd_Eye nEye, const int controller)
{ {
if (selectedAtom==-1) char string[200];
return;
if (controller == seconddevice) {
Vector3 pos;
PrepareControllerGlyph(nEye, controller, &pos);
pos /=scaling;
pos-=UserPosition;
pos=Vector3(pos[0], -pos[2], pos[1]);
pos-=Vector3(atoms[currentset][selectedAtom*4+0], atoms[currentset][selectedAtom*4+1], atoms[currentset][selectedAtom*4+2]);
char dis [200];
sprintf (dis, "%0.2fa", pos.length());
int l=strlen (dis);
float *vert;
vert=new float[l*4*(4+3+2)];
for (int i=0;i<l;i++) {
float u=GetTextureCoordinate(dis[i]);
FillVerticesGlyph (vert, i, u);
} //for
short int *ind=FillIndicesGlyph(l);
RenderNumbersControllerGlyph (l, vert, ind, numbersTexture);
return;
} // if
if (selectedAtom==-1)
return;
Vector3 pos; Vector3 pos;
PrepareControllerGlyph(nEye, controller, &pos); PrepareControllerGlyph(nEye, controller, &pos);
if (controller == seconddevice) {
//display atom number if (selectedAtom==-1) { //isos
char atom [200]; sprintf (string, "%d", currentiso+1);
sprintf (atom, "%d", selectedAtom+1); } else {
//sprintf (atom, "%d %.2f %.2f %.2f", selectedAtom+1, atoms[currentset][selectedAtom*4+0], atoms[currentset][selectedAtom*4+1], atoms[currentset][selectedAtom*4+2]); pos /=scaling;
int l=strlen (atom); pos-=UserPosition;
pos=Vector3(pos[0], -pos[2], pos[1]);
pos-=Vector3(atoms[currentset][selectedAtom*4+0], atoms[currentset][selectedAtom*4+1], atoms[currentset][selectedAtom*4+2]);
sprintf (string, "%0.2fa", pos.length());
} //if selectedatom
} else { // if controller == firstdevice
if (selectedAtom==-1) { //timestep
sprintf (string, "%d", currentset+1);
} else {
//display atom number
sprintf (string, "%d", selectedAtom+1);
//sprintf (atom, "%d %.2f %.2f %.2f", selectedAtom+1, atoms[currentset][selectedAtom*4+0], atoms[currentset][selectedAtom*4+1], atoms[currentset][selectedAtom*4+2]);
}
}
int l=strlen (string);
float *vert; float *vert;
vert=new float[l*4*(4+3+2)]; vert=new float[l*4*(4+3+2)];
for (int i=0;i<l;i++) { for (int i=0;i<l;i++) {
float u=GetTextureCoordinate(atom[i]); float u=GetTextureCoordinate(string[i]);
FillVerticesGlyph (vert, i, u); FillVerticesGlyph (vert, i, u);
} }
...@@ -2814,7 +2907,7 @@ void CMainApplication::RenderScene(vr::Hmd_Eye nEye) ...@@ -2814,7 +2907,7 @@ void CMainApplication::RenderScene(vr::Hmd_Eye nEye)
PaintGrid(nEye, i); PaintGrid(nEye, i);
} //for all isos in descending order } //for all isos in descending order
if ((e = glGetError()) != GL_NO_ERROR) if ((e = glGetError()) != GL_NO_ERROR)
dprintf("Gl error after paintgrid: %d, %s\n", e, gluErrorString(e)); dprintf("Gl error after paintgrid within RenderScene: %d, %s\n", e, gluErrorString(e));
if (numAtoms!=0) { if (numAtoms!=0) {
if (menubutton == Infobox && savetodisk) if (menubutton == Infobox && savetodisk)
RenderInfo(nEye); RenderInfo(nEye);
......
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