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;
}