diff --git a/NOMADVRLib/ConfigFile.cpp b/NOMADVRLib/ConfigFile.cpp
index 10ff95acc01515209f453b1293701e40cc9ce435..aa7d86c51e1b2d84f4534d9664f571b986d23640 100644
--- a/NOMADVRLib/ConfigFile.cpp
+++ b/NOMADVRLib/ConfigFile.cpp
@@ -46,6 +46,7 @@ Solid *solid;
 
 bool saveStereo;
 int screenshotdownscaling;
+bool hapticFeedback;
 
 //markers such as hole positions and electron positions
 float ** markers;
@@ -176,6 +177,7 @@ int loadConfigFile(const char * f)
 		voxelSize[i]=-1;
 	saveStereo=false;
 	screenshotdownscaling=1;
+	hapticFeedback=false;
 	//
 	FILE *F = fopen(f, "r");
 	if (F == 0)
@@ -472,6 +474,8 @@ int loadConfigFile(const char * f)
 			r= fscanf(F, "%d", &screenshotdownscaling);
 			if (r<1)
 				eprintf ("Error reading screenshotdownscaling value");
+		} else if (!strcmp (s, "hapticfeedback")) {
+			hapticFeedback=true;
 		} else if (!strcmp (s, "supercell")) {
 			r=fscanf (F, "%f %f %f", supercell, supercell+1, supercell+2);
 		} else if (!strcmp (s, "\x0d")) { //discard windows newline (problem in Sebastian Kokott's phone (?!)
diff --git a/NOMADVRLib/ConfigFile.h b/NOMADVRLib/ConfigFile.h
index 690d90a9d1a6da4d12c429e6e6779e885f50e252..cf3dae009b26e17d0cca70c7ee1b33cd78995a03 100644
--- a/NOMADVRLib/ConfigFile.h
+++ b/NOMADVRLib/ConfigFile.h
@@ -42,6 +42,8 @@ extern Solid *solid;
 extern bool saveStereo;
 extern int screenshotdownscaling;
 
+extern bool hapticFeedback;
+
 //markers such as hole positions and electron positions
 extern float ** markers;
 extern float ** markercolours;
diff --git a/NOMADVRLib/atoms.cpp b/NOMADVRLib/atoms.cpp
index 8a8f1b6a8cc72a50bfa4d107dbbca5fa3d459c9c..f306f4ff253b6a233da6b911e1d0925969bbcca0 100644
--- a/NOMADVRLib/atoms.cpp
+++ b/NOMADVRLib/atoms.cpp
@@ -202,9 +202,10 @@ int findAtom(const char *const s)
 
 const char * readAtomsXYZErrors[] = {
 	"All Ok",//0
-	"could not open file", //-1
-	"error loading atom type and position line", //-2
-	"atom type unknown", //-3
+	"Could not open file", //-1
+	"Error loading atom type and position line", //-2
+	"Atom type unknown", //-3
+	"Corrupt xyz file" //-4
 };
 
 int readAtomsXYZ(const char *const file, int **numatoms, int *timesteps, float ***pos) 
@@ -220,10 +221,18 @@ int readAtomsXYZ(const char *const file, int **numatoms, int *timesteps, float *
 		return -1;
 	}
 	*timesteps=0;
+	int blanklines=0;
 	while (!feof(f)) {
 		r=fscanf(f, "%d", &mynumatoms);
-		if (r<1)
+		if (r<1) {
+			blanklines++;
+			if (blanklines>3) {
+				eprintf("Corrupt xyz file %s. Error at %d atoms\n", file, mynumatoms);
+				return -4;
+			}
 			continue; //there may be a blank line at the end of the file
+		}
+		blanklines=0;
 		(*timesteps)++;
 		discardline (f);
 		//eprintf ("Getting atoms, mynumatoms=%d",mynumatoms);
@@ -245,6 +254,7 @@ int readAtomsXYZ(const char *const file, int **numatoms, int *timesteps, float *
 				//return -3;
 			}
 			(mypos.back())[4*i+3]=(float)a;
+			//RGH FIXME, add cloned atoms
 		}
 	}
 
diff --git a/OpenVR/TimestepData/hellovr_opengl_main.cpp b/OpenVR/TimestepData/hellovr_opengl_main.cpp
index 23ba7280bea44304ed19e69876c7354d70432061..87bc0517f31410ece61a987e0a133e0ff59fdf13 100644
--- a/OpenVR/TimestepData/hellovr_opengl_main.cpp
+++ b/OpenVR/TimestepData/hellovr_opengl_main.cpp
@@ -1077,8 +1077,10 @@ void CMainApplication::ProcessVREvent( const vr::VREvent_t & event )
 
 
 void CMainApplication::HapticFeedback(){
-	HapticFeedback(firstdevice);
-	HapticFeedback(seconddevice);
+	if (hapticFeedback) {
+		HapticFeedback(firstdevice);
+		HapticFeedback(seconddevice);
+	}
 }
 //-----------------------------------------------------------------------------
 // Purpose: Haptic feedback if controller near an atom
@@ -1092,19 +1094,53 @@ void CMainApplication::HapticFeedback(int device)
 		if (dp.bPoseIsValid) {
 			vr::HmdMatrix34_t mat=dp.mDeviceToAbsoluteTracking;
 			Vector3 controllerPos(mat.m[0][3], mat.m[1][3],mat.m[2][3]);
-			for (int i=0;i<numAtoms[currentset];i++) {
-				Vector3 posatom(atoms[currentset][i*4+0], atoms[currentset][i*4+1], atoms[currentset][i*4+2]);
-				//remember rotation
+			int atomsInTimestep;
+			if (currentset==0)
+				atomsInTimestep=numAtoms[0];
+			else
+				atomsInTimestep=numAtoms[currentset]-numAtoms[currentset-1];
+			for (int i=0;i<atomsInTimestep;i++) {
+				float atomr=atomRadius(atoms[currentset][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
+				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])++)
+						for (p[2]=0;p[2]<std::max(1,repetitions[2]);(p[2])++) {
+							float delta[3];
+							::GetDisplacement(p, delta);
+							Vector3 iPos(delta[0], delta[1], delta[2]);
+
+							Vector3 up(-UserPosition.x, -UserPosition.y, UserPosition.z);
+							Vector3 pos=posatom-up+iPos;
+							pos=Vector3 (pos.x, pos.y, -pos.z);
+							float l=(pos - controllerPos).length();
+							if (l<atomr*atomScaling) {
+								m_pHMD->TriggerHapticPulse(device, 0, 3000);
+								return;
+							}
+						}
+			}
+			//now cloned atoms
+			if (currentset==0 && clonedAtoms) {
 				Vector3 up(-UserPosition.x, -UserPosition.y, UserPosition.z);
-				Vector3 pos=posatom-up;
-				pos.z=-pos.z;
-				float l=(pos - controllerPos).length();
-				if (l<0.2f) {
-					m_pHMD->TriggerHapticPulse(device, 0, 3000);
-					return;
+				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]);
+					Vector3 pos=posatom-up;
+					pos.z=-pos.z;
+					float l=(pos - controllerPos).length();
+					if (l<atomr*atomScaling) {
+						m_pHMD->TriggerHapticPulse(device, 0, 3000);
+						return;
+					}
 				}
+					
 			}
-		}
+		} // pose is valid
+			
+		
 	}
 }
 
@@ -1378,8 +1414,8 @@ void CMainApplication::SetupScene()
 {
 	SetupIsosurfaces();
 	SetupAtoms();
-	delete[] clonedAtoms;
-	clonedAtoms=0;
+	//delete[] clonedAtoms; //required for haptic feedback
+	//clonedAtoms=0;
 	SetupUnitCell();
 	SetupMarker();
 }
@@ -2314,6 +2350,7 @@ void CMainApplication::RenderScene(vr::Hmd_Eye nEye)
 	if (ISOS==0) {
 		RenderAtoms(nEye);
 		RenderUnitCell(nEye);
+		RenderAllTrackedRenderModels(nEye);
 		return;
 	}