Fix xyz loading, allow loading from web.

Cleanup fixes.
OpenVR: messages on extra thread to avoid interrupting VR.
Option "disablereloadreset" to keep user state on ncfg reload. By default,
resets to timestep 0, userpos from ncfg, etc.
parent f7b78a93
......@@ -86,6 +86,8 @@ int secret;
const char * server;
int port;
bool resetTimestepOnReload;
const char * loadConfigFileErrors[] =
{
"All Ok",//0
......@@ -115,12 +117,34 @@ const char * loadConfigFileErrors[] =
"Error loading analytics json file, add 400 to see the error",//<-400
};
void cleanMarkers()
{
for (int i=0;i<TIMESTEPS;i++)
delete markers[i];
delete[] markers;
markers=nullptr;
}
void cleanMarkerColours() {
for (int i=0;i<TIMESTEPS;i++)
delete markercolours[i];
delete[] markercolours;
markercolours=nullptr;
}
void updateTIMESTEPS (int timesteps)
{
if (TIMESTEPS==0)
if (TIMESTEPS==0) {
TIMESTEPS=timesteps;
else
TIMESTEPS=std::min(TIMESTEPS, timesteps);
} else {
if (TIMESTEPS!=timesteps) {
if (markers)
cleanMarkers();
if (markercolours)
cleanMarkerColours();
TIMESTEPS=std::min(TIMESTEPS, timesteps);
}
}
}
int readString(FILE *f, char *s)
......@@ -155,6 +179,9 @@ int readString(FILE *f, char *s)
void fixFile(char * file)
{
if (!strncmp (file, "http://", 7) || !strncmp(file, "https://", 8))
return;
#ifdef WIN32
const char c='\\';
#else
......@@ -190,13 +217,11 @@ void cleanConfig()
SCREENSHOT=nullptr;
if (markers) {
cleanMarkers();
for (int i=0;i<TIMESTEPS;i++) {
delete[] markers[i];
delete[] markercolours[i];
}
delete[] markers;
delete[] markercolours;
markers=nullptr;
markercolours=nullptr;
}
for (int i=0;i<info.size();i++) {
......@@ -301,8 +326,10 @@ void initState()
secret=0;
server=nullptr;
port=-1;
resetTimestepOnReload=true;
}
int loadConfigFile(const char * f)
{
//default values
......@@ -335,10 +362,7 @@ int loadConfigFile(const char * f)
if (!strcmp(s, "timesteps")) {
int timesteps;
r = fscanf(F, "%d", &timesteps);
if (TIMESTEPS==0)
TIMESTEPS=timesteps;
else
TIMESTEPS=std::min(TIMESTEPS, timesteps);
updateTIMESTEPS(timesteps);
}
else if (!strcmp(s, "isos")) {
if (ISOS!=0)
......@@ -572,6 +596,8 @@ int loadConfigFile(const char * f)
fclose(F);
return -17;
}
if (markers)
cleanMarkers();
markers=new float* [TIMESTEPS];
for (int i=0;i<TIMESTEPS;i++) {
markers[i]=new float[3];
......@@ -755,6 +781,8 @@ int loadConfigFile(const char * f)
#endif
} else if (!strcmp (s, "\x0d")) { //discard windows newline (problem in Sebastian Kokott's phone (?!)
continue;
} else if (!strcmp (s, "disablereloadreset")) {
resetTimestepOnReload=false;
} else if (!strcmp (s, "server")) { //multiuser support
int r;
if (server)
......
......@@ -88,6 +88,8 @@ extern int secret;
extern const char * server;
extern int port;
extern bool resetTimestepOnReload;
struct information {
float pos[3];
float size;
......
......@@ -38,7 +38,7 @@ grid::~grid()
void grid::coordinates(const float pos[3], int c[3])
{
for (int i=0;i<3;i++) {
c[i]=floor((pos[i]-m[i])/dif[i]*dims);
c[i]=static_cast<int>(floor((pos[i]-m[i])/dif[i]*dims));
if (c[i]>=dims)
c[i]=dims-1;
else if (c[i]<0)
......@@ -52,7 +52,7 @@ void grid::add (float *p) //compatible with the atoms xyzr
coordinates (p, pos);
content[pos[0]*dims*dims + pos[1]*dims+pos[2]].push_back(p);
float ar=atomRadius(p[3]);
float ar=atomRadius(static_cast<int>(p[3]));
if (ar>maxradius)
maxradius=ar;
}
......@@ -61,7 +61,7 @@ bool grid::compare (float *a, float *b)
{
if (a<=b) //already returned when searching a beforehand
return false;
float sqd=atomRadius(a[3])+atomRadius(b[3]);
float sqd=atomRadius(static_cast<int>(a[3]))+atomRadius(static_cast<int>(b[3]));
sqd*=sqd;
float d=0;
for (int i=0;i<3;i++)
......@@ -82,8 +82,8 @@ std::vector<float*> grid::find (float *p)
float mp[3];
float Mp[3];
for (int i=0;i<3;i++) {
mp[i]=p[i]-(atomRadius(p[3])+maxradius)/scale;
Mp[i]=p[i]+(atomRadius(p[3])+maxradius)/scale;
mp[i]=p[i]-(atomRadius(static_cast<int>(p[3]))+maxradius)/scale;
Mp[i]=p[i]+(atomRadius(static_cast<int>(p[3]))+maxradius)/scale;
}
coordinates(mp, mc);
coordinates(Mp, Mc);
......
......@@ -227,7 +227,7 @@ int findAtom(const char *const s)
strcpy (x, s);
char *p=x+strlen(x);
p--;
while (*p > '0' && *p <= '9') {
while (*p >= '0' && *p <= '9') {
*p='\0';
*p--;
if (p==x)
......@@ -260,7 +260,8 @@ const char * readAtomsXYZErrors[] = {
"Could not open file", //-1
"Error loading atom type and position line", //-2
"Atom type unknown", //-3
"Corrupt xyz file" //-4
"Corrupt xyz file", //-4
"Unable to download xyz file" //-5
};
void cleanAtoms (int **numatoms, int timesteps, float ***pos)
......@@ -276,10 +277,27 @@ void cleanAtoms (int **numatoms, int timesteps, float ***pos)
int readAtomsXYZ(const char *const file, int **numatoms, int *timesteps, float ***pos)
{
const char *myfile=nullptr;
const char *webdownload="material.xyz";
//add http support
if (!strncmp(file, "http:", 5) || !strncmp(file, "https:", 6)) {
char cmd[2048];
int ret;
sprintf (cmd, "wget %s -O %s", file, webdownload);
ret=system(cmd);
if (ret!=0) {
*numatoms=nullptr;
*pos=nullptr;
return (-5);
}
myfile=webdownload;
} else {
myfile = file;
}
int mynumatoms;
std::vector<float*> mypos;
std::vector<int> mynum;
FILE *f=fopen (file, "r");
FILE *f=fopen (myfile, "r");
int r;
char s[100];
if (f==0) {
......@@ -294,6 +312,7 @@ int readAtomsXYZ(const char *const file, int **numatoms, int *timesteps, float *
blanklines++;
if (blanklines>3) {
eprintf("Corrupt xyz file %s. Error at %d atoms\n", file, mynumatoms);
fclose(f);
return -4;
}
continue; //there may be a blank line at the end of the file
......@@ -311,8 +330,10 @@ int readAtomsXYZ(const char *const file, int **numatoms, int *timesteps, float *
char line[512];
fgets(line, 512, f);
r=sscanf (line, "%s %f %f %f %f", s, mypos.back()+4*i+0, mypos.back()+4*i+1,mypos.back()+4*i+2, &unused);
if (r<4)
if (r<4) {
fclose (f);
return -2;
}
int a=findAtom(s);
if (a==-1) {
eprintf ("Read atoms xyz, atom type unknown: %s", s);
......@@ -331,7 +352,7 @@ int readAtomsXYZ(const char *const file, int **numatoms, int *timesteps, float *
(*numatoms)[i]=mynum[i];
//eprintf ("Getting atoms, numatoms=%d",(*numatoms)[i]);
}
fclose (f);
return 0;
}
......@@ -367,9 +388,10 @@ int readAtomsCube(const char *const file, int **numatoms, int *timesteps, float
discardline(f); //two comments
discardline(f);
r = fscanf(f, "%d %f %f %f", *numatoms, cubetrans + 0, cubetrans + 1, cubetrans + 2);
if (r < 4)
if (r < 4) {
fclose (f);
return -2;
}
//rgh FIXME. Is this always bohr?
for (int i=0;i<3;i++)
cubetrans[i]*= 0.52918f;
......
......@@ -227,6 +227,9 @@ void CleanAtoms (GLuint **AtomVAO /*[4]*/, GLuint **AtomVertBuffer /*[3]*/, GLui
if (!numAtoms)
return;
if (*AtomVAO==nullptr)
return;
glDeleteVertexArrays(4, *AtomVAO);
glDeleteBuffers(3, *AtomVertBuffer);
glDeleteBuffers(1, BondIndices);
......@@ -764,6 +767,7 @@ GLenum SetupUnitCell(GLuint *UnitCellVAO, GLuint *UnitCellVertBuffer, GLuint *Un
if ((e = glGetError()) != GL_NO_ERROR)
eprintf( "opengl error %d, glBufferData index, l %d\n", e, __LINE__);
glBindVertexArray(0);
delete[] tmp;
return e;
}
......
......@@ -351,6 +351,7 @@ private: // OpenGL bookkeeping
char *pixels, *pixels2; //for saving screenshots to disk
int framecounter;
bool savetodisk;
bool showInfoBox;
int selectedAtom;
......@@ -370,7 +371,7 @@ private: // OpenGL bookkeeping
void UDP();
int UDPContr(SOCKET s, char c, int device);
int UDPHead(SOCKET s);
int sock, s;
SOCKET sock, s;
struct sockaddr_in serv_addr;
void Send(char c, int32_t value);
void Send(char c, bool value);
......@@ -417,6 +418,10 @@ void dprintf( const char *fmt, ... )
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_WARNING, "Warning", buffer, 0);
}
void message (char *buffer)
{
MessageBoxA (0, buffer, "Warning", 0);
}
//pure windows, no sdl
void eprintf( const char *fmt, ... )
......@@ -439,7 +444,7 @@ void eprintf( const char *fmt, ... )
if ( g_bPrintf )
printf( "%s", buffer );
MessageBoxA(0, buffer, "Warning", 0);
std::thread(message, buffer).detach();
}
int CMainApplication::LoadConfigFile (const char *c)
......@@ -689,7 +694,10 @@ void CMainApplication::connectTCP()
eprintf ("short read at socket\n");
return;
}
currentset=ntohl(tmp)%TIMESTEPS;
if (TIMESTEPS!=0)
currentset=ntohl(tmp)%TIMESTEPS;
else
currentset=ntohl(tmp);
break;
case 'i':
n=recv (sock, (char*)&tmp, sizeof(tmp), 0);
......@@ -726,13 +734,6 @@ void CMainApplication::connectTCP()
std::unique_lock<std::mutex> lk(cleanupmutex);
cleanupcond.wait(lk);
//OpenGL commands only in main thread
//CleanScene();
//LoadConfigFile(myargv[currentConfig]);
//SetupScene();
//cleanupmutex.lock();
//cleanup=0;
//cleanupmutex.unlock();
}
break;
case 'X':
......@@ -850,6 +851,8 @@ CMainApplication::CMainApplication(int argc, char *argv[])
, identifier(0)
, whenDrag (3)
, cleanup (0)
, showInfoBox (true)
, m_unInfoVAO (0)
{
LoadConfigFile(argv[currentConfig]);
for (int j=0;j<3;j++)
......@@ -1134,6 +1137,7 @@ void CMainApplication::Shutdown()
if (tcpconn) {
closesocket(sock);
sock=INVALID_SOCKET;
cleanupcond.notify_one(); //in case we are waiting for update
tcpconn->join();
delete tcpconn;
tcpconn=nullptr;
......@@ -1357,7 +1361,11 @@ void CMainApplication::Send(char c, bool value)
void CMainApplication::SendConfigFile()
{
Send('n', currentConfig);
if (sock != INVALID_SOCKET) {
Send('n', currentConfig);
} else {//notify for local execution
cleanup=1;
}
}
void CMainApplication::SendTimestep()
......@@ -1501,19 +1509,12 @@ bool CMainApplication::HandleInput()
if (currentConfig>=myargc)
currentConfig=1;
SendConfigFile();
//we will soon receive an order to reload the scene, so avoid double-reloading + race here
//CleanScene();
//LoadConfigFile(myargv[currentConfig]);
//SetupScene();
} else if (state.rAxis[0].y < -0.7 && state.rAxis[0].x > -0.4 && state.rAxis[0].x < 0.4) {
//prev config file
currentConfig--;
if (currentConfig<=0)
currentConfig=myargc-1;
SendConfigFile();
//CleanScene();
//LoadConfigFile(myargv[currentConfig]);
//SetupScene();
}
}
} else { //Drag and Drop
......@@ -1552,8 +1553,12 @@ bool CMainApplication::HandleInput()
else if(unDevice !=firstdevice && seconddevice==-1)
seconddevice=unDevice;
*/
if (firstdevice==unDevice)
savetodisk = !savetodisk;
if (firstdevice==unDevice) {
if (menubutton==Record)
savetodisk = !savetodisk;
else if (menubutton==Infobox)
showInfoBox= !showInfoBox;
}
else {
showAtoms= !showAtoms;
SendShowAtoms();
......@@ -1793,7 +1798,6 @@ void CMainApplication::RenderFrame()
cleanup=0;
cleanupmutex.unlock();
cleanupcond.notify_one();
//return;
}
int e;
......@@ -2089,7 +2093,8 @@ void CMainApplication::CleanScene()
CleanMarker(&m_unMarkerVAO, &m_glMarkerVertBuffer);
}
//infocube
::CleanInfoCube(&m_unInfoVAO, &m_unInfoVertBuffer, &m_unInfoIndexBuffer);
if (m_unInfoVAO != 0)
::CleanInfoCube(&m_unInfoVAO, &m_unInfoVertBuffer, &m_unInfoIndexBuffer);
cleanConfig();
ISOS=0;
}
......@@ -2108,6 +2113,14 @@ void CMainApplication::SetupScene()
SetupInfoCube();
movementspeed/=scaling;
SetupInfoBoxTexture();
SetupCameras(); //near and far plane may have changed
if (resetTimestepOnReload) {
currentset=0;
currentiso=ISOS;
UserPosition=Vector3(-userpos[0], -userpos[1], -userpos[2]);
SendUserPos();
selectedAtom=-1;
}
}
void CMainApplication::SetupInfoCube()
......@@ -2155,7 +2168,7 @@ Matrix4 i = matDeviceToTracking;
Matrix4 trans;
Vector3 iPos = (*pos)+Vector3(0,0.02,0); //raise glyph
Vector3 iPos = (*pos)+Vector3(0.0f,0.02f,0.0f); //raise glyph
int e;
trans.scale(0.05).translate(iPos); //translate(0,0.1,0);
......@@ -2178,31 +2191,31 @@ return true;
void FillVerticesGlyph (float * const vert, const int i, const float u)
{
for (int j=0;j<4;j++) {
vert[i*9*4+j*9+2]=0; //z
vert[i*9*4+j*9+3]=1; //w
vert[i*9*4+j*9+4]=0; //nx
vert[i*9*4+j*9+5]=0; //ny
vert[i*9*4+j*9+6]=-1; //nz
}
vert [i*9*4+0*9+0]=i+0; //x
vert [i*9*4+0*9+1]=0; //y
vert[i*9*4+j*9+2]=0.0f; //z
vert[i*9*4+j*9+3]=1.0f; //w
vert[i*9*4+j*9+4]=0.0f; //nx
vert[i*9*4+j*9+5]=0.0f; //ny
vert[i*9*4+j*9+6]=-1.0f; //nz
}
vert [i*9*4+0*9+0]=static_cast<float>(i+0); //x
vert [i*9*4+0*9+1]=0.0f; //y
vert [i*9*4+0*9+7]=u; //u
vert [i*9*4+0*9+8]=1; //v
vert [i*9*4+0*9+8]=1.0f; //v
vert [i*9*4+1*9+0]=i+1; //x
vert [i*9*4+1*9+1]=0; //y
vert [i*9*4+1*9+0]=static_cast<float>(i+1); //x
vert [i*9*4+1*9+1]=0.0f; //y
vert [i*9*4+1*9+7]=u+1.0f/16.0f; //u
vert [i*9*4+1*9+8]=1; //v
vert [i*9*4+1*9+8]=1.0f; //v
vert [i*9*4+2*9+0]=i+0; //x
vert [i*9*4+2*9+1]=1; //y
vert [i*9*4+2*9+0]=static_cast<float>(i+0); //x
vert [i*9*4+2*9+1]=1.0f; //y
vert [i*9*4+2*9+7]=u; //u
vert [i*9*4+2*9+8]=0; //v
vert [i*9*4+2*9+8]=0.0f; //v
vert [i*9*4+3*9+0]=i+1; //x
vert [i*9*4+3*9+1]=1; //y
vert [i*9*4+3*9+0]=static_cast<float>(i+1); //x
vert [i*9*4+3*9+1]=1.0f; //y
vert [i*9*4+3*9+7]=u+1.0f/16.0f; //u
vert [i*9*4+3*9+8]=0; //v
vert [i*9*4+3*9+8]=0.0f; //v
}
short int *FillIndicesGlyph (int l)
......@@ -2303,7 +2316,7 @@ void CMainApplication::RenderControllerGlyph (const vr::Hmd_Eye nEye, const int
SendDragDrop(pos);
}
if (selectedAtom==-1) { //isos
if (selectedAtom==-1 || numAtoms==nullptr || numAtoms[currentset]>=selectedAtom) { //isos
sprintf (string, "%d", currentiso+1);
} else {
pos-=Vector3(atoms[currentset][selectedAtom*4+0], atoms[currentset][selectedAtom*4+1], atoms[currentset][selectedAtom*4+2]);
......@@ -3328,7 +3341,7 @@ void CMainApplication::RenderScene(vr::Hmd_Eye nEye)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
if (menubutton==Infobox && savetodisk)
if (showInfoBox)
RenderInfo(nEye);
RenderAtoms(nEye);
RenderUnitCell(nEye);
......@@ -3954,17 +3967,11 @@ char * MainErrors [] = {
int main(int argc, char *argv[])
{
//https://stackoverflow.com/questions/8544090/detected-memory-leaks
/*_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
_CrtSetBreakAlloc(639);
_CrtSetBreakAlloc(783);
_CrtSetBreakAlloc(676);
_CrtSetBreakAlloc(675);
_CrtSetBreakAlloc(639);
_CrtSetBreakAlloc(125);
_CrtSetBreakAlloc(118);
_CrtSetBreakAlloc(117);
_CrtSetBreakAlloc(94);
_CrtSetBreakAlloc(93);*/
_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );/*
_CrtSetBreakAlloc(1969);
_CrtSetBreakAlloc(1918);
_CrtSetBreakAlloc(1226);
*/
TMPDIR=".\\";
//http://stackoverflow.com/questions/4991967/how-does-wsastartup-function-initiates-use-of-the-winsock-dll
WSADATA wsaData;
......
......@@ -47,6 +47,13 @@ Subdirectories:
Transforms a json from encyclopedia or archive into an XYZ file
Useful for the remote visualization infrastructure
proxy: Back-end support for multiuser support in OpenVR NOMAD VR.
NOMADVRproxy listens to connections and forwards user actions to rest of
users.
MD-Driver/SimpleMove and MD-Driver/PeriodicTable: see MD-Driver/Readme
Support for atom drag-and-drop functionality in OpenVR NOMAD VR.
More platforms will be added in the future.
The code is distributed under the Apache 2.0 License (See LICENSE file).
......
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