diff --git a/NOMADVRLib/ConfigFile.cpp b/NOMADVRLib/ConfigFile.cpp index 63976160203008cd48beb901b315eca7ba38a95a..549af326797f09b289d8b6eabc3de93bc3f0bf96 100644 --- a/NOMADVRLib/ConfigFile.cpp +++ b/NOMADVRLib/ConfigFile.cpp @@ -78,8 +78,9 @@ const char * loadConfigFileErrors[] = "markercolours with no previous correct timesteps parameter", //-18 "Error reading atomcolour", // -19 "Error loading xyz file, add 100 to see the error",//<-100 - "Error loading cube file, add 100 to see the error",//<-200 - "Error loading json file, add 200 to see the error",//<-300 + "Error loading cube file, add 200 to see the error",//<-200 + "Error loading encyclopedia json file, add 300 to see the error",//<-300 + "Error loading analytics json file, add 400 to see the error",//<-400 }; void updateTIMESTEPS (int timesteps) @@ -180,6 +181,7 @@ int loadConfigFile(const char * f) screenshotdownscaling=1; hapticFeedback=false; showcontrollers=false; + inv_abc_init=false; // FILE *F = fopen(f, "r"); if (F == 0) @@ -328,7 +330,7 @@ int loadConfigFile(const char * f) } has_abc = true; } - else if (!strcmp(s, "json")) { + else if (!strcmp(s, "json") || !strcmp (s, "encyclopediajson")) { r=readString(F, s); if (r!=0) return -14; @@ -344,7 +346,24 @@ int loadConfigFile(const char * f) numClonedAtoms=clonedAtoms[0].size()/4; has_abc=true; updateTIMESTEPS (timesteps); - } + } + else if (!strcmp(s, "analyticsjson")) { + r = readString(F, s); + if (r != 0) + return -14; + char file[256]; + sprintf(file, "%s%s", PATH, s); + fixFile(file); + int e; + int timesteps; + //rgh fixme, we know only one + e = readAtomsAnalyticsJson(file, &numAtoms, ×teps, &atoms, abc, &clonedAtoms); + if (e<0) + return e - 400; + numClonedAtoms = clonedAtoms[0].size() / 4; + has_abc = true; + updateTIMESTEPS(timesteps); + } else if (!strcmp(s, "baseurl")) { r=readString (F, base_url); if (r!=0) diff --git a/NOMADVRLib/IsosurfacesGL.cpp b/NOMADVRLib/IsosurfacesGL.cpp index f1c0ac93d9eac0a0c038614c53b03380e0ef1f08..16997994eee2700bc8a41c84676825622813edcb 100644 --- a/NOMADVRLib/IsosurfacesGL.cpp +++ b/NOMADVRLib/IsosurfacesGL.cpp @@ -2,6 +2,7 @@ #include <vector> #include <math.h> +#include <stdint.h> #include "MyGL.h" #include "eprintf.h" diff --git a/NOMADVRLib/atoms.cpp b/NOMADVRLib/atoms.cpp index 354cf0d722a8c14c9e071b6b08a191c3f2c691fe..957e559e64a4987cfcfd9ebabd45fc174f3a74ab 100644 --- a/NOMADVRLib/atoms.cpp +++ b/NOMADVRLib/atoms.cpp @@ -24,6 +24,11 @@ const char * TMPDIR;//filled by main //="/storage/540E-1AE2/"; #endif +bool inv_abc_init=false; +float inv_abc[3][3]; + + + const char * const atomNames[] = { @@ -493,7 +498,7 @@ return readAtomsJson (cmd, numatoms, timesteps, pos, abc, clonedAtoms, token); bool isAlmostZero(float coordinate) { - return (coordinate < 1E-5); + return (fabs(coordinate) < 1E-5); } void add (std::vector<float> *v, float x, float y, float z, float a) @@ -504,6 +509,71 @@ void add (std::vector<float> *v, float x, float y, float z, float a) v->push_back(a); } +const char * readAtomsAnalyticsJsonErrors[] = { + "All Ok",//0 + "Could not open file", //-1 + "atom_species not in json", //-2 + "json parse error or no atom_positions", //-3 + "lattice_vectors not in json", //-4 +}; + +int readAtomsAnalyticsJson(const char *const f, int **numatoms, int *timesteps, float ***pos, float abc[3][3], + std::vector<float>** clonedAtoms) +{ + float tmppos[3]; + + FILE *fp = fopen(f, "r"); + if (fp == 0) { + eprintf("readAtomsAnalyticsJson, could not open file %s", f); + return -1; + } + char readBuffer[65536]; + rapidjson::FileReadStream is(fp, readBuffer, sizeof(readBuffer)); + rapidjson::Document json; + json.ParseStream(is); + fclose(fp); + *timesteps = 1; + *pos = new float*[*timesteps]; + *numatoms = new int[*timesteps]; + *clonedAtoms=new std::vector<float>[*timesteps]; + if (!json.HasParseError() && json.HasMember("atom_positions")) { + if (json.HasMember("lattice_vectors")) { + const rapidjson::GenericValue<rapidjson::UTF8<> > &lv = json["lattice_vectors"]; + const rapidjson::GenericValue<rapidjson::UTF8<> > &flatdata = lv["flatData"]; + for (int i=0;i<3;i++) + for (int j=0;j<3;j++) + abc[i][j]=flatdata[i*3+j].GetFloat()*1e10; // meter -> aangstrom + } else return (-4); + const rapidjson::GenericValue<rapidjson::UTF8<> > &result = json["atom_positions"]; + if (!result.HasMember("shape")) + return (-1); + const rapidjson::GenericValue<rapidjson::UTF8<> > &shape = result["shape"]; //[numatoms, 3] + **numatoms = shape[0].GetInt(); + (*pos)[0] = new float[**numatoms * 4]; + if (json.HasMember("atom_species")) { + const rapidjson::GenericValue<rapidjson::UTF8<> > &results = json["atom_species"]; + for (int i = 0; i < **numatoms ; i++) + (*pos)[0][i*4+3]=results[i].GetInt()-1; + + + //atoms are stored in space coordinates, in meters + //rgh FIXME: disable cloned atoms for now + const rapidjson::GenericValue<rapidjson::UTF8<> > &flatdata = result["flatData"]; + for (int i = 0; i < **numatoms ; i++) { + for (int j=0;j<3;j++) + (*pos)[0][i*4+j] = flatdata[i*3+j].GetFloat()*1e10; //we store them in aangstrom + CloneSpatialAtoms((*pos)[0], (*pos)[0][3], *clonedAtoms); + } + } + else return (-2); + + } + else return (-3); + + TransformAtoms(*clonedAtoms, abc); + return 0; +} + int readAtomsJson (const char *const f, int **numatoms, int *timesteps, float ***pos, float abc[3][3], std::vector<float>** clonedAtoms, const char *const token) { @@ -600,13 +670,14 @@ int readAtomsJson (const char *const f, int **numatoms, int *timesteps, float ** (**pos)[4*i+s]=tmppos[0]*abc[0][s]+tmppos[1]*abc[1][s]+tmppos[2]*abc[2][s]; - } - TransformAtoms(*clonedAtoms, abc); + } + TransformAtoms(*clonedAtoms, abc); //eprintf ("readAtomsJson, end"); return 0; } +//from abc coordinates to spatial coordinates void TransformAtoms(std::vector<float>* clonedAtoms, const float abc[3][3]) { float tmppos[3]; @@ -618,6 +689,57 @@ void TransformAtoms(std::vector<float>* clonedAtoms, const float abc[3][3]) } } +//returns false if abc is not an invertible matrix (should not happen) +bool CloneSpatialAtoms (float tmppos[3], float k, std::vector<float>* clonedAtoms) +{ //move atoms to abc coordinates, then Clone() + + if (!inv_abc_init) { + inv_abc_init=true; + //Contains code from OpenVR samples/shared/Matrices.cpp under the + //BSD 3-clause "New" or "Revised" License + //https://github.com/ValveSoftware/openvr/blob/master/LICENSE + float tmp[9]; + float determinant; + + tmp[0] = abc[1][1] * abc[2][2] - abc[1][2] * abc[2][1]; + tmp[1] = abc[0][2] * abc[2][1] - abc[0][1] * abc[2][2]; + tmp[2] = abc[0][1] * abc[1][2] - abc[0][2] * abc[1][1]; + tmp[3] = abc[1][2] * abc[2][0] - abc[1][0] * abc[2][2]; + tmp[4] = abc[0][0] * abc[2][2] - abc[0][2] * abc[2][0]; + tmp[5] = abc[0][2] * abc[1][0] - abc[0][0] * abc[1][2]; + tmp[6] = abc[1][0] * abc[2][1] - abc[1][1] * abc[2][0]; + tmp[7] = abc[0][1] * abc[2][0] - abc[0][0] * abc[2][1]; + tmp[8] = abc[0][0] * abc[1][1] - abc[0][1] * abc[1][0]; + + // check determinant if it is 0 + determinant = abc[0][0] * tmp[0] + abc[0][1] * tmp[3] + abc[0][2] * tmp[6]; + if(fabs(determinant) <= 1e-5) + { + return false; // cannot inverse, make it idenety matrix + } + + // divide by the determinant + float invDeterminant = 1.0f / determinant; + inv_abc[0][0] = invDeterminant * tmp[0]; + inv_abc[0][1] = invDeterminant * tmp[1]; + inv_abc[0][2] = invDeterminant * tmp[2]; + inv_abc[1][0] = invDeterminant * tmp[3]; + inv_abc[1][1] = invDeterminant * tmp[4]; + inv_abc[1][2] = invDeterminant * tmp[5]; + inv_abc[2][0] = invDeterminant * tmp[6]; + inv_abc[2][1] = invDeterminant * tmp[7]; + inv_abc[2][2] = invDeterminant * tmp[8]; + } + + float t[3]; + for (int s=0;s<3;s++) + t[s]=tmppos[0]*inv_abc[0][s]+tmppos[1]*inv_abc[1][s]+tmppos[2]*inv_abc[2][s]; + + Clone (t, k, clonedAtoms); + return true; +} + +//tmppos in abc coordinates void Clone (float tmppos[3], float k, std::vector<float>* clonedAtoms) { bool iaz[3]; diff --git a/NOMADVRLib/atoms.hpp b/NOMADVRLib/atoms.hpp index 7c6a7434630a4a85bd22422bcd4f0e0c9b85aaa2..ca4c71a6ef8ecceb9c77a9d35722153a6f850105 100644 --- a/NOMADVRLib/atoms.hpp +++ b/NOMADVRLib/atoms.hpp @@ -16,6 +16,8 @@ extern const char * TMPDIR; int readAtomsXYZ(const char *const file, int **numatoms, int *timesteps, float ***pos); int readAtomsCube(const char *const file, int **numatoms, int *timesteps, float ***pos); int readAtomsJson (const char *const file, int **numatoms, int *timesteps, float ***pos, float abc[3][3], std::vector<float>** clonedAtoms, const char *const token=0); +int readAtomsAnalyticsJson(const char *const f, int **numatoms, int *timesteps, float ***pos, float abc[3][3], + std::vector<float>** clonedAtoms); int readAtomsJsonURL (const char *const f, int **numatoms, int *timesteps, float ***pos, float abc[3][3], std::vector<float>** clonedAtoms, const char *const token=0); #if defined(WIN32) || defined(CAVE) int readAtomsJsonURLwget (const char *const f, int **numatoms, int *timesteps, float ***pos, float abc[3][3], std::vector<float>** clonedAtoms, const char *const token=0); @@ -28,6 +30,7 @@ const float MISSINGB=1.f; extern const char * readAtomsXYZErrors[]; extern const char * readAtomsCubeErrors[]; extern const char * readAtomsJsonErrors[]; +extern const char * readAtomsAnalyticsJsonErrors[]; float atomRadius (int i); int findAtom(const char *const s); @@ -35,6 +38,10 @@ int findAtom(const char *const s); //internal functions void discardline (FILE *F); void Clone (float tmppos[3], float k, std::vector<float>* clonedAtoms); +bool CloneSpatialAtoms (float tmppos[3], float k, std::vector<float>* clonedAtoms); void TransformAtoms(std::vector<float>* clonedAtoms, const float abc[3][3]); +extern bool inv_abc_init; +extern float inv_abc[3][3]; + #endif //__ATOMS_H diff --git a/OpenVR/TimestepData/hellovr_opengl_main.cpp b/OpenVR/TimestepData/hellovr_opengl_main.cpp index 38cba011875ceced4c37a24671e9568915429426..2061fd9bd86bbdb56b55e31bbe9ba98cd316f3d7 100644 --- a/OpenVR/TimestepData/hellovr_opengl_main.cpp +++ b/OpenVR/TimestepData/hellovr_opengl_main.cpp @@ -17,7 +17,7 @@ #include <stdio.h> #include <string> #include <cstdlib> - +#include <algorithm> #include <winsock2.h> @@ -955,7 +955,7 @@ bool CMainApplication::HandleInput() buttonPressed[1][unDevice] = true; if (firstdevice == -1) firstdevice = unDevice; - else if(seconddevice==-1) + else if(unDevice !=firstdevice && seconddevice==-1) seconddevice=unDevice; if (firstdevice==unDevice) @@ -974,7 +974,7 @@ bool CMainApplication::HandleInput() buttonPressed[0][unDevice] = true; if (firstdevice == -1) firstdevice = unDevice; - else if(seconddevice==-1) + else if(unDevice !=firstdevice && seconddevice==-1) seconddevice=unDevice; if (unDevice == firstdevice) { @@ -993,6 +993,8 @@ bool CMainApplication::HandleInput() { if (firstdevice == -1) firstdevice = unDevice; + else if (unDevice !=firstdevice && seconddevice==-1) + seconddevice=unDevice; if (unDevice == firstdevice) { Matrix4 tmp = m_mat4HMDPose; UserPosition += tmp.invert()*Vector3(0, 0, speed); @@ -1087,23 +1089,30 @@ void CMainApplication::HapticFeedback(){ //----------------------------------------------------------------------------- void CMainApplication::HapticFeedback(int device) { + if (!numAtoms) + return; if (device!=-1) { vr::VRControllerState_t cs; vr::TrackedDevicePose_t dp; m_pHMD->GetControllerStateWithPose( vr::TrackingUniverseStanding, device, &cs, &dp ); if (dp.bPoseIsValid) { + int mycurrentset; + if (fixedAtoms) + mycurrentset=0; + else + mycurrentset=currentset; vr::HmdMatrix34_t mat=dp.mDeviceToAbsoluteTracking; Vector3 controllerPos(mat.m[0][3], mat.m[1][3],mat.m[2][3]); int atomsInTimestep; - if (currentset==0) + if (mycurrentset==0) atomsInTimestep=numAtoms[0]; else - atomsInTimestep=numAtoms[currentset]-numAtoms[currentset-1]; + atomsInTimestep=numAtoms[mycurrentset]-numAtoms[mycurrentset-1]; for (int i=0;i<atomsInTimestep;i++) { - float atomr=atomRadius(atoms[currentset][i*4+3]); + float atomr=atomRadius(static_cast<int>(atoms[mycurrentset][i*4+3])); //Vector3 posatom(atoms[currentset][i*4+0], atoms[currentset][i*4+1], atoms[currentset][i*4+2]); - Vector3 posatom(atoms[currentset][i*4+0], atoms[currentset][i*4+2], atoms[currentset][i*4+1]); //y/z flipped + Vector3 posatom(atoms[mycurrentset][i*4+0], atoms[mycurrentset][i*4+2], atoms[mycurrentset][i*4+1]); //y/z flipped int p[3]; for (p[0]=0;p[0]<std::max(1,repetitions[0]);(p[0])++) for (p[1]=0;p[1]<std::max(1,repetitions[1]);(p[1])++) @@ -1123,11 +1132,11 @@ void CMainApplication::HapticFeedback(int device) } } //now cloned atoms - if (currentset==0 && clonedAtoms) { + if (mycurrentset==0 && clonedAtoms) { Vector3 up(-UserPosition.x, -UserPosition.y, UserPosition.z); for (int i=0;i<numClonedAtoms;i++) { - float atomr=atomRadius(clonedAtoms[currentset][i*4+3]); - Vector3 posatom(clonedAtoms[currentset][i*4+0], clonedAtoms[currentset][i*4+2], clonedAtoms[currentset][i*4+1]); + float atomr=atomRadius(static_cast<int>(clonedAtoms[mycurrentset][i*4+3])); + Vector3 posatom(clonedAtoms[mycurrentset][i*4+0], clonedAtoms[mycurrentset][i*4+2], clonedAtoms[mycurrentset][i*4+1]); Vector3 pos=posatom-up; pos.z=-pos.z; float l=(pos - controllerPos).length(); @@ -1601,7 +1610,7 @@ void CMainApplication::SetupIsosurfaces() //matFinal.translate(translations[p%ISOS][0]+cubetrans[0], translations[p%ISOS][1]+cubetrans[1], translations[p%ISOS][2]+cubetrans[2]); Matrix4 matcubetrans, mvs; if (voxelSize[0]!=-1) { - mvs.scale(1.0 / (double)voxelSize[0], 1.0 / (double)voxelSize[1], 1.0 / (double)voxelSize[2]); + mvs.scale(1.0f / (float)voxelSize[0], 1.0f / (float)voxelSize[1], 1.0f / (float)voxelSize[2]); matcubetrans.translate(cubetrans[0], cubetrans[1], cubetrans[2]); //angstrom //if abc, in abc coordinates /*Matrix4 abcm (abc[0][0], abc[1][0], abc[2][0], 0, @@ -2958,7 +2967,10 @@ int main(int argc, char *argv[]) MessageBoxA(0, readAtomsXYZErrors[-r-100], "XYZ file reading error", 0); else if (-300<r) MessageBoxA(0, readAtomsCubeErrors[-r-200], "Cube file reading error", 0); - else MessageBoxA(0, readAtomsJsonErrors[-r-300], "Json reading error", 0); + else if (-400<r) + MessageBoxA(0, readAtomsJsonErrors[-r-300], "Encyclopedia Json reading error", 0); + else + MessageBoxA(0, readAtomsAnalyticsJsonErrors[-r-400], "Analytics Json reading error", 0); return -100+r; }