diff --git a/NOMADVRLib/CompileGLShader.cpp b/NOMADVRLib/CompileGLShader.cpp
index c65cfecbedc96d622caffdfa1e4153aed99225a5..66ee2533d5de11bab19697fc94cbeacd1d6b2911 100644
--- a/NOMADVRLib/CompileGLShader.cpp
+++ b/NOMADVRLib/CompileGLShader.cpp
@@ -1,3 +1,20 @@
+/*
+# Copyright 2016-2018 The NOMAD Developers Group
+ #
+ # 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 <stdio.h>
 #include "MyGL.h"
 #include "eprintf.h"
diff --git a/NOMADVRLib/CompileGLShader.h b/NOMADVRLib/CompileGLShader.h
index 654c9260dc773467f0620b6089623a68d6ac1415..4fdf64fea8d7dc00d8c46a87b9b2e386d22019a5 100644
--- a/NOMADVRLib/CompileGLShader.h
+++ b/NOMADVRLib/CompileGLShader.h
@@ -1,3 +1,20 @@
+/*
+# Copyright 2016-2018 The NOMAD Developers Group
+ #
+ # 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 "MyGL.h"
 
 #define SHADERNAME 0
diff --git a/NOMADVRLib/ConfigFile.cpp b/NOMADVRLib/ConfigFile.cpp
index 01a168e0fba05236b34e9a26bfa8981799556f59..970ed897013e504c1a162e5c5c353e7259179e7d 100644
--- a/NOMADVRLib/ConfigFile.cpp
+++ b/NOMADVRLib/ConfigFile.cpp
@@ -1,3 +1,20 @@
+/*
+# Copyright 2016-2018 The NOMAD Developers Group
+ #
+ # 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 <algorithm>
 #include <errno.h>
 #include <string.h>
@@ -46,6 +63,8 @@ int voxelSize[3];
 float unitcellcolour[4];
 float supercellcolour[4];
 
+float infolinecolour[4];
+
 int repetitions[3];
 Solid *solid;
 
@@ -65,6 +84,8 @@ float cubetrans[3];
 float animationspeed;
 float movementspeed;
 
+std::vector<information> info;
+
 const char * loadConfigFileErrors[] =
 {
 	"All Ok",//0
@@ -214,6 +235,11 @@ void initState()
 
 	animationspeed=1.0f;
 	movementspeed=1.0f;
+
+	infolinecolour[0] = 1.0f;
+	infolinecolour[1] = 1.0f;
+	infolinecolour[2] = 0.0f;
+	infolinecolour[3] = 1.0f;
 }
 
 int loadConfigFile(const char * f)
@@ -609,6 +635,10 @@ int loadConfigFile(const char * f)
 			r=fscanf (F, "%f %f %f", atomtrajectorycolour, atomtrajectorycolour+1, atomtrajectorycolour+2);
 			if (r<3)
 				eprintf ("Error reading atomtrajectorycolour value");
+		}else if (!strcmp (s, "infolinecolour")) {
+			r=fscanf (F, "%f %f %f", infolinecolour, infolinecolour+1, infolinecolour+2);
+			if (r<3)
+				eprintf ("Error reading atomtrajectorycolour value");
 		} else if (!strcmp (s, "animationspeed")) {
 			r=fscanf (F, "%f", &animationspeed);
 			if (r<1)
@@ -617,6 +647,21 @@ int loadConfigFile(const char * f)
 			r=fscanf (F, "%f", &movementspeed);
 			if (r<1)
 				eprintf ("Error reading movementspeed");
+#ifdef WIN32
+		} else if (!strcmp (s, "info")) {
+			information i;
+			r=fscanf (F, "%f %f %f %f %d", i.pos, i.pos+1, i.pos+2, &(i.size), &(i.atom));
+			if (r<5)
+				eprintf ("Error reading info");
+			r=readString(F, s);
+			if (r!=0)
+				eprintf ("Error reading info");
+			char file[256];
+			sprintf (file, "%s%s", PATH, s);
+			i.filename=strdup(file);
+			//i.tex=LoadPNG(i.filename); //opengl not initialized yet
+			info.push_back(i);
+#endif
 		} else if (!strcmp (s, "\x0d")) { //discard windows newline (problem in Sebastian Kokott's phone (?!)
 			continue;
 		} else {
diff --git a/NOMADVRLib/ConfigFile.h b/NOMADVRLib/ConfigFile.h
index 82662e6576ba76ee87952180cd271beeb54bedcd..186ad84e60f9514dcb0cf50610d454ec002d5aca 100644
--- a/NOMADVRLib/ConfigFile.h
+++ b/NOMADVRLib/ConfigFile.h
@@ -1,6 +1,23 @@
+/*
+# Copyright 2016-2018 The NOMAD Developers Group
+ #
+ # 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.
+*/
+
 #ifndef __CONFIGFILE_H
 #define __CONFIGFILE_H
 #include <vector>
+#include "MyGL.h"
 #include "polyhedron.h"
 
 extern const char * PATH;
@@ -40,6 +57,8 @@ extern float markerscaling;
 extern float unitcellcolour[4];
 extern float supercellcolour[4];
 
+extern float infolinecolour[4];
+
 extern int repetitions[3];
 
 extern Solid *solid;
@@ -67,4 +86,14 @@ extern const char * loadConfigFileErrors[];
 
 int loadConfigFile(const char * f);
 
+struct information {
+	float pos[3];
+	float size;
+	int atom; //-1=do not draw line
+	const char* filename;
+	GLuint tex;
+};
+
+extern std::vector<information> info;
+
 #endif //__CONFIGFILE_H
diff --git a/NOMADVRLib/Grid.cpp b/NOMADVRLib/Grid.cpp
index a73ddb0988ce7c5f60b42a83fd8bbad68a8b0a40..e9baf5b088372b591c1c9e7c399bf7360c5f6161 100644
--- a/NOMADVRLib/Grid.cpp
+++ b/NOMADVRLib/Grid.cpp
@@ -1,3 +1,20 @@
+/*
+# Copyright 2016-2018 The NOMAD Developers Group
+ #
+ # 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 "Grid.h"
 #include "atoms.hpp" //for radius
 #include <math.h>
diff --git a/NOMADVRLib/Grid.h b/NOMADVRLib/Grid.h
index 57069897d01bb3d131fb288b084364b6a49e3124..8a8fa98d3244845970fe88cc202b9791c14acb42 100644
--- a/NOMADVRLib/Grid.h
+++ b/NOMADVRLib/Grid.h
@@ -1,3 +1,20 @@
+/*
+# Copyright 2016-2018 The NOMAD Developers Group
+ #
+ # 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 <vector>
 
 class grid 
diff --git a/NOMADVRLib/IsoShaders.cpp b/NOMADVRLib/IsoShaders.cpp
index 1ccae5950fe5dca19ffbf749ead90d610e2a366e..cb9826fbf4b443221f5901f9c7e3b61ca3cf39b6 100644
--- a/NOMADVRLib/IsoShaders.cpp
+++ b/NOMADVRLib/IsoShaders.cpp
@@ -1,3 +1,19 @@
+/*
+# Copyright 2016-2018 The NOMAD Developers Group
+ #
+ # 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 "IsoShaders.h"
 
 #define GRIDSTR "1"
@@ -55,21 +71,15 @@ const char *const IsoTransparentShaders [] = {"Iso Transparent Renderer",
 	"layout(location = 0) in vec4 position;\n"
 	"layout(location = 1) in vec3 normalsIn;\n"
 	"layout(location = 2) in vec4 colorIn;\n"
-	//		"layout(location = 3) in vec2 uvIn;\n"
 	"out vec4 color;\n"
 	"out vec3 n;\n"
 	"out highp vec4 pos;\n"
-	//		"out vec2 uv;\n"
 	"void main()\n"
 	"{\n"
 	"	color = vec4(colorIn.rgba);\n"
 	"   n=normalize(normalsIn);\n"
-	//		"   uv=uvIn;\n"
-//	"int i=gl_InstanceID / " GRIDSTR ";\n"
-//	"int j=gl_InstanceID % " GRIDSTR ";\n"
-	"	pos = matrix * (position /*+ vec4 (float(i)*0.15*101.0, 0, float(j)*0.15*101.0, 0)*/);\n"
+	"	pos = matrix * position;\n"
 	"   gl_Position = pos;\n"
-	//"	gl_Position = matrix * position;\n"
 	"}\n",
 
 		// Fragment Shader
@@ -86,16 +96,13 @@ const char *const IsoTransparentShaders [] = {"Iso Transparent Renderer",
 	"void main()\n"
 	"{\n"
 	"highp vec4 mytex=texture(diffuse, vec2(pos.x/pos.w*0.5+0.5, pos.y/pos.w*0.5+0.5));\n"
-	//http://www.gamedev.net/topic/556521-glsl-manual-shadow-map-biasscale/
-	//"vec2 d=vec2(dFdx(pos.z), dFdy(pos.z));\n"
-	//"highp float m=sqrt(d.x*d.x + d.y*d.y);\n"
-	"if ((pos.z/pos.w+1.0)/2.0 <= mytex.r+0.0001 ) discard;\n"
+
+	"if ((pos.z/pos.w+1.0)/2.0 <= mytex.r+0.00001 ) discard;\n"
 
 	"lowp vec3 nn=normalize(n);"
 	"lowp float a=max(0.0, dot(nn, vec3(0,sqrt(2.0)/2.0,sqrt(2.0)/2.0)));\n"
 	"lowp float b=max(0.0, dot(nn, vec3(0,0,1)));\n"
 	"highp vec4 res=color;\n"
-	//"outputColor = vec4(pos.x/pos.w*0.5+0.5, pos.y/pos.w*0.5+0.5, 0,1);\n"
 	"	outputColor = vec4 ((res.rgb) * (0.2 + 0.2*a + 0.3*b), color.a);\n" 
 
 	"}\n",
diff --git a/NOMADVRLib/IsoShaders.h b/NOMADVRLib/IsoShaders.h
index 7757ef6ead085b4fc22c46b62a727440ba3c36eb..972769bd62015403ce5396e507473d1032331097 100644
--- a/NOMADVRLib/IsoShaders.h
+++ b/NOMADVRLib/IsoShaders.h
@@ -1,3 +1,20 @@
+/*
+# Copyright 2016-2018 The NOMAD Developers Group
+ #
+ # 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.
+*/
+
+
 extern const char * const IsoShaders[];
 extern const char *const IsoTransparentShaders [];
 extern const char *const IsoBlendShaders [];
diff --git a/NOMADVRLib/IsosurfacesGL.cpp b/NOMADVRLib/IsosurfacesGL.cpp
index 16997994eee2700bc8a41c84676825622813edcb..2239aa6a3390ce912f4c625902037395aefe5b28 100644
--- a/NOMADVRLib/IsosurfacesGL.cpp
+++ b/NOMADVRLib/IsosurfacesGL.cpp
@@ -1,4 +1,22 @@
-//#if 0
+/*Uses code from rply which uses the MIT license*/
+/*http://w3.impa.br/~diego/software/rply/*/
+/*This license is compatible with Apache 2.0*/
+
+/*
+# Copyright 2016-2018 The NOMAD Developers Group
+ #
+ # 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 <vector>
 #include <math.h>
@@ -153,11 +171,7 @@ int vertex_cb(p_ply_argument argument) {
 
 int face_cb(p_ply_argument argument) {
     long length, value_index;
-//	int v;
     ply_get_argument_property(argument, nullptr, &length, &value_index);
-    //discard the first call with a 3
-	//if (value_index == 0 && 3 != (v = (int)ply_get_argument_value(argument)))
-	//	dprintf("Non-triangular face: %d vertices\n", v);
     if (value_index>=0 && value_index<=2)
         CubeIndices[CurrentIndex++]=(int)(ply_get_argument_value(argument));
 
@@ -350,13 +364,11 @@ if ((e = glGetError()) != GL_NO_ERROR)
 #else
 void CleanDepthTexture (GLuint t, int width, int height)
 {
-//eprintf ("CleanDepthTexture, t %d, w %d, h %d\n", t, width, height);
 GLenum e;
 const std::vector<float> z(width * height * 4, 0.0f);
 glBindTexture(GL_TEXTURE_2D, t);
 if ((e = glGetError()) != GL_NO_ERROR)
 	eprintf("CleanDepthTexture: Gl error after glBindTexture: %d\n", e);
-//rgh FIXME: invalid operation here:
 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_DEPTH_COMPONENT, GL_FLOAT, z.data());
 if ((e = glGetError()) != GL_NO_ERROR)
 	eprintf("CleanDepthTexture: Gl error after glTexSubImage2D: %d\n", e);
@@ -416,7 +428,7 @@ return glGetError();
 GLenum SetupBlending (GLuint *vao, GLuint *vertex, GLuint *indices)
 {
 	GLenum e;
-	float z = 0.0f; //(m_fNearClip + m_fFarClip) / 2.0f;
+	float z = 0.0f; 
 	const float points[] = {
 		-1, -1, z, 0, 0,
 		-1, 1, z, 0, 1,
@@ -482,4 +494,4 @@ if ((e = glGetError()) != GL_NO_ERROR)
 	eprintf("Gl error BlendTextures glDrawElements: %d\n", e);
 	}
 }
-//#endif
+
diff --git a/NOMADVRLib/IsosurfacesGL.h b/NOMADVRLib/IsosurfacesGL.h
index 317c377989298cb42f7c76d9a634be626030410f..add94fb32d4a2d74c70b0e286e4b6ddaa4f5d01f 100644
--- a/NOMADVRLib/IsosurfacesGL.h
+++ b/NOMADVRLib/IsosurfacesGL.h
@@ -1,3 +1,20 @@
+/*
+# Copyright 2016-2018 The NOMAD Developers Group
+ #
+ # 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.
+*/
+
+
 #ifndef __ISOSURFACESGL_H
 #define __ISOSURFACESGL_H
 
diff --git a/NOMADVRLib/MyGL.h b/NOMADVRLib/MyGL.h
index 5811a1818ad8d31754ff190f929d79f66e47af15..23961c9b84e883618078587369b1769863c4f1d1 100644
--- a/NOMADVRLib/MyGL.h
+++ b/NOMADVRLib/MyGL.h
@@ -1,3 +1,19 @@
+/*
+# Copyright 2016-2018 The NOMAD Developers Group
+ #
+ # 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.
+*/
+
 #ifndef __MYGL_H
 #define __MYGL_H
 
diff --git a/NOMADVRLib/TessShaders.cpp b/NOMADVRLib/TessShaders.cpp
index 0e3f46ce47aab4d2e5897699b03fe4594d650441..a34e2ebb6412ef8908297464774a68610e7e7f9e 100644
--- a/NOMADVRLib/TessShaders.cpp
+++ b/NOMADVRLib/TessShaders.cpp
@@ -1,3 +1,19 @@
+/*
+# Copyright 2016-2018 The NOMAD Developers Group
+ #
+ # 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 "TessShaders.h"
 
 /*rgh: for now default tesselation control, using 
@@ -16,18 +32,16 @@ const char * const AtomShaders [] = {
 "#version 300 es\n"
 #endif
 	"uniform sampler2D atomData;\n"
-	"uniform float totalatoms;\n" //(float)atomsInPeriodicTable
+    "uniform float totalatoms;\n" //(float)atomsInPeriodicTable
 	"layout(location = 0) in vec3 center;\n"
 	"layout(location = 1) in float atomIn;\n"
 	"out vec4 vcolor;\n" //color , radius
 	"out vec3 vcen;"
 	"void main()\n"
 	"{\n"
-	//"gl_Position = matrix * vec4(position+center, 1);\n"
 	"float coord=atomIn/totalatoms+0.5/totalatoms;\n"
 	"vcolor=vec4(texture(atomData, vec2(coord, 0)));\n"
 	"vcen=center;\n"
-	//"color.a=1;\n"
 	"}\n",
 
 	//fragment shader
@@ -37,20 +51,14 @@ const char * const AtomShaders [] = {
 "#version 300 es\n"
 #endif
 	"in lowp vec4 color;\n"
-//	"in highp vec3 vertex;"
 	"in highp vec3 normal;"
 	"out lowp vec4 outputColor;\n"
 	"void main()\n"
 	"{\n"
-	//"vec3 U = dFdx(vertex);                 "
-	//"vec3 V = dFdy(vertex);                 "
 	"highp vec3 nn = normalize(normal);"
-	//"vec3 nn = normalize(cross(U,V));"
 	"lowp float a=abs(dot(nn, vec3(0,sqrt(2.0)/2.0,sqrt(2.0)/2.0)));\n"
 	"lowp float b=max(0.0, dot(nn, vec3(0,0,1)));\n"
 	"highp vec4 res=color;\n"
-//rgh FIXME: make this depend on the background colour. Otherwise looks almost black with white background
-//version for white background:
 	"	outputColor = vec4 ((res.rgb) * (0.4 + 0.3*a + 0.3*b), color.a);\n"
 	"}\n",
 
@@ -60,18 +68,13 @@ const char * const AtomShaders [] = {
 #else
 "#version 320 es\n"
 #endif
-	//"layout(triangles, equal_spacing, cw) in;\n"
 	"layout(quads, equal_spacing, cw) in;\n"
 	"#define pi 3.1415926535897932384626433832795\n"
 	"uniform mat4 matrix;\n"
-	//"uniform mat4 mv;\n"
 	"in vec4 vcolor[];\n" //color , radius
 	"in vec3 vcen[];"
 	"out vec4 color;\n" //color 
 	"out vec3 normal;\n"
-//	"out vec3 vertex;"
-//	"uniform mat4 Projection;\n"
-//	"uniform mat4 Modelview;\n"
 
 	"void main()\n"
 	"{\n"
@@ -87,8 +90,6 @@ const char * const AtomShaders [] = {
 
 const char * const AtomShadersNoTess [] = {
 	"Atom Renderer No Tess",
-	//No Tess means smooth shading looks very strange. Better use per-face lighting
-		// vertex shader
 //Android 21 gives error: only supports up to '310 es'
 #if defined(WIN32) || defined(CAVE)
 	"#version 410\n"
@@ -97,7 +98,7 @@ const char * const AtomShadersNoTess [] = {
 #endif
 	"uniform sampler2D atomData;\n"
 	"uniform mat4 matrix;\n"
-	"uniform float totalatoms;\n" //(float)atomsInPeriodicTable
+    "uniform float totalatoms;\n" //(float)atomsInPeriodicTable
 	"layout(location = 0) in vec3 pos;\n"
 	"layout(location = 1) in vec3 normalIn;\n"
 	"layout(location = 2) in float atomIn;\n"
@@ -128,7 +129,6 @@ const char * const AtomShadersNoTess [] = {
 	"{\n"
 	"highp vec3 U = dFdx(vertex);                 "
 	"highp vec3 V = dFdy(vertex);                 "
-	//"highp vec3 nn = normalize(normal);\n"
 	"highp vec3 nn = normalize(cross(U,V));"
 	"lowp float a=abs(dot(nn, vec3(0,sqrt(2.0)/2.0,sqrt(2.0)/2.0)));\n"
 	"lowp float b=max(0.0, dot(nn, vec3(0,0,1)));\n"
diff --git a/NOMADVRLib/TessShaders.h b/NOMADVRLib/TessShaders.h
index 6c584ec7e007e1f349663a99da401ac3b56234e4..c4b9f214b76b5dc1b4bd9501949d848e13d3c7de 100644
--- a/NOMADVRLib/TessShaders.h
+++ b/NOMADVRLib/TessShaders.h
@@ -1,2 +1,18 @@
+/*
+# Copyright 2016-2018 The NOMAD Developers Group
+ #
+ # 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.
+*/
+
 extern const char * const AtomShaders[];
 extern const char * const AtomShadersNoTess [];
diff --git a/NOMADVRLib/UnitCellShaders.cpp b/NOMADVRLib/UnitCellShaders.cpp
index b60f4cfad271924922499acd814547210735583e..ee27e6ff2066b413efbc8bd293ab28d0332c138b 100644
--- a/NOMADVRLib/UnitCellShaders.cpp
+++ b/NOMADVRLib/UnitCellShaders.cpp
@@ -1,3 +1,19 @@
+/*
+# Copyright 2016-2018 The NOMAD Developers Group
+ #
+ # 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 "UnitCellShaders.h"
 
 const char * const UnitCellShaders [] = {"Unit Cell Renderer",
diff --git a/NOMADVRLib/UnitCellShaders.h b/NOMADVRLib/UnitCellShaders.h
index c538960440c78a5c8c9c6f967b853eeaf9dfecf1..9c648d976543f2e1acbc874f46bcfc0ffbff1076 100644
--- a/NOMADVRLib/UnitCellShaders.h
+++ b/NOMADVRLib/UnitCellShaders.h
@@ -1 +1,17 @@
+/*
+# Copyright 2016-2018 The NOMAD Developers Group
+ #
+ # 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.
+*/
+
 extern const char * const UnitCellShaders[];
\ No newline at end of file
diff --git a/NOMADVRLib/atoms.cpp b/NOMADVRLib/atoms.cpp
index 48ff1138ad0080bfd021f8e1bb03fb450963e6c0..3cd42ad28779acb78ff6711502404119531734f3 100644
--- a/NOMADVRLib/atoms.cpp
+++ b/NOMADVRLib/atoms.cpp
@@ -1,3 +1,20 @@
+/*
+# Copyright 2016-2018 The NOMAD Developers Group
+ #
+ # 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.
+*/
+
+
 #define NOMINMAX
 
 #include <stdio.h>
diff --git a/NOMADVRLib/atoms.hpp b/NOMADVRLib/atoms.hpp
index 5f04bb498c64a94348243227bf86c1cc9b6094b0..347ef277d158b063fbfbcea00ed7ce83cdfb81ee 100644
--- a/NOMADVRLib/atoms.hpp
+++ b/NOMADVRLib/atoms.hpp
@@ -1,3 +1,19 @@
+/*
+# Copyright 2016-2018 The NOMAD Developers Group
+ #
+ # 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.
+*/
+
 //Data from https://gitlab.rzg.mpg.de/nomad-lab/encyclopedia-gui/blob/lauri_viz/viztools/structure/build/js/structureviewer.js
 //rgb radius for easy transference to a texture
 //jmol colours from https://gitlab.com/ase/ase/blob/master/ase/data/colors.py
diff --git a/NOMADVRLib/atomsGL.cpp b/NOMADVRLib/atomsGL.cpp
index fd32c83afaaae95db972c7b40c6eb2f91568e199..e495b4725a541fb5cd89008748b7b61cb238a4e7 100644
--- a/NOMADVRLib/atomsGL.cpp
+++ b/NOMADVRLib/atomsGL.cpp
@@ -1,3 +1,20 @@
+/*
+# Copyright 2016-2018 The NOMAD Developers Group
+ #
+ # 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 <math.h>
 
 #include "eprintf.h"
@@ -423,6 +440,79 @@ GLenum SetupAtoms(GLuint **AtomVAO /*[4]*/, GLuint **AtomVertBuffer /*[3]*/, GLu
 	return e;
 }
 
+GLenum SetupInfoCube (GLuint *VAO, GLuint *VertBuffer, GLuint *IndexBuffer)
+{
+	glGenVertexArrays(1, VAO);
+	glGenBuffers(1, VertBuffer);
+	glGenBuffers(1, IndexBuffer);
+
+	glBindVertexArray(*VAO);
+	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *IndexBuffer);
+	glBindBuffer(GL_ARRAY_BUFFER, *VertBuffer);
+
+	glEnableVertexAttribArray(0);
+	glEnableVertexAttribArray(1);
+	glEnableVertexAttribArray(2);
+	glDisableVertexAttribArray(3);
+	//vec4 pos, vec3 normal, vec2 uv
+	const int Nvert=9*26;
+	const GLfloat vert[]={
+		-1, +1, -1, 0,		0, 0, -1,	0, 1, //-z
+		-1, -1, -1,	0,		0, 0, -1,	0, 0,
+		+1, +1, -1,	0,		0, 0, -1,	1, 1,
+		+1, -1, -1,	0,		0, 0, -1,	1, 0,
+		-1, +1, +1, 0,		0, 0, 1,	0, 0,//+z
+		-1, -1, +1,	0,		0, 0, 1,	0, 1,
+		+1, +1, +1,	0,		0, 0, 1,	1, 0,
+		+1, -1, +1,	0,		0, 0, 1,	1, 1,
+
+		+1, -1, -1, 0,		+1, 0, 0,	0, 1,//+x
+		+1, -1, +1, 0,		+1, 0, 0,	0, 0,//+x
+		+1, +1, -1, 0,		+1, 0, 0,	1, 1,//+x
+		+1, +1, +1, 0,		+1, 0, 0,	1, 0,//+x
+		-1, -1, -1, 0,		-1, 0, 0,	0, 0,//-x
+		-1, -1, +1, 0,		-1, 0, 0,	0, 1,//-x
+		-1, +1, -1, 0,		-1, 0, 0,	1, 0,//-x
+		-1, +1, +1, 0,		-1, 0, 0,	1, 1,//-x
+
+		-1, 1, +1, 0,		0, -1, 0,	0, 1, //+y
+		-1, 1, -1, 0,		0, -1, 0,	0, 0,
+		+1, 1, +1, 0,		0, -1, 0,	1, 1,
+		+1, 1, -1, 0,		0, -1, 0,	1, 0,
+		-1, -1, +1, 0,		0, +1, 0,	0, 0,//-y
+		-1, -1, -1, 0,		0, +1, 0,	0, 1,
+		+1, -1, +1, 0,		0, +1, 0,	1, 0,
+		+1, -1, -1, 0,		0, +1, 0,	1, 1,
+		0, 0, 0, 1,			0,0,0,		0,0, //for the line between the cube and the atom
+		0, 0, 1, 1,			0, 0, 0,	0, 0, //for the line between the cube and the atom
+
+	};
+	const short int ind[]={
+		0, 1, 2, //z
+		1, 3, 2,
+		4, 5, 6,
+		5, 7, 6,
+		8, 9, 10,//x
+		9, 11, 10,
+		12, 13, 14,
+		13, 15, 14,
+		16, 17, 18,//y
+		17, 19, 18,
+		20, 21, 22,
+		21, 23, 22,
+	};
+
+	glBufferData(GL_ARRAY_BUFFER, sizeof(float) * Nvert , vert,
+			GL_STATIC_DRAW);
+	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(ind), ind, GL_STATIC_DRAW);
+	glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (const void *)(0));
+	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (const void *)(4*sizeof(float)));
+	glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (const void *)(7*sizeof(float)));
+	glBindVertexArray(0);
+
+	return glGetError();
+}
+
 GLenum SetupMarker(GLuint *MarkerVAO, GLuint *MarkerVertBuffer)
 {
 	if (!markers)
diff --git a/NOMADVRLib/atomsGL.h b/NOMADVRLib/atomsGL.h
index 1014028c0142ed314dca819bcb39fd7807aeaf75..09cab91bd07451f1610c1f1d713a4a41579387bf 100644
--- a/NOMADVRLib/atomsGL.h
+++ b/NOMADVRLib/atomsGL.h
@@ -1,3 +1,25 @@
+/*This code is based on openvr, which uses the 3-clause BSD license*/
+/*https://github.com/ValveSoftware/openvr/blob/master/LICENSE*/
+//========= Copyright Valve Corporaion ============//
+/*This license is compatible with Apache 2.0*/
+
+/*This code is therefore licensed under Apache 2.0*/
+/*
+# Copyright 2016-2018 The NOMAD Developers Group
+ #
+ # 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.
+*/
+
 #ifndef __ATOMSGL_H
 #define __ATOMSGL_H
 
@@ -9,6 +31,7 @@ GLenum SetupAtoms(GLuint **AtomVAO, GLuint **AtomVertBuffer, GLuint *BondIndices
 GLenum SetupAtomsNoTess (GLuint **AtomVAO, GLuint **AtomVertBuffer, GLuint **AtomIndexBuffer);
 GLenum SetupUnitCell(GLuint *UnitCellVAO, GLuint *UnitCellVertBuffer, GLuint *UnitCellIndexBuffer);
 GLenum SetupMarker(GLuint *MarkerVAO, GLuint *MarkerVertBuffer);
+GLenum SetupInfoCube (GLuint *VAO, GLuint *VertBuffer, GLuint *IndexBuffer);
 
 bool PrepareUnitCellAtomShader (GLuint *AtomP, GLuint *cellP, GLuint *MarkerP, 
 								GLint *AtomMatrixLocation, GLint *UnitCellMatrixLocation,  GLint *UnitCellColourLocation,
diff --git a/NOMADVRLib/eprintf.h b/NOMADVRLib/eprintf.h
index 6d2b302c7bcec586b8eb668dcab0af1db141f4af..796956bc14bef64819c8dd7c16eb321187661a3a 100644
--- a/NOMADVRLib/eprintf.h
+++ b/NOMADVRLib/eprintf.h
@@ -1,2 +1,19 @@
+/*
+# Copyright 2016-2018 The NOMAD Developers Group
+ #
+ # 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.
+*/
+
+
 //This function needs to be defined globally once (normally in main) and is used for error reporting
 extern void eprintf( const char *fmt, ... );
\ No newline at end of file
diff --git a/NOMADVRLib/markerShaders.cpp b/NOMADVRLib/markerShaders.cpp
index c3fffd87617246008113c23ae284093663d5dff4..2820bb00c0e5c303307cba35b49173fd411e9e38 100644
--- a/NOMADVRLib/markerShaders.cpp
+++ b/NOMADVRLib/markerShaders.cpp
@@ -1,3 +1,19 @@
+/*
+# Copyright 2016-2018 The NOMAD Developers Group
+ #
+ # 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 "markerShaders.h"
 
 const char * const MarkerShaders [] = {
@@ -17,7 +33,6 @@ const char * const MarkerShaders [] = {
 	"out vec3 vrad;" // ellipsoid
 	"void main()\n"
 	"{\n"
-	//"gl_Position = matrix * vec4(position+center, 1);\n"
 	"vcolor=colour;\n"
 	"vcen=centersize.xyz;\n"
 	"vec3 sc=vec3(0.5, 0.5, 0.5);\n"
@@ -55,14 +70,12 @@ const char * const MarkerShaders [] = {
 #else
 "#version 320 es\n"
 #endif
-	//"layout(triangles, equal_spacing, cw) in;\n"
 	"layout(quads, equal_spacing, cw) in;\n"
 	"#define pi 3.1415926535897932384626433832795\n"
 	"uniform mat4 matrix;\n"
-	//"uniform mat4 mv;\n"
 	"in vec4 vcolor[];\n" //color
 	"in vec3 vcen[];"
-	"in vec3 vrad[];" // ellipsoid
+	"in vec3 vrad[];" 
 	"out vec4 color;\n" //color 
 	"out vec3 normal;\n"
 	"void main()\n"
diff --git a/NOMADVRLib/markerShaders.h b/NOMADVRLib/markerShaders.h
index 32099065bf0e886578a42c45ebf5a92c44434a19..b180ee01d7aaaa69e315e9e515c6068431e2e6a8 100644
--- a/NOMADVRLib/markerShaders.h
+++ b/NOMADVRLib/markerShaders.h
@@ -1 +1,18 @@
+/*
+# Copyright 2016-2018 The NOMAD Developers Group
+ #
+ # 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.
+*/
+
+
 extern const char * const MarkerShaders [];
\ No newline at end of file
diff --git a/NOMADVRLib/polyhedron.cpp b/NOMADVRLib/polyhedron.cpp
index ec86a7ba828fcb74feb257e760fc8e627cba70cf..09af6e91b712057d69a5de392ab586cef330651c 100644
--- a/NOMADVRLib/polyhedron.cpp
+++ b/NOMADVRLib/polyhedron.cpp
@@ -1,7 +1,26 @@
+/*Uses code from Philip Rideout which uses the public domain license*/
+//http://prideout.net/blog/?p=48
+/*This license is compatible with Apache 2.0*/
+
+/*
+# Copyright 2016-2018 The NOMAD Developers Group
+ #
+ # 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 <math.h>
 #include "polyhedron.h"
 
-//http://prideout.net/blog/?p=48 //public domain code
 const int Icosahedron::nFaces=20;
 const int Icosahedron::Faces[] = { //20 faces, 60 ints
 	2, 1, 0,
diff --git a/NOMADVRLib/polyhedron.h b/NOMADVRLib/polyhedron.h
index 73da8189020a0d05e07a236b40073240f2ad2644..75e717a63879a7be4e9bf3b91ea0aa9e6c82a144 100644
--- a/NOMADVRLib/polyhedron.h
+++ b/NOMADVRLib/polyhedron.h
@@ -1,3 +1,22 @@
+/*Uses code from Stackoverflow which uses the MIT license and the CC BY-SA 3.0*/
+/*These licenses are compatible with Apache 2.0*/
+
+/*
+# Copyright 2016-2018 The NOMAD Developers Group
+ #
+ # 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.
+*/
+
 #ifndef __POLYHEDRON_H
 #define __POLYHEDRON_H
 
@@ -56,7 +75,6 @@ public:
 			break;
 		case Sphere:
 //https://stackoverflow.com/questions/23143921/python-program-to-create-sphere-coordinates-not-working
-//http://blog.andreaskahler.com/2009/06/creating-icosphere-mesh-in-code.html For the future
 			nVerts=SphereFacets*SphereFacets;
 			
 			float *tVerts=new float[nVerts*3];
diff --git a/OpenVR/TimestepData/LoadPNG.cpp b/OpenVR/TimestepData/LoadPNG.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a34ce3f3988937fe3de99681b62acf846c580c97
--- /dev/null
+++ b/OpenVR/TimestepData/LoadPNG.cpp
@@ -0,0 +1,50 @@
+/*
+# Copyright 2016-2018 The NOMAD Developers Group
+ #
+ # 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 <vector>
+#include "LoadPNG.h"
+#include "shared/lodepng.h"
+
+GLuint LoadPNG (const char *image)
+{
+	GLuint m_iTexture;
+	glGenTextures(1, &m_iTexture);
+	glBindTexture(GL_TEXTURE_2D, m_iTexture);
+
+	std::vector<unsigned char> imageRGBA;
+	unsigned nImageWidth, nImageHeight;
+	unsigned nError = lodepng::decode(imageRGBA, nImageWidth, nImageHeight,
+			image);
+	
+	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, nImageWidth, nImageHeight,
+			0, GL_RGBA, GL_UNSIGNED_BYTE, &imageRGBA[0]);
+
+	glGenerateMipmap(GL_TEXTURE_2D);
+
+	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_MAG_FILTER, GL_LINEAR);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+
+	//rgh fixme: revise this if texture sampling is too slow
+	GLfloat fLargest;
+	glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &fLargest);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, fLargest);
+	
+	glBindTexture( GL_TEXTURE_2D, 0 );
+
+	return m_iTexture;
+}
\ No newline at end of file
diff --git a/OpenVR/TimestepData/LoadPNG.h b/OpenVR/TimestepData/LoadPNG.h
new file mode 100644
index 0000000000000000000000000000000000000000..d25f20b69058d156fad9dabef6baf00cf4b1f4cf
--- /dev/null
+++ b/OpenVR/TimestepData/LoadPNG.h
@@ -0,0 +1,7 @@
+#ifndef LOADPNG_H
+#define LOADPNG_H
+#include "NOMADVRLib/MyGL.h"
+
+GLuint LoadPNG (const char *image);
+
+#endif
\ No newline at end of file
diff --git a/OpenVR/TimestepData/hellovr_opengl_main.cpp b/OpenVR/TimestepData/hellovr_opengl_main.cpp
index 25fa8db2d59af9a756c771481cfe85d838814a1a..495c72fddad50f37e85ae3dbd04877be92576135 100644
--- a/OpenVR/TimestepData/hellovr_opengl_main.cpp
+++ b/OpenVR/TimestepData/hellovr_opengl_main.cpp
@@ -1,6 +1,30 @@
-//========= Copyright Valve Corporaion ============//
+/*This code is based on openvr, which uses the 3-clause BSD license*/
+/*https://github.com/ValveSoftware/openvr/blob/master/LICENSE*/
+//========= Copyright Valve Corporaion ============//
+/*This license is compatible with Apache 2.0*/
+
+/*This code is therefore licensed under Apache 2.0*/
+/*
+ # Copyright 2016-2018 The NOMAD Developers Group
+ #
+ # 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.
+*/
+
 #define NOMINMAX
 
+//#define NOSAVINGSCREENSHOTS
+
+
 #define _CRTDBG_MAP_ALLOC
 #include <stdlib.h>
 #include <crtdbg.h>
@@ -28,6 +52,7 @@
 #include "shared/pathtools.h"
 
 #include "rply/rply.h"
+#include "LoadPNG.h"
 
 #include "NOMADVRLib/ConfigFile.h"
 #include "NOMADVRLib/atoms.hpp"
@@ -125,7 +150,7 @@ public:
 	void SetupAtoms();
 	void SetupUnitCell();
 	void SetupMarker();
-
+	void SetupInfoCube();
 
 	void DrawControllers();
 
@@ -138,6 +163,7 @@ public:
 	void RenderScene(vr::Hmd_Eye nEye);
 	void RenderAtoms(const vr::Hmd_Eye &nEye);
 	void RenderAtomsUnitCell(const vr::Hmd_Eye &nEye, int p[3]);
+	void RenderInfo(const vr::Hmd_Eye &nEye);
 
 	void RenderUnitCell(const vr::Hmd_Eye &nEye);
 	//Vector3 GetDisplacement(int p[3]);
@@ -231,6 +257,11 @@ private: // OpenGL bookkeeping
 	//for markers
 	GLuint m_glMarkerVertBuffer;
 	GLuint m_unMarkerVAO;
+	//for infocube
+	GLuint m_unInfoVertBuffer;
+	GLuint m_unInfoVAO;
+	GLuint m_unInfoIndexBuffer;
+
 
 	int currentset;
 	float elapsedtime;
@@ -946,7 +977,10 @@ bool CMainApplication::HandleInput()
 			//rgh: the name of the variable seems to make it so :o) Possibly so that a different model can be used with the correct deformation
 			//m_rbShowTrackedDevice[unDevice] = state.ulButtonPressed == 0;
 
-			if (!buttonPressed[1][unDevice] && state.ulButtonTouched&vr::ButtonMaskFromId(vr::k_EButton_ApplicationMenu)) {
+			if (!buttonPressed[1][unDevice] && 
+				(state.ulButtonTouched&vr::ButtonMaskFromId(vr::k_EButton_ApplicationMenu) ||
+				state.ulButtonPressed&vr::ButtonMaskFromId(vr::k_EButton_ApplicationMenu))
+				) {
 				buttonPressed[1][unDevice] = true;
 				if (firstdevice == -1)
 					firstdevice = unDevice;
@@ -958,13 +992,20 @@ bool CMainApplication::HandleInput()
 				else
 					showAtoms= !showAtoms;
 			}
-			else if (buttonPressed[1][unDevice] && 0 == (state.ulButtonTouched&vr::ButtonMaskFromId(vr::k_EButton_ApplicationMenu)))
+			else if (buttonPressed[1][unDevice] && 
+				0 == (state.ulButtonTouched&vr::ButtonMaskFromId(vr::k_EButton_ApplicationMenu)) &&
+				0 == (state.ulButtonPressed&vr::ButtonMaskFromId(vr::k_EButton_ApplicationMenu))
+				)
 			{
 				buttonPressed[1][unDevice] = false;
 			}
 
 			
-			if (!buttonPressed[0][unDevice] && state.ulButtonTouched&vr::ButtonMaskFromId(vr::k_EButton_Grip))
+			if (!buttonPressed[0][unDevice] && 
+					(state.ulButtonTouched&vr::ButtonMaskFromId(vr::k_EButton_Grip) || 
+					 state.ulButtonPressed&vr::ButtonMaskFromId(vr::k_EButton_Grip) 
+					)
+				)
 			{
 				buttonPressed[0][unDevice] = true;
 				if (firstdevice == -1)
@@ -981,7 +1022,10 @@ bool CMainApplication::HandleInput()
 					if (currentiso > ISOS)
 						currentiso = 0;
 				}
-			} else if (buttonPressed[0][unDevice] && (state.ulButtonTouched&vr::ButtonMaskFromId(vr::k_EButton_Grip)) == 0)
+			} else if (buttonPressed[0][unDevice] && (
+				(state.ulButtonTouched&vr::ButtonMaskFromId(vr::k_EButton_Grip)) == 0 &&
+				(state.ulButtonPressed&vr::ButtonMaskFromId(vr::k_EButton_Grip)) == 0
+				))
 				buttonPressed[0][unDevice] = false;
 
 			if (state.rAxis[1].x >0.1)
@@ -1161,6 +1205,7 @@ void CMainApplication::HapticFeedback(int device)
 //-----------------------------------------------------------------------------
 void CMainApplication::RenderFrame()
 {
+	int e;
 	// for now as fast as possible
 	if ( m_pHMD )
 	{
@@ -1170,8 +1215,22 @@ void CMainApplication::RenderFrame()
 
 		vr::Texture_t leftEyeTexture = {(void*)leftEyeDesc.m_nResolveTextureId, vr::API_OpenGL, vr::ColorSpace_Gamma };
 		vr::VRCompositor()->Submit(vr::Eye_Left, &leftEyeTexture );
+		if ((e = glGetError()) != GL_NO_ERROR) {//error messages 
+			//after 19/02/2017, the SDK gives an 1282 error (possibly because this version is no longer supported
+			//One error is created for each eye, but later passes work well
+			//Discarding the error for now; an update of the code to the latest SDK should fix the issue completely.
+			//dprintf("Gl error after VRCompositor()->Submit leftEyeTexture: %d, %s\n", e, gluErrorString(e));
+		}
+
 		vr::Texture_t rightEyeTexture = {(void*)rightEyeDesc.m_nResolveTextureId, vr::API_OpenGL, vr::ColorSpace_Gamma };
 		vr::VRCompositor()->Submit(vr::Eye_Right, &rightEyeTexture );
+		if ((e = glGetError()) != GL_NO_ERROR) {//error messages 
+			//after 19/02/2017, the SDK gives an 1282 error (possibly because this version is no longer supported
+			//One error is created for each eye, but later passes work well
+			//Discarding the error for now; an update of the code to the latest SDK should fix the issue completely.
+			//dprintf("Gl error after VRCompositor()->Submit rightEyeTexture: %d, %s\n", e, gluErrorString(e));
+		}
+
 	}
 
 	if ( m_bVblank && m_bGlFinishHack )
@@ -1367,6 +1426,7 @@ bool CMainApplication::SetupTexturemaps()
 	//					[1,2] Depth texture for depth peeling ping pong (needs to be initialized after SetupStereoRenderTargets)
 	//					[3..ZLAYERS+2] Colour textures for transparency
 	//sdl_textures: 6	[0..5] a b c alpha beta gamma text for axis labels
+	//also initializes information textures
 	//std::string sExecutableDirectory = Path_StripFilename(Path_GetExecutablePath());
 	//std::string strFullPath = Path_MakeAbsolute("../cube_texture.png", sExecutableDirectory);
 
@@ -1406,6 +1466,10 @@ bool CMainApplication::SetupTexturemaps()
 	}
 	*/
 
+	for (int i=0;i<info.size();i++) {
+		info[i].tex=LoadPNG(info[i].filename);
+	}
+
 	return ( m_iTexture != 0 && e==GL_NO_ERROR);
 }
 
@@ -1430,12 +1494,23 @@ void CMainApplication::SetupScene()
 	//clonedAtoms=0;
 	SetupUnitCell();
 	SetupMarker();
+	SetupInfoCube();
+}
+
+void CMainApplication::SetupInfoCube()
+{
+GLenum e;
+e=::SetupInfoCube(&m_unInfoVAO, &m_unInfoVertBuffer, &m_unInfoIndexBuffer);
+if (e!=GL_NO_ERROR)
+	eprintf ("Error in SetupInfoCube()");
 }
 
 void CMainApplication::SetupMarker()
 {
 GLenum e;
 e=::SetupMarker(&m_unMarkerVAO, &m_glMarkerVertBuffer);
+if (e!=GL_NO_ERROR)
+	eprintf ("Error in SetupMarker()");
 }
 
 void CMainApplication::SetupUnitCell()
@@ -2053,11 +2128,12 @@ void CMainApplication::RenderStereoTargets()
 	//this will kill the performance
 	char name[100];
 
+#ifndef NOSAVINGSCREENSHOTS
 	if (savetodisk) {
 		sprintf(name, "%sL%05d.bmp", SCREENSHOT, framecounter);
 		SaveScreenshot(name);
 	}
-
+#endif
  	glBindFramebuffer( GL_FRAMEBUFFER, 0 );
 	
 	glDisable( GL_MULTISAMPLE );
@@ -2079,11 +2155,12 @@ void CMainApplication::RenderStereoTargets()
  	glViewport(0, 0, m_nRenderWidth, m_nRenderHeight );
  	RenderScene( vr::Eye_Right );
 
+#ifndef NOSAVINGSCREENSHOTS
 	if (savetodisk && saveStereo) {
 		sprintf(name, "%sR%05d.bmp", SCREENSHOT, framecounter);
 		SaveScreenshot(name);
 	}
-
+#endif
  	glBindFramebuffer( GL_FRAMEBUFFER, 0 );
  	
 	glDisable( GL_MULTISAMPLE );
@@ -2097,10 +2174,11 @@ void CMainApplication::RenderStereoTargets()
 
  	glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0 );
-
+#ifndef NOSAVINGSCREENSHOTS
 	if (savetodisk) {
 		framecounter++;
 	}
+#endif
 }
 
 void CMainApplication::PaintGrid(const vr::Hmd_Eye &nEye, int iso) {
@@ -2320,12 +2398,6 @@ void CMainApplication::RenderAtoms(const vr::Hmd_Eye &nEye)
 	if ((e = glGetError()) != GL_NO_ERROR)
 		dprintf("Gl error before RenderAtoms timestep =%d: %d, %s\n", currentset, e, gluErrorString(e));
 
-
-
-
-	
-	if ((e = glGetError()) != GL_NO_ERROR)
-		dprintf("Gl error 0 timestep =%d: %d, %s\n", currentset, e, gluErrorString(e));
 	glBindTexture(GL_TEXTURE_2D, m_iTexture[3+ZLAYERS]);
 	if ((e = glGetError()) != GL_NO_ERROR)
 		dprintf("Gl error 2 timestep =%d: %d, %s\n", currentset, e, gluErrorString(e));
@@ -2344,6 +2416,67 @@ void CMainApplication::CleanDepthTexture ()
 ::CleanDepthTexture(m_iTexture[1]);
 }
 
+void CMainApplication::RenderInfo(const vr::Hmd_Eye &nEye)
+{
+int e;
+glBindVertexArray(m_unInfoVAO);
+glActiveTexture( GL_TEXTURE0 );
+glBindBuffer(GL_ARRAY_BUFFER, m_unInfoVertBuffer);
+glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_unInfoIndexBuffer);
+glUseProgram(m_unRenderModelProgramID);
+
+for (int i=0;i<info.size(); i++) {
+	Matrix4 trans;
+
+	Vector3 iPos(info[i].pos[0], info[i].pos[1], info[i].pos[2]);
+
+	trans.translate(iPos).rotateX(-90).translate(UserPosition);
+
+	Matrix4 scal;
+	scal.scale(info[i].size);
+	Matrix4 transform = GetCurrentViewProjectionMatrix(nEye)*trans*scal;
+	glUniformMatrix4fv(m_nRenderModelMatrixLocation, 1, GL_FALSE, transform.get());
+	glBindTexture(GL_TEXTURE_2D, info[i].tex);
+	glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, 0);
+	e=glGetError();
+	if (e!=0)
+		eprintf("glerror after RenderInfo, %d, %s", e, glewGetErrorString(e));
+}
+
+//now line
+glUseProgram(m_unUnitCellProgramID);
+for (int i = 0; i < info.size(); i++) {
+	if (info[i].atom < 1)
+		continue;
+	if (info[i].atom-1 > numAtoms[currentset]) {
+		//wrong atom
+		continue;
+	}
+	Vector3 iPos(info[i].pos[0], info[i].pos[1], info[i].pos[2]);
+	Matrix4 nt=Matrix4(0, 0, 0, 0,
+		0, 0, 0, 0,
+		atoms[currentset][(info[i].atom - 1)*4+0] - iPos[0],
+		atoms[currentset][(info[i].atom - 1)*4+1] - iPos[1],
+		atoms[currentset][(info[i].atom - 1)*4+2] - iPos[2],
+		0,
+		iPos[0], iPos[1], iPos[2], 1
+		);//.transpose();
+	Matrix4 trans;
+	trans.rotateX(-90).translate(UserPosition);
+	Matrix4 transform = GetCurrentViewProjectionMatrix(nEye)*trans*nt;
+	glUniformMatrix4fv(m_nUnitCellMatrixLocation, 1, GL_FALSE, transform.get());
+	if ((e = glGetError()) != GL_NO_ERROR)
+		dprintf("Gl error after glUniform4fv 1 RenderUnitCell: %d, %s\n", e, gluErrorString(e));
+
+	glUniform4fv(m_nUnitCellColourLocation, 1, infolinecolour);
+
+	glDrawArrays(GL_LINES, 24, 2);
+}
+glBindTexture(GL_TEXTURE_2D, 0);
+glBindVertexArray(0);
+}
+
+
 //-----------------------------------------------------------------------------
 // Purpose:
 //-----------------------------------------------------------------------------
@@ -2359,6 +2492,7 @@ void CMainApplication::RenderScene(vr::Hmd_Eye nEye)
 	glEnable(GL_DEPTH_TEST);
 
 	if (ISOS==0) {
+		RenderInfo(nEye);
 		RenderAtoms(nEye);
 		RenderUnitCell(nEye);
 		if (showcontrollers)
@@ -2395,6 +2529,7 @@ void CMainApplication::RenderScene(vr::Hmd_Eye nEye)
 				if ((e = glGetError()) != GL_NO_ERROR)
 					dprintf("Gl error after paintgrid: %d, %s\n", e, gluErrorString(e));
 				if (numAtoms!=0) {
+					RenderInfo(nEye);
 					RenderAtoms(nEye);
 					RenderUnitCell(nEye);
 				}
@@ -2494,6 +2629,7 @@ void CMainApplication::RenderScene(vr::Hmd_Eye nEye)
 			glBindTexture(GL_TEXTURE_2D, 0);
 			glUseProgram(m_unSceneProgramID);
 			PaintGrid(nEye, currentiso);
+			RenderInfo(nEye);
 			if (showcontrollers)
 				RenderAllTrackedRenderModels(nEye);
 		} //else currentiso =isos
diff --git a/OpenVR/TimestepData/hsv.c b/OpenVR/TimestepData/hsv.c
deleted file mode 100644
index ae63e658cbeecc35385ae6df85cd5d620d991844..0000000000000000000000000000000000000000
--- a/OpenVR/TimestepData/hsv.c
+++ /dev/null
@@ -1,31 +0,0 @@
-#include <math.h>
-#include "hsv.h"
-//http://stackoverflow.com/questions/3018313/algorithm-to-convert-rgb-to-hsv-and-hsv-to-rgb-in-range-0-255-for-both
-void hsv2rgb(float *hsv, float *rgb) {
-	float h = hsv[0], s = hsv[1], v = hsv[2], p, q, t, f, r, g, b;
-
-	(h == 360.) ? (h = 0.) : (h /= 60.);
-	f = h - floorf(h);
-
-	p = v*(1.f - s);
-	q = v*(1.f - s*f);
-	t = v*(1.f - s*(1.f - f));
-
-	if (0. <= h && h < 1.){
-		r = v; g = t; b = p;
-	}	else if (1. <= h && h < 2.) {
-		r = q; g = v; b = p;
-	}	else if (2. <= h && h < 3.){
-		r = p; g = v; b = t;
-	}else if (3. <= h && h < 4.){
-		r = p; g = q; b = v;
-	}else if (4. <= h && h < 5.){
-		r = t; g = p; b = v;
-	}else if (5. <= h && h < 6.){
-		r = v; g = p;b = q;
-	}
-	else{
-		r = 0.; g = 0.; b = 0.;
-	}
-	rgb[0] = r; rgb[1] = g; rgb[2] = b;
-}
\ No newline at end of file
diff --git a/OpenVR/TimestepData/hsv.h b/OpenVR/TimestepData/hsv.h
deleted file mode 100644
index fa2bbdb129b87414aca20e3702ee5963b4f6ffbb..0000000000000000000000000000000000000000
--- a/OpenVR/TimestepData/hsv.h
+++ /dev/null
@@ -1 +0,0 @@
-void hsv2rgb(float *hsv, float *rgb);